aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2024-01-29 11:20:20 +0100
committerUlf Hermann <ulf.hermann@qt.io>2024-01-30 17:14:09 +0100
commit6a278ea43e7d49d7339206a311a63dc2ee291b01 (patch)
treee50f4504b49186c7bd3e658bf2078c2e19b55fd7
parent642d531e42fb233709155f8c8feb7d429c48db38 (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.cpp7
-rw-r--r--src/qmlmodels/qqmldmlistaccessordata_p.h12
-rw-r--r--tests/auto/qml/qqmlinstantiator/data/listDataDestruction.qml20
-rw-r--r--tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp12
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