Qt 6.x
The Qt SDK
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
19#include <QtCore/qdebug.h>
20#include <QtCore/qmetaobject.h>
21#include <QtCore/qfileinfo.h>
22#include <QtCore/qjsonvalue.h>
23#include <QtCore/qjsonobject.h>
24#include <QtCore/qjsonarray.h>
25#include <QtCore/qjsondocument.h>
26
27#include <private/qmetaobject_p.h>
28#include <private/qqmldebugconnector_p.h>
29#include <private/qversionedpacket_p.h>
30
32
34
35class NullDevice : public QIODevice
36{
37public:
39
40protected:
41 qint64 readData(char *data, qint64 maxlen) final;
42 qint64 writeData(const char *data, qint64 len) final;
43};
44
46{
48 return maxlen;
49}
50
52{
54 return len;
55}
56
57// check whether the data can be saved
58// (otherwise we assert in QVariant::operator<< when actually saving it)
59static bool isSaveable(const QVariant &value)
60{
61 const int valType = static_cast<int>(value.userType());
62 if (valType >= QMetaType::User)
63 return false;
64 NullDevice nullDevice;
65 QDataStream fakeStream(&nullDevice);
66 return QMetaType(valType).save(fakeStream, value.constData());
67}
68
70 QQmlEngineDebugService(2, parent), m_watch(new QQmlWatcher(this)), m_statesDelegate(nullptr)
71{
73 this, &QQmlEngineDebugServiceImpl::propertyChanged);
74
75 // Move the message into the correct thread for processing
77 this, &QQmlEngineDebugServiceImpl::processMessage, Qt::QueuedConnection);
78}
79
81{
82 delete m_statesDelegate;
83}
84
87{
88 ds << data.url << data.lineNumber << data.columnNumber << data.idString
89 << data.objectName << data.objectType << data.objectId << data.contextId
90 << data.parentId;
91 return ds;
92}
93
96{
97 ds >> data.url >> data.lineNumber >> data.columnNumber >> data.idString
98 >> data.objectName >> data.objectType >> data.objectId >> data.contextId
99 >> data.parentId;
100 return ds;
101}
102
105{
106 ds << (int)data.type << data.name;
107 ds << (isSaveable(data.value) ? data.value : QVariant());
108 ds << data.valueTypeName << data.binding << data.hasNotifySignal;
109 return ds;
110}
111
114{
115 int type;
116 ds >> type >> data.name >> data.value >> data.valueTypeName
117 >> data.binding >> data.hasNotifySignal;
119 return ds;
120}
121
122static inline bool isSignalPropertyName(const QString &signalName)
123{
124 // see QmlCompiler::isSignalPropertyName
125 return signalName.size() >= 3 && signalName.startsWith(QLatin1String("on")) &&
126 signalName.at(2).isLetter() && signalName.at(2).isUpper();
127}
128
129static bool hasValidSignal(QObject *object, const QString &propertyName)
130{
131 if (!isSignalPropertyName(propertyName))
132 return false;
133
134 QString signalName = propertyName.mid(2);
135 signalName[0] = signalName.at(0).toLower();
136
137 int sigIdx = QQmlPropertyPrivate::findSignalByName(object->metaObject(), signalName.toLatin1()).methodIndex();
138
139 if (sigIdx == -1)
140 return false;
141
142 return true;
143}
144
146QQmlEngineDebugServiceImpl::propertyData(QObject *obj, int propIdx)
147{
149
150 QMetaProperty prop = obj->metaObject()->property(propIdx);
151
154 rv.name = QString::fromUtf8(prop.name());
156 QQmlAbstractBinding *binding =
158 if (binding)
159 rv.binding = binding->expression();
160
161 rv.value = valueContents(prop.read(obj));
162
163 if (prop.metaType().flags().testFlag(QMetaType::PointerToQObject)) {
165 } else if (QQmlMetaType::isList(prop.metaType())) {
167 } else if (prop.userType() == QMetaType::QVariant) {
169 } else if (rv.value.isValid()) {
171 }
172
173 return rv;
174}
175
176QVariant QQmlEngineDebugServiceImpl::valueContents(QVariant value) const
177{
178 // We can't send JS objects across the wire, so transform them to variant
179 // maps for serialization.
180 if (value.userType() == qMetaTypeId<QJSValue>())
182 const QMetaType metaType = value.metaType();
183 const int metaTypeId = metaType.id();
184
185 //QObject * is not streamable.
186 //Convert all such instances to a String value
187
188 if (value.userType() == QMetaType::QVariantList) {
191 int count = list.size();
192 contents.reserve(count);
193 for (int i = 0; i < count; i++)
194 contents << valueContents(list.at(i));
195 return contents;
196 }
197
198 if (value.userType() == QMetaType::QVariantMap) {
200 const auto map = value.toMap();
201 for (auto i = map.cbegin(), end = map.cend(); i != end; ++i)
202 contents.insert(i.key(), valueContents(i.value()));
203 return contents;
204 }
205
206 switch (metaTypeId) {
207 case QMetaType::QRect:
208 case QMetaType::QRectF:
209 case QMetaType::QPoint:
210 case QMetaType::QPointF:
211 case QMetaType::QSize:
212 case QMetaType::QSizeF:
213 case QMetaType::QFont:
214 // Don't call the toString() method on those. The stream operators are better.
215 return value;
216 case QMetaType::QJsonValue:
217 return value.toJsonValue().toVariant();
218 case QMetaType::QJsonObject:
219 return value.toJsonObject().toVariantMap();
220 case QMetaType::QJsonArray:
221 return value.toJsonArray().toVariantList();
222 case QMetaType::QJsonDocument:
223 return value.toJsonDocument().toVariant();
224 default:
225 if (QQmlMetaType::isValueType(metaType)) {
227 if (mo) {
228 int toStringIndex = mo->indexOfMethod("toString()");
229 if (toStringIndex != -1) {
230 QMetaMethod mm = mo->method(toStringIndex);
231 QString s;
232 if (mm.invokeOnGadget(value.data(), Q_RETURN_ARG(QString, s)))
233 return s;
234 }
235 }
236 }
237
238 if (isSaveable(value))
239 return value;
240 }
241
242 if (metaType.flags().testFlag(QMetaType::PointerToQObject)) {
244 if (o) {
245 QString name = o->objectName();
246 if (name.isEmpty())
247 name = QStringLiteral("<unnamed object>");
248 return name;
249 }
250 }
251
252 return QString(QStringLiteral("<unknown value>"));
253}
254
255void QQmlEngineDebugServiceImpl::buildObjectDump(QDataStream &message,
256 QObject *object, bool recur, bool dumpProperties)
257{
258 message << objectData(object);
259
260 QObjectList children = object->children();
261
262 int childrenCount = children.size();
263 for (int ii = 0; ii < children.size(); ++ii) {
264 if (qobject_cast<QQmlContext*>(children[ii]))
265 --childrenCount;
266 }
267
268 message << childrenCount << recur;
269
270 QList<QQmlObjectProperty> fakeProperties;
271
272 for (int ii = 0; ii < children.size(); ++ii) {
273 QObject *child = children.at(ii);
274 if (qobject_cast<QQmlContext*>(child))
275 continue;
276 if (recur)
277 buildObjectDump(message, child, recur, dumpProperties);
278 else
279 message << objectData(child);
280 }
281
282 if (!dumpProperties) {
283 message << 0;
284 return;
285 }
286
287 QList<int> propertyIndexes;
288 for (int ii = 0; ii < object->metaObject()->propertyCount(); ++ii) {
289 if (object->metaObject()->property(ii).isScriptable())
290 propertyIndexes << ii;
291 }
292
293 QQmlData *ddata = QQmlData::get(object);
294 if (ddata && ddata->signalHandlers) {
295 QQmlBoundSignal *signalHandler = ddata->signalHandlers;
296
297 while (signalHandler) {
300 prop.hasNotifySignal = false;
301 QQmlBoundSignalExpression *expr = signalHandler->expression();
302 if (expr) {
303 prop.value = expr->expression();
304 QObject *scope = expr->scopeObject();
305 if (scope) {
306 const QByteArray methodName = QMetaObjectPrivate::signal(scope->metaObject(),
307 signalHandler->signalIndex()).name();
308 const QLatin1String methodNameStr(methodName);
309 if (methodNameStr.size() != 0) {
310 prop.name = QLatin1String("on") + QChar(methodNameStr.at(0)).toUpper()
311 + methodNameStr.mid(1);
312 }
313 }
314 }
315 fakeProperties << prop;
316
317 signalHandler = nextSignal(signalHandler);
318 }
319 }
320
321 message << int(propertyIndexes.size() + fakeProperties.size());
322
323 for (int ii = 0; ii < propertyIndexes.size(); ++ii)
324 message << propertyData(object, propertyIndexes.at(ii));
325
326 for (int ii = 0; ii < fakeProperties.size(); ++ii)
327 message << fakeProperties[ii];
328}
329
330void QQmlEngineDebugServiceImpl::prepareDeferredObjects(QObject *obj)
331{
333
334 QObjectList children = obj->children();
335 for (int ii = 0; ii < children.size(); ++ii) {
336 QObject *child = children.at(ii);
337 prepareDeferredObjects(child);
338 }
339
340}
341
342void QQmlEngineDebugServiceImpl::storeObjectIds(QObject *co)
343{
345 QObjectList children = co->children();
346 for (int ii = 0; ii < children.size(); ++ii)
347 storeObjectIds(children.at(ii));
348}
349
350void QQmlEngineDebugServiceImpl::buildObjectList(QDataStream &message,
351 QQmlContext *ctxt,
352 const QList<QPointer<QObject> > &instances)
353{
354 if (!ctxt->isValid())
355 return;
356
358
359 QString ctxtName = ctxt->objectName();
360 int ctxtId = QQmlDebugService::idForObject(ctxt);
361 if (ctxt->contextObject())
362 storeObjectIds(ctxt->contextObject());
363
364 message << ctxtName << ctxtId;
365
366 int count = 0;
367
368 QQmlRefPointer<QQmlContextData> child = p->childContexts();
369 while (child) {
370 ++count;
371 child = child->nextChild();
372 }
373
374 message << count;
375
376 child = p->childContexts();
377 while (child) {
378 buildObjectList(message, child->asQQmlContext(), instances);
379 child = child->nextChild();
380 }
381
382 count = 0;
383 for (int ii = 0; ii < instances.size(); ++ii) {
384 QQmlData *data = QQmlData::get(instances.at(ii));
385 if (data->context == p.data())
386 count ++;
387 }
388 message << count;
389
390 for (int ii = 0; ii < instances.size(); ++ii) {
391 QQmlData *data = QQmlData::get(instances.at(ii));
392 if (data->context == p.data())
393 message << objectData(instances.at(ii));
394 }
395}
396
397void QQmlEngineDebugServiceImpl::buildStatesList(bool cleanList,
398 const QList<QPointer<QObject> > &instances)
399{
400 if (auto delegate = statesDelegate())
401 delegate->buildStatesList(cleanList, instances);
402}
403
405QQmlEngineDebugServiceImpl::objectData(QObject *object)
406{
407 QQmlData *ddata = QQmlData::get(object);
409 if (ddata && ddata->outerContext) {
410 rv.url = ddata->outerContext->url();
411 rv.lineNumber = ddata->lineNumber;
412 rv.columnNumber = ddata->columnNumber;
413 } else {
414 rv.lineNumber = -1;
415 rv.columnNumber = -1;
416 }
417
418 QQmlContext *context = qmlContext(object);
419 if (context && context->isValid())
421
422 rv.objectName = object->objectName();
427 return rv;
428}
429
431{
433}
434
438QList<QObject*> QQmlEngineDebugServiceImpl::objectForLocationInfo(const QString &filename,
439 int lineNumber, int columnNumber)
440{
441 QList<QObject *> objects;
442 const QHash<int, QObject *> &hash = objectsForIds();
443 for (QHash<int, QObject *>::ConstIterator i = hash.constBegin(); i != hash.constEnd(); ++i) {
444 QQmlData *ddata = QQmlData::get(i.value());
445 if (ddata && ddata->outerContext && ddata->outerContext->isValid()) {
446 if (QFileInfo(ddata->outerContext->urlString()).fileName() == filename &&
447 ddata->lineNumber == lineNumber &&
448 ddata->columnNumber >= columnNumber) {
449 objects << i.value();
450 }
451 }
452 }
453 return objects;
454}
455
456void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message)
457{
459
462 ds >> type >> queryId;
463
465
466 if (type == "LIST_ENGINES") {
467 rs << QByteArray("LIST_ENGINES_R");
468 rs << queryId << int(m_engines.size());
469
470 for (int ii = 0; ii < m_engines.size(); ++ii) {
471 QJSEngine *engine = m_engines.at(ii);
472
473 QString engineName = engine->objectName();
475
476 rs << engineName << engineId;
477 }
478
479 } else if (type == "LIST_OBJECTS") {
480 qint32 engineId = -1;
481 ds >> engineId;
482
484 qobject_cast<QQmlEngine *>(QQmlDebugService::objectForId(engineId));
485
486 rs << QByteArray("LIST_OBJECTS_R") << queryId;
487
488 if (engine) {
489 QQmlContext *rootContext = engine->rootContext();
490 QQmlContextPrivate *ctxtPriv = QQmlContextPrivate::get(rootContext);
491 ctxtPriv->cleanInstances(); // Clean deleted objects
492 const QList<QPointer<QObject>> instances = ctxtPriv->instances();
493 buildObjectList(rs, rootContext, instances);
494 buildStatesList(true, instances);
495 }
496
497 } else if (type == "FETCH_OBJECT") {
498 qint32 objectId;
499 bool recurse;
500 bool dumpProperties = true;
501
502 ds >> objectId >> recurse >> dumpProperties;
503
504 QObject *object = QQmlDebugService::objectForId(objectId);
505
506 rs << QByteArray("FETCH_OBJECT_R") << queryId;
507
508 if (object) {
509 if (recurse)
510 prepareDeferredObjects(object);
511 buildObjectDump(rs, object, recurse, dumpProperties);
512 }
513
514 } else if (type == "FETCH_OBJECTS_FOR_LOCATION") {
516 qint32 lineNumber;
517 qint32 columnNumber;
518 bool recurse;
519 bool dumpProperties = true;
520
521 ds >> file >> lineNumber >> columnNumber >> recurse >> dumpProperties;
522
523 const QList<QObject*> objects = objectForLocationInfo(file, lineNumber, columnNumber);
524
525 rs << QByteArray("FETCH_OBJECTS_FOR_LOCATION_R") << queryId
526 << int(objects.size());
527
528 for (QObject *object : objects) {
529 if (recurse)
530 prepareDeferredObjects(object);
531 buildObjectDump(rs, object, recurse, dumpProperties);
532 }
533
534 } else if (type == "WATCH_OBJECT") {
535 qint32 objectId;
536
537 ds >> objectId;
538 bool ok = m_watch->addWatch(queryId, objectId);
539
540 rs << QByteArray("WATCH_OBJECT_R") << queryId << ok;
541
542 } else if (type == "WATCH_PROPERTY") {
543 qint32 objectId;
545
546 ds >> objectId >> property;
547 bool ok = m_watch->addWatch(queryId, objectId, property);
548
549 rs << QByteArray("WATCH_PROPERTY_R") << queryId << ok;
550
551 } else if (type == "WATCH_EXPR_OBJECT") {
552 qint32 debugId;
553 QString expr;
554
555 ds >> debugId >> expr;
556 bool ok = m_watch->addWatch(queryId, debugId, expr);
557
558 rs << QByteArray("WATCH_EXPR_OBJECT_R") << queryId << ok;
559
560 } else if (type == "NO_WATCH") {
561 bool ok = m_watch->removeWatch(queryId);
562
563 rs << QByteArray("NO_WATCH_R") << queryId << ok;
564
565 } else if (type == "EVAL_EXPRESSION") {
566 qint32 objectId;
567 QString expr;
568
569 ds >> objectId >> expr;
570 qint32 engineId = -1;
571 if (!ds.atEnd())
572 ds >> engineId;
573
574 QObject *object = QQmlDebugService::objectForId(objectId);
575 QQmlContext *context = qmlContext(object);
576 if (!context || !context->isValid()) {
577 QQmlEngine *engine = qobject_cast<QQmlEngine *>(
579 if (engine && m_engines.contains(engine))
580 context = engine->rootContext();
581 }
583 if (context && context->isValid()) {
584 QQmlExpression exprObj(context, object, expr);
585 bool undefined = false;
586 QVariant value = exprObj.evaluate(&undefined);
587 if (undefined)
588 result = QString(QStringLiteral("<undefined>"));
589 else
590 result = valueContents(value);
591 } else {
592 result = QString(QStringLiteral("<unknown context>"));
593 }
594
595 rs << QByteArray("EVAL_EXPRESSION_R") << queryId << result;
596
597 } else if (type == "SET_BINDING") {
598 qint32 objectId;
599 QString propertyName;
600 QVariant expr;
601 bool isLiteralValue;
602 QString filename;
603 qint32 line;
604 ds >> objectId >> propertyName >> expr >> isLiteralValue >>
605 filename >> line;
606 bool ok = setBinding(objectId, propertyName, expr, isLiteralValue,
607 filename, line);
608
609 rs << QByteArray("SET_BINDING_R") << queryId << ok;
610
611 } else if (type == "RESET_BINDING") {
612 qint32 objectId;
613 QString propertyName;
614 ds >> objectId >> propertyName;
615 bool ok = resetBinding(objectId, propertyName);
616
617 rs << QByteArray("RESET_BINDING_R") << queryId << ok;
618
619 } else if (type == "SET_METHOD_BODY") {
620 qint32 objectId;
622 QString methodBody;
623 ds >> objectId >> methodName >> methodBody;
624 bool ok = setMethodBody(objectId, methodName, methodBody);
625
626 rs << QByteArray("SET_METHOD_BODY_R") << queryId << ok;
627
628 }
629 emit messageToClient(name(), rs.data());
630}
631
632bool QQmlEngineDebugServiceImpl::setBinding(int objectId,
633 const QString &propertyName,
634 const QVariant &expression,
635 bool isLiteralValue,
636 QString filename,
637 int line,
638 int column)
639{
640 bool ok = true;
641 QObject *object = objectForId(objectId);
642 QQmlContext *context = qmlContext(object);
643
644 if (object && context && context->isValid()) {
645 QQmlProperty property(object, propertyName, context);
646 if (property.isValid()) {
647
648 bool inBaseState = true;
649 if (auto delegate = statesDelegate()) {
650 delegate->updateBinding(context, property, expression, isLiteralValue,
651 filename, line, column, &inBaseState);
652 }
653
654 if (inBaseState) {
655 if (isLiteralValue) {
656 property.write(expression);
657 } else if (hasValidSignal(object, propertyName)) {
659 QQmlContextData::get(context), object, expression.toString(),
660 filename, line, column);
662 } else if (property.isProperty()) {
663 QQmlBinding *binding = QQmlBinding::create(&QQmlPropertyPrivate::get(property)->core, expression.toString(), object, QQmlContextData::get(context), filename, line);
664 binding->setTarget(property);
666 binding->update();
667 } else {
668 ok = false;
669 qWarning() << "QQmlEngineDebugService::setBinding: unable to set property" << propertyName << "on object" << object;
670 }
671 }
672
673 } else {
674 // not a valid property
675 if (auto delegate = statesDelegate())
676 ok = delegate->setBindingForInvalidProperty(object, propertyName, expression, isLiteralValue);
677 if (!ok)
678 qWarning() << "QQmlEngineDebugService::setBinding: unable to set property" << propertyName << "on object" << object;
679 }
680 }
681 return ok;
682}
683
684bool QQmlEngineDebugServiceImpl::resetBinding(int objectId, const QString &propertyName)
685{
686 QObject *object = objectForId(objectId);
687 QQmlContext *context = qmlContext(object);
688
689 if (object && context && context->isValid()) {
690 QStringView parentPropertyRef(propertyName);
691 const int idx = parentPropertyRef.indexOf(QLatin1Char('.'));
692 if (idx != -1)
693 parentPropertyRef = parentPropertyRef.left(idx);
694
695 const QByteArray parentProperty = parentPropertyRef.toLatin1();
696 if (object->property(parentProperty).isValid()) {
697 QQmlProperty property(object, propertyName);
699 if (property.isResettable()) {
700 // Note: this will reset the property in any case, without regard to states
701 // Right now almost no QQuickItem has reset methods for its properties (with the
702 // notable exception of QQuickAnchors), so this is not a big issue
703 // later on, setBinding does take states into account
704 property.reset();
705 } else {
706 // overwrite with default value
707 QQmlType objType = QQmlMetaType::qmlType(object->metaObject());
708 if (objType.isValid()) {
709 if (QObject *emptyObject = objType.create()) {
710 if (emptyObject->property(parentProperty).isValid()) {
711 QVariant defaultValue = QQmlProperty(emptyObject, propertyName).read();
712 if (defaultValue.isValid()) {
713 setBinding(objectId, propertyName, defaultValue, true);
714 }
715 }
716 delete emptyObject;
717 }
718 }
719 }
720 return true;
721 }
722
723 if (hasValidSignal(object, propertyName)) {
724 QQmlProperty property(object, propertyName, context);
726 return true;
727 }
728
729 if (auto delegate = statesDelegate()) {
730 delegate->resetBindingForInvalidProperty(object, propertyName);
731 return true;
732 }
733
734 return false;
735 }
736 // object or context null.
737 return false;
738}
739
740bool QQmlEngineDebugServiceImpl::setMethodBody(int objectId, const QString &method, const QString &body)
741{
742 QObject *object = objectForId(objectId);
743 QQmlContext *context = qmlContext(object);
744 if (!object || !context || !context->isValid())
745 return false;
747
748 QQmlPropertyData dummy;
749 const QQmlPropertyData *prop = QQmlPropertyCache::property(object, method, contextData, &dummy);
750
751 if (!prop || !prop->isVMEFunction())
752 return false;
753
754 QMetaMethod metaMethod = object->metaObject()->method(prop->coreIndex());
755 QList<QByteArray> paramNames = metaMethod.parameterNames();
756
757 QString paramStr;
758 for (int ii = 0; ii < paramNames.size(); ++ii) {
759 if (ii != 0) paramStr.append(QLatin1Char(','));
760 paramStr.append(QString::fromUtf8(paramNames.at(ii)));
761 }
762
763 const QString jsfunction = QLatin1String("(function ") + method + QLatin1Char('(') + paramStr +
764 QLatin1String(") {") + body + QLatin1String("\n})");
765
766 QQmlVMEMetaObject *vmeMetaObject = QQmlVMEMetaObject::get(object);
767 Q_ASSERT(vmeMetaObject); // the fact we found the property above should guarentee this
768
769 QV4::ExecutionEngine *v4 = qmlEngine(object)->handle();
770 QV4::Scope scope(v4);
771
772 int lineNumber = 0;
773 QV4::ScopedFunctionObject oldMethod(scope, vmeMetaObject->vmeMethod(prop->coreIndex()));
774 if (oldMethod && oldMethod->d()->function)
775 lineNumber = oldMethod->d()->function->compiledFunction->location.line();
776
777 QV4::ScopedValue v(scope, QQmlJavaScriptExpression::evalFunction(contextData, object, jsfunction, contextData->urlString(), lineNumber));
778 vmeMetaObject->setVmeMethod(prop->coreIndex(), v);
779 return true;
780}
781
782void QQmlEngineDebugServiceImpl::propertyChanged(
783 qint32 id, qint32 objectId, const QMetaProperty &property, const QVariant &value)
784{
786 rs << QByteArray("UPDATE_WATCH") << id << objectId << QByteArray(property.name()) << valueContents(value);
787 emit messageToClient(name(), rs.data());
788}
789
791{
793 Q_ASSERT(!m_engines.contains(engine));
794
795 m_engines.append(engine);
796 emit attachedToEngine(engine);
797}
798
800{
802 Q_ASSERT(m_engines.contains(engine));
803
804 m_engines.removeAll(engine);
805 emit detachedFromEngine(engine);
806}
807
809{
811 if (!m_engines.contains(engine))
812 return;
813
815 qint32 objectId = QQmlDebugService::idForObject(object);
816 qint32 parentId = QQmlDebugService::idForObject(object->parent());
817
819
820 //unique queryId -1
821 rs << QByteArray("OBJECT_CREATED") << qint32(-1) << engineId << objectId << parentId;
822 emit messageToClient(name(), rs.data());
823}
824
826
827#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
Definition qchar.h:48
QChar toLower() const noexcept
Returns the lowercase equivalent if the character is uppercase or titlecase; otherwise returns the ch...
Definition qchar.h:448
constexpr bool isUpper() const noexcept
Returns true if the character is an uppercase letter, for example category() is Letter_Uppercase.
Definition qchar.h:475
QChar toUpper() const noexcept
Returns the uppercase equivalent if the character is lowercase or titlecase; otherwise returns the ch...
Definition qchar.h:449
constexpr bool isLetter() const noexcept
Returns true if the character is a letter (Letter_* categories); otherwise returns false.
Definition qchar.h:470
\inmodule QtCore\reentrant
Definition qdatastream.h:30
\inmodule QtCore \reentrant
Definition qfileinfo.h:22
QString fileName() const
Returns the name of the file, excluding the path.
\inmodule QtCore
Definition qhash.h:1135
\inmodule QtCore
Definition qhash.h:818
\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:292
The QJSValue class acts as a container for Qt/JavaScript data types.
Definition qjsvalue.h:31
qsizetype size() const noexcept
Definition qlist.h:386
QList< T > toList() const noexcept
Definition qlist.h:716
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
qsizetype removeAll(const AT &t)
Definition qlist.h:575
void append(parameter_type t)
Definition qlist.h:441
const_iterator cend() const
Definition qmap.h:604
const_iterator cbegin() const
Definition qmap.h:600
\inmodule QtCore
Definition qmetaobject.h:18
int methodIndex() const
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
QByteArray name() 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:320
constexpr TypeFlags flags() const
Definition qmetatype.h:2628
int id(int=0) const
Definition qmetatype.h:454
@ PointerToQObject
Definition qmetatype.h:385
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:775
\inmodule QtCore
Definition qobject.h:90
const QObjectList & children() const
Returns a list of child objects.
Definition qobject.h:171
QString objectName
the name of this object
Definition qobject.h:94
const QByteArray & data() const
Returns a reference to the raw packet data.
Definition qpacket.cpp:77
\inmodule QtCore
Definition qpointer.h:18
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.
QString findObjectId(const QObject *obj) const
static QQmlRefPointer< QQmlContextData > get(QQmlContext *context)
bool isValid() const
QString urlString() const
static QQmlContextPrivate * get(QQmlContext *context)
QList< QPointer< QObject > > instances() const
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.
QQmlBoundSignal * signalHandlers
Definition qqmldata_p.h:153
static QQmlData * get(QObjectPrivate *priv, bool create)
Definition qqmldata_p.h:199
quint16 lineNumber
Definition qqmldata_p.h:168
quint16 columnNumber
Definition qqmldata_p.h:169
QQmlContextData * outerContext
Definition qqmldata_p.h:149
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.
QObject * create() const
Definition qqmltype.cpp:462
bool isValid() const
Definition qqmltype_p.h:58
QV4::ReturnedValue vmeMethod(int index) const
static QQmlVMEMetaObject * get(QObject *o)
void setVmeMethod(int index, const QV4::Value &function)
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:76
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
QByteArray toLatin1() const &
Definition qstring.h:559
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition qstring.cpp:5299
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5857
QString mid(qsizetype position, qsizetype n=-1) const
Returns a string that contains n characters of this string, starting at the specified position index.
Definition qstring.cpp:5204
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
Definition qstring.h:1079
QString & append(QChar c)
Definition qstring.cpp:3227
\inmodule QtCore
Definition qvariant.h:64
T value() const &
Definition qvariant.h:511
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:707
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)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qWarning
Definition qlogging.h:162
#define Q_RETURN_ARG(Type, data)
Definition qobjectdefs.h:63
GLsizei const GLfloat * v
[13]
GLuint * queryId
GLuint GLuint end
GLenum GLenum GLsizei count
GLuint object
[3]
GLenum type
GLuint GLsizei const GLchar * message
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint name
GLenum GLenum GLsizei void GLsizei void * column
GLhandleARB obj
[2]
GLenum GLsizei len
GLuint64EXT * result
[6]
GLdouble s
[6]
Definition qopenglext.h:235
GLfloat GLfloat p
[1]
void qmlExecuteDeferred(QObject *object)
Definition qqml.cpp:48
QQmlEngine * qmlEngine(const QObject *obj)
Definition qqml.cpp:76
QQmlContext * qmlContext(const QObject *obj)
Definition qqml.cpp:71
static bool isSaveable(const QVariant &value)
static bool hasValidSignal(QObject *object, const QString &propertyName)
static bool isSignalPropertyName(const QString &signalName)
QDataStream & operator>>(QDataStream &ds, QQmlEngineDebugServiceImpl::QQmlObjectData &data)
QDataStream & operator<<(QDataStream &ds, const QQmlEngineDebugServiceImpl::QQmlObjectData &data)
#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:44
long long qint64
Definition qtypes.h:55
static QVariant toVariant(const QV4::Value &value, QMetaType typeHint, bool createJSValueForObjectsAndSymbols, 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:17
bool contains(const AT &t) const noexcept
Definition qlist.h:44
static Q_CORE_EXPORT QMetaMethod signal(const QMetaObject *m, int signal_index)
\inmodule QtCore
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent