]> cloud.milkyroute.net Git - dolphin.git/commitdiff
Remove items from m_filteredItems if their parent is deleted
authorFrank Reininghaus <frank78ac@googlemail.com>
Mon, 18 Feb 2013 22:49:33 +0000 (23:49 +0100)
committerFrank Reininghaus <frank78ac@googlemail.com>
Mon, 18 Feb 2013 22:50:38 +0000 (23:50 +0100)
Fixes the problem that filtered children of expanded deleted folders
reappear if the filter is cleared.

BUG: 315210
FIXED-IN: 4.10.1
REVIEW: 108976

src/kitemviews/kfileitemmodel.cpp
src/tests/kfileitemmodeltest.cpp

index 6c015db372cdb1df85995e56c3d79560cc21b97a..d4c08a52e07ea9f0dee6669245adb138b6cf67c6 100644 (file)
@@ -795,6 +795,33 @@ void KFileItemModel::slotItemsDeleted(const KFileItemList& items)
         foreach (const KFileItem& item, itemsToRemove) {
             m_filteredItems.remove(item);
         }
+
+        if (m_requestRole[ExpandedParentsCountRole] && m_expandedParentsCountRoot >= 0) {
+            // Remove all filtered children of deleted items. First, we put the
+            // deleted URLs into a set to provide fast lookup while iterating
+            // over m_filteredItems and prevent quadratic complexity if there
+            // are N removed items and N filtered items.
+            QSet<KUrl> urlsToRemove;
+            urlsToRemove.reserve(itemsToRemove.count());
+            foreach (const KFileItem& item, itemsToRemove) {
+                KUrl url = item.url();
+                url.adjustPath(KUrl::RemoveTrailingSlash);
+                urlsToRemove.insert(url);
+            }
+
+            QSet<KFileItem>::iterator it = m_filteredItems.begin();
+            while (it != m_filteredItems.end()) {
+                const KUrl url = it->url();
+                KUrl parentUrl = url.upUrl();
+                parentUrl.adjustPath(KUrl::RemoveTrailingSlash);
+
+                if (urlsToRemove.contains(parentUrl)) {
+                    it = m_filteredItems.erase(it);
+                } else {
+                    ++it;
+                }
+            }
+        }
     }
 
     removeItems(itemsToRemove);
index 719459c6f7acc08a1642f52aef782f9a46ef4ab7..b76f4bee97319d379d3ca02301223395a7c5d591 100644 (file)
@@ -76,6 +76,7 @@ private slots:
     void testNameFilter();
     void testEmptyPath();
     void testRemoveHiddenItems();
+    void removeParentOfHiddenItems();
 
 private:
     bool isModelConsistent() const;
@@ -849,6 +850,56 @@ void KFileItemModelTest::testRemoveHiddenItems()
     m_model->setShowHiddenFiles(false);
 }
 
+/**
+ * Verify that filtered items are removed when their parent is deleted.
+ */
+void KFileItemModelTest::removeParentOfHiddenItems()
+{
+    QSet<QByteArray> modelRoles = m_model->roles();
+    modelRoles << "isExpanded" << "isExpandable" << "expandedParentsCount";
+    m_model->setRoles(modelRoles);
+
+    QStringList files;
+    files << "a/1" << "a/b/1" << "a/b/c/1" << "a/b/c/d/1";
+    m_testDir->createFiles(files);
+
+    m_model->loadDirectory(m_testDir->url());
+    QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsInserted(KItemRangeList)), DefaultTimeout));
+    QCOMPARE(m_model->count(), 1); // Only "a/"
+
+    // Expand "a/".
+    m_model->setExpanded(0, true);
+    QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsInserted(KItemRangeList)), DefaultTimeout));
+    QCOMPARE(m_model->count(), 3); // 3 items: "a/", "a/b/", "a/1"
+
+    // Expand "a/b/".
+    m_model->setExpanded(1, true);
+    QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsInserted(KItemRangeList)), DefaultTimeout));
+    QCOMPARE(m_model->count(), 5); // 5 items: "a/", "a/b/", "a/b/c", "a/b/1", "a/1"
+
+    // Expand "a/b/c/".
+    m_model->setExpanded(2, true);
+    QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsInserted(KItemRangeList)), DefaultTimeout));
+    QCOMPARE(m_model->count(), 7); // 7 items: "a/", "a/b/", "a/b/c", "a/b/c/d/", "a/b/c/1", "a/b/1", "a/1"
+
+    // Set a name filter that matches nothing -> only the expanded folders remain.
+    m_model->setNameFilter("xyz");
+    QCOMPARE(m_model->count(), 3);
+    QCOMPARE(itemsInModel(), QStringList() << "a" << "b" << "c");
+
+    // Simulate the deletion of the directory "a/b/".
+    QSignalSpy spyItemsRemoved(m_model, SIGNAL(itemsRemoved(KItemRangeList)));
+    m_model->slotItemsDeleted(KFileItemList() << m_model->fileItem(1));
+    QCOMPARE(spyItemsRemoved.count(), 1);
+    QCOMPARE(m_model->count(), 1);
+    QCOMPARE(itemsInModel(), QStringList() << "a");
+
+    // Remove the filter -> only the file "a/1" should appear.
+    m_model->setNameFilter(QString());
+    QCOMPARE(m_model->count(), 2);
+    QCOMPARE(itemsInModel(), QStringList() << "a" << "1");
+}
+
 bool KFileItemModelTest::isModelConsistent() const
 {
     if (m_model->m_items.count() != m_model->m_itemData.count()) {