Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qqmlenginedebugservice.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5#include "qqmlwatcher.h"
6
7#include <private/qqmldebugstatesdelegate_p.h>
8#include <private/qqmlboundsignal_p.h>
9#include <qqmlengine.h>
10#include <private/qqmlmetatype_p.h>
11#include <qqmlproperty.h>
12#include <private/qqmlproperty_p.h>
13#include <private/qqmlbinding_p.h>
14#include <private/qqmlcontext_p.h>
15#include <private/qqmlvaluetype_p.h>
16#include <private/qqmlvmemetaobject_p.h>
17#include <private/qqmlexpression_p.h>
18#include <private/qqmlsignalnames_p.h>
19
20#include <QtCore/qdebug.h>
21#include <QtCore/qmetaobject.h>
22#include <QtCore/qfileinfo.h>
23#include <QtCore/qjsonvalue.h>
24#include <QtCore/qjsonobject.h>
25#include <QtCore/qjsonarray.h>
26#include <QtCore/qjsondocument.h>
27
28#include <private/qmetaobject_p.h>
29#include <private/qqmldebugconnector_p.h>
30#include <private/qversionedpacket_p.h>
31
33
34using QQmlDebugPacket = QVersionedPacket<QQmlDebugConnector>;
35
36class NullDevice : public QIODevice
37{
38public:
40
41protected:
42 qint64 readData(char *data, qint64 maxlen) final;
43 qint64 writeData(const char *data, qint64 len) final;
44};
45
47{
49 return maxlen;
50}
51
53{
55 return len;
56}
57
58// check whether the data can be saved
59// (otherwise we assert in QVariant::operator<< when actually saving it)
60static bool isSaveable(const QVariant &value)
61{
62 const int valType = static_cast<int>(value.userType());
63 if (valType >= QMetaType::User)
64 return false;
65 NullDevice nullDevice;
66 QDataStream fakeStream(&nullDevice);
67 return QMetaType(valType).save(fakeStream, value.constData());
68}
69
71 QQmlEngineDebugService(2, parent), m_watch(new QQmlWatcher(this)), m_statesDelegate(nullptr)
72{
74 this, &QQmlEngineDebugServiceImpl::propertyChanged);
75
76 // Move the message into the correct thread for processing
78 this, &QQmlEngineDebugServiceImpl::processMessage, Qt::QueuedConnection);
79}
80
82{
83 delete m_statesDelegate;
84}
85
88{
89 ds << data.url << data.lineNumber << data.columnNumber << data.idString
90 << data.objectName << data.objectType << data.objectId << data.contextId
91 << data.parentId;
92 return ds;
93}
94
97{
98 ds >> data.url >> data.lineNumber >> data.columnNumber >> data.idString
99 >> data.objectName >> data.objectType >> data.objectId >> data.contextId
100 >> data.parentId;
101 return ds;
102}
103
106{
107 ds << (int)data.type << data.name;
108 ds << (isSaveable(data.value) ? data.value : QVariant());
109 ds << data.valueTypeName << data.binding << data.hasNotifySignal;
110 return ds;
111}
112
115{
116 int type;
117 ds >> type >> data.name >> data.value >> data.valueTypeName
118 >> data.binding >> data.hasNotifySignal;
120 return ds;
121}
122
123static bool hasValidSignal(QObject *object, const QString &propertyName)
124{
125 auto signalName = QQmlSignalNames::handlerNameToSignalName(propertyName);
126 if (!signalName)
127 return false;
128
129 int sigIdx = QQmlPropertyPrivate::findSignalByName(object->metaObject(), signalName->toLatin1())
130 .methodIndex();
131
132 if (sigIdx == -1)
133 return false;
134
135 return true;
136}
137
139QQmlEngineDebugServiceImpl::propertyData(QObject *obj, int propIdx)
140{
142
143 QMetaProperty prop = obj->metaObject()->property(propIdx);
144
146 rv.valueTypeName = QString::fromUtf8(prop.typeName());
147 rv.name = QString::fromUtf8(prop.name());
148 rv.hasNotifySignal = prop.hasNotifySignal();
149 QQmlAbstractBinding *binding =
151 if (binding)
152 rv.binding = binding->expression();
153
154 rv.value = valueContents(prop.read(obj));
155
156 if (prop.metaType().flags().testFlag(QMetaType::PointerToQObject)) {
158 } else if (QQmlMetaType::isList(prop.metaType())) {
159 rv.type = QQmlObjectProperty::List;
160 } else if (prop.userType() == QMetaType::QVariant) {
162 } else if (rv.value.isValid()) {
164 }
165
166 return rv;
167}
168
169QVariant QQmlEngineDebugServiceImpl::valueContents(QVariant value) const
170{
171 // We can't send JS objects across the wire, so transform them to variant
172 // maps for serialization.
173 if (value.userType() == qMetaTypeId<QJSValue>())
175 const QMetaType metaType = value.metaType();
176 const int metaTypeId = metaType.id();
177
178 //QObject * is not streamable.
179 //Convert all such instances to a String value
180
181 if (value.userType() == QMetaType::QVariantList) {
184 int count = list.size();
185 contents.reserve(count);
186 for (int i = 0; i < count; i++)
187 contents << valueContents(list.at(i));
188 return contents;
189 }
190
191 if (value.userType() == QMetaType::QVariantMap) {
193 const auto map = value.toMap();
194 for (auto i = map.cbegin(), end = map.cend(); i != end; ++i)
195 contents.insert(i.key(), valueContents(i.value()));
196 return contents;
197 }
198
199 switch (metaTypeId) {
200 case QMetaType::QRect:
201 case QMetaType::QRectF:
202 case QMetaType::QPoint:
203 case QMetaType::QPointF:
204 case QMetaType::QSize:
205 case QMetaType::QSizeF:
206 case QMetaType::QFont:
207 // Don't call the toString() method on those. The stream operators are better.
208 return value;
209 case QMetaType::QJsonValue:
210 return value.toJsonValue().toVariant();
211 case QMetaType::QJsonObject:
212 return value.toJsonObject().toVariantMap();
213 case QMetaType::QJsonArray:
214 return value.toJsonArray().toVariantList();
215 case QMetaType::QJsonDocument:
216 return value.toJsonDocument().toVariant();
217 default:
218 if (QQmlMetaType::isValueType(metaType)) {
220 if (mo) {
221 int toStringIndex = mo->indexOfMethod("toString()");
222 if (toStringIndex != -1) {
223 QMetaMethod mm = mo->method(toStringIndex);
224 QString s;
225 if (mm.invokeOnGadget(value.data(), Q_RETURN_ARG(QString, s)))
226 return s;
227 }
228 }
229 }
230
231 if (isSaveable(value))
232 return value;
233 }
234
235 if (metaType.flags().testFlag(QMetaType::PointerToQObject)) {
237 if (o) {
238 QString name = o->objectName();
239 if (name.isEmpty())
240 name = QStringLiteral("<unnamed object>");
241 return name;
242 }
243 }
244
245 return QString(QStringLiteral("<unknown value>"));
246}
247
248void QQmlEngineDebugServiceImpl::buildObjectDump(QDataStream &message,
249 QObject *object, bool recur, bool dumpProperties)
250{
251 message << objectData(object);
252
253 QObjectList children = object->children();
254
255 int childrenCount = children.size();
256 for (int ii = 0; ii < children.size(); ++ii) {
257 if (qobject_cast<QQmlContext*>(children[ii]))
258 --childrenCount;
259 }
260
261 message << childrenCount << recur;
262
263 QList<QQmlObjectProperty> fakeProperties;
264
265 for (int ii = 0; ii < children.size(); ++ii) {
266 QObject *child = children.at(ii);
267 if (qobject_cast<QQmlContext*>(child))
268 continue;
269 if (recur)
270 buildObjectDump(message, child, recur, dumpProperties);
271 else
272 message << objectData(child);
273 }
274
275 if (!dumpProperties) {
276 message << 0;
277 return;
278 }
279
280 QList<int> propertyIndexes;
281 for (int ii = 0; ii < object->metaObject()->propertyCount(); ++ii) {
282 if (object->metaObject()->property(ii).isScriptable())
283 propertyIndexes << ii;
284 }
285
286 QQmlData *ddata = QQmlData::get(object);
287 if (ddata && ddata->signalHandlers) {
288 QQmlBoundSignal *signalHandler = ddata->signalHandlers;
289
290 while (signalHandler) {
293 prop.hasNotifySignal = false;
294 QQmlBoundSignalExpression *expr = signalHandler->expression();
295 if (expr) {
296 prop.value = expr->expression();
297 QObject *scope = expr->scopeObject();
298 if (scope) {
299 const QByteArray methodName = QMetaObjectPrivate::signal(scope->metaObject(),
300 signalHandler->signalIndex()).name();
301 if (!methodName.isEmpty()) {
303 }
304 }
305 }
306 fakeProperties << prop;
307
308 signalHandler = nextSignal(signalHandler);
309 }
310 }
311
312 message << int(propertyIndexes.size() + fakeProperties.size());
313
314 for (int ii = 0; ii < propertyIndexes.size(); ++ii)
315 message << propertyData(object, propertyIndexes.at(ii));
316
317 for (int ii = 0; ii < fakeProperties.size(); ++ii)
318 message << fakeProperties[ii];
319}
320
321void QQmlEngineDebugServiceImpl::prepareDeferredObjects(QObject *obj)
322{
324
325 QObjectList children = obj->children();
326 for (int ii = 0; ii < children.size(); ++ii) {
327 QObject *child = children.at(ii);
328 prepareDeferredObjects(child);
329 }
330
331}
332
333void QQmlEngineDebugServiceImpl::storeObjectIds(QObject *co)
334{
336 QObjectList children = co->children();
337 for (int ii = 0; ii < children.size(); ++ii)
338 storeObjectIds(children.at(ii));
339}
340
341void QQmlEngineDebugServiceImpl::buildObjectList(QDataStream &message,
342 QQmlContext *ctxt,
343 const QList<QPointer<QObject> > &instances)
344{
345 if (!ctxt->isValid())
346 return;
347
348 QQmlRefPointer<QQmlContextData> p = QQmlContextData::get(ctxt);
349
350 QString ctxtName = ctxt->objectName();
351 int ctxtId = QQmlDebugService::idForObject(ctxt);
352 if (ctxt->contextObject())
353 storeObjectIds(ctxt->contextObject());
354
355 message << ctxtName << ctxtId;
356
357 int count = 0;
358
359 QQmlRefPointer<QQmlContextData> child = p->childContexts();
360 while (child) {
361 ++count;
362 child = child->nextChild();
363 }
364
365 message << count;
366
367 child = p->childContexts();
368 while (child) {
369 buildObjectList(message, child->asQQmlContext(), instances);
370 child = child->nextChild();
371 }
372
373 count = 0;
374 for (int ii = 0; ii < instances.size(); ++ii) {
375 QQmlData *data = QQmlData::get(instances.at(ii));
376 if (data->context == p.data())
377 count ++;
378 }
379 message << count;
380
381 for (int ii = 0; ii < instances.size(); ++ii) {
382 QQmlData *data = QQmlData::get(instances.at(ii));
383 if (data->context == p.data())
384 message << objectData(instances.at(ii));
385 }
386}
387
388void QQmlEngineDebugServiceImpl::buildStatesList(bool cleanList,
389 const QList<QPointer<QObject> > &instances)
390{
391 if (auto delegate = statesDelegate())
392 delegate->buildStatesList(cleanList, instances);
393}
394
396QQmlEngineDebugServiceImpl::objectData(QObject *object)
397{
398 QQmlData *ddata = QQmlData::get(object);
400 if (ddata && ddata->outerContext) {
401 rv.url = ddata->outerContext->url();
402 rv.lineNumber = ddata->lineNumber;
403 rv.columnNumber = ddata->columnNumber;
404 } else {
405 rv.lineNumber = -1;
406 rv.columnNumber = -1;
407 }
408
409 QQmlContext *context = qmlContext(object);
410 if (context && context->isValid())
411 rv.idString = QQmlContextData::get(context)->findObjectId(object);
412
413 rv.objectName = object->objectName();
414 rv.objectId = QQmlDebugService::idForObject(object);
415 rv.contextId = QQmlDebugService::idForObject(qmlContext(object));
416 rv.parentId = QQmlDebugService::idForObject(object->parent());
417 rv.objectType = QQmlMetaType::prettyTypeName(object);
418 return rv;
419}
420
425
429QList<QObject*> QQmlEngineDebugServiceImpl::objectForLocationInfo(const QString &filename,
430 int lineNumber, int columnNumber)
431{
432 QList<QObject *> objects;
433 const QHash<int, QObject *> &hash = objectsForIds();
434 for (QHash<int, QObject *>::ConstIterator i = hash.constBegin(); i != hash.constEnd(); ++i) {
435 QQmlData *ddata = QQmlData::get(i.value());
436 if (ddata && ddata->outerContext && ddata->outerContext->isValid()) {
437 if (QFileInfo(ddata->outerContext->urlString()).fileName() == filename &&
438 ddata->lineNumber == lineNumber &&
439 ddata->columnNumber >= columnNumber) {
440 objects << i.value();
441 }
442 }
443 }
444 return objects;
445}
446
447void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message)
448{
450
453 ds >> type >> queryId;
454
456
457 if (type == "LIST_ENGINES") {
458 rs << QByteArray("LIST_ENGINES_R");
459 rs << queryId << int(m_engines.size());
460
461 for (int ii = 0; ii < m_engines.size(); ++ii) {
462 QJSEngine *engine = m_engines.at(ii);
463
464 QString engineName = engine->objectName();
466
467 rs << engineName << engineId;
468 }
469
470 } else if (type == "LIST_OBJECTS") {
471 qint32 engineId = -1;
472 ds >> engineId;
473
475 qobject_cast<QQmlEngine *>(QQmlDebugService::objectForId(engineId));
476
477 rs << QByteArray("LIST_OBJECTS_R") << queryId;
478
479 if (engine) {
480 QQmlContext *rootContext = engine->rootContext();
481 QQmlContextPrivate *ctxtPriv = QQmlContextPrivate::get(rootContext);
482 ctxtPriv->cleanInstances(); // Clean deleted objects
483 const QList<QPointer<QObject>> instances = ctxtPriv->instances();
484 buildObjectList(rs, rootContext, instances);
485 buildStatesList(true, instances);
486 }
487
488 } else if (type == "FETCH_OBJECT") {
489 qint32 objectId;
490 bool recurse;
491 bool dumpProperties = true;
492
493 ds >> objectId >> recurse >> dumpProperties;
494
495 QObject *object = QQmlDebugService::objectForId(objectId);
496
497 rs << QByteArray("FETCH_OBJECT_R") << queryId;
498
499 if (object) {
500 if (recurse)
501 prepareDeferredObjects(object);
502 buildObjectDump(rs, object, recurse, dumpProperties);
503 }
504
505 } else if (type == "FETCH_OBJECTS_FOR_LOCATION") {
507 qint32 lineNumber;
508 qint32 columnNumber;
509 bool recurse;
510 bool dumpProperties = true;
511
512 ds >> file >> lineNumber >> columnNumber >> recurse >> dumpProperties;
513
514 const QList<QObject*> objects = objectForLocationInfo(file, lineNumber, columnNumber);
515
516 rs << QByteArray("FETCH_OBJECTS_FOR_LOCATION_R") << queryId
517 << int(objects.size());
518
519 for (QObject *object : objects) {
520 if (recurse)
521 prepareDeferredObjects(object);
522 buildObjectDump(rs, object, recurse, dumpProperties);
523 }
524
525 } else if (type == "WATCH_OBJECT") {
526 qint32 objectId;
527
528 ds >> objectId;
529 bool ok = m_watch->addWatch(queryId, objectId);
530
531 rs << QByteArray("WATCH_OBJECT_R") << queryId << ok;
532
533 } else if (type == "WATCH_PROPERTY") {
534 qint32 objectId;
536
537 ds >> objectId >> property;
538 bool ok = m_watch->addWatch(queryId, objectId, property);
539
540 rs << QByteArray("WATCH_PROPERTY_R") << queryId << ok;
541
542 } else if (type == "WATCH_EXPR_OBJECT") {
543 qint32 debugId;
544 QString expr;
545
546 ds >> debugId >> expr;
547 bool ok = m_watch->addWatch(queryId, debugId, expr);
548
549 rs << QByteArray("WATCH_EXPR_OBJECT_R") << queryId << ok;
550
551 } else if (type == "NO_WATCH") {
552 bool ok = m_watch->removeWatch(queryId);
553
554 rs << QByteArray("NO_WATCH_R") << queryId << ok;
555
556 } else if (type == "EVAL_EXPRESSION") {
557 qint32 objectId;
558 QString expr;
559
560 ds >> objectId >> expr;
561 qint32 engineId = -1;
562 if (!ds.atEnd())
563 ds >> engineId;
564
565 QObject *object = QQmlDebugService::objectForId(objectId);
566 QQmlContext *context = qmlContext(object);
567 if (!context || !context->isValid()) {
568 QQmlEngine *engine = qobject_cast<QQmlEngine *>(
570 if (engine && m_engines.contains(engine))
571 context = engine->rootContext();
572 }
574 if (context && context->isValid()) {
575 QQmlExpression exprObj(context, object, expr);
576 bool undefined = false;
577 QVariant value = exprObj.evaluate(&undefined);
578 if (undefined)
579 result = QString(QStringLiteral("<undefined>"));
580 else
581 result = valueContents(value);
582 } else {
583 result = QString(QStringLiteral("<unknown context>"));
584 }
585
586 rs << QByteArray("EVAL_EXPRESSION_R") << queryId << result;
587
588 } else if (type == "SET_BINDING") {
589 qint32 objectId;
590 QString propertyName;
591 QVariant expr;
592 bool isLiteralValue;
593 QString filename;
594 qint32 line;
595 ds >> objectId >> propertyName >> expr >> isLiteralValue >>
596 filename >> line;
597 bool ok = setBinding(objectId, propertyName, expr, isLiteralValue,
598 filename, line);
599
600 rs << QByteArray("SET_BINDING_R") << queryId << ok;
601
602 } else if (type == "RESET_BINDING") {
603 qint32 objectId;
604 QString propertyName;
605 ds >> objectId >> propertyName;
606 bool ok = resetBinding(objectId, propertyName);
607
608 rs << QByteArray("RESET_BINDING_R") << queryId << ok;
609
610 } else if (type == "SET_METHOD_BODY") {
611 qint32 objectId;
613 QString methodBody;
614 ds >> objectId >> methodName >> methodBody;
615 bool ok = setMethodBody(objectId, methodName, methodBody);
616
617 rs << QByteArray("SET_METHOD_BODY_R") << queryId << ok;
618
619 }
620 emit messageToClient(name(), rs.data());
621}
622
623bool QQmlEngineDebugServiceImpl::setBinding(int objectId,
624 const QString &propertyName,
625 const QVariant &expression,
626 bool isLiteralValue,
627 QString filename,
628 int line,
629 int column)
630{
631 bool ok = true;
632 QObject *object = objectForId(objectId);
633 QQmlContext *context = qmlContext(object);
634
635 if (object && context && context->isValid()) {
636 QQmlProperty property(object, propertyName, context);
637 if (property.isValid()) {
638
639 bool inBaseState = true;
640 if (auto delegate = statesDelegate()) {
641 delegate->updateBinding(context, property, expression, isLiteralValue,
642 filename, line, column, &inBaseState);
643 }
644
645 if (inBaseState) {
646 if (isLiteralValue) {
647 property.write(expression);
648 } else if (hasValidSignal(object, propertyName)) {
650 QQmlContextData::get(context), object, expression.toString(),
651 filename, line, column);
653 } else if (property.isProperty()) {
654 QQmlBinding *binding = QQmlBinding::create(&QQmlPropertyPrivate::get(property)->core, expression.toString(), object, QQmlContextData::get(context), filename, line);
655 binding->setTarget(property);
657 binding->update();
658 } else {
659 ok = false;
660 qWarning() << "QQmlEngineDebugService::setBinding: unable to set property" << propertyName << "on object" << object;
661 }
662 }
663
664 } else {
665 // not a valid property
666 if (auto delegate = statesDelegate())
667 ok = delegate->setBindingForInvalidProperty(object, propertyName, expression, isLiteralValue);
668 if (!ok)
669 qWarning() << "QQmlEngineDebugService::setBinding: unable to set property" << propertyName << "on object" << object;
670 }
671 }
672 return ok;
673}
674
675bool QQmlEngineDebugServiceImpl::resetBinding(int objectId, const QString &propertyName)
676{
677 QObject *object = objectForId(objectId);
678 QQmlContext *context = qmlContext(object);
679
680 if (object && context && context->isValid()) {
681 QStringView parentPropertyRef(propertyName);
682 const int idx = parentPropertyRef.indexOf(QLatin1Char('.'));
683 if (idx != -1)
684 parentPropertyRef = parentPropertyRef.left(idx);
685
686 const QByteArray parentProperty = parentPropertyRef.toLatin1();
687 if (object->property(parentProperty).isValid()) {
688 QQmlProperty property(object, propertyName);
690 if (property.isResettable()) {
691 // Note: this will reset the property in any case, without regard to states
692 // Right now almost no QQuickItem has reset methods for its properties (with the
693 // notable exception of QQuickAnchors), so this is not a big issue
694 // later on, setBinding does take states into account
695 property.reset();
696 } else {
697 // overwrite with default value
698 QQmlType objType = QQmlMetaType::qmlType(object->metaObject());
699 if (objType.isValid()) {
700 if (QObject *emptyObject = objType.create()) {
701 if (emptyObject->property(parentProperty).isValid()) {
702 QVariant defaultValue = QQmlProperty(emptyObject, propertyName).read();
703 if (defaultValue.isValid()) {
704 setBinding(objectId, propertyName, defaultValue, true);
705 }
706 }
707 delete emptyObject;
708 }
709 }
710 }
711 return true;
712 }
713
714 if (hasValidSignal(object, propertyName)) {
715 QQmlProperty property(object, propertyName, context);
717 return true;
718 }
719
720 if (auto delegate = statesDelegate()) {
721 delegate->resetBindingForInvalidProperty(object, propertyName);
722 return true;
723 }
724
725 return false;
726 }
727 // object or context null.
728 return false;
729}
730
731bool QQmlEngineDebugServiceImpl::setMethodBody(int objectId, const QString &method, const QString &body)
732{
733 QObject *object = objectForId(objectId);
734 QQmlContext *context = qmlContext(object);
735 if (!object || !context || !context->isValid())
736 return false;
737 QQmlRefPointer<QQmlContextData> contextData = QQmlContextData::get(context);
738
739 QQmlPropertyData dummy;
740 const QQmlPropertyData *prop = QQmlPropertyCache::property(object, method, contextData, &dummy);
741
742 if (!prop || !prop->isVMEFunction())
743 return false;
744
745 QMetaMethod metaMethod = object->metaObject()->method(prop->coreIndex());
746 QList<QByteArray> paramNames = metaMethod.parameterNames();
747
748 QString paramStr;
749 for (int ii = 0; ii < paramNames.size(); ++ii) {
750 if (ii != 0) paramStr.append(QLatin1Char(','));
751 paramStr.append(QString::fromUtf8(paramNames.at(ii)));
752 }
753
754 const QString jsfunction = QLatin1String("(function ") + method + QLatin1Char('(') + paramStr +
755 QLatin1String(") {") + body + QLatin1String("\n})");
756
757 QQmlVMEMetaObject *vmeMetaObject = QQmlVMEMetaObject::get(object);
758 Q_ASSERT(vmeMetaObject); // the fact we found the property above should guarentee this
759
760 QV4::ExecutionEngine *v4 = qmlEngine(object)->handle();
761 QV4::Scope scope(v4);
762
763 int lineNumber = 0;
765 scope, vmeMetaObject->vmeMethod(prop->coreIndex()));
766 if (oldMethod && oldMethod->d()->function)
767 lineNumber = oldMethod->d()->function->compiledFunction->location.line();
768
769 QV4::ScopedValue v(scope, QQmlJavaScriptExpression::evalFunction(contextData, object, jsfunction, contextData->urlString(), lineNumber));
770 vmeMetaObject->setVmeMethod(prop->coreIndex(), v);
771 return true;
772}
773
774void QQmlEngineDebugServiceImpl::propertyChanged(
775 qint32 id, qint32 objectId, const QMetaProperty &property, const QVariant &value)
776{
778 rs << QByteArray("UPDATE_WATCH") << id << objectId << QByteArray(property.name()) << valueContents(value);
779 emit messageToClient(name(), rs.data());
780}
781
783{
785 Q_ASSERT(!m_engines.contains(engine));
786
787 m_engines.append(engine);
788 emit attachedToEngine(engine);
789}
790
792{
794 Q_ASSERT(m_engines.contains(engine));
795
796 m_engines.removeAll(engine);
797 emit detachedFromEngine(engine);
798}
799
801{
803 if (!m_engines.contains(engine))
804 return;
805
807 qint32 objectId = QQmlDebugService::idForObject(object);
808 qint32 parentId = QQmlDebugService::idForObject(object->parent());
809
811
812 //unique queryId -1
813 rs << QByteArray("OBJECT_CREATED") << qint32(-1) << engineId << objectId << parentId;
814 emit messageToClient(name(), rs.data());
815}
816
818
819#include "moc_qqmlenginedebugservice.cpp"
qint64 writeData(const char *data, qint64 len) final
Writes up to maxSize bytes from data to the device.
qint64 readData(char *data, qint64 maxlen) final
Reads up to maxSize bytes from the device into data, and returns the number of bytes read or -1 if an...
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore\reentrant
Definition qdatastream.h:46
QString fileName() const
\inmodule QtCore
Definition qhash.h:1145
\inmodule QtCore \reentrant
Definition qiodevice.h:34
virtual bool open(QIODeviceBase::OpenMode mode)
Opens the device and sets its OpenMode to mode.
The QJSEngine class provides an environment for evaluating JavaScript code.
Definition qjsengine.h:26
QV4::ExecutionEngine * handle() const
Definition qjsengine.h:298
The QJSValue class acts as a container for Qt/JavaScript data types.
Definition qjsvalue.h:31
qsizetype size() const noexcept
Definition qlist.h:397
QList< T > toList() const noexcept
Definition qlist.h:723
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
qsizetype removeAll(const AT &t)
Definition qlist.h:592
void append(parameter_type t)
Definition qlist.h:458
const_iterator cend() const
Definition qmap.h:605
const_iterator cbegin() const
Definition qmap.h:601
\inmodule QtCore
Definition qmetaobject.h:19
bool invokeOnGadget(void *gadget, QGenericReturnArgument returnValue, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument()) const
QList< QByteArray > parameterNames() const
Returns a list of parameter names.
\inmodule QtCore
const char * typeName() const
Returns the name of this property's type.
int userType() const
QMetaType metaType() const
QVariant read(const QObject *obj) const
Reads the property's value from the given object.
const char * name() const
Returns this property's name.
bool hasNotifySignal() const
Returns true if this property has a corresponding change notify signal; otherwise returns false.
\inmodule QtCore
Definition qmetatype.h:341
constexpr TypeFlags flags() const
Definition qmetatype.h:2658
int id(int=0) const
Definition qmetatype.h:475
@ PointerToQObject
Definition qmetatype.h:406
bool save(QDataStream &stream, const void *data) const
Writes the object pointed to by data to the given stream.
friend class QVariant
Definition qmetatype.h:796
\inmodule QtCore
Definition qobject.h:103
QString objectName
the name of this object
Definition qobject.h:107
void setTarget(const QQmlProperty &)
virtual QString expression() const
void update(QQmlPropertyData::WriteFlags flags=QQmlPropertyData::DontRemoveBinding)
static QQmlBinding * create(const QQmlPropertyData *, const QQmlScriptString &, QObject *, QQmlContext *)
QQmlBoundSignalExpression * expression() const
Returns the signal expression.
static QQmlRefPointer< QQmlContextData > get(QQmlContext *context)
static QQmlContextPrivate * get(QQmlContext *context)
The QQmlContext class defines a context within a QML engine.
Definition qqmlcontext.h:25
bool isValid() const
Returns whether the context is valid.
QObject * contextObject() const
Return the context object, or \nullptr if there is no context object.
static QQmlData * get(QObjectPrivate *priv, bool create)
Definition qqmldata_p.h:199
static int idForObject(QObject *)
Returns a unique id for object.
static QObject * objectForId(int id)
void objectCreated(QJSEngine *, QObject *) override
void engineAboutToBeAdded(QJSEngine *) override
void messageReceived(const QByteArray &) override
QQmlEngineDebugServiceImpl(QObject *=nullptr)
void scheduleMessage(const QByteArray &)
void engineAboutToBeRemoved(QJSEngine *) override
QQmlDebugStatesDelegate * statesDelegate()
The QQmlEngine class provides an environment for instantiating QML components.
Definition qqmlengine.h:57
The QQmlExpression class evaluates JavaScript in a QML context.
static QV4::ReturnedValue evalFunction(const QQmlRefPointer< QQmlContextData > &ctxt, QObject *scope, const QString &code, const QString &filename, quint16 line)
static QString prettyTypeName(const QObject *object)
Returns the pretty QML type name (e.g.
static bool isList(QMetaType type)
static const QMetaObject * metaObjectForValueType(QMetaType type)
static QObject * toQObject(const QVariant &, bool *ok=nullptr)
static QQmlType qmlType(const QString &qualifiedName, QTypeRevision version)
Returns the type (if any) of URI-qualified named qualifiedName and version specified by version_major...
static bool isValueType(QMetaType type)
const QQmlPropertyData * property(const K &key, QObject *object, const QQmlRefPointer< QQmlContextData > &context) const
bool isVMEFunction() const
static void takeSignalExpression(const QQmlProperty &that, QQmlBoundSignalExpression *)
Set the signal expression associated with this signal property to expr.
static void setBinding(QQmlAbstractBinding *binding, BindingFlags flags=None, QQmlPropertyData::WriteFlags writeFlags=QQmlPropertyData::DontRemoveBinding)
static void removeBinding(const QQmlProperty &that)
static void setSignalExpression(const QQmlProperty &that, QQmlBoundSignalExpression *)
Set the signal expression associated with this signal property to expr.
static QQmlPropertyPrivate * get(const QQmlProperty &p)
static QMetaMethod findSignalByName(const QMetaObject *mo, const QByteArray &)
Return the signal corresponding to name.
static QQmlAbstractBinding * binding(QObject *, QQmlPropertyIndex index)
The QQmlProperty class abstracts accessing properties on objects created from QML.
QVariant read() const
Returns the property value.
static QString signalNameToHandlerName(QAnyStringView signal)
static std::optional< QString > handlerNameToSignalName(QStringView handler)
static QQmlVMEMetaObject * get(QObject *o)
bool removeWatch(int id)
bool addWatch(int id, quint32 objectId)
void propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value)
\inmodule QtCore
Definition qstringview.h:78
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:6018
QString & append(QChar c)
Definition qstring.cpp:3252
QString url(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
Definition qurl.cpp:2817
\inmodule QtCore
Definition qvariant.h:65
T value() const &
Definition qvariant.h:516
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:714
QString toString() const
Returns the variant as a QString if the variant has a userType() including, but not limited to:
#define this
Definition dialogs.cpp:9
QHash< int, QWidget * > hash
[35multi]
QMap< QString, QString > map
[6]
auto signalIndex
auto mo
[7]
Combined button and popup list for selecting options.
@ QueuedConnection
static void * context
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char * method
static QString methodName(const QDBusIntrospection::Method &method)
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qWarning
Definition qlogging.h:166
#define Q_RETURN_ARG(Type, data)
Definition qobjectdefs.h:64
GLsizei const GLfloat * v
[13]
GLuint * queryId
GLuint GLuint end
GLenum GLenum GLsizei count
GLuint object
[3]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum type
GLuint GLsizei const GLchar * message
GLuint name
GLenum GLenum GLsizei void GLsizei void * column
GLhandleARB obj
[2]
GLdouble s
[6]
Definition qopenglext.h:235
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
GLenum GLsizei len
void qmlExecuteDeferred(QObject *object)
Definition qqml.cpp:49
QQmlEngine * qmlEngine(const QObject *obj)
Definition qqml.cpp:80
QQmlContext * qmlContext(const QObject *obj)
Definition qqml.cpp:75
static bool isSaveable(const QVariant &value)
static bool hasValidSignal(QObject *object, const QString &propertyName)
QDataStream & operator>>(QDataStream &ds, QQmlEngineDebugServiceImpl::QQmlObjectData &data)
QDataStream & operator<<(QDataStream &ds, const QQmlEngineDebugServiceImpl::QQmlObjectData &data)
int objectForId(const ObjectContainer *objectContainer, const CompiledObject &component, int id)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
#define emit
#define Q_UNUSED(x)
int qint32
Definition qtypes.h:49
long long qint64
Definition qtypes.h:60
static QVariant toVariant(const QV4::Value &value, QMetaType typeHint, JSToQVariantConversionBehavior conversionBehavior, V4ObjectSet *visitedObjects)
const char property[13]
Definition qwizard.cpp:101
QList< int > list
[14]
QFile file
[0]
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection)
QObject::connect nullptr
QByteArray readData()
QLayoutItem * child
[0]
QJSEngine engine
[0]
\inmodule QtCore \reentrant
Definition qchar.h:18
bool contains(const AT &t) const noexcept
Definition qlist.h:45
static Q_CORE_EXPORT QMetaMethod signal(const QMetaObject *m, int signal_index)
\inmodule QtCore