Forward the contents of the parents argument through this proxy.
authorStephen Kelly <stephen.kelly@kdab.com>
Fri, 25 Nov 2011 12:54:38 +0000 (13:54 +0100)
committerQt by Nokia <qt-info@nokia.com>
Fri, 9 Dec 2011 01:39:06 +0000 (02:39 +0100)
Change-Id: Ifabc2a7deec8ea045bf9a9f46fb3a97410dd33f2
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
src/widgets/itemviews/qsortfilterproxymodel.cpp
src/widgets/itemviews/qsortfilterproxymodel.h
tests/auto/widgets/itemviews/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp

index 90f5719..f29ad7b 100644 (file)
@@ -207,8 +207,8 @@ public:
     void _q_sourceAboutToBeReset();
     void _q_sourceReset();
 
-    void _q_sourceLayoutAboutToBeChanged();
-    void _q_sourceLayoutChanged();
+    void _q_sourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents);
+    void _q_sourceLayoutChanged(const QList<QPersistentModelIndex> &sourceParents);
 
     void _q_sourceRowsAboutToBeInserted(const QModelIndex &source_parent,
                                         int start, int end);
@@ -1247,21 +1247,40 @@ void QSortFilterProxyModelPrivate::_q_sourceReset()
         sort();
 }
 
-void QSortFilterProxyModelPrivate::_q_sourceLayoutAboutToBeChanged()
+void QSortFilterProxyModelPrivate::_q_sourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents)
 {
     Q_Q(QSortFilterProxyModel);
     saved_persistent_indexes.clear();
-    emit q->layoutAboutToBeChanged();
+
+    QList<QPersistentModelIndex> parents;
+    foreach (const QPersistentModelIndex &parent, sourceParents) {
+        if (!parent.isValid()) {
+            parents << QModelIndex();
+            continue;
+        }
+        const QModelIndex mappedParent = q->mapFromSource(parent);
+        // Might be filtered out.
+        if (mappedParent.isValid())
+            parents << mappedParent;
+    }
+
+    // All parents filtered out.
+    if (!sourceParents.isEmpty() && parents.isEmpty())
+        return;
+
+    emit q->layoutAboutToBeChanged(parents);
     if (persistent.indexes.isEmpty())
         return;
 
     saved_persistent_indexes = store_persistent_indexes();
 }
 
-void QSortFilterProxyModelPrivate::_q_sourceLayoutChanged()
+void QSortFilterProxyModelPrivate::_q_sourceLayoutChanged(const QList<QPersistentModelIndex> &sourceParents)
 {
     Q_Q(QSortFilterProxyModel);
 
+    // Optimize: We only actually have to clear the mapping related to the contents of
+    // sourceParents, not everything.
     qDeleteAll(source_index_mapping);
     source_index_mapping.clear();
 
@@ -1274,7 +1293,21 @@ void QSortFilterProxyModelPrivate::_q_sourceLayoutChanged()
         source_index_mapping.clear();
     }
 
-    emit q->layoutChanged();
+    QList<QPersistentModelIndex> parents;
+    foreach (const QPersistentModelIndex &parent, sourceParents) {
+        if (!parent.isValid()) {
+            parents << QModelIndex();
+            continue;
+        }
+        const QModelIndex mappedParent = q->mapFromSource(parent);
+        if (mappedParent.isValid())
+            parents << mappedParent;
+    }
+
+    if (!sourceParents.isEmpty() && parents.isEmpty())
+        return;
+
+    emit q->layoutChanged(parents);
 }
 
 void QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeInserted(
@@ -1689,11 +1722,11 @@ void QSortFilterProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
     disconnect(d->model, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)),
                this, SLOT(_q_sourceColumnsMoved(QModelIndex,int,int,QModelIndex,int)));
 
-    disconnect(d->model, SIGNAL(layoutAboutToBeChanged()),
-               this, SLOT(_q_sourceLayoutAboutToBeChanged()));
+    disconnect(d->model, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>)),
+               this, SLOT(_q_sourceLayoutAboutToBeChanged(QList<QPersistentModelIndex>)));
 
-    disconnect(d->model, SIGNAL(layoutChanged()),
-               this, SLOT(_q_sourceLayoutChanged()));
+    disconnect(d->model, SIGNAL(layoutChanged(QList<QPersistentModelIndex>)),
+               this, SLOT(_q_sourceLayoutChanged(QList<QPersistentModelIndex>)));
 
     disconnect(d->model, SIGNAL(modelAboutToBeReset()), this, SLOT(_q_sourceAboutToBeReset()));
     disconnect(d->model, SIGNAL(modelReset()), this, SLOT(_q_sourceReset()));
