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