7#include <QtQml/qqmlengine.h>
8#include <QtQml/private/qqmlcomponentattached_p.h>
9#include <QtQml/private/qqmljavascriptexpression_p.h>
10#include <QtQml/private/qqmlguardedcontextdata_p.h>
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
196void QQmlContextData::installContext(QQmlData *ddata, QQmlContextData::QmlObjectKind kind)
199 if (kind == QQmlContextData::DocumentRoot) {
200 if (ddata->context) {
201 Q_ASSERT(ddata->context !=
this);
202 Q_ASSERT(ddata->outerContext);
203 Q_ASSERT(ddata->outerContext !=
this);
204 QQmlRefPointer<QQmlContextData> c = ddata->context;
205 while (QQmlRefPointer<QQmlContextData> linked = c->linkedContext())
207 c->setLinkedContext(
this);
209 ddata->context =
this;
211 ddata->ownContext.reset(ddata->context);
212 }
else if (!ddata->context) {
213 ddata->context =
this;
216 addOwnedObject(ddata);
219QUrl QQmlContextData::resolvedUrl(
const QUrl &src)
const
222 if (src.isRelative() && !src.isEmpty()) {
223 const QUrl ownUrl = url();
224 if (ownUrl.isValid()) {
225 resolved = ownUrl.resolved(src);
227 for (QQmlRefPointer<QQmlContextData> ctxt = parent(); ctxt; ctxt = ctxt->parent()) {
228 const QUrl ctxtUrl = ctxt->url();
229 if (ctxtUrl.isValid()) {
230 resolved = ctxtUrl.resolved(src);
235 if (m_engine && resolved.isEmpty())
236 resolved = m_engine->baseUrl().resolved(src);
242 if (resolved.isEmpty())
245 return m_engine ? m_engine->interceptUrl(resolved, QQmlAbstractUrlInterceptor::UrlString)
249void QQmlContextData::emitDestruction()
251 if (!m_hasEmittedDestruction) {
252 m_hasEmittedDestruction =
true;
257 while (m_componentAttacheds) {
258 QQmlComponentAttached *attached = m_componentAttacheds;
259 attached->removeFromList();
260 emit attached->destruction();
263 for (QQmlRefPointer<QQmlContextData> child = m_childContexts; !child.isNull(); child = child->m_nextChild)
264 child->emitDestruction();
269void QQmlContextData::invalidate()
273 clearChildrenAndSiblings();
274 clearImportedScripts();
280void QQmlContextData::clearContextRecursively()
285 for (
auto ctxIt = m_childContexts; ctxIt; ctxIt = ctxIt->m_nextChild)
286 ctxIt->clearContextRecursively();
291void QQmlContextData::clearChildrenAndSiblings()
293 while (m_childContexts) {
294 Q_ASSERT(m_childContexts !=
this);
295 m_childContexts->invalidate();
299 *m_prevChild = m_nextChild;
300 if (m_nextChild) m_nextChild->m_prevChild = m_prevChild;
301 m_nextChild =
nullptr;
302 m_prevChild =
nullptr;
306void QQmlContextData::clearImportedScripts()
308 if (!m_hasWeakImportedScripts) {
309 if (m_engine && !m_importedScripts.isNullOrUndefined()) {
310 QV4::Scope scope(m_engine->handle());
311 QV4::ScopedValue val(scope, m_importedScripts.value());
312 m_importedScripts.~PersistentValue();
313 new (&m_weakImportedScripts) QV4::WeakValue();
314 m_weakImportedScripts.set(m_engine->handle(), val);
315 m_hasWeakImportedScripts =
true;
318 m_importedScripts.clear();
323void QQmlContextData::clearOwnedObjects()
325 while (m_ownedObjects) {
326 QQmlData *co = m_ownedObjects;
327 m_ownedObjects = m_ownedObjects->nextContextObject;
329 if (co->context ==
this)
330 co->context =
nullptr;
331 co->outerContext =
nullptr;
332 co->nextContextObject =
nullptr;
333 co->prevContextObject =
nullptr;
337void QQmlContextData::clearContextGuards()
339 for (QQmlGuardedContextData *contextGuard = m_contextGuards; contextGuard;) {
341 QQmlGuardedContextData *next = contextGuard->next();
342 contextGuard->setContextData({});
345 m_contextGuards =
nullptr;
348void QQmlContextData::clearIdValues()
350 delete[] std::exchange(m_idValues,
nullptr);
354void QQmlContextData::clearExpressions()
356 QQmlJavaScriptExpression *expression = m_expressions;
358 QQmlJavaScriptExpression *nextExpression = expression->m_nextExpression;
360 expression->m_prevExpression =
nullptr;
361 expression->m_nextExpression =
nullptr;
363 expression->setContext(
nullptr);
365 expression = nextExpression;
367 m_expressions =
nullptr;
370QQmlContextData::~QQmlContextData()
372 Q_ASSERT(refCount() == 0);
376 if (!m_hasWeakImportedScripts) {
379 m_importedScripts.clear();
382 if (m_hasWeakImportedScripts)
383 m_weakImportedScripts.~WeakValue();
385 m_importedScripts.~PersistentValue();
386 m_linkedContext.reset();
388 Q_ASSERT(refCount() == 1);
391 Q_ASSERT(refCount() == 1);
394 Q_ASSERT(refCount() == 1);
396 clearContextGuards();
397 Q_ASSERT(refCount() == 1);
401 Q_ASSERT(refCount() == 1);
403 delete m_publicContext;
405 Q_ASSERT(refCount() == 1);
408void QQmlContextData::refreshExpressionsRecursive(QQmlJavaScriptExpression *expression)
410 QQmlJavaScriptExpression::DeleteWatcher w(expression);
412 if (expression->m_nextExpression)
413 refreshExpressionsRecursive(expression->m_nextExpression);
416 expression->refresh();
419void QQmlContextData::refreshExpressionsRecursive(
bool isGlobal)
422 if (hasExpressionsToRun(isGlobal) && (m_nextChild || m_childContexts)) {
423 QQmlGuardedContextData guard(
this);
426 m_childContexts->refreshExpressionsRecursive(isGlobal);
428 if (guard.isNull())
return;
431 m_nextChild->refreshExpressionsRecursive(isGlobal);
433 if (guard.isNull())
return;
435 if (hasExpressionsToRun(isGlobal))
436 refreshExpressionsRecursive(m_expressions);
438 }
else if (hasExpressionsToRun(isGlobal)) {
439 refreshExpressionsRecursive(m_expressions);
440 }
else if (m_nextChild && m_childContexts) {
441 QQmlGuardedContextData guard(
this);
442 m_childContexts->refreshExpressionsRecursive(isGlobal);
443 if (!guard.isNull() && m_nextChild)
444 m_nextChild->refreshExpressionsRecursive(isGlobal);
445 }
else if (m_nextChild) {
446 m_nextChild->refreshExpressionsRecursive(isGlobal);
447 }
else if (m_childContexts) {
448 m_childContexts->refreshExpressionsRecursive(isGlobal);
455void QQmlContextData::refreshExpressions()
457 bool isGlobal = (m_parent ==
nullptr);
460 if (hasExpressionsToRun(isGlobal) && m_childContexts) {
461 QQmlGuardedContextData guard(
this);
462 m_childContexts->refreshExpressionsRecursive(isGlobal);
463 if (!guard.isNull() && hasExpressionsToRun(isGlobal))
464 refreshExpressionsRecursive(m_expressions);
465 }
else if (hasExpressionsToRun(isGlobal)) {
466 refreshExpressionsRecursive(m_expressions);
467 }
else if (m_childContexts) {
468 m_childContexts->refreshExpressionsRecursive(isGlobal);
472void QQmlContextData::addOwnedObject(QQmlData *data)
474 if (data->outerContext) {
475 if (data->nextContextObject)
476 data->nextContextObject->prevContextObject = data->prevContextObject;
477 if (data->prevContextObject)
478 *data->prevContextObject = data->nextContextObject;
479 else if (data->outerContext->m_ownedObjects == data)
480 data->outerContext->m_ownedObjects = data->nextContextObject;
483 data->outerContext =
this;
485 data->nextContextObject = m_ownedObjects;
486 if (data->nextContextObject)
487 data->nextContextObject->prevContextObject = &data->nextContextObject;
488 data->prevContextObject = &m_ownedObjects;
489 m_ownedObjects = data;
492void QQmlContextData::setIdValue(
int idx, QObject *obj)
494 m_idValues[idx] = obj;
495 m_idValues[idx].setContext(
this);
498QString QQmlContextData::findObjectId(
const QObject *obj)
const
500 for (
int ii = 0; ii < m_idValueCount; ii++) {
501 if (m_idValues[ii] == obj)
502 return propertyName(ii);
505 const QVariant objVariant = QVariant::fromValue(obj);
506 if (m_publicContext) {
507 QQmlContextPrivate *p = QQmlContextPrivate::get(m_publicContext);
508 for (
int ii = 0; ii < p->numPropertyValues(); ++ii)
509 if (p->propertyValue(ii) == objVariant)
510 return propertyName(ii);
513 if (m_contextObject) {
515 for (
const QMetaObject *metaObject = m_contextObject->metaObject();
516 metaObject; metaObject = metaObject->superClass()) {
517 for (
int i = metaObject->propertyOffset(), end = metaObject->propertyCount();
519 const QMetaProperty prop = metaObject->property(i);
520 if (prop.metaType().flags() & QMetaType::PointerToQObject
521 && prop.read(m_contextObject) == objVariant) {
522 return QString::fromUtf8(prop.name());
531void QQmlContextData::setTypeCompilationUnit(
532 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit)
534 m_propertyNameCache = QV4::IdentifierHash();
535 delete[] std::exchange(m_idValues,
nullptr);
536 initFromTypeCompilationUnit(unit, m_componentObjectIndex);
539void QQmlContextData::initFromTypeCompilationUnit(
const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
int subComponentIndex)
541 m_typeCompilationUnit = unit;
542 m_componentObjectIndex = subComponentIndex == -1 ? 0 : subComponentIndex;
543 Q_ASSERT(!m_idValues);
544 m_idValueCount = m_typeCompilationUnit->objectAt(m_componentObjectIndex)
545 ->nNamedObjectsInComponent;
546 if (m_idValueCount > 0)
547 m_idValues =
new ContextGuard[m_idValueCount];
550void QQmlContextData::addComponentAttached(QQmlComponentAttached *attached)
552 attached->insertIntoList(&m_componentAttacheds);
555void QQmlContextData::addExpression(QQmlJavaScriptExpression *expression)
557 expression->insertIntoList(&m_expressions);
560void QQmlContextData::initPropertyNames()
const
562 if (m_typeCompilationUnit) {
563 m_propertyNameCache = m_typeCompilationUnit->namedObjectsPerComponent(m_componentObjectIndex);
565 auto engine = m_engine;
571 for (
auto ctxt = parent(); ctxt; ctxt = ctxt->parent()) {
572 if ((engine = ctxt->engine()))
577 m_propertyNameCache = QV4::IdentifierHash(engine->handle());
579 Q_ASSERT(m_propertyNameCache.isValid());
582QUrl QQmlContextData::url()
const
584 if (m_typeCompilationUnit)
585 return m_typeCompilationUnit->finalUrl();
589QString QQmlContextData::urlString()
const
591 if (m_typeCompilationUnit)
592 return m_typeCompilationUnit->finalUrlString();
593 return m_baseUrlString;
Combined button and popup list for selecting options.