From 6fe8ed82cdc3e2ec4f6fc9980a41d457b6aed110 Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Fri, 18 Jun 2021 09:24:04 +0200 Subject: Ensure model is in context if required properties are not used We need to set the set the contextObject already in QQmlDelegateModelPrivate::object, as the context property might be accessed in a child component before we are able to run setRequiredProperties (which would set-up the context in case there are no required properties). Instead of delaying setting the context object, we clear it now in setRequiredProperties. This has the drawback that one might be able to access context properties on initial component setup which should not exist (due to the presence of required properties). This could be avoided by inspecting the Compilation Unit and only setting the context if we do not find required properties, however that needs further work to expose the necessary information. Fixes: QTBUG-94223 Change-Id: I678de81408539417fc650f94da4c9f0d3167653d Reviewed-by: Ulf Hermann Reviewed-by: Qt CI Bot (cherry picked from commit 58cd06033cacadab541efaa16a3eecec37dab0fa) Reviewed-by: Qt Cherry-pick Bot --- src/qmlmodels/qqmldelegatemodel.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'src/qmlmodels') diff --git a/src/qmlmodels/qqmldelegatemodel.cpp b/src/qmlmodels/qqmldelegatemodel.cpp index cbefc5d535..5c5f464cd5 100644 --- a/src/qmlmodels/qqmldelegatemodel.cpp +++ b/src/qmlmodels/qqmldelegatemodel.cpp @@ -963,8 +963,19 @@ void QQDMIncubationTask::initializeRequiredProperties(QQmlDelegateModelItem *mod if (incubatorPriv->hadRequiredProperties()) { QQmlData *d = QQmlData::get(object); auto contextData = d ? d->context : nullptr; - if (contextData) + if (contextData) { contextData->setExtraObject(modelItemToIncubate); + } + + // If we have required properties, we clear the context object + // so that the model role names are not polluting the context + if (incubating) { + Q_ASSERT(incubating->contextData); + incubating->contextData->setContextObject(nullptr); + } + if (proxyContext) { + proxyContext->setContextObject(nullptr); + } if (incubatorPriv->requiredProperties().empty()) return; @@ -1277,6 +1288,7 @@ QObject *QQmlDelegateModelPrivate::object(Compositor::Group group, int index, QQ QQmlRefPointer ctxt = QQmlContextData::createRefCounted( QQmlContextData::get(creationContext ? creationContext : m_context.data())); + ctxt->setContextObject(cacheItem); cacheItem->contextData = ctxt; if (m_adaptorModel.hasProxyObject()) { @@ -1286,6 +1298,7 @@ QObject *QQmlDelegateModelPrivate::object(Compositor::Group group, int index, QQ QObject *proxied = proxy->proxiedObject(); cacheItem->incubationTask->proxiedObject = proxied; cacheItem->incubationTask->proxyContext = ctxt; + ctxt->setContextObject(cacheItem); // We don't own the proxied object. We need to clear it if it goes away. QObject::connect(proxied, &QObject::destroyed, cacheItem, &QQmlDelegateModelItem::childContextObjectDestroyed); -- cgit v1.2.3