From afca8efa2601d9566c8d34d7b67dfb5abc729956 Mon Sep 17 00:00:00 2001 From: Tirtha Chatterjee Date: Mon, 29 Aug 2011 04:12:05 +0530 Subject: [PATCH] Added support for highlighting items by typing their name on the keyboard. --- src/CMakeLists.txt | 1 + src/kitemviews/kfileitemmodel.cpp | 18 +++++ src/kitemviews/kfileitemmodel.h | 4 + src/kitemviews/kitemlistcontroller.cpp | 28 ++++++- src/kitemviews/kitemlistcontroller.h | 4 + .../kitemlistkeyboardsearchmanager.cpp | 54 ++++++++++++++ .../kitemlistkeyboardsearchmanager_p.h | 73 +++++++++++++++++++ src/kitemviews/kitemmodelbase.cpp | 5 ++ src/kitemviews/kitemmodelbase.h | 7 ++ 9 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 src/kitemviews/kitemlistkeyboardsearchmanager.cpp create mode 100644 src/kitemviews/kitemlistkeyboardsearchmanager_p.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 31d3f8928..b443aa773 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -25,6 +25,7 @@ set(dolphinprivate_LIB_SRCS kitemviews/kitemlistcontainer.cpp kitemviews/kitemlistcontroller.cpp kitemviews/kitemlistgroupheader.cpp + kitemviews/kitemlistkeyboardsearchmanager.cpp kitemviews/kitemlistrubberband.cpp kitemviews/kitemlistselectionmanager.cpp kitemviews/kitemlistsizehintresolver.cpp diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp index f36ab8380..c2f49f705 100644 --- a/src/kitemviews/kfileitemmodel.cpp +++ b/src/kitemviews/kfileitemmodel.cpp @@ -124,6 +124,24 @@ bool KFileItemModel::setData(int index, const QHash& value return false; } +int KFileItemModel::indexForKeyboardSearch(const QString& text, int startFromIndex) const +{ + startFromIndex = qMax(0, startFromIndex); + for (int i = startFromIndex; i < count(); i++) { + if (data(i)["name"].toString().startsWith(text, Qt::CaseInsensitive)) { + kDebug() << data(i)["name"].toString(); + return i; + } + } + for (int i = 0; i < startFromIndex; i++) { + if (data(i)["name"].toString().startsWith(text, Qt::CaseInsensitive)) { + kDebug() << data(i)["name"].toString(); + return i; + } + } + return -1; +} + bool KFileItemModel::supportsGrouping() const { return true; diff --git a/src/kitemviews/kfileitemmodel.h b/src/kitemviews/kfileitemmodel.h index 654c7dbeb..0fecbcf3f 100644 --- a/src/kitemviews/kfileitemmodel.h +++ b/src/kitemviews/kfileitemmodel.h @@ -54,6 +54,10 @@ public: virtual QHash data(int index) const; virtual bool setData(int index, const QHash &values); + /** + * @reimp + */ + virtual int indexForKeyboardSearch(const QString& text, int startFromIndex = 0) const; /** * @return True * @reimp diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp index c0875ce39..207535ce1 100644 --- a/src/kitemviews/kitemlistcontroller.cpp +++ b/src/kitemviews/kitemlistcontroller.cpp @@ -25,6 +25,7 @@ #include "kitemlistview.h" #include "kitemlistrubberband_p.h" #include "kitemlistselectionmanager.h" +#include "kitemlistkeyboardsearchmanager_p.h" #include #include @@ -42,10 +43,12 @@ KItemListController::KItemListController(QObject* parent) : m_model(0), m_view(0), m_selectionManager(new KItemListSelectionManager(this)), + m_keyboardManager(new KItemListKeyboardSearchManager(this)), m_pressedIndex(-1), m_pressedMousePos(), m_oldSelection() { + connect(m_keyboardManager, SIGNAL(requestItemActivation(QString,bool)), this, SLOT(slotKeyboardActivationRequested(QString,bool))); } KItemListController::~KItemListController() @@ -202,10 +205,12 @@ bool KItemListController::keyPressEvent(QKeyEvent* event) m_selectionManager->endAnchoredSelection(); m_selectionManager->setSelected(index, 1, KItemListSelectionManager::Toggle); m_selectionManager->beginAnchoredSelection(index); + break; } default: - break; + m_keyboardManager->addKeys(event->text()); + return false; } if (m_selectionManager->currentItem() != index) { @@ -227,6 +232,27 @@ bool KItemListController::keyPressEvent(QKeyEvent* event) return true; } +void KItemListController::slotKeyboardActivationRequested(const QString& text, bool searchFromNextItem) +{ + if (!m_model) { + return; + } + const int currentIndex = m_selectionManager->currentItem(); + int index; + if (searchFromNextItem) { + index = m_model->indexForKeyboardSearch(text, (currentIndex + 1) % m_model->count()); + } + else { + index = m_model->indexForKeyboardSearch(text, currentIndex); + } + if (index >= 0) { + m_selectionManager->setCurrentItem(index); + m_selectionManager->clearSelection(); + m_selectionManager->setSelected(index, 1); + m_selectionManager->beginAnchoredSelection(index); + } +} + bool KItemListController::inputMethodEvent(QInputMethodEvent* event) { Q_UNUSED(event); diff --git a/src/kitemviews/kitemlistcontroller.h b/src/kitemviews/kitemlistcontroller.h index 134e11673..04d49854e 100644 --- a/src/kitemviews/kitemlistcontroller.h +++ b/src/kitemviews/kitemlistcontroller.h @@ -31,6 +31,7 @@ #include class KItemModelBase; +class KItemListKeyboardSearchManager; class KItemListSelectionManager; class KItemListView; class QGraphicsSceneHoverEvent; @@ -132,6 +133,8 @@ private slots: */ void slotRubberBandChanged(); + void slotKeyboardActivationRequested(const QString& text, bool searchFromNextItem); + private: /** * Creates a QDrag object to start a drag-operation. @@ -146,6 +149,7 @@ private: KItemModelBase* m_model; KItemListView* m_view; KItemListSelectionManager* m_selectionManager; + KItemListKeyboardSearchManager* m_keyboardManager; int m_pressedIndex; QPointF m_pressedMousePos; diff --git a/src/kitemviews/kitemlistkeyboardsearchmanager.cpp b/src/kitemviews/kitemlistkeyboardsearchmanager.cpp new file mode 100644 index 000000000..34633d65c --- /dev/null +++ b/src/kitemviews/kitemlistkeyboardsearchmanager.cpp @@ -0,0 +1,54 @@ +/*************************************************************************** + * Copyright (C) 2011 by Tirtha Chatterjee * + * * + * Based on the Itemviews NG project from Trolltech Labs: * + * http://qt.gitorious.org/qt-labs/itemviews-ng * + * * + * 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 "kitemlistkeyboardsearchmanager_p.h" + +#include +#include + +#include + +KItemListKeyboardSearchManager::KItemListKeyboardSearchManager(QObject* parent) : + QObject(parent) +{ + m_keyboardInputTime.invalidate(); +} + +KItemListKeyboardSearchManager::~KItemListKeyboardSearchManager() +{ +} + +void KItemListKeyboardSearchManager::addKeys(const QString& keys) +{ + const bool keyboardTimeWasValid = m_keyboardInputTime.isValid(); + const qint64 keyboardInputTimeElapsed = m_keyboardInputTime.restart(); + if (keyboardInputTimeElapsed > QApplication::keyboardInputInterval() + || !keyboardTimeWasValid || keys.isEmpty()) { + m_searchedString.clear(); + } + const bool searchFromNextItem = m_searchedString.isEmpty(); + if (!keys.isEmpty()) { + m_searchedString.append(keys); + emit requestItemActivation(m_searchedString, searchFromNextItem); + } + m_keyboardInputTime.start(); +} diff --git a/src/kitemviews/kitemlistkeyboardsearchmanager_p.h b/src/kitemviews/kitemlistkeyboardsearchmanager_p.h new file mode 100644 index 000000000..cf41f3bed --- /dev/null +++ b/src/kitemviews/kitemlistkeyboardsearchmanager_p.h @@ -0,0 +1,73 @@ +/*************************************************************************** + * Copyright (C) 2011 by Tirtha Chatterjee * + * * + * Based on the Itemviews NG project from Trolltech Labs: * + * http://qt.gitorious.org/qt-labs/itemviews-ng * + * * + * 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 * + ***************************************************************************/ + +#ifndef KITEMLISTKEYBOARDMANAGER_H +#define KITEMLISTKEYBOARDMANAGER_H + +#include + +#include +#include +#include + +class KItemListController; +class QInputMethodEvent; +class QKeyEvent; + +/** + * @brief Controls the keyboard searching ability for a KItemListController. + * + * @see KItemListController + * @see KItemModelBase + */ +class LIBDOLPHINPRIVATE_EXPORT KItemListKeyboardSearchManager : public QObject +{ + Q_OBJECT + +public: + + KItemListKeyboardSearchManager(QObject* parent = 0); + virtual ~KItemListKeyboardSearchManager(); + + /** + * Add \a keys to the text buffer used for searching. + */ + void addKeys(const QString& keys); + +signals: + + /** + * Is emitted when a text is to be searched. + * @param searchFromNextItem if true, start searching + * from item next to current item. Otherwise, search from + * current item. + */ + void requestItemActivation(const QString& string, bool searchFromNextItem); + +private: + QString m_searchedString; + QElapsedTimer m_keyboardInputTime; +}; + +#endif + + diff --git a/src/kitemviews/kitemmodelbase.cpp b/src/kitemviews/kitemmodelbase.cpp index fc604e729..69f62bcb0 100644 --- a/src/kitemviews/kitemmodelbase.cpp +++ b/src/kitemviews/kitemmodelbase.cpp @@ -109,6 +109,11 @@ QMimeData* KItemModelBase::createMimeData(const QSet& indexes) const return 0; } +int KItemModelBase::indexForKeyboardSearch(const QString& text, int startFromIndex) const +{ + return -1; +} + void KItemModelBase::onGroupRoleChanged(const QByteArray& current, const QByteArray& previous) { Q_UNUSED(current); diff --git a/src/kitemviews/kitemmodelbase.h b/src/kitemviews/kitemmodelbase.h index 467046959..c4e046402 100644 --- a/src/kitemviews/kitemmodelbase.h +++ b/src/kitemviews/kitemmodelbase.h @@ -116,6 +116,13 @@ public: */ virtual QMimeData* createMimeData(const QSet& indexes) const; + /** + * @return Reimplement this to return the index for the first item + * beginning with string typed in through the keyboard, -1 if not found. + * @param text the text which has been typed in through the keyboard + * @param startFromIndex the index from which to start searching from + */ + virtual int indexForKeyboardSearch(const QString& text, int startFromIndex = 0) const; signals: /** * Is emitted if one or more items have been inserted. Each item-range consists -- 2.47.3