summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristiaan Janssen <christiaan.janssen@digia.com>2013-06-06 16:14:37 +0200
committerKai Koehne <kai.koehne@digia.com>2013-06-11 14:42:50 +0300
commit89f7206fea7d18d621779e0aba30d390f196e374 (patch)
tree9bf518a68c301fc945884bc154883fce018bb866
parente96414023748a03f63a88886b163177a7a862946 (diff)
downloadqt-creator-89f7206fea7d18d621779e0aba30d390f196e374.tar.gz
Import QmlDebug library
Change-Id: Ia714aa86537aa0bdabc098cb4bee3d08abe93723 Reviewed-by: Kai Koehne <kai.koehne@digia.com>
-rw-r--r--libs/qmldebug/baseenginedebugclient.cpp451
-rw-r--r--libs/qmldebug/baseenginedebugclient.h268
-rw-r--r--libs/qmldebug/basetoolsclient.cpp54
-rw-r--r--libs/qmldebug/basetoolsclient.h102
-rw-r--r--libs/qmldebug/declarativeenginedebugclient.cpp107
-rw-r--r--libs/qmldebug/declarativeenginedebugclient.h59
-rw-r--r--libs/qmldebug/declarativeenginedebugclientv2.h51
-rw-r--r--libs/qmldebug/declarativetoolsclient.cpp543
-rw-r--r--libs/qmldebug/declarativetoolsclient.h85
-rw-r--r--libs/qmldebug/qdebugmessageclient.cpp71
-rw-r--r--libs/qmldebug/qdebugmessageclient.h70
-rw-r--r--libs/qmldebug/qmldebug-lib.pri40
-rw-r--r--libs/qmldebug/qmldebug.pro8
-rw-r--r--libs/qmldebug/qmldebug.qbs43
-rw-r--r--libs/qmldebug/qmldebug_dependencies.pri1
-rw-r--r--libs/qmldebug/qmldebug_global.h41
-rw-r--r--libs/qmldebug/qmldebugclient.cpp414
-rw-r--r--libs/qmldebug/qmldebugclient.h110
-rw-r--r--libs/qmldebug/qmldebugconstants.h48
-rw-r--r--libs/qmldebug/qmlenginedebugclient.h51
-rw-r--r--libs/qmldebug/qmloutputparser.cpp113
-rw-r--r--libs/qmldebug/qmloutputparser.h62
-rw-r--r--libs/qmldebug/qmlprofilereventlocation.h50
-rw-r--r--libs/qmldebug/qmlprofilereventtypes.h67
-rw-r--r--libs/qmldebug/qmlprofilertraceclient.cpp264
-rw-r--r--libs/qmldebug/qmlprofilertraceclient.h117
-rw-r--r--libs/qmldebug/qmltoolsclient.cpp348
-rw-r--r--libs/qmldebug/qmltoolsclient.h89
-rw-r--r--libs/qmldebug/qpacketprotocol.cpp541
-rw-r--r--libs/qmldebug/qpacketprotocol.h112
-rw-r--r--libs/qmldebug/qv8profilerclient.cpp157
-rw-r--r--libs/qmldebug/qv8profilerclient.h93
-rw-r--r--qtcreatorlibrary.pri7
33 files changed, 4637 insertions, 0 deletions
diff --git a/libs/qmldebug/baseenginedebugclient.cpp b/libs/qmldebug/baseenginedebugclient.cpp
new file mode 100644
index 0000000000..6e47669214
--- /dev/null
+++ b/libs/qmldebug/baseenginedebugclient.cpp
@@ -0,0 +1,451 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "baseenginedebugclient.h"
+#include "qmldebugconstants.h"
+
+namespace QmlDebug {
+
+struct QmlObjectData {
+ QUrl url;
+ int lineNumber;
+ int columnNumber;
+ QString idString;
+ QString objectName;
+ QString objectType;
+ int objectId;
+ int contextId;
+};
+
+QDataStream &operator>>(QDataStream &ds, QmlObjectData &data)
+{
+ ds >> data.url >> data.lineNumber >> data.columnNumber >> data.idString
+ >> data.objectName >> data.objectType >> data.objectId >> data.contextId;
+ return ds;
+}
+
+struct QmlObjectProperty {
+ enum Type { Unknown, Basic, Object, List, SignalProperty, Variant };
+ Type type;
+ QString name;
+ QVariant value;
+ QString valueTypeName;
+ QString binding;
+ bool hasNotifySignal;
+};
+
+QDataStream &operator>>(QDataStream &ds, QmlObjectProperty &data)
+{
+ int type;
+ ds >> type >> data.name >> data.value >> data.valueTypeName
+ >> data.binding >> data.hasNotifySignal;
+ data.type = (QmlObjectProperty::Type)type;
+ return ds;
+}
+
+void BaseEngineDebugClient::decode(QDataStream &ds,
+ ObjectReference &o,
+ bool simple)
+{
+ QmlObjectData data;
+ ds >> data;
+ int parentId = -1;
+ // qt > 4.8.3
+ if (objectName() != QLatin1String(Constants::QDECLARATIVE_ENGINE))
+ ds >> parentId;
+ o.m_debugId = data.objectId;
+ o.m_className = data.objectType;
+ o.m_idString = data.idString;
+ 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;
+ o.m_contextDebugId = data.contextId;
+ o.m_needsMoreData = simple;
+ o.m_parentId = parentId;
+
+ if (simple)
+ return;
+
+ int childCount;
+ bool recur;
+ ds >> childCount >> recur;
+
+ for (int ii = 0; ii < childCount; ++ii) {
+ o.m_children.append(ObjectReference());
+ decode(ds, o.m_children.last(), !recur);
+ }
+
+ int propCount;
+ ds >> propCount;
+
+ for (int ii = 0; ii < propCount; ++ii) {
+ QmlObjectProperty data;
+ ds >> data;
+ PropertyReference prop;
+ prop.m_objectDebugId = o.m_debugId;
+ prop.m_name = data.name;
+ prop.m_binding = data.binding;
+ prop.m_hasNotifySignal = data.hasNotifySignal;
+ prop.m_valueTypeName = data.valueTypeName;
+ switch (data.type) {
+ case QmlObjectProperty::Basic:
+ case QmlObjectProperty::List:
+ case QmlObjectProperty::SignalProperty:
+ case QmlObjectProperty::Variant:
+ {
+ prop.m_value = data.value;
+ break;
+ }
+ case QmlObjectProperty::Object:
+ {
+ ObjectReference obj;
+ obj.m_debugId = prop.m_value.toInt();
+ prop.m_value = qVariantFromValue(obj);
+ break;
+ }
+ case QmlObjectProperty::Unknown:
+ break;
+ }
+ o.m_properties << prop;
+ }
+}
+
+void BaseEngineDebugClient::decode(QDataStream &ds,
+ QVariantList &o,
+ bool simple)
+{
+ int count;
+ ds >> count;
+ for (int i = 0; i < count; i++) {
+ ObjectReference obj;
+ decode(ds, obj, simple);
+ o << QVariant::fromValue(obj);
+ }
+}
+
+void BaseEngineDebugClient::decode(QDataStream &ds,
+ ContextReference &c)
+{
+ ds >> c.m_name >> c.m_debugId;
+
+ int contextCount;
+ ds >> contextCount;
+
+ for (int ii = 0; ii < contextCount; ++ii) {
+ c.m_contexts.append(ContextReference());
+ decode(ds, c.m_contexts.last());
+ }
+
+ int objectCount;
+ ds >> objectCount;
+
+ for (int ii = 0; ii < objectCount; ++ii) {
+ ObjectReference obj;
+ decode(ds, obj, true);
+ obj.m_contextDebugId = c.m_debugId;
+ c.m_objects << obj;
+ }
+}
+
+void BaseEngineDebugClient::statusChanged(ClientStatus status)
+{
+ emit newStatus(status);
+}
+
+void BaseEngineDebugClient::messageReceived(const QByteArray &data)
+{
+ QDataStream ds(data);
+ int queryId;
+ QByteArray type;
+ ds >> type >> queryId;
+
+ if (type == "OBJECT_CREATED") {
+ int engineId;
+ int objectId;
+ int parentId;
+ ds >> engineId >> objectId >> parentId;
+ emit newObject(engineId, objectId, parentId);
+ } else if (type == "LIST_ENGINES_R") {
+ int count;
+ ds >> count;
+ QList<EngineReference> engines;
+ for (int ii = 0; ii < count; ++ii) {
+ EngineReference eng;
+ ds >> eng.m_name;
+ ds >> eng.m_debugId;
+ engines << eng;
+ }
+ emit result(queryId, QVariant::fromValue(engines), type);
+ } else if (type == "LIST_OBJECTS_R") {
+ ContextReference rootContext;
+ if (!ds.atEnd())
+ decode(ds, rootContext);
+ emit result(queryId, QVariant::fromValue(rootContext), type);
+ } else if (type == "FETCH_OBJECT_R") {
+ ObjectReference object;
+ if (!ds.atEnd())
+ decode(ds, object, false);
+ emit result(queryId, QVariant::fromValue(object), type);
+ } else if (type == "FETCH_OBJECTS_FOR_LOCATION_R") {
+ QVariantList objects;
+ if (!ds.atEnd())
+ decode(ds, objects, false);
+ emit result(queryId, objects, type);
+ } else if (type == "EVAL_EXPRESSION_R") {;
+ QVariant exprResult;
+ ds >> exprResult;
+ emit result(queryId, exprResult, type);
+ } else if (type == "WATCH_PROPERTY_R" ||
+ type == "WATCH_OBJECT_R" ||
+ type == "WATCH_EXPR_OBJECT_R" ||
+ type == "SET_BINDING_R" ||
+ type == "RESET_BINDING_R" ||
+ type == "SET_METHOD_BODY_R") {
+ bool valid;
+ ds >> valid;
+ emit result(queryId, valid, type);
+ } else if (type == "UPDATE_WATCH") {
+ int debugId;
+ QByteArray name;
+ QVariant value;
+ ds >> debugId >> name >> value;
+ emit valueChanged(debugId, name, value);
+ }
+}
+
+BaseEngineDebugClient::BaseEngineDebugClient(const QString &clientName,
+ QmlDebugConnection *conn)
+ : QmlDebugClient(clientName, conn),
+ m_nextId(1)
+{
+ setObjectName(clientName);
+}
+
+quint32 BaseEngineDebugClient::addWatch(const PropertyReference &property)
+{
+ quint32 id = 0;
+ if (status() == Enabled) {
+ id = getId();
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("WATCH_PROPERTY") << id << property.m_objectDebugId
+ << property.m_name.toUtf8();
+ sendMessage(message);
+ }
+ return id;
+}
+
+quint32 BaseEngineDebugClient::addWatch(const ContextReference &/*context*/,
+ const QString &/*id*/)
+{
+ qWarning("QmlEngineDebugClient::addWatch(): Not implemented");
+ return 0;
+}
+
+quint32 BaseEngineDebugClient::addWatch(const ObjectReference &object,
+ const QString &expr)
+{
+ quint32 id = 0;
+ if (status() == Enabled) {
+ id = getId();
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("WATCH_EXPR_OBJECT") << id << object.m_debugId << expr;
+ sendMessage(message);
+ }
+ return id;
+}
+
+quint32 BaseEngineDebugClient::addWatch(int objectDebugId)
+{
+ quint32 id = 0;
+ if (status() == Enabled) {
+ id = getId();
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("WATCH_OBJECT") << id << objectDebugId;
+ sendMessage(message);
+ }
+ return id;
+}
+
+quint32 BaseEngineDebugClient::addWatch(const FileReference &/*file*/)
+{
+ qWarning("QmlEngineDebugClient::addWatch(): Not implemented");
+ return 0;
+}
+
+void BaseEngineDebugClient::removeWatch(quint32 id)
+{
+ if (status() == Enabled) {
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("NO_WATCH") << id;
+ sendMessage(message);
+ }
+}
+
+quint32 BaseEngineDebugClient::queryAvailableEngines()
+{
+ quint32 id = 0;
+ if (status() == Enabled) {
+ id = getId();
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("LIST_ENGINES") << id;
+ sendMessage(message);
+ }
+ return id;
+}
+
+quint32 BaseEngineDebugClient::queryRootContexts(const EngineReference &engine)
+{
+ quint32 id = 0;
+ if (status() == Enabled && engine.m_debugId != -1) {
+ id = getId();
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("LIST_OBJECTS") << id << engine.m_debugId;
+ sendMessage(message);
+ }
+ return id;
+}
+
+quint32 BaseEngineDebugClient::queryObject(int objectId)
+{
+ quint32 id = 0;
+ if (status() == Enabled && objectId != -1) {
+ id = getId();
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("FETCH_OBJECT") << id << objectId << false <<
+ true;
+ sendMessage(message);
+ }
+ return id;
+}
+
+quint32 BaseEngineDebugClient::queryObjectRecursive(int objectId)
+{
+ quint32 id = 0;
+ if (status() == Enabled && objectId != -1) {
+ id = getId();
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("FETCH_OBJECT") << id << objectId << true <<
+ true;
+ sendMessage(message);
+ }
+ return id;
+}
+
+quint32 BaseEngineDebugClient::queryExpressionResult(int objectDebugId,
+ const QString &expr,
+ int engineId)
+{
+ quint32 id = 0;
+ if (status() == Enabled && objectDebugId != -1) {
+ id = getId();
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("EVAL_EXPRESSION") << id << objectDebugId << expr
+ << engineId;
+ sendMessage(message);
+ }
+ return id;
+}
+
+quint32 BaseEngineDebugClient::setBindingForObject(
+ int objectDebugId,
+ const QString &propertyName,
+ const QVariant &bindingExpression,
+ bool isLiteralValue,
+ QString source, int line)
+{
+ quint32 id = 0;
+ if (status() == Enabled && objectDebugId != -1) {
+ id = getId();
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("SET_BINDING") << id << objectDebugId << propertyName
+ << bindingExpression << isLiteralValue << source << line;
+ sendMessage(message);
+ }
+ return id;
+}
+
+quint32 BaseEngineDebugClient::resetBindingForObject(
+ int objectDebugId,
+ const QString &propertyName)
+{
+ quint32 id = 0;
+ if (status() == Enabled && objectDebugId != -1) {
+ id = getId();
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("RESET_BINDING") << id << objectDebugId << propertyName;
+ sendMessage(message);
+ }
+ return id;
+}
+
+quint32 BaseEngineDebugClient::setMethodBody(
+ int objectDebugId, const QString &methodName,
+ const QString &methodBody)
+{
+ quint32 id = 0;
+ if (status() == Enabled && objectDebugId != -1) {
+ id = getId();
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("SET_METHOD_BODY") << id << objectDebugId
+ << methodName << methodBody;
+ sendMessage(message);
+ }
+ return id;
+}
+
+quint32 BaseEngineDebugClient::queryObjectsForLocation(
+ const QString &fileName, int lineNumber, int columnNumber)
+{
+ quint32 id = 0;
+ if (status() == Enabled) {
+ id = getId();
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("FETCH_OBJECTS_FOR_LOCATION") << id <<
+ fileName << lineNumber << columnNumber << false <<
+ true;
+ sendMessage(message);
+ }
+ return id;
+}
+
+} // namespace QmlDebug
diff --git a/libs/qmldebug/baseenginedebugclient.h b/libs/qmldebug/baseenginedebugclient.h
new file mode 100644
index 0000000000..b4a39090c4
--- /dev/null
+++ b/libs/qmldebug/baseenginedebugclient.h
@@ -0,0 +1,268 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef BASEENGINEDEBUGCLIENT_H
+#define BASEENGINEDEBUGCLIENT_H
+
+#include "qmldebug_global.h"
+#include "qmldebugclient.h"
+#include <qurl.h>
+#include <qvariant.h>
+
+namespace QmlDebug {
+
+class QmlDebugConnection;
+class PropertyReference;
+class ContextReference;
+class ObjectReference;
+class FileReference;
+class EngineReference;
+
+class QMLDEBUG_EXPORT BaseEngineDebugClient : public QmlDebugClient
+{
+ Q_OBJECT
+public:
+ BaseEngineDebugClient(const QString &clientName,
+ QmlDebugConnection *conn);
+
+ quint32 addWatch(const PropertyReference &property);
+ quint32 addWatch(const ContextReference &context, const QString &id);
+ quint32 addWatch(const ObjectReference &object, const QString &expr);
+ quint32 addWatch(int objectDebugId);
+ quint32 addWatch(const FileReference &file);
+
+ void removeWatch(quint32 watch);
+
+ quint32 queryAvailableEngines();
+ quint32 queryRootContexts(const EngineReference &context);
+ quint32 queryObject(int objectId);
+ quint32 queryObjectRecursive(int objectId);
+ quint32 queryExpressionResult(int objectDebugId,
+ const QString &expr, int engineId = -1);
+ virtual quint32 setBindingForObject(int objectDebugId, const QString &propertyName,
+ const QVariant &bindingExpression,
+ bool isLiteralValue,
+ QString source, int line);
+ virtual quint32 resetBindingForObject(int objectDebugId,
+ const QString &propertyName);
+ virtual quint32 setMethodBody(int objectDebugId, const QString &methodName,
+ const QString &methodBody);
+
+ virtual quint32 queryObjectsForLocation(const QString &fileName, int lineNumber,
+ int columnNumber);
+
+signals:
+ void newStatus(QmlDebug::ClientStatus status);
+ void newObject(int engineId, int objectId, int parentId);
+ void valueChanged(int debugId, const QByteArray &name,
+ const QVariant &value);
+ void result(quint32 queryId, const QVariant &result, const QByteArray &type);
+
+protected:
+ virtual void statusChanged(ClientStatus status);
+ virtual void messageReceived(const QByteArray &);
+
+ quint32 getId() { return m_nextId++; }
+
+ void decode(QDataStream &d, ContextReference &context);
+ void decode(QDataStream &d, ObjectReference &object, bool simple);
+ void decode(QDataStream &d, QVariantList &object, bool simple);
+
+private:
+ quint32 m_nextId;
+};
+
+class FileReference
+{
+public:
+ FileReference() : m_lineNumber(-1), m_columnNumber(-1) {}
+ FileReference(const QUrl &url, int line, int column)
+ : m_url(url),
+ m_lineNumber(line),
+ m_columnNumber(column)
+ {
+ }
+
+ QUrl url() const { return m_url; }
+ int lineNumber() const { return m_lineNumber; }
+ int columnNumber() const { return m_columnNumber; }
+
+private:
+ friend class BaseEngineDebugClient;
+ QUrl m_url;
+ int m_lineNumber;
+ int m_columnNumber;
+};
+
+class EngineReference
+{
+public:
+ EngineReference() : m_debugId(-1) {}
+ explicit EngineReference(int id) : m_debugId(id) {}
+
+ int debugId() const { return m_debugId; }
+ QString name() const { return m_name; }
+
+private:
+ friend class BaseEngineDebugClient;
+ int m_debugId;
+ QString m_name;
+};
+
+class ObjectReference
+{
+public:
+ ObjectReference()
+ : m_debugId(-1), m_parentId(-1), m_contextDebugId(-1), m_needsMoreData(false)
+ {
+ }
+ explicit ObjectReference(int id)
+ : m_debugId(id), m_parentId(-1), m_contextDebugId(-1), m_needsMoreData(false)
+ {
+ }
+ ObjectReference(int id, int parentId, const FileReference &source)
+ : m_debugId(id), m_parentId(parentId), m_source(source),
+ m_contextDebugId(-1), m_needsMoreData(false)
+ {
+ }
+
+ int debugId() const { return m_debugId; }
+ int parentId() const { return m_parentId; }
+ QString className() const { return m_className; }
+ QString idString() const { return m_idString; }
+ QString name() const { return m_name; }
+ bool isValid() const { return m_debugId != -1; }
+
+ FileReference source() const { return m_source; }
+ int contextDebugId() const { return m_contextDebugId; }
+ bool needsMoreData() const { return m_needsMoreData; }
+
+ QList<PropertyReference> properties() const { return m_properties; }
+ QList<ObjectReference> children() const { return m_children; }
+
+ int insertObjectInTree(const ObjectReference &obj)
+ {
+ for (int i = 0; i < m_children.count(); i++) {
+ if (m_children[i].debugId() == obj.debugId()) {
+ m_children.replace(i, obj);
+ return debugId();
+ } else {
+ if (m_children[i].insertObjectInTree(obj))
+ return debugId();
+ }
+ }
+ return -1;
+ }
+
+ bool operator ==(const ObjectReference &obj) const
+ {
+ return m_debugId == obj.debugId();
+ }
+
+private:
+ friend class BaseEngineDebugClient;
+ int m_debugId;
+ int m_parentId;
+ QString m_className;
+ QString m_idString;
+ QString m_name;
+ FileReference m_source;
+ int m_contextDebugId;
+ bool m_needsMoreData;
+ QList<PropertyReference> m_properties;
+ QList<ObjectReference> m_children;
+};
+
+class ContextReference
+{
+public:
+ ContextReference() : m_debugId(-1) {}
+
+ int debugId() const { return m_debugId; }
+ QString name() const { return m_name; }
+
+ QList<ObjectReference> objects() const { return m_objects; }
+ QList<ContextReference> contexts() const { return m_contexts; }
+
+private:
+ friend class BaseEngineDebugClient;
+ int m_debugId;
+ QString m_name;
+ QList<ObjectReference> m_objects;
+ QList<ContextReference> m_contexts;
+};
+
+class PropertyReference
+{
+public:
+ PropertyReference() : m_objectDebugId(-1), m_hasNotifySignal(false) {}
+
+ int debugId() const { return m_objectDebugId; }
+ QString name() const { return m_name; }
+ QVariant value() const { return m_value; }
+ QString valueTypeName() const { return m_valueTypeName; }
+ QString binding() const { return m_binding; }
+ bool hasNotifySignal() const { return m_hasNotifySignal; }
+
+private:
+ friend class BaseEngineDebugClient;
+ int m_objectDebugId;
+ QString m_name;
+ QVariant m_value;
+ QString m_valueTypeName;
+ QString m_binding;
+ bool m_hasNotifySignal;
+};
+
+} // namespace QmlDebug
+
+Q_DECLARE_METATYPE(QmlDebug::ObjectReference)
+Q_DECLARE_METATYPE(QmlDebug::EngineReference)
+Q_DECLARE_METATYPE(QList<QmlDebug::EngineReference>)
+Q_DECLARE_METATYPE(QmlDebug::ContextReference)
+
+QT_BEGIN_NAMESPACE
+inline QDebug operator<<(QDebug dbg, const QmlDebug::EngineReference &ref) {
+ dbg.nospace() << "(Engine " << ref.debugId() << "/" << ref.name() << ")";
+ return dbg.space();
+}
+
+inline QDebug operator<<(QDebug dbg, const QmlDebug::ContextReference &ref) {
+ dbg.nospace() << "(Context " << ref.debugId() << "/" << ref.name() << ")";
+ return dbg.space();
+}
+
+inline QDebug operator<<(QDebug dbg, const QmlDebug::ObjectReference &ref) {
+ dbg.nospace() << "(Object " << ref.debugId() << "/"
+ << (ref.idString().isEmpty() ? ref.idString() : ref.className()) << ")";
+ return dbg.space();
+}
+QT_END_NAMESPACE
+
+#endif // BASEENGINEDEBUGCLIENT_H
diff --git a/libs/qmldebug/basetoolsclient.cpp b/libs/qmldebug/basetoolsclient.cpp
new file mode 100644
index 0000000000..351a351e8a
--- /dev/null
+++ b/libs/qmldebug/basetoolsclient.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "basetoolsclient.h"
+
+namespace QmlDebug {
+
+BaseToolsClient::BaseToolsClient(QmlDebugConnection* client, QLatin1String clientName)
+ : QmlDebugClient(clientName, client)
+{
+ setObjectName(clientName);
+}
+
+void BaseToolsClient::statusChanged(ClientStatus status)
+{
+ emit newStatus(status);
+}
+
+void BaseToolsClient::recurseObjectIdList(const ObjectReference &ref,
+ QList<int> &debugIds, QList<QString> &objectIds)
+{
+ debugIds << ref.debugId();
+ objectIds << ref.idString();
+ foreach (const ObjectReference &child, ref.children())
+ recurseObjectIdList(child, debugIds, objectIds);
+}
+
+} // namespace QmlDebug
diff --git a/libs/qmldebug/basetoolsclient.h b/libs/qmldebug/basetoolsclient.h
new file mode 100644
index 0000000000..9342118f5a
--- /dev/null
+++ b/libs/qmldebug/basetoolsclient.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef BASETOOLSCLIENT_H
+#define BASETOOLSCLIENT_H
+
+#include "qmldebugclient.h"
+#include "baseenginedebugclient.h"
+
+namespace QmlDebug {
+
+class QMLDEBUG_EXPORT BaseToolsClient : public QmlDebugClient
+{
+ Q_OBJECT
+public:
+ BaseToolsClient(QmlDebugConnection *client, QLatin1String clientName);
+
+ virtual void setCurrentObjects(const QList<int> &debugIds) = 0;
+ virtual void reload(const QHash<QString, QByteArray> &changesHash) = 0;
+ virtual bool supportReload() const = 0;
+ virtual void setDesignModeBehavior(bool inDesignMode) = 0;
+ virtual void setAnimationSpeed(qreal slowDownFactor) = 0;
+ virtual void setAnimationPaused(bool paused) = 0;
+ virtual void changeToSelectTool() = 0;
+ virtual void changeToSelectMarqueeTool() = 0;
+ virtual void changeToZoomTool() = 0;
+ virtual void showAppOnTop(bool showOnTop) = 0;
+
+ virtual void createQmlObject(const QString &qmlText, int parentDebugId,
+ const QStringList &imports, const QString &filename,
+ int order) = 0;
+ virtual void destroyQmlObject(int debugId) = 0;
+ virtual void reparentQmlObject(int debugId, int newParent) = 0;
+
+ virtual void applyChangesToQmlFile() = 0;
+ virtual void applyChangesFromQmlFile() = 0;
+
+ virtual QList<int> currentObjects() const = 0;
+
+ // ### Qt 4.8: remove if we can have access to qdeclarativecontextdata or id's
+ virtual void setObjectIdList(
+ const QList<ObjectReference> &objectRoots) = 0;
+
+ virtual void clearComponentCache() = 0;
+
+signals:
+ void newStatus(QmlDebug::ClientStatus status);
+
+ void currentObjectsChanged(const QList<int> &debugIds);
+ void selectToolActivated();
+ void selectMarqueeToolActivated();
+ void zoomToolActivated();
+ void animationSpeedChanged(qreal slowdownFactor);
+ void animationPausedChanged(bool paused);
+ void designModeBehaviorChanged(bool inDesignMode);
+ void showAppOnTopChanged(bool showAppOnTop);
+ void reloaded(); // the server has reloaded the document
+ void destroyedObject(int);
+
+ void logActivity(QString client, QString message);
+
+protected:
+ void statusChanged(ClientStatus status);
+
+ void recurseObjectIdList(const ObjectReference &ref,
+ QList<int> &debugIds, QList<QString> &objectIds);
+protected:
+ enum LogDirection {
+ LogSend,
+ LogReceive
+ };
+};
+
+} // namespace QmlDebug
+
+#endif // BASETOOLSCLIENT_H
diff --git a/libs/qmldebug/declarativeenginedebugclient.cpp b/libs/qmldebug/declarativeenginedebugclient.cpp
new file mode 100644
index 0000000000..662e32d03b
--- /dev/null
+++ b/libs/qmldebug/declarativeenginedebugclient.cpp
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "declarativeenginedebugclient.h"
+#include "qmldebugconstants.h"
+
+namespace QmlDebug {
+
+DeclarativeEngineDebugClient::DeclarativeEngineDebugClient(
+ QmlDebugConnection *connection)
+ : BaseEngineDebugClient(QLatin1String(Constants::QDECLARATIVE_ENGINE), connection)
+{
+}
+
+quint32 DeclarativeEngineDebugClient::setBindingForObject(
+ int objectDebugId,
+ const QString &propertyName,
+ const QVariant &bindingExpression,
+ bool isLiteralValue,
+ QString source, int line)
+{
+ quint32 id = 0;
+ if (status() == Enabled && objectDebugId != -1) {
+ id = getId();
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("SET_BINDING") << objectDebugId << propertyName
+ << bindingExpression << isLiteralValue << source << line;
+ sendMessage(message);
+ }
+ return id;
+}
+
+quint32 DeclarativeEngineDebugClient::resetBindingForObject(
+ int objectDebugId,
+ const QString &propertyName)
+{
+ quint32 id = 0;
+ if (status() == Enabled && objectDebugId != -1) {
+ id = getId();
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("RESET_BINDING") << objectDebugId << propertyName;
+ sendMessage(message);
+ }
+ return id;
+}
+
+quint32 DeclarativeEngineDebugClient::setMethodBody(
+ int objectDebugId, const QString &methodName,
+ const QString &methodBody)
+{
+ quint32 id = 0;
+ if (status() == Enabled && objectDebugId != -1) {
+ id = getId();
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray("SET_METHOD_BODY") << objectDebugId
+ << methodName << methodBody;
+ sendMessage(message);
+ }
+ return id;
+}
+
+void DeclarativeEngineDebugClient::messageReceived(const QByteArray &data)
+{
+ QDataStream ds(data);
+ QByteArray type;
+ ds >> type;
+
+ if (type == "OBJECT_CREATED") {
+ int engineId;
+ int objectId;
+ ds >> engineId >> objectId;
+ emit newObject(engineId, objectId, -1);
+ return;
+ } else {
+ BaseEngineDebugClient::messageReceived(data);
+ }
+}
+} // namespace QmlDebug
diff --git a/libs/qmldebug/declarativeenginedebugclient.h b/libs/qmldebug/declarativeenginedebugclient.h
new file mode 100644
index 0000000000..3dc9102547
--- /dev/null
+++ b/libs/qmldebug/declarativeenginedebugclient.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef DECLARATIVEENGINEDEBUGCLIENT_H
+#define DECLARATIVEENGINEDEBUGCLIENT_H
+
+#include "baseenginedebugclient.h"
+
+namespace QmlDebug {
+
+class QmlDebugConnection;
+
+class QMLDEBUG_EXPORT DeclarativeEngineDebugClient : public BaseEngineDebugClient
+{
+ Q_OBJECT
+public:
+ explicit DeclarativeEngineDebugClient(QmlDebugConnection *conn);
+
+ quint32 setBindingForObject(int objectDebugId, const QString &propertyName,
+ const QVariant &bindingExpression,
+ bool isLiteralValue,
+ QString source, int line);
+ quint32 resetBindingForObject(int objectDebugId, const QString &propertyName);
+ quint32 setMethodBody(int objectDebugId, const QString &methodName,
+ const QString &methodBody);
+
+protected:
+ void messageReceived(const QByteArray &data);
+};
+
+} // namespace QmlDebug
+
+#endif // DECLARATIVEENGINEDEBUGCLIENT_H
diff --git a/libs/qmldebug/declarativeenginedebugclientv2.h b/libs/qmldebug/declarativeenginedebugclientv2.h
new file mode 100644
index 0000000000..aeb2ef6ee2
--- /dev/null
+++ b/libs/qmldebug/declarativeenginedebugclientv2.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef DECLARATIVEENGINEDEBUGCLIENTV2_H
+#define DECLARATIVEENGINEDEBUGCLIENTV2_H
+
+#include "baseenginedebugclient.h"
+
+namespace QmlDebug {
+
+class QmlDebugConnection;
+
+class QMLDEBUG_EXPORT DeclarativeEngineDebugClientV2 : public BaseEngineDebugClient
+{
+ Q_OBJECT
+public:
+ explicit DeclarativeEngineDebugClientV2(QmlDebugConnection *conn)
+ : BaseEngineDebugClient(QLatin1String("DeclarativeDebugger"), conn)
+ {
+ }
+};
+
+} // namespace QmlDebug
+
+#endif // DECLARATIVEENGINEDEBUGCLIENTV2_H
diff --git a/libs/qmldebug/declarativetoolsclient.cpp b/libs/qmldebug/declarativetoolsclient.cpp
new file mode 100644
index 0000000000..ba540eeb6b
--- /dev/null
+++ b/libs/qmldebug/declarativetoolsclient.cpp
@@ -0,0 +1,543 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "declarativetoolsclient.h"
+#include <QMetaEnum>
+#include <QStringList>
+
+namespace QmlDebug {
+namespace Internal {
+
+namespace Constants {
+
+enum DesignTool {
+ NoTool = 0,
+ SelectionToolMode = 1,
+ MarqueeSelectionToolMode = 2,
+ MoveToolMode = 3,
+ ResizeToolMode = 4,
+ ZoomMode = 6
+};
+
+}
+
+class InspectorProtocol : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(Message Tool)
+
+public:
+ enum Message {
+ AnimationSpeedChanged = 0,
+ AnimationPausedChanged = 19, // highest value
+ ChangeTool = 1,
+ ClearComponentCache = 2,
+ ColorChanged = 3,
+ CreateObject = 5,
+ CurrentObjectsChanged = 6,
+ DestroyObject = 7,
+ MoveObject = 8,
+ ObjectIdList = 9,
+ Reload = 10,
+ Reloaded = 11,
+ SetAnimationSpeed = 12,
+ SetAnimationPaused = 18,
+ SetCurrentObjects = 14,
+ SetDesignMode = 15,
+ ShowAppOnTop = 16,
+ ToolChanged = 17
+ };
+
+ enum Tool {
+ ColorPickerTool,
+ SelectMarqueeTool,
+ SelectTool,
+ ZoomTool
+ };
+
+ static inline QString toString(Message message)
+ {
+ return QString::fromUtf8(staticMetaObject.enumerator(0).valueToKey(message));
+ }
+
+ static inline QString toString(Tool tool)
+ {
+ return QString::fromUtf8(staticMetaObject.enumerator(1).valueToKey(tool));
+ }
+};
+
+inline QDataStream & operator<< (QDataStream &stream, InspectorProtocol::Message message)
+{
+ return stream << static_cast<quint32>(message);
+}
+
+inline QDataStream & operator>> (QDataStream &stream, InspectorProtocol::Message &message)
+{
+ quint32 i;
+ stream >> i;
+ message = static_cast<InspectorProtocol::Message>(i);
+ return stream;
+}
+
+inline QDebug operator<< (QDebug dbg, InspectorProtocol::Message message)
+{
+ dbg << InspectorProtocol::toString(message);
+ return dbg;
+}
+
+inline QDataStream & operator<< (QDataStream &stream, InspectorProtocol::Tool tool)
+{
+ return stream << static_cast<quint32>(tool);
+}
+
+inline QDataStream & operator>> (QDataStream &stream, InspectorProtocol::Tool &tool)
+{
+ quint32 i;
+ stream >> i;
+ tool = static_cast<InspectorProtocol::Tool>(i);
+ return stream;
+}
+
+inline QDebug operator<< (QDebug dbg, InspectorProtocol::Tool tool)
+{
+ dbg << InspectorProtocol::toString(tool);
+ return dbg;
+}
+
+} // internal
+
+using namespace Internal;
+
+DeclarativeToolsClient::DeclarativeToolsClient(QmlDebugConnection *client)
+ : BaseToolsClient(client,QLatin1String("QDeclarativeObserverMode")),
+ m_connection(client)
+{
+ setObjectName(name());
+}
+
+void DeclarativeToolsClient::messageReceived(const QByteArray &message)
+{
+ QDataStream ds(message);
+
+ InspectorProtocol::Message type;
+ ds >> type;
+
+ switch (type) {
+ case InspectorProtocol::CurrentObjectsChanged: {
+ int objectCount;
+ ds >> objectCount;
+
+ log(LogReceive, type, QString::fromLatin1("%1 [list of debug ids]").arg(objectCount));
+
+ m_currentDebugIds.clear();
+
+ for (int i = 0; i < objectCount; ++i) {
+ int debugId;
+ ds >> debugId;
+ if (debugId != -1)
+ m_currentDebugIds << debugId;
+ }
+
+ emit currentObjectsChanged(m_currentDebugIds);
+ break;
+ }
+ case InspectorProtocol::ToolChanged: {
+ int toolId;
+ ds >> toolId;
+
+ log(LogReceive, type, QString::number(toolId));
+
+ if (toolId == Constants::ZoomMode)
+ emit zoomToolActivated();
+ else if (toolId == Constants::SelectionToolMode)
+ emit selectToolActivated();
+ else if (toolId == Constants::MarqueeSelectionToolMode)
+ emit selectMarqueeToolActivated();
+ break;
+ }
+ case InspectorProtocol::AnimationSpeedChanged: {
+ qreal slowDownFactor;
+ ds >> slowDownFactor;
+
+ log(LogReceive, type, QString::number(slowDownFactor));
+
+ emit animationSpeedChanged(slowDownFactor);
+ break;
+ }
+ case InspectorProtocol::AnimationPausedChanged: {
+ bool paused;
+ ds >> paused;
+
+ log(LogReceive, type, paused ? QLatin1String("true")
+ : QLatin1String("false"));
+
+ emit animationPausedChanged(paused);
+ break;
+ }
+ case InspectorProtocol::SetDesignMode: {
+ bool inDesignMode;
+ ds >> inDesignMode;
+
+ log(LogReceive, type, QLatin1String(inDesignMode ? "true" : "false"));
+
+ emit designModeBehaviorChanged(inDesignMode);
+ break;
+ }
+ case InspectorProtocol::ShowAppOnTop: {
+ bool showAppOnTop;
+ ds >> showAppOnTop;
+
+ log(LogReceive, type, QLatin1String(showAppOnTop ? "true" : "false"));
+
+ emit showAppOnTopChanged(showAppOnTop);
+ break;
+ }
+ case InspectorProtocol::Reloaded: {
+ log(LogReceive, type);
+ emit reloaded();
+ break;
+ }
+ default:
+ log(LogReceive, type, QLatin1String("Warning: Not handling message"));
+ }
+}
+
+QList<int> DeclarativeToolsClient::currentObjects() const
+{
+ return m_currentDebugIds;
+}
+
+void DeclarativeToolsClient::setCurrentObjects(const QList<int> &debugIds)
+{
+ if (!m_connection || !m_connection->isConnected())
+ return;
+
+ if (debugIds == m_currentDebugIds)
+ return;
+
+ m_currentDebugIds = debugIds;
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+
+ InspectorProtocol::Message cmd = InspectorProtocol::SetCurrentObjects;
+ ds << cmd
+ << debugIds.length();
+
+ foreach (int id, debugIds) {
+ ds << id;
+ }
+
+ log(LogSend, cmd, QString::fromLatin1("%1 [list of ids]").arg(debugIds.length()));
+
+ sendMessage(message);
+}
+
+void DeclarativeToolsClient::setObjectIdList(
+ const QList<ObjectReference> &objectRoots)
+{
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+
+ QList<int> debugIds;
+ QList<QString> objectIds;
+
+ foreach (const ObjectReference &ref, objectRoots)
+ recurseObjectIdList(ref, debugIds, objectIds);
+
+ InspectorProtocol::Message cmd = InspectorProtocol::ObjectIdList;
+ ds << cmd
+ << debugIds.length();
+
+ Q_ASSERT(debugIds.length() == objectIds.length());
+
+ for (int i = 0; i < debugIds.length(); ++i) {
+ ds << debugIds[i] << objectIds[i];
+ }
+
+ log(LogSend, cmd,
+ QString::fromLatin1("%1 %2 [list of debug / object ids]").arg(debugIds.length()));
+
+ sendMessage(message);
+}
+
+void DeclarativeToolsClient::clearComponentCache()
+{
+ if (!m_connection || !m_connection->isConnected())
+ return;
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+
+ InspectorProtocol::Message cmd = InspectorProtocol::ClearComponentCache;
+ ds << cmd;
+
+ log(LogSend, cmd);
+
+ sendMessage(message);
+}
+
+void DeclarativeToolsClient::reload(const QHash<QString,
+ QByteArray> &changesHash)
+{
+ Q_UNUSED(changesHash);
+
+ if (!m_connection || !m_connection->isConnected())
+ return;
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+
+ InspectorProtocol::Message cmd = InspectorProtocol::Reload;
+ ds << cmd;
+
+ log(LogSend, cmd);
+
+ sendMessage(message);
+}
+
+void DeclarativeToolsClient::setDesignModeBehavior(bool inDesignMode)
+{
+ if (!m_connection || !m_connection->isConnected())
+ return;
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+
+ InspectorProtocol::Message cmd = InspectorProtocol::SetDesignMode;
+ ds << cmd
+ << inDesignMode;
+
+ log(LogSend, cmd, QLatin1String(inDesignMode ? "true" : "false"));
+
+ sendMessage(message);
+}
+
+void DeclarativeToolsClient::setAnimationSpeed(qreal slowDownFactor)
+{
+ if (!m_connection || !m_connection->isConnected())
+ return;
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+
+ InspectorProtocol::Message cmd = InspectorProtocol::SetAnimationSpeed;
+ ds << cmd
+ << slowDownFactor;
+
+
+ log(LogSend, cmd, QString::number(slowDownFactor));
+
+ sendMessage(message);
+}
+
+void DeclarativeToolsClient::setAnimationPaused(bool paused)
+{
+ if (!m_connection || !m_connection->isConnected())
+ return;
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+
+ InspectorProtocol::Message cmd = InspectorProtocol::SetAnimationPaused;
+ ds << cmd
+ << paused;
+
+ log(LogSend, cmd, paused ? QLatin1String("true") : QLatin1String("false"));
+
+ sendMessage(message);
+}
+
+void DeclarativeToolsClient::changeToSelectTool()
+{
+ if (!m_connection || !m_connection->isConnected())
+ return;
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+
+ InspectorProtocol::Message cmd = InspectorProtocol::ChangeTool;
+ InspectorProtocol::Tool tool = InspectorProtocol::SelectTool;
+ ds << cmd
+ << tool;
+
+ log(LogSend, cmd, InspectorProtocol::toString(tool));
+
+ sendMessage(message);
+}
+
+void DeclarativeToolsClient::changeToSelectMarqueeTool()
+{
+ if (!m_connection || !m_connection->isConnected())
+ return;
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+
+ InspectorProtocol::Message cmd = InspectorProtocol::ChangeTool;
+ InspectorProtocol::Tool tool = InspectorProtocol::SelectMarqueeTool;
+ ds << cmd
+ << tool;
+
+ log(LogSend, cmd, InspectorProtocol::toString(tool));
+
+ sendMessage(message);
+}
+
+void DeclarativeToolsClient::changeToZoomTool()
+{
+ if (!m_connection || !m_connection->isConnected())
+ return;
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+
+ InspectorProtocol::Message cmd = InspectorProtocol::ChangeTool;
+ InspectorProtocol::Tool tool = InspectorProtocol::ZoomTool;
+ ds << cmd
+ << tool;
+
+ log(LogSend, cmd, InspectorProtocol::toString(tool));
+
+ sendMessage(message);
+}
+
+void DeclarativeToolsClient::showAppOnTop(bool showOnTop)
+{
+ if (!m_connection || !m_connection->isConnected())
+ return;
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+
+ InspectorProtocol::Message cmd = InspectorProtocol::ShowAppOnTop;
+ ds << cmd << showOnTop;
+
+ log(LogSend, cmd, QLatin1String(showOnTop ? "true" : "false"));
+
+ sendMessage(message);
+}
+
+void DeclarativeToolsClient::createQmlObject(const QString &qmlText,
+ int parentDebugId,
+ const QStringList &imports,
+ const QString &filename, int order)
+{
+ if (!m_connection || !m_connection->isConnected())
+ return;
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+
+ InspectorProtocol::Message cmd = InspectorProtocol::CreateObject;
+ ds << cmd
+ << qmlText
+ << parentDebugId
+ << imports
+ << filename
+ << order;
+
+ log(LogSend, cmd, QString::fromLatin1("%1 %2 [%3] %4").arg(qmlText,
+ QString::number(parentDebugId),
+ imports.join(QLatin1String(",")), filename));
+
+ sendMessage(message);
+}
+
+void DeclarativeToolsClient::destroyQmlObject(int debugId)
+{
+ if (!m_connection || !m_connection->isConnected())
+ return;
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+
+ InspectorProtocol::Message cmd = InspectorProtocol::DestroyObject;
+ ds << cmd << debugId;
+
+ log(LogSend, cmd, QString::number(debugId));
+
+ sendMessage(message);
+}
+
+void DeclarativeToolsClient::reparentQmlObject(int debugId, int newParent)
+{
+ if (!m_connection || !m_connection->isConnected())
+ return;
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+
+ InspectorProtocol::Message cmd = InspectorProtocol::MoveObject;
+ ds << cmd
+ << debugId
+ << newParent;
+
+ log(LogSend, cmd, QString::fromLatin1("%1 %2").arg(QString::number(debugId),
+ QString::number(newParent)));
+
+ sendMessage(message);
+}
+
+
+void DeclarativeToolsClient::applyChangesToQmlFile()
+{
+ if (!m_connection || !m_connection->isConnected())
+ return;
+
+ // TODO
+}
+
+void DeclarativeToolsClient::applyChangesFromQmlFile()
+{
+ if (!m_connection || !m_connection->isConnected())
+ return;
+
+ // TODO
+}
+
+void DeclarativeToolsClient::log(LogDirection direction,
+ int message,
+ const QString &extra)
+{
+ QString msg;
+ if (direction == LogSend)
+ msg += QLatin1String("sending ");
+ else
+ msg += QLatin1String("receiving ");
+
+ InspectorProtocol::Message msgType
+ = static_cast<InspectorProtocol::Message>(message);
+ msg += InspectorProtocol::toString(msgType);
+ msg += QLatin1Char(' ');
+ msg += extra;
+ emit logActivity(name(), msg);
+}
+
+} // namespace QmlDebug
+
+#include "declarativetoolsclient.moc"
diff --git a/libs/qmldebug/declarativetoolsclient.h b/libs/qmldebug/declarativetoolsclient.h
new file mode 100644
index 0000000000..4f942639a9
--- /dev/null
+++ b/libs/qmldebug/declarativetoolsclient.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef DECLARATIVETOOLSCLIENT_H
+#define DECLARATIVETOOLSCLIENT_H
+
+#include "basetoolsclient.h"
+
+namespace QmlDebug {
+
+class QMLDEBUG_EXPORT DeclarativeToolsClient : public BaseToolsClient
+{
+ Q_OBJECT
+public:
+ DeclarativeToolsClient(QmlDebugConnection *client);
+
+ void setCurrentObjects(const QList<int> &debugIds);
+ void reload(const QHash<QString, QByteArray> &changesHash);
+ bool supportReload() const { return false; }
+ void setDesignModeBehavior(bool inDesignMode);
+ void setAnimationSpeed(qreal slowDownFactor);
+ void setAnimationPaused(bool paused);
+ void changeToSelectTool();
+ void changeToSelectMarqueeTool();
+ void changeToZoomTool();
+ void showAppOnTop(bool showOnTop);
+
+ void createQmlObject(const QString &qmlText, int parentDebugId,
+ const QStringList &imports, const QString &filename,
+ int order);
+ void destroyQmlObject(int debugId);
+ void reparentQmlObject(int debugId, int newParent);
+
+ void applyChangesToQmlFile();
+ void applyChangesFromQmlFile();
+
+ QList<int> currentObjects() const;
+
+ // ### Qt 4.8: remove if we can have access to qdeclarativecontextdata or id's
+ void setObjectIdList(const QList<ObjectReference> &objectRoots);
+
+ void clearComponentCache();
+
+protected:
+ void messageReceived(const QByteArray &);
+
+private:
+ void log(LogDirection direction,
+ int message,
+ const QString &extra = QString());
+
+private:
+ QList<int> m_currentDebugIds;
+ QmlDebugConnection *m_connection;
+};
+
+} // namespace QmlDebug
+
+#endif // DECLARATIVETOOLSCLIENT_H
diff --git a/libs/qmldebug/qdebugmessageclient.cpp b/libs/qmldebug/qdebugmessageclient.cpp
new file mode 100644
index 0000000000..8b9517bcf8
--- /dev/null
+++ b/libs/qmldebug/qdebugmessageclient.cpp
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "qdebugmessageclient.h"
+
+#include <QDataStream>
+
+namespace QmlDebug {
+
+QDebugMessageClient::QDebugMessageClient(QmlDebugConnection *client)
+ : QmlDebugClient(QLatin1String("DebugMessages"), client)
+{
+}
+
+QDebugMessageClient::~QDebugMessageClient()
+{
+}
+
+void QDebugMessageClient::statusChanged(ClientStatus status)
+{
+ emit newStatus(status);
+}
+
+void QDebugMessageClient::messageReceived(const QByteArray &data)
+{
+ QDataStream ds(data);
+ QByteArray command;
+ ds >> command;
+
+ if (command == "MESSAGE") {
+ int type;
+ int line;
+ QByteArray debugMessage;
+ QByteArray file;
+ QByteArray function;
+ ds >> type >> debugMessage >> file >> line >> function;
+ QDebugContextInfo info;
+ info.line = line;
+ info.file = QString::fromUtf8(file);
+ info.function = QString::fromUtf8(function);
+ emit message(QtMsgType(type), QString::fromUtf8(debugMessage), info);
+ }
+}
+
+} // namespace QmlDebug
diff --git a/libs/qmldebug/qdebugmessageclient.h b/libs/qmldebug/qdebugmessageclient.h
new file mode 100644
index 0000000000..60bf0769f5
--- /dev/null
+++ b/libs/qmldebug/qdebugmessageclient.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QDEBUGMESSAGECLIENT_H
+#define QDEBUGMESSAGECLIENT_H
+
+#include "qmldebugclient.h"
+#include "qmldebug_global.h"
+
+namespace QmlDebug {
+
+class QDebugMessageClientPrivate;
+struct QDebugContextInfo
+{
+ int line;
+ QString file;
+ QString function;
+};
+
+class QMLDEBUG_EXPORT QDebugMessageClient : public QmlDebugClient
+{
+ Q_OBJECT
+
+public:
+ explicit QDebugMessageClient(QmlDebugConnection *client);
+ ~QDebugMessageClient();
+
+protected:
+ virtual void statusChanged(ClientStatus status);
+ virtual void messageReceived(const QByteArray &);
+
+signals:
+ void newStatus(QmlDebug::ClientStatus);
+ void message(QtMsgType, const QString &,
+ const QmlDebug::QDebugContextInfo &);
+
+private:
+ class QDebugMessageClientPrivate *d;
+ Q_DISABLE_COPY(QDebugMessageClient)
+};
+
+} // namespace QmlDebug
+
+#endif // QDEBUGMESSAGECLIENT_H
diff --git a/libs/qmldebug/qmldebug-lib.pri b/libs/qmldebug/qmldebug-lib.pri
new file mode 100644
index 0000000000..54f09258b0
--- /dev/null
+++ b/libs/qmldebug/qmldebug-lib.pri
@@ -0,0 +1,40 @@
+contains(CONFIG, dll) {
+ DEFINES += QMLDEBUG_LIB
+} else {
+ DEFINES += QMLDEBUG_STATIC_LIB
+}
+
+INCLUDEPATH += $$PWD/..
+
+HEADERS += \
+ $$PWD/qmlprofilereventlocation.h \
+ $$PWD/qmldebugclient.h \
+ $$PWD/baseenginedebugclient.h \
+ $$PWD/declarativeenginedebugclient.h \
+ $$PWD/declarativeenginedebugclientv2.h \
+ $$PWD/qmloutputparser.h \
+ $$PWD/qmldebug_global.h \
+ $$PWD/qmlprofilereventtypes.h \
+ $$PWD/qmlprofilertraceclient.h \
+ $$PWD/qpacketprotocol.h \
+ $$PWD/qv8profilerclient.h \
+ $$PWD/qmldebugconstants.h \
+ $$PWD/qdebugmessageclient.h \
+ $$PWD/qmlenginedebugclient.h \
+ $$PWD/basetoolsclient.h \
+ $$PWD/declarativetoolsclient.h \
+ $$PWD/qmltoolsclient.h
+
+SOURCES += \
+ $$PWD/qmldebugclient.cpp \
+ $$PWD/baseenginedebugclient.cpp \
+ $$PWD/qmloutputparser.cpp \
+ $$PWD/qmlprofilertraceclient.cpp \
+ $$PWD/qpacketprotocol.cpp \
+ $$PWD/qv8profilerclient.cpp \
+ $$PWD/qdebugmessageclient.cpp \
+ $$PWD/basetoolsclient.cpp \
+ $$PWD/declarativetoolsclient.cpp \
+ $$PWD/qmltoolsclient.cpp \
+ $$PWD/declarativeenginedebugclient.cpp
+
diff --git a/libs/qmldebug/qmldebug.pro b/libs/qmldebug/qmldebug.pro
new file mode 100644
index 0000000000..38b901f860
--- /dev/null
+++ b/libs/qmldebug/qmldebug.pro
@@ -0,0 +1,8 @@
+QT += network
+
+include(../../qtcreatorlibrary.pri)
+include(qmldebug-lib.pri)
+
+OTHER_FILES += \
+ qmldebug.pri
+
diff --git a/libs/qmldebug/qmldebug.qbs b/libs/qmldebug/qmldebug.qbs
new file mode 100644
index 0000000000..beba356937
--- /dev/null
+++ b/libs/qmldebug/qmldebug.qbs
@@ -0,0 +1,43 @@
+import qbs.base 1.0
+import "../QtcLibrary.qbs" as QtcLibrary
+
+QtcLibrary {
+ name: "QmlDebug"
+
+ cpp.defines: base.concat("QMLDEBUG_LIB")
+
+ Depends { name: "cpp" }
+ Depends { name: "Qt"; submodules: ["gui", "network"] }
+
+ files: [
+ "baseenginedebugclient.cpp",
+ "baseenginedebugclient.h",
+ "basetoolsclient.cpp",
+ "basetoolsclient.h",
+ "declarativeenginedebugclient.cpp",
+ "declarativeenginedebugclient.h",
+ "declarativeenginedebugclientv2.h",
+ "declarativetoolsclient.cpp",
+ "declarativetoolsclient.h",
+ "qdebugmessageclient.cpp",
+ "qdebugmessageclient.h",
+ "qmldebug_global.h",
+ "qmldebugclient.cpp",
+ "qmldebugclient.h",
+ "qmldebugconstants.h",
+ "qmlenginedebugclient.h",
+ "qmloutputparser.cpp",
+ "qmloutputparser.h",
+ "qmlprofilereventlocation.h",
+ "qmlprofilereventtypes.h",
+ "qmlprofilertraceclient.cpp",
+ "qmlprofilertraceclient.h",
+ "qmltoolsclient.cpp",
+ "qmltoolsclient.h",
+ "qpacketprotocol.cpp",
+ "qpacketprotocol.h",
+ "qv8profilerclient.cpp",
+ "qv8profilerclient.h",
+ ]
+}
+
diff --git a/libs/qmldebug/qmldebug_dependencies.pri b/libs/qmldebug/qmldebug_dependencies.pri
new file mode 100644
index 0000000000..a99b82c4ef
--- /dev/null
+++ b/libs/qmldebug/qmldebug_dependencies.pri
@@ -0,0 +1 @@
+QTC_LIB_NAME = QmlDebug
diff --git a/libs/qmldebug/qmldebug_global.h b/libs/qmldebug/qmldebug_global.h
new file mode 100644
index 0000000000..9d41083577
--- /dev/null
+++ b/libs/qmldebug/qmldebug_global.h
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QMLDEBUG_GLOBAL_H
+#define QMLDEBUG_GLOBAL_H
+
+#if defined(QMLDEBUG_LIB)
+# define QMLDEBUG_EXPORT Q_DECL_EXPORT
+#elif defined(QMLDEBUG_STATIC_LIB)
+# define QMLDEBUG_EXPORT
+#else
+# define QMLDEBUG_EXPORT Q_DECL_IMPORT
+#endif
+
+#endif // QMLDEBUG_GLOBAL_H
diff --git a/libs/qmldebug/qmldebugclient.cpp b/libs/qmldebug/qmldebugclient.cpp
new file mode 100644
index 0000000000..6fd35d3c13
--- /dev/null
+++ b/libs/qmldebug/qmldebugclient.cpp
@@ -0,0 +1,414 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "qmldebugclient.h"
+
+#include "qpacketprotocol.h"
+
+#include <qdebug.h>
+#include <qstringlist.h>
+#include <qnetworkproxy.h>
+
+namespace QmlDebug {
+
+const int protocolVersion = 1;
+const QString serverId = QLatin1String("QDeclarativeDebugServer");
+const QString clientId = QLatin1String("QDeclarativeDebugClient");
+
+class QmlDebugClientPrivate
+{
+ // Q_DECLARE_PUBLIC(QmlDebugClient)
+public:
+ QmlDebugClientPrivate();
+
+ QString name;
+ QmlDebugConnection *connection;
+};
+
+class QmlDebugConnectionPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QmlDebugConnectionPrivate(QmlDebugConnection *c);
+ QmlDebugConnection *q;
+ QPacketProtocol *protocol;
+ QIODevice *device; // Currently a QTcpSocket
+
+ bool gotHello;
+ QHash <QString, float> serverPlugins;
+ QHash<QString, QmlDebugClient *> plugins;
+
+ void advertisePlugins();
+ void connectDeviceSignals();
+
+public Q_SLOTS:
+ void connected();
+ void readyRead();
+ void deviceAboutToClose();
+};
+
+QmlDebugConnectionPrivate::QmlDebugConnectionPrivate(QmlDebugConnection *c)
+ : QObject(c), q(c), protocol(0), device(0), gotHello(false)
+{
+ protocol = new QPacketProtocol(q, this);
+ QObject::connect(c, SIGNAL(connected()), this, SLOT(connected()));
+ QObject::connect(protocol, SIGNAL(readyRead()), this, SLOT(readyRead()));
+}
+
+void QmlDebugConnectionPrivate::advertisePlugins()
+{
+ if (!q->isConnected() || !gotHello)
+ return;
+
+ QPacket pack;
+ pack << serverId << 1 << plugins.keys();
+ protocol->send(pack);
+ q->flush();
+}
+
+void QmlDebugConnectionPrivate::connected()
+{
+ QPacket pack;
+ pack << serverId << 0 << protocolVersion << plugins.keys();
+ protocol->send(pack);
+ q->flush();
+}
+
+void QmlDebugConnectionPrivate::readyRead()
+{
+ if (!gotHello) {
+ QPacket pack = protocol->read();
+ QString name;
+
+ pack >> name;
+
+ bool validHello = false;
+ if (name == clientId) {
+ int op = -1;
+ pack >> op;
+ if (op == 0) {
+ int version = -1;
+ pack >> version;
+ if (version == protocolVersion) {
+ QStringList pluginNames;
+ QList<float> pluginVersions;
+ pack >> pluginNames;
+ if (!pack.isEmpty())
+ pack >> pluginVersions;
+
+ const int pluginNamesSize = pluginNames.size();
+ const int pluginVersionsSize = pluginVersions.size();
+ for (int i = 0; i < pluginNamesSize; ++i) {
+ float pluginVersion = 1.0;
+ if (i < pluginVersionsSize)
+ pluginVersion = pluginVersions.at(i);
+ serverPlugins.insert(pluginNames.at(i), pluginVersion);
+ }
+
+ validHello = true;
+ }
+ }
+ }
+
+ if (!validHello) {
+ qWarning("QML Debug Client: Invalid hello message");
+ QObject::disconnect(protocol, SIGNAL(readyRead()), this, SLOT(readyRead()));
+ return;
+ }
+ gotHello = true;
+
+ QHash<QString, QmlDebugClient *>::Iterator iter = plugins.begin();
+ for (; iter != plugins.end(); ++iter) {
+ ClientStatus newStatus = Unavailable;
+ if (serverPlugins.contains(iter.key()))
+ newStatus = Enabled;
+ iter.value()->statusChanged(newStatus);
+ }
+ }
+
+ while (protocol->packetsAvailable()) {
+ QPacket pack = protocol->read();
+ QString name;
+ pack >> name;
+
+ if (name == clientId) {
+ int op = -1;
+ pack >> op;
+
+ if (op == 1) {
+ // Service Discovery
+ QHash<QString, float> oldServerPlugins = serverPlugins;
+ serverPlugins.clear();
+
+ QStringList pluginNames;
+ QList<float> pluginVersions;
+ pack >> pluginNames;
+ if (!pack.isEmpty())
+ pack >> pluginVersions;
+
+ const int pluginNamesSize = pluginNames.size();
+ const int pluginVersionsSize = pluginVersions.size();
+ for (int i = 0; i < pluginNamesSize; ++i) {
+ float pluginVersion = 1.0;
+ if (i < pluginVersionsSize)
+ pluginVersion = pluginVersions.at(i);
+ serverPlugins.insert(pluginNames.at(i), pluginVersion);
+ }
+
+ QHash<QString, QmlDebugClient *>::Iterator iter = plugins.begin();
+ for (; iter != plugins.end(); ++iter) {
+ const QString pluginName = iter.key();
+ ClientStatus newStatus = Unavailable;
+ if (serverPlugins.contains(pluginName))
+ newStatus = Enabled;
+
+ if (oldServerPlugins.contains(pluginName)
+ != serverPlugins.contains(pluginName)) {
+ iter.value()->statusChanged(newStatus);
+ }
+ }
+ } else {
+ qWarning() << "QML Debug Client: Unknown control message id" << op;
+ }
+ } else {
+ QByteArray message;
+ pack >> message;
+
+ QHash<QString, QmlDebugClient *>::Iterator iter =
+ plugins.find(name);
+ if (iter == plugins.end())
+ qWarning() << "QML Debug Client: Message received for missing plugin" << name;
+ else
+ (*iter)->messageReceived(message);
+ }
+ }
+}
+
+void QmlDebugConnectionPrivate::deviceAboutToClose()
+{
+ // This is nasty syntax but we want to emit our own aboutToClose signal (by calling QIODevice::close())
+ // without calling the underlying device close fn as that would cause an infinite loop
+ q->QIODevice::close();
+}
+
+QmlDebugConnection::QmlDebugConnection(QObject *parent)
+ : QIODevice(parent), d(new QmlDebugConnectionPrivate(this))
+{
+}
+
+QmlDebugConnection::~QmlDebugConnection()
+{
+ QHash<QString, QmlDebugClient*>::iterator iter = d->plugins.begin();
+ for (; iter != d->plugins.end(); ++iter) {
+ iter.value()->d_func()->connection = 0;
+ iter.value()->statusChanged(NotConnected);
+ }
+}
+
+bool QmlDebugConnection::isConnected() const
+{
+ return state() == QAbstractSocket::ConnectedState;
+}
+
+qint64 QmlDebugConnection::readData(char *data, qint64 maxSize)
+{
+ return d->device->read(data, maxSize);
+}
+
+qint64 QmlDebugConnection::writeData(const char *data, qint64 maxSize)
+{
+ return d->device->write(data, maxSize);
+}
+
+void QmlDebugConnection::internalError(QAbstractSocket::SocketError socketError)
+{
+ setErrorString(d->device->errorString());
+ emit error(socketError);
+}
+
+qint64 QmlDebugConnection::bytesAvailable() const
+{
+ return d->device->bytesAvailable();
+}
+
+bool QmlDebugConnection::isSequential() const
+{
+ return true;
+}
+
+void QmlDebugConnection::close()
+{
+ if (isOpen()) {
+ QIODevice::close();
+ d->device->close();
+ emit stateChanged(QAbstractSocket::UnconnectedState);
+
+ QHash<QString, QmlDebugClient*>::iterator iter = d->plugins.begin();
+ for (; iter != d->plugins.end(); ++iter) {
+ iter.value()->statusChanged(NotConnected);
+ }
+ }
+}
+
+bool QmlDebugConnection::waitForConnected(int msecs)
+{
+ QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(d->device);
+ if (socket)
+ return socket->waitForConnected(msecs);
+ return false;
+}
+
+// For ease of refactoring we use QAbstractSocket's states even if we're actually using a OstChannel underneath
+// since serial ports have a subset of the socket states afaics
+QAbstractSocket::SocketState QmlDebugConnection::state() const
+{
+ QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(d->device);
+ if (socket)
+ return socket->state();
+
+ return QAbstractSocket::UnconnectedState;
+}
+
+void QmlDebugConnection::flush()
+{
+ QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(d->device);
+ if (socket) {
+ socket->flush();
+ return;
+ }
+}
+
+void QmlDebugConnection::connectToHost(const QString &hostName, quint16 port)
+{
+ QTcpSocket *socket = new QTcpSocket(d);
+ socket->setProxy(QNetworkProxy::NoProxy);
+ d->device = socket;
+ d->connectDeviceSignals();
+ d->gotHello = false;
+ connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SIGNAL(stateChanged(QAbstractSocket::SocketState)));
+ connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(internalError(QAbstractSocket::SocketError)));
+ connect(socket, SIGNAL(connected()), this, SIGNAL(connected()));
+ socket->connectToHost(hostName, port);
+ QIODevice::open(ReadWrite | Unbuffered);
+}
+
+void QmlDebugConnectionPrivate::connectDeviceSignals()
+{
+ connect(device, SIGNAL(bytesWritten(qint64)), q, SIGNAL(bytesWritten(qint64)));
+ connect(device, SIGNAL(readyRead()), q, SIGNAL(readyRead()));
+ connect(device, SIGNAL(aboutToClose()), this, SLOT(deviceAboutToClose()));
+}
+
+//
+
+QmlDebugClientPrivate::QmlDebugClientPrivate()
+ : connection(0)
+{
+}
+
+QmlDebugClient::QmlDebugClient(const QString &name,
+ QmlDebugConnection *parent)
+ : QObject(parent), d_ptr(new QmlDebugClientPrivate())
+{
+ Q_D(QmlDebugClient);
+ d->name = name;
+ d->connection = parent;
+
+ if (!d->connection)
+ return;
+
+ if (d->connection->d->plugins.contains(name)) {
+ qWarning() << "QML Debug Client: Conflicting plugin name" << name;
+ d->connection = 0;
+ } else {
+ d->connection->d->plugins.insert(name, this);
+ d->connection->d->advertisePlugins();
+ }
+}
+
+QmlDebugClient::~QmlDebugClient()
+{
+ Q_D(const QmlDebugClient);
+ if (d->connection && d->connection->d) {
+ d->connection->d->plugins.remove(d->name);
+ d->connection->d->advertisePlugins();
+ }
+}
+
+QString QmlDebugClient::name() const
+{
+ Q_D(const QmlDebugClient);
+ return d->name;
+}
+
+float QmlDebugClient::serviceVersion() const
+{
+ Q_D(const QmlDebugClient);
+ if (d->connection && d->connection->d->serverPlugins.contains(d->name))
+ return d->connection->d->serverPlugins.value(d->name);
+ return -1;
+}
+
+ClientStatus QmlDebugClient::status() const
+{
+ Q_D(const QmlDebugClient);
+ if (!d->connection
+ || !d->connection->isConnected()
+ || !d->connection->d->gotHello)
+ return NotConnected;
+
+ if (d->connection->d->serverPlugins.contains(d->name))
+ return Enabled;
+
+ return Unavailable;
+}
+
+void QmlDebugClient::sendMessage(const QByteArray &message)
+{
+ Q_D(QmlDebugClient);
+ if (status() != Enabled)
+ return;
+
+ QPacket pack;
+ pack << d->name << message;
+ d->connection->d->protocol->send(pack);
+ d->connection->flush();
+}
+
+void QmlDebugClient::statusChanged(ClientStatus)
+{
+}
+
+void QmlDebugClient::messageReceived(const QByteArray &)
+{
+}
+
+} // namespace QmlDebug
+
+#include <qmldebugclient.moc>
diff --git a/libs/qmldebug/qmldebugclient.h b/libs/qmldebug/qmldebugclient.h
new file mode 100644
index 0000000000..d33b639fec
--- /dev/null
+++ b/libs/qmldebug/qmldebugclient.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QMLDEBUGCLIENT_H
+#define QMLDEBUGCLIENT_H
+
+#include "qmldebug_global.h"
+#include <qtcpsocket.h>
+
+namespace QmlDebug {
+
+class QmlDebugConnectionPrivate;
+class QMLDEBUG_EXPORT QmlDebugConnection : public QIODevice
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QmlDebugConnection)
+public:
+ QmlDebugConnection(QObject * = 0);
+ ~QmlDebugConnection();
+
+ void connectToHost(const QString &hostName, quint16 port);
+
+ qint64 bytesAvailable() const;
+ bool isConnected() const;
+ QAbstractSocket::SocketState state() const;
+ void flush();
+ bool isSequential() const;
+ void close();
+ bool waitForConnected(int msecs = 30000);
+
+signals:
+ void connected();
+ void stateChanged(QAbstractSocket::SocketState socketState);
+ void error(QAbstractSocket::SocketError socketError);
+
+protected:
+ qint64 readData(char *data, qint64 maxSize);
+ qint64 writeData(const char *data, qint64 maxSize);
+
+private slots:
+ void internalError(QAbstractSocket::SocketError error);
+
+private:
+ QmlDebugConnectionPrivate *d;
+ friend class QmlDebugClient;
+ friend class QmlDebugClientPrivate;
+};
+
+enum ClientStatus {
+ NotConnected,
+ Unavailable,
+ Enabled
+};
+
+class QmlDebugClientPrivate;
+class QMLDEBUG_EXPORT QmlDebugClient : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QmlDebugClient)
+ Q_DISABLE_COPY(QmlDebugClient)
+
+public:
+ QmlDebugClient(const QString &, QmlDebugConnection *parent);
+ ~QmlDebugClient();
+
+ QString name() const;
+ float serviceVersion() const;
+ ClientStatus status() const;
+
+ virtual void sendMessage(const QByteArray &);
+
+protected:
+ virtual void statusChanged(ClientStatus);
+ virtual void messageReceived(const QByteArray &);
+
+private:
+ friend class QmlDebugConnection;
+ friend class QmlDebugConnectionPrivate;
+ QScopedPointer<QmlDebugClientPrivate> d_ptr;
+};
+
+} // namespace QmlDebug
+
+#endif // QMLDEBUGCLIENT_H
diff --git a/libs/qmldebug/qmldebugconstants.h b/libs/qmldebug/qmldebugconstants.h
new file mode 100644
index 0000000000..8f207a1af5
--- /dev/null
+++ b/libs/qmldebug/qmldebugconstants.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QMLDEBUGCONSTANTS_H
+#define QMLDEBUGCONSTANTS_H
+
+namespace QmlDebug {
+namespace Constants {
+
+const char STR_WAITING_FOR_CONNECTION[] = "Waiting for connection ";
+const char STR_ON_PORT_PATTERN[] = "on port (\\d+)";
+const char STR_UNABLE_TO_LISTEN[] = "Unable to listen ";
+const char STR_IGNORING_DEBUGGER[] = "Ignoring \"-qmljsdebugger=";
+const char STR_IGNORING_DEBUGGER2[] = "Ignoring\"-qmljsdebugger="; // There is (was?) a bug in one of the error strings - safest to handle both
+const char STR_CONNECTION_ESTABLISHED[] = "Connection established";
+
+const char QDECLARATIVE_ENGINE[] = "QDeclarativeEngine";
+
+} // namespace Constants
+} // namespace QmlDebug
+
+#endif // QMLDEBUGCONSTANTS_H
diff --git a/libs/qmldebug/qmlenginedebugclient.h b/libs/qmldebug/qmlenginedebugclient.h
new file mode 100644
index 0000000000..9d0fcf0ca4
--- /dev/null
+++ b/libs/qmldebug/qmlenginedebugclient.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QMLENGINEDEBUGCLIENT_H
+#define QMLENGINEDEBUGCLIENT_H
+
+#include "baseenginedebugclient.h"
+
+namespace QmlDebug {
+
+class QmlDebugConnection;
+
+class QMLDEBUG_EXPORT QmlEngineDebugClient : public BaseEngineDebugClient
+{
+ Q_OBJECT
+public:
+ explicit QmlEngineDebugClient(QmlDebugConnection *conn)
+ : BaseEngineDebugClient(QLatin1String("QmlDebugger"), conn)
+ {
+ }
+};
+
+} // namespace QmlDebug
+
+#endif // QMLENGINEDEBUGCLIENT_H
diff --git a/libs/qmldebug/qmloutputparser.cpp b/libs/qmldebug/qmloutputparser.cpp
new file mode 100644
index 0000000000..33a44a3086
--- /dev/null
+++ b/libs/qmldebug/qmloutputparser.cpp
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "qmloutputparser.h"
+#include "qmldebugconstants.h"
+#include <QRegExp>
+
+namespace QmlDebug {
+
+QmlOutputParser::QmlOutputParser(QObject *parent)
+ : QObject(parent)
+{
+}
+
+void QmlOutputParser::setNoOutputText(const QString &text)
+{
+ m_noOutputText = text;
+}
+
+void QmlOutputParser::processOutput(const QString &output)
+{
+ m_buffer.append(output);
+
+ while (true) {
+ const int nlIndex = m_buffer.indexOf(QLatin1Char('\n'));
+ if (nlIndex < 0) // no further complete lines
+ break;
+
+ const QString msg = m_buffer.left(nlIndex);
+ m_buffer = m_buffer.right(m_buffer.size() - nlIndex - 1);
+
+ // used in Qt4
+ static const QString qddserver4 = QLatin1String("QDeclarativeDebugServer: ");
+ // used in Qt5
+ static const QString qddserver5 = QLatin1String("QML Debugger: ");
+
+ QString status;
+ int index = msg.indexOf(qddserver4);
+ if (index != -1) {
+ status = msg;
+ status.remove(0, index + qddserver4.length()); // chop of 'QDeclarativeDebugServer: '
+ } else {
+ index = msg.indexOf(qddserver5);
+ if (index != -1) {
+ status = msg;
+ status.remove(0, index + qddserver5.length()); // chop of 'QML Debugger: '
+ }
+ }
+ if (!status.isEmpty()) {
+ static QString waitingForConnection = QLatin1String(Constants::STR_WAITING_FOR_CONNECTION);
+ static QString unableToListen = QLatin1String(Constants::STR_UNABLE_TO_LISTEN);
+ static QString debuggingNotEnabled = QLatin1String(Constants::STR_IGNORING_DEBUGGER);
+ static QString debuggingNotEnabled2 = QLatin1String(Constants::STR_IGNORING_DEBUGGER2);
+ static QString connectionEstablished = QLatin1String(Constants::STR_CONNECTION_ESTABLISHED);
+
+ if (status.startsWith(waitingForConnection)) {
+ status.remove(0, waitingForConnection.size()); // chop of 'Waiting for connection '
+
+ static QRegExp waitingTcp(
+ QString::fromLatin1(Constants::STR_ON_PORT_PATTERN));
+ if (waitingTcp.indexIn(status) > -1) {
+ bool canConvert;
+ quint16 port = waitingTcp.cap(1).toUShort(&canConvert);
+ if (canConvert)
+ emit waitingForConnectionOnPort(port);
+ continue;
+ }
+ } else if (status.startsWith(unableToListen)) {
+ //: Error message shown after 'Could not connect ... debugger:"
+ emit errorMessage(tr("The port seems to be in use."));
+ } else if (status.startsWith(debuggingNotEnabled) || status.startsWith(debuggingNotEnabled2)) {
+ //: Error message shown after 'Could not connect ... debugger:"
+ emit errorMessage(tr("The application is not set up for QML/JS debugging."));
+ } else if (status.startsWith(connectionEstablished)) {
+ emit connectionEstablishedMessage();
+ } else {
+ emit unknownMessage(status);
+ }
+ } else if (msg.contains(m_noOutputText)) {
+ emit noOutputMessage();
+ }
+
+
+ }
+}
+
+} // namespace QmlDebug
diff --git a/libs/qmldebug/qmloutputparser.h b/libs/qmldebug/qmloutputparser.h
new file mode 100644
index 0000000000..8d394c789f
--- /dev/null
+++ b/libs/qmldebug/qmloutputparser.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QMLOUTPUTPARSER_H
+#define QMLOUTPUTPARSER_H
+
+#include "qmldebug_global.h"
+
+#include <QObject>
+
+namespace QmlDebug {
+
+class QMLDEBUG_EXPORT QmlOutputParser : public QObject
+{
+ Q_OBJECT
+public:
+ QmlOutputParser(QObject *parent = 0);
+
+ void setNoOutputText(const QString &text);
+ void processOutput(const QString &output);
+
+signals:
+ void waitingForConnectionOnPort(quint16 port);
+ void connectionEstablishedMessage();
+ void errorMessage(const QString &detailedError);
+ void unknownMessage(const QString &unknownMessage);
+ void noOutputMessage();
+
+private:
+ QString m_noOutputText;
+ QString m_buffer;
+};
+
+} // namespace QmlDebug
+
+#endif // QMLOUTPUTPARSER_H
diff --git a/libs/qmldebug/qmlprofilereventlocation.h b/libs/qmldebug/qmlprofilereventlocation.h
new file mode 100644
index 0000000000..8190490654
--- /dev/null
+++ b/libs/qmldebug/qmlprofilereventlocation.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QMLPROFILEREVENTLOCATION_H
+#define QMLPROFILEREVENTLOCATION_H
+
+#include "qmldebug_global.h"
+
+#include <QString>
+
+namespace QmlDebug {
+
+struct QMLDEBUG_EXPORT QmlEventLocation
+{
+ QmlEventLocation() : line(-1),column(-1) {}
+ QmlEventLocation(const QString &file, int lineNumber, int columnNumber) : filename(file), line(lineNumber), column(columnNumber) {}
+ QString filename;
+ int line;
+ int column;
+};
+
+}
+
+#endif // QMLPROFILEREVENTLOCATION_H
diff --git a/libs/qmldebug/qmlprofilereventtypes.h b/libs/qmldebug/qmlprofilereventtypes.h
new file mode 100644
index 0000000000..7928bdf984
--- /dev/null
+++ b/libs/qmldebug/qmlprofilereventtypes.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QMLPROFILEREVENTTYPES_H
+#define QMLPROFILEREVENTTYPES_H
+
+namespace QmlDebug {
+
+enum QmlEventType {
+ Painting,
+ Compiling,
+ Creating,
+ Binding,
+ HandlingSignal,
+ PixmapCacheEvent,
+ SceneGraphFrameEvent,
+
+ MaximumQmlEventType
+};
+
+enum BindingType {
+ QmlBinding,
+ V8Binding,
+ OptimizedBinding,
+
+ MaximumBindingType
+};
+
+namespace Constants {
+const char TYPE_PAINTING_STR[] = "Painting";
+const char TYPE_COMPILING_STR[] = "Compiling";
+const char TYPE_CREATING_STR[] = "Creating";
+const char TYPE_BINDING_STR[] = "Binding";
+const char TYPE_HANDLINGSIGNAL_STR[] = "HandlingSignal";
+const char PROFILER_FILE_VERSION[] = "1.02";
+const int QML_MIN_LEVEL = 1;
+}
+
+} // namespace QmlDebug
+
+#endif //QMLPROFILEREVENTTYPES_H
diff --git a/libs/qmldebug/qmlprofilertraceclient.cpp b/libs/qmldebug/qmlprofilertraceclient.cpp
new file mode 100644
index 0000000000..c7c99d353d
--- /dev/null
+++ b/libs/qmldebug/qmlprofilertraceclient.cpp
@@ -0,0 +1,264 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "qmlprofilertraceclient.h"
+
+namespace QmlDebug {
+
+class QmlProfilerTraceClientPrivate {
+public:
+ QmlProfilerTraceClientPrivate(QmlProfilerTraceClient *_q)
+ : q(_q)
+ , inProgressRanges(0)
+ , maximumTime(0)
+ , recording(false)
+ {
+ ::memset(rangeCount, 0, MaximumQmlEventType * sizeof(int));
+ }
+
+ void sendRecordingStatus();
+
+ QmlProfilerTraceClient *q;
+ qint64 inProgressRanges;
+ QStack<qint64> rangeStartTimes[MaximumQmlEventType];
+ QStack<QStringList> rangeDatas[MaximumQmlEventType];
+ QStack<QmlEventLocation> rangeLocations[MaximumQmlEventType];
+ QStack<BindingType> bindingTypes;
+ int rangeCount[MaximumQmlEventType];
+ qint64 maximumTime;
+ bool recording;
+};
+
+} // namespace QmlDebug
+
+using namespace QmlDebug;
+
+static const int GAP_TIME = 150;
+
+void QmlProfilerTraceClientPrivate::sendRecordingStatus()
+{
+ QByteArray ba;
+ QDataStream stream(&ba, QIODevice::WriteOnly);
+ stream << recording;
+ q->sendMessage(ba);
+}
+
+QmlProfilerTraceClient::QmlProfilerTraceClient(QmlDebugConnection *client)
+ : QmlDebugClient(QLatin1String("CanvasFrameRate"), client)
+ , d(new QmlProfilerTraceClientPrivate(this))
+{
+}
+
+QmlProfilerTraceClient::~QmlProfilerTraceClient()
+{
+ //Disable profiling if started by client
+ //Profiling data will be lost!!
+ if (isRecording())
+ setRecording(false);
+ delete d;
+}
+
+void QmlProfilerTraceClient::clearData()
+{
+ ::memset(d->rangeCount, 0, MaximumQmlEventType * sizeof(int));
+ for (int eventType = 0; eventType < MaximumQmlEventType; eventType++) {
+ d->rangeDatas[eventType].clear();
+ d->rangeLocations[eventType].clear();
+ d->rangeStartTimes[eventType].clear();
+ }
+ d->bindingTypes.clear();
+ emit cleared();
+}
+
+void QmlProfilerTraceClient::sendRecordingStatus()
+{
+ d->sendRecordingStatus();
+}
+
+bool QmlProfilerTraceClient::isEnabled() const
+{
+ return status() == Enabled;
+}
+
+bool QmlProfilerTraceClient::isRecording() const
+{
+ return d->recording;
+}
+
+void QmlProfilerTraceClient::setRecording(bool v)
+{
+ if (v == d->recording)
+ return;
+
+ d->recording = v;
+
+ if (status() == Enabled)
+ sendRecordingStatus();
+
+ emit recordingChanged(v);
+}
+
+void QmlProfilerTraceClient::setRecordingFromServer(bool v)
+{
+ if (v == d->recording)
+ return;
+ d->recording = v;
+ emit recordingChanged(v);
+}
+
+void QmlProfilerTraceClient::statusChanged(ClientStatus /*status*/)
+{
+ emit enabledChanged();
+}
+
+void QmlProfilerTraceClient::messageReceived(const QByteArray &data)
+{
+ QByteArray rwData = data;
+ QDataStream stream(&rwData, QIODevice::ReadOnly);
+
+ qint64 time;
+ int messageType;
+
+ stream >> time >> messageType;
+
+ if (messageType >= MaximumMessage)
+ return;
+
+ if (time > (d->maximumTime + GAP_TIME) && 0 == d->inProgressRanges)
+ emit gap(time);
+
+ if (messageType == Event) {
+ int event;
+ stream >> event;
+
+ // stop with the first data
+ if (d->recording && event != StartTrace)
+ setRecordingFromServer(false);
+ else if ((!d->recording) && event == StartTrace)
+ setRecordingFromServer(true);
+
+ if (event == EndTrace) {
+ emit this->traceFinished(time);
+ d->maximumTime = time;
+ d->maximumTime = qMax(time, d->maximumTime);
+ } else if (event == AnimationFrame) {
+ int frameRate, animationCount;
+ stream >> frameRate >> animationCount;
+ emit this->frame(time, frameRate, animationCount);
+ d->maximumTime = qMax(time, d->maximumTime);
+ } else if (event == StartTrace) {
+ emit this->traceStarted(time);
+ d->maximumTime = time;
+ } else if (event < MaximumEventType) {
+ emit this->event((EventType)event, time);
+ d->maximumTime = qMax(time, d->maximumTime);
+ }
+ } else if (messageType == Complete) {
+ emit complete();
+ } else if (messageType == SceneGraphFrame) {
+ int sgEventType;
+ int count = 0;
+ qint64 params[5];
+
+ stream >> sgEventType;
+ while (!stream.atEnd()) {
+ stream >> params[count++];
+ }
+ emit sceneGraphFrame(SceneGraphFrameEvent, sgEventType, time, params[0], params[1], params[2], params[3], params[4]);
+ } else {
+ int range;
+ stream >> range;
+
+ if (range >= MaximumQmlEventType)
+ return;
+
+ if (messageType == RangeStart) {
+ d->rangeStartTimes[range].push(time);
+ d->inProgressRanges |= (static_cast<qint64>(1) << range);
+ ++d->rangeCount[range];
+
+ // read binding type
+ if ((QmlEventType)range == Binding) {
+ int bindingType = (int)QmlBinding;
+ if (!stream.atEnd())
+ stream >> bindingType;
+ d->bindingTypes.push((BindingType)bindingType);
+ }
+
+ // stop with the first data
+ if (d->recording)
+ setRecordingFromServer(false);
+ } else if (messageType == RangeData) {
+ QString data;
+ stream >> data;
+
+ int count = d->rangeCount[range];
+ if (count > 0) {
+ while (d->rangeDatas[range].count() < count)
+ d->rangeDatas[range].push(QStringList());
+ d->rangeDatas[range][count-1] << data;
+ }
+
+ } else if (messageType == RangeLocation) {
+ QString fileName;
+ int line;
+ int column = -1;
+ stream >> fileName >> line;
+
+ if (!stream.atEnd())
+ stream >> column;
+
+ if (d->rangeCount[range] > 0)
+ d->rangeLocations[range].push(QmlEventLocation(fileName, line, column));
+ } else {
+ if (d->rangeCount[range] > 0) {
+ --d->rangeCount[range];
+ if (d->inProgressRanges & (static_cast<qint64>(1) << range))
+ d->inProgressRanges &= ~(static_cast<qint64>(1) << range);
+
+ d->maximumTime = qMax(time, d->maximumTime);
+ QStringList data = d->rangeDatas[range].count() ? d->rangeDatas[range].pop() : QStringList();
+ QmlEventLocation location = d->rangeLocations[range].count() ? d->rangeLocations[range].pop() : QmlEventLocation();
+
+ qint64 startTime = d->rangeStartTimes[range].pop();
+ BindingType bindingType = QmlBinding;
+ if ((QmlEventType)range == Binding)
+ bindingType = d->bindingTypes.pop();
+ emit this->range((QmlEventType)range, bindingType, startTime, time - startTime, data, location);
+ if (d->rangeCount[range] == 0) {
+ int count = d->rangeDatas[range].count() +
+ d->rangeStartTimes[range].count() +
+ d->rangeLocations[range].count();
+ if (count != 0)
+ qWarning() << "incorrectly nested data";
+ }
+ }
+ }
+ }
+}
diff --git a/libs/qmldebug/qmlprofilertraceclient.h b/libs/qmldebug/qmlprofilertraceclient.h
new file mode 100644
index 0000000000..83c4e8772c
--- /dev/null
+++ b/libs/qmldebug/qmlprofilertraceclient.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QMLPROFILERTRACECLIENT_H
+#define QMLPROFILERTRACECLIENT_H
+
+#include "qmldebugclient.h"
+#include "qmlprofilereventtypes.h"
+#include "qmlprofilereventlocation.h"
+#include "qmldebug_global.h"
+
+#include <QStack>
+#include <QStringList>
+
+namespace QmlDebug {
+
+class QMLDEBUG_EXPORT QmlProfilerTraceClient : public QmlDebug::QmlDebugClient
+{
+ Q_OBJECT
+ Q_PROPERTY(bool enabled READ isEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(bool recording READ isRecording WRITE setRecording NOTIFY recordingChanged)
+
+ // don't hide by signal
+ using QObject::event;
+
+public:
+ QmlProfilerTraceClient(QmlDebugConnection *client);
+ ~QmlProfilerTraceClient();
+
+ enum EventType {
+ FramePaint,
+ Mouse,
+ Key,
+ AnimationFrame,
+ EndTrace,
+ StartTrace,
+
+ MaximumEventType
+ };
+
+ enum Message {
+ Event,
+ RangeStart,
+ RangeData,
+ RangeLocation,
+ RangeEnd,
+ Complete,
+ PixmapCacheEvent,
+ SceneGraphFrame,
+
+ MaximumMessage
+ };
+
+ bool isEnabled() const;
+ bool isRecording() const;
+ void setRecording(bool);
+
+public slots:
+ void clearData();
+ void sendRecordingStatus();
+
+signals:
+ void complete();
+ void gap(qint64 time);
+ void event(int event, qint64 time);
+ void traceFinished( qint64 time );
+ void traceStarted( qint64 time );
+ void range(int type, int bindingType, qint64 startTime, qint64 length,
+ const QStringList &data, const QmlDebug::QmlEventLocation &location);
+ void frame(qint64 time, int frameRate, int animationCount);
+ void sceneGraphFrame(int eventType, int sgEventType, qint64 time, qint64 param1, qint64 param2, qint64 param3, qint64 param4, qint64 param5);
+
+ void recordingChanged(bool arg);
+
+ void enabledChanged();
+ void cleared();
+
+protected:
+ virtual void statusChanged(ClientStatus status);
+ virtual void messageReceived(const QByteArray &);
+
+private:
+ void setRecordingFromServer(bool);
+
+private:
+ class QmlProfilerTraceClientPrivate *d;
+};
+
+} // namespace QmlDebug
+
+#endif // QMLPROFILERTRACECLIENT_H
diff --git a/libs/qmldebug/qmltoolsclient.cpp b/libs/qmldebug/qmltoolsclient.cpp
new file mode 100644
index 0000000000..12f876b2b8
--- /dev/null
+++ b/libs/qmldebug/qmltoolsclient.cpp
@@ -0,0 +1,348 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "qmltoolsclient.h"
+#include <QStringList>
+
+//INSPECTOR SERVICE PROTOCOL
+// <HEADER><COMMAND><DATA>
+// <HEADER> : <type{request, response, event}><requestId/eventId>[<response_success_bool>]
+// <COMMAND> : {"enable", "disable", "select", "reload", "setAnimationSpeed",
+// "showAppOnTop", "createObject", "destroyObject", "moveObject",
+// "clearCache"}
+// <DATA> : select: <debugIds_int_list>
+// reload: <hash<changed_filename_string, filecontents_bytearray>>
+// setAnimationSpeed: <speed_real>
+// showAppOnTop: <set_bool>
+// createObject: <qml_string><parentId_int><imports_string_list><filename_string>
+// destroyObject: <debugId_int>
+// moveObject: <debugId_int><newParentId_int>
+// clearCache: void
+
+const char REQUEST[] = "request";
+const char RESPONSE[] = "response";
+const char EVENT[] = "event";
+const char ENABLE[] = "enable";
+const char DISABLE[] = "disable";
+const char SELECT[] = "select";
+const char RELOAD[] = "reload";
+const char SET_ANIMATION_SPEED[] = "setAnimationSpeed";
+const char SHOW_APP_ON_TOP[] = "showAppOnTop";
+const char CREATE_OBJECT[] = "createObject";
+const char DESTROY_OBJECT[] = "destroyObject";
+const char MOVE_OBJECT[] = "moveObject";
+const char CLEAR_CACHE[] = "clearCache";
+
+namespace QmlDebug {
+
+QmlToolsClient::QmlToolsClient(QmlDebugConnection *client)
+ : BaseToolsClient(client, QLatin1String("QmlInspector")),
+ m_connection(client),
+ m_requestId(0),
+ m_reloadQueryId(-1),
+ m_slowDownFactor(1),
+ m_destroyObjectQueryId(-1)
+{
+ setObjectName(name());
+}
+
+void QmlToolsClient::messageReceived(const QByteArray &message)
+{
+ QDataStream ds(message);
+
+ QByteArray type;
+ int requestId;
+ ds >> type >> requestId;
+
+ if (type == QByteArray(RESPONSE)) {
+ bool success = false;
+ ds >> success;
+
+ if ((m_reloadQueryId != -1) && (m_reloadQueryId == requestId) && success)
+ emit reloaded();
+
+ if ((m_destroyObjectQueryId != -1) && (m_destroyObjectQueryId == requestId)
+ && success && !ds.atEnd()) {
+ int objectDebugId;
+ ds >> objectDebugId;
+ emit destroyedObject(objectDebugId);
+ }
+
+ log(LogReceive, type, QString(QLatin1String("requestId: %1 success: %2"))
+ .arg(QString::number(requestId)).arg(QString::number(success)));
+ } else if (type == QByteArray(EVENT)) {
+ QByteArray event;
+ ds >> event;
+ if (event == QByteArray(SELECT)) {
+ m_currentDebugIds.clear();
+ QList<int> debugIds;
+ ds >> debugIds;
+
+ QStringList debugIdStrings;
+ foreach (int debugId, debugIds) {
+ if (debugId != -1) {
+ m_currentDebugIds << debugId;
+ debugIdStrings << QString::number(debugId);
+ }
+ }
+ log(LogReceive, type + ':' + event,
+ QString::fromLatin1("[%1]").arg(debugIdStrings.join(QLatin1String(","))));
+ emit currentObjectsChanged(m_currentDebugIds);
+ }
+ } else {
+ log(LogReceive, type, QLatin1String("Warning: Not handling message"));
+ }
+}
+
+QList<int> QmlToolsClient::currentObjects() const
+{
+ return m_currentDebugIds;
+}
+
+void QmlToolsClient::setCurrentObjects(const QList<int> &debugIds)
+{
+ if (!m_connection || !m_connection->isConnected())
+ return;
+
+ if (debugIds == m_currentDebugIds)
+ return;
+
+ m_currentDebugIds = debugIds;
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray(REQUEST) << m_requestId++
+ << QByteArray(SELECT) << m_currentDebugIds;
+
+ log(LogSend, SELECT, QString::fromLatin1("%1 [list of ids]").arg(debugIds.length()));
+
+ sendMessage(message);
+}
+
+void QmlToolsClient::setObjectIdList(
+ const QList<ObjectReference> &/*objectRoots*/)
+{
+ //NOT IMPLEMENTED
+}
+
+void QmlToolsClient::clearComponentCache()
+{
+ if (!m_connection || !m_connection->isConnected())
+ return;
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray(REQUEST) << m_requestId++
+ << QByteArray(CLEAR_CACHE);
+
+ log(LogSend, CLEAR_CACHE);
+
+ sendMessage(message);
+}
+
+void QmlToolsClient::reload(const QHash<QString, QByteArray> &changesHash)
+{
+ if (!m_connection || !m_connection->isConnected())
+ return;
+
+ m_reloadQueryId = m_requestId;
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray(REQUEST) << m_requestId++
+ << QByteArray(RELOAD) << changesHash;
+
+ log(LogSend, RELOAD);
+
+ sendMessage(message);
+}
+
+void QmlToolsClient::setDesignModeBehavior(bool inDesignMode)
+{
+ if (!m_connection || !m_connection->isConnected())
+ return;
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray(REQUEST) << m_requestId++;
+ if (inDesignMode)
+ ds << QByteArray(ENABLE);
+ else
+ ds << QByteArray(DISABLE);
+
+ log(LogSend, ENABLE, QLatin1String(inDesignMode ? "true" : "false"));
+
+ sendMessage(message);
+}
+
+void QmlToolsClient::setAnimationSpeed(qreal slowDownFactor)
+{
+ if (!m_connection || !m_connection->isConnected())
+ return;
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray(REQUEST) << m_requestId++
+ << QByteArray(SET_ANIMATION_SPEED) << slowDownFactor;
+
+ log(LogSend, SET_ANIMATION_SPEED, QString::number(slowDownFactor));
+
+ sendMessage(message);
+ //Cache non-zero values
+ if (slowDownFactor)
+ m_slowDownFactor = slowDownFactor;
+}
+
+void QmlToolsClient::setAnimationPaused(bool paused)
+{
+ if (paused)
+ setAnimationSpeed(0);
+ else
+ setAnimationSpeed(m_slowDownFactor);
+}
+
+void QmlToolsClient::changeToSelectTool()
+{
+// NOT IMPLEMENTED
+}
+
+void QmlToolsClient::changeToSelectMarqueeTool()
+{
+// NOT IMPLEMENTED
+}
+
+void QmlToolsClient::changeToZoomTool()
+{
+// NOT IMPLEMENTED
+}
+
+void QmlToolsClient::showAppOnTop(bool showOnTop)
+{
+ if (!m_connection || !m_connection->isConnected())
+ return;
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray(REQUEST) << m_requestId++
+ << QByteArray(SHOW_APP_ON_TOP) << showOnTop;
+
+ log(LogSend, SHOW_APP_ON_TOP, QLatin1String(showOnTop ? "true" : "false"));
+
+ sendMessage(message);
+}
+
+void QmlToolsClient::createQmlObject(const QString &qmlText,
+ int parentDebugId,
+ const QStringList &imports,
+ const QString &filename, int order)
+{
+ if (!m_connection || !m_connection->isConnected())
+ return;
+
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray(REQUEST) << m_requestId++
+ << QByteArray(CREATE_OBJECT)
+ << qmlText
+ << parentDebugId
+ << imports
+ << filename
+ << order;
+
+ log(LogSend, CREATE_OBJECT, QString::fromLatin1("%1 %2 [%3] %4").arg(qmlText,
+ QString::number(parentDebugId),
+ imports.join(QLatin1String(",")), filename));
+
+ sendMessage(message);
+}
+
+void QmlToolsClient::destroyQmlObject(int debugId)
+{
+ if (!m_connection || !m_connection->isConnected())
+ return;
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ m_destroyObjectQueryId = m_requestId;
+ ds << QByteArray(REQUEST) << m_requestId++
+ << QByteArray(DESTROY_OBJECT) << debugId;
+
+ log(LogSend, DESTROY_OBJECT, QString::number(debugId));
+
+ sendMessage(message);
+}
+
+void QmlToolsClient::reparentQmlObject(int debugId, int newParent)
+{
+ if (!m_connection || !m_connection->isConnected())
+ return;
+ QByteArray message;
+ QDataStream ds(&message, QIODevice::WriteOnly);
+ ds << QByteArray(REQUEST) << m_requestId++
+ << QByteArray(MOVE_OBJECT) << debugId << newParent;
+
+ log(LogSend, MOVE_OBJECT, QString::fromLatin1("%1 %2").arg(QString::number(debugId),
+ QString::number(newParent)));
+
+ sendMessage(message);
+}
+
+
+void QmlToolsClient::applyChangesToQmlFile()
+{
+ if (!m_connection || !m_connection->isConnected())
+ return;
+
+ // TODO
+}
+
+void QmlToolsClient::applyChangesFromQmlFile()
+{
+ if (!m_connection || !m_connection->isConnected())
+ return;
+
+ // TODO
+}
+
+void QmlToolsClient::log(LogDirection direction,
+ const QByteArray &message,
+ const QString &extra)
+{
+ QString msg;
+ if (direction == LogSend)
+ msg += QLatin1String("sending ");
+ else
+ msg += QLatin1String("receiving ");
+
+ msg += QLatin1String(message);
+ msg += QLatin1Char(' ');
+ msg += extra;
+ emit logActivity(name(), msg);
+}
+
+} // namespace QmlDebug
diff --git a/libs/qmldebug/qmltoolsclient.h b/libs/qmldebug/qmltoolsclient.h
new file mode 100644
index 0000000000..b153842da1
--- /dev/null
+++ b/libs/qmldebug/qmltoolsclient.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QMLTOOLSCLIENT_H
+#define QMLTOOLSCLIENT_H
+
+#include "basetoolsclient.h"
+
+namespace QmlDebug {
+
+class QMLDEBUG_EXPORT QmlToolsClient : public BaseToolsClient
+{
+ Q_OBJECT
+public:
+ explicit QmlToolsClient(QmlDebugConnection *client);
+
+ void setCurrentObjects(const QList<int> &debugIds);
+ void reload(const QHash<QString, QByteArray> &changesHash);
+ bool supportReload() const { return true; }
+ void setDesignModeBehavior(bool inDesignMode);
+ void setAnimationSpeed(qreal slowDownFactor);
+ void setAnimationPaused(bool paused);
+ void changeToSelectTool();
+ void changeToSelectMarqueeTool();
+ void changeToZoomTool();
+ void showAppOnTop(bool showOnTop);
+
+ void createQmlObject(const QString &qmlText, int parentDebugId,
+ const QStringList &imports, const QString &filename,
+ int order);
+ void destroyQmlObject(int debugId);
+ void reparentQmlObject(int debugId, int newParent);
+
+ void applyChangesToQmlFile();
+ void applyChangesFromQmlFile();
+
+ QList<int> currentObjects() const;
+
+ // ### Qt 4.8: remove if we can have access to qdeclarativecontextdata or id's
+ void setObjectIdList(const QList<ObjectReference> &objectRoots);
+
+ void clearComponentCache();
+
+protected:
+ void messageReceived(const QByteArray &);
+
+private:
+ void log(LogDirection direction,
+ const QByteArray &message,
+ const QString &extra = QString());
+
+private:
+ QList<int> m_currentDebugIds;
+ QmlDebugConnection *m_connection;
+ int m_requestId;
+ int m_reloadQueryId;
+ qreal m_slowDownFactor;
+ int m_destroyObjectQueryId;
+};
+
+} // namespace QmlDebug
+
+#endif // QMLTOOLSCLIENT_H
diff --git a/libs/qmldebug/qpacketprotocol.cpp b/libs/qmldebug/qpacketprotocol.cpp
new file mode 100644
index 0000000000..d9aa7493a9
--- /dev/null
+++ b/libs/qmldebug/qpacketprotocol.cpp
@@ -0,0 +1,541 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "qpacketprotocol.h"
+
+#include <qbuffer.h>
+#include <qelapsedtimer.h>
+
+namespace QmlDebug {
+
+static const unsigned int MAX_PACKET_SIZE = 0x7FFFFFFF;
+
+/*!
+ \class QPacketProtocol
+ \internal
+
+ \brief The QPacketProtocol class encapsulates communicating discrete packets
+ across fragmented IO channels, such as TCP sockets.
+
+ QPacketProtocol makes it simple to send arbitrary sized data "packets" across
+ fragmented transports such as TCP and UDP.
+
+ As transmission boundaries are not respected, sending packets over protocols
+ like TCP frequently involves "stitching" them back together at the receiver.
+ QPacketProtocol makes this easier by performing this task for you. Packet
+ data sent using QPacketProtocol is prepended with a 4-byte size header
+ allowing the receiving QPacketProtocol to buffer the packet internally until
+ it has all been received. QPacketProtocol does not perform any sanity
+ checking on the size or on the data, so this class should only be used in
+ prototyping or trusted situations where DOS attacks are unlikely.
+
+ QPacketProtocol does not perform any communications itself. Instead it can
+ operate on any QIODevice that supports the QIODevice::readyRead() signal. A
+ logical "packet" is encapsulated by the companion QPacket class. The
+ following example shows two ways to send data using QPacketProtocol. The
+ transmitted data is equivalent in both.
+
+ \code
+ QTcpSocket socket;
+ // ... connect socket ...
+
+ QPacketProtocol protocol(&socket);
+
+ // Send packet the quick way
+ protocol.send() << "Hello world" << 123;
+
+ // Send packet the longer way
+ QPacket packet;
+ packet << "Hello world" << 123;
+ protocol.send(packet);
+ \endcode
+
+ Likewise, the following shows how to read data from QPacketProtocol, assuming
+ that the QPacketProtocol::readyRead() signal has been emitted.
+
+ \code
+ // ... QPacketProtocol::readyRead() is emitted ...
+
+ int a;
+ QByteArray b;
+
+ // Receive packet the quick way
+ protocol.read() >> a >> b;
+
+ // Receive packet the longer way
+ QPacket packet = protocol.read();
+ p >> a >> b;
+ \endcode
+
+ \ingroup io
+ \sa QPacket
+*/
+
+class QPacketProtocolPrivate : public QObject
+{
+ Q_OBJECT
+
+public:
+ QPacketProtocolPrivate(QPacketProtocol *parent, QIODevice *_dev)
+ : QObject(parent), inProgressSize(-1), maxPacketSize(MAX_PACKET_SIZE),
+ waitingForPacket(false), dev(_dev)
+ {
+ Q_ASSERT(4 == sizeof(qint32));
+
+ QObject::connect(this, SIGNAL(readyRead()),
+ parent, SIGNAL(readyRead()));
+ QObject::connect(this, SIGNAL(packetWritten()),
+ parent, SIGNAL(packetWritten()));
+ QObject::connect(this, SIGNAL(invalidPacket()),
+ parent, SIGNAL(invalidPacket()));
+ QObject::connect(dev, SIGNAL(readyRead()),
+ this, SLOT(readyToRead()));
+ QObject::connect(dev, SIGNAL(aboutToClose()),
+ this, SLOT(aboutToClose()));
+ QObject::connect(dev, SIGNAL(bytesWritten(qint64)),
+ this, SLOT(bytesWritten(qint64)));
+ }
+
+Q_SIGNALS:
+ void readyRead();
+ void packetWritten();
+ void invalidPacket();
+
+public Q_SLOTS:
+ void aboutToClose()
+ {
+ inProgress.clear();
+ sendingPackets.clear();
+ inProgressSize = -1;
+ }
+
+ void bytesWritten(qint64 bytes)
+ {
+ Q_ASSERT(!sendingPackets.isEmpty());
+
+ while (bytes) {
+ if (sendingPackets.at(0) > bytes) {
+ sendingPackets[0] -= bytes;
+ bytes = 0;
+ } else {
+ bytes -= sendingPackets.at(0);
+ sendingPackets.removeFirst();
+ emit packetWritten();
+ }
+ }
+ }
+
+ void readyToRead()
+ {
+ while (true) {
+ // Need to get trailing data
+ if (-1 == inProgressSize) {
+ // We need a size header of sizeof(qint32)
+ if (sizeof(qint32) > (uint)dev->bytesAvailable())
+ return;
+
+ // Read size header
+ int read = dev->read((char *)&inProgressSize, sizeof(qint32));
+ Q_ASSERT(read == sizeof(qint32));
+ Q_UNUSED(read);
+
+ // Check sizing constraints
+ if (inProgressSize > maxPacketSize) {
+ QObject::disconnect(dev, SIGNAL(readyRead()),
+ this, SLOT(readyToRead()));
+ QObject::disconnect(dev, SIGNAL(aboutToClose()),
+ this, SLOT(aboutToClose()));
+ QObject::disconnect(dev, SIGNAL(bytesWritten(qint64)),
+ this, SLOT(bytesWritten(qint64)));
+ dev = 0;
+ emit invalidPacket();
+ return;
+ }
+
+ inProgressSize -= sizeof(qint32);
+ } else {
+ inProgress.append(dev->read(inProgressSize - inProgress.size()));
+
+ if (inProgressSize == inProgress.size()) {
+ // Packet has arrived!
+ packets.append(inProgress);
+ inProgressSize = -1;
+ inProgress.clear();
+
+ waitingForPacket = false;
+ emit readyRead();
+ } else
+ return;
+ }
+ }
+ }
+
+public:
+ QList<qint64> sendingPackets;
+ QList<QByteArray> packets;
+ QByteArray inProgress;
+ qint32 inProgressSize;
+ qint32 maxPacketSize;
+ bool waitingForPacket;
+ QIODevice *dev;
+};
+
+/*!
+ Construct a QPacketProtocol instance that works on \a dev with the
+ specified \a parent.
+ */
+QPacketProtocol::QPacketProtocol(QIODevice *dev, QObject *parent)
+ : QObject(parent), d(new QPacketProtocolPrivate(this, dev))
+{
+ Q_ASSERT(dev);
+}
+
+/*!
+ Destroys the QPacketProtocol instance.
+ */
+QPacketProtocol::~QPacketProtocol()
+{
+}
+
+/*!
+ Returns the maximum packet size allowed. By default this is
+ 2,147,483,647 bytes.
+
+ If a packet claiming to be larger than the maximum packet size is received,
+ the QPacketProtocol::invalidPacket() signal is emitted.
+
+ \sa QPacketProtocol::setMaximumPacketSize()
+ */
+qint32 QPacketProtocol::maximumPacketSize() const
+{
+ return d->maxPacketSize;
+}
+
+/*!
+ Sets the maximum allowable packet size to \a max.
+
+ \sa QPacketProtocol::maximumPacketSize()
+ */
+qint32 QPacketProtocol::setMaximumPacketSize(qint32 max)
+{
+ if (max > (signed)sizeof(qint32))
+ d->maxPacketSize = max;
+ return d->maxPacketSize;
+}
+
+/*!
+ Returns a streamable object that is transmitted on destruction. For example
+
+ \code
+ protocol.send() << "Hello world" << 123;
+ \endcode
+
+ will send a packet containing "Hello world" and 123. To construct more
+ complex packets, explicitly construct a QPacket instance.
+ */
+QPacketAutoSend QPacketProtocol::send()
+{
+ return QPacketAutoSend(this);
+}
+
+/*!
+ \fn void QPacketProtocol::send(const QPacket & packet)
+
+ Transmit the \a packet.
+ */
+void QPacketProtocol::send(const QPacket & p)
+{
+ if (p.b.isEmpty())
+ return; // We don't send empty packets
+
+ qint64 sendSize = p.b.size() + sizeof(qint32);
+
+ d->sendingPackets.append(sendSize);
+ qint32 sendSize32 = sendSize;
+ qint64 writeBytes = d->dev->write((char *)&sendSize32, sizeof(qint32));
+ Q_ASSERT(writeBytes == sizeof(qint32));
+ writeBytes = d->dev->write(p.b);
+ Q_ASSERT(writeBytes == p.b.size());
+ Q_UNUSED(writeBytes); // For building in release mode.
+}
+
+/*!
+ Returns the number of received packets yet to be read.
+ */
+qint64 QPacketProtocol::packetsAvailable() const
+{
+ return d->packets.count();
+}
+
+/*!
+ Discard any unread packets.
+ */
+void QPacketProtocol::clear()
+{
+ d->packets.clear();
+}
+
+/*!
+ Return the next unread packet, or an invalid QPacket instance if no packets
+ are available. This method does NOT block.
+ */
+QPacket QPacketProtocol::read()
+{
+ if (0 == d->packets.count())
+ return QPacket();
+
+ QPacket rv(d->packets.at(0));
+ d->packets.removeFirst();
+ return rv;
+}
+
+
+/*
+ Returns the difference between msecs and elapsed. If msecs is -1,
+ however, -1 is returned.
+*/
+static int qt_timeout_value(int msecs, int elapsed)
+{
+ if (msecs == -1)
+ return -1;
+
+ int timeout = msecs - elapsed;
+ return timeout < 0 ? 0 : timeout;
+}
+
+/*!
+ This function locks until a new packet is available for reading and the
+ \l{QIODevice::}{readyRead()} signal has been emitted. The function
+ will timeout after \a msecs milliseconds; the default timeout is
+ 30000 milliseconds.
+
+ The function returns true if the readyRead() signal is emitted and
+ there is new data available for reading; otherwise it returns false
+ (if an error occurred or the operation timed out).
+ */
+
+bool QPacketProtocol::waitForReadyRead(int msecs)
+{
+ if (!d->packets.isEmpty())
+ return true;
+
+ QElapsedTimer stopWatch;
+ stopWatch.start();
+
+ d->waitingForPacket = true;
+ do {
+ if (!d->dev->waitForReadyRead(msecs))
+ return false;
+ if (!d->waitingForPacket)
+ return true;
+ msecs = qt_timeout_value(msecs, stopWatch.elapsed());
+ } while (true);
+}
+
+/*!
+ Return the QIODevice passed to the QPacketProtocol constructor.
+*/
+QIODevice *QPacketProtocol::device()
+{
+ return d->dev;
+}
+
+/*!
+ \fn void QPacketProtocol::readyRead()
+
+ Emitted whenever a new packet is received. Applications may use
+ QPacketProtocol::read() to retrieve this packet.
+ */
+
+/*!
+ \fn void QPacketProtocol::invalidPacket()
+
+ A packet larger than the maximum allowable packet size was received. The
+ packet will be discarded and, as it indicates corruption in the protocol, no
+ further packets will be received.
+ */
+
+/*!
+ \fn void QPacketProtocol::packetWritten()
+
+ Emitted each time a packet is completing written to the device. This signal
+ may be used for communications flow control.
+ */
+
+/*!
+ \class QPacket
+ \internal
+
+ \brief The QPacket class encapsulates an unfragmentable packet of data to be
+ transmitted by QPacketProtocol.
+
+ The QPacket class works together with QPacketProtocol to make it simple to
+ send arbitrary sized data "packets" across fragmented transports such as TCP
+ and UDP.
+
+ QPacket provides a QDataStream interface to an unfragmentable packet.
+ Applications should construct a QPacket, propagate it with data and then
+ transmit it over a QPacketProtocol instance. For example:
+ \code
+ QPacketProtocol protocol(...);
+
+ QPacket myPacket;
+ myPacket << "Hello world!" << 123;
+ protocol.send(myPacket);
+ \endcode
+
+ As long as both ends of the connection are using the QPacketProtocol class,
+ the data within this packet will be delivered unfragmented at the other end,
+ ready for extraction.
+
+ \code
+ QByteArray greeting;
+ int count;
+
+ QPacket myPacket = protocol.read();
+
+ myPacket >> greeting >> count;
+ \endcode
+
+ Only packets returned from QPacketProtocol::read() may be read from. QPacket
+ instances constructed by directly by applications are for transmission only
+ and are considered "write only". Attempting to read data from them will
+ result in undefined behavior.
+
+ \ingroup io
+ \sa QPacketProtocol
+ */
+
+/*!
+ Constructs an empty write-only packet.
+ */
+QPacket::QPacket()
+ : QDataStream(), buf(0)
+{
+ buf = new QBuffer(&b);
+ buf->open(QIODevice::WriteOnly);
+ setDevice(buf);
+ setVersion(QDataStream::Qt_4_7);
+}
+
+/*!
+ Destroys the QPacket instance.
+ */
+QPacket::~QPacket()
+{
+ if (buf) {
+ delete buf;
+ buf = 0;
+ }
+}
+
+/*!
+ Creates a copy of \a other. The initial stream positions are shared, but the
+ two packets are otherwise independent.
+ */
+QPacket::QPacket(const QPacket & other)
+ : QDataStream(), b(other.b), buf(0)
+{
+ buf = new QBuffer(&b);
+ buf->open(other.buf->openMode());
+ setDevice(buf);
+}
+
+/*!
+ \internal
+ */
+QPacket::QPacket(const QByteArray & ba)
+ : QDataStream(), b(ba), buf(0)
+{
+ buf = new QBuffer(&b);
+ buf->open(QIODevice::ReadOnly);
+ setDevice(buf);
+}
+
+/*!
+ Returns true if this packet is empty - that is, contains no data.
+ */
+bool QPacket::isEmpty() const
+{
+ return b.isEmpty();
+}
+
+/*!
+ Returns raw packet data.
+ */
+QByteArray QPacket::data() const
+{
+ return b;
+}
+
+/*!
+ Clears data in the packet. This is useful for reusing one writable packet.
+ For example
+ \code
+ QPacketProtocol protocol(...);
+
+ QPacket packet;
+
+ packet << "Hello world!" << 123;
+ protocol.send(packet);
+
+ packet.clear();
+ packet << "Goodbyte world!" << 789;
+ protocol.send(packet);
+ \endcode
+ */
+void QPacket::clear()
+{
+ QBuffer::OpenMode oldMode = buf->openMode();
+ buf->close();
+ b.clear();
+ buf->setBuffer(&b); // reset QBuffer internals with new size of b.
+ buf->open(oldMode);
+}
+
+/*!
+ \class QPacketAutoSend
+ \internal
+
+ \internal
+ */
+QPacketAutoSend::QPacketAutoSend(QPacketProtocol *_p)
+ : QPacket(), p(_p)
+{
+}
+
+QPacketAutoSend::~QPacketAutoSend()
+{
+ if (!b.isEmpty())
+ p->send(*this);
+}
+
+} // namespace QmlDebug
+
+#include <qpacketprotocol.moc>
diff --git a/libs/qmldebug/qpacketprotocol.h b/libs/qmldebug/qpacketprotocol.h
new file mode 100644
index 0000000000..b1ce313809
--- /dev/null
+++ b/libs/qmldebug/qpacketprotocol.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QPACKETPROTOCOL_H
+#define QPACKETPROTOCOL_H
+
+#include <qobject.h>
+#include <qdatastream.h>
+
+QT_BEGIN_NAMESPACE
+class QIODevice;
+class QBuffer;
+QT_END_NAMESPACE
+
+namespace QmlDebug {
+
+class QPacket;
+class QPacketAutoSend;
+
+class QPacketProtocolPrivate;
+
+class QPacketProtocol : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit QPacketProtocol(QIODevice *dev, QObject *parent = 0);
+ virtual ~QPacketProtocol();
+
+ qint32 maximumPacketSize() const;
+ qint32 setMaximumPacketSize(qint32);
+
+ QPacketAutoSend send();
+ void send(const QPacket &);
+
+ qint64 packetsAvailable() const;
+ QPacket read();
+
+ bool waitForReadyRead(int msecs = 3000);
+
+ void clear();
+
+ QIODevice *device();
+
+Q_SIGNALS:
+ void readyRead();
+ void invalidPacket();
+ void packetWritten();
+
+private:
+ QPacketProtocolPrivate *d;
+};
+
+
+class QPacket : public QDataStream
+{
+public:
+ QPacket();
+ QPacket(const QPacket &);
+ virtual ~QPacket();
+
+ void clear();
+ bool isEmpty() const;
+ QByteArray data() const;
+
+protected:
+ friend class QPacketProtocol;
+ QPacket(const QByteArray &ba);
+ QByteArray b;
+ QBuffer *buf;
+};
+
+class QPacketAutoSend : public QPacket
+{
+public:
+ virtual ~QPacketAutoSend();
+
+private:
+ friend class QPacketProtocol;
+ QPacketAutoSend(QPacketProtocol *);
+ QPacketProtocol *p;
+};
+
+} // QmlDebug
+
+#endif
diff --git a/libs/qmldebug/qv8profilerclient.cpp b/libs/qmldebug/qv8profilerclient.cpp
new file mode 100644
index 0000000000..f93335c4fe
--- /dev/null
+++ b/libs/qmldebug/qv8profilerclient.cpp
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "qv8profilerclient.h"
+
+namespace QmlDebug {
+
+class QV8ProfilerClientPrivate {
+public:
+ QV8ProfilerClientPrivate(QV8ProfilerClient *_q)
+ : q(_q)
+ , recording(false)
+ {
+ }
+
+ void sendRecordingStatus();
+
+ QV8ProfilerClient *q;
+ bool recording;
+};
+
+} // namespace QmlDebug
+
+using namespace QmlDebug;
+
+void QV8ProfilerClientPrivate::sendRecordingStatus()
+{
+ QByteArray ba;
+ QDataStream stream(&ba, QIODevice::WriteOnly);
+ QByteArray cmd("V8PROFILER");
+ QByteArray option("");
+ QByteArray title("");
+
+ if (recording)
+ option = "start";
+ else
+ option = "stop";
+ stream << cmd << option << title;
+ q->sendMessage(ba);
+}
+
+QV8ProfilerClient::QV8ProfilerClient(QmlDebugConnection *client)
+ : QmlDebugClient(QLatin1String("V8Profiler"), client)
+ , d(new QV8ProfilerClientPrivate(this))
+{
+}
+
+QV8ProfilerClient::~QV8ProfilerClient()
+{
+ //Disable profiling if started by client
+ //Profiling data will be lost!!
+ if (isRecording())
+ setRecording(false);
+ delete d;
+}
+
+void QV8ProfilerClient::clearData()
+{
+ emit cleared();
+}
+
+bool QV8ProfilerClient::isEnabled() const
+{
+ return status() == Enabled;
+}
+
+void QV8ProfilerClient::sendRecordingStatus()
+{
+ d->sendRecordingStatus();
+}
+
+bool QV8ProfilerClient::isRecording() const
+{
+ return d->recording;
+}
+
+void QV8ProfilerClient::setRecording(bool v)
+{
+ if (v == d->recording)
+ return;
+
+ d->recording = v;
+
+ if (status() == Enabled)
+ sendRecordingStatus();
+
+ emit recordingChanged(v);
+}
+
+void QV8ProfilerClient::setRecordingFromServer(bool v)
+{
+ if (v == d->recording)
+ return;
+
+ d->recording = v;
+
+ emit recordingChanged(v);
+}
+
+void QV8ProfilerClient::statusChanged(ClientStatus /*status*/)
+{
+ emit enabledChanged();
+}
+
+void QV8ProfilerClient::messageReceived(const QByteArray &data)
+{
+ QByteArray rwData = data;
+ QDataStream stream(&rwData, QIODevice::ReadOnly);
+
+ int messageType;
+
+ stream >> messageType;
+
+ if (messageType == V8Complete) {
+ setRecordingFromServer(false);
+ emit complete();
+ } else if (messageType == V8ProfilingStarted) {
+ setRecordingFromServer(true);
+ } else if (messageType == V8Entry) {
+ QString filename;
+ QString function;
+ int lineNumber;
+ double totalTime;
+ double selfTime;
+ int depth;
+
+ stream >> filename >> function >> lineNumber >> totalTime >> selfTime >> depth;
+ emit this->v8range(depth, function, filename, lineNumber, totalTime, selfTime);
+ }
+}
+
diff --git a/libs/qmldebug/qv8profilerclient.h b/libs/qmldebug/qv8profilerclient.h
new file mode 100644
index 0000000000..39e77bd98f
--- /dev/null
+++ b/libs/qmldebug/qv8profilerclient.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef QV8PROFILERCLIENT_H
+#define QV8PROFILERCLIENT_H
+
+#include "qmldebugclient.h"
+#include "qmlprofilereventtypes.h"
+#include "qmldebug_global.h"
+
+#include <QStack>
+#include <QStringList>
+
+namespace QmlDebug {
+
+class QMLDEBUG_EXPORT QV8ProfilerClient : public QmlDebugClient
+{
+ Q_OBJECT
+ Q_PROPERTY(bool enabled READ isEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(bool recording READ isRecording WRITE setRecording NOTIFY recordingChanged)
+
+public:
+ enum Message {
+ V8Entry,
+ V8Complete,
+ V8SnapshotChunk,
+ V8SnapshotComplete,
+ V8ProfilingStarted,
+
+ V8MaximumMessage
+ };
+
+ QV8ProfilerClient(QmlDebugConnection *client);
+ ~QV8ProfilerClient();
+
+ bool isEnabled() const;
+ bool isRecording() const;
+ void setRecording(bool);
+
+public slots:
+ void clearData();
+ void sendRecordingStatus();
+
+signals:
+ void complete();
+ void v8range(int depth, const QString &function, const QString &filename,
+ int lineNumber, double totalTime, double selfTime);
+
+ void recordingChanged(bool arg);
+
+ void enabledChanged();
+ void cleared();
+
+private:
+ void setRecordingFromServer(bool);
+
+protected:
+ virtual void statusChanged(ClientStatus);
+ virtual void messageReceived(const QByteArray &);
+
+private:
+ class QV8ProfilerClientPrivate *d;
+};
+
+} // namespace QmlDebug
+
+#endif // QV8PROFILERCLIENT_H
diff --git a/qtcreatorlibrary.pri b/qtcreatorlibrary.pri
new file mode 100644
index 0000000000..9e525ccfdf
--- /dev/null
+++ b/qtcreatorlibrary.pri
@@ -0,0 +1,7 @@
+IDE_SOURCE_TREE=$$(IDE_SOURCE_TREE)
+IDE_BUILD_TREE=$$(IDE_BUILD_TREE)
+
+isEmpty(IDE_SOURCE_TREE):error(Set IDE_SOURCE_TREE environment variable)
+isEmpty(IDE_BUILD_TREE):error(Set IDE_BUILD_TREE environment variable)
+
+include($$IDE_SOURCE_TREE/src/qtcreatorlibrary.pri)