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>
14void QQmlContextData::installContext(QQmlData *ddata, QQmlContextData::QmlObjectKind kind)
17 if (kind == QQmlContextData::DocumentRoot) {
19 Q_ASSERT(ddata->context !=
this);
20 Q_ASSERT(ddata->outerContext);
21 Q_ASSERT(ddata->outerContext !=
this);
22 QQmlRefPointer<QQmlContextData> c = ddata->context;
23 while (QQmlRefPointer<QQmlContextData> linked = c->linkedContext())
25 c->setLinkedContext(
this);
27 ddata->context =
this;
29 ddata->ownContext.reset(ddata->context);
30 }
else if (!ddata->context) {
31 ddata->context =
this;
34 addOwnedObject(ddata);
37QUrl QQmlContextData::resolvedUrl(
const QUrl &src)
const
40 if (src.isRelative() && !src.isEmpty()) {
41 const QUrl ownUrl = url();
42 if (ownUrl.isValid()) {
43 resolved = ownUrl.resolved(src);
45 for (QQmlRefPointer<QQmlContextData> ctxt = parent(); ctxt; ctxt = ctxt->parent()) {
46 const QUrl ctxtUrl = ctxt->url();
47 if (ctxtUrl.isValid()) {
48 resolved = ctxtUrl.resolved(src);
53 if (m_engine && resolved.isEmpty())
54 resolved = m_engine->baseUrl().resolved(src);
60 if (resolved.isEmpty())
63 return m_engine ? m_engine->interceptUrl(resolved, QQmlAbstractUrlInterceptor::UrlString)
67void QQmlContextData::emitDestruction()
69 if (!m_hasEmittedDestruction) {
70 m_hasEmittedDestruction =
true;
75 while (m_componentAttacheds) {
76 QQmlComponentAttached *attached = m_componentAttacheds;
77 attached->removeFromList();
78 emit attached->destruction();
81 for (QQmlRefPointer<QQmlContextData> child = m_childContexts; !child.isNull(); child = child->m_nextChild)
82 child->emitDestruction();
87void QQmlContextData::invalidate()
91 clearChildrenAndSiblings();
92 clearImportedScripts();
98void QQmlContextData::clearContextRecursively()
103 for (
auto ctxIt = m_childContexts; ctxIt; ctxIt = ctxIt->m_nextChild)
104 ctxIt->clearContextRecursively();
109void QQmlContextData::clearChildrenAndSiblings()
111 while (m_childContexts) {
112 Q_ASSERT(m_childContexts !=
this);
113 m_childContexts->invalidate();
117 *m_prevChild = m_nextChild;
118 if (m_nextChild) m_nextChild->m_prevChild = m_prevChild;
119 m_nextChild =
nullptr;
120 m_prevChild =
nullptr;
124void QQmlContextData::clearImportedScripts()
126 if (!m_hasWeakImportedScripts) {
127 if (m_engine && !m_importedScripts.isNullOrUndefined()) {
128 QV4::Scope scope(m_engine->handle());
129 QV4::ScopedValue val(scope, m_importedScripts.value());
130 m_importedScripts.~PersistentValue();
131 new (&m_weakImportedScripts) QV4::WeakValue();
132 m_weakImportedScripts.set(m_engine->handle(), val);
133 m_hasWeakImportedScripts =
true;
136 m_importedScripts.clear();
141void QQmlContextData::clearOwnedObjects()
143 while (m_ownedObjects) {
144 QQmlData *co = m_ownedObjects;
145 m_ownedObjects = m_ownedObjects->nextContextObject;
147 if (co->context ==
this)
148 co->context =
nullptr;
149 co->outerContext =
nullptr;
150 co->nextContextObject =
nullptr;
151 co->prevContextObject =
nullptr;
155void QQmlContextData::clearContextGuards()
157 for (QQmlGuardedContextData *contextGuard = m_contextGuards; contextGuard;) {
159 QQmlGuardedContextData *next = contextGuard->next();
160 contextGuard->setContextData({});
163 m_contextGuards =
nullptr;
166void QQmlContextData::clearIdValues()
168 delete[] std::exchange(m_idValues,
nullptr);
172void QQmlContextData::clearExpressions()
174 QQmlJavaScriptExpression *expression = m_expressions;
176 QQmlJavaScriptExpression *nextExpression = expression->m_nextExpression;
178 expression->m_prevExpression =
nullptr;
179 expression->m_nextExpression =
nullptr;
181 expression->setContext(
nullptr);
183 expression = nextExpression;
185 m_expressions =
nullptr;
188QQmlContextData::~QQmlContextData()
190 Q_ASSERT(refCount() == 0);
194 if (!m_hasWeakImportedScripts) {
197 m_importedScripts.clear();
200 if (m_hasWeakImportedScripts)
201 m_weakImportedScripts.~WeakValue();
203 m_importedScripts.~PersistentValue();
204 m_linkedContext.reset();
206 Q_ASSERT(refCount() == 1);
209 Q_ASSERT(refCount() == 1);
212 Q_ASSERT(refCount() == 1);
214 clearContextGuards();
215 Q_ASSERT(refCount() == 1);
219 Q_ASSERT(refCount() == 1);
221 delete m_publicContext;
223 Q_ASSERT(refCount() == 1);
226void QQmlContextData::refreshExpressionsRecursive(QQmlJavaScriptExpression *expression)
228 QQmlJavaScriptExpression::DeleteWatcher w(expression);
230 if (expression->m_nextExpression)
231 refreshExpressionsRecursive(expression->m_nextExpression);
234 expression->refresh();
237void QQmlContextData::refreshExpressionsRecursive(
bool isGlobal)
240 if (hasExpressionsToRun(isGlobal) && (m_nextChild || m_childContexts)) {
241 QQmlGuardedContextData guard(
this);
244 m_childContexts->refreshExpressionsRecursive(isGlobal);
246 if (guard.isNull())
return;
249 m_nextChild->refreshExpressionsRecursive(isGlobal);
251 if (guard.isNull())
return;
253 if (hasExpressionsToRun(isGlobal))
254 refreshExpressionsRecursive(m_expressions);
256 }
else if (hasExpressionsToRun(isGlobal)) {
257 refreshExpressionsRecursive(m_expressions);
258 }
else if (m_nextChild && m_childContexts) {
259 QQmlGuardedContextData guard(
this);
260 m_childContexts->refreshExpressionsRecursive(isGlobal);
261 if (!guard.isNull() && m_nextChild)
262 m_nextChild->refreshExpressionsRecursive(isGlobal);
263 }
else if (m_nextChild) {
264 m_nextChild->refreshExpressionsRecursive(isGlobal);
265 }
else if (m_childContexts) {
266 m_childContexts->refreshExpressionsRecursive(isGlobal);
273void QQmlContextData::refreshExpressions()
275 bool isGlobal = (m_parent ==
nullptr);
278 if (hasExpressionsToRun(isGlobal) && m_childContexts) {
279 QQmlGuardedContextData guard(
this);
280 m_childContexts->refreshExpressionsRecursive(isGlobal);
281 if (!guard.isNull() && hasExpressionsToRun(isGlobal))
282 refreshExpressionsRecursive(m_expressions);
283 }
else if (hasExpressionsToRun(isGlobal)) {
284 refreshExpressionsRecursive(m_expressions);
285 }
else if (m_childContexts) {
286 m_childContexts->refreshExpressionsRecursive(isGlobal);
290void QQmlContextData::addOwnedObject(QQmlData *data)
292 if (data->outerContext) {
293 if (data->nextContextObject)
294 data->nextContextObject->prevContextObject = data->prevContextObject;
295 if (data->prevContextObject)
296 *data->prevContextObject = data->nextContextObject;
297 else if (data->outerContext->m_ownedObjects == data)
298 data->outerContext->m_ownedObjects = data->nextContextObject;
301 data->outerContext =
this;
303 data->nextContextObject = m_ownedObjects;
304 if (data->nextContextObject)
305 data->nextContextObject->prevContextObject = &data->nextContextObject;
306 data->prevContextObject = &m_ownedObjects;
307 m_ownedObjects = data;
310void QQmlContextData::setIdValue(
int idx, QObject *obj)
312 m_idValues[idx] = obj;
313 m_idValues[idx].setContext(
this);
316QString QQmlContextData::findObjectId(
const QObject *obj)
const
318 for (
int ii = 0; ii < m_idValueCount; ii++) {
319 if (m_idValues[ii] == obj)
320 return propertyName(ii);
323 const QVariant objVariant = QVariant::fromValue(obj);
324 if (m_publicContext) {
325 QQmlContextPrivate *p = QQmlContextPrivate::get(m_publicContext);
326 for (
int ii = 0; ii < p->numPropertyValues(); ++ii)
327 if (p->propertyValue(ii) == objVariant)
328 return propertyName(ii);
331 if (m_contextObject) {
333 for (
const QMetaObject *metaObject = m_contextObject->metaObject();
334 metaObject; metaObject = metaObject->superClass()) {
335 for (
int i = metaObject->propertyOffset(), end = metaObject->propertyCount();
337 const QMetaProperty prop = metaObject->property(i);
338 if (prop.metaType().flags() & QMetaType::PointerToQObject
339 && prop.read(m_contextObject) == objVariant) {
340 return QString::fromUtf8(prop.name());
349void QQmlContextData::initFromTypeCompilationUnit(
const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
int subComponentIndex)
351 m_typeCompilationUnit = unit;
352 m_componentObjectIndex = subComponentIndex == -1 ? 0 : subComponentIndex;
353 Q_ASSERT(!m_idValues);
354 m_idValueCount = m_typeCompilationUnit->objectAt(m_componentObjectIndex)
355 ->nNamedObjectsInComponent;
356 if (m_idValueCount > 0)
357 m_idValues =
new ContextGuard[m_idValueCount];
360void QQmlContextData::addComponentAttached(QQmlComponentAttached *attached)
362 attached->insertIntoList(&m_componentAttacheds);
365void QQmlContextData::addExpression(QQmlJavaScriptExpression *expression)
367 expression->insertIntoList(&m_expressions);
370void QQmlContextData::initPropertyNames()
const
372 if (m_typeCompilationUnit)
373 m_propertyNameCache = m_typeCompilationUnit->namedObjectsPerComponent(m_componentObjectIndex);
375 m_propertyNameCache = QV4::IdentifierHash(m_engine->handle());
376 Q_ASSERT(m_propertyNameCache.isValid());
379QUrl QQmlContextData::url()
const
381 if (m_typeCompilationUnit)
382 return m_typeCompilationUnit->finalUrl();
386QString QQmlContextData::urlString()
const
388 if (m_typeCompilationUnit)
389 return m_typeCompilationUnit->finalUrlString();
390 return m_baseUrlString;
Combined button and popup list for selecting options.