File indexing completed on 2024-05-19 05:48:09

0001 /*
0002  * SPDX-FileCopyrightText: 2011 Tirtha Chatterjee <tirtha.p.chatterjee@gmail.com>
0003  *
0004  * Based on the Itemviews NG project from Trolltech Labs
0005  *
0006  * SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #include "kitemlistkeyboardsearchmanager.h"
0010 
0011 KItemListKeyboardSearchManager::KItemListKeyboardSearchManager(QObject *parent)
0012     : QObject(parent)
0013     , m_isSearchRestarted(false)
0014     , m_timeout(1000)
0015 {
0016     m_keyboardInputTime.invalidate();
0017 }
0018 
0019 KItemListKeyboardSearchManager::~KItemListKeyboardSearchManager()
0020 {
0021 }
0022 
0023 bool KItemListKeyboardSearchManager::shouldClearSearchIfInputTimeReached()
0024 {
0025     const bool keyboardTimeWasValid = m_keyboardInputTime.isValid();
0026     const qint64 keyboardInputTimeElapsed = m_keyboardInputTime.restart();
0027     return (keyboardInputTimeElapsed > m_timeout) || !keyboardTimeWasValid;
0028 }
0029 
0030 bool KItemListKeyboardSearchManager::isSearchAsYouTypeActive() const
0031 {
0032     return !m_searchedString.isEmpty() && !m_keyboardInputTime.hasExpired(m_timeout);
0033 }
0034 
0035 void KItemListKeyboardSearchManager::addKeys(const QString &keys)
0036 {
0037     if (shouldClearSearchIfInputTimeReached()) {
0038         m_searchedString.clear();
0039     }
0040 
0041     const bool newSearch = m_searchedString.isEmpty();
0042 
0043     // Do not start a new search if the user pressed Space. Only add
0044     // it to the search string if a search is in progress already.
0045     if (newSearch && keys == QLatin1Char(' ')) {
0046         return;
0047     }
0048 
0049     if (!keys.isEmpty()) {
0050         m_searchedString.append(keys);
0051 
0052         // Special case:
0053         // If the same key is pressed repeatedly, the next item matching that key should be highlighted
0054         const QChar firstKey = m_searchedString.length() > 0 ? m_searchedString.at(0) : QChar();
0055         const bool sameKey = m_searchedString.length() > 1 && m_searchedString.count(firstKey) == m_searchedString.length();
0056 
0057         // Searching for a matching item should start from the next item if either
0058         // 1. a new search is started and a search has not been restarted or
0059         // 2. a 'repeated key' search is done.
0060         const bool searchFromNextItem = (!m_isSearchRestarted && newSearch) || sameKey;
0061 
0062         // to remember not to searchFromNextItem if selection was deselected
0063         // losing keyboard search context basically
0064         m_isSearchRestarted = false;
0065 
0066         Q_EMIT changeCurrentItem(sameKey ? firstKey : m_searchedString, searchFromNextItem);
0067     }
0068     m_keyboardInputTime.start();
0069 }
0070 
0071 void KItemListKeyboardSearchManager::setTimeout(qint64 milliseconds)
0072 {
0073     m_timeout = milliseconds;
0074 }
0075 
0076 qint64 KItemListKeyboardSearchManager::timeout() const
0077 {
0078     return m_timeout;
0079 }
0080 
0081 void KItemListKeyboardSearchManager::cancelSearch()
0082 {
0083     m_isSearchRestarted = true;
0084     m_searchedString.clear();
0085 }
0086 
0087 void KItemListKeyboardSearchManager::slotCurrentChanged(int current, int previous)
0088 {
0089     Q_UNUSED(previous)
0090 
0091     if (current < 0) {
0092         // The current item has been removed. We should cancel the search.
0093         cancelSearch();
0094     }
0095 }
0096 
0097 void KItemListKeyboardSearchManager::slotSelectionChanged(const KItemSet &current, const KItemSet &previous)
0098 {
0099     if (!previous.isEmpty() && current.isEmpty() && previous.count() > 0 && current.count() == 0) {
0100         // The selection has been emptied. We should cancel the search.
0101         cancelSearch();
0102     }
0103 }
0104 
0105 #include "moc_kitemlistkeyboardsearchmanager.cpp"