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