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 | #include "RowRepeatStorage.h" |
20 | |
21 | #include <QList> |
22 | #include <QPair> |
23 | #include <QDebug> |
24 | |
25 | #include "calligra_sheets_limits.h" |
26 | |
27 | using namespace Calligra::Sheets; |
28 | |
29 | RowRepeatStorage::RowRepeatStorage() |
30 | { |
31 | } |
32 | |
33 | void RowRepeatStorage::dump() const |
34 | { |
35 | for (QMap<int, int>::const_iterator it = m_data.begin(); it != m_data.end(); ++it) { |
36 | qDebug() << "[" << (it.key() - it.value() + 1) << it.key() << "] =" << it.value(); |
37 | } |
38 | } |
39 | |
40 | void RowRepeatStorage::setRowRepeat(int firstRow, int rowRepeat) |
41 | { |
42 | const int lastRow = firstRow + rowRepeat - 1; |
43 | // see if m_data contains a range that includes firstRow |
44 | QMap<int, int>::iterator it = m_data.lowerBound(firstRow); |
45 | typedef QPair<int, int> intPair; |
46 | QList<intPair> newRanges; |
47 | // returns first range that ends at or after firstRow |
48 | if (it != m_data.end()) { |
49 | while (it != m_data.end() && (it.key() - it.value() + 1) <= lastRow) { |
50 | if ((it.key() - it.value() + 1) < firstRow) { |
51 | // starts before the new range, so we want to change the row repeat value of this range |
52 | // but since the key is the end of the range, we can only remove it and re-insert it later |
53 | newRanges.append(qMakePair(firstRow - 1, it.value() - (it.key() - firstRow + 1))); |
54 | if (it.key() > lastRow) { |
55 | // ends after the new range, so also adjust the end |
56 | it.value() = it.key() - lastRow; |
57 | ++it; |
58 | } else { |
59 | it = m_data.erase(it); |
60 | } |
61 | } else { |
62 | // starts inside the new range, ends in or after the new range |
63 | if (it.key() <= lastRow) { |
64 | // ends inside the new range, so just remove |
65 | it = m_data.erase(it); |
66 | } else { |
67 | // ends after the new range, adjust and go to the next |
68 | it.value() = it.key() - lastRow; |
69 | ++it; |
70 | } |
71 | } |
72 | } |
73 | } |
74 | |
75 | // finally set the new range of row-repeat values |
76 | if (rowRepeat != 1) |
77 | m_data[lastRow] = rowRepeat; |
78 | |
79 | foreach (const intPair& p, newRanges) { |
80 | if (p.second > 1) m_data[p.first] = p.second; |
81 | } |
82 | } |
83 | |
84 | int RowRepeatStorage::rowRepeat(int row) const |
85 | { |
86 | // first range that ends at or after row |
87 | QMap<int, int>::const_iterator it = m_data.lowerBound(row); |
88 | // not found? default value = 1 |
89 | if (it == m_data.end()) return 1; |
90 | // otherwise, see if row is actually inside the range |
91 | if (it.key() - it.value() + 1 <= row) { |
92 | return it.value(); |
93 | } |
94 | return 1; |
95 | } |
96 | |
97 | int RowRepeatStorage::firstIdenticalRow(int row) const |
98 | { |
99 | // first range that ends at or after row |
100 | QMap<int, int>::const_iterator it = m_data.lowerBound(row); |
101 | // not found? default value = row |
102 | if (it == m_data.end()) return row; |
103 | // otherwise, see if row is actually inside the range |
104 | if (it.key() - it.value() + 1 <= row) { |
105 | return it.key() - it.value() + 1; |
106 | } |
107 | return row; |
108 | } |
109 | |
110 | void RowRepeatStorage::insertRows(int row, int count) |
111 | { |
112 | typedef QPair<int, int> intPair; |
113 | QList<intPair> newRanges; |
114 | |
115 | // first range that ends at or after row |
116 | QMap<int, int>::iterator it = m_data.lowerBound(row); |
117 | while (it != m_data.end()) { |
118 | if (it.key() - it.value() + 1 < row) { |
119 | // starts before the newly inserted rows, so split it up |
120 | newRanges.append(qMakePair(row-1, row - it.key() + it.value() - 1)); |
121 | newRanges.append(qMakePair(it.key() + count, it.key() - row + 1)); |
122 | } else { |
123 | newRanges.append(qMakePair(it.key() + count, it.value())); |
124 | } |
125 | it = m_data.erase(it); |
126 | } |
127 | |
128 | m_data[row+count-1] = count; |
129 | foreach (const intPair& p, newRanges) { |
130 | if (p.second > 1) m_data[p.first] = p.second; |
131 | } |
132 | } |
133 | |
134 | void RowRepeatStorage::removeRows(int row, int count) |
135 | { |
136 | typedef QPair<int, int> intPair; |
137 | QList<intPair> newRanges; |
138 | |
139 | // first range that ends at or after row |
140 | QMap<int, int>::iterator it = m_data.lowerBound(row); |
141 | while (it != m_data.end()) { |
142 | if (it.key() - it.value() + 1 < row) { |
143 | // starts before removed rows |
144 | newRanges.append(qMakePair(row-1, row - it.key() + it.value() - 1)); |
145 | } |
146 | if (it.key() >= row + count) { |
147 | // ends after the removed rows |
148 | newRanges.append(qMakePair(it.key() - count, qMin(it.value(), it.key() - row - count + 1))); |
149 | } |
150 | it = m_data.erase(it); |
151 | } |
152 | |
153 | foreach (const intPair& p, newRanges) { |
154 | if (p.second > 1) m_data[p.first] = p.second; |
155 | } |
156 | } |
157 | |
158 | void RowRepeatStorage::insertShiftDown(const QRect &rect) |
159 | { |
160 | RowRepeatStorage s2 = *this; |
161 | s2.insertRows(rect.top(), rect.height()); |
162 | |
163 | typedef QPair<int, int> intPair; |
164 | QList<intPair> newRanges; |
165 | |
166 | for (int row = 1; row <= KS_rowMax;) { |
167 | int repeat1 = rowRepeat(row); |
168 | int repeat2 = s2.rowRepeat(row); |
169 | repeat1 -= row - firstIdenticalRow(row); |
170 | repeat2 -= row - s2.firstIdenticalRow(row); |
171 | int repeat = qMin(repeat1, repeat2); |
172 | if (repeat > 1) { |
173 | newRanges.append(qMakePair(row + repeat - 1, repeat)); |
174 | } |
175 | row += repeat; |
176 | } |
177 | |
178 | m_data.clear(); |
179 | foreach (const intPair& p, newRanges) { |
180 | if (p.second > 1) m_data[p.first] = p.second; |
181 | } |
182 | } |
183 | |
184 | void RowRepeatStorage::removeShiftUp(const QRect &rect) |
185 | { |
186 | RowRepeatStorage s2 = *this; |
187 | s2.removeRows(rect.top(), rect.height()); |
188 | |
189 | typedef QPair<int, int> intPair; |
190 | QList<intPair> newRanges; |
191 | |
192 | for (int row = 1; row <= KS_rowMax;) { |
193 | int repeat1 = rowRepeat(row); |
194 | int repeat2 = s2.rowRepeat(row); |
195 | repeat1 -= row - firstIdenticalRow(row); |
196 | repeat2 -= row - s2.firstIdenticalRow(row); |
197 | int repeat = qMin(repeat1, repeat2); |
198 | if (repeat > 1) { |
199 | newRanges.append(qMakePair(row + repeat - 1, repeat)); |
200 | } |
201 | row += repeat; |
202 | } |
203 | |
204 | m_data.clear(); |
205 | foreach (const intPair& p, newRanges) { |
206 | if (p.second > 1) m_data[p.first] = p.second; |
207 | } |
208 | } |
209 | |
210 | void RowRepeatStorage::insertShiftRight(const QRect &rect) |
211 | { |
212 | splitRowRepeat(rect.top()); |
213 | splitRowRepeat(rect.bottom()+1); |
214 | } |
215 | |
216 | void RowRepeatStorage::removeShiftLeft(const QRect &rect) |
217 | { |
218 | // identical to insert |
219 | insertShiftRight(rect); |
220 | } |
221 | |
222 | void RowRepeatStorage::splitRowRepeat(int row) |
223 | { |
224 | // first range that ends at or after row |
225 | QMap<int, int>::iterator it = m_data.lowerBound(row); |
226 | if (it != m_data.end() && (it.key() - it.value() + 1) < row) { |
227 | // range starts before row, ends in or after it; split it |
228 | int start = it.key() - it.value() + 1; |
229 | int count = row - start; |
230 | it.value() = it.key() - row + 1; |
231 | if (count > 1) m_data[start+count-1] = count; |
232 | } |
233 | } |
234 | |