Ensure that showDirs is respected in FolderListModel
authorChris Adams <christopher.adams@nokia.com>
Mon, 23 May 2011 05:38:53 +0000 (15:38 +1000)
committerChris Adams <christopher.adams@nokia.com>
Mon, 23 May 2011 07:07:57 +0000 (17:07 +1000)
Calling index() on a QDirModel can modify the filters applied.
This patch to FolderListModel ensures that filtering is reset if
required, so that programmatically selecting a subfolder in a
folder does not cause that subfolder to become visible if showDirs
is set to false.

Task-number: QTBUG-17837
Reviewed-by: Martin Jones
Change-Id: I449321d5170ecedf2a0cb36483d50020305a26dd

src/imports/folderlistmodel/qdeclarativefolderlistmodel.cpp
src/imports/folderlistmodel/qdeclarativefolderlistmodel.h
tests/auto/declarative/qdeclarativefolderlistmodel/data/resetFiltering.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativefolderlistmodel/data/resetfiltering/innerdir/test2.txt [new file with mode: 0644]
tests/auto/declarative/qdeclarativefolderlistmodel/data/resetfiltering/test.txt [new file with mode: 0644]
tests/auto/declarative/qdeclarativefolderlistmodel/tst_qdeclarativefolderlistmodel.cpp

