aboutsummaryrefslogtreecommitdiffstats
path: root/src/qmldebug
diff options
context:
space:
mode:
Diffstat (limited to 'src/qmldebug')
-rw-r--r--src/qmldebug/qmldebug.pro21
-rw-r--r--src/qmldebug/qqmldebugclient.cpp130
-rw-r--r--src/qmldebug/qqmldebugclient_p.h91
-rw-r--r--src/qmldebug/qqmldebugclient_p_p.h72
-rw-r--r--src/qmldebug/qqmldebugconnection.cpp467
-rw-r--r--src/qmldebug/qqmldebugconnection_p.h105
-rw-r--r--src/qmldebug/qqmlenginecontrolclient.cpp153
-rw-r--r--src/qmldebug/qqmlenginecontrolclient_p.h86
-rw-r--r--src/qmldebug/qqmlenginecontrolclient_p_p.h91
-rw-r--r--src/qmldebug/qqmleventlocation_p.h73
-rw-r--r--src/qmldebug/qqmlprofilerclient.cpp360
-rw-r--r--src/qmldebug/qqmlprofilerclient_p.h114
-rw-r--r--src/qmldebug/qqmlprofilerclient_p_p.h70
13 files changed, 1833 insertions, 0 deletions
diff --git a/src/qmldebug/qmldebug.pro b/src/qmldebug/qmldebug.pro
new file mode 100644
index 0000000000..e5f6de3314
--- /dev/null
+++ b/src/qmldebug/qmldebug.pro
@@ -0,0 +1,21 @@
+TARGET = QtQmlDebug
+QT = core-private network packetprotocol-private qml-private
+CONFIG += static internal_module
+
+load(qt_module)
+
+SOURCES += \
+ qqmldebugclient.cpp \
+ qqmldebugconnection.cpp \
+ qqmlenginecontrolclient.cpp \
+ qqmlprofilerclient.cpp
+
+HEADERS += \
+ qqmldebugclient_p.h \
+ qqmldebugclient_p_p.h \
+ qqmldebugconnection_p.h \
+ qqmlenginecontrolclient_p.h \
+ qqmlenginecontrolclient_p_p.h \
+ qqmleventlocation_p.h \
+ qqmlprofilerclient_p.h \
+ qqmlprofilerclient_p_p.h
diff --git a/src/qmldebug/qqmldebugclient.cpp b/src/qmldebug/qqmldebugclient.cpp
new file mode 100644
index 0000000000..7f1e8c637c
--- /dev/null
+++ b/src/qmldebug/qqmldebugclient.cpp
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmldebugclient_p_p.h"
+#include "qqmldebugconnection_p.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qpointer.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlDebugClient::QQmlDebugClient(const QString &name, QQmlDebugConnection *parent) :
+ QObject(*(new QQmlDebugClientPrivate(name, parent)), parent)
+{
+ Q_D(QQmlDebugClient);
+ d->addToConnection();
+}
+
+QQmlDebugClient::QQmlDebugClient(QQmlDebugClientPrivate &dd) :
+ QObject(dd, dd.connection.data())
+{
+ Q_D(QQmlDebugClient);
+ d->addToConnection();
+}
+
+QQmlDebugClient::~QQmlDebugClient()
+{
+ Q_D(QQmlDebugClient);
+ if (d->connection && !d->connection->removeClient(d->name))
+ qWarning() << "QQmlDebugClient: Plugin not registered" << d->name;
+}
+
+QQmlDebugClientPrivate::QQmlDebugClientPrivate(const QString &name,
+ QQmlDebugConnection *connection) :
+ name(name), connection(connection)
+{
+}
+
+void QQmlDebugClientPrivate::addToConnection()
+{
+ Q_Q(QQmlDebugClient);
+ if (connection && !connection->addClient(name, q)) {
+ qWarning() << "QQmlDebugClient: Conflicting plugin name" << name;
+ connection = 0;
+ }
+}
+
+QString QQmlDebugClient::name() const
+{
+ Q_D(const QQmlDebugClient);
+ return d->name;
+}
+
+float QQmlDebugClient::serviceVersion() const
+{
+ Q_D(const QQmlDebugClient);
+ return d->connection->serviceVersion(d->name);
+}
+
+QQmlDebugClient::State QQmlDebugClient::state() const
+{
+ Q_D(const QQmlDebugClient);
+ if (!d->connection || !d->connection->isConnected())
+ return NotConnected;
+
+ if (d->connection->serviceVersion(d->name) != -1)
+ return Enabled;
+
+ return Unavailable;
+}
+
+void QQmlDebugClient::sendMessage(const QByteArray &message)
+{
+ Q_D(QQmlDebugClient);
+ d->connection->sendMessage(d->name, message);
+}
+
+QQmlDebugConnection *QQmlDebugClient::connection() const
+{
+ Q_D(const QQmlDebugClient);
+ return d->connection;
+}
+
+void QQmlDebugClient::stateChanged(QQmlDebugClient::State state)
+{
+ Q_UNUSED(state);
+}
+
+void QQmlDebugClient::messageReceived(const QByteArray &message)
+{
+ Q_UNUSED(message);
+}
+
+QT_END_NAMESPACE
diff --git a/src/qmldebug/qqmldebugclient_p.h b/src/qmldebug/qqmldebugclient_p.h
new file mode 100644
index 0000000000..723de5ee43
--- /dev/null
+++ b/src/qmldebug/qqmldebugclient_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLDEBUGCLIENT_P_H
+#define QQMLDEBUGCLIENT_P_H
+
+#include <QtCore/qobject.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QQmlDebugConnection;
+class QQmlDebugClientPrivate;
+class QQmlDebugClient : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QQmlDebugClient)
+ Q_DECLARE_PRIVATE(QQmlDebugClient)
+
+public:
+ enum State { NotConnected, Unavailable, Enabled };
+
+ QQmlDebugClient(const QString &name, QQmlDebugConnection *parent);
+ ~QQmlDebugClient();
+
+ QString name() const;
+ float serviceVersion() const;
+ State state() const;
+ void sendMessage(const QByteArray &message);
+
+ QQmlDebugConnection *connection() const;
+
+protected:
+ QQmlDebugClient(QQmlDebugClientPrivate &dd);
+
+private:
+ friend class QQmlDebugConnection;
+
+ virtual void stateChanged(State state);
+ virtual void messageReceived(const QByteArray &message);
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLDEBUGCLIENT_P_H
diff --git a/src/qmldebug/qqmldebugclient_p_p.h b/src/qmldebug/qqmldebugclient_p_p.h
new file mode 100644
index 0000000000..7c033d2bf9
--- /dev/null
+++ b/src/qmldebug/qqmldebugclient_p_p.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLDEBUGCLIENT_P_P_H
+#define QQMLDEBUGCLIENT_P_P_H
+
+#include "qqmldebugclient_p.h"
+#include <private/qobject_p.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QQmlDebugClientPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QQmlDebugClient)
+public:
+ QQmlDebugClientPrivate(const QString &name, QQmlDebugConnection *connection);
+ void addToConnection();
+
+ QString name;
+ QPointer<QQmlDebugConnection> connection;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLDEBUGCLIENT_P_P_H
diff --git a/src/qmldebug/qqmldebugconnection.cpp b/src/qmldebug/qqmldebugconnection.cpp
new file mode 100644
index 0000000000..35a540bff8
--- /dev/null
+++ b/src/qmldebug/qqmldebugconnection.cpp
@@ -0,0 +1,467 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmldebugconnection_p.h"
+#include "qqmldebugclient_p.h"
+
+#include <private/qpacketprotocol_p.h>
+#include <private/qpacket_p.h>
+#include <private/qobject_p.h>
+
+#include <QtCore/qeventloop.h>
+#include <QtCore/qtimer.h>
+#include <QtCore/qdatastream.h>
+#include <QtNetwork/qlocalserver.h>
+#include <QtNetwork/qlocalsocket.h>
+#include <QtNetwork/qtcpsocket.h>
+
+QT_BEGIN_NAMESPACE
+
+static const int protocolVersion = 1;
+static const QString serverId = QLatin1String("QDeclarativeDebugServer");
+static const QString clientId = QLatin1String("QDeclarativeDebugClient");
+
+class QQmlDebugConnectionPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QQmlDebugConnection)
+
+public:
+ QQmlDebugConnectionPrivate();
+ QPacketProtocol *protocol;
+ QIODevice *device;
+ QLocalServer *server;
+ QEventLoop handshakeEventLoop;
+ QTimer handshakeTimer;
+
+ bool gotHello;
+ int currentDataStreamVersion;
+ int maximumDataStreamVersion;
+ QHash <QString, float> serverPlugins;
+ QHash<QString, QQmlDebugClient *> plugins;
+ QStringList removedPlugins;
+
+ void advertisePlugins();
+ void connectDeviceSignals();
+ void flush();
+};
+
+QQmlDebugConnectionPrivate::QQmlDebugConnectionPrivate() :
+ protocol(0), device(0), server(0), gotHello(false),
+ currentDataStreamVersion(QDataStream::Qt_4_7),
+ maximumDataStreamVersion(QDataStream::Qt_DefaultCompiledVersion)
+{
+ handshakeTimer.setSingleShot(true);
+ handshakeTimer.setInterval(3000);
+}
+
+void QQmlDebugConnectionPrivate::advertisePlugins()
+{
+ Q_Q(QQmlDebugConnection);
+ if (!q->isConnected())
+ return;
+
+ QPacket pack(currentDataStreamVersion);
+ pack << serverId << 1 << plugins.keys();
+ protocol->send(pack.data());
+ flush();
+}
+
+void QQmlDebugConnection::socketConnected()
+{
+ Q_D(QQmlDebugConnection);
+ QPacket pack(d->currentDataStreamVersion);
+ pack << serverId << 0 << protocolVersion << d->plugins.keys() << d->maximumDataStreamVersion
+ << true; // We accept multiple messages per packet
+ d->protocol->send(pack.data());
+ d->flush();
+}
+
+void QQmlDebugConnection::socketDisconnected()
+{
+ Q_D(QQmlDebugConnection);
+ d->gotHello = false;
+ emit disconnected();
+}
+
+void QQmlDebugConnection::protocolReadyRead()
+{
+ Q_D(QQmlDebugConnection);
+ if (!d->gotHello) {
+ QPacket pack(d->currentDataStreamVersion, d->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.atEnd())
+ 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);
+ d->serverPlugins.insert(pluginNames.at(i), pluginVersion);
+ }
+
+ pack >> d->currentDataStreamVersion;
+ validHello = true;
+ }
+ }
+ }
+
+ if (!validHello) {
+ qWarning("QQmlDebugConnection: Invalid hello message");
+ QObject::disconnect(d->protocol, SIGNAL(protocolReadyRead()), this, SLOT(protocolReadyRead()));
+ return;
+ }
+ d->gotHello = true;
+ emit connected();
+
+ QHash<QString, QQmlDebugClient *>::Iterator iter = d->plugins.begin();
+ for (; iter != d->plugins.end(); ++iter) {
+ QQmlDebugClient::State newState = QQmlDebugClient::Unavailable;
+ if (d->serverPlugins.contains(iter.key()))
+ newState = QQmlDebugClient::Enabled;
+ iter.value()->stateChanged(newState);
+ }
+
+ d->handshakeTimer.stop();
+ d->handshakeEventLoop.quit();
+ }
+
+ while (d->protocol->packetsAvailable()) {
+ QPacket pack(d->currentDataStreamVersion, d->protocol->read());
+ QString name;
+ pack >> name;
+
+ if (name == clientId) {
+ int op = -1;
+ pack >> op;
+
+ if (op == 1) {
+ // Service Discovery
+ QHash<QString, float> oldServerPlugins = d->serverPlugins;
+ d->serverPlugins.clear();
+
+ QStringList pluginNames;
+ QList<float> pluginVersions;
+ pack >> pluginNames;
+ if (!pack.atEnd())
+ 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);
+ d->serverPlugins.insert(pluginNames.at(i), pluginVersion);
+ }
+
+ QHash<QString, QQmlDebugClient *>::Iterator iter = d->plugins.begin();
+ for (; iter != d->plugins.end(); ++iter) {
+ const QString pluginName = iter.key();
+ QQmlDebugClient::State newSate = QQmlDebugClient::Unavailable;
+ if (d->serverPlugins.contains(pluginName))
+ newSate = QQmlDebugClient::Enabled;
+
+ if (oldServerPlugins.contains(pluginName)
+ != d->serverPlugins.contains(pluginName)) {
+ iter.value()->stateChanged(newSate);
+ }
+ }
+ } else {
+ qWarning() << "QQmlDebugConnection: Unknown control message id" << op;
+ }
+ } else {
+ QHash<QString, QQmlDebugClient *>::Iterator iter = d->plugins.find(name);
+ if (iter == d->plugins.end()) {
+ // We can get more messages for plugins we have removed because it takes time to
+ // send the advertisement message but the removal is instant locally.
+ if (!d->removedPlugins.contains(name))
+ qWarning() << "QQmlDebugConnection: Message received for missing plugin"
+ << name;
+ } else {
+ QQmlDebugClient *client = *iter;
+ QByteArray message;
+ while (!pack.atEnd()) {
+ pack >> message;
+ client->messageReceived(message);
+ }
+ }
+ }
+ }
+}
+
+void QQmlDebugConnection::handshakeTimeout()
+{
+ Q_D(QQmlDebugConnection);
+ if (!d->gotHello) {
+ qWarning() << "QQmlDebugConnection: Did not get handshake answer in time";
+ d->handshakeEventLoop.quit();
+ }
+}
+
+QQmlDebugConnection::QQmlDebugConnection(QObject *parent) :
+ QObject(*(new QQmlDebugConnectionPrivate), parent)
+{
+ Q_D(QQmlDebugConnection);
+ connect(&d->handshakeTimer, SIGNAL(timeout()), this, SLOT(handshakeTimeout()));
+}
+
+QQmlDebugConnection::~QQmlDebugConnection()
+{
+ Q_D(QQmlDebugConnection);
+ QHash<QString, QQmlDebugClient*>::iterator iter = d->plugins.begin();
+ for (; iter != d->plugins.end(); ++iter)
+ iter.value()->stateChanged(QQmlDebugClient::NotConnected);
+}
+
+int QQmlDebugConnection::currentDataStreamVersion() const
+{
+ Q_D(const QQmlDebugConnection);
+ return d->currentDataStreamVersion;
+}
+
+void QQmlDebugConnection::setMaximumDataStreamVersion(int maximumVersion)
+{
+ Q_D(QQmlDebugConnection);
+ d->maximumDataStreamVersion = maximumVersion;
+}
+
+bool QQmlDebugConnection::isConnected() const
+{
+ Q_D(const QQmlDebugConnection);
+ return d->gotHello;
+}
+
+bool QQmlDebugConnection::isConnecting() const
+{
+ Q_D(const QQmlDebugConnection);
+ return !d->gotHello && d->device;
+}
+
+void QQmlDebugConnection::close()
+{
+ Q_D(QQmlDebugConnection);
+ if (d->gotHello) {
+ d->gotHello = false;
+ d->device->close();
+
+ QHash<QString, QQmlDebugClient*>::iterator iter = d->plugins.begin();
+ for (; iter != d->plugins.end(); ++iter)
+ iter.value()->stateChanged(QQmlDebugClient::NotConnected);
+ }
+
+ if (d->device) {
+ d->device->deleteLater();
+ d->device = 0;
+ }
+}
+
+bool QQmlDebugConnection::waitForConnected(int msecs)
+{
+ Q_D(QQmlDebugConnection);
+ QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(d->device);
+ if (!socket) {
+ if (!d->server || (!d->server->hasPendingConnections() &&
+ !d->server->waitForNewConnection(msecs)))
+ return false;
+ } else if (!socket->waitForConnected(msecs)) {
+ return false;
+ }
+ // wait for handshake
+ d->handshakeTimer.start();
+ d->handshakeEventLoop.exec();
+ return d->gotHello;
+}
+
+QQmlDebugClient *QQmlDebugConnection::client(const QString &name) const
+{
+ Q_D(const QQmlDebugConnection);
+ return d->plugins.value(name, 0);
+}
+
+bool QQmlDebugConnection::addClient(const QString &name, QQmlDebugClient *client)
+{
+ Q_D(QQmlDebugConnection);
+ if (d->plugins.contains(name))
+ return false;
+ d->removedPlugins.removeAll(name);
+ d->plugins.insert(name, client);
+ d->advertisePlugins();
+ return true;
+}
+
+bool QQmlDebugConnection::removeClient(const QString &name)
+{
+ Q_D(QQmlDebugConnection);
+ if (!d->plugins.contains(name))
+ return false;
+ d->plugins.remove(name);
+ d->removedPlugins.append(name);
+ d->advertisePlugins();
+ return true;
+}
+
+float QQmlDebugConnection::serviceVersion(const QString &serviceName) const
+{
+ Q_D(const QQmlDebugConnection);
+ return d->serverPlugins.value(serviceName, -1);
+}
+
+bool QQmlDebugConnection::sendMessage(const QString &name, const QByteArray &message)
+{
+ Q_D(QQmlDebugConnection);
+ if (!isConnected() || !d->serverPlugins.contains(name))
+ return false;
+
+ QPacket pack(d->currentDataStreamVersion);
+ pack << name << message;
+ d->protocol->send(pack.data());
+ d->flush();
+
+ return true;
+}
+
+void QQmlDebugConnectionPrivate::flush()
+{
+ QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(device);
+ if (socket)
+ socket->flush();
+}
+
+void QQmlDebugConnection::connectToHost(const QString &hostName, quint16 port)
+{
+ Q_D(QQmlDebugConnection);
+ if (d->gotHello)
+ close();
+ QTcpSocket *socket = new QTcpSocket(this);
+ d->device = socket;
+ d->connectDeviceSignals();
+ connect(socket, SIGNAL(connected()), this, SLOT(socketConnected()));
+ connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
+ this, SIGNAL(socketError(QAbstractSocket::SocketError)));
+ connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
+ this, SIGNAL(socketStateChanged(QAbstractSocket::SocketState)));
+ socket->connectToHost(hostName, port);
+}
+
+void QQmlDebugConnection::startLocalServer(const QString &fileName)
+{
+ Q_D(QQmlDebugConnection);
+ if (d->gotHello)
+ close();
+ if (d->server)
+ d->server->deleteLater();
+ d->server = new QLocalServer(this);
+ // QueuedConnection so that waitForNewConnection() returns true.
+ connect(d->server, SIGNAL(newConnection()), this, SLOT(newConnection()), Qt::QueuedConnection);
+ d->server->listen(fileName);
+}
+
+class LocalSocketSignalTranslator : public QObject
+{
+ Q_OBJECT
+public:
+ LocalSocketSignalTranslator(QLocalSocket *parent) : QObject(parent)
+ {
+ connect(parent, SIGNAL(stateChanged(QLocalSocket::LocalSocketState)),
+ this, SLOT(onStateChanged(QLocalSocket::LocalSocketState)));
+ connect(parent, SIGNAL(error(QLocalSocket::LocalSocketError)),
+ this, SLOT(onError(QLocalSocket::LocalSocketError)));
+ }
+
+signals:
+ void socketError(QAbstractSocket::SocketError error);
+ void socketStateChanged(QAbstractSocket::SocketState state);
+
+public slots:
+ void onError(QLocalSocket::LocalSocketError error)
+ {
+ emit socketError(static_cast<QAbstractSocket::SocketError>(error));
+ }
+
+ void onStateChanged(QLocalSocket::LocalSocketState state)
+ {
+ emit socketStateChanged(static_cast<QAbstractSocket::SocketState>(state));
+ }
+};
+
+void QQmlDebugConnection::newConnection()
+{
+ Q_D(QQmlDebugConnection);
+ delete d->device;
+ QLocalSocket *socket = d->server->nextPendingConnection();
+ d->server->close();
+ d->device = socket;
+ d->connectDeviceSignals();
+ LocalSocketSignalTranslator *translator = new LocalSocketSignalTranslator(socket);
+
+ QObject::connect(translator, SIGNAL(socketError(QAbstractSocket::SocketError)),
+ this, SIGNAL(socketError(QAbstractSocket::SocketError)));
+ QObject::connect(translator, SIGNAL(socketStateChanged(QAbstractSocket::SocketState)),
+ this, SIGNAL(socketStateChanged(QAbstractSocket::SocketState)));
+ socketConnected();
+}
+
+void QQmlDebugConnectionPrivate::connectDeviceSignals()
+{
+ Q_Q(QQmlDebugConnection);
+ delete protocol;
+ protocol = new QPacketProtocol(device, q);
+ QObject::connect(protocol, SIGNAL(readyRead()), q, SLOT(protocolReadyRead()));
+ QObject::connect(device, SIGNAL(disconnected()), q, SLOT(socketDisconnected()));
+}
+
+QT_END_NAMESPACE
+
+#include <qqmldebugconnection.moc>
diff --git a/src/qmldebug/qqmldebugconnection_p.h b/src/qmldebug/qqmldebugconnection_p.h
new file mode 100644
index 0000000000..40753fc998
--- /dev/null
+++ b/src/qmldebug/qqmldebugconnection_p.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLDEBUGCONNECTION_P_H
+#define QQMLDEBUGCONNECTION_P_H
+
+#include <QtCore/qobject.h>
+#include <QtNetwork/qabstractsocket.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QQmlDebugClient;
+class QQmlDebugConnectionPrivate;
+class QQmlDebugConnection : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QQmlDebugConnection)
+ Q_DECLARE_PRIVATE(QQmlDebugConnection)
+public:
+ QQmlDebugConnection(QObject *parent = 0);
+ ~QQmlDebugConnection();
+
+ void connectToHost(const QString &hostName, quint16 port);
+ void startLocalServer(const QString &fileName);
+
+ int currentDataStreamVersion() const;
+ void setMaximumDataStreamVersion(int maximumVersion);
+
+ bool isConnected() const;
+ bool isConnecting() const;
+
+ void close();
+ bool waitForConnected(int msecs = 30000);
+
+ QQmlDebugClient *client(const QString &name) const;
+ bool addClient(const QString &name, QQmlDebugClient *client);
+ bool removeClient(const QString &name);
+
+ float serviceVersion(const QString &serviceName) const;
+ bool sendMessage(const QString &name, const QByteArray &message);
+
+signals:
+ void connected();
+ void disconnected();
+ void socketError(QAbstractSocket::SocketError socketError);
+ void socketStateChanged(QAbstractSocket::SocketState socketState);
+
+private Q_SLOTS:
+ void newConnection();
+ void socketConnected();
+ void socketDisconnected();
+ void protocolReadyRead();
+ void handshakeTimeout();
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLDEBUGCONNECTION_P_H
diff --git a/src/qmldebug/qqmlenginecontrolclient.cpp b/src/qmldebug/qqmlenginecontrolclient.cpp
new file mode 100644
index 0000000000..c95ae5c6ee
--- /dev/null
+++ b/src/qmldebug/qqmlenginecontrolclient.cpp
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlenginecontrolclient_p.h"
+#include "qqmlenginecontrolclient_p_p.h"
+#include "qqmldebugconnection_p.h"
+
+#include <private/qqmldebugserviceinterfaces_p.h>
+#include <private/qpacket_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlEngineControlClient::QQmlEngineControlClient(QQmlDebugConnection *connection) :
+ QQmlDebugClient(*(new QQmlEngineControlClientPrivate(connection)))
+{
+}
+
+QQmlEngineControlClient::QQmlEngineControlClient(QQmlEngineControlClientPrivate &dd) :
+ QQmlDebugClient(dd)
+{
+}
+
+/*!
+ * Block the starting or stopping of the engine with id \a engineId for now. By calling
+ * releaseEngine later the block can be lifted again. In the debugged application the engine control
+ * server waits until a message is received before continuing. So by not sending a message here we
+ * delay the process. Blocks add up. You have to call releaseEngine() as often as you've called
+ * blockEngine before. The intention of that is to allow different debug clients to use the same
+ * engine control and communicate with their respective counterparts before the QML engine starts or
+ * shuts down.
+ */
+void QQmlEngineControlClient::blockEngine(int engineId)
+{
+ Q_D(QQmlEngineControlClient);
+ Q_ASSERT(d->blockedEngines.contains(engineId));
+ d->blockedEngines[engineId].blockers++;
+}
+
+/*!
+ * Release the engine with id \a engineId. If no other blocks are present, depending on what the
+ * engine is waiting for, the start or stop command is sent to the process being debugged.
+ */
+void QQmlEngineControlClient::releaseEngine(int engineId)
+{
+ Q_D(QQmlEngineControlClient);
+ Q_ASSERT(d->blockedEngines.contains(engineId));
+
+ QQmlEngineControlClientPrivate::EngineState &state = d->blockedEngines[engineId];
+ if (--state.blockers == 0) {
+ Q_ASSERT(state.releaseCommand != QQmlEngineControlClientPrivate::InvalidCommand);
+ d->sendCommand(state.releaseCommand, engineId);
+ d->blockedEngines.remove(engineId);
+ }
+}
+
+QList<int> QQmlEngineControlClient::blockedEngines() const
+{
+ Q_D(const QQmlEngineControlClient);
+ return d->blockedEngines.keys();
+}
+
+void QQmlEngineControlClient::messageReceived(const QByteArray &data)
+{
+ Q_D(QQmlEngineControlClient);
+ QPacket stream(d->connection->currentDataStreamVersion(), data);
+ int message;
+ int id;
+ QString name;
+
+ stream >> message >> id;
+
+ if (!stream.atEnd())
+ stream >> name;
+
+ QQmlEngineControlClientPrivate::EngineState &state = d->blockedEngines[id];
+ Q_ASSERT(state.blockers == 0);
+ Q_ASSERT(state.releaseCommand == QQmlEngineControlClientPrivate::InvalidCommand);
+
+ switch (message) {
+ case QQmlEngineControlClientPrivate::EngineAboutToBeAdded:
+ state.releaseCommand = QQmlEngineControlClientPrivate::StartWaitingEngine;
+ emit engineAboutToBeAdded(id, name);
+ break;
+ case QQmlEngineControlClientPrivate::EngineAdded:
+ emit engineAdded(id, name);
+ break;
+ case QQmlEngineControlClientPrivate::EngineAboutToBeRemoved:
+ state.releaseCommand = QQmlEngineControlClientPrivate::StopWaitingEngine;
+ emit engineAboutToBeRemoved(id, name);
+ break;
+ case QQmlEngineControlClientPrivate::EngineRemoved:
+ emit engineRemoved(id, name);
+ break;
+ }
+
+ if (state.blockers == 0 &&
+ state.releaseCommand != QQmlEngineControlClientPrivate::InvalidCommand) {
+ d->sendCommand(state.releaseCommand, id);
+ d->blockedEngines.remove(id);
+ }
+}
+
+QQmlEngineControlClientPrivate::QQmlEngineControlClientPrivate(QQmlDebugConnection *connection) :
+ QQmlDebugClientPrivate(QQmlEngineControlService::s_key, connection)
+{
+}
+
+void QQmlEngineControlClientPrivate::sendCommand(
+ QQmlEngineControlClientPrivate::CommandType command, int engineId)
+{
+ Q_Q(QQmlEngineControlClient);
+ QPacket stream(connection->currentDataStreamVersion());
+ stream << int(command) << engineId;
+ q->sendMessage(stream.data());
+}
+
+QT_END_NAMESPACE
diff --git a/src/qmldebug/qqmlenginecontrolclient_p.h b/src/qmldebug/qqmlenginecontrolclient_p.h
new file mode 100644
index 0000000000..6affc46ffc
--- /dev/null
+++ b/src/qmldebug/qqmlenginecontrolclient_p.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLENGINECONTROLCLIENT_P_H
+#define QQMLENGINECONTROLCLIENT_P_H
+
+#include "qqmldebugclient_p.h"
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QQmlEngineControlClientPrivate;
+class QQmlEngineControlClient : public QQmlDebugClient
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQmlEngineControlClient)
+public:
+ QQmlEngineControlClient(QQmlDebugConnection *connection);
+
+ void blockEngine(int engineId);
+ void releaseEngine(int engineId);
+
+ QList<int> blockedEngines() const;
+
+signals:
+ void engineAboutToBeAdded(int engineId, const QString &name);
+ void engineAdded(int engineId, const QString &name);
+ void engineAboutToBeRemoved(int engineId, const QString &name);
+ void engineRemoved(int engineId, const QString &name);
+
+protected:
+ QQmlEngineControlClient(QQmlEngineControlClientPrivate &dd);
+
+private:
+ void messageReceived(const QByteArray &);
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLENGINECONTROLCLIENT_P_H
diff --git a/src/qmldebug/qqmlenginecontrolclient_p_p.h b/src/qmldebug/qqmlenginecontrolclient_p_p.h
new file mode 100644
index 0000000000..597ae23e3a
--- /dev/null
+++ b/src/qmldebug/qqmlenginecontrolclient_p_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLENGINECONTROLCLIENT_P_P_H
+#define QQMLENGINECONTROLCLIENT_P_P_H
+
+#include "qqmlenginecontrolclient_p.h"
+#include "qqmldebugclient_p_p.h"
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QQmlEngineControlClientPrivate : public QQmlDebugClientPrivate
+{
+ Q_DECLARE_PUBLIC(QQmlEngineControlClient)
+public:
+ enum MessageType {
+ EngineAboutToBeAdded,
+ EngineAdded,
+ EngineAboutToBeRemoved,
+ EngineRemoved
+ };
+
+ enum CommandType {
+ StartWaitingEngine,
+ StopWaitingEngine,
+ InvalidCommand
+ };
+
+ QQmlEngineControlClientPrivate(QQmlDebugConnection *connection);
+
+ void sendCommand(CommandType command, int engineId);
+
+ struct EngineState {
+ EngineState(CommandType command = InvalidCommand) : releaseCommand(command), blockers(0) {}
+ CommandType releaseCommand;
+ int blockers;
+ };
+
+ QHash<int, EngineState> blockedEngines;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLENGINECONTROLCLIENT_P_P_H
diff --git a/src/qmldebug/qqmleventlocation_p.h b/src/qmldebug/qqmleventlocation_p.h
new file mode 100644
index 0000000000..c3a2b93f0f
--- /dev/null
+++ b/src/qmldebug/qqmleventlocation_p.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLEVENTLOCATION_P_H
+#define QQMLEVENTLOCATION_P_H
+
+#include <QtCore/qstring.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+struct QQmlEventLocation
+{
+ QQmlEventLocation() : line(-1), column(-1) {}
+ QQmlEventLocation(const QString &file, int lineNumber, int columnNumber) :
+ filename(file), line(lineNumber), column(columnNumber) {}
+
+ QString filename;
+ int line;
+ int column;
+};
+
+Q_DECLARE_TYPEINFO(QQmlEventLocation, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+#endif // QQMLEVENTLOCATION_P_H
diff --git a/src/qmldebug/qqmlprofilerclient.cpp b/src/qmldebug/qqmlprofilerclient.cpp
new file mode 100644
index 0000000000..6f6b04ade9
--- /dev/null
+++ b/src/qmldebug/qqmlprofilerclient.cpp
@@ -0,0 +1,360 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlprofilerclient_p_p.h"
+#include "qqmldebugconnection_p.h"
+#include <private/qqmldebugserviceinterfaces_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlProfilerClient::QQmlProfilerClient(QQmlDebugConnection *connection) :
+ QQmlDebugClient(*(new QQmlProfilerClientPrivate(connection)))
+{
+}
+
+QQmlProfilerClient::QQmlProfilerClient(QQmlProfilerClientPrivate &dd) :
+ QQmlDebugClient(dd)
+{
+}
+
+QQmlProfilerClientPrivate::QQmlProfilerClientPrivate(QQmlDebugConnection *connection) :
+ QQmlDebugClientPrivate(QQmlProfilerService::s_key, connection),
+ features(std::numeric_limits<quint64>::max())
+{
+}
+
+void QQmlProfilerClient::setFeatures(quint64 features)
+{
+ Q_D(QQmlProfilerClient);
+ d->features = features;
+}
+
+void QQmlProfilerClient::sendRecordingStatus(bool record, int engineId, quint32 flushInterval)
+{
+ Q_D(const QQmlProfilerClient);
+
+ QPacket stream(d->connection->currentDataStreamVersion());
+ stream << record << engineId << d->features << flushInterval;
+ sendMessage(stream.data());
+}
+
+void QQmlProfilerClient::traceStarted(qint64 time, int engineId)
+{
+ Q_UNUSED(time);
+ Q_UNUSED(engineId);
+}
+
+void QQmlProfilerClient::traceFinished(qint64 time, int engineId)
+{
+ Q_UNUSED(time);
+ Q_UNUSED(engineId);
+}
+
+void QQmlProfilerClient::rangeStart(QQmlProfilerDefinitions::RangeType type, qint64 startTime)
+{
+ Q_UNUSED(type);
+ Q_UNUSED(startTime);
+}
+
+void QQmlProfilerClient::rangeData(QQmlProfilerDefinitions::RangeType type, qint64 time,
+ const QString &data)
+{
+ Q_UNUSED(type);
+ Q_UNUSED(time);
+ Q_UNUSED(data);
+}
+
+void QQmlProfilerClient::rangeLocation(QQmlProfilerDefinitions::RangeType type, qint64 time,
+ const QQmlEventLocation &location)
+{
+ Q_UNUSED(type);
+ Q_UNUSED(time);
+ Q_UNUSED(location);
+}
+
+void QQmlProfilerClient::rangeEnd(QQmlProfilerDefinitions::RangeType type, qint64 endTime)
+{
+ Q_UNUSED(type);
+ Q_UNUSED(endTime);
+}
+
+void QQmlProfilerClient::animationFrame(qint64 time, int frameRate, int animationCount,
+ int threadId)
+{
+ Q_UNUSED(time);
+ Q_UNUSED(frameRate);
+ Q_UNUSED(animationCount);
+ Q_UNUSED(threadId);
+}
+
+void QQmlProfilerClient::sceneGraphEvent(QQmlProfilerDefinitions::SceneGraphFrameType type,
+ qint64 time, qint64 numericData1, qint64 numericData2,
+ qint64 numericData3, qint64 numericData4,
+ qint64 numericData5)
+{
+ Q_UNUSED(type);
+ Q_UNUSED(time);
+ Q_UNUSED(numericData1);
+ Q_UNUSED(numericData2);
+ Q_UNUSED(numericData3);
+ Q_UNUSED(numericData4);
+ Q_UNUSED(numericData5);
+}
+
+void QQmlProfilerClient::pixmapCacheEvent(QQmlProfilerDefinitions::PixmapEventType type,
+ qint64 time, const QString &url, int numericData1,
+ int numericData2)
+{
+ Q_UNUSED(type);
+ Q_UNUSED(time);
+ Q_UNUSED(url);
+ Q_UNUSED(numericData1);
+ Q_UNUSED(numericData2);
+}
+
+void QQmlProfilerClient::memoryAllocation(QQmlProfilerDefinitions::MemoryType type, qint64 time,
+ qint64 amount)
+{
+ Q_UNUSED(type);
+ Q_UNUSED(time);
+ Q_UNUSED(amount);
+}
+
+void QQmlProfilerClient::inputEvent(QQmlProfilerDefinitions::InputEventType type, qint64 time,
+ int a, int b)
+{
+ Q_UNUSED(type);
+ Q_UNUSED(time);
+ Q_UNUSED(a);
+ Q_UNUSED(b);
+}
+
+void QQmlProfilerClient::complete()
+{
+}
+
+void QQmlProfilerClient::unknownEvent(QQmlProfilerDefinitions::Message messageType, qint64 time,
+ int detailType)
+{
+ Q_UNUSED(messageType);
+ Q_UNUSED(time);
+ Q_UNUSED(detailType);
+}
+
+void QQmlProfilerClient::unknownData(QPacket &stream)
+{
+ Q_UNUSED(stream);
+}
+
+inline QQmlProfilerDefinitions::ProfileFeature featureFromRangeType(
+ QQmlProfilerDefinitions::RangeType range)
+{
+ switch (range) {
+ case QQmlProfilerDefinitions::Painting:
+ return QQmlProfilerDefinitions::ProfilePainting;
+ case QQmlProfilerDefinitions::Compiling:
+ return QQmlProfilerDefinitions::ProfileCompiling;
+ case QQmlProfilerDefinitions::Creating:
+ return QQmlProfilerDefinitions::ProfileCreating;
+ case QQmlProfilerDefinitions::Binding:
+ return QQmlProfilerDefinitions::ProfileBinding;
+ case QQmlProfilerDefinitions::HandlingSignal:
+ return QQmlProfilerDefinitions::ProfileHandlingSignal;
+ case QQmlProfilerDefinitions::Javascript:
+ return QQmlProfilerDefinitions::ProfileJavaScript;
+ default:
+ return QQmlProfilerDefinitions::MaximumProfileFeature;
+ }
+}
+
+void QQmlProfilerClient::messageReceived(const QByteArray &data)
+{
+ Q_D(const QQmlProfilerClient);
+
+ QPacket stream(d->connection->currentDataStreamVersion(), data);
+
+ // Force all the 1 << <FLAG> expressions to be done in 64 bit, to silence some warnings
+ const quint64 one = static_cast<quint64>(1);
+
+ qint64 time;
+ int messageType;
+
+ stream >> time >> messageType;
+
+ if (messageType >= QQmlProfilerDefinitions::MaximumMessage) {
+ unknownEvent(static_cast<QQmlProfilerDefinitions::Message>(messageType), time, -1);
+ return;
+ }
+
+ if (messageType == QQmlProfilerDefinitions::Event) {
+ int type;
+ stream >> type;
+
+ QQmlProfilerDefinitions::EventType eventType =
+ static_cast<QQmlProfilerDefinitions::EventType>(type);
+
+ if (eventType == QQmlProfilerDefinitions::EndTrace) {
+ int engineId = -1;
+ if (!stream.atEnd())
+ stream >> engineId;
+ traceFinished(time, engineId);
+ } else if (eventType == QQmlProfilerDefinitions::AnimationFrame) {
+ if (!(d->features & one << QQmlProfilerDefinitions::ProfileAnimations))
+ return;
+
+ int frameRate, animationCount;
+ int threadId = 0;
+ stream >> frameRate >> animationCount;
+ if (!stream.atEnd())
+ stream >> threadId;
+
+ animationFrame(time, frameRate, animationCount, threadId);
+ } else if (type == QQmlProfilerDefinitions::StartTrace) {
+ int engineId = -1;
+ if (!stream.atEnd())
+ stream >> engineId;
+ traceStarted(time, engineId);
+ } else if (eventType == QQmlProfilerDefinitions::Key ||
+ eventType == QQmlProfilerDefinitions::Mouse) {
+
+ if (!(d->features & one << QQmlProfilerDefinitions::ProfileInputEvents))
+ return;
+
+ int type;
+ if (!stream.atEnd()) {
+ stream >> type;
+ } else {
+ type = (eventType == QQmlProfilerDefinitions::Key) ?
+ QQmlProfilerDefinitions::InputKeyUnknown :
+ QQmlProfilerDefinitions::InputMouseUnknown;
+ }
+
+ int a = 0;
+ if (!stream.atEnd())
+ stream >> a;
+
+ int b = 0;
+ if (!stream.atEnd())
+ stream >> b;
+
+ inputEvent(static_cast<QQmlProfilerDefinitions::InputEventType>(type), time, a, b);
+ } else {
+ unknownEvent(QQmlProfilerDefinitions::Event, time, type);
+ }
+ } else if (messageType == QQmlProfilerDefinitions::Complete) {
+ complete();
+ } else if (messageType == QQmlProfilerDefinitions::SceneGraphFrame) {
+ if (!(d->features & one << QQmlProfilerDefinitions::ProfileSceneGraph))
+ return;
+
+ int type;
+ int count = 0;
+ qint64 params[5];
+
+ stream >> type;
+ while (!stream.atEnd())
+ stream >> params[count++];
+
+ while (count < 5)
+ params[count++] = 0;
+
+ sceneGraphEvent(static_cast<QQmlProfilerDefinitions::SceneGraphFrameType>(type), time,
+ params[0], params[1], params[2], params[3], params[4]);
+ } else if (messageType == QQmlProfilerDefinitions::PixmapCacheEvent) {
+ if (!(d->features & one << QQmlProfilerDefinitions::ProfilePixmapCache))
+ return;
+
+ int type, param1 = 0, param2 = 0;
+ QString pixUrl;
+ stream >> type >> pixUrl;
+
+ QQmlProfilerDefinitions::PixmapEventType pixmapEventType =
+ static_cast<QQmlProfilerDefinitions::PixmapEventType>(type);
+
+ if (pixmapEventType == QQmlProfilerDefinitions::PixmapReferenceCountChanged ||
+ pixmapEventType == QQmlProfilerDefinitions::PixmapCacheCountChanged) {
+ stream >> param1;
+ } else if (pixmapEventType == QQmlProfilerDefinitions::PixmapSizeKnown) {
+ stream >> param1 >> param2;
+ }
+
+ pixmapCacheEvent(pixmapEventType, time, pixUrl, param1, param2);
+ } else if (messageType == QQmlProfilerDefinitions::MemoryAllocation) {
+ if (!(d->features & one << QQmlProfilerDefinitions::ProfileMemory))
+ return;
+ int type;
+ qint64 delta;
+ stream >> type >> delta;
+ memoryAllocation((QQmlProfilerDefinitions::MemoryType)type, time, delta);
+ } else {
+ int range;
+ stream >> range;
+
+ QQmlProfilerDefinitions::RangeType rangeType =
+ static_cast<QQmlProfilerDefinitions::RangeType>(range);
+
+ if (range >= QQmlProfilerDefinitions::MaximumRangeType ||
+ !(d->features & one << featureFromRangeType(rangeType)))
+ return;
+
+ if (messageType == QQmlProfilerDefinitions::RangeStart) {
+ rangeStart(rangeType, time);
+ } else if (messageType == QQmlProfilerDefinitions::RangeData) {
+ QString data;
+ stream >> data;
+ rangeData(rangeType, time, data);
+ } else if (messageType == QQmlProfilerDefinitions::RangeLocation) {
+ QQmlEventLocation location;
+ stream >> location.filename >> location.line;
+
+ if (!stream.atEnd())
+ stream >> location.column;
+
+ rangeLocation(rangeType, time, location);
+ } else if (messageType == QQmlProfilerDefinitions::RangeEnd) {
+ rangeEnd(rangeType, time);
+ } else {
+ unknownEvent(static_cast<QQmlProfilerDefinitions::Message>(messageType), time, range);
+ }
+ }
+
+ if (!stream.atEnd())
+ unknownData(stream);
+}
+QT_END_NAMESPACE
diff --git a/src/qmldebug/qqmlprofilerclient_p.h b/src/qmldebug/qqmlprofilerclient_p.h
new file mode 100644
index 0000000000..832c05fef7
--- /dev/null
+++ b/src/qmldebug/qqmlprofilerclient_p.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLPROFILERCLIENT_P_H
+#define QQMLPROFILERCLIENT_P_H
+
+#include "qqmldebugclient_p.h"
+#include "qqmleventlocation_p.h"
+#include <private/qqmlprofilerdefinitions_p.h>
+#include <private/qpacket_p.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QQmlProfilerClientPrivate;
+class QQmlProfilerClient : public QQmlDebugClient
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQmlProfilerClient)
+
+public:
+ QQmlProfilerClient(QQmlDebugConnection *connection);
+ void setFeatures(quint64 features);
+
+public slots:
+ void sendRecordingStatus(bool record, int engineId = -1, quint32 flushInterval = 0);
+
+protected:
+ QQmlProfilerClient(QQmlProfilerClientPrivate &dd);
+
+private:
+ virtual void messageReceived(const QByteArray &message);
+
+ virtual void traceStarted(qint64 time, int engineId);
+ virtual void traceFinished(qint64 time, int engineId);
+
+ virtual void rangeStart(QQmlProfilerDefinitions::RangeType type, qint64 startTime);
+ virtual void rangeData(QQmlProfilerDefinitions::RangeType type, qint64 time,
+ const QString &data);
+ virtual void rangeLocation(QQmlProfilerDefinitions::RangeType type, qint64 time,
+ const QQmlEventLocation &location);
+ virtual void rangeEnd(QQmlProfilerDefinitions::RangeType type, qint64 endTime);
+
+ virtual void animationFrame(qint64 time, int frameRate, int animationCount, int threadId);
+
+ virtual void sceneGraphEvent(QQmlProfilerDefinitions::SceneGraphFrameType type, qint64 time,
+ qint64 numericData1, qint64 numericData2, qint64 numericData3,
+ qint64 numericData4, qint64 numericData5);
+
+ virtual void pixmapCacheEvent(QQmlProfilerDefinitions::PixmapEventType type, qint64 time,
+ const QString &url, int numericData1, int numericData2);
+
+ virtual void memoryAllocation(QQmlProfilerDefinitions::MemoryType type, qint64 time,
+ qint64 amount);
+
+ virtual void inputEvent(QQmlProfilerDefinitions::InputEventType type, qint64 time, int a,
+ int b);
+
+ virtual void complete();
+
+ virtual void unknownEvent(QQmlProfilerDefinitions::Message messageType, qint64 time,
+ int detailType);
+ virtual void unknownData(QPacket &stream);
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLPROFILERCLIENT_P_H
diff --git a/src/qmldebug/qqmlprofilerclient_p_p.h b/src/qmldebug/qqmlprofilerclient_p_p.h
new file mode 100644
index 0000000000..8238c97dd8
--- /dev/null
+++ b/src/qmldebug/qqmlprofilerclient_p_p.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLPROFILERCLIENT_P_P_H
+#define QQMLPROFILERCLIENT_P_P_H
+
+#include "qqmlprofilerclient_p.h"
+#include "qqmldebugclient_p_p.h"
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QQmlProfilerClientPrivate : public QQmlDebugClientPrivate
+{
+ Q_DECLARE_PUBLIC(QQmlProfilerClient)
+public:
+ QQmlProfilerClientPrivate(QQmlDebugConnection *connection);
+ quint64 features;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLPROFILERCLIENT_P_P_H
+