Reimplement name-filtering

The filtering of items has not been implemented yet in
the KFileItemModel of the new view-engine. The patch brings back
this functionality again, but some minor issues are open:
- When filtering trees expanded directories should only get
  hidden if no child is visible
- Regular expressions are not supported yet (they have not been
  supported in Dolphin 1.x but it is now quite simple to implement).
- When filtering previews and removing the filter it might be
  possible that the preview is not shown (is most probably an
  an already existing bug in KFileItemModelRolesUpdater).

BUG: 287642
FIXED-IN: 4.8.0
This commit is contained in:
Peter Penz 2011-11-30 00:18:22 +01:00
parent 3719ce7d2a
commit 7b8fbf7374
4 changed files with 102 additions and 3 deletions

View file

@ -40,6 +40,8 @@ KFileItemModel::KFileItemModel(KDirLister* dirLister, QObject* parent) :
m_caseSensitivity(Qt::CaseInsensitive), m_caseSensitivity(Qt::CaseInsensitive),
m_itemData(), m_itemData(),
m_items(), m_items(),
m_nameFilter(),
m_filteredItems(),
m_requestRole(), m_requestRole(),
m_minimumUpdateIntervalTimer(0), m_minimumUpdateIntervalTimer(0),
m_maximumUpdateIntervalTimer(0), m_maximumUpdateIntervalTimer(0),
@ -475,6 +477,57 @@ void KFileItemModel::setExpanded(const QSet<KUrl>& urls)
} }
} }
void KFileItemModel::setNameFilter(const QString& nameFilter)
{
if (m_nameFilter != nameFilter) {
// TODO #1: Assure that expanded items only can get hidden
// if no child item is visible
// TODO #2: If the user entered a '*' use a regular expression
m_nameFilter = nameFilter;
const QString filter = nameFilter.toLower();
// 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, filter)) {
m_filteredItems.append(itemData->item);
newFilteredItems.append(itemData->item);
}
}
if (!newFilteredItems.isEmpty()) {
slotItemsDeleted(newFilteredItems);
}
// Check which hidden items from m_filteredItems should
// get visible again and hence removed from m_filteredItems.
KFileItemList newVisibleItems;
for (int i = m_filteredItems.count() - 1; i >= 0; --i) {
const KFileItem item = m_filteredItems.at(i);
if (matchesNameFilter(item, filter)) {
newVisibleItems.append(item);
m_filteredItems.removeAt(i);
}
}
if (!newVisibleItems.isEmpty()) {
slotNewItems(newVisibleItems);
dispatchPendingItemsToInsert();
}
}
}
QString KFileItemModel::nameFilter() const
{
return m_nameFilter;
}
void KFileItemModel::onGroupedSortingChanged(bool current) void KFileItemModel::onGroupedSortingChanged(bool current)
{ {
Q_UNUSED(current); Q_UNUSED(current);
@ -1654,4 +1707,10 @@ QList<QPair<int, QVariant> > KFileItemModel::genericStringRoleGroups(const QByte
return groups; return groups;
} }
bool KFileItemModel::matchesNameFilter(const KFileItem& item, const QString& nameFilter)
{
const QString itemText = item.text().toLower();
return itemText.contains(nameFilter);
}
#include "kfileitemmodel.moc" #include "kfileitemmodel.moc"

View file

@ -134,6 +134,9 @@ public:
*/ */
void setExpanded(const QSet<KUrl>& urls); void setExpanded(const QSet<KUrl>& urls);
void setNameFilter(const QString& nameFilter);
QString nameFilter() const;
signals: signals:
void loadingCompleted(); void loadingCompleted();
@ -271,6 +274,11 @@ private:
*/ */
bool isChildItem(int index) const; bool isChildItem(int index) const;
/**
* @return True if the given item matches with the name filter.
*/
static bool matchesNameFilter(const KFileItem& item, const QString& nameFilter);
private: private:
QWeakPointer<KDirLister> m_dirLister; QWeakPointer<KDirLister> m_dirLister;
@ -284,6 +292,9 @@ private:
QList<ItemData*> m_itemData; QList<ItemData*> m_itemData;
QHash<KUrl, int> m_items; // Allows O(1) access for KFileItemModel::index(const KFileItem& item) QHash<KUrl, int> m_items; // Allows O(1) access for KFileItemModel::index(const KFileItem& item)
QString m_nameFilter;
KFileItemList m_filteredItems; // Items that got hidden by KFileItemModel::setNameFilter()
bool m_requestRole[RolesCount]; bool m_requestRole[RolesCount];
QTimer* m_minimumUpdateIntervalTimer; QTimer* m_minimumUpdateIntervalTimer;

View file

@ -75,6 +75,8 @@ private slots:
void testIndexForKeyboardSearch(); void testIndexForKeyboardSearch();
void testNameFilter();
private: private:
bool isModelConsistent() const; bool isModelConsistent() const;
QStringList itemsInModel() const; QStringList itemsInModel() const;
@ -643,6 +645,34 @@ void KFileItemModelTest::testIndexForKeyboardSearch()
// TODO: Maybe we should also test keyboard searches in directories which are not sorted by Name? // TODO: Maybe we should also test keyboard searches in directories which are not sorted by Name?
} }
void KFileItemModelTest::testNameFilter()
{
QStringList files;
files << "A1" << "A2" << "Abc" << "Bcd" << "Cde";
m_testDir->createFiles(files);
m_dirLister->openUrl(m_testDir->url());
QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsInserted(KItemRangeList)), DefaultTimeout));
m_model->setNameFilter("A"); // Shows A1, A2 and Abc
QCOMPARE(m_model->count(), 3);
m_model->setNameFilter("A2"); // Shows only A2
QCOMPARE(m_model->count(), 1);
m_model->setNameFilter("A2"); // Shows only A1
QCOMPARE(m_model->count(), 1);
m_model->setNameFilter("Bc"); // Shows "Abc" and "Bcd"
QCOMPARE(m_model->count(), 2);
m_model->setNameFilter("bC"); // Shows "Abc" and "Bcd"
QCOMPARE(m_model->count(), 2);
m_model->setNameFilter(QString()); // Shows again all items
QCOMPARE(m_model->count(), 5);
}
bool KFileItemModelTest::isModelConsistent() const bool KFileItemModelTest::isModelConsistent() const
{ {
for (int i = 0; i < m_model->count(); ++i) { for (int i = 0; i < m_model->count(); ++i) {

View file

@ -459,13 +459,12 @@ void DolphinView::refresh()
void DolphinView::setNameFilter(const QString& nameFilter) void DolphinView::setNameFilter(const QString& nameFilter)
{ {
Q_UNUSED(nameFilter); fileItemModel()->setNameFilter(nameFilter);
//m_viewModeController->setNameFilter(nameFilter);
} }
QString DolphinView::nameFilter() const QString DolphinView::nameFilter() const
{ {
return QString(); //m_viewModeController->nameFilter(); return fileItemModel()->nameFilter();
} }
void DolphinView::calculateItemCount(int& fileCount, void DolphinView::calculateItemCount(int& fileCount,