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 | |
63 | Q_DECLARE_METATYPE(QSharedPointer<QTextDocument>) |
64 | |
65 | using namespace Calligra::Sheets; |
66 | |
67 | typedef RectStorage<QString> NamedAreaStorage; |
68 | |
69 | class CellStorage::Private |
70 | { |
71 | public: |
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* ; |
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 | |
161 | void 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 | |
236 | CellStorage::CellStorage(Sheet* sheet) |
237 | : QObject(sheet) |
238 | , d(new Private(sheet)) |
239 | { |
240 | } |
241 | |
242 | CellStorage::CellStorage(const CellStorage& other) |
243 | : QObject(other.d->sheet) |
244 | , d(new Private(*other.d, other.d->sheet)) |
245 | { |
246 | } |
247 | |
248 | CellStorage::CellStorage(const CellStorage& other, Sheet* sheet) |
249 | : QObject(sheet) |
250 | , d(new Private(*other.d, sheet)) |
251 | { |
252 | } |
253 | |
254 | CellStorage::~CellStorage() |
255 | { |
256 | delete d; |
257 | } |
258 | |
259 | Sheet* CellStorage::sheet() const |
260 | { |
261 | return d->sheet; |
262 | } |
263 | |
264 | void 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 | |
306 | Binding 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 | |
314 | void 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 | |
326 | void 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 | |
338 | QString CellStorage::(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 | |
346 | void CellStorage::(const Region& region, const QString& ) |
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 | |
364 | Conditions 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 | |
372 | void 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 | |
390 | Database 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 | |
406 | QList< 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 | |
414 | void 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 | |
426 | Formula 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 | |
434 | void 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 | |
464 | QString 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 | |
472 | void 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 | |
490 | QString 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 | |
503 | QList< 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 | |
511 | void 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 | |
523 | void 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 | |
536 | void CellStorage::emitInsertNamedArea(const Region ®ion, const QString &namedArea) |
537 | { |
538 | emit insertNamedArea(region, namedArea); |
539 | } |
540 | |
541 | Style 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 | |
549 | Style 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 | |
557 | void 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 | |
575 | void 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 | |
587 | QString 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 | |
595 | void 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 | |
613 | QSharedPointer<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 | |
621 | void 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 | |
637 | Validity 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 | |
645 | void 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 | |
663 | Value 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 | |
671 | Value 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 | |
680 | void 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 | |
717 | bool 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 | |
733 | bool 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 | |
749 | void 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 | |
765 | Cell 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 | |
778 | int 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 | |
792 | int 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 | |
806 | QList<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 | |
825 | bool 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 | |
841 | bool 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 | |
857 | bool 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 | |
883 | void 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 | |
897 | void 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 | |
923 | QRect 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 | |
938 | void 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> > = 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 | |
1000 | void 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> > = 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 | |
1060 | void 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> > = 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 | |
1121 | void 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> > = 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 | |
1183 | void 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> > = 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 | |
1245 | void 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> > = 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 | |
1306 | void 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> > = 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 | |
1368 | void 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> > = 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 | |
1429 | Cell 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 | |
1448 | Cell 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 | |
1470 | Cell 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 | |
1487 | Cell 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 | |
1504 | Cell 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 | |
1522 | Cell 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 | |
1544 | Cell 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 | |
1561 | Cell 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 | |
1578 | int 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 | |
1599 | int 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 | |
1620 | CellStorage 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 | |
1632 | const BindingStorage* CellStorage::bindingStorage() const |
1633 | { |
1634 | return d->bindingStorage; |
1635 | } |
1636 | |
1637 | const CommentStorage* CellStorage::() const |
1638 | { |
1639 | return d->commentStorage; |
1640 | } |
1641 | |
1642 | const ConditionsStorage* CellStorage::conditionsStorage() const |
1643 | { |
1644 | return d->conditionsStorage; |
1645 | } |
1646 | |
1647 | const FormulaStorage* CellStorage::formulaStorage() const |
1648 | { |
1649 | return d->formulaStorage; |
1650 | } |
1651 | |
1652 | const FusionStorage* CellStorage::fusionStorage() const |
1653 | { |
1654 | return d->fusionStorage; |
1655 | } |
1656 | |
1657 | const LinkStorage* CellStorage::linkStorage() const |
1658 | { |
1659 | return d->linkStorage; |
1660 | } |
1661 | |
1662 | const StyleStorage* CellStorage::styleStorage() const |
1663 | { |
1664 | return d->styleStorage; |
1665 | } |
1666 | |
1667 | const UserInputStorage* CellStorage::userInputStorage() const |
1668 | { |
1669 | return d->userInputStorage; |
1670 | } |
1671 | |
1672 | const ValidityStorage* CellStorage::validityStorage() const |
1673 | { |
1674 | return d->validityStorage; |
1675 | } |
1676 | |
1677 | const ValueStorage* CellStorage::valueStorage() const |
1678 | { |
1679 | return d->valueStorage; |
1680 | } |
1681 | |
1682 | void 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 | |
1693 | void 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 | |
1710 | void 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 | |
1718 | void 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 | |
1726 | void CellStorage::invalidateStyleCache() |
1727 | { |
1728 | d->styleStorage->invalidateCache(); |
1729 | } |
1730 | |
1731 | int 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 | |
1739 | int 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 | |
1747 | void 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 | |