From 2b505519238759b05315ce5b9c6d1427a0adae84 Mon Sep 17 00:00:00 2001 From: David Faure Date: Sun, 11 Aug 2024 11:45:56 +0200 Subject: [PATCH] QIdentityProxyModel: add setHandleSourceDataChanges(bool) Some sub-classes have special handling of source model data changes, they relied on disconnecting the connections to the _q_*layout* slots in the private class using the SLOT macro. This isn't possible any more after the recent port to PMF connects. Sub-classes resorting to using private API is a clear sign some functionality is missing from the public API, so a cleaner solution for this issue is adding this setter which enables sub-classes to tell QIdentityProxyModel to leave handling of the dataChanged signal to them. Similar to commit 675b4f63feab7c81c75e49f6dea82a39dd18f489 (but this should be the last one needed). [ChangeLog][QtCore][QIdentityProxyModel] Added setHandleSourceDataChanges(bool) method to allow sub-classes to indicate to QIdentityProxyModel that they will handle source model data changes on their own. Also added a getter, isHandleSourceDataChanges(). Task-number: QTBUG-127959 Change-Id: Id8f567c330e4ee834940a62b6497d8cbb8ba4a46 Reviewed-by: Axel Spoerl (cherry picked from commit 5a31800d41273a14436c543438a142562f74f857) Reviewed-by: Qt Cherry-pick Bot --- .../itemmodels/qidentityproxymodel.cpp | 39 +++++++++++++++++-- src/corelib/itemmodels/qidentityproxymodel.h | 2 + .../itemmodels/qidentityproxymodel_p.h | 1 + .../tst_qidentityproxymodel.cpp | 21 +++++++++- 4 files changed, 59 insertions(+), 4 deletions(-) diff --git a/src/corelib/itemmodels/qidentityproxymodel.cpp b/src/corelib/itemmodels/qidentityproxymodel.cpp index ffa038d6183..da4bc097cb4 100644 --- a/src/corelib/itemmodels/qidentityproxymodel.cpp +++ b/src/corelib/itemmodels/qidentityproxymodel.cpp @@ -331,12 +331,15 @@ void QIdentityProxyModel::setSourceModel(QAbstractItemModel* newSourceModel) &QIdentityProxyModelPrivate::sourceModelAboutToBeReset), QObjectPrivate::connect(m, &QAbstractItemModel::modelReset, d, &QIdentityProxyModelPrivate::sourceModelReset), - QObjectPrivate::connect(m, &QAbstractItemModel::dataChanged, d, - &QIdentityProxyModelPrivate::sourceDataChanged), QObjectPrivate::connect(m, &QAbstractItemModel::headerDataChanged, d, &QIdentityProxyModelPrivate::sourceHeaderDataChanged), }; + if (d->m_handleDataChanges) { + d->m_sourceModelConnections.emplace_back( + QObjectPrivate::connect(m, &QAbstractItemModel::dataChanged, d, + &QIdentityProxyModelPrivate::sourceDataChanged)); + } if (d->m_handleLayoutChanges) { d->m_sourceModelConnections.emplace_back( QObjectPrivate::connect(m, &QAbstractItemModel::layoutAboutToBeChanged, d, @@ -355,7 +358,7 @@ void QIdentityProxyModel::setSourceModel(QAbstractItemModel* newSourceModel) If \a b is \c true, this proxy model will handle the source model layout changes (by connecting to \c QAbstractItemModel::layoutAboutToBeChanged - and \c QAbstractItemModel::layoutChanged singals). + and \c QAbstractItemModel::layoutChanged signals). The default is for this proxy model to handle the source model layout changes. @@ -381,6 +384,36 @@ bool QIdentityProxyModel::handleSourceLayoutChanges() const return d_func()->m_handleLayoutChanges; } +/*! + \since 6.8 + + If \a b is \c true, this proxy model will handle the source model data + changes (by connecting to \c QAbstractItemModel::dataChanged signal). + + The default is for this proxy model to handle the source model data + changes. + + In sub-classes of QIdentityProxyModel, it may be useful to set this to + \c false if you need to specially handle the source model data changes. + + \note Calling this method will only have an effect after calling setSourceModel(). +*/ +void QIdentityProxyModel::setHandleSourceDataChanges(bool b) +{ + d_func()->m_handleDataChanges = b; +} + +/*! + \since 6.8 + + Returns \c true if this proxy model handles the source model data + changes, otherwise returns \c false. +*/ +bool QIdentityProxyModel::handleSourceDataChanges() const +{ + return d_func()->m_handleDataChanges; +} + void QIdentityProxyModelPrivate::sourceColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end) { Q_ASSERT(parent.isValid() ? parent.model() == model : true); diff --git a/src/corelib/itemmodels/qidentityproxymodel.h b/src/corelib/itemmodels/qidentityproxymodel.h index 456e108082e..af3534160a7 100644 --- a/src/corelib/itemmodels/qidentityproxymodel.h +++ b/src/corelib/itemmodels/qidentityproxymodel.h @@ -45,10 +45,12 @@ public: bool moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count, const QModelIndex &destinationParent, int destinationChild) override; bool handleSourceLayoutChanges() const; + bool handleSourceDataChanges() const; protected: QIdentityProxyModel(QIdentityProxyModelPrivate &dd, QObject* parent); void setHandleSourceLayoutChanges(bool); + void setHandleSourceDataChanges(bool); private: Q_DECLARE_PRIVATE(QIdentityProxyModel) diff --git a/src/corelib/itemmodels/qidentityproxymodel_p.h b/src/corelib/itemmodels/qidentityproxymodel_p.h index 78e1f5316c1..bb63dd3cd2e 100644 --- a/src/corelib/itemmodels/qidentityproxymodel_p.h +++ b/src/corelib/itemmodels/qidentityproxymodel_p.h @@ -64,6 +64,7 @@ public: private: bool m_handleLayoutChanges = true; + bool m_handleDataChanges = true; QVarLengthArray m_sourceModelConnections; }; diff --git a/tests/auto/corelib/itemmodels/qidentityproxymodel/tst_qidentityproxymodel.cpp b/tests/auto/corelib/itemmodels/qidentityproxymodel/tst_qidentityproxymodel.cpp index 99b74bc09ad..72f71d3d046 100644 --- a/tests/auto/corelib/itemmodels/qidentityproxymodel/tst_qidentityproxymodel.cpp +++ b/tests/auto/corelib/itemmodels/qidentityproxymodel/tst_qidentityproxymodel.cpp @@ -37,6 +37,7 @@ class IdentityProxyModel : public QIdentityProxyModel public: // The name has to be different than the method from the base class void setHandleSLC(bool b) { setHandleSourceLayoutChanges(b); } + void setHandleSDC(bool b) { setHandleSourceDataChanges(b); } }; class tst_QIdentityProxyModel : public QObject @@ -65,6 +66,7 @@ private slots: void createPersistentOnLayoutAboutToBeChanged(); void testSetHandleLayoutChanges(); + void testSetHandleDataChanges(); protected: void verifyIdentity(QAbstractItemModel *model, const QModelIndex &parent = QModelIndex()); @@ -541,12 +543,29 @@ void tst_QIdentityProxyModel::testSetHandleLayoutChanges() proxy.setSourceModel(nullptr); - // Disable handling (connecting to layotu signals) of source model layout changes + // Disable handling (connecting to layout signals) of source model layout changes proxy.setHandleSLC(false); proxy.setSourceModel(&model); for (const auto &m : layoutSignals) QVERIFY(!model.isConnected(m)); } +void tst_QIdentityProxyModel::testSetHandleDataChanges() +{ + const auto signal = QMetaMethod::fromSignal(&QAbstractItemModel::dataChanged); + + DataChangedModel model; + IdentityProxyModel proxy; + proxy.setSourceModel(&model); + QVERIFY(model.isConnected(signal)); // Connected by default + + proxy.setSourceModel(nullptr); + + // Disable handling (connecting to data signals) of source model data changes + proxy.setHandleSDC(false); + proxy.setSourceModel(&model); + QVERIFY(!model.isConnected(signal)); +} + QTEST_MAIN(tst_QIdentityProxyModel) #include "tst_qidentityproxymodel.moc"