1/* This file is part of the KDE project
2 Copyright 2007 Stefan Nikolaus <stefan.nikolaus@kdemail.net>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18*/
19
20#ifndef CALLIGRA_SHEETS_CELL_STORAGE
21#define CALLIGRA_SHEETS_CELL_STORAGE
22
23#include <QPair>
24#include <QRect>
25#include <QTextDocument>
26
27#include "Cell.h"
28#include "calligra_sheets_limits.h"
29#include "PointStorage.h"
30
31#include "database/Database.h"
32
33class KoXmlWriter;
34
35class KUndo2Command;
36
37namespace Calligra
38{
39namespace Sheets
40{
41class Binding;
42class BindingStorage;
43class Cell;
44class CommentStorage;
45class Conditions;
46class ConditionsStorage;
47class Formula;
48class FormulaStorage;
49class FusionStorage;
50class LinkStorage;
51class Region;
52class RichTextStorage;
53class Sheet;
54class StyleStorage;
55class UserInputStorage;
56class Validity;
57class ValidityStorage;
58class Value;
59class ValueStorage;
60
61/**
62 * \ingroup Storage
63 * The cell storage.
64 * A wrapper around a couple of storages, which hold the cell data.
65 * Provides methods to iterate over the non-empty cells.
66 * Emits Damages on changes.
67 * Capable of recording the old data for undoing.
68 *
69 * \author Stefan Nikolaus <stefan.nikolaus@kdemail.net>
70 *
71 * \note If you fill the storage, do it row-wise. That's more performant.
72 */
73class CALLIGRA_SHEETS_ODF_EXPORT CellStorage : public QObject
74{
75 Q_OBJECT
76public:
77 enum Visiting {
78 Values = 0x01,
79 Formulas = 0x02,
80 Comments = 0x04,
81 Links = 0x08,
82 Styles = 0x10,
83 ConditionStyles = 0x20,
84 Validities = 0x40,
85 VisitContent = 0x03, ///< just visit the cell contents: values, formulas
86 VisitAll = 0xFF ///< visit all: cell contents, styles, comments, ...
87 };
88
89 /**
90 * Constructor.
91 * Creates an empty storage for \p sheet.
92 */
93 explicit CellStorage(Sheet *sheet);
94
95 /**
96 * Copy constructor.
97 * \note Take care: does not perform a deep copy!
98 */
99 CellStorage(const CellStorage& other);
100
101 /**
102 * Copy constructor.
103 * Creates a CellStorage for \p sheet and copies the data from \p other.
104 */
105 CellStorage(const CellStorage& other, Sheet* sheet);
106
107 /**
108 * Destructor.
109 */
110 ~CellStorage();
111
112 /**
113 * \return the sheet this CellStorage is for.
114 */
115 Sheet* sheet() const;
116
117 /**
118 * Removes all data at \p col , \p row .
119 */
120 void take(int col, int row);
121
122 /**
123 * \return the binding associated with the Cell at \p column , \p row .
124 */
125 Binding binding(int column, int row) const;
126 void setBinding(const Region& region, const Binding& binding);
127 void removeBinding(const Region& region, const Binding& binding);
128
129 /**
130 * \return the comment associated with the Cell at \p column , \p row .
131 */
132 QString comment(int column, int row) const;
133 void setComment(const Region& region, const QString& comment);
134
135 /**
136 * \return the conditional formattings associated with the Cell at \p column , \p row .
137 */
138 Conditions conditions(int column, int row) const;
139 void setConditions(const Region& region, Conditions conditions);
140
141 /**
142 * \return the database associated with the Cell at \p column , \p row .
143 */
144 Database database(int column, int row) const;
145 QList< QPair<QRectF, Database> > databases(const Region& region) const;
146 void setDatabase(const Region& region, const Database& database);
147
148 /**
149 * \return the formula associated with the Cell at \p column , \p row .
150 */
151 Formula formula(int column, int row) const;
152 void setFormula(int column, int row, const Formula& formula);
153
154 /**
155 * \return the hyperlink associated with the Cell at \p column , \p row .
156 */
157 QString link(int column, int row) const;
158 void setLink(int column, int row, const QString& link);
159
160 /**
161 * \return the named area's name associated with the Cell at \p column , \p row .
162 */
163 QString namedArea(int column, int row) const;
164 QList< QPair<QRectF, QString> > namedAreas(const Region& region) const;
165 void setNamedArea(const Region& region, const QString& namedArea);
166 void emitInsertNamedArea(const Region &region, const QString &namedArea);
167 void removeNamedArea(const Region& region, const QString& namedArea);
168
169 /**
170 * \return the Style associated with the Cell at \p column , \p row .
171 */
172 Style style(int column, int row) const;
173
174 /**
175 * \return the Style associated with \p rect.
176 */
177 Style style(const QRect& rect) const;
178 void setStyle(const Region& region, const Style& style);
179 void insertSubStyle(const QRect& rect, const SharedSubStyle& subStyle);
180
181 /**
182 * \return the user input associated with the Cell at \p column , \p row .
183 */
184 QString userInput(int column, int row) const;
185 void setUserInput(int column, int row, const QString& input);
186
187 /**
188 * \return the validity checks associated with the Cell at \p column , \p row .
189 */
190 Validity validity(int column, int row) const;
191 void setValidity(const Region& region, Validity validity);
192
193 /**
194 * \return the value associated with the Cell at \p column , \p row .
195 */
196 Value value(int column, int row) const;
197
198 /**
199 * Creates a value array containing the values in \p region.
200 */
201 Value valueRegion(const Region& region) const;
202 void setValue(int column, int row, const Value& value);
203
204 QSharedPointer<QTextDocument> richText(int column, int row) const;
205 void setRichText(int column, int row, QSharedPointer<QTextDocument> text);
206
207 /**
208 */
209 bool doesMergeCells(int column, int row) const;
210 bool isPartOfMerged(int column, int row) const;
211
212 /**
213 * Merge the cell at \p column, \p row with the \p numXCells adjacent cells in horizontal
214 * direction and with the \p numYCells adjacent cells in vertical direction. I.e. the
215 * resulting cell spans \p numXCells + 1 columns and \p numYCells + 1 rows. Passing \c 0
216 * as \p numXCells and \p numYCells unmerges the cell at \p column, \p row.
217 *
218 * \param column the master cell's column
219 * \param row the master cell's row
220 * \param numXCells number of horizontal cells to be merged in
221 * \param numYCells number of vertical cells to be merged in
222 *
223 */
224 void mergeCells(int column, int row, int numXCells, int numYCells);
225 Cell masterCell(int column, int row) const;
226 int mergedXCells(int column, int row) const;
227 int mergedYCells(int column, int row) const;
228 QList<Cell> masterCells(const Region& region) const;
229
230 /**
231 * \return \c true, if the cell's value is a matrix and obscures other cells
232 */
233 bool locksCells(int column, int row) const;
234 bool isLocked(int column, int row) const;
235 bool hasLockedCells(const Region& region) const;
236 void lockCells(const QRect& rect);
237 void unlockCells(int column, int row);
238 QRect lockedCells(int column, int row) const;
239
240 /**
241 * Insert \p number columns at \p position .
242 * \return the data, that became out of range (shifted over the end)
243 */
244 void insertColumns(int position, int number = 1);
245
246 /**
247 * Removes \p number columns at \p position .
248 * \return the removed data
249 */
250 void removeColumns(int position, int number = 1);
251
252 /**
253 * Insert \p number rows at \p position .
254 * \return the data, that became out of range (shifted over the end)
255 */
256 void insertRows(int position, int number = 1);
257
258 /**
259 * Removes \p number rows at \p position .
260 * \return the removed data
261 */
262 void removeRows(int position, int number = 1);
263
264 /**
265 * Shifts the data right of \p rect to the left by the width of \p rect .
266 * The data formerly contained in \p rect becomes overridden.
267 */
268 void removeShiftLeft(const QRect& rect);
269
270 /**
271 * Shifts the data in and right of \p rect to the right by the width of \p rect .
272 */
273 void insertShiftRight(const QRect& rect);
274
275 /**
276 * Shifts the data below \p rect to the top by the height of \p rect .
277 * The data formerly contained in \p rect becomes overridden.
278 */
279 void removeShiftUp(const QRect& rect);
280
281 /**
282 * Shifts the data in and below \p rect to the bottom by the height of \p rect .
283 */
284 void insertShiftDown(const QRect& rect);
285
286 /**
287 * Retrieve the first used data in \p col .
288 * Can be used in conjunction with nextInColumn() to loop through a column.
289 * \return the first used data in \p col or the default data, if the column is empty.
290 */
291 Cell firstInColumn(int col, Visiting visiting = VisitAll) const;
292
293 /**
294 * Retrieve the first used data in \p row .
295 * Can be used in conjunction with nextInRow() to loop through a row.
296 * \return the first used data in \p row or the default data, if the row is empty.
297 */
298 Cell firstInRow(int row, Visiting visiting = VisitAll) const;
299
300 /**
301 * Retrieve the last used data in \p col .
302 * Can be used in conjunction with prevInColumn() to loop through a column.
303 * \return the last used data in \p col or the default data, if the column is empty.
304 */
305 Cell lastInColumn(int col, Visiting visiting = VisitAll) const;
306
307 /**
308 * Retrieve the last used data in \p row .
309 * Can be used in conjunction with prevInRow() to loop through a row.
310 * \return the last used data in \p row or the default data, if the row is empty.
311 */
312 Cell lastInRow(int row, Visiting visiting = VisitAll) const;
313
314 /**
315 * Retrieve the next used data in \p col after \p row .
316 * Can be used in conjunction with firstInColumn() to loop through a column.
317 * \return the next used data in \p col or the default data, there is no further data.
318 */
319 Cell nextInColumn(int col, int row, Visiting visiting = VisitAll) const;
320
321 /**
322 * Retrieve the next used data in \p row after \p col .
323 * Can be used in conjunction with firstInRow() to loop through a row.
324 * \return the next used data in \p row or the default data, if there is no further data.
325 */
326 Cell nextInRow(int col, int row, Visiting visiting = VisitAll) const;
327
328 /**
329 * Retrieve the previous used data in \p col after \p row .
330 * Can be used in conjunction with lastInColumn() to loop through a column.
331 * \return the previous used data in \p col or the default data, there is no further data.
332 */
333 Cell prevInColumn(int col, int row, Visiting visiting = VisitAll) const;
334
335 /**
336 * Retrieve the previous used data in \p row after \p col .
337 * Can be used in conjunction with lastInRow() to loop through a row.
338 * \return the previous used data in \p row or the default data, if there is no further data.
339 */
340 Cell prevInRow(int col, int row, Visiting visiting = VisitAll) const;
341
342 /**
343 * The maximum occupied column, i.e. the horizontal storage dimension.
344 * \return the maximum column
345 */
346 int columns(bool includeStyles = true) const;
347
348 /**
349 * The maximum occupied row, i.e. the vertical storage dimension.
350 * \return the maximum row
351 */
352 int rows(bool includeStyles = true) const;
353
354 /**
355 * The number of rows that are consecutive to, and identical to \p row. This includes the row
356 * itself.
357 */
358 int rowRepeat(int row) const;
359
360 /**
361 * The first row in the block of consecutive identical rows \p row is in.
362 */
363 int firstIdenticalRow(int row) const;
364
365 /**
366 * Set how often the specified row is repeated. \p row is the index of the first row in a block,
367 * \p count is the number of times it is repeated (including the first one). This method is used
368 * during loading.
369 */
370 void setRowsRepeated(int row, int count);
371
372 /**
373 * Creates a substorage consisting of the values in \p region.
374 * \return a subset of the storage stripped down to the values in \p region
375 */
376 CellStorage subStorage(const Region& region) const;
377
378 const BindingStorage* bindingStorage() const;
379 const CommentStorage* commentStorage() const;
380 const ConditionsStorage* conditionsStorage() const;
381 const FormulaStorage* formulaStorage() const;
382 const FusionStorage* fusionStorage() const;
383 const LinkStorage* linkStorage() const;
384 const StyleStorage* styleStorage() const;
385 const UserInputStorage* userInputStorage() const;
386 const ValidityStorage* validityStorage() const;
387 const ValueStorage* valueStorage() const;
388
389 void loadConditions(const QList<QPair<QRegion, Conditions> >& conditions);
390 void loadStyles(const QList<QPair<QRegion, Style> >& styles);
391
392 void invalidateStyleCache();
393
394 /**
395 * Starts the undo recording.
396 * While recording the undo data of each storage operation is saved in
397 * an undo command, that can be retrieved when the recording is stopped.
398 * \see stopUndoRecording
399 */
400 void startUndoRecording();
401
402 /**
403 * Stops the undo recording.
404 * An undo command has to be passed as \p parent command and
405 * for each sub-storage an undo-capable command is attached to \p parent.
406 * \see startUndoRecording
407 */
408 void stopUndoRecording(KUndo2Command *parent);
409
410Q_SIGNALS:
411 void insertNamedArea(const Region&, const QString&);
412 void namedAreaRemoved(const QString&);
413
414private:
415 // do not allow assignment
416 CellStorage& operator=(const CellStorage&);
417
418 class Private;
419 Private * const d;
420};
421
422class UserInputStorage : public PointStorage<QString>
423{
424public:
425 UserInputStorage& operator=(const PointStorage<QString>& o) {
426 PointStorage<QString>::operator=(o);
427 return *this;
428 }
429};
430
431class LinkStorage : public PointStorage<QString>
432{
433public:
434 LinkStorage& operator=(const PointStorage<QString>& o) {
435 PointStorage<QString>::operator=(o);
436 return *this;
437 }
438};
439
440class RichTextStorage : public PointStorage<QSharedPointer<QTextDocument> >
441{
442public:
443 RichTextStorage& operator=(const PointStorage<QSharedPointer<QTextDocument> >& o) {
444 PointStorage<QSharedPointer<QTextDocument> >::operator=(o);
445 return *this;
446 }
447};
448
449} // namespace Sheets
450} // namespace Calligra
451
452#endif // CALLIGRA_SHEETS_CELL_STORAGE
453