File indexing completed on 2024-04-28 16:21:19
0001 /* This file is part of the KDE project 0002 Copyright 2010 Marijn Kruisselbrink <mkruisselbrink@kde.org> 0003 Copyright 2007, 2009 Stefan Nikolaus <stefan.nikolaus@kdemail.net> 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 "CellStorage.h" 0023 #include "CellStorage_p.h" 0024 0025 // Qt 0026 #ifdef CALLIGRA_SHEETS_MT 0027 #include <QReadWriteLock> 0028 #include <QReadLocker> 0029 #include <QWriteLocker> 0030 #endif 0031 0032 // Calligra 0033 #include <KoXmlWriter.h> 0034 0035 // Sheets 0036 #include "BindingStorage.h" 0037 #include "ConditionsStorage.h" 0038 #include "Damages.h" 0039 #include "DependencyManager.h" 0040 #include "FormulaStorage.h" 0041 #include "Map.h" 0042 #include "ModelSupport.h" 0043 #include "RecalcManager.h" 0044 #include "RectStorage.h" 0045 #include "RowRepeatStorage.h" 0046 #include "Sheet.h" 0047 #include "StyleStorage.h" 0048 #include "ValidityStorage.h" 0049 #include "ValueStorage.h" 0050 0051 // commands 0052 #include "commands/PointStorageUndoCommand.h" 0053 #include "commands/RectStorageUndoCommand.h" 0054 #include "commands/StyleStorageUndoCommand.h" 0055 0056 // database 0057 #include "database/DatabaseStorage.h" 0058 #include "database/DatabaseManager.h" 0059 0060 Q_DECLARE_METATYPE(QSharedPointer<QTextDocument>) 0061 0062 using namespace Calligra::Sheets; 0063 0064 typedef RectStorage<QString> NamedAreaStorage; 0065 0066 class Q_DECL_HIDDEN CellStorage::Private 0067 { 0068 public: 0069 Private(Sheet* sheet) 0070 : sheet(sheet) 0071 , bindingStorage(new BindingStorage(sheet->map())) 0072 , commentStorage(new CommentStorage(sheet->map())) 0073 , conditionsStorage(new ConditionsStorage(sheet->map())) 0074 , databaseStorage(new DatabaseStorage(sheet->map())) 0075 , formulaStorage(new FormulaStorage()) 0076 , fusionStorage(new FusionStorage(sheet->map())) 0077 , linkStorage(new LinkStorage()) 0078 , matrixStorage(new MatrixStorage(sheet->map())) 0079 , namedAreaStorage(new NamedAreaStorage(sheet->map())) 0080 , styleStorage(new StyleStorage(sheet->map())) 0081 , userInputStorage(new UserInputStorage()) 0082 , validityStorage(new ValidityStorage(sheet->map())) 0083 , valueStorage(new ValueStorage()) 0084 , richTextStorage(new RichTextStorage()) 0085 , rowRepeatStorage(new RowRepeatStorage()) 0086 , undoData(0) 0087 #ifdef CALLIGRA_SHEETS_MT 0088 , bigUglyLock(QReadWriteLock::Recursive) 0089 #endif 0090 {} 0091 0092 Private(const Private& other, Sheet* sheet) 0093 : sheet(sheet) 0094 , bindingStorage(new BindingStorage(*other.bindingStorage)) 0095 , commentStorage(new CommentStorage(*other.commentStorage)) 0096 , conditionsStorage(new ConditionsStorage(*other.conditionsStorage)) 0097 , databaseStorage(new DatabaseStorage(*other.databaseStorage)) 0098 , formulaStorage(new FormulaStorage(*other.formulaStorage)) 0099 , fusionStorage(new FusionStorage(*other.fusionStorage)) 0100 , linkStorage(new LinkStorage(*other.linkStorage)) 0101 , matrixStorage(new MatrixStorage(*other.matrixStorage)) 0102 , namedAreaStorage(new NamedAreaStorage(*other.namedAreaStorage)) 0103 , styleStorage(new StyleStorage(*other.styleStorage)) 0104 , userInputStorage(new UserInputStorage(*other.userInputStorage)) 0105 , validityStorage(new ValidityStorage(*other.validityStorage)) 0106 , valueStorage(new ValueStorage(*other.valueStorage)) 0107 , richTextStorage(new RichTextStorage(*other.richTextStorage)) 0108 , rowRepeatStorage(new RowRepeatStorage(*other.rowRepeatStorage)) 0109 , undoData(0) 0110 #ifdef CALLIGRA_SHEETS_MT 0111 , bigUglyLock(QReadWriteLock::Recursive) 0112 #endif 0113 {} 0114 0115 ~Private() { 0116 delete bindingStorage; 0117 delete commentStorage; 0118 delete conditionsStorage; 0119 delete databaseStorage; 0120 delete formulaStorage; 0121 delete fusionStorage; 0122 delete linkStorage; 0123 delete matrixStorage; 0124 delete namedAreaStorage; 0125 delete styleStorage; 0126 delete userInputStorage; 0127 delete validityStorage; 0128 delete valueStorage; 0129 delete richTextStorage; 0130 delete rowRepeatStorage; 0131 } 0132 0133 void createCommand(KUndo2Command *parent) const; 0134 0135 Sheet* sheet; 0136 BindingStorage* bindingStorage; 0137 CommentStorage* commentStorage; 0138 ConditionsStorage* conditionsStorage; 0139 DatabaseStorage* databaseStorage; 0140 FormulaStorage* formulaStorage; 0141 FusionStorage* fusionStorage; 0142 LinkStorage* linkStorage; 0143 MatrixStorage* matrixStorage; 0144 NamedAreaStorage* namedAreaStorage; 0145 StyleStorage* styleStorage; 0146 UserInputStorage* userInputStorage; 0147 ValidityStorage* validityStorage; 0148 ValueStorage* valueStorage; 0149 RichTextStorage* richTextStorage; 0150 RowRepeatStorage* rowRepeatStorage; 0151 CellStorageUndoData* undoData; 0152 0153 #ifdef CALLIGRA_SHEETS_MT 0154 QReadWriteLock bigUglyLock; 0155 #endif 0156 }; 0157 0158 void CellStorage::Private::createCommand(KUndo2Command *parent) const 0159 { 0160 if (!undoData->bindings.isEmpty()) { 0161 RectStorageUndoCommand<Binding> *const command 0162 = new RectStorageUndoCommand<Binding>(sheet->model(), SourceRangeRole, parent); 0163 command->add(undoData->bindings); 0164 } 0165 if (!undoData->comments.isEmpty()) { 0166 RectStorageUndoCommand<QString> *const command 0167 = new RectStorageUndoCommand<QString>(sheet->model(), CommentRole, parent); 0168 command->add(undoData->comments); 0169 } 0170 if (!undoData->conditions.isEmpty()) { 0171 RectStorageUndoCommand<Conditions> *const command 0172 = new RectStorageUndoCommand<Conditions>(sheet->model(), ConditionRole, parent); 0173 command->add(undoData->conditions); 0174 } 0175 if (!undoData->databases.isEmpty()) { 0176 RectStorageUndoCommand<Database> *const command 0177 = new RectStorageUndoCommand<Database>(sheet->model(), TargetRangeRole, parent); 0178 command->add(undoData->databases); 0179 } 0180 if (!undoData->formulas.isEmpty()) { 0181 PointStorageUndoCommand<Formula> *const command 0182 = new PointStorageUndoCommand<Formula>(sheet->model(), FormulaRole, parent); 0183 command->add(undoData->formulas); 0184 } 0185 if (!undoData->fusions.isEmpty()) { 0186 RectStorageUndoCommand<bool> *const command 0187 = new RectStorageUndoCommand<bool>(sheet->model(), FusionedRangeRole, parent); 0188 command->add(undoData->fusions); 0189 } 0190 if (!undoData->links.isEmpty()) { 0191 PointStorageUndoCommand<QString> *const command 0192 = new PointStorageUndoCommand<QString>(sheet->model(), LinkRole, parent); 0193 command->add(undoData->links); 0194 } 0195 if (!undoData->matrices.isEmpty()) { 0196 RectStorageUndoCommand<bool> *const command 0197 = new RectStorageUndoCommand<bool>(sheet->model(), LockedRangeRole, parent); 0198 command->add(undoData->matrices); 0199 } 0200 if (!undoData->namedAreas.isEmpty()) { 0201 RectStorageUndoCommand<QString> *const command 0202 = new RectStorageUndoCommand<QString>(sheet->model(), NamedAreaRole, parent); 0203 command->add(undoData->namedAreas); 0204 } 0205 if (!undoData->richTexts.isEmpty()) { 0206 PointStorageUndoCommand<QSharedPointer<QTextDocument> > *const command 0207 = new PointStorageUndoCommand<QSharedPointer<QTextDocument> >(sheet->model(), RichTextRole, parent); 0208 command->add(undoData->richTexts); 0209 } 0210 if (!undoData->styles.isEmpty()) { 0211 StyleStorageUndoCommand *const command 0212 = new StyleStorageUndoCommand(styleStorage, parent); 0213 command->add(undoData->styles); 0214 } 0215 if (!undoData->userInputs.isEmpty()) { 0216 PointStorageUndoCommand<QString> *const command 0217 = new PointStorageUndoCommand<QString>(sheet->model(), UserInputRole, parent); 0218 command->add(undoData->userInputs); 0219 } 0220 if (!undoData->validities.isEmpty()) { 0221 RectStorageUndoCommand<Validity> *const command 0222 = new RectStorageUndoCommand<Validity>(sheet->model(), ValidityRole, parent); 0223 command->add(undoData->validities); 0224 } 0225 if (!undoData->values.isEmpty()) { 0226 PointStorageUndoCommand<Value> *const command 0227 = new PointStorageUndoCommand<Value>(sheet->model(), ValueRole, parent); 0228 command->add(undoData->values); 0229 } 0230 } 0231 0232 0233 CellStorage::CellStorage(Sheet* sheet) 0234 : QObject(sheet) 0235 , d(new Private(sheet)) 0236 { 0237 } 0238 0239 CellStorage::CellStorage(const CellStorage& other) 0240 : QObject(other.d->sheet) 0241 , d(new Private(*other.d, other.d->sheet)) 0242 { 0243 } 0244 0245 CellStorage::CellStorage(const CellStorage& other, Sheet* sheet) 0246 : QObject(sheet) 0247 , d(new Private(*other.d, sheet)) 0248 { 0249 } 0250 0251 CellStorage::~CellStorage() 0252 { 0253 delete d; 0254 } 0255 0256 Sheet* CellStorage::sheet() const 0257 { 0258 return d->sheet; 0259 } 0260 0261 void CellStorage::take(int col, int row) 0262 { 0263 #ifdef CALLIGRA_SHEETS_MT 0264 QWriteLocker(&d->bigUglyLock); 0265 #endif 0266 0267 Formula oldFormula; 0268 QString oldLink; 0269 QString oldUserInput; 0270 Value oldValue; 0271 QSharedPointer<QTextDocument> oldRichText; 0272 0273 oldFormula = d->formulaStorage->take(col, row); 0274 oldLink = d->linkStorage->take(col, row); 0275 oldUserInput = d->userInputStorage->take(col, row); 0276 oldValue = d->valueStorage->take(col, row); 0277 oldRichText = d->richTextStorage->take(col, row); 0278 0279 if (!d->sheet->map()->isLoading()) { 0280 // Trigger a recalculation of the consuming cells. 0281 CellDamage::Changes changes = CellDamage:: Binding | CellDamage::Formula | CellDamage::Value; 0282 d->sheet->map()->addDamage(new CellDamage(Cell(d->sheet, col, row), changes)); 0283 0284 d->rowRepeatStorage->setRowRepeat(row, 1); 0285 } 0286 // also trigger a relayout of the first non-empty cell to the left of this cell 0287 int prevCol; 0288 Value v = d->valueStorage->prevInRow(col, row, &prevCol); 0289 if (!v.isEmpty()) 0290 d->sheet->map()->addDamage(new CellDamage(Cell(d->sheet, prevCol, row), CellDamage::Appearance)); 0291 0292 0293 // recording undo? 0294 if (d->undoData) { 0295 d->undoData->formulas << qMakePair(QPoint(col, row), oldFormula); 0296 d->undoData->links << qMakePair(QPoint(col, row), oldLink); 0297 d->undoData->userInputs << qMakePair(QPoint(col, row), oldUserInput); 0298 d->undoData->values << qMakePair(QPoint(col, row), oldValue); 0299 d->undoData->richTexts << qMakePair(QPoint(col, row), oldRichText); 0300 } 0301 } 0302 0303 Binding CellStorage::binding(int column, int row) const 0304 { 0305 #ifdef CALLIGRA_SHEETS_MT 0306 QReadLocker rl(&d->bigUglyLock); 0307 #endif 0308 return d->bindingStorage->contains(QPoint(column, row)); 0309 } 0310 0311 void CellStorage::setBinding(const Region& region, const Binding& binding) 0312 { 0313 #ifdef CALLIGRA_SHEETS_MT 0314 QWriteLocker(&d->bigUglyLock); 0315 #endif 0316 // recording undo? 0317 if (d->undoData) 0318 d->undoData->bindings << d->bindingStorage->undoData(region); 0319 0320 d->bindingStorage->insert(region, binding); 0321 } 0322 0323 void CellStorage::removeBinding(const Region& region, const Binding& binding) 0324 { 0325 #ifdef CALLIGRA_SHEETS_MT 0326 QWriteLocker(&d->bigUglyLock); 0327 #endif 0328 // recording undo? 0329 if (d->undoData) { 0330 d->undoData->bindings << d->bindingStorage->undoData(region); 0331 } 0332 d->bindingStorage->remove(region, binding); 0333 } 0334 0335 QString CellStorage::comment(int column, int row) const 0336 { 0337 #ifdef CALLIGRA_SHEETS_MT 0338 QReadLocker rl(&d->bigUglyLock); 0339 #endif 0340 return d->commentStorage->contains(QPoint(column, row)); 0341 } 0342 0343 void CellStorage::setComment(const Region& region, const QString& comment) 0344 { 0345 #ifdef CALLIGRA_SHEETS_MT 0346 QWriteLocker(&d->bigUglyLock); 0347 #endif 0348 // recording undo? 0349 if (d->undoData) 0350 d->undoData->comments << d->commentStorage->undoData(region); 0351 0352 d->commentStorage->insert(region, comment); 0353 if (!d->sheet->map()->isLoading()) { 0354 foreach (const QRect& r, region.rects()) { 0355 d->rowRepeatStorage->splitRowRepeat(r.top()); 0356 d->rowRepeatStorage->splitRowRepeat(r.bottom()+1); 0357 } 0358 } 0359 } 0360 0361 Conditions CellStorage::conditions(int column, int row) const 0362 { 0363 #ifdef CALLIGRA_SHEETS_MT 0364 QReadLocker rl(&d->bigUglyLock); 0365 #endif 0366 return d->conditionsStorage->contains(QPoint(column, row)); 0367 } 0368 0369 void CellStorage::setConditions(const Region& region, Conditions conditions) 0370 { 0371 #ifdef CALLIGRA_SHEETS_MT 0372 QWriteLocker(&d->bigUglyLock); 0373 #endif 0374 // recording undo? 0375 if (d->undoData) 0376 d->undoData->conditions << d->conditionsStorage->undoData(region); 0377 0378 d->conditionsStorage->insert(region, conditions); 0379 if (!d->sheet->map()->isLoading()) { 0380 foreach (const QRect& r, region.rects()) { 0381 d->rowRepeatStorage->splitRowRepeat(r.top()); 0382 d->rowRepeatStorage->splitRowRepeat(r.bottom()+1); 0383 } 0384 } 0385 } 0386 0387 Database CellStorage::database(int column, int row) const 0388 { 0389 #ifdef CALLIGRA_SHEETS_MT 0390 QReadLocker rl(&d->bigUglyLock); 0391 #endif 0392 QPair<QRectF, Database> pair = d->databaseStorage->containedPair(QPoint(column, row)); 0393 if (pair.first.isEmpty()) 0394 return Database(); 0395 if (pair.second.isEmpty()) 0396 return Database(); 0397 // update the range, which might get changed 0398 Database database = pair.second; 0399 database.setRange(Region(pair.first.toRect(), d->sheet)); 0400 return database; 0401 } 0402 0403 QList< QPair<QRectF, Database> > CellStorage::databases(const Region& region) const 0404 { 0405 #ifdef CALLIGRA_SHEETS_MT 0406 QReadLocker rl(&d->bigUglyLock); 0407 #endif 0408 return d->databaseStorage->intersectingPairs(region); 0409 } 0410 0411 void CellStorage::setDatabase(const Region& region, const Database& database) 0412 { 0413 #ifdef CALLIGRA_SHEETS_MT 0414 QWriteLocker(&d->bigUglyLock); 0415 #endif 0416 // recording undo? 0417 if (d->undoData) 0418 d->undoData->databases << d->databaseStorage->undoData(region); 0419 0420 d->databaseStorage->insert(region, database); 0421 } 0422 0423 Formula CellStorage::formula(int column, int row) const 0424 { 0425 #ifdef CALLIGRA_SHEETS_MT 0426 QReadLocker rl(&d->bigUglyLock); 0427 #endif 0428 return d->formulaStorage->lookup(column, row, Formula::empty()); 0429 } 0430 0431 void CellStorage::setFormula(int column, int row, const Formula& formula) 0432 { 0433 #ifdef CALLIGRA_SHEETS_MT 0434 QWriteLocker(&d->bigUglyLock); 0435 #endif 0436 Formula old = Formula::empty(); 0437 if (formula.expression().isEmpty()) 0438 old = d->formulaStorage->take(column, row, Formula::empty()); 0439 else 0440 old = d->formulaStorage->insert(column, row, formula); 0441 0442 // formula changed? 0443 if (formula != old) { 0444 if (!d->sheet->map()->isLoading()) { 0445 // trigger an update of the dependencies and a recalculation 0446 d->sheet->map()->addDamage(new CellDamage(Cell(d->sheet, column, row), CellDamage::Formula | CellDamage::Value)); 0447 d->rowRepeatStorage->setRowRepeat(row, 1); 0448 } 0449 // recording undo? 0450 if (d->undoData) { 0451 d->undoData->formulas << qMakePair(QPoint(column, row), old); 0452 // Also store the old value, if there wasn't a formula before, 0453 // because the new value is calculated later by the damage 0454 // processing and is not recorded for undoing. 0455 if (old == Formula()) 0456 d->undoData->values << qMakePair(QPoint(column, row), value(column, row)); 0457 } 0458 } 0459 } 0460 0461 QString CellStorage::link(int column, int row) const 0462 { 0463 #ifdef CALLIGRA_SHEETS_MT 0464 QReadLocker rl(&d->bigUglyLock); 0465 #endif 0466 return d->linkStorage->lookup(column, row); 0467 } 0468 0469 void CellStorage::setLink(int column, int row, const QString& link) 0470 { 0471 #ifdef CALLIGRA_SHEETS_MT 0472 QWriteLocker(&d->bigUglyLock); 0473 #endif 0474 QString old; 0475 if (link.isEmpty()) 0476 old = d->linkStorage->take(column, row); 0477 else 0478 old = d->linkStorage->insert(column, row, link); 0479 0480 // recording undo? 0481 if (d->undoData && link != old) 0482 d->undoData->links << qMakePair(QPoint(column, row), old); 0483 if (!d->sheet->map()->isLoading()) 0484 d->rowRepeatStorage->setRowRepeat(row, 1); 0485 } 0486 0487 QString CellStorage::namedArea(int column, int row) const 0488 { 0489 #ifdef CALLIGRA_SHEETS_MT 0490 QReadLocker rl(&d->bigUglyLock); 0491 #endif 0492 QPair<QRectF, QString> pair = d->namedAreaStorage->containedPair(QPoint(column, row)); 0493 if (pair.first.isEmpty()) 0494 return QString(); 0495 if (pair.second.isEmpty()) 0496 return QString(); 0497 return pair.second; 0498 } 0499 0500 QList< QPair<QRectF, QString> > CellStorage::namedAreas(const Region& region) const 0501 { 0502 #ifdef CALLIGRA_SHEETS_MT 0503 QReadLocker rl(&d->bigUglyLock); 0504 #endif 0505 return d->namedAreaStorage->intersectingPairs(region); 0506 } 0507 0508 void CellStorage::setNamedArea(const Region& region, const QString& namedArea) 0509 { 0510 #ifdef CALLIGRA_SHEETS_MT 0511 QWriteLocker(&d->bigUglyLock); 0512 #endif 0513 // recording undo? 0514 if (d->undoData) 0515 d->undoData->namedAreas << d->namedAreaStorage->undoData(region); 0516 0517 d->namedAreaStorage->insert(region, namedArea); 0518 } 0519 0520 void CellStorage::removeNamedArea(const Region& region, const QString& namedArea) 0521 { 0522 #ifdef CALLIGRA_SHEETS_MT 0523 QWriteLocker(&d->bigUglyLock); 0524 #endif 0525 // recording undo? 0526 if (d->undoData) 0527 d->undoData->namedAreas << d->namedAreaStorage->undoData(region); 0528 0529 d->namedAreaStorage->remove(region, namedArea); 0530 } 0531 0532 0533 void CellStorage::emitInsertNamedArea(const Region ®ion, const QString &namedArea) 0534 { 0535 emit insertNamedArea(region, namedArea); 0536 } 0537 0538 Style CellStorage::style(int column, int row) const 0539 { 0540 #ifdef CALLIGRA_SHEETS_MT 0541 QReadLocker rl(&d->bigUglyLock); 0542 #endif 0543 return d->styleStorage->contains(QPoint(column, row)); 0544 } 0545 0546 Style CellStorage::style(const QRect& rect) const 0547 { 0548 #ifdef CALLIGRA_SHEETS_MT 0549 QReadLocker rl(&d->bigUglyLock); 0550 #endif 0551 return d->styleStorage->contains(rect); 0552 } 0553 0554 void CellStorage::setStyle(const Region& region, const Style& style) 0555 { 0556 #ifdef CALLIGRA_SHEETS_MT 0557 QWriteLocker(&d->bigUglyLock); 0558 #endif 0559 // recording undo? 0560 if (d->undoData) 0561 d->undoData->styles << d->styleStorage->undoData(region); 0562 0563 d->styleStorage->insert(region, style); 0564 if (!d->sheet->map()->isLoading()) { 0565 foreach (const QRect& r, region.rects()) { 0566 d->rowRepeatStorage->splitRowRepeat(r.top()); 0567 d->rowRepeatStorage->splitRowRepeat(r.bottom()+1); 0568 } 0569 } 0570 } 0571 0572 void CellStorage::insertSubStyle(const QRect &rect, const SharedSubStyle &subStyle) 0573 { 0574 #ifdef CALLIGRA_SHEETS_MT 0575 QWriteLocker(&d->bigUglyLock); 0576 #endif 0577 d->styleStorage->insert(rect, subStyle); 0578 if (!d->sheet->map()->isLoading()) { 0579 d->rowRepeatStorage->splitRowRepeat(rect.top()); 0580 d->rowRepeatStorage->splitRowRepeat(rect.bottom()+1); 0581 } 0582 } 0583 0584 QString CellStorage::userInput(int column, int row) const 0585 { 0586 #ifdef CALLIGRA_SHEETS_MT 0587 QReadLocker rl(&d->bigUglyLock); 0588 #endif 0589 return d->userInputStorage->lookup(column, row); 0590 } 0591 0592 void CellStorage::setUserInput(int column, int row, const QString& userInput) 0593 { 0594 #ifdef CALLIGRA_SHEETS_MT 0595 QWriteLocker(&d->bigUglyLock); 0596 #endif 0597 QString old; 0598 if (userInput.isEmpty()) 0599 old = d->userInputStorage->take(column, row); 0600 else 0601 old = d->userInputStorage->insert(column, row, userInput); 0602 0603 // recording undo? 0604 if (d->undoData && userInput != old) 0605 d->undoData->userInputs << qMakePair(QPoint(column, row), old); 0606 if (!d->sheet->map()->isLoading()) 0607 d->rowRepeatStorage->setRowRepeat(row, 1); 0608 } 0609 0610 QSharedPointer<QTextDocument> CellStorage::richText(int column, int row) const 0611 { 0612 #ifdef CALLIGRA_SHEETS_MT 0613 QReadLocker rl(&d->bigUglyLock); 0614 #endif 0615 return d->richTextStorage->lookup(column, row); 0616 } 0617 0618 void CellStorage::setRichText(int column, int row, QSharedPointer<QTextDocument> text) 0619 { 0620 #ifdef CALLIGRA_SHEETS_MT 0621 QWriteLocker(&d->bigUglyLock); 0622 #endif 0623 QSharedPointer<QTextDocument> old; 0624 if (text.isNull()) 0625 old = d->richTextStorage->take(column, row); 0626 else 0627 old = d->richTextStorage->insert(column, row, text); 0628 0629 // recording undo? 0630 if (d->undoData && text != old) 0631 d->undoData->richTexts << qMakePair(QPoint(column, row), old); 0632 } 0633 0634 Validity CellStorage::validity(int column, int row) const 0635 { 0636 #ifdef CALLIGRA_SHEETS_MT 0637 QReadLocker rl(&d->bigUglyLock); 0638 #endif 0639 return d->validityStorage->contains(QPoint(column, row)); 0640 } 0641 0642 void CellStorage::setValidity(const Region& region, Validity validity) 0643 { 0644 #ifdef CALLIGRA_SHEETS_MT 0645 QWriteLocker(&d->bigUglyLock); 0646 #endif 0647 // recording undo? 0648 if (d->undoData) 0649 d->undoData->validities << d->validityStorage->undoData(region); 0650 0651 d->validityStorage->insert(region, validity); 0652 if (!d->sheet->map()->isLoading()) { 0653 foreach (const QRect& r, region.rects()) { 0654 d->rowRepeatStorage->splitRowRepeat(r.top()); 0655 d->rowRepeatStorage->splitRowRepeat(r.bottom()+1); 0656 } 0657 } 0658 } 0659 0660 Value CellStorage::value(int column, int row) const 0661 { 0662 #ifdef CALLIGRA_SHEETS_MT 0663 QReadLocker rl(&d->bigUglyLock); 0664 #endif 0665 return d->valueStorage->lookup(column, row); 0666 } 0667 0668 Value CellStorage::valueRegion(const Region& region) const 0669 { 0670 #ifdef CALLIGRA_SHEETS_MT 0671 QReadLocker rl(&d->bigUglyLock); 0672 #endif 0673 // create a subStorage with adjusted origin 0674 return Value(d->valueStorage->subStorage(region, false), region.boundingRect().size()); 0675 } 0676 0677 void CellStorage::setValue(int column, int row, const Value& value) 0678 { 0679 #ifdef CALLIGRA_SHEETS_MT 0680 QWriteLocker(&d->bigUglyLock); 0681 #endif 0682 // release any lock 0683 unlockCells(column, row); 0684 0685 Value old; 0686 if (value.isEmpty()) 0687 old = d->valueStorage->take(column, row); 0688 else 0689 old = d->valueStorage->insert(column, row, value); 0690 0691 // value changed? 0692 if (value != old) { 0693 if (!d->sheet->map()->isLoading()) { 0694 // Always trigger a repainting and a binding update. 0695 CellDamage::Changes changes = CellDamage::Appearance | CellDamage::Binding; 0696 // Trigger a recalculation of the consuming cells, only if we are not 0697 // already in a recalculation process. 0698 if (!d->sheet->map()->recalcManager()->isActive()) 0699 changes |= CellDamage::Value; 0700 d->sheet->map()->addDamage(new CellDamage(Cell(d->sheet, column, row), changes)); 0701 // Also trigger a relayouting of the first non-empty cell to the left of this one 0702 int prevCol; 0703 Value v = d->valueStorage->prevInRow(column, row, &prevCol); 0704 if (!v.isEmpty()) 0705 d->sheet->map()->addDamage(new CellDamage(Cell(d->sheet, prevCol, row), CellDamage::Appearance)); 0706 d->rowRepeatStorage->setRowRepeat(row, 1); 0707 } 0708 // recording undo? 0709 if (d->undoData) 0710 d->undoData->values << qMakePair(QPoint(column, row), old); 0711 } 0712 } 0713 0714 bool CellStorage::doesMergeCells(int column, int row) const 0715 { 0716 #ifdef CALLIGRA_SHEETS_MT 0717 QReadLocker rl(&d->bigUglyLock); 0718 #endif 0719 const QPair<QRectF, bool> pair = d->fusionStorage->containedPair(QPoint(column, row)); 0720 if (pair.first.isNull()) 0721 return false; 0722 if (pair.second == false) 0723 return false; 0724 // master cell? 0725 if (pair.first.toRect().topLeft() != QPoint(column, row)) 0726 return false; 0727 return true; 0728 } 0729 0730 bool CellStorage::isPartOfMerged(int column, int row) const 0731 { 0732 #ifdef CALLIGRA_SHEETS_MT 0733 QReadLocker rl(&d->bigUglyLock); 0734 #endif 0735 const QPair<QRectF, bool> pair = d->fusionStorage->containedPair(QPoint(column, row)); 0736 if (pair.first.isNull()) 0737 return false; 0738 if (pair.second == false) 0739 return false; 0740 // master cell? 0741 if (pair.first.toRect().topLeft() == QPoint(column, row)) 0742 return false; 0743 return true; 0744 } 0745 0746 void CellStorage::mergeCells(int column, int row, int numXCells, int numYCells) 0747 { 0748 #ifdef CALLIGRA_SHEETS_MT 0749 QWriteLocker(&d->bigUglyLock); 0750 #endif 0751 // Start by unmerging the cells that we merge right now 0752 const QPair<QRectF, bool> pair = d->fusionStorage->containedPair(QPoint(column, row)); 0753 if (!pair.first.isNull()) 0754 d->fusionStorage->insert(Region(pair.first.toRect()), false); 0755 // Merge the cells 0756 if (numXCells != 0 || numYCells != 0) 0757 d->fusionStorage->insert(Region(column, row, numXCells + 1, numYCells + 1), true); 0758 if (!d->sheet->map()->isLoading()) 0759 d->rowRepeatStorage->setRowRepeat(row, 1); 0760 } 0761 0762 Cell CellStorage::masterCell(int column, int row) const 0763 { 0764 #ifdef CALLIGRA_SHEETS_MT 0765 QReadLocker rl(&d->bigUglyLock); 0766 #endif 0767 const QPair<QRectF, bool> pair = d->fusionStorage->containedPair(QPoint(column, row)); 0768 if (pair.first.isNull()) 0769 return Cell(d->sheet, column, row); 0770 if (pair.second == false) 0771 return Cell(d->sheet, column, row); 0772 return Cell(d->sheet, pair.first.toRect().topLeft()); 0773 } 0774 0775 int CellStorage::mergedXCells(int column, int row) const 0776 { 0777 #ifdef CALLIGRA_SHEETS_MT 0778 QReadLocker rl(&d->bigUglyLock); 0779 #endif 0780 const QPair<QRectF, bool> pair = d->fusionStorage->containedPair(QPoint(column, row)); 0781 if (pair.first.isNull()) 0782 return 0; 0783 // Not the master cell? 0784 if (pair.first.topLeft() != QPoint(column, row)) 0785 return 0; 0786 return pair.first.toRect().width() - 1; 0787 } 0788 0789 int CellStorage::mergedYCells(int column, int row) const 0790 { 0791 #ifdef CALLIGRA_SHEETS_MT 0792 QReadLocker rl(&d->bigUglyLock); 0793 #endif 0794 const QPair<QRectF, bool> pair = d->fusionStorage->containedPair(QPoint(column, row)); 0795 if (pair.first.isNull()) 0796 return 0; 0797 // Not the master cell? 0798 if (pair.first.topLeft() != QPoint(column, row)) 0799 return 0; 0800 return pair.first.toRect().height() - 1; 0801 } 0802 0803 QList<Cell> CellStorage::masterCells(const Region& region) const 0804 { 0805 #ifdef CALLIGRA_SHEETS_MT 0806 QReadLocker rl(&d->bigUglyLock); 0807 #endif 0808 const QList<QPair<QRectF, bool> > pairs = d->fusionStorage->intersectingPairs(region); 0809 if (pairs.isEmpty()) 0810 return QList<Cell>(); 0811 QList<Cell> masterCells; 0812 for (int i = 0; i < pairs.count(); ++i) { 0813 if (pairs[i].first.isNull()) 0814 continue; 0815 if (pairs[i].second == false) 0816 continue; 0817 masterCells.append(Cell(d->sheet, pairs[i].first.toRect().topLeft())); 0818 } 0819 return masterCells; 0820 } 0821 0822 bool CellStorage::locksCells(int column, int row) const 0823 { 0824 #ifdef CALLIGRA_SHEETS_MT 0825 QReadLocker rl(&d->bigUglyLock); 0826 #endif 0827 const QPair<QRectF, bool> pair = d->matrixStorage->containedPair(QPoint(column, row)); 0828 if (pair.first.isNull()) 0829 return false; 0830 if (pair.second == false) 0831 return false; 0832 // master cell? 0833 if (pair.first.toRect().topLeft() != QPoint(column, row)) 0834 return false; 0835 return true; 0836 } 0837 0838 bool CellStorage::isLocked(int column, int row) const 0839 { 0840 #ifdef CALLIGRA_SHEETS_MT 0841 QReadLocker rl(&d->bigUglyLock); 0842 #endif 0843 const QPair<QRectF, bool> pair = d->matrixStorage->containedPair(QPoint(column, row)); 0844 if (pair.first.isNull()) 0845 return false; 0846 if (pair.second == false) 0847 return false; 0848 // master cell? 0849 if (pair.first.toRect().topLeft() == QPoint(column, row)) 0850 return false; 0851 return true; 0852 } 0853 0854 bool CellStorage::hasLockedCells(const Region& region) const 0855 { 0856 #ifdef CALLIGRA_SHEETS_MT 0857 QReadLocker rl(&d->bigUglyLock); 0858 #endif 0859 typedef QPair<QRectF, bool> RectBoolPair; 0860 QList<QPair<QRectF, bool> > pairs = d->matrixStorage->intersectingPairs(region); 0861 foreach (const RectBoolPair& pair, pairs) { 0862 if (pair.first.isNull()) 0863 continue; 0864 if (pair.second == false) 0865 continue; 0866 // more than just the master cell in the region? 0867 const QPoint topLeft = pair.first.toRect().topLeft(); 0868 if (pair.first.width() >= 1) { 0869 if (region.contains(topLeft + QPoint(1, 0), d->sheet)) 0870 return true; 0871 } 0872 if (pair.first.height() >= 1) { 0873 if (region.contains(topLeft + QPoint(0, 1), d->sheet)) 0874 return true; 0875 } 0876 } 0877 return false; 0878 } 0879 0880 void CellStorage::lockCells(const QRect& rect) 0881 { 0882 #ifdef CALLIGRA_SHEETS_MT 0883 QWriteLocker(&d->bigUglyLock); 0884 #endif 0885 // Start by unlocking the cells that we lock right now 0886 const QPair<QRectF, bool> pair = d->matrixStorage->containedPair(rect.topLeft()); // FIXME 0887 if (!pair.first.isNull()) 0888 d->matrixStorage->insert(Region(pair.first.toRect()), false); 0889 // Lock the cells 0890 if (rect.width() > 1 || rect.height() > 1) 0891 d->matrixStorage->insert(Region(rect), true); 0892 } 0893 0894 void CellStorage::unlockCells(int column, int row) 0895 { 0896 #ifdef CALLIGRA_SHEETS_MT 0897 QWriteLocker(&d->bigUglyLock); 0898 #endif 0899 const QPair<QRectF, bool> pair = d->matrixStorage->containedPair(QPoint(column, row)); 0900 if (pair.first.isNull()) 0901 return; 0902 if (pair.second == false) 0903 return; 0904 if (pair.first.toRect().topLeft() != QPoint(column, row)) 0905 return; 0906 const QRect rect = pair.first.toRect(); 0907 d->matrixStorage->insert(Region(rect), false); 0908 // clear the values 0909 for (int r = rect.top(); r <= rect.bottom(); ++r) { 0910 for (int c = rect.left(); c <= rect.right(); ++c) { 0911 if (r != rect.top() || c != rect.left()) 0912 setValue(c, r, Value()); 0913 } 0914 } 0915 // recording undo? 0916 if (d->undoData) 0917 d->undoData->matrices << pair; 0918 } 0919 0920 QRect CellStorage::lockedCells(int column, int row) const 0921 { 0922 #ifdef CALLIGRA_SHEETS_MT 0923 QReadLocker rl(&d->bigUglyLock); 0924 #endif 0925 const QPair<QRectF, bool> pair = d->matrixStorage->containedPair(QPoint(column, row)); 0926 if (pair.first.isNull()) 0927 return QRect(column, row, 1, 1); 0928 if (pair.second == false) 0929 return QRect(column, row, 1, 1); 0930 if (pair.first.toRect().topLeft() != QPoint(column, row)) 0931 return QRect(column, row, 1, 1); 0932 return pair.first.toRect(); 0933 } 0934 0935 void CellStorage::insertColumns(int position, int number) 0936 { 0937 #ifdef CALLIGRA_SHEETS_MT 0938 QWriteLocker(&d->bigUglyLock); 0939 #endif 0940 // Trigger a dependency update of the cells, which have a formula. (old positions) 0941 // FIXME Stefan: Would it be better to directly alter the dependency tree? 0942 // TODO Stefan: Optimize: Avoid the double creation of the sub-storages, but don't process 0943 // formulas, that will get out of bounds after the operation. 0944 const Region invalidRegion(QRect(QPoint(position, 1), QPoint(KS_colMax, KS_rowMax)), d->sheet); 0945 PointStorage<Formula> subStorage = d->formulaStorage->subStorage(invalidRegion); 0946 Cell cell; 0947 for (int i = 0; i < subStorage.count(); ++i) { 0948 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i)); 0949 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula)); 0950 } 0951 // Trigger an update of the bindings and the named areas. 0952 d->sheet->map()->addDamage(new CellDamage(d->sheet, invalidRegion, CellDamage::Binding | CellDamage::NamedArea)); 0953 0954 QList< QPair<QRectF, Binding> > bindings = d->bindingStorage->insertColumns(position, number); 0955 QList< QPair<QRectF, QString> > comments = d->commentStorage->insertColumns(position, number); 0956 QList< QPair<QRectF, Conditions> > conditions = d->conditionsStorage->insertColumns(position, number); 0957 QList< QPair<QRectF, Database> > databases = d->databaseStorage->insertColumns(position, number); 0958 QVector< QPair<QPoint, Formula> > formulas = d->formulaStorage->insertColumns(position, number); 0959 QList< QPair<QRectF, bool> > fusions = d->fusionStorage->insertColumns(position, number); 0960 QVector< QPair<QPoint, QString> > links = d->linkStorage->insertColumns(position, number); 0961 QList< QPair<QRectF, bool> > matrices = d->matrixStorage->insertColumns(position, number); 0962 QList< QPair<QRectF, QString> > namedAreas = d->namedAreaStorage->insertColumns(position, number); 0963 QList< QPair<QRectF, SharedSubStyle> > styles = d->styleStorage->insertColumns(position, number); 0964 QVector< QPair<QPoint, QString> > userInputs = d->userInputStorage->insertColumns(position, number); 0965 QVector< QPair<QPoint, QSharedPointer<QTextDocument> > > richTexts = d->richTextStorage->insertColumns(position, number); 0966 QList< QPair<QRectF, Validity> > validities = d->validityStorage->insertColumns(position, number); 0967 QVector< QPair<QPoint, Value> > values = d->valueStorage->insertColumns(position, number); 0968 // recording undo? 0969 if (d->undoData) { 0970 d->undoData->bindings << bindings; 0971 d->undoData->comments << comments; 0972 d->undoData->conditions << conditions; 0973 d->undoData->databases << databases; 0974 d->undoData->formulas << formulas; 0975 d->undoData->fusions << fusions; 0976 d->undoData->links << links; 0977 d->undoData->matrices << matrices; 0978 d->undoData->namedAreas << namedAreas; 0979 d->undoData->styles << styles; 0980 d->undoData->userInputs << userInputs; 0981 d->undoData->validities << validities; 0982 d->undoData->values << values; 0983 d->undoData->richTexts << richTexts; 0984 } 0985 0986 // Trigger a dependency update of the cells, which have a formula. (new positions) 0987 subStorage = d->formulaStorage->subStorage(invalidRegion); 0988 for (int i = 0; i < subStorage.count(); ++i) { 0989 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i)); 0990 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula)); 0991 } 0992 // Trigger a recalculation only for the cells, that depend on values in the changed region. 0993 Region providers = d->sheet->map()->dependencyManager()->reduceToProvidingRegion(invalidRegion); 0994 d->sheet->map()->addDamage(new CellDamage(d->sheet, providers, CellDamage::Value)); 0995 } 0996 0997 void CellStorage::removeColumns(int position, int number) 0998 { 0999 #ifdef CALLIGRA_SHEETS_MT 1000 QWriteLocker(&d->bigUglyLock); 1001 #endif 1002 // Trigger a dependency update of the cells, which have a formula. (old positions) 1003 const Region invalidRegion(QRect(QPoint(position, 1), QPoint(KS_colMax, KS_rowMax)), d->sheet); 1004 PointStorage<Formula> subStorage = d->formulaStorage->subStorage(invalidRegion); 1005 Cell cell; 1006 for (int i = 0; i < subStorage.count(); ++i) { 1007 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i)); 1008 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula)); 1009 } 1010 // Trigger an update of the bindings and the named areas. 1011 const Region region(QRect(QPoint(position - 1, 1), QPoint(KS_colMax, KS_rowMax)), d->sheet); 1012 d->sheet->map()->addDamage(new CellDamage(d->sheet, region, CellDamage::Binding | CellDamage::NamedArea)); 1013 1014 QList< QPair<QRectF, Binding> > bindings = d->bindingStorage->removeColumns(position, number); 1015 QList< QPair<QRectF, QString> > comments = d->commentStorage->removeColumns(position, number); 1016 QList< QPair<QRectF, Conditions> > conditions = d->conditionsStorage->removeColumns(position, number); 1017 QList< QPair<QRectF, Database> > databases = d->databaseStorage->removeColumns(position, number); 1018 QVector< QPair<QPoint, Formula> > formulas = d->formulaStorage->removeColumns(position, number); 1019 QList< QPair<QRectF, bool> > fusions = d->fusionStorage->removeColumns(position, number); 1020 QVector< QPair<QPoint, QString> > links = d->linkStorage->removeColumns(position, number); 1021 QList< QPair<QRectF, bool> > matrices = d->matrixStorage->removeColumns(position, number); 1022 QList< QPair<QRectF, QString> > namedAreas = d->namedAreaStorage->removeColumns(position, number); 1023 QList< QPair<QRectF, SharedSubStyle> > styles = d->styleStorage->removeColumns(position, number); 1024 QVector< QPair<QPoint, QString> > userInputs = d->userInputStorage->removeColumns(position, number); 1025 QList< QPair<QRectF, Validity> > validities = d->validityStorage->removeColumns(position, number); 1026 QVector< QPair<QPoint, Value> > values = d->valueStorage->removeColumns(position, number); 1027 QVector< QPair<QPoint, QSharedPointer<QTextDocument> > > richTexts = d->richTextStorage->removeColumns(position, number); 1028 // recording undo? 1029 if (d->undoData) { 1030 d->undoData->bindings << bindings; 1031 d->undoData->comments << comments; 1032 d->undoData->conditions << conditions; 1033 d->undoData->databases << databases; 1034 d->undoData->formulas << formulas; 1035 d->undoData->fusions << fusions; 1036 d->undoData->links << links; 1037 d->undoData->matrices << matrices; 1038 d->undoData->namedAreas << namedAreas; 1039 d->undoData->styles << styles; 1040 d->undoData->userInputs << userInputs; 1041 d->undoData->validities << validities; 1042 d->undoData->values << values; 1043 d->undoData->richTexts << richTexts; 1044 } 1045 1046 // Trigger a dependency update of the cells, which have a formula. (new positions) 1047 subStorage = d->formulaStorage->subStorage(invalidRegion); 1048 for (int i = 0; i < subStorage.count(); ++i) { 1049 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i)); 1050 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula)); 1051 } 1052 // Trigger a recalculation only for the cells, that depend on values in the changed region. 1053 Region providers = d->sheet->map()->dependencyManager()->reduceToProvidingRegion(invalidRegion); 1054 d->sheet->map()->addDamage(new CellDamage(d->sheet, providers, CellDamage::Value)); 1055 } 1056 1057 void CellStorage::insertRows(int position, int number) 1058 { 1059 #ifdef CALLIGRA_SHEETS_MT 1060 QWriteLocker(&d->bigUglyLock); 1061 #endif 1062 // Trigger a dependency update of the cells, which have a formula. (old positions) 1063 const Region invalidRegion(QRect(QPoint(1, position), QPoint(KS_colMax, KS_rowMax)), d->sheet); 1064 PointStorage<Formula> subStorage = d->formulaStorage->subStorage(invalidRegion); 1065 Cell cell; 1066 for (int i = 0; i < subStorage.count(); ++i) { 1067 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i)); 1068 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula)); 1069 } 1070 // Trigger an update of the bindings and the named areas. 1071 d->sheet->map()->addDamage(new CellDamage(d->sheet, invalidRegion, CellDamage::Binding | CellDamage::NamedArea)); 1072 1073 QList< QPair<QRectF, Binding> > bindings = d->bindingStorage->insertRows(position, number); 1074 QList< QPair<QRectF, QString> > comments = d->commentStorage->insertRows(position, number); 1075 QList< QPair<QRectF, Conditions> > conditions = d->conditionsStorage->insertRows(position, number); 1076 QList< QPair<QRectF, Database> > databases = d->databaseStorage->insertRows(position, number); 1077 QVector< QPair<QPoint, Formula> > formulas = d->formulaStorage->insertRows(position, number); 1078 QList< QPair<QRectF, bool> > fusions = d->fusionStorage->insertRows(position, number); 1079 QVector< QPair<QPoint, QString> > links = d->linkStorage->insertRows(position, number); 1080 QList< QPair<QRectF, bool> > matrices = d->matrixStorage->insertRows(position, number); 1081 QList< QPair<QRectF, QString> > namedAreas = d->namedAreaStorage->insertRows(position, number); 1082 QList< QPair<QRectF, SharedSubStyle> > styles = d->styleStorage->insertRows(position, number); 1083 QVector< QPair<QPoint, QString> > userInputs = d->userInputStorage->insertRows(position, number); 1084 QList< QPair<QRectF, Validity> > validities = d->validityStorage->insertRows(position, number); 1085 QVector< QPair<QPoint, Value> > values = d->valueStorage->insertRows(position, number); 1086 QVector< QPair<QPoint, QSharedPointer<QTextDocument> > > richTexts = d->richTextStorage->insertRows(position, number); 1087 // recording undo? 1088 if (d->undoData) { 1089 d->undoData->bindings << bindings; 1090 d->undoData->comments << comments; 1091 d->undoData->conditions << conditions; 1092 d->undoData->databases << databases; 1093 d->undoData->formulas << formulas; 1094 d->undoData->fusions << fusions; 1095 d->undoData->links << links; 1096 d->undoData->matrices << matrices; 1097 d->undoData->namedAreas << namedAreas; 1098 d->undoData->styles << styles; 1099 d->undoData->userInputs << userInputs; 1100 d->undoData->validities << validities; 1101 d->undoData->values << values; 1102 d->undoData->richTexts << richTexts; 1103 } 1104 1105 // Trigger a dependency update of the cells, which have a formula. (new positions) 1106 subStorage = d->formulaStorage->subStorage(invalidRegion); 1107 for (int i = 0; i < subStorage.count(); ++i) { 1108 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i)); 1109 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula)); 1110 } 1111 // Trigger a recalculation only for the cells, that depend on values in the changed region. 1112 Region providers = d->sheet->map()->dependencyManager()->reduceToProvidingRegion(invalidRegion); 1113 d->sheet->map()->addDamage(new CellDamage(d->sheet, providers, CellDamage::Value)); 1114 1115 d->rowRepeatStorage->insertRows(position, number); 1116 } 1117 1118 void CellStorage::removeRows(int position, int number) 1119 { 1120 #ifdef CALLIGRA_SHEETS_MT 1121 QWriteLocker(&d->bigUglyLock); 1122 #endif 1123 // Trigger a dependency update of the cells, which have a formula. (old positions) 1124 const Region invalidRegion(QRect(QPoint(1, position), QPoint(KS_colMax, KS_rowMax)), d->sheet); 1125 PointStorage<Formula> subStorage = d->formulaStorage->subStorage(invalidRegion); 1126 Cell cell; 1127 for (int i = 0; i < subStorage.count(); ++i) { 1128 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i)); 1129 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula)); 1130 } 1131 // Trigger an update of the bindings and the named areas. 1132 const Region region(QRect(QPoint(1, position - 1), QPoint(KS_colMax, KS_rowMax)), d->sheet); 1133 d->sheet->map()->addDamage(new CellDamage(d->sheet, region, CellDamage::Binding | CellDamage::NamedArea)); 1134 1135 QList< QPair<QRectF, Binding> > bindings = d->bindingStorage->removeRows(position, number); 1136 QList< QPair<QRectF, QString> > comments = d->commentStorage->removeRows(position, number); 1137 QList< QPair<QRectF, Conditions> > conditions = d->conditionsStorage->removeRows(position, number); 1138 QList< QPair<QRectF, Database> > databases = d->databaseStorage->removeRows(position, number); 1139 QVector< QPair<QPoint, Formula> > formulas = d->formulaStorage->removeRows(position, number); 1140 QList< QPair<QRectF, bool> > fusions = d->fusionStorage->removeRows(position, number); 1141 QVector< QPair<QPoint, QString> > links = d->linkStorage->removeRows(position, number); 1142 QList< QPair<QRectF, bool> > matrices = d->matrixStorage->removeRows(position, number); 1143 QList< QPair<QRectF, QString> > namedAreas = d->namedAreaStorage->removeRows(position, number); 1144 QList< QPair<QRectF, SharedSubStyle> > styles = d->styleStorage->removeRows(position, number); 1145 QVector< QPair<QPoint, QString> > userInputs = d->userInputStorage->removeRows(position, number); 1146 QList< QPair<QRectF, Validity> > validities = d->validityStorage->removeRows(position, number); 1147 QVector< QPair<QPoint, Value> > values = d->valueStorage->removeRows(position, number); 1148 QVector< QPair<QPoint, QSharedPointer<QTextDocument> > > richTexts = d->richTextStorage->removeRows(position, number); 1149 // recording undo? 1150 if (d->undoData) { 1151 d->undoData->bindings << bindings; 1152 d->undoData->comments << comments; 1153 d->undoData->conditions << conditions; 1154 d->undoData->databases << databases; 1155 d->undoData->formulas << formulas; 1156 d->undoData->fusions << fusions; 1157 d->undoData->links << links; 1158 d->undoData->matrices << matrices; 1159 d->undoData->namedAreas << namedAreas; 1160 d->undoData->styles << styles; 1161 d->undoData->userInputs << userInputs; 1162 d->undoData->validities << validities; 1163 d->undoData->values << values; 1164 d->undoData->richTexts << richTexts; 1165 } 1166 1167 // Trigger a dependency update of the cells, which have a formula. (new positions) 1168 subStorage = d->formulaStorage->subStorage(invalidRegion); 1169 for (int i = 0; i < subStorage.count(); ++i) { 1170 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i)); 1171 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula)); 1172 } 1173 // Trigger a recalculation only for the cells, that depend on values in the changed region. 1174 Region providers = d->sheet->map()->dependencyManager()->reduceToProvidingRegion(invalidRegion); 1175 d->sheet->map()->addDamage(new CellDamage(d->sheet, providers, CellDamage::Value)); 1176 1177 d->rowRepeatStorage->removeRows(position, number); 1178 } 1179 1180 void CellStorage::removeShiftLeft(const QRect& rect) 1181 { 1182 #ifdef CALLIGRA_SHEETS_MT 1183 QWriteLocker(&d->bigUglyLock); 1184 #endif 1185 // Trigger a dependency update of the cells, which have a formula. (old positions) 1186 const Region invalidRegion(QRect(rect.topLeft(), QPoint(KS_colMax, rect.bottom())), d->sheet); 1187 PointStorage<Formula> subStorage = d->formulaStorage->subStorage(invalidRegion); 1188 Cell cell; 1189 for (int i = 0; i < subStorage.count(); ++i) { 1190 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i)); 1191 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula)); 1192 } 1193 // Trigger an update of the bindings and the named areas. 1194 const Region region(QRect(rect.topLeft() - QPoint(1, 0), QPoint(KS_colMax, rect.bottom())), d->sheet); 1195 d->sheet->map()->addDamage(new CellDamage(d->sheet, region, CellDamage::Binding | CellDamage::NamedArea)); 1196 1197 QList< QPair<QRectF, Binding> > bindings = d->bindingStorage->removeShiftLeft(rect); 1198 QList< QPair<QRectF, QString> > comments = d->commentStorage->removeShiftLeft(rect); 1199 QList< QPair<QRectF, Conditions> > conditions = d->conditionsStorage->removeShiftLeft(rect); 1200 QList< QPair<QRectF, Database> > databases = d->databaseStorage->removeShiftLeft(rect); 1201 QVector< QPair<QPoint, Formula> > formulas = d->formulaStorage->removeShiftLeft(rect); 1202 QList< QPair<QRectF, bool> > fusions = d->fusionStorage->removeShiftLeft(rect); 1203 QVector< QPair<QPoint, QString> > links = d->linkStorage->removeShiftLeft(rect); 1204 QList< QPair<QRectF, bool> > matrices = d->matrixStorage->removeShiftLeft(rect); 1205 QList< QPair<QRectF, QString> > namedAreas = d->namedAreaStorage->removeShiftLeft(rect); 1206 QList< QPair<QRectF, SharedSubStyle> > styles = d->styleStorage->removeShiftLeft(rect); 1207 QVector< QPair<QPoint, QString> > userInputs = d->userInputStorage->removeShiftLeft(rect); 1208 QList< QPair<QRectF, Validity> > validities = d->validityStorage->removeShiftLeft(rect); 1209 QVector< QPair<QPoint, Value> > values = d->valueStorage->removeShiftLeft(rect); 1210 QVector< QPair<QPoint, QSharedPointer<QTextDocument> > > richTexts = d->richTextStorage->removeShiftLeft(rect); 1211 // recording undo? 1212 if (d->undoData) { 1213 d->undoData->bindings << bindings; 1214 d->undoData->comments << comments; 1215 d->undoData->conditions << conditions; 1216 d->undoData->databases << databases; 1217 d->undoData->formulas << formulas; 1218 d->undoData->fusions << fusions; 1219 d->undoData->links << links; 1220 d->undoData->matrices << matrices; 1221 d->undoData->namedAreas << namedAreas; 1222 d->undoData->styles << styles; 1223 d->undoData->userInputs << userInputs; 1224 d->undoData->validities << validities; 1225 d->undoData->values << values; 1226 d->undoData->richTexts << richTexts; 1227 } 1228 1229 // Trigger a dependency update of the cells, which have a formula. (new positions) 1230 subStorage = d->formulaStorage->subStorage(invalidRegion); 1231 for (int i = 0; i < subStorage.count(); ++i) { 1232 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i)); 1233 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula)); 1234 } 1235 // Trigger a recalculation only for the cells, that depend on values in the changed region. 1236 Region providers = d->sheet->map()->dependencyManager()->reduceToProvidingRegion(invalidRegion); 1237 d->sheet->map()->addDamage(new CellDamage(d->sheet, providers, CellDamage::Value)); 1238 1239 d->rowRepeatStorage->removeShiftLeft(rect); 1240 } 1241 1242 void CellStorage::insertShiftRight(const QRect& rect) 1243 { 1244 #ifdef CALLIGRA_SHEETS_MT 1245 QWriteLocker(&d->bigUglyLock); 1246 #endif 1247 // Trigger a dependency update of the cells, which have a formula. (old positions) 1248 const Region invalidRegion(QRect(rect.topLeft(), QPoint(KS_colMax, rect.bottom())), d->sheet); 1249 PointStorage<Formula> subStorage = d->formulaStorage->subStorage(invalidRegion); 1250 Cell cell; 1251 for (int i = 0; i < subStorage.count(); ++i) { 1252 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i)); 1253 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula)); 1254 } 1255 // Trigger an update of the bindings and the named areas. 1256 d->sheet->map()->addDamage(new CellDamage(d->sheet, invalidRegion, CellDamage::Binding | CellDamage::NamedArea)); 1257 1258 QList< QPair<QRectF, Binding> > bindings = d->bindingStorage->insertShiftRight(rect); 1259 QList< QPair<QRectF, QString> > comments = d->commentStorage->insertShiftRight(rect); 1260 QList< QPair<QRectF, Conditions> > conditions = d->conditionsStorage->insertShiftRight(rect); 1261 QList< QPair<QRectF, Database> > databases = d->databaseStorage->insertShiftRight(rect); 1262 QVector< QPair<QPoint, Formula> > formulas = d->formulaStorage->insertShiftRight(rect); 1263 QList< QPair<QRectF, bool> > fusions = d->fusionStorage->insertShiftRight(rect); 1264 QVector< QPair<QPoint, QString> > links = d->linkStorage->insertShiftRight(rect); 1265 QList< QPair<QRectF, bool> > matrices = d->matrixStorage->insertShiftRight(rect); 1266 QList< QPair<QRectF, QString> > namedAreas = d->namedAreaStorage->insertShiftRight(rect); 1267 QList< QPair<QRectF, SharedSubStyle> > styles = d->styleStorage->insertShiftRight(rect); 1268 QVector< QPair<QPoint, QString> > userInputs = d->userInputStorage->insertShiftRight(rect); 1269 QList< QPair<QRectF, Validity> > validities = d->validityStorage->insertShiftRight(rect); 1270 QVector< QPair<QPoint, Value> > values = d->valueStorage->insertShiftRight(rect); 1271 QVector< QPair<QPoint, QSharedPointer<QTextDocument> > > richTexts = d->richTextStorage->insertShiftRight(rect); 1272 // recording undo? 1273 if (d->undoData) { 1274 d->undoData->bindings << bindings; 1275 d->undoData->comments << comments; 1276 d->undoData->conditions << conditions; 1277 d->undoData->databases << databases; 1278 d->undoData->formulas << formulas; 1279 d->undoData->fusions << fusions; 1280 d->undoData->links << links; 1281 d->undoData->matrices << matrices; 1282 d->undoData->namedAreas << namedAreas; 1283 d->undoData->styles << styles; 1284 d->undoData->userInputs << userInputs; 1285 d->undoData->validities << validities; 1286 d->undoData->values << values; 1287 d->undoData->richTexts << richTexts; 1288 } 1289 1290 // Trigger a dependency update of the cells, which have a formula. (new positions) 1291 subStorage = d->formulaStorage->subStorage(invalidRegion); 1292 for (int i = 0; i < subStorage.count(); ++i) { 1293 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i)); 1294 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula)); 1295 } 1296 // Trigger a recalculation only for the cells, that depend on values in the changed region. 1297 Region providers = d->sheet->map()->dependencyManager()->reduceToProvidingRegion(invalidRegion); 1298 d->sheet->map()->addDamage(new CellDamage(d->sheet, providers, CellDamage::Value)); 1299 1300 d->rowRepeatStorage->insertShiftRight(rect); 1301 } 1302 1303 void CellStorage::removeShiftUp(const QRect& rect) 1304 { 1305 #ifdef CALLIGRA_SHEETS_MT 1306 QWriteLocker(&d->bigUglyLock); 1307 #endif 1308 // Trigger a dependency update of the cells, which have a formula. (old positions) 1309 const Region invalidRegion(QRect(rect.topLeft(), QPoint(rect.right(), KS_rowMax)), d->sheet); 1310 PointStorage<Formula> subStorage = d->formulaStorage->subStorage(invalidRegion); 1311 Cell cell; 1312 for (int i = 0; i < subStorage.count(); ++i) { 1313 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i)); 1314 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula)); 1315 } 1316 // Trigger an update of the bindings and the named areas. 1317 const Region region(QRect(rect.topLeft() - QPoint(0, 1), QPoint(rect.right(), KS_rowMax)), d->sheet); 1318 d->sheet->map()->addDamage(new CellDamage(d->sheet, region, CellDamage::Binding | CellDamage::NamedArea)); 1319 1320 QList< QPair<QRectF, Binding> > bindings = d->bindingStorage->removeShiftUp(rect); 1321 QList< QPair<QRectF, QString> > comments = d->commentStorage->removeShiftUp(rect); 1322 QList< QPair<QRectF, Conditions> > conditions = d->conditionsStorage->removeShiftUp(rect); 1323 QList< QPair<QRectF, Database> > databases = d->databaseStorage->removeShiftUp(rect); 1324 QVector< QPair<QPoint, Formula> > formulas = d->formulaStorage->removeShiftUp(rect); 1325 QList< QPair<QRectF, bool> > fusions = d->fusionStorage->removeShiftUp(rect); 1326 QVector< QPair<QPoint, QString> > links = d->linkStorage->removeShiftUp(rect); 1327 QList< QPair<QRectF, bool> > matrices = d->matrixStorage->removeShiftUp(rect); 1328 QList< QPair<QRectF, QString> > namedAreas = d->namedAreaStorage->removeShiftUp(rect); 1329 QList< QPair<QRectF, SharedSubStyle> > styles = d->styleStorage->removeShiftUp(rect); 1330 QVector< QPair<QPoint, QString> > userInputs = d->userInputStorage->removeShiftUp(rect); 1331 QList< QPair<QRectF, Validity> > validities = d->validityStorage->removeShiftUp(rect); 1332 QVector< QPair<QPoint, Value> > values = d->valueStorage->removeShiftUp(rect); 1333 QVector< QPair<QPoint, QSharedPointer<QTextDocument> > > richTexts = d->richTextStorage->removeShiftUp(rect); 1334 // recording undo? 1335 if (d->undoData) { 1336 d->undoData->bindings << bindings; 1337 d->undoData->comments << comments; 1338 d->undoData->conditions << conditions; 1339 d->undoData->databases << databases; 1340 d->undoData->formulas << formulas; 1341 d->undoData->fusions << fusions; 1342 d->undoData->links << links; 1343 d->undoData->matrices << matrices; 1344 d->undoData->namedAreas << namedAreas; 1345 d->undoData->styles << styles; 1346 d->undoData->userInputs << userInputs; 1347 d->undoData->validities << validities; 1348 d->undoData->values << values; 1349 d->undoData->richTexts << richTexts; 1350 } 1351 1352 // Trigger a dependency update of the cells, which have a formula. (new positions) 1353 subStorage = d->formulaStorage->subStorage(invalidRegion); 1354 for (int i = 0; i < subStorage.count(); ++i) { 1355 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i)); 1356 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula)); 1357 } 1358 // Trigger a recalculation only for the cells, that depend on values in the changed region. 1359 Region providers = d->sheet->map()->dependencyManager()->reduceToProvidingRegion(invalidRegion); 1360 d->sheet->map()->addDamage(new CellDamage(d->sheet, providers, CellDamage::Value)); 1361 1362 d->rowRepeatStorage->removeShiftUp(rect); 1363 } 1364 1365 void CellStorage::insertShiftDown(const QRect& rect) 1366 { 1367 #ifdef CALLIGRA_SHEETS_MT 1368 QWriteLocker(&d->bigUglyLock); 1369 #endif 1370 // Trigger a dependency update of the cells, which have a formula. (old positions) 1371 const Region invalidRegion(QRect(rect.topLeft(), QPoint(rect.right(), KS_rowMax)), d->sheet); 1372 PointStorage<Formula> subStorage = d->formulaStorage->subStorage(invalidRegion); 1373 Cell cell; 1374 for (int i = 0; i < subStorage.count(); ++i) { 1375 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i)); 1376 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula)); 1377 } 1378 // Trigger an update of the bindings and the named areas. 1379 d->sheet->map()->addDamage(new CellDamage(d->sheet, invalidRegion, CellDamage::Binding | CellDamage::NamedArea)); 1380 1381 QList< QPair<QRectF, Binding> > bindings = d->bindingStorage->insertShiftDown(rect); 1382 QList< QPair<QRectF, QString> > comments = d->commentStorage->insertShiftDown(rect); 1383 QList< QPair<QRectF, Conditions> > conditions = d->conditionsStorage->insertShiftDown(rect); 1384 QList< QPair<QRectF, Database> > databases = d->databaseStorage->insertShiftDown(rect); 1385 QVector< QPair<QPoint, Formula> > formulas = d->formulaStorage->insertShiftDown(rect); 1386 QList< QPair<QRectF, bool> > fusions = d->fusionStorage->insertShiftDown(rect); 1387 QVector< QPair<QPoint, QString> > links = d->linkStorage->insertShiftDown(rect); 1388 QList< QPair<QRectF, bool> > matrices = d->matrixStorage->insertShiftDown(rect); 1389 QList< QPair<QRectF, QString> > namedAreas = d->namedAreaStorage->insertShiftDown(rect); 1390 QList< QPair<QRectF, SharedSubStyle> > styles = d->styleStorage->insertShiftDown(rect); 1391 QVector< QPair<QPoint, QString> > userInputs = d->userInputStorage->insertShiftDown(rect); 1392 QList< QPair<QRectF, Validity> > validities = d->validityStorage->insertShiftDown(rect); 1393 QVector< QPair<QPoint, Value> > values = d->valueStorage->insertShiftDown(rect); 1394 QVector< QPair<QPoint, QSharedPointer<QTextDocument> > > richTexts = d->richTextStorage->insertShiftDown(rect); 1395 // recording undo? 1396 if (d->undoData) { 1397 d->undoData->bindings << bindings; 1398 d->undoData->comments << comments; 1399 d->undoData->conditions << conditions; 1400 d->undoData->databases << databases; 1401 d->undoData->formulas << formulas; 1402 d->undoData->fusions << fusions; 1403 d->undoData->links << links; 1404 d->undoData->matrices << matrices; 1405 d->undoData->namedAreas << namedAreas; 1406 d->undoData->styles << styles; 1407 d->undoData->userInputs << userInputs; 1408 d->undoData->validities << validities; 1409 d->undoData->values << values; 1410 d->undoData->richTexts << richTexts; 1411 } 1412 1413 // Trigger a dependency update of the cells, which have a formula. (new positions) 1414 subStorage = d->formulaStorage->subStorage(invalidRegion); 1415 for (int i = 0; i < subStorage.count(); ++i) { 1416 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i)); 1417 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula)); 1418 } 1419 // Trigger a recalculation only for the cells, that depend on values in the changed region. 1420 Region providers = d->sheet->map()->dependencyManager()->reduceToProvidingRegion(invalidRegion); 1421 d->sheet->map()->addDamage(new CellDamage(d->sheet, providers, CellDamage::Value)); 1422 1423 d->rowRepeatStorage->insertShiftDown(rect); 1424 } 1425 1426 Cell CellStorage::firstInColumn(int col, Visiting visiting) const 1427 { 1428 #ifdef CALLIGRA_SHEETS_MT 1429 QReadLocker rl(&d->bigUglyLock); 1430 #endif 1431 Q_UNUSED(visiting); 1432 1433 int newRow = 0; 1434 int tmpRow = 0; 1435 d->formulaStorage->firstInColumn(col, &tmpRow); 1436 newRow = tmpRow; 1437 d->valueStorage->firstInColumn(col, &tmpRow); 1438 if (tmpRow) 1439 newRow = newRow ? qMin(newRow, tmpRow) : tmpRow; 1440 if (!newRow) 1441 return Cell(); 1442 return Cell(d->sheet, col, newRow); 1443 } 1444 1445 Cell CellStorage::firstInRow(int row, Visiting visiting) const 1446 { 1447 #ifdef CALLIGRA_SHEETS_MT 1448 QReadLocker rl(&d->bigUglyLock); 1449 #endif 1450 int newCol = 0; 1451 int tmpCol = 0; 1452 d->formulaStorage->firstInRow(row, &tmpCol); 1453 newCol = tmpCol; 1454 d->valueStorage->firstInRow(row, &tmpCol); 1455 if (tmpCol) 1456 newCol = newCol ? qMin(newCol, tmpCol) : tmpCol; 1457 if (visiting == VisitAll) { 1458 tmpCol = d->styleStorage->firstColumnIndexInRow(row); 1459 if (tmpCol) 1460 newCol = newCol ? qMin(newCol, tmpCol) : tmpCol; 1461 } 1462 if (!newCol) 1463 return Cell(); 1464 return Cell(d->sheet, newCol, row); 1465 } 1466 1467 Cell CellStorage::lastInColumn(int col, Visiting visiting) const 1468 { 1469 #ifdef CALLIGRA_SHEETS_MT 1470 QReadLocker rl(&d->bigUglyLock); 1471 #endif 1472 Q_UNUSED(visiting); 1473 int newRow = 0; 1474 int tmpRow = 0; 1475 d->formulaStorage->lastInColumn(col, &tmpRow); 1476 newRow = tmpRow; 1477 d->valueStorage->lastInColumn(col, &tmpRow); 1478 newRow = qMax(newRow, tmpRow); 1479 if (!newRow) 1480 return Cell(); 1481 return Cell(d->sheet, col, newRow); 1482 } 1483 1484 Cell CellStorage::lastInRow(int row, Visiting visiting) const 1485 { 1486 #ifdef CALLIGRA_SHEETS_MT 1487 QReadLocker rl(&d->bigUglyLock); 1488 #endif 1489 Q_UNUSED(visiting); 1490 int newCol = 0; 1491 int tmpCol = 0; 1492 d->formulaStorage->lastInRow(row, &tmpCol); 1493 newCol = tmpCol; 1494 d->valueStorage->lastInRow(row, &tmpCol); 1495 newCol = qMax(newCol, tmpCol); 1496 if (!newCol) 1497 return Cell(); 1498 return Cell(d->sheet, newCol, row); 1499 } 1500 1501 Cell CellStorage::nextInColumn(int col, int row, Visiting visiting) const 1502 { 1503 #ifdef CALLIGRA_SHEETS_MT 1504 QReadLocker rl(&d->bigUglyLock); 1505 #endif 1506 Q_UNUSED(visiting); 1507 int newRow = 0; 1508 int tmpRow = 0; 1509 d->formulaStorage->nextInColumn(col, row, &tmpRow); 1510 newRow = tmpRow; 1511 d->valueStorage->nextInColumn(col, row, &tmpRow); 1512 if (tmpRow) 1513 newRow = newRow ? qMin(newRow, tmpRow) : tmpRow; 1514 if (!newRow) 1515 return Cell(); 1516 return Cell(d->sheet, col, newRow); 1517 } 1518 1519 Cell CellStorage::nextInRow(int col, int row, Visiting visiting) const 1520 { 1521 #ifdef CALLIGRA_SHEETS_MT 1522 QReadLocker rl(&d->bigUglyLock); 1523 #endif 1524 int newCol = 0; 1525 int tmpCol = 0; 1526 d->formulaStorage->nextInRow(col, row, &tmpCol); 1527 newCol = tmpCol; 1528 d->valueStorage->nextInRow(col, row, &tmpCol); 1529 if (tmpCol) 1530 newCol = newCol ? qMin(newCol, tmpCol) : tmpCol; 1531 if (visiting == VisitAll) { 1532 tmpCol = d->styleStorage->nextColumnIndexInRow(col, row); 1533 if (tmpCol) 1534 newCol = newCol ? qMin(newCol, tmpCol) : tmpCol; 1535 } 1536 if (!newCol) 1537 return Cell(); 1538 return Cell(d->sheet, newCol, row); 1539 } 1540 1541 Cell CellStorage::prevInColumn(int col, int row, Visiting visiting) const 1542 { 1543 #ifdef CALLIGRA_SHEETS_MT 1544 QReadLocker rl(&d->bigUglyLock); 1545 #endif 1546 Q_UNUSED(visiting); 1547 int newRow = 0; 1548 int tmpRow = 0; 1549 d->formulaStorage->prevInColumn(col, row, &tmpRow); 1550 newRow = tmpRow; 1551 d->valueStorage->prevInColumn(col, row, &tmpRow); 1552 newRow = qMax(newRow, tmpRow); 1553 if (!newRow) 1554 return Cell(); 1555 return Cell(d->sheet, col, newRow); 1556 } 1557 1558 Cell CellStorage::prevInRow(int col, int row, Visiting visiting) const 1559 { 1560 #ifdef CALLIGRA_SHEETS_MT 1561 QReadLocker rl(&d->bigUglyLock); 1562 #endif 1563 Q_UNUSED(visiting); 1564 int newCol = 0; 1565 int tmpCol = 0; 1566 d->formulaStorage->prevInRow(col, row, &tmpCol); 1567 newCol = tmpCol; 1568 d->valueStorage->prevInRow(col, row, &tmpCol); 1569 newCol = qMax(newCol, tmpCol); 1570 if (!newCol) 1571 return Cell(); 1572 return Cell(d->sheet, newCol, row); 1573 } 1574 1575 int CellStorage::columns(bool includeStyles) const 1576 { 1577 #ifdef CALLIGRA_SHEETS_MT 1578 QReadLocker rl(&d->bigUglyLock); 1579 #endif 1580 int max = 0; 1581 max = qMax(max, d->commentStorage->usedArea().right()); 1582 max = qMax(max, d->conditionsStorage->usedArea().right()); 1583 max = qMax(max, d->fusionStorage->usedArea().right()); 1584 if (includeStyles) max = qMax(max, d->styleStorage->usedArea().right()); 1585 max = qMax(max, d->validityStorage->usedArea().right()); 1586 max = qMax(max, d->formulaStorage->columns()); 1587 max = qMax(max, d->linkStorage->columns()); 1588 max = qMax(max, d->valueStorage->columns()); 1589 1590 // don't include bindings cause the bindingStorage does only listen to all cells in the sheet. 1591 //max = qMax(max, d->bindingStorage->usedArea().right()); 1592 1593 return max; 1594 } 1595 1596 int CellStorage::rows(bool includeStyles) const 1597 { 1598 #ifdef CALLIGRA_SHEETS_MT 1599 QReadLocker rl(&d->bigUglyLock); 1600 #endif 1601 int max = 0; 1602 max = qMax(max, d->commentStorage->usedArea().bottom()); 1603 max = qMax(max, d->conditionsStorage->usedArea().bottom()); 1604 max = qMax(max, d->fusionStorage->usedArea().bottom()); 1605 if (includeStyles) max = qMax(max, d->styleStorage->usedArea().bottom()); 1606 max = qMax(max, d->validityStorage->usedArea().bottom()); 1607 max = qMax(max, d->formulaStorage->rows()); 1608 max = qMax(max, d->linkStorage->rows()); 1609 max = qMax(max, d->valueStorage->rows()); 1610 1611 // don't include bindings cause the bindingStorage does only listen to all cells in the sheet. 1612 //max = qMax(max, d->bindingStorage->usedArea().bottom()); 1613 1614 return max; 1615 } 1616 1617 CellStorage CellStorage::subStorage(const Region& region) const 1618 { 1619 #ifdef CALLIGRA_SHEETS_MT 1620 QReadLocker rl(&d->bigUglyLock); 1621 #endif 1622 CellStorage subStorage(d->sheet); 1623 *subStorage.d->formulaStorage = d->formulaStorage->subStorage(region); 1624 *subStorage.d->linkStorage = d->linkStorage->subStorage(region); 1625 *subStorage.d->valueStorage = d->valueStorage->subStorage(region); 1626 return subStorage; 1627 } 1628 1629 const BindingStorage* CellStorage::bindingStorage() const 1630 { 1631 return d->bindingStorage; 1632 } 1633 1634 const CommentStorage* CellStorage::commentStorage() const 1635 { 1636 return d->commentStorage; 1637 } 1638 1639 const ConditionsStorage* CellStorage::conditionsStorage() const 1640 { 1641 return d->conditionsStorage; 1642 } 1643 1644 const FormulaStorage* CellStorage::formulaStorage() const 1645 { 1646 return d->formulaStorage; 1647 } 1648 1649 const FusionStorage* CellStorage::fusionStorage() const 1650 { 1651 return d->fusionStorage; 1652 } 1653 1654 const LinkStorage* CellStorage::linkStorage() const 1655 { 1656 return d->linkStorage; 1657 } 1658 1659 const StyleStorage* CellStorage::styleStorage() const 1660 { 1661 return d->styleStorage; 1662 } 1663 1664 const UserInputStorage* CellStorage::userInputStorage() const 1665 { 1666 return d->userInputStorage; 1667 } 1668 1669 const ValidityStorage* CellStorage::validityStorage() const 1670 { 1671 return d->validityStorage; 1672 } 1673 1674 const ValueStorage* CellStorage::valueStorage() const 1675 { 1676 return d->valueStorage; 1677 } 1678 1679 void CellStorage::startUndoRecording() 1680 { 1681 #ifdef CALLIGRA_SHEETS_MT 1682 QWriteLocker(&d->bigUglyLock); 1683 #endif 1684 // If undoData is not null, the recording wasn't stopped. 1685 // Should not happen, hence this assertion. 1686 Q_ASSERT(d->undoData == 0); 1687 d->undoData = new CellStorageUndoData(); 1688 } 1689 1690 void CellStorage::stopUndoRecording(KUndo2Command *parent) 1691 { 1692 #ifdef CALLIGRA_SHEETS_MT 1693 QWriteLocker(&d->bigUglyLock); 1694 #endif 1695 // If undoData is null, the recording wasn't started. 1696 // Should not happen, hence this assertion. 1697 Q_ASSERT(d->undoData != 0); 1698 // append sub-commands to the parent command 1699 d->createCommand(parent); // needs d->undoData 1700 for (int i = 0; i < d->undoData->namedAreas.count(); ++i) { 1701 emit namedAreaRemoved(d->undoData->namedAreas[i].second); 1702 } 1703 delete d->undoData; 1704 d->undoData = 0; 1705 } 1706 1707 void CellStorage::loadConditions(const QList<QPair<QRegion, Conditions> >& conditions) 1708 { 1709 #ifdef CALLIGRA_SHEETS_MT 1710 QWriteLocker(&d->bigUglyLock); 1711 #endif 1712 d->conditionsStorage->load(conditions); 1713 } 1714 1715 void CellStorage::loadStyles(const QList<QPair<QRegion, Style> > &styles) 1716 { 1717 #ifdef CALLIGRA_SHEETS_MT 1718 QWriteLocker(&d->bigUglyLock); 1719 #endif 1720 d->styleStorage->load(styles); 1721 } 1722 1723 void CellStorage::invalidateStyleCache() 1724 { 1725 d->styleStorage->invalidateCache(); 1726 } 1727 1728 int CellStorage::rowRepeat(int row) const 1729 { 1730 #ifdef CALLIGRA_SHEETS_MT 1731 QReadLocker rl(&d->bigUglyLock); 1732 #endif 1733 return d->rowRepeatStorage->rowRepeat(row); 1734 } 1735 1736 int CellStorage::firstIdenticalRow(int row) const 1737 { 1738 #ifdef CALLIGRA_SHEETS_MT 1739 QReadLocker rl(&d->bigUglyLock); 1740 #endif 1741 return d->rowRepeatStorage->firstIdenticalRow(row); 1742 } 1743 1744 void CellStorage::setRowsRepeated(int row, int count) 1745 { 1746 #ifdef CALLIGRA_SHEETS_MT 1747 QWriteLocker(&d->bigUglyLock); 1748 #endif 1749 d->rowRepeatStorage->setRowRepeat(row, count); 1750 }