Support wildcards for the filter

Thanks to Janardhan Reddy for the patch!

BUG: 155986
FIXED-IN: 4.8.0
This commit is contained in:
Peter Penz 2011-12-10 21:28:01 +01:00
parent 780e42533a
commit cf704d2db6
5 changed files with 158 additions and 25 deletions

View file

@ -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

View file

@ -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<KUrl>& 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<KFileItem> 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<QPair<int, QVariant> > 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"

View file

@ -23,6 +23,7 @@
#include <libdolphin_export.h>
#include <KFileItemList>
#include <KUrl>
#include <kitemviews/kfileitemmodelfilter_p.h>
#include <kitemviews/kitemmodelbase.h>
#include <QHash>
@ -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<KDirLister> m_dirLister;
@ -311,7 +307,7 @@ private:
QList<ItemData*> m_itemData;
QHash<KUrl, int> m_items; // Allows O(1) access for KFileItemModel::index(const KFileItem& item)
QString m_nameFilter;
KFileItemModelFilter m_filter;
QSet<KFileItem> m_filteredItems; // Items that got hidden by KFileItemModel::setNameFilter()
bool m_requestRole[RolesCount];

View file

@ -0,0 +1,74 @@
/***************************************************************************
* Copyright (C) 2011 by Janardhan Reddy *
* <annapareddyjanardhanreddy@gmail.com> *
* *
* 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 <KFileItem>
#include <QRegExp>
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);
}
}

View file

@ -0,0 +1,73 @@
/***************************************************************************
* Copyright (C) 2011 by Janardhan Reddy *
* <annapareddyjanardhanreddy@gmail.com> *
* *
* 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 <libdolphin_export.h>
#include <QString>
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