]> cloud.milkyroute.net Git - dolphin.git/blob - src/kitemviews/kitemlistselectionmanager.cpp
Implement beginAnchoredSelection() and endAnchoredSelection().
[dolphin.git] / src / kitemviews / kitemlistselectionmanager.cpp
1 /***************************************************************************
2 * Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com> *
3 * Copyright (C) 2011 by Frank Reininghaus <frank78ac@googlemail.com> *
4 * *
5 * Based on the Itemviews NG project from Trolltech Labs: *
6 * http://qt.gitorious.org/qt-labs/itemviews-ng *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
22 ***************************************************************************/
23
24 #include "kitemlistselectionmanager.h"
25
26 #include "kitemmodelbase.h"
27 #include <KDebug>
28
29 KItemListSelectionManager::KItemListSelectionManager(QObject* parent) :
30 QObject(parent),
31 m_currentItem(-1),
32 m_anchorItem(-1),
33 m_selectedItems(),
34 m_isAnchoredSelectionActive(false),
35 m_model(0)
36 {
37 }
38
39 KItemListSelectionManager::~KItemListSelectionManager()
40 {
41 }
42
43 void KItemListSelectionManager::setCurrentItem(int current)
44 {
45 const int previous = m_currentItem;
46 if (m_model && current >= 0 && current < m_model->count()) {
47 m_currentItem = current;
48 } else {
49 m_currentItem = -1;
50 }
51
52 if (m_currentItem != previous) {
53 emit currentChanged(m_currentItem, previous);
54 }
55 }
56
57 int KItemListSelectionManager::currentItem() const
58 {
59 return m_currentItem;
60 }
61
62 void KItemListSelectionManager::setSelectedItems(const QSet<int>& items)
63 {
64 if (m_selectedItems != items) {
65 const QSet<int> previous = m_selectedItems;
66 m_selectedItems = items;
67 emit selectionChanged(m_selectedItems, previous);
68 }
69 }
70
71 QSet<int> KItemListSelectionManager::selectedItems() const
72 {
73 QSet<int> selectedItems = m_selectedItems;
74
75 if (m_isAnchoredSelectionActive) {
76 const int from = qMin(m_anchorItem, m_currentItem);
77 const int to = qMax(m_anchorItem, m_currentItem);
78
79 for (int index = from; index <= to; index++) {
80 selectedItems.insert(index);
81 }
82 }
83
84 return selectedItems;
85 }
86
87 bool KItemListSelectionManager::hasSelection() const
88 {
89 return !m_selectedItems.isEmpty() || m_isAnchoredSelectionActive;
90 }
91
92 void KItemListSelectionManager::setSelected(int index, int count, SelectionMode mode)
93 {
94 if (index < 0 || count < 1 || !m_model || index >= m_model->count()) {
95 return;
96 }
97
98 const QSet<int> previous = m_selectedItems;
99
100 count = qMin(count, m_model->count() - index);
101
102 const int endIndex = index + count -1;
103 switch (mode) {
104 case Select:
105 for (int i = index; i <= endIndex; ++i) {
106 m_selectedItems.insert(i);
107 }
108 break;
109
110 case Deselect:
111 for (int i = index; i <= endIndex; ++i) {
112 m_selectedItems.remove(i);
113 }
114 break;
115
116 case Toggle:
117 for (int i = index; i <= endIndex; ++i) {
118 if (m_selectedItems.contains(i)) {
119 m_selectedItems.remove(i);
120 } else {
121 m_selectedItems.insert(i);
122 }
123 }
124 break;
125
126 default:
127 Q_ASSERT(false);
128 break;
129 }
130
131 if (m_selectedItems != previous) {
132 emit selectionChanged(m_selectedItems, previous);
133 }
134 }
135
136 void KItemListSelectionManager::clearSelection()
137 {
138 if (!m_selectedItems.isEmpty()) {
139 const QSet<int> previous = m_selectedItems;
140 m_selectedItems.clear();
141 m_isAnchoredSelectionActive = false;
142 emit selectionChanged(m_selectedItems, previous);
143 }
144 else if (m_isAnchoredSelectionActive) {
145 m_isAnchoredSelectionActive = false;
146 // TODO: the 'previous' parameter of the signal has to be set correctly, but do we actually need it?
147 emit selectionChanged(m_selectedItems, m_selectedItems);
148 }
149 }
150
151 void KItemListSelectionManager::beginAnchoredSelection(int anchor)
152 {
153 m_isAnchoredSelectionActive = true;
154 setAnchorItem(anchor);
155 }
156
157 void KItemListSelectionManager::endAnchoredSelection()
158 {
159 if (m_isAnchoredSelectionActive) {
160 const int from = qMin(m_anchorItem, m_currentItem);
161 const int to = qMax(m_anchorItem, m_currentItem);
162
163 for (int index = from; index <= to; index++) {
164 m_selectedItems.insert(index);
165 }
166
167 m_isAnchoredSelectionActive = false;
168 }
169 }
170
171 void KItemListSelectionManager::setAnchorItem(int anchor)
172 {
173 const int previous = m_anchorItem;
174 if (m_model && anchor < m_model->count()) {
175 m_anchorItem = anchor;
176 } else {
177 m_anchorItem = -1;
178 }
179
180 if (m_anchorItem != previous) {
181 emit anchorChanged(m_anchorItem, previous);
182 }
183 }
184
185 int KItemListSelectionManager::anchorItem() const
186 {
187 return m_anchorItem;
188 }
189
190 bool KItemListSelectionManager::isAnchoredSelectionActive() const
191 {
192 return m_isAnchoredSelectionActive;
193 }
194
195 void KItemListSelectionManager::setAnchoredSelectionActive(bool active)
196 {
197 m_isAnchoredSelectionActive = active;
198 }
199
200 KItemModelBase* KItemListSelectionManager::model() const
201 {
202 return m_model;
203 }
204
205 void KItemListSelectionManager::setModel(KItemModelBase* model)
206 {
207 m_model = model;
208 if (model && model->count() > 0) {
209 m_currentItem = 0;
210 }
211 }
212
213 void KItemListSelectionManager::itemsInserted(const KItemRangeList& itemRanges)
214 {
215 // Update the current item
216 if (m_currentItem < 0) {
217 setCurrentItem(0);
218 } else {
219 int inc = 0;
220 foreach (const KItemRange& itemRange, itemRanges) {
221 if (m_currentItem < itemRange.index) {
222 break;
223 }
224 inc += itemRange.count;
225 }
226 setCurrentItem(m_currentItem + inc);
227 }
228
229 // Update the anchor item
230 if (m_anchorItem < 0) {
231 setAnchorItem(0);
232 } else {
233 int inc = 0;
234 foreach (const KItemRange& itemRange, itemRanges) {
235 if (m_anchorItem < itemRange.index) {
236 break;
237 }
238 inc += itemRange.count;
239 }
240 setAnchorItem(m_anchorItem + inc);
241 }
242
243 // Update the selections
244 if (!m_selectedItems.isEmpty()) {
245 const QSet<int> previous = m_selectedItems;
246
247 QSet<int> current;
248 current.reserve(m_selectedItems.count());
249 QSetIterator<int> it(m_selectedItems);
250 while (it.hasNext()) {
251 const int index = it.next();
252 int inc = 0;
253 foreach (const KItemRange& itemRange, itemRanges) {
254 if (index < itemRange.index) {
255 break;
256 }
257 inc += itemRange.count;
258 }
259 current.insert(index + inc);
260 }
261
262 if (current != previous) {
263 m_selectedItems = current;
264 emit selectionChanged(current, previous);
265 }
266 }
267 }
268
269 void KItemListSelectionManager::itemsRemoved(const KItemRangeList& itemRanges)
270 {
271 // Update the current item
272 if (m_currentItem >= 0) {
273 int currentItem = m_currentItem;
274 foreach (const KItemRange& itemRange, itemRanges) {
275 if (currentItem < itemRange.index) {
276 break;
277 }
278 if (currentItem >= itemRange.index + itemRange.count) {
279 currentItem -= itemRange.count;
280 } else if (currentItem >= m_model->count()) {
281 currentItem = m_model->count() - 1;
282 }
283 }
284 setCurrentItem(currentItem);
285 }
286
287 // Update the anchor item
288 if (m_anchorItem >= 0) {
289 int anchorItem = m_anchorItem;
290 foreach (const KItemRange& itemRange, itemRanges) {
291 if (anchorItem < itemRange.index) {
292 break;
293 }
294 if (anchorItem >= itemRange.index + itemRange.count) {
295 anchorItem -= itemRange.count;
296 } else if (anchorItem >= m_model->count()) {
297 anchorItem = m_model->count() - 1;
298 }
299 }
300 setAnchorItem(anchorItem);
301 }
302
303 // Update the selections
304 if (!m_selectedItems.isEmpty()) {
305 const QSet<int> previous = m_selectedItems;
306
307 QSet<int> current;
308 current.reserve(m_selectedItems.count());
309 QSetIterator<int> it(m_selectedItems);
310 while (it.hasNext()) {
311 int index = it.next();
312 int dec = 0;
313 foreach (const KItemRange& itemRange, itemRanges) {
314 if (index < itemRange.index) {
315 break;
316 }
317
318 if (index < itemRange.index + itemRange.count) {
319 // The selection is part of the removed range
320 // and will get deleted
321 index = -1;
322 break;
323 }
324
325 dec += itemRange.count;
326 }
327 index -= dec;
328 if (index >= 0) {
329 current.insert(index);
330 }
331 }
332
333 if (current != previous) {
334 m_selectedItems = current;
335 emit selectionChanged(current, previous);
336 }
337 }
338 }
339
340 #include "kitemlistselectionmanager.moc"