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);
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();
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(
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()));
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()));
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))
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> >();
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:
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();
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
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);
// 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)