FolderListModel: pessimize change signals when the filter changes
authorShawn Rutledge <shawn.rutledge@digia.com>
Tue, 4 Mar 2014 15:05:50 +0000 (16:05 +0100)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Tue, 18 Mar 2014 09:18:57 +0000 (10:18 +0100)
FileInfoThread doesn't have separate signals for insertions, deletions
and updates, so QQuickFolderListModel shouldn't make an assumption
that if the list got bigger, an insertion was the only thing that
happened.

Task-number: QTBUG-36576
Change-Id: Ibb02d64e1645dd6df231d28a93e424aaad0effff
Reviewed-by: Alan Alpert <aalpert@blackberry.com>
src/imports/folderlistmodel/qquickfolderlistmodel.cpp
tests/auto/qml/qquickfolderlistmodel/data/resetfiltering/test1.html [new file with mode: 0644]
tests/auto/qml/qquickfolderlistmodel/data/resetfiltering/test2.html [new file with mode: 0644]
tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp

index 5ed38db3d723fe71d363adaa22b2d0cc46239c3f..5dc4332d69eb6ddb414abafd01927b033b5c6f9b 100644 (file)
@@ -158,35 +158,28 @@ void QQuickFolderListModelPrivate::_q_directoryUpdated(const QString &directory,
     Q_UNUSED(directory);
 
     QModelIndex parent;
-    if (data.size() > list.size()) {
-        //File(s) removed. Since I do not know how many
-        //or where I need to update the whole list from the first item.
-        data = list;
-        q->beginRemoveRows(parent, fromIndex, toIndex);
-        q->endRemoveRows();
-        if (list.size() > 0) {
-            q->beginInsertRows(parent, fromIndex, list.size()-1);
-            q->endInsertRows();
-        }
-        emit q->rowCountChanged();
-    } else if (data.size() < list.size()) {
-        //qDebug() << "File added. FromIndex: " << fromIndex << " toIndex: " << toIndex << " list size: " << list.size();
-        //File(s) added. Calculate how many and insert
-        //from the first changed one.
-        toIndex = fromIndex + (list.size() - data.size()-1);
-        q->beginInsertRows(parent, fromIndex, toIndex);
-        q->endInsertRows();
-        data = list;
-        emit q->rowCountChanged();
+    if (data.size() == list.size()) {
         QModelIndex modelIndexFrom = q->createIndex(fromIndex, 0);
         QModelIndex modelIndexTo = q->createIndex(toIndex, 0);
+        data = list;
         emit q->dataChanged(modelIndexFrom, modelIndexTo);
     } else {
-        //qDebug() << "File has been updated";
-        QModelIndex modelIndexFrom = q->createIndex(fromIndex, 0);
-        QModelIndex modelIndexTo = q->createIndex(toIndex, 0);
+        // File(s) inserted or removed. Since I do not know how many
+        // or where, I need to update the whole list from the first item.
+        // This is a little pessimistic, but optimizing it would require
+        // more information in the signal from FileInfoThread.
+        if (data.size() > 0) {
+            q->beginRemoveRows(parent, 0, data.size() - 1);
+            q->endRemoveRows();
+        }
         data = list;
-        emit q->dataChanged(modelIndexFrom, modelIndexTo);
+        if (list.size() > 0) {
+            if (toIndex > list.size() - 1)
+                toIndex = list.size() - 1;
+            q->beginInsertRows(parent, 0, data.size() - 1);
+            q->endInsertRows();
+        }
+        emit q->rowCountChanged();
     }
 }
 
diff --git a/tests/auto/qml/qquickfolderlistmodel/data/resetfiltering/test1.html b/tests/auto/qml/qquickfolderlistmodel/data/resetfiltering/test1.html
new file mode 100644 (file)
index 0000000..4da4639
--- /dev/null
@@ -0,0 +1 @@
+<P>This file contains some HTML.</P>
diff --git a/tests/auto/qml/qquickfolderlistmodel/data/resetfiltering/test2.html b/tests/auto/qml/qquickfolderlistmodel/data/resetfiltering/test2.html
new file mode 100644 (file)
index 0000000..4da4639
--- /dev/null
@@ -0,0 +1 @@
+<P>This file contains some HTML.</P>
index a6e6345223881134c1c912c973d28dcf9e7d36c8..4296ae4f094c1e1bb1c09fef4dfa591d0defd16f 100644 (file)
@@ -73,6 +73,7 @@ private slots:
     void basicProperties();
     void showFiles();
     void resetFiltering();
+    void nameFilters();
     void refresh();
     void cdUp();
 #ifdef Q_OS_WIN32
@@ -169,26 +170,50 @@ void tst_qquickfolderlistmodel::resetFiltering()
     QAbstractListModel *flm = qobject_cast<QAbstractListModel*>(component.create());
     QVERIFY(flm != 0);
 
+    flm->setProperty("folder", testFileUrl("resetfiltering"));
+    // _q_directoryUpdated may be triggered if model was empty before, but there won't be a rowsRemoved signal
+    QTRY_COMPARE(flm->property("count").toInt(),3); // all files visible
+
+    flm->setProperty("folder", testFileUrl("resetfiltering/innerdir"));
+    // _q_directoryChanged is triggered so it's a total model refresh
+    QTRY_COMPARE(flm->property("count").toInt(),1); // should just be "test2.txt" visible
+
+    flm->setProperty("folder", testFileUrl("resetfiltering"));
+    // _q_directoryChanged is triggered so it's a total model refresh
+    QTRY_COMPARE(flm->property("count").toInt(),3); // all files visible
+}
+
+void tst_qquickfolderlistmodel::nameFilters()
+{
+    // see QTBUG-36576
+    QQmlComponent component(&engine, testFileUrl("resetFiltering.qml"));
+    checkNoErrors(component);
+
+    QAbstractListModel *flm = qobject_cast<QAbstractListModel*>(component.create());
+    QVERIFY(flm != 0);
+
     connect(flm, SIGNAL(rowsRemoved(QModelIndex,int,int)),
             this, SLOT(removed(QModelIndex,int,int)));
 
+    QTRY_VERIFY(flm->rowCount() > 0);
     flm->setProperty("folder", testFileUrl("resetfiltering"));
-    QTRY_COMPARE(flm->property("count").toInt(),1); // should just be "test.txt" visible
+    QTRY_COMPARE(flm->property("count").toInt(),3); // all files visible
+
     int count = flm->rowCount();
+    flm->setProperty("nameFilters", QStringList() << "*.txt");
+    // _q_directoryUpdated triggered with range 0:1
+    QTRY_COMPARE(flm->property("count").toInt(),1);
+    QCOMPARE(flm->data(flm->index(0),FileNameRole), QVariant("test.txt"));
     QCOMPARE(removeStart, 0);
     QCOMPARE(removeEnd, count-1);
 
-    flm->setProperty("folder", testFileUrl("resetfiltering/innerdir"));
-    QTRY_COMPARE(flm->property("count").toInt(),1); // should just be "test2.txt" visible
-    count = flm->rowCount();
-    QCOMPARE(removeStart, 0);
-    QCOMPARE(removeEnd, count-1);
+    flm->setProperty("nameFilters", QStringList() << "*.html");
+    QTRY_COMPARE(flm->property("count").toInt(),2);
+    QCOMPARE(flm->data(flm->index(0),FileNameRole), QVariant("test1.html"));
+    QCOMPARE(flm->data(flm->index(1),FileNameRole), QVariant("test2.html"));
 
-    flm->setProperty("folder", testFileUrl("resetfiltering"));
-    QTRY_COMPARE(flm->property("count").toInt(),1); // should just be "test.txt" visible
-    count = flm->rowCount();
-    QCOMPARE(removeStart, 0);
-    QCOMPARE(removeEnd, count-1);
+    flm->setProperty("nameFilters", QStringList());
+    QTRY_COMPARE(flm->property("count").toInt(),3); // all files visible
 }
 
 void tst_qquickfolderlistmodel::refresh()