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