File indexing completed on 2024-04-28 16:21:27

0001 /* This file is part of the KDE project
0002    Copyright 2010 Marijn Kruisselbrink <mkruisselbrink@kde.org>
0003    Copyright 2005-2007 Stefan Nikolaus <stefan.nikolaus@kdemail.net>
0004 
0005    This program is free software; you can redistribute it and/or modify
0006    it under the terms of the GNU Library General Public License as published by
0007    the Free Software Foundation; either version 2 of the License, or
0008    (at your option) any later version.
0009 
0010    This program is distributed in the hope that it will be useful,
0011    but WITHOUT ANY WARRANTY; without even the implied warranty of
0012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013    GNU Library General Public License for more details.
0014 
0015    You should have received a copy of the GNU Library General Public License
0016    along with this program; if not, write to the Free Software
0017    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
0018 */
0019 
0020 
0021 #ifndef CALLIGRA_SHEETS_REGION
0022 #define CALLIGRA_SHEETS_REGION
0023 
0024 #include <QList>
0025 #include <QRect>
0026 #include <QSet>
0027 #include <QSharedDataPointer>
0028 #include <QString>
0029 
0030 #include "SheetsDebug.h"
0031 #include "sheets_odf_export.h"
0032 
0033 inline uint qHash(const QPoint& point)
0034 {
0035     return (static_cast<uint>(point.x()) << 16) + static_cast<uint>(point.y());
0036 }
0037 
0038 namespace Calligra
0039 {
0040 namespace Sheets
0041 {
0042 class Cell;
0043 class Map;
0044 class Sheet;
0045 
0046 /**
0047  * \class Region
0048  * \brief The one for all class for points and ranges.
0049  * \author Stefan Nikolaus <stefan.nikolaus@kdemail.net>
0050  * \since 1.5
0051  */
0052 class CALLIGRA_SHEETS_ODF_EXPORT Region
0053 {
0054 public:
0055     class Element;
0056     class Point;
0057     class Range;
0058 
0059     /**
0060      * Constructor.
0061      * Creates an empty region.
0062      */
0063     Region();
0064 
0065     /**
0066      * Constructor.
0067      * Creates a region consisting of a point.
0068      * @param point the point's location
0069      * @param sheet the sheet the point belongs to
0070      */
0071     explicit Region(const QPoint& point, Sheet* sheet = 0);
0072 
0073     /**
0074      * Constructor.
0075      * Creates a region consisting of a range.
0076      * @param range the range's location
0077      * @param sheet the sheet the range belongs to
0078      */
0079     explicit Region(const QRect& range, Sheet* sheet = 0);
0080 
0081     /**
0082      * Constructor.
0083      * Creates a region consisting of the region defined in @p expression .
0084      * @param expression a string representing the region (e.g. "A1:B3")
0085      * @param map used to determine the sheet, if it's named in the string
0086      * @param sheet the fallback sheet, if \p expression does not contain one
0087      */
0088     explicit Region(const QString& expression, const Map* map = 0, Sheet* sheet = 0);
0089 
0090     /**
0091      * Copy Constructor.
0092      * Creates a copy of the region.
0093      * @param region the region to copy
0094      */
0095     Region(const Region& region);
0096 
0097     /**
0098      * Constructor.
0099      * Creates a region consisting of a point.
0100      * @param col the column of the point
0101      * @param row the row of the point
0102      * @param sheet the sheet the point belongs to
0103      */
0104     Region(int col, int row, Sheet* sheet = 0);
0105 
0106     /**
0107      * Constructor.
0108      * Creates a region consisting of a range at the location
0109      * @param col the column of the range' starting point
0110      * @param row the row of the range' starting point
0111      * @param width the width of the range
0112      * @param height the height of the range
0113      * @param sheet the sheet the range belongs to
0114      */
0115     Region(int col, int row, int width, int height, Sheet* sheet = 0);
0116 
0117     /**
0118      * Destructor.
0119      */
0120     virtual ~Region();
0121 
0122 
0123     /**
0124      *  @return a QRegion that unifies all contained ranges
0125      */
0126     QVector<QRect> rects() const;
0127 
0128     /**
0129      * @param originSheet The name is created relative to this sheet.
0130      * @return the name of the region (e.g. "A1:A2")
0131      */
0132     QString name(Sheet* originSheet = 0) const;
0133 
0134     /**
0135      * @param sRegion will be modified, if a valid sheet was found. The sheetname
0136      * will be removed
0137      * @return sheet named in the @p sRegion or null
0138      */
0139     Sheet* filterSheetName(QString& sRegion);
0140 
0141 
0142 
0143     /**
0144      * @return @c true, if this region contains no elements
0145      */
0146     bool isEmpty() const;
0147 
0148     /**
0149      * @return @c true, if this region contains only a single point
0150      */
0151     bool isSingular() const;
0152 
0153     /**
0154      * @return @c true, if this region is contiguous
0155      */
0156     bool isContiguous() const;
0157 
0158     /**
0159      * @return @c true, if this region contains at least one valid point or one valid range
0160      */
0161     bool isValid() const;
0162 
0163     /**
0164      * @param col The column to check
0165      *
0166      * @return @c True, if the column @p col is selected. If column @p col
0167      * is not given, it returns true, if at least one column is selected
0168      *
0169      * \note If you want to check more than one column for selection, use
0170      * columnsSelected(). It returns a set of all selected columns at once.
0171      */
0172     bool isColumnSelected(uint col = 0) const;
0173 
0174     /**
0175      * @param row the row to check
0176      *
0177      * @return @c true , if the row @p row is selected. If row @p row
0178      * is not given, it returns true, if at least one row is selected
0179      *
0180      * \note If you want to check more than one row for selection, use
0181      * rowsSelected(). It returns a set of all selected rows at once.
0182      */
0183     bool isRowSelected(uint row = 0) const;
0184 
0185     /**
0186      * @return @c true , if at least one column or one row is selected
0187      */
0188     bool isColumnOrRowSelected() const;
0189 
0190     /**
0191      * @return @c true , if all cells in the sheet are selected
0192      */
0193     bool isAllSelected() const;
0194 
0195     /**
0196      * @return a set of column numbers, for those columns, that are selected
0197      */
0198     QSet<int> columnsSelected() const;
0199 
0200     /**
0201      * @return a set of row numbers, for those rows, that are selected
0202      */
0203     QSet<int> rowsSelected() const;
0204 
0205     /**
0206      * @return a set of column numbers, for those columns, that have at least
0207      * one cell selected
0208      */
0209     QSet<int> columnsAffected() const;
0210 
0211     /**
0212      * @return a set of row numbers, for those rows, that have at least
0213      * one cell selected
0214      */
0215     QSet<int> rowsAffected() const;
0216 
0217     /**
0218      * @param point the point's location
0219      * @param sheet the sheet the point belongs to
0220      * @return @c true, if the region contains the point @p point
0221      */
0222     bool contains(const QPoint& point, Sheet* sheet = 0) const;
0223 
0224 
0225 
0226     /* TODO Stefan #2: Optimize! Adjacent Points/Ranges */
0227     /**
0228      * Adds the point @p point to this region.
0229      * @param point the point's location
0230      * @param sheet the sheet the point belongs to
0231      */
0232     Element* add(const QPoint& point, Sheet* sheet = 0);
0233 
0234     /**
0235      * Adds the range @p range to this region.
0236      * @param range the range's location
0237      * @param sheet the sheet the range belongs to
0238      */
0239     Element* add(const QRect& range, Sheet* sheet = 0);
0240 
0241     /**
0242      * Adds the region @p region to this region.
0243      * @param region the region to be added
0244      * @param sheet the fallback sheet used, if an element has no sheet set
0245      */
0246     Element* add(const Region& region, Sheet* sheet = 0);
0247 
0248     /* TODO Stefan #3: Improve! */
0249     /**
0250      * Subtracts the point @p point from this region.
0251      * @param point the point's location
0252      * @param sheet the sheet the point belongs to
0253      */
0254     void sub(const QPoint& point, Sheet* sheet);
0255 
0256     /**
0257      * Subtracts the range @p range from this region.
0258      * @param range the range's location
0259      * @param sheet the sheet the range belongs to
0260      */
0261     void sub(const QRect& range, Sheet* sheet);
0262 
0263     /**
0264      * Subtracts the region @p region from this region.
0265      * @param region the region to subtract
0266      */
0267     void sub(const Region& region);
0268 
0269     /**
0270      * Intersects the region @p region and this region and
0271      * returns the result of the intersection as a new Region.
0272      */
0273     Region intersected(const Region& region) const;
0274 
0275     /**
0276      * Intersects this region with the row @p row and returns
0277      * the result of the intersection as a new Region.
0278      */
0279     Region intersectedWithRow(int row) const;
0280 
0281     /**
0282      * @param point the point's location
0283      * @param sheet the sheet the point belongs to
0284      */
0285     virtual Element* eor(const QPoint& point, Sheet* sheet = 0);
0286 
0287     /**
0288      * Deletes all elements of the region. The result is an empty region.
0289      */
0290     virtual void clear();
0291 
0292 
0293     QRect firstRange() const;
0294     QRect lastRange() const;
0295     Sheet* firstSheet() const;
0296     Sheet* lastSheet() const;
0297 
0298     QRect boundingRect() const;
0299 
0300 
0301     static QRect normalized(const QRect& rect);
0302 
0303 
0304     /**
0305      * @param region the region to compare
0306      * @return @c true, if this region equals region @p region
0307      */
0308     bool operator==(const Region& region) const;
0309     inline bool operator!=(const Region& region) const {
0310         return !operator==(region);
0311     }
0312 
0313     /**
0314      * @param region the region to copy
0315      */
0316     void operator=(const Region& region);
0317 
0318 
0319 
0320     /**
0321      * @return the map to which this region belongs.
0322      */
0323     const Map* map() const;
0324 
0325     /**
0326      * Sets the map to which this region belongs.
0327      */
0328     void setMap(const Map*);
0329 
0330 
0331     typedef QList<Element*>::Iterator      Iterator;
0332     typedef QList<Element*>::ConstIterator ConstIterator;
0333 
0334     ConstIterator constBegin() const;
0335     ConstIterator constEnd() const;
0336 
0337     static bool isValid(const QPoint& point);
0338     static bool isValid(const QRect& rect);
0339 
0340 protected:
0341     /**
0342      * @return the list of elements
0343      */
0344     QList<Element*>& cells() const;
0345 
0346     /**
0347      * @param index the index of the element in whose front the new point
0348      * is inserted
0349      * @param point the location of the point to be inserted
0350      * @param sheet the sheet the point belongs to
0351      * @param multi @c true to allow multiple occurrences of a point
0352      * @return the added point, a null pointer, if @p point is not
0353      * valid or the element containing @p point
0354      */
0355     Element* insert(int index, const QPoint& point, Sheet* sheet, bool multi = true);
0356 
0357     /**
0358      * @param index the index of the element in whose front the new range
0359      * is inserted
0360      * @param range the location of the range to be inserted
0361      * @param sheet the sheet the range belongs to
0362      * @param multi @c true to allow multiple occurrences of a range
0363      * @return the added range, a null pointer, if @p range is not
0364      * valid or the element containing @p range
0365      */
0366     Element* insert(int index, const QRect& range, Sheet* sheet, bool multi = true);
0367 
0368     /**
0369      * @internal used to create derived Points
0370      */
0371     virtual Point* createPoint(const QPoint&) const;
0372 
0373     /**
0374      * @internal used to create derived Points
0375      */
0376     virtual Point* createPoint(const QString&) const;
0377 
0378     /**
0379      * @internal used to create derived Points
0380      */
0381     virtual Point* createPoint(const Point&) const;
0382 
0383     /**
0384      * @internal used to create derived Ranges
0385      */
0386     virtual Range* createRange(const QRect&) const;
0387 
0388     /**
0389      * @internal used to create derived Ranges
0390      */
0391     virtual Range* createRange(const Point&, const Point&) const;
0392 
0393     /**
0394      * @internal used to create derived Ranges
0395      */
0396     virtual Range* createRange(const QString&) const;
0397 
0398     /**
0399      * @internal used to create derived Ranges
0400      */
0401     virtual Range* createRange(const Range&) const;
0402 
0403 private:
0404     class Private;
0405     QSharedDataPointer<Private> d;
0406 };
0407 
0408 
0409 /***************************************************************************
0410   class Region::Element
0411 ****************************************************************************/
0412 /**
0413  * Base class for region elements, which can be points or ranges.
0414  * This class is used by Calligra::Sheets::Region and could not be used outside of it.
0415  *
0416  * Size:
0417  * m_sheet: 4 bytes
0418  * vtable: 4 bytes
0419  * sum: 8 bytes
0420  */
0421 class CALLIGRA_SHEETS_ODF_EXPORT Region::Element
0422 {
0423 public:
0424     enum Type { Undefined, Point, Range };
0425 
0426     Element();
0427     virtual ~Element();
0428 
0429     virtual Type type() const {
0430         return Undefined;
0431     }
0432     virtual bool isValid() const {
0433         return false;
0434     }
0435     virtual bool isColumn() const {
0436         return false;
0437     }
0438     virtual bool isRow() const {
0439         return false;
0440     }
0441     virtual bool isAll() const {
0442         return false;
0443     }
0444 
0445     virtual bool contains(const QPoint&) const {
0446         return false;
0447     }
0448     virtual bool contains(const QRect&) const {
0449         return false;
0450     }
0451 
0452     virtual QString name(Sheet* = 0) const {
0453         return QString("");
0454     }
0455     virtual QRect rect() const {
0456         return QRect();
0457     }
0458 
0459     virtual bool isColumnFixed() const {
0460         return false;
0461     }
0462     virtual bool isRowFixed() const {
0463         return false;
0464     }
0465     virtual bool isTopFixed() const {
0466         return false;
0467     }
0468     virtual bool isLeftFixed() const {
0469         return false;
0470     }
0471     virtual bool isBottomFixed() const {
0472         return false;
0473     }
0474     virtual bool isRightFixed() const {
0475         return false;
0476     }
0477 
0478     Sheet* sheet() const {
0479         return m_sheet;
0480     }
0481     void setSheet(Sheet* sheet) {
0482         m_sheet = sheet;
0483     }
0484 
0485 protected:
0486     /* TODO Stefan #6:
0487         Elaborate, if this pointer could be avoided by QDict or whatever in
0488         Region.
0489     */
0490     Sheet* m_sheet;
0491 };
0492 
0493 
0494 /***************************************************************************
0495   class Region::Point
0496 ****************************************************************************/
0497 
0498 /**
0499  * A point in a region.
0500  * This class is used by Calligra::Sheets::Region and could not be used outside of it.
0501  *
0502  * Size:
0503  * m_sheet: 4 bytes
0504  * vtable: 4 bytes
0505  * m_point: 8 bytes
0506  * sum: 16 bytes
0507  */
0508 class CALLIGRA_SHEETS_ODF_EXPORT Region::Point : public Region::Element
0509 {
0510 public:
0511     Point() : Element(), m_point() {}
0512     Point(int col, int row) : Element(), m_point(col, row) {}
0513     Point(const QPoint&);
0514     Point(const QString&);
0515     ~Point() override;
0516 
0517     Type type() const override {
0518         return Element::Point;
0519     }
0520     bool isValid() const override {
0521         return (!m_point.isNull() && Region::isValid(m_point));
0522     }
0523     bool isColumn() const override {
0524         return false;
0525     }
0526     bool isRow() const override {
0527         return false;
0528     }
0529     bool isAll() const override {
0530         return false;
0531     }
0532 
0533     bool contains(const QPoint&) const override;
0534     bool contains(const QRect&) const override;
0535 
0536     QString name(Sheet* originSheet = 0) const override;
0537 
0538     QRect rect() const override {
0539         return QRect(m_point, m_point);
0540     }
0541 
0542     bool isColumnFixed() const override {
0543         return m_fixedColumn;
0544     }
0545     bool isRowFixed() const override {
0546         return m_fixedRow;
0547     }
0548     bool isTopFixed() const override {
0549         return m_fixedRow;
0550     }
0551     bool isLeftFixed() const override {
0552         return m_fixedColumn;
0553     }
0554     bool isBottomFixed() const override {
0555         return m_fixedRow;
0556     }
0557     bool isRightFixed() const override {
0558         return m_fixedColumn;
0559     }
0560 
0561     QPoint pos() const {
0562         return m_point;
0563     }
0564     Cell cell() const;
0565 
0566     bool operator==(const Point& other) const {
0567         return ((m_point == other.m_point) && (m_sheet == other.m_sheet));
0568     }
0569 
0570 private:
0571     QPoint m_point;
0572     bool m_fixedColumn;
0573     bool m_fixedRow;
0574 };
0575 
0576 
0577 /***************************************************************************
0578   class Region:.Range
0579 ****************************************************************************/
0580 
0581 /**
0582  * A range in a region.
0583  * This class is used by Calligra::Sheets::Region and could not be used outside of it.
0584  *
0585  * Size:
0586  * m_sheet: 4 bytes
0587  * vtable: 4 bytes
0588  * m_range: 16 bytes
0589  * sum: 24 bytes
0590  */
0591 class CALLIGRA_SHEETS_ODF_EXPORT Region::Range : public Region::Element
0592 {
0593 public:
0594     Range(const QRect&);
0595     Range(const Region::Point&, const Region::Point&);
0596     Range(const QString&);
0597     ~Range() override;
0598 
0599     Type type() const override {
0600         return Element::Range;
0601     }
0602     bool isValid() const override {
0603         return !m_range.isNull() && Region::isValid(m_range);
0604     }
0605     bool isColumn() const override;
0606     bool isRow() const override;
0607     bool isAll() const override;
0608 
0609     bool contains(const QPoint&) const override;
0610     bool contains(const QRect&) const override;
0611 
0612     QString name(Sheet* originSheet = 0) const override;
0613 
0614     QRect rect() const override {
0615         return m_range;
0616     }
0617 
0618     bool isColumnFixed() const override {
0619         return m_fixedLeft && m_fixedRight;
0620     }
0621     bool isRowFixed() const override {
0622         return m_fixedTop && m_fixedBottom;
0623     }
0624     bool isTopFixed() const override {
0625         return m_fixedTop;
0626     }
0627     bool isLeftFixed() const override {
0628         return m_fixedLeft;
0629     }
0630     bool isBottomFixed() const override {
0631         return m_fixedBottom;
0632     }
0633     bool isRightFixed() const override {
0634         return m_fixedRight;
0635     }
0636 
0637     int width() const;
0638     int height() const;
0639 
0640 private:
0641     QRect m_range;
0642     bool m_fixedTop;
0643     bool m_fixedLeft;
0644     bool m_fixedBottom;
0645     bool m_fixedRight;
0646 };
0647 
0648 } // namespace Sheets
0649 } // namespace Calligra
0650 
0651 Q_DECLARE_TYPEINFO(Calligra::Sheets::Region, Q_MOVABLE_TYPE);
0652 
0653 
0654 /***************************************************************************
0655   QDebug support
0656 ****************************************************************************/
0657 
0658 inline QDebug operator<<(QDebug str, const Calligra::Sheets::Region& r)
0659 {
0660     return str << qPrintable(r.name());
0661 }
0662 
0663 #endif // CALLIGRA_SHEETS_REGION