1 /***************************************************************************
2 * Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com> *
3 * Copyright (C) 2011 by Frank Reininghaus <frank78ac@googlemail.com> *
5 * Based on the Itemviews NG project from Trolltech Labs: *
6 * http://qt.gitorious.org/qt-labs/itemviews-ng *
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. *
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. *
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 ***************************************************************************/
24 #include "kitemlistselectionmanager.h"
26 #include "kitemmodelbase.h"
29 KItemListSelectionManager::KItemListSelectionManager(QObject
* parent
) :
34 m_isAnchoredSelectionActive(false),
39 KItemListSelectionManager::~KItemListSelectionManager()
43 void KItemListSelectionManager::setCurrentItem(int current
)
45 const int previous
= m_currentItem
;
46 const QSet
<int> previousSelection
= selectedItems();
48 if (m_model
&& current
>= 0 && current
< m_model
->count()) {
49 m_currentItem
= current
;
54 if (m_currentItem
!= previous
) {
55 emit
currentChanged(m_currentItem
, previous
);
57 if (m_isAnchoredSelectionActive
) {
58 const QSet
<int> selection
= selectedItems();
59 if (selection
!= previousSelection
) {
60 emit
selectionChanged(selection
, previousSelection
);
66 int KItemListSelectionManager::currentItem() const
71 void KItemListSelectionManager::setSelectedItems(const QSet
<int>& items
)
73 if (m_selectedItems
!= items
) {
74 const QSet
<int> previous
= m_selectedItems
;
75 m_selectedItems
= items
;
76 emit
selectionChanged(m_selectedItems
, previous
);
80 QSet
<int> KItemListSelectionManager::selectedItems() const
82 QSet
<int> selectedItems
= m_selectedItems
;
84 if (m_isAnchoredSelectionActive
&& m_anchorItem
!= m_currentItem
) {
85 Q_ASSERT(m_anchorItem
>= 0);
86 Q_ASSERT(m_currentItem
>= 0);
87 const int from
= qMin(m_anchorItem
, m_currentItem
);
88 const int to
= qMax(m_anchorItem
, m_currentItem
);
90 for (int index
= from
; index
<= to
; ++index
) {
91 selectedItems
.insert(index
);
98 bool KItemListSelectionManager::hasSelection() const
100 return !m_selectedItems
.isEmpty() || (m_isAnchoredSelectionActive
&& m_anchorItem
!= m_currentItem
);
103 void KItemListSelectionManager::setSelected(int index
, int count
, SelectionMode mode
)
105 if (index
< 0 || count
< 1 || !m_model
|| index
>= m_model
->count()) {
109 endAnchoredSelection();
110 const QSet
<int> previous
= selectedItems();
112 count
= qMin(count
, m_model
->count() - index
);
114 const int endIndex
= index
+ count
-1;
117 for (int i
= index
; i
<= endIndex
; ++i
) {
118 m_selectedItems
.insert(i
);
123 for (int i
= index
; i
<= endIndex
; ++i
) {
124 m_selectedItems
.remove(i
);
129 for (int i
= index
; i
<= endIndex
; ++i
) {
130 if (m_selectedItems
.contains(i
)) {
131 m_selectedItems
.remove(i
);
133 m_selectedItems
.insert(i
);
143 const QSet
<int> selection
= selectedItems();
144 if (selection
!= previous
) {
145 emit
selectionChanged(selection
, previous
);
149 void KItemListSelectionManager::clearSelection()
151 const QSet
<int> previous
= selectedItems();
152 if (!previous
.isEmpty()) {
153 m_selectedItems
.clear();
154 m_isAnchoredSelectionActive
= false;
155 emit
selectionChanged(QSet
<int>(), previous
);
159 void KItemListSelectionManager::beginAnchoredSelection(int anchor
)
161 if (anchor
>= 0 && m_model
&& anchor
< m_model
->count()) {
162 m_isAnchoredSelectionActive
= true;
163 setAnchorItem(anchor
);
164 Q_ASSERT(m_anchorItem
>= 0);
168 void KItemListSelectionManager::endAnchoredSelection()
170 if (m_isAnchoredSelectionActive
&& (m_anchorItem
!= m_currentItem
)) {
171 Q_ASSERT(m_anchorItem
>= 0);
172 Q_ASSERT(m_currentItem
>= 0);
173 const int from
= qMin(m_anchorItem
, m_currentItem
);
174 const int to
= qMax(m_anchorItem
, m_currentItem
);
176 for (int index
= from
; index
<= to
; ++index
) {
177 m_selectedItems
.insert(index
);
181 m_isAnchoredSelectionActive
= false;
184 void KItemListSelectionManager::setAnchorItem(int anchor
)
186 if (!m_isAnchoredSelectionActive
) {
190 if (anchor
< 0 || (m_model
&& anchor
>= m_model
->count())) {
191 // Index is out of range
195 if (m_anchorItem
!= anchor
) {
196 const int previous
= m_anchorItem
;
197 m_anchorItem
= anchor
;
198 emit
anchorChanged(m_anchorItem
, previous
);
202 int KItemListSelectionManager::anchorItem() const
207 bool KItemListSelectionManager::isAnchoredSelectionActive() const
209 return m_isAnchoredSelectionActive
;
212 KItemModelBase
* KItemListSelectionManager::model() const
217 void KItemListSelectionManager::setModel(KItemModelBase
* model
)
220 if (model
&& model
->count() > 0) {
225 void KItemListSelectionManager::itemsInserted(const KItemRangeList
& itemRanges
)
227 // Store the current selection (needed in the selectionChanged() signal)
228 const QSet
<int> previousSelection
= selectedItems();
230 // Update the current item
231 if (m_currentItem
< 0) {
234 const int previousCurrent
= m_currentItem
;
236 foreach (const KItemRange
& itemRange
, itemRanges
) {
237 if (m_currentItem
< itemRange
.index
) {
240 inc
+= itemRange
.count
;
242 // Calling setCurrentItem would trigger the selectionChanged signal, but we want to
243 // emit it only once in this function -> change the current item manually and emit currentChanged
244 m_currentItem
+= inc
;
245 emit
currentChanged(m_currentItem
, previousCurrent
);
248 // Update the anchor item
249 if (m_anchorItem
< 0) {
252 const int previousAnchor
= m_anchorItem
;
254 foreach (const KItemRange
& itemRange
, itemRanges
) {
255 if (m_anchorItem
< itemRange
.index
) {
258 inc
+= itemRange
.count
;
261 emit
anchorChanged(m_anchorItem
, previousAnchor
);
264 // Update the selections
265 if (!m_selectedItems
.isEmpty()) {
266 const QSet
<int> previous
= m_selectedItems
;
267 m_selectedItems
.clear();
268 QSetIterator
<int> it(previous
);
269 while (it
.hasNext()) {
270 const int index
= it
.next();
272 foreach (const KItemRange
& itemRange
, itemRanges
) {
273 if (index
< itemRange
.index
) {
276 inc
+= itemRange
.count
;
278 m_selectedItems
.insert(index
+ inc
);
282 const QSet
<int> selection
= selectedItems();
283 if (selection
!= previousSelection
) {
284 emit
selectionChanged(selection
, previousSelection
);
288 void KItemListSelectionManager::itemsRemoved(const KItemRangeList
& itemRanges
)
290 // Store the current selection (needed in the selectionChanged() signal)
291 const QSet
<int> previousSelection
= selectedItems();
293 // Update the current item
294 if (m_currentItem
>= 0) {
295 const int previousCurrent
= m_currentItem
;
296 int currentItem
= m_currentItem
;
297 foreach (const KItemRange
& itemRange
, itemRanges
) {
298 if (currentItem
< itemRange
.index
) {
301 if (currentItem
>= itemRange
.index
+ itemRange
.count
) {
302 currentItem
-= itemRange
.count
;
303 } else if (currentItem
>= m_model
->count()) {
304 currentItem
= m_model
->count() - 1;
307 // Calling setCurrentItem would trigger the selectionChanged signal, but we want to
308 // emit it only once in this function -> change the current item manually and emit currentChanged
309 m_currentItem
= currentItem
;
310 emit
currentChanged(m_currentItem
, previousCurrent
);
313 // Update the anchor item
314 if (m_anchorItem
>= 0) {
315 const int previousAnchor
= m_anchorItem
;
316 int anchorItem
= m_anchorItem
;
317 foreach (const KItemRange
& itemRange
, itemRanges
) {
318 if (anchorItem
< itemRange
.index
) {
321 if (anchorItem
>= itemRange
.index
+ itemRange
.count
) {
322 anchorItem
-= itemRange
.count
;
323 } else if (anchorItem
>= m_model
->count()) {
324 anchorItem
= m_model
->count() - 1;
327 m_anchorItem
= anchorItem
;
328 if (m_anchorItem
< 0) {
329 m_isAnchoredSelectionActive
= false;
332 emit
anchorChanged(m_anchorItem
, previousAnchor
);
335 // Update the selections
336 if (!m_selectedItems
.isEmpty()) {
337 const QSet
<int> previous
= m_selectedItems
;
338 m_selectedItems
.clear();
339 QSetIterator
<int> it(previous
);
340 while (it
.hasNext()) {
341 int index
= it
.next();
343 foreach (const KItemRange
& itemRange
, itemRanges
) {
344 if (index
< itemRange
.index
) {
348 if (index
< itemRange
.index
+ itemRange
.count
) {
349 // The selection is part of the removed range
350 // and will get deleted
355 dec
+= itemRange
.count
;
359 m_selectedItems
.insert(index
);
364 const QSet
<int> selection
= selectedItems();
365 if (selection
!= previousSelection
) {
366 emit
selectionChanged(selection
, previousSelection
);
370 #include "kitemlistselectionmanager.moc"