StatusQ(SubmodelProxyModel): Submodel type fixed
There was inconsistency in qvariant type of submodels depending if it was initial call for a given row (creating proxy) or further calls (returning cached object). It led to subtle issues in views - view was reporting type errors and failing assigning submodels properly when used with submodel proxy with already initialized and cached proxy submodels. Closes: #14507
This commit is contained in:
parent
bbd0e71fd6
commit
e8a78e21b8
|
@ -50,13 +50,13 @@ QVariant SubmodelProxyModel::data(const QModelIndex &index, int role) const
|
||||||
context->setContextProperty(QStringLiteral("submodel"), submodel);
|
context->setContextProperty(QStringLiteral("submodel"), submodel);
|
||||||
|
|
||||||
QObject* instance = m_delegateModel->create(context);
|
QObject* instance = m_delegateModel->create(context);
|
||||||
|
|
||||||
instance->setParent(submodelObj);
|
instance->setParent(submodelObj);
|
||||||
|
|
||||||
submodelObj->setProperty(attachementPropertyName,
|
QVariant wrappedInstance = QVariant::fromValue(instance);
|
||||||
QVariant::fromValue(QPointer(instance)));
|
|
||||||
|
|
||||||
return QVariant::fromValue(instance);
|
submodelObj->setProperty(attachementPropertyName, wrappedInstance);
|
||||||
|
|
||||||
|
return QVariant::fromValue(wrappedInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
return QIdentityProxyModel::data(index, role);
|
return QIdentityProxyModel::data(index, role);
|
||||||
|
|
|
@ -78,6 +78,50 @@ private slots:
|
||||||
QQmlEngine::CppOwnership);
|
QQmlEngine::CppOwnership);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void submodelTypeTest() {
|
||||||
|
QQmlEngine engine;
|
||||||
|
QQmlComponent delegate(&engine);
|
||||||
|
|
||||||
|
auto delegateData = R"(
|
||||||
|
import QtQml 2.15
|
||||||
|
QtObject {
|
||||||
|
property var count: submodel.count
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
delegate.setData(delegateData, QUrl());
|
||||||
|
|
||||||
|
SubmodelProxyModel model;
|
||||||
|
|
||||||
|
auto source = R"([
|
||||||
|
{ balances: [ { balance: 4 } ], name: "name 1" }
|
||||||
|
])";
|
||||||
|
|
||||||
|
ListModelWrapper sourceModel(engine, source);
|
||||||
|
model.setSourceModel(sourceModel);
|
||||||
|
model.setDelegateModel(&delegate);
|
||||||
|
model.setSubmodelRoleName(QStringLiteral("balances"));
|
||||||
|
|
||||||
|
QCOMPARE(model.rowCount(), 1);
|
||||||
|
|
||||||
|
QVariant balances = model.data(model.index(0, 0),
|
||||||
|
sourceModel.role("balances"));
|
||||||
|
|
||||||
|
QVERIFY(balances.isValid());
|
||||||
|
|
||||||
|
QVariant balances2 = model.data(model.index(0, 0),
|
||||||
|
sourceModel.role("balances"));
|
||||||
|
|
||||||
|
// SubmodelProxyModel may create proxy objects on demand, then first
|
||||||
|
// call to data(...) returns freshly created object, the next calls
|
||||||
|
// related to the same row should return cached object. It's important
|
||||||
|
// to have QVariant type identical in both cases. E.g. returning raw
|
||||||
|
// pointer in first call and pointer wrapped into QPointer in the next
|
||||||
|
// one leads to problems in UI components in some scenarios even if
|
||||||
|
// those QVariant types are automatically convertible.
|
||||||
|
QCOMPARE(balances2.type(), balances.type());
|
||||||
|
}
|
||||||
|
|
||||||
void usingNonObjectSubmodelRoleTest() {
|
void usingNonObjectSubmodelRoleTest() {
|
||||||
QQmlEngine engine;
|
QQmlEngine engine;
|
||||||
QQmlComponent delegate(&engine);
|
QQmlComponent delegate(&engine);
|
||||||
|
|
Loading…
Reference in New Issue