From 7b8fbf737496e44e7676a437f000377d737dfd9c Mon Sep 17 00:00:00 2001 From: Peter Penz Date: Wed, 30 Nov 2011 00:18:22 +0100 Subject: [PATCH] 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 --- src/kitemviews/kfileitemmodel.cpp | 59 +++++++++++++++++++++++++++++++ src/kitemviews/kfileitemmodel.h | 11 ++++++ src/tests/kfileitemmodeltest.cpp | 30 ++++++++++++++++ src/views/dolphinview.cpp | 5 ++- 4 files changed, 102 insertions(+), 3 deletions(-) diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp index d1e0fc6f1..bd83bf621 100644 --- a/src/kitemviews/kfileitemmodel.cpp +++ b/src/kitemviews/kfileitemmodel.cpp @@ -40,6 +40,8 @@ KFileItemModel::KFileItemModel(KDirLister* dirLister, QObject* parent) : m_caseSensitivity(Qt::CaseInsensitive), m_itemData(), m_items(), + m_nameFilter(), + m_filteredItems(), m_requestRole(), m_minimumUpdateIntervalTimer(0), m_maximumUpdateIntervalTimer(0), @@ -475,6 +477,57 @@ void KFileItemModel::setExpanded(const QSet& 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) { Q_UNUSED(current); @@ -1654,4 +1707,10 @@ QList > KFileItemModel::genericStringRoleGroups(const QByte return groups; } +bool KFileItemModel::matchesNameFilter(const KFileItem& item, const QString& nameFilter) +{ + const QString itemText = item.text().toLower(); + return itemText.contains(nameFilter); +} + #include "kfileitemmodel.moc" diff --git a/src/kitemviews/kfileitemmodel.h b/src/kitemviews/kfileitemmodel.h index 8cbcb1216..a83d57ba8 100644 --- a/src/kitemviews/kfileitemmodel.h +++ b/src/kitemviews/kfileitemmodel.h @@ -134,6 +134,9 @@ public: */ void setExpanded(const QSet& urls); + void setNameFilter(const QString& nameFilter); + QString nameFilter() const; + signals: void loadingCompleted(); @@ -271,6 +274,11 @@ private: */ 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: QWeakPointer m_dirLister; @@ -284,6 +292,9 @@ private: QList m_itemData; QHash 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]; QTimer* m_minimumUpdateIntervalTimer; diff --git a/src/tests/kfileitemmodeltest.cpp b/src/tests/kfileitemmodeltest.cpp index 59e817fff..23b899136 100644 --- a/src/tests/kfileitemmodeltest.cpp +++ b/src/tests/kfileitemmodeltest.cpp @@ -75,6 +75,8 @@ private slots: void testIndexForKeyboardSearch(); + void testNameFilter(); + private: bool isModelConsistent() 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? } +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 { for (int i = 0; i < m_model->count(); ++i) { diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp index 829e1a302..857aae395 100644 --- a/src/views/dolphinview.cpp +++ b/src/views/dolphinview.cpp @@ -459,13 +459,12 @@ void DolphinView::refresh() void DolphinView::setNameFilter(const QString& nameFilter) { - Q_UNUSED(nameFilter); - //m_viewModeController->setNameFilter(nameFilter); + fileItemModel()->setNameFilter(nameFilter); } QString DolphinView::nameFilter() const { - return QString(); //m_viewModeController->nameFilter(); + return fileItemModel()->nameFilter(); } void DolphinView::calculateItemCount(int& fileCount, -- 2.47.3