src/declarative/qml/qdeclarativecontext.cpp
branchGCC_SURGE
changeset 31 5daf16870df6
parent 30 5dc02b23752f
child 33 3e2da88830cd
equal deleted inserted replaced
27:93b982ccede2 31:5daf16870df6
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qdeclarativecontext.h"
       
    43 #include "private/qdeclarativecontext_p.h"
       
    44 
       
    45 #include "private/qdeclarativecomponent_p.h"
       
    46 #include "private/qdeclarativeexpression_p.h"
       
    47 #include "private/qdeclarativeengine_p.h"
       
    48 #include "qdeclarativeengine.h"
       
    49 #include "private/qdeclarativecompiledbindings_p.h"
       
    50 #include "qdeclarativeinfo.h"
       
    51 #include "private/qdeclarativeglobalscriptclass_p.h"
       
    52 
       
    53 #include <qscriptengine.h>
       
    54 #include <QtCore/qvarlengtharray.h>
       
    55 #include <QtCore/qdebug.h>
       
    56 
       
    57 #include <private/qscriptdeclarativeclass_p.h>
       
    58 
       
    59 QT_BEGIN_NAMESPACE
       
    60 
       
    61 QDeclarativeContextPrivate::QDeclarativeContextPrivate()
       
    62 : data(0), notifyIndex(-1)
       
    63 {
       
    64 }
       
    65 
       
    66 /*!
       
    67     \class QDeclarativeContext
       
    68     \since 4.7
       
    69     \brief The QDeclarativeContext class defines a context within a QML engine.
       
    70     \mainclass
       
    71 
       
    72     Contexts allow data to be exposed to the QML components instantiated by the
       
    73     QML engine.
       
    74 
       
    75     Each QDeclarativeContext contains a set of properties, distinct from its QObject 
       
    76     properties, that allow data to be explicitly bound to a context by name.  The 
       
    77     context properties are defined and updated by calling 
       
    78     QDeclarativeContext::setContextProperty().  The following example shows a Qt model 
       
    79     being bound to a context and then accessed from a QML file.
       
    80 
       
    81     \code
       
    82     QDeclarativeEngine engine;
       
    83     QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
       
    84     context->setContextProperty("myModel", modelData);
       
    85 
       
    86     QDeclarativeComponent component(&engine, "ListView { model=myModel }");
       
    87     component.create(context);
       
    88     \endcode
       
    89 
       
    90     To simplify binding and maintaining larger data sets, a context object can be set
       
    91     on a QDeclarativeContext.  All the properties of the context object are available
       
    92     by name in the context, as though they were all individually added through calls
       
    93     to QDeclarativeContext::setContextProperty().  Changes to the property's values are 
       
    94     detected through the property's notify signal.  Setting a context object is both 
       
    95     faster and easier than manually adding and maintaing context property values.
       
    96 
       
    97     The following example has the same effect as the previous one, but it uses a context
       
    98     object.
       
    99 
       
   100     \code
       
   101     class MyDataSet : ... {
       
   102         ...
       
   103         Q_PROPERTY(QAbstractItemModel *myModel READ model NOTIFY modelChanged)
       
   104         ...
       
   105     };
       
   106 
       
   107     MyDataSet *myDataSet = new MyDataSet;
       
   108     QDeclarativeEngine engine;
       
   109     QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
       
   110     context->setContextObject(myDataSet);
       
   111 
       
   112     QDeclarativeComponent component(&engine, "ListView { model=myModel }");
       
   113     component.create(context);
       
   114     \endcode
       
   115 
       
   116     All properties added explicitly by QDeclarativeContext::setContextProperty() take 
       
   117     precedence over the context object's properties.
       
   118 
       
   119     Contexts form a hierarchy.  The root of this heirarchy is the QDeclarativeEngine's
       
   120     \l {QDeclarativeEngine::rootContext()}{root context}.  A component instance can 
       
   121     access the data in its own context, as well as all its ancestor contexts.  Data
       
   122     can be made available to all instances by modifying the 
       
   123     \l {QDeclarativeEngine::rootContext()}{root context}.
       
   124 
       
   125     The following example defines two contexts - \c context1 and \c context2.  The
       
   126     second context overrides the "b" context property inherited from the first with a
       
   127     new value.
       
   128 
       
   129     \code
       
   130     QDeclarativeEngine engine;
       
   131     QDeclarativeContext *context1 = new QDeclarativeContext(engine.rootContext());
       
   132     QDeclarativeContext *context2 = new QDeclarativeContext(context1);
       
   133 
       
   134     context1->setContextProperty("a", 12);
       
   135     context1->setContextProperty("b", 12);
       
   136 
       
   137     context2->setContextProperty("b", 15);
       
   138     \endcode
       
   139 
       
   140     While QML objects instantiated in a context are not strictly owned by that 
       
   141     context, their bindings are.  If a context is destroyed, the property bindings of 
       
   142     outstanding QML objects will stop evaluating.
       
   143 
       
   144     \note Setting the context object or adding new context properties after an object
       
   145     has been created in that context is an expensive operation (essentially forcing all bindings
       
   146     to reevaluate). Thus whenever possible you should complete "setup" of the context
       
   147     before using it to create any objects.
       
   148 */
       
   149 
       
   150 /*! \internal */
       
   151 QDeclarativeContext::QDeclarativeContext(QDeclarativeEngine *e, bool)
       
   152 : QObject(*(new QDeclarativeContextPrivate))
       
   153 {
       
   154     Q_D(QDeclarativeContext);
       
   155     d->data = new QDeclarativeContextData(this);
       
   156 
       
   157     d->data->engine = e;
       
   158 }
       
   159 
       
   160 /*!
       
   161     Create a new QDeclarativeContext as a child of \a engine's root context, and the
       
   162     QObject \a parent.
       
   163 */
       
   164 QDeclarativeContext::QDeclarativeContext(QDeclarativeEngine *engine, QObject *parent)
       
   165 : QObject(*(new QDeclarativeContextPrivate), parent)
       
   166 {
       
   167     Q_D(QDeclarativeContext);
       
   168     d->data = new QDeclarativeContextData(this);
       
   169 
       
   170     d->data->setParent(engine?QDeclarativeContextData::get(engine->rootContext()):0);
       
   171 }
       
   172 
       
   173 /*!
       
   174     Create a new QDeclarativeContext with the given \a parentContext, and the
       
   175     QObject \a parent.
       
   176 */
       
   177 QDeclarativeContext::QDeclarativeContext(QDeclarativeContext *parentContext, QObject *parent)
       
   178 : QObject(*(new QDeclarativeContextPrivate), parent)
       
   179 {
       
   180     Q_D(QDeclarativeContext);
       
   181     d->data = new QDeclarativeContextData(this);
       
   182 
       
   183     d->data->setParent(parentContext?QDeclarativeContextData::get(parentContext):0);
       
   184 }
       
   185 
       
   186 /*!
       
   187     \internal
       
   188 */
       
   189 QDeclarativeContext::QDeclarativeContext(QDeclarativeContextData *data)
       
   190 : QObject(*(new QDeclarativeContextPrivate), 0)
       
   191 {
       
   192     Q_D(QDeclarativeContext);
       
   193     d->data = data;
       
   194 }
       
   195 
       
   196 /*!
       
   197     Destroys the QDeclarativeContext.
       
   198 
       
   199     Any expressions, or sub-contexts dependent on this context will be
       
   200     invalidated, but not destroyed (unless they are parented to the QDeclarativeContext
       
   201     object).
       
   202  */
       
   203 QDeclarativeContext::~QDeclarativeContext()
       
   204 {
       
   205     Q_D(QDeclarativeContext);
       
   206 
       
   207     if (!d->data->isInternal)
       
   208         d->data->destroy();
       
   209 }
       
   210 
       
   211 /*!
       
   212     Returns whether the context is valid.
       
   213 
       
   214     To be valid, a context must have a engine, and it's contextObject(), if any, 
       
   215     must not have been deleted.
       
   216 */
       
   217 bool QDeclarativeContext::isValid() const
       
   218 {
       
   219     Q_D(const QDeclarativeContext);
       
   220     return d->data && d->data->isValid();
       
   221 }
       
   222 
       
   223 /*!
       
   224     Return the context's QDeclarativeEngine, or 0 if the context has no QDeclarativeEngine or the
       
   225     QDeclarativeEngine was destroyed.
       
   226 */
       
   227 QDeclarativeEngine *QDeclarativeContext::engine() const
       
   228 {
       
   229     Q_D(const QDeclarativeContext);
       
   230     return d->data->engine;
       
   231 }
       
   232 
       
   233 /*!
       
   234     Return the context's parent QDeclarativeContext, or 0 if this context has no
       
   235     parent or if the parent has been destroyed.
       
   236 */
       
   237 QDeclarativeContext *QDeclarativeContext::parentContext() const
       
   238 {
       
   239     Q_D(const QDeclarativeContext);
       
   240     return d->data->parent?d->data->parent->asQDeclarativeContext():0;
       
   241 }
       
   242 
       
   243 /*!
       
   244     Return the context object, or 0 if there is no context object.
       
   245 */
       
   246 QObject *QDeclarativeContext::contextObject() const
       
   247 {
       
   248     Q_D(const QDeclarativeContext);
       
   249     return d->data->contextObject;
       
   250 }
       
   251 
       
   252 /*!
       
   253     Set the context \a object.
       
   254 */
       
   255 void QDeclarativeContext::setContextObject(QObject *object)
       
   256 {
       
   257     Q_D(QDeclarativeContext);
       
   258 
       
   259     QDeclarativeContextData *data = d->data;
       
   260 
       
   261     if (data->isInternal) {
       
   262         qWarning("QDeclarativeContext: Cannot set context object for internal context.");
       
   263         return;
       
   264     }
       
   265 
       
   266     if (!isValid()) {
       
   267         qWarning("QDeclarativeContext: Cannot set context object on invalid context.");
       
   268         return;
       
   269     }
       
   270 
       
   271     data->contextObject = object;
       
   272 }
       
   273 
       
   274 /*!
       
   275     Set a the \a value of the \a name property on this context.
       
   276 */
       
   277 void QDeclarativeContext::setContextProperty(const QString &name, const QVariant &value)
       
   278 {
       
   279     Q_D(QDeclarativeContext);
       
   280     if (d->notifyIndex == -1)
       
   281         d->notifyIndex = this->metaObject()->methodCount();
       
   282 
       
   283     QDeclarativeContextData *data = d->data;
       
   284 
       
   285     if (data->isInternal) {
       
   286         qWarning("QDeclarativeContext: Cannot set property on internal context.");
       
   287         return;
       
   288     }
       
   289 
       
   290     if (!isValid()) {
       
   291         qWarning("QDeclarativeContext: Cannot set property on invalid context.");
       
   292         return;
       
   293     }
       
   294 
       
   295     if (data->engine) {
       
   296         bool ok;
       
   297         QObject *o = QDeclarativeEnginePrivate::get(data->engine)->toQObject(value, &ok);
       
   298         if (ok) {
       
   299             setContextProperty(name, o);
       
   300             return;
       
   301         }
       
   302     }
       
   303 
       
   304     if (!data->propertyNames) data->propertyNames = new QDeclarativeIntegerCache(data->engine);
       
   305 
       
   306     int idx = data->propertyNames->value(name);
       
   307     if (idx == -1) {
       
   308         data->propertyNames->add(name, data->idValueCount + d->propertyValues.count());
       
   309         d->propertyValues.append(value);
       
   310 
       
   311         data->refreshExpressions();
       
   312     } else {
       
   313         d->propertyValues[idx] = value;
       
   314         QMetaObject::activate(this, idx + d->notifyIndex, 0);
       
   315     }
       
   316 }
       
   317 
       
   318 /*!
       
   319     Set the \a value of the \a name property on this context.
       
   320 
       
   321     QDeclarativeContext does \bold not take ownership of \a value.
       
   322 */
       
   323 void QDeclarativeContext::setContextProperty(const QString &name, QObject *value)
       
   324 {
       
   325     Q_D(QDeclarativeContext);
       
   326     if (d->notifyIndex == -1)
       
   327         d->notifyIndex = this->metaObject()->methodCount();
       
   328 
       
   329     QDeclarativeContextData *data = d->data;
       
   330 
       
   331     if (data->isInternal) {
       
   332         qWarning("QDeclarativeContext: Cannot set property on internal context.");
       
   333         return;
       
   334     }
       
   335 
       
   336     if (!isValid()) {
       
   337         qWarning("QDeclarativeContext: Cannot set property on invalid context.");
       
   338         return;
       
   339     }
       
   340 
       
   341     if (!data->propertyNames) data->propertyNames = new QDeclarativeIntegerCache(data->engine);
       
   342     int idx = data->propertyNames->value(name);
       
   343 
       
   344     if (idx == -1) {
       
   345         data->propertyNames->add(name, data->idValueCount + d->propertyValues.count());
       
   346         d->propertyValues.append(QVariant::fromValue(value));
       
   347 
       
   348         data->refreshExpressions();
       
   349     } else {
       
   350         d->propertyValues[idx] = QVariant::fromValue(value);
       
   351         QMetaObject::activate(this, idx + d->notifyIndex, 0);
       
   352     }
       
   353 }
       
   354 
       
   355 /*!
       
   356   Returns the value of the \a name property for this context
       
   357   as a QVariant.
       
   358  */
       
   359 QVariant QDeclarativeContext::contextProperty(const QString &name) const
       
   360 {
       
   361     Q_D(const QDeclarativeContext);
       
   362     QVariant value;
       
   363     int idx = -1;
       
   364 
       
   365     QDeclarativeContextData *data = d->data;
       
   366 
       
   367     if (data->propertyNames)
       
   368         idx = data->propertyNames->value(name);
       
   369 
       
   370     if (idx == -1) {
       
   371         QByteArray utf8Name = name.toUtf8();
       
   372         if (data->contextObject) {
       
   373             QObject *obj = data->contextObject;
       
   374             QDeclarativePropertyCache::Data local;
       
   375             QDeclarativePropertyCache::Data *property = 
       
   376                 QDeclarativePropertyCache::property(data->engine, obj, name, local);
       
   377 
       
   378             if (property) value = obj->metaObject()->property(property->coreIndex).read(obj);
       
   379         }
       
   380         if (!value.isValid() && parentContext())
       
   381             value = parentContext()->contextProperty(name);
       
   382     } else {
       
   383         if (idx >= d->propertyValues.count())
       
   384             value = QVariant::fromValue(data->idValues[idx - d->propertyValues.count()].data());
       
   385         else
       
   386             value = d->propertyValues[idx];
       
   387     }
       
   388 
       
   389     return value;
       
   390 }
       
   391 
       
   392 /*!
       
   393     Resolves the URL \a src relative to the URL of the
       
   394     containing component.
       
   395 
       
   396     \sa QDeclarativeEngine::baseUrl(), setBaseUrl()
       
   397 */
       
   398 QUrl QDeclarativeContext::resolvedUrl(const QUrl &src)
       
   399 {
       
   400     Q_D(QDeclarativeContext);
       
   401     return d->data->resolvedUrl(src);
       
   402 }
       
   403 
       
   404 QUrl QDeclarativeContextData::resolvedUrl(const QUrl &src)
       
   405 {
       
   406     QDeclarativeContextData *ctxt = this;
       
   407 
       
   408     if (src.isRelative() && !src.isEmpty()) {
       
   409         if (ctxt) {
       
   410             while(ctxt) {
       
   411                 if(ctxt->url.isValid())
       
   412                     break;
       
   413                 else
       
   414                     ctxt = ctxt->parent;
       
   415             }
       
   416 
       
   417             if (ctxt)
       
   418                 return ctxt->url.resolved(src);
       
   419             else if (engine)
       
   420                 return engine->baseUrl().resolved(src);
       
   421         }
       
   422         return QUrl();
       
   423     } else {
       
   424         return src;
       
   425     }
       
   426 }
       
   427 
       
   428 
       
   429 /*!
       
   430     Explicitly sets the url resolvedUrl() will use for relative references to \a baseUrl.
       
   431 
       
   432     Calling this function will override the url of the containing
       
   433     component used by default.
       
   434 
       
   435     \sa resolvedUrl()
       
   436 */
       
   437 void QDeclarativeContext::setBaseUrl(const QUrl &baseUrl)
       
   438 {
       
   439     Q_D(QDeclarativeContext);
       
   440 
       
   441     d->data->url = baseUrl;
       
   442 }
       
   443 
       
   444 /*!
       
   445     Returns the base url of the component, or the containing component
       
   446     if none is set.
       
   447 */
       
   448 QUrl QDeclarativeContext::baseUrl() const
       
   449 {
       
   450     Q_D(const QDeclarativeContext);
       
   451     const QDeclarativeContextData* data = d->data;
       
   452     while (data && data->url.isEmpty()) 
       
   453         data = data->parent;
       
   454 
       
   455     if (data)
       
   456         return data->url;
       
   457     else
       
   458         return QUrl();
       
   459 }
       
   460 
       
   461 int QDeclarativeContextPrivate::context_count(QDeclarativeListProperty<QObject> *prop)
       
   462 {
       
   463     QDeclarativeContext *context = static_cast<QDeclarativeContext*>(prop->object);
       
   464     QDeclarativeContextPrivate *d = QDeclarativeContextPrivate::get(context);
       
   465     int contextProperty = (int)(intptr_t)prop->data;
       
   466 
       
   467     if (d->propertyValues.at(contextProperty).userType() != qMetaTypeId<QList<QObject*> >()) {
       
   468         return 0;
       
   469     } else {
       
   470         return ((const QList<QObject> *)d->propertyValues.at(contextProperty).constData())->count();
       
   471     }
       
   472 }
       
   473 
       
   474 QObject *QDeclarativeContextPrivate::context_at(QDeclarativeListProperty<QObject> *prop, int index)
       
   475 {
       
   476     QDeclarativeContext *context = static_cast<QDeclarativeContext*>(prop->object);
       
   477     QDeclarativeContextPrivate *d = QDeclarativeContextPrivate::get(context);
       
   478     int contextProperty = (int)(intptr_t)prop->data;
       
   479 
       
   480     if (d->propertyValues.at(contextProperty).userType() != qMetaTypeId<QList<QObject*> >()) {
       
   481         return 0;
       
   482     } else {
       
   483         return ((const QList<QObject*> *)d->propertyValues.at(contextProperty).constData())->at(index);
       
   484     }
       
   485 }
       
   486 
       
   487 
       
   488 QDeclarativeContextData::QDeclarativeContextData()
       
   489 : parent(0), engine(0), isInternal(false), publicContext(0), propertyNames(0), contextObject(0),
       
   490   imports(0), childContexts(0), nextChild(0), prevChild(0), expressions(0), contextObjects(0),
       
   491   contextGuards(0), idValues(0), idValueCount(0), optimizedBindings(0), linkedContext(0),
       
   492   componentAttached(0)
       
   493 {
       
   494 }
       
   495 
       
   496 QDeclarativeContextData::QDeclarativeContextData(QDeclarativeContext *ctxt)
       
   497 : parent(0), engine(0), isInternal(false), publicContext(ctxt), propertyNames(0), contextObject(0),
       
   498   imports(0), childContexts(0), nextChild(0), prevChild(0), expressions(0), contextObjects(0),
       
   499   contextGuards(0), idValues(0), idValueCount(0), optimizedBindings(0), linkedContext(0),
       
   500   componentAttached(0)
       
   501 {
       
   502 }
       
   503 
       
   504 void QDeclarativeContextData::invalidate()
       
   505 {
       
   506     while (childContexts) 
       
   507         childContexts->invalidate();
       
   508 
       
   509     while (componentAttached) {
       
   510         QDeclarativeComponentAttached *a = componentAttached;
       
   511         componentAttached = a->next;
       
   512         if (componentAttached) componentAttached->prev = &componentAttached;
       
   513 
       
   514         a->next = 0;
       
   515         a->prev = 0;
       
   516 
       
   517         emit a->destruction();
       
   518     }
       
   519 
       
   520     if (prevChild) {
       
   521         *prevChild = nextChild;
       
   522         if (nextChild) nextChild->prevChild = prevChild;
       
   523         nextChild = 0;
       
   524         prevChild = 0;
       
   525     }
       
   526 
       
   527     engine = 0;
       
   528     parent = 0;
       
   529 }
       
   530 
       
   531 void QDeclarativeContextData::clearExpressions()
       
   532 {
       
   533     QDeclarativeAbstractExpression *expression = expressions;
       
   534     while (expression) {
       
   535         QDeclarativeAbstractExpression *nextExpression = expression->m_nextExpression;
       
   536 
       
   537         expression->m_context = 0;
       
   538         expression->m_prevExpression = 0;
       
   539         expression->m_nextExpression = 0;
       
   540 
       
   541         expression = nextExpression;
       
   542     }
       
   543     expressions = 0;
       
   544 }
       
   545 
       
   546 void QDeclarativeContextData::destroy()
       
   547 {
       
   548     if (linkedContext) 
       
   549         linkedContext->destroy();
       
   550 
       
   551     if (engine) invalidate();
       
   552 
       
   553     clearExpressions();
       
   554 
       
   555     while (contextObjects) {
       
   556         QDeclarativeData *co = contextObjects;
       
   557         contextObjects = contextObjects->nextContextObject;
       
   558 
       
   559         co->context = 0;
       
   560         co->outerContext = 0;
       
   561         co->nextContextObject = 0;
       
   562         co->prevContextObject = 0;
       
   563     }
       
   564 
       
   565     QDeclarativeGuardedContextData *contextGuard = contextGuards;
       
   566     while (contextGuard) {
       
   567         QDeclarativeGuardedContextData *next = contextGuard->m_next;
       
   568         contextGuard->m_next = 0;
       
   569         contextGuard->m_prev = 0;
       
   570         contextGuard->m_contextData = 0;
       
   571         contextGuard = next;
       
   572     }
       
   573     contextGuards = 0;
       
   574 
       
   575     if (propertyNames)
       
   576         propertyNames->release();
       
   577 
       
   578     if (imports)
       
   579         imports->release();
       
   580 
       
   581     if (optimizedBindings)
       
   582         optimizedBindings->release();
       
   583 
       
   584     delete [] idValues;
       
   585 
       
   586     if (isInternal)
       
   587         delete publicContext;
       
   588 
       
   589     delete this;
       
   590 }
       
   591 
       
   592 void QDeclarativeContextData::setParent(QDeclarativeContextData *p)
       
   593 {
       
   594     if (p) {
       
   595         parent = p;
       
   596         engine = p->engine;
       
   597         nextChild = p->childContexts;
       
   598         if (nextChild) nextChild->prevChild = &nextChild;
       
   599         prevChild = &p->childContexts;
       
   600         p->childContexts = this;
       
   601     }
       
   602 }
       
   603 
       
   604 /* 
       
   605 Refreshes all expressions that could possibly depend on this context.  Refreshing flushes all 
       
   606 context-tree dependent caches in the expressions, and should occur every time the context tree 
       
   607  *structure* (not values) changes.
       
   608 */
       
   609 void QDeclarativeContextData::refreshExpressions()
       
   610 {
       
   611     QDeclarativeContextData *child = childContexts;
       
   612     while (child) {
       
   613         child->refreshExpressions();
       
   614         child = child->nextChild;
       
   615     }
       
   616 
       
   617     QDeclarativeAbstractExpression *expression = expressions;
       
   618     while (expression) {
       
   619         expression->refresh();
       
   620         expression = expression->m_nextExpression;
       
   621     }
       
   622 }
       
   623 
       
   624 void QDeclarativeContextData::addObject(QObject *o)
       
   625 {
       
   626     QDeclarativeData *data = QDeclarativeData::get(o, true);
       
   627 
       
   628     Q_ASSERT(data->context == 0);
       
   629 
       
   630     data->context = this;
       
   631     data->outerContext = this;
       
   632 
       
   633     data->nextContextObject = contextObjects;
       
   634     if (data->nextContextObject) 
       
   635         data->nextContextObject->prevContextObject = &data->nextContextObject;
       
   636     data->prevContextObject = &contextObjects;
       
   637     contextObjects = data;
       
   638 }
       
   639 
       
   640 void QDeclarativeContextData::addImportedScript(const QDeclarativeParser::Object::ScriptBlock &script)
       
   641 {
       
   642     if (!engine) 
       
   643         return;
       
   644 
       
   645     Q_ASSERT(script.codes.count() == 1);
       
   646 
       
   647     QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine);
       
   648     QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
       
   649 
       
   650     const QString &code = script.codes.at(0);
       
   651     const QString &url = script.files.at(0);
       
   652     const QDeclarativeParser::Object::ScriptBlock::Pragmas &pragmas = script.pragmas.at(0);
       
   653 
       
   654     Q_ASSERT(!url.isEmpty());
       
   655 
       
   656     if (pragmas & QDeclarativeParser::Object::ScriptBlock::Shared) {
       
   657 
       
   658         QHash<QString, QScriptValue>::Iterator iter = enginePriv->m_sharedScriptImports.find(url);
       
   659         if (iter == enginePriv->m_sharedScriptImports.end()) {
       
   660             QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
       
   661 
       
   662             scriptContext->pushScope(enginePriv->contextClass->newUrlContext(url));
       
   663             scriptContext->pushScope(enginePriv->globalClass->globalObject());
       
   664         
       
   665             QScriptValue scope = scriptEngine->newObject();
       
   666             scriptContext->setActivationObject(scope);
       
   667             scriptContext->pushScope(scope);
       
   668 
       
   669             scriptEngine->evaluate(code, url, 1);
       
   670 
       
   671             if (scriptEngine->hasUncaughtException()) {
       
   672                 QDeclarativeError error;
       
   673                 QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error);
       
   674                 enginePriv->warning(error);
       
   675             }
       
   676 
       
   677             scriptEngine->popContext();
       
   678 
       
   679             iter = enginePriv->m_sharedScriptImports.insert(url, scope);
       
   680         }
       
   681 
       
   682         importedScripts.append(*iter);
       
   683 
       
   684     } else {
       
   685 
       
   686         QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
       
   687 
       
   688         scriptContext->pushScope(enginePriv->contextClass->newUrlContext(this, 0, url));
       
   689         scriptContext->pushScope(enginePriv->globalClass->globalObject());
       
   690         
       
   691         QScriptValue scope = scriptEngine->newObject();
       
   692         scriptContext->setActivationObject(scope);
       
   693         scriptContext->pushScope(scope);
       
   694 
       
   695         scriptEngine->evaluate(code, url, 1);
       
   696 
       
   697         if (scriptEngine->hasUncaughtException()) {
       
   698             QDeclarativeError error;
       
   699             QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error);
       
   700             enginePriv->warning(error);
       
   701         }
       
   702 
       
   703         scriptEngine->popContext();
       
   704 
       
   705         importedScripts.append(scope);
       
   706 
       
   707     }
       
   708 }
       
   709 
       
   710 void QDeclarativeContextData::setIdProperty(int idx, QObject *obj)
       
   711 {
       
   712     idValues[idx] = obj;
       
   713     idValues[idx].context = this;
       
   714 }
       
   715 
       
   716 void QDeclarativeContextData::setIdPropertyData(QDeclarativeIntegerCache *data)
       
   717 {
       
   718     Q_ASSERT(!propertyNames);
       
   719     propertyNames = data;
       
   720     propertyNames->addref();
       
   721 
       
   722     idValueCount = data->count();
       
   723     idValues = new ContextGuard[idValueCount];
       
   724 }
       
   725 
       
   726 QString QDeclarativeContextData::findObjectId(const QObject *obj) const
       
   727 {
       
   728     if (!idValues || !propertyNames)
       
   729         return QString();
       
   730 
       
   731     for (int i=0; i<idValueCount; i++) {
       
   732         if (idValues[i] == obj)
       
   733             return propertyNames->findId(i);
       
   734     }    
       
   735 
       
   736     if (linkedContext)
       
   737         return linkedContext->findObjectId(obj);
       
   738     return QString();
       
   739 }
       
   740 
       
   741 QDeclarativeContext *QDeclarativeContextData::asQDeclarativeContext()
       
   742 {
       
   743     if (!publicContext) 
       
   744         publicContext = new QDeclarativeContext(this);
       
   745     return publicContext;
       
   746 }
       
   747 
       
   748 QDeclarativeContextPrivate *QDeclarativeContextData::asQDeclarativeContextPrivate()
       
   749 {
       
   750     return QDeclarativeContextPrivate::get(asQDeclarativeContext());
       
   751 }
       
   752 
       
   753 QT_END_NAMESPACE