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

0001 /* This file is part of the KDE project
0002    Copyright 2010 Marijn Kruisselbrink <mkruisselbrink@kde.org>
0003 
0004    This library is free software; you can redistribute it and/or
0005    modify it under the terms of the GNU Library General Public
0006    License as published by the Free Software Foundation; either
0007    version 2 of the License, or (at your option) any later version.
0008 
0009    This library is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    Library General Public License for more details.
0013 
0014    You should have received a copy of the GNU Library General Public License
0015    along with this library; see the file COPYING.LIB.  If not, write to
0016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017    Boston, MA 02110-1301, USA.
0018 */
0019 
0020 #include "RowFormatStorage.h"
0021 
0022 #include "calligra_sheets_limits.h"
0023 #include "3rdparty/mdds/flat_segment_tree.hpp"
0024 
0025 #include "Map.h"
0026 #include "RowColumnFormat.h"
0027 #include "Sheet.h"
0028 
0029 using namespace Calligra::Sheets;
0030 
0031 class Q_DECL_HIDDEN RowFormatStorage::Private
0032 {
0033 public:
0034     Private();
0035     qreal rawRowHeight(int row, int* lastRow = 0, int* firstRow = 0) const;
0036 
0037     Sheet* sheet;
0038     mdds::flat_segment_tree<int, qreal> rowHeights;
0039     mdds::flat_segment_tree<int, bool> hidden;
0040     mdds::flat_segment_tree<int, bool> filtered;
0041     mdds::flat_segment_tree<int, bool> hasPageBreak;
0042 };
0043 
0044 RowFormatStorage::Private::Private()
0045     : rowHeights(1, KS_rowMax+1, -1)
0046     , hidden(1, KS_rowMax+1, false)
0047     , filtered(1, KS_rowMax+1, false)
0048     , hasPageBreak(1, KS_rowMax+1, false)
0049 {
0050 }
0051 
0052 RowFormatStorage::RowFormatStorage(Sheet* sheet)
0053     : d(new Private)
0054 {
0055     d->sheet = sheet;
0056 }
0057 
0058 RowFormatStorage::~RowFormatStorage()
0059 {
0060     delete d;
0061 }
0062 
0063 RowFormatStorage& RowFormatStorage::operator=(const RowFormatStorage& r)
0064 {
0065     *d = *r.d;
0066     return *this;
0067 }
0068 
0069 Sheet* RowFormatStorage::sheet() const
0070 {
0071     return d->sheet;
0072 }
0073 
0074 qreal RowFormatStorage::rowHeight(int row, int *lastRow, int *firstRow) const
0075 {
0076     qreal v = d->rawRowHeight(row, lastRow, firstRow);
0077     if (v == -1) {
0078         return d->sheet->map()->defaultRowFormat()->height();
0079     } else {
0080         return v;
0081     }
0082 }
0083 
0084 qreal RowFormatStorage::Private::rawRowHeight(int row, int *lastRow, int *firstRow) const
0085 {
0086     qreal v;
0087     if (!rowHeights.search(row, v, firstRow, lastRow)) {
0088         if (firstRow) *firstRow = row;
0089         if (lastRow) *lastRow = row;
0090         return -1;
0091     } else {
0092         if (lastRow) (*lastRow)--;
0093         return v;
0094     }
0095 }
0096 
0097 void RowFormatStorage::setRowHeight(int firstRow, int lastRow, qreal height)
0098 {
0099     // first get old row height to properly update documentSize
0100     qreal deltaHeight = -totalVisibleRowHeight(firstRow, lastRow);
0101 
0102     d->rowHeights.insert_back(firstRow, lastRow+1, height);
0103 
0104     deltaHeight += totalVisibleRowHeight(firstRow, lastRow);
0105     d->sheet->adjustDocumentHeight(deltaHeight);
0106 }
0107 
0108 qreal RowFormatStorage::totalRowHeight(int firstRow, int lastRow) const
0109 {
0110     if (lastRow < firstRow) return 0;
0111     qreal res = 0;
0112     for (int row = firstRow; row <= lastRow; ++row) {
0113         int last;
0114         qreal h = rowHeight(row, &last);
0115         res += (qMin(last, lastRow) - row + 1) * h;
0116         row = last;
0117     }
0118     return res;
0119 }
0120 
0121 qreal RowFormatStorage::visibleHeight(int row, int *lastRow, int *firstRow) const
0122 {
0123     if (isHiddenOrFiltered(row, lastRow, firstRow)) {
0124         return 0.0;
0125     } else {
0126         int hLastRow, hFirstRow;
0127         qreal height = rowHeight(row, &hLastRow, &hFirstRow);
0128         if (lastRow) *lastRow = qMin(*lastRow, hLastRow);
0129         if (firstRow) *firstRow = qMax(*firstRow, hFirstRow);
0130         return height;
0131     }
0132 }
0133 
0134 qreal RowFormatStorage::totalVisibleRowHeight(int firstRow, int lastRow) const
0135 {
0136     if (lastRow < firstRow) return 0;
0137     qreal res = 0;
0138     for (int row = firstRow; row <= lastRow; ++row) {
0139         int last;
0140         qreal h = visibleHeight(row, &last);
0141         res += (qMin(last, lastRow) - row + 1) * h;
0142         row = last;
0143     }
0144     return res;
0145 }
0146 
0147 int RowFormatStorage::rowForPosition(qreal ypos, qreal *topOfRow) const
0148 {
0149     int row = 1;
0150     qreal y = 0;
0151     while (row < KS_rowMax) {
0152         int last;
0153         const qreal h = visibleHeight(row, &last);
0154         if (h == 0) {
0155             row = last+1;
0156             continue;
0157         }
0158         const int cnt = last - row + 1;
0159         const int maxcnt = qMin(int((ypos - y) / h), cnt);
0160         y += maxcnt * h;
0161         row += maxcnt;
0162         if (maxcnt < cnt) {
0163             if (topOfRow) *topOfRow = y;
0164             return row;
0165         }
0166     }
0167     return KS_rowMax;
0168 }
0169 
0170 bool RowFormatStorage::isHidden(int row, int *lastRow, int *firstRow) const
0171 {
0172     bool v;
0173     if (!d->hidden.search(row, v, firstRow, lastRow)) {
0174         if (firstRow) *firstRow = row;
0175         if (lastRow) *lastRow = row;
0176         return false;
0177     } else {
0178         if (lastRow) (*lastRow)--;
0179         return v;
0180     }
0181 }
0182 
0183 void RowFormatStorage::setHidden(int firstRow, int lastRow, bool hidden)
0184 {
0185     qreal deltaHeight = 0;
0186     if (hidden) deltaHeight -= totalVisibleRowHeight(firstRow, lastRow);
0187     d->hidden.insert_back(firstRow, lastRow+1, hidden);
0188     if (!hidden) deltaHeight += totalVisibleRowHeight(firstRow, lastRow);
0189     d->sheet->adjustDocumentHeight(deltaHeight);
0190 }
0191 
0192 bool RowFormatStorage::isFiltered(int row, int* lastRow, int *firstRow) const
0193 {
0194     bool v;
0195     if (!d->filtered.search(row, v, firstRow, lastRow)) {
0196         if (firstRow) *firstRow = row;
0197         if (lastRow) *lastRow = row;
0198         return false;
0199     } else {
0200         if (lastRow) (*lastRow)--;
0201         return v;
0202     }
0203 }
0204 
0205 void RowFormatStorage::setFiltered(int firstRow, int lastRow, bool filtered)
0206 {
0207     qreal deltaHeight = 0;
0208     if (filtered) deltaHeight -= totalVisibleRowHeight(firstRow, lastRow);
0209     d->filtered.insert_back(firstRow, lastRow+1, filtered);
0210     if (!filtered) deltaHeight += totalVisibleRowHeight(firstRow, lastRow);
0211     d->sheet->adjustDocumentHeight(deltaHeight);
0212 }
0213 
0214 bool RowFormatStorage::isHiddenOrFiltered(int row, int* lastRow, int* firstRow) const
0215 {
0216     int hLastRow, hFirstRow, fLastRow, fFirstRow;
0217     bool v = isHidden(row, &hLastRow, &hFirstRow);
0218     v = isFiltered(row, &fLastRow, &fFirstRow) || v;
0219     if (lastRow) *lastRow = qMin(hLastRow, fLastRow);
0220     if (firstRow) *firstRow = qMax(hFirstRow, fFirstRow);
0221     return v;
0222 }
0223 
0224 bool RowFormatStorage::hasPageBreak(int row, int* lastRow, int* firstRow) const
0225 {
0226     bool v;
0227     if (!d->hasPageBreak.search(row, v, firstRow, lastRow)) {
0228         if (lastRow) *lastRow = row;
0229         if (firstRow) *firstRow = row;
0230         return false;
0231     } else {
0232         if (lastRow) (*lastRow)--;
0233         return v;
0234     }
0235 }
0236 
0237 void RowFormatStorage::setPageBreak(int firstRow, int lastRow, bool pageBreak)
0238 {
0239     d->hasPageBreak.insert_back(firstRow, lastRow+1, pageBreak);
0240 }
0241 
0242 int RowFormatStorage::lastNonDefaultRow() const
0243 {
0244     int row = KS_rowMax;
0245     int firstRow;
0246     while (row > 0 && isDefaultRow(row, 0, &firstRow)) {
0247         row = firstRow-1;
0248     }
0249     if (row < 1) return 1;
0250     return row;
0251 }
0252 
0253 bool RowFormatStorage::rowsAreEqual(int row1, int row2) const
0254 {
0255     return rowHeight(row1) == rowHeight(row2)
0256             && isHidden(row1) == isHidden(row2)
0257             && isFiltered(row1) == isFiltered(row2)
0258             && hasPageBreak(row1) == hasPageBreak(row2);
0259 }
0260 
0261 bool RowFormatStorage::isDefaultRow(int row, int* lastRow, int* firstRow) const
0262 {
0263     bool isDef = true;
0264     int l, f;
0265     isDef = d->rawRowHeight(row, lastRow, firstRow) == -1 && isDef;
0266     isDef = !isHiddenOrFiltered(row, &l, &f) && isDef;
0267     if (lastRow) *lastRow = qMin(*lastRow, l);
0268     if (firstRow) *firstRow = qMax(*firstRow, f);
0269     isDef = !hasPageBreak(row, &l, &f) && isDef;
0270     if (lastRow) *lastRow = qMin(*lastRow, l);
0271     if (firstRow) *firstRow = qMax(*firstRow, f);
0272     return isDef;
0273 }
0274 
0275 void RowFormatStorage::setDefault(int firstRow, int lastRow)
0276 {
0277     setRowHeight(firstRow, lastRow, -1);
0278     setHidden(firstRow, lastRow, false);
0279     setFiltered(firstRow, lastRow, false);
0280     setPageBreak(firstRow, lastRow, false);
0281 }
0282 
0283 void RowFormatStorage::insertRows(int row, int number)
0284 {
0285     qreal deltaHeight = -totalRowHeight(KS_rowMax - number + 1, KS_rowMax);
0286     d->rowHeights.shift_right(row, number, false);
0287     deltaHeight += totalRowHeight(row, row + number - 1);
0288     d->sheet->adjustDocumentHeight(deltaHeight);
0289 
0290     d->hidden.shift_right(row, number, false);
0291     d->filtered.shift_right(row, number, false);
0292     d->hasPageBreak.shift_right(row, number, false);
0293 }
0294 
0295 void RowFormatStorage::removeRows(int row, int number)
0296 {
0297     qreal deltaHeight = -totalRowHeight(row, row + number - 1);
0298     d->rowHeights.shift_left(row, row+number-1);
0299     deltaHeight += totalRowHeight(KS_rowMax - number + 1, KS_rowMax);
0300     d->sheet->adjustDocumentHeight(deltaHeight);
0301 
0302     d->hidden.shift_left(row, row+number-1);
0303     d->filtered.shift_left(row, row+number-1);
0304     d->hasPageBreak.shift_left(row, row+number-1);
0305 }
0306