┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFrank Reininghaus <[email protected]>2011-08-30 13:10:38 +0200
committerFrank Reininghaus <[email protected]>2011-08-30 18:22:56 +0200
commit9dc7cd79e7f650ccf57520888c069eef5d03a57f (patch)
tree2065e7b8ce20ee1127a03af618357258c0e6d0b8 /src
parent1e897556b035cf950a8071266d18b3e191d4c7d7 (diff)
KItemListKeyboardSearchManager improvements and unit tests
This commit implements a 'repeated key search' feature, similar to QAbstractItemView, and adds unit tests for keyboard searching.
Diffstat (limited to 'src')
-rw-r--r--src/kitemviews/kitemlistkeyboardsearchmanager.cpp17
-rw-r--r--src/kitemviews/kitemlistkeyboardsearchmanager_p.h4
-rw-r--r--src/tests/CMakeLists.txt8
-rw-r--r--src/tests/kfileitemmodeltest.cpp53
-rw-r--r--src/tests/kitemlistkeyboardsearchmanagertest.cpp121
5 files changed, 197 insertions, 6 deletions
diff --git a/src/kitemviews/kitemlistkeyboardsearchmanager.cpp b/src/kitemviews/kitemlistkeyboardsearchmanager.cpp
index 9552a7582..cefedfc2c 100644
--- a/src/kitemviews/kitemlistkeyboardsearchmanager.cpp
+++ b/src/kitemviews/kitemlistkeyboardsearchmanager.cpp
@@ -45,10 +45,23 @@ void KItemListKeyboardSearchManager::addKeys(const QString& keys)
|| !keyboardTimeWasValid || keys.isEmpty()) {
m_searchedString.clear();
}
- const bool searchFromNextItem = m_searchedString.isEmpty();
+
+ const bool newSearch = m_searchedString.isEmpty();
+
if (!keys.isEmpty()) {
m_searchedString.append(keys);
- emit changeCurrentItem(m_searchedString, searchFromNextItem);
+
+ // Special case:
+ // If the same key is pressed repeatedly, the next item matching that key should be highlighted
+ const QChar firstKey = m_searchedString.length() > 0 ? m_searchedString.at(0) : QChar();
+ 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
+ // 2. a 'repeated key' search is done.
+ const bool searchFromNextItem = newSearch || sameKey;
+
+ emit changeCurrentItem(sameKey ? firstKey : m_searchedString, searchFromNextItem);
}
m_keyboardInputTime.start();
}
diff --git a/src/kitemviews/kitemlistkeyboardsearchmanager_p.h b/src/kitemviews/kitemlistkeyboardsearchmanager_p.h
index 3441dd7bc..05de76a8c 100644
--- a/src/kitemviews/kitemlistkeyboardsearchmanager_p.h
+++ b/src/kitemviews/kitemlistkeyboardsearchmanager_p.h
@@ -29,10 +29,6 @@
#include <QString>
#include <QElapsedTimer>
-class KItemListController;
-class QInputMethodEvent;
-class QKeyEvent;
-
/**
* @brief Controls the keyboard searching ability for a KItemListController.
*
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index b35dc3b8b..d8f2250e9 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -32,6 +32,14 @@ set(kfileitemmodeltest_SRCS
kde4_add_unit_test(kfileitemmodeltest TEST ${kfileitemmodeltest_SRCS})
target_link_libraries(kfileitemmodeltest dolphinprivate ${KDE4_KIO_LIBS} ${QT_QTTEST_LIBRARY})
+# KItemListKeyboardSearchManagerTest
+set(kitemlistkeyboardsearchmanagertest_SRCS
+ kitemlistkeyboardsearchmanagertest.cpp
+ ../kitemviews/kitemlistkeyboardsearchmanager.cpp
+)
+kde4_add_unit_test(kitemlistkeyboardsearchmanagertest TEST ${kitemlistkeyboardsearchmanagertest_SRCS})
+target_link_libraries(kitemlistkeyboardsearchmanagertest ${KDE4_KIO_LIBS} ${QT_QTTEST_LIBRARY})
+
# DolphinSearchBox
if (Nepomuk_FOUND)
set(dolphinsearchboxtest_SRCS
diff --git a/src/tests/kfileitemmodeltest.cpp b/src/tests/kfileitemmodeltest.cpp
index 091632eab..f8398c578 100644
--- a/src/tests/kfileitemmodeltest.cpp
+++ b/src/tests/kfileitemmodeltest.cpp
@@ -1,5 +1,6 @@
/***************************************************************************
* Copyright (C) 2011 by Peter Penz <[email protected]> *
+ * Copyright (C) 2011 by Frank Reininghaus <[email protected]> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
@@ -49,6 +50,8 @@ private slots:
void testExpansionLevelsCompare_data();
void testExpansionLevelsCompare();
+ void testIndexForKeyboardSearch();
+
private:
bool isModelConsistent() const;
@@ -327,6 +330,56 @@ void KFileItemModelTest::testExpansionLevelsCompare()
QCOMPARE(m_model->expansionLevelsCompare(a, b), result);
}
+void KFileItemModelTest::testIndexForKeyboardSearch()
+{
+ QStringList files;
+ files << "a" << "aa" << "Image.jpg" << "Image.png" << "Text" << "Text1" << "Text2" << "Text11";
+ m_testDir->createFiles(files);
+
+ m_dirLister->openUrl(m_testDir->url());
+ QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsInserted(KItemRangeList)), DefaultTimeout));
+
+ // Search from index 0
+ QCOMPARE(m_model->indexForKeyboardSearch("a", 0), 0);
+ QCOMPARE(m_model->indexForKeyboardSearch("aa", 0), 1);
+ QCOMPARE(m_model->indexForKeyboardSearch("i", 0), 2);
+ QCOMPARE(m_model->indexForKeyboardSearch("image", 0), 2);
+ QCOMPARE(m_model->indexForKeyboardSearch("image.jpg", 0), 2);
+ QCOMPARE(m_model->indexForKeyboardSearch("image.png", 0), 3);
+ QCOMPARE(m_model->indexForKeyboardSearch("t", 0), 4);
+ QCOMPARE(m_model->indexForKeyboardSearch("text", 0), 4);
+ QCOMPARE(m_model->indexForKeyboardSearch("text1", 0), 5);
+ QCOMPARE(m_model->indexForKeyboardSearch("text2", 0), 6);
+ QCOMPARE(m_model->indexForKeyboardSearch("text11", 0), 7);
+
+ // Start a search somewhere in the middle
+ QCOMPARE(m_model->indexForKeyboardSearch("a", 1), 1);
+ QCOMPARE(m_model->indexForKeyboardSearch("i", 3), 3);
+ QCOMPARE(m_model->indexForKeyboardSearch("t", 5), 5);
+ QCOMPARE(m_model->indexForKeyboardSearch("text1", 6), 7);
+
+ // Test searches that go past the last item back to index 0
+ QCOMPARE(m_model->indexForKeyboardSearch("a", 2), 0);
+ QCOMPARE(m_model->indexForKeyboardSearch("i", 7), 2);
+ QCOMPARE(m_model->indexForKeyboardSearch("image.jpg", 3), 2);
+ QCOMPARE(m_model->indexForKeyboardSearch("text2", 7), 6);
+
+ // Test searches that yield no result
+ QCOMPARE(m_model->indexForKeyboardSearch("aaa", 0), -1);
+ QCOMPARE(m_model->indexForKeyboardSearch("b", 0), -1);
+ QCOMPARE(m_model->indexForKeyboardSearch("image.svg", 0), -1);
+ QCOMPARE(m_model->indexForKeyboardSearch("text3", 0), -1);
+ QCOMPARE(m_model->indexForKeyboardSearch("text3", 5), -1);
+
+ // Test upper case searches (note that search is case insensitive)
+ QCOMPARE(m_model->indexForKeyboardSearch("A", 0), 0);
+ QCOMPARE(m_model->indexForKeyboardSearch("aA", 0), 1);
+ QCOMPARE(m_model->indexForKeyboardSearch("TexT", 5), 5);
+ QCOMPARE(m_model->indexForKeyboardSearch("IMAGE", 4), 2);
+
+ // TODO: Maybe we should also test keyboard searches in directories which are not sorted by Name?
+}
+
bool KFileItemModelTest::isModelConsistent() const
{
for (int i = 0; i < m_model->count(); ++i) {
diff --git a/src/tests/kitemlistkeyboardsearchmanagertest.cpp b/src/tests/kitemlistkeyboardsearchmanagertest.cpp
new file mode 100644
index 000000000..be483930d
--- /dev/null
+++ b/src/tests/kitemlistkeyboardsearchmanagertest.cpp
@@ -0,0 +1,121 @@
+/***************************************************************************
+ * Copyright (C) 2011 by Frank Reininghaus <[email protected]> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#include <qtest_kde.h>
+
+#include "kitemviews/kitemlistkeyboardsearchmanager_p.h"
+
+class KItemListKeyboardSearchManagerTest : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void init();
+
+ void testBasicKeyboardSearch();
+ void testAbortedKeyboardSearch();
+ void testRepeatedKeyPress();
+
+private:
+ KItemListKeyboardSearchManager m_keyboardSearchManager;
+};
+
+void KItemListKeyboardSearchManagerTest::init()
+{
+ // Make sure that the previous search string is cleared
+ m_keyboardSearchManager.addKeys("");
+}
+
+void KItemListKeyboardSearchManagerTest::testBasicKeyboardSearch()
+{
+ QSignalSpy spy(&m_keyboardSearchManager, SIGNAL(changeCurrentItem(QString,bool)));
+
+ m_keyboardSearchManager.addKeys("f");
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.takeFirst(), QList<QVariant>() << "f" << true);
+
+ m_keyboardSearchManager.addKeys("i");
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.takeFirst(), QList<QVariant>() << "fi" << false);
+
+ m_keyboardSearchManager.addKeys("l");
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.takeFirst(), QList<QVariant>() << "fil" << false);
+
+ m_keyboardSearchManager.addKeys("e");
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.takeFirst(), QList<QVariant>() << "file" << false);
+}
+
+void KItemListKeyboardSearchManagerTest::testAbortedKeyboardSearch()
+{
+ QSignalSpy spy(&m_keyboardSearchManager, SIGNAL(changeCurrentItem(QString,bool)));
+
+ m_keyboardSearchManager.addKeys("f");
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.takeFirst(), QList<QVariant>() << "f" << true);
+
+ m_keyboardSearchManager.addKeys("i");
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.takeFirst(), QList<QVariant>() << "fi" << false);
+
+ // If the delay between two key presses is larger than QApplication::keyboardInputInterval(),
+ // a new search is started. We add a small safety margin to avoid race conditions.
+ QTest::qWait(QApplication::keyboardInputInterval() + 10);
+
+ m_keyboardSearchManager.addKeys("l");
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.takeFirst(), QList<QVariant>() << "l" << true);
+
+ m_keyboardSearchManager.addKeys("e");
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.takeFirst(), QList<QVariant>() << "le" << false);
+}
+
+void KItemListKeyboardSearchManagerTest::testRepeatedKeyPress()
+{
+ // If the same key is pressed repeatedly, the next matching item should be highlighted after
+ // each key press. To achieve, that, the manager emits the changeCurrentItem(QString,bool)
+ // signal, where
+ // 1. the string contains the repeated key only once, and
+ // 2. the bool searchFromNextItem is true.
+
+ QSignalSpy spy(&m_keyboardSearchManager, SIGNAL(changeCurrentItem(QString,bool)));
+
+ m_keyboardSearchManager.addKeys("p");
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.takeFirst(), QList<QVariant>() << "p" << true);
+
+ m_keyboardSearchManager.addKeys("p");
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.takeFirst(), QList<QVariant>() << "p" << true);
+
+ m_keyboardSearchManager.addKeys("p");
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.takeFirst(), QList<QVariant>() << "p" << true);
+
+ // Now press another key -> the search string contains all pressed keys
+ m_keyboardSearchManager.addKeys("q");
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.takeFirst(), QList<QVariant>() << "pppq" << false);
+}
+
+QTEST_KDEMAIN(KItemListKeyboardSearchManagerTest, NoGUI)
+
+#include "kitemlistkeyboardsearchmanagertest.moc"