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>
This commit is contained in:
parent
7ec1dba095
commit
8ea33db635
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue