summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/declarative/debugger/debugger.pri18
-rw-r--r--src/declarative/debugger/qmldebug.cpp603
-rw-r--r--src/declarative/debugger/qmldebug.h237
-rw-r--r--src/declarative/debugger/qmldebugclient.cpp14
-rw-r--r--src/declarative/debugger/qmldebugclient.h3
-rw-r--r--src/declarative/debugger/qmldebugger.cpp359
-rw-r--r--src/declarative/debugger/qmldebugger.h103
-rw-r--r--src/declarative/debugger/qmldebugserver.cpp81
-rw-r--r--src/declarative/debugger/qmldebugserver.h4
-rw-r--r--src/declarative/debugger/qmlobjecttree.cpp78
-rw-r--r--src/declarative/debugger/qmlpropertyview.cpp228
-rw-r--r--src/declarative/debugger/qmlpropertyview_p.h89
-rw-r--r--src/declarative/debugger/qmlwatches.cpp308
-rw-r--r--src/declarative/debugger/qmlwatches_p.h111
-rw-r--r--src/declarative/qml/qml.pri2
-rw-r--r--src/declarative/qml/qmlcomponent.cpp7
-rw-r--r--src/declarative/qml/qmlcontext.cpp33
-rw-r--r--src/declarative/qml/qmlcontext.h5
-rw-r--r--src/declarative/qml/qmlcontext_p.h4
-rw-r--r--src/declarative/qml/qmlengine.cpp20
-rw-r--r--src/declarative/qml/qmlengine_p.h1
-rw-r--r--src/declarative/qml/qmlenginedebug.cpp268
-rw-r--r--src/declarative/qml/qmlenginedebug_p.h (renamed from src/declarative/debugger/qmlobjecttree_p.h)69
-rw-r--r--src/declarative/qml/qmlvme.cpp2
-rw-r--r--src/declarative/util/qfxview.cpp10
-rw-r--r--tools/qmldebugger/engine.cpp172
-rw-r--r--tools/qmldebugger/engine.h52
-rw-r--r--tools/qmldebugger/main.cpp4
-rw-r--r--tools/qmldebugger/qmldebugger.pro4
29 files changed, 1547 insertions, 1342 deletions
diff --git a/src/declarative/debugger/debugger.pri b/src/declarative/debugger/debugger.pri
index aa36675..33076ea 100644
--- a/src/declarative/debugger/debugger.pri
+++ b/src/declarative/debugger/debugger.pri
@@ -1,17 +1,11 @@
-SOURCES += debugger/qmldebugger.cpp \
- debugger/qmldebuggerstatus.cpp \
- debugger/qmlpropertyview.cpp \
- debugger/qmlwatches.cpp \
- debugger/qmlobjecttree.cpp \
+SOURCES += debugger/qmldebuggerstatus.cpp \
debugger/qpacketprotocol.cpp \
debugger/qmldebugserver.cpp \
- debugger/qmldebugclient.cpp
+ debugger/qmldebugclient.cpp \
+ debugger/qmldebug.cpp
-HEADERS += debugger/qmldebugger.h \
- debugger/qmldebuggerstatus.h \
- debugger/qmlpropertyview_p.h \
- debugger/qmlwatches_p.h \
- debugger/qmlobjecttree_p.h \
+HEADERS += debugger/qmldebuggerstatus.h \
debugger/qpacketprotocol.h \
debugger/qmldebugserver.h \
- debugger/qmldebugclient.h
+ debugger/qmldebugclient.h \
+ debugger/qmldebug.h
diff --git a/src/declarative/debugger/qmldebug.cpp b/src/declarative/debugger/qmldebug.cpp
new file mode 100644
index 0000000..1808bba
--- /dev/null
+++ b/src/declarative/debugger/qmldebug.cpp
@@ -0,0 +1,603 @@
+#include "qmldebug.h"
+#include "qmldebugclient.h"
+#include <private/qobject_p.h>
+#include <private/qmlenginedebug_p.h>
+
+class QmlEngineDebugClient : public QmlDebugClientPlugin
+{
+public:
+ QmlEngineDebugClient(QmlDebugClient *client, QmlEngineDebugPrivate *p);
+
+protected:
+ virtual void messageReceived(const QByteArray &);
+
+private:
+ QmlEngineDebugPrivate *priv;
+};
+
+class QmlEngineDebugPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlEngineDebug)
+public:
+ QmlEngineDebugPrivate(QmlDebugClient *);
+
+ void message(const QByteArray &);
+
+ QmlEngineDebugClient client;
+ int nextId;
+ int getId();
+
+ void decode(QDataStream &, QmlDebugContextReference &);
+ void decode(QDataStream &, QmlDebugObjectReference &, bool simple);
+ static void remove(QmlEngineDebug *, QmlDebugEnginesQuery *);
+ static void remove(QmlEngineDebug *, QmlDebugRootContextQuery *);
+ static void remove(QmlEngineDebug *, QmlDebugObjectQuery *);
+
+ QHash<int, QmlDebugEnginesQuery *> enginesQuery;
+ QHash<int, QmlDebugRootContextQuery *> rootContextQuery;
+ QHash<int, QmlDebugObjectQuery *> objectQuery;
+};
+
+QmlEngineDebugClient::QmlEngineDebugClient(QmlDebugClient *client,
+ QmlEngineDebugPrivate *p)
+: QmlDebugClientPlugin(QLatin1String("QmlEngine"), client), priv(p)
+{
+ setEnabled(true);
+}
+
+void QmlEngineDebugClient::messageReceived(const QByteArray &data)
+{
+ priv->message(data);
+}
+
+QmlEngineDebugPrivate::QmlEngineDebugPrivate(QmlDebugClient *c)
+: client(c, this), nextId(0)
+{
+}
+
+int QmlEngineDebugPrivate::getId()
+{
+ return nextId++;
+}
+
+void QmlEngineDebugPrivate::remove(QmlEngineDebug *c, QmlDebugEnginesQuery *q)
+{
+ QmlEngineDebugPrivate *p = (QmlEngineDebugPrivate *)QObjectPrivate::get(c);
+ p->enginesQuery.remove(q->m_queryId);
+}
+
+void QmlEngineDebugPrivate::remove(QmlEngineDebug *c,
+ QmlDebugRootContextQuery *q)
+{
+ QmlEngineDebugPrivate *p = (QmlEngineDebugPrivate *)QObjectPrivate::get(c);
+ p->rootContextQuery.remove(q->m_queryId);
+}
+
+void QmlEngineDebugPrivate::remove(QmlEngineDebug *c, QmlDebugObjectQuery *q)
+{
+ QmlEngineDebugPrivate *p = (QmlEngineDebugPrivate *)QObjectPrivate::get(c);
+ p->objectQuery.remove(q->m_queryId);
+}
+
+Q_DECLARE_METATYPE(QmlDebugObjectReference);
+void QmlEngineDebugPrivate::decode(QDataStream &ds, QmlDebugObjectReference &o,
+ bool simple)
+{
+ QmlEngineDebugServer::QmlObjectData data;
+ ds >> data;
+ o.m_debugId = data.objectId;
+ o.m_class = data.objectType;
+ o.m_name = data.objectName;
+ o.m_source.m_url = data.url;
+ o.m_source.m_lineNumber = data.lineNumber;
+ o.m_source.m_columnNumber = data.columnNumber;
+
+ if (simple)
+ return;
+
+ int propCount;
+ ds >> propCount;
+
+ for (int ii = 0; ii < propCount; ++ii) {
+ QmlEngineDebugServer::QmlObjectProperty data;
+ ds >> data;
+ QmlDebugPropertyReference prop;
+ prop.m_name = data.name;
+ if (data.type == QmlEngineDebugServer::QmlObjectProperty::Basic)
+ prop.m_value = data.value;
+ else if (data.type == QmlEngineDebugServer::QmlObjectProperty::Object) {
+ QmlDebugObjectReference obj;
+ obj.m_debugId = prop.m_value.toInt();
+ prop.m_value = qVariantFromValue(obj);
+ }
+
+ o.m_properties << prop;
+ }
+
+ int childCount;
+ bool recur;
+ ds >> childCount >> recur;
+
+ for (int ii = 0; ii < childCount; ++ii) {
+ o.m_children.append(QmlDebugObjectReference());
+ decode(ds, o.m_children.last(), !recur);
+ }
+}
+
+void QmlEngineDebugPrivate::decode(QDataStream &ds, QmlDebugContextReference &c)
+{
+ ds >> c.m_name >> c.m_debugId;
+
+ int contextCount;
+ ds >> contextCount;
+
+ for (int ii = 0; ii < contextCount; ++ii) {
+ c.m_contexts.append(QmlDebugContextReference());
+ decode(ds, c.m_contexts.last());
+ }
+
+ int objectCount;
+ ds >> objectCount;
+
+ for (int ii = 0; ii < objectCount; ++ii) {
+ QmlDebugObjectReference obj;
+ decode(ds, obj, true);
+
+ c.m_objects << obj;
+ }
+}
+
+void QmlEngineDebugPrivate::message(const QByteArray &data)
+{
+ QDataStream ds(data);
+
+ QByteArray type;
+ ds >> type;
+
+ if (type == "LIST_ENGINES_R") {
+ int queryId;
+ ds >> queryId;
+
+ QmlDebugEnginesQuery *query = enginesQuery.value(queryId);
+ if (!query)
+ return;
+ enginesQuery.remove(queryId);
+
+ int count;
+ ds >> count;
+
+ for (int ii = 0; ii < count; ++ii) {
+ QmlDebugEngineReference ref;
+ ds >> ref.m_name;
+ ds >> ref.m_debugId;
+ query->m_engines << ref;
+ }
+
+ query->m_client = 0;
+ query->setState(QmlDebugQuery::Completed);
+ } else if (type == "LIST_OBJECTS_R") {
+ int queryId;
+ ds >> queryId;
+
+ QmlDebugRootContextQuery *query = rootContextQuery.value(queryId);
+ if (!query)
+ return;
+ rootContextQuery.remove(queryId);
+
+ if (!ds.atEnd())
+ decode(ds, query->m_context);
+
+ query->m_client = 0;
+ query->setState(QmlDebugQuery::Completed);
+ } else if (type == "FETCH_OBJECT_R") {
+ int queryId;
+ ds >> queryId;
+
+ QmlDebugObjectQuery *query = objectQuery.value(queryId);
+ if (!query)
+ return;
+ objectQuery.remove(queryId);
+
+ if (!ds.atEnd())
+ decode(ds, query->m_object, false);
+
+ query->m_client = 0;
+ query->setState(QmlDebugQuery::Completed);
+ }
+}
+
+QmlEngineDebug::QmlEngineDebug(QmlDebugClient *client, QObject *parent)
+: QObject(*(new QmlEngineDebugPrivate(client)), parent)
+{
+}
+
+QmlDebugWatch *QmlEngineDebug::addWatch(const QmlDebugPropertyReference &, QObject *)
+{
+ qWarning("QmlEngineDebug::addWatch(): Not implemented");
+ return 0;
+}
+
+QmlDebugWatch *QmlEngineDebug::addWatch(const QmlDebugContextReference &, const QString &, QObject *)
+{
+ qWarning("QmlEngineDebug::addWatch(): Not implemented");
+ return 0;
+}
+
+QmlDebugWatch *QmlEngineDebug::addWatch(const QmlDebugObjectReference &, const QString &, QObject *)
+{
+ qWarning("QmlEngineDebug::addWatch(): Not implemented");
+ return 0;
+}
+
+QmlDebugWatch *QmlEngineDebug::addWatch(const QmlDebugObjectReference &, QObject *)
+{
+ qWarning("QmlEngineDebug::addWatch(): Not implemented");
+ return 0;
+}
+
+QmlDebugWatch *QmlEngineDebug::addWatch(const QmlDebugFileReference &, QObject *)
+{
+ qWarning("QmlEngineDebug::addWatch(): Not implemented");
+ return 0;
+}
+
+QmlDebugEnginesQuery *QmlEngineDebug::queryAvailableEngines(QObject *parent)
+{
+ Q_D(QmlEngineDebug);
+
+ QmlDebugEnginesQuery *query = new QmlDebugEnginesQuery(parent);
+ if (d->client.isConnected()) {
+ query->m_client = this;
+ int queryId = d->getId();
+ query->m_queryId = queryId;
+ d->enginesQuery.insert(queryId, query);
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("LIST_ENGINES") << queryId;
+ d->client.sendMessage(message);
+ } else {
+ query->m_state = QmlDebugQuery::Error;
+ }
+
+ return query;
+}
+
+QmlDebugRootContextQuery *QmlEngineDebug::queryRootContexts(const QmlDebugEngineReference &engine, QObject *parent)
+{
+ Q_D(QmlEngineDebug);
+
+ QmlDebugRootContextQuery *query = new QmlDebugRootContextQuery(parent);
+ if (d->client.isConnected() && engine.debugId() != -1) {
+ query->m_client = this;
+ int queryId = d->getId();
+ query->m_queryId = queryId;
+ d->rootContextQuery.insert(queryId, query);
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("LIST_OBJECTS") << queryId << engine.debugId();
+ d->client.sendMessage(message);
+ } else {
+ query->m_state = QmlDebugQuery::Error;
+ }
+
+ return query;
+}
+
+QmlDebugObjectQuery *QmlEngineDebug::queryObject(const QmlDebugObjectReference &object, QObject *parent)
+{
+ Q_D(QmlEngineDebug);
+
+ QmlDebugObjectQuery *query = new QmlDebugObjectQuery(parent);
+ if (d->client.isConnected() && object.debugId() != -1) {
+ query->m_client = this;
+ int queryId = d->getId();
+ query->m_queryId = queryId;
+ d->objectQuery.insert(queryId, query);
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("FETCH_OBJECT") << queryId << object.debugId()
+ << false;
+ d->client.sendMessage(message);
+ } else {
+ query->m_state = QmlDebugQuery::Error;
+ }
+
+ return query;
+}
+
+QmlDebugObjectQuery *QmlEngineDebug::queryObjectRecursive(const QmlDebugObjectReference &object, QObject *parent)
+{
+ Q_D(QmlEngineDebug);
+
+ QmlDebugObjectQuery *query = new QmlDebugObjectQuery(parent);
+ if (d->client.isConnected() && object.debugId() != -1) {
+ query->m_client = this;
+ int queryId = d->getId();
+ query->m_queryId = queryId;
+ d->objectQuery.insert(queryId, query);
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("FETCH_OBJECT") << queryId << object.debugId()
+ << true;
+ d->client.sendMessage(message);
+ } else {
+ query->m_state = QmlDebugQuery::Error;
+ }
+
+ return query;
+}
+
+QmlDebugQuery::QmlDebugQuery(QObject *parent)
+: QObject(parent), m_state(Waiting)
+{
+}
+
+QmlDebugQuery::State QmlDebugQuery::state() const
+{
+ return m_state;
+}
+
+bool QmlDebugQuery::isWaiting() const
+{
+ return m_state == Waiting;
+}
+
+void QmlDebugQuery::setState(State s)
+{
+ if (m_state == s)
+ return;
+ m_state = s;
+ emit stateChanged(m_state);
+}
+
+QmlDebugEnginesQuery::QmlDebugEnginesQuery(QObject *parent)
+: QmlDebugQuery(parent), m_client(0), m_queryId(-1)
+{
+}
+
+QmlDebugEnginesQuery::~QmlDebugEnginesQuery()
+{
+ if (m_client && m_queryId != -1)
+ QmlEngineDebugPrivate::remove(m_client, this);
+}
+
+QList<QmlDebugEngineReference> QmlDebugEnginesQuery::engines() const
+{
+ return m_engines;
+}
+
+QmlDebugRootContextQuery::QmlDebugRootContextQuery(QObject *parent)
+: QmlDebugQuery(parent), m_client(0), m_queryId(-1)
+{
+}
+
+QmlDebugRootContextQuery::~QmlDebugRootContextQuery()
+{
+ if (m_client && m_queryId != -1)
+ QmlEngineDebugPrivate::remove(m_client, this);
+}
+
+QmlDebugContextReference QmlDebugRootContextQuery::rootContext() const
+{
+ return m_context;
+}
+
+QmlDebugObjectQuery::QmlDebugObjectQuery(QObject *parent)
+: QmlDebugQuery(parent), m_client(0), m_queryId(-1)
+{
+}
+
+QmlDebugObjectQuery::~QmlDebugObjectQuery()
+{
+ if (m_client && m_queryId != -1)
+ QmlEngineDebugPrivate::remove(m_client, this);
+}
+
+QmlDebugObjectReference QmlDebugObjectQuery::object() const
+{
+ return m_object;
+}
+
+QmlDebugEngineReference::QmlDebugEngineReference()
+: m_debugId(-1)
+{
+}
+
+QmlDebugEngineReference::QmlDebugEngineReference(int debugId)
+: m_debugId(debugId)
+{
+}
+
+QmlDebugEngineReference::QmlDebugEngineReference(const QmlDebugEngineReference &o)
+: m_debugId(o.m_debugId), m_name(o.m_name)
+{
+}
+
+QmlDebugEngineReference &
+QmlDebugEngineReference::operator=(const QmlDebugEngineReference &o)
+{
+ m_debugId = o.m_debugId; m_name = o.m_name;
+ return *this;
+}
+
+int QmlDebugEngineReference::debugId() const
+{
+ return m_debugId;
+}
+
+QString QmlDebugEngineReference::name() const
+{
+ return m_name;
+}
+
+QmlDebugObjectReference::QmlDebugObjectReference()
+: m_debugId(-1)
+{
+}
+
+QmlDebugObjectReference::QmlDebugObjectReference(int debugId)
+: m_debugId(debugId)
+{
+}
+
+QmlDebugObjectReference::QmlDebugObjectReference(const QmlDebugObjectReference &o)
+: m_debugId(o.m_debugId), m_class(o.m_class), m_name(o.m_name),
+ m_source(o.m_source), m_properties(o.m_properties), m_children(o.m_children)
+{
+}
+
+QmlDebugObjectReference &
+QmlDebugObjectReference::operator=(const QmlDebugObjectReference &o)
+{
+ m_debugId = o.m_debugId; m_class = o.m_class; m_name = o.m_name;
+ m_source = o.m_source; m_properties = o.m_properties;
+ m_children = o.m_children;
+ return *this;
+}
+
+int QmlDebugObjectReference::debugId() const
+{
+ return m_debugId;
+}
+
+QString QmlDebugObjectReference::className() const
+{
+ return m_class;
+}
+
+QString QmlDebugObjectReference::name() const
+{
+ return m_name;
+}
+
+QmlDebugFileReference QmlDebugObjectReference::source() const
+{
+ return m_source;
+}
+
+QList<QmlDebugPropertyReference> QmlDebugObjectReference::properties() const
+{
+ return m_properties;
+}
+
+QList<QmlDebugObjectReference> QmlDebugObjectReference::children() const
+{
+ return m_children;
+}
+
+QmlDebugContextReference::QmlDebugContextReference()
+: m_debugId(-1)
+{
+}
+
+QmlDebugContextReference::QmlDebugContextReference(const QmlDebugContextReference &o)
+: m_debugId(o.m_debugId), m_name(o.m_name), m_objects(o.m_objects), m_contexts(o.m_contexts)
+{
+}
+
+QmlDebugContextReference &QmlDebugContextReference::operator=(const QmlDebugContextReference &o)
+{
+ m_debugId = o.m_debugId; m_name = o.m_name; m_objects = o.m_objects;
+ m_contexts = o.m_contexts;
+ return *this;
+}
+
+int QmlDebugContextReference::debugId() const
+{
+ return m_debugId;
+}
+
+QString QmlDebugContextReference::name() const
+{
+ return m_name;
+}
+
+QList<QmlDebugObjectReference> QmlDebugContextReference::objects() const
+{
+ return m_objects;
+}
+
+QList<QmlDebugContextReference> QmlDebugContextReference::contexts() const
+{
+ return m_contexts;
+}
+
+QmlDebugFileReference::QmlDebugFileReference()
+: m_lineNumber(-1), m_columnNumber(-1)
+{
+}
+
+QmlDebugFileReference::QmlDebugFileReference(const QmlDebugFileReference &o)
+: m_url(o.m_url), m_lineNumber(o.m_lineNumber), m_columnNumber(o.m_columnNumber)
+{
+}
+
+QmlDebugFileReference &QmlDebugFileReference::operator=(const QmlDebugFileReference &o)
+{
+ m_url = o.m_url; m_lineNumber = o.m_lineNumber; m_columnNumber = o.m_columnNumber;
+ return *this;
+}
+
+QUrl QmlDebugFileReference::url() const
+{
+ return m_url;
+}
+
+void QmlDebugFileReference::setUrl(const QUrl &u)
+{
+ m_url = u;
+}
+
+int QmlDebugFileReference::lineNumber() const
+{
+ return m_lineNumber;
+}
+
+void QmlDebugFileReference::setLineNumber(int l)
+{
+ m_lineNumber = l;
+}
+
+int QmlDebugFileReference::columnNumber() const
+{
+ return m_columnNumber;
+}
+
+void QmlDebugFileReference::setColumnNumber(int c)
+{
+ m_columnNumber = c;
+}
+
+QmlDebugPropertyReference::QmlDebugPropertyReference()
+{
+}
+
+QmlDebugPropertyReference::QmlDebugPropertyReference(const QmlDebugPropertyReference &o)
+: m_name(o.m_name), m_value(o.m_value), m_binding(o.m_binding)
+{
+}
+
+QmlDebugPropertyReference &QmlDebugPropertyReference::operator=(const QmlDebugPropertyReference &o)
+{
+ m_name = o.m_name; m_value = o.m_value; m_binding = o.m_binding;
+ return *this;
+}
+
+QString QmlDebugPropertyReference::name() const
+{
+ return m_name;
+}
+
+QVariant QmlDebugPropertyReference::value() const
+{
+ return m_value;
+}
+
+QString QmlDebugPropertyReference::binding() const
+{
+ return m_binding;
+}
diff --git a/src/declarative/debugger/qmldebug.h b/src/declarative/debugger/qmldebug.h
new file mode 100644
index 0000000..52a5400
--- /dev/null
+++ b/src/declarative/debugger/qmldebug.h
@@ -0,0 +1,237 @@
+#ifndef QMLDEBUG_H
+#define QMLDEBUG_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qvariant.h>
+
+class QmlDebugClient;
+class QmlDebugWatch;
+class QmlDebugEnginesQuery;
+class QmlDebugRootContextQuery;
+class QmlDebugObjectQuery;
+class QmlDebugPropertyReference;
+class QmlDebugContextReference;
+class QmlDebugObjectReference;
+class QmlDebugFileReference;
+class QmlDebugEngineReference;
+class QmlEngineDebugPrivate;
+class Q_DECLARATIVE_EXPORT QmlEngineDebug : public QObject
+{
+Q_OBJECT
+public:
+ QmlEngineDebug(QmlDebugClient *, QObject * = 0);
+
+ QmlDebugWatch *addWatch(const QmlDebugPropertyReference &,
+ QObject *parent = 0);
+ QmlDebugWatch *addWatch(const QmlDebugContextReference &, const QString &,
+ QObject *parent = 0);
+ QmlDebugWatch *addWatch(const QmlDebugObjectReference &, const QString &,
+ QObject *parent = 0);
+ QmlDebugWatch *addWatch(const QmlDebugObjectReference &,
+ QObject *parent = 0);
+ QmlDebugWatch *addWatch(const QmlDebugFileReference &,
+ QObject *parent = 0);
+
+ QmlDebugEnginesQuery *queryAvailableEngines(QObject *parent = 0);
+ QmlDebugRootContextQuery *queryRootContexts(const QmlDebugEngineReference &,
+ QObject *parent = 0);
+ QmlDebugObjectQuery *queryObject(const QmlDebugObjectReference &,
+ QObject *parent = 0);
+ QmlDebugObjectQuery *queryObjectRecursive(const QmlDebugObjectReference &,
+ QObject *parent = 0);
+
+private:
+ Q_DECLARE_PRIVATE(QmlEngineDebug);
+};
+
+class Q_DECLARATIVE_EXPORT QmlDebugWatch : public QObject
+{
+Q_OBJECT
+public:
+ enum State { Waiting, Active, Inactive, Dead };
+
+ State state() const;
+
+signals:
+ void stateChanged(State);
+ void objectChanged(int, const QmlDebugObjectReference &);
+ void valueChanged(int, const QVariant &);
+};
+
+class Q_DECLARATIVE_EXPORT QmlDebugQuery : public QObject
+{
+Q_OBJECT
+public:
+ enum State { Waiting, Error, Completed };
+
+ State state() const;
+ bool isWaiting() const;
+
+// bool waitUntilCompleted();
+
+signals:
+ void stateChanged(State);
+
+protected:
+ QmlDebugQuery(QObject *);
+
+private:
+ friend class QmlEngineDebug;
+ friend class QmlEngineDebugPrivate;
+ void setState(State);
+ State m_state;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDebugFileReference
+{
+public:
+ QmlDebugFileReference();
+ QmlDebugFileReference(const QmlDebugFileReference &);
+ QmlDebugFileReference &operator=(const QmlDebugFileReference &);
+
+ QUrl url() const;
+ void setUrl(const QUrl &);
+ int lineNumber() const;
+ void setLineNumber(int);
+ int columnNumber() const;
+ void setColumnNumber(int);
+
+private:
+ friend class QmlEngineDebugPrivate;
+ QUrl m_url;
+ int m_lineNumber;
+ int m_columnNumber;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDebugEngineReference
+{
+public:
+ QmlDebugEngineReference();
+ QmlDebugEngineReference(int);
+ QmlDebugEngineReference(const QmlDebugEngineReference &);
+ QmlDebugEngineReference &operator=(const QmlDebugEngineReference &);
+
+ int debugId() const;
+ QString name() const;
+
+private:
+ friend class QmlEngineDebugPrivate;
+ int m_debugId;
+ QString m_name;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDebugObjectReference
+{
+public:
+ QmlDebugObjectReference();
+ QmlDebugObjectReference(int);
+ QmlDebugObjectReference(const QmlDebugObjectReference &);
+ QmlDebugObjectReference &operator=(const QmlDebugObjectReference &);
+
+ int debugId() const;
+ QString className() const;
+ QString name() const;
+
+ QmlDebugFileReference source() const;
+
+ QList<QmlDebugPropertyReference> properties() const;
+ QList<QmlDebugObjectReference> children() const;
+
+private:
+ friend class QmlEngineDebugPrivate;
+ int m_debugId;
+ QString m_class;
+ QString m_name;
+ QmlDebugFileReference m_source;
+ QList<QmlDebugPropertyReference> m_properties;
+ QList<QmlDebugObjectReference> m_children;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDebugContextReference
+{
+public:
+ QmlDebugContextReference();
+ QmlDebugContextReference(const QmlDebugContextReference &);
+ QmlDebugContextReference &operator=(const QmlDebugContextReference &);
+
+ int debugId() const;
+ QString name() const;
+
+ QList<QmlDebugObjectReference> objects() const;
+ QList<QmlDebugContextReference> contexts() const;
+
+private:
+ friend class QmlEngineDebugPrivate;
+ int m_debugId;
+ QString m_name;
+ QList<QmlDebugObjectReference> m_objects;
+ QList<QmlDebugContextReference> m_contexts;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDebugPropertyReference
+{
+public:
+ QmlDebugPropertyReference();
+ QmlDebugPropertyReference(const QmlDebugPropertyReference &);
+ QmlDebugPropertyReference &operator=(const QmlDebugPropertyReference &);
+
+ QString name() const;
+ QVariant value() const;
+ QString binding() const;
+
+private:
+ friend class QmlEngineDebugPrivate;
+ QString m_name;
+ QVariant m_value;
+ QString m_binding;
+};
+
+
+class Q_DECLARATIVE_EXPORT QmlDebugEnginesQuery : public QmlDebugQuery
+{
+Q_OBJECT
+public:
+ virtual ~QmlDebugEnginesQuery();
+ QList<QmlDebugEngineReference> engines() const;
+private:
+ friend class QmlEngineDebug;
+ friend class QmlEngineDebugPrivate;
+ QmlDebugEnginesQuery(QObject *);
+ QmlEngineDebug *m_client;
+ int m_queryId;
+ QList<QmlDebugEngineReference> m_engines;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDebugRootContextQuery : public QmlDebugQuery
+{
+Q_OBJECT
+public:
+ virtual ~QmlDebugRootContextQuery();
+ QmlDebugContextReference rootContext() const;
+private:
+ friend class QmlEngineDebug;
+ friend class QmlEngineDebugPrivate;
+ QmlDebugRootContextQuery(QObject *);
+ QmlEngineDebug *m_client;
+ int m_queryId;
+ QmlDebugContextReference m_context;
+};
+
+class Q_DECLARATIVE_EXPORT QmlDebugObjectQuery : public QmlDebugQuery
+{
+Q_OBJECT
+public:
+ virtual ~QmlDebugObjectQuery();
+ QmlDebugObjectReference object() const;
+private:
+ friend class QmlEngineDebug;
+ friend class QmlEngineDebugPrivate;
+ QmlDebugObjectQuery(QObject *);
+ QmlEngineDebug *m_client;
+ int m_queryId;
+ QmlDebugObjectReference m_object;
+
+};
+
+#endif // QMLDEBUG_H
diff --git a/src/declarative/debugger/qmldebugclient.cpp b/src/declarative/debugger/qmldebugclient.cpp
index e442333..562d87d 100644
--- a/src/declarative/debugger/qmldebugclient.cpp
+++ b/src/declarative/debugger/qmldebugclient.cpp
@@ -97,6 +97,11 @@ QmlDebugClient::QmlDebugClient(QObject *parent)
{
}
+bool QmlDebugClient::isConnected() const
+{
+ return state() == ConnectedState;
+}
+
class QmlDebugClientPluginPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QmlDebugClientPlugin);
@@ -169,11 +174,18 @@ void QmlDebugClientPlugin::setEnabled(bool e)
}
}
+bool QmlDebugClientPlugin::isConnected() const
+{
+ Q_D(const QmlDebugClientPlugin);
+
+ return d->client->isConnected();
+}
+
void QmlDebugClientPlugin::sendMessage(const QByteArray &message)
{
Q_D(QmlDebugClientPlugin);
- if (!d->client || d->client->state() != QTcpSocket::ConnectedState)
+ if (!d->client || !d->client->isConnected())
return;
QPacket pack;
diff --git a/src/declarative/debugger/qmldebugclient.h b/src/declarative/debugger/qmldebugclient.h
index 3fbf534..194e913 100644
--- a/src/declarative/debugger/qmldebugclient.h
+++ b/src/declarative/debugger/qmldebugclient.h
@@ -58,6 +58,7 @@ class Q_DECLARATIVE_EXPORT QmlDebugClient : public QTcpSocket
public:
QmlDebugClient(QObject * = 0);
+ bool isConnected() const;
private:
QmlDebugClientPrivate *d;
friend class QmlDebugClientPlugin;
@@ -79,6 +80,8 @@ public:
bool isEnabled() const;
void setEnabled(bool);
+ bool isConnected() const;
+
void sendMessage(const QByteArray &);
protected:
diff --git a/src/declarative/debugger/qmldebugger.cpp b/src/declarative/debugger/qmldebugger.cpp
deleted file mode 100644
index 78c4090..0000000
--- a/src/declarative/debugger/qmldebugger.cpp
+++ /dev/null
@@ -1,359 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qmldebugger.h"
-#include <QtGui/qtreewidget.h>
-#include <QtGui/qboxlayout.h>
-#include <QtGui/qplaintextedit.h>
-#include <QTextBlock>
-#include <QtGui/qtabwidget.h>
-#include <QtDeclarative/qmlbindablevalue.h>
-#include <QtDeclarative/qmldebuggerstatus.h>
-#include <private/qmlboundsignal_p.h>
-#include <private/qmlcontext_p.h>
-#include <private/qmlengine_p.h>
-#include <private/qmlexpression_p.h>
-#include <private/qmlobjecttree_p.h>
-#include <QtCore/qdebug.h>
-#include <QtCore/qfile.h>
-#include <QtCore/qurl.h>
-#include <QtGui/qsplitter.h>
-#include <QtGui/qpushbutton.h>
-#include <QtGui/qtablewidget.h>
-#include <QtGui/qevent.h>
-#include <QtDeclarative/qmlexpression.h>
-#include <private/qmlpropertyview_p.h>
-#include <private/qmlwatches_p.h>
-
-QT_BEGIN_NAMESPACE
-
-QmlDebugger::QmlDebugger(QWidget *parent)
-: QWidget(parent), m_tree(0), m_warnings(0), m_watchTable(0), m_watches(0),
- m_properties(0), m_text(0), m_highlightedItem(0)
-{
- QHBoxLayout *layout = new QHBoxLayout;
- setLayout(layout);
- QSplitter *splitter = new QSplitter(this);
- layout->addWidget(splitter);
-
- QWidget *treeWid = new QWidget(this);
- QVBoxLayout *vlayout = new QVBoxLayout;
- vlayout->setContentsMargins(0, 0, 0, 0);
- treeWid->setLayout(vlayout);
- splitter->addWidget(treeWid);
-
- m_tree = new QmlObjectTree(treeWid);
- m_tree->setHeaderHidden(true);
- QObject::connect(m_tree, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, SLOT(itemClicked(QTreeWidgetItem *)));
- QObject::connect(m_tree, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(itemDoubleClicked(QTreeWidgetItem *)));
- QObject::connect(m_tree, SIGNAL(addWatch(QObject*,QString)), this, SLOT(addWatch(QObject*,QString)));
- vlayout->addWidget(m_tree);
-
- QPushButton *pb = new QPushButton(tr("Refresh"), treeWid);
- QObject::connect(pb, SIGNAL(clicked()), this, SLOT(refresh()));
- vlayout->addWidget(pb);
-
- QTabWidget *tabs = new QTabWidget(this);
-
- m_text = new QPlainTextEdit(this);
- m_text->setReadOnly(true);
- tabs->addTab(m_text, tr("File"));
-
- m_warnings = new QTreeWidget(this);
- m_warnings->setHeaderHidden(true);
- tabs->addTab(m_warnings, tr("Warnings"));
-
- m_watches = new QmlWatches(this);
- m_watchTable = new QTableView(this);
- m_watchTable->setSelectionMode(QTableWidget::NoSelection);
- m_watchTable->setModel(m_watches);
- tabs->addTab(m_watchTable, tr("Watches"));
-
- m_properties = new QmlPropertyView(m_watches, this);
- QObject::connect(m_properties, SIGNAL(objectClicked(quint32)),
- this, SLOT(highlightObject(quint32)));
- tabs->addTab(m_properties, tr("Properties"));
- tabs->setCurrentWidget(m_properties);
-
- splitter->addWidget(tabs);
- splitter->setStretchFactor(1, 2);
-
- setGeometry(0, 100, 800, 600);
-}
-
-void QmlDebugger::itemDoubleClicked(QTreeWidgetItem *)
-{
-}
-
-void QmlDebugger::addWatch(QObject *obj, const QString &expr)
-{
- QmlContext *ctxt = qmlContext(obj);
- if(ctxt) {
- QmlExpressionObject *e= new QmlExpressionObject(ctxt, expr, obj, m_watches);
- m_watches->addWatch(e);
- }
-}
-
-void QmlDebugger::highlightObject(quint32 id)
-{
- QHash<quint32, QTreeWidgetItem *>::ConstIterator iter = m_items.find(id);
- if (m_highlightedItem) {
- m_highlightedItem->setBackground(0, QPalette().base());
- m_highlightedItem = 0;
- }
-
- if (iter != m_items.end()) {
- m_highlightedItem = *iter;
- m_highlightedItem->setBackground(0, QColor("cyan"));
- m_tree->expandItem(m_highlightedItem);
- m_tree->scrollToItem(m_highlightedItem);
- }
-}
-
-void QmlDebugger::itemClicked(QTreeWidgetItem *i)
-{
- QmlDebuggerItem *item = static_cast<QmlDebuggerItem *>(i);
-
- if(m_selectedItem) {
- QmlDebuggerStatus *debug =
- qobject_cast<QmlDebuggerStatus *>(m_selectedItem);
- Q_ASSERT(debug);
- debug->setSelectedState(false);
- m_selectedItem = 0;
- }
-
- if(item->object) {
- QmlDebuggerStatus *debug =
- qobject_cast<QmlDebuggerStatus *>(item->object);
- if(debug) {
- debug->setSelectedState(true);
- m_selectedItem = item->object;
- }
-
- m_properties->setObject(item->object);
- }
-
- if(item->url.scheme() == QLatin1String("file")) {
- QString f = item->url.toLocalFile();
- QFile file(f);
- file.open(QIODevice::ReadOnly);
- QByteArray ba = file.readAll();
- QTextStream stream(ba, QIODevice::ReadOnly);
- const QString code = stream.readAll();
-
- m_text->setPlainText(code);
-
- if(item->startLine != -1) {
- QTextDocument *document = m_text->document();
- QTextCharFormat format;
- format.setForeground(Qt::lightGray);
-
- {
- QTextCursor cursor(document);
- cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
- cursor.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, item->endLine);
- cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
- cursor.setCharFormat(format);
- }
-
- {
- QTextCursor cursor(document);
- cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
- cursor.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor, item->startLine - 1);
- cursor.setCharFormat(format);
- }
-
- {
- QTextCursor cursor(document);
- cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
- cursor.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, item->startLine - 1);
- m_text->setTextCursor(cursor);
- m_text->centerCursor();
- }
-
-
- }
-
- }
-}
-
-bool QmlDebugger::makeItem(QObject *obj, QmlDebuggerItem *item)
-{
- bool rv = true;
-
- QString text;
-
- item->object = obj;
-
- if(QmlBindableValue *bv = qobject_cast<QmlBindableValue *>(obj)) {
- QmlExpressionPrivate *p = bv->d;
-
- text = bv->property().name() + QLatin1String(": ") + bv->expression();
- item->setForeground(0, Qt::green);
- item->bindableValue = bv;
-
- if(p->log) {
- QTreeWidgetItem *warningItem = 0;
-
- for(int ii = 0; ii < p->log->count(); ++ii) {
- const QmlExpressionLog &log = p->log->at(ii);
-
- QString variant; QDebug d(&variant); d << log.result();
-
- if(!log.warnings().isEmpty()) {
-
- if(!warningItem) {
- warningItem = new QTreeWidgetItem(m_warnings);
- warningItem->setText(0, bv->expression());
- }
-
- QTreeWidgetItem *entry = new QTreeWidgetItem(warningItem);
- entry->setExpanded(true);
-
- entry->setText(0, variant);
-
- foreach(const QString &warning, log.warnings()) {
- QTreeWidgetItem *w = new QTreeWidgetItem(entry);
- w->setText(0, warning);
- }
- }
-
- }
-
- }
-
- delete item;
- return false;
-
- } else if(qobject_cast<QmlBoundSignal *>(obj)) {
- delete item;
- return false;
- } else {
- QmlContext *context = qmlContext(obj);
- QmlContext *parentContext = qmlContext(obj->parent());
-
- text = QLatin1String(obj->metaObject()->className());
-
- if(context && context != parentContext) {
- QmlContextPrivate *p = static_cast<QmlContextPrivate *>(QObjectPrivate::get(context));
-
- QString toolTipString;
- if(!p->url.toString().isEmpty()) {
- item->url = p->url;
- toolTipString = QLatin1String("URL: ") + p->url.toString();
- }
-
- if(!p->typeName.isEmpty()) {
- if(!toolTipString.isEmpty())
- toolTipString.prepend(QLatin1Char('\n'));
- toolTipString.prepend(tr("Root type: ") + text);
- text = QString::fromAscii(p->typeName);
- }
-
- if(!toolTipString.isEmpty())
- item->setToolTip(0, toolTipString);
-
- item->setForeground(0, QColor("orange"));
-
- if(p->startLine != -1) {
- item->startLine = p->startLine;
- item->endLine = p->endLine;
- }
-
- } else {
- item->setExpanded(true);
- }
-
- if(!context)
- item->setForeground(0, Qt::lightGray);
- }
-
- m_items.insert(m_watches->objectId(obj), item);
- item->setText(0, text);
-
- return rv;
-}
-
-void QmlDebugger::buildTree(QObject *obj, QmlDebuggerItem *parent)
-{
- QObjectList children = obj->children();
-
- for (int ii = 0; ii < children.count(); ++ii) {
- QmlDebuggerItem *item = new QmlDebuggerItem(parent);
- if(makeItem(children.at(ii), item))
- buildTree(children.at(ii), item);
- }
-}
-
-void QmlDebugger::refresh()
-{
- setDebugObject(m_object);
-}
-
-bool operator<(const QPair<quint32, QPair<int, QString> > &lhs,
- const QPair<quint32, QPair<int, QString> > &rhs)
-{
- return lhs.first < rhs.first;
-}
-
-void QmlDebugger::setCanvas(QSimpleCanvas *c)
-{
- Q_UNUSED(c);
-}
-
-void QmlDebugger::setDebugObject(QObject *obj)
-{
- m_tree->clear();
- m_warnings->clear();
- m_items.clear();
- m_highlightedItem = 0;
-
- m_object = obj;
- if(!obj)
- return;
-
- QmlDebuggerItem *item = new QmlDebuggerItem(m_tree);
- makeItem(obj, item);
- buildTree(obj, item);
- item->setExpanded(true);
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qmldebugger.h b/src/declarative/debugger/qmldebugger.h
deleted file mode 100644
index 03efeb6..0000000
--- a/src/declarative/debugger/qmldebugger.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QMLDEBUGGER_H
-#define QMLDEBUGGER_H
-
-#include <QtCore/qpointer.h>
-#include <QtCore/qset.h>
-#include <QtGui/qwidget.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Declarative)
-
-class QTreeWidget;
-class QTreeWidgetItem;
-class QPlainTextEdit;
-class QmlDebuggerItem;
-class QTableView;
-class QmlPropertyView;
-class QmlWatches;
-class QmlObjectTree;
-class QmlContext;
-class QSimpleCanvas;
-class QmlDebugger : public QWidget
-{
-Q_OBJECT
-public:
- QmlDebugger(QWidget *parent = 0);
-
- void setDebugObject(QObject *);
- void setCanvas(QSimpleCanvas *);
-
-public slots:
- void refresh();
-
-private slots:
- void itemClicked(QTreeWidgetItem *);
- void itemDoubleClicked(QTreeWidgetItem *);
- void highlightObject(quint32);
- void addWatch(QObject *, const QString &);
-
-private:
- void buildTree(QObject *obj, QmlDebuggerItem *parent);
- bool makeItem(QObject *obj, QmlDebuggerItem *item);
- QmlObjectTree *m_tree;
- QTreeWidget *m_warnings;
- QTableView *m_watchTable;
- QmlWatches *m_watches;
- QmlPropertyView *m_properties;
- QPlainTextEdit *m_text;
- QPointer<QObject> m_object;
- QPointer<QObject> m_selectedItem;
-
- QTreeWidgetItem *m_highlightedItem;
- QHash<quint32, QTreeWidgetItem *> m_items;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QMLDEBUGGER_H
diff --git a/src/declarative/debugger/qmldebugserver.cpp b/src/declarative/debugger/qmldebugserver.cpp
index e055ad5..ddfb88a 100644
--- a/src/declarative/debugger/qmldebugserver.cpp
+++ b/src/declarative/debugger/qmldebugserver.cpp
@@ -253,6 +253,87 @@ bool QmlDebugServerPlugin::isEnabled() const
return (d->server && d->server->d_func()->enabledPlugins.contains(d->name));
}
+namespace {
+
+ struct ObjectReference
+ {
+ QPointer<QObject> object;
+ int id;
+ };
+
+ struct ObjectReferenceHash
+ {
+ ObjectReferenceHash() : nextId(0) {}
+
+ QHash<QObject *, ObjectReference> objects;
+ QHash<int, QObject *> ids;
+
+ int nextId;
+ };
+
+}
+Q_GLOBAL_STATIC(ObjectReferenceHash, objectReferenceHash);
+
+
+/*!
+ Returns a unique id for \a object. Calling this method multiple times
+ for the same object will return the same id.
+*/
+int QmlDebugServerPlugin::idForObject(QObject *object)
+{
+ if (!object)
+ return -1;
+
+ ObjectReferenceHash *hash = objectReferenceHash();
+ QHash<QObject *, ObjectReference>::Iterator iter =
+ hash->objects.find(object);
+
+ if (iter == hash->objects.end()) {
+ int id = hash->nextId++;
+
+ hash->ids.insert(id, object);
+ iter = hash->objects.insert(object, ObjectReference());
+ iter->object = object;
+ iter->id = id;
+ } else if (iter->object != object) {
+ int id = hash->nextId++;
+
+ hash->ids.remove(iter->id);
+
+ hash->ids.insert(id, object);
+ iter->object = object;
+ iter->id = id;
+ }
+ return iter->id;
+}
+
+/*!
+ Returns the object for unique \a id. If the object has not previously been
+ assigned an id, through idForObject(), then 0 is returned. If the object
+ has been destroyed, 0 is returned.
+*/
+QObject *QmlDebugServerPlugin::objectForId(int id)
+{
+ ObjectReferenceHash *hash = objectReferenceHash();
+
+ QHash<int, QObject *>::Iterator iter = hash->ids.find(id);
+ if (iter == hash->ids.end())
+ return 0;
+
+
+ QHash<QObject *, ObjectReference>::Iterator objIter =
+ hash->objects.find(*iter);
+ Q_ASSERT(objIter != hash->objects.end());
+
+ if (objIter->object == 0) {
+ hash->ids.erase(iter);
+ hash->objects.erase(objIter);
+ return 0;
+ } else {
+ return *iter;
+ }
+}
+
bool QmlDebugServerPlugin::isDebuggingEnabled()
{
return QmlDebugServer::instance() != 0;
diff --git a/src/declarative/debugger/qmldebugserver.h b/src/declarative/debugger/qmldebugserver.h
index 02fe7d1..b15ee2e 100644
--- a/src/declarative/debugger/qmldebugserver.h
+++ b/src/declarative/debugger/qmldebugserver.h
@@ -63,6 +63,10 @@ public:
void sendMessage(const QByteArray &);
+ static int idForObject(QObject *);
+ static QObject *objectForId(int);
+
+
static bool isDebuggingEnabled();
static QString objectToString(QObject *obj);
diff --git a/src/declarative/debugger/qmlobjecttree.cpp b/src/declarative/debugger/qmlobjecttree.cpp
deleted file mode 100644
index 8a2358a..0000000
--- a/src/declarative/debugger/qmlobjecttree.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <private/qmlobjecttree_p.h>
-#include <QtDeclarative/qml.h>
-#include <QtGui/qevent.h>
-#include <QtGui/qmenu.h>
-#include <QtCore/qlist.h>
-#include <QtGui/qaction.h>
-#include <QtGui/qinputdialog.h>
-#include <QtGui/qboxlayout.h>
-
-QT_BEGIN_NAMESPACE
-
-QmlObjectTree::QmlObjectTree(QWidget *parent)
-: QTreeWidget(parent)
-{
-}
-
-void QmlObjectTree::mousePressEvent(QMouseEvent *me)
-{
- QTreeWidget::mousePressEvent(me);
- if(me->button() == Qt::RightButton && me->type() == QEvent::MouseButtonPress) {
- QAction action(tr("Add watch..."), 0);
- QList<QAction *> actions;
- actions << &action;
- QmlDebuggerItem *item = static_cast<QmlDebuggerItem *>(currentItem());
- if(item && qmlContext(item->object) &&
- QMenu::exec(actions, me->globalPos())) {
-
- bool ok = false;
- QString watch = QInputDialog::getText(this, tr("Watch expression"), tr("Expression:"), QLineEdit::Normal, QString(), &ok);
-
- if(ok && !watch.isEmpty())
- emit addWatch(item->object, watch);
- }
- }
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qmlpropertyview.cpp b/src/declarative/debugger/qmlpropertyview.cpp
deleted file mode 100644
index 76a192d..0000000
--- a/src/declarative/debugger/qmlpropertyview.cpp
+++ /dev/null
@@ -1,228 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qmlpropertyview_p.h"
-#include <QtGui/qboxlayout.h>
-#include <QtGui/qtreewidget.h>
-#include <QtCore/qmetaobject.h>
-#include <QtCore/qdebug.h>
-#include <QtDeclarative/qmlbindablevalue.h>
-#include <private/qmlboundsignal_p.h>
-
-QT_BEGIN_NAMESPACE
-
-QmlPropertyView::QmlPropertyView(QmlWatches *watches, QWidget *parent)
-: QWidget(parent), m_tree(0), m_watches(watches)
-{
- QVBoxLayout *layout = new QVBoxLayout;
- layout->setContentsMargins(0, 0, 0, 0);
- layout->setSpacing(0);
- setLayout(layout);
-
- m_tree = new QTreeWidget(this);
- m_tree->setHeaderLabels(QStringList() << tr("Property") << tr("Value"));
- QObject::connect(m_tree, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)),
- this, SLOT(itemDoubleClicked(QTreeWidgetItem *)));
- QObject::connect(m_tree, SIGNAL(itemClicked(QTreeWidgetItem *, int)),
- this, SLOT(itemClicked(QTreeWidgetItem *)));
-
- m_tree->setColumnCount(2);
-
- layout->addWidget(m_tree);
-}
-
-class QmlPropertyViewItem : public QObject, public QTreeWidgetItem
-{
-Q_OBJECT
-public:
- QmlPropertyViewItem(QTreeWidget *widget);
- QmlPropertyViewItem(QTreeWidgetItem *parent);
-
- QObject *object;
- QMetaProperty property;
-
- quint32 exprId;
-
-public slots:
- void refresh();
-};
-
-QmlPropertyViewItem::QmlPropertyViewItem(QTreeWidget *widget)
-: QTreeWidgetItem(widget), object(0), exprId(0)
-{
-}
-
-QmlPropertyViewItem::QmlPropertyViewItem(QTreeWidgetItem *parent)
-: QTreeWidgetItem(parent), object(0), exprId(0)
-{
-}
-
-void QmlPropertyViewItem::refresh()
-{
- QVariant v = property.read(object);
- QString str = v.toString();
-
- if (QmlMetaType::isObject(v.userType()))
- str = QmlWatches::objectToString(QmlMetaType::toQObject(v));
-
- setText(1, str);
-}
-
-void QmlPropertyView::itemClicked(QTreeWidgetItem *i)
-{
- QmlPropertyViewItem *item = static_cast<QmlPropertyViewItem *>(i);
-
- if(item->object) {
- QVariant v = item->property.read(item->object);
- if (QmlMetaType::isObject(v.userType())) {
- QObject *obj = QmlMetaType::toQObject(v);
-
- if(obj) {
- quint32 id = m_watches->objectId(obj);
- emit objectClicked(id);
- }
- }
- }
-
-}
-
-void QmlPropertyView::itemDoubleClicked(QTreeWidgetItem *i)
-{
- QmlPropertyViewItem *item = static_cast<QmlPropertyViewItem *>(i);
-
- if(item->object) {
- quint32 objectId = m_watches->objectId(item->object);
-
- if(m_watches->hasWatch(objectId, item->property.name())) {
- m_watches->remWatch(objectId, item->property.name());
- item->setForeground(0, Qt::black);
- } else {
- m_watches->addWatch(objectId, item->property.name());
- item->setForeground(0, Qt::red);
- }
- }
-
-}
-
-void QmlPropertyView::setObject(QObject *object)
-{
- m_object = object;
-
- m_tree->clear();
- if(!m_object)
- return;
-
- QMultiHash<QByteArray, QPair<QString, quint32> > bindings;
- QHash<QByteArray, QString> sigs;
- QObjectList children = object->children();
-
- foreach(QObject *child, children) {
- if(QmlBindableValue *value = qobject_cast<QmlBindableValue *>(child)) {
- bindings.insert(value->property().name().toUtf8(), qMakePair(value->expression(), value->id()));
- } else if(QmlBoundSignal *signal = qobject_cast<QmlBoundSignal *>(child)) {
- QMetaMethod method = object->metaObject()->method(signal->index());
- QByteArray sig = method.signature();
- sigs.insert(sig, signal->expression());
- }
- }
-
- quint32 objectId = m_watches->objectId(object);
-
- const QMetaObject *mo = object->metaObject();
- for(int ii = 0; ii < mo->propertyCount(); ++ii) {
- QMetaProperty p = mo->property(ii);
-
- if(QmlMetaType::isList(p.userType()) ||
- QmlMetaType::isQmlList(p.userType()))
- continue;
-
- QmlPropertyViewItem *item = new QmlPropertyViewItem(m_tree);
-
- item->object = object;
- item->property = p;
-
- item->setText(0, QLatin1String(p.name()));
- if(m_watches->hasWatch(objectId, p.name()))
- item->setForeground(0, Qt::red);
-
- static int refreshIdx = -1;
- if(refreshIdx == -1)
- refreshIdx = QmlPropertyViewItem::staticMetaObject.indexOfMethod("refresh()");
-
- if(p.hasNotifySignal())
- QMetaObject::connect(object, p.notifySignalIndex(),
- item, refreshIdx);
-
-
- QMultiHash<QByteArray, QPair<QString, quint32> >::Iterator iter =
- bindings.find(p.name());
-
- while(iter != bindings.end() && iter.key() == p.name()) {
- QmlPropertyViewItem *binding = new QmlPropertyViewItem(item);
- binding->exprId = iter.value().second;
- binding->setText(1, iter.value().first);
- binding->setForeground(1, Qt::green);
- ++iter;
- }
-
- item->setExpanded(true);
- item->refresh();
- }
-
- for(QHash<QByteArray, QString>::ConstIterator iter = sigs.begin();
- iter != sigs.end();
- ++iter) {
-
- QTreeWidgetItem *item = new QTreeWidgetItem(m_tree);
- item->setText(0, QString::fromAscii(iter.key()));
- item->setForeground(0, Qt::blue);
- item->setText(1, iter.value());
- }
-}
-
-void QmlPropertyView::refresh()
-{
- setObject(m_object);
-}
-
-QT_END_NAMESPACE
-
-#include "qmlpropertyview.moc"
diff --git a/src/declarative/debugger/qmlpropertyview_p.h b/src/declarative/debugger/qmlpropertyview_p.h
deleted file mode 100644
index 4694482..0000000
--- a/src/declarative/debugger/qmlpropertyview_p.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QMLPROPERTYVIEW_P_H
-#define QMLPROPERTYVIEW_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtGui/qwidget.h>
-#include <QtCore/qpointer.h>
-#include <private/qmlwatches_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QTreeWidget;
-class QTreeWidgetItem;
-class QmlPropertyView : public QWidget
-{
- Q_OBJECT
-public:
- QmlPropertyView(QmlWatches *watches, QWidget *parent = 0);
-
- void setObject(QObject *);
-
-signals:
- void objectClicked(quint32);
-
-public slots:
- void refresh();
- void itemDoubleClicked(QTreeWidgetItem *);
- void itemClicked(QTreeWidgetItem *);
-
-private:
- QPointer<QObject> m_object;
- QTreeWidget *m_tree;
- QmlWatches *m_watches;
-};
-
-QT_END_NAMESPACE
-
-#endif // QMLPROPERTYVIEW_P_H
-
diff --git a/src/declarative/debugger/qmlwatches.cpp b/src/declarative/debugger/qmlwatches.cpp
deleted file mode 100644
index 8fc9e89..0000000
--- a/src/declarative/debugger/qmlwatches.cpp
+++ /dev/null
@@ -1,308 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qmlwatches_p.h"
-#include <QtCore/qmetaobject.h>
-#include <QtCore/qdebug.h>
-#include <QtGui/qcolor.h>
-#include <QtDeclarative/qmlmetatype.h>
-#include <QtDeclarative/qmlexpression.h>
-
-QT_BEGIN_NAMESPACE
-
-QString QmlWatches::objectToString(QObject *obj)
-{
- if(!obj)
- return QLatin1String("NULL");
-
- QString objectName = obj->objectName();
- if(objectName.isEmpty())
- objectName = QLatin1String("<unnamed>");
-
- QString rv = QLatin1String(obj->metaObject()->className()) +
- QLatin1String(": ") + objectName;
-
- return rv;
-}
-
-class QmlWatchesProxy : public QObject
-{
- Q_OBJECT
-public:
- QmlWatchesProxy(QObject *object,
- const QMetaProperty &prop,
- int column,
- QmlWatches *parent = 0);
-
- QmlWatchesProxy(QmlExpressionObject *object,
- int column,
- QmlWatches *parent = 0);
-
-public slots:
- void refresh();
-
-private:
- QmlWatches *m_watches;
- QObject *m_object;
- QMetaProperty m_property;
-
- QmlExpressionObject *m_expr;
- int m_column;
-};
-
-QmlWatchesProxy::QmlWatchesProxy(QmlExpressionObject *object,
- int column,
- QmlWatches *parent)
-: QObject(parent), m_watches(parent), m_object(0), m_expr(object), m_column(column)
-{
- QObject::connect(m_expr, SIGNAL(valueChanged()), this, SLOT(refresh()));
-}
-
-QmlWatchesProxy::QmlWatchesProxy(QObject *object,
- const QMetaProperty &prop,
- int column,
- QmlWatches *parent)
-: QObject(parent), m_watches(parent), m_object(object), m_property(prop),
- m_expr(0), m_column(column)
-{
- static int refreshIdx = -1;
- if(refreshIdx == -1)
- refreshIdx = QmlWatchesProxy::staticMetaObject.indexOfMethod("refresh()");
-
- QMetaObject::connect(m_object, prop.notifySignalIndex(),
- this, refreshIdx);
-}
-
-void QmlWatchesProxy::refresh()
-{
- QVariant v;
- if(m_expr) v = m_expr->value();
- else v= m_property.read(m_object);
-
- m_watches->addValue(m_column, v);
-}
-
-QmlWatches::QmlWatches(QObject *parent)
-: QAbstractTableModel(parent), m_uniqueId(0)
-{
-}
-
-bool QmlWatches::hasWatch(quint32 objectId, const QByteArray &property)
-{
- return m_watches.contains(qMakePair(objectId, property));
-}
-
-void QmlWatches::addWatch(QmlExpressionObject *expr)
-{
- int oldColumn = columnCount(QModelIndex());
-
- m_watches.append(qMakePair(quint32(0), QByteArray()));
-
- beginInsertColumns(QModelIndex(), oldColumn, oldColumn);
- endInsertColumns();
-
- m_columnNames.append(expr->expression());
-
- QmlWatchesProxy *proxy = new QmlWatchesProxy(expr, oldColumn, this);
- m_proxies.append(proxy);
-
- proxy->refresh();
- m_values[m_values.count() - 1].first = true;
-}
-
-void QmlWatches::addWatch(quint32 objectId, const QByteArray &property)
-{
- if(hasWatch(objectId, property))
- return;
-
- int oldColumn = columnCount(QModelIndex());
-
- m_watches.append(qMakePair(objectId, property));
-
- beginInsertColumns(QModelIndex(), oldColumn, oldColumn);
- endInsertColumns();
-
- QObject *obj = object(objectId);
- m_columnNames.append(QLatin1String(property) + QLatin1String(" on ") + objectToString(obj));
- QMetaProperty prop =
- obj->metaObject()->property(obj->metaObject()->indexOfProperty(property.constData()));
- QmlWatchesProxy *proxy = new QmlWatchesProxy(obj, prop, oldColumn, this);
- m_proxies.append(proxy);
- proxy->refresh();
- m_values[m_values.count() - 1].first = true;
-}
-
-void QmlWatches::remWatch(quint32 objectId, const QByteArray &property)
-{
- QPair<quint32, QByteArray> watch = qMakePair(objectId, property);
- for(int ii = 0; ii < m_watches.count(); ++ii) {
- if(m_watches.at(ii) == watch) {
- m_watches.removeAt(ii);
- m_columnNames.removeAt(ii);
- if(m_proxies.at(ii))
- delete m_proxies.at(ii);
- m_proxies.removeAt(ii);
-
-
- for(QList<Value>::Iterator iter = m_values.begin();
- iter != m_values.end();
- ) {
- if(iter->column == ii) {
- iter = m_values.erase(iter);
- } else {
- if(iter->column > ii)
- --iter->column;
- ++iter;
- }
- }
- reset();
- return;
- }
- }
-}
-
-quint32 QmlWatches::objectId(QObject *object)
-{
- Q_ASSERT(object);
-
- QHash<QObject *, QPair<QPointer<QObject>, quint32> *>::Iterator iter =
- m_objects.find(object);
- if(iter == m_objects.end()) {
- iter = m_objects.insert(object, new QPair<QPointer<QObject>, quint32>(QPointer<QObject>(object), m_uniqueId++));
- m_objectIds.insert(iter.value()->second, iter.value());
- }
-
- if(iter.value()->first != object) {
- iter.value()->first = object;
- iter.value()->second = m_uniqueId++;
-
- m_objectIds.insert(iter.value()->second, iter.value());
- }
- return iter.value()->second;
-}
-
-QObject *QmlWatches::object(quint32 id)
-{
- QHash<quint32, QPair<QPointer<QObject>, quint32> *>::Iterator iter =
- m_objectIds.find(id);
- if(iter == m_objectIds.end())
- return 0;
-
- if(!iter.value()->first) {
- m_objectIds.erase(iter);
- return 0;
- }
-
- return iter.value()->first;
-}
-
-void QmlWatches::addValue(int column, const QVariant &value)
-{
- int row = m_values.count();
-
- beginInsertRows(QModelIndex(), row, row);
- Value v;
- v.column = column;
- v.variant = value;
- v.first = false;
- m_values.append(v);
- endInsertRows();
-}
-
-int QmlWatches::columnCount(const QModelIndex &) const
-{
- return m_watches.count();
-}
-
-int QmlWatches::rowCount(const QModelIndex &) const
-{
- return m_values.count();
-}
-
-QVariant QmlWatches::headerData(int section, Qt::Orientation orientation, int role) const
-{
- if (orientation == Qt::Horizontal && section < m_columnNames.count() &&
- role == Qt::DisplayRole)
- return m_columnNames.at(section);
- else
- return QVariant();
-}
-
-QVariant QmlWatches::data(const QModelIndex &idx, int role) const
-{
- if(m_values.at(idx.row()).column == idx.column()) {
- if(role == Qt::DisplayRole) {
- const QVariant &value = m_values.at(idx.row()).variant;
-
- QString str = value.toString();
-
- if(str.isEmpty() && QmlMetaType::isObject(value.userType())) {
- QObject *o = QmlMetaType::toQObject(value);
- if(o) {
- QString objectName = o->objectName();
- if(objectName.isEmpty())
- objectName = QLatin1String("<unnamed>");
- str = QLatin1String(o->metaObject()->className()) +
- QLatin1String(": ") + objectName;
- }
- }
-
- if(str.isEmpty()) {
- QDebug d(&str);
- d << value;
- }
- return QVariant(str);
- } else if(role == Qt::BackgroundRole) {
- if(m_values.at(idx.row()).first)
- return QColor(Qt::green);
- else
- return QVariant();
- } else {
- return QVariant();
- }
- } else {
- return QVariant();
- }
-}
-
-QT_END_NAMESPACE
-
-#include "qmlwatches.moc"
diff --git a/src/declarative/debugger/qmlwatches_p.h b/src/declarative/debugger/qmlwatches_p.h
deleted file mode 100644
index dfec979..0000000
--- a/src/declarative/debugger/qmlwatches_p.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QMLWATCHES_P_H
-#define QMLWATCHES_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qbytearray.h>
-#include <QtCore/qobject.h>
-#include <QtCore/qpointer.h>
-#include <QtCore/qset.h>
-#include <QtCore/qstringlist.h>
-#include <QtCore/qabstractitemmodel.h>
-
-QT_BEGIN_NAMESPACE
-
-class QmlWatchesProxy;
-class QmlExpressionObject;
-
-class QmlWatches : public QAbstractTableModel
-{
- Q_OBJECT
-public:
- QmlWatches(QObject *parent = 0);
-
- bool hasWatch(quint32 objectId, const QByteArray &property);
- void addWatch(quint32 objectId, const QByteArray &property);
- void remWatch(quint32 objectId, const QByteArray &property);
-
- void addWatch(QmlExpressionObject *);
-
- quint32 objectId(QObject *);
- QObject *object(quint32);
-
- static QString objectToString(QObject *obj);
-protected:
- int columnCount(const QModelIndex &) const;
- int rowCount(const QModelIndex &) const;
- QVariant data(const QModelIndex &, int) const;
- QVariant headerData(int, Qt::Orientation, int) const;
-
-private:
- friend class QmlWatchesProxy;
- QList<QPair<quint32, QByteArray> > m_watches;
-
- void addValue(int, const QVariant &);
- struct Value {
- int column;
- QVariant variant;
- bool first;
- };
- QList<Value> m_values;
- QStringList m_columnNames;
- QList<QPointer<QmlWatchesProxy> > m_proxies;
-
- quint32 m_uniqueId;
- QHash<QObject *, QPair<QPointer<QObject>, quint32> *> m_objects;
- QHash<quint32, QPair<QPointer<QObject>, quint32> *> m_objectIds;
-};
-
-QT_END_NAMESPACE
-
-#endif // QMLWATCHES_P_H
diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri
index fa09935..f549a5e 100644
--- a/src/declarative/qml/qml.pri
+++ b/src/declarative/qml/qml.pri
@@ -25,6 +25,7 @@ SOURCES += qml/qmlparser.cpp \
qml/qmlinfo.cpp \
qml/qmlerror.cpp \
qml/qmlscriptparser.cpp \
+ qml/qmlenginedebug.cpp \
qml/qmlbasicscript.cpp
HEADERS += qml/qmlparser_p.h \
@@ -66,6 +67,7 @@ HEADERS += qml/qmlparser_p.h \
qml/qmlerror.h \
qml/qmlscriptparser_p.h \
qml/qmlbasicscript_p.h \
+ qml/qmlenginedebug_p.h \
qml/qpodvector_p.h
# for qtscript debugger
diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp
index a9f5442..06e15ec 100644
--- a/src/declarative/qml/qmlcomponent.cpp
+++ b/src/declarative/qml/qmlcomponent.cpp
@@ -523,8 +523,9 @@ QObject *QmlComponent::beginCreate(QmlContext *context)
if (!d->engine->d_func()->rootComponent)
d->engine->d_func()->rootComponent = this;
- QmlContext *ctxt =
- new QmlContext(context, 0);
+ QmlContextPrivate *contextPriv =
+ static_cast<QmlContextPrivate *>(QObjectPrivate::get(context));
+ QmlContext *ctxt = new QmlContext(context, 0, true);
static_cast<QmlContextPrivate*>(ctxt->d_ptr)->url = d->cc->url;
if(d->start != -1) {
// ### FIXME
@@ -558,6 +559,8 @@ QObject *QmlComponent::beginCreate(QmlContext *context)
delete ctxt;
}
+ if (rv && !contextPriv->isInternal && ep->isDebugging)
+ contextPriv->instances.append(rv);
return rv;
}
diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp
index b590596..0b2742d 100644
--- a/src/declarative/qml/qmlcontext.cpp
+++ b/src/declarative/qml/qmlcontext.cpp
@@ -54,8 +54,8 @@
QT_BEGIN_NAMESPACE
QmlContextPrivate::QmlContextPrivate()
-: parent(0), engine(0), notifyIndex(-1), highPriorityCount(0),
- startLine(-1), endLine(-1)
+: parent(0), engine(0), isInternal(false), notifyIndex(-1),
+ highPriorityCount(0), startLine(-1), endLine(-1)
{
}
@@ -212,7 +212,7 @@ void QmlContextPrivate::addDefaultObject(QObject *object, Priority priority)
*/
/*! \internal */
-QmlContext::QmlContext(QmlEngine *e)
+QmlContext::QmlContext(QmlEngine *e, bool)
: QObject(*(new QmlContextPrivate))
{
Q_D(QmlContext);
@@ -221,6 +221,20 @@ QmlContext::QmlContext(QmlEngine *e)
}
/*!
+ Create a new QmlContext as a child of \a engine's root context, and the
+ QObject \a parent.
+*/
+QmlContext::QmlContext(QmlEngine *engine, QObject *parent)
+: QObject(*(new QmlContextPrivate), parent)
+{
+ Q_D(QmlContext);
+ QmlContext *parentContext = engine?engine->rootContext():0;
+ d->parent = parentContext;
+ d->engine = parentContext->engine();
+ d->init();
+}
+
+/*!
Create a new QmlContext with the given \a parentContext, and the
QObject \a parent.
*/
@@ -234,6 +248,19 @@ QmlContext::QmlContext(QmlContext *parentContext, QObject *parent)
}
/*!
+ \internal
+*/
+QmlContext::QmlContext(QmlContext *parentContext, QObject *parent, bool)
+: QObject(*(new QmlContextPrivate), parent)
+{
+ Q_D(QmlContext);
+ d->parent = parentContext;
+ d->engine = parentContext->engine();
+ d->isInternal = true;
+ d->init();
+}
+
+/*!
Destroys the QmlContext.
Any expressions, or sub-contexts dependent on this context will be
diff --git a/src/declarative/qml/qmlcontext.h b/src/declarative/qml/qmlcontext.h
index f5858cb..a0bb8e5 100644
--- a/src/declarative/qml/qmlcontext.h
+++ b/src/declarative/qml/qmlcontext.h
@@ -62,6 +62,7 @@ class Q_DECLARATIVE_EXPORT QmlContext : public QObject
Q_DECLARE_PRIVATE(QmlContext)
public:
+ QmlContext(QmlEngine *parent, QObject *objParent=0);
QmlContext(QmlContext *parent, QObject *objParent=0);
virtual ~QmlContext();
@@ -86,6 +87,7 @@ private Q_SLOTS:
void objectDestroyed(QObject *);
private:
+ friend class QmlVME;
friend class QmlEngine;
friend class QmlEnginePrivate;
friend class QmlExpression;
@@ -97,7 +99,8 @@ private:
friend class QmlScriptPrivate;
friend class QmlBoundSignalProxy;
friend class QmlSimpleDeclarativeData;
- QmlContext(QmlEngine *);
+ QmlContext(QmlContext *parent, QObject *objParent, bool);
+ QmlContext(QmlEngine *, bool);
};
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h
index 569b320..f896873 100644
--- a/src/declarative/qml/qmlcontext_p.h
+++ b/src/declarative/qml/qmlcontext_p.h
@@ -76,6 +76,7 @@ public:
QmlContext *parent;
QmlEngine *engine;
+ bool isInternal;
QHash<QString, int> propertyNames;
QList<QVariant> propertyValues;
@@ -110,6 +111,9 @@ public:
QmlSimpleDeclarativeData contextData;
QObjectList contextObjects;
+
+ // Only used for debugging
+ QList<QPointer<QObject> > instances;
};
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
index d88d11f..6eb0005 100644
--- a/src/declarative/qml/qmlengine.cpp
+++ b/src/declarative/qml/qmlengine.cpp
@@ -72,6 +72,7 @@
#include "private/qmlmetaproperty_p.h"
#include <private/qmlbindablevalue_p.h>
#include <private/qmlvme_p.h>
+#include <private/qmlenginedebug_p.h>
Q_DECLARE_METATYPE(QmlMetaProperty)
Q_DECLARE_METATYPE(QList<QObject *>);
@@ -132,8 +133,9 @@ QStack<QmlEngine *> *QmlEngineStack::engines()
QmlEnginePrivate::QmlEnginePrivate(QmlEngine *e)
-: rootContext(0), currentBindContext(0), currentExpression(0), q(e),
- rootComponent(0), networkAccessManager(0), typeManager(e), uniqueId(1)
+: rootContext(0), currentBindContext(0), currentExpression(0), q(e),
+ isDebugging(false), rootComponent(0), networkAccessManager(0), typeManager(e),
+ uniqueId(1)
{
QScriptValue qtObject = scriptEngine.newQMetaObject(StaticQtMetaObject::get());
scriptEngine.globalObject().setProperty(QLatin1String("Qt"), qtObject);
@@ -179,12 +181,14 @@ void QmlEnginePrivate::clear(SimpleList<QmlParserStatus> &pss)
pss.clear();
}
+Q_GLOBAL_STATIC(QmlEngineDebugServer, qmlEngineDebugServer);
+
void QmlEnginePrivate::init()
{
scriptEngine.installTranslatorFunctions();
contextClass = new QmlContextScriptClass(q);
objectClass = new QmlObjectScriptClass(q);
- rootContext = new QmlContext(q);
+ rootContext = new QmlContext(q,true);
#ifdef QT_SCRIPTTOOLS_LIB
if (qmlDebugger()){
debugger = new QScriptEngineDebugger(q);
@@ -198,6 +202,13 @@ void QmlEnginePrivate::init()
scriptEngine.newFunction(QmlEngine::createQmlObject, 1));
scriptEngine.globalObject().setProperty(QLatin1String("createComponent"),
scriptEngine.newFunction(QmlEngine::createComponent, 1));
+
+ if (QCoreApplication::instance()->thread() == q->thread() &&
+ QmlEngineDebugServer::isDebuggingEnabled()) {
+ qmlEngineDebugServer();
+ isDebugging = true;
+ QmlEngineDebugServer::addEngine(q);
+ }
}
QmlContext *QmlEnginePrivate::setCurrentBindContext(QmlContext *c)
@@ -423,6 +434,9 @@ QmlEngine::QmlEngine(QObject *parent)
*/
QmlEngine::~QmlEngine()
{
+ Q_D(QmlEngine);
+ if (d->isDebugging)
+ QmlEngineDebugServer::remEngine(this);
}
/*!
diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h
index 9171fbb..1ec1b24 100644
--- a/src/declarative/qml/qmlengine_p.h
+++ b/src/declarative/qml/qmlengine_p.h
@@ -117,6 +117,7 @@ public:
QmlContext *currentBindContext;
QmlExpression *currentExpression;
QmlEngine *q;
+ bool isDebugging;
#ifdef QT_SCRIPTTOOLS_LIB
QScriptEngineDebugger *debugger;
#endif
diff --git a/src/declarative/qml/qmlenginedebug.cpp b/src/declarative/qml/qmlenginedebug.cpp
new file mode 100644
index 0000000..b5e44e7
--- /dev/null
+++ b/src/declarative/qml/qmlenginedebug.cpp
@@ -0,0 +1,268 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmlenginedebug_p.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qmetaobject.h>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlmetatype.h>
+#include "qmlcontext_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QList<QmlEngine *> QmlEngineDebugServer::m_engines;
+QmlEngineDebugServer::QmlEngineDebugServer(QObject *parent)
+: QmlDebugServerPlugin(QLatin1String("QmlEngine"), parent)
+{
+}
+
+QDataStream &operator<<(QDataStream &ds,
+ const QmlEngineDebugServer::QmlObjectData &data)
+{
+ ds << data.url << data.lineNumber << data.columnNumber << data.objectName
+ << data.objectType << data.objectId;
+ return ds;
+}
+
+QDataStream &operator>>(QDataStream &ds,
+ QmlEngineDebugServer::QmlObjectData &data)
+{
+ ds >> data.url >> data.lineNumber >> data.columnNumber >> data.objectName
+ >> data.objectType >> data.objectId;
+ return ds;
+}
+
+QDataStream &operator<<(QDataStream &ds,
+ const QmlEngineDebugServer::QmlObjectProperty &data)
+{
+ ds << (int)data.type << data.name << data.value;
+ return ds;
+}
+
+QDataStream &operator>>(QDataStream &ds,
+ QmlEngineDebugServer::QmlObjectProperty &data)
+{
+ int type;
+ ds >> type >> data.name >> data.value;
+ data.type = (QmlEngineDebugServer::QmlObjectProperty::Type)type;
+ return ds;
+}
+
+QmlEngineDebugServer::QmlObjectProperty
+QmlEngineDebugServer::propertyData(QObject *obj, int propIdx)
+{
+ QmlObjectProperty rv;
+
+ QMetaProperty prop = obj->metaObject()->property(propIdx);
+
+ rv.type = QmlObjectProperty::Unknown;
+ rv.name = prop.name();
+
+ if (prop.type() < QVariant::UserType) {
+ rv.type = QmlObjectProperty::Basic;
+ rv.value = prop.read(obj);
+ } else if (QmlMetaType::isObject(prop.userType())) {
+ rv.type = QmlObjectProperty::Object;
+ } else if (QmlMetaType::isList(prop.userType()) ||
+ QmlMetaType::isQmlList(prop.userType())) {
+ rv.type = QmlObjectProperty::List;
+ }
+ return rv;
+}
+
+void QmlEngineDebugServer::buildObjectDump(QDataStream &message,
+ QObject *object, bool recur)
+{
+ message << objectData(object);
+ message << object->metaObject()->propertyCount();
+
+ for (int ii = 0; ii < object->metaObject()->propertyCount(); ++ii)
+ message << propertyData(object, ii);
+
+ QObjectList children = object->children();
+ message << children.count() << recur;
+
+ for (int ii = 0; ii < children.count(); ++ii) {
+ QObject *child = children.at(ii);
+ if (recur)
+ buildObjectDump(message, child, recur);
+ else
+ message << objectData(child);
+ }
+}
+
+void QmlEngineDebugServer::buildObjectList(QDataStream &message,
+ QmlContext *ctxt)
+{
+ QmlContextPrivate *p = (QmlContextPrivate *)QObjectPrivate::get(ctxt);
+
+ QString ctxtName = ctxt->objectName();
+ int ctxtId = QmlDebugServerPlugin::idForObject(ctxt);
+
+ message << ctxtName << ctxtId;
+
+ int count = 0;
+
+ for (QSet<QmlContext *>::ConstIterator iter = p->childContexts.begin();
+ iter != p->childContexts.end(); ++iter) {
+ QmlContextPrivate *p = (QmlContextPrivate *)QObjectPrivate::get(*iter);
+ if (p->isInternal)
+ continue;
+ ++count;
+ }
+
+ message << count;
+
+ for (QSet<QmlContext *>::ConstIterator iter = p->childContexts.begin();
+ iter != p->childContexts.end(); ++iter) {
+ QmlContextPrivate *p = (QmlContextPrivate *)QObjectPrivate::get(*iter);
+ if (p->isInternal)
+ continue;
+ buildObjectList(message, *iter);
+ }
+
+ // Clean deleted objects
+ for (int ii = 0; ii < p->instances.count(); ++ii) {
+ if (!p->instances.at(ii)) {
+ p->instances.removeAt(ii);
+ --ii;
+ }
+ }
+
+ message << p->instances.count();
+ for (int ii = 0; ii < p->instances.count(); ++ii) {
+ message << objectData(p->instances.at(ii));
+ }
+}
+
+QmlEngineDebugServer::QmlObjectData
+QmlEngineDebugServer::objectData(QObject *object)
+{
+ QmlObjectData rv;
+ rv.lineNumber = -1;
+ rv.columnNumber = -1;
+
+ rv.objectName = object->objectName();
+ rv.objectType = object->metaObject()->className();
+ rv.objectId = QmlDebugServerPlugin::idForObject(object);
+
+ return rv;
+}
+
+void QmlEngineDebugServer::messageReceived(const QByteArray &message)
+{
+ QDataStream ds(message);
+
+ QByteArray type;
+ ds >> type;
+
+ if (type == "LIST_ENGINES") {
+ int queryId;
+ ds >> queryId;
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("LIST_ENGINES_R");
+ rs << queryId << m_engines.count();
+
+ for (int ii = 0; ii < m_engines.count(); ++ii) {
+ QmlEngine *engine = m_engines.at(ii);
+
+ QString engineName = engine->objectName();
+ int engineId = QmlDebugServerPlugin::idForObject(engine);
+
+ rs << engineName << engineId;
+ }
+
+ sendMessage(reply);
+ } else if (type == "LIST_OBJECTS") {
+ int queryId;
+ int engineId = -1;
+ ds >> queryId >> engineId;
+
+ QmlEngine *engine =
+ qobject_cast<QmlEngine *>(QmlDebugServerPlugin::objectForId(engineId));
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("LIST_OBJECTS_R") << queryId;
+
+ if (engine)
+ buildObjectList(rs, engine->rootContext());
+
+ sendMessage(reply);
+ } else if (type == "FETCH_OBJECT") {
+ int queryId;
+ int objectId;
+ bool recurse;
+
+ ds >> queryId >> objectId >> recurse;
+
+ QObject *object = QmlDebugServerPlugin::objectForId(objectId);
+
+ QByteArray reply;
+ QDataStream rs(&reply, QIODevice::WriteOnly);
+ rs << QByteArray("FETCH_OBJECT_R") << queryId;
+
+ if (object)
+ buildObjectDump(rs, object, recurse);
+
+ sendMessage(reply);
+ }
+}
+
+void QmlEngineDebugServer::addEngine(QmlEngine *engine)
+{
+ Q_ASSERT(engine);
+ Q_ASSERT(!m_engines.contains(engine));
+
+ m_engines.append(engine);
+}
+
+void QmlEngineDebugServer::remEngine(QmlEngine *engine)
+{
+ Q_ASSERT(engine);
+ Q_ASSERT(m_engines.contains(engine));
+
+ m_engines.removeAll(engine);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/debugger/qmlobjecttree_p.h b/src/declarative/qml/qmlenginedebug_p.h
index 54d6d8e..634f55f 100644
--- a/src/declarative/debugger/qmlobjecttree_p.h
+++ b/src/declarative/qml/qmlenginedebug_p.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QMLOBJECTTREE_P_H
-#define QMLOBJECTTREE_P_H
+#ifndef QMLENGINEDEBUG_P_H
+#define QMLENGINEDEBUG_P_H
//
// W A R N I N G
@@ -53,49 +53,56 @@
// We mean it.
//
-#include <QtGui/qtreewidget.h>
+#include <QtDeclarative/qmldebugserver.h>
#include <QtCore/qurl.h>
-#include <QtCore/qpointer.h>
+#include <QtCore/qvariant.h>
QT_BEGIN_NAMESPACE
-class QmlBindableValue;
-class QmlDebuggerItem : public QTreeWidgetItem
+class QmlEngine;
+class QmlContext;
+class QDataStream;
+class QmlEngineDebugServer : public QmlDebugServerPlugin
{
public:
- QmlDebuggerItem(QTreeWidget *wid)
- : QTreeWidgetItem(wid), startLine(-1), endLine(-1)
- {
- }
+ QmlEngineDebugServer(QObject * = 0);
- QmlDebuggerItem(QTreeWidgetItem *item)
- : QTreeWidgetItem(item), startLine(-1), endLine(-1)
- {
- }
+ struct QmlObjectData {
+ QUrl url;
+ int lineNumber;
+ int columnNumber;
+ QString objectName;
+ QString objectType;
+ int objectId;
+ };
- int startLine;
- int endLine;
- QUrl url;
+ struct QmlObjectProperty {
+ enum Type { Unknown, Basic, Object, List };
+ Type type;
+ QString name;
+ QVariant value;
+ };
- QPointer<QObject> object;
- QPointer<QmlBindableValue> bindableValue;
-};
+ static void addEngine(QmlEngine *);
+ static void remEngine(QmlEngine *);
-class QmlContext;
-class QmlObjectTree : public QTreeWidget
-{
- Q_OBJECT
-public:
- QmlObjectTree(QWidget *parent = 0);
+protected:
+ virtual void messageReceived(const QByteArray &);
-signals:
- void addWatch(QObject *, const QString &);
+private:
+ void buildObjectList(QDataStream &, QmlContext *);
+ void buildObjectDump(QDataStream &, QObject *, bool);
+ QmlObjectData objectData(QObject *);
+ QmlObjectProperty propertyData(QObject *, int);
-protected:
- virtual void mousePressEvent(QMouseEvent *);
+ static QList<QmlEngine *> m_engines;
};
+Q_DECLARATIVE_EXPORT QDataStream &operator<<(QDataStream &, const QmlEngineDebugServer::QmlObjectData &);
+Q_DECLARATIVE_EXPORT QDataStream &operator>>(QDataStream &, QmlEngineDebugServer::QmlObjectData &);
+Q_DECLARATIVE_EXPORT QDataStream &operator<<(QDataStream &, const QmlEngineDebugServer::QmlObjectProperty &);
+Q_DECLARATIVE_EXPORT QDataStream &operator>>(QDataStream &, QmlEngineDebugServer::QmlObjectProperty &);
QT_END_NAMESPACE
-#endif // QMLOBJECTTREE_P_H
+#endif // QMLENGINEDEBUG_P_H
diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp
index a11caeb..2acf1e2 100644
--- a/src/declarative/qml/qmlvme.cpp
+++ b/src/declarative/qml/qmlvme.cpp
@@ -521,7 +521,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlCompiledComp
if (signal.parameterTypes().isEmpty()) {
(void *)new QmlBoundSignal(QmlContext::activeContext(), primitives.at(instr.storeSignal.value), target, instr.storeSignal.signalIndex, target);
} else {
- (void *)new QmlBoundSignalProxy(new QmlContext(QmlContext::activeContext(), target), primitives.at(instr.storeSignal.value), target, instr.storeSignal.signalIndex, target);
+ (void *)new QmlBoundSignalProxy(new QmlContext(QmlContext::activeContext(), target, true), primitives.at(instr.storeSignal.value), target, instr.storeSignal.signalIndex, target);
}
}
break;
diff --git a/src/declarative/util/qfxview.cpp b/src/declarative/util/qfxview.cpp
index 0a3afda..103442c 100644
--- a/src/declarative/util/qfxview.cpp
+++ b/src/declarative/util/qfxview.cpp
@@ -65,7 +65,6 @@
QT_BEGIN_NAMESPACE
DEFINE_BOOL_CONFIG_OPTION(itemTreeDump, ITEMTREE_DUMP);
-DEFINE_BOOL_CONFIG_OPTION(qmlDebugger, QML_DEBUGGER);
static QVariant stringToPixmap(const QString &str)
{
@@ -325,15 +324,6 @@ void QFxView::continueExecute()
if (itemTreeDump())
item->dump();
- if(qmlDebugger()) {
- QmlDebugger *debugger = new QmlDebugger;
- debugger->setDebugObject(item);
- debugger->setCanvas(this);
- debugger->show();
- raise();
- debugger->raise();
- }
-
QPerformanceLog::displayData();
QPerformanceLog::clear();
d->root = item;
diff --git a/tools/qmldebugger/engine.cpp b/tools/qmldebugger/engine.cpp
new file mode 100644
index 0000000..46d30c4
--- /dev/null
+++ b/tools/qmldebugger/engine.cpp
@@ -0,0 +1,172 @@
+#include "engine.h"
+#include <QtDeclarative/qmldebugclient.h>
+#include <QPushButton>
+#include <QVBoxLayout>
+#include <QLineEdit>
+#include <private/qmlenginedebug_p.h>
+#include <QtDeclarative/qmlcomponent.h>
+#include <QtDeclarative/qfxitem.h>
+
+QT_BEGIN_NAMESPACE
+
+class DebuggerEngineItem : public QObject
+{
+Q_OBJECT
+Q_PROPERTY(QString name READ name CONSTANT);
+Q_PROPERTY(QString engineId READ engineId CONSTANT);
+
+public:
+ DebuggerEngineItem(const QString &name, int id)
+ : m_name(name), m_engineId(id) {}
+
+ QString name() const { return m_name; }
+ int engineId() const { return m_engineId; }
+
+private:
+ QString m_name;
+ int m_engineId;
+};
+
+EnginePane::EnginePane(QmlDebugClient *client, QWidget *parent)
+: QWidget(parent), m_client(client), m_engines(0), m_context(0), m_object(0)
+{
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->setContentsMargins(0, 0, 0, 0);
+
+ setLayout(layout);
+
+ m_engineView = new QFxView(this);
+ m_engineView->rootContext()->setContextProperty("engines", qVariantFromValue(&m_engineItems));
+ m_engineView->setContentResizable(true);
+ m_engineView->setUrl(QUrl::fromLocalFile("engines.qml"));
+ m_engineView->execute();
+ m_engineView->setFixedHeight(100);
+ QObject::connect(m_engineView->root(), SIGNAL(engineClicked(int)),
+ this, SLOT(engineSelected(int)));
+ QObject::connect(m_engineView->root(), SIGNAL(refreshEngines()),
+ this, SLOT(queryEngines()));
+
+ layout->addWidget(m_engineView);
+
+
+ m_text = new QLineEdit(this);
+ layout->addWidget(m_text);
+
+ QPushButton *query = new QPushButton("Fetch object", this);
+ QObject::connect(query, SIGNAL(clicked()), this, SLOT(fetchClicked()));
+ layout->addWidget(query);
+
+ layout->addStretch(10);
+}
+
+void EnginePane::engineSelected(int id)
+{
+ qWarning() << "Engine selected" << id;
+ queryContext(id);
+}
+
+void EnginePane::queryContext(int id)
+{
+ if (m_context) {
+ delete m_context;
+ m_context = 0;
+ }
+
+ m_context = m_client.queryRootContexts(QmlDebugEngineReference(id), this);
+ if (!m_context->isWaiting())
+ contextChanged();
+ else
+ QObject::connect(m_context, SIGNAL(stateChanged(State)),
+ this, SLOT(contextChanged()));
+}
+
+void EnginePane::contextChanged()
+{
+ dump(m_context->rootContext(), 0);
+ delete m_context; m_context = 0;
+}
+
+void EnginePane::dump(const QmlDebugContextReference &ctxt, int ind)
+{
+ QByteArray indent(ind * 4, ' ');
+ qWarning().nospace() << indent.constData() << ctxt.debugId() << " "
+ << qPrintable(ctxt.name());
+
+ for (int ii = 0; ii < ctxt.contexts().count(); ++ii)
+ dump(ctxt.contexts().at(ii), ind + 1);
+
+ for (int ii = 0; ii < ctxt.objects().count(); ++ii)
+ dump(ctxt.objects().at(ii), ind);
+}
+
+void EnginePane::dump(const QmlDebugObjectReference &obj, int ind)
+{
+ QByteArray indent(ind * 4, ' ');
+ qWarning().nospace() << indent.constData() << qPrintable(obj.className())
+ << " " << qPrintable(obj.name()) << " "
+ << obj.debugId();
+
+ for (int ii = 0; ii < obj.children().count(); ++ii)
+ dump(obj.children().at(ii), ind + 1);
+}
+
+void EnginePane::queryEngines()
+{
+ if (m_engines)
+ return;
+
+ m_engines = m_client.queryAvailableEngines(this);
+ if (!m_engines->isWaiting())
+ enginesChanged();
+ else
+ QObject::connect(m_engines, SIGNAL(stateChanged(State)),
+ this, SLOT(enginesChanged()));
+}
+
+void EnginePane::enginesChanged()
+{
+ qDeleteAll(m_engineItems);
+ m_engineItems.clear();
+
+ QList<QmlDebugEngineReference> engines = m_engines->engines();
+ delete m_engines; m_engines = 0;
+
+ for (int ii = 0; ii < engines.count(); ++ii)
+ m_engineItems << new DebuggerEngineItem(engines.at(ii).name(),
+ engines.at(ii).debugId());
+
+ m_engineView->rootContext()->setContextProperty("engines", qVariantFromValue(&m_engineItems));
+}
+
+void EnginePane::fetchClicked()
+{
+ int id = m_text->text().toInt();
+ fetchObject(id);
+}
+
+void EnginePane::fetchObject(int id)
+{
+ if (m_object) {
+ delete m_object;
+ m_object = 0;
+ }
+
+ m_object = m_client.queryObjectRecursive(QmlDebugObjectReference(id), this);
+ if (!m_object->isWaiting())
+ objectFetched();
+ else
+ QObject::connect(m_object, SIGNAL(stateChanged(State)),
+ this, SLOT(objectFetched()));
+}
+
+void EnginePane::objectFetched()
+{
+ dump(m_object->object(), 0);
+ delete m_object; m_object = 0;
+}
+
+
+#include "engine.moc"
+
+QT_END_NAMESPACE
+
diff --git a/tools/qmldebugger/engine.h b/tools/qmldebugger/engine.h
new file mode 100644
index 0000000..191cd1d
--- /dev/null
+++ b/tools/qmldebugger/engine.h
@@ -0,0 +1,52 @@
+#ifndef ENGINE_H
+#define ENGINE_H
+
+#include <QWidget>
+#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlcontext.h>
+#include <QtDeclarative/qfxview.h>
+#include <QtDeclarative/qmldebug.h>
+
+QT_BEGIN_NAMESPACE
+
+class QmlDebugClient;
+class EngineClientPlugin;
+class QLineEdit;
+class EnginePane : public QWidget
+{
+Q_OBJECT
+public:
+ EnginePane(QmlDebugClient *, QWidget *parent = 0);
+
+private slots:
+ void queryEngines();
+ void enginesChanged();
+
+ void queryContext(int);
+ void contextChanged();
+
+ void fetchClicked();
+ void fetchObject(int);
+ void objectFetched();
+
+ void engineSelected(int);
+
+private:
+ void dump(const QmlDebugContextReference &, int);
+ void dump(const QmlDebugObjectReference &, int);
+
+ QmlEngineDebug m_client;
+ QmlDebugEnginesQuery *m_engines;
+ QmlDebugRootContextQuery *m_context;
+ QmlDebugObjectQuery *m_object;
+
+ QLineEdit *m_text;
+
+ QFxView *m_engineView;
+ QList<QObject *> m_engineItems;
+};
+
+QT_END_NAMESPACE
+
+#endif // ENGINE_H
+
diff --git a/tools/qmldebugger/main.cpp b/tools/qmldebugger/main.cpp
index 5b94cbb..4bed41d 100644
--- a/tools/qmldebugger/main.cpp
+++ b/tools/qmldebugger/main.cpp
@@ -9,6 +9,7 @@
#include <QtCore/qdatastream.h>
#include "canvasframerate.h"
#include "canvasscene.h"
+#include "engine.h"
#include <QVBoxLayout>
#include <QPushButton>
#include <QLineEdit>
@@ -77,6 +78,9 @@ Shell::Shell(QWidget *parent)
CanvasScene *cs = new CanvasScene(&client, this);
tabs->addTab(cs, tr("Scene"));
+ EnginePane *ep = new EnginePane(&client, this);
+ tabs->addTab(ep, tr("QML Engine"));
+
QObject::connect(&client, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(connectionStateChanged()));
connectionStateChanged();
}
diff --git a/tools/qmldebugger/qmldebugger.pro b/tools/qmldebugger/qmldebugger.pro
index 358dbae..1068858 100644
--- a/tools/qmldebugger/qmldebugger.pro
+++ b/tools/qmldebugger/qmldebugger.pro
@@ -3,8 +3,8 @@ QT += network declarative
contains(QT_CONFIG, opengles2)|contains(QT_CONFIG, opengles1): QT += opengl
# Input
-HEADERS += canvasframerate.h canvasscene.h
-SOURCES += main.cpp canvasframerate.cpp canvasscene.cpp
+HEADERS += canvasframerate.h canvasscene.h engine.h
+SOURCES += main.cpp canvasframerate.cpp canvasscene.cpp engine.cpp
target.path=$$[QT_INSTALL_BINS]
INSTALLS += target