From cf704d2db699887a6f262cd51313e6ae02e4a8bd Mon Sep 17 00:00:00 2001 From: Peter Penz Date: Sat, 10 Dec 2011 21:28:01 +0100 Subject: [PATCH] Support wildcards for the filter Thanks to Janardhan Reddy for the patch! BUG: 155986 FIXED-IN: 4.8.0 --- src/CMakeLists.txt | 1 + src/kitemviews/kfileitemmodel.cpp | 27 +++------ src/kitemviews/kfileitemmodel.h | 8 +-- src/kitemviews/kfileitemmodelfilter.cpp | 74 +++++++++++++++++++++++++ src/kitemviews/kfileitemmodelfilter_p.h | 73 ++++++++++++++++++++++++ 5 files changed, 158 insertions(+), 25 deletions(-) create mode 100644 src/kitemviews/kfileitemmodelfilter.cpp create mode 100644 src/kitemviews/kfileitemmodelfilter_p.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8a197f4086..16171ede03 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -23,6 +23,7 @@ set(dolphinprivate_LIB_SRCS kitemviews/kfileitemlistview.cpp kitemviews/kfileitemlistwidget.cpp kitemviews/kfileitemmodel.cpp + kitemviews/kfileitemmodelfilter.cpp kitemviews/kfileitemmodelrolesupdater.cpp kitemviews/kitemlistcontainer.cpp kitemviews/kitemlistcontroller.cpp diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp index df02706736..e77c42f717 100644 --- a/src/kitemviews/kfileitemmodel.cpp +++ b/src/kitemviews/kfileitemmodel.cpp @@ -40,7 +40,7 @@ KFileItemModel::KFileItemModel(KDirLister* dirLister, QObject* parent) : m_caseSensitivity(Qt::CaseInsensitive), m_itemData(), m_items(), - m_nameFilter(), + m_filter(), m_filteredItems(), m_requestRole(), m_minimumUpdateIntervalTimer(0), @@ -501,17 +501,17 @@ void KFileItemModel::setExpanded(const QSet& urls) void KFileItemModel::setNameFilter(const QString& nameFilter) { - if (m_nameFilter != nameFilter) { + if (m_filter.pattern() != nameFilter) { dispatchPendingItemsToInsert(); - m_nameFilter = nameFilter; + m_filter.setPattern(nameFilter); // Check which shown items from m_itemData must get // hidden and hence moved to m_filteredItems. KFileItemList newFilteredItems; foreach (ItemData* itemData, m_itemData) { - if (!matchesNameFilter(itemData->item)) { + if (!m_filter.matches(itemData->item)) { newFilteredItems.append(itemData->item); m_filteredItems.insert(itemData->item); } @@ -526,7 +526,7 @@ void KFileItemModel::setNameFilter(const QString& nameFilter) QMutableSetIterator it(m_filteredItems); while (it.hasNext()) { const KFileItem item = it.next(); - if (matchesNameFilter(item)) { + if (m_filter.matches(item)) { newVisibleItems.append(item); m_filteredItems.remove(item); } @@ -538,7 +538,7 @@ void KFileItemModel::setNameFilter(const QString& nameFilter) QString KFileItemModel::nameFilter() const { - return m_nameFilter; + return m_filter.pattern(); } void KFileItemModel::onGroupedSortingChanged(bool current) @@ -686,7 +686,7 @@ void KFileItemModel::slotNewItems(const KFileItemList& items) } } - if (m_nameFilter.isEmpty()) { + if (m_filter.pattern().isEmpty()) { m_pendingItemsToInsert.append(items); } else { // The name-filter is active. Hide filtered items @@ -694,7 +694,7 @@ void KFileItemModel::slotNewItems(const KFileItemList& items) // the filtered items in m_filteredItems. KFileItemList filteredItems; foreach (const KFileItem& item, items) { - if (matchesNameFilter(item)) { + if (m_filter.matches(item)) { filteredItems.append(item); } else { m_filteredItems.insert(item); @@ -1769,15 +1769,4 @@ QList > KFileItemModel::genericStringRoleGroups(const QByte return groups; } -bool KFileItemModel::matchesNameFilter(const KFileItem& item) const -{ - // TODO #1: A performance improvement would be possible by caching m_nameFilter.toLower(). - // Before adding yet-another-member it should be checked whether it brings a noticable - // improvement at all. - - // TODO #2: If the user entered a '*' use a regular expression - const QString itemText = item.text().toLower(); - return itemText.contains(m_nameFilter.toLower()); -} - #include "kfileitemmodel.moc" diff --git a/src/kitemviews/kfileitemmodel.h b/src/kitemviews/kfileitemmodel.h index 36ed37ba67..20cc75e522 100644 --- a/src/kitemviews/kfileitemmodel.h +++ b/src/kitemviews/kfileitemmodel.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -293,11 +294,6 @@ private: */ bool isChildItem(int index) const; - /** - * @return True if the given item matches with the current set name filter. - */ - bool matchesNameFilter(const KFileItem& item) const; - private: QWeakPointer m_dirLister; @@ -311,7 +307,7 @@ private: QList m_itemData; QHash m_items; // Allows O(1) access for KFileItemModel::index(const KFileItem& item) - QString m_nameFilter; + KFileItemModelFilter m_filter; QSet m_filteredItems; // Items that got hidden by KFileItemModel::setNameFilter() bool m_requestRole[RolesCount]; diff --git a/src/kitemviews/kfileitemmodelfilter.cpp b/src/kitemviews/kfileitemmodelfilter.cpp new file mode 100644 index 0000000000..dd40e2452f --- /dev/null +++ b/src/kitemviews/kfileitemmodelfilter.cpp @@ -0,0 +1,74 @@ +/*************************************************************************** + * Copyright (C) 2011 by Janardhan Reddy * + * * + * * + * 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 "kfileitemmodelfilter_p.h" + +#include +#include + +KFileItemModelFilter::KFileItemModelFilter() : + m_useRegExp(false), + m_regExp(0), + m_lowerCasePattern(), + m_pattern() +{ +} + +KFileItemModelFilter::~KFileItemModelFilter() +{ + delete m_regExp; + m_regExp = 0; +} + +void KFileItemModelFilter::setPattern(const QString& filter) +{ + m_pattern = filter; + m_lowerCasePattern = filter.toLower(); + + m_useRegExp = filter.contains('*') || + filter.contains('?') || + filter.contains('['); + if (m_useRegExp) { + if (!m_regExp) { + m_regExp = new QRegExp(); + m_regExp->setCaseSensitivity(Qt::CaseInsensitive); + m_regExp->setMinimal(false); + m_regExp->setPatternSyntax(QRegExp::WildcardUnix); + } + m_regExp->setPattern(filter); + } +} + +QString KFileItemModelFilter::pattern() const +{ + return m_pattern; +} + +bool KFileItemModelFilter::matches(const KFileItem& item) const +{ + if (m_useRegExp) { + return m_regExp->exactMatch(item.text()); + } else { + return item.text().toLower().contains(m_lowerCasePattern); + } +} diff --git a/src/kitemviews/kfileitemmodelfilter_p.h b/src/kitemviews/kfileitemmodelfilter_p.h new file mode 100644 index 0000000000..8f4595eb19 --- /dev/null +++ b/src/kitemviews/kfileitemmodelfilter_p.h @@ -0,0 +1,73 @@ +/*************************************************************************** + * Copyright (C) 2011 by Janardhan Reddy * + * * + * * + * 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 KFILEITEMMODELFILTER_H +#define KFILEITEMMODELFILTER_H + +#include +#include + +class KFileItem; +class QRegExp; + +/** + * @brief Allows to check whether an item of the KFileItemModel + * matches with a set filter-string. + * + * Currently the filter is only checked for the KFileItem::text() + * property of the KFileItem, but this might get extended in + * future. + */ +class LIBDOLPHINPRIVATE_EXPORT KFileItemModelFilter +{ + +public: + KFileItemModelFilter(); + virtual ~KFileItemModelFilter(); + + /** + * Sets the pattern that is used for a comparison with the item + * in KFileItemModelFilter::matches(). Per default the pattern + * defines a sub-string. As soon as the pattern contains at least + * a '*', '?' or '[' the pattern represents a regular expression. + */ + void setPattern(const QString& pattern); + QString pattern() const; + + /** + * @return True if the item matches with the pattern defined by + * KFileItemModelFilter::setPattern(). + */ + bool matches(const KFileItem& item) const; + +private: + bool m_useRegExp; // If true, m_regExp is used for filtering, + // otherwise m_lowerCaseFilter is used. + QRegExp* m_regExp; + QString m_lowerCasePattern; // Lowercase version of m_filter for + // faster comparison in matches(). + QString m_pattern; // Property set by setFilter(). +}; +#endif + +