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