File indexing completed on 2024-04-28 16:21:25
0001 /* This file is part of the KDE project 0002 Copyright 2007 Stefan Nikolaus <stefan.nikolaus@kdemail.net> 0003 Copyright 2005-2006 Inge Wallin <inge@lysator.liu.se> 0004 Copyright 2004 Ariya Hidayat <ariya@kde.org> 0005 Copyright 2002-2003 Norbert Andres <nandres@web.de> 0006 Copyright 2000-2002 Laurent Montel <montel@kde.org> 0007 Copyright 2002 John Dailey <dailey@vt.edu> 0008 Copyright 2002 Phillip Mueller <philipp.mueller@gmx.de> 0009 Copyright 2000 Werner Trobin <trobin@kde.org> 0010 Copyright 1999-2000 Simon Hausmann <hausmann@kde.org> 0011 Copyright 1999 David Faure <faure@kde.org> 0012 Copyright 1998-2000 Torben Weis <weis@kde.org> 0013 0014 This library is free software; you can redistribute it and/or 0015 modify it under the terms of the GNU Library General Public 0016 License as published by the Free Software Foundation; either 0017 version 2 of the License, or (at your option) any later version. 0018 0019 This library is distributed in the hope that it will be useful, 0020 but WITHOUT ANY WARRANTY; without even the implied warranty of 0021 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0022 Library General Public License for more details. 0023 0024 You should have received a copy of the GNU Library General Public License 0025 along with this library; see the file COPYING.LIB. If not, write to 0026 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0027 Boston, MA 02110-1301, USA. 0028 */ 0029 0030 // Local 0031 #include "NamedAreaManager.h" 0032 0033 #include <KoXmlReader.h> 0034 0035 // Qt 0036 #include <QDomElement> 0037 #include <QHash> 0038 0039 // Sheets 0040 #include "CellStorage.h" 0041 #include "FormulaStorage.h" 0042 #include "LoadingInfo.h" 0043 #include "Map.h" 0044 #include "Region.h" 0045 #include "Sheet.h" 0046 #include "Util.h" 0047 0048 using namespace Calligra::Sheets; 0049 0050 struct NamedArea { 0051 QString name; 0052 Sheet* sheet; 0053 QRect range; 0054 }; 0055 0056 class Q_DECL_HIDDEN NamedAreaManager::Private 0057 { 0058 public: 0059 const Map* map; 0060 QHash<QString, NamedArea> namedAreas; 0061 }; 0062 0063 NamedAreaManager::NamedAreaManager(const Map* map) 0064 : d(new Private) 0065 { 0066 d->map = map; 0067 connect(this, SIGNAL(namedAreaAdded(QString)), 0068 this, SIGNAL(namedAreaModified(QString))); 0069 connect(this, SIGNAL(namedAreaRemoved(QString)), 0070 this, SIGNAL(namedAreaModified(QString))); 0071 } 0072 0073 NamedAreaManager::~NamedAreaManager() 0074 { 0075 delete d; 0076 } 0077 0078 const Map *NamedAreaManager::map() const 0079 { 0080 return d->map; 0081 } 0082 0083 void NamedAreaManager::insert(const Region& region, const QString& name) 0084 { 0085 // NOTE Stefan: Only contiguous regions are supported (OpenDocument compatibility). 0086 Q_ASSERT(!name.isEmpty()); 0087 NamedArea namedArea; 0088 namedArea.range = region.lastRange(); 0089 namedArea.sheet = region.lastSheet(); 0090 namedArea.name = name; 0091 namedArea.sheet->cellStorage()->setNamedArea(Region(region.lastRange(), region.lastSheet()), name); 0092 d->namedAreas[name] = namedArea; 0093 emit namedAreaAdded(name); 0094 } 0095 0096 void NamedAreaManager::remove(const QString& name) 0097 { 0098 if (!d->namedAreas.contains(name)) 0099 return; 0100 NamedArea namedArea = d->namedAreas.value(name); 0101 namedArea.sheet->cellStorage()->removeNamedArea(Region(namedArea.range, namedArea.sheet), name); 0102 d->namedAreas.remove(name); 0103 emit namedAreaRemoved(name); 0104 const QList<Sheet*> sheets = namedArea.sheet->map()->sheetList(); 0105 foreach(Sheet* sheet, sheets) { 0106 const QString tmp = '\'' + name + '\''; 0107 const FormulaStorage* const storage = sheet->formulaStorage(); 0108 for (int c = 0; c < storage->count(); ++c) { 0109 if (storage->data(c).expression().contains(tmp)) { 0110 Cell(sheet, storage->col(c), storage->row(c)).makeFormula(); 0111 } 0112 } 0113 } 0114 } 0115 0116 void NamedAreaManager::remove(Sheet* sheet) 0117 { 0118 const QList<NamedArea> namedAreas = d->namedAreas.values(); 0119 for (int i = 0; i < namedAreas.count(); ++i) { 0120 if (namedAreas[i].sheet == sheet) 0121 remove(namedAreas[i].name); 0122 } 0123 } 0124 0125 Calligra::Sheets::Region NamedAreaManager::namedArea(const QString& name) const 0126 { 0127 if (!d->namedAreas.contains(name)) 0128 return Region(); 0129 const NamedArea namedArea = d->namedAreas.value(name); 0130 return Region(namedArea.range, namedArea.sheet); 0131 } 0132 0133 Sheet* NamedAreaManager::sheet(const QString& name) const 0134 { 0135 if (!d->namedAreas.contains(name)) 0136 return 0; 0137 return d->namedAreas.value(name).sheet; 0138 } 0139 0140 bool NamedAreaManager::contains(const QString& name) const 0141 { 0142 return d->namedAreas.contains(name); 0143 } 0144 0145 QList<QString> NamedAreaManager::areaNames() const 0146 { 0147 return d->namedAreas.keys(); 0148 } 0149 0150 void NamedAreaManager::regionChanged(const Region& region) 0151 { 0152 Sheet* sheet; 0153 QList< QPair<QRectF, QString> > namedAreas; 0154 Region::ConstIterator end(region.constEnd()); 0155 for (Region::ConstIterator it = region.constBegin(); it != end; ++it) { 0156 sheet = (*it)->sheet(); 0157 namedAreas = sheet->cellStorage()->namedAreas(Region((*it)->rect(), sheet)); 0158 for (int j = 0; j < namedAreas.count(); ++j) { 0159 Q_ASSERT(d->namedAreas.contains(namedAreas[j].second)); 0160 d->namedAreas[namedAreas[j].second].range = namedAreas[j].first.toRect(); 0161 emit namedAreaModified(namedAreas[j].second); 0162 } 0163 } 0164 } 0165 0166 void NamedAreaManager::updateAllNamedAreas() 0167 { 0168 QList< QPair<QRectF, QString> > namedAreas; 0169 const QRect rect(QPoint(1, 1), QPoint(KS_colMax, KS_rowMax)); 0170 const QList<Sheet*> sheets = d->map->sheetList(); 0171 for (int i = 0; i < sheets.count(); ++i) { 0172 namedAreas = sheets[i]->cellStorage()->namedAreas(Region(rect, sheets[i])); 0173 for (int j = 0; j < namedAreas.count(); ++j) { 0174 Q_ASSERT(d->namedAreas.contains(namedAreas[j].second)); 0175 d->namedAreas[namedAreas[j].second].range = namedAreas[j].first.toRect(); 0176 emit namedAreaModified(namedAreas[j].second); 0177 } 0178 } 0179 } 0180 0181 void NamedAreaManager::loadXML(const KoXmlElement& parent) 0182 { 0183 KoXmlElement element; 0184 forEachElement(element, parent) { 0185 if (element.tagName() == "reference") { 0186 Sheet* sheet = 0; 0187 QString tabname; 0188 QString refname; 0189 int left = 0; 0190 int right = 0; 0191 int top = 0; 0192 int bottom = 0; 0193 KoXmlElement sheetName = element.namedItem("tabname").toElement(); 0194 if (!sheetName.isNull()) 0195 sheet = d->map->findSheet(sheetName.text()); 0196 if (!sheet) 0197 continue; 0198 KoXmlElement referenceName = element.namedItem("refname").toElement(); 0199 if (!referenceName.isNull()) 0200 refname = referenceName.text(); 0201 KoXmlElement rect = element.namedItem("rect").toElement(); 0202 if (!rect.isNull()) { 0203 bool ok; 0204 if (rect.hasAttribute("left-rect")) 0205 left = rect.attribute("left-rect").toInt(&ok); 0206 if (rect.hasAttribute("right-rect")) 0207 right = rect.attribute("right-rect").toInt(&ok); 0208 if (rect.hasAttribute("top-rect")) 0209 top = rect.attribute("top-rect").toInt(&ok); 0210 if (rect.hasAttribute("bottom-rect")) 0211 bottom = rect.attribute("bottom-rect").toInt(&ok); 0212 } 0213 insert(Region(QRect(QPoint(left, top), QPoint(right, bottom)), sheet), refname); 0214 } 0215 } 0216 } 0217 0218 QDomElement NamedAreaManager::saveXML(QDomDocument& doc) const 0219 { 0220 QDomElement element = doc.createElement("areaname"); 0221 const QList<NamedArea> namedAreas = d->namedAreas.values(); 0222 for (int i = 0; i < namedAreas.count(); ++i) { 0223 QDomElement e = doc.createElement("reference"); 0224 QDomElement tabname = doc.createElement("tabname"); 0225 tabname.appendChild(doc.createTextNode(namedAreas[i].sheet->sheetName())); 0226 e.appendChild(tabname); 0227 0228 QDomElement refname = doc.createElement("refname"); 0229 refname.appendChild(doc.createTextNode(namedAreas[i].name)); 0230 e.appendChild(refname); 0231 0232 QDomElement rect = doc.createElement("rect"); 0233 rect.setAttribute("left-rect", QString::number((namedAreas[i].range).left())); 0234 rect.setAttribute("right-rect", QString::number((namedAreas[i].range).right())); 0235 rect.setAttribute("top-rect", QString::number((namedAreas[i].range).top())); 0236 rect.setAttribute("bottom-rect", QString::number((namedAreas[i].range).bottom())); 0237 e.appendChild(rect); 0238 element.appendChild(e); 0239 } 0240 return element; 0241 }