Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / src / declarative / qml / qdeclarativecontext.cpp
index 4f0d704..709af9e 100644 (file)
@@ -1,34 +1,34 @@
 /****************************************************************************
 **
-** 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_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
 ** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file.  Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 **
 ** In addition, as a special exception, Nokia gives you certain additional
-** rights.  These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 **
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
 **
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
 **
 **
 **
 ****************************************************************************/
 
 #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/qdeclarativeglobalscriptclass_p.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()
@@ -313,7 +312,7 @@ void QDeclarativeContext::setContextProperty(const QString &name, const QVariant
         }
     }
 
-    if (!data->propertyNames) data->propertyNames = new QDeclarativeIntegerCache(data->engine);
+    if (!data->propertyNames) data->propertyNames = new QDeclarativeIntegerCache();
 
     int idx = data->propertyNames->value(name);
     if (idx == -1) {
@@ -350,7 +349,7 @@ void QDeclarativeContext::setContextProperty(const QString &name, QObject *value
         return;
     }
 
-    if (!data->propertyNames) data->propertyNames = new QDeclarativeIntegerCache(data->engine);
+    if (!data->propertyNames) data->propertyNames = new QDeclarativeIntegerCache();
     int idx = data->propertyNames->value(name);
 
     if (idx == -1) {
@@ -383,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);
@@ -402,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.
 
@@ -498,31 +511,25 @@ QObject *QDeclarativeContextPrivate::context_at(QDeclarativeListProperty<QObject
 
 
 QDeclarativeContextData::QDeclarativeContextData()
-: parent(0), engine(0), isInternal(false), ownedByParent(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), 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;
@@ -534,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;
@@ -608,8 +623,15 @@ 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]);
+    }
 
     delete [] idValues;
 
@@ -632,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);
+
     }
 }
 
@@ -686,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)