diff options
author | Ulf Hermann <[email protected]> | 2022-07-12 08:47:11 +0200 |
---|---|---|
committer | Ulf Hermann <[email protected]> | 2022-07-21 13:19:04 +0200 |
commit | e4f4e7341f5fbfbb246c7fc4ee99fed5cce42fca (patch) | |
tree | ade043953c41cee5882ac2fca49630de1d91831e /src/qmlmodels/qqmltableinstancemodel.cpp | |
parent | 80cb4091d6cc5b7d13b80668f6e393788d763b3e (diff) |
QmlModels: Fix context and extra object handling
If we have a bound context, we still need to record the information that
the object's context belongs to a delegate. For this purpose we have
the extra object. Even when we create the object in the component's
creation context, the object creator still produces a private internal
context for each object. We unconditionally attach the extra object to
that one, and check the whole context hierarchy for extra objects.
As we now record the creation context for model items incubated from
bound components, we need to make sure not to (re)set its context object
and not to forcibly invalidate it. We have QQmlRefPointer::reset() for
that anyway.
As a drive-by we also assert that the object ref count doesn't overflow,
as that has happened during testing.
Pick-to: 6.4
Fixes: QTBUG-104884
Change-Id: I836916c63656124a0f9d7b04902debba59b9f3a3
Reviewed-by: Fabian Kosmale <[email protected]>
Diffstat (limited to 'src/qmlmodels/qqmltableinstancemodel.cpp')
-rw-r--r-- | src/qmlmodels/qqmltableinstancemodel.cpp | 47 |
1 files changed, 27 insertions, 20 deletions
diff --git a/src/qmlmodels/qqmltableinstancemodel.cpp b/src/qmlmodels/qqmltableinstancemodel.cpp index e145702463..39102c27c9 100644 --- a/src/qmlmodels/qqmltableinstancemodel.cpp +++ b/src/qmlmodels/qqmltableinstancemodel.cpp @@ -29,13 +29,7 @@ void QQmlTableInstanceModel::deleteModelItemLater(QQmlDelegateModelItem *modelIt delete modelItem->object; modelItem->object = nullptr; - - if (modelItem->contextData) { - modelItem->contextData->invalidate(); - Q_ASSERT(modelItem->contextData->refCount() == 1); - modelItem->contextData = nullptr; - } - + modelItem->contextData.reset(); modelItem->deleteLater(); } @@ -67,8 +61,7 @@ QQmlTableInstanceModel::~QQmlTableInstanceModel() if (modelItem->object) { delete modelItem->object; modelItem->object = nullptr; - modelItem->contextData->invalidate(); - modelItem->contextData = nullptr; + modelItem->contextData.reset(); } } @@ -295,17 +288,31 @@ void QQmlTableInstanceModel::incubateModelItem(QQmlDelegateModelItem *modelItem, modelItem->incubationTask = new QQmlTableInstanceModelIncubationTask(this, modelItem, incubationMode); QQmlContext *creationContext = modelItem->delegate->creationContext(); - QQmlRefPointer<QQmlContextData> ctxt = QQmlContextData::createRefCounted( - QQmlContextData::get(creationContext ? creationContext : m_qmlContext.data())); - ctxt->setContextObject(modelItem); - modelItem->contextData = ctxt; - - QQmlComponentPrivate::get(modelItem->delegate)->incubateObject( - modelItem->incubationTask, - modelItem->delegate, - m_qmlContext->engine(), - ctxt, - QQmlContextData::get(m_qmlContext)); + const QQmlRefPointer<QQmlContextData> componentContext + = QQmlContextData::get(creationContext ? creationContext : m_qmlContext.data()); + + QQmlComponentPrivate *cp = QQmlComponentPrivate::get(modelItem->delegate); + if (cp->isBound()) { + modelItem->contextData = componentContext; + cp->incubateObject( + modelItem->incubationTask, + modelItem->delegate, + m_qmlContext->engine(), + componentContext, + QQmlContextData::get(m_qmlContext)); + } else { + QQmlRefPointer<QQmlContextData> ctxt = QQmlContextData::createRefCounted( + QQmlContextData::get(creationContext ? creationContext : m_qmlContext.data())); + ctxt->setContextObject(modelItem); + modelItem->contextData = ctxt; + + cp->incubateObject( + modelItem->incubationTask, + modelItem->delegate, + m_qmlContext->engine(), + ctxt, + QQmlContextData::get(m_qmlContext)); + } } // Remove the temporary guard |