Initial import from the monolithic Qt.
[profile/ivi/qtdeclarative.git] / src / declarative / qml / qdeclarativecontextscriptclass.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 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 "private/qdeclarativecontextscriptclass_p.h"
43
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"
49
50 QT_BEGIN_NAMESPACE
51
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;
60     bool isUrlContext:1;
61
62     QDeclarativeContextData *getContext(QDeclarativeEngine *engine) {
63         if (isSharedContext) {
64             return QDeclarativeEnginePrivate::get(engine)->sharedContext;
65         } else {
66             return context.contextData();
67         }
68     }
69
70     QObject *getScope(QDeclarativeEngine *engine) {
71         if (isSharedContext) {
72             return QDeclarativeEnginePrivate::get(engine)->sharedScope;
73         } else {
74             return scopeObject.data();
75         }
76     }
77 };
78
79 struct UrlContextData : public ContextData {
80     UrlContextData(QDeclarativeContextData *c, QObject *o, const QString &u) 
81     : ContextData(c, o), url(u) {
82         isUrlContext = true;
83     }
84     UrlContextData(const QString &u) 
85     : ContextData(0, 0), url(u) {
86         isUrlContext = true;
87     }
88     QString url;
89 };
90
91 /*
92     The QDeclarativeContextScriptClass handles property access for a QDeclarativeContext
93     via QtScript.
94  */
95 QDeclarativeContextScriptClass::QDeclarativeContextScriptClass(QDeclarativeEngine *bindEngine)
96 : QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine),
97   lastScopeObject(0), lastContext(0), lastData(0), lastPropertyIndex(-1)
98 {
99 }
100
101 QDeclarativeContextScriptClass::~QDeclarativeContextScriptClass()
102 {
103 }
104
105 QScriptValue QDeclarativeContextScriptClass::newContext(QDeclarativeContextData *context, QObject *scopeObject)
106 {
107     QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
108
109     return newObject(scriptEngine, this, new ContextData(context, scopeObject));
110 }
111
112 QScriptValue QDeclarativeContextScriptClass::newUrlContext(QDeclarativeContextData *context, QObject *scopeObject, 
113                                                            const QString &url)
114 {
115     QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
116
117     return newObject(scriptEngine, this, new UrlContextData(context, scopeObject, url));
118 }
119
120 QScriptValue QDeclarativeContextScriptClass::newUrlContext(const QString &url)
121 {
122     QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
123
124     return newObject(scriptEngine, this, new UrlContextData(url));
125 }
126
127 QScriptValue QDeclarativeContextScriptClass::newSharedContext()
128 {
129     QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
130
131     return newObject(scriptEngine, this, new ContextData());
132 }
133
134 QDeclarativeContextData *QDeclarativeContextScriptClass::contextFromValue(const QScriptValue &v)
135 {
136     if (scriptClass(v) != this)
137         return 0;
138
139     ContextData *data = (ContextData *)object(v);
140     return data->getContext(engine);
141 }
142
143 QUrl QDeclarativeContextScriptClass::urlFromValue(const QScriptValue &v)
144 {
145     if (scriptClass(v) != this)
146         return QUrl();
147
148     ContextData *data = (ContextData *)object(v);
149     if (data->isUrlContext) {
150         return QUrl(static_cast<UrlContextData *>(data)->url);
151     } else {
152         return QUrl();
153     }
154 }
155
156 QObject *QDeclarativeContextScriptClass::setOverrideObject(QScriptValue &v, QObject *override)
157 {
158     if (scriptClass(v) != this)
159         return 0;
160
161     ContextData *data = (ContextData *)object(v);
162     QObject *rv = data->overrideObject;
163     data->overrideObject = override;
164     return rv;
165 }
166
167 QScriptClass::QueryFlags 
168 QDeclarativeContextScriptClass::queryProperty(Object *object, const Identifier &name, 
169                                      QScriptClass::QueryFlags flags)
170 {
171     Q_UNUSED(flags);
172     
173     lastScopeObject = 0;
174     lastContext = 0;
175     lastData = 0;
176     lastPropertyIndex = -1;
177
178     QDeclarativeContextData *bindContext = ((ContextData *)object)->getContext(engine);
179     QObject *scopeObject = ((ContextData *)object)->getScope(engine);
180     if (!bindContext)
181         return 0;
182
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);
190         if (rv) {
191             lastScopeObject = overrideObject;
192             lastContext = bindContext;
193             return rv;
194         }
195     }
196
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
203         if (rv) return rv;
204         bindContext = bindContext->parent;
205     }
206
207     return 0;
208 }
209
210 QScriptClass::QueryFlags 
211 QDeclarativeContextScriptClass::queryProperty(QDeclarativeContextData *bindContext, QObject *scopeObject,
212                                               const Identifier &name,
213                                               QScriptClass::QueryFlags flags, 
214                                               bool includeTypes)
215 {
216     QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
217
218     lastPropertyIndex = bindContext->propertyNames?bindContext->propertyNames->value(name):-1;
219     if (lastPropertyIndex != -1) {
220         lastContext = bindContext;
221         return QScriptClass::HandlesReadAccess;
222     }
223
224     if (includeTypes && bindContext->imports) { 
225         QDeclarativeTypeNameCache::Data *data = bindContext->imports->data(name);
226
227         if (data)  {
228             lastData = data;
229             lastContext = bindContext;
230             lastScopeObject = scopeObject;
231             return QScriptClass::HandlesReadAccess;
232         }
233     }
234
235     if (scopeObject) {
236         QScriptClass::QueryFlags rv = 
237             ep->objectClass->queryProperty(scopeObject, name, flags, bindContext, 
238                                            QDeclarativeObjectScriptClass::ImplicitObject | QDeclarativeObjectScriptClass::SkipAttachedProperties);
239         if (rv) {
240             lastScopeObject = scopeObject;
241             lastContext = bindContext;
242             return rv;
243         }
244     }
245
246     if (bindContext->contextObject) {
247         QScriptClass::QueryFlags rv = 
248             ep->objectClass->queryProperty(bindContext->contextObject, name, flags, bindContext, 
249                                            QDeclarativeObjectScriptClass::ImplicitObject | QDeclarativeObjectScriptClass::SkipAttachedProperties);
250
251         if (rv) {
252             lastScopeObject = bindContext->contextObject;
253             lastContext = bindContext;
254             return rv;
255         }
256     }
257
258     return 0;
259 }
260
261 QDeclarativeContextScriptClass::Value
262 QDeclarativeContextScriptClass::property(Object *object, const Identifier &name)
263 {
264     Q_UNUSED(object);
265
266     QDeclarativeContextData *bindContext = lastContext;
267     Q_ASSERT(bindContext);
268
269     QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
270     QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
271
272     if (lastData) {
273
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));
278         } else {
279             int index = lastData->importedScriptIndex;
280             if (index < bindContext->importedScripts.count()) {
281                 return Value(scriptEngine, bindContext->importedScripts.at(index));
282             } else {
283                 return Value();
284             }
285         }
286
287     } else if (lastScopeObject) {
288
289         return ep->objectClass->property(lastScopeObject, name);
290
291     } else if (lastPropertyIndex != -1) {
292
293         QScriptValue rv;
294         if (lastPropertyIndex < bindContext->idValueCount) {
295             rv =  ep->objectClass->newQObject(bindContext->idValues[lastPropertyIndex].data());
296
297             if (ep->captureProperties) 
298                 ep->capturedProperties << QDeclarativeEnginePrivate::CapturedProperty(&bindContext->idValues[lastPropertyIndex].bindings);
299         } else {
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> >());
304             } else {
305                 rv = ep->scriptValueFromVariant(value);
306             }
307
308             if (ep->captureProperties) 
309                 ep->capturedProperties << QDeclarativeEnginePrivate::CapturedProperty(bindContext->asQDeclarativeContext(), -1, lastPropertyIndex + cp->notifyIndex);
310         }
311
312         return Value(scriptEngine, rv);
313
314     } else {
315
316         return Value(scriptEngine, lastFunction);
317
318     }
319 }
320
321 void QDeclarativeContextScriptClass::setProperty(Object *object, const Identifier &name, 
322                                         const QScriptValue &value)
323 {
324     Q_UNUSED(object);
325     Q_ASSERT(lastScopeObject);
326
327     QDeclarativeContextData *bindContext = lastContext;
328     Q_ASSERT(bindContext);
329
330     QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
331
332     ep->objectClass->setProperty(lastScopeObject, name, value, context(), bindContext);
333 }
334
335 QT_END_NAMESPACE