1 /* This file is part of the KDE project
2    Copyright 2010 Marijn Kruisselbrink <mkruisselbrink@kde.org>
3    Copyright 2007 Stefan Nikolaus <stefan.nikolaus@kdemail.net>
4    Copyright 1998,1999 Torben Weis <weis@kde.org>
5    Copyright 1999-2007 The KSpread Team <calligra-devel@kde.org>
6 
7    This library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Library General Public
9    License as published by the Free Software Foundation; either
10    version 2 of the License, or (at your option) any later version.
11 
12    This library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Library General Public License for more details.
16 
17    You should have received a copy of the GNU Library General Public License
18    along with this library; see the file COPYING.LIB.  If not, write to
19    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20    Boston, MA 02110-1301, USA.
21 */
22 
23 #ifndef CALLIGRA_SHEETS_SHEET
24 #define CALLIGRA_SHEETS_SHEET
25 
26 #include <QClipboard>
27 #include <QHash>
28 #include <QList>
29 #include <QRect>
30 
31 #include <KoDocument.h>
32 #include <KoShapeBasedDocumentBase.h>
33 #include <KoShapeUserData.h>
34 
35 #include "Cell.h"
36 #include "Style.h"
37 #include "Global.h"
38 #include "ProtectableObject.h"
39 #include "calligra_sheets_limits.h"
40 
41 class QAbstractItemModel;
42 class QDomElement;
43 
44 class KoShape;
45 
46 namespace Calligra
47 {
48 namespace Sheets
49 {
50 class Cell;
51 class CellStorage;
52 class ColumnFormat;
53 class CommentStorage;
54 class ConditionsStorage;
55 class FormulaStorage;
56 class DocBase;
57 class FusionStorage;
58 class LinkStorage;
59 class HeaderFooter;
60 class Map;
61 class PrintSettings;
62 class Region;
63 class RowFormat;
64 class RowFormatStorage;
65 class Sheet;
66 class SheetPrint;
67 class Style;
68 class StyleStorage;
69 class Validity;
70 class ValidityStorage;
71 class ValueStorage;
72 class View;
73 class SheetTest;
74 
75 /**
76  * A sheet contains several cells.
77  */
78 class CALLIGRA_SHEETS_ODF_EXPORT Sheet : public KoShapeUserData, public KoShapeBasedDocumentBase,
79         public ProtectableObject
80 {
81     Q_OBJECT
82     Q_PROPERTY(QString sheetName READ sheetName)
83     Q_PROPERTY(bool autoCalc READ isAutoCalculationEnabled WRITE setAutoCalculationEnabled)
84     Q_PROPERTY(bool showGrid READ getShowGrid WRITE setShowGrid)
85 
86 public:
87     enum ChangeRef       { ColumnInsert, ColumnRemove, RowInsert, RowRemove };
88     enum TestType        { Text, Validity, Comment, ConditionalCellAttribute };
89 
90     /**
91      * Creates a sheet in \p map with the name \p sheetName.
92      */
93     Sheet(Map* map, const QString& sheetName);
94 
95     /**
96      * Copy constructor.
97      * Creates a sheet with the contents and the settings of \p other.
98      */
99     Sheet(const Sheet& other);
100 
101     /**
102      * Destructor.
103      */
104     ~Sheet() override;
105 
106     /**
107      * \return a model for this sheet
108      */
109     QAbstractItemModel *model() const;
110 
111     /**
112      * \return the map this sheet belongs to
113      */
114     Map* map() const;
115 
116     /**
117      * \return the document this sheet belongs to
118      */
119     DocBase* doc() const;
120 
121     // KoShapeBasedDocumentBase interface
122     void addShape(KoShape* shape) override;
123     void removeShape(KoShape* shape) override;
124     KoDocumentResourceManager* resourceManager() const override;
125 
126     /**
127      * Deletes all shapes without emitting shapeRemoved()
128      */
129     void deleteShapes();
130 
131     /**
132      * \ingroup Embedding
133      * Returns the sheet's shapes.
134      * \return the shapes this sheet contains
135      */
136     QList<KoShape*> shapes() const;
137 
138     //////////////////////////////////////////////////////////////////////////
139     //
140     //BEGIN Methods related to sheet properties
141     //
142 
143     /**
144      * \return the name of this sheet
145      */
146     QString sheetName() const;
147 
148     /**
149      * Renames a sheet. This will automatically adapt all formulas
150      * in all sheets and all cells to reflect the new name.
151      *
152      * If the name really changed then sig_nameChanged is emitted
153      * and the GUI will reflect the change.
154      *
155      * @param name The new sheet name.
156      * @param init If set to true then no formula will be changed and no signal
157      *             will be emitted and no undo action created. Usually you do not
158      *             want to do that.
159      *
160      * @return @c true if the sheet was renamed successfully
161      * @return @c false if the sheet could not be renamed. Usually the reason is
162      * that this name is already used.
163      *
164      * @see changeCellTabName
165      * @see TabBar::renameTab
166      * @see sheetName
167      */
168     bool setSheetName(const QString& name, bool init = false);
169 
170     /**
171      * \return \c true , if a document is currently loading
172      */
173     bool isLoading();
174 
175     /**
176      * Returns the layout direction of the sheet.
177      */
178     Qt::LayoutDirection layoutDirection() const;
179 
180     /**
181      * Sets the layout direction of the sheet. For example, for Arabic or Hebrew
182      * documents, it is possibly to layout the sheet from right to left.
183      */
184     void setLayoutDirection(Qt::LayoutDirection dir);
185 
186     /**
187      * Returns, if the grid shall be shown on the screen
188      */
189     bool getShowGrid() const;
190 
191     /**
192      * Sets, if the grid shall be shown on the screen
193      */
194     void setShowGrid(bool _showGrid);
195 
196     /**
197      * Sets, if formula shall be shown instead of the result
198      */
199     bool getShowFormula() const;
200 
201     void setShowFormula(bool _showFormula);
202 
203     /**
204      * Sets, if indicator must be shown when the cell holds a formula
205      */
206     bool getShowFormulaIndicator() const;
207 
208     void setShowFormulaIndicator(bool _showFormulaIndicator);
209 
210     /**
211      * Returns true if comment indicator is visible.
212      */
213     bool getShowCommentIndicator() const;
214 
215     /**
216      * If b is true, comment indicator is visible, otherwise
217      * it will be hidden.
218      */
219     void setShowCommentIndicator(bool b);
220 
221     bool getLcMode() const;
222 
223     void setLcMode(bool _lcMode);
224 
225     bool isAutoCalculationEnabled() const;
226 
227     void setAutoCalculationEnabled(bool enable);
228 
229     bool getShowColumnNumber() const;
230 
231     void setShowColumnNumber(bool _showColumnNumber);
232 
233     bool getHideZero() const;
234 
235     void setHideZero(bool _hideZero);
236 
237     bool getFirstLetterUpper() const;
238 
239     void setFirstLetterUpper(bool _firstUpper);
240 
241     /**
242      * @return true if this sheet is hidden
243      */
244     bool isHidden()const;
245 
246     /**
247      * Hides or shows this sheets
248      */
249     void setHidden(bool hidden);
250 
251     /**
252      * @return a flag that indicates whether the sheet should paint the page breaks.
253      *
254      * @see setShowPageOutline
255      * @see Sheet::Private::showPageOutline
256      */
257     bool isShowPageOutline() const;
258 
259     /**
260      * Turns the page break lines on or off.
261      *
262      * @see isShowPageOutline
263      * @see Sheet::Private::showPageOutline
264      */
265     void setShowPageOutline(bool _b);
266 
267     struct BackgroundImageProperties {
BackgroundImagePropertiesBackgroundImageProperties268         BackgroundImageProperties()
269         : repeat(Repeat)
270         , opacity(1.0)
271         , horizontalPosition(HorizontalCenter)
272         , verticalPosition(VerticalCenter)
273         {}
274 
275         enum Repetition {
276             NoRepeat,
277             Repeat,
278             Stretch
279         };
280         Repetition repeat;
281 
282         float opacity;
283 
284         enum HorizontalPosition {
285             Left,
286             HorizontalCenter,
287             Right
288         };
289         HorizontalPosition horizontalPosition;
290 
291         enum VerticalPosition {
292             Top,
293             VerticalCenter,
294             Bottom
295         };
296         VerticalPosition verticalPosition;
297 
298         //TODO filterName
299     };
300 
301     /**
302      * Set background image for this sheet
303      */
304     void setBackgroundImage( const QImage& image );
305 
306     /**
307      * @return The QImage used as the background picture for this sheet
308      */
309     QImage backgroundImage() const;
310 
311     void setBackgroundImageProperties( const BackgroundImageProperties& properties );
312 
313     BackgroundImageProperties backgroundImageProperties() const;
314 
315     //
316     //END Methods related to sheet properties
317     //
318     //////////////////////////////////////////////////////////////////////////
319     //
320     //BEGIN Methods related to old KSpread file format
321     //
322 
323     /**
324      * \ingroup NativeFormat
325      * Saves the sheet and all it's children in XML format
326      */
327     QDomElement saveXML(QDomDocument&);
328 
329     /**
330      * \ingroup NativeFormat
331      * Loads the sheet and all it's children in XML format
332      */
333     bool loadXML(const KoXmlElement&);
334 
335     /**
336      * \ingroup NativeFormat
337      * Loads a children
338      */
339     bool loadChildren(KoStore* _store);
340 
341     //
342     //END Methods related to old KSpread file format
343     //
344     //////////////////////////////////////////////////////////////////////////
345     //
346     //BEGIN Methods related to row formats
347     //
348 
349     /**
350      * \ingroup ColumnRowFormat
351      * \return the row format storage for this sheet.
352      */
353     const RowFormatStorage* rowFormats() const;
354     RowFormatStorage* rowFormats();
355 
356     //
357     //END Methods related to row formats
358     //
359     //////////////////////////////////////////////////////////////////////////
360     //
361     //BEGIN Methods related to column formats
362     //
363 
364     /**
365      * \ingroup ColumnRowFormat
366      * \return the column format of column \p _column . The default column format,
367      * if no special one exists.
368      */
369     const ColumnFormat* columnFormat(int _column) const;
370 
371     /**
372      * \ingroup ColumnRowFormat
373      * If no special ColumnFormat exists for this column, then a new one is created.
374      *
375      * @return a non default ColumnFormat for this column.
376      */
377     ColumnFormat* nonDefaultColumnFormat(int _column, bool force_creation = true);
378 
379     /**
380      * \ingroup ColumnRowFormat
381      * \return the first non-default row format
382      */
383     ColumnFormat* firstCol() const;
384     ColumnFormat *nextColumn(int col) const;
385 
386     /**
387      * \ingroup ColumnRowFormat
388      */
389     void setDefaultWidth(double width);
390 
391     //
392     //END Methods related to column formats
393     //
394     //////////////////////////////////////////////////////////////////////////
395     //
396     //BEGIN Methods for Storage access
397     //
398 
399     /**
400      * \ingroup Storage
401      * \return the cell storage
402      */
403     CellStorage* cellStorage() const;
404 
405     const CommentStorage* commentStorage() const;
406     const ConditionsStorage* conditionsStorage() const;
407     const FormulaStorage* formulaStorage() const;
408     const FusionStorage* fusionStorage() const;
409     const LinkStorage* linkStorage() const;
410     const StyleStorage* styleStorage() const;
411     const ValidityStorage* validityStorage() const;
412     const ValueStorage* valueStorage() const;
413 
414     /**
415      * \ingroup Storage
416      * Determines the used area, i.e. the area spanning from A1 to the maximum
417      * occupied column and row.
418      * \return the used area
419      */
420     QRect usedArea(bool onlyContent = false) const;
421 
422     //
423     //END Methods for Storage access
424     //
425     //////////////////////////////////////////////////////////////////////////
426     //
427     //BEGIN UNSORTED METHODS !!!
428     //
429 
430     /**
431      * \ingroup Coordinates
432      * Determines the row for a given position \p _ypos . If the position is
433      * on the border between two cells, the upper row is returned. Also, the offset
434      * between the coordinate system root and the upper row border is determined.
435      *
436      * \param _ypos the position for which the row should be determined
437      * \param _top the offset between the coordinate system root and the upper row border
438      *
439      * \return the row for the given position \p _ypos
440      */
441     int topRow(qreal _ypos, qreal &_top) const;
442 
443     /**
444      * \ingroup Coordinates
445      * Determines the row for a given position \p _ypos . If the position is
446      * on the border between two cells, the lower row is returned.
447      *
448      * \param _ypos the position for which the row should be determined
449      *
450      * \return the row for the given position \p _ypos
451      */
452     int bottomRow(double _ypos) const;
453 
454     /**
455      * \ingroup Coordinates
456      * Determines the column for a given position \p _xpos . If the position is
457      * on the border between two cells, the left column is returned. Also, the offset
458      * between the coordinate system root and the left column border is determined.
459      *
460      * \param _xpos the position for which the column should be determined
461      * \param _left the offset between the coordinate system root and the left column border
462      *
463      * \return the column for the given position \p _xpos
464      */
465     int leftColumn(qreal _xpos, qreal &_left) const;
466 
467     /**
468      * \ingroup Coordinates
469      * Determines the column for a given position \p _xpos . If the position is
470      * on the border between two cells, the right column is returned.
471      *
472      * \param _xpos the position for which the column should be determined
473      *
474      * \return the column for the given position \p _xpos
475      */
476     int rightColumn(double _xpos) const;
477 
478     /**
479      * \ingroup Coordinates
480      * Calculates the region in document coordinates occupied by a range of cells.
481      * \param cellRange the range of cells
482      * \return the document area covered by the cells
483      */
484     QRectF cellCoordinatesToDocument(const QRect& cellRange) const;
485 
486     /**
487      * \ingroup Coordinates
488      * Calculates the cell range covering a document area.
489      * \param area the document area
490      * \return the cell range covering the area
491      */
492     QRect documentToCellCoordinates(const QRectF& area) const;
493 
494     /**
495      * \ingroup Coordinates
496      * @return the left corner of the column as double.
497      * Use this method, when you later calculate other positions depending on this one
498      * to avoid rounding problems
499      * @param col the column's index
500      */
501     double columnPosition(int col) const;
502 
503     /**
504      * \ingroup Coordinates
505      * @return the top corner of the row as double.
506      * Use this method, when you later calculate other positions depending on this one
507      * to avoid rounding problems
508      * @param _row the row's index
509      */
510     double rowPosition(int _row) const;
511 
512     /**
513      * \ingroup Coordinates
514      * \return the document size
515      */
516     QSizeF documentSize() const;
517 
518     /**
519      * \ingroup Coordinates
520      * Adjusts the internal reference of the sum of the widths of all columns.
521      * Used in resizing of columns.
522      */
523     void adjustDocumentWidth(double deltaWidth);
524 
525     /**
526      * \ingroup Coordinates
527      * Adjusts the internal reference of the sum of the heights of all rows.
528      * Used in resizing of rows.
529      */
530     void adjustDocumentHeight(double deltaHeight);
531 
532     /**
533      * Adjusts the position of cell anchored shapes as a result of a column size change/insertion/removal.
534      * All cell anchored shapes with x coordinates >= minX and < maxX will be moved by delta.
535      */
536     void adjustCellAnchoredShapesX(qreal minX, qreal maxX, qreal delta);
537     void adjustCellAnchoredShapesX(qreal delta, int firstCol, int lastCol = KS_colMax);
538 
539     /**
540      * Adjusts the position of cell anchored shapes as a result of a row size change/insertion/removal.
541      * All cell anchored shapes with y coordinates >= minY and < maxY will be moved by delta.
542      */
543     void adjustCellAnchoredShapesY(qreal minY, qreal maxY, qreal delta);
544     void adjustCellAnchoredShapesY(qreal delta, int firstRow, int lastRow = KS_rowMax);
545 
546     //
547     //END UNSORTED METHODS
548     //
549     //////////////////////////////////////////////////////////////////////////
550     //
551     //BEGIN Methods related to manipulations of selected cells
552     //
553 
554     /**
555      * \ingroup Commands
556      */
557     bool areaIsEmpty(const Region& area, TestType _type = Text) ;
558 
559     //
560     //END Methods related to manipulations of selected cells
561     //
562     //////////////////////////////////////////////////////////////////////////
563     //
564     //BEGIN Methods related to column/row operations
565     //
566 
567     /**
568      * \ingroup Commands
569      * Helper method.
570      * \see ShiftManipulator
571      */
572     void insertShiftRight(const QRect& rect);
573 
574     /**
575      * \ingroup Commands
576      * Helper method.
577      * \see ShiftManipulator
578      */
579     void insertShiftDown(const QRect& rect);
580 
581     /**
582      * \ingroup Commands
583      * Helper method.
584      * \see ShiftManipulator
585      */
586     void removeShiftUp(const QRect& rect);
587 
588     /**
589      * \ingroup Commands
590      * Helper method.
591      * \see ShiftManipulator
592      */
593     void removeShiftLeft(const QRect& rect);
594 
595     /**
596      * \ingroup ColumnRowFormat
597      * Helper method.
598      * \see InsertDeleteColumnManipulator
599      * Moves all columns which are >= \p col \p number positions to the right
600      * and inserts a new and empty column.
601      */
602     void insertColumns(int row, int numbers);
603 
604     /**
605      * Helper method.
606      * \see InsertDeleteRowManipulator
607      * Moves all rows which are >= \p row \p number positions down
608      * and inserts a new and empty row.
609      */
610     void insertRows(int row, int numbers);
611 
612     /**
613      * \ingroup ColumnRowFormat
614      * Helper method.
615      * \see InsertDeleteColumnManipulator
616      * Deletes \p number columns beginning at \p col .
617      */
618     void removeColumns(int row, int numbers);
619 
620     /**
621      * \ingroup ColumnRowFormat
622      * Helper method.
623      * \see InsertDeleteRowManipulator
624      * Deletes \p number rows beginning at \p row .
625      */
626     void removeRows(int row, int number);
627 
628     //
629     //END Methods related column/row operations
630     //
631     //////////////////////////////////////////////////////////////////////////
632     //
633     //BEGIN UNSORTED METHODS !!!
634     //
635 
636     void hideSheet(bool _hide);
637 
638     /**
639      * \ingroup Value
640      * Change name of reference when the user inserts or removes a column,
641      * a row or a cell (= insertion of a row [or column] on a single column [or row]).
642      * For example the formula =Sheet1!A1 is changed into =Sheet1!B1 if a Column
643      * is inserted before A.
644      *
645      * @param pos the point of insertion (only one coordinate may be used, depending
646      * on the other parameters).
647      * @param fullRowOrColumn if true, a whole row or column has been inserted/removed.
648      *                        if false, we inserted or removed a cell
649      * @param ref see ChangeRef
650      * @param sheetName completes the pos specification by giving the sheet name
651      * @param number number of columns which were inserted
652      */
653     void changeNameCellRef(const QPoint& pos, bool fullRowOrColumn, ChangeRef ref,
654                            const QString& sheetName, int number);
655 
656     /**
657      * \ingroup ColumnRowFormat
658      * Insert the non-default column format \p columnFormat.
659      */
660     void insertColumnFormat(ColumnFormat* columnFormat);
661 
662     /**
663      * \ingroup ColumnRowFormat
664      * Inserts the non-default row format \p rowFormat.
665      */
666     void insertRowFormat(RowFormat* rowFormat);
667 
668     /**
669      * \ingroup ColumnRowFormat
670      * Deletes the column format at \p column.
671      */
672     void deleteColumnFormat(int column);
673 
674     /**
675      * \ingroup ColumnRowFormat
676      * Deletes the row format at \p row (changes the format of that row to be the default format).
677      */
678     void deleteRowFormat(int row);
679 
680     //
681     //END UNSORTED METHODS
682     //
683     //////////////////////////////////////////////////////////////////////////
684     //
685     //BEGIN UNSORTED METHODS !!!
686     //
687 
688     /**
689      * Shows a status \p message in the status bar for \p timeout msecs.
690      */
691     void showStatusMessage(const QString &message, int timeout = 3000);
692 
693     void updateLocale();
694 
695 
696     /**
697      * \ingroup Page
698      * The page layout manager.
699      */
700     SheetPrint *print() const;
701 
702     /**
703      * \ingroup Page
704      * Print settings.
705      */
706     PrintSettings* printSettings() const;
707 
708     /**
709      * \ingroup Page
710      * Sets the print settings.
711      */
712     void setPrintSettings(const PrintSettings& settings);
713 
714     /**
715      * \ingroup Page
716      * \return the header & footer object
717      */
718     HeaderFooter *headerFooter() const;
719 
720     /**
721      * Applies a database filter.
722      */
723     void applyDatabaseFilter(const Database& database);
724 #ifndef NDEBUG
725     void printDebug();
726 #endif
727 
728     //
729     //END UNSORTED METHODS
730     //
731     //////////////////////////////////////////////////////////////////////////
732 
733 Q_SIGNALS:
734     /**
735      * Emitted, if the document size changed.
736      * E.g. if some columns were inserted.
737      * \param size new size
738      */
739     void documentSizeChanged(const QSizeF &size);
740 
741     /**
742      * Emitted, if the visible size changed.
743      * E.g. if the document size changed or the user selected an area,
744      * which was not visible before.
745      */
746     void visibleSizeChanged();
747 
748     /**
749      * Emitted, if a status \p message should be shown in the status bar
750      * for \p timeout msecs.
751      */
752     void statusMessage(const QString& message, int timeout);
753 
754     /**
755      * \ingroup Embedding
756      * Emitted, if a \p shape was added.
757      * \param sheet this sheet (for the View to determine, if it's the active one)
758      * \param shape the shape
759      */
760     void shapeAdded(Sheet *sheet, KoShape *shape);
761 
762     /**
763      * \ingroup Embedding
764      * Emitted, if a \p shape was removed.
765      * \param sheet this sheet (for the View to determine, if it's the active one)
766      * \param shape the shape
767      */
768     void shapeRemoved(Sheet *sheet, KoShape *shape);
769 
770 protected:
771     /**
772      * \ingroup Value
773      * Change the name of a sheet in all formulas.
774      * When you change name sheet Sheet1 -> Price
775      * for all cell which refers to Sheet1, this function changes the name.
776      */
777     void changeCellTabName(QString const & old_name, QString const & new_name);
778 
779     //
780     //////////////////////////////////////////////////////////////////////////
781     //
782 
783     /**
784      * \ingroup Commands
785      * \see areaIsEmpty()
786      */
787     bool cellIsEmpty(const Cell& cell, TestType _type);
788 
789     /**
790      * \ingroup Value
791      * \see changeNameCellRef()
792      */
793     QString changeNameCellRefHelper(const QPoint& pos, bool fullRowOrColumn, ChangeRef ref,
794                                     int NbCol, const QPoint& point, bool isColumnFixed,
795                                     bool isRowFixed);
796     QString changeNameCellRefHelper(const QPoint& pos, const QRect& rect, bool fullRowOrColumn, ChangeRef ref,
797                                     int NbCol, const QPoint& point, bool isColumnFixed,
798                                     bool isRowFixed);
799 
800 private:
801     /**
802      * \ingroup NativeFormat
803      */
804     void convertObscuringBorders();
805 
806     /**
807      * \ingroup NativeFormat
808      */
809     void checkContentDirection(QString const & name);
810 
811     // disable assignment operator
812     void operator=(const Sheet& other);
813 
814     friend class SheetTest;
815 
816     class Private;
817     Private * const d;
818 };
819 
820 } // namespace Sheets
821 } // namespace Calligra
822 
823 Q_DECLARE_METATYPE(Calligra::Sheets::Sheet*)
824 
825 #endif  // CALLIGRA_SHEETS_SHEET
826