Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qqmlcontextdata_p.h
Go to the documentation of this file.
1// Copyright (C) 2020 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 QQMLCONTEXTDATA_P_H
5#define QQMLCONTEXTDATA_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 <QtQml/private/qtqmlglobal_p.h>
19#include <QtQml/private/qqmlcontext_p.h>
20#include <QtQml/private/qqmlguard_p.h>
21#include <QtQml/private/qqmltypenamecache_p.h>
22#include <QtQml/private/qqmlnotifier_p.h>
23#include <QtQml/private/qv4identifierhash_p.h>
24#include <QtQml/private/qv4executablecompilationunit_p.h>
25
27
32
33class Q_QML_PRIVATE_EXPORT QQmlContextData
34{
35public:
38 {
39 return QQmlRefPointer<QQmlContextData>(new QQmlContextData(RefCounted, nullptr, parent),
41 }
42
43 // Owned by the parent. When the parent is reset to nullptr, it will be deref'd.
46 {
47 Q_ASSERT(!parent.isNull());
48 return QQmlRefPointer<QQmlContextData>(new QQmlContextData(OwnedByParent, nullptr, parent));
49 }
50
51 void addref() const { ++m_refCount; }
52 void release() const { if (--m_refCount == 0) delete this; }
53 int count() const { return m_refCount; }
54 int refCount() const { return m_refCount; }
55
57 {
58 return m_typeCompilationUnit;
59 }
60 void initFromTypeCompilationUnit(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
61 int subComponentIndex);
62
64 return QQmlContextPrivate::get(context)->m_data;
65 }
66
67 void emitDestruction();
68 void clearContext();
69 void clearContextRecursively();
70 void invalidate();
71
72 bool isValid() const
73 {
74 return m_engine && (!m_isInternal || !m_contextObject
75 || !QObjectPrivate::get(m_contextObject)->wasDeleted);
76 }
77
78 bool isInternal() const { return m_isInternal; }
79 void setInternal(bool isInternal) { m_isInternal = isInternal; }
80
81 bool isJSContext() const { return m_isJSContext; }
82 void setJSContext(bool isJSContext) { m_isJSContext = isJSContext; }
83
84 bool isPragmaLibraryContext() const { return m_isPragmaLibraryContext; }
85 void setPragmaLibraryContext(bool library) { m_isPragmaLibraryContext = library; }
86
87 QQmlRefPointer<QQmlContextData> parent() const { return m_parent; }
89 {
90 if (!m_parent)
91 return;
92
93 m_parent = nullptr;
94 if (m_ownedByParent) {
95 m_ownedByParent = false;
96 release();
97 }
98 }
99
100 void refreshExpressions();
101
102 void addOwnedObject(QQmlData *ownedObject);
103 QQmlData *ownedObjects() const { return m_ownedObjects; }
104 void setOwnedObjects(QQmlData *ownedObjects) { m_ownedObjects = ownedObjects; }
105
109 };
110 void installContext(QQmlData *ddata, QmlObjectKind kind);
111
112 QUrl resolvedUrl(const QUrl &) const;
113
114 // My containing QQmlContext. If isInternal is true this owns publicContext.
115 // If internal is false publicContext owns this.
117 {
118 if (!m_publicContext)
119 m_publicContext = new QQmlContext(*new QQmlContextPrivate(this));
120 return m_publicContext;
121 }
122
124 {
125 return QQmlContextPrivate::get(asQQmlContext());
126 }
127
128 QObject *contextObject() const { return m_contextObject; }
129 void setContextObject(QObject *contextObject) { m_contextObject = contextObject; }
130
131 QQmlEngine *engine() const { return m_engine; }
132 void setEngine(QQmlEngine *engine) { m_engine = engine; }
133
134 QQmlContext *publicContext() const { return m_publicContext; }
136 {
137 if (!m_publicContext)
138 return;
139
140 m_publicContext = nullptr;
141 if (m_ownedByPublicContext) {
142 m_ownedByPublicContext = false;
143 release();
144 }
145 }
146
147 int propertyIndex(const QString &name) const
148 {
149 ensurePropertyNames();
150 return m_propertyNameCache.value(name);
151 }
152
154 {
155 ensurePropertyNames();
156 return m_propertyNameCache.value(name);
157 }
158
160 {
161 ensurePropertyNames();
162 return m_propertyNameCache.findId(index);
163 }
164
166 {
167 Q_ASSERT(!m_propertyNameCache.isEmpty());
168 m_propertyNameCache.add(name, index);
169 }
170
171 void setExpressions(QQmlJavaScriptExpression *expressions) { m_expressions = expressions; }
173 {
174 QQmlJavaScriptExpression *expressions = m_expressions;
175 m_expressions = nullptr;
176 return expressions;
177 }
178
180 {
181 m_childContexts = childContexts.data();
182 }
183 QQmlRefPointer<QQmlContextData> childContexts() const { return m_childContexts; }
185 {
186 QQmlRefPointer<QQmlContextData> childContexts = m_childContexts;
187 m_childContexts = nullptr;
188 return childContexts;
189 }
190 QQmlRefPointer<QQmlContextData> nextChild() const { return m_nextChild; }
191
192 int numIdValues() const { return m_idValueCount; }
193 void setIdValue(int index, QObject *idValue);
194 bool isIdValueSet(int index) const { return m_idValues[index].wasSet(); }
195 QQmlNotifier *idValueBindings(int index) const { return m_idValues[index].bindings(); }
196 QObject *idValue(int index) const { return m_idValues[index].data(); }
197
198 // Return the outermost id for obj, if any.
199 QString findObjectId(const QObject *obj) const;
200
201 // url() and urlString() prefer the CU's URL over explicitly set baseUrls. They
202 // don't search the context hierarchy.
203 // baseUrl() and baseUrlString() search the context hierarchy and prefer explicit
204 // base URLs over CU Urls.
205
206 QUrl url() const;
207 QString urlString() const;
208
209 void setBaseUrlString(const QString &baseUrlString) { m_baseUrlString = baseUrlString; }
211 {
212 for (const QQmlContextData *data = this; data; data = data->m_parent) {
213 if (!data->m_baseUrlString.isEmpty())
214 return data->m_baseUrlString;
215 if (data->m_typeCompilationUnit)
216 return data->m_typeCompilationUnit->finalUrlString();
217 }
218 return QString();
219 }
220
221 void setBaseUrl(const QUrl &baseUrl) { m_baseUrl = baseUrl; }
222 QUrl baseUrl() const
223 {
224 for (const QQmlContextData *data = this; data; data = data->m_parent) {
225 if (!data->m_baseUrl.isEmpty())
226 return data->m_baseUrl;
227 if (data->m_typeCompilationUnit)
228 return data->m_typeCompilationUnit->finalUrl();
229 }
230 return QUrl();
231 }
232
233 QQmlRefPointer<QQmlTypeNameCache> imports() const { return m_imports; }
234 void setImports(const QQmlRefPointer<QQmlTypeNameCache> &imports) { m_imports = imports; }
235
236 QQmlIncubatorPrivate *incubator() const { return m_hasExtraObject ? nullptr : m_incubator; }
238 {
239 Q_ASSERT(!m_hasExtraObject || m_extraObject == nullptr);
240 m_hasExtraObject = false;
241 m_incubator = incubator;
242 }
243
244 QObject *extraObject() const { return m_hasExtraObject ? m_extraObject : nullptr; }
245 void setExtraObject(QObject *extraObject)
246 {
247 Q_ASSERT(m_hasExtraObject || m_incubator == nullptr);
248 m_hasExtraObject = true;
249 m_extraObject = extraObject;
250 }
251
252 bool isRootObjectInCreation() const { return m_isRootObjectInCreation; }
253 void setRootObjectInCreation(bool rootInCreation) { m_isRootObjectInCreation = rootInCreation; }
254
255 QV4::PersistentValue importedScripts() const { return m_importedScripts; }
256 void setImportedScripts(const QV4::PersistentValue &scripts) { m_importedScripts = scripts; }
257
258 QQmlRefPointer<QQmlContextData> linkedContext() const { return m_linkedContext; }
260
261 bool hasUnresolvedNames() const { return m_unresolvedNames; }
262 void setUnresolvedNames(bool hasUnresolvedNames) { m_unresolvedNames = hasUnresolvedNames; }
263
264 QQmlComponentAttached *componentAttacheds() const { return m_componentAttacheds; }
265 void addComponentAttached(QQmlComponentAttached *attached);
266
267 void addExpression(QQmlJavaScriptExpression *expression);
268
270 return m_typeCompilationUnit && m_typeCompilationUnit->valueTypesAreAddressable();
271 }
272
273private:
275 friend class QQmlContextPrivate;
276
277 enum Ownership {
278 RefCounted,
279 OwnedByParent,
280 OwnedByPublicContext
281 };
282
283 // id guards
284 struct ContextGuard : public QQmlGuard<QObject>
285 {
286 enum Tag {
287 NoTag,
288 ObjectWasSet
289 };
290
291 inline ContextGuard() : QQmlGuard<QObject>(&ContextGuard::objectDestroyedImpl, nullptr), m_context(nullptr) {}
292 inline ContextGuard &operator=(QObject *obj);
293
294 inline bool wasSet() const;
295
296 QQmlNotifier *bindings() { return &m_bindings; }
297 void setContext(const QQmlRefPointer<QQmlContextData> &context)
298 {
299 m_context = context.data();
300 }
301
302 private:
303 inline static void objectDestroyedImpl(QQmlGuardImpl *);
304 // Not refcounted, as it always belongs to the QQmlContextData.
306 QQmlNotifier m_bindings;
307 };
308
309 // It's OK to pass a half-created publicContext here. We will not dereference it during
310 // construction.
312 Ownership ownership, QQmlContext *publicContext,
314 : m_parent(parent.data()),
315 m_engine(engine ? engine : (parent.isNull() ? nullptr : parent->engine())),
316 m_isInternal(false), m_isJSContext(false), m_isPragmaLibraryContext(false),
317 m_unresolvedNames(false), m_hasEmittedDestruction(false), m_isRootObjectInCreation(false),
318 m_ownedByParent(ownership == OwnedByParent),
319 m_ownedByPublicContext(ownership == OwnedByPublicContext), m_hasExtraObject(false),
320 m_dummy(0), m_publicContext(publicContext), m_incubator(nullptr)
321 {
322 Q_ASSERT(!m_ownedByParent || !m_ownedByPublicContext);
323 if (!m_parent)
324 return;
325
326 m_nextChild = m_parent->m_childContexts;
327 if (m_nextChild)
328 m_nextChild->m_prevChild = &m_nextChild;
329 m_prevChild = &m_parent->m_childContexts;
330 m_parent->m_childContexts = this;
331 }
332
334
335 bool hasExpressionsToRun(bool isGlobalRefresh) const
336 {
337 return m_expressions && (!isGlobalRefresh || m_unresolvedNames);
338 }
339
340 void refreshExpressionsRecursive(bool isGlobal);
341 void refreshExpressionsRecursive(QQmlJavaScriptExpression *);
342 void initPropertyNames() const;
343
344 void ensurePropertyNames() const
345 {
346 if (m_propertyNameCache.isEmpty())
347 initPropertyNames();
348 Q_ASSERT(!m_propertyNameCache.isEmpty());
349 }
350
351 // My parent context and engine
352 QQmlContextData *m_parent = nullptr;
353 QQmlEngine *m_engine = nullptr;
354
355 mutable quint32 m_refCount = 1;
356 quint32 m_isInternal:1;
357 quint32 m_isJSContext:1;
358 quint32 m_isPragmaLibraryContext:1;
359 quint32 m_unresolvedNames:1; // True if expressions in this context failed to resolve a toplevel name
360 quint32 m_hasEmittedDestruction:1;
361 quint32 m_isRootObjectInCreation:1;
362 quint32 m_ownedByParent:1;
363 quint32 m_ownedByPublicContext:1;
364 quint32 m_hasExtraObject:1; // used in QQmlDelegateModelItem::dataForObject to find the corresponding QQmlDelegateModelItem of an object
366 QT_WARNING_DISABLE_GCC("-Wattributes")
367 [[maybe_unused]] quint32 m_dummy:23;
369 QQmlContext *m_publicContext = nullptr;
370
371 union {
372 // The incubator that is constructing this context if any
374 // a pointer to extra data, currently only used in QQmlDelegateModel
376 };
377
378 // Compilation unit for contexts that belong to a compiled type.
380
381 // object index in CompiledData::Unit to component that created this context
382 int m_componentObjectIndex = -1;
383
384 // flag indicates whether the context owns the cache (after mutation) or not.
385 mutable QV4::IdentifierHash m_propertyNameCache;
386
387 // Context object
388 QObject *m_contextObject = nullptr;
389
390 // Any script blocks that exist on this context
391 QV4::PersistentValue m_importedScripts; // This is a JS Array
392
393 QUrl m_baseUrl;
394 QString m_baseUrlString;
395
396 // List of imports that apply to this context
398
399 // My children, not refcounted as that would create cyclic references
400 QQmlContextData *m_childContexts = nullptr;
401
402 // My peers in parent's childContexts list; not refcounted
403 QQmlContextData *m_nextChild = nullptr;
404 QQmlContextData **m_prevChild = nullptr;
405
406 // Expressions that use this context
407 QQmlJavaScriptExpression *m_expressions = nullptr;
408
409 // Doubly-linked list of objects that are owned by this context
410 QQmlData *m_ownedObjects = nullptr;
411
412 // Doubly-linked list of context guards (XXX merge with contextObjects)
413 QQmlGuardedContextData *m_contextGuards = nullptr;
414
415 ContextGuard *m_idValues = nullptr;
416 int m_idValueCount = 0;
417
418 // Linked contexts. this owns linkedContext.
419 QQmlRefPointer<QQmlContextData> m_linkedContext;
420
421 // Linked list of uses of the Component attached property in this context
422 QQmlComponentAttached *m_componentAttacheds = nullptr;
423};
424
425QQmlContextData::ContextGuard &QQmlContextData::ContextGuard::operator=(QObject *obj)
426{
428 m_context.setTag(ObjectWasSet);
429 m_bindings.notify(); // For alias connections
430 return *this;
431}
432
433 void QQmlContextData::ContextGuard::objectDestroyedImpl(QQmlGuardImpl *impl)
434{
435 auto This = static_cast<QQmlContextData::ContextGuard *>(impl);
436 if (QObject *contextObject = This->m_context->contextObject()) {
437 if (!QObjectPrivate::get(contextObject)->wasDeleted)
438 This->m_bindings.notify();
439 }
440}
441
442bool QQmlContextData::ContextGuard::wasSet() const
443{
444 return m_context.tag() == ObjectWasSet;
445}
446
448
449#endif // QQMLCONTEXTDATA_P_H
uint wasDeleted
Definition qobject.h:66
static QObjectPrivate * get(QObject *o)
Definition qobject_p.h:153
\inmodule QtCore
Definition qobject.h:90
QObject * idValue(int index) const
void setContextObject(QObject *contextObject)
bool hasUnresolvedNames() const
void setRootObjectInCreation(bool rootInCreation)
int propertyIndex(const QString &name) const
void setOwnedObjects(QQmlData *ownedObjects)
QQmlContext * asQQmlContext()
void setInternal(bool isInternal)
QQmlRefPointer< QQmlTypeNameCache > imports() const
bool isJSContext() const
void setExtraObject(QObject *extraObject)
static QQmlRefPointer< QQmlContextData > get(QQmlContext *context)
bool valueTypesAreAddressable() const
int numIdValues() const
QQmlData * ownedObjects() const
QV4::PersistentValue importedScripts() const
void setEngine(QQmlEngine *engine)
QObject * contextObject() const
QQmlRefPointer< QQmlContextData > nextChild() const
bool isValid() const
QQmlIncubatorPrivate * incubator() const
bool isInternal() const
void setUnresolvedNames(bool hasUnresolvedNames)
QQmlRefPointer< QQmlContextData > takeChildContexts()
QQmlIncubatorPrivate * m_incubator
void setPragmaLibraryContext(bool library)
void setImportedScripts(const QV4::PersistentValue &scripts)
QString baseUrlString() const
QQmlNotifier * idValueBindings(int index) const
void setLinkedContext(const QQmlRefPointer< QQmlContextData > &context)
void release() const
static QQmlRefPointer< QQmlContextData > createChild(const QQmlRefPointer< QQmlContextData > &parent)
void setBaseUrl(const QUrl &baseUrl)
QQmlComponentAttached * componentAttacheds() const
QObject * extraObject() const
void setImports(const QQmlRefPointer< QQmlTypeNameCache > &imports)
void setIncubator(QQmlIncubatorPrivate *incubator)
QQmlRefPointer< QQmlContextData > childContexts() const
void setExpressions(QQmlJavaScriptExpression *expressions)
void addPropertyNameAndIndex(const QString &name, int index)
void setBaseUrlString(const QString &baseUrlString)
static QQmlRefPointer< QQmlContextData > createRefCounted(const QQmlRefPointer< QQmlContextData > &parent)
int propertyIndex(QV4::String *name) const
bool isIdValueSet(int index) const
QQmlRefPointer< QV4::ExecutableCompilationUnit > typeCompilationUnit() const
void addref() const
QQmlRefPointer< QQmlContextData > linkedContext() const
QQmlContext * publicContext() const
QQmlJavaScriptExpression * takeExpressions()
bool isPragmaLibraryContext() const
QQmlRefPointer< QQmlContextData > parent() const
void setChildContexts(const QQmlRefPointer< QQmlContextData > &childContexts)
void setJSContext(bool isJSContext)
QQmlEngine * engine() const
QQmlContextPrivate * asQQmlContextPrivate()
bool isRootObjectInCreation() const
QString propertyName(int index) const
static QQmlContextPrivate * get(QQmlContext *context)
The QQmlContext class defines a context within a QML engine.
Definition qqmlcontext.h:25
The QQmlEngine class provides an environment for instantiating QML components.
Definition qqmlengine.h:57
QQmlGuard< QObject > & operator=(const QQmlGuard< QObject > &o)
T * data() const
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
\inmodule QtCore
Definition qurl.h:94
Combined button and popup list for selecting options.
bool isNull(const T &t)
static void * context
#define QT_WARNING_POP
#define QT_WARNING_DISABLE_GCC(text)
#define QT_WARNING_PUSH
GLuint index
[2]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint name
GLhandleARB obj
[2]
static QUrl resolvedUrl(const QUrl &url, const QQmlRefPointer< QQmlContextData > &context)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
Tag
unsigned int quint32
Definition qtypes.h:45
QUrl url("example.com")
[constructor-url-reference]
QUrl baseUrl
QObject::connect nullptr
sem release()
QJSEngine engine
[0]
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent