6#include <QtQml/qqmlengine.h>
7#include <QtQml/private/qqmlcomponentattached_p.h>
8#include <QtQml/private/qqmljavascriptexpression_p.h>
9#include <QtQml/private/qqmlguardedcontextdata_p.h>
13void QQmlContextData::installContext(QQmlData *ddata, QQmlContextData::QmlObjectKind kind)
16 if (kind == QQmlContextData::DocumentRoot) {
18 Q_ASSERT(ddata->context !=
this);
19 Q_ASSERT(ddata->outerContext);
20 Q_ASSERT(ddata->outerContext !=
this);
21 QQmlRefPointer<QQmlContextData> c = ddata->context;
22 while (QQmlRefPointer<QQmlContextData> linked = c->linkedContext())
24 c->setLinkedContext(
this);
26 ddata->context =
this;
28 ddata->ownContext.reset(ddata->context);
29 }
else if (!ddata->context) {
30 ddata->context =
this;
33 addOwnedObject(ddata);
36QUrl QQmlContextData::resolvedUrl(
const QUrl &src)
const
39 if (src.isRelative() && !src.isEmpty()) {
40 const QUrl ownUrl = url();
41 if (ownUrl.isValid()) {
42 resolved = ownUrl.resolved(src);
44 for (QQmlRefPointer<QQmlContextData> ctxt = parent(); ctxt; ctxt = ctxt->parent()) {
45 const QUrl ctxtUrl = ctxt->url();
46 if (ctxtUrl.isValid()) {
47 resolved = ctxtUrl.resolved(src);
52 if (m_engine && resolved.isEmpty())
53 resolved = m_engine->baseUrl().resolved(src);
59 if (resolved.isEmpty())
62 return m_engine ? m_engine->interceptUrl(resolved, QQmlAbstractUrlInterceptor::UrlString)
66void QQmlContextData::emitDestruction()
68 if (!m_hasEmittedDestruction) {
69 m_hasEmittedDestruction =
true;
74 while (m_componentAttacheds) {
75 QQmlComponentAttached *attached = m_componentAttacheds;
76 attached->removeFromList();
77 emit attached->destruction();
80 for (QQmlRefPointer<QQmlContextData> child = m_childContexts; !child.isNull(); child = child->m_nextChild)
81 child->emitDestruction();
86void QQmlContextData::invalidate()
90 clearChildrenAndSiblings();
91 clearImportedScripts();
97void QQmlContextData::clearContextRecursively()
102 for (
auto ctxIt = m_childContexts; ctxIt; ctxIt = ctxIt->m_nextChild)
103 ctxIt->clearContextRecursively();
108void QQmlContextData::clearChildrenAndSiblings()
110 while (m_childContexts) {
111 Q_ASSERT(m_childContexts !=
this);
112 m_childContexts->invalidate();
116 *m_prevChild = m_nextChild;
117 if (m_nextChild) m_nextChild->m_prevChild = m_prevChild;
118 m_nextChild =
nullptr;
119 m_prevChild =
nullptr;
123void QQmlContextData::clearImportedScripts()
125 if (!m_hasWeakImportedScripts) {
126 if (m_engine && !m_importedScripts.isNullOrUndefined()) {
127 QV4::Scope scope(m_engine->handle());
128 QV4::ScopedValue val(scope, m_importedScripts.value());
129 m_importedScripts.~PersistentValue();
130 new (&m_weakImportedScripts) QV4::WeakValue();
131 m_weakImportedScripts.set(m_engine->handle(), val);
132 m_hasWeakImportedScripts =
true;
135 m_importedScripts.clear();
140void QQmlContextData::clearOwnedObjects()
142 while (m_ownedObjects) {
143 QQmlData *co = m_ownedObjects;
144 m_ownedObjects = m_ownedObjects->nextContextObject;
146 if (co->context ==
this)
147 co->context =
nullptr;
148 co->outerContext =
nullptr;
149 co->nextContextObject =
nullptr;
150 co->prevContextObject =
nullptr;
154void QQmlContextData::clearContextGuards()
156 for (QQmlGuardedContextData *contextGuard = m_contextGuards; contextGuard;) {
158 QQmlGuardedContextData *next = contextGuard->next();
159 contextGuard->setContextData({});
162 m_contextGuards =
nullptr;
165void QQmlContextData::clearIdValues()
167 delete[] std::exchange(m_idValues,
nullptr);
171void QQmlContextData::clearExpressions()
173 QQmlJavaScriptExpression *expression = m_expressions;
175 QQmlJavaScriptExpression *nextExpression = expression->m_nextExpression;
177 expression->m_prevExpression =
nullptr;
178 expression->m_nextExpression =
nullptr;
180 expression->setContext(
nullptr);
182 expression = nextExpression;
184 m_expressions =
nullptr;
187QQmlContextData::~QQmlContextData()
189 Q_ASSERT(refCount() == 0);
193 if (!m_hasWeakImportedScripts) {
196 m_importedScripts.clear();
199 if (m_hasWeakImportedScripts)
200 m_weakImportedScripts.~WeakValue();
202 m_importedScripts.~PersistentValue();
203 m_linkedContext.reset();
205 Q_ASSERT(refCount() == 1);
208 Q_ASSERT(refCount() == 1);
211 Q_ASSERT(refCount() == 1);
213 clearContextGuards();
214 Q_ASSERT(refCount() == 1);
218 Q_ASSERT(refCount() == 1);
220 delete m_publicContext;
222 Q_ASSERT(refCount() == 1);
225void QQmlContextData::refreshExpressionsRecursive(QQmlJavaScriptExpression *expression)
227 QQmlJavaScriptExpression::DeleteWatcher w(expression);
229 if (expression->m_nextExpression)
230 refreshExpressionsRecursive(expression->m_nextExpression);
233 expression->refresh();
236void QQmlContextData::refreshExpressionsRecursive(
bool isGlobal)
239 if (hasExpressionsToRun(isGlobal) && (m_nextChild || m_childContexts)) {
240 QQmlGuardedContextData guard(
this);
243 m_childContexts->refreshExpressionsRecursive(isGlobal);
245 if (guard.isNull())
return;
248 m_nextChild->refreshExpressionsRecursive(isGlobal);
250 if (guard.isNull())
return;
252 if (hasExpressionsToRun(isGlobal))
253 refreshExpressionsRecursive(m_expressions);
255 }
else if (hasExpressionsToRun(isGlobal)) {
256 refreshExpressionsRecursive(m_expressions);
257 }
else if (m_nextChild && m_childContexts) {
258 QQmlGuardedContextData guard(
this);
259 m_childContexts->refreshExpressionsRecursive(isGlobal);
260 if (!guard.isNull() && m_nextChild)
261 m_nextChild->refreshExpressionsRecursive(isGlobal);
262 }
else if (m_nextChild) {
263 m_nextChild->refreshExpressionsRecursive(isGlobal);
264 }
else if (m_childContexts) {
265 m_childContexts->refreshExpressionsRecursive(isGlobal);
272void QQmlContextData::refreshExpressions()
274 bool isGlobal = (m_parent ==
nullptr);
277 if (hasExpressionsToRun(isGlobal) && m_childContexts) {
278 QQmlGuardedContextData guard(
this);
279 m_childContexts->refreshExpressionsRecursive(isGlobal);
280 if (!guard.isNull() && hasExpressionsToRun(isGlobal))
281 refreshExpressionsRecursive(m_expressions);
282 }
else if (hasExpressionsToRun(isGlobal)) {
283 refreshExpressionsRecursive(m_expressions);
284 }
else if (m_childContexts) {
285 m_childContexts->refreshExpressionsRecursive(isGlobal);
289void QQmlContextData::addOwnedObject(QQmlData *data)
291 if (data->outerContext) {
292 if (data->nextContextObject)
293 data->nextContextObject->prevContextObject = data->prevContextObject;
294 if (data->prevContextObject)
295 *data->prevContextObject = data->nextContextObject;
296 else if (data->outerContext->m_ownedObjects == data)
297 data->outerContext->m_ownedObjects = data->nextContextObject;
300 data->outerContext =
this;
302 data->nextContextObject = m_ownedObjects;
303 if (data->nextContextObject)
304 data->nextContextObject->prevContextObject = &data->nextContextObject;
305 data->prevContextObject = &m_ownedObjects;
306 m_ownedObjects = data;
309void QQmlContextData::setIdValue(
int idx, QObject *obj)
311 m_idValues[idx] = obj;
312 m_idValues[idx].setContext(
this);
315QString QQmlContextData::findObjectId(
const QObject *obj)
const
317 for (
int ii = 0; ii < m_idValueCount; ii++) {
318 if (m_idValues[ii] == obj)
319 return propertyName(ii);
322 const QVariant objVariant = QVariant::fromValue(obj);
323 if (m_publicContext) {
324 QQmlContextPrivate *p = QQmlContextPrivate::get(m_publicContext);
325 for (
int ii = 0; ii < p->numPropertyValues(); ++ii)
326 if (p->propertyValue(ii) == objVariant)
327 return propertyName(ii);
330 if (m_contextObject) {
332 for (
const QMetaObject *metaObject = m_contextObject->metaObject();
333 metaObject; metaObject = metaObject->superClass()) {
334 for (
int i = metaObject->propertyOffset(), end = metaObject->propertyCount();
336 const QMetaProperty prop = metaObject->property(i);
337 if (prop.metaType().flags() & QMetaType::PointerToQObject
338 && prop.read(m_contextObject) == objVariant) {
339 return QString::fromUtf8(prop.name());
348void QQmlContextData::initFromTypeCompilationUnit(
const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
int subComponentIndex)
350 m_typeCompilationUnit = unit;
351 m_componentObjectIndex = subComponentIndex == -1 ? 0 : subComponentIndex;
352 Q_ASSERT(!m_idValues);
353 m_idValueCount = m_typeCompilationUnit->objectAt(m_componentObjectIndex)
354 ->nNamedObjectsInComponent;
355 if (m_idValueCount > 0)
356 m_idValues =
new ContextGuard[m_idValueCount];
359void QQmlContextData::addComponentAttached(QQmlComponentAttached *attached)
361 attached->insertIntoList(&m_componentAttacheds);
364void QQmlContextData::addExpression(QQmlJavaScriptExpression *expression)
366 expression->insertIntoList(&m_expressions);
369void QQmlContextData::initPropertyNames()
const
371 if (m_typeCompilationUnit)
372 m_propertyNameCache = m_typeCompilationUnit->namedObjectsPerComponent(m_componentObjectIndex);
374 m_propertyNameCache = QV4::IdentifierHash(m_engine->handle());
375 Q_ASSERT(!m_propertyNameCache.isEmpty());
378QUrl QQmlContextData::url()
const
380 if (m_typeCompilationUnit)
381 return m_typeCompilationUnit->finalUrl();
385QString QQmlContextData::urlString()
const
387 if (m_typeCompilationUnit)
388 return m_typeCompilationUnit->finalUrlString();
389 return m_baseUrlString;
Combined button and popup list for selecting options.