@@ -1742,11 +1775,11 @@ void QSortFilterProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
     connect(d->model, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)),
             this, SLOT(_q_sourceColumnsMoved(QModelIndex,int,int,QModelIndex,int)));
 
-    connect(d->model, SIGNAL(layoutAboutToBeChanged()),
-            this, SLOT(_q_sourceLayoutAboutToBeChanged()));
+    connect(d->model, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>)),
+            this, SLOT(_q_sourceLayoutAboutToBeChanged(QList<QPersistentModelIndex>)));
 
-    connect(d->model, SIGNAL(layoutChanged()),
-            this, SLOT(_q_sourceLayoutChanged()));
+    connect(d->model, SIGNAL(layoutChanged(QList<QPersistentModelIndex>)),
+            this, SLOT(_q_sourceLayoutChanged(QList<QPersistentModelIndex>)));
 
     connect(d->model, SIGNAL(modelAboutToBeReset()), this, SLOT(_q_sourceAboutToBeReset()));
     connect(d->model, SIGNAL(modelReset()), this, SLOT(_q_sourceReset()));
index 1ce84ec..bbeec14 100644 (file)
@@ -179,8 +179,8 @@ private:
     Q_PRIVATE_SLOT(d_func(), void _q_sourceHeaderDataChanged(Qt::Orientation orientation, int start, int end))
     Q_PRIVATE_SLOT(d_func(), void _q_sourceAboutToBeReset())
     Q_PRIVATE_SLOT(d_func(), void _q_sourceReset())
-    Q_PRIVATE_SLOT(d_func(), void _q_sourceLayoutAboutToBeChanged())
-    Q_PRIVATE_SLOT(d_func(), void _q_sourceLayoutChanged())
+    Q_PRIVATE_SLOT(d_func(), void _q_sourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents))
+    Q_PRIVATE_SLOT(d_func(), void _q_sourceLayoutChanged(const QList<QPersistentModelIndex> &sourceParents))
     Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeInserted(const QModelIndex &source_parent, int start, int end))
     Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsInserted(const QModelIndex &source_parent, int start, int end))
     Q_PRIVATE_SLOT(d_func(), void _q_sourceRowsAboutToBeRemoved(const QModelIndex &source_parent, int start, int end))
index 1d4bb56..cc8299e 100644 (file)
@@ -3233,6 +3233,16 @@ void tst_QSortFilterProxyModel::testParentLayoutChanged()
     proxy.setDynamicSortFilter(true);
 
     proxy.setSourceModel(&model);
+    proxy.setObjectName("proxy");
+
+    // When Proxy1 emits layoutChanged(QList<QPersistentModelIndex>) this
+    // one will too, with mapped indexes.
+    QSortFilterProxyModel proxy2;
+    proxy2.sort(0, Qt::AscendingOrder);
+    proxy2.setDynamicSortFilter(true);
+
+    proxy2.setSourceModel(&proxy);
+    proxy2.setObjectName("proxy2");
 
     qRegisterMetaType<QList<QPersistentModelIndex> >();
 
@@ -3245,6 +3255,9 @@ void tst_QSortFilterProxyModel::testParentLayoutChanged()
     QSignalSpy parentsAboutToBeChangedSpy(&proxy, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>)));
     QSignalSpy parentsChangedSpy(&proxy, SIGNAL(layoutChanged(QList<QPersistentModelIndex>)));
 
+    QSignalSpy proxy2ParentsAboutToBeChangedSpy(&proxy2, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>)));
+    QSignalSpy proxy2ParentsChangedSpy(&proxy2, SIGNAL(layoutChanged(QList<QPersistentModelIndex>)));
+
     QStandardItem *item = model.invisibleRootItem()->child(1)->child(1);
 
     // Ensure mapped:
@@ -3257,6 +3270,8 @@ void tst_QSortFilterProxyModel::testParentLayoutChanged()
     QCOMPARE(layoutChangedSpy.size(), 1);
     QCOMPARE(parentsAboutToBeChangedSpy.size(), 1);
     QCOMPARE(parentsChangedSpy.size(), 1);
