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
4#include "qqmlwatcher.h"
5
6#include "qqmlexpression.h"
7#include "qqmlcontext.h"
8#include "qqml.h"
9
10#include <private/qqmldebugservice_p.h>
11#include <private/qqmlproperty_p.h>
12#include <private/qqmlvaluetype_p.h>
13
14#include <QtCore/qmetaobject.h>
15#include <QtCore/qdebug.h>
16
17QT_BEGIN_NAMESPACE
18
19
20class QQmlWatchProxy : public QObject
21{
22 Q_OBJECT
23public:
24 QQmlWatchProxy(int id,
25 QObject *object,
26 int debugId,
27 const QMetaProperty &prop,
28 QQmlWatcher *parent = nullptr);
29
30 QQmlWatchProxy(int id,
31 QQmlExpression *exp,
32 int debugId,
33 QQmlWatcher *parent = nullptr);
34
35public slots:
36 void notifyValueChanged(); // Needs to be a slot because of QQmlPropertyPrivate::connect()
37
38private:
39 friend class QQmlWatcher;
40 int m_id;
41 QQmlWatcher *m_watch;
42 QObject *m_object;
43 int m_debugId;
44 QMetaProperty m_property;
45
46 QQmlExpression *m_expr;
47};
48
49QQmlWatchProxy::QQmlWatchProxy(int id, QQmlExpression *exp, int debugId, QQmlWatcher *parent)
50 : QObject(parent),
51 m_id(id),
52 m_watch(parent),
53 m_object(nullptr),
54 m_debugId(debugId),
55 m_expr(exp)
56{
57 QObject::connect(sender: m_expr, signal: &QQmlExpression::valueChanged,
58 context: this, slot: &QQmlWatchProxy::notifyValueChanged);
59}
60
61QQmlWatchProxy::QQmlWatchProxy(int id, QObject *object, int debugId, const QMetaProperty &prop,
62 QQmlWatcher *parent)
63 : QObject(parent),
64 m_id(id),
65 m_watch(parent),
66 m_object(object),
67 m_debugId(debugId),
68 m_property(prop),
69 m_expr(nullptr)
70{
71 static int refreshIdx = -1;
72 if(refreshIdx == -1)
73 refreshIdx = QQmlWatchProxy::staticMetaObject.indexOfMethod(method: "notifyValueChanged()");
74
75 if (prop.hasNotifySignal())
76 QQmlPropertyPrivate::connect(sender: m_object, signal_index: prop.notifySignalIndex(), receiver: this, method_index: refreshIdx);
77}
78
79void QQmlWatchProxy::notifyValueChanged()
80{
81 QVariant v;
82 if (m_expr)
83 v = m_expr->evaluate();
84 else
85 v = m_property.read(obj: m_object);
86 emit m_watch->propertyChanged(id: m_id, objectId: m_debugId, property: m_property, value: v);
87}
88
89
90QQmlWatcher::QQmlWatcher(QObject *parent)
91 : QObject(parent)
92{
93}
94
95bool QQmlWatcher::addWatch(int id, quint32 debugId)
96{
97 QObject *object = QQmlDebugService::objectForId(id: debugId);
98 if (object) {
99 int propCount = object->metaObject()->propertyCount();
100 for (int ii=0; ii<propCount; ii++)
101 addPropertyWatch(id, object, objectId: debugId, property: object->metaObject()->property(index: ii));
102 return true;
103 }
104 return false;
105}
106
107bool QQmlWatcher::addWatch(int id, quint32 debugId, const QByteArray &property)
108{
109 QObject *object = QQmlDebugService::objectForId(id: debugId);
110 if (object) {
111 int index = object->metaObject()->indexOfProperty(name: property.constData());
112 if (index >= 0) {
113 addPropertyWatch(id, object, objectId: debugId, property: object->metaObject()->property(index));
114 return true;
115 }
116 }
117 return false;
118}
119
120bool QQmlWatcher::addWatch(int id, quint32 objectId, const QString &expr)
121{
122 QObject *object = QQmlDebugService::objectForId(id: objectId);
123 QQmlContext *context = qmlContext(object);
124 if (context) {
125 QQmlExpression *exprObj = new QQmlExpression(context, object, expr);
126 exprObj->setNotifyOnValueChanged(true);
127 QQmlWatchProxy *proxy = new QQmlWatchProxy(id, exprObj, objectId, this);
128 exprObj->setParent(proxy);
129 m_proxies[id].append(t: proxy);
130 proxy->notifyValueChanged();
131 return true;
132 }
133 return false;
134}
135
136bool QQmlWatcher::removeWatch(int id)
137{
138 if (!m_proxies.contains(key: id))
139 return false;
140
141 QList<QPointer<QQmlWatchProxy> > proxies = m_proxies.take(key: id);
142 qDeleteAll(c: proxies);
143 return true;
144}
145
146void QQmlWatcher::addPropertyWatch(int id, QObject *object, quint32 debugId, const QMetaProperty &property)
147{
148 QQmlWatchProxy *proxy = new QQmlWatchProxy(id, object, debugId, property, this);
149 m_proxies[id].append(t: proxy);
150
151 proxy->notifyValueChanged();
152}
153
154QT_END_NAMESPACE
155
156#include <qqmlwatcher.moc>
157
158#include "moc_qqmlwatcher.cpp"
159

source code of qtdeclarative/src/plugins/qmltooling/qmldbg_debugger/qqmlwatcher.cpp