Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmlcomponent_p.h
Go to the documentation of this file.
1// Copyright (C) 2016 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
4#ifndef QQMLCOMPONENT_P_H
5#define QQMLCOMPONENT_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include "qqmlcomponent.h"
19
20#include "qqmlengine_p.h"
21#include "qqmlerror.h"
22#include <private/qqmlobjectcreator_p.h>
23#include <private/qqmltypedata_p.h>
24#include <private/qqmlguardedcontextdata_p.h>
25
26#include <QtCore/QString>
27#include <QtCore/QStringList>
28#include <QtCore/QList>
29#include <QtCore/qtclasshelpermacros.h>
30
31#include <private/qobject_p.h>
32
34
35class QQmlComponent;
36class QQmlEngine;
37
38class QQmlComponentAttached;
39class Q_QML_EXPORT QQmlComponentPrivate : public QObjectPrivate, public QQmlTypeData::TypeDataCallback
40{
41 Q_DECLARE_PUBLIC(QQmlComponent)
42
43public:
44 QQmlComponentPrivate()
45 : progress(0.), start(-1), engine(nullptr) {}
46
47 void loadUrl(const QUrl &newUrl, QQmlComponent::CompilationMode mode = QQmlComponent::PreferSynchronous);
48
49 QQmlType loadedType() const { return loadHelper ? loadHelper->type() : QQmlType(); }
50
51 QObject *beginCreate(QQmlRefPointer<QQmlContextData>);
52 void completeCreate();
53 void initializeObjectWithInitialProperties(QV4::QmlContext *qmlContext, const QV4::Value &valuemap, QObject *toCreate, RequiredProperties *requiredProperties);
54 static void setInitialProperties(
55 QV4::ExecutionEngine *engine, QV4::QmlContext *qmlContext, const QV4::Value &o,
56 const QV4::Value &v, RequiredProperties *requiredProperties, QObject *createdComponent,
57 QQmlObjectCreator *creator);
58 static QQmlError unsetRequiredPropertyToQQmlError(const RequiredPropertyInfo &unsetRequiredProperty);
59
60 virtual void incubateObject(
61 QQmlIncubator *incubationTask,
62 QQmlComponent *component,
63 QQmlEngine *engine,
64 const QQmlRefPointer<QQmlContextData> &context,
65 const QQmlRefPointer<QQmlContextData> &forContext);
66
67 QQmlRefPointer<QQmlTypeData> typeData;
68 QQmlRefPointer<LoadHelper> loadHelper;
69
70 void typeDataReady(QQmlTypeData *) override;
71 void typeDataProgress(QQmlTypeData *, qreal) override;
72
73 void fromTypeData(const QQmlRefPointer<QQmlTypeData> &data);
74
75 QUrl url;
76 qreal progress;
77 std::unique_ptr<QString> inlineComponentName;
78
79 /* points to the sub-object in a QML file that should be instantiated
80 used create instances of QtQml's Component type and indirectly for inline components */
81 int start;
82
83 bool hadTopLevelRequiredProperties() const;
84 QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
85
86 struct AnnotatedQmlError
87 {
88 AnnotatedQmlError() = default;
89
90 AnnotatedQmlError(QQmlError error)
91 : error(std::move(error))
92 {
93 }
94
95
96 AnnotatedQmlError(QQmlError error, bool transient)
97 : error(std::move(error)), isTransient(transient)
98 {
99 }
100 QQmlError error;
101 bool isTransient = false; // tells if the error is temporary (e.g. unset required property)
102 };
103
104 struct ConstructionState {
105 ConstructionState() = default;
106 inline ~ConstructionState();
107 Q_DISABLE_COPY(ConstructionState)
108 inline ConstructionState(ConstructionState &&other) noexcept;
109
110 void swap(ConstructionState &other)
111 {
112 m_creatorOrRequiredProperties.swap(other.m_creatorOrRequiredProperties);
113 }
114
115 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QQmlComponentPrivate::ConstructionState);
116
117 inline void ensureRequiredPropertyStorage(QObject *target);
118 inline RequiredProperties *requiredProperties();
119 inline void addPendingRequiredProperty(
120 const QObject *object, const QQmlPropertyData *propData,
121 const RequiredPropertyInfo &info);
122 inline bool hasUnsetRequiredProperties() const;
123 inline void clearRequiredProperties();
124
125 inline void appendErrors(const QList<QQmlError> &qmlErrors);
126 inline void appendCreatorErrors();
127
128 inline QQmlObjectCreator *creator();
129 inline const QQmlObjectCreator *creator() const;
130 inline void clear();
131 inline bool hasCreator() const;
132 inline QQmlObjectCreator *initCreator(
133 const QQmlRefPointer<QQmlContextData> &parentContext,
134 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
135 const QQmlRefPointer<QQmlContextData> &creationContext);
136
137 QList<AnnotatedQmlError> errors;
138 inline bool isCompletePending() const;
139 inline void setCompletePending(bool isPending);
140
141 QObject *target() const
142 {
143 if (m_creatorOrRequiredProperties.isNull())
144 return nullptr;
145
146 if (m_creatorOrRequiredProperties.isT1()) {
147 const auto &objects = m_creatorOrRequiredProperties.asT1()->allCreatedObjects();
148 return objects.isEmpty() ? nullptr : objects.at(0);
149 }
150
151 Q_ASSERT(m_creatorOrRequiredProperties.isT2());
152 return m_creatorOrRequiredProperties.asT2()->target;
153 }
154
155 private:
156 QBiPointer<QQmlObjectCreator, RequiredPropertiesAndTarget> m_creatorOrRequiredProperties;
157 };
158 ConstructionState state;
159
160 using DeferredState = std::vector<ConstructionState>;
161 static void beginDeferred(QQmlEnginePrivate *enginePriv, QObject *object, DeferredState* deferredState);
162 static void completeDeferred(QQmlEnginePrivate *enginePriv, DeferredState *deferredState);
163
164 static void complete(QQmlEnginePrivate *enginePriv, ConstructionState *state);
165 static QQmlProperty removePropertyFromRequired(QObject *createdComponent, const QString &name, RequiredProperties *requiredProperties,
166 QQmlEngine *engine, bool *wasInRequiredProperties = nullptr);
167
168 QQmlEngine *engine;
169 QQmlGuardedContextData creationContext;
170
171 void clear();
172
173 static QQmlComponentPrivate *get(QQmlComponent *c) {
174 return static_cast<QQmlComponentPrivate *>(QObjectPrivate::get(c));
175 }
176
177 QObject *doBeginCreate(QQmlComponent *q, QQmlContext *context);
178 bool setInitialProperty(QObject *component, const QString &name, const QVariant& value);
179
180 enum CreateBehavior {
181 CreateDefault,
182 CreateWarnAboutRequiredProperties,
183 };
184 QObject *createWithProperties(QObject *parent, const QVariantMap &properties,
185 QQmlContext *context, CreateBehavior behavior = CreateDefault,
186 bool createFromQml = false);
187
188 bool isBound() const { return compilationUnit && (compilationUnit->componentsAreBound()); }
189 void prepareLoadFromModule(
190 QAnyStringView uri, QAnyStringView typeName, QQmlTypeLoader::Mode mode);
191 void completeLoadFromModule(
192 QAnyStringView uri, QAnyStringView typeName);
193};
194
195QQmlComponentPrivate::ConstructionState::~ConstructionState()
196{
197 if (m_creatorOrRequiredProperties.isT1())
198 delete m_creatorOrRequiredProperties.asT1();
199 else
200 delete m_creatorOrRequiredProperties.asT2();
201}
202
203QQmlComponentPrivate::ConstructionState::ConstructionState(ConstructionState &&other) noexcept
204{
205 errors = std::move(other.errors);
206 m_creatorOrRequiredProperties = std::exchange(other.m_creatorOrRequiredProperties, {});
207}
208
209/*!
210 \internal A list of pending required properties that need
211 to be set in order for object construction to be successful.
212 */
213inline RequiredProperties *QQmlComponentPrivate::ConstructionState::requiredProperties() {
214 if (m_creatorOrRequiredProperties.isNull())
215 return nullptr;
216 else if (m_creatorOrRequiredProperties.isT1())
217 return m_creatorOrRequiredProperties.asT1()->requiredProperties();
218 else
219 return m_creatorOrRequiredProperties.asT2();
220}
221
222inline void QQmlComponentPrivate::ConstructionState::addPendingRequiredProperty(
223 const QObject *object, const QQmlPropertyData *propData, const RequiredPropertyInfo &info)
224{
225 Q_ASSERT(requiredProperties());
226 requiredProperties()->insert({object, propData}, info);
227}
228
229inline bool QQmlComponentPrivate::ConstructionState::hasUnsetRequiredProperties() const {
230 auto properties = const_cast<ConstructionState *>(this)->requiredProperties();
231 return properties && !properties->isEmpty();
232}
233
234inline void QQmlComponentPrivate::ConstructionState::clearRequiredProperties()
235{
236 if (auto reqProps = requiredProperties())
237 reqProps->clear();
238}
239
240inline void QQmlComponentPrivate::ConstructionState::appendErrors(const QList<QQmlError> &qmlErrors)
241{
242 for (const QQmlError &e : qmlErrors)
243 errors.emplaceBack(e);
244}
245
246//! \internal Moves errors from creator into construction state itself
247inline void QQmlComponentPrivate::ConstructionState::appendCreatorErrors()
248{
249 if (!hasCreator())
250 return;
251 auto creatorErrorCount = creator()->errors.size();
252 if (creatorErrorCount == 0)
253 return;
254 auto existingErrorCount = errors.size();
255 errors.resize(existingErrorCount + creatorErrorCount);
256 for (qsizetype i = 0; i < creatorErrorCount; ++i)
257 errors[existingErrorCount + i] = AnnotatedQmlError { std::move(creator()->errors[i]) };
258 creator()->errors.clear();
259}
260
261inline QQmlObjectCreator *QQmlComponentPrivate::ConstructionState::creator()
262{
263 if (m_creatorOrRequiredProperties.isT1())
264 return m_creatorOrRequiredProperties.asT1();
265 return nullptr;
266}
267
268inline const QQmlObjectCreator *QQmlComponentPrivate::ConstructionState::creator() const
269{
270 if (m_creatorOrRequiredProperties.isT1())
271 return m_creatorOrRequiredProperties.asT1();
272 return nullptr;
273}
274
275inline bool QQmlComponentPrivate::ConstructionState::hasCreator() const
276{
277 return creator() != nullptr;
278}
279
280inline void QQmlComponentPrivate::ConstructionState::clear()
281{
282 if (m_creatorOrRequiredProperties.isT1()) {
283 delete m_creatorOrRequiredProperties.asT1();
284 m_creatorOrRequiredProperties = static_cast<QQmlObjectCreator *>(nullptr);
285 }
286}
287
288inline QQmlObjectCreator *QQmlComponentPrivate::ConstructionState::initCreator(
289 const QQmlRefPointer<QQmlContextData> &parentContext,
290 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
291 const QQmlRefPointer<QQmlContextData> &creationContext)
292{
293 if (m_creatorOrRequiredProperties.isT1())
294 delete m_creatorOrRequiredProperties.asT1();
295 else
296 delete m_creatorOrRequiredProperties.asT2();
297 m_creatorOrRequiredProperties = new QQmlObjectCreator(
298 parentContext, compilationUnit, creationContext);
299 return m_creatorOrRequiredProperties.asT1();
300}
301
302inline bool QQmlComponentPrivate::ConstructionState::isCompletePending() const
303{
304 return m_creatorOrRequiredProperties.flag();
305}
306
307inline void QQmlComponentPrivate::ConstructionState::setCompletePending(bool isPending)
308{
309 m_creatorOrRequiredProperties.setFlagValue(isPending);
310}
311
312/*!
313 \internal
314 This is meant to be used in the context of QQmlComponent::loadFromModule,
315 when dealing with a C++ type. In that case, we do not have a creator,
316 and need a separate storage for required properties and the target object.
317 */
318inline void QQmlComponentPrivate::ConstructionState::ensureRequiredPropertyStorage(QObject *target)
319{
320 Q_ASSERT(m_creatorOrRequiredProperties.isT2() || m_creatorOrRequiredProperties.isNull());
321 if (m_creatorOrRequiredProperties.isNull())
322 m_creatorOrRequiredProperties = new RequiredPropertiesAndTarget(target);
323 else
324 m_creatorOrRequiredProperties.asT2()->target = target;
325}
326
327QT_END_NAMESPACE
328
329#endif // QQMLCOMPONENT_P_H
\inmodule QtCore
Definition qobject.h:103
void setInitialState(QObject *o) override
Called after the object is first created, but before complex property bindings are evaluated and,...
void statusChanged(Status s) override
Called when the status of the incubator changes.
QQmlComponentIncubator(QV4::Heap::QmlIncubatorObject *inc, IncubationMode mode)
QV4::PersistentValue incubatorObject
The QQmlComponent class encapsulates a QML component definition.
The QQmlError class encapsulates a QML error.
Definition qqmlerror.h:18
Status
Specifies the status of the QQmlIncubator.
Combined button and popup list for selecting options.
DECLARE_HEAP_OBJECT(QmlContext, ExecutionContext)
Definition qjsvalue.h:23
Q_STATIC_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core")
static void removePendingQPropertyBinding(QV4::Value *object, const QString &propertyName, QQmlObjectCreator *creator)
static void QQmlComponent_setQmlParent(QObject *me, QObject *parent)
DEFINE_OBJECT_VTABLE(QV4::QmlIncubatorObject)
V4_DEFINE_EXTENSION(QQmlComponentExtension, componentExtension)
static QQmlParserStatus * parserStatusCast(const QQmlType &type, QObject *rv)
double d
[1]
static ReturnedValue method_set_statusChanged(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_get_status(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_get_object(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
void statusChanged(QQmlIncubator::Status)
void setInitialState(QObject *, RequiredProperties *requiredProperties)
static ReturnedValue method_forceCompletion(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)