Qt 6.x
The Qt SDK
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
qquickdeferredexecute.cpp
Go to the documentation of this file.
1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include <QtCore/qhash.h>
7#include <QtQml/qqmlengine.h>
8#include <QtQml/private/qqmldata_p.h>
9#include <QtQml/private/qqmlcomponent_p.h>
10#include <QtQml/private/qqmlobjectcreator_p.h>
11
12#include <deque>
13
15
16namespace QtQuickPrivate {
17
18static void cancelDeferred(QQmlData *ddata, int propertyIndex)
19{
20 auto dit = ddata->deferredData.rbegin();
21 while (dit != ddata->deferredData.rend()) {
22 (*dit)->bindings.remove(propertyIndex);
23 ++dit;
24 }
25}
26
28{
29 QObject *object = property.object();
30 QQmlData *ddata = QQmlData::get(object);
31 Q_ASSERT(!ddata->deferredData.isEmpty());
32
33 int propertyIndex = property.index();
34 int wasInProgress = enginePriv->inProgressCreations;
35
36 /* we don't want deferred properties to suddenly depend on arbitrary
37 other properties which might have trigerred the construction of
38 objects as a consequence of a read.
39 */
41 auto cleanup = qScopeGuard([&](){
43 });
44
45 for (auto dit = ddata->deferredData.rbegin(); dit != ddata->deferredData.rend(); ++dit) {
46 QQmlData::DeferredData *deferData = *dit;
47
48 auto bindings = deferData->bindings;
49 auto range = bindings.equal_range(propertyIndex);
50 if (range.first == bindings.end())
51 continue;
52
54 state.setCompletePending(true);
55
56 QQmlContextData *creationContext = nullptr;
57 state.initCreator(deferData->context->parent(), deferData->compilationUnit, creationContext);
58
59 enginePriv->inProgressCreations++;
60
61 std::deque<const QV4::CompiledData::Binding *> reversedBindings;
62 std::copy(range.first, range.second, std::front_inserter(reversedBindings));
63 state.creator()->beginPopulateDeferred(deferData->context);
64 for (const QV4::CompiledData::Binding *binding : reversedBindings)
65 state.creator()->populateDeferredBinding(property, deferData->deferredIdx, binding);
66 state.creator()->finalizePopulateDeferred();
67 state.appendCreatorErrors();
68
69 deferredState->push_back(std::move(state));
70
71 // Cleanup any remaining deferred bindings for this property, also in inner contexts,
72 // to avoid executing them later and overriding the property that was just populated.
73 cancelDeferred(ddata, propertyIndex);
74 break;
75 }
76
77 return enginePriv->inProgressCreations > wasInProgress;
78}
79
81 QQuickUntypedDeferredPointer *delegate, bool isOwnState)
82{
83 QQmlData *data = QQmlData::get(object);
84 if (data && !data->deferredData.isEmpty() && !data->wasDeleted(object) && data->context) {
85 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine());
86
88 if (beginDeferred(ep, QQmlProperty(object, property), &state)) {
89 if (QQmlComponentPrivate::DeferredState *delegateState = delegate->deferredState())
90 delegateState->swap(state);
91 } else if (isOwnState) {
92 delegate->clearDeferredState();
93 }
94
95 // Release deferred data for those compilation units that no longer have deferred bindings
96 data->releaseDeferredData();
97 } else if (isOwnState) {
98 delegate->clearDeferredState();
99 }
100}
101
103{
104 QQmlData *data = QQmlData::get(object);
105 if (data)
107}
108
110{
113 if (!state)
114 return;
115
116 QQmlData *data = QQmlData::get(object);
117 if (data && !data->wasDeleted(object)) {
118 /* we don't want deferred properties to suddenly depend on arbitrary
119 other properties which might have trigerred the construction of
120 objects as a consequence of a read.
121 */
123 auto cleanup = qScopeGuard([&](){
125 });
126
127 QQmlComponentPrivate::DeferredState localState = std::move(*state);
128 delegate->clearDeferredState();
129 QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine());
131 } else {
132 delegate->clearDeferredState();
133 }
134}
135
136} // QtQuickPrivate
137
QPair< iterator, iterator > equal_range(const Key &key)
Definition qhash.h:2128
\inmodule QtCore
Definition qobject.h:90
std::vector< ConstructionState > DeferredState
static void completeDeferred(QQmlEnginePrivate *enginePriv, DeferredState *deferredState)
QQmlRefPointer< QQmlContextData > parent() const
QVector< DeferredData * > deferredData
Definition qqmldata_p.h:187
static QQmlData * get(QObjectPrivate *priv, bool create)
Definition qqmldata_p.h:199
static QQmlEnginePrivate * get(QQmlEngine *e)
The QQmlProperty class abstracts accessing properties on objects created from QML.
QQmlComponentPrivate::DeferredState * deferredState() const
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
else opt state
[0]
Combined button and popup list for selecting options.
BindingEvaluationState * suspendCurrentBindingStatus()
void restoreBindingStatus(BindingEvaluationState *status)
static void cancelDeferred(QQmlData *ddata, int propertyIndex)
void completeDeferred(QObject *object, const QString &property, QQuickUntypedDeferredPointer *delegate)
static bool beginDeferred(QQmlEnginePrivate *enginePriv, const QQmlProperty &property, QQmlComponentPrivate::DeferredState *deferredState)
GLuint index
[2]
GLsizei range
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
static Q_CONSTINIT thread_local QBindingStatus bindingStatus
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
Definition qscopeguard.h:60
#define Q_UNUSED(x)
const char property[13]
Definition qwizard.cpp:101
QQmlRefPointer< QQmlContextData > context
Definition qqmldata_p.h:183
unsigned int deferredIdx
Definition qqmldata_p.h:176
QQmlRefPointer< QV4::ExecutableCompilationUnit > compilationUnit
Definition qqmldata_p.h:180
QMultiHash< int, const QV4::CompiledData::Binding * > bindings
Definition qqmldata_p.h:177