source: trunk/src/declarative/qml/qdeclarativecontextscriptclass.cpp@ 949

Last change on this file since 949 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 12.1 KB
Line 
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
50QT_BEGIN_NAMESPACE
51
52struct 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
79struct 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 */
95QDeclarativeContextScriptClass::QDeclarativeContextScriptClass(QDeclarativeEngine *bindEngine)
96: QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine),
97 lastScopeObject(0), lastContext(0), lastData(0), lastPropertyIndex(-1)
98{
99}
100
101QDeclarativeContextScriptClass::~QDeclarativeContextScriptClass()
102{
103}
104
105QScriptValue 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
112QScriptValue 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
120QScriptValue QDeclarativeContextScriptClass::newUrlContext(const QString &url)
121{
122 QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
123
124 return newObject(scriptEngine, this, new UrlContextData(url));
125}
126
127QScriptValue QDeclarativeContextScriptClass::newSharedContext()
128{
129 QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
130
131 return newObject(scriptEngine, this, new ContextData());
132}
133
134QDeclarativeContextData *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
143QUrl 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
156QObject *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
167QScriptClass::QueryFlags
168QDeclarativeContextScriptClass::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
210QScriptClass::QueryFlags
211QDeclarativeContextScriptClass::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
260QDeclarativeContextScriptClass::Value
261QDeclarativeContextScriptClass::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
321void 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
335QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.