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