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"
25 #include "kitemlistcontroller.h"
26 #include "kitemlistview.h"
27 #include "kitemmodelbase.h"
29 #include <QAccessible>
31 KItemListSelectionManager::KItemListSelectionManager(QObject
* parent
) :
36 m_isAnchoredSelectionActive(false),
41 KItemListSelectionManager::~KItemListSelectionManager()
45 void KItemListSelectionManager::setCurrentItem(int current
)
47 const int previous
= m_currentItem
;
48 const QSet
<int> previousSelection
= selectedItems();
50 if (m_model
&& current
>= 0 && current
< m_model
->count()) {
51 m_currentItem
= current
;
56 if (m_currentItem
!= previous
) {
57 emit
currentChanged(m_currentItem
, previous
);
59 if (m_isAnchoredSelectionActive
) {
60 const QSet
<int> selection
= selectedItems();
61 if (selection
!= previousSelection
) {
62 emit
selectionChanged(selection
, previousSelection
);
66 KItemListController
*controller
= static_cast<KItemListController
*>(parent());
67 QAccessible::updateAccessibility(controller
->view(), current
+1, QAccessible::Focus
);
70 int KItemListSelectionManager::currentItem() const
75 void KItemListSelectionManager::setSelectedItems(const QSet
<int>& items
)
77 if (m_selectedItems
!= items
) {
78 const QSet
<int> previous
= m_selectedItems
;
79 m_selectedItems
= items
;
80 emit
selectionChanged(m_selectedItems
, previous
);
84 QSet
<int> KItemListSelectionManager::selectedItems() const
86 QSet
<int> selectedItems
= m_selectedItems
;
88 if (m_isAnchoredSelectionActive
&& m_anchorItem
!= m_currentItem
) {
89 Q_ASSERT(m_anchorItem
>= 0);
90 Q_ASSERT(m_currentItem
>= 0);
91 const int from
= qMin(m_anchorItem
, m_currentItem
);
92 const int to
= qMax(m_anchorItem
, m_currentItem
);
94 for (int index
= from
; index
<= to
; ++index
) {
95 selectedItems
.insert(index
);
102 bool KItemListSelectionManager::isSelected(int index
) const
104 if (m_selectedItems
.contains(index
)) {
108 if (m_isAnchoredSelectionActive
&& m_anchorItem
!= m_currentItem
) {
109 Q_ASSERT(m_anchorItem
>= 0);
110 Q_ASSERT(m_currentItem
>= 0);
111 const int from
= qMin(m_anchorItem
, m_currentItem
);
112 const int to
= qMax(m_anchorItem
, m_currentItem
);
114 if (from
<= index
&& index
<= to
) {
122 bool KItemListSelectionManager::hasSelection() const
124 return !m_selectedItems
.isEmpty() || (m_isAnchoredSelectionActive
&& m_anchorItem
!= m_currentItem
);
127 void KItemListSelectionManager::setSelected(int index
, int count
, SelectionMode mode
)
129 if (index
< 0 || count
< 1 || !m_model
|| index
>= m_model
->count()) {
133 endAnchoredSelection();
134 const QSet
<int> previous
= selectedItems();
136 count
= qMin(count
, m_model
->count() - index
);
138 const int endIndex
= index
+ count
-1;
141 for (int i
= index
; i
<= endIndex
; ++i
) {
142 m_selectedItems
.insert(i
);
147 for (int i
= index
; i
<= endIndex
; ++i
) {
148 m_selectedItems
.remove(i
);
153 for (int i
= index
; i
<= endIndex
; ++i
) {
154 if (m_selectedItems
.contains(i
)) {
155 m_selectedItems
.remove(i
);
157 m_selectedItems
.insert(i
);
167 const QSet
<int> selection
= selectedItems();
168 if (selection
!= previous
) {
169 emit
selectionChanged(selection
, previous
);
173 void KItemListSelectionManager::clearSelection()
175 const QSet
<int> previous
= selectedItems();
176 if (!previous
.isEmpty()) {
177 m_selectedItems
.clear();
178 m_isAnchoredSelectionActive
= false;
179 emit
selectionChanged(QSet
<int>(), previous
);
183 void KItemListSelectionManager::beginAnchoredSelection(int anchor
)
185 if (anchor
>= 0 && m_model
&& anchor
< m_model
->count()) {
186 m_isAnchoredSelectionActive
= true;
187 m_anchorItem
= anchor
;
191 void KItemListSelectionManager::endAnchoredSelection()
193 if (m_isAnchoredSelectionActive
&& (m_anchorItem
!= m_currentItem
)) {
194 Q_ASSERT(m_anchorItem
>= 0);
195 Q_ASSERT(m_currentItem
>= 0);
196 const int from
= qMin(m_anchorItem
, m_currentItem
);
197 const int to
= qMax(m_anchorItem
, m_currentItem
);
199 for (int index
= from
; index
<= to
; ++index
) {
200 m_selectedItems
.insert(index
);
204 m_isAnchoredSelectionActive
= false;
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) {
253 foreach (const KItemRange
& itemRange
, itemRanges
) {
254 if (m_anchorItem
< itemRange
.index
) {
257 inc
+= itemRange
.count
;
262 // Update the selections
263 if (!m_selectedItems
.isEmpty()) {
264 const QSet
<int> previous
= m_selectedItems
;
265 m_selectedItems
.clear();
266 m_selectedItems
.reserve(previous
.count());
267 QSetIterator
<int> it(previous
);
268 while (it
.hasNext()) {
269 const int index
= it
.next();
271 foreach (const KItemRange
& itemRange
, itemRanges
) {
272 if (index
< itemRange
.index
) {
275 inc
+= itemRange
.count
;
277 m_selectedItems
.insert(index
+ inc
);
281 const QSet
<int> selection
= selectedItems();
282 if (selection
!= previousSelection
) {
283 emit
selectionChanged(selection
, previousSelection
);
287 void KItemListSelectionManager::itemsRemoved(const KItemRangeList
& itemRanges
)
289 // Store the current selection (needed in the selectionChanged() signal)
290 const QSet
<int> previousSelection
= selectedItems();
292 // Update the current item
293 if (m_currentItem
>= 0) {
294 const int previousCurrent
= m_currentItem
;
295 // Calling setCurrentItem() would trigger the selectionChanged signal, but we want to
296 // emit it only once in this function -> change the current item manually and emit currentChanged
297 m_currentItem
= indexAfterRangesRemoving(m_currentItem
, itemRanges
);
298 if (m_currentItem
!= previousCurrent
) {
299 emit
currentChanged(m_currentItem
, previousCurrent
);
302 if (m_currentItem
< 0) {
303 // The current item has been removed.
304 m_currentItem
= qMin(previousCurrent
, m_model
->count() - 1);
305 emit
currentChanged(m_currentItem
, -1);
309 // Update the anchor item
310 if (m_anchorItem
>= 0) {
311 m_anchorItem
= indexAfterRangesRemoving(m_anchorItem
, itemRanges
);
312 if (m_anchorItem
< 0) {
313 m_isAnchoredSelectionActive
= false;
317 // Update the selections and the anchor item
318 if (!m_selectedItems
.isEmpty()) {
319 const QSet
<int> previous
= m_selectedItems
;
320 m_selectedItems
.clear();
321 m_selectedItems
.reserve(previous
.count());
322 QSetIterator
<int> it(previous
);
323 while (it
.hasNext()) {
324 const int index
= indexAfterRangesRemoving(it
.next(), itemRanges
);
326 m_selectedItems
.insert(index
);
331 const QSet
<int> selection
= selectedItems();
332 if (selection
!= previousSelection
) {
333 emit
selectionChanged(selection
, previousSelection
);
336 Q_ASSERT(m_currentItem
< m_model
->count());
337 Q_ASSERT(m_anchorItem
< m_model
->count());
340 void KItemListSelectionManager::itemsMoved(const KItemRange
& itemRange
, const QList
<int>& movedToIndexes
)
342 // Store the current selection (needed in the selectionChanged() signal)
343 const QSet
<int> previousSelection
= selectedItems();
345 // Update the current item
346 if (m_currentItem
>= itemRange
.index
&& m_currentItem
< itemRange
.index
+ itemRange
.count
) {
347 const int previousCurrentItem
= m_currentItem
;
348 const int newCurrentItem
= movedToIndexes
.at(previousCurrentItem
- itemRange
.index
);
350 // Calling setCurrentItem would trigger the selectionChanged signal, but we want to
351 // emit it only once in this function -> change the current item manually and emit currentChanged
352 m_currentItem
= newCurrentItem
;
353 emit
currentChanged(newCurrentItem
, previousCurrentItem
);
356 // Update the anchor item
357 if (m_anchorItem
>= itemRange
.index
&& m_anchorItem
< itemRange
.index
+ itemRange
.count
) {
358 m_anchorItem
= movedToIndexes
.at(m_anchorItem
- itemRange
.index
);
361 // Update the selections
362 if (!m_selectedItems
.isEmpty()) {
363 const QSet
<int> previous
= m_selectedItems
;
364 m_selectedItems
.clear();
365 m_selectedItems
.reserve(previous
.count());
366 QSetIterator
<int> it(previous
);
367 while (it
.hasNext()) {
368 const int index
= it
.next();
369 if (index
>= itemRange
.index
&& index
< itemRange
.index
+ itemRange
.count
) {
370 m_selectedItems
.insert(movedToIndexes
.at(index
- itemRange
.index
));
373 m_selectedItems
.insert(index
);
378 const QSet
<int> selection
= selectedItems();
379 if (selection
!= previousSelection
) {
380 emit
selectionChanged(selection
, previousSelection
);
384 int KItemListSelectionManager::indexAfterRangesRemoving(int index
, const KItemRangeList
& itemRanges
) const
387 foreach (const KItemRange
& itemRange
, itemRanges
) {
388 if (index
< itemRange
.index
) {
392 if (index
< itemRange
.index
+ itemRange
.count
) {
393 // The index is part of the removed range
397 dec
+= itemRange
.count
;
401 #include "kitemlistselectionmanager.moc"