1 /* This file is part of the KDE project
2    Copyright 2010 Marijn Kruisselbrink <mkruisselbrink@kde.org>
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 #include "RowFormatStorage.h"
21 
22 #include "calligra_sheets_limits.h"
23 #include "3rdparty/mdds/flat_segment_tree.hpp"
24 
25 #include "Map.h"
26 #include "RowColumnFormat.h"
27 #include "Sheet.h"
28 
29 using namespace Calligra::Sheets;
30 
31 class Q_DECL_HIDDEN RowFormatStorage::Private
32 {
33 public:
34     Private();
35     qreal rawRowHeight(int row, int* lastRow = 0, int* firstRow = 0) const;
36 
37     Sheet* sheet;
38     mdds::flat_segment_tree<int, qreal> rowHeights;
39     mdds::flat_segment_tree<int, bool> hidden;
40     mdds::flat_segment_tree<int, bool> filtered;
41     mdds::flat_segment_tree<int, bool> hasPageBreak;
42 };
43 
Private()44 RowFormatStorage::Private::Private()
45     : rowHeights(1, KS_rowMax+1, -1)
46     , hidden(1, KS_rowMax+1, false)
47     , filtered(1, KS_rowMax+1, false)
48     , hasPageBreak(1, KS_rowMax+1, false)
49 {
50 }
51 
RowFormatStorage(Sheet * sheet)52 RowFormatStorage::RowFormatStorage(Sheet* sheet)
53     : d(new Private)
54 {
55     d->sheet = sheet;
56 }
57 
~RowFormatStorage()58 RowFormatStorage::~RowFormatStorage()
59 {
60     delete d;
61 }
62 
operator =(const RowFormatStorage & r)63 RowFormatStorage& RowFormatStorage::operator=(const RowFormatStorage& r)
64 {
65     *d = *r.d;
66     return *this;
67 }
68 
sheet() const69 Sheet* RowFormatStorage::sheet() const
70 {
71     return d->sheet;
72 }
73 
rowHeight(int row,int * lastRow,int * firstRow) const74 qreal RowFormatStorage::rowHeight(int row, int *lastRow, int *firstRow) const
75 {
76     qreal v = d->rawRowHeight(row, lastRow, firstRow);
77     if (v == -1) {
78         return d->sheet->map()->defaultRowFormat()->height();
79     } else {
80         return v;
81     }
82 }
83 
rawRowHeight(int row,int * lastRow,int * firstRow) const84 qreal RowFormatStorage::Private::rawRowHeight(int row, int *lastRow, int *firstRow) const
85 {
86     qreal v;
87     if (!rowHeights.search(row, v, firstRow, lastRow)) {
88         if (firstRow) *firstRow = row;
89         if (lastRow) *lastRow = row;
90         return -1;
91     } else {
92         if (lastRow) (*lastRow)--;
93         return v;
94     }
95 }
96 
setRowHeight(int firstRow,int lastRow,qreal height)97 void RowFormatStorage::setRowHeight(int firstRow, int lastRow, qreal height)
98 {
99     // first get old row height to properly update documentSize
100     qreal deltaHeight = -totalVisibleRowHeight(firstRow, lastRow);
101 
102     d->rowHeights.insert_back(firstRow, lastRow+1, height);
103 
104     deltaHeight += totalVisibleRowHeight(firstRow, lastRow);
105     d->sheet->adjustDocumentHeight(deltaHeight);
106 }
107 
totalRowHeight(int firstRow,int lastRow) const108 qreal RowFormatStorage::totalRowHeight(int firstRow, int lastRow) const
109 {
110     if (lastRow < firstRow) return 0;
111     qreal res = 0;
112     for (int row = firstRow; row <= lastRow; ++row) {
113         int last;
114         qreal h = rowHeight(row, &last);
115         res += (qMin(last, lastRow) - row + 1) * h;
116         row = last;
117     }
118     return res;
119 }
120 
visibleHeight(int row,int * lastRow,int * firstRow) const121 qreal RowFormatStorage::visibleHeight(int row, int *lastRow, int *firstRow) const
122 {
123     if (isHiddenOrFiltered(row, lastRow, firstRow)) {
124         return 0.0;
125     } else {
126         int hLastRow, hFirstRow;
127         qreal height = rowHeight(row, &hLastRow, &hFirstRow);
128         if (lastRow) *lastRow = qMin(*lastRow, hLastRow);
129         if (firstRow) *firstRow = qMax(*firstRow, hFirstRow);
130         return height;
131     }
132 }
133 
totalVisibleRowHeight(int firstRow,int lastRow) const134 qreal RowFormatStorage::totalVisibleRowHeight(int firstRow, int lastRow) const
135 {
136     if (lastRow < firstRow) return 0;
137     qreal res = 0;
138     for (int row = firstRow; row <= lastRow; ++row) {
139         int last;
140         qreal h = visibleHeight(row, &last);
141         res += (qMin(last, lastRow) - row + 1) * h;
142         row = last;
143     }
144     return res;
145 }
146 
rowForPosition(qreal ypos,qreal * topOfRow) const147 int RowFormatStorage::rowForPosition(qreal ypos, qreal *topOfRow) const
148 {
149     int row = 1;
150     qreal y = 0;
151     while (row < KS_rowMax) {
152         int last;
153         const qreal h = visibleHeight(row, &last);
154         if (h == 0) {
155             row = last+1;
156             continue;
157         }
158         const int cnt = last - row + 1;
159         const int maxcnt = qMin(int((ypos - y) / h), cnt);
160         y += maxcnt * h;
161         row += maxcnt;
162         if (maxcnt < cnt) {
163             if (topOfRow) *topOfRow = y;
164             return row;
165         }
166     }
167     return KS_rowMax;
168 }
169 
isHidden(int row,int * lastRow,int * firstRow) const170 bool RowFormatStorage::isHidden(int row, int *lastRow, int *firstRow) const
171 {
172     bool v;
173     if (!d->hidden.search(row, v, firstRow, lastRow)) {
174         if (firstRow) *firstRow = row;
175         if (lastRow) *lastRow = row;
176         return false;
177     } else {
178         if (lastRow) (*lastRow)--;
179         return v;
180     }
181 }
182 
setHidden(int firstRow,int lastRow,bool hidden)183 void RowFormatStorage::setHidden(int firstRow, int lastRow, bool hidden)
184 {
185     qreal deltaHeight = 0;
186     if (hidden) deltaHeight -= totalVisibleRowHeight(firstRow, lastRow);
187     d->hidden.insert_back(firstRow, lastRow+1, hidden);
188     if (!hidden) deltaHeight += totalVisibleRowHeight(firstRow, lastRow);
189     d->sheet->adjustDocumentHeight(deltaHeight);
190 }
191 
isFiltered(int row,int * lastRow,int * firstRow) const192 bool RowFormatStorage::isFiltered(int row, int* lastRow, int *firstRow) const
193 {
194     bool v;
195     if (!d->filtered.search(row, v, firstRow, lastRow)) {
196         if (firstRow) *firstRow = row;
197         if (lastRow) *lastRow = row;
198         return false;
199     } else {
200         if (lastRow) (*lastRow)--;
201         return v;
202     }
203 }
204 
setFiltered(int firstRow,int lastRow,bool filtered)205 void RowFormatStorage::setFiltered(int firstRow, int lastRow, bool filtered)
206 {
207     qreal deltaHeight = 0;
208     if (filtered) deltaHeight -= totalVisibleRowHeight(firstRow, lastRow);
209     d->filtered.insert_back(firstRow, lastRow+1, filtered);
210     if (!filtered) deltaHeight += totalVisibleRowHeight(firstRow, lastRow);
211     d->sheet->adjustDocumentHeight(deltaHeight);
212 }
213 
isHiddenOrFiltered(int row,int * lastRow,int * firstRow) const214 bool RowFormatStorage::isHiddenOrFiltered(int row, int* lastRow, int* firstRow) const
215 {
216     int hLastRow, hFirstRow, fLastRow, fFirstRow;
217     bool v = isHidden(row, &hLastRow, &hFirstRow);
218     v = isFiltered(row, &fLastRow, &fFirstRow) || v;
219     if (lastRow) *lastRow = qMin(hLastRow, fLastRow);
220     if (firstRow) *firstRow = qMax(hFirstRow, fFirstRow);
221     return v;
222 }
223 
hasPageBreak(int row,int * lastRow,int * firstRow) const224 bool RowFormatStorage::hasPageBreak(int row, int* lastRow, int* firstRow) const
225 {
226     bool v;
227     if (!d->hasPageBreak.search(row, v, firstRow, lastRow)) {
228         if (lastRow) *lastRow = row;
229         if (firstRow) *firstRow = row;
230         return false;
231     } else {
232         if (lastRow) (*lastRow)--;
233         return v;
234     }
235 }
236 
setPageBreak(int firstRow,int lastRow,bool pageBreak)237 void RowFormatStorage::setPageBreak(int firstRow, int lastRow, bool pageBreak)
238 {
239     d->hasPageBreak.insert_back(firstRow, lastRow+1, pageBreak);
240 }
241 
lastNonDefaultRow() const242 int RowFormatStorage::lastNonDefaultRow() const
243 {
244     int row = KS_rowMax;
245     int firstRow;
246     while (row > 0 && isDefaultRow(row, 0, &firstRow)) {
247         row = firstRow-1;
248     }
249     if (row < 1) return 1;
250     return row;
251 }
252 
rowsAreEqual(int row1,int row2) const253 bool RowFormatStorage::rowsAreEqual(int row1, int row2) const
254 {
255     return rowHeight(row1) == rowHeight(row2)
256             && isHidden(row1) == isHidden(row2)
257             && isFiltered(row1) == isFiltered(row2)
258             && hasPageBreak(row1) == hasPageBreak(row2);
259 }
260 
isDefaultRow(int row,int * lastRow,int * firstRow) const261 bool RowFormatStorage::isDefaultRow(int row, int* lastRow, int* firstRow) const
262 {
263     bool isDef = true;
264     int l, f;
265     isDef = d->rawRowHeight(row, lastRow, firstRow) == -1 && isDef;
266     isDef = !isHiddenOrFiltered(row, &l, &f) && isDef;
267     if (lastRow) *lastRow = qMin(*lastRow, l);
268     if (firstRow) *firstRow = qMax(*firstRow, f);
269     isDef = !hasPageBreak(row, &l, &f) && isDef;
270     if (lastRow) *lastRow = qMin(*lastRow, l);
271     if (firstRow) *firstRow = qMax(*firstRow, f);
272     return isDef;
273 }
274 
setDefault(int firstRow,int lastRow)275 void RowFormatStorage::setDefault(int firstRow, int lastRow)
276 {
277     setRowHeight(firstRow, lastRow, -1);
278     setHidden(firstRow, lastRow, false);
279     setFiltered(firstRow, lastRow, false);
280     setPageBreak(firstRow, lastRow, false);
281 }
282 
insertRows(int row,int number)283 void RowFormatStorage::insertRows(int row, int number)
284 {
285     qreal deltaHeight = -totalRowHeight(KS_rowMax - number + 1, KS_rowMax);
286     d->rowHeights.shift_right(row, number, false);
287     deltaHeight += totalRowHeight(row, row + number - 1);
288     d->sheet->adjustDocumentHeight(deltaHeight);
289 
290     d->hidden.shift_right(row, number, false);
291     d->filtered.shift_right(row, number, false);
292     d->hasPageBreak.shift_right(row, number, false);
293 }
294 
removeRows(int row,int number)295 void RowFormatStorage::removeRows(int row, int number)
296 {
297     qreal deltaHeight = -totalRowHeight(row, row + number - 1);
298     d->rowHeights.shift_left(row, row+number-1);
299     deltaHeight += totalRowHeight(KS_rowMax - number + 1, KS_rowMax);
300     d->sheet->adjustDocumentHeight(deltaHeight);
301 
302     d->hidden.shift_left(row, row+number-1);
303     d->filtered.shift_left(row, row+number-1);
304     d->hasPageBreak.shift_left(row, row+number-1);
305 }
306 
307