Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / src / declarative / qml / qdeclarativecontext.cpp
index 2b96d8f..709af9e 100644 (file)
@@ -1,8 +1,7 @@
 /****************************************************************************
 **
-** 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/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()
@@ -382,8 +382,8 @@ QVariant QDeclarativeContext::contextProperty(const QString &name) const
         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);
@@ -401,6 +401,20 @@ QVariant QDeclarativeContext::contextProperty(const QString &name) const
 }
 
 /*!
+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.
 
@@ -497,31 +511,25 @@ QObject *QDeclarativeContextPrivate::context_at(QDeclarativeListProperty<QObject
 
 
 QDeclarativeContextData::QDeclarativeContextData()
-: parent(0), engine(0), isInternal(false), ownedByParent(false), isJSContext(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), optimizedBindings(0), 
-  linkedContext(0), componentAttached(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), publicContext(ctxt), 
-  propertyNames(0), contextObject(0), imports(0), childContexts(0), nextChild(0), prevChild(0), 
-  expressions(0), contextObjects(0), contextGuards(0), idValues(0), idValueCount(0), optimizedBindings(0), 
-  linkedContext(0), componentAttached(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;
@@ -533,6 +541,14 @@ void QDeclarativeContextData::invalidate()
         emit a->destruction();
     }
 
+    while (childContexts) {
+        if (childContexts->ownedByParent) {
+            childContexts->destroy();
+        } else {
+            childContexts->invalidate();
+        }
+    }
+
     if (prevChild) {
         *prevChild = nextChild;
         if (nextChild) nextChild->prevChild = prevChild;
@@ -607,8 +623,11 @@ void QDeclarativeContextData::destroy()
     if (imports)
         imports->release();
 
-    if (optimizedBindings)
-        optimizedBindings->release();
+    if (v4bindings)
+        v4bindings->release();
+
+    if (v8bindings)
+        v8bindings->release();
 
     for (int ii = 0; ii < importedScripts.count(); ++ii) {
         qPersistentDispose(importedScripts[ii]);
@@ -635,23 +654,89 @@ void QDeclarativeContextData::setParent(QDeclarativeContextData *p, bool parentT
     }
 }
 
-/*
-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);
+
     }
 }
 
@@ -689,12 +774,19 @@ void QDeclarativeContextData::setIdPropertyData(QDeclarativeIntegerCache *data)
 
 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)