1 /* This file is part of the KDE project
2 Copyright 2010 Marijn Kruisselbrink <mkruisselbrink@kde.org>
3 Copyright 2007, 2009 Stefan Nikolaus <stefan.nikolaus@kdemail.net>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20
21 // Local
22 #include "CellStorage.h"
23 #include "CellStorage_p.h"
24
25 // Qt
26 #ifdef CALLIGRA_SHEETS_MT
27 #include <QReadWriteLock>
28 #include <QReadLocker>
29 #include <QWriteLocker>
30 #endif
31
32 // Calligra
33 #include <KoXmlWriter.h>
34
35 // Sheets
36 #include "BindingStorage.h"
37 #include "ConditionsStorage.h"
38 #include "Damages.h"
39 #include "DependencyManager.h"
40 #include "FormulaStorage.h"
41 #include "Map.h"
42 #include "ModelSupport.h"
43 #include "RecalcManager.h"
44 #include "RectStorage.h"
45 #include "RowRepeatStorage.h"
46 #include "Sheet.h"
47 #include "StyleStorage.h"
48 #include "ValidityStorage.h"
49 #include "ValueStorage.h"
50
51 // commands
52 #include "commands/PointStorageUndoCommand.h"
53 #include "commands/RectStorageUndoCommand.h"
54 #include "commands/StyleStorageUndoCommand.h"
55
56 // database
57 #include "database/DatabaseStorage.h"
58 #include "database/DatabaseManager.h"
59
60 Q_DECLARE_METATYPE(QSharedPointer<QTextDocument>)
61
62 using namespace Calligra::Sheets;
63
64 typedef RectStorage<QString> NamedAreaStorage;
65
66 class Q_DECL_HIDDEN CellStorage::Private
67 {
68 public:
Private(Sheet * sheet)69 Private(Sheet* sheet)
70 : sheet(sheet)
71 , bindingStorage(new BindingStorage(sheet->map()))
72 , commentStorage(new CommentStorage(sheet->map()))
73 , conditionsStorage(new ConditionsStorage(sheet->map()))
74 , databaseStorage(new DatabaseStorage(sheet->map()))
75 , formulaStorage(new FormulaStorage())
76 , fusionStorage(new FusionStorage(sheet->map()))
77 , linkStorage(new LinkStorage())
78 , matrixStorage(new MatrixStorage(sheet->map()))
79 , namedAreaStorage(new NamedAreaStorage(sheet->map()))
80 , styleStorage(new StyleStorage(sheet->map()))
81 , userInputStorage(new UserInputStorage())
82 , validityStorage(new ValidityStorage(sheet->map()))
83 , valueStorage(new ValueStorage())
84 , richTextStorage(new RichTextStorage())
85 , rowRepeatStorage(new RowRepeatStorage())
86 , undoData(0)
87 #ifdef CALLIGRA_SHEETS_MT
88 , bigUglyLock(QReadWriteLock::Recursive)
89 #endif
90 {}
91
Private(const Private & other,Sheet * sheet)92 Private(const Private& other, Sheet* sheet)
93 : sheet(sheet)
94 , bindingStorage(new BindingStorage(*other.bindingStorage))
95 , commentStorage(new CommentStorage(*other.commentStorage))
96 , conditionsStorage(new ConditionsStorage(*other.conditionsStorage))
97 , databaseStorage(new DatabaseStorage(*other.databaseStorage))
98 , formulaStorage(new FormulaStorage(*other.formulaStorage))
99 , fusionStorage(new FusionStorage(*other.fusionStorage))
100 , linkStorage(new LinkStorage(*other.linkStorage))
101 , matrixStorage(new MatrixStorage(*other.matrixStorage))
102 , namedAreaStorage(new NamedAreaStorage(*other.namedAreaStorage))
103 , styleStorage(new StyleStorage(*other.styleStorage))
104 , userInputStorage(new UserInputStorage(*other.userInputStorage))
105 , validityStorage(new ValidityStorage(*other.validityStorage))
106 , valueStorage(new ValueStorage(*other.valueStorage))
107 , richTextStorage(new RichTextStorage(*other.richTextStorage))
108 , rowRepeatStorage(new RowRepeatStorage(*other.rowRepeatStorage))
109 , undoData(0)
110 #ifdef CALLIGRA_SHEETS_MT
111 , bigUglyLock(QReadWriteLock::Recursive)
112 #endif
113 {}
114
~Private()115 ~Private() {
116 delete bindingStorage;
117 delete commentStorage;
118 delete conditionsStorage;
119 delete databaseStorage;
120 delete formulaStorage;
121 delete fusionStorage;
122 delete linkStorage;
123 delete matrixStorage;
124 delete namedAreaStorage;
125 delete styleStorage;
126 delete userInputStorage;
127 delete validityStorage;
128 delete valueStorage;
129 delete richTextStorage;
130 delete rowRepeatStorage;
131 }
132
133 void createCommand(KUndo2Command *parent) const;
134
135 Sheet* sheet;
136 BindingStorage* bindingStorage;
137 CommentStorage* commentStorage;
138 ConditionsStorage* conditionsStorage;
139 DatabaseStorage* databaseStorage;
140 FormulaStorage* formulaStorage;
141 FusionStorage* fusionStorage;
142 LinkStorage* linkStorage;
143 MatrixStorage* matrixStorage;
144 NamedAreaStorage* namedAreaStorage;
145 StyleStorage* styleStorage;
146 UserInputStorage* userInputStorage;
147 ValidityStorage* validityStorage;
148 ValueStorage* valueStorage;
149 RichTextStorage* richTextStorage;
150 RowRepeatStorage* rowRepeatStorage;
151 CellStorageUndoData* undoData;
152
153 #ifdef CALLIGRA_SHEETS_MT
154 QReadWriteLock bigUglyLock;
155 #endif
156 };
157
createCommand(KUndo2Command * parent) const158 void CellStorage::Private::createCommand(KUndo2Command *parent) const
159 {
160 if (!undoData->bindings.isEmpty()) {
161 RectStorageUndoCommand<Binding> *const command
162 = new RectStorageUndoCommand<Binding>(sheet->model(), SourceRangeRole, parent);
163 command->add(undoData->bindings);
164 }
165 if (!undoData->comments.isEmpty()) {
166 RectStorageUndoCommand<QString> *const command
167 = new RectStorageUndoCommand<QString>(sheet->model(), CommentRole, parent);
168 command->add(undoData->comments);
169 }
170 if (!undoData->conditions.isEmpty()) {
171 RectStorageUndoCommand<Conditions> *const command
172 = new RectStorageUndoCommand<Conditions>(sheet->model(), ConditionRole, parent);
173 command->add(undoData->conditions);
174 }
175 if (!undoData->databases.isEmpty()) {
176 RectStorageUndoCommand<Database> *const command
177 = new RectStorageUndoCommand<Database>(sheet->model(), TargetRangeRole, parent);
178 command->add(undoData->databases);
179 }
180 if (!undoData->formulas.isEmpty()) {
181 PointStorageUndoCommand<Formula> *const command
182 = new PointStorageUndoCommand<Formula>(sheet->model(), FormulaRole, parent);
183 command->add(undoData->formulas);
184 }
185 if (!undoData->fusions.isEmpty()) {
186 RectStorageUndoCommand<bool> *const command
187 = new RectStorageUndoCommand<bool>(sheet->model(), FusionedRangeRole, parent);
188 command->add(undoData->fusions);
189 }
190 if (!undoData->links.isEmpty()) {
191 PointStorageUndoCommand<QString> *const command
192 = new PointStorageUndoCommand<QString>(sheet->model(), LinkRole, parent);
193 command->add(undoData->links);
194 }
195 if (!undoData->matrices.isEmpty()) {
196 RectStorageUndoCommand<bool> *const command
197 = new RectStorageUndoCommand<bool>(sheet->model(), LockedRangeRole, parent);
198 command->add(undoData->matrices);
199 }
200 if (!undoData->namedAreas.isEmpty()) {
201 RectStorageUndoCommand<QString> *const command
202 = new RectStorageUndoCommand<QString>(sheet->model(), NamedAreaRole, parent);
203 command->add(undoData->namedAreas);
204 }
205 if (!undoData->richTexts.isEmpty()) {
206 PointStorageUndoCommand<QSharedPointer<QTextDocument> > *const command
207 = new PointStorageUndoCommand<QSharedPointer<QTextDocument> >(sheet->model(), RichTextRole, parent);
208 command->add(undoData->richTexts);
209 }
210 if (!undoData->styles.isEmpty()) {
211 StyleStorageUndoCommand *const command
212 = new StyleStorageUndoCommand(styleStorage, parent);
213 command->add(undoData->styles);
214 }
215 if (!undoData->userInputs.isEmpty()) {
216 PointStorageUndoCommand<QString> *const command
217 = new PointStorageUndoCommand<QString>(sheet->model(), UserInputRole, parent);
218 command->add(undoData->userInputs);
219 }
220 if (!undoData->validities.isEmpty()) {
221 RectStorageUndoCommand<Validity> *const command
222 = new RectStorageUndoCommand<Validity>(sheet->model(), ValidityRole, parent);
223 command->add(undoData->validities);
224 }
225 if (!undoData->values.isEmpty()) {
226 PointStorageUndoCommand<Value> *const command
227 = new PointStorageUndoCommand<Value>(sheet->model(), ValueRole, parent);
228 command->add(undoData->values);
229 }
230 }
231
232
CellStorage(Sheet * sheet)233 CellStorage::CellStorage(Sheet* sheet)
234 : QObject(sheet)
235 , d(new Private(sheet))
236 {
237 }
238
CellStorage(const CellStorage & other)239 CellStorage::CellStorage(const CellStorage& other)
240 : QObject(other.d->sheet)
241 , d(new Private(*other.d, other.d->sheet))
242 {
243 }
244
CellStorage(const CellStorage & other,Sheet * sheet)245 CellStorage::CellStorage(const CellStorage& other, Sheet* sheet)
246 : QObject(sheet)
247 , d(new Private(*other.d, sheet))
248 {
249 }
250
~CellStorage()251 CellStorage::~CellStorage()
252 {
253 delete d;
254 }
255
sheet() const256 Sheet* CellStorage::sheet() const
257 {
258 return d->sheet;
259 }
260
take(int col,int row)261 void CellStorage::take(int col, int row)
262 {
263 #ifdef CALLIGRA_SHEETS_MT
264 QWriteLocker(&d->bigUglyLock);
265 #endif
266
267 Formula oldFormula;
268 QString oldLink;
269 QString oldUserInput;
270 Value oldValue;
271 QSharedPointer<QTextDocument> oldRichText;
272
273 oldFormula = d->formulaStorage->take(col, row);
274 oldLink = d->linkStorage->take(col, row);
275 oldUserInput = d->userInputStorage->take(col, row);
276 oldValue = d->valueStorage->take(col, row);
277 oldRichText = d->richTextStorage->take(col, row);
278
279 if (!d->sheet->map()->isLoading()) {
280 // Trigger a recalculation of the consuming cells.
281 CellDamage::Changes changes = CellDamage:: Binding | CellDamage::Formula | CellDamage::Value;
282 d->sheet->map()->addDamage(new CellDamage(Cell(d->sheet, col, row), changes));
283
284 d->rowRepeatStorage->setRowRepeat(row, 1);
285 }
286 // also trigger a relayout of the first non-empty cell to the left of this cell
287 int prevCol;
288 Value v = d->valueStorage->prevInRow(col, row, &prevCol);
289 if (!v.isEmpty())
290 d->sheet->map()->addDamage(new CellDamage(Cell(d->sheet, prevCol, row), CellDamage::Appearance));
291
292
293 // recording undo?
294 if (d->undoData) {
295 d->undoData->formulas << qMakePair(QPoint(col, row), oldFormula);
296 d->undoData->links << qMakePair(QPoint(col, row), oldLink);
297 d->undoData->userInputs << qMakePair(QPoint(col, row), oldUserInput);
298 d->undoData->values << qMakePair(QPoint(col, row), oldValue);
299 d->undoData->richTexts << qMakePair(QPoint(col, row), oldRichText);
300 }
301 }
302
binding(int column,int row) const303 Binding CellStorage::binding(int column, int row) const
304 {
305 #ifdef CALLIGRA_SHEETS_MT
306 QReadLocker rl(&d->bigUglyLock);
307 #endif
308 return d->bindingStorage->contains(QPoint(column, row));
309 }
310
setBinding(const Region & region,const Binding & binding)311 void CellStorage::setBinding(const Region& region, const Binding& binding)
312 {
313 #ifdef CALLIGRA_SHEETS_MT
314 QWriteLocker(&d->bigUglyLock);
315 #endif
316 // recording undo?
317 if (d->undoData)
318 d->undoData->bindings << d->bindingStorage->undoData(region);
319
320 d->bindingStorage->insert(region, binding);
321 }
322
removeBinding(const Region & region,const Binding & binding)323 void CellStorage::removeBinding(const Region& region, const Binding& binding)
324 {
325 #ifdef CALLIGRA_SHEETS_MT
326 QWriteLocker(&d->bigUglyLock);
327 #endif
328 // recording undo?
329 if (d->undoData) {
330 d->undoData->bindings << d->bindingStorage->undoData(region);
331 }
332 d->bindingStorage->remove(region, binding);
333 }
334
comment(int column,int row) const335 QString CellStorage::comment(int column, int row) const
336 {
337 #ifdef CALLIGRA_SHEETS_MT
338 QReadLocker rl(&d->bigUglyLock);
339 #endif
340 return d->commentStorage->contains(QPoint(column, row));
341 }
342
setComment(const Region & region,const QString & comment)343 void CellStorage::setComment(const Region& region, const QString& comment)
344 {
345 #ifdef CALLIGRA_SHEETS_MT
346 QWriteLocker(&d->bigUglyLock);
347 #endif
348 // recording undo?
349 if (d->undoData)
350 d->undoData->comments << d->commentStorage->undoData(region);
351
352 d->commentStorage->insert(region, comment);
353 if (!d->sheet->map()->isLoading()) {
354 foreach (const QRect& r, region.rects()) {
355 d->rowRepeatStorage->splitRowRepeat(r.top());
356 d->rowRepeatStorage->splitRowRepeat(r.bottom()+1);
357 }
358 }
359 }
360
conditions(int column,int row) const361 Conditions CellStorage::conditions(int column, int row) const
362 {
363 #ifdef CALLIGRA_SHEETS_MT
364 QReadLocker rl(&d->bigUglyLock);
365 #endif
366 return d->conditionsStorage->contains(QPoint(column, row));
367 }
368
setConditions(const Region & region,Conditions conditions)369 void CellStorage::setConditions(const Region& region, Conditions conditions)
370 {
371 #ifdef CALLIGRA_SHEETS_MT
372 QWriteLocker(&d->bigUglyLock);
373 #endif
374 // recording undo?
375 if (d->undoData)
376 d->undoData->conditions << d->conditionsStorage->undoData(region);
377
378 d->conditionsStorage->insert(region, conditions);
379 if (!d->sheet->map()->isLoading()) {
380 foreach (const QRect& r, region.rects()) {
381 d->rowRepeatStorage->splitRowRepeat(r.top());
382 d->rowRepeatStorage->splitRowRepeat(r.bottom()+1);
383 }
384 }
385 }
386
database(int column,int row) const387 Database CellStorage::database(int column, int row) const
388 {
389 #ifdef CALLIGRA_SHEETS_MT
390 QReadLocker rl(&d->bigUglyLock);
391 #endif
392 QPair<QRectF, Database> pair = d->databaseStorage->containedPair(QPoint(column, row));
393 if (pair.first.isEmpty())
394 return Database();
395 if (pair.second.isEmpty())
396 return Database();
397 // update the range, which might get changed
398 Database database = pair.second;
399 database.setRange(Region(pair.first.toRect(), d->sheet));
400 return database;
401 }
402
databases(const Region & region) const403 QList< QPair<QRectF, Database> > CellStorage::databases(const Region& region) const
404 {
405 #ifdef CALLIGRA_SHEETS_MT
406 QReadLocker rl(&d->bigUglyLock);
407 #endif
408 return d->databaseStorage->intersectingPairs(region);
409 }
410
setDatabase(const Region & region,const Database & database)411 void CellStorage::setDatabase(const Region& region, const Database& database)
412 {
413 #ifdef CALLIGRA_SHEETS_MT
414 QWriteLocker(&d->bigUglyLock);
415 #endif
416 // recording undo?
417 if (d->undoData)
418 d->undoData->databases << d->databaseStorage->undoData(region);
419
420 d->databaseStorage->insert(region, database);
421 }
422
formula(int column,int row) const423 Formula CellStorage::formula(int column, int row) const
424 {
425 #ifdef CALLIGRA_SHEETS_MT
426 QReadLocker rl(&d->bigUglyLock);
427 #endif
428 return d->formulaStorage->lookup(column, row, Formula::empty());
429 }
430
setFormula(int column,int row,const Formula & formula)431 void CellStorage::setFormula(int column, int row, const Formula& formula)
432 {
433 #ifdef CALLIGRA_SHEETS_MT
434 QWriteLocker(&d->bigUglyLock);
435 #endif
436 Formula old = Formula::empty();
437 if (formula.expression().isEmpty())
438 old = d->formulaStorage->take(column, row, Formula::empty());
439 else
440 old = d->formulaStorage->insert(column, row, formula);
441
442 // formula changed?
443 if (formula != old) {
444 if (!d->sheet->map()->isLoading()) {
445 // trigger an update of the dependencies and a recalculation
446 d->sheet->map()->addDamage(new CellDamage(Cell(d->sheet, column, row), CellDamage::Formula | CellDamage::Value));
447 d->rowRepeatStorage->setRowRepeat(row, 1);
448 }
449 // recording undo?
450 if (d->undoData) {
451 d->undoData->formulas << qMakePair(QPoint(column, row), old);
452 // Also store the old value, if there wasn't a formula before,
453 // because the new value is calculated later by the damage
454 // processing and is not recorded for undoing.
455 if (old == Formula())
456 d->undoData->values << qMakePair(QPoint(column, row), value(column, row));
457 }
458 }
459 }
460
link(int column,int row) const461 QString CellStorage::link(int column, int row) const
462 {
463 #ifdef CALLIGRA_SHEETS_MT
464 QReadLocker rl(&d->bigUglyLock);
465 #endif
466 return d->linkStorage->lookup(column, row);
467 }
468
setLink(int column,int row,const QString & link)469 void CellStorage::setLink(int column, int row, const QString& link)
470 {
471 #ifdef CALLIGRA_SHEETS_MT
472 QWriteLocker(&d->bigUglyLock);
473 #endif
474 QString old;
475 if (link.isEmpty())
476 old = d->linkStorage->take(column, row);
477 else
478 old = d->linkStorage->insert(column, row, link);
479
480 // recording undo?
481 if (d->undoData && link != old)
482 d->undoData->links << qMakePair(QPoint(column, row), old);
483 if (!d->sheet->map()->isLoading())
484 d->rowRepeatStorage->setRowRepeat(row, 1);
485 }
486
namedArea(int column,int row) const487 QString CellStorage::namedArea(int column, int row) const
488 {
489 #ifdef CALLIGRA_SHEETS_MT
490 QReadLocker rl(&d->bigUglyLock);
491 #endif
492 QPair<QRectF, QString> pair = d->namedAreaStorage->containedPair(QPoint(column, row));
493 if (pair.first.isEmpty())
494 return QString();
495 if (pair.second.isEmpty())
496 return QString();
497 return pair.second;
498 }
499
namedAreas(const Region & region) const500 QList< QPair<QRectF, QString> > CellStorage::namedAreas(const Region& region) const
501 {
502 #ifdef CALLIGRA_SHEETS_MT
503 QReadLocker rl(&d->bigUglyLock);
504 #endif
505 return d->namedAreaStorage->intersectingPairs(region);
506 }
507
setNamedArea(const Region & region,const QString & namedArea)508 void CellStorage::setNamedArea(const Region& region, const QString& namedArea)
509 {
510 #ifdef CALLIGRA_SHEETS_MT
511 QWriteLocker(&d->bigUglyLock);
512 #endif
513 // recording undo?
514 if (d->undoData)
515 d->undoData->namedAreas << d->namedAreaStorage->undoData(region);
516
517 d->namedAreaStorage->insert(region, namedArea);
518 }
519
removeNamedArea(const Region & region,const QString & namedArea)520 void CellStorage::removeNamedArea(const Region& region, const QString& namedArea)
521 {
522 #ifdef CALLIGRA_SHEETS_MT
523 QWriteLocker(&d->bigUglyLock);
524 #endif
525 // recording undo?
526 if (d->undoData)
527 d->undoData->namedAreas << d->namedAreaStorage->undoData(region);
528
529 d->namedAreaStorage->remove(region, namedArea);
530 }
531
532
emitInsertNamedArea(const Region & region,const QString & namedArea)533 void CellStorage::emitInsertNamedArea(const Region ®ion, const QString &namedArea)
534 {
535 emit insertNamedArea(region, namedArea);
536 }
537
style(int column,int row) const538 Style CellStorage::style(int column, int row) const
539 {
540 #ifdef CALLIGRA_SHEETS_MT
541 QReadLocker rl(&d->bigUglyLock);
542 #endif
543 return d->styleStorage->contains(QPoint(column, row));
544 }
545
style(const QRect & rect) const546 Style CellStorage::style(const QRect& rect) const
547 {
548 #ifdef CALLIGRA_SHEETS_MT
549 QReadLocker rl(&d->bigUglyLock);
550 #endif
551 return d->styleStorage->contains(rect);
552 }
553
setStyle(const Region & region,const Style & style)554 void CellStorage::setStyle(const Region& region, const Style& style)
555 {
556 #ifdef CALLIGRA_SHEETS_MT
557 QWriteLocker(&d->bigUglyLock);
558 #endif
559 // recording undo?
560 if (d->undoData)
561 d->undoData->styles << d->styleStorage->undoData(region);
562
563 d->styleStorage->insert(region, style);
564 if (!d->sheet->map()->isLoading()) {
565 foreach (const QRect& r, region.rects()) {
566 d->rowRepeatStorage->splitRowRepeat(r.top());
567 d->rowRepeatStorage->splitRowRepeat(r.bottom()+1);
568 }
569 }
570 }
571
insertSubStyle(const QRect & rect,const SharedSubStyle & subStyle)572 void CellStorage::insertSubStyle(const QRect &rect, const SharedSubStyle &subStyle)
573 {
574 #ifdef CALLIGRA_SHEETS_MT
575 QWriteLocker(&d->bigUglyLock);
576 #endif
577 d->styleStorage->insert(rect, subStyle);
578 if (!d->sheet->map()->isLoading()) {
579 d->rowRepeatStorage->splitRowRepeat(rect.top());
580 d->rowRepeatStorage->splitRowRepeat(rect.bottom()+1);
581 }
582 }
583
userInput(int column,int row) const584 QString CellStorage::userInput(int column, int row) const
585 {
586 #ifdef CALLIGRA_SHEETS_MT
587 QReadLocker rl(&d->bigUglyLock);
588 #endif
589 return d->userInputStorage->lookup(column, row);
590 }
591
setUserInput(int column,int row,const QString & userInput)592 void CellStorage::setUserInput(int column, int row, const QString& userInput)
593 {
594 #ifdef CALLIGRA_SHEETS_MT
595 QWriteLocker(&d->bigUglyLock);
596 #endif
597 QString old;
598 if (userInput.isEmpty())
599 old = d->userInputStorage->take(column, row);
600 else
601 old = d->userInputStorage->insert(column, row, userInput);
602
603 // recording undo?
604 if (d->undoData && userInput != old)
605 d->undoData->userInputs << qMakePair(QPoint(column, row), old);
606 if (!d->sheet->map()->isLoading())
607 d->rowRepeatStorage->setRowRepeat(row, 1);
608 }
609
richText(int column,int row) const610 QSharedPointer<QTextDocument> CellStorage::richText(int column, int row) const
611 {
612 #ifdef CALLIGRA_SHEETS_MT
613 QReadLocker rl(&d->bigUglyLock);
614 #endif
615 return d->richTextStorage->lookup(column, row);
616 }
617
setRichText(int column,int row,QSharedPointer<QTextDocument> text)618 void CellStorage::setRichText(int column, int row, QSharedPointer<QTextDocument> text)
619 {
620 #ifdef CALLIGRA_SHEETS_MT
621 QWriteLocker(&d->bigUglyLock);
622 #endif
623 QSharedPointer<QTextDocument> old;
624 if (text.isNull())
625 old = d->richTextStorage->take(column, row);
626 else
627 old = d->richTextStorage->insert(column, row, text);
628
629 // recording undo?
630 if (d->undoData && text != old)
631 d->undoData->richTexts << qMakePair(QPoint(column, row), old);
632 }
633
validity(int column,int row) const634 Validity CellStorage::validity(int column, int row) const
635 {
636 #ifdef CALLIGRA_SHEETS_MT
637 QReadLocker rl(&d->bigUglyLock);
638 #endif
639 return d->validityStorage->contains(QPoint(column, row));
640 }
641
setValidity(const Region & region,Validity validity)642 void CellStorage::setValidity(const Region& region, Validity validity)
643 {
644 #ifdef CALLIGRA_SHEETS_MT
645 QWriteLocker(&d->bigUglyLock);
646 #endif
647 // recording undo?
648 if (d->undoData)
649 d->undoData->validities << d->validityStorage->undoData(region);
650
651 d->validityStorage->insert(region, validity);
652 if (!d->sheet->map()->isLoading()) {
653 foreach (const QRect& r, region.rects()) {
654 d->rowRepeatStorage->splitRowRepeat(r.top());
655 d->rowRepeatStorage->splitRowRepeat(r.bottom()+1);
656 }
657 }
658 }
659
value(int column,int row) const660 Value CellStorage::value(int column, int row) const
661 {
662 #ifdef CALLIGRA_SHEETS_MT
663 QReadLocker rl(&d->bigUglyLock);
664 #endif
665 return d->valueStorage->lookup(column, row);
666 }
667
valueRegion(const Region & region) const668 Value CellStorage::valueRegion(const Region& region) const
669 {
670 #ifdef CALLIGRA_SHEETS_MT
671 QReadLocker rl(&d->bigUglyLock);
672 #endif
673 // create a subStorage with adjusted origin
674 return Value(d->valueStorage->subStorage(region, false), region.boundingRect().size());
675 }
676
setValue(int column,int row,const Value & value)677 void CellStorage::setValue(int column, int row, const Value& value)
678 {
679 #ifdef CALLIGRA_SHEETS_MT
680 QWriteLocker(&d->bigUglyLock);
681 #endif
682 // release any lock
683 unlockCells(column, row);
684
685 Value old;
686 if (value.isEmpty())
687 old = d->valueStorage->take(column, row);
688 else
689 old = d->valueStorage->insert(column, row, value);
690
691 // value changed?
692 if (value != old) {
693 if (!d->sheet->map()->isLoading()) {
694 // Always trigger a repainting and a binding update.
695 CellDamage::Changes changes = CellDamage::Appearance | CellDamage::Binding;
696 // Trigger a recalculation of the consuming cells, only if we are not
697 // already in a recalculation process.
698 if (!d->sheet->map()->recalcManager()->isActive())
699 changes |= CellDamage::Value;
700 d->sheet->map()->addDamage(new CellDamage(Cell(d->sheet, column, row), changes));
701 // Also trigger a relayouting of the first non-empty cell to the left of this one
702 int prevCol;
703 Value v = d->valueStorage->prevInRow(column, row, &prevCol);
704 if (!v.isEmpty())
705 d->sheet->map()->addDamage(new CellDamage(Cell(d->sheet, prevCol, row), CellDamage::Appearance));
706 d->rowRepeatStorage->setRowRepeat(row, 1);
707 }
708 // recording undo?
709 if (d->undoData)
710 d->undoData->values << qMakePair(QPoint(column, row), old);
711 }
712 }
713
doesMergeCells(int column,int row) const714 bool CellStorage::doesMergeCells(int column, int row) const
715 {
716 #ifdef CALLIGRA_SHEETS_MT
717 QReadLocker rl(&d->bigUglyLock);
718 #endif
719 const QPair<QRectF, bool> pair = d->fusionStorage->containedPair(QPoint(column, row));
720 if (pair.first.isNull())
721 return false;
722 if (pair.second == false)
723 return false;
724 // master cell?
725 if (pair.first.toRect().topLeft() != QPoint(column, row))
726 return false;
727 return true;
728 }
729
isPartOfMerged(int column,int row) const730 bool CellStorage::isPartOfMerged(int column, int row) const
731 {
732 #ifdef CALLIGRA_SHEETS_MT
733 QReadLocker rl(&d->bigUglyLock);
734 #endif
735 const QPair<QRectF, bool> pair = d->fusionStorage->containedPair(QPoint(column, row));
736 if (pair.first.isNull())
737 return false;
738 if (pair.second == false)
739 return false;
740 // master cell?
741 if (pair.first.toRect().topLeft() == QPoint(column, row))
742 return false;
743 return true;
744 }
745
mergeCells(int column,int row,int numXCells,int numYCells)746 void CellStorage::mergeCells(int column, int row, int numXCells, int numYCells)
747 {
748 #ifdef CALLIGRA_SHEETS_MT
749 QWriteLocker(&d->bigUglyLock);
750 #endif
751 // Start by unmerging the cells that we merge right now
752 const QPair<QRectF, bool> pair = d->fusionStorage->containedPair(QPoint(column, row));
753 if (!pair.first.isNull())
754 d->fusionStorage->insert(Region(pair.first.toRect()), false);
755 // Merge the cells
756 if (numXCells != 0 || numYCells != 0)
757 d->fusionStorage->insert(Region(column, row, numXCells + 1, numYCells + 1), true);
758 if (!d->sheet->map()->isLoading())
759 d->rowRepeatStorage->setRowRepeat(row, 1);
760 }
761
masterCell(int column,int row) const762 Cell CellStorage::masterCell(int column, int row) const
763 {
764 #ifdef CALLIGRA_SHEETS_MT
765 QReadLocker rl(&d->bigUglyLock);
766 #endif
767 const QPair<QRectF, bool> pair = d->fusionStorage->containedPair(QPoint(column, row));
768 if (pair.first.isNull())
769 return Cell(d->sheet, column, row);
770 if (pair.second == false)
771 return Cell(d->sheet, column, row);
772 return Cell(d->sheet, pair.first.toRect().topLeft());
773 }
774
mergedXCells(int column,int row) const775 int CellStorage::mergedXCells(int column, int row) const
776 {
777 #ifdef CALLIGRA_SHEETS_MT
778 QReadLocker rl(&d->bigUglyLock);
779 #endif
780 const QPair<QRectF, bool> pair = d->fusionStorage->containedPair(QPoint(column, row));
781 if (pair.first.isNull())
782 return 0;
783 // Not the master cell?
784 if (pair.first.topLeft() != QPoint(column, row))
785 return 0;
786 return pair.first.toRect().width() - 1;
787 }
788
mergedYCells(int column,int row) const789 int CellStorage::mergedYCells(int column, int row) const
790 {
791 #ifdef CALLIGRA_SHEETS_MT
792 QReadLocker rl(&d->bigUglyLock);
793 #endif
794 const QPair<QRectF, bool> pair = d->fusionStorage->containedPair(QPoint(column, row));
795 if (pair.first.isNull())
796 return 0;
797 // Not the master cell?
798 if (pair.first.topLeft() != QPoint(column, row))
799 return 0;
800 return pair.first.toRect().height() - 1;
801 }
802
masterCells(const Region & region) const803 QList<Cell> CellStorage::masterCells(const Region& region) const
804 {
805 #ifdef CALLIGRA_SHEETS_MT
806 QReadLocker rl(&d->bigUglyLock);
807 #endif
808 const QList<QPair<QRectF, bool> > pairs = d->fusionStorage->intersectingPairs(region);
809 if (pairs.isEmpty())
810 return QList<Cell>();
811 QList<Cell> masterCells;
812 for (int i = 0; i < pairs.count(); ++i) {
813 if (pairs[i].first.isNull())
814 continue;
815 if (pairs[i].second == false)
816 continue;
817 masterCells.append(Cell(d->sheet, pairs[i].first.toRect().topLeft()));
818 }
819 return masterCells;
820 }
821
locksCells(int column,int row) const822 bool CellStorage::locksCells(int column, int row) const
823 {
824 #ifdef CALLIGRA_SHEETS_MT
825 QReadLocker rl(&d->bigUglyLock);
826 #endif
827 const QPair<QRectF, bool> pair = d->matrixStorage->containedPair(QPoint(column, row));
828 if (pair.first.isNull())
829 return false;
830 if (pair.second == false)
831 return false;
832 // master cell?
833 if (pair.first.toRect().topLeft() != QPoint(column, row))
834 return false;
835 return true;
836 }
837
isLocked(int column,int row) const838 bool CellStorage::isLocked(int column, int row) const
839 {
840 #ifdef CALLIGRA_SHEETS_MT
841 QReadLocker rl(&d->bigUglyLock);
842 #endif
843 const QPair<QRectF, bool> pair = d->matrixStorage->containedPair(QPoint(column, row));
844 if (pair.first.isNull())
845 return false;
846 if (pair.second == false)
847 return false;
848 // master cell?
849 if (pair.first.toRect().topLeft() == QPoint(column, row))
850 return false;
851 return true;
852 }
853
hasLockedCells(const Region & region) const854 bool CellStorage::hasLockedCells(const Region& region) const
855 {
856 #ifdef CALLIGRA_SHEETS_MT
857 QReadLocker rl(&d->bigUglyLock);
858 #endif
859 typedef QPair<QRectF, bool> RectBoolPair;
860 QList<QPair<QRectF, bool> > pairs = d->matrixStorage->intersectingPairs(region);
861 foreach (const RectBoolPair& pair, pairs) {
862 if (pair.first.isNull())
863 continue;
864 if (pair.second == false)
865 continue;
866 // more than just the master cell in the region?
867 const QPoint topLeft = pair.first.toRect().topLeft();
868 if (pair.first.width() >= 1) {
869 if (region.contains(topLeft + QPoint(1, 0), d->sheet))
870 return true;
871 }
872 if (pair.first.height() >= 1) {
873 if (region.contains(topLeft + QPoint(0, 1), d->sheet))
874 return true;
875 }
876 }
877 return false;
878 }
879
lockCells(const QRect & rect)880 void CellStorage::lockCells(const QRect& rect)
881 {
882 #ifdef CALLIGRA_SHEETS_MT
883 QWriteLocker(&d->bigUglyLock);
884 #endif
885 // Start by unlocking the cells that we lock right now
886 const QPair<QRectF, bool> pair = d->matrixStorage->containedPair(rect.topLeft()); // FIXME
887 if (!pair.first.isNull())
888 d->matrixStorage->insert(Region(pair.first.toRect()), false);
889 // Lock the cells
890 if (rect.width() > 1 || rect.height() > 1)
891 d->matrixStorage->insert(Region(rect), true);
892 }
893
unlockCells(int column,int row)894 void CellStorage::unlockCells(int column, int row)
895 {
896 #ifdef CALLIGRA_SHEETS_MT
897 QWriteLocker(&d->bigUglyLock);
898 #endif
899 const QPair<QRectF, bool> pair = d->matrixStorage->containedPair(QPoint(column, row));
900 if (pair.first.isNull())
901 return;
902 if (pair.second == false)
903 return;
904 if (pair.first.toRect().topLeft() != QPoint(column, row))
905 return;
906 const QRect rect = pair.first.toRect();
907 d->matrixStorage->insert(Region(rect), false);
908 // clear the values
909 for (int r = rect.top(); r <= rect.bottom(); ++r) {
910 for (int c = rect.left(); c <= rect.right(); ++c) {
911 if (r != rect.top() || c != rect.left())
912 setValue(c, r, Value());
913 }
914 }
915 // recording undo?
916 if (d->undoData)
917 d->undoData->matrices << pair;
918 }
919
lockedCells(int column,int row) const920 QRect CellStorage::lockedCells(int column, int row) const
921 {
922 #ifdef CALLIGRA_SHEETS_MT
923 QReadLocker rl(&d->bigUglyLock);
924 #endif
925 const QPair<QRectF, bool> pair = d->matrixStorage->containedPair(QPoint(column, row));
926 if (pair.first.isNull())
927 return QRect(column, row, 1, 1);
928 if (pair.second == false)
929 return QRect(column, row, 1, 1);
930 if (pair.first.toRect().topLeft() != QPoint(column, row))
931 return QRect(column, row, 1, 1);
932 return pair.first.toRect();
933 }
934
insertColumns(int position,int number)935 void CellStorage::insertColumns(int position, int number)
936 {
937 #ifdef CALLIGRA_SHEETS_MT
938 QWriteLocker(&d->bigUglyLock);
939 #endif
940 // Trigger a dependency update of the cells, which have a formula. (old positions)
941 // FIXME Stefan: Would it be better to directly alter the dependency tree?
942 // TODO Stefan: Optimize: Avoid the double creation of the sub-storages, but don't process
943 // formulas, that will get out of bounds after the operation.
944 const Region invalidRegion(QRect(QPoint(position, 1), QPoint(KS_colMax, KS_rowMax)), d->sheet);
945 PointStorage<Formula> subStorage = d->formulaStorage->subStorage(invalidRegion);
946 Cell cell;
947 for (int i = 0; i < subStorage.count(); ++i) {
948 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
949 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
950 }
951 // Trigger an update of the bindings and the named areas.
952 d->sheet->map()->addDamage(new CellDamage(d->sheet, invalidRegion, CellDamage::Binding | CellDamage::NamedArea));
953
954 QList< QPair<QRectF, Binding> > bindings = d->bindingStorage->insertColumns(position, number);
955 QList< QPair<QRectF, QString> > comments = d->commentStorage->insertColumns(position, number);
956 QList< QPair<QRectF, Conditions> > conditions = d->conditionsStorage->insertColumns(position, number);
957 QList< QPair<QRectF, Database> > databases = d->databaseStorage->insertColumns(position, number);
958 QVector< QPair<QPoint, Formula> > formulas = d->formulaStorage->insertColumns(position, number);
959 QList< QPair<QRectF, bool> > fusions = d->fusionStorage->insertColumns(position, number);
960 QVector< QPair<QPoint, QString> > links = d->linkStorage->insertColumns(position, number);
961 QList< QPair<QRectF, bool> > matrices = d->matrixStorage->insertColumns(position, number);
962 QList< QPair<QRectF, QString> > namedAreas = d->namedAreaStorage->insertColumns(position, number);
963 QList< QPair<QRectF, SharedSubStyle> > styles = d->styleStorage->insertColumns(position, number);
964 QVector< QPair<QPoint, QString> > userInputs = d->userInputStorage->insertColumns(position, number);
965 QVector< QPair<QPoint, QSharedPointer<QTextDocument> > > richTexts = d->richTextStorage->insertColumns(position, number);
966 QList< QPair<QRectF, Validity> > validities = d->validityStorage->insertColumns(position, number);
967 QVector< QPair<QPoint, Value> > values = d->valueStorage->insertColumns(position, number);
968 // recording undo?
969 if (d->undoData) {
970 d->undoData->bindings << bindings;
971 d->undoData->comments << comments;
972 d->undoData->conditions << conditions;
973 d->undoData->databases << databases;
974 d->undoData->formulas << formulas;
975 d->undoData->fusions << fusions;
976 d->undoData->links << links;
977 d->undoData->matrices << matrices;
978 d->undoData->namedAreas << namedAreas;
979 d->undoData->styles << styles;
980 d->undoData->userInputs << userInputs;
981 d->undoData->validities << validities;
982 d->undoData->values << values;
983 d->undoData->richTexts << richTexts;
984 }
985
986 // Trigger a dependency update of the cells, which have a formula. (new positions)
987 subStorage = d->formulaStorage->subStorage(invalidRegion);
988 for (int i = 0; i < subStorage.count(); ++i) {
989 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
990 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
991 }
992 // Trigger a recalculation only for the cells, that depend on values in the changed region.
993 Region providers = d->sheet->map()->dependencyManager()->reduceToProvidingRegion(invalidRegion);
994 d->sheet->map()->addDamage(new CellDamage(d->sheet, providers, CellDamage::Value));
995 }
996
removeColumns(int position,int number)997 void CellStorage::removeColumns(int position, int number)
998 {
999 #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
insertRows(int position,int number)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
removeRows(int position,int number)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
removeShiftLeft(const QRect & rect)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
insertShiftRight(const QRect & rect)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
removeShiftUp(const QRect & rect)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
insertShiftDown(const QRect & rect)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
firstInColumn(int col,Visiting visiting) const1426 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
firstInRow(int row,Visiting visiting) const1445 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
lastInColumn(int col,Visiting visiting) const1467 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
lastInRow(int row,Visiting visiting) const1484 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
nextInColumn(int col,int row,Visiting visiting) const1501 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
nextInRow(int col,int row,Visiting visiting) const1519 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
prevInColumn(int col,int row,Visiting visiting) const1541 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
prevInRow(int col,int row,Visiting visiting) const1558 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
columns(bool includeStyles) const1575 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
rows(bool includeStyles) const1596 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
subStorage(const Region & region) const1617 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
bindingStorage() const1629 const BindingStorage* CellStorage::bindingStorage() const
1630 {
1631 return d->bindingStorage;
1632 }
1633
commentStorage() const1634 const CommentStorage* CellStorage::commentStorage() const
1635 {
1636 return d->commentStorage;
1637 }
1638
conditionsStorage() const1639 const ConditionsStorage* CellStorage::conditionsStorage() const
1640 {
1641 return d->conditionsStorage;
1642 }
1643
formulaStorage() const1644 const FormulaStorage* CellStorage::formulaStorage() const
1645 {
1646 return d->formulaStorage;
1647 }
1648
fusionStorage() const1649 const FusionStorage* CellStorage::fusionStorage() const
1650 {
1651 return d->fusionStorage;
1652 }
1653
linkStorage() const1654 const LinkStorage* CellStorage::linkStorage() const
1655 {
1656 return d->linkStorage;
1657 }
1658
styleStorage() const1659 const StyleStorage* CellStorage::styleStorage() const
1660 {
1661 return d->styleStorage;
1662 }
1663
userInputStorage() const1664 const UserInputStorage* CellStorage::userInputStorage() const
1665 {
1666 return d->userInputStorage;
1667 }
1668
validityStorage() const1669 const ValidityStorage* CellStorage::validityStorage() const
1670 {
1671 return d->validityStorage;
1672 }
1673
valueStorage() const1674 const ValueStorage* CellStorage::valueStorage() const
1675 {
1676 return d->valueStorage;
1677 }
1678
startUndoRecording()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
stopUndoRecording(KUndo2Command * parent)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
loadConditions(const QList<QPair<QRegion,Conditions>> & conditions)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
loadStyles(const QList<QPair<QRegion,Style>> & styles)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
invalidateStyleCache()1723 void CellStorage::invalidateStyleCache()
1724 {
1725 d->styleStorage->invalidateCache();
1726 }
1727
rowRepeat(int row) const1728 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
firstIdenticalRow(int row) const1736 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
setRowsRepeated(int row,int count)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 }
1751