|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2010 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/qdeclarativevme_p.h" |
|
43 |
|
44 #include "private/qdeclarativecompiler_p.h" |
|
45 #include "private/qdeclarativeboundsignal_p.h" |
|
46 #include "private/qdeclarativestringconverters_p.h" |
|
47 #include "private/qmetaobjectbuilder_p.h" |
|
48 #include "private/qdeclarativedata_p.h" |
|
49 #include "qdeclarative.h" |
|
50 #include "private/qdeclarativecustomparser_p.h" |
|
51 #include "qdeclarativeengine.h" |
|
52 #include "qdeclarativecontext.h" |
|
53 #include "qdeclarativecomponent.h" |
|
54 #include "private/qdeclarativebinding_p.h" |
|
55 #include "private/qdeclarativeengine_p.h" |
|
56 #include "private/qdeclarativecomponent_p.h" |
|
57 #include "private/qdeclarativevmemetaobject_p.h" |
|
58 #include "private/qdeclarativebinding_p_p.h" |
|
59 #include "private/qdeclarativecontext_p.h" |
|
60 #include "private/qdeclarativecompiledbindings_p.h" |
|
61 #include "private/qdeclarativeglobal_p.h" |
|
62 #include "qdeclarativescriptstring.h" |
|
63 |
|
64 #include <QStack> |
|
65 #include <QWidget> |
|
66 #include <QColor> |
|
67 #include <QPointF> |
|
68 #include <QSizeF> |
|
69 #include <QRectF> |
|
70 #include <QtCore/qdebug.h> |
|
71 #include <QtCore/qvarlengtharray.h> |
|
72 #include <QtCore/qcoreapplication.h> |
|
73 #include <QtCore/qdatetime.h> |
|
74 |
|
75 QT_BEGIN_NAMESPACE |
|
76 |
|
77 QDeclarativeVME::QDeclarativeVME() |
|
78 { |
|
79 } |
|
80 |
|
81 #define VME_EXCEPTION(desc) \ |
|
82 { \ |
|
83 QDeclarativeError error; \ |
|
84 error.setDescription(desc.trimmed()); \ |
|
85 error.setLine(instr.line); \ |
|
86 error.setUrl(comp->url); \ |
|
87 vmeErrors << error; \ |
|
88 break; \ |
|
89 } |
|
90 |
|
91 struct ListInstance |
|
92 { |
|
93 ListInstance() |
|
94 : type(0) {} |
|
95 ListInstance(int t) |
|
96 : type(t) {} |
|
97 |
|
98 int type; |
|
99 QDeclarativeListProperty<void> qListProperty; |
|
100 }; |
|
101 |
|
102 QObject *QDeclarativeVME::run(QDeclarativeContextData *ctxt, QDeclarativeCompiledData *comp, |
|
103 int start, int count, const QBitField &bindingSkipList) |
|
104 { |
|
105 QDeclarativeVMEStack<QObject *> stack; |
|
106 |
|
107 if (start == -1) start = 0; |
|
108 if (count == -1) count = comp->bytecode.count(); |
|
109 |
|
110 return run(stack, ctxt, comp, start, count, bindingSkipList); |
|
111 } |
|
112 |
|
113 void QDeclarativeVME::runDeferred(QObject *object) |
|
114 { |
|
115 QDeclarativeData *data = QDeclarativeData::get(object); |
|
116 |
|
117 if (!data || !data->context || !data->deferredComponent) |
|
118 return; |
|
119 |
|
120 QDeclarativeContextData *ctxt = data->context; |
|
121 QDeclarativeCompiledData *comp = data->deferredComponent; |
|
122 int start = data->deferredIdx + 1; |
|
123 int count = data->deferredComponent->bytecode.at(data->deferredIdx).defer.deferCount; |
|
124 QDeclarativeVMEStack<QObject *> stack; |
|
125 stack.push(object); |
|
126 |
|
127 run(stack, ctxt, comp, start, count, QBitField()); |
|
128 } |
|
129 |
|
130 QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, |
|
131 QDeclarativeContextData *ctxt, |
|
132 QDeclarativeCompiledData *comp, |
|
133 int start, int count, |
|
134 const QBitField &bindingSkipList) |
|
135 { |
|
136 Q_ASSERT(comp); |
|
137 Q_ASSERT(ctxt); |
|
138 const QList<QDeclarativeCompiledData::TypeReference> &types = comp->types; |
|
139 const QList<QString> &primitives = comp->primitives; |
|
140 const QList<QByteArray> &datas = comp->datas; |
|
141 const QList<QDeclarativeCompiledData::CustomTypeData> &customTypeData = comp->customTypeData; |
|
142 const QList<int> &intData = comp->intData; |
|
143 const QList<float> &floatData = comp->floatData; |
|
144 const QList<QDeclarativePropertyCache *> &propertyCaches = comp->propertyCaches; |
|
145 const QList<QDeclarativeParser::Object::ScriptBlock> &scripts = comp->scripts; |
|
146 const QList<QUrl> &urls = comp->urls; |
|
147 |
|
148 QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding> bindValues; |
|
149 QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus> parserStatus; |
|
150 |
|
151 QDeclarativeVMEStack<ListInstance> qliststack; |
|
152 |
|
153 vmeErrors.clear(); |
|
154 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(ctxt->engine); |
|
155 |
|
156 int status = -1; //for dbus |
|
157 QDeclarativePropertyPrivate::WriteFlags flags = QDeclarativePropertyPrivate::BypassInterceptor; |
|
158 |
|
159 for (int ii = start; !isError() && ii < (start + count); ++ii) { |
|
160 const QDeclarativeInstruction &instr = comp->bytecode.at(ii); |
|
161 |
|
162 switch(instr.type) { |
|
163 case QDeclarativeInstruction::Init: |
|
164 { |
|
165 if (instr.init.bindingsSize) |
|
166 bindValues = QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding>(instr.init.bindingsSize); |
|
167 if (instr.init.parserStatusSize) |
|
168 parserStatus = QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus>(instr.init.parserStatusSize); |
|
169 if (instr.init.contextCache != -1) |
|
170 ctxt->setIdPropertyData(comp->contextCaches.at(instr.init.contextCache)); |
|
171 if (instr.init.compiledBinding != -1) |
|
172 ctxt->optimizedBindings = new QDeclarativeCompiledBindings(datas.at(instr.init.compiledBinding).constData(), ctxt); |
|
173 } |
|
174 break; |
|
175 |
|
176 case QDeclarativeInstruction::CreateObject: |
|
177 { |
|
178 QBitField bindings; |
|
179 if (instr.create.bindingBits != -1) { |
|
180 const QByteArray &bits = datas.at(instr.create.bindingBits); |
|
181 bindings = QBitField((const quint32*)bits.constData(), |
|
182 bits.size() * 8); |
|
183 } |
|
184 if (stack.isEmpty()) |
|
185 bindings = bindings.united(bindingSkipList); |
|
186 |
|
187 QObject *o = |
|
188 types.at(instr.create.type).createInstance(ctxt, bindings); |
|
189 |
|
190 if (!o) { |
|
191 if(types.at(instr.create.type).component) |
|
192 vmeErrors << types.at(instr.create.type).component->errors(); |
|
193 |
|
194 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create object of type %1").arg(QString::fromLatin1(types.at(instr.create.type).className))); |
|
195 } |
|
196 |
|
197 QDeclarativeData *ddata = QDeclarativeData::get(o); |
|
198 Q_ASSERT(ddata); |
|
199 |
|
200 if (stack.isEmpty()) { |
|
201 if (ddata->context) { |
|
202 Q_ASSERT(ddata->context != ctxt); |
|
203 Q_ASSERT(ddata->outerContext); |
|
204 Q_ASSERT(ddata->outerContext != ctxt); |
|
205 QDeclarativeContextData *c = ddata->context; |
|
206 while (c->linkedContext) c = c->linkedContext; |
|
207 c->linkedContext = ctxt; |
|
208 } else { |
|
209 ctxt->addObject(o); |
|
210 } |
|
211 |
|
212 ddata->ownContext = true; |
|
213 } else if (!ddata->context) { |
|
214 ctxt->addObject(o); |
|
215 } |
|
216 |
|
217 ddata->setImplicitDestructible(); |
|
218 ddata->outerContext = ctxt; |
|
219 ddata->lineNumber = instr.line; |
|
220 ddata->columnNumber = instr.create.column; |
|
221 |
|
222 if (instr.create.data != -1) { |
|
223 QDeclarativeCustomParser *customParser = |
|
224 types.at(instr.create.type).type->customParser(); |
|
225 customParser->setCustomData(o, datas.at(instr.create.data)); |
|
226 } |
|
227 if (!stack.isEmpty()) { |
|
228 QObject *parent = stack.top(); |
|
229 if (o->isWidgetType()) { |
|
230 QWidget *widget = static_cast<QWidget*>(o); |
|
231 if (parent->isWidgetType()) { |
|
232 QWidget *parentWidget = static_cast<QWidget*>(parent); |
|
233 widget->setParent(parentWidget); |
|
234 } else { |
|
235 // TODO: parent might be a layout |
|
236 } |
|
237 } else { |
|
238 QDeclarative_setParent_noEvent(o, parent); |
|
239 } |
|
240 } |
|
241 stack.push(o); |
|
242 } |
|
243 break; |
|
244 |
|
245 case QDeclarativeInstruction::CreateSimpleObject: |
|
246 { |
|
247 QObject *o = (QObject *)operator new(instr.createSimple.typeSize + |
|
248 sizeof(QDeclarativeData)); |
|
249 ::memset(o, 0, instr.createSimple.typeSize + sizeof(QDeclarativeData)); |
|
250 instr.createSimple.create(o); |
|
251 |
|
252 QDeclarativeData *ddata = |
|
253 (QDeclarativeData *)(((const char *)o) + instr.createSimple.typeSize); |
|
254 ddata->lineNumber = instr.line; |
|
255 ddata->columnNumber = instr.createSimple.column; |
|
256 |
|
257 QObjectPrivate::get(o)->declarativeData = ddata; |
|
258 ddata->context = ddata->outerContext = ctxt; |
|
259 ddata->nextContextObject = ctxt->contextObjects; |
|
260 if (ddata->nextContextObject) |
|
261 ddata->nextContextObject->prevContextObject = &ddata->nextContextObject; |
|
262 ddata->prevContextObject = &ctxt->contextObjects; |
|
263 ctxt->contextObjects = ddata; |
|
264 |
|
265 QObject *parent = stack.top(); |
|
266 QDeclarative_setParent_noEvent(o, parent); |
|
267 |
|
268 stack.push(o); |
|
269 } |
|
270 break; |
|
271 |
|
272 case QDeclarativeInstruction::SetId: |
|
273 { |
|
274 QObject *target = stack.top(); |
|
275 ctxt->setIdProperty(instr.setId.index, target); |
|
276 } |
|
277 break; |
|
278 |
|
279 |
|
280 case QDeclarativeInstruction::SetDefault: |
|
281 { |
|
282 ctxt->contextObject = stack.top(); |
|
283 } |
|
284 break; |
|
285 |
|
286 case QDeclarativeInstruction::CreateComponent: |
|
287 { |
|
288 QDeclarativeComponent *qcomp = |
|
289 new QDeclarativeComponent(ctxt->engine, comp, ii + 1, instr.createComponent.count, |
|
290 stack.isEmpty() ? 0 : stack.top()); |
|
291 |
|
292 QDeclarativeData *ddata = QDeclarativeData::get(qcomp, true); |
|
293 Q_ASSERT(ddata); |
|
294 |
|
295 ctxt->addObject(qcomp); |
|
296 |
|
297 if (stack.isEmpty()) |
|
298 ddata->ownContext = true; |
|
299 |
|
300 ddata->setImplicitDestructible(); |
|
301 ddata->outerContext = ctxt; |
|
302 ddata->lineNumber = instr.line; |
|
303 ddata->columnNumber = instr.create.column; |
|
304 |
|
305 QDeclarativeComponentPrivate::get(qcomp)->creationContext = ctxt; |
|
306 |
|
307 stack.push(qcomp); |
|
308 ii += instr.createComponent.count; |
|
309 } |
|
310 break; |
|
311 |
|
312 case QDeclarativeInstruction::StoreMetaObject: |
|
313 { |
|
314 QObject *target = stack.top(); |
|
315 |
|
316 QMetaObject mo; |
|
317 const QByteArray &metadata = datas.at(instr.storeMeta.data); |
|
318 QMetaObjectBuilder::fromRelocatableData(&mo, 0, metadata); |
|
319 |
|
320 const QDeclarativeVMEMetaData *data = |
|
321 (const QDeclarativeVMEMetaData *)datas.at(instr.storeMeta.aliasData).constData(); |
|
322 |
|
323 (void)new QDeclarativeVMEMetaObject(target, &mo, data, comp); |
|
324 |
|
325 QDeclarativeData *ddata = QDeclarativeData::get(target, true); |
|
326 if (ddata->propertyCache) ddata->propertyCache->release(); |
|
327 ddata->propertyCache = propertyCaches.at(instr.storeMeta.propertyCache); |
|
328 ddata->propertyCache->addref(); |
|
329 } |
|
330 break; |
|
331 |
|
332 case QDeclarativeInstruction::StoreVariant: |
|
333 { |
|
334 QObject *target = stack.top(); |
|
335 // XXX - can be more efficient |
|
336 QVariant v = QDeclarativeStringConverters::variantFromString(primitives.at(instr.storeString.value)); |
|
337 void *a[] = { &v, 0, &status, &flags }; |
|
338 QMetaObject::metacall(target, QMetaObject::WriteProperty, |
|
339 instr.storeString.propertyIndex, a); |
|
340 } |
|
341 break; |
|
342 |
|
343 case QDeclarativeInstruction::StoreVariantInteger: |
|
344 { |
|
345 QObject *target = stack.top(); |
|
346 QVariant v(instr.storeInteger.value); |
|
347 void *a[] = { &v, 0, &status, &flags }; |
|
348 QMetaObject::metacall(target, QMetaObject::WriteProperty, |
|
349 instr.storeString.propertyIndex, a); |
|
350 } |
|
351 break; |
|
352 |
|
353 case QDeclarativeInstruction::StoreVariantDouble: |
|
354 { |
|
355 QObject *target = stack.top(); |
|
356 QVariant v(instr.storeDouble.value); |
|
357 void *a[] = { &v, 0, &status, &flags }; |
|
358 QMetaObject::metacall(target, QMetaObject::WriteProperty, |
|
359 instr.storeString.propertyIndex, a); |
|
360 } |
|
361 break; |
|
362 |
|
363 case QDeclarativeInstruction::StoreVariantBool: |
|
364 { |
|
365 QObject *target = stack.top(); |
|
366 QVariant v(instr.storeBool.value); |
|
367 void *a[] = { &v, 0, &status, &flags }; |
|
368 QMetaObject::metacall(target, QMetaObject::WriteProperty, |
|
369 instr.storeString.propertyIndex, a); |
|
370 } |
|
371 break; |
|
372 |
|
373 case QDeclarativeInstruction::StoreString: |
|
374 { |
|
375 QObject *target = stack.top(); |
|
376 void *a[] = { (void *)&primitives.at(instr.storeString.value), 0, &status, &flags }; |
|
377 QMetaObject::metacall(target, QMetaObject::WriteProperty, |
|
378 instr.storeString.propertyIndex, a); |
|
379 } |
|
380 break; |
|
381 |
|
382 case QDeclarativeInstruction::StoreUrl: |
|
383 { |
|
384 QObject *target = stack.top(); |
|
385 void *a[] = { (void *)&urls.at(instr.storeUrl.value), 0, &status, &flags }; |
|
386 QMetaObject::metacall(target, QMetaObject::WriteProperty, |
|
387 instr.storeUrl.propertyIndex, a); |
|
388 } |
|
389 break; |
|
390 |
|
391 case QDeclarativeInstruction::StoreFloat: |
|
392 { |
|
393 QObject *target = stack.top(); |
|
394 float f = instr.storeFloat.value; |
|
395 void *a[] = { &f, 0, &status, &flags }; |
|
396 QMetaObject::metacall(target, QMetaObject::WriteProperty, |
|
397 instr.storeFloat.propertyIndex, a); |
|
398 } |
|
399 break; |
|
400 |
|
401 case QDeclarativeInstruction::StoreDouble: |
|
402 { |
|
403 QObject *target = stack.top(); |
|
404 double d = instr.storeDouble.value; |
|
405 void *a[] = { &d, 0, &status, &flags }; |
|
406 QMetaObject::metacall(target, QMetaObject::WriteProperty, |
|
407 instr.storeDouble.propertyIndex, a); |
|
408 } |
|
409 break; |
|
410 |
|
411 case QDeclarativeInstruction::StoreBool: |
|
412 { |
|
413 QObject *target = stack.top(); |
|
414 void *a[] = { (void *)&instr.storeBool.value, 0, &status, &flags }; |
|
415 QMetaObject::metacall(target, QMetaObject::WriteProperty, |
|
416 instr.storeBool.propertyIndex, a); |
|
417 } |
|
418 break; |
|
419 |
|
420 case QDeclarativeInstruction::StoreInteger: |
|
421 { |
|
422 QObject *target = stack.top(); |
|
423 void *a[] = { (void *)&instr.storeInteger.value, 0, &status, &flags }; |
|
424 QMetaObject::metacall(target, QMetaObject::WriteProperty, |
|
425 instr.storeInteger.propertyIndex, a); |
|
426 } |
|
427 break; |
|
428 |
|
429 case QDeclarativeInstruction::StoreColor: |
|
430 { |
|
431 QObject *target = stack.top(); |
|
432 QColor c = QColor::fromRgba(instr.storeColor.value); |
|
433 void *a[] = { &c, 0, &status, &flags }; |
|
434 QMetaObject::metacall(target, QMetaObject::WriteProperty, |
|
435 instr.storeColor.propertyIndex, a); |
|
436 } |
|
437 break; |
|
438 |
|
439 case QDeclarativeInstruction::StoreDate: |
|
440 { |
|
441 QObject *target = stack.top(); |
|
442 QDate d = QDate::fromJulianDay(instr.storeDate.value); |
|
443 void *a[] = { &d, 0, &status, &flags }; |
|
444 QMetaObject::metacall(target, QMetaObject::WriteProperty, |
|
445 instr.storeDate.propertyIndex, a); |
|
446 } |
|
447 break; |
|
448 |
|
449 case QDeclarativeInstruction::StoreTime: |
|
450 { |
|
451 QObject *target = stack.top(); |
|
452 QTime t; |
|
453 t.setHMS(intData.at(instr.storeTime.valueIndex), |
|
454 intData.at(instr.storeTime.valueIndex+1), |
|
455 intData.at(instr.storeTime.valueIndex+2), |
|
456 intData.at(instr.storeTime.valueIndex+3)); |
|
457 void *a[] = { &t, 0, &status, &flags }; |
|
458 QMetaObject::metacall(target, QMetaObject::WriteProperty, |
|
459 instr.storeTime.propertyIndex, a); |
|
460 } |
|
461 break; |
|
462 |
|
463 case QDeclarativeInstruction::StoreDateTime: |
|
464 { |
|
465 QObject *target = stack.top(); |
|
466 QTime t; |
|
467 t.setHMS(intData.at(instr.storeDateTime.valueIndex+1), |
|
468 intData.at(instr.storeDateTime.valueIndex+2), |
|
469 intData.at(instr.storeDateTime.valueIndex+3), |
|
470 intData.at(instr.storeDateTime.valueIndex+4)); |
|
471 QDateTime dt(QDate::fromJulianDay(intData.at(instr.storeDateTime.valueIndex)), t); |
|
472 void *a[] = { &dt, 0, &status, &flags }; |
|
473 QMetaObject::metacall(target, QMetaObject::WriteProperty, |
|
474 instr.storeDateTime.propertyIndex, a); |
|
475 } |
|
476 break; |
|
477 |
|
478 case QDeclarativeInstruction::StorePoint: |
|
479 { |
|
480 QObject *target = stack.top(); |
|
481 QPoint p = QPointF(floatData.at(instr.storeRealPair.valueIndex), |
|
482 floatData.at(instr.storeRealPair.valueIndex+1)).toPoint(); |
|
483 void *a[] = { &p, 0, &status, &flags }; |
|
484 QMetaObject::metacall(target, QMetaObject::WriteProperty, |
|
485 instr.storeRealPair.propertyIndex, a); |
|
486 } |
|
487 break; |
|
488 |
|
489 case QDeclarativeInstruction::StorePointF: |
|
490 { |
|
491 QObject *target = stack.top(); |
|
492 QPointF p(floatData.at(instr.storeRealPair.valueIndex), |
|
493 floatData.at(instr.storeRealPair.valueIndex+1)); |
|
494 void *a[] = { &p, 0, &status, &flags }; |
|
495 QMetaObject::metacall(target, QMetaObject::WriteProperty, |
|
496 instr.storeRealPair.propertyIndex, a); |
|
497 } |
|
498 break; |
|
499 |
|
500 case QDeclarativeInstruction::StoreSize: |
|
501 { |
|
502 QObject *target = stack.top(); |
|
503 QSize p = QSizeF(floatData.at(instr.storeRealPair.valueIndex), |
|
504 floatData.at(instr.storeRealPair.valueIndex+1)).toSize(); |
|
505 void *a[] = { &p, 0, &status, &flags }; |
|
506 QMetaObject::metacall(target, QMetaObject::WriteProperty, |
|
507 instr.storeRealPair.propertyIndex, a); |
|
508 } |
|
509 break; |
|
510 |
|
511 case QDeclarativeInstruction::StoreSizeF: |
|
512 { |
|
513 QObject *target = stack.top(); |
|
514 QSizeF s(floatData.at(instr.storeRealPair.valueIndex), |
|
515 floatData.at(instr.storeRealPair.valueIndex+1)); |
|
516 void *a[] = { &s, 0, &status, &flags }; |
|
517 QMetaObject::metacall(target, QMetaObject::WriteProperty, |
|
518 instr.storeRealPair.propertyIndex, a); |
|
519 } |
|
520 break; |
|
521 |
|
522 case QDeclarativeInstruction::StoreRect: |
|
523 { |
|
524 QObject *target = stack.top(); |
|
525 QRect r = QRectF(floatData.at(instr.storeRect.valueIndex), |
|
526 floatData.at(instr.storeRect.valueIndex+1), |
|
527 floatData.at(instr.storeRect.valueIndex+2), |
|
528 floatData.at(instr.storeRect.valueIndex+3)).toRect(); |
|
529 void *a[] = { &r, 0, &status, &flags }; |
|
530 QMetaObject::metacall(target, QMetaObject::WriteProperty, |
|
531 instr.storeRect.propertyIndex, a); |
|
532 } |
|
533 break; |
|
534 |
|
535 case QDeclarativeInstruction::StoreRectF: |
|
536 { |
|
537 QObject *target = stack.top(); |
|
538 QRectF r(floatData.at(instr.storeRect.valueIndex), |
|
539 floatData.at(instr.storeRect.valueIndex+1), |
|
540 floatData.at(instr.storeRect.valueIndex+2), |
|
541 floatData.at(instr.storeRect.valueIndex+3)); |
|
542 void *a[] = { &r, 0, &status, &flags }; |
|
543 QMetaObject::metacall(target, QMetaObject::WriteProperty, |
|
544 instr.storeRect.propertyIndex, a); |
|
545 } |
|
546 break; |
|
547 |
|
548 case QDeclarativeInstruction::StoreVector3D: |
|
549 { |
|
550 QObject *target = stack.top(); |
|
551 QVector3D p(floatData.at(instr.storeVector3D.valueIndex), |
|
552 floatData.at(instr.storeVector3D.valueIndex+1), |
|
553 floatData.at(instr.storeVector3D.valueIndex+2)); |
|
554 void *a[] = { &p, 0, &status, &flags }; |
|
555 QMetaObject::metacall(target, QMetaObject::WriteProperty, |
|
556 instr.storeVector3D.propertyIndex, a); |
|
557 } |
|
558 break; |
|
559 |
|
560 case QDeclarativeInstruction::StoreObject: |
|
561 { |
|
562 QObject *assignObj = stack.pop(); |
|
563 QObject *target = stack.top(); |
|
564 |
|
565 void *a[] = { (void *)&assignObj, 0, &status, &flags }; |
|
566 QMetaObject::metacall(target, QMetaObject::WriteProperty, |
|
567 instr.storeObject.propertyIndex, a); |
|
568 } |
|
569 break; |
|
570 |
|
571 |
|
572 case QDeclarativeInstruction::AssignCustomType: |
|
573 { |
|
574 QObject *target = stack.top(); |
|
575 QDeclarativeCompiledData::CustomTypeData data = customTypeData.at(instr.assignCustomType.valueIndex); |
|
576 const QString &primitive = primitives.at(data.index); |
|
577 QDeclarativeMetaType::StringConverter converter = |
|
578 QDeclarativeMetaType::customStringConverter(data.type); |
|
579 QVariant v = (*converter)(primitive); |
|
580 |
|
581 QMetaProperty prop = |
|
582 target->metaObject()->property(instr.assignCustomType.propertyIndex); |
|
583 if (v.isNull() || ((int)prop.type() != data.type && prop.userType() != data.type)) |
|
584 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name()))); |
|
585 |
|
586 void *a[] = { (void *)v.data(), 0, &status, &flags }; |
|
587 QMetaObject::metacall(target, QMetaObject::WriteProperty, |
|
588 instr.assignCustomType.propertyIndex, a); |
|
589 } |
|
590 break; |
|
591 |
|
592 case QDeclarativeInstruction::AssignSignalObject: |
|
593 { |
|
594 // XXX optimize |
|
595 |
|
596 QObject *assign = stack.pop(); |
|
597 QObject *target = stack.top(); |
|
598 int sigIdx = instr.assignSignalObject.signal; |
|
599 const QByteArray &pr = datas.at(sigIdx); |
|
600 |
|
601 QDeclarativeProperty prop(target, QString::fromUtf8(pr)); |
|
602 if (prop.type() & QDeclarativeProperty::SignalProperty) { |
|
603 |
|
604 QMetaMethod method = QDeclarativeMetaType::defaultMethod(assign); |
|
605 if (method.signature() == 0) |
|
606 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object type %1 with no default method").arg(QString::fromLatin1(assign->metaObject()->className()))); |
|
607 |
|
608 if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature())) |
|
609 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot connect mismatched signal/slot %1 %vs. %2").arg(QString::fromLatin1(method.signature())).arg(QString::fromLatin1(prop.method().signature()))); |
|
610 |
|
611 QMetaObject::connect(target, prop.index(), assign, method.methodIndex()); |
|
612 |
|
613 } else { |
|
614 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign an object to signal property %1").arg(QString::fromUtf8(pr))); |
|
615 } |
|
616 |
|
617 |
|
618 } |
|
619 break; |
|
620 |
|
621 case QDeclarativeInstruction::StoreSignal: |
|
622 { |
|
623 QObject *target = stack.top(); |
|
624 QObject *context = stack.at(stack.count() - 1 - instr.assignBinding.context); |
|
625 |
|
626 QMetaMethod signal = target->metaObject()->method(instr.storeSignal.signalIndex); |
|
627 |
|
628 QDeclarativeBoundSignal *bs = new QDeclarativeBoundSignal(target, signal, target); |
|
629 QDeclarativeExpression *expr = |
|
630 new QDeclarativeExpression(ctxt, context, primitives.at(instr.storeSignal.value)); |
|
631 expr->setSourceLocation(comp->name, instr.line); |
|
632 bs->setExpression(expr); |
|
633 } |
|
634 break; |
|
635 |
|
636 case QDeclarativeInstruction::StoreImportedScript: |
|
637 { |
|
638 ctxt->addImportedScript(scripts.at(instr.storeScript.value)); |
|
639 } |
|
640 break; |
|
641 |
|
642 case QDeclarativeInstruction::StoreScriptString: |
|
643 { |
|
644 QObject *target = stack.top(); |
|
645 QObject *scope = stack.at(stack.count() - 1 - instr.storeScriptString.scope); |
|
646 QDeclarativeScriptString ss; |
|
647 ss.setContext(ctxt->asQDeclarativeContext()); |
|
648 ss.setScopeObject(scope); |
|
649 ss.setScript(primitives.at(instr.storeScriptString.value)); |
|
650 |
|
651 void *a[] = { &ss, 0, &status, &flags }; |
|
652 QMetaObject::metacall(target, QMetaObject::WriteProperty, |
|
653 instr.storeScriptString.propertyIndex, a); |
|
654 } |
|
655 break; |
|
656 |
|
657 case QDeclarativeInstruction::BeginObject: |
|
658 { |
|
659 QObject *target = stack.top(); |
|
660 QDeclarativeParserStatus *status = reinterpret_cast<QDeclarativeParserStatus *>(reinterpret_cast<char *>(target) + instr.begin.castValue); |
|
661 parserStatus.append(status); |
|
662 status->d = &parserStatus.values[parserStatus.count - 1]; |
|
663 |
|
664 status->classBegin(); |
|
665 } |
|
666 break; |
|
667 |
|
668 case QDeclarativeInstruction::StoreBinding: |
|
669 { |
|
670 QObject *target = |
|
671 stack.at(stack.count() - 1 - instr.assignBinding.owner); |
|
672 QObject *context = |
|
673 stack.at(stack.count() - 1 - instr.assignBinding.context); |
|
674 |
|
675 QDeclarativeProperty mp = |
|
676 QDeclarativePropertyPrivate::restore(datas.at(instr.assignBinding.property), target, ctxt); |
|
677 |
|
678 int coreIndex = mp.index(); |
|
679 |
|
680 if (stack.count() == 1 && bindingSkipList.testBit(coreIndex)) |
|
681 break; |
|
682 |
|
683 QDeclarativeBinding *bind = new QDeclarativeBinding((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, comp->name, instr.line, 0); |
|
684 bindValues.append(bind); |
|
685 bind->m_mePtr = &bindValues.values[bindValues.count - 1]; |
|
686 bind->setTarget(mp); |
|
687 bind->addToObject(target); |
|
688 } |
|
689 break; |
|
690 |
|
691 case QDeclarativeInstruction::StoreCompiledBinding: |
|
692 { |
|
693 QObject *target = |
|
694 stack.at(stack.count() - 1 - instr.assignBinding.owner); |
|
695 QObject *scope = |
|
696 stack.at(stack.count() - 1 - instr.assignBinding.context); |
|
697 |
|
698 int property = instr.assignBinding.property; |
|
699 if (stack.count() == 1 && bindingSkipList.testBit(property & 0xFFFF)) |
|
700 break; |
|
701 |
|
702 QDeclarativeAbstractBinding *binding = |
|
703 ctxt->optimizedBindings->configBinding(instr.assignBinding.value, target, scope, property); |
|
704 bindValues.append(binding); |
|
705 binding->m_mePtr = &bindValues.values[bindValues.count - 1]; |
|
706 binding->addToObject(target); |
|
707 } |
|
708 break; |
|
709 |
|
710 case QDeclarativeInstruction::StoreValueSource: |
|
711 { |
|
712 QObject *obj = stack.pop(); |
|
713 QDeclarativePropertyValueSource *vs = reinterpret_cast<QDeclarativePropertyValueSource *>(reinterpret_cast<char *>(obj) + instr.assignValueSource.castValue); |
|
714 QObject *target = stack.at(stack.count() - 1 - instr.assignValueSource.owner); |
|
715 |
|
716 QDeclarativeProperty prop = |
|
717 QDeclarativePropertyPrivate::restore(datas.at(instr.assignValueSource.property), target, ctxt); |
|
718 obj->setParent(target); |
|
719 vs->setTarget(prop); |
|
720 } |
|
721 break; |
|
722 |
|
723 case QDeclarativeInstruction::StoreValueInterceptor: |
|
724 { |
|
725 QObject *obj = stack.pop(); |
|
726 QDeclarativePropertyValueInterceptor *vi = reinterpret_cast<QDeclarativePropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.assignValueInterceptor.castValue); |
|
727 QObject *target = stack.at(stack.count() - 1 - instr.assignValueInterceptor.owner); |
|
728 QDeclarativeProperty prop = |
|
729 QDeclarativePropertyPrivate::restore(datas.at(instr.assignValueInterceptor.property), target, ctxt); |
|
730 obj->setParent(target); |
|
731 vi->setTarget(prop); |
|
732 QDeclarativeVMEMetaObject *mo = static_cast<QDeclarativeVMEMetaObject *>((QMetaObject*)target->metaObject()); |
|
733 mo->registerInterceptor(prop.index(), QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), vi); |
|
734 } |
|
735 break; |
|
736 |
|
737 case QDeclarativeInstruction::StoreObjectQList: |
|
738 { |
|
739 QObject *assign = stack.pop(); |
|
740 |
|
741 const ListInstance &list = qliststack.top(); |
|
742 list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, assign); |
|
743 } |
|
744 break; |
|
745 |
|
746 case QDeclarativeInstruction::AssignObjectList: |
|
747 { |
|
748 // This is only used for assigning interfaces |
|
749 QObject *assign = stack.pop(); |
|
750 const ListInstance &list = qliststack.top(); |
|
751 |
|
752 int type = list.type; |
|
753 |
|
754 void *ptr = 0; |
|
755 |
|
756 const char *iid = QDeclarativeMetaType::interfaceIId(type); |
|
757 if (iid) |
|
758 ptr = assign->qt_metacast(iid); |
|
759 if (!ptr) |
|
760 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to list")); |
|
761 |
|
762 |
|
763 list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, ptr); |
|
764 } |
|
765 break; |
|
766 |
|
767 case QDeclarativeInstruction::StoreVariantObject: |
|
768 { |
|
769 QObject *assign = stack.pop(); |
|
770 QObject *target = stack.top(); |
|
771 |
|
772 QVariant v = QVariant::fromValue(assign); |
|
773 void *a[] = { &v, 0, &status, &flags }; |
|
774 QMetaObject::metacall(target, QMetaObject::WriteProperty, |
|
775 instr.storeObject.propertyIndex, a); |
|
776 } |
|
777 break; |
|
778 |
|
779 case QDeclarativeInstruction::StoreInterface: |
|
780 { |
|
781 QObject *assign = stack.pop(); |
|
782 QObject *target = stack.top(); |
|
783 |
|
784 int coreIdx = instr.storeObject.propertyIndex; |
|
785 QMetaProperty prop = target->metaObject()->property(coreIdx); |
|
786 int t = prop.userType(); |
|
787 const char *iid = QDeclarativeMetaType::interfaceIId(t); |
|
788 bool ok = false; |
|
789 if (iid) { |
|
790 void *ptr = assign->qt_metacast(iid); |
|
791 if (ptr) { |
|
792 void *a[] = { &ptr, 0, &status, &flags }; |
|
793 QMetaObject::metacall(target, |
|
794 QMetaObject::WriteProperty, |
|
795 coreIdx, a); |
|
796 ok = true; |
|
797 } |
|
798 } |
|
799 |
|
800 if (!ok) |
|
801 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to interface property")); |
|
802 } |
|
803 break; |
|
804 |
|
805 case QDeclarativeInstruction::FetchAttached: |
|
806 { |
|
807 QObject *target = stack.top(); |
|
808 |
|
809 QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.fetchAttached.id, target); |
|
810 |
|
811 if (!qmlObject) |
|
812 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create attached object")); |
|
813 |
|
814 stack.push(qmlObject); |
|
815 } |
|
816 break; |
|
817 |
|
818 case QDeclarativeInstruction::FetchQList: |
|
819 { |
|
820 QObject *target = stack.top(); |
|
821 |
|
822 qliststack.push(ListInstance(instr.fetchQmlList.type)); |
|
823 |
|
824 void *a[1]; |
|
825 a[0] = (void *)&(qliststack.top().qListProperty); |
|
826 QMetaObject::metacall(target, QMetaObject::ReadProperty, |
|
827 instr.fetchQmlList.property, a); |
|
828 } |
|
829 break; |
|
830 |
|
831 case QDeclarativeInstruction::FetchObject: |
|
832 { |
|
833 QObject *target = stack.top(); |
|
834 |
|
835 QObject *obj = 0; |
|
836 // NOTE: This assumes a cast to QObject does not alter the |
|
837 // object pointer |
|
838 void *a[1]; |
|
839 a[0] = &obj; |
|
840 QMetaObject::metacall(target, QMetaObject::ReadProperty, |
|
841 instr.fetch.property, a); |
|
842 |
|
843 if (!obj) |
|
844 VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot set properties on %1 as it is null").arg(QString::fromUtf8(target->metaObject()->property(instr.fetch.property).name()))); |
|
845 |
|
846 stack.push(obj); |
|
847 } |
|
848 break; |
|
849 |
|
850 case QDeclarativeInstruction::PopQList: |
|
851 { |
|
852 qliststack.pop(); |
|
853 } |
|
854 break; |
|
855 |
|
856 case QDeclarativeInstruction::Defer: |
|
857 { |
|
858 if (instr.defer.deferCount) { |
|
859 QObject *target = stack.top(); |
|
860 QDeclarativeData *data = |
|
861 QDeclarativeData::get(target, true); |
|
862 comp->addref(); |
|
863 data->deferredComponent = comp; |
|
864 data->deferredIdx = ii; |
|
865 ii += instr.defer.deferCount; |
|
866 } |
|
867 } |
|
868 break; |
|
869 |
|
870 case QDeclarativeInstruction::PopFetchedObject: |
|
871 { |
|
872 stack.pop(); |
|
873 } |
|
874 break; |
|
875 |
|
876 case QDeclarativeInstruction::FetchValueType: |
|
877 { |
|
878 QObject *target = stack.top(); |
|
879 QDeclarativeValueType *valueHandler = |
|
880 ep->valueTypes[instr.fetchValue.type]; |
|
881 valueHandler->read(target, instr.fetchValue.property); |
|
882 stack.push(valueHandler); |
|
883 } |
|
884 break; |
|
885 |
|
886 case QDeclarativeInstruction::PopValueType: |
|
887 { |
|
888 QDeclarativeValueType *valueHandler = |
|
889 static_cast<QDeclarativeValueType *>(stack.pop()); |
|
890 QObject *target = stack.top(); |
|
891 valueHandler->write(target, instr.fetchValue.property, |
|
892 QDeclarativePropertyPrivate::BypassInterceptor); |
|
893 } |
|
894 break; |
|
895 |
|
896 default: |
|
897 qFatal("QDeclarativeCompiledData: Internal error - unknown instruction %d", instr.type); |
|
898 break; |
|
899 } |
|
900 } |
|
901 |
|
902 if (isError()) { |
|
903 if (!stack.isEmpty()) { |
|
904 delete stack.at(0); // ### What about failures in deferred creation? |
|
905 } else { |
|
906 ctxt->destroy(); |
|
907 } |
|
908 |
|
909 QDeclarativeEnginePrivate::clear(bindValues); |
|
910 QDeclarativeEnginePrivate::clear(parserStatus); |
|
911 ep->finalizedParserStatus.clear(); |
|
912 return 0; |
|
913 } |
|
914 |
|
915 if (bindValues.count) |
|
916 ep->bindValues << bindValues; |
|
917 if (parserStatus.count) |
|
918 ep->parserStatus << parserStatus; |
|
919 |
|
920 Q_ASSERT(stack.count() == 1); |
|
921 return stack.top(); |
|
922 } |
|
923 |
|
924 bool QDeclarativeVME::isError() const |
|
925 { |
|
926 return !vmeErrors.isEmpty(); |
|
927 } |
|
928 |
|
929 QList<QDeclarativeError> QDeclarativeVME::errors() const |
|
930 { |
|
931 return vmeErrors; |
|
932 } |
|
933 |
|
934 QObject * |
|
935 QDeclarativeCompiledData::TypeReference::createInstance(QDeclarativeContextData *ctxt, |
|
936 const QBitField &bindings) const |
|
937 { |
|
938 if (type) { |
|
939 QObject *rv = 0; |
|
940 void *memory = 0; |
|
941 |
|
942 type->create(&rv, &memory, sizeof(QDeclarativeData)); |
|
943 QDeclarativeData *ddata = new (memory) QDeclarativeData; |
|
944 ddata->ownMemory = false; |
|
945 QObjectPrivate::get(rv)->declarativeData = ddata; |
|
946 |
|
947 return rv; |
|
948 } else { |
|
949 Q_ASSERT(component); |
|
950 return QDeclarativeComponentPrivate::get(component)->create(ctxt, bindings); |
|
951 } |
|
952 } |
|
953 |
|
954 |
|
955 QT_END_NAMESPACE |