diff options
3 files changed, 102 insertions, 16 deletions
diff --git a/src/widgets/itemviews/qsortfilterproxymodel.cpp b/src/widgets/itemviews/qsortfilterproxymodel.cpp index 90f5719782..f29ad7bc57 100644 --- a/src/widgets/itemviews/qsortfilterproxymodel.cpp +++ b/src/widgets/itemviews/qsortfilterproxymodel.cpp @@ -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())); diff --git a/src/widgets/itemviews/qsortfilterproxymodel.h b/src/widgets/itemviews/qsortfilterproxymodel.h index 1ce84ec11e..bbeec1470c 100644 --- a/src/widgets/itemviews/qsortfilterproxymodel.h +++ b/src/widgets/itemviews/qsortfilterproxymodel.h @@ -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)) diff --git a/tests/auto/widgets/itemviews/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp b/tests/auto/widgets/itemviews/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp index 1d4bb5616f..cc8299e28f 100644 --- a/tests/auto/widgets/itemviews/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp +++ b/tests/auto/widgets/itemviews/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp @@ -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) |