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/qdeclarativeenginedebug_p.h"
|
---|
43 |
|
---|
44 | #include "private/qdeclarativeboundsignal_p.h"
|
---|
45 | #include "qdeclarativeengine.h"
|
---|
46 | #include "private/qdeclarativemetatype_p.h"
|
---|
47 | #include "qdeclarativeproperty.h"
|
---|
48 | #include "private/qdeclarativeproperty_p.h"
|
---|
49 | #include "private/qdeclarativebinding_p.h"
|
---|
50 | #include "private/qdeclarativecontext_p.h"
|
---|
51 | #include "private/qdeclarativewatcher_p.h"
|
---|
52 | #include "private/qdeclarativevaluetype_p.h"
|
---|
53 | #include "private/qdeclarativevmemetaobject_p.h"
|
---|
54 | #include "private/qdeclarativeexpression_p.h"
|
---|
55 |
|
---|
56 | #include <QtCore/qdebug.h>
|
---|
57 | #include <QtCore/qmetaobject.h>
|
---|
58 |
|
---|
59 | QT_BEGIN_NAMESPACE
|
---|
60 |
|
---|
61 | Q_GLOBAL_STATIC(QDeclarativeEngineDebugServer, qmlEngineDebugServer);
|
---|
62 |
|
---|
63 | QDeclarativeEngineDebugServer *QDeclarativeEngineDebugServer::instance()
|
---|
64 | {
|
---|
65 | return qmlEngineDebugServer();
|
---|
66 | }
|
---|
67 |
|
---|
68 | QDeclarativeEngineDebugServer::QDeclarativeEngineDebugServer(QObject *parent)
|
---|
69 | : QDeclarativeDebugService(QLatin1String("QDeclarativeEngine"), parent),
|
---|
70 | m_watch(new QDeclarativeWatcher(this))
|
---|
71 | {
|
---|
72 | QObject::connect(m_watch, SIGNAL(propertyChanged(int,int,QMetaProperty,QVariant)),
|
---|
73 | this, SLOT(propertyChanged(int,int,QMetaProperty,QVariant)));
|
---|
74 | }
|
---|
75 |
|
---|
76 | QDataStream &operator<<(QDataStream &ds,
|
---|
77 | const QDeclarativeEngineDebugServer::QDeclarativeObjectData &data)
|
---|
78 | {
|
---|
79 | ds << data.url << data.lineNumber << data.columnNumber << data.idString
|
---|
80 | << data.objectName << data.objectType << data.objectId << data.contextId;
|
---|
81 | return ds;
|
---|
82 | }
|
---|
83 |
|
---|
84 | QDataStream &operator>>(QDataStream &ds,
|
---|
85 | QDeclarativeEngineDebugServer::QDeclarativeObjectData &data)
|
---|
86 | {
|
---|
87 | ds >> data.url >> data.lineNumber >> data.columnNumber >> data.idString
|
---|
88 | >> data.objectName >> data.objectType >> data.objectId >> data.contextId;
|
---|
89 | return ds;
|
---|
90 | }
|
---|
91 |
|
---|
92 | QDataStream &operator<<(QDataStream &ds,
|
---|
93 | const QDeclarativeEngineDebugServer::QDeclarativeObjectProperty &data)
|
---|
94 | {
|
---|
95 | ds << (int)data.type << data.name << data.value << data.valueTypeName
|
---|
96 | << data.binding << data.hasNotifySignal;
|
---|
97 | return ds;
|
---|
98 | }
|
---|
99 |
|
---|
100 | QDataStream &operator>>(QDataStream &ds,
|
---|
101 | QDeclarativeEngineDebugServer::QDeclarativeObjectProperty &data)
|
---|
102 | {
|
---|
103 | int type;
|
---|
104 | ds >> type >> data.name >> data.value >> data.valueTypeName
|
---|
105 | >> data.binding >> data.hasNotifySignal;
|
---|
106 | data.type = (QDeclarativeEngineDebugServer::QDeclarativeObjectProperty::Type)type;
|
---|
107 | return ds;
|
---|
108 | }
|
---|
109 |
|
---|
110 | static inline bool isSignalPropertyName(const QString &signalName)
|
---|
111 | {
|
---|
112 | // see QmlCompiler::isSignalPropertyName
|
---|
113 | return signalName.length() >= 3 && signalName.startsWith(QLatin1String("on")) &&
|
---|
114 | signalName.at(2).isLetter() && signalName.at(2).isUpper();
|
---|
115 | }
|
---|
116 |
|
---|
117 | static bool hasValidSignal(QObject *object, const QString &propertyName)
|
---|
118 | {
|
---|
119 | if (!isSignalPropertyName(propertyName))
|
---|
120 | return false;
|
---|
121 |
|
---|
122 | QString signalName = propertyName.mid(2);
|
---|
123 | signalName[0] = signalName.at(0).toLower();
|
---|
124 |
|
---|
125 | int sigIdx = QDeclarativePropertyPrivate::findSignalByName(object->metaObject(), signalName.toLatin1()).methodIndex();
|
---|
126 |
|
---|
127 | if (sigIdx == -1)
|
---|
128 | return false;
|
---|
129 |
|
---|
130 | return true;
|
---|
131 | }
|
---|
132 |
|
---|
133 | QDeclarativeEngineDebugServer::QDeclarativeObjectProperty
|
---|
134 | QDeclarativeEngineDebugServer::propertyData(QObject *obj, int propIdx)
|
---|
135 | {
|
---|
136 | QDeclarativeObjectProperty rv;
|
---|
137 |
|
---|
138 | QMetaProperty prop = obj->metaObject()->property(propIdx);
|
---|
139 |
|
---|
140 | rv.type = QDeclarativeObjectProperty::Unknown;
|
---|
141 | rv.valueTypeName = QString::fromUtf8(prop.typeName());
|
---|
142 | rv.name = QString::fromUtf8(prop.name());
|
---|
143 | rv.hasNotifySignal = prop.hasNotifySignal();
|
---|
144 | QDeclarativeAbstractBinding *binding =
|
---|
145 | QDeclarativePropertyPrivate::binding(QDeclarativeProperty(obj, rv.name));
|
---|
146 | if (binding)
|
---|
147 | rv.binding = binding->expression();
|
---|
148 |
|
---|
149 | QVariant value;
|
---|
150 | if (prop.userType() != 0) {
|
---|
151 | value = prop.read(obj);
|
---|
152 | }
|
---|
153 | rv.value = valueContents(value);
|
---|
154 |
|
---|
155 | if (QDeclarativeValueTypeFactory::isValueType(prop.userType())) {
|
---|
156 | rv.type = QDeclarativeObjectProperty::Basic;
|
---|
157 | } else if (QDeclarativeMetaType::isQObject(prop.userType())) {
|
---|
158 | rv.type = QDeclarativeObjectProperty::Object;
|
---|
159 | } else if (QDeclarativeMetaType::isList(prop.userType())) {
|
---|
160 | rv.type = QDeclarativeObjectProperty::List;
|
---|
161 | }
|
---|
162 |
|
---|
163 | return rv;
|
---|
164 | }
|
---|
165 |
|
---|
166 | QVariant QDeclarativeEngineDebugServer::valueContents(const QVariant &value) const
|
---|
167 | {
|
---|
168 | int userType = value.userType();
|
---|
169 | if (QDeclarativeValueTypeFactory::isValueType(userType))
|
---|
170 | return value;
|
---|
171 |
|
---|
172 | /*
|
---|
173 | if (QDeclarativeMetaType::isList(userType)) {
|
---|
174 | int count = QDeclarativeMetaType::listCount(value);
|
---|
175 | QVariantList contents;
|
---|
176 | for (int i=0; i<count; i++)
|
---|
177 | contents << valueContents(QDeclarativeMetaType::listAt(value, i));
|
---|
178 | return contents;
|
---|
179 | } else */
|
---|
180 | if (QDeclarativeMetaType::isQObject(userType)) {
|
---|
181 | QObject *o = QDeclarativeMetaType::toQObject(value);
|
---|
182 | if (o) {
|
---|
183 | QString name = o->objectName();
|
---|
184 | if (name.isEmpty())
|
---|
185 | name = QLatin1String("<unnamed object>");
|
---|
186 | return name;
|
---|
187 | }
|
---|
188 | }
|
---|
189 |
|
---|
190 | return QLatin1String("<unknown value>");
|
---|
191 | }
|
---|
192 |
|
---|
193 | void QDeclarativeEngineDebugServer::buildObjectDump(QDataStream &message,
|
---|
194 | QObject *object, bool recur, bool dumpProperties)
|
---|
195 | {
|
---|
196 | message << objectData(object);
|
---|
197 |
|
---|
198 | // Some children aren't added to an object until particular properties are read
|
---|
199 | // - e.g. child state objects aren't added until the 'states' property is read -
|
---|
200 | // but this should only affect internal objects that aren't shown by the
|
---|
201 | // debugger anyway.
|
---|
202 |
|
---|
203 | QObjectList children = object->children();
|
---|
204 |
|
---|
205 | int childrenCount = children.count();
|
---|
206 | for (int ii = 0; ii < children.count(); ++ii) {
|
---|
207 | if (qobject_cast<QDeclarativeContext*>(children[ii]) || QDeclarativeBoundSignal::cast(children[ii]))
|
---|
208 | --childrenCount;
|
---|
209 | }
|
---|
210 |
|
---|
211 | message << childrenCount << recur;
|
---|
212 |
|
---|
213 | QList<QDeclarativeObjectProperty> fakeProperties;
|
---|
214 |
|
---|
215 | for (int ii = 0; ii < children.count(); ++ii) {
|
---|
216 | QObject *child = children.at(ii);
|
---|
217 | if (qobject_cast<QDeclarativeContext*>(child))
|
---|
218 | continue;
|
---|
219 | QDeclarativeBoundSignal *signal = QDeclarativeBoundSignal::cast(child);
|
---|
220 | if (signal) {
|
---|
221 | if (!dumpProperties)
|
---|
222 | continue;
|
---|
223 | QDeclarativeObjectProperty prop;
|
---|
224 | prop.type = QDeclarativeObjectProperty::SignalProperty;
|
---|
225 | prop.hasNotifySignal = false;
|
---|
226 | QDeclarativeExpression *expr = signal->expression();
|
---|
227 | if (expr) {
|
---|
228 | prop.value = expr->expression();
|
---|
229 | QObject *scope = expr->scopeObject();
|
---|
230 | if (scope) {
|
---|
231 | QString sig = QLatin1String(scope->metaObject()->method(signal->index()).signature());
|
---|
232 | int lparen = sig.indexOf(QLatin1Char('('));
|
---|
233 | if (lparen >= 0) {
|
---|
234 | QString methodName = sig.mid(0, lparen);
|
---|
235 | prop.name = QLatin1String("on") + methodName[0].toUpper()
|
---|
236 | + methodName.mid(1);
|
---|
237 | }
|
---|
238 | }
|
---|
239 | }
|
---|
240 | fakeProperties << prop;
|
---|
241 | } else {
|
---|
242 | if (recur)
|
---|
243 | buildObjectDump(message, child, recur, dumpProperties);
|
---|
244 | else
|
---|
245 | message << objectData(child);
|
---|
246 | }
|
---|
247 | }
|
---|
248 |
|
---|
249 | if (!dumpProperties) {
|
---|
250 | message << 0;
|
---|
251 | return;
|
---|
252 | }
|
---|
253 |
|
---|
254 | message << (object->metaObject()->propertyCount() + fakeProperties.count());
|
---|
255 |
|
---|
256 | for (int ii = 0; ii < object->metaObject()->propertyCount(); ++ii)
|
---|
257 | message << propertyData(object, ii);
|
---|
258 |
|
---|
259 | for (int ii = 0; ii < fakeProperties.count(); ++ii)
|
---|
260 | message << fakeProperties[ii];
|
---|
261 | }
|
---|
262 |
|
---|
263 | void QDeclarativeEngineDebugServer::buildObjectList(QDataStream &message, QDeclarativeContext *ctxt)
|
---|
264 | {
|
---|
265 | QDeclarativeContextData *p = QDeclarativeContextData::get(ctxt);
|
---|
266 |
|
---|
267 | QString ctxtName = ctxt->objectName();
|
---|
268 | int ctxtId = QDeclarativeDebugService::idForObject(ctxt);
|
---|
269 |
|
---|
270 | message << ctxtName << ctxtId;
|
---|
271 |
|
---|
272 | int count = 0;
|
---|
273 |
|
---|
274 | QDeclarativeContextData *child = p->childContexts;
|
---|
275 | while (child) {
|
---|
276 | ++count;
|
---|
277 | child = child->nextChild;
|
---|
278 | }
|
---|
279 |
|
---|
280 | message << count;
|
---|
281 |
|
---|
282 | child = p->childContexts;
|
---|
283 | while (child) {
|
---|
284 | buildObjectList(message, child->asQDeclarativeContext());
|
---|
285 | child = child->nextChild;
|
---|
286 | }
|
---|
287 |
|
---|
288 | // Clean deleted objects
|
---|
289 | QDeclarativeContextPrivate *ctxtPriv = QDeclarativeContextPrivate::get(ctxt);
|
---|
290 | for (int ii = 0; ii < ctxtPriv->instances.count(); ++ii) {
|
---|
291 | if (!ctxtPriv->instances.at(ii)) {
|
---|
292 | ctxtPriv->instances.removeAt(ii);
|
---|
293 | --ii;
|
---|
294 | }
|
---|
295 | }
|
---|
296 |
|
---|
297 | message << ctxtPriv->instances.count();
|
---|
298 | for (int ii = 0; ii < ctxtPriv->instances.count(); ++ii) {
|
---|
299 | message << objectData(ctxtPriv->instances.at(ii));
|
---|
300 | }
|
---|
301 | }
|
---|
302 |
|
---|
303 | QDeclarativeEngineDebugServer::QDeclarativeObjectData
|
---|
304 | QDeclarativeEngineDebugServer::objectData(QObject *object)
|
---|
305 | {
|
---|
306 | QDeclarativeData *ddata = QDeclarativeData::get(object);
|
---|
307 | QDeclarativeObjectData rv;
|
---|
308 | if (ddata && ddata->outerContext) {
|
---|
309 | rv.url = ddata->outerContext->url;
|
---|
310 | rv.lineNumber = ddata->lineNumber;
|
---|
311 | rv.columnNumber = ddata->columnNumber;
|
---|
312 | } else {
|
---|
313 | rv.lineNumber = -1;
|
---|
314 | rv.columnNumber = -1;
|
---|
315 | }
|
---|
316 |
|
---|
317 | QDeclarativeContext *context = qmlContext(object);
|
---|
318 | if (context) {
|
---|
319 | QDeclarativeContextData *cdata = QDeclarativeContextData::get(context);
|
---|
320 | if (cdata)
|
---|
321 | rv.idString = cdata->findObjectId(object);
|
---|
322 | }
|
---|
323 |
|
---|
324 | rv.objectName = object->objectName();
|
---|
325 | rv.objectId = QDeclarativeDebugService::idForObject(object);
|
---|
326 | rv.contextId = QDeclarativeDebugService::idForObject(qmlContext(object));
|
---|
327 |
|
---|
328 | QDeclarativeType *type = QDeclarativeMetaType::qmlType(object->metaObject());
|
---|
329 | if (type) {
|
---|
330 | QString typeName = QLatin1String(type->qmlTypeName());
|
---|
331 | int lastSlash = typeName.lastIndexOf(QLatin1Char('/'));
|
---|
332 | rv.objectType = lastSlash < 0 ? typeName : typeName.mid(lastSlash+1);
|
---|
333 | } else {
|
---|
334 | rv.objectType = QString::fromUtf8(object->metaObject()->className());
|
---|
335 | int marker = rv.objectType.indexOf(QLatin1String("_QMLTYPE_"));
|
---|
336 | if (marker != -1)
|
---|
337 | rv.objectType = rv.objectType.left(marker);
|
---|
338 | }
|
---|
339 |
|
---|
340 | return rv;
|
---|
341 | }
|
---|
342 |
|
---|
343 | void QDeclarativeEngineDebugServer::messageReceived(const QByteArray &message)
|
---|
344 | {
|
---|
345 | QDataStream ds(message);
|
---|
346 |
|
---|
347 | QByteArray type;
|
---|
348 | ds >> type;
|
---|
349 |
|
---|
350 | if (type == "LIST_ENGINES") {
|
---|
351 | int queryId;
|
---|
352 | ds >> queryId;
|
---|
353 |
|
---|
354 | QByteArray reply;
|
---|
355 | QDataStream rs(&reply, QIODevice::WriteOnly);
|
---|
356 | rs << QByteArray("LIST_ENGINES_R");
|
---|
357 | rs << queryId << m_engines.count();
|
---|
358 |
|
---|
359 | for (int ii = 0; ii < m_engines.count(); ++ii) {
|
---|
360 | QDeclarativeEngine *engine = m_engines.at(ii);
|
---|
361 |
|
---|
362 | QString engineName = engine->objectName();
|
---|
363 | int engineId = QDeclarativeDebugService::idForObject(engine);
|
---|
364 |
|
---|
365 | rs << engineName << engineId;
|
---|
366 | }
|
---|
367 |
|
---|
368 | sendMessage(reply);
|
---|
369 | } else if (type == "LIST_OBJECTS") {
|
---|
370 | int queryId;
|
---|
371 | int engineId = -1;
|
---|
372 | ds >> queryId >> engineId;
|
---|
373 |
|
---|
374 | QDeclarativeEngine *engine =
|
---|
375 | qobject_cast<QDeclarativeEngine *>(QDeclarativeDebugService::objectForId(engineId));
|
---|
376 |
|
---|
377 | QByteArray reply;
|
---|
378 | QDataStream rs(&reply, QIODevice::WriteOnly);
|
---|
379 | rs << QByteArray("LIST_OBJECTS_R") << queryId;
|
---|
380 |
|
---|
381 | if (engine)
|
---|
382 | buildObjectList(rs, engine->rootContext());
|
---|
383 |
|
---|
384 | sendMessage(reply);
|
---|
385 | } else if (type == "FETCH_OBJECT") {
|
---|
386 | int queryId;
|
---|
387 | int objectId;
|
---|
388 | bool recurse;
|
---|
389 | bool dumpProperties = true;
|
---|
390 |
|
---|
391 | ds >> queryId >> objectId >> recurse >> dumpProperties;
|
---|
392 |
|
---|
393 | QObject *object = QDeclarativeDebugService::objectForId(objectId);
|
---|
394 |
|
---|
395 | QByteArray reply;
|
---|
396 | QDataStream rs(&reply, QIODevice::WriteOnly);
|
---|
397 | rs << QByteArray("FETCH_OBJECT_R") << queryId;
|
---|
398 |
|
---|
399 | if (object)
|
---|
400 | buildObjectDump(rs, object, recurse, dumpProperties);
|
---|
401 |
|
---|
402 | sendMessage(reply);
|
---|
403 | } else if (type == "WATCH_OBJECT") {
|
---|
404 | int queryId;
|
---|
405 | int objectId;
|
---|
406 |
|
---|
407 | ds >> queryId >> objectId;
|
---|
408 | bool ok = m_watch->addWatch(queryId, objectId);
|
---|
409 |
|
---|
410 | QByteArray reply;
|
---|
411 | QDataStream rs(&reply, QIODevice::WriteOnly);
|
---|
412 | rs << QByteArray("WATCH_OBJECT_R") << queryId << ok;
|
---|
413 |
|
---|
414 | sendMessage(reply);
|
---|
415 | } else if (type == "WATCH_PROPERTY") {
|
---|
416 | int queryId;
|
---|
417 | int objectId;
|
---|
418 | QByteArray property;
|
---|
419 |
|
---|
420 | ds >> queryId >> objectId >> property;
|
---|
421 | bool ok = m_watch->addWatch(queryId, objectId, property);
|
---|
422 |
|
---|
423 | QByteArray reply;
|
---|
424 | QDataStream rs(&reply, QIODevice::WriteOnly);
|
---|
425 | rs << QByteArray("WATCH_PROPERTY_R") << queryId << ok;
|
---|
426 |
|
---|
427 | sendMessage(reply);
|
---|
428 | } else if (type == "WATCH_EXPR_OBJECT") {
|
---|
429 | int queryId;
|
---|
430 | int debugId;
|
---|
431 | QString expr;
|
---|
432 |
|
---|
433 | ds >> queryId >> debugId >> expr;
|
---|
434 | bool ok = m_watch->addWatch(queryId, debugId, expr);
|
---|
435 |
|
---|
436 | QByteArray reply;
|
---|
437 | QDataStream rs(&reply, QIODevice::WriteOnly);
|
---|
438 | rs << QByteArray("WATCH_EXPR_OBJECT_R") << queryId << ok;
|
---|
439 | sendMessage(reply);
|
---|
440 | } else if (type == "NO_WATCH") {
|
---|
441 | int queryId;
|
---|
442 |
|
---|
443 | ds >> queryId;
|
---|
444 | m_watch->removeWatch(queryId);
|
---|
445 | } else if (type == "EVAL_EXPRESSION") {
|
---|
446 | int queryId;
|
---|
447 | int objectId;
|
---|
448 | QString expr;
|
---|
449 |
|
---|
450 | ds >> queryId >> objectId >> expr;
|
---|
451 |
|
---|
452 | QObject *object = QDeclarativeDebugService::objectForId(objectId);
|
---|
453 | QDeclarativeContext *context = qmlContext(object);
|
---|
454 | QVariant result;
|
---|
455 | if (object && context) {
|
---|
456 | QDeclarativeExpression exprObj(context, object, expr);
|
---|
457 | bool undefined = false;
|
---|
458 | QVariant value = exprObj.evaluate(&undefined);
|
---|
459 | if (undefined)
|
---|
460 | result = QLatin1String("<undefined>");
|
---|
461 | else
|
---|
462 | result = valueContents(value);
|
---|
463 | } else {
|
---|
464 | result = QLatin1String("<unknown context>");
|
---|
465 | }
|
---|
466 |
|
---|
467 | QByteArray reply;
|
---|
468 | QDataStream rs(&reply, QIODevice::WriteOnly);
|
---|
469 | rs << QByteArray("EVAL_EXPRESSION_R") << queryId << result;
|
---|
470 |
|
---|
471 | sendMessage(reply);
|
---|
472 | } else if (type == "SET_BINDING") {
|
---|
473 | int objectId;
|
---|
474 | QString propertyName;
|
---|
475 | QVariant expr;
|
---|
476 | bool isLiteralValue;
|
---|
477 | ds >> objectId >> propertyName >> expr >> isLiteralValue;
|
---|
478 | setBinding(objectId, propertyName, expr, isLiteralValue);
|
---|
479 | } else if (type == "RESET_BINDING") {
|
---|
480 | int objectId;
|
---|
481 | QString propertyName;
|
---|
482 | ds >> objectId >> propertyName;
|
---|
483 | resetBinding(objectId, propertyName);
|
---|
484 | } else if (type == "SET_METHOD_BODY") {
|
---|
485 | int objectId;
|
---|
486 | QString methodName;
|
---|
487 | QString methodBody;
|
---|
488 | ds >> objectId >> methodName >> methodBody;
|
---|
489 | setMethodBody(objectId, methodName, methodBody);
|
---|
490 | }
|
---|
491 | }
|
---|
492 |
|
---|
493 | void QDeclarativeEngineDebugServer::setBinding(int objectId,
|
---|
494 | const QString &propertyName,
|
---|
495 | const QVariant &expression,
|
---|
496 | bool isLiteralValue)
|
---|
497 | {
|
---|
498 | QObject *object = objectForId(objectId);
|
---|
499 | QDeclarativeContext *context = qmlContext(object);
|
---|
500 |
|
---|
501 | if (object && context) {
|
---|
502 |
|
---|
503 | QDeclarativeProperty property(object, propertyName, context);
|
---|
504 | if (isLiteralValue) {
|
---|
505 | property.write(expression);
|
---|
506 | } else if (hasValidSignal(object, propertyName)) {
|
---|
507 | QDeclarativeExpression *declarativeExpression = new QDeclarativeExpression(context, object, expression.toString());
|
---|
508 | QDeclarativeExpression *oldExpression = QDeclarativePropertyPrivate::setSignalExpression(property, declarativeExpression);
|
---|
509 | declarativeExpression->setSourceLocation(oldExpression->sourceFile(), oldExpression->lineNumber());
|
---|
510 | } else if (property.isProperty()) {
|
---|
511 | QDeclarativeBinding *binding = new QDeclarativeBinding(expression.toString(), object, context);
|
---|
512 | binding->setTarget(property);
|
---|
513 | binding->setNotifyOnValueChanged(true);
|
---|
514 | QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::setBinding(property, binding);
|
---|
515 | if (oldBinding)
|
---|
516 | oldBinding->destroy();
|
---|
517 | binding->update();
|
---|
518 | } else {
|
---|
519 | qWarning() << "QDeclarativeEngineDebugServer::setBinding: unable to set property" << propertyName << "on object" << object;
|
---|
520 | }
|
---|
521 | }
|
---|
522 | }
|
---|
523 |
|
---|
524 | void QDeclarativeEngineDebugServer::resetBinding(int objectId, const QString &propertyName)
|
---|
525 | {
|
---|
526 | QObject *object = objectForId(objectId);
|
---|
527 | QDeclarativeContext *context = qmlContext(object);
|
---|
528 |
|
---|
529 | if (object && context) {
|
---|
530 | if (object->property(propertyName.toLatin1()).isValid()) {
|
---|
531 | QDeclarativeProperty property(object, propertyName);
|
---|
532 | QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(property);
|
---|
533 | if (oldBinding) {
|
---|
534 | QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::setBinding(property, 0);
|
---|
535 | if (oldBinding)
|
---|
536 | oldBinding->destroy();
|
---|
537 | } else {
|
---|
538 | if (property.isResettable()) {
|
---|
539 | property.reset();
|
---|
540 | }
|
---|
541 | }
|
---|
542 | }
|
---|
543 | }
|
---|
544 | }
|
---|
545 |
|
---|
546 | void QDeclarativeEngineDebugServer::setMethodBody(int objectId, const QString &method, const QString &body)
|
---|
547 | {
|
---|
548 | QObject *object = objectForId(objectId);
|
---|
549 | QDeclarativeContext *context = qmlContext(object);
|
---|
550 | if (!object || !context || !context->engine())
|
---|
551 | return;
|
---|
552 | QDeclarativeContextData *contextData = QDeclarativeContextData::get(context);
|
---|
553 | if (!contextData)
|
---|
554 | return;
|
---|
555 |
|
---|
556 | QDeclarativePropertyCache::Data dummy;
|
---|
557 | QDeclarativePropertyCache::Data *prop =
|
---|
558 | QDeclarativePropertyCache::property(context->engine(), object, method, dummy);
|
---|
559 |
|
---|
560 | if (!prop || !(prop->flags & QDeclarativePropertyCache::Data::IsVMEFunction))
|
---|
561 | return;
|
---|
562 |
|
---|
563 | QMetaMethod metaMethod = object->metaObject()->method(prop->coreIndex);
|
---|
564 | QList<QByteArray> paramNames = metaMethod.parameterNames();
|
---|
565 |
|
---|
566 | QString paramStr;
|
---|
567 | for (int ii = 0; ii < paramNames.count(); ++ii) {
|
---|
568 | if (ii != 0) paramStr.append(QLatin1String(","));
|
---|
569 | paramStr.append(QString::fromUtf8(paramNames.at(ii)));
|
---|
570 | }
|
---|
571 |
|
---|
572 | QString jsfunction = QLatin1String("(function ") + method + QLatin1String("(") + paramStr +
|
---|
573 | QLatin1String(") {");
|
---|
574 | jsfunction += body;
|
---|
575 | jsfunction += QLatin1String("\n})");
|
---|
576 |
|
---|
577 | QDeclarativeVMEMetaObject *vmeMetaObject =
|
---|
578 | static_cast<QDeclarativeVMEMetaObject*>(QObjectPrivate::get(object)->metaObject);
|
---|
579 | Q_ASSERT(vmeMetaObject); // the fact we found the property above should guarentee this
|
---|
580 |
|
---|
581 | int lineNumber = vmeMetaObject->vmeMethodLineNumber(prop->coreIndex);
|
---|
582 | vmeMetaObject->setVmeMethod(prop->coreIndex, QDeclarativeExpressionPrivate::evalInObjectScope(contextData, object, jsfunction, contextData->url.toString(), lineNumber, 0));
|
---|
583 | }
|
---|
584 |
|
---|
585 | void QDeclarativeEngineDebugServer::propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value)
|
---|
586 | {
|
---|
587 | QByteArray reply;
|
---|
588 | QDataStream rs(&reply, QIODevice::WriteOnly);
|
---|
589 |
|
---|
590 | rs << QByteArray("UPDATE_WATCH") << id << objectId << QByteArray(property.name()) << valueContents(value);
|
---|
591 |
|
---|
592 | sendMessage(reply);
|
---|
593 | }
|
---|
594 |
|
---|
595 | void QDeclarativeEngineDebugServer::addEngine(QDeclarativeEngine *engine)
|
---|
596 | {
|
---|
597 | Q_ASSERT(engine);
|
---|
598 | Q_ASSERT(!m_engines.contains(engine));
|
---|
599 |
|
---|
600 | m_engines.append(engine);
|
---|
601 | }
|
---|
602 |
|
---|
603 | void QDeclarativeEngineDebugServer::remEngine(QDeclarativeEngine *engine)
|
---|
604 | {
|
---|
605 | Q_ASSERT(engine);
|
---|
606 | Q_ASSERT(m_engines.contains(engine));
|
---|
607 |
|
---|
608 | m_engines.removeAll(engine);
|
---|
609 | }
|
---|
610 |
|
---|
611 | void QDeclarativeEngineDebugServer::objectCreated(QDeclarativeEngine *engine, QObject *object)
|
---|
612 | {
|
---|
613 | Q_ASSERT(engine);
|
---|
614 | Q_ASSERT(m_engines.contains(engine));
|
---|
615 |
|
---|
616 | int engineId = QDeclarativeDebugService::idForObject(engine);
|
---|
617 | int objectId = QDeclarativeDebugService::idForObject(object);
|
---|
618 |
|
---|
619 | QByteArray reply;
|
---|
620 | QDataStream rs(&reply, QIODevice::WriteOnly);
|
---|
621 |
|
---|
622 | rs << QByteArray("OBJECT_CREATED") << engineId << objectId;
|
---|
623 | sendMessage(reply);
|
---|
624 | }
|
---|
625 |
|
---|
626 | QT_END_NAMESPACE
|
---|