From 258a29f61fb379b6a259070213cd68ffa56d6d2d Mon Sep 17 00:00:00 2001 From: Frank Reininghaus Date: Wed, 10 Aug 2011 11:43:05 +0200 Subject: [PATCH] Initial support for anchored selections in the selection manager --- src/kitemviews/kitemlistselectionmanager.cpp | 57 +++++++++++++++++++- src/kitemviews/kitemlistselectionmanager.h | 7 +++ src/tests/kitemlistselectionmanagertest.cpp | 40 +++++++++++--- 3 files changed, 94 insertions(+), 10 deletions(-) diff --git a/src/kitemviews/kitemlistselectionmanager.cpp b/src/kitemviews/kitemlistselectionmanager.cpp index cdc6dbc7d..7b7c6bc54 100644 --- a/src/kitemviews/kitemlistselectionmanager.cpp +++ b/src/kitemviews/kitemlistselectionmanager.cpp @@ -30,6 +30,8 @@ KItemListSelectionManager::KItemListSelectionManager(QObject* parent) : m_currentItem(-1), m_anchorItem(-1), m_selectedItems(), + m_isAnchoredSelectionActive(false), + m_anchoredSelectionMode(KItemListSelectionManager::Select), m_model(0) { } @@ -68,12 +70,37 @@ void KItemListSelectionManager::setSelectedItems(const QSet& items) QSet KItemListSelectionManager::selectedItems() const { - return m_selectedItems; + QSet selectedItems = m_selectedItems; + + if (m_isAnchoredSelectionActive) { + const int from = qMin(m_anchorItem, m_currentItem); + const int to = qMax(m_anchorItem, m_currentItem); + + for (int index = from; index <= to; index++) { + switch (m_anchoredSelectionMode) { + case Select: + selectedItems.insert(index); + break; + case Deselect: + selectedItems.remove(index); + break; + case Toggle: + if (selectedItems.contains(index)) { + selectedItems.remove(index); + } else { + selectedItems.insert(index); + } + break; + } + } + } + + return selectedItems; } bool KItemListSelectionManager::hasSelection() const { - return !m_selectedItems.isEmpty(); + return !m_selectedItems.isEmpty() || (m_isAnchoredSelectionActive && m_anchoredSelectionMode == KItemListSelectionManager::Select); } void KItemListSelectionManager::setSelected(int index, int count, SelectionMode mode) @@ -125,8 +152,14 @@ void KItemListSelectionManager::clearSelection() if (!m_selectedItems.isEmpty()) { const QSet previous = m_selectedItems; m_selectedItems.clear(); + m_isAnchoredSelectionActive = false; emit selectionChanged(m_selectedItems, previous); } + else if (m_isAnchoredSelectionActive) { + m_isAnchoredSelectionActive = false; + // TODO: the 'previous' parameter of the signal has to be set correctly, but do we actually need it? + emit selectionChanged(m_selectedItems, m_selectedItems); + } } void KItemListSelectionManager::beginAnchoredSelection(int anchor, SelectionMode mode) @@ -158,6 +191,26 @@ int KItemListSelectionManager::anchorItem() const return m_anchorItem; } +bool KItemListSelectionManager::isAnchoredSelectionActive() const +{ + return m_isAnchoredSelectionActive; +} + +void KItemListSelectionManager::setAnchoredSelectionActive(bool active) +{ + m_isAnchoredSelectionActive = active; +} + +KItemListSelectionManager::SelectionMode KItemListSelectionManager::anchoredSelectionMode() const +{ + return m_anchoredSelectionMode; +} + +void KItemListSelectionManager::setAnchoredSelectionMode(KItemListSelectionManager::SelectionMode mode) +{ + m_anchoredSelectionMode = mode; +} + KItemModelBase* KItemListSelectionManager::model() const { return m_model; diff --git a/src/kitemviews/kitemlistselectionmanager.h b/src/kitemviews/kitemlistselectionmanager.h index 5b329b40e..9de4c66b2 100644 --- a/src/kitemviews/kitemlistselectionmanager.h +++ b/src/kitemviews/kitemlistselectionmanager.h @@ -64,6 +64,11 @@ public: void setAnchorItem(int anchor); int anchorItem() const; + bool isAnchoredSelectionActive() const; + void setAnchoredSelectionActive(bool active); + SelectionMode anchoredSelectionMode() const; + void setAnchoredSelectionMode(SelectionMode mode); + KItemModelBase* model() const; signals: @@ -80,6 +85,8 @@ private: int m_currentItem; int m_anchorItem; QSet m_selectedItems; + bool m_isAnchoredSelectionActive; + SelectionMode m_anchoredSelectionMode; KItemModelBase* m_model; diff --git a/src/tests/kitemlistselectionmanagertest.cpp b/src/tests/kitemlistselectionmanagertest.cpp index 6b0059a5c..2832a4c76 100644 --- a/src/tests/kitemlistselectionmanagertest.cpp +++ b/src/tests/kitemlistselectionmanagertest.cpp @@ -92,7 +92,12 @@ void KItemListSelectionManagerTest::testConstructor() void KItemListSelectionManagerTest::testCurrentItemAnchorItem() { QSignalSpy spyCurrent(m_selectionManager, SIGNAL(currentChanged(int,int))); - QSignalSpy spyAnchor(m_selectionManager, SIGNAL(anchorChanged(int,int)));; + QSignalSpy spyAnchor(m_selectionManager, SIGNAL(anchorChanged(int,int))); + + m_selectionManager->setAnchoredSelectionActive(true); + QVERIFY(m_selectionManager->isAnchoredSelectionActive()); + m_selectionManager->setAnchoredSelectionMode(KItemListSelectionManager::Select); + QCOMPARE(m_selectionManager->anchoredSelectionMode(), KItemListSelectionManager::Select); // Set current item and check that the selection manager emits the currentChanged(int,int) signal correctly. m_selectionManager->setCurrentItem(4); @@ -101,13 +106,6 @@ void KItemListSelectionManagerTest::testCurrentItemAnchorItem() QCOMPARE(qvariant_cast(spyCurrent.at(0).at(0)), 4); spyCurrent.takeFirst(); - m_selectionManager->setCurrentItem(2); - QCOMPARE(m_selectionManager->currentItem(), 2); - QCOMPARE(spyCurrent.count(), 1); - QCOMPARE(qvariant_cast(spyCurrent.at(0).at(0)), 2); - QCOMPARE(qvariant_cast(spyCurrent.at(0).at(1)), 4); - spyCurrent.takeFirst(); - // Set anchor item and check that the selection manager emits the anchorChanged(int,int) signal correctly. m_selectionManager->setAnchorItem(3); QCOMPARE(m_selectionManager->anchorItem(), 3); @@ -122,6 +120,21 @@ void KItemListSelectionManagerTest::testCurrentItemAnchorItem() QCOMPARE(qvariant_cast(spyAnchor.at(0).at(1)), 3); spyAnchor.takeFirst(); + // Items between current and anchor should be selected now + QCOMPARE(m_selectionManager->selectedItems(), QSet() << 4 << 5); + QVERIFY(m_selectionManager->hasSelection()); + + // Change current item again and check the selection + m_selectionManager->setCurrentItem(2); + QCOMPARE(m_selectionManager->currentItem(), 2); + QCOMPARE(spyCurrent.count(), 1); + QCOMPARE(qvariant_cast(spyCurrent.at(0).at(0)), 2); + QCOMPARE(qvariant_cast(spyCurrent.at(0).at(1)), 4); + spyCurrent.takeFirst(); + + QCOMPARE(m_selectionManager->selectedItems(), QSet() << 2 << 3 << 4 << 5); + QVERIFY(m_selectionManager->hasSelection()); + // Inserting items should update current item and anchor item. m_selectionManager->itemsInserted(KItemRangeList() << KItemRange(0, 1) << @@ -140,6 +153,9 @@ void KItemListSelectionManagerTest::testCurrentItemAnchorItem() QCOMPARE(qvariant_cast(spyAnchor.at(0).at(1)), 5); spyAnchor.takeFirst(); + QCOMPARE(m_selectionManager->selectedItems(), QSet() << 5 << 6 << 7 << 8); + QVERIFY(m_selectionManager->hasSelection()); + // Removing items should update current item and anchor item. m_selectionManager->itemsRemoved(KItemRangeList() << KItemRange(0, 2) << @@ -157,6 +173,14 @@ void KItemListSelectionManagerTest::testCurrentItemAnchorItem() QCOMPARE(qvariant_cast(spyAnchor.at(0).at(0)), 5); QCOMPARE(qvariant_cast(spyAnchor.at(0).at(1)), 8); spyAnchor.takeFirst(); + + QCOMPARE(m_selectionManager->selectedItems(), QSet() << 2 << 3 << 4 << 5); + QVERIFY(m_selectionManager->hasSelection()); + + // Verify that clearSelection() also clears the anchored selection. + m_selectionManager->clearSelection(); + QCOMPARE(m_selectionManager->selectedItems(), QSet()); + QVERIFY(!m_selectionManager->hasSelection()); } void KItemListSelectionManagerTest::testSetSelected_data() -- 2.47.3