1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
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
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.
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.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include "private/qdeclarativecontextscriptclass_p.h"
44 #include "private/qdeclarativeengine_p.h"
45 #include "private/qdeclarativecontext_p.h"
46 #include "private/qdeclarativetypenamescriptclass_p.h"
47 #include "private/qdeclarativelistscriptclass_p.h"
48 #include "private/qdeclarativeguard_p.h"
52 struct ContextData : public QScriptDeclarativeClass::Object {
53 ContextData() : overrideObject(0), isSharedContext(true) {}
54 ContextData(QDeclarativeContextData *c, QObject *o)
55 : context(c), scopeObject(o), overrideObject(0), isSharedContext(false), isUrlContext(false) {}
56 QDeclarativeGuardedContextData context;
57 QDeclarativeGuard<QObject> scopeObject;
58 QObject *overrideObject;
59 bool isSharedContext:1;
62 QDeclarativeContextData *getContext(QDeclarativeEngine *engine) {
63 if (isSharedContext) {
64 return QDeclarativeEnginePrivate::get(engine)->sharedContext;
66 return context.contextData();
70 QObject *getScope(QDeclarativeEngine *engine) {
71 if (isSharedContext) {
72 return QDeclarativeEnginePrivate::get(engine)->sharedScope;
74 return scopeObject.data();
79 struct UrlContextData : public ContextData {
80 UrlContextData(QDeclarativeContextData *c, QObject *o, const QString &u)
81 : ContextData(c, o), url(u) {
84 UrlContextData(const QString &u)
85 : ContextData(0, 0), url(u) {
92 The QDeclarativeContextScriptClass handles property access for a QDeclarativeContext
95 QDeclarativeContextScriptClass::QDeclarativeContextScriptClass(QDeclarativeEngine *bindEngine)
96 : QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine),
97 lastScopeObject(0), lastContext(0), lastData(0), lastPropertyIndex(-1)
101 QDeclarativeContextScriptClass::~QDeclarativeContextScriptClass()
105 QScriptValue QDeclarativeContextScriptClass::newContext(QDeclarativeContextData *context, QObject *scopeObject)
107 QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
109 return newObject(scriptEngine, this, new ContextData(context, scopeObject));
112 QScriptValue QDeclarativeContextScriptClass::newUrlContext(QDeclarativeContextData *context, QObject *scopeObject,
115 QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
117 return newObject(scriptEngine, this, new UrlContextData(context, scopeObject, url));
120 QScriptValue QDeclarativeContextScriptClass::newUrlContext(const QString &url)
122 QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
124 return newObject(scriptEngine, this, new UrlContextData(url));
127 QScriptValue QDeclarativeContextScriptClass::newSharedContext()
129 QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
131 return newObject(scriptEngine, this, new ContextData());
134 QDeclarativeContextData *QDeclarativeContextScriptClass::contextFromValue(const QScriptValue &v)
136 if (scriptClass(v) != this)
139 ContextData *data = (ContextData *)object(v);
140 return data->getContext(engine);
143 QUrl QDeclarativeContextScriptClass::urlFromValue(const QScriptValue &v)
145 if (scriptClass(v) != this)
148 ContextData *data = (ContextData *)object(v);
149 if (data->isUrlContext) {
150 return QUrl(static_cast<UrlContextData *>(data)->url);
156 QObject *QDeclarativeContextScriptClass::setOverrideObject(QScriptValue &v, QObject *override)
158 if (scriptClass(v) != this)
161 ContextData *data = (ContextData *)object(v);
162 QObject *rv = data->overrideObject;
163 data->overrideObject = override;
167 QScriptClass::QueryFlags
168 QDeclarativeContextScriptClass::queryProperty(Object *object, const Identifier &name,
169 QScriptClass::QueryFlags flags)
176 lastPropertyIndex = -1;
178 QDeclarativeContextData *bindContext = ((ContextData *)object)->getContext(engine);
179 QObject *scopeObject = ((ContextData *)object)->getScope(engine);
183 QObject *overrideObject = ((ContextData *)object)->overrideObject;
184 if (overrideObject) {
185 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
186 QScriptClass::QueryFlags rv =
187 ep->objectClass->queryProperty(overrideObject, name, flags, bindContext,
188 QDeclarativeObjectScriptClass::ImplicitObject |
189 QDeclarativeObjectScriptClass::SkipAttachedProperties);
191 lastScopeObject = overrideObject;
192 lastContext = bindContext;
197 bool includeTypes = true;
198 while (bindContext) {
199 QScriptClass::QueryFlags rv =
200 queryProperty(bindContext, scopeObject, name, flags, includeTypes);
201 scopeObject = 0; // Only applies to the first context
202 includeTypes = false; // Only applies to the first context
204 bindContext = bindContext->parent;
210 QScriptClass::QueryFlags
211 QDeclarativeContextScriptClass::queryProperty(QDeclarativeContextData *bindContext, QObject *scopeObject,
212 const Identifier &name,
213 QScriptClass::QueryFlags flags,
216 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
218 lastPropertyIndex = bindContext->propertyNames?bindContext->propertyNames->value(name):-1;
219 if (lastPropertyIndex != -1) {
220 lastContext = bindContext;
221 return QScriptClass::HandlesReadAccess;
224 if (includeTypes && bindContext->imports) {
225 QDeclarativeTypeNameCache::Data *data = bindContext->imports->data(name);
229 lastContext = bindContext;
230 lastScopeObject = scopeObject;
231 return QScriptClass::HandlesReadAccess;
236 QScriptClass::QueryFlags rv =
237 ep->objectClass->queryProperty(scopeObject, name, flags, bindContext,
238 QDeclarativeObjectScriptClass::ImplicitObject | QDeclarativeObjectScriptClass::SkipAttachedProperties);
240 lastScopeObject = scopeObject;
241 lastContext = bindContext;
246 if (bindContext->contextObject) {
247 QScriptClass::QueryFlags rv =
248 ep->objectClass->queryProperty(bindContext->contextObject, name, flags, bindContext,
249 QDeclarativeObjectScriptClass::ImplicitObject | QDeclarativeObjectScriptClass::SkipAttachedProperties);
252 lastScopeObject = bindContext->contextObject;
253 lastContext = bindContext;
261 QDeclarativeContextScriptClass::Value
262 QDeclarativeContextScriptClass::property(Object *object, const Identifier &name)
266 QDeclarativeContextData *bindContext = lastContext;
267 Q_ASSERT(bindContext);
269 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
270 QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
274 if (lastData->type) {
275 return Value(scriptEngine, ep->typeNameClass->newObject(lastScopeObject, lastData->type));
276 } else if (lastData->typeNamespace) {
277 return Value(scriptEngine, ep->typeNameClass->newObject(lastScopeObject, lastData->typeNamespace));
279 int index = lastData->importedScriptIndex;
280 if (index < bindContext->importedScripts.count()) {
281 return Value(scriptEngine, bindContext->importedScripts.at(index));
287 } else if (lastScopeObject) {
289 return ep->objectClass->property(lastScopeObject, name);
291 } else if (lastPropertyIndex != -1) {
294 if (lastPropertyIndex < bindContext->idValueCount) {
295 rv = ep->objectClass->newQObject(bindContext->idValues[lastPropertyIndex].data());
297 if (ep->captureProperties)
298 ep->capturedProperties << QDeclarativeEnginePrivate::CapturedProperty(&bindContext->idValues[lastPropertyIndex].bindings);
300 QDeclarativeContextPrivate *cp = bindContext->asQDeclarativeContextPrivate();
301 const QVariant &value = cp->propertyValues.at(lastPropertyIndex);
302 if (value.userType() == qMetaTypeId<QList<QObject*> >()) {
303 rv = ep->listClass->newList(QDeclarativeListProperty<QObject>(bindContext->asQDeclarativeContext(), (void*)lastPropertyIndex, 0, QDeclarativeContextPrivate::context_count, QDeclarativeContextPrivate::context_at), qMetaTypeId<QDeclarativeListProperty<QObject> >());
305 rv = ep->scriptValueFromVariant(value);
308 if (ep->captureProperties)
309 ep->capturedProperties << QDeclarativeEnginePrivate::CapturedProperty(bindContext->asQDeclarativeContext(), -1, lastPropertyIndex + cp->notifyIndex);
312 return Value(scriptEngine, rv);
316 return Value(scriptEngine, lastFunction);
321 void QDeclarativeContextScriptClass::setProperty(Object *object, const Identifier &name,
322 const QScriptValue &value)
325 Q_ASSERT(lastScopeObject);
327 QDeclarativeContextData *bindContext = lastContext;
328 Q_ASSERT(bindContext);
330 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
332 ep->objectClass->setProperty(lastScopeObject, name, value, context(), bindContext);