/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
**
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
**
**
**
+**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qdeclarativecontext.h"
-#include "private/qdeclarativecontext_p.h"
+#include "qdeclarativecontext_p.h"
+#include "qdeclarativecomponentattached_p.h"
-#include "private/qdeclarativecomponent_p.h"
-#include "private/qdeclarativeexpression_p.h"
-#include "private/qdeclarativeengine_p.h"
+#include "qdeclarativecomponent_p.h"
+#include "qdeclarativeexpression_p.h"
+#include "qdeclarativeengine_p.h"
#include "qdeclarativeengine.h"
#include "qdeclarativeinfo.h"
-#include "private/qdeclarativev4bindings_p.h"
-#include "private/qv8bindings_p.h"
+#include <private/qv4bindings_p.h>
+#include <private/qv8bindings_p.h>
-#include <qscriptengine.h>
+#include <qjsengine.h>
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qdebug.h>
-#include <private/qscriptdeclarativeclass_p.h>
-
QT_BEGIN_NAMESPACE
QDeclarativeContextPrivate::QDeclarativeContextPrivate()
QByteArray utf8Name = name.toUtf8();
if (data->contextObject) {
QObject *obj = data->contextObject;
- QDeclarativePropertyCache::Data local;
- QDeclarativePropertyCache::Data *property =
+ QDeclarativePropertyData local;
+ QDeclarativePropertyData *property =
QDeclarativePropertyCache::property(data->engine, obj, name, local);
if (property) value = obj->metaObject()->property(property->coreIndex).read(obj);
}
/*!
+Returns the name of \a object in this context, or an empty string if \a object
+is not named in the context. Objects are named by setContextProperty(), or by ids in
+the case of QML created contexts.
+
+If the object has multiple names, the first is returned.
+*/
+QString QDeclarativeContext::nameForObject(QObject *object) const
+{
+ Q_D(const QDeclarativeContext);
+
+ return d->data->findObjectId(object);
+}
+
+/*!
Resolves the URL \a src relative to the URL of the
containing component.
QDeclarativeContextData::QDeclarativeContextData()
-: parent(0), engine(0), isInternal(false), ownedByParent(false), isJSContext(false), isPragmaLibraryContext(false),
- publicContext(0), propertyNames(0), contextObject(0), imports(0), childContexts(0), nextChild(0), prevChild(0),
- expressions(0), contextObjects(0), contextGuards(0), idValues(0), idValueCount(0), linkedContext(0),
+: parent(0), engine(0), isInternal(false), ownedByParent(false), isJSContext(false),
+ isPragmaLibraryContext(false), unresolvedNames(false), publicContext(0), activeVMEData(0),
+ propertyNames(0), contextObject(0), imports(0), childContexts(0), nextChild(0), prevChild(0),
+ expressions(0), contextObjects(0), contextGuards(0), idValues(0), idValueCount(0), linkedContext(0),
componentAttached(0), v4bindings(0), v8bindings(0)
{
}
QDeclarativeContextData::QDeclarativeContextData(QDeclarativeContext *ctxt)
-: parent(0), engine(0), isInternal(false), ownedByParent(false), isJSContext(false), isPragmaLibraryContext(false),
- publicContext(ctxt), propertyNames(0), contextObject(0), imports(0), childContexts(0), nextChild(0), prevChild(0),
- expressions(0), contextObjects(0), contextGuards(0), idValues(0), idValueCount(0), linkedContext(0),
+: parent(0), engine(0), isInternal(false), ownedByParent(false), isJSContext(false),
+ isPragmaLibraryContext(false), unresolvedNames(false), publicContext(ctxt), activeVMEData(0),
+ propertyNames(0), contextObject(0), imports(0), childContexts(0), nextChild(0), prevChild(0),
+ expressions(0), contextObjects(0), contextGuards(0), idValues(0), idValueCount(0), linkedContext(0),
componentAttached(0), v4bindings(0), v8bindings(0)
{
}
void QDeclarativeContextData::invalidate()
{
- while (childContexts) {
- if (childContexts->ownedByParent) {
- childContexts->destroy();
- } else {
- childContexts->invalidate();
- }
- }
-
while (componentAttached) {
QDeclarativeComponentAttached *a = componentAttached;
componentAttached = a->next;
emit a->destruction();
}
+ while (childContexts) {
+ if (childContexts->ownedByParent) {
+ childContexts->destroy();
+ } else {
+ childContexts->invalidate();
+ }
+ }
+
if (prevChild) {
*prevChild = nextChild;
if (nextChild) nextChild->prevChild = prevChild;
}
}
-/*
-Refreshes all expressions that could possibly depend on this context. Refreshing flushes all
-context-tree dependent caches in the expressions, and should occur every time the context tree
- *structure* (not values) changes.
-*/
-void QDeclarativeContextData::refreshExpressions()
+void QDeclarativeContextData::refreshExpressionsRecursive(QDeclarativeAbstractExpression *expression)
{
- QDeclarativeContextData *child = childContexts;
- while (child) {
- child->refreshExpressions();
- child = child->nextChild;
- }
+ QDeleteWatcher w(expression);
- QDeclarativeAbstractExpression *expression = expressions;
- while (expression) {
+ if (expression->m_nextExpression)
+ refreshExpressionsRecursive(expression->m_nextExpression);
+
+ if (!w.wasDeleted())
expression->refresh();
- expression = expression->m_nextExpression;
+}
+
+static inline bool expressions_to_run(QDeclarativeContextData *ctxt, bool isGlobalRefresh)
+{
+ return ctxt->expressions && (!isGlobalRefresh || ctxt->unresolvedNames);
+}
+
+void QDeclarativeContextData::refreshExpressionsRecursive(bool isGlobal)
+{
+ // For efficiency, we try and minimize the number of guards we have to create
+ if (expressions_to_run(this, isGlobal) && (nextChild || childContexts)) {
+ QDeclarativeGuardedContextData guard(this);
+
+ if (childContexts)
+ childContexts->refreshExpressionsRecursive(isGlobal);
+
+ if (guard.isNull()) return;
+
+ if (nextChild)
+ nextChild->refreshExpressionsRecursive(isGlobal);
+
+ if (guard.isNull()) return;
+
+ if (expressions_to_run(this, isGlobal))
+ refreshExpressionsRecursive(expressions);
+
+ } else if (expressions_to_run(this, isGlobal)) {
+
+ refreshExpressionsRecursive(expressions);
+
+ } else if (nextChild && childContexts) {
+
+ QDeclarativeGuardedContextData guard(this);
+
+ childContexts->refreshExpressionsRecursive(isGlobal);
+
+ if (!guard.isNull() && nextChild)
+ nextChild->refreshExpressionsRecursive(isGlobal);
+
+ } else if (nextChild) {
+
+ nextChild->refreshExpressionsRecursive(isGlobal);
+
+ } else if (childContexts) {
+
+ childContexts->refreshExpressionsRecursive(isGlobal);
+
+ }
+}
+
+// Refreshes all expressions that could possibly depend on this context. Refreshing flushes all
+// context-tree dependent caches in the expressions, and should occur every time the context tree
+// *structure* (not values) changes.
+void QDeclarativeContextData::refreshExpressions()
+{
+ bool isGlobal = (parent == 0);
+
+ // For efficiency, we try and minimize the number of guards we have to create
+ if (expressions_to_run(this, isGlobal) && childContexts) {
+ QDeclarativeGuardedContextData guard(this);
+
+ childContexts->refreshExpressionsRecursive(isGlobal);
+
+ if (!guard.isNull() && expressions_to_run(this, isGlobal))
+ refreshExpressionsRecursive(expressions);
+
+ } else if (expressions_to_run(this, isGlobal)) {
+
+ refreshExpressionsRecursive(expressions);
+
+ } else if (childContexts) {
+
+ childContexts->refreshExpressionsRecursive(isGlobal);
+
}
}
QString QDeclarativeContextData::findObjectId(const QObject *obj) const
{
- if (!idValues || !propertyNames)
+ if (!propertyNames)
return QString();
- for (int i=0; i<idValueCount; i++) {
- if (idValues[i] == obj)
- return propertyNames->findId(i);
+ for (int ii = 0; ii < idValueCount; ii++) {
+ if (idValues[ii] == obj)
+ return propertyNames->findId(ii);
+ }
+
+ if (publicContext) {
+ QDeclarativeContextPrivate *p = QDeclarativeContextPrivate::get(publicContext);
+ for (int ii = 0; ii < p->propertyValues.count(); ++ii)
+ if (p->propertyValues.at(ii) == QVariant::fromValue((QObject *)obj))
+ return propertyNames->findId(ii);
}
if (linkedContext)