index 9fe01bf..8a91667 100644 (file)
@@ -53,7 +53,7 @@ class QDeclarativeFolderListModelPrivate
 {
 public:
     QDeclarativeFolderListModelPrivate()
-        : sortField(QDeclarativeFolderListModel::Name), sortReversed(false), count(0) {
+        : sortField(QDeclarativeFolderListModel::Name), sortReversed(false), count(0), showDirs(true), showDots(false), showOnlyReadable(false), insideRefresh(false) {
         nameFilters << QLatin1String("*");
     }
 
@@ -90,6 +90,10 @@ public:
     QDeclarativeFolderListModel::SortField sortField;
     bool sortReversed;
     int count;
+    bool showDirs;
+    bool showDots;
+    bool showOnlyReadable;
+    bool insideRefresh;
 };
 
 /*!
@@ -222,15 +226,39 @@ void QDeclarativeFolderListModel::setFolder(const QUrl &folder)
 {
     if (folder == d->folder)
         return;
-    QModelIndex index = d->model.index(folder.toLocalFile());
-    if ((index.isValid() && d->model.isDir(index)) || folder.toLocalFile().isEmpty()) {
 
+    QModelIndex index = d->model.index(folder.toLocalFile()); // This can modify the filtering rules.
+    if ((index.isValid() && d->model.isDir(index)) || folder.toLocalFile().isEmpty()) {
         d->folder = folder;
-        QMetaObject::invokeMethod(this, "refresh", Qt::QueuedConnection);
+        QMetaObject::invokeMethod(this, "resetFiltering", Qt::QueuedConnection); // resetFiltering will invoke refresh().
         emit folderChanged();
     }
 }
 
+void QDeclarativeFolderListModel::resetFiltering()
+{
+    // ensure that we reset the filtering rules, because the QDirModel::index()
+    // function isn't quite as const as it claims to be.
+    QDir::Filters filt = d->model.filter();
+
+    if (d->showDirs)
+        filt |= (QDir::AllDirs | QDir::Drives);
+    else
+        filt &= ~(QDir::AllDirs | QDir::Drives);
+
+    if (d->showDots)
+        filt &= ~QDir::NoDotAndDotDot;
+    else
+        filt |= QDir::NoDotAndDotDot;
+
+    if (d->showOnlyReadable)
+        filt |= QDir::Readable;
+    else
+        filt &= ~QDir::Readable;
+
+    d->model.setFilter(filt); // this causes a refresh().
+}
+
 /*!
     \qmlproperty url FolderListModel::parentFolder
 
@@ -363,12 +391,17 @@ bool QDeclarativeFolderListModel::isFolder(int index) const
 
 void QDeclarativeFolderListModel::refresh()
 {
+    if (d->insideRefresh)
+        return;
+    d->insideRefresh = true;
+
     d->folderIndex = QModelIndex();
     if (d->count) {
         emit beginRemoveRows(QModelIndex(), 0, d->count-1);
         d->count = 0;
         emit endRemoveRows();
     }
+
     d->folderIndex = d->model.index(d->folder.toLocalFile());
     int newcount = d->model.rowCount(d->folderIndex);
     if (newcount) {
@@ -376,6 +409,8 @@ void QDeclarativeFolderListModel::refresh()
         d->count = newcount;
         emit endInsertRows();
     }
+
+    d->insideRefresh = false; // finished refreshing.
 }
 
 void QDeclarativeFolderListModel::inserted(const QModelIndex &index, int start, int end)
@@ -423,10 +458,13 @@ void  QDeclarativeFolderListModel::setShowDirs(bool on)
 {
     if (!(d->model.filter() & QDir::AllDirs) == !on)
         return;
-    if (on)
+    if (on) {
+        d->showDirs = true;
         d->model.setFilter(d->model.filter() | QDir::AllDirs | QDir::Drives);
-    else
+    } else {
+        d->showDirs = false;
         d->model.setFilter(d->model.filter() & ~(QDir::AllDirs | QDir::Drives));
+    }
 }
 
 /*!
@@ -448,10 +486,13 @@ void  QDeclarativeFolderListModel::setShowDotAndDotDot(bool on)
 {
     if (!(d->model.filter() & QDir::NoDotAndDotDot) == on)
         return;
-    if (on)
+    if (on) {
+        d->showDots = true;
         d->model.setFilter(d->model.filter() & ~QDir::NoDotAndDotDot);
-    else
+    } else {
+        d->showDots = false;
         d->model.setFilter(d->model.filter() | QDir::NoDotAndDotDot);
+    }
 }
 
 /*!
@@ -473,10 +514,13 @@ void QDeclarativeFolderListModel::setShowOnlyReadable(bool on)
 {
     if (!(d->model.filter() & QDir::Readable) == !on)
         return;
-    if (on)
+    if (on) {
+        d->showOnlyReadable = true;
         d->model.setFilter(d->model.filter() | QDir::Readable);
-    else
+    } else {
+        d->showOnlyReadable = false;
         d->model.setFilter(d->model.filter() & ~QDir::Readable);
+    }
 }
 
 //![code]
index 17dc84c..b0d91e4 100644 (file)
@@ -136,6 +136,7 @@ Q_SIGNALS:
 //![class end]
 private Q_SLOTS:
     void refresh();
+    void resetFiltering();
     void inserted(const QModelIndex &index, int start, int end);
     void removed(const QModelIndex &index, int start, int end);
     void handleDataChanged(const QModelIndex &start, const QModelIndex &end);
diff --git a/tests/auto/declarative/qdeclarativefolderlistmodel/data/resetFiltering.qml b/tests/auto/declarative/qdeclarativefolderlistmodel/data/resetFiltering.qml
new file mode 100644 (file)
index 0000000..d9a8ec4
--- /dev/null
@@ -0,0 +1,5 @@
+import Qt.labs.folderlistmodel 1.0
+
+FolderListModel {
+    showDirs: false
+}
diff --git a/tests/auto/declarative/qdeclarativefolderlistmodel/data/resetfiltering/innerdir/test2.txt b/tests/auto/declarative/qdeclarativefolderlistmodel/data/resetfiltering/innerdir/test2.txt
new file mode 100644 (file)
index 0000000..97e64bb
--- /dev/null
@@ -0,0 +1 @@
+This file contains some text.
diff --git a/tests/auto/declarative/qdeclarativefolderlistmodel/data/resetfiltering/test.txt b/tests/auto/declarative/qdeclarativefolderlistmodel/data/resetfiltering/test.txt
new file mode 100644 (file)
index 0000000..97e64bb
--- /dev/null
@@ -0,0 +1 @@
+This file contains some text.
index ffd5d38..0594cbe 100644 (file)
@@ -72,6 +72,7 @@ public slots:
 
 private slots:
     void basicProperties();
+    void resetFiltering();
     void refresh();
 
 private:
@@ -109,7 +110,7 @@ void tst_qdeclarativefolderlistmodel::basicProperties()
     QVERIFY(flm != 0);
 
     flm->setProperty("folder",QUrl::fromLocalFile(SRCDIR "/data"));
-    QTRY_COMPARE(flm->property("count").toInt(),2); // wait for refresh
+    QTRY_COMPARE(flm->property("count").toInt(),4); // wait for refresh
     QCOMPARE(flm->property("folder").toUrl(), QUrl::fromLocalFile(SRCDIR "/data"));
     QCOMPARE(flm->property("parentFolder").toUrl(), QUrl::fromLocalFile(SRCDIR));
     QCOMPARE(flm->property("sortField").toInt(), int(Name));
@@ -125,6 +126,37 @@ void tst_qdeclarativefolderlistmodel::basicProperties()
     QCOMPARE(flm->property("folder").toUrl(), QUrl::fromLocalFile(""));
 }
 
+void tst_qdeclarativefolderlistmodel::resetFiltering()
+{
+    // see QTBUG-17837
+    QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/resetFiltering.qml"));
+    checkNoErrors(component);
+
+    QAbstractListModel *flm = qobject_cast<QAbstractListModel*>(component.create());
+    QVERIFY(flm != 0);
+
+    connect(flm, SIGNAL(rowsRemoved(const QModelIndex&,int,int)),
+            this, SLOT(removed(const QModelIndex&,int,int)));
+
+    flm->setProperty("folder",QUrl::fromLocalFile(SRCDIR "/data/resetfiltering"));
+    QTRY_COMPARE(flm->property("count").toInt(),1); // should just be "test.txt" visible
+    int count = flm->rowCount();
+    QCOMPARE(removeStart, 0);
+    QCOMPARE(removeEnd, count-1);
+
+    flm->setProperty("folder",QUrl::fromLocalFile(SRCDIR "/data/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("folder",QUrl::fromLocalFile(SRCDIR "/data/resetfiltering"));
+    QTRY_COMPARE(flm->property("count").toInt(),1); // should just be "test.txt" visible
+    count = flm->rowCount();
+    QCOMPARE(removeStart, 0);
+    QCOMPARE(removeEnd, count-1);
+}
+
 void tst_qdeclarativefolderlistmodel::refresh()
 {
     QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/basic.qml"));
@@ -134,7 +166,7 @@ void tst_qdeclarativefolderlistmodel::refresh()
     QVERIFY(flm != 0);
 
     flm->setProperty("folder",QUrl::fromLocalFile(SRCDIR "/data"));
-    QTRY_COMPARE(flm->property("count").toInt(),2); // wait for refresh
+    QTRY_COMPARE(flm->property("count").toInt(),4); // wait for refresh
 
     int count = flm->rowCount();