diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2024-01-29 11:20:20 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2024-01-30 17:14:09 +0100 |
commit | 6a278ea43e7d49d7339206a311a63dc2ee291b01 (patch) | |
tree | e50f4504b49186c7bd3e658bf2078c2e19b55fd7 | |
parent | 642d531e42fb233709155f8c8feb7d429c48db38 (diff) |
QmlModels: Explicitly clear list data dynamic metaobject
Otherwise it can try to access model objects after they are deleted.
Pick-to: 6.7
Fixes: QTBUG-121588
Change-Id: I4420611be19dc650b7bf29ae805a7477e4c3d7c0
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Nicolas Fella <nicolas.fella@kdab.com>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
-rw-r--r-- | src/qmlmodels/qqmldmlistaccessordata.cpp | 7 | ||||
-rw-r--r-- | src/qmlmodels/qqmldmlistaccessordata_p.h | 12 | ||||
-rw-r--r-- | tests/auto/qml/qqmlinstantiator/data/listDataDestruction.qml | 20 | ||||
-rw-r--r-- | tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp | 12 |
4 files changed, 44 insertions, 7 deletions
diff --git a/src/qmlmodels/qqmldmlistaccessordata.cpp b/src/qmlmodels/qqmldmlistaccessordata.cpp index c84bdc0a3f..bfd353771c 100644 --- a/src/qmlmodels/qqmldmlistaccessordata.cpp +++ b/src/qmlmodels/qqmldmlistaccessordata.cpp @@ -16,6 +16,13 @@ QQmlDMListAccessorData::QQmlDMListAccessorData( dataType->addref(); } +QQmlDMListAccessorData::~QQmlDMListAccessorData() +{ + QObjectPrivate *d = QObjectPrivate::get(this); + static_cast<VDMListDelegateDataType *>(d->metaObject)->release(); + d->metaObject = nullptr; +} + void QQmlDMListAccessorData::setModelData(const QVariant &data) { if (data == cachedData) return; diff --git a/src/qmlmodels/qqmldmlistaccessordata_p.h b/src/qmlmodels/qqmldmlistaccessordata_p.h index 1bdd6d3acd..12ec484a9c 100644 --- a/src/qmlmodels/qqmldmlistaccessordata_p.h +++ b/src/qmlmodels/qqmldmlistaccessordata_p.h @@ -29,8 +29,11 @@ class QQmlDMListAccessorData : public QQmlDelegateModelItem Q_PROPERTY(QVariant modelData READ modelData WRITE setModelData NOTIFY modelDataChanged FINAL) QT_ANONYMOUS_PROPERTY(QVariant READ modelData WRITE setModelData NOTIFY modelDataChanged) public: - QQmlDMListAccessorData(const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType, - VDMListDelegateDataType *dataType, int index, int row, int column, const QVariant &value); + QQmlDMListAccessorData( + const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType, + VDMListDelegateDataType *dataType, int index, int row, int column, + const QVariant &value); + ~QQmlDMListAccessorData(); QVariant modelData() const { @@ -273,11 +276,6 @@ public: return true; } - void objectDestroyed(QObject *) override - { - release(); - } - void emitAllSignals(QQmlDMListAccessorData *accessor) const; int metaCall(QObject *object, QMetaObject::Call call, int id, void **arguments) final; diff --git a/tests/auto/qml/qqmlinstantiator/data/listDataDestruction.qml b/tests/auto/qml/qqmlinstantiator/data/listDataDestruction.qml new file mode 100644 index 0000000000..82d707af37 --- /dev/null +++ b/tests/auto/qml/qqmlinstantiator/data/listDataDestruction.qml @@ -0,0 +1,20 @@ +import QtQml + +QtObject { + id: menu + + Component.onCompleted: dt = new Date(); + property date dt + property Instantiator i: Instantiator { + model: { + var model = []; + var d = menu.dt; + model.push({text: "A"}); + return model; + } + delegate: QtObject { + objectName: modelData.text + Component.onCompleted: menu.objectName = objectName + } + } +} diff --git a/tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp b/tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp index f6d2752889..6db46d04a8 100644 --- a/tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp +++ b/tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp @@ -36,6 +36,8 @@ private slots: void handlerWithParent(); void boundDelegateComponent(); + + void listDataDestruction(); }; tst_qqmlinstantiator::tst_qqmlinstantiator() @@ -308,6 +310,16 @@ void tst_qqmlinstantiator::boundDelegateComponent() QCOMPARE(b->objectAt(2)->objectName(), QStringLiteral("root3")); } +void tst_qqmlinstantiator::listDataDestruction() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("listDataDestruction.qml")); + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + QScopedPointer<QObject> o(component.create()); + QVERIFY(!o.isNull()); + QCOMPARE(o->objectName(), QLatin1String("A")); +} + class SingleBoolItemModel : public QAbstractListModel { Q_OBJECT |