File indexing completed on 2024-04-28 16:21:24
0001 /* This file is part of the KDE project 0002 Copyright 2010 Marijn Kruisselbrink <mkruisselbrink@kde.org> 0003 Copyright (C) 1998, 1999 Torben Weis <weis@kde.org> 0004 0005 This library is free software; you can redistribute it and/or 0006 modify it under the terms of the GNU Library General Public 0007 License as published by the Free Software Foundation; either 0008 version 2 of the License, or (at your option) any later version. 0009 0010 This library is distributed in the hope that it will be useful, 0011 but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 Library General Public License for more details. 0014 0015 You should have received a copy of the GNU Library General Public License 0016 along with this library; see the file COPYING.LIB. If not, write to 0017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 Boston, MA 02110-1301, USA. 0019 */ 0020 0021 // Local 0022 #include "Map.h" 0023 0024 #include <stdlib.h> 0025 #include <time.h> 0026 0027 #include <QTimer> 0028 0029 #include <kcodecs.h> 0030 #include <kcompletion.h> 0031 0032 #include <KoGlobal.h> 0033 #include <KoEmbeddedDocumentSaver.h> 0034 #include <KoStyleManager.h> 0035 #include <KoParagraphStyle.h> 0036 #include <KoUpdater.h> 0037 #include <KoProgressUpdater.h> 0038 0039 #include "ApplicationSettings.h" 0040 #include "BindingManager.h" 0041 #include "CalculationSettings.h" 0042 #include "CellStorage.h" 0043 #include "Damages.h" 0044 #include "DependencyManager.h" 0045 #include "DocBase.h" 0046 #include "LoadingInfo.h" 0047 #include "Localization.h" 0048 #include "NamedAreaManager.h" 0049 #include "RecalcManager.h" 0050 #include "RowColumnFormat.h" 0051 #include "Sheet.h" 0052 #include "StyleManager.h" 0053 #include "ValueCalc.h" 0054 #include "ValueConverter.h" 0055 #include "ValueFormatter.h" 0056 #include "ValueParser.h" 0057 0058 // database 0059 #include "database/DatabaseManager.h" 0060 0061 using namespace Calligra::Sheets; 0062 0063 class Q_DECL_HIDDEN Map::Private 0064 { 0065 public: 0066 DocBase* doc; 0067 0068 /** 0069 * List of all sheets in this map. 0070 */ 0071 QList<Sheet*> lstSheets; 0072 QList<Sheet*> lstDeletedSheets; 0073 0074 // used to give every Sheet a unique default name. 0075 int tableId; 0076 0077 // used to determine the loading progress 0078 int overallRowCount; 0079 int loadedRowsCounter; 0080 0081 LoadingInfo* loadingInfo; 0082 bool readwrite; 0083 0084 BindingManager* bindingManager; 0085 DatabaseManager* databaseManager; 0086 DependencyManager* dependencyManager; 0087 NamedAreaManager* namedAreaManager; 0088 RecalcManager* recalcManager; 0089 StyleManager* styleManager; 0090 KoStyleManager* textStyleManager; 0091 0092 ApplicationSettings* applicationSettings; 0093 CalculationSettings* calculationSettings; 0094 ValueCalc* calc; 0095 ValueConverter* converter; 0096 ValueFormatter* formatter; 0097 ValueParser* parser; 0098 0099 // default objects 0100 ColumnFormat* defaultColumnFormat; 0101 RowFormat* defaultRowFormat; 0102 0103 QList<Damage*> damages; 0104 bool isLoading; 0105 0106 int syntaxVersion; 0107 0108 KCompletion listCompletion; 0109 }; 0110 0111 0112 Map::Map(DocBase* doc, int syntaxVersion) 0113 : QObject(doc), 0114 d(new Private) 0115 { 0116 setObjectName(QLatin1String("Map")); // necessary for D-Bus 0117 d->doc = doc; 0118 d->tableId = 1; 0119 d->overallRowCount = 0; 0120 d->loadedRowsCounter = 0; 0121 d->loadingInfo = 0; 0122 d->readwrite = true; 0123 0124 d->bindingManager = new BindingManager(this); 0125 d->databaseManager = new DatabaseManager(this); 0126 d->dependencyManager = new DependencyManager(this); 0127 d->namedAreaManager = new NamedAreaManager(this); 0128 d->recalcManager = new RecalcManager(this); 0129 d->styleManager = new StyleManager(); 0130 d->textStyleManager = new KoStyleManager(this); 0131 d->applicationSettings = new ApplicationSettings(); 0132 d->calculationSettings = new CalculationSettings(); 0133 0134 d->parser = new ValueParser(d->calculationSettings); 0135 d->converter = new ValueConverter(d->parser); 0136 d->calc = new ValueCalc(d->converter); 0137 d->formatter = new ValueFormatter(d->converter); 0138 0139 d->defaultColumnFormat = new ColumnFormat(); 0140 d->defaultRowFormat = new RowFormat(); 0141 0142 QFont font(KoGlobal::defaultFont()); 0143 d->defaultRowFormat->setHeight(font.pointSizeF() + 4); 0144 d->defaultColumnFormat->setWidth((font.pointSizeF() + 4) * 5); 0145 0146 d->isLoading = false; 0147 0148 // default document properties 0149 d->syntaxVersion = syntaxVersion; 0150 0151 connect(this, SIGNAL(sheetAdded(Sheet*)), 0152 d->dependencyManager, SLOT(addSheet(Sheet*))); 0153 connect(this, SIGNAL(sheetAdded(Sheet*)), 0154 d->recalcManager, SLOT(addSheet(Sheet*))); 0155 connect(this, SIGNAL(sheetRemoved(Sheet*)), 0156 d->dependencyManager, SLOT(removeSheet(Sheet*))); 0157 connect(this, SIGNAL(sheetRemoved(Sheet*)), 0158 d->recalcManager, SLOT(removeSheet(Sheet*))); 0159 connect(this, SIGNAL(sheetRevived(Sheet*)), 0160 d->dependencyManager, SLOT(addSheet(Sheet*))); 0161 connect(this, SIGNAL(sheetRevived(Sheet*)), 0162 d->recalcManager, SLOT(addSheet(Sheet*))); 0163 connect(d->namedAreaManager, SIGNAL(namedAreaModified(QString)), 0164 d->dependencyManager, SLOT(namedAreaModified(QString))); 0165 connect(this, SIGNAL(damagesFlushed(QList<Damage*>)), 0166 this, SLOT(handleDamages(QList<Damage*>))); 0167 } 0168 0169 Map::~Map() 0170 { 0171 // Because some of the shapes might be using a sheet in this map, delete 0172 // all shapes in each sheet before all sheets are deleted together. 0173 foreach(Sheet *sheet, d->lstSheets) 0174 sheet->deleteShapes(); 0175 // we have to explicitly delete the Sheets, not let QObject take care of that 0176 // as the sheet in its destructor expects the Map to still exist 0177 qDeleteAll(d->lstSheets); 0178 d->lstSheets.clear(); 0179 0180 deleteLoadingInfo(); 0181 0182 delete d->bindingManager; 0183 delete d->databaseManager; 0184 delete d->dependencyManager; 0185 delete d->namedAreaManager; 0186 delete d->recalcManager; 0187 delete d->styleManager; 0188 0189 delete d->parser; 0190 delete d->formatter; 0191 delete d->converter; 0192 delete d->calc; 0193 delete d->calculationSettings; 0194 delete d->applicationSettings; 0195 0196 delete d->defaultColumnFormat; 0197 delete d->defaultRowFormat; 0198 0199 delete d; 0200 } 0201 0202 DocBase* Map::doc() const 0203 { 0204 return d->doc; 0205 } 0206 0207 void Map::setReadWrite(bool readwrite) 0208 { 0209 d->readwrite = readwrite; 0210 } 0211 0212 bool Map::isReadWrite() const 0213 { 0214 return d->readwrite; 0215 } 0216 0217 bool Map::completeLoading(KoStore *store) 0218 { 0219 Q_UNUSED(store); 0220 0221 QPointer<KoUpdater> dependencyUpdater, recalcUpdater; 0222 if (doc() && doc()->progressUpdater()) { 0223 dependencyUpdater = doc()->progressUpdater()->startSubtask(1, "Calligra::Sheets::DependencyManager::updateAllDependencies"); 0224 recalcUpdater = doc()->progressUpdater()->startSubtask(1, "Calligra::Sheets::RecalcManager::recalc"); 0225 } 0226 0227 // Initial build of all cell dependencies. 0228 d->dependencyManager->updateAllDependencies(this, dependencyUpdater); 0229 // Recalc the whole workbook now, since there may be formulas other spreadsheets support, 0230 // but Calligra Sheets does not. 0231 d->recalcManager->recalcMap(recalcUpdater); 0232 0233 return true; 0234 } 0235 0236 bool Map::completeSaving(KoStore *store, KoXmlWriter *manifestWriter, KoShapeSavingContext * context) 0237 { 0238 Q_UNUSED(store); 0239 Q_UNUSED(manifestWriter); 0240 Q_UNUSED(context); 0241 return true; 0242 } 0243 0244 BindingManager* Map::bindingManager() const 0245 { 0246 return d->bindingManager; 0247 } 0248 0249 DatabaseManager* Map::databaseManager() const 0250 { 0251 return d->databaseManager; 0252 } 0253 0254 DependencyManager* Map::dependencyManager() const 0255 { 0256 return d->dependencyManager; 0257 } 0258 0259 NamedAreaManager* Map::namedAreaManager() const 0260 { 0261 return d->namedAreaManager; 0262 } 0263 0264 RecalcManager* Map::recalcManager() const 0265 { 0266 return d->recalcManager; 0267 } 0268 0269 StyleManager* Map::styleManager() const 0270 { 0271 return d->styleManager; 0272 } 0273 0274 KoStyleManager* Map::textStyleManager() const 0275 { 0276 return d->textStyleManager; 0277 } 0278 0279 ValueParser* Map::parser() const 0280 { 0281 return d->parser; 0282 } 0283 0284 ValueFormatter* Map::formatter() const 0285 { 0286 return d->formatter; 0287 } 0288 0289 ValueConverter* Map::converter() const 0290 { 0291 return d->converter; 0292 } 0293 0294 ValueCalc* Map::calc() const 0295 { 0296 return d->calc; 0297 } 0298 0299 const ColumnFormat* Map::defaultColumnFormat() const 0300 { 0301 return d->defaultColumnFormat; 0302 } 0303 0304 const RowFormat* Map::defaultRowFormat() const 0305 { 0306 return d->defaultRowFormat; 0307 } 0308 0309 void Map::setDefaultColumnWidth(double width) 0310 { 0311 d->defaultColumnFormat->setWidth(width); 0312 } 0313 0314 void Map::setDefaultRowHeight(double height) 0315 { 0316 d->defaultRowFormat->setHeight(height); 0317 } 0318 0319 ApplicationSettings* Map::settings() const 0320 { 0321 return d->applicationSettings; 0322 } 0323 0324 CalculationSettings* Map::calculationSettings() const 0325 { 0326 return d->calculationSettings; 0327 } 0328 0329 Sheet* Map::createSheet(const QString& name) 0330 { 0331 QString sheetName(i18n("Sheet%1", d->tableId++)); 0332 if ( !name.isEmpty() ) 0333 sheetName = name; 0334 Sheet* sheet = new Sheet(this, sheetName); 0335 connect(sheet, SIGNAL(statusMessage(QString,int)), 0336 this, SIGNAL(statusMessage(QString,int))); 0337 return sheet; 0338 } 0339 0340 void Map::addSheet(Sheet *_sheet) 0341 { 0342 d->lstSheets.append(_sheet); 0343 emit sheetAdded(_sheet); 0344 } 0345 0346 Sheet *Map::addNewSheet(const QString& name) 0347 { 0348 Sheet *t = createSheet(name); 0349 addSheet(t); 0350 return t; 0351 } 0352 0353 void Map::moveSheet(const QString & _from, const QString & _to, bool _before) 0354 { 0355 Sheet* sheetfrom = findSheet(_from); 0356 Sheet* sheetto = findSheet(_to); 0357 0358 int from = d->lstSheets.indexOf(sheetfrom) ; 0359 int to = d->lstSheets.indexOf(sheetto) ; 0360 if (!_before) 0361 ++to; 0362 0363 if (to > (int)d->lstSheets.count()) { 0364 d->lstSheets.append(sheetfrom); 0365 d->lstSheets.removeAt(from); 0366 } else if (from < to) { 0367 d->lstSheets.insert(to, sheetfrom); 0368 d->lstSheets.removeAt(from); 0369 } else { 0370 d->lstSheets.removeAt(from); 0371 d->lstSheets.insert(to, sheetfrom); 0372 } 0373 } 0374 0375 QDomElement Map::save(QDomDocument& doc) 0376 { 0377 QDomElement spread = doc.documentElement(); 0378 0379 QDomElement locale = static_cast<Localization*>(d->calculationSettings->locale())->save(doc); 0380 spread.appendChild(locale); 0381 0382 QDomElement areaname = d->namedAreaManager->saveXML(doc); 0383 spread.appendChild(areaname); 0384 0385 QDomElement defaults = doc.createElement("defaults"); 0386 defaults.setAttribute("row-height", QString::number(d->defaultRowFormat->height())); 0387 defaults.setAttribute("col-width", QString::number(d->defaultColumnFormat->width())); 0388 spread.appendChild(defaults); 0389 0390 QDomElement s = d->styleManager->save(doc); 0391 spread.appendChild(s); 0392 0393 QDomElement mymap = doc.createElement("map"); 0394 0395 QByteArray password; 0396 this->password(password); 0397 if (!password.isNull()) { 0398 if (password.size() > 0) { 0399 QByteArray str = KCodecs::base64Encode(password); 0400 mymap.setAttribute("protected", QString(str.data())); 0401 } else { 0402 mymap.setAttribute("protected", ""); 0403 } 0404 } 0405 0406 foreach(Sheet* sheet, d->lstSheets) { 0407 QDomElement e = sheet->saveXML(doc); 0408 if (e.isNull()) 0409 return e; 0410 mymap.appendChild(e); 0411 } 0412 return mymap; 0413 } 0414 0415 bool Map::loadXML(const KoXmlElement& mymap) 0416 { 0417 d->isLoading = true; 0418 loadingInfo()->setFileFormat(LoadingInfo::NativeFormat); 0419 const QString activeSheet = mymap.attribute("activeTable"); 0420 const QPoint marker(mymap.attribute("markerColumn").toInt(), mymap.attribute("markerRow").toInt()); 0421 loadingInfo()->setCursorPosition(findSheet(activeSheet), marker); 0422 const QPointF offset(mymap.attribute("xOffset").toDouble(), mymap.attribute("yOffset").toDouble()); 0423 loadingInfo()->setScrollingOffset(findSheet(activeSheet), offset); 0424 0425 KoXmlNode n = mymap.firstChild(); 0426 if (n.isNull()) { 0427 // We need at least one sheet ! 0428 doc()->setErrorMessage(i18n("This document has no sheets (tables).")); 0429 d->isLoading = false; 0430 return false; 0431 } 0432 while (!n.isNull()) { 0433 KoXmlElement e = n.toElement(); 0434 if (!e.isNull() && e.tagName() == "table") { 0435 Sheet *t = addNewSheet(); 0436 if (!t->loadXML(e)) { 0437 d->isLoading = false; 0438 return false; 0439 } 0440 } 0441 n = n.nextSibling(); 0442 } 0443 0444 loadXmlProtection(mymap); 0445 0446 if (!activeSheet.isEmpty()) { 0447 // Used by View's constructor 0448 loadingInfo()->setInitialActiveSheet(findSheet(activeSheet)); 0449 } 0450 0451 d->isLoading = false; 0452 return true; 0453 } 0454 0455 Sheet* Map::findSheet(const QString & _name) const 0456 { 0457 foreach(Sheet* sheet, d->lstSheets) { 0458 if (_name.toLower() == sheet->sheetName().toLower()) 0459 return sheet; 0460 } 0461 return 0; 0462 } 0463 0464 Sheet * Map::nextSheet(Sheet * currentSheet) const 0465 { 0466 if (currentSheet == d->lstSheets.last()) 0467 return currentSheet; 0468 int index = 0; 0469 foreach(Sheet* sheet, d->lstSheets) { 0470 if (sheet == currentSheet) 0471 return d->lstSheets.value(++index); 0472 ++index; 0473 } 0474 return 0; 0475 } 0476 0477 Sheet * Map::previousSheet(Sheet * currentSheet) const 0478 { 0479 if (currentSheet == d->lstSheets.first()) 0480 return currentSheet; 0481 int index = 0; 0482 foreach(Sheet* sheet, d->lstSheets) { 0483 if (sheet == currentSheet) 0484 return d->lstSheets.value(--index); 0485 ++index; 0486 } 0487 return 0; 0488 } 0489 0490 bool Map::loadChildren(KoStore * _store) 0491 { 0492 foreach(Sheet* sheet, d->lstSheets) { 0493 if (!sheet->loadChildren(_store)) 0494 return false; 0495 } 0496 return true; 0497 } 0498 0499 void Map::removeSheet(Sheet* sheet) 0500 { 0501 d->lstSheets.removeAll(sheet); 0502 d->lstDeletedSheets.append(sheet); 0503 d->namedAreaManager->remove(sheet); 0504 emit sheetRemoved(sheet); 0505 } 0506 0507 void Map::reviveSheet(Sheet* sheet) 0508 { 0509 d->lstDeletedSheets.removeAll(sheet); 0510 d->lstSheets.append(sheet); 0511 emit sheetRevived(sheet); 0512 } 0513 0514 // FIXME cache this for faster operation 0515 QStringList Map::visibleSheets() const 0516 { 0517 QStringList result; 0518 foreach(Sheet* sheet, d->lstSheets) { 0519 if (!sheet->isHidden()) 0520 result.append(sheet->sheetName()); 0521 } 0522 return result; 0523 } 0524 0525 // FIXME cache this for faster operation 0526 QStringList Map::hiddenSheets() const 0527 { 0528 QStringList result; 0529 foreach(Sheet* sheet, d->lstSheets) { 0530 if (sheet->isHidden()) 0531 result.append(sheet->sheetName()); 0532 } 0533 return result; 0534 } 0535 0536 Sheet* Map::sheet(int index) const 0537 { 0538 return d->lstSheets.value(index); 0539 } 0540 0541 int Map::indexOf(Sheet* sheet) const 0542 { 0543 return d->lstSheets.indexOf(sheet); 0544 } 0545 0546 QList<Sheet*>& Map::sheetList() const 0547 { 0548 return d->lstSheets; 0549 } 0550 0551 int Map::count() const 0552 { 0553 return d->lstSheets.count(); 0554 } 0555 0556 void Map::setOverallRowsCounter(int number) 0557 { 0558 d->overallRowCount = number; 0559 } 0560 0561 int Map::increaseLoadedRowsCounter(int number) 0562 { 0563 d->loadedRowsCounter += number; 0564 if (d->overallRowCount) { 0565 return 100 * d->loadedRowsCounter / d->overallRowCount; 0566 } 0567 return -1; 0568 } 0569 0570 bool Map::isLoading() const 0571 { 0572 // The KoDocument state is necessary to avoid damages while importing a file (through a filter). 0573 return d->isLoading || (d->doc && d->doc->isLoading()); 0574 } 0575 0576 void Map::setLoading(bool l) { 0577 d->isLoading = l; 0578 } 0579 0580 int Map::syntaxVersion() const 0581 { 0582 return d->syntaxVersion; 0583 } 0584 0585 void Map::setSyntaxVersion(int version) 0586 { 0587 d->syntaxVersion = version; 0588 } 0589 0590 LoadingInfo* Map::loadingInfo() const 0591 { 0592 if (!d->loadingInfo) { 0593 d->loadingInfo = new LoadingInfo(); 0594 } 0595 return d->loadingInfo; 0596 } 0597 0598 void Map::deleteLoadingInfo() 0599 { 0600 delete d->loadingInfo; 0601 d->loadingInfo = 0; 0602 } 0603 0604 KCompletion& Map::stringCompletion() 0605 { 0606 return d->listCompletion; 0607 } 0608 0609 void Map::addStringCompletion(const QString &stringCompletion) 0610 { 0611 if (d->listCompletion.items().contains(stringCompletion) == 0) { 0612 d->listCompletion.addItem(stringCompletion); 0613 } 0614 } 0615 0616 void Map::addDamage(Damage* damage) 0617 { 0618 // Do not create a new Damage, if we are in loading process. Check for it before 0619 // calling this function. This prevents unnecessary memory allocations (new). 0620 // see FIXME in Sheet::setSheetName(). 0621 // Q_ASSERT(!isLoading()); 0622 Q_CHECK_PTR(damage); 0623 0624 #ifndef NDEBUG 0625 if (damage->type() == Damage::Cell) { 0626 debugSheetsDamage << "Adding\t" << *static_cast<CellDamage*>(damage); 0627 } else if (damage->type() == Damage::Sheet) { 0628 debugSheetsDamage << "Adding\t" << *static_cast<SheetDamage*>(damage); 0629 } else if (damage->type() == Damage::Selection) { 0630 debugSheetsDamage << "Adding\t" << *static_cast<SelectionDamage*>(damage); 0631 } else { 0632 debugSheetsDamage << "Adding\t" << *damage; 0633 } 0634 #endif 0635 0636 d->damages.append(damage); 0637 0638 if (d->damages.count() == 1) { 0639 QTimer::singleShot(0, this, SLOT(flushDamages())); 0640 } 0641 } 0642 0643 void Map::flushDamages() 0644 { 0645 // Copy the damages to process. This allows new damages while processing. 0646 QList<Damage*> damages = d->damages; 0647 d->damages.clear(); 0648 emit damagesFlushed(damages); 0649 qDeleteAll(damages); 0650 } 0651 0652 void Map::handleDamages(const QList<Damage*>& damages) 0653 { 0654 Region bindingChangedRegion; 0655 Region formulaChangedRegion; 0656 Region namedAreaChangedRegion; 0657 Region valueChangedRegion; 0658 WorkbookDamage::Changes workbookChanges = WorkbookDamage::None; 0659 0660 QList<Damage*>::ConstIterator end(damages.end()); 0661 for (QList<Damage*>::ConstIterator it = damages.begin(); it != end; ++it) { 0662 Damage* damage = *it; 0663 0664 if (damage->type() == Damage::Cell) { 0665 CellDamage* cellDamage = static_cast<CellDamage*>(damage); 0666 debugSheetsDamage << "Processing\t" << *cellDamage; 0667 Sheet* const damagedSheet = cellDamage->sheet(); 0668 const Region& region = cellDamage->region(); 0669 const CellDamage::Changes changes = cellDamage->changes(); 0670 0671 // TODO Stefan: Detach the style cache from the CellView cache. 0672 if ((changes.testFlag(CellDamage::Appearance))) { 0673 // Rebuild the style storage cache. 0674 damagedSheet->cellStorage()->invalidateStyleCache(); // FIXME more fine-grained 0675 } 0676 if ((cellDamage->changes() & CellDamage::Binding) && 0677 !workbookChanges.testFlag(WorkbookDamage::Value)) { 0678 bindingChangedRegion.add(region, damagedSheet); 0679 } 0680 if ((cellDamage->changes() & CellDamage::Formula) && 0681 !workbookChanges.testFlag(WorkbookDamage::Formula)) { 0682 formulaChangedRegion.add(region, damagedSheet); 0683 } 0684 if ((cellDamage->changes() & CellDamage::NamedArea) && 0685 !workbookChanges.testFlag(WorkbookDamage::Formula)) { 0686 namedAreaChangedRegion.add(region, damagedSheet); 0687 } 0688 if ((cellDamage->changes() & CellDamage::Value) && 0689 !workbookChanges.testFlag(WorkbookDamage::Value)) { 0690 valueChangedRegion.add(region, damagedSheet); 0691 } 0692 continue; 0693 } 0694 0695 if (damage->type() == Damage::Sheet) { 0696 SheetDamage* sheetDamage = static_cast<SheetDamage*>(damage); 0697 debugSheetsDamage << "Processing\t" << *sheetDamage; 0698 // Sheet* damagedSheet = sheetDamage->sheet(); 0699 0700 if (sheetDamage->changes() & SheetDamage::PropertiesChanged) { 0701 } 0702 continue; 0703 } 0704 0705 if (damage->type() == Damage::Workbook) { 0706 WorkbookDamage* workbookDamage = static_cast<WorkbookDamage*>(damage); 0707 debugSheetsDamage << "Processing\t" << *damage; 0708 0709 workbookChanges |= workbookDamage->changes(); 0710 if (workbookDamage->changes() & WorkbookDamage::Formula) { 0711 formulaChangedRegion.clear(); 0712 } 0713 if (workbookDamage->changes() & WorkbookDamage::Value) { 0714 valueChangedRegion.clear(); 0715 } 0716 continue; 0717 } 0718 // debugSheetsDamage <<"Unhandled\t" << *damage; 0719 } 0720 0721 // Update the named areas. 0722 if (!namedAreaChangedRegion.isEmpty()) { 0723 d->namedAreaManager->regionChanged(namedAreaChangedRegion); 0724 } 0725 // First, update the dependencies. 0726 if (!formulaChangedRegion.isEmpty()) { 0727 d->dependencyManager->regionChanged(formulaChangedRegion); 0728 } 0729 // Tell the RecalcManager which cells have had a value change. 0730 if (!valueChangedRegion.isEmpty()) { 0731 d->recalcManager->regionChanged(valueChangedRegion); 0732 } 0733 if (workbookChanges.testFlag(WorkbookDamage::Formula)) { 0734 d->namedAreaManager->updateAllNamedAreas(); 0735 d->dependencyManager->updateAllDependencies(this); 0736 } 0737 if (workbookChanges.testFlag(WorkbookDamage::Value)) { 0738 d->recalcManager->recalcMap(); 0739 d->bindingManager->updateAllBindings(); 0740 } 0741 // Update the bindings 0742 if (!bindingChangedRegion.isEmpty()) { 0743 d->bindingManager->regionChanged(bindingChangedRegion); 0744 } 0745 } 0746 0747 void Map::addCommand(KUndo2Command *command) 0748 { 0749 emit commandAdded(command); 0750 } 0751 0752 KoDocumentResourceManager* Map::resourceManager() const 0753 { 0754 if (!doc()) return 0; 0755 return doc()->resourceManager(); 0756 }