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 | ** Commercial Usage
|
---|
11 | ** Licensees holding valid Qt Commercial licenses may use this file in
|
---|
12 | ** accordance with the Qt Commercial License Agreement provided with the
|
---|
13 | ** Software or, alternatively, in accordance with the terms contained in
|
---|
14 | ** a written agreement between you and Nokia.
|
---|
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 | ** GNU General Public License Usage
|
---|
29 | ** Alternatively, this file may be used under the terms of the GNU
|
---|
30 | ** General Public License version 3.0 as published by the Free Software
|
---|
31 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
---|
32 | ** packaging of this file. Please review the following information to
|
---|
33 | ** ensure the GNU General Public License version 3.0 requirements will be
|
---|
34 | ** met: http://www.gnu.org/copyleft/gpl.html.
|
---|
35 | **
|
---|
36 | ** If you have questions regarding the use of this file, please contact
|
---|
37 | ** Nokia at qt-info@nokia.com.
|
---|
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 | return QScriptClass::HandlesReadAccess;
|
---|
231 | }
|
---|
232 | }
|
---|
233 |
|
---|
234 | if (scopeObject) {
|
---|
235 | QScriptClass::QueryFlags rv =
|
---|
236 | ep->objectClass->queryProperty(scopeObject, name, flags, bindContext,
|
---|
237 | QDeclarativeObjectScriptClass::ImplicitObject | QDeclarativeObjectScriptClass::SkipAttachedProperties);
|
---|
238 | if (rv) {
|
---|
239 | lastScopeObject = scopeObject;
|
---|
240 | lastContext = bindContext;
|
---|
241 | return rv;
|
---|
242 | }
|
---|
243 | }
|
---|
244 |
|
---|
245 | if (bindContext->contextObject) {
|
---|
246 | QScriptClass::QueryFlags rv =
|
---|
247 | ep->objectClass->queryProperty(bindContext->contextObject, name, flags, bindContext,
|
---|
248 | QDeclarativeObjectScriptClass::ImplicitObject | QDeclarativeObjectScriptClass::SkipAttachedProperties);
|
---|
249 |
|
---|
250 | if (rv) {
|
---|
251 | lastScopeObject = bindContext->contextObject;
|
---|
252 | lastContext = bindContext;
|
---|
253 | return rv;
|
---|
254 | }
|
---|
255 | }
|
---|
256 |
|
---|
257 | return 0;
|
---|
258 | }
|
---|
259 |
|
---|
260 | QDeclarativeContextScriptClass::Value
|
---|
261 | QDeclarativeContextScriptClass::property(Object *object, const Identifier &name)
|
---|
262 | {
|
---|
263 | Q_UNUSED(object);
|
---|
264 |
|
---|
265 | QDeclarativeContextData *bindContext = lastContext;
|
---|
266 | Q_ASSERT(bindContext);
|
---|
267 |
|
---|
268 | QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
|
---|
269 | QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
|
---|
270 |
|
---|
271 | if (lastScopeObject) {
|
---|
272 |
|
---|
273 | return ep->objectClass->property(lastScopeObject, name);
|
---|
274 |
|
---|
275 | } else if (lastData) {
|
---|
276 |
|
---|
277 | if (lastData->type) {
|
---|
278 | return Value(scriptEngine, ep->typeNameClass->newObject(bindContext->contextObject, lastData->type));
|
---|
279 | } else if (lastData->typeNamespace) {
|
---|
280 | return Value(scriptEngine, ep->typeNameClass->newObject(bindContext->contextObject,
|
---|
281 | lastData->typeNamespace));
|
---|
282 | } else {
|
---|
283 | int index = lastData->importedScriptIndex;
|
---|
284 | if (index < bindContext->importedScripts.count()) {
|
---|
285 | return Value(scriptEngine, bindContext->importedScripts.at(index));
|
---|
286 | } else {
|
---|
287 | return Value();
|
---|
288 | }
|
---|
289 | }
|
---|
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
|
---|