diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2019-10-08 15:05:15 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2019-10-08 13:26:44 +0000 |
commit | 8ea33db63505cbdbad3d298908211d78a4812519 (patch) | |
tree | 31136c8a0859f3ed2d042a652645ec5635bc8c0f | |
parent | 7ec1dba0953593ffdf97b0a93fb6442d3cd085df (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.cpp | 12 | ||||
-rw-r--r-- | tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp | 27 |
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" |