+    QCOMPARE(proxy2ParentsAboutToBeChangedSpy.size(), 1);
+    QCOMPARE(proxy2ParentsChangedSpy.size(), 1);
 
     QVariantList beforeSignal = parentsAboutToBeChangedSpy.first();
     QVariantList afterSignal = parentsChangedSpy.first();
@@ -3275,6 +3290,16 @@ void tst_QSortFilterProxyModel::testParentLayoutChanged()
 
     QVERIFY(beforeParents.first() == proxy.mapFromSource(model.indexFromItem(model.invisibleRootItem()->child(1))));
 
+    QList<QPersistentModelIndex> proxy2BeforeList = proxy2ParentsAboutToBeChangedSpy.first().first().value<QList<QPersistentModelIndex> >();
+    QList<QPersistentModelIndex> proxy2AfterList = proxy2ParentsChangedSpy.first().first().value<QList<QPersistentModelIndex> >();
+
+    QCOMPARE(proxy2BeforeList.size(), beforeParents.size());
+    QCOMPARE(proxy2AfterList.size(), afterParents.size());
+    foreach (const QPersistentModelIndex &idx, proxy2BeforeList)
+        QVERIFY(beforeParents.contains(proxy2.mapToSource(idx)));
+    foreach (const QPersistentModelIndex &idx, proxy2AfterList)
+        QVERIFY(afterParents.contains(proxy2.mapToSource(idx)));
+
 }
 
 class SignalArgumentChecker : public QObject
@@ -3378,12 +3403,28 @@ void tst_QSortFilterProxyModel::moveSourceRows()
 
     proxy.setSourceModel(&model);
 
+    QSortFilterProxyModel filterProxy;
+    filterProxy.setDynamicSortFilter(true);
+    filterProxy.sort(0, Qt::AscendingOrder);
+    filterProxy.setSourceModel(&proxy);
+    filterProxy.setFilterRegExp("6"); // One of the parents
+
+    QSortFilterProxyModel filterBothProxy;
+    filterBothProxy.setDynamicSortFilter(true);
+    filterBothProxy.sort(0, Qt::AscendingOrder);
+    filterBothProxy.setSourceModel(&proxy);
+    filterBothProxy.setFilterRegExp("5"); // The parents are 6 and 3. This filters both out.
+
     QSignalSpy modelBeforeSpy(&model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
     QSignalSpy modelAfterSpy(&model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)));
     QSignalSpy proxyBeforeMoveSpy(m_proxy, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)));
     QSignalSpy proxyAfterMoveSpy(m_proxy, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)));
     QSignalSpy proxyBeforeParentLayoutSpy(&proxy, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>)));
     QSignalSpy proxyAfterParentLayoutSpy(&proxy, SIGNAL(layoutChanged(QList<QPersistentModelIndex>)));
+    QSignalSpy filterBeforeParentLayoutSpy(&filterProxy, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>)));
+    QSignalSpy filterAfterParentLayoutSpy(&filterProxy, SIGNAL(layoutChanged(QList<QPersistentModelIndex>)));
+    QSignalSpy filterBothBeforeParentLayoutSpy(&filterBothProxy, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>)));
+    QSignalSpy filterBothAfterParentLayoutSpy(&filterBothProxy, SIGNAL(layoutChanged(QList<QPersistentModelIndex>)));
 
     {
         ModelMoveCommand moveCommand(&model, 0);
@@ -3404,6 +3445,18 @@ void tst_QSortFilterProxyModel::moveSourceRows()
     // But it doesn't notify a move.
     QCOMPARE(proxyBeforeMoveSpy.size(), 0);
     QCOMPARE(proxyAfterMoveSpy.size(), 0);
+
+    QCOMPARE(filterBeforeParentLayoutSpy.size(), 1);
+    QCOMPARE(filterAfterParentLayoutSpy.size(), 1);
+
+    QList<QPersistentModelIndex> filterBeforeParents = filterBeforeParentLayoutSpy.first().first().value<QList<QPersistentModelIndex> >();
+    QList<QPersistentModelIndex> filterAfterParents = filterAfterParentLayoutSpy.first().first().value<QList<QPersistentModelIndex> >();
+
+    QCOMPARE(filterBeforeParents.size(), 1);
+    QCOMPARE(filterAfterParents.size(), 1);
+
+    QCOMPARE(filterBothBeforeParentLayoutSpy.size(), 0);
+    QCOMPARE(filterBothAfterParentLayoutSpy.size(), 0);
 }
 
 QTEST_MAIN(tst_QSortFilterProxyModel)