diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp --- a/src/kitemviews/kitemlistcontroller.cpp +++ b/src/kitemviews/kitemlistcontroller.cpp @@ -61,6 +61,8 @@ this, &KItemListController::slotChangeCurrentItem); connect(m_selectionManager, &KItemListSelectionManager::currentChanged, m_keyboardManager, &KItemListKeyboardSearchManager::slotCurrentChanged); + connect(m_selectionManager, &KItemListSelectionManager::selectionChanged, + m_keyboardManager, &KItemListKeyboardSearchManager::slotSelectionChanged); m_autoActivationTimer = new QTimer(this); m_autoActivationTimer->setSingleShot(true); @@ -472,19 +474,18 @@ if (!m_model || m_model->count() == 0) { return; } - const int currentIndex = m_selectionManager->currentItem(); int index; if (searchFromNextItem) { + const int currentIndex = m_selectionManager->currentItem(); index = m_model->indexForKeyboardSearch(text, (currentIndex + 1) % m_model->count()); } else { - index = m_model->indexForKeyboardSearch(text, currentIndex); + index = m_model->indexForKeyboardSearch(text, 0); } if (index >= 0) { m_selectionManager->setCurrentItem(index); if (m_selectionBehavior != NoSelection) { - m_selectionManager->clearSelection(); - m_selectionManager->setSelected(index, 1); + m_selectionManager->replaceSelection(index); m_selectionManager->beginAnchoredSelection(index); } diff --git a/src/kitemviews/kitemlistselectionmanager.h b/src/kitemviews/kitemlistselectionmanager.h --- a/src/kitemviews/kitemlistselectionmanager.h +++ b/src/kitemviews/kitemlistselectionmanager.h @@ -62,6 +62,7 @@ bool hasSelection() const; void setSelected(int index, int count = 1, SelectionMode mode = Select); + void replaceSelection(int index, int count = 1); void clearSelection(); void beginAnchoredSelection(int anchor); diff --git a/src/kitemviews/kitemlistselectionmanager.cpp b/src/kitemviews/kitemlistselectionmanager.cpp --- a/src/kitemviews/kitemlistselectionmanager.cpp +++ b/src/kitemviews/kitemlistselectionmanager.cpp @@ -173,6 +173,20 @@ } } +void KItemListSelectionManager::replaceSelection(int index, int count) +{ + // Equivalent to: + // clearSelection(); + // setSelected(index, count); + // but emitting once only selectionChanged + const KItemSet previous = selectedItems(); + if (!previous.isEmpty()) { + m_selectedItems.clear(); + m_isAnchoredSelectionActive = false; + } + setSelected(index, count); +} + void KItemListSelectionManager::beginAnchoredSelection(int anchor) { if (anchor >= 0 && m_model && anchor < m_model->count()) { diff --git a/src/kitemviews/private/kitemlistkeyboardsearchmanager.h b/src/kitemviews/private/kitemlistkeyboardsearchmanager.h --- a/src/kitemviews/private/kitemlistkeyboardsearchmanager.h +++ b/src/kitemviews/private/kitemlistkeyboardsearchmanager.h @@ -24,6 +24,7 @@ #define KITEMLISTKEYBOARDSEARCHMANAGER_H #include "dolphin_export.h" +#include "kitemviews/kitemset.h" #include #include @@ -64,6 +65,7 @@ public slots: void slotCurrentChanged(int current, int previous); + void slotSelectionChanged(const KItemSet& current, const KItemSet& previous); signals: /** @@ -79,6 +81,7 @@ private: QString m_searchedString; + bool m_isSearchRestarted; QElapsedTimer m_keyboardInputTime; qint64 m_timeout; }; diff --git a/src/kitemviews/private/kitemlistkeyboardsearchmanager.cpp b/src/kitemviews/private/kitemlistkeyboardsearchmanager.cpp --- a/src/kitemviews/private/kitemlistkeyboardsearchmanager.cpp +++ b/src/kitemviews/private/kitemlistkeyboardsearchmanager.cpp @@ -22,9 +22,9 @@ #include "kitemlistkeyboardsearchmanager.h" - KItemListKeyboardSearchManager::KItemListKeyboardSearchManager(QObject* parent) : QObject(parent), + m_isSearchRestarted(false), m_timeout(1000) { m_keyboardInputTime.invalidate(); @@ -64,9 +64,13 @@ const bool sameKey = m_searchedString.length() > 1 && m_searchedString.count(firstKey) == m_searchedString.length(); // Searching for a matching item should start from the next item if either - // 1. a new search is started, or + // 1. a new search is started and a search has not been restarted or // 2. a 'repeated key' search is done. - const bool searchFromNextItem = newSearch || sameKey; + const bool searchFromNextItem = (!m_isSearchRestarted && newSearch) || sameKey; + + // to remember not to searchFromNextItem if selection was deselected + // loosing keyboard search context basically + m_isSearchRestarted = false; emit changeCurrentItem(sameKey ? firstKey : m_searchedString, searchFromNextItem); } @@ -85,6 +89,7 @@ void KItemListKeyboardSearchManager::cancelSearch() { + m_isSearchRestarted = true; m_searchedString.clear(); } @@ -97,3 +102,11 @@ cancelSearch(); } } + +void KItemListKeyboardSearchManager::slotSelectionChanged(const KItemSet& current, const KItemSet& previous) +{ + if (!previous.isEmpty() && current.isEmpty() && previous.count() > 0 && current.count() == 0) { + // The selection has been emptied. We should cancel the search. + cancelSearch(); + } +} diff --git a/src/tests/kitemlistcontrollertest.cpp b/src/tests/kitemlistcontrollertest.cpp --- a/src/tests/kitemlistcontrollertest.cpp +++ b/src/tests/kitemlistcontrollertest.cpp @@ -326,6 +326,12 @@ << qMakePair(KeyPress(Qt::Key_E), ViewState(13, KItemSet() << 13)) << qMakePair(KeyPress(Qt::Key_Space), ViewState(14, KItemSet() << 14)) << qMakePair(KeyPress(Qt::Key_3), ViewState(15, KItemSet() << 15)) + << qMakePair(KeyPress(Qt::Key_Escape), ViewState(15, KItemSet())) + << qMakePair(KeyPress(Qt::Key_E), ViewState(13, KItemSet() << 13)) + << qMakePair(KeyPress(Qt::Key_E), ViewState(14, KItemSet() << 14)) + << qMakePair(KeyPress(Qt::Key_E), ViewState(15, KItemSet() << 15)) + << qMakePair(KeyPress(Qt::Key_Escape), ViewState(15, KItemSet())) + << qMakePair(KeyPress(Qt::Key_E), ViewState(13, KItemSet() << 13)) << qMakePair(KeyPress(Qt::Key_Home), ViewState(0, KItemSet() << 0)) << qMakePair(KeyPress(Qt::Key_Escape), ViewState(0, KItemSet())); diff --git a/src/tests/kitemlistkeyboardsearchmanagertest.cpp b/src/tests/kitemlistkeyboardsearchmanagertest.cpp --- a/src/tests/kitemlistkeyboardsearchmanagertest.cpp +++ b/src/tests/kitemlistkeyboardsearchmanagertest.cpp @@ -51,7 +51,7 @@ m_keyboardSearchManager.addKeys("f"); QCOMPARE(spy.count(), 1); - QCOMPARE(spy.takeFirst(), QList() << "f" << true); + QCOMPARE(spy.takeFirst(), QList() << "f" << false); m_keyboardSearchManager.addKeys("i"); QCOMPARE(spy.count(), 1); @@ -77,7 +77,7 @@ m_keyboardSearchManager.addKeys("f"); QCOMPARE(spy.count(), 1); - QCOMPARE(spy.takeFirst(), QList() << "f" << true); + QCOMPARE(spy.takeFirst(), QList() << "f" << false); m_keyboardSearchManager.addKeys("i"); QCOMPARE(spy.count(), 1); @@ -94,6 +94,13 @@ m_keyboardSearchManager.addKeys("e"); QCOMPARE(spy.count(), 1); QCOMPARE(spy.takeFirst(), QList() << "le" << false); + + // the selection was deselected, for instance with Esc or a click outside the selection + m_keyboardSearchManager.slotSelectionChanged(KItemSet(), KItemSet() << 1); + + m_keyboardSearchManager.addKeys("a"); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.takeFirst(), QList() << "a" << false); } void KItemListKeyboardSearchManagerTest::testRepeatedKeyPress() @@ -109,7 +116,7 @@ m_keyboardSearchManager.addKeys("p"); QCOMPARE(spy.count(), 1); - QCOMPARE(spy.takeFirst(), QList() << "p" << true); + QCOMPARE(spy.takeFirst(), QList() << "p" << false); m_keyboardSearchManager.addKeys("p"); QCOMPARE(spy.count(), 1); @@ -138,7 +145,7 @@ // Simulate that the user enters "a_b". m_keyboardSearchManager.addKeys("a"); QCOMPARE(spy.count(), 1); - QCOMPARE(spy.takeFirst(), QList() << "a" << true); + QCOMPARE(spy.takeFirst(), QList() << "a" << false); m_keyboardSearchManager.addKeys(""); QCOMPARE(spy.count(), 0);