1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
4#include "qqmlenginedebugclient_p_p.h"
5#include <private/qqmldebugconnection_p.h>
6
7QT_BEGIN_NAMESPACE
8
9struct QQmlObjectData {
10 QUrl url;
11 qint32 lineNumber = -1;
12 qint32 columnNumber = -1;
13 QString idString;
14 QString objectName;
15 QString objectType;
16 qint32 objectId = -1;
17 qint32 contextId = -1;
18 qint32 parentId = -1;
19};
20
21QPacket &operator>>(QPacket &ds, QQmlObjectData &data)
22{
23 ds >> data.url >> data.lineNumber >> data.columnNumber >> data.idString
24 >> data.objectName >> data.objectType >> data.objectId >> data.contextId
25 >> data.parentId;
26 return ds;
27}
28
29struct QQmlObjectProperty {
30 enum Type { Unknown, Basic, Object, List, SignalProperty };
31 Type type = Unknown;
32 QString name;
33 QVariant value;
34 QString valueTypeName;
35 QString binding;
36 bool hasNotifySignal = false;
37};
38
39QPacket &operator>>(QPacket &ds, QQmlObjectProperty &data)
40{
41 qint32 type;
42 ds >> type >> data.name >> data.value >> data.valueTypeName
43 >> data.binding >> data.hasNotifySignal;
44 data.type = QQmlObjectProperty::Type(type);
45 return ds;
46}
47
48QQmlEngineDebugClient::QQmlEngineDebugClient(QQmlDebugConnection *connection) :
49 QQmlDebugClient(*new QQmlEngineDebugClientPrivate(connection))
50{
51}
52
53QQmlEngineDebugClientPrivate::QQmlEngineDebugClientPrivate(QQmlDebugConnection *connection) :
54 QQmlDebugClientPrivate (QLatin1String("QmlDebugger"), connection)
55{
56}
57
58
59qint32 QQmlEngineDebugClient::addWatch(
60 const QQmlEngineDebugPropertyReference &property, bool *success)
61{
62 qint32 id = -1;
63 *success = false;
64 if (state() == QQmlDebugClient::Enabled) {
65 id = getId();
66 QPacket ds(connection()->currentDataStreamVersion());
67 ds << QByteArray("WATCH_PROPERTY") << id << property.objectDebugId
68 << property.name.toUtf8();
69 sendMessage(message: ds.data());
70 *success = true;
71 }
72 return id;
73}
74
75qint32 QQmlEngineDebugClient::addWatch(
76 const QQmlEngineDebugContextReference &, const QString &, bool *success)
77{
78 *success = false;
79 qWarning(msg: "QQmlEngineDebugClient::addWatch(): Not implemented");
80 return -1;
81}
82
83qint32 QQmlEngineDebugClient::addWatch(
84 const QQmlEngineDebugObjectReference &object, const QString &expr,
85 bool *success)
86{
87 qint32 id = -1;
88 *success = false;
89 if (state() == QQmlDebugClient::Enabled) {
90 id = getId();
91 QPacket ds(connection()->currentDataStreamVersion());
92 ds << QByteArray("WATCH_EXPR_OBJECT") << id << object.debugId << expr;
93 sendMessage(message: ds.data());
94 *success = true;
95 }
96 return id;
97}
98
99qint32 QQmlEngineDebugClient::addWatch(
100 const QQmlEngineDebugObjectReference &object, bool *success)
101{
102 qint32 id = -1;
103 *success = false;
104 if (state() == QQmlDebugClient::Enabled) {
105 id = getId();
106 QPacket ds(connection()->currentDataStreamVersion());
107 ds << QByteArray("WATCH_OBJECT") << id << object.debugId;
108 sendMessage(message: ds.data());
109 *success = true;
110 }
111 return id;
112}
113
114qint32 QQmlEngineDebugClient::addWatch(
115 const QQmlEngineDebugFileReference &, bool *success)
116{
117 *success = false;
118 qWarning(msg: "QQmlEngineDebugClient::addWatch(): Not implemented");
119 return -1;
120}
121
122void QQmlEngineDebugClient::removeWatch(qint32 id, bool *success)
123{
124 *success = false;
125 if (state() == QQmlDebugClient::Enabled) {
126 QPacket ds(connection()->currentDataStreamVersion());
127 ds << QByteArray("NO_WATCH") << id;
128 sendMessage(message: ds.data());
129 *success = true;
130 }
131}
132
133qint32 QQmlEngineDebugClient::queryAvailableEngines(bool *success)
134{
135 Q_D(QQmlEngineDebugClient);
136 d->engines.clear();
137 qint32 id = -1;
138 *success = false;
139 if (state() == QQmlDebugClient::Enabled) {
140 id = getId();
141 QPacket ds(connection()->currentDataStreamVersion());
142 ds << QByteArray("LIST_ENGINES") << id;
143 sendMessage(message: ds.data());
144 *success = true;
145 }
146 return id;
147}
148
149qint32 QQmlEngineDebugClient::queryRootContexts(
150 const QQmlEngineDebugEngineReference &engine, bool *success)
151{
152 Q_D(QQmlEngineDebugClient);
153 d->rootContext = QQmlEngineDebugContextReference();
154 qint32 id = -1;
155 *success = false;
156 if (state() == QQmlDebugClient::Enabled && engine.debugId != -1) {
157 id = getId();
158 QPacket ds(connection()->currentDataStreamVersion());
159 ds << QByteArray("LIST_OBJECTS") << id << engine.debugId;
160 sendMessage(message: ds.data());
161 *success = true;
162 }
163 return id;
164}
165
166qint32 QQmlEngineDebugClient::queryObject(
167 const QQmlEngineDebugObjectReference &object, bool *success)
168{
169 Q_D(QQmlEngineDebugClient);
170 d->object = QQmlEngineDebugObjectReference();
171 qint32 id = -1;
172 *success = false;
173 if (state() == QQmlDebugClient::Enabled && object.debugId != -1) {
174 id = getId();
175 QPacket ds(connection()->currentDataStreamVersion());
176 ds << QByteArray("FETCH_OBJECT") << id << object.debugId << false << true;
177 sendMessage(message: ds.data());
178 *success = true;
179 }
180 return id;
181}
182
183qint32 QQmlEngineDebugClient::queryObjectsForLocation(
184 const QString &file, qint32 lineNumber, qint32 columnNumber, bool *success)
185{
186 Q_D(QQmlEngineDebugClient);
187 d->objects.clear();
188 qint32 id = -1;
189 *success = false;
190 if (state() == QQmlDebugClient::Enabled) {
191 id = getId();
192 QPacket ds(connection()->currentDataStreamVersion());
193 ds << QByteArray("FETCH_OBJECTS_FOR_LOCATION") << id << file << lineNumber
194 << columnNumber << false << true;
195 sendMessage(message: ds.data());
196 *success = true;
197 }
198 return id;
199}
200
201qint32 QQmlEngineDebugClient::queryObjectRecursive(
202 const QQmlEngineDebugObjectReference &object, bool *success)
203{
204 Q_D(QQmlEngineDebugClient);
205 d->object = QQmlEngineDebugObjectReference();
206 qint32 id = -1;
207 *success = false;
208 if (state() == QQmlDebugClient::Enabled && object.debugId != -1) {
209 id = getId();
210 QPacket ds(connection()->currentDataStreamVersion());
211 ds << QByteArray("FETCH_OBJECT") << id << object.debugId << true << true;
212 sendMessage(message: ds.data());
213 *success = true;
214 }
215 return id;
216}
217
218qint32 QQmlEngineDebugClient::queryObjectsForLocationRecursive(const QString &file,
219 qint32 lineNumber, qint32 columnNumber, bool *success)
220{
221 Q_D(QQmlEngineDebugClient);
222 d->objects.clear();
223 qint32 id = -1;
224 *success = false;
225 if (state() == QQmlDebugClient::Enabled) {
226 id = getId();
227 QPacket ds(connection()->currentDataStreamVersion());
228 ds << QByteArray("FETCH_OBJECTS_FOR_LOCATION") << id << file << lineNumber
229 << columnNumber << true << true;
230 sendMessage(message: ds.data());
231 *success = true;
232 }
233 return id;
234}
235
236qint32 QQmlEngineDebugClient::queryExpressionResult(
237 qint32 objectDebugId, const QString &expr, bool *success)
238{
239 Q_D(QQmlEngineDebugClient);
240 d->exprResult = QVariant();
241 qint32 id = -1;
242 *success = false;
243 if (state() == QQmlDebugClient::Enabled) {
244 id = getId();
245 QPacket ds(connection()->currentDataStreamVersion());
246 ds << QByteArray("EVAL_EXPRESSION") << id << objectDebugId << expr
247 << engines()[0].debugId;
248 sendMessage(message: ds.data());
249 *success = true;
250 }
251 return id;
252}
253
254qint32 QQmlEngineDebugClient::queryExpressionResultBC(
255 qint32 objectDebugId, const QString &expr, bool *success)
256{
257 Q_D(QQmlEngineDebugClient);
258 d->exprResult = QVariant();
259 qint32 id = -1;
260 *success = false;
261 if (state() == QQmlDebugClient::Enabled) {
262 id = getId();
263 QPacket ds(connection()->currentDataStreamVersion());
264 ds << QByteArray("EVAL_EXPRESSION") << id << objectDebugId << expr;
265 sendMessage(message: ds.data());
266 *success = true;
267 }
268 return id;
269}
270
271qint32 QQmlEngineDebugClient::setBindingForObject(
272 qint32 objectDebugId,
273 const QString &propertyName,
274 const QVariant &bindingExpression,
275 bool isLiteralValue,
276 const QString &source, qint32 line,
277 bool *success)
278{
279 qint32 id = -1;
280 *success = false;
281 if (state() == QQmlDebugClient::Enabled && objectDebugId != -1) {
282 id = getId();
283 QPacket ds(connection()->currentDataStreamVersion());
284 ds << QByteArray("SET_BINDING") << id << objectDebugId << propertyName
285 << bindingExpression << isLiteralValue << source << line;
286 sendMessage(message: ds.data());
287 *success = true;
288 }
289 return id;
290}
291
292qint32 QQmlEngineDebugClient::resetBindingForObject(
293 qint32 objectDebugId,
294 const QString &propertyName,
295 bool *success)
296{
297 qint32 id = -1;
298 *success = false;
299 if (state() == QQmlDebugClient::Enabled && objectDebugId != -1) {
300 id = getId();
301 QPacket ds(connection()->currentDataStreamVersion());
302 ds << QByteArray("RESET_BINDING") << id << objectDebugId << propertyName;
303 sendMessage(message: ds.data());
304 *success = true;
305 }
306 return id;
307}
308
309qint32 QQmlEngineDebugClient::setMethodBody(
310 qint32 objectDebugId, const QString &methodName,
311 const QString &methodBody, bool *success)
312{
313 qint32 id = -1;
314 *success = false;
315 if (state() == QQmlDebugClient::Enabled && objectDebugId != -1) {
316 id = getId();
317 QPacket ds(connection()->currentDataStreamVersion());
318 ds << QByteArray("SET_METHOD_BODY") << id << objectDebugId
319 << methodName << methodBody;
320 sendMessage(message: ds.data());
321 *success = true;
322 }
323 return id;
324}
325
326void QQmlEngineDebugClient::decode(QPacket &ds,
327 QQmlEngineDebugObjectReference &o,
328 bool simple)
329{
330 QQmlObjectData data;
331 ds >> data;
332 o.debugId = data.objectId;
333 o.className = data.objectType;
334 o.idString = data.idString;
335 o.name = data.objectName;
336 o.source.url = data.url;
337 o.source.lineNumber = data.lineNumber;
338 o.source.columnNumber = data.columnNumber;
339 o.contextDebugId = data.contextId;
340
341 if (simple)
342 return;
343
344 qint32 childCount;
345 bool recur;
346 ds >> childCount >> recur;
347
348 for (qint32 ii = 0; ii < childCount; ++ii) {
349 o.children.append(t: QQmlEngineDebugObjectReference());
350 decode(ds, o&: o.children.last(), simple: !recur);
351 }
352
353 qint32 propCount;
354 ds >> propCount;
355
356 for (qint32 ii = 0; ii < propCount; ++ii) {
357 QQmlObjectProperty data;
358 ds >> data;
359 QQmlEngineDebugPropertyReference prop;
360 prop.objectDebugId = o.debugId;
361 prop.name = data.name;
362 prop.binding = data.binding;
363 prop.hasNotifySignal = data.hasNotifySignal;
364 prop.valueTypeName = data.valueTypeName;
365 switch (data.type) {
366 case QQmlObjectProperty::Basic:
367 case QQmlObjectProperty::List:
368 case QQmlObjectProperty::SignalProperty:
369 {
370 prop.value = data.value;
371 break;
372 }
373 case QQmlObjectProperty::Object:
374 {
375 QQmlEngineDebugObjectReference obj;
376 obj.name = data.value.toString();
377 obj.className = prop.valueTypeName;
378 prop.value = QVariant::fromValue(value: obj);
379 break;
380 }
381 case QQmlObjectProperty::Unknown:
382 break;
383 }
384 o.properties << prop;
385 }
386}
387
388void QQmlEngineDebugClient::decode(QPacket &ds,
389 QList<QQmlEngineDebugObjectReference> &o,
390 bool simple)
391{
392 qint32 count;
393 ds >> count;
394 for (qint32 i = 0; i < count; i++) {
395 QQmlEngineDebugObjectReference obj;
396 decode(ds, o&: obj, simple);
397 o << obj;
398 }
399}
400
401QList<QQmlEngineDebugEngineReference> QQmlEngineDebugClient::engines() const
402{
403 Q_D(const QQmlEngineDebugClient);
404 return d->engines;
405}
406
407QQmlEngineDebugContextReference QQmlEngineDebugClient::rootContext() const
408{
409 Q_D(const QQmlEngineDebugClient);
410 return d->rootContext;
411}
412
413QQmlEngineDebugObjectReference QQmlEngineDebugClient::object() const
414{
415 Q_D(const QQmlEngineDebugClient);
416 return d->object;
417}
418
419QList<QQmlEngineDebugObjectReference> QQmlEngineDebugClient::objects() const
420{
421 Q_D(const QQmlEngineDebugClient);
422 return d->objects;
423}
424
425QVariant QQmlEngineDebugClient::resultExpr() const
426{
427 Q_D(const QQmlEngineDebugClient);
428 return d->exprResult;
429}
430
431bool QQmlEngineDebugClient::valid() const
432{
433 Q_D(const QQmlEngineDebugClient);
434 return d->valid;
435}
436
437void QQmlEngineDebugClient::decode(QPacket &ds,
438 QQmlEngineDebugContextReference &c)
439{
440 ds >> c.name >> c.debugId;
441
442 qint32 contextCount;
443 ds >> contextCount;
444
445 for (qint32 ii = 0; ii < contextCount; ++ii) {
446 c.contexts.append(t: QQmlEngineDebugContextReference());
447 decode(ds, c&: c.contexts.last());
448 }
449
450 qint32 objectCount;
451 ds >> objectCount;
452
453 for (qint32 ii = 0; ii < objectCount; ++ii) {
454 QQmlEngineDebugObjectReference obj;
455 decode(ds, o&: obj, simple: true);
456
457 obj.contextDebugId = c.debugId;
458 c.objects << obj;
459 }
460}
461
462void QQmlEngineDebugClient::messageReceived(const QByteArray &data)
463{
464 Q_D(QQmlEngineDebugClient);
465 d->valid = false;
466 QPacket ds(connection()->currentDataStreamVersion(), data);
467
468 qint32 queryId;
469 QByteArray type;
470 ds >> type >> queryId;
471
472 //qDebug() << "QQmlEngineDebugPrivate::message()" << type;
473
474 if (type == "LIST_ENGINES_R") {
475 qint32 count;
476 ds >> count;
477
478 d->engines.clear();
479 for (qint32 ii = 0; ii < count; ++ii) {
480 QQmlEngineDebugEngineReference eng;
481 ds >> eng.name;
482 ds >> eng.debugId;
483 d->engines << eng;
484 }
485 } else if (type == "LIST_OBJECTS_R") {
486 if (!ds.atEnd())
487 decode(ds, c&: d->rootContext);
488
489 } else if (type == "FETCH_OBJECT_R") {
490 if (!ds.atEnd())
491 decode(ds, o&: d->object, simple: false);
492
493 } else if (type == "FETCH_OBJECTS_FOR_LOCATION_R") {
494 if (!ds.atEnd())
495 decode(ds, o&: d->objects, simple: false);
496
497 } else if (type == "EVAL_EXPRESSION_R") {;
498 ds >> d->exprResult;
499
500 } else if (type == "WATCH_PROPERTY_R") {
501 ds >> d->valid;
502
503 } else if (type == "WATCH_OBJECT_R") {
504 ds >> d->valid;
505
506 } else if (type == "WATCH_EXPR_OBJECT_R") {
507 ds >> d->valid;
508
509 } else if (type == "UPDATE_WATCH") {
510 qint32 debugId;
511 QByteArray name;
512 QVariant value;
513 ds >> debugId >> name >> value;
514 emit valueChanged(name, value);
515 return;
516
517 } else if (type == "OBJECT_CREATED") {
518 qint32 engineId;
519 qint32 objectId;
520 qint32 parentId;
521 ds >> engineId >> objectId >> parentId;
522 emit newObject(objectId);
523 return;
524 } else if (type == "SET_BINDING_R") {
525 ds >> d->valid;
526 } else if (type == "RESET_BINDING_R") {
527 ds >> d->valid;
528 } else if (type == "SET_METHOD_BODY_R") {
529 ds >> d->valid;
530 } else if (type == "NO_WATCH_R") {
531 ds >> d->valid;
532 }
533 emit result();
534}
535
536
537qint32 QQmlEngineDebugClient::getId()
538{
539 Q_D(QQmlEngineDebugClient);
540 return d->nextId++;
541}
542
543QT_END_NAMESPACE
544
545#include "moc_qqmlenginedebugclient_p.cpp"
546

source code of qtdeclarative/src/qmldebug/qqmlenginedebugclient.cpp