aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2019-10-08 15:05:15 +0200
committerSimon Hausmann <simon.hausmann@qt.io>2019-10-08 13:26:44 +0000
commit8ea33db63505cbdbad3d298908211d78a4812519 (patch)
tree31136c8a0859f3ed2d042a652645ec5635bc8c0f
parent7ec1dba0953593ffdf97b0a93fb6442d3cd085df (diff)
QQmlListModel: handle nested list models during iteration
ListElement::getProperty returns in turn a list model The ModelObjectOwnPropertyKeyIterator should however return the concrete values, and not some proxy object. This would cause funny return values in the best case, and a crash in case of QTBUG-79083. We therefore convert the nested model to a JavaScript array in ModelObjectOwnPropertyKeyIterator::next, which avoids beforementioned issues. Fixes: QTBUG-79083 Change-Id: If038598ff1c3c59090e994aaba5fba94a6964224 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r--src/qmlmodels/qqmllistmodel.cpp12
-rw-r--r--tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp27
2 files changed, 38 insertions, 1 deletions
diff --git a/src/qmlmodels/qqmllistmodel.cpp b/src/qmlmodels/qqmllistmodel.cpp
index 1cd089f454..d68815cbc1 100644
--- a/src/qmlmodels/qqmllistmodel.cpp
+++ b/src/qmlmodels/qqmllistmodel.cpp
@@ -1641,8 +1641,18 @@ PropertyKey ModelObjectOwnPropertyKeyIterator::next(const Object *o, Property *p
if (attrs)
*attrs = QV4::Attr_Data;
if (pd) {
+
QVariant value = that->d()->m_model->data(that->d()->elementIndex(), role.index);
- pd->value = v4->fromVariant(value);
+ if (auto recursiveListModel = qvariant_cast<QQmlListModel*>(value)) {
+ auto size = recursiveListModel->count();
+ auto array = ScopedArrayObject{scope, v4->newArrayObject(size)};
+ for (auto i = 0; i < size; i++) {
+ array->arrayPut(i, QJSValuePrivate::convertedToValue(v4, recursiveListModel->get(i)));
+ }
+ pd->value = array;
+ } else {
+ pd->value = v4->fromVariant(value);
+ }
}
return roleName->toPropertyKey();
}
diff --git a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
index 77ab0ecbc0..b47062ee94 100644
--- a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
+++ b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
@@ -128,6 +128,7 @@ private slots:
void qobjectTrackerForDynamicModelObjects();
void crash_append_empty_array();
void dynamic_roles_crash_QTBUG_38907();
+ void nestedListModelIteration();
};
bool tst_qqmllistmodel::compareVariantList(const QVariantList &testList, QVariant object)
@@ -1667,6 +1668,32 @@ void tst_qqmllistmodel::dynamic_roles_crash_QTBUG_38907()
QVERIFY(retVal.toBool());
}
+void tst_qqmllistmodel::nestedListModelIteration()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ QTest::ignoreMessage(QtMsgType::QtDebugMsg ,R"({"subItems":[{"a":1,"b":0,"c":0},{"a":0,"b":2,"c":0},{"a":0,"b":0,"c":3}]})");
+ component.setData(
+ R"(import QtQuick 2.5
+ Item {
+ visible: true
+ width: 640
+ height: 480
+ ListModel {
+ id : model
+ }
+ Component.onCompleted: {
+ var tempData = {
+ subItems: [{a: 1}, {b: 2}, {c: 3}]
+ }
+ model.insert(0, tempData)
+ console.log(JSON.stringify(model.get(0)))
+ }
+ })",
+ QUrl());
+ QScopedPointer<QObject>(component.create());
+}
+
QTEST_MAIN(tst_qqmllistmodel)
#include "tst_qqmllistmodel.moc"