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// KDE
33#include <klocale.h>
34
35// Calligra
36#include <KoXmlWriter.h>
37
38// KSpread
39#include "BindingStorage.h"
40#include "ConditionsStorage.h"
41#include "Damages.h"
42#include "DependencyManager.h"
43#include "FormulaStorage.h"
44#include "Map.h"
45#include "ModelSupport.h"
46#include "RecalcManager.h"
47#include "RectStorage.h"
48#include "RowRepeatStorage.h"
49#include "Sheet.h"
50#include "StyleStorage.h"
51#include "ValidityStorage.h"
52#include "ValueStorage.h"
53
54// commands
55#include "commands/PointStorageUndoCommand.h"
56#include "commands/RectStorageUndoCommand.h"
57#include "commands/StyleStorageUndoCommand.h"
58
59// database
60#include "database/DatabaseStorage.h"
61#include "database/DatabaseManager.h"
62
63Q_DECLARE_METATYPE(QSharedPointer<QTextDocument>)
64
65using namespace Calligra::Sheets;
66
67typedef RectStorage<QString> NamedAreaStorage;
68
69class CellStorage::Private
70{
71public:
72 Private(Sheet* sheet)
73 : sheet(sheet)
74 , bindingStorage(new BindingStorage(sheet->map()))
75 , commentStorage(new CommentStorage(sheet->map()))
76 , conditionsStorage(new ConditionsStorage(sheet->map()))
77 , databaseStorage(new DatabaseStorage(sheet->map()))
78 , formulaStorage(new FormulaStorage())
79 , fusionStorage(new FusionStorage(sheet->map()))
80 , linkStorage(new LinkStorage())
81 , matrixStorage(new MatrixStorage(sheet->map()))
82 , namedAreaStorage(new NamedAreaStorage(sheet->map()))
83 , styleStorage(new StyleStorage(sheet->map()))
84 , userInputStorage(new UserInputStorage())
85 , validityStorage(new ValidityStorage(sheet->map()))
86 , valueStorage(new ValueStorage())
87 , richTextStorage(new RichTextStorage())
88 , rowRepeatStorage(new RowRepeatStorage())
89 , undoData(0)
90#ifdef CALLIGRA_SHEETS_MT
91 , bigUglyLock(QReadWriteLock::Recursive)
92#endif
93 {}
94
95 Private(const Private& other, Sheet* sheet)
96 : sheet(sheet)
97 , bindingStorage(new BindingStorage(*other.bindingStorage))
98 , commentStorage(new CommentStorage(*other.commentStorage))
99 , conditionsStorage(new ConditionsStorage(*other.conditionsStorage))
100 , databaseStorage(new DatabaseStorage(*other.databaseStorage))
101 , formulaStorage(new FormulaStorage(*other.formulaStorage))
102 , fusionStorage(new FusionStorage(*other.fusionStorage))
103 , linkStorage(new LinkStorage(*other.linkStorage))
104 , matrixStorage(new MatrixStorage(*other.matrixStorage))
105 , namedAreaStorage(new NamedAreaStorage(*other.namedAreaStorage))
106 , styleStorage(new StyleStorage(*other.styleStorage))
107 , userInputStorage(new UserInputStorage(*other.userInputStorage))
108 , validityStorage(new ValidityStorage(*other.validityStorage))
109 , valueStorage(new ValueStorage(*other.valueStorage))
110 , richTextStorage(new RichTextStorage(*other.richTextStorage))
111 , rowRepeatStorage(new RowRepeatStorage(*other.rowRepeatStorage))
112 , undoData(0)
113#ifdef CALLIGRA_SHEETS_MT
114 , bigUglyLock(QReadWriteLock::Recursive)
115#endif
116 {}
117
118 ~Private() {
119 delete bindingStorage;
120 delete commentStorage;
121 delete conditionsStorage;
122 delete databaseStorage;
123 delete formulaStorage;
124 delete fusionStorage;
125 delete linkStorage;
126 delete matrixStorage;
127 delete namedAreaStorage;
128 delete styleStorage;
129 delete userInputStorage;
130 delete validityStorage;
131 delete valueStorage;
132 delete richTextStorage;
133 delete rowRepeatStorage;
134 }
135
136 void createCommand(KUndo2Command *parent) const;
137
138 Sheet* sheet;
139 BindingStorage* bindingStorage;
140 CommentStorage* commentStorage;
141 ConditionsStorage* conditionsStorage;
142 DatabaseStorage* databaseStorage;
143 FormulaStorage* formulaStorage;
144 FusionStorage* fusionStorage;
145 LinkStorage* linkStorage;
146 MatrixStorage* matrixStorage;
147 NamedAreaStorage* namedAreaStorage;
148 StyleStorage* styleStorage;
149 UserInputStorage* userInputStorage;
150 ValidityStorage* validityStorage;
151 ValueStorage* valueStorage;
152 RichTextStorage* richTextStorage;
153 RowRepeatStorage* rowRepeatStorage;
154 CellStorageUndoData* undoData;
155
156#ifdef CALLIGRA_SHEETS_MT
157 QReadWriteLock bigUglyLock;
158#endif
159};
160
161void CellStorage::Private::createCommand(KUndo2Command *parent) const
162{
163 if (!undoData->bindings.isEmpty()) {
164 RectStorageUndoCommand<Binding> *const command
165 = new RectStorageUndoCommand<Binding>(sheet->model(), SourceRangeRole, parent);
166 command->add(undoData->bindings);
167 }
168 if (!undoData->comments.isEmpty()) {
169 RectStorageUndoCommand<QString> *const command
170 = new RectStorageUndoCommand<QString>(sheet->model(), CommentRole, parent);
171 command->add(undoData->comments);
172 }
173 if (!undoData->conditions.isEmpty()) {
174 RectStorageUndoCommand<Conditions> *const command
175 = new RectStorageUndoCommand<Conditions>(sheet->model(), ConditionRole, parent);
176 command->add(undoData->conditions);
177 }
178 if (!undoData->databases.isEmpty()) {
179 RectStorageUndoCommand<Database> *const command
180 = new RectStorageUndoCommand<Database>(sheet->model(), TargetRangeRole, parent);
181 command->add(undoData->databases);
182 }
183 if (!undoData->formulas.isEmpty()) {
184 PointStorageUndoCommand<Formula> *const command
185 = new PointStorageUndoCommand<Formula>(sheet->model(), FormulaRole, parent);
186 command->add(undoData->formulas);
187 }
188 if (!undoData->fusions.isEmpty()) {
189 RectStorageUndoCommand<bool> *const command
190 = new RectStorageUndoCommand<bool>(sheet->model(), FusionedRangeRole, parent);
191 command->add(undoData->fusions);
192 }
193 if (!undoData->links.isEmpty()) {
194 PointStorageUndoCommand<QString> *const command
195 = new PointStorageUndoCommand<QString>(sheet->model(), LinkRole, parent);
196 command->add(undoData->links);
197 }
198 if (!undoData->matrices.isEmpty()) {
199 RectStorageUndoCommand<bool> *const command
200 = new RectStorageUndoCommand<bool>(sheet->model(), LockedRangeRole, parent);
201 command->add(undoData->matrices);
202 }
203 if (!undoData->namedAreas.isEmpty()) {
204 RectStorageUndoCommand<QString> *const command
205 = new RectStorageUndoCommand<QString>(sheet->model(), NamedAreaRole, parent);
206 command->add(undoData->namedAreas);
207 }
208 if (!undoData->richTexts.isEmpty()) {
209 PointStorageUndoCommand<QSharedPointer<QTextDocument> > *const command
210 = new PointStorageUndoCommand<QSharedPointer<QTextDocument> >(sheet->model(), RichTextRole, parent);
211 command->add(undoData->richTexts);
212 }
213 if (!undoData->styles.isEmpty()) {
214 StyleStorageUndoCommand *const command
215 = new StyleStorageUndoCommand(styleStorage, parent);
216 command->add(undoData->styles);
217 }
218 if (!undoData->userInputs.isEmpty()) {
219 PointStorageUndoCommand<QString> *const command
220 = new PointStorageUndoCommand<QString>(sheet->model(), UserInputRole, parent);
221 command->add(undoData->userInputs);
222 }
223 if (!undoData->validities.isEmpty()) {
224 RectStorageUndoCommand<Validity> *const command
225 = new RectStorageUndoCommand<Validity>(sheet->model(), ValidityRole, parent);
226 command->add(undoData->validities);
227 }
228 if (!undoData->values.isEmpty()) {
229 PointStorageUndoCommand<Value> *const command
230 = new PointStorageUndoCommand<Value>(sheet->model(), ValueRole, parent);
231 command->add(undoData->values);
232 }
233}
234
235
236CellStorage::CellStorage(Sheet* sheet)
237 : QObject(sheet)
238 , d(new Private(sheet))
239{
240}
241
242CellStorage::CellStorage(const CellStorage& other)
243 : QObject(other.d->sheet)
244 , d(new Private(*other.d, other.d->sheet))
245{
246}
247
248CellStorage::CellStorage(const CellStorage& other, Sheet* sheet)
249 : QObject(sheet)
250 , d(new Private(*other.d, sheet))
251{
252}
253
254CellStorage::~CellStorage()
255{
256 delete d;
257}
258
259Sheet* CellStorage::sheet() const
260{
261 return d->sheet;
262}
263
264void CellStorage::take(int col, int row)
265{
266#ifdef CALLIGRA_SHEETS_MT
267 QWriteLocker(&d->bigUglyLock);
268#endif
269
270 Formula oldFormula;
271 QString oldLink;
272 QString oldUserInput;
273 Value oldValue;
274 QSharedPointer<QTextDocument> oldRichText;
275
276 oldFormula = d->formulaStorage->take(col, row);
277 oldLink = d->linkStorage->take(col, row);
278 oldUserInput = d->userInputStorage->take(col, row);
279 oldValue = d->valueStorage->take(col, row);
280 oldRichText = d->richTextStorage->take(col, row);
281
282 if (!d->sheet->map()->isLoading()) {
283 // Trigger a recalculation of the consuming cells.
284 CellDamage::Changes changes = CellDamage:: Binding | CellDamage::Formula | CellDamage::Value;
285 d->sheet->map()->addDamage(new CellDamage(Cell(d->sheet, col, row), changes));
286
287 d->rowRepeatStorage->setRowRepeat(row, 1);
288 }
289 // also trigger a relayout of the first non-empty cell to the left of this cell
290 int prevCol;
291 Value v = d->valueStorage->prevInRow(col, row, &prevCol);
292 if (!v.isEmpty())
293 d->sheet->map()->addDamage(new CellDamage(Cell(d->sheet, prevCol, row), CellDamage::Appearance));
294
295
296 // recording undo?
297 if (d->undoData) {
298 d->undoData->formulas << qMakePair(QPoint(col, row), oldFormula);
299 d->undoData->links << qMakePair(QPoint(col, row), oldLink);
300 d->undoData->userInputs << qMakePair(QPoint(col, row), oldUserInput);
301 d->undoData->values << qMakePair(QPoint(col, row), oldValue);
302 d->undoData->richTexts << qMakePair(QPoint(col, row), oldRichText);
303 }
304}
305
306Binding CellStorage::binding(int column, int row) const
307{
308#ifdef CALLIGRA_SHEETS_MT
309 QReadLocker rl(&d->bigUglyLock);
310#endif
311 return d->bindingStorage->contains(QPoint(column, row));
312}
313
314void CellStorage::setBinding(const Region& region, const Binding& binding)
315{
316#ifdef CALLIGRA_SHEETS_MT
317 QWriteLocker(&d->bigUglyLock);
318#endif
319 // recording undo?
320 if (d->undoData)
321 d->undoData->bindings << d->bindingStorage->undoData(region);
322
323 d->bindingStorage->insert(region, binding);
324}
325
326void CellStorage::removeBinding(const Region& region, const Binding& binding)
327{
328#ifdef CALLIGRA_SHEETS_MT
329 QWriteLocker(&d->bigUglyLock);
330#endif
331 // recording undo?
332 if (d->undoData) {
333 d->undoData->bindings << d->bindingStorage->undoData(region);
334 }
335 d->bindingStorage->remove(region, binding);
336}
337
338QString CellStorage::comment(int column, int row) const
339{
340#ifdef CALLIGRA_SHEETS_MT
341 QReadLocker rl(&d->bigUglyLock);
342#endif
343 return d->commentStorage->contains(QPoint(column, row));
344}
345
346void CellStorage::setComment(const Region& region, const QString& comment)
347{
348#ifdef CALLIGRA_SHEETS_MT
349 QWriteLocker(&d->bigUglyLock);
350#endif
351 // recording undo?
352 if (d->undoData)
353 d->undoData->comments << d->commentStorage->undoData(region);
354
355 d->commentStorage->insert(region, comment);
356 if (!d->sheet->map()->isLoading()) {
357 foreach (const QRect& r, region.rects()) {
358 d->rowRepeatStorage->splitRowRepeat(r.top());
359 d->rowRepeatStorage->splitRowRepeat(r.bottom()+1);
360 }
361 }
362}
363
364Conditions CellStorage::conditions(int column, int row) const
365{
366#ifdef CALLIGRA_SHEETS_MT
367 QReadLocker rl(&d->bigUglyLock);
368#endif
369 return d->conditionsStorage->contains(QPoint(column, row));
370}
371
372void CellStorage::setConditions(const Region& region, Conditions conditions)
373{
374#ifdef CALLIGRA_SHEETS_MT
375 QWriteLocker(&d->bigUglyLock);
376#endif
377 // recording undo?
378 if (d->undoData)
379 d->undoData->conditions << d->conditionsStorage->undoData(region);
380
381 d->conditionsStorage->insert(region, conditions);
382 if (!d->sheet->map()->isLoading()) {
383 foreach (const QRect& r, region.rects()) {
384 d->rowRepeatStorage->splitRowRepeat(r.top());
385 d->rowRepeatStorage->splitRowRepeat(r.bottom()+1);
386 }
387 }
388}
389
390Database CellStorage::database(int column, int row) const
391{
392#ifdef CALLIGRA_SHEETS_MT
393 QReadLocker rl(&d->bigUglyLock);
394#endif
395 QPair<QRectF, Database> pair = d->databaseStorage->containedPair(QPoint(column, row));
396 if (pair.first.isEmpty())
397 return Database();
398 if (pair.second.isEmpty())
399 return Database();
400 // update the range, which might get changed
401 Database database = pair.second;
402 database.setRange(Region(pair.first.toRect(), d->sheet));
403 return database;
404}
405
406QList< QPair<QRectF, Database> > CellStorage::databases(const Region& region) const
407{
408#ifdef CALLIGRA_SHEETS_MT
409 QReadLocker rl(&d->bigUglyLock);
410#endif
411 return d->databaseStorage->intersectingPairs(region);
412}
413
414void CellStorage::setDatabase(const Region& region, const Database& database)
415{
416#ifdef CALLIGRA_SHEETS_MT
417 QWriteLocker(&d->bigUglyLock);
418#endif
419 // recording undo?
420 if (d->undoData)
421 d->undoData->databases << d->databaseStorage->undoData(region);
422
423 d->databaseStorage->insert(region, database);
424}
425
426Formula CellStorage::formula(int column, int row) const
427{
428#ifdef CALLIGRA_SHEETS_MT
429 QReadLocker rl(&d->bigUglyLock);
430#endif
431 return d->formulaStorage->lookup(column, row, Formula::empty());
432}
433
434void CellStorage::setFormula(int column, int row, const Formula& formula)
435{
436#ifdef CALLIGRA_SHEETS_MT
437 QWriteLocker(&d->bigUglyLock);
438#endif
439 Formula old = Formula::empty();
440 if (formula.expression().isEmpty())
441 old = d->formulaStorage->take(column, row, Formula::empty());
442 else
443 old = d->formulaStorage->insert(column, row, formula);
444
445 // formula changed?
446 if (formula != old) {
447 if (!d->sheet->map()->isLoading()) {
448 // trigger an update of the dependencies and a recalculation
449 d->sheet->map()->addDamage(new CellDamage(Cell(d->sheet, column, row), CellDamage::Formula | CellDamage::Value));
450 d->rowRepeatStorage->setRowRepeat(row, 1);
451 }
452 // recording undo?
453 if (d->undoData) {
454 d->undoData->formulas << qMakePair(QPoint(column, row), old);
455 // Also store the old value, if there wasn't a formula before,
456 // because the new value is calculated later by the damage
457 // processing and is not recorded for undoing.
458 if (old == Formula())
459 d->undoData->values << qMakePair(QPoint(column, row), value(column, row));
460 }
461 }
462}
463
464QString CellStorage::link(int column, int row) const
465{
466#ifdef CALLIGRA_SHEETS_MT
467 QReadLocker rl(&d->bigUglyLock);
468#endif
469 return d->linkStorage->lookup(column, row);
470}
471
472void CellStorage::setLink(int column, int row, const QString& link)
473{
474#ifdef CALLIGRA_SHEETS_MT
475 QWriteLocker(&d->bigUglyLock);
476#endif
477 QString old;
478 if (link.isEmpty())
479 old = d->linkStorage->take(column, row);
480 else
481 old = d->linkStorage->insert(column, row, link);
482
483 // recording undo?
484 if (d->undoData && link != old)
485 d->undoData->links << qMakePair(QPoint(column, row), old);
486 if (!d->sheet->map()->isLoading())
487 d->rowRepeatStorage->setRowRepeat(row, 1);
488}
489
490QString CellStorage::namedArea(int column, int row) const
491{
492#ifdef CALLIGRA_SHEETS_MT
493 QReadLocker rl(&d->bigUglyLock);
494#endif
495 QPair<QRectF, QString> pair = d->namedAreaStorage->containedPair(QPoint(column, row));
496 if (pair.first.isEmpty())
497 return QString();
498 if (pair.second.isEmpty())
499 return QString();
500 return pair.second;
501}
502
503QList< QPair<QRectF, QString> > CellStorage::namedAreas(const Region& region) const
504{
505#ifdef CALLIGRA_SHEETS_MT
506 QReadLocker rl(&d->bigUglyLock);
507#endif
508 return d->namedAreaStorage->intersectingPairs(region);
509}
510
511void CellStorage::setNamedArea(const Region& region, const QString& namedArea)
512{
513#ifdef CALLIGRA_SHEETS_MT
514 QWriteLocker(&d->bigUglyLock);
515#endif
516 // recording undo?
517 if (d->undoData)
518 d->undoData->namedAreas << d->namedAreaStorage->undoData(region);
519
520 d->namedAreaStorage->insert(region, namedArea);
521}
522
523void CellStorage::removeNamedArea(const Region& region, const QString& namedArea)
524{
525#ifdef CALLIGRA_SHEETS_MT
526 QWriteLocker(&d->bigUglyLock);
527#endif
528 // recording undo?
529 if (d->undoData)
530 d->undoData->namedAreas << d->namedAreaStorage->undoData(region);
531
532 d->namedAreaStorage->remove(region, namedArea);
533}
534
535
536void CellStorage::emitInsertNamedArea(const Region &region, const QString &namedArea)
537{
538 emit insertNamedArea(region, namedArea);
539}
540
541Style CellStorage::style(int column, int row) const
542{
543#ifdef CALLIGRA_SHEETS_MT
544 QReadLocker rl(&d->bigUglyLock);
545#endif
546 return d->styleStorage->contains(QPoint(column, row));
547}
548
549Style CellStorage::style(const QRect& rect) const
550{
551#ifdef CALLIGRA_SHEETS_MT
552 QReadLocker rl(&d->bigUglyLock);
553#endif
554 return d->styleStorage->contains(rect);
555}
556
557void CellStorage::setStyle(const Region& region, const Style& style)
558{
559#ifdef CALLIGRA_SHEETS_MT
560 QWriteLocker(&d->bigUglyLock);
561#endif
562 // recording undo?
563 if (d->undoData)
564 d->undoData->styles << d->styleStorage->undoData(region);
565
566 d->styleStorage->insert(region, style);
567 if (!d->sheet->map()->isLoading()) {
568 foreach (const QRect& r, region.rects()) {
569 d->rowRepeatStorage->splitRowRepeat(r.top());
570 d->rowRepeatStorage->splitRowRepeat(r.bottom()+1);
571 }
572 }
573}
574
575void CellStorage::insertSubStyle(const QRect &rect, const SharedSubStyle &subStyle)
576{
577#ifdef CALLIGRA_SHEETS_MT
578 QWriteLocker(&d->bigUglyLock);
579#endif
580 d->styleStorage->insert(rect, subStyle);
581 if (!d->sheet->map()->isLoading()) {
582 d->rowRepeatStorage->splitRowRepeat(rect.top());
583 d->rowRepeatStorage->splitRowRepeat(rect.bottom()+1);
584 }
585}
586
587QString CellStorage::userInput(int column, int row) const
588{
589#ifdef CALLIGRA_SHEETS_MT
590 QReadLocker rl(&d->bigUglyLock);
591#endif
592 return d->userInputStorage->lookup(column, row);
593}
594
595void CellStorage::setUserInput(int column, int row, const QString& userInput)
596{
597#ifdef CALLIGRA_SHEETS_MT
598 QWriteLocker(&d->bigUglyLock);
599#endif
600 QString old;
601 if (userInput.isEmpty())
602 old = d->userInputStorage->take(column, row);
603 else
604 old = d->userInputStorage->insert(column, row, userInput);
605
606 // recording undo?
607 if (d->undoData && userInput != old)
608 d->undoData->userInputs << qMakePair(QPoint(column, row), old);
609 if (!d->sheet->map()->isLoading())
610 d->rowRepeatStorage->setRowRepeat(row, 1);
611}
612
613QSharedPointer<QTextDocument> CellStorage::richText(int column, int row) const
614{
615#ifdef CALLIGRA_SHEETS_MT
616 QReadLocker rl(&d->bigUglyLock);
617#endif
618 return d->richTextStorage->lookup(column, row);
619}
620
621void CellStorage::setRichText(int column, int row, QSharedPointer<QTextDocument> text)
622{
623#ifdef CALLIGRA_SHEETS_MT
624 QWriteLocker(&d->bigUglyLock);
625#endif
626 QSharedPointer<QTextDocument> old;
627 if (text.isNull())
628 old = d->richTextStorage->take(column, row);
629 else
630 old = d->richTextStorage->insert(column, row, text);
631
632 // recording undo?
633 if (d->undoData && text != old)
634 d->undoData->richTexts << qMakePair(QPoint(column, row), old);
635}
636
637Validity CellStorage::validity(int column, int row) const
638{
639#ifdef CALLIGRA_SHEETS_MT
640 QReadLocker rl(&d->bigUglyLock);
641#endif
642 return d->validityStorage->contains(QPoint(column, row));
643}
644
645void CellStorage::setValidity(const Region& region, Validity validity)
646{
647#ifdef CALLIGRA_SHEETS_MT
648 QWriteLocker(&d->bigUglyLock);
649#endif
650 // recording undo?
651 if (d->undoData)
652 d->undoData->validities << d->validityStorage->undoData(region);
653
654 d->validityStorage->insert(region, validity);
655 if (!d->sheet->map()->isLoading()) {
656 foreach (const QRect& r, region.rects()) {
657 d->rowRepeatStorage->splitRowRepeat(r.top());
658 d->rowRepeatStorage->splitRowRepeat(r.bottom()+1);
659 }
660 }
661}
662
663Value CellStorage::value(int column, int row) const
664{
665#ifdef CALLIGRA_SHEETS_MT
666 QReadLocker rl(&d->bigUglyLock);
667#endif
668 return d->valueStorage->lookup(column, row);
669}
670
671Value CellStorage::valueRegion(const Region& region) const
672{
673#ifdef CALLIGRA_SHEETS_MT
674 QReadLocker rl(&d->bigUglyLock);
675#endif
676 // create a subStorage with adjusted origin
677 return Value(d->valueStorage->subStorage(region, false), region.boundingRect().size());
678}
679
680void CellStorage::setValue(int column, int row, const Value& value)
681{
682#ifdef CALLIGRA_SHEETS_MT
683 QWriteLocker(&d->bigUglyLock);
684#endif
685 // release any lock
686 unlockCells(column, row);
687
688 Value old;
689 if (value.isEmpty())
690 old = d->valueStorage->take(column, row);
691 else
692 old = d->valueStorage->insert(column, row, value);
693
694 // value changed?
695 if (value != old) {
696 if (!d->sheet->map()->isLoading()) {
697 // Always trigger a repainting and a binding update.
698 CellDamage::Changes changes = CellDamage::Appearance | CellDamage::Binding;
699 // Trigger a recalculation of the consuming cells, only if we are not
700 // already in a recalculation process.
701 if (!d->sheet->map()->recalcManager()->isActive())
702 changes |= CellDamage::Value;
703 d->sheet->map()->addDamage(new CellDamage(Cell(d->sheet, column, row), changes));
704 // Also trigger a relayouting of the first non-empty cell to the left of this one
705 int prevCol;
706 Value v = d->valueStorage->prevInRow(column, row, &prevCol);
707 if (!v.isEmpty())
708 d->sheet->map()->addDamage(new CellDamage(Cell(d->sheet, prevCol, row), CellDamage::Appearance));
709 d->rowRepeatStorage->setRowRepeat(row, 1);
710 }
711 // recording undo?
712 if (d->undoData)
713 d->undoData->values << qMakePair(QPoint(column, row), old);
714 }
715}
716
717bool CellStorage::doesMergeCells(int column, int row) const
718{
719#ifdef CALLIGRA_SHEETS_MT
720 QReadLocker rl(&d->bigUglyLock);
721#endif
722 const QPair<QRectF, bool> pair = d->fusionStorage->containedPair(QPoint(column, row));
723 if (pair.first.isNull())
724 return false;
725 if (pair.second == false)
726 return false;
727 // master cell?
728 if (pair.first.toRect().topLeft() != QPoint(column, row))
729 return false;
730 return true;
731}
732
733bool CellStorage::isPartOfMerged(int column, int row) const
734{
735#ifdef CALLIGRA_SHEETS_MT
736 QReadLocker rl(&d->bigUglyLock);
737#endif
738 const QPair<QRectF, bool> pair = d->fusionStorage->containedPair(QPoint(column, row));
739 if (pair.first.isNull())
740 return false;
741 if (pair.second == false)
742 return false;
743 // master cell?
744 if (pair.first.toRect().topLeft() == QPoint(column, row))
745 return false;
746 return true;
747}
748
749void CellStorage::mergeCells(int column, int row, int numXCells, int numYCells)
750{
751#ifdef CALLIGRA_SHEETS_MT
752 QWriteLocker(&d->bigUglyLock);
753#endif
754 // Start by unmerging the cells that we merge right now
755 const QPair<QRectF, bool> pair = d->fusionStorage->containedPair(QPoint(column, row));
756 if (!pair.first.isNull())
757 d->fusionStorage->insert(Region(pair.first.toRect()), false);
758 // Merge the cells
759 if (numXCells != 0 || numYCells != 0)
760 d->fusionStorage->insert(Region(column, row, numXCells + 1, numYCells + 1), true);
761 if (!d->sheet->map()->isLoading())
762 d->rowRepeatStorage->setRowRepeat(row, 1);
763}
764
765Cell CellStorage::masterCell(int column, int row) const
766{
767#ifdef CALLIGRA_SHEETS_MT
768 QReadLocker rl(&d->bigUglyLock);
769#endif
770 const QPair<QRectF, bool> pair = d->fusionStorage->containedPair(QPoint(column, row));
771 if (pair.first.isNull())
772 return Cell(d->sheet, column, row);
773 if (pair.second == false)
774 return Cell(d->sheet, column, row);
775 return Cell(d->sheet, pair.first.toRect().topLeft());
776}
777
778int CellStorage::mergedXCells(int column, int row) const
779{
780#ifdef CALLIGRA_SHEETS_MT
781 QReadLocker rl(&d->bigUglyLock);
782#endif
783 const QPair<QRectF, bool> pair = d->fusionStorage->containedPair(QPoint(column, row));
784 if (pair.first.isNull())
785 return 0;
786 // Not the master cell?
787 if (pair.first.topLeft() != QPoint(column, row))
788 return 0;
789 return pair.first.toRect().width() - 1;
790}
791
792int CellStorage::mergedYCells(int column, int row) const
793{
794#ifdef CALLIGRA_SHEETS_MT
795 QReadLocker rl(&d->bigUglyLock);
796#endif
797 const QPair<QRectF, bool> pair = d->fusionStorage->containedPair(QPoint(column, row));
798 if (pair.first.isNull())
799 return 0;
800 // Not the master cell?
801 if (pair.first.topLeft() != QPoint(column, row))
802 return 0;
803 return pair.first.toRect().height() - 1;
804}
805
806QList<Cell> CellStorage::masterCells(const Region& region) const
807{
808#ifdef CALLIGRA_SHEETS_MT
809 QReadLocker rl(&d->bigUglyLock);
810#endif
811 const QList<QPair<QRectF, bool> > pairs = d->fusionStorage->intersectingPairs(region);
812 if (pairs.isEmpty())
813 return QList<Cell>();
814 QList<Cell> masterCells;
815 for (int i = 0; i < pairs.count(); ++i) {
816 if (pairs[i].first.isNull())
817 continue;
818 if (pairs[i].second == false)
819 continue;
820 masterCells.append(Cell(d->sheet, pairs[i].first.toRect().topLeft()));
821 }
822 return masterCells;
823}
824
825bool CellStorage::locksCells(int column, int row) const
826{
827#ifdef CALLIGRA_SHEETS_MT
828 QReadLocker rl(&d->bigUglyLock);
829#endif
830 const QPair<QRectF, bool> pair = d->matrixStorage->containedPair(QPoint(column, row));
831 if (pair.first.isNull())
832 return false;
833 if (pair.second == false)
834 return false;
835 // master cell?
836 if (pair.first.toRect().topLeft() != QPoint(column, row))
837 return false;
838 return true;
839}
840
841bool CellStorage::isLocked(int column, int row) const
842{
843#ifdef CALLIGRA_SHEETS_MT
844 QReadLocker rl(&d->bigUglyLock);
845#endif
846 const QPair<QRectF, bool> pair = d->matrixStorage->containedPair(QPoint(column, row));
847 if (pair.first.isNull())
848 return false;
849 if (pair.second == false)
850 return false;
851 // master cell?
852 if (pair.first.toRect().topLeft() == QPoint(column, row))
853 return false;
854 return true;
855}
856
857bool CellStorage::hasLockedCells(const Region& region) const
858{
859#ifdef CALLIGRA_SHEETS_MT
860 QReadLocker rl(&d->bigUglyLock);
861#endif
862 typedef QPair<QRectF, bool> RectBoolPair;
863 QList<QPair<QRectF, bool> > pairs = d->matrixStorage->intersectingPairs(region);
864 foreach (const RectBoolPair& pair, pairs) {
865 if (pair.first.isNull())
866 continue;
867 if (pair.second == false)
868 continue;
869 // more than just the master cell in the region?
870 const QPoint topLeft = pair.first.toRect().topLeft();
871 if (pair.first.width() >= 1) {
872 if (region.contains(topLeft + QPoint(1, 0), d->sheet))
873 return true;
874 }
875 if (pair.first.height() >= 1) {
876 if (region.contains(topLeft + QPoint(0, 1), d->sheet))
877 return true;
878 }
879 }
880 return false;
881}
882
883void CellStorage::lockCells(const QRect& rect)
884{
885#ifdef CALLIGRA_SHEETS_MT
886 QWriteLocker(&d->bigUglyLock);
887#endif
888 // Start by unlocking the cells that we lock right now
889 const QPair<QRectF, bool> pair = d->matrixStorage->containedPair(rect.topLeft()); // FIXME
890 if (!pair.first.isNull())
891 d->matrixStorage->insert(Region(pair.first.toRect()), false);
892 // Lock the cells
893 if (rect.width() > 1 || rect.height() > 1)
894 d->matrixStorage->insert(Region(rect), true);
895}
896
897void CellStorage::unlockCells(int column, int row)
898{
899#ifdef CALLIGRA_SHEETS_MT
900 QWriteLocker(&d->bigUglyLock);
901#endif
902 const QPair<QRectF, bool> pair = d->matrixStorage->containedPair(QPoint(column, row));
903 if (pair.first.isNull())
904 return;
905 if (pair.second == false)
906 return;
907 if (pair.first.toRect().topLeft() != QPoint(column, row))
908 return;
909 const QRect rect = pair.first.toRect();
910 d->matrixStorage->insert(Region(rect), false);
911 // clear the values
912 for (int r = rect.top(); r <= rect.bottom(); ++r) {
913 for (int c = rect.left(); c <= rect.right(); ++c) {
914 if (r != rect.top() || c != rect.left())
915 setValue(c, r, Value());
916 }
917 }
918 // recording undo?
919 if (d->undoData)
920 d->undoData->matrices << pair;
921}
922
923QRect CellStorage::lockedCells(int column, int row) const
924{
925#ifdef CALLIGRA_SHEETS_MT
926 QReadLocker rl(&d->bigUglyLock);
927#endif
928 const QPair<QRectF, bool> pair = d->matrixStorage->containedPair(QPoint(column, row));
929 if (pair.first.isNull())
930 return QRect(column, row, 1, 1);
931 if (pair.second == false)
932 return QRect(column, row, 1, 1);
933 if (pair.first.toRect().topLeft() != QPoint(column, row))
934 return QRect(column, row, 1, 1);
935 return pair.first.toRect();
936}
937
938void CellStorage::insertColumns(int position, int number)
939{
940#ifdef CALLIGRA_SHEETS_MT
941 QWriteLocker(&d->bigUglyLock);
942#endif
943 // Trigger a dependency update of the cells, which have a formula. (old positions)
944 // FIXME Stefan: Would it be better to directly alter the dependency tree?
945 // TODO Stefan: Optimize: Avoid the double creation of the sub-storages, but don't process
946 // formulas, that will get out of bounds after the operation.
947 const Region invalidRegion(QRect(QPoint(position, 1), QPoint(KS_colMax, KS_rowMax)), d->sheet);
948 PointStorage<Formula> subStorage = d->formulaStorage->subStorage(invalidRegion);
949 Cell cell;
950 for (int i = 0; i < subStorage.count(); ++i) {
951 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
952 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
953 }
954 // Trigger an update of the bindings and the named areas.
955 d->sheet->map()->addDamage(new CellDamage(d->sheet, invalidRegion, CellDamage::Binding | CellDamage::NamedArea));
956
957 QList< QPair<QRectF, Binding> > bindings = d->bindingStorage->insertColumns(position, number);
958 QList< QPair<QRectF, QString> > comments = d->commentStorage->insertColumns(position, number);
959 QList< QPair<QRectF, Conditions> > conditions = d->conditionsStorage->insertColumns(position, number);
960 QList< QPair<QRectF, Database> > databases = d->databaseStorage->insertColumns(position, number);
961 QVector< QPair<QPoint, Formula> > formulas = d->formulaStorage->insertColumns(position, number);
962 QList< QPair<QRectF, bool> > fusions = d->fusionStorage->insertColumns(position, number);
963 QVector< QPair<QPoint, QString> > links = d->linkStorage->insertColumns(position, number);
964 QList< QPair<QRectF, bool> > matrices = d->matrixStorage->insertColumns(position, number);
965 QList< QPair<QRectF, QString> > namedAreas = d->namedAreaStorage->insertColumns(position, number);
966 QList< QPair<QRectF, SharedSubStyle> > styles = d->styleStorage->insertColumns(position, number);
967 QVector< QPair<QPoint, QString> > userInputs = d->userInputStorage->insertColumns(position, number);
968 QVector< QPair<QPoint, QSharedPointer<QTextDocument> > > richTexts = d->richTextStorage->insertColumns(position, number);
969 QList< QPair<QRectF, Validity> > validities = d->validityStorage->insertColumns(position, number);
970 QVector< QPair<QPoint, Value> > values = d->valueStorage->insertColumns(position, number);
971 // recording undo?
972 if (d->undoData) {
973 d->undoData->bindings << bindings;
974 d->undoData->comments << comments;
975 d->undoData->conditions << conditions;
976 d->undoData->databases << databases;
977 d->undoData->formulas << formulas;
978 d->undoData->fusions << fusions;
979 d->undoData->links << links;
980 d->undoData->matrices << matrices;
981 d->undoData->namedAreas << namedAreas;
982 d->undoData->styles << styles;
983 d->undoData->userInputs << userInputs;
984 d->undoData->validities << validities;
985 d->undoData->values << values;
986 d->undoData->richTexts << richTexts;
987 }
988
989 // Trigger a dependency update of the cells, which have a formula. (new positions)
990 subStorage = d->formulaStorage->subStorage(invalidRegion);
991 for (int i = 0; i < subStorage.count(); ++i) {
992 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
993 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
994 }
995 // Trigger a recalculation only for the cells, that depend on values in the changed region.
996 Region providers = d->sheet->map()->dependencyManager()->reduceToProvidingRegion(invalidRegion);
997 d->sheet->map()->addDamage(new CellDamage(d->sheet, providers, CellDamage::Value));
998}
999
1000void CellStorage::removeColumns(int position, int number)
1001{
1002#ifdef CALLIGRA_SHEETS_MT
1003 QWriteLocker(&d->bigUglyLock);
1004#endif
1005 // Trigger a dependency update of the cells, which have a formula. (old positions)
1006 const Region invalidRegion(QRect(QPoint(position, 1), QPoint(KS_colMax, KS_rowMax)), d->sheet);
1007 PointStorage<Formula> subStorage = d->formulaStorage->subStorage(invalidRegion);
1008 Cell cell;
1009 for (int i = 0; i < subStorage.count(); ++i) {
1010 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
1011 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
1012 }
1013 // Trigger an update of the bindings and the named areas.
1014 const Region region(QRect(QPoint(position - 1, 1), QPoint(KS_colMax, KS_rowMax)), d->sheet);
1015 d->sheet->map()->addDamage(new CellDamage(d->sheet, region, CellDamage::Binding | CellDamage::NamedArea));
1016
1017 QList< QPair<QRectF, Binding> > bindings = d->bindingStorage->removeColumns(position, number);
1018 QList< QPair<QRectF, QString> > comments = d->commentStorage->removeColumns(position, number);
1019 QList< QPair<QRectF, Conditions> > conditions = d->conditionsStorage->removeColumns(position, number);
1020 QList< QPair<QRectF, Database> > databases = d->databaseStorage->removeColumns(position, number);
1021 QVector< QPair<QPoint, Formula> > formulas = d->formulaStorage->removeColumns(position, number);
1022 QList< QPair<QRectF, bool> > fusions = d->fusionStorage->removeColumns(position, number);
1023 QVector< QPair<QPoint, QString> > links = d->linkStorage->removeColumns(position, number);
1024 QList< QPair<QRectF, bool> > matrices = d->matrixStorage->removeColumns(position, number);
1025 QList< QPair<QRectF, QString> > namedAreas = d->namedAreaStorage->removeColumns(position, number);
1026 QList< QPair<QRectF, SharedSubStyle> > styles = d->styleStorage->removeColumns(position, number);
1027 QVector< QPair<QPoint, QString> > userInputs = d->userInputStorage->removeColumns(position, number);
1028 QList< QPair<QRectF, Validity> > validities = d->validityStorage->removeColumns(position, number);
1029 QVector< QPair<QPoint, Value> > values = d->valueStorage->removeColumns(position, number);
1030 QVector< QPair<QPoint, QSharedPointer<QTextDocument> > > richTexts = d->richTextStorage->removeColumns(position, number);
1031 // recording undo?
1032 if (d->undoData) {
1033 d->undoData->bindings << bindings;
1034 d->undoData->comments << comments;
1035 d->undoData->conditions << conditions;
1036 d->undoData->databases << databases;
1037 d->undoData->formulas << formulas;
1038 d->undoData->fusions << fusions;
1039 d->undoData->links << links;
1040 d->undoData->matrices << matrices;
1041 d->undoData->namedAreas << namedAreas;
1042 d->undoData->styles << styles;
1043 d->undoData->userInputs << userInputs;
1044 d->undoData->validities << validities;
1045 d->undoData->values << values;
1046 d->undoData->richTexts << richTexts;
1047 }
1048
1049 // Trigger a dependency update of the cells, which have a formula. (new positions)
1050 subStorage = d->formulaStorage->subStorage(invalidRegion);
1051 for (int i = 0; i < subStorage.count(); ++i) {
1052 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
1053 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
1054 }
1055 // Trigger a recalculation only for the cells, that depend on values in the changed region.
1056 Region providers = d->sheet->map()->dependencyManager()->reduceToProvidingRegion(invalidRegion);
1057 d->sheet->map()->addDamage(new CellDamage(d->sheet, providers, CellDamage::Value));
1058}
1059
1060void CellStorage::insertRows(int position, int number)
1061{
1062#ifdef CALLIGRA_SHEETS_MT
1063 QWriteLocker(&d->bigUglyLock);
1064#endif
1065 // Trigger a dependency update of the cells, which have a formula. (old positions)
1066 const Region invalidRegion(QRect(QPoint(1, position), QPoint(KS_colMax, KS_rowMax)), d->sheet);
1067 PointStorage<Formula> subStorage = d->formulaStorage->subStorage(invalidRegion);
1068 Cell cell;
1069 for (int i = 0; i < subStorage.count(); ++i) {
1070 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
1071 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
1072 }
1073 // Trigger an update of the bindings and the named areas.
1074 d->sheet->map()->addDamage(new CellDamage(d->sheet, invalidRegion, CellDamage::Binding | CellDamage::NamedArea));
1075
1076 QList< QPair<QRectF, Binding> > bindings = d->bindingStorage->insertRows(position, number);
1077 QList< QPair<QRectF, QString> > comments = d->commentStorage->insertRows(position, number);
1078 QList< QPair<QRectF, Conditions> > conditions = d->conditionsStorage->insertRows(position, number);
1079 QList< QPair<QRectF, Database> > databases = d->databaseStorage->insertRows(position, number);
1080 QVector< QPair<QPoint, Formula> > formulas = d->formulaStorage->insertRows(position, number);
1081 QList< QPair<QRectF, bool> > fusions = d->fusionStorage->insertRows(position, number);
1082 QVector< QPair<QPoint, QString> > links = d->linkStorage->insertRows(position, number);
1083 QList< QPair<QRectF, bool> > matrices = d->matrixStorage->insertRows(position, number);
1084 QList< QPair<QRectF, QString> > namedAreas = d->namedAreaStorage->insertRows(position, number);
1085 QList< QPair<QRectF, SharedSubStyle> > styles = d->styleStorage->insertRows(position, number);
1086 QVector< QPair<QPoint, QString> > userInputs = d->userInputStorage->insertRows(position, number);
1087 QList< QPair<QRectF, Validity> > validities = d->validityStorage->insertRows(position, number);
1088 QVector< QPair<QPoint, Value> > values = d->valueStorage->insertRows(position, number);
1089 QVector< QPair<QPoint, QSharedPointer<QTextDocument> > > richTexts = d->richTextStorage->insertRows(position, number);
1090 // recording undo?
1091 if (d->undoData) {
1092 d->undoData->bindings << bindings;
1093 d->undoData->comments << comments;
1094 d->undoData->conditions << conditions;
1095 d->undoData->databases << databases;
1096 d->undoData->formulas << formulas;
1097 d->undoData->fusions << fusions;
1098 d->undoData->links << links;
1099 d->undoData->matrices << matrices;
1100 d->undoData->namedAreas << namedAreas;
1101 d->undoData->styles << styles;
1102 d->undoData->userInputs << userInputs;
1103 d->undoData->validities << validities;
1104 d->undoData->values << values;
1105 d->undoData->richTexts << richTexts;
1106 }
1107
1108 // Trigger a dependency update of the cells, which have a formula. (new positions)
1109 subStorage = d->formulaStorage->subStorage(invalidRegion);
1110 for (int i = 0; i < subStorage.count(); ++i) {
1111 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
1112 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
1113 }
1114 // Trigger a recalculation only for the cells, that depend on values in the changed region.
1115 Region providers = d->sheet->map()->dependencyManager()->reduceToProvidingRegion(invalidRegion);
1116 d->sheet->map()->addDamage(new CellDamage(d->sheet, providers, CellDamage::Value));
1117
1118 d->rowRepeatStorage->insertRows(position, number);
1119}
1120
1121void CellStorage::removeRows(int position, int number)
1122{
1123#ifdef CALLIGRA_SHEETS_MT
1124 QWriteLocker(&d->bigUglyLock);
1125#endif
1126 // Trigger a dependency update of the cells, which have a formula. (old positions)
1127 const Region invalidRegion(QRect(QPoint(1, position), QPoint(KS_colMax, KS_rowMax)), d->sheet);
1128 PointStorage<Formula> subStorage = d->formulaStorage->subStorage(invalidRegion);
1129 Cell cell;
1130 for (int i = 0; i < subStorage.count(); ++i) {
1131 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
1132 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
1133 }
1134 // Trigger an update of the bindings and the named areas.
1135 const Region region(QRect(QPoint(1, position - 1), QPoint(KS_colMax, KS_rowMax)), d->sheet);
1136 d->sheet->map()->addDamage(new CellDamage(d->sheet, region, CellDamage::Binding | CellDamage::NamedArea));
1137
1138 QList< QPair<QRectF, Binding> > bindings = d->bindingStorage->removeRows(position, number);
1139 QList< QPair<QRectF, QString> > comments = d->commentStorage->removeRows(position, number);
1140 QList< QPair<QRectF, Conditions> > conditions = d->conditionsStorage->removeRows(position, number);
1141 QList< QPair<QRectF, Database> > databases = d->databaseStorage->removeRows(position, number);
1142 QVector< QPair<QPoint, Formula> > formulas = d->formulaStorage->removeRows(position, number);
1143 QList< QPair<QRectF, bool> > fusions = d->fusionStorage->removeRows(position, number);
1144 QVector< QPair<QPoint, QString> > links = d->linkStorage->removeRows(position, number);
1145 QList< QPair<QRectF, bool> > matrices = d->matrixStorage->removeRows(position, number);
1146 QList< QPair<QRectF, QString> > namedAreas = d->namedAreaStorage->removeRows(position, number);
1147 QList< QPair<QRectF, SharedSubStyle> > styles = d->styleStorage->removeRows(position, number);
1148 QVector< QPair<QPoint, QString> > userInputs = d->userInputStorage->removeRows(position, number);
1149 QList< QPair<QRectF, Validity> > validities = d->validityStorage->removeRows(position, number);
1150 QVector< QPair<QPoint, Value> > values = d->valueStorage->removeRows(position, number);
1151 QVector< QPair<QPoint, QSharedPointer<QTextDocument> > > richTexts = d->richTextStorage->removeRows(position, number);
1152 // recording undo?
1153 if (d->undoData) {
1154 d->undoData->bindings << bindings;
1155 d->undoData->comments << comments;
1156 d->undoData->conditions << conditions;
1157 d->undoData->databases << databases;
1158 d->undoData->formulas << formulas;
1159 d->undoData->fusions << fusions;
1160 d->undoData->links << links;
1161 d->undoData->matrices << matrices;
1162 d->undoData->namedAreas << namedAreas;
1163 d->undoData->styles << styles;
1164 d->undoData->userInputs << userInputs;
1165 d->undoData->validities << validities;
1166 d->undoData->values << values;
1167 d->undoData->richTexts << richTexts;
1168 }
1169
1170 // Trigger a dependency update of the cells, which have a formula. (new positions)
1171 subStorage = d->formulaStorage->subStorage(invalidRegion);
1172 for (int i = 0; i < subStorage.count(); ++i) {
1173 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
1174 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
1175 }
1176 // Trigger a recalculation only for the cells, that depend on values in the changed region.
1177 Region providers = d->sheet->map()->dependencyManager()->reduceToProvidingRegion(invalidRegion);
1178 d->sheet->map()->addDamage(new CellDamage(d->sheet, providers, CellDamage::Value));
1179
1180 d->rowRepeatStorage->removeRows(position, number);
1181}
1182
1183void CellStorage::removeShiftLeft(const QRect& rect)
1184{
1185#ifdef CALLIGRA_SHEETS_MT
1186 QWriteLocker(&d->bigUglyLock);
1187#endif
1188 // Trigger a dependency update of the cells, which have a formula. (old positions)
1189 const Region invalidRegion(QRect(rect.topLeft(), QPoint(KS_colMax, rect.bottom())), d->sheet);
1190 PointStorage<Formula> subStorage = d->formulaStorage->subStorage(invalidRegion);
1191 Cell cell;
1192 for (int i = 0; i < subStorage.count(); ++i) {
1193 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
1194 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
1195 }
1196 // Trigger an update of the bindings and the named areas.
1197 const Region region(QRect(rect.topLeft() - QPoint(1, 0), QPoint(KS_colMax, rect.bottom())), d->sheet);
1198 d->sheet->map()->addDamage(new CellDamage(d->sheet, region, CellDamage::Binding | CellDamage::NamedArea));
1199
1200 QList< QPair<QRectF, Binding> > bindings = d->bindingStorage->removeShiftLeft(rect);
1201 QList< QPair<QRectF, QString> > comments = d->commentStorage->removeShiftLeft(rect);
1202 QList< QPair<QRectF, Conditions> > conditions = d->conditionsStorage->removeShiftLeft(rect);
1203 QList< QPair<QRectF, Database> > databases = d->databaseStorage->removeShiftLeft(rect);
1204 QVector< QPair<QPoint, Formula> > formulas = d->formulaStorage->removeShiftLeft(rect);
1205 QList< QPair<QRectF, bool> > fusions = d->fusionStorage->removeShiftLeft(rect);
1206 QVector< QPair<QPoint, QString> > links = d->linkStorage->removeShiftLeft(rect);
1207 QList< QPair<QRectF, bool> > matrices = d->matrixStorage->removeShiftLeft(rect);
1208 QList< QPair<QRectF, QString> > namedAreas = d->namedAreaStorage->removeShiftLeft(rect);
1209 QList< QPair<QRectF, SharedSubStyle> > styles = d->styleStorage->removeShiftLeft(rect);
1210 QVector< QPair<QPoint, QString> > userInputs = d->userInputStorage->removeShiftLeft(rect);
1211 QList< QPair<QRectF, Validity> > validities = d->validityStorage->removeShiftLeft(rect);
1212 QVector< QPair<QPoint, Value> > values = d->valueStorage->removeShiftLeft(rect);
1213 QVector< QPair<QPoint, QSharedPointer<QTextDocument> > > richTexts = d->richTextStorage->removeShiftLeft(rect);
1214 // recording undo?
1215 if (d->undoData) {
1216 d->undoData->bindings << bindings;
1217 d->undoData->comments << comments;
1218 d->undoData->conditions << conditions;
1219 d->undoData->databases << databases;
1220 d->undoData->formulas << formulas;
1221 d->undoData->fusions << fusions;
1222 d->undoData->links << links;
1223 d->undoData->matrices << matrices;
1224 d->undoData->namedAreas << namedAreas;
1225 d->undoData->styles << styles;
1226 d->undoData->userInputs << userInputs;
1227 d->undoData->validities << validities;
1228 d->undoData->values << values;
1229 d->undoData->richTexts << richTexts;
1230 }
1231
1232 // Trigger a dependency update of the cells, which have a formula. (new positions)
1233 subStorage = d->formulaStorage->subStorage(invalidRegion);
1234 for (int i = 0; i < subStorage.count(); ++i) {
1235 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
1236 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
1237 }
1238 // Trigger a recalculation only for the cells, that depend on values in the changed region.
1239 Region providers = d->sheet->map()->dependencyManager()->reduceToProvidingRegion(invalidRegion);
1240 d->sheet->map()->addDamage(new CellDamage(d->sheet, providers, CellDamage::Value));
1241
1242 d->rowRepeatStorage->removeShiftLeft(rect);
1243}
1244
1245void CellStorage::insertShiftRight(const QRect& rect)
1246{
1247#ifdef CALLIGRA_SHEETS_MT
1248 QWriteLocker(&d->bigUglyLock);
1249#endif
1250 // Trigger a dependency update of the cells, which have a formula. (old positions)
1251 const Region invalidRegion(QRect(rect.topLeft(), QPoint(KS_colMax, rect.bottom())), d->sheet);
1252 PointStorage<Formula> subStorage = d->formulaStorage->subStorage(invalidRegion);
1253 Cell cell;
1254 for (int i = 0; i < subStorage.count(); ++i) {
1255 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
1256 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
1257 }
1258 // Trigger an update of the bindings and the named areas.
1259 d->sheet->map()->addDamage(new CellDamage(d->sheet, invalidRegion, CellDamage::Binding | CellDamage::NamedArea));
1260
1261 QList< QPair<QRectF, Binding> > bindings = d->bindingStorage->insertShiftRight(rect);
1262 QList< QPair<QRectF, QString> > comments = d->commentStorage->insertShiftRight(rect);
1263 QList< QPair<QRectF, Conditions> > conditions = d->conditionsStorage->insertShiftRight(rect);
1264 QList< QPair<QRectF, Database> > databases = d->databaseStorage->insertShiftRight(rect);
1265 QVector< QPair<QPoint, Formula> > formulas = d->formulaStorage->insertShiftRight(rect);
1266 QList< QPair<QRectF, bool> > fusions = d->fusionStorage->insertShiftRight(rect);
1267 QVector< QPair<QPoint, QString> > links = d->linkStorage->insertShiftRight(rect);
1268 QList< QPair<QRectF, bool> > matrices = d->matrixStorage->insertShiftRight(rect);
1269 QList< QPair<QRectF, QString> > namedAreas = d->namedAreaStorage->insertShiftRight(rect);
1270 QList< QPair<QRectF, SharedSubStyle> > styles = d->styleStorage->insertShiftRight(rect);
1271 QVector< QPair<QPoint, QString> > userInputs = d->userInputStorage->insertShiftRight(rect);
1272 QList< QPair<QRectF, Validity> > validities = d->validityStorage->insertShiftRight(rect);
1273 QVector< QPair<QPoint, Value> > values = d->valueStorage->insertShiftRight(rect);
1274 QVector< QPair<QPoint, QSharedPointer<QTextDocument> > > richTexts = d->richTextStorage->insertShiftRight(rect);
1275 // recording undo?
1276 if (d->undoData) {
1277 d->undoData->bindings << bindings;
1278 d->undoData->comments << comments;
1279 d->undoData->conditions << conditions;
1280 d->undoData->databases << databases;
1281 d->undoData->formulas << formulas;
1282 d->undoData->fusions << fusions;
1283 d->undoData->links << links;
1284 d->undoData->matrices << matrices;
1285 d->undoData->namedAreas << namedAreas;
1286 d->undoData->styles << styles;
1287 d->undoData->userInputs << userInputs;
1288 d->undoData->validities << validities;
1289 d->undoData->values << values;
1290 d->undoData->richTexts << richTexts;
1291 }
1292
1293 // Trigger a dependency update of the cells, which have a formula. (new positions)
1294 subStorage = d->formulaStorage->subStorage(invalidRegion);
1295 for (int i = 0; i < subStorage.count(); ++i) {
1296 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
1297 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
1298 }
1299 // Trigger a recalculation only for the cells, that depend on values in the changed region.
1300 Region providers = d->sheet->map()->dependencyManager()->reduceToProvidingRegion(invalidRegion);
1301 d->sheet->map()->addDamage(new CellDamage(d->sheet, providers, CellDamage::Value));
1302
1303 d->rowRepeatStorage->insertShiftRight(rect);
1304}
1305
1306void CellStorage::removeShiftUp(const QRect& rect)
1307{
1308#ifdef CALLIGRA_SHEETS_MT
1309 QWriteLocker(&d->bigUglyLock);
1310#endif
1311 // Trigger a dependency update of the cells, which have a formula. (old positions)
1312 const Region invalidRegion(QRect(rect.topLeft(), QPoint(rect.right(), KS_rowMax)), d->sheet);
1313 PointStorage<Formula> subStorage = d->formulaStorage->subStorage(invalidRegion);
1314 Cell cell;
1315 for (int i = 0; i < subStorage.count(); ++i) {
1316 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
1317 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
1318 }
1319 // Trigger an update of the bindings and the named areas.
1320 const Region region(QRect(rect.topLeft() - QPoint(0, 1), QPoint(rect.right(), KS_rowMax)), d->sheet);
1321 d->sheet->map()->addDamage(new CellDamage(d->sheet, region, CellDamage::Binding | CellDamage::NamedArea));
1322
1323 QList< QPair<QRectF, Binding> > bindings = d->bindingStorage->removeShiftUp(rect);
1324 QList< QPair<QRectF, QString> > comments = d->commentStorage->removeShiftUp(rect);
1325 QList< QPair<QRectF, Conditions> > conditions = d->conditionsStorage->removeShiftUp(rect);
1326 QList< QPair<QRectF, Database> > databases = d->databaseStorage->removeShiftUp(rect);
1327 QVector< QPair<QPoint, Formula> > formulas = d->formulaStorage->removeShiftUp(rect);
1328 QList< QPair<QRectF, bool> > fusions = d->fusionStorage->removeShiftUp(rect);
1329 QVector< QPair<QPoint, QString> > links = d->linkStorage->removeShiftUp(rect);
1330 QList< QPair<QRectF, bool> > matrices = d->matrixStorage->removeShiftUp(rect);
1331 QList< QPair<QRectF, QString> > namedAreas = d->namedAreaStorage->removeShiftUp(rect);
1332 QList< QPair<QRectF, SharedSubStyle> > styles = d->styleStorage->removeShiftUp(rect);
1333 QVector< QPair<QPoint, QString> > userInputs = d->userInputStorage->removeShiftUp(rect);
1334 QList< QPair<QRectF, Validity> > validities = d->validityStorage->removeShiftUp(rect);
1335 QVector< QPair<QPoint, Value> > values = d->valueStorage->removeShiftUp(rect);
1336 QVector< QPair<QPoint, QSharedPointer<QTextDocument> > > richTexts = d->richTextStorage->removeShiftUp(rect);
1337 // recording undo?
1338 if (d->undoData) {
1339 d->undoData->bindings << bindings;
1340 d->undoData->comments << comments;
1341 d->undoData->conditions << conditions;
1342 d->undoData->databases << databases;
1343 d->undoData->formulas << formulas;
1344 d->undoData->fusions << fusions;
1345 d->undoData->links << links;
1346 d->undoData->matrices << matrices;
1347 d->undoData->namedAreas << namedAreas;
1348 d->undoData->styles << styles;
1349 d->undoData->userInputs << userInputs;
1350 d->undoData->validities << validities;
1351 d->undoData->values << values;
1352 d->undoData->richTexts << richTexts;
1353 }
1354
1355 // Trigger a dependency update of the cells, which have a formula. (new positions)
1356 subStorage = d->formulaStorage->subStorage(invalidRegion);
1357 for (int i = 0; i < subStorage.count(); ++i) {
1358 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
1359 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
1360 }
1361 // Trigger a recalculation only for the cells, that depend on values in the changed region.
1362 Region providers = d->sheet->map()->dependencyManager()->reduceToProvidingRegion(invalidRegion);
1363 d->sheet->map()->addDamage(new CellDamage(d->sheet, providers, CellDamage::Value));
1364
1365 d->rowRepeatStorage->removeShiftUp(rect);
1366}
1367
1368void CellStorage::insertShiftDown(const QRect& rect)
1369{
1370#ifdef CALLIGRA_SHEETS_MT
1371 QWriteLocker(&d->bigUglyLock);
1372#endif
1373 // Trigger a dependency update of the cells, which have a formula. (old positions)
1374 const Region invalidRegion(QRect(rect.topLeft(), QPoint(rect.right(), KS_rowMax)), d->sheet);
1375 PointStorage<Formula> subStorage = d->formulaStorage->subStorage(invalidRegion);
1376 Cell cell;
1377 for (int i = 0; i < subStorage.count(); ++i) {
1378 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
1379 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
1380 }
1381 // Trigger an update of the bindings and the named areas.
1382 d->sheet->map()->addDamage(new CellDamage(d->sheet, invalidRegion, CellDamage::Binding | CellDamage::NamedArea));
1383
1384 QList< QPair<QRectF, Binding> > bindings = d->bindingStorage->insertShiftDown(rect);
1385 QList< QPair<QRectF, QString> > comments = d->commentStorage->insertShiftDown(rect);
1386 QList< QPair<QRectF, Conditions> > conditions = d->conditionsStorage->insertShiftDown(rect);
1387 QList< QPair<QRectF, Database> > databases = d->databaseStorage->insertShiftDown(rect);
1388 QVector< QPair<QPoint, Formula> > formulas = d->formulaStorage->insertShiftDown(rect);
1389 QList< QPair<QRectF, bool> > fusions = d->fusionStorage->insertShiftDown(rect);
1390 QVector< QPair<QPoint, QString> > links = d->linkStorage->insertShiftDown(rect);
1391 QList< QPair<QRectF, bool> > matrices = d->matrixStorage->insertShiftDown(rect);
1392 QList< QPair<QRectF, QString> > namedAreas = d->namedAreaStorage->insertShiftDown(rect);
1393 QList< QPair<QRectF, SharedSubStyle> > styles = d->styleStorage->insertShiftDown(rect);
1394 QVector< QPair<QPoint, QString> > userInputs = d->userInputStorage->insertShiftDown(rect);
1395 QList< QPair<QRectF, Validity> > validities = d->validityStorage->insertShiftDown(rect);
1396 QVector< QPair<QPoint, Value> > values = d->valueStorage->insertShiftDown(rect);
1397 QVector< QPair<QPoint, QSharedPointer<QTextDocument> > > richTexts = d->richTextStorage->insertShiftDown(rect);
1398 // recording undo?
1399 if (d->undoData) {
1400 d->undoData->bindings << bindings;
1401 d->undoData->comments << comments;
1402 d->undoData->conditions << conditions;
1403 d->undoData->databases << databases;
1404 d->undoData->formulas << formulas;
1405 d->undoData->fusions << fusions;
1406 d->undoData->links << links;
1407 d->undoData->matrices << matrices;
1408 d->undoData->namedAreas << namedAreas;
1409 d->undoData->styles << styles;
1410 d->undoData->userInputs << userInputs;
1411 d->undoData->validities << validities;
1412 d->undoData->values << values;
1413 d->undoData->richTexts << richTexts;
1414 }
1415
1416 // Trigger a dependency update of the cells, which have a formula. (new positions)
1417 subStorage = d->formulaStorage->subStorage(invalidRegion);
1418 for (int i = 0; i < subStorage.count(); ++i) {
1419 cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
1420 d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
1421 }
1422 // Trigger a recalculation only for the cells, that depend on values in the changed region.
1423 Region providers = d->sheet->map()->dependencyManager()->reduceToProvidingRegion(invalidRegion);
1424 d->sheet->map()->addDamage(new CellDamage(d->sheet, providers, CellDamage::Value));
1425
1426 d->rowRepeatStorage->insertShiftDown(rect);
1427}
1428
1429Cell CellStorage::firstInColumn(int col, Visiting visiting) const
1430{
1431#ifdef CALLIGRA_SHEETS_MT
1432 QReadLocker rl(&d->bigUglyLock);
1433#endif
1434 Q_UNUSED(visiting);
1435
1436 int newRow = 0;
1437 int tmpRow = 0;
1438 d->formulaStorage->firstInColumn(col, &tmpRow);
1439 newRow = tmpRow;
1440 d->valueStorage->firstInColumn(col, &tmpRow);
1441 if (tmpRow)
1442 newRow = newRow ? qMin(newRow, tmpRow) : tmpRow;
1443 if (!newRow)
1444 return Cell();
1445 return Cell(d->sheet, col, newRow);
1446}
1447
1448Cell CellStorage::firstInRow(int row, Visiting visiting) const
1449{
1450#ifdef CALLIGRA_SHEETS_MT
1451 QReadLocker rl(&d->bigUglyLock);
1452#endif
1453 int newCol = 0;
1454 int tmpCol = 0;
1455 d->formulaStorage->firstInRow(row, &tmpCol);
1456 newCol = tmpCol;
1457 d->valueStorage->firstInRow(row, &tmpCol);
1458 if (tmpCol)
1459 newCol = newCol ? qMin(newCol, tmpCol) : tmpCol;
1460 if (visiting == VisitAll) {
1461 tmpCol = d->styleStorage->firstColumnIndexInRow(row);
1462 if (tmpCol)
1463 newCol = newCol ? qMin(newCol, tmpCol) : tmpCol;
1464 }
1465 if (!newCol)
1466 return Cell();
1467 return Cell(d->sheet, newCol, row);
1468}
1469
1470Cell CellStorage::lastInColumn(int col, Visiting visiting) const
1471{
1472#ifdef CALLIGRA_SHEETS_MT
1473 QReadLocker rl(&d->bigUglyLock);
1474#endif
1475 Q_UNUSED(visiting);
1476 int newRow = 0;
1477 int tmpRow = 0;
1478 d->formulaStorage->lastInColumn(col, &tmpRow);
1479 newRow = tmpRow;
1480 d->valueStorage->lastInColumn(col, &tmpRow);
1481 newRow = qMax(newRow, tmpRow);
1482 if (!newRow)
1483 return Cell();
1484 return Cell(d->sheet, col, newRow);
1485}
1486
1487Cell CellStorage::lastInRow(int row, Visiting visiting) const
1488{
1489#ifdef CALLIGRA_SHEETS_MT
1490 QReadLocker rl(&d->bigUglyLock);
1491#endif
1492 Q_UNUSED(visiting);
1493 int newCol = 0;
1494 int tmpCol = 0;
1495 d->formulaStorage->lastInRow(row, &tmpCol);
1496 newCol = tmpCol;
1497 d->valueStorage->lastInRow(row, &tmpCol);
1498 newCol = qMax(newCol, tmpCol);
1499 if (!newCol)
1500 return Cell();
1501 return Cell(d->sheet, newCol, row);
1502}
1503
1504Cell CellStorage::nextInColumn(int col, int row, Visiting visiting) const
1505{
1506#ifdef CALLIGRA_SHEETS_MT
1507 QReadLocker rl(&d->bigUglyLock);
1508#endif
1509 Q_UNUSED(visiting);
1510 int newRow = 0;
1511 int tmpRow = 0;
1512 d->formulaStorage->nextInColumn(col, row, &tmpRow);
1513 newRow = tmpRow;
1514 d->valueStorage->nextInColumn(col, row, &tmpRow);
1515 if (tmpRow)
1516 newRow = newRow ? qMin(newRow, tmpRow) : tmpRow;
1517 if (!newRow)
1518 return Cell();
1519 return Cell(d->sheet, col, newRow);
1520}
1521
1522Cell CellStorage::nextInRow(int col, int row, Visiting visiting) const
1523{
1524#ifdef CALLIGRA_SHEETS_MT
1525 QReadLocker rl(&d->bigUglyLock);
1526#endif
1527 int newCol = 0;
1528 int tmpCol = 0;
1529 d->formulaStorage->nextInRow(col, row, &tmpCol);
1530 newCol = tmpCol;
1531 d->valueStorage->nextInRow(col, row, &tmpCol);
1532 if (tmpCol)
1533 newCol = newCol ? qMin(newCol, tmpCol) : tmpCol;
1534 if (visiting == VisitAll) {
1535 tmpCol = d->styleStorage->nextColumnIndexInRow(col, row);
1536 if (tmpCol)
1537 newCol = newCol ? qMin(newCol, tmpCol) : tmpCol;
1538 }
1539 if (!newCol)
1540 return Cell();
1541 return Cell(d->sheet, newCol, row);
1542}
1543
1544Cell CellStorage::prevInColumn(int col, int row, Visiting visiting) const
1545{
1546#ifdef CALLIGRA_SHEETS_MT
1547 QReadLocker rl(&d->bigUglyLock);
1548#endif
1549 Q_UNUSED(visiting);
1550 int newRow = 0;
1551 int tmpRow = 0;
1552 d->formulaStorage->prevInColumn(col, row, &tmpRow);
1553 newRow = tmpRow;
1554 d->valueStorage->prevInColumn(col, row, &tmpRow);
1555 newRow = qMax(newRow, tmpRow);
1556 if (!newRow)
1557 return Cell();
1558 return Cell(d->sheet, col, newRow);
1559}
1560
1561Cell CellStorage::prevInRow(int col, int row, Visiting visiting) const
1562{
1563#ifdef CALLIGRA_SHEETS_MT
1564 QReadLocker rl(&d->bigUglyLock);
1565#endif
1566 Q_UNUSED(visiting);
1567 int newCol = 0;
1568 int tmpCol = 0;
1569 d->formulaStorage->prevInRow(col, row, &tmpCol);
1570 newCol = tmpCol;
1571 d->valueStorage->prevInRow(col, row, &tmpCol);
1572 newCol = qMax(newCol, tmpCol);
1573 if (!newCol)
1574 return Cell();
1575 return Cell(d->sheet, newCol, row);
1576}
1577
1578int CellStorage::columns(bool includeStyles) const
1579{
1580#ifdef CALLIGRA_SHEETS_MT
1581 QReadLocker rl(&d->bigUglyLock);
1582#endif
1583 int max = 0;
1584 max = qMax(max, d->commentStorage->usedArea().right());
1585 max = qMax(max, d->conditionsStorage->usedArea().right());
1586 max = qMax(max, d->fusionStorage->usedArea().right());
1587 if (includeStyles) max = qMax(max, d->styleStorage->usedArea().right());
1588 max = qMax(max, d->validityStorage->usedArea().right());
1589 max = qMax(max, d->formulaStorage->columns());
1590 max = qMax(max, d->linkStorage->columns());
1591 max = qMax(max, d->valueStorage->columns());
1592
1593 // don't include bindings cause the bindingStorage does only listen to all cells in the sheet.
1594 //max = qMax(max, d->bindingStorage->usedArea().right());
1595
1596 return max;
1597}
1598
1599int CellStorage::rows(bool includeStyles) const
1600{
1601#ifdef CALLIGRA_SHEETS_MT
1602 QReadLocker rl(&d->bigUglyLock);
1603#endif
1604 int max = 0;
1605 max = qMax(max, d->commentStorage->usedArea().bottom());
1606 max = qMax(max, d->conditionsStorage->usedArea().bottom());
1607 max = qMax(max, d->fusionStorage->usedArea().bottom());
1608 if (includeStyles) max = qMax(max, d->styleStorage->usedArea().bottom());
1609 max = qMax(max, d->validityStorage->usedArea().bottom());
1610 max = qMax(max, d->formulaStorage->rows());
1611 max = qMax(max, d->linkStorage->rows());
1612 max = qMax(max, d->valueStorage->rows());
1613
1614 // don't include bindings cause the bindingStorage does only listen to all cells in the sheet.
1615 //max = qMax(max, d->bindingStorage->usedArea().bottom());
1616
1617 return max;
1618}
1619
1620CellStorage CellStorage::subStorage(const Region& region) const
1621{
1622#ifdef CALLIGRA_SHEETS_MT
1623 QReadLocker rl(&d->bigUglyLock);
1624#endif
1625 CellStorage subStorage(d->sheet);
1626 *subStorage.d->formulaStorage = d->formulaStorage->subStorage(region);
1627 *subStorage.d->linkStorage = d->linkStorage->subStorage(region);
1628 *subStorage.d->valueStorage = d->valueStorage->subStorage(region);
1629 return subStorage;
1630}
1631
1632const BindingStorage* CellStorage::bindingStorage() const
1633{
1634 return d->bindingStorage;
1635}
1636
1637const CommentStorage* CellStorage::commentStorage() const
1638{
1639 return d->commentStorage;
1640}
1641
1642const ConditionsStorage* CellStorage::conditionsStorage() const
1643{
1644 return d->conditionsStorage;
1645}
1646
1647const FormulaStorage* CellStorage::formulaStorage() const
1648{
1649 return d->formulaStorage;
1650}
1651
1652const FusionStorage* CellStorage::fusionStorage() const
1653{
1654 return d->fusionStorage;
1655}
1656
1657const LinkStorage* CellStorage::linkStorage() const
1658{
1659 return d->linkStorage;
1660}
1661
1662const StyleStorage* CellStorage::styleStorage() const
1663{
1664 return d->styleStorage;
1665}
1666
1667const UserInputStorage* CellStorage::userInputStorage() const
1668{
1669 return d->userInputStorage;
1670}
1671
1672const ValidityStorage* CellStorage::validityStorage() const
1673{
1674 return d->validityStorage;
1675}
1676
1677const ValueStorage* CellStorage::valueStorage() const
1678{
1679 return d->valueStorage;
1680}
1681
1682void CellStorage::startUndoRecording()
1683{
1684#ifdef CALLIGRA_SHEETS_MT
1685 QWriteLocker(&d->bigUglyLock);
1686#endif
1687 // If undoData is not null, the recording wasn't stopped.
1688 // Should not happen, hence this assertion.
1689 Q_ASSERT(d->undoData == 0);
1690 d->undoData = new CellStorageUndoData();
1691}
1692
1693void CellStorage::stopUndoRecording(KUndo2Command *parent)
1694{
1695#ifdef CALLIGRA_SHEETS_MT
1696 QWriteLocker(&d->bigUglyLock);
1697#endif
1698 // If undoData is null, the recording wasn't started.
1699 // Should not happen, hence this assertion.
1700 Q_ASSERT(d->undoData != 0);
1701 // append sub-commands to the parent command
1702 d->createCommand(parent); // needs d->undoData
1703 for (int i = 0; i < d->undoData->namedAreas.count(); ++i) {
1704 emit namedAreaRemoved(d->undoData->namedAreas[i].second);
1705 }
1706 delete d->undoData;
1707 d->undoData = 0;
1708}
1709
1710void CellStorage::loadConditions(const QList<QPair<QRegion, Conditions> >& conditions)
1711{
1712#ifdef CALLIGRA_SHEETS_MT
1713 QWriteLocker(&d->bigUglyLock);
1714#endif
1715 d->conditionsStorage->load(conditions);
1716}
1717
1718void CellStorage::loadStyles(const QList<QPair<QRegion, Style> > &styles)
1719{
1720#ifdef CALLIGRA_SHEETS_MT
1721 QWriteLocker(&d->bigUglyLock);
1722#endif
1723 d->styleStorage->load(styles);
1724}
1725
1726void CellStorage::invalidateStyleCache()
1727{
1728 d->styleStorage->invalidateCache();
1729}
1730
1731int CellStorage::rowRepeat(int row) const
1732{
1733#ifdef CALLIGRA_SHEETS_MT
1734 QReadLocker rl(&d->bigUglyLock);
1735#endif
1736 return d->rowRepeatStorage->rowRepeat(row);
1737}
1738
1739int CellStorage::firstIdenticalRow(int row) const
1740{
1741#ifdef CALLIGRA_SHEETS_MT
1742 QReadLocker rl(&d->bigUglyLock);
1743#endif
1744 return d->rowRepeatStorage->firstIdenticalRow(row);
1745}
1746
1747void CellStorage::setRowsRepeated(int row, int count)
1748{
1749#ifdef CALLIGRA_SHEETS_MT
1750 QWriteLocker(&d->bigUglyLock);
1751#endif
1752 d->rowRepeatStorage->setRowRepeat(row, count);
1753}
1754
1755#include "CellStorage.moc"
1756