aboutsummaryrefslogtreecommitdiffstats
path: root/src/qmldebug
diff options
context:
space:
mode:
Diffstat (limited to 'src/qmldebug')
-rw-r--r--src/qmldebug/qmldebug.pro31
-rw-r--r--src/qmldebug/qqmldebugclient.cpp7
-rw-r--r--src/qmldebug/qqmldebugclient_p.h5
-rw-r--r--src/qmldebug/qqmldebugconnection.cpp23
-rw-r--r--src/qmldebug/qqmldebugconnection_p.h2
-rw-r--r--src/qmldebug/qqmldebugmessageclient.cpp90
-rw-r--r--src/qmldebug/qqmldebugmessageclient_p.h82
-rw-r--r--src/qmldebug/qqmlenginecontrolclient.cpp40
-rw-r--r--src/qmldebug/qqmlenginedebugclient.cpp566
-rw-r--r--src/qmldebug/qqmlenginedebugclient_p.h168
-rw-r--r--src/qmldebug/qqmlenginedebugclient_p_p.h76
-rw-r--r--src/qmldebug/qqmlinspectorclient.cpp150
-rw-r--r--src/qmldebug/qqmlinspectorclient_p.h85
-rw-r--r--src/qmldebug/qqmlinspectorclient_p_p.h (renamed from src/qmldebug/qqmleventlocation_p.h)26
-rw-r--r--src/qmldebug/qqmlpreviewclient.cpp139
-rw-r--r--src/qmldebug/qqmlpreviewclient_p.h111
-rw-r--r--src/qmldebug/qqmlpreviewclient_p_p.h70
-rw-r--r--src/qmldebug/qqmlprofilerclient.cpp515
-rw-r--r--src/qmldebug/qqmlprofilerclient_p.h62
-rw-r--r--src/qmldebug/qqmlprofilerclient_p_p.h63
-rw-r--r--src/qmldebug/qqmlprofilerclientdefinitions_p.h163
-rw-r--r--src/qmldebug/qqmlprofilerevent.cpp273
-rw-r--r--src/qmldebug/qqmlprofilerevent_p.h355
-rw-r--r--src/qmldebug/qqmlprofilereventlocation.cpp56
-rw-r--r--src/qmldebug/qqmlprofilereventlocation_p.h121
-rw-r--r--src/qmldebug/qqmlprofilereventreceiver_p.h74
-rw-r--r--src/qmldebug/qqmlprofilereventtype.cpp110
-rw-r--r--src/qmldebug/qqmlprofilereventtype_p.h125
-rw-r--r--src/qmldebug/qqmlprofilertypedevent.cpp224
-rw-r--r--src/qmldebug/qqmlprofilertypedevent_p.h76
-rw-r--r--src/qmldebug/qv4debugclient.cpp578
-rw-r--r--src/qmldebug/qv4debugclient_p.h121
-rw-r--r--src/qmldebug/qv4debugclient_p_p.h80
33 files changed, 4297 insertions, 370 deletions
diff --git a/src/qmldebug/qmldebug.pro b/src/qmldebug/qmldebug.pro
index e5f6de3314..94d300b765 100644
--- a/src/qmldebug/qmldebug.pro
+++ b/src/qmldebug/qmldebug.pro
@@ -1,5 +1,5 @@
TARGET = QtQmlDebug
-QT = core-private network packetprotocol-private qml-private
+QT = core-private network packetprotocol-private
CONFIG += static internal_module
load(qt_module)
@@ -7,15 +7,38 @@ load(qt_module)
SOURCES += \
qqmldebugclient.cpp \
qqmldebugconnection.cpp \
+ qqmldebugmessageclient.cpp \
qqmlenginecontrolclient.cpp \
- qqmlprofilerclient.cpp
+ qqmlenginedebugclient.cpp \
+ qqmlinspectorclient.cpp \
+ qqmlpreviewclient.cpp \
+ qqmlprofilerclient.cpp \
+ qqmlprofilerevent.cpp \
+ qqmlprofilereventlocation.cpp \
+ qqmlprofilereventtype.cpp \
+ qqmlprofilertypedevent.cpp \
+ qv4debugclient.cpp
HEADERS += \
qqmldebugclient_p.h \
qqmldebugclient_p_p.h \
qqmldebugconnection_p.h \
+ qqmldebugmessageclient_p.h \
+ qqmlenginedebugclient_p.h \
+ qqmlenginedebugclient_p_p.h \
qqmlenginecontrolclient_p.h \
qqmlenginecontrolclient_p_p.h \
- qqmleventlocation_p.h \
+ qqmlinspectorclient_p.h \
+ qqmlinspectorclient_p_p.h \
+ qqmlpreviewclient_p.h \
+ qqmlpreviewclient_p_p.h \
qqmlprofilerclient_p.h \
- qqmlprofilerclient_p_p.h
+ qqmlprofilerclient_p_p.h \
+ qqmlprofilerevent_p.h \
+ qqmlprofilereventlocation_p.h \
+ qqmlprofilereventreceiver_p.h \
+ qqmlprofilereventtype_p.h \
+ qqmlprofilertypedevent_p.h \
+ qqmlprofilerclientdefinitions_p.h \
+ qv4debugclient_p.h \
+ qv4debugclient_p_p.h
diff --git a/src/qmldebug/qqmldebugclient.cpp b/src/qmldebug/qqmldebugclient.cpp
index 7f1e8c637c..03123cc6e0 100644
--- a/src/qmldebug/qqmldebugclient.cpp
+++ b/src/qmldebug/qqmldebugclient.cpp
@@ -77,7 +77,7 @@ void QQmlDebugClientPrivate::addToConnection()
Q_Q(QQmlDebugClient);
if (connection && !connection->addClient(name, q)) {
qWarning() << "QQmlDebugClient: Conflicting plugin name" << name;
- connection = 0;
+ connection = nullptr;
}
}
@@ -117,11 +117,6 @@ QQmlDebugConnection *QQmlDebugClient::connection() const
return d->connection;
}
-void QQmlDebugClient::stateChanged(QQmlDebugClient::State state)
-{
- Q_UNUSED(state);
-}
-
void QQmlDebugClient::messageReceived(const QByteArray &message)
{
Q_UNUSED(message);
diff --git a/src/qmldebug/qqmldebugclient_p.h b/src/qmldebug/qqmldebugclient_p.h
index 723de5ee43..469b65d4a9 100644
--- a/src/qmldebug/qqmldebugclient_p.h
+++ b/src/qmldebug/qqmldebugclient_p.h
@@ -76,13 +76,14 @@ public:
QQmlDebugConnection *connection() const;
+signals:
+ void stateChanged(State state);
+
protected:
QQmlDebugClient(QQmlDebugClientPrivate &dd);
private:
friend class QQmlDebugConnection;
-
- virtual void stateChanged(State state);
virtual void messageReceived(const QByteArray &message);
};
diff --git a/src/qmldebug/qqmldebugconnection.cpp b/src/qmldebug/qqmldebugconnection.cpp
index 73ccd7c854..4e087ee6db 100644
--- a/src/qmldebug/qqmldebugconnection.cpp
+++ b/src/qmldebug/qqmldebugconnection.cpp
@@ -63,15 +63,15 @@ class QQmlDebugConnectionPrivate : public QObjectPrivate
public:
QQmlDebugConnectionPrivate();
- QPacketProtocol *protocol;
- QIODevice *device;
- QLocalServer *server;
+ QPacketProtocol *protocol = nullptr;
+ QIODevice *device = nullptr;
+ QLocalServer *server = nullptr;
QEventLoop handshakeEventLoop;
QTimer handshakeTimer;
- bool gotHello;
- int currentDataStreamVersion;
- int maximumDataStreamVersion;
+ bool gotHello = false;
+ int currentDataStreamVersion = QDataStream::Qt_4_7;
+ int maximumDataStreamVersion = QDataStream::Qt_DefaultCompiledVersion;
QHash <QString, float> serverPlugins;
QHash<QString, QQmlDebugClient *> plugins;
QStringList removedPlugins;
@@ -81,10 +81,7 @@ public:
void flush();
};
-QQmlDebugConnectionPrivate::QQmlDebugConnectionPrivate() :
- protocol(0), device(0), server(0), gotHello(false),
- currentDataStreamVersion(QDataStream::Qt_4_7),
- maximumDataStreamVersion(QDataStream::Qt_DefaultCompiledVersion)
+QQmlDebugConnectionPrivate::QQmlDebugConnectionPrivate()
{
handshakeTimer.setSingleShot(true);
handshakeTimer.setInterval(3000);
@@ -262,7 +259,7 @@ QQmlDebugConnection::~QQmlDebugConnection()
Q_D(QQmlDebugConnection);
QHash<QString, QQmlDebugClient*>::iterator iter = d->plugins.begin();
for (; iter != d->plugins.end(); ++iter)
- iter.value()->stateChanged(QQmlDebugClient::NotConnected);
+ emit iter.value()->stateChanged(QQmlDebugClient::NotConnected);
}
int QQmlDebugConnection::currentDataStreamVersion() const
@@ -298,12 +295,12 @@ void QQmlDebugConnection::close()
QHash<QString, QQmlDebugClient*>::iterator iter = d->plugins.begin();
for (; iter != d->plugins.end(); ++iter)
- iter.value()->stateChanged(QQmlDebugClient::NotConnected);
+ emit iter.value()->stateChanged(QQmlDebugClient::NotConnected);
}
if (d->device) {
d->device->deleteLater();
- d->device = 0;
+ d->device = nullptr;
}
}
diff --git a/src/qmldebug/qqmldebugconnection_p.h b/src/qmldebug/qqmldebugconnection_p.h
index be425b6cbf..ad9376886c 100644
--- a/src/qmldebug/qqmldebugconnection_p.h
+++ b/src/qmldebug/qqmldebugconnection_p.h
@@ -64,7 +64,7 @@ class QQmlDebugConnection : public QObject
Q_DISABLE_COPY(QQmlDebugConnection)
Q_DECLARE_PRIVATE(QQmlDebugConnection)
public:
- QQmlDebugConnection(QObject *parent = 0);
+ QQmlDebugConnection(QObject *parent = nullptr);
~QQmlDebugConnection();
void connectToHost(const QString &hostName, quint16 port);
diff --git a/src/qmldebug/qqmldebugmessageclient.cpp b/src/qmldebug/qqmldebugmessageclient.cpp
new file mode 100644
index 0000000000..0892404194
--- /dev/null
+++ b/src/qmldebug/qqmldebugmessageclient.cpp
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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 "qqmldebugmessageclient_p.h"
+
+#include <QtCore/qdatastream.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QQmlDebugMessageClient
+ \internal
+
+ \brief Client for the debug message service
+
+ The QQmlDebugMessageClient receives debug messages routed through the QML
+ debug connection via QDebugMessageService.
+ */
+
+QQmlDebugMessageClient::QQmlDebugMessageClient(QQmlDebugConnection *client)
+ : QQmlDebugClient(QLatin1String("DebugMessages"), client)
+{
+}
+
+void QQmlDebugMessageClient::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;
+ QQmlDebugContextInfo info;
+ info.line = line;
+ info.file = QString::fromUtf8(file);
+ info.function = QString::fromUtf8(function);
+ info.timestamp = -1;
+ if (!ds.atEnd()) {
+ QByteArray category;
+ ds >> category;
+ info.category = QString::fromUtf8(category);
+ if (!ds.atEnd())
+ ds >> info.timestamp;
+ }
+ emit message(QtMsgType(type), QString::fromUtf8(debugMessage), info);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/qmldebug/qqmldebugmessageclient_p.h b/src/qmldebug/qqmldebugmessageclient_p.h
new file mode 100644
index 0000000000..a2a7f28f81
--- /dev/null
+++ b/src/qmldebug/qqmldebugmessageclient_p.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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 QQMLDEBUGMESSAGECLIENT_P_H
+#define QQMLDEBUGMESSAGECLIENT_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
+
+struct QQmlDebugContextInfo
+{
+ int line;
+ QString file;
+ QString function;
+ QString category;
+ qint64 timestamp;
+};
+
+class QQmlDebugMessageClient : public QQmlDebugClient
+{
+ Q_OBJECT
+
+public:
+ explicit QQmlDebugMessageClient(QQmlDebugConnection *client);
+
+ virtual void messageReceived(const QByteArray &) override;
+
+signals:
+ void message(QtMsgType, const QString &, const QQmlDebugContextInfo &);
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLDEBUGMESSAGECLIENT_P_H
diff --git a/src/qmldebug/qqmlenginecontrolclient.cpp b/src/qmldebug/qqmlenginecontrolclient.cpp
index 3f75298e51..cdc724ef2f 100644
--- a/src/qmldebug/qqmlenginecontrolclient.cpp
+++ b/src/qmldebug/qqmlenginecontrolclient.cpp
@@ -41,7 +41,6 @@
#include "qqmlenginecontrolclient_p_p.h"
#include "qqmldebugconnection_p.h"
-#include <private/qqmldebugserviceinterfaces_p.h>
#include <private/qpacket_p.h>
QT_BEGIN_NAMESPACE
@@ -99,8 +98,8 @@ void QQmlEngineControlClient::messageReceived(const QByteArray &data)
{
Q_D(QQmlEngineControlClient);
QPacket stream(d->connection->currentDataStreamVersion(), data);
- int message;
- int id;
+ qint32 message;
+ qint32 id;
QString name;
stream >> message >> id;
@@ -108,36 +107,41 @@ void QQmlEngineControlClient::messageReceived(const QByteArray &data)
if (!stream.atEnd())
stream >> name;
- QQmlEngineControlClientPrivate::EngineState &state = d->blockedEngines[id];
- Q_ASSERT(state.blockers == 0);
- Q_ASSERT(state.releaseCommand == QQmlEngineControlClientPrivate::InvalidCommand);
+ auto handleWaiting = [&](
+ QQmlEngineControlClientPrivate::CommandType command, std::function<void()> emitter) {
+ QQmlEngineControlClientPrivate::EngineState &state = d->blockedEngines[id];
+ Q_ASSERT(state.blockers == 0);
+ Q_ASSERT(state.releaseCommand == QQmlEngineControlClientPrivate::InvalidCommand);
+ state.releaseCommand = command;
+ emitter();
+ if (state.blockers == 0) {
+ d->sendCommand(state.releaseCommand, id);
+ d->blockedEngines.remove(id);
+ }
+ };
switch (message) {
case QQmlEngineControlClientPrivate::EngineAboutToBeAdded:
- state.releaseCommand = QQmlEngineControlClientPrivate::StartWaitingEngine;
- emit engineAboutToBeAdded(id, name);
+ handleWaiting(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);
+ handleWaiting(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)
+ QQmlDebugClientPrivate(QLatin1String("EngineControl"), connection)
{
}
@@ -146,7 +150,7 @@ void QQmlEngineControlClientPrivate::sendCommand(
{
Q_Q(QQmlEngineControlClient);
QPacket stream(connection->currentDataStreamVersion());
- stream << int(command) << engineId;
+ stream << static_cast<qint32>(command) << engineId;
q->sendMessage(stream.data());
}
diff --git a/src/qmldebug/qqmlenginedebugclient.cpp b/src/qmldebug/qqmlenginedebugclient.cpp
new file mode 100644
index 0000000000..ec45ec33bc
--- /dev/null
+++ b/src/qmldebug/qqmlenginedebugclient.cpp
@@ -0,0 +1,566 @@
+/****************************************************************************
+**
+** 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:GPL-EXCEPT$
+** 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 General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** 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-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlenginedebugclient_p_p.h"
+#include <private/qqmldebugconnection_p.h>
+
+QT_BEGIN_NAMESPACE
+
+struct QQmlObjectData {
+ QUrl url;
+ int lineNumber = -1;
+ int columnNumber = -1;
+ QString idString;
+ QString objectName;
+ QString objectType;
+ int objectId = -1;
+ int contextId = -1;
+ int parentId = -1;
+};
+
+QPacket &operator>>(QPacket &ds, QQmlObjectData &data)
+{
+ ds >> data.url >> data.lineNumber >> data.columnNumber >> data.idString
+ >> data.objectName >> data.objectType >> data.objectId >> data.contextId
+ >> data.parentId;
+ return ds;
+}
+
+struct QQmlObjectProperty {
+ enum Type { Unknown, Basic, Object, List, SignalProperty };
+ Type type = Unknown;
+ QString name;
+ QVariant value;
+ QString valueTypeName;
+ QString binding;
+ bool hasNotifySignal = false;
+};
+
+QPacket &operator>>(QPacket &ds, QQmlObjectProperty &data)
+{
+ int type;
+ ds >> type >> data.name >> data.value >> data.valueTypeName
+ >> data.binding >> data.hasNotifySignal;
+ data.type = (QQmlObjectProperty::Type)type;
+ return ds;
+}
+
+QQmlEngineDebugClient::QQmlEngineDebugClient(QQmlDebugConnection *connection) :
+ QQmlDebugClient(*new QQmlEngineDebugClientPrivate(connection))
+{
+}
+
+QQmlEngineDebugClientPrivate::QQmlEngineDebugClientPrivate(QQmlDebugConnection *connection) :
+ QQmlDebugClientPrivate (QLatin1String("QmlDebugger"), connection)
+{
+}
+
+
+quint32 QQmlEngineDebugClient::addWatch(
+ const QQmlEngineDebugPropertyReference &property, bool *success)
+{
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("WATCH_PROPERTY") << id << property.objectDebugId
+ << property.name.toUtf8();
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::addWatch(
+ const QQmlEngineDebugContextReference &, const QString &, bool *success)
+{
+ *success = false;
+ qWarning("QQmlEngineDebugClient::addWatch(): Not implemented");
+ return 0;
+}
+
+quint32 QQmlEngineDebugClient::addWatch(
+ const QQmlEngineDebugObjectReference &object, const QString &expr,
+ bool *success)
+{
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("WATCH_EXPR_OBJECT") << id << object.debugId << expr;
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::addWatch(
+ const QQmlEngineDebugObjectReference &object, bool *success)
+{
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("WATCH_OBJECT") << id << object.debugId;
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::addWatch(
+ const QQmlEngineDebugFileReference &, bool *success)
+{
+ *success = false;
+ qWarning("QQmlEngineDebugClient::addWatch(): Not implemented");
+ return 0;
+}
+
+void QQmlEngineDebugClient::removeWatch(quint32 id, bool *success)
+{
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled) {
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("NO_WATCH") << id;
+ sendMessage(ds.data());
+ *success = true;
+ }
+}
+
+quint32 QQmlEngineDebugClient::queryAvailableEngines(bool *success)
+{
+ Q_D(QQmlEngineDebugClient);
+ d->engines.clear();
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("LIST_ENGINES") << id;
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::queryRootContexts(
+ const QQmlEngineDebugEngineReference &engine, bool *success)
+{
+ Q_D(QQmlEngineDebugClient);
+ d->rootContext = QQmlEngineDebugContextReference();
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled && engine.debugId != -1) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("LIST_OBJECTS") << id << engine.debugId;
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::queryObject(
+ const QQmlEngineDebugObjectReference &object, bool *success)
+{
+ Q_D(QQmlEngineDebugClient);
+ d->object = QQmlEngineDebugObjectReference();
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled && object.debugId != -1) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("FETCH_OBJECT") << id << object.debugId << false << true;
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::queryObjectsForLocation(
+ const QString &file, int lineNumber, int columnNumber, bool *success)
+{
+ Q_D(QQmlEngineDebugClient);
+ d->objects.clear();
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("FETCH_OBJECTS_FOR_LOCATION") << id << file << lineNumber
+ << columnNumber << false << true;
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::queryObjectRecursive(
+ const QQmlEngineDebugObjectReference &object, bool *success)
+{
+ Q_D(QQmlEngineDebugClient);
+ d->object = QQmlEngineDebugObjectReference();
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled && object.debugId != -1) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("FETCH_OBJECT") << id << object.debugId << true << true;
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::queryObjectsForLocationRecursive(const QString &file,
+ int lineNumber, int columnNumber, bool *success)
+{
+ Q_D(QQmlEngineDebugClient);
+ d->objects.clear();
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("FETCH_OBJECTS_FOR_LOCATION") << id << file << lineNumber
+ << columnNumber << true << true;
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::queryExpressionResult(
+ int objectDebugId, const QString &expr, bool *success)
+{
+ Q_D(QQmlEngineDebugClient);
+ d->exprResult = QVariant();
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("EVAL_EXPRESSION") << id << objectDebugId << expr
+ << engines()[0].debugId;
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::queryExpressionResultBC(
+ int objectDebugId, const QString &expr, bool *success)
+{
+ Q_D(QQmlEngineDebugClient);
+ d->exprResult = QVariant();
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("EVAL_EXPRESSION") << id << objectDebugId << expr;
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::setBindingForObject(
+ int objectDebugId,
+ const QString &propertyName,
+ const QVariant &bindingExpression,
+ bool isLiteralValue,
+ const QString &source, int line,
+ bool *success)
+{
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled && objectDebugId != -1) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("SET_BINDING") << id << objectDebugId << propertyName
+ << bindingExpression << isLiteralValue << source << line;
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::resetBindingForObject(
+ int objectDebugId,
+ const QString &propertyName,
+ bool *success)
+{
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled && objectDebugId != -1) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("RESET_BINDING") << id << objectDebugId << propertyName;
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+quint32 QQmlEngineDebugClient::setMethodBody(
+ int objectDebugId, const QString &methodName,
+ const QString &methodBody, bool *success)
+{
+ quint32 id = -1;
+ *success = false;
+ if (state() == QQmlDebugClient::Enabled && objectDebugId != -1) {
+ id = getId();
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("SET_METHOD_BODY") << id << objectDebugId
+ << methodName << methodBody;
+ sendMessage(ds.data());
+ *success = true;
+ }
+ return id;
+}
+
+void QQmlEngineDebugClient::decode(QPacket &ds,
+ QQmlEngineDebugObjectReference &o,
+ bool simple)
+{
+ QQmlObjectData data;
+ ds >> data;
+ o.debugId = data.objectId;
+ o.className = data.objectType;
+ o.idString = data.idString;
+ o.name = data.objectName;
+ o.source.url = data.url;
+ o.source.lineNumber = data.lineNumber;
+ o.source.columnNumber = data.columnNumber;
+ o.contextDebugId = data.contextId;
+
+ if (simple)
+ return;
+
+ int childCount;
+ bool recur;
+ ds >> childCount >> recur;
+
+ for (int ii = 0; ii < childCount; ++ii) {
+ o.children.append(QQmlEngineDebugObjectReference());
+ decode(ds, o.children.last(), !recur);
+ }
+
+ int propCount;
+ ds >> propCount;
+
+ for (int ii = 0; ii < propCount; ++ii) {
+ QQmlObjectProperty data;
+ ds >> data;
+ QQmlEngineDebugPropertyReference prop;
+ prop.objectDebugId = o.debugId;
+ prop.name = data.name;
+ prop.binding = data.binding;
+ prop.hasNotifySignal = data.hasNotifySignal;
+ prop.valueTypeName = data.valueTypeName;
+ switch (data.type) {
+ case QQmlObjectProperty::Basic:
+ case QQmlObjectProperty::List:
+ case QQmlObjectProperty::SignalProperty:
+ {
+ prop.value = data.value;
+ break;
+ }
+ case QQmlObjectProperty::Object:
+ {
+ QQmlEngineDebugObjectReference obj;
+ obj.name = data.value.toString();
+ obj.className = prop.valueTypeName;
+ prop.value = qVariantFromValue(obj);
+ break;
+ }
+ case QQmlObjectProperty::Unknown:
+ break;
+ }
+ o.properties << prop;
+ }
+}
+
+void QQmlEngineDebugClient::decode(QPacket &ds,
+ QList<QQmlEngineDebugObjectReference> &o,
+ bool simple)
+{
+ int count;
+ ds >> count;
+ for (int i = 0; i < count; i++) {
+ QQmlEngineDebugObjectReference obj;
+ decode(ds, obj, simple);
+ o << obj;
+ }
+}
+
+QList<QQmlEngineDebugEngineReference> QQmlEngineDebugClient::engines() const
+{
+ Q_D(const QQmlEngineDebugClient);
+ return d->engines;
+}
+
+QQmlEngineDebugContextReference QQmlEngineDebugClient::rootContext() const
+{
+ Q_D(const QQmlEngineDebugClient);
+ return d->rootContext;
+}
+
+QQmlEngineDebugObjectReference QQmlEngineDebugClient::object() const
+{
+ Q_D(const QQmlEngineDebugClient);
+ return d->object;
+}
+
+QList<QQmlEngineDebugObjectReference> QQmlEngineDebugClient::objects() const
+{
+ Q_D(const QQmlEngineDebugClient);
+ return d->objects;
+}
+
+QVariant QQmlEngineDebugClient::resultExpr() const
+{
+ Q_D(const QQmlEngineDebugClient);
+ return d->exprResult;
+}
+
+bool QQmlEngineDebugClient::valid() const
+{
+ Q_D(const QQmlEngineDebugClient);
+ return d->valid;
+}
+
+void QQmlEngineDebugClient::decode(QPacket &ds,
+ QQmlEngineDebugContextReference &c)
+{
+ ds >> c.name >> c.debugId;
+
+ int contextCount;
+ ds >> contextCount;
+
+ for (int ii = 0; ii < contextCount; ++ii) {
+ c.contexts.append(QQmlEngineDebugContextReference());
+ decode(ds, c.contexts.last());
+ }
+
+ int objectCount;
+ ds >> objectCount;
+
+ for (int ii = 0; ii < objectCount; ++ii) {
+ QQmlEngineDebugObjectReference obj;
+ decode(ds, obj, true);
+
+ obj.contextDebugId = c.debugId;
+ c.objects << obj;
+ }
+}
+
+void QQmlEngineDebugClient::messageReceived(const QByteArray &data)
+{
+ Q_D(QQmlEngineDebugClient);
+ d->valid = false;
+ QPacket ds(connection()->currentDataStreamVersion(), data);
+
+ int queryId;
+ QByteArray type;
+ ds >> type >> queryId;
+
+ //qDebug() << "QQmlEngineDebugPrivate::message()" << type;
+
+ if (type == "LIST_ENGINES_R") {
+ int count;
+ ds >> count;
+
+ d->engines.clear();
+ for (int ii = 0; ii < count; ++ii) {
+ QQmlEngineDebugEngineReference eng;
+ ds >> eng.name;
+ ds >> eng.debugId;
+ d->engines << eng;
+ }
+ } else if (type == "LIST_OBJECTS_R") {
+ if (!ds.atEnd())
+ decode(ds, d->rootContext);
+
+ } else if (type == "FETCH_OBJECT_R") {
+ if (!ds.atEnd())
+ decode(ds, d->object, false);
+
+ } else if (type == "FETCH_OBJECTS_FOR_LOCATION_R") {
+ if (!ds.atEnd())
+ decode(ds, d->objects, false);
+
+ } else if (type == "EVAL_EXPRESSION_R") {;
+ ds >> d->exprResult;
+
+ } else if (type == "WATCH_PROPERTY_R") {
+ ds >> d->valid;
+
+ } else if (type == "WATCH_OBJECT_R") {
+ ds >> d->valid;
+
+ } else if (type == "WATCH_EXPR_OBJECT_R") {
+ ds >> d->valid;
+
+ } else if (type == "UPDATE_WATCH") {
+ int debugId;
+ QByteArray name;
+ QVariant value;
+ ds >> debugId >> name >> value;
+ emit valueChanged(name, value);
+ return;
+
+ } else if (type == "OBJECT_CREATED") {
+ int engineId, objectId, parentId;
+ ds >> engineId >> objectId >> parentId;
+ emit newObject(objectId);
+ return;
+ } else if (type == "SET_BINDING_R") {
+ ds >> d->valid;
+ } else if (type == "RESET_BINDING_R") {
+ ds >> d->valid;
+ } else if (type == "SET_METHOD_BODY_R") {
+ ds >> d->valid;
+ } else if (type == "NO_WATCH_R") {
+ ds >> d->valid;
+ }
+ emit result();
+}
+
+
+quint32 QQmlEngineDebugClient::getId()
+{
+ Q_D(QQmlEngineDebugClient);
+ return d->nextId++;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qmldebug/qqmlenginedebugclient_p.h b/src/qmldebug/qqmlenginedebugclient_p.h
new file mode 100644
index 0000000000..4a9cc3a020
--- /dev/null
+++ b/src/qmldebug/qqmlenginedebugclient_p.h
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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:GPL-EXCEPT$
+** 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 General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** 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-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLENGINEDEBUGCLIENT_H
+#define QQMLENGINEDEBUGCLIENT_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qqmldebugclient_p.h>
+#include <private/qpacket_p.h>
+
+#include <QtCore/qurl.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
+struct QQmlEngineDebugPropertyReference
+{
+ int objectDebugId = -1;
+ QString name;
+ QVariant value;
+ QString valueTypeName;
+ QString binding;
+ bool hasNotifySignal = false;
+};
+
+struct QQmlEngineDebugFileReference
+{
+ QUrl url;
+ int lineNumber = -1;
+ int columnNumber = -1;
+};
+
+struct QQmlEngineDebugObjectReference
+{
+ int debugId = -1;
+ QString className;
+ QString idString;
+ QString name;
+ QQmlEngineDebugFileReference source;
+ int contextDebugId = -1;
+ QList<QQmlEngineDebugPropertyReference> properties;
+ QList<QQmlEngineDebugObjectReference> children;
+};
+
+struct QQmlEngineDebugContextReference
+{
+ int debugId = -1;
+ QString name;
+ QList<QQmlEngineDebugObjectReference> objects;
+ QList<QQmlEngineDebugContextReference> contexts;
+};
+
+struct QQmlEngineDebugEngineReference
+{
+ int debugId = -1;
+ QString name;
+};
+
+class QQmlEngineDebugClientPrivate;
+class QQmlEngineDebugClient : public QQmlDebugClient
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQmlEngineDebugClient)
+
+public:
+ explicit QQmlEngineDebugClient(QQmlDebugConnection *conn);
+
+ quint32 addWatch(const QQmlEngineDebugPropertyReference &,
+ bool *success);
+ quint32 addWatch(const QQmlEngineDebugContextReference &, const QString &,
+ bool *success);
+ quint32 addWatch(const QQmlEngineDebugObjectReference &, const QString &,
+ bool *success);
+ quint32 addWatch(const QQmlEngineDebugObjectReference &,
+ bool *success);
+ quint32 addWatch(const QQmlEngineDebugFileReference &,
+ bool *success);
+
+ void removeWatch(quint32 watch, bool *success);
+
+ quint32 queryAvailableEngines(bool *success);
+ quint32 queryRootContexts(const QQmlEngineDebugEngineReference &,
+ bool *success);
+ quint32 queryObject(const QQmlEngineDebugObjectReference &,
+ bool *success);
+ quint32 queryObjectsForLocation(const QString &file,
+ int lineNumber, int columnNumber, bool *success);
+ quint32 queryObjectRecursive(const QQmlEngineDebugObjectReference &,
+ bool *success);
+ quint32 queryObjectsForLocationRecursive(const QString &file,
+ int lineNumber, int columnNumber, bool *success);
+ quint32 queryExpressionResult(int objectDebugId,
+ const QString &expr,
+ bool *success);
+ quint32 queryExpressionResultBC(int objectDebugId,
+ const QString &expr,
+ bool *success);
+ quint32 setBindingForObject(int objectDebugId, const QString &propertyName,
+ const QVariant &bindingExpression,
+ bool isLiteralValue,
+ const QString &source, int line, bool *success);
+ quint32 resetBindingForObject(int objectDebugId,
+ const QString &propertyName, bool *success);
+ quint32 setMethodBody(int objectDebugId, const QString &methodName,
+ const QString &methodBody, bool *success);
+
+ quint32 getId();
+
+ void decode(QPacket &ds, QQmlEngineDebugContextReference &);
+ void decode(QPacket &ds, QQmlEngineDebugObjectReference &, bool simple);
+ void decode(QPacket &ds, QList<QQmlEngineDebugObjectReference> &o, bool simple);
+
+ QList<QQmlEngineDebugEngineReference> engines() const;
+ QQmlEngineDebugContextReference rootContext() const;
+ QQmlEngineDebugObjectReference object() const;
+ QList<QQmlEngineDebugObjectReference> objects() const;
+ QVariant resultExpr() const;
+ bool valid() const;
+
+signals:
+ void newObject(int objectId);
+ void valueChanged(QByteArray,QVariant);
+ void result();
+
+protected:
+ void messageReceived(const QByteArray &) override;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QQmlEngineDebugObjectReference)
+
+#endif // QQMLENGINEDEBUGCLIENT_H
diff --git a/src/qmldebug/qqmlenginedebugclient_p_p.h b/src/qmldebug/qqmlenginedebugclient_p_p.h
new file mode 100644
index 0000000000..7c992ad3ab
--- /dev/null
+++ b/src/qmldebug/qqmlenginedebugclient_p_p.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 QQMLENGINEDEBUGCLIENT_P_P_H
+#define QQMLENGINEDEBUGCLIENT_P_P_H
+
+#include "qqmlenginedebugclient_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 QQmlEngineDebugClientPrivate : public QQmlDebugClientPrivate
+{
+ Q_DECLARE_PUBLIC(QQmlEngineDebugClient)
+public:
+ QQmlEngineDebugClientPrivate(QQmlDebugConnection *connection);
+
+ quint32 nextId = 0;
+ bool valid = false;
+ QList<QQmlEngineDebugEngineReference> engines;
+ QQmlEngineDebugContextReference rootContext;
+ QQmlEngineDebugObjectReference object;
+ QList<QQmlEngineDebugObjectReference> objects;
+ QVariant exprResult;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLENGINEDEBUGCLIENT_P_P_H
diff --git a/src/qmldebug/qqmlinspectorclient.cpp b/src/qmldebug/qqmlinspectorclient.cpp
new file mode 100644
index 0000000000..1de52bd0c1
--- /dev/null
+++ b/src/qmldebug/qqmlinspectorclient.cpp
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 "qqmlinspectorclient_p_p.h"
+
+#include <private/qpacket_p.h>
+#include <private/qqmldebugconnection_p.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlInspectorClient::QQmlInspectorClient(QQmlDebugConnection *connection) :
+ QQmlDebugClient(*new QQmlInspectorClientPrivate(connection))
+{
+}
+
+QQmlInspectorClientPrivate::QQmlInspectorClientPrivate(QQmlDebugConnection *connection) :
+ QQmlDebugClientPrivate(QLatin1String("QmlInspector"), connection)
+{
+}
+
+int QQmlInspectorClient::setInspectToolEnabled(bool enabled)
+{
+ Q_D(QQmlInspectorClient);
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("request") << ++(d->m_lastRequestId)
+ << QByteArray(enabled ? "enable" : "disable");
+
+ sendMessage(ds.data());
+ return d->m_lastRequestId;
+}
+
+int QQmlInspectorClient::setShowAppOnTop(bool showOnTop)
+{
+ Q_D(QQmlInspectorClient);
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("request") << ++(d->m_lastRequestId)
+ << QByteArray("showAppOnTop") << showOnTop;
+
+ sendMessage(ds.data());
+ return d->m_lastRequestId;
+}
+
+int QQmlInspectorClient::setAnimationSpeed(qreal speed)
+{
+ Q_D(QQmlInspectorClient);
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("request") << ++(d->m_lastRequestId)
+ << QByteArray("setAnimationSpeed") << speed;
+
+ sendMessage(ds.data());
+ return d->m_lastRequestId;
+}
+
+int QQmlInspectorClient::select(const QList<int> &objectIds)
+{
+ Q_D(QQmlInspectorClient);
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("request") << ++(d->m_lastRequestId)
+ << QByteArray("select") << objectIds;
+
+ sendMessage(ds.data());
+ return d->m_lastRequestId;
+}
+
+int QQmlInspectorClient::createObject(const QString &qml, int parentId, const QStringList &imports,
+ const QString &filename)
+{
+ Q_D(QQmlInspectorClient);
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("request") << ++(d->m_lastRequestId)
+ << QByteArray("createObject") << qml << parentId << imports << filename;
+ sendMessage(ds.data());
+ return d->m_lastRequestId;
+}
+
+int QQmlInspectorClient::moveObject(int childId, int newParentId)
+{
+ Q_D(QQmlInspectorClient);
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("request") << ++(d->m_lastRequestId)
+ << QByteArray("moveObject") << childId << newParentId;
+ sendMessage(ds.data());
+ return d->m_lastRequestId;
+}
+
+int QQmlInspectorClient::destroyObject(int objectId)
+{
+ Q_D(QQmlInspectorClient);
+ QPacket ds(connection()->currentDataStreamVersion());
+ ds << QByteArray("request") << ++(d->m_lastRequestId)
+ << QByteArray("destroyObject") << objectId;
+ sendMessage(ds.data());
+ return d->m_lastRequestId;
+}
+
+void QQmlInspectorClient::messageReceived(const QByteArray &message)
+{
+ QPacket ds(connection()->currentDataStreamVersion(), message);
+ QByteArray type;
+ ds >> type;
+
+ if (type != QByteArray("response")) {
+ qDebug() << "Unhandled message of type" << type;
+ return;
+ }
+
+ int responseId;
+ bool result;
+ ds >> responseId >> result;
+ emit responseReceived(responseId, result);
+}
+
+QT_END_NAMESPACE
diff --git a/src/qmldebug/qqmlinspectorclient_p.h b/src/qmldebug/qqmlinspectorclient_p.h
new file mode 100644
index 0000000000..d4ab136c9a
--- /dev/null
+++ b/src/qmldebug/qqmlinspectorclient_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 QQMLINSPECTORCLIENT_P_H
+#define QQMLINSPECTORCLIENT_P_H
+
+#include <private/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 QQmlInspectorClientPrivate;
+class QQmlInspectorClient : public QQmlDebugClient
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQmlInspectorClient)
+
+public:
+ QQmlInspectorClient(QQmlDebugConnection *connection);
+
+ int setInspectToolEnabled(bool enabled);
+ int setShowAppOnTop(bool showOnTop);
+ int setAnimationSpeed(qreal speed);
+ int select(const QList<int> &objectIds);
+ int createObject(const QString &qml, int parentId, const QStringList &imports,
+ const QString &filename);
+ int moveObject(int childId, int newParentId);
+ int destroyObject(int objectId);
+
+signals:
+ void responseReceived(int requestId, bool result);
+
+protected:
+ void messageReceived(const QByteArray &message) override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLINSPECTORCLIENT_P_H
diff --git a/src/qmldebug/qqmleventlocation_p.h b/src/qmldebug/qqmlinspectorclient_p_p.h
index c3a2b93f0f..91537dd994 100644
--- a/src/qmldebug/qqmleventlocation_p.h
+++ b/src/qmldebug/qqmlinspectorclient_p_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -37,10 +37,11 @@
**
****************************************************************************/
-#ifndef QQMLEVENTLOCATION_P_H
-#define QQMLEVENTLOCATION_P_H
+#ifndef QQMLINSPECTORCLIENT_P_P_H
+#define QQMLINSPECTORCLIENT_P_P_H
-#include <QtCore/qstring.h>
+#include "qqmlinspectorclient_p.h"
+#include "qqmldebugclient_p_p.h"
//
// W A R N I N G
@@ -55,19 +56,14 @@
QT_BEGIN_NAMESPACE
-struct QQmlEventLocation
+class QQmlInspectorClientPrivate : public QQmlDebugClientPrivate
{
- 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_PUBLIC(QQmlInspectorClient)
+public:
+ QQmlInspectorClientPrivate(QQmlDebugConnection *connection);
+ int m_lastRequestId = -1;
};
-Q_DECLARE_TYPEINFO(QQmlEventLocation, Q_MOVABLE_TYPE);
-
QT_END_NAMESPACE
-#endif // QQMLEVENTLOCATION_P_H
+#endif // QQMLINSPECTORCLIENT_P_P_H
diff --git a/src/qmldebug/qqmlpreviewclient.cpp b/src/qmldebug/qqmlpreviewclient.cpp
new file mode 100644
index 0000000000..60937b9cfd
--- /dev/null
+++ b/src/qmldebug/qqmlpreviewclient.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 "qqmlpreviewclient_p_p.h"
+#include <private/qpacket_p.h>
+
+#include <QtCore/qurl.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qdir.h>
+#include <QtQml/qqmlfile.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlPreviewClient::QQmlPreviewClient(QQmlDebugConnection *connection)
+ : QQmlDebugClient(*(new QQmlPreviewClientPrivate(connection)))
+{
+}
+
+void QQmlPreviewClient::messageReceived(const QByteArray &message)
+{
+ QPacket packet(connection()->currentDataStreamVersion(), message);
+
+ qint8 command;
+ packet >> command;
+
+ switch (command) {
+ case Error: {
+ QString seviceError;
+ packet >> seviceError;
+ emit error(seviceError);
+ break;
+ }
+ case Request: {
+ QString fileName;
+ packet >> fileName;
+ emit request(fileName);
+ break;
+ }
+ case Fps: {
+ FpsInfo info;
+ packet >> info.numSyncs >> info.minSync >> info.maxSync >> info.totalSync
+ >> info.numRenders >> info.minRender >> info.maxRender >> info.totalRender;
+ emit fps(info);
+ break;
+ }
+ default:
+ emit error(QString::fromLatin1("Unknown command received: %1").arg(command));
+ break;
+ }
+}
+
+void QQmlPreviewClient::sendDirectory(const QString &path, const QStringList &entries)
+{
+ QPacket packet(connection()->currentDataStreamVersion());
+ packet << static_cast<qint8>(Directory) << path << entries;
+ sendMessage(packet.data());
+}
+
+void QQmlPreviewClient::sendFile(const QString &path, const QByteArray &contents)
+{
+ QPacket packet(connection()->currentDataStreamVersion());
+ packet << static_cast<qint8>(File) << path << contents;
+ sendMessage(packet.data());
+}
+
+void QQmlPreviewClient::sendError(const QString &path)
+{
+ QPacket packet(connection()->currentDataStreamVersion());
+ packet << static_cast<qint8>(Error) << path;
+ sendMessage(packet.data());
+}
+
+void QQmlPreviewClient::triggerLoad(const QUrl &url)
+{
+ QPacket packet(connection()->currentDataStreamVersion());
+ packet << static_cast<qint8>(Load) << url;
+ sendMessage(packet.data());
+}
+
+void QQmlPreviewClient::triggerRerun()
+{
+ QPacket packet(connection()->currentDataStreamVersion());
+ packet << static_cast<qint8>(Rerun);
+ sendMessage(packet.data());
+}
+
+void QQmlPreviewClient::triggerZoom(float factor)
+{
+ QPacket packet(connection()->currentDataStreamVersion());
+ packet << static_cast<qint8>(Zoom) << factor;
+ sendMessage(packet.data());
+}
+
+void QQmlPreviewClient::triggerLanguage(const QUrl &url, const QString &locale)
+{
+ QPacket packet(connection()->currentDataStreamVersion());
+ packet << static_cast<qint8>(Language) << url << locale;
+ sendMessage(packet.data());
+}
+
+QT_END_NAMESPACE
diff --git a/src/qmldebug/qqmlpreviewclient_p.h b/src/qmldebug/qqmlpreviewclient_p.h
new file mode 100644
index 0000000000..65661613e9
--- /dev/null
+++ b/src/qmldebug/qqmlpreviewclient_p.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 QQMLPREVIEWCLIENT_P_H
+#define QQMLPREVIEWCLIENT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qqmldebugclient_p.h>
+#include <private/qqmldebugconnection_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlPreviewClientPrivate;
+class QQmlPreviewClient : public QQmlDebugClient
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQmlPreviewClient)
+public:
+ enum Command {
+ File,
+ Load,
+ Request,
+ Error,
+ Rerun,
+ Directory,
+ ClearCache,
+ Zoom,
+ Fps,
+ Language
+ };
+
+ struct FpsInfo {
+ quint16 numSyncs = 0;
+ quint16 minSync = std::numeric_limits<quint16>::max();
+ quint16 maxSync = 0;
+ quint16 totalSync = 0;
+
+ quint16 numRenders = 0;
+ quint16 minRender = std::numeric_limits<quint16>::max();
+ quint16 maxRender = 0;
+ quint16 totalRender = 0;
+ };
+
+ QQmlPreviewClient(QQmlDebugConnection *parent);
+ void messageReceived(const QByteArray &message) override;
+
+ void sendDirectory(const QString &path, const QStringList &entries);
+ void sendFile(const QString &path, const QByteArray &contents);
+ void sendError(const QString &path);
+
+ void triggerLoad(const QUrl &url);
+ void triggerRerun();
+ void triggerZoom(float factor);
+ void triggerLanguage(const QUrl &url, const QString &locale);
+
+signals:
+ void request(const QString &path);
+ void error(const QString &message);
+ void fps(const FpsInfo &info);
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLPREVIEWCLIENT_P_H
diff --git a/src/qmldebug/qqmlpreviewclient_p_p.h b/src/qmldebug/qqmlpreviewclient_p_p.h
new file mode 100644
index 0000000000..8fb2b4b18c
--- /dev/null
+++ b/src/qmldebug/qqmlpreviewclient_p_p.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 QQMLPREVIEWCLIENT_P_P_H
+#define QQMLPREVIEWCLIENT_P_P_H
+
+#include "qqmlpreviewclient_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 QQmlPreviewClientPrivate : public QQmlDebugClientPrivate
+{
+ Q_DECLARE_PUBLIC(QQmlPreviewClient)
+public:
+ QQmlPreviewClientPrivate(QQmlDebugConnection *connection)
+ : QQmlDebugClientPrivate(QLatin1String("QmlPreview"), connection)
+ {}
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLPREVIEWCLIENT_P_P_H
diff --git a/src/qmldebug/qqmlprofilerclient.cpp b/src/qmldebug/qqmlprofilerclient.cpp
index 3676bd933c..5477af89d4 100644
--- a/src/qmldebug/qqmlprofilerclient.cpp
+++ b/src/qmldebug/qqmlprofilerclient.cpp
@@ -39,341 +39,330 @@
#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)))
+QQmlProfilerClientPrivate::~QQmlProfilerClientPrivate()
{
}
-QQmlProfilerClient::QQmlProfilerClient(QQmlProfilerClientPrivate &dd) :
- QQmlDebugClient(dd)
+int QQmlProfilerClientPrivate::resolveType(const QQmlProfilerTypedEvent &event)
{
+ int typeIndex = -1;
+ if (event.serverTypeId != 0) {
+ QHash<qint64, int>::ConstIterator it = serverTypeIds.constFind(event.serverTypeId);
+
+ if (it != serverTypeIds.constEnd()) {
+ typeIndex = it.value();
+ } else {
+ typeIndex = eventReceiver->numLoadedEventTypes();
+ eventReceiver->addEventType(event.type);
+ serverTypeIds[event.serverTypeId] = typeIndex;
+ }
+ } else {
+ QHash<QQmlProfilerEventType, int>::ConstIterator it = eventTypeIds.constFind(event.type);
+
+ if (it != eventTypeIds.constEnd()) {
+ typeIndex = it.value();
+ } else {
+ typeIndex = eventReceiver->numLoadedEventTypes();
+ eventReceiver->addEventType(event.type);
+ eventTypeIds[event.type] = typeIndex;
+ }
+ }
+ return typeIndex;
}
-QQmlProfilerClientPrivate::QQmlProfilerClientPrivate(QQmlDebugConnection *connection) :
- QQmlDebugClientPrivate(QQmlProfilerService::s_key, connection),
- features(std::numeric_limits<quint64>::max())
+int QQmlProfilerClientPrivate::resolveStackTop()
{
+ if (rangesInProgress.isEmpty())
+ return -1;
+
+ QQmlProfilerTypedEvent &typedEvent = rangesInProgress.top();
+ int typeIndex = typedEvent.event.typeIndex();
+ if (typeIndex >= 0)
+ return typeIndex;
+
+ typeIndex = resolveType(typedEvent);
+ typedEvent.event.setTypeIndex(typeIndex);
+ while (!pendingMessages.isEmpty()
+ && pendingMessages.head().timestamp() < typedEvent.event.timestamp()) {
+ forwardEvents(pendingMessages.dequeue());
+ }
+ forwardEvents(typedEvent.event);
+ return typeIndex;
}
-void QQmlProfilerClient::setFeatures(quint64 features)
+void QQmlProfilerClientPrivate::forwardEvents(const QQmlProfilerEvent &last)
{
- Q_D(QQmlProfilerClient);
- d->features = features;
+ forwardDebugMessages(last.timestamp());
+ eventReceiver->addEvent(last);
}
-void QQmlProfilerClient::sendRecordingStatus(bool record, int engineId, quint32 flushInterval)
+void QQmlProfilerClientPrivate::forwardDebugMessages(qint64 untilTimestamp)
{
- Q_D(const QQmlProfilerClient);
+ while (!pendingDebugMessages.isEmpty()
+ && pendingDebugMessages.front().timestamp() <= untilTimestamp) {
+ eventReceiver->addEvent(pendingDebugMessages.dequeue());
+ }
+}
- QPacket stream(d->connection->currentDataStreamVersion());
- stream << record << engineId << d->features << flushInterval << true;
- sendMessage(stream.data());
+void QQmlProfilerClientPrivate::processCurrentEvent()
+{
+ // RangeData and RangeLocation always apply to the range on the top of the stack. Furthermore,
+ // all ranges are perfectly nested. This is why we can defer the type resolution until either
+ // the range ends or a child range starts. With only the information in RangeStart we wouldn't
+ // be able to uniquely identify the event type.
+ Message rangeStage = currentEvent.type.rangeType() == MaximumRangeType ?
+ currentEvent.type.message() : currentEvent.event.rangeStage();
+ switch (rangeStage) {
+ case RangeStart:
+ resolveStackTop();
+ rangesInProgress.push(currentEvent);
+ break;
+ case RangeEnd: {
+ int typeIndex = resolveStackTop();
+ if (typeIndex == -1)
+ break;
+ currentEvent.event.setTypeIndex(typeIndex);
+ while (!pendingMessages.isEmpty())
+ forwardEvents(pendingMessages.dequeue());
+ forwardEvents(currentEvent.event);
+ rangesInProgress.pop();
+ break;
+ }
+ case RangeData:
+ if (!rangesInProgress.isEmpty())
+ rangesInProgress.top().type.setData(currentEvent.type.data());
+ break;
+ case RangeLocation:
+ if (!rangesInProgress.isEmpty())
+ rangesInProgress.top().type.setLocation(currentEvent.type.location());
+ break;
+ case DebugMessage:
+ currentEvent.event.setTypeIndex(resolveType(currentEvent));
+ pendingDebugMessages.enqueue(currentEvent.event);
+ break;
+ default: {
+ int typeIndex = resolveType(currentEvent);
+ currentEvent.event.setTypeIndex(typeIndex);
+ if (rangesInProgress.isEmpty())
+ forwardEvents(currentEvent.event);
+ else
+ pendingMessages.enqueue(currentEvent.event);
+ break;
+ }
+ }
}
-void QQmlProfilerClient::traceStarted(qint64 time, int engineId)
+void QQmlProfilerClientPrivate::sendRecordingStatus(int engineId)
{
- Q_UNUSED(time);
- Q_UNUSED(engineId);
+ Q_Q(QQmlProfilerClient);
+ QPacket stream(connection->currentDataStreamVersion());
+ stream << recording << engineId; // engineId -1 is OK. It means "all of them"
+ if (recording) {
+ stream << requestedFeatures << flushInterval;
+ stream << true; // yes, we support type IDs
+ }
+ q->sendMessage(stream.data());
}
-void QQmlProfilerClient::traceFinished(qint64 time, int engineId)
+QQmlProfilerClient::QQmlProfilerClient(QQmlDebugConnection *connection,
+ QQmlProfilerEventReceiver *eventReceiver,
+ quint64 features)
+ : QQmlDebugClient(*(new QQmlProfilerClientPrivate(connection, eventReceiver)))
{
- Q_UNUSED(time);
- Q_UNUSED(engineId);
+ Q_D(QQmlProfilerClient);
+ setRequestedFeatures(features);
+ connect(this, &QQmlDebugClient::stateChanged, this, &QQmlProfilerClient::onStateChanged);
+ connect(d->engineControl.data(), &QQmlEngineControlClient::engineAboutToBeAdded,
+ this, &QQmlProfilerClient::sendRecordingStatus);
+ connect(d->engineControl.data(), &QQmlEngineControlClient::engineAboutToBeRemoved,
+ this, [d](int engineId) {
+ // We may already be done with that engine. Then we don't need to block it.
+ if (d->trackedEngines.contains(engineId))
+ d->engineControl->blockEngine(engineId);
+ });
+ connect(this, &QQmlProfilerClient::traceFinished,
+ d->engineControl.data(), [d](qint64 timestamp, const QList<int> &engineIds) {
+ Q_UNUSED(timestamp);
+ // The engines might not be blocked because the trace can get finished before engine control
+ // sees them.
+ for (int blocked : d->engineControl->blockedEngines()) {
+ if (engineIds.contains(blocked))
+ d->engineControl->releaseEngine(blocked);
+ }
+ });
}
-void QQmlProfilerClient::rangeStart(QQmlProfilerDefinitions::RangeType type, qint64 startTime)
+QQmlProfilerClient::~QQmlProfilerClient()
{
- Q_UNUSED(type);
- Q_UNUSED(startTime);
+ //Disable profiling if started by client
+ //Profiling data will be lost!!
+ if (isRecording())
+ setRecording(false);
}
-void QQmlProfilerClient::rangeData(QQmlProfilerDefinitions::RangeType type, qint64 time,
- const QString &data)
+void QQmlProfilerClient::clearEvents()
{
- Q_UNUSED(type);
- Q_UNUSED(time);
- Q_UNUSED(data);
+ Q_D(QQmlProfilerClient);
+ d->rangesInProgress.clear();
+ d->pendingMessages.clear();
+ d->pendingDebugMessages.clear();
+ if (d->recordedFeatures != 0) {
+ d->recordedFeatures = 0;
+ emit recordedFeaturesChanged(0);
+ }
+ emit cleared();
}
-void QQmlProfilerClient::rangeLocation(QQmlProfilerDefinitions::RangeType type, qint64 time,
- const QQmlEventLocation &location)
+void QQmlProfilerClient::clearAll()
{
- Q_UNUSED(type);
- Q_UNUSED(time);
- Q_UNUSED(location);
+ Q_D(QQmlProfilerClient);
+ d->serverTypeIds.clear();
+ d->eventTypeIds.clear();
+ d->trackedEngines.clear();
+ clearEvents();
}
-void QQmlProfilerClient::rangeEnd(QQmlProfilerDefinitions::RangeType type, qint64 endTime)
+void QQmlProfilerClientPrivate::finalize()
{
- Q_UNUSED(type);
- Q_UNUSED(endTime);
+ while (!rangesInProgress.isEmpty()) {
+ currentEvent = rangesInProgress.top();
+ currentEvent.event.setRangeStage(RangeEnd);
+ currentEvent.event.setTimestamp(maximumTime);
+ processCurrentEvent();
+ }
+ forwardDebugMessages(std::numeric_limits<qint64>::max());
}
-void QQmlProfilerClient::animationFrame(qint64 time, int frameRate, int animationCount,
- int threadId)
+
+void QQmlProfilerClient::sendRecordingStatus(int engineId)
{
- Q_UNUSED(time);
- Q_UNUSED(frameRate);
- Q_UNUSED(animationCount);
- Q_UNUSED(threadId);
+ Q_D(QQmlProfilerClient);
+ d->sendRecordingStatus(engineId);
}
-void QQmlProfilerClient::sceneGraphEvent(QQmlProfilerDefinitions::SceneGraphFrameType type,
- qint64 time, qint64 numericData1, qint64 numericData2,
- qint64 numericData3, qint64 numericData4,
- qint64 numericData5)
+bool QQmlProfilerClient::isRecording() const
{
- Q_UNUSED(type);
- Q_UNUSED(time);
- Q_UNUSED(numericData1);
- Q_UNUSED(numericData2);
- Q_UNUSED(numericData3);
- Q_UNUSED(numericData4);
- Q_UNUSED(numericData5);
+ Q_D(const QQmlProfilerClient);
+ return d->recording;
}
-void QQmlProfilerClient::pixmapCacheEvent(QQmlProfilerDefinitions::PixmapEventType type,
- qint64 time, const QString &url, int numericData1,
- int numericData2)
+void QQmlProfilerClient::setRecording(bool v)
{
- Q_UNUSED(type);
- Q_UNUSED(time);
- Q_UNUSED(url);
- Q_UNUSED(numericData1);
- Q_UNUSED(numericData2);
+ Q_D(QQmlProfilerClient);
+ if (v == d->recording)
+ return;
+
+ d->recording = v;
+
+ if (state() == Enabled)
+ sendRecordingStatus();
+
+ emit recordingChanged(v);
}
-void QQmlProfilerClient::memoryAllocation(QQmlProfilerDefinitions::MemoryType type, qint64 time,
- qint64 amount)
+quint64 QQmlProfilerClient::recordedFeatures() const
{
- Q_UNUSED(type);
- Q_UNUSED(time);
- Q_UNUSED(amount);
+ Q_D(const QQmlProfilerClient);
+ return d->recordedFeatures;
}
-void QQmlProfilerClient::inputEvent(QQmlProfilerDefinitions::InputEventType type, qint64 time,
- int a, int b)
+void QQmlProfilerClient::setRequestedFeatures(quint64 features)
{
- Q_UNUSED(type);
- Q_UNUSED(time);
- Q_UNUSED(a);
- Q_UNUSED(b);
+ Q_D(QQmlProfilerClient);
+ d->requestedFeatures = features;
+ if (features & static_cast<quint64>(1) << ProfileDebugMessages) {
+ if (d->messageClient.isNull()) {
+ d->messageClient.reset(new QQmlDebugMessageClient(connection()));
+ connect(d->messageClient.data(), &QQmlDebugMessageClient::message, this,
+ [this](QtMsgType type, const QString &text, const QQmlDebugContextInfo &context)
+ {
+ Q_D(QQmlProfilerClient);
+ d->updateFeatures(ProfileDebugMessages);
+ d->currentEvent.event.setTimestamp(context.timestamp > 0 ? context.timestamp : 0);
+ d->currentEvent.event.setTypeIndex(-1);
+ d->currentEvent.event.setString(text);
+ d->currentEvent.type = QQmlProfilerEventType(
+ DebugMessage, MaximumRangeType, type,
+ QQmlProfilerEventLocation(context.file, context.line, 1));
+ d->currentEvent.serverTypeId = 0;
+ d->processCurrentEvent();
+ });
+ }
+ } else {
+ d->messageClient.reset();
+ }
}
-void QQmlProfilerClient::complete()
+void QQmlProfilerClient::setFlushInterval(quint32 flushInterval)
{
+ Q_D(QQmlProfilerClient);
+ d->flushInterval = flushInterval;
}
-void QQmlProfilerClient::unknownEvent(QQmlProfilerDefinitions::Message messageType, qint64 time,
- int detailType)
+QQmlProfilerClient::QQmlProfilerClient(QQmlProfilerClientPrivate &dd) :
+ QQmlDebugClient(dd)
{
- Q_UNUSED(messageType);
- Q_UNUSED(time);
- Q_UNUSED(detailType);
+ Q_D(QQmlProfilerClient);
+ connect(d->engineControl.data(), &QQmlEngineControlClient::engineAboutToBeAdded,
+ this, &QQmlProfilerClient::sendRecordingStatus);
}
-void QQmlProfilerClient::unknownData(QPacket &stream)
+bool QQmlProfilerClientPrivate::updateFeatures(ProfileFeature feature)
{
- Q_UNUSED(stream);
+ Q_Q(QQmlProfilerClient);
+ quint64 flag = 1ULL << feature;
+ if (!(requestedFeatures & flag))
+ return false;
+ if (!(recordedFeatures & flag)) {
+ recordedFeatures |= flag;
+ emit q->recordedFeaturesChanged(recordedFeatures);
+ }
+ return true;
}
-inline QQmlProfilerDefinitions::ProfileFeature featureFromRangeType(
- QQmlProfilerDefinitions::RangeType range)
+void QQmlProfilerClient::onStateChanged(State status)
{
- 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;
+ if (status == Enabled) {
+ sendRecordingStatus(-1);
+ } else {
+ Q_D(QQmlProfilerClient);
+ d->finalize();
}
+
}
void QQmlProfilerClient::messageReceived(const QByteArray &data)
{
Q_D(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;
+ stream >> d->currentEvent;
+
+ d->maximumTime = qMax(d->currentEvent.event.timestamp(), d->maximumTime);
+ if (d->currentEvent.type.message() == Complete) {
+ d->finalize();
+ emit complete(d->maximumTime);
+ } else if (d->currentEvent.type.message() == Event
+ && d->currentEvent.type.detailType() == StartTrace) {
+ const QList<int> engineIds = d->currentEvent.event.numbers<QList<int>, qint32>();
+ d->trackedEngines.append(engineIds);
+ d->forwardDebugMessages(d->currentEvent.event.timestamp());
+ emit traceStarted(d->currentEvent.event.timestamp(), engineIds);
+ } else if (d->currentEvent.type.message() == Event
+ && d->currentEvent.type.detailType() == EndTrace) {
+ const QList<int> engineIds = d->currentEvent.event.numbers<QList<int>, qint32>();
+ for (int engineId : engineIds)
+ d->trackedEngines.removeAll(engineId);
+ d->forwardDebugMessages(d->currentEvent.event.timestamp());
+ emit traceFinished(d->currentEvent.event.timestamp(), engineIds);
+ } else if (d->updateFeatures(d->currentEvent.type.feature())) {
+ d->processCurrentEvent();
}
-
- 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;
-
- qint64 typeId = 0;
- if (messageType == QQmlProfilerDefinitions::RangeStart) {
- rangeStart(rangeType, time);
- if (!stream.atEnd()) {
- stream >> typeId;
- auto i = d->types.constFind(typeId);
- if (i != d->types.constEnd()) {
- rangeLocation(rangeType, time, i->location);
- rangeData(rangeType, time, i->name);
- }
- }
- } else if (messageType == QQmlProfilerDefinitions::RangeData) {
- QString data;
- stream >> data;
- rangeData(rangeType, time, data);
- if (!stream.atEnd()) {
- stream >> typeId;
- d->types[typeId].name = data;
- }
- } else if (messageType == QQmlProfilerDefinitions::RangeLocation) {
- QQmlEventLocation location;
- stream >> location.filename >> location.line;
-
- if (!stream.atEnd())
- stream >> location.column;
-
- rangeLocation(rangeType, time, location);
- if (!stream.atEnd()) {
- stream >> typeId;
- d->types[typeId].location = 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
#include "moc_qqmlprofilerclient_p.cpp"
diff --git a/src/qmldebug/qqmlprofilerclient_p.h b/src/qmldebug/qqmlprofilerclient_p.h
index a328cad26c..89c117a8b5 100644
--- a/src/qmldebug/qqmlprofilerclient_p.h
+++ b/src/qmldebug/qqmlprofilerclient_p.h
@@ -41,8 +41,10 @@
#define QQMLPROFILERCLIENT_P_H
#include "qqmldebugclient_p.h"
-#include "qqmleventlocation_p.h"
-#include <private/qqmlprofilerdefinitions_p.h>
+#include "qqmlprofilereventlocation_p.h"
+#include "qqmlprofilereventreceiver_p.h"
+#include "qqmlprofilerclientdefinitions_p.h"
+
#include <private/qpacket_p.h>
//
@@ -63,48 +65,38 @@ class QQmlProfilerClient : public QQmlDebugClient
{
Q_OBJECT
Q_DECLARE_PRIVATE(QQmlProfilerClient)
+ Q_PROPERTY(bool recording READ isRecording WRITE setRecording NOTIFY recordingChanged)
public:
- QQmlProfilerClient(QQmlDebugConnection *connection);
- void setFeatures(quint64 features);
- void sendRecordingStatus(bool record, int engineId = -1, quint32 flushInterval = 0);
-
-protected:
- QQmlProfilerClient(QQmlProfilerClientPrivate &dd);
-
-private:
- void messageReceived(const QByteArray &message) override;
+ QQmlProfilerClient(QQmlDebugConnection *connection, QQmlProfilerEventReceiver *eventReceiver,
+ quint64 features = std::numeric_limits<quint64>::max());
+ ~QQmlProfilerClient();
- virtual void traceStarted(qint64 time, int engineId);
- virtual void traceFinished(qint64 time, int engineId);
+ bool isRecording() const;
+ void setRecording(bool);
+ quint64 recordedFeatures() const;
+ virtual void messageReceived(const QByteArray &) override;
- 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);
+ void clearEvents();
+ void clearAll();
- virtual void animationFrame(qint64 time, int frameRate, int animationCount, int threadId);
+ void sendRecordingStatus(int engineId = -1);
+ void setRequestedFeatures(quint64 features);
+ void setFlushInterval(quint32 flushInterval);
- 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);
+protected:
+ QQmlProfilerClient(QQmlProfilerClientPrivate &dd);
+ void onStateChanged(State status);
- virtual void inputEvent(QQmlProfilerDefinitions::InputEventType type, qint64 time, int a,
- int b);
+signals:
+ void complete(qint64 maximumTime);
+ void traceFinished(qint64 timestamp, const QList<int> &engineIds);
+ void traceStarted(qint64 timestamp, const QList<int> &engineIds);
- virtual void complete();
+ void recordingChanged(bool arg);
+ void recordedFeaturesChanged(quint64 features);
- virtual void unknownEvent(QQmlProfilerDefinitions::Message messageType, qint64 time,
- int detailType);
- virtual void unknownData(QPacket &stream);
+ void cleared();
};
QT_END_NAMESPACE
diff --git a/src/qmldebug/qqmlprofilerclient_p_p.h b/src/qmldebug/qqmlprofilerclient_p_p.h
index 9c44113aa8..52d42eae82 100644
--- a/src/qmldebug/qqmlprofilerclient_p_p.h
+++ b/src/qmldebug/qqmlprofilerclient_p_p.h
@@ -40,8 +40,15 @@
#ifndef QQMLPROFILERCLIENT_P_P_H
#define QQMLPROFILERCLIENT_P_P_H
-#include "qqmlprofilerclient_p.h"
#include "qqmldebugclient_p_p.h"
+#include "qqmldebugmessageclient_p.h"
+#include "qqmlenginecontrolclient_p.h"
+#include "qqmlprofilerclient_p.h"
+#include "qqmlprofilertypedevent_p.h"
+#include "qqmlprofilerclientdefinitions_p.h"
+
+#include <QtCore/qqueue.h>
+#include <QtCore/qstack.h>
//
// W A R N I N G
@@ -56,23 +63,53 @@
QT_BEGIN_NAMESPACE
-struct QQmlProfilerRangeType
-{
- QQmlEventLocation location;
- QString name;
-};
-
-class QQmlProfilerClientPrivate : public QQmlDebugClientPrivate
-{
+class QQmlProfilerClientPrivate : public QQmlDebugClientPrivate {
Q_DECLARE_PUBLIC(QQmlProfilerClient)
public:
- QQmlProfilerClientPrivate(QQmlDebugConnection *connection);
- quint64 features;
+ QQmlProfilerClientPrivate(QQmlDebugConnection *connection,
+ QQmlProfilerEventReceiver *eventReceiver)
+ : QQmlDebugClientPrivate(QLatin1String("CanvasFrameRate"), connection)
+ , eventReceiver(eventReceiver)
+ , engineControl(new QQmlEngineControlClient(connection))
+ , maximumTime(0)
+ , recording(false)
+ , requestedFeatures(0)
+ , recordedFeatures(0)
+ , flushInterval(0)
+ {
+ }
- QHash<qint64, QQmlProfilerRangeType> types;
+ virtual ~QQmlProfilerClientPrivate() override;
+
+ void sendRecordingStatus(int engineId);
+ bool updateFeatures(ProfileFeature feature);
+ int resolveType(const QQmlProfilerTypedEvent &type);
+ int resolveStackTop();
+ void forwardEvents(const QQmlProfilerEvent &last);
+ void forwardDebugMessages(qint64 untilTimestamp);
+ void processCurrentEvent();
+ void finalize();
+
+ QQmlProfilerEventReceiver *eventReceiver;
+ QScopedPointer<QQmlEngineControlClient> engineControl;
+ QScopedPointer<QQmlDebugMessageClient> messageClient;
+ qint64 maximumTime;
+ bool recording;
+ quint64 requestedFeatures;
+ quint64 recordedFeatures;
+ quint32 flushInterval;
+
+ // Reuse the same event, so that we don't have to constantly reallocate all the data.
+ QQmlProfilerTypedEvent currentEvent;
+ QHash<QQmlProfilerEventType, int> eventTypeIds;
+ QHash<qint64, int> serverTypeIds;
+ QStack<QQmlProfilerTypedEvent> rangesInProgress;
+ QQueue<QQmlProfilerEvent> pendingMessages;
+ QQueue<QQmlProfilerEvent> pendingDebugMessages;
+
+ QList<int> trackedEngines;
};
QT_END_NAMESPACE
#endif // QQMLPROFILERCLIENT_P_P_H
-
diff --git a/src/qmldebug/qqmlprofilerclientdefinitions_p.h b/src/qmldebug/qqmlprofilerclientdefinitions_p.h
new file mode 100644
index 0000000000..be1c6318af
--- /dev/null
+++ b/src/qmldebug/qqmlprofilerclientdefinitions_p.h
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 QQMLPROFILERCLIENTDEFINITIONS_P_H
+#define QQMLPROFILERCLIENTDEFINITIONS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+enum Message {
+ Event,
+ RangeStart,
+ RangeData,
+ RangeLocation,
+ RangeEnd,
+ Complete, // end of transmission
+ PixmapCacheEvent,
+ SceneGraphFrame,
+ MemoryAllocation,
+ DebugMessage,
+
+ MaximumMessage
+};
+
+enum EventType {
+ FramePaint,
+ Mouse,
+ Key,
+ AnimationFrame,
+ EndTrace,
+ StartTrace,
+
+ MaximumEventType
+};
+
+enum RangeType {
+ Painting,
+ Compiling,
+ Creating,
+ Binding, //running a binding
+ HandlingSignal, //running a signal handler
+ Javascript,
+
+ MaximumRangeType
+};
+
+enum PixmapEventType {
+ PixmapSizeKnown,
+ PixmapReferenceCountChanged,
+ PixmapCacheCountChanged,
+ PixmapLoadingStarted,
+ PixmapLoadingFinished,
+ PixmapLoadingError,
+
+ MaximumPixmapEventType
+};
+
+enum SceneGraphFrameType {
+ SceneGraphRendererFrame, // Render Thread
+ SceneGraphAdaptationLayerFrame, // Render Thread
+ SceneGraphContextFrame, // Render Thread
+ SceneGraphRenderLoopFrame, // Render Thread
+ SceneGraphTexturePrepare, // Render Thread
+ SceneGraphTextureDeletion, // Render Thread
+ SceneGraphPolishAndSync, // GUI Thread
+ SceneGraphWindowsRenderShow, // Unused
+ SceneGraphWindowsAnimations, // GUI Thread
+ SceneGraphPolishFrame, // GUI Thread
+
+ MaximumSceneGraphFrameType,
+ NumRenderThreadFrameTypes = SceneGraphPolishAndSync,
+ NumGUIThreadFrameTypes = MaximumSceneGraphFrameType - NumRenderThreadFrameTypes
+};
+
+enum MemoryType {
+ HeapPage,
+ LargeItem,
+ SmallItem
+};
+
+enum ProfileFeature {
+ ProfileJavaScript,
+ ProfileMemory,
+ ProfilePixmapCache,
+ ProfileSceneGraph,
+ ProfileAnimations,
+ ProfilePainting,
+ ProfileCompiling,
+ ProfileCreating,
+ ProfileBinding,
+ ProfileHandlingSignal,
+ ProfileInputEvents,
+ ProfileDebugMessages,
+
+ MaximumProfileFeature
+};
+
+enum InputEventType {
+ InputKeyPress,
+ InputKeyRelease,
+ InputKeyUnknown,
+
+ InputMousePress,
+ InputMouseRelease,
+ InputMouseMove,
+ InputMouseDoubleClick,
+ InputMouseWheel,
+ InputMouseUnknown,
+
+ MaximumInputEventType
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLPROFILERCLIENTDEFINITIONS_P_H
diff --git a/src/qmldebug/qqmlprofilerevent.cpp b/src/qmldebug/qqmlprofilerevent.cpp
new file mode 100644
index 0000000000..30ae1c79a1
--- /dev/null
+++ b/src/qmldebug/qqmlprofilerevent.cpp
@@ -0,0 +1,273 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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 "qqmlprofilerevent_p.h"
+#include <QtCore/qdatastream.h>
+
+QT_BEGIN_NAMESPACE
+
+bool operator==(const QQmlProfilerEvent &event1, const QQmlProfilerEvent &event2)
+{
+ if (event1.timestamp() != event2.timestamp() || event1.typeIndex() != event2.typeIndex())
+ return false;
+
+ // This is not particularly efficient, but we also don't need to do this very often.
+ return event1.numbers<QVarLengthArray<qint64>>() == event2.numbers<QVarLengthArray<qint64>>();
+}
+
+bool operator!=(const QQmlProfilerEvent &event1, const QQmlProfilerEvent &event2)
+{
+ return !(event1 == event2);
+}
+
+enum SerializationType {
+ OneByte = 0,
+ TwoByte = 1,
+ FourByte = 2,
+ EightByte = 3,
+ TypeMask = 0x3
+};
+
+enum SerializationTypeOffset {
+ TimestampOffset = 0,
+ TypeIndexOffset = 2,
+ DataLengthOffset = 4,
+ DataOffset = 6
+};
+
+template<typename Number>
+static inline void readNumbers(QDataStream &stream, Number *data, quint16 length)
+{
+ for (quint16 i = 0; i != length; ++i)
+ stream >> data[i];
+}
+
+template<typename Number>
+static inline Number readNumber(QDataStream &stream, qint8 type)
+{
+ switch (type) {
+ case OneByte: {
+ qint8 value;
+ stream >> value;
+ return static_cast<Number>(value);
+ }
+ case TwoByte: {
+ qint16 value;
+ stream >> value;
+ return static_cast<Number>(value);
+ }
+ case FourByte: {
+ qint32 value;
+ stream >> value;
+ return static_cast<Number>(value);
+ }
+ case EightByte: {
+ qint64 value;
+ stream >> value;
+ return static_cast<Number>(value);
+ }
+ default:
+ Q_UNREACHABLE();
+ return 0;
+ }
+}
+
+QDataStream &operator>>(QDataStream &stream, QQmlProfilerEvent &event)
+{
+ qint8 type;
+ stream >> type;
+
+ event.m_timestamp = readNumber<qint64>(stream, (type >> TimestampOffset) & TypeMask);
+ event.m_typeIndex = readNumber<qint32>(stream, (type >> TypeIndexOffset) & TypeMask);
+ event.m_dataLength = readNumber<quint16>(stream, (type >> DataLengthOffset) & TypeMask);
+
+ uint bytesPerNumber = 1 << ((type >> DataOffset) & TypeMask);
+
+ if (event.m_dataLength * bytesPerNumber > sizeof(event.m_data)) {
+ event.m_dataType = static_cast<QQmlProfilerEvent::Type>((bytesPerNumber * 8)
+ | QQmlProfilerEvent::External);
+ event.m_data.external = malloc(event.m_dataLength * bytesPerNumber);
+ } else {
+ event.m_dataType = static_cast<QQmlProfilerEvent::Type>(bytesPerNumber * 8);
+ }
+
+ switch (event.m_dataType) {
+ case QQmlProfilerEvent::Inline8Bit:
+ readNumbers<qint8>(stream, event.m_data.internal8bit, event.m_dataLength);
+ break;
+ case QQmlProfilerEvent::External8Bit:
+ readNumbers<qint8>(stream, static_cast<qint8 *>(event.m_data.external),
+ event.m_dataLength);
+ break;
+ case QQmlProfilerEvent::Inline16Bit:
+ readNumbers<qint16>(stream, event.m_data.internal16bit, event.m_dataLength);
+ break;
+ case QQmlProfilerEvent::External16Bit:
+ readNumbers<qint16>(stream, static_cast<qint16 *>(event.m_data.external),
+ event.m_dataLength);
+ break;
+ case QQmlProfilerEvent::Inline32Bit:
+ readNumbers<qint32>(stream, event.m_data.internal32bit, event.m_dataLength);
+ break;
+ case QQmlProfilerEvent::External32Bit:
+ readNumbers<qint32>(stream, static_cast<qint32 *>(event.m_data.external),
+ event.m_dataLength);
+ break;
+ case QQmlProfilerEvent::Inline64Bit:
+ readNumbers<qint64>(stream, event.m_data.internal64bit, event.m_dataLength);
+ break;
+ case QQmlProfilerEvent::External64Bit:
+ readNumbers<qint64>(stream, static_cast<qint64 *>(event.m_data.external),
+ event.m_dataLength);
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+
+ return stream;
+}
+
+static inline qint8 minimumType(const QQmlProfilerEvent &event, quint16 length,
+ quint16 origBitsPerNumber)
+{
+ qint8 type = OneByte;
+ bool ok = true;
+ for (quint16 i = 0; i < length;) {
+ if ((1 << type) == origBitsPerNumber / 8)
+ return type;
+ switch (type) {
+ case OneByte:
+ ok = (event.number<qint8>(i) == event.number<qint64>(i));
+ break;
+ case TwoByte:
+ ok = (event.number<qint16>(i) == event.number<qint64>(i));
+ break;
+ case FourByte:
+ ok = (event.number<qint32>(i) == event.number<qint64>(i));
+ break;
+ default:
+ // EightByte isn't possible, as (1 << type) == origBitsPerNumber / 8 then.
+ Q_UNREACHABLE();
+ break;
+ }
+
+ if (ok)
+ ++i;
+ else
+ ++type;
+ }
+ return type;
+}
+
+template<typename Number>
+static inline qint8 minimumType(Number number)
+{
+ if (static_cast<qint8>(number) == number)
+ return OneByte;
+ if (static_cast<qint16>(number) == number)
+ return TwoByte;
+ if (static_cast<qint32>(number) == number)
+ return FourByte;
+ return EightByte;
+}
+
+template<typename Number>
+static inline void writeNumbers(QDataStream &stream, const QQmlProfilerEvent &event, quint16 length)
+{
+ for (quint16 i = 0; i != length; ++i)
+ stream << event.number<Number>(i);
+}
+
+template<typename Number>
+static inline void writeNumber(QDataStream &stream, Number number, qint8 type)
+{
+ switch (type) {
+ case OneByte:
+ stream << static_cast<qint8>(number);
+ break;
+ case TwoByte:
+ stream << static_cast<qint16>(number);
+ break;
+ case FourByte:
+ stream << static_cast<qint32>(number);
+ break;
+ case EightByte:
+ stream << static_cast<qint64>(number);
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+}
+
+QDataStream &operator<<(QDataStream &stream, const QQmlProfilerEvent &event)
+{
+ qint8 type = minimumType(event.m_timestamp); // << TimestampOffset;
+ type |= minimumType(event.m_typeIndex) << TypeIndexOffset;
+ type |= minimumType(event.m_dataLength) << DataLengthOffset;
+ type |= minimumType(event, event.m_dataLength, event.m_dataType) << DataOffset;
+ stream << type;
+
+ writeNumber(stream, event.m_timestamp, (type >> TimestampOffset) & TypeMask);
+ writeNumber(stream, event.m_typeIndex, (type >> TypeIndexOffset) & TypeMask);
+ writeNumber(stream, event.m_dataLength, (type >> DataLengthOffset) & TypeMask);
+
+ switch ((type >> DataOffset) & TypeMask) {
+ case OneByte:
+ writeNumbers<qint8>(stream, event, event.m_dataLength);
+ break;
+ case TwoByte:
+ writeNumbers<qint16>(stream, event, event.m_dataLength);
+ break;
+ case FourByte:
+ writeNumbers<qint32>(stream, event, event.m_dataLength);
+ break;
+ case EightByte:
+ writeNumbers<qint64>(stream, event, event.m_dataLength);
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+
+ return stream;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qmldebug/qqmlprofilerevent_p.h b/src/qmldebug/qqmlprofilerevent_p.h
new file mode 100644
index 0000000000..1e205d8dbb
--- /dev/null
+++ b/src/qmldebug/qqmlprofilerevent_p.h
@@ -0,0 +1,355 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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 QQMLPROFILEREVENT_P_H
+#define QQMLPROFILEREVENT_P_H
+
+#include "qqmlprofilerclientdefinitions_p.h"
+
+#include <QtCore/qstring.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qmetatype.h>
+
+#include <initializer_list>
+#include <type_traits>
+
+//
+// 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 QQmlProfilerEvent {
+ QQmlProfilerEvent() :
+ m_timestamp(-1), m_typeIndex(-1), m_dataType(Inline8Bit), m_dataLength(0)
+ {}
+
+ template<typename Number>
+ QQmlProfilerEvent(qint64 timestamp, int typeIndex, std::initializer_list<Number> list)
+ : m_timestamp(timestamp), m_typeIndex(typeIndex)
+ {
+ assignNumbers<std::initializer_list<Number>, Number>(list);
+ }
+
+ QQmlProfilerEvent(qint64 timestamp, int typeIndex, const QString &data)
+ : m_timestamp(timestamp), m_typeIndex(typeIndex)
+ {
+ assignNumbers<QByteArray, qint8>(data.toUtf8());
+ }
+
+ template<typename Number>
+ QQmlProfilerEvent(qint64 timestamp, int typeIndex, const QVector<Number> &data)
+ : m_timestamp(timestamp), m_typeIndex(typeIndex)
+ {
+ assignNumbers<QVector<Number>, Number>(data);
+ }
+
+ QQmlProfilerEvent(const QQmlProfilerEvent &other)
+ : m_timestamp(other.m_timestamp), m_typeIndex(other.m_typeIndex),
+ m_dataType(other.m_dataType), m_dataLength(other.m_dataLength)
+ {
+ assignData(other);
+ }
+
+ QQmlProfilerEvent(QQmlProfilerEvent &&other)
+ {
+ memcpy(static_cast<void *>(this), static_cast<const void *>(&other), sizeof(QQmlProfilerEvent));
+ other.m_dataType = Inline8Bit; // prevent dtor from deleting the pointer
+ }
+
+ QQmlProfilerEvent &operator=(const QQmlProfilerEvent &other)
+ {
+ if (this != &other) {
+ clearPointer();
+ m_timestamp = other.m_timestamp;
+ m_typeIndex = other.m_typeIndex;
+ m_dataType = other.m_dataType;
+ m_dataLength = other.m_dataLength;
+ assignData(other);
+ }
+ return *this;
+ }
+
+ QQmlProfilerEvent &operator=(QQmlProfilerEvent &&other)
+ {
+ if (this != &other) {
+ memcpy(static_cast<void *>(this), static_cast<const void *>(&other), sizeof(QQmlProfilerEvent));
+ other.m_dataType = Inline8Bit;
+ }
+ return *this;
+ }
+
+ ~QQmlProfilerEvent()
+ {
+ clearPointer();
+ }
+
+ qint64 timestamp() const { return m_timestamp; }
+ void setTimestamp(qint64 timestamp) { m_timestamp = timestamp; }
+
+ int typeIndex() const { return m_typeIndex; }
+ void setTypeIndex(int typeIndex) { m_typeIndex = typeIndex; }
+
+ template<typename Number>
+ Number number(int i) const
+ {
+ // Trailing zeroes can be omitted, for example for SceneGraph events
+ if (i >= m_dataLength)
+ return 0;
+ switch (m_dataType) {
+ case Inline8Bit:
+ return m_data.internal8bit[i];
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_GCC("-Warray-bounds") // Mingw 5.3 gcc doesn't get the type/length logic.
+ case Inline16Bit:
+ return m_data.internal16bit[i];
+ case Inline32Bit:
+ return m_data.internal32bit[i];
+ case Inline64Bit:
+ return m_data.internal64bit[i];
+QT_WARNING_POP
+ case External8Bit:
+ return static_cast<const qint8 *>(m_data.external)[i];
+ case External16Bit:
+ return static_cast<const qint16 *>(m_data.external)[i];
+ case External32Bit:
+ return static_cast<const qint32 *>(m_data.external)[i];
+ case External64Bit:
+ return static_cast<const qint64 *>(m_data.external)[i];
+ default:
+ return 0;
+ }
+ }
+
+ template<typename Number>
+ void setNumber(int i, Number number)
+ {
+ QVarLengthArray<Number> nums = numbers<QVarLengthArray<Number>, Number>();
+ int prevSize = nums.size();
+ if (i >= prevSize) {
+ nums.resize(i + 1);
+ // Fill with zeroes. We don't want to accidentally prevent squeezing.
+ while (prevSize < i)
+ nums[prevSize++] = 0;
+ }
+ nums[i] = number;
+ setNumbers<QVarLengthArray<Number>, Number>(nums);
+ }
+
+ template<typename Container, typename Number>
+ void setNumbers(const Container &numbers)
+ {
+ clearPointer();
+ assignNumbers<Container, Number>(numbers);
+ }
+
+ template<typename Number>
+ void setNumbers(std::initializer_list<Number> numbers)
+ {
+ setNumbers<std::initializer_list<Number>, Number>(numbers);
+ }
+
+ template<typename Container, typename Number = qint64>
+ Container numbers() const
+ {
+ Container container;
+ for (int i = 0; i < m_dataLength; ++i)
+ container.append(number<Number>(i));
+ return container;
+ }
+
+ QString string() const
+ {
+ switch (m_dataType) {
+ case External8Bit:
+ return QString::fromUtf8(static_cast<const char *>(m_data.external), m_dataLength);
+ case Inline8Bit:
+ return QString::fromUtf8(m_data.internalChar, m_dataLength);
+ default:
+ Q_UNREACHABLE();
+ return QString();
+ }
+ }
+
+ void setString(const QString &data)
+ {
+ clearPointer();
+ assignNumbers<QByteArray, char>(data.toUtf8());
+ }
+
+ Message rangeStage() const
+ {
+ Q_ASSERT(m_dataType == Inline8Bit);
+ return static_cast<Message>(m_data.internal8bit[0]);
+ }
+
+ void setRangeStage(Message stage)
+ {
+ clearPointer();
+ m_dataType = Inline8Bit;
+ m_dataLength = 1;
+ m_data.internal8bit[0] = stage;
+ }
+
+ bool isValid() const
+ {
+ return m_timestamp != -1;
+ }
+
+private:
+ enum Type: quint16 {
+ External = 1,
+ Inline8Bit = 8,
+ External8Bit = Inline8Bit | External,
+ Inline16Bit = 16,
+ External16Bit = Inline16Bit | External,
+ Inline32Bit = 32,
+ External32Bit = Inline32Bit | External,
+ Inline64Bit = 64,
+ External64Bit = Inline64Bit | External
+ };
+
+ qint64 m_timestamp;
+
+ static const int s_internalDataLength = 8;
+ union {
+ void *external;
+ char internalChar [s_internalDataLength];
+ qint8 internal8bit [s_internalDataLength];
+ qint16 internal16bit[s_internalDataLength / 2];
+ qint32 internal32bit[s_internalDataLength / 4];
+ qint64 internal64bit[s_internalDataLength / 8];
+ } m_data;
+
+ qint32 m_typeIndex;
+ Type m_dataType;
+ quint16 m_dataLength;
+
+ void assignData(const QQmlProfilerEvent &other)
+ {
+ if (m_dataType & External) {
+ uint length = m_dataLength * (other.m_dataType / 8);
+ m_data.external = malloc(length);
+ memcpy(m_data.external, other.m_data.external, length);
+ } else {
+ memcpy(&m_data, &other.m_data, sizeof(m_data));
+ }
+ }
+
+ template<typename Big, typename Small>
+ bool squeezable(Big source)
+ {
+ return static_cast<Small>(source) == source;
+ }
+
+ template<typename Container, typename Number>
+ typename std::enable_if<(sizeof(Number) > 1), bool>::type
+ squeeze(const Container &numbers)
+ {
+ typedef typename QIntegerForSize<sizeof(Number) / 2>::Signed Small;
+ foreach (Number item, numbers) {
+ if (!squeezable<Number, Small>(item))
+ return false;
+ }
+ assignNumbers<Container, Small>(numbers);
+ return true;
+ }
+
+ template<typename Container, typename Number>
+ typename std::enable_if<(sizeof(Number) <= 1), bool>::type
+ squeeze(const Container &)
+ {
+ return false;
+ }
+
+ template<typename Container, typename Number>
+ void assignNumbers(const Container &numbers)
+ {
+ Number *data;
+ m_dataLength = squeezable<size_t, quint16>(static_cast<size_t>(numbers.size())) ?
+ static_cast<quint16>(numbers.size()) : std::numeric_limits<quint16>::max();
+ if (m_dataLength > sizeof(m_data) / sizeof(Number)) {
+ if (squeeze<Container, Number>(numbers))
+ return;
+ m_dataType = static_cast<Type>((sizeof(Number) * 8) | External);
+ m_data.external = malloc(m_dataLength * sizeof(Number));
+ data = static_cast<Number *>(m_data.external);
+ } else {
+ m_dataType = static_cast<Type>(sizeof(Number) * 8);
+ data = static_cast<Number *>(m_dataType & External ? m_data.external : &m_data);
+ }
+ quint16 i = 0;
+ for (Number item : numbers) {
+ if (i >= m_dataLength)
+ break;
+ data[i++] = item;
+ }
+ }
+
+ void clearPointer()
+ {
+ if (m_dataType & External)
+ free(m_data.external);
+ }
+
+ friend QDataStream &operator>>(QDataStream &stream, QQmlProfilerEvent &event);
+ friend QDataStream &operator<<(QDataStream &stream, const QQmlProfilerEvent &event);
+};
+
+bool operator==(const QQmlProfilerEvent &event1, const QQmlProfilerEvent &event2);
+bool operator!=(const QQmlProfilerEvent &event1, const QQmlProfilerEvent &event2);
+
+QDataStream &operator>>(QDataStream &stream, QQmlProfilerEvent &event);
+QDataStream &operator<<(QDataStream &stream, const QQmlProfilerEvent &event);
+
+Q_DECLARE_TYPEINFO(QQmlProfilerEvent, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QQmlProfilerEvent)
+
+#endif // QQMLPROFILEREVENT_P_H
diff --git a/src/qmldebug/qqmlprofilereventlocation.cpp b/src/qmldebug/qqmlprofilereventlocation.cpp
new file mode 100644
index 0000000000..8be44c17a3
--- /dev/null
+++ b/src/qmldebug/qqmlprofilereventlocation.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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 "qqmlprofilereventlocation_p.h"
+
+#include <QtCore/qdatastream.h>
+
+QT_BEGIN_NAMESPACE
+
+QDataStream &operator>>(QDataStream &stream, QQmlProfilerEventLocation &location)
+{
+ return stream >> location.m_filename >> location.m_line >> location.m_column;
+}
+
+QDataStream &operator<<(QDataStream &stream, const QQmlProfilerEventLocation &location)
+{
+ return stream << location.m_filename << location.m_line << location.m_column;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qmldebug/qqmlprofilereventlocation_p.h b/src/qmldebug/qqmlprofilereventlocation_p.h
new file mode 100644
index 0000000000..6f37eab14b
--- /dev/null
+++ b/src/qmldebug/qqmlprofilereventlocation_p.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** 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 QQMLPROFILEREVENTLOCATION_P_H
+#define QQMLPROFILEREVENTLOCATION_P_H
+
+#include <QtCore/qstring.h>
+#include <QtCore/qhash.h>
+#include <QtCore/qdatastream.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 QQmlProfilerEventLocation
+{
+public:
+ QQmlProfilerEventLocation() : m_line(-1),m_column(-1) {}
+ QQmlProfilerEventLocation(const QString &file, int lineNumber, int columnNumber) :
+ m_filename(file), m_line(lineNumber), m_column(columnNumber)
+ {}
+
+ void clear()
+ {
+ m_filename.clear();
+ m_line = m_column = -1;
+ }
+
+ bool isValid() const
+ {
+ return !m_filename.isEmpty();
+ }
+
+ QString filename() const { return m_filename; }
+ int line() const { return m_line; }
+ int column() const { return m_column; }
+
+private:
+ friend QDataStream &operator>>(QDataStream &stream, QQmlProfilerEventLocation &location);
+ friend QDataStream &operator<<(QDataStream &stream, const QQmlProfilerEventLocation &location);
+
+ QString m_filename;
+ int m_line;
+ int m_column;
+};
+
+inline bool operator==(const QQmlProfilerEventLocation &location1,
+ const QQmlProfilerEventLocation &location2)
+{
+ // compare filename last as it's expensive.
+ return location1.line() == location2.line() && location1.column() == location2.column()
+ && location1.filename() == location2.filename();
+}
+
+inline bool operator!=(const QQmlProfilerEventLocation &location1,
+ const QQmlProfilerEventLocation &location2)
+{
+ return !(location1 == location2);
+}
+
+inline uint qHash(const QQmlProfilerEventLocation &location)
+{
+ return qHash(location.filename())
+ ^ ((location.line() & 0xfff) // 12 bits of line number
+ | ((location.column() << 16) & 0xff0000)); // 8 bits of column
+
+}
+
+QDataStream &operator>>(QDataStream &stream, QQmlProfilerEventLocation &location);
+QDataStream &operator<<(QDataStream &stream, const QQmlProfilerEventLocation &location);
+
+Q_DECLARE_TYPEINFO(QQmlProfilerEventLocation, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+#endif // QQMLPROFILEREVENTLOCATION_P_H
diff --git a/src/qmldebug/qqmlprofilereventreceiver_p.h b/src/qmldebug/qqmlprofilereventreceiver_p.h
new file mode 100644
index 0000000000..defe64a42e
--- /dev/null
+++ b/src/qmldebug/qqmlprofilereventreceiver_p.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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 QQMLPROFILEREVENTRECEIVER_P_H
+#define QQMLPROFILEREVENTRECEIVER_P_H
+
+#include "qqmlprofilerevent_p.h"
+#include "qqmlprofilereventtype_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 QQmlProfilerEventReceiver : public QObject
+{
+ Q_OBJECT
+public:
+ QQmlProfilerEventReceiver(QObject *parent = nullptr) : QObject(parent) {}
+
+ virtual int numLoadedEventTypes() const = 0;
+ virtual void addEventType(const QQmlProfilerEventType &type) = 0;
+ virtual void addEvent(const QQmlProfilerEvent &event) = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLPROFILEREVENTRECEIVER_P_H
diff --git a/src/qmldebug/qqmlprofilereventtype.cpp b/src/qmldebug/qqmlprofilereventtype.cpp
new file mode 100644
index 0000000000..c92e914d74
--- /dev/null
+++ b/src/qmldebug/qqmlprofilereventtype.cpp
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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 "qqmlprofilereventtype_p.h"
+#include "qqmlprofilerclientdefinitions_p.h"
+
+#include <QtCore/qdatastream.h>
+
+QT_BEGIN_NAMESPACE
+
+QDataStream &operator>>(QDataStream &stream, QQmlProfilerEventType &type)
+{
+ quint8 message;
+ quint8 rangeType;
+ stream >> type.m_displayName >> type.m_data >> type.m_location >> message >> rangeType
+ >> type.m_detailType;
+ type.m_message = static_cast<Message>(message);
+ type.m_rangeType = static_cast<RangeType>(rangeType);
+ return stream;
+}
+
+QDataStream &operator<<(QDataStream &stream, const QQmlProfilerEventType &type)
+{
+ return stream << type.m_displayName << type.m_data << type.m_location
+ << static_cast<quint8>(type.m_message) << static_cast<quint8>(type.m_rangeType)
+ << type.m_detailType;
+}
+
+ProfileFeature QQmlProfilerEventType::feature() const
+{
+ switch (m_message) {
+ case Event: {
+ switch (m_detailType) {
+ case Mouse:
+ case Key:
+ return ProfileInputEvents;
+ case AnimationFrame:
+ return ProfileAnimations;
+ default:
+ return MaximumProfileFeature;
+ }
+ }
+ case PixmapCacheEvent:
+ return ProfilePixmapCache;
+ case SceneGraphFrame:
+ return ProfileSceneGraph;
+ case MemoryAllocation:
+ return ProfileMemory;
+ case DebugMessage:
+ return ProfileDebugMessages;
+ default:
+ break;
+ }
+
+ switch (m_rangeType) {
+ case Painting:
+ return ProfilePainting;
+ case Compiling:
+ return ProfileCompiling;
+ case Creating:
+ return ProfileCreating;
+ case Binding:
+ return ProfileBinding;
+ case HandlingSignal:
+ return ProfileHandlingSignal;
+ case Javascript:
+ return ProfileJavaScript;
+ default:
+ return MaximumProfileFeature;
+ }
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/qmldebug/qqmlprofilereventtype_p.h b/src/qmldebug/qqmlprofilereventtype_p.h
new file mode 100644
index 0000000000..7189df53ef
--- /dev/null
+++ b/src/qmldebug/qqmlprofilereventtype_p.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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 QQMLPROFILEREVENTTYPE_P_H
+#define QQMLPROFILEREVENTTYPE_P_H
+
+#include "qqmlprofilereventlocation_p.h"
+#include "qqmlprofilerclientdefinitions_p.h"
+
+#include <QtCore/qstring.h>
+#include <QtCore/qmetatype.h>
+#include <QtCore/qhash.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 QQmlProfilerEventType {
+public:
+ QQmlProfilerEventType(Message message = MaximumMessage, RangeType rangeType = MaximumRangeType,
+ int detailType = -1,
+ const QQmlProfilerEventLocation &location = QQmlProfilerEventLocation(),
+ const QString &data = QString(), const QString displayName = QString()) :
+ m_displayName(displayName), m_data(data), m_location(location), m_message(message),
+ m_rangeType(rangeType), m_detailType(detailType)
+ {}
+
+ void setDisplayName(const QString &displayName) { m_displayName = displayName; }
+ void setData(const QString &data) { m_data = data; }
+ void setLocation(const QQmlProfilerEventLocation &location) { m_location = location; }
+
+ ProfileFeature feature() const;
+ QString displayName() const { return m_displayName; }
+ QString data() const { return m_data; }
+ QQmlProfilerEventLocation location() const { return m_location; }
+ Message message() const { return m_message; }
+ RangeType rangeType() const { return m_rangeType; }
+ int detailType() const { return m_detailType; }
+
+private:
+ friend QDataStream &operator>>(QDataStream &stream, QQmlProfilerEventType &type);
+ friend QDataStream &operator<<(QDataStream &stream, const QQmlProfilerEventType &type);
+
+ QString m_displayName;
+ QString m_data;
+ QQmlProfilerEventLocation m_location;
+ Message m_message;
+ RangeType m_rangeType;
+ int m_detailType; // can be EventType, BindingType, PixmapEventType or SceneGraphFrameType
+};
+
+QDataStream &operator>>(QDataStream &stream, QQmlProfilerEventType &type);
+QDataStream &operator<<(QDataStream &stream, const QQmlProfilerEventType &type);
+
+inline uint qHash(const QQmlProfilerEventType &type)
+{
+ return qHash(type.location())
+ ^ (((type.message() << 12) & 0xf000) // 4 bits message
+ | ((type.rangeType() << 24) & 0xf000000) // 4 bits rangeType
+ | ((static_cast<uint>(type.detailType()) << 28) & 0xf0000000)); // 4 bits detailType
+}
+
+inline bool operator==(const QQmlProfilerEventType &type1, const QQmlProfilerEventType &type2)
+{
+ return type1.message() == type2.message() && type1.rangeType() == type2.rangeType()
+ && type1.detailType() == type2.detailType() && type1.location() == type2.location();
+}
+
+inline bool operator!=(const QQmlProfilerEventType &type1, const QQmlProfilerEventType &type2)
+{
+ return !(type1 == type2);
+}
+
+Q_DECLARE_TYPEINFO(QQmlProfilerEventType, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QQmlProfilerEventType)
+
+#endif // QQMLPROFILEREVENTTYPE_P_H
diff --git a/src/qmldebug/qqmlprofilertypedevent.cpp b/src/qmldebug/qqmlprofilertypedevent.cpp
new file mode 100644
index 0000000000..94591ba7e3
--- /dev/null
+++ b/src/qmldebug/qqmlprofilertypedevent.cpp
@@ -0,0 +1,224 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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 "qqmlprofilertypedevent_p.h"
+#include "qqmlprofilerclientdefinitions_p.h"
+
+#include <QtCore/qvarlengtharray.h>
+
+QT_BEGIN_NAMESPACE
+
+QDataStream &operator>>(QDataStream &stream, QQmlProfilerTypedEvent &event)
+{
+ qint64 time;
+ qint32 messageType;
+ qint32 subtype;
+
+ stream >> time >> messageType;
+
+ if (messageType < 0 || messageType > MaximumMessage)
+ messageType = MaximumMessage;
+
+ RangeType rangeType = MaximumRangeType;
+ if (!stream.atEnd()) {
+ stream >> subtype;
+ if (subtype >= 0 && subtype < MaximumRangeType)
+ rangeType = static_cast<RangeType>(subtype);
+ } else {
+ subtype = -1;
+ }
+
+ event.event.setTimestamp(time > 0 ? time : 0);
+ event.event.setTypeIndex(-1);
+ event.serverTypeId = 0;
+
+ switch (messageType) {
+ case Event: {
+ event.type = QQmlProfilerEventType(
+ static_cast<Message>(messageType),
+ MaximumRangeType, subtype);
+ switch (subtype) {
+ case StartTrace:
+ case EndTrace: {
+ QVarLengthArray<qint32> engineIds;
+ while (!stream.atEnd()) {
+ qint32 id;
+ stream >> id;
+ engineIds << id;
+ }
+ event.event.setNumbers<QVarLengthArray<qint32>, qint32>(engineIds);
+ break;
+ }
+ case AnimationFrame: {
+ qint32 frameRate, animationCount;
+ qint32 threadId;
+ stream >> frameRate >> animationCount;
+ if (!stream.atEnd())
+ stream >> threadId;
+ else
+ threadId = 0;
+
+ event.event.setNumbers<qint32>({frameRate, animationCount, threadId});
+ break;
+ }
+ case Mouse:
+ case Key:
+ int inputType = (subtype == Key ? InputKeyUnknown : InputMouseUnknown);
+ if (!stream.atEnd())
+ stream >> inputType;
+ qint32 a = -1;
+ if (!stream.atEnd())
+ stream >> a;
+ qint32 b = -1;
+ if (!stream.atEnd())
+ stream >> b;
+
+ event.event.setNumbers<qint32>({inputType, a, b});
+ break;
+ }
+
+ break;
+ }
+ case Complete: {
+ event.type = QQmlProfilerEventType(
+ static_cast<Message>(messageType),
+ MaximumRangeType, subtype);
+ break;
+ }
+ case SceneGraphFrame: {
+ QVarLengthArray<qint64> params;
+ qint64 param;
+
+ while (!stream.atEnd()) {
+ stream >> param;
+ params.push_back(param);
+ }
+
+ event.type = QQmlProfilerEventType(
+ static_cast<Message>(messageType),
+ MaximumRangeType, subtype);
+ event.event.setNumbers<QVarLengthArray<qint64>, qint64>(params);
+ break;
+ }
+ case PixmapCacheEvent: {
+ qint32 width = 0, height = 0, refcount = 0;
+ QString filename;
+ stream >> filename;
+ if (subtype == PixmapReferenceCountChanged || subtype == PixmapCacheCountChanged) {
+ stream >> refcount;
+ } else if (subtype == PixmapSizeKnown) {
+ stream >> width >> height;
+ refcount = 1;
+ }
+
+ event.type = QQmlProfilerEventType(
+ static_cast<Message>(messageType),
+ MaximumRangeType, subtype,
+ QQmlProfilerEventLocation(filename, 0, 0));
+ event.event.setNumbers<qint32>({width, height, refcount});
+ break;
+ }
+ case MemoryAllocation: {
+ qint64 delta;
+ stream >> delta;
+
+ event.type = QQmlProfilerEventType(
+ static_cast<Message>(messageType),
+ MaximumRangeType, subtype);
+ event.event.setNumbers<qint64>({delta});
+ break;
+ }
+ case RangeStart: {
+ if (!stream.atEnd()) {
+ qint64 typeId;
+ stream >> typeId;
+ if (stream.status() == QDataStream::Ok)
+ event.serverTypeId = typeId;
+ // otherwise it's the old binding type of 4 bytes
+ }
+
+ event.type = QQmlProfilerEventType(MaximumMessage, rangeType, -1);
+ event.event.setRangeStage(RangeStart);
+ break;
+ }
+ case RangeData: {
+ QString data;
+ stream >> data;
+
+ event.type = QQmlProfilerEventType(MaximumMessage, rangeType, -1,
+ QQmlProfilerEventLocation(), data);
+ event.event.setRangeStage(RangeData);
+ if (!stream.atEnd())
+ stream >> event.serverTypeId;
+ break;
+ }
+ case RangeLocation: {
+ QString filename;
+ qint32 line = 0;
+ qint32 column = 0;
+ stream >> filename >> line;
+
+ if (!stream.atEnd()) {
+ stream >> column;
+ if (!stream.atEnd())
+ stream >> event.serverTypeId;
+ }
+
+ event.type = QQmlProfilerEventType(MaximumMessage, rangeType, -1,
+ QQmlProfilerEventLocation(filename, line, column));
+ event.event.setRangeStage(RangeLocation);
+ break;
+ }
+ case RangeEnd: {
+ event.type = QQmlProfilerEventType(MaximumMessage, rangeType, -1);
+ event.event.setRangeStage(RangeEnd);
+ break;
+ }
+ default:
+ event.event.setNumbers<char>({});
+ event.type = QQmlProfilerEventType(
+ static_cast<Message>(messageType),
+ MaximumRangeType, subtype);
+ break;
+ }
+
+ return stream;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qmldebug/qqmlprofilertypedevent_p.h b/src/qmldebug/qqmlprofilertypedevent_p.h
new file mode 100644
index 0000000000..e7e947f2ef
--- /dev/null
+++ b/src/qmldebug/qqmlprofilertypedevent_p.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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 QQMLPROFILERTYPEDEVENT_P_H
+#define QQMLPROFILERTYPEDEVENT_P_H
+
+#include "qqmlprofilerevent_p.h"
+#include "qqmlprofilereventtype_p.h"
+
+#include <QtCore/qdatastream.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 QQmlProfilerTypedEvent
+{
+ QQmlProfilerEvent event;
+ QQmlProfilerEventType type;
+ qint64 serverTypeId = 0;
+};
+
+QDataStream &operator>>(QDataStream &stream, QQmlProfilerTypedEvent &event);
+
+Q_DECLARE_TYPEINFO(QQmlProfilerTypedEvent, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QQmlProfilerTypedEvent)
+
+#endif // QQMLPROFILERTYPEDEVENT_P_H
diff --git a/src/qmldebug/qv4debugclient.cpp b/src/qmldebug/qv4debugclient.cpp
new file mode 100644
index 0000000000..76c2f1ebea
--- /dev/null
+++ b/src/qmldebug/qv4debugclient.cpp
@@ -0,0 +1,578 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 "qv4debugclient_p.h"
+#include "qv4debugclient_p_p.h"
+#include "qqmldebugconnection_p.h"
+
+#include <private/qpacket_p.h>
+
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QJsonValue>
+#include <QJsonArray>
+
+QT_BEGIN_NAMESPACE
+
+const char *V8REQUEST = "v8request";
+const char *V8MESSAGE = "v8message";
+const char *SEQ = "seq";
+const char *TYPE = "type";
+const char *COMMAND = "command";
+const char *ARGUMENTS = "arguments";
+const char *STEPACTION = "stepaction";
+const char *STEPCOUNT = "stepcount";
+const char *EXPRESSION = "expression";
+const char *FRAME = "frame";
+const char *CONTEXT = "context";
+const char *GLOBAL = "global";
+const char *DISABLEBREAK = "disable_break";
+const char *HANDLES = "handles";
+const char *INCLUDESOURCE = "includeSource";
+const char *FROMFRAME = "fromFrame";
+const char *TOFRAME = "toFrame";
+const char *BOTTOM = "bottom";
+const char *NUMBER = "number";
+const char *FRAMENUMBER = "frameNumber";
+const char *TYPES = "types";
+const char *IDS = "ids";
+const char *FILTER = "filter";
+const char *FROMLINE = "fromLine";
+const char *TOLINE = "toLine";
+const char *TARGET = "target";
+const char *LINE = "line";
+const char *COLUMN = "column";
+const char *ENABLED = "enabled";
+const char *CONDITION = "condition";
+const char *IGNORECOUNT = "ignoreCount";
+const char *BREAKPOINT = "breakpoint";
+const char *FLAGS = "flags";
+
+const char *CONTINEDEBUGGING = "continue";
+const char *EVALUATE = "evaluate";
+const char *LOOKUP = "lookup";
+const char *BACKTRACE = "backtrace";
+const char *SCOPE = "scope";
+const char *SCOPES = "scopes";
+const char *SCRIPTS = "scripts";
+const char *SOURCE = "source";
+const char *SETBREAKPOINT = "setbreakpoint";
+const char *CLEARBREAKPOINT = "clearbreakpoint";
+const char *CHANGEBREAKPOINT = "changebreakpoint";
+const char *SETEXCEPTIONBREAK = "setexceptionbreak";
+const char *VERSION = "version";
+const char *DISCONNECT = "disconnect";
+const char *GARBAGECOLLECTOR = "gc";
+
+const char *CONNECT = "connect";
+const char *INTERRUPT = "interrupt";
+
+const char *REQUEST = "request";
+const char *IN = "in";
+const char *NEXT = "next";
+const char *OUT = "out";
+
+const char *SCRIPT = "script";
+const char *SCRIPTREGEXP = "scriptRegExp";
+const char *EVENT = "event";
+
+const char *ALL = "all";
+const char *UNCAUGHT = "uncaught";
+
+#define VARIANTMAPINIT \
+ Q_D(QV4DebugClient); \
+ QJsonObject jsonVal; \
+ jsonVal.insert(QLatin1String(SEQ), d->seq++); \
+ jsonVal.insert(QLatin1String(TYPE), QLatin1String(REQUEST));
+
+QV4DebugClient::QV4DebugClient(QQmlDebugConnection *connection)
+ : QQmlDebugClient(*new QV4DebugClientPrivate(connection))
+{
+ QObject::connect(this, &QQmlDebugClient::stateChanged,
+ this, [this](State state) { d_func()->onStateChanged(state); });
+}
+
+QV4DebugClientPrivate::QV4DebugClientPrivate(QQmlDebugConnection *connection) :
+ QQmlDebugClientPrivate(QLatin1String("V8Debugger"), connection)
+{
+}
+
+void QV4DebugClient::connect()
+{
+ Q_D(QV4DebugClient);
+ d->sendMessage(CONNECT);
+}
+
+void QV4DebugClient::interrupt()
+{
+ Q_D(QV4DebugClient);
+ d->sendMessage(INTERRUPT);
+}
+
+void QV4DebugClient::continueDebugging(StepAction action)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "continue",
+ // "arguments" : { "stepaction" : <"in", "next" or "out">,
+ // "stepcount" : <number of steps (default 1)>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.insert(QLatin1String(COMMAND), QLatin1String(CONTINEDEBUGGING));
+
+ if (action != Continue) {
+ QJsonObject args;
+ switch (action) {
+ case In:
+ args.insert(QLatin1String(STEPACTION), QLatin1String(IN));
+ break;
+ case Out:
+ args.insert(QLatin1String(STEPACTION), QLatin1String(OUT));
+ break;
+ case Next:
+ args.insert(QLatin1String(STEPACTION), QLatin1String(NEXT));
+ break;
+ default:
+ break;
+ }
+ jsonVal.insert(QLatin1String(ARGUMENTS), args);
+ }
+
+ d->sendMessage(V8REQUEST, jsonVal);
+}
+
+void QV4DebugClient::evaluate(const QString &expr, int frame, int context)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "evaluate",
+ // "arguments" : { "expression" : <expression to evaluate>,
+ // "frame" : <number>,
+ // "context" : <object ID>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.insert(QLatin1String(COMMAND), QLatin1String(EVALUATE));
+
+ QJsonObject args;
+ args.insert(QLatin1String(EXPRESSION), expr);
+
+ if (frame != -1)
+ args.insert(QLatin1String(FRAME), frame);
+
+ if (context != -1)
+ args.insert(QLatin1String(CONTEXT), context);
+
+ jsonVal.insert(QLatin1String(ARGUMENTS), args);
+
+ d->sendMessage(V8REQUEST, jsonVal);
+}
+
+void QV4DebugClient::lookup(const QList<int> &handles, bool includeSource)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "lookup",
+ // "arguments" : { "handles" : <array of handles>,
+ // "includeSource" : <boolean indicating whether the source will be included when script objects are returned>,
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.insert(QLatin1String(COMMAND),(QLatin1String(LOOKUP)));
+
+ QJsonObject args;
+ QJsonArray array;
+
+ for (int handle : handles)
+ array.append(handle);
+
+ args.insert(QLatin1String(HANDLES), array);
+
+ if (includeSource)
+ args.insert(QLatin1String(INCLUDESOURCE), includeSource);
+
+ jsonVal.insert(QLatin1String(ARGUMENTS), args);
+
+ d->sendMessage(V8REQUEST, jsonVal);
+}
+
+void QV4DebugClient::backtrace(int fromFrame, int toFrame, bool bottom)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "backtrace",
+ // "arguments" : { "fromFrame" : <number>
+ // "toFrame" : <number>
+ // "bottom" : <boolean, set to true if the bottom of the stack is requested>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.insert(QLatin1String(COMMAND), QLatin1String(BACKTRACE));
+
+ QJsonObject args;
+
+ if (fromFrame != -1)
+ args.insert(QLatin1String(FROMFRAME), fromFrame);
+
+ if (toFrame != -1)
+ args.insert(QLatin1String(TOFRAME), toFrame);
+
+ if (bottom)
+ args.insert(QLatin1String(BOTTOM), bottom);
+
+ jsonVal.insert(QLatin1String(ARGUMENTS), args);
+ d->sendMessage(V8REQUEST, jsonVal);
+}
+
+void QV4DebugClient::frame(int number)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "frame",
+ // "arguments" : { "number" : <frame number>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.insert(QLatin1String(COMMAND), QLatin1String(FRAME));
+
+ if (number != -1) {
+ QJsonObject args;
+ args.insert(QLatin1String(NUMBER), number);
+ jsonVal.insert(QLatin1String(ARGUMENTS), args);
+ }
+
+ d->sendMessage(V8REQUEST, jsonVal);
+}
+
+void QV4DebugClient::scope(int number, int frameNumber)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "scope",
+ // "arguments" : { "number" : <scope number>
+ // "frameNumber" : <frame number, optional uses selected frame if missing>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.insert(QLatin1String(COMMAND), QLatin1String(SCOPE));
+
+ if (number != -1) {
+ QJsonObject args;
+ args.insert(QLatin1String(NUMBER), number);
+
+ if (frameNumber != -1)
+ args.insert(QLatin1String(FRAMENUMBER), frameNumber);
+
+ jsonVal.insert(QLatin1String(ARGUMENTS), args);
+ }
+
+ d->sendMessage(V8REQUEST, jsonVal);
+}
+
+void QV4DebugClient::scripts(int types, const QList<int> &ids, bool includeSource)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "scripts",
+ // "arguments" : { "types" : <types of scripts to retrieve
+ // set bit 0 for native scripts
+ // set bit 1 for extension scripts
+ // set bit 2 for normal scripts
+ // (default is 4 for normal scripts)>
+ // "ids" : <array of id's of scripts to return. If this is not specified all scripts are requrned>
+ // "includeSource" : <boolean indicating whether the source code should be included for the scripts returned>
+ // "filter" : <string or number: filter string or script id.
+ // If a number is specified, then only the script with the same number as its script id will be retrieved.
+ // If a string is specified, then only scripts whose names contain the filter string will be retrieved.>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.insert(QLatin1String(COMMAND), QLatin1String(SCRIPTS));
+
+ QJsonObject args;
+ args.insert(QLatin1String(TYPES), types);
+
+ if (ids.count()) {
+ QJsonArray array;
+ for (int id : ids)
+ array.append(id);
+
+ args.insert(QLatin1String(IDS), array);
+ }
+
+ if (includeSource)
+ args.insert(QLatin1String(INCLUDESOURCE), includeSource);
+
+ jsonVal.insert(QLatin1String(ARGUMENTS), args);
+ d->sendMessage(V8REQUEST, jsonVal);
+}
+
+void QV4DebugClient::setBreakpoint(const QString &target, int line, int column, bool enabled,
+ const QString &condition, int ignoreCount)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "setbreakpoint",
+ // "arguments" : { "type" : "scriptRegExp"
+ // "target" : <function expression or script identification>
+ // "line" : <line in script or function>
+ // "column" : <character position within the line>
+ // "enabled" : <initial enabled state. True or false, default is true>
+ // "condition" : <string with break point condition>
+ // "ignoreCount" : <number specifying the number of break point hits to ignore, default value is 0>
+ // }
+ // }
+
+ VARIANTMAPINIT;
+ jsonVal.insert(QLatin1String(COMMAND), QLatin1String(SETBREAKPOINT));
+
+ QJsonObject args;
+
+ args.insert(QLatin1String(TYPE), QLatin1String(SCRIPTREGEXP));
+ args.insert(QLatin1String(TARGET), target);
+
+ if (line != -1)
+ args.insert(QLatin1String(LINE), line);
+
+ if (column != -1)
+ args.insert(QLatin1String(COLUMN), column);
+
+ args.insert(QLatin1String(ENABLED), enabled);
+
+ if (!condition.isEmpty())
+ args.insert(QLatin1String(CONDITION), condition);
+
+ if (ignoreCount != -1)
+ args.insert(QLatin1String(IGNORECOUNT), ignoreCount);
+
+ jsonVal.insert(QLatin1String(ARGUMENTS),args);
+ d->sendMessage(V8REQUEST, jsonVal);
+}
+
+void QV4DebugClient::clearBreakpoint(int breakpoint)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "clearbreakpoint",
+ // "arguments" : { "breakpoint" : <number of the break point to clear>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.insert(QLatin1String(COMMAND), QLatin1String(CLEARBREAKPOINT));
+
+ QJsonObject args;
+ args.insert(QLatin1String(BREAKPOINT), breakpoint);
+ jsonVal.insert(QLatin1String(ARGUMENTS),args);
+
+ d->sendMessage(V8REQUEST, jsonVal);
+}
+
+void QV4DebugClient::changeBreakpoint(int breakpoint, bool enabled)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "changebreakpoint",
+ // "arguments" : { "breakpoint" : <number of the break point to change>
+ // "enabled" : <bool: enables the break type if true, disables if false>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.insert(QLatin1String(COMMAND), QLatin1String(CHANGEBREAKPOINT));
+
+ QJsonObject args;
+ args.insert(QLatin1String(BREAKPOINT), breakpoint);
+ args.insert(QLatin1String(ENABLED), enabled);
+
+ jsonVal.insert(QLatin1String(ARGUMENTS), args);
+ d->sendMessage(V8REQUEST, jsonVal);
+}
+
+void QV4DebugClient::setExceptionBreak(Exception type, bool enabled)
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "setexceptionbreak",
+ // "arguments" : { "type" : <string: "all", or "uncaught">,
+ // "enabled" : <optional bool: enables the break type if true>
+ // }
+ // }
+ VARIANTMAPINIT;
+ jsonVal.insert(QLatin1String(COMMAND), QLatin1String(SETEXCEPTIONBREAK));
+
+ QJsonObject args;
+
+ if (type == All)
+ args.insert(QLatin1String(TYPE), QLatin1String(ALL));
+ else if (type == Uncaught)
+ args.insert(QLatin1String(TYPE), QLatin1String(UNCAUGHT));
+
+ if (enabled)
+ args.insert(QLatin1String(ENABLED), enabled);
+
+ jsonVal.insert(QLatin1String(ARGUMENTS), args);
+ d->sendMessage(V8REQUEST, jsonVal);
+}
+
+void QV4DebugClient::version()
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "version",
+ // }
+ VARIANTMAPINIT;
+ jsonVal.insert(QLatin1String(COMMAND), QLatin1String(VERSION));
+ d->sendMessage(V8REQUEST, jsonVal);
+}
+
+QV4DebugClient::Response QV4DebugClient::response() const
+{
+ Q_D(const QV4DebugClient);
+ const QJsonObject value = QJsonDocument::fromJson(d->response).object();
+ return {
+ value.value(QLatin1String(COMMAND)).toString(),
+ value.value(QLatin1String("body"))
+ };
+}
+
+void QV4DebugClient::disconnect()
+{
+ // { "seq" : <number>,
+ // "type" : "request",
+ // "command" : "disconnect",
+ // }
+ VARIANTMAPINIT;
+ jsonVal.insert(QLatin1String(COMMAND), QLatin1String(DISCONNECT));
+ d->sendMessage(DISCONNECT, jsonVal);
+}
+
+void QV4DebugClientPrivate::onStateChanged(QQmlDebugClient::State state)
+{
+ if (state == QQmlDebugClient::Enabled)
+ flushSendBuffer();
+}
+
+void QV4DebugClient::messageReceived(const QByteArray &data)
+{
+ Q_D(QV4DebugClient);
+ QPacket ds(connection()->currentDataStreamVersion(), data);
+ QByteArray command;
+ ds >> command;
+
+ if (command == "V8DEBUG") {
+ QByteArray type;
+ ds >> type >> d->response;
+
+ if (type == CONNECT) {
+ emit connected();
+
+ } else if (type == INTERRUPT) {
+ emit interrupted();
+
+ } else if (type == V8MESSAGE) {
+ const QJsonObject value = QJsonDocument::fromJson(d->response).object();
+ QString type = value.value(QLatin1String(TYPE)).toString();
+
+ if (type == QLatin1String("response")) {
+
+ if (!value.value(QLatin1String("success")).toBool()) {
+ emit failure();
+ qDebug() << "Received success == false response from application:"
+ << value.value(QLatin1String("message")).toString();
+ return;
+ }
+
+ QString debugCommand(value.value(QLatin1String(COMMAND)).toString());
+ if (debugCommand == QLatin1String(BACKTRACE) ||
+ debugCommand == QLatin1String(LOOKUP) ||
+ debugCommand == QLatin1String(SETBREAKPOINT) ||
+ debugCommand == QLatin1String(EVALUATE) ||
+ debugCommand == QLatin1String(VERSION) ||
+ debugCommand == QLatin1String(DISCONNECT) ||
+ debugCommand == QLatin1String(GARBAGECOLLECTOR) ||
+ debugCommand == QLatin1String(CHANGEBREAKPOINT) ||
+ debugCommand == QLatin1String(CLEARBREAKPOINT) ||
+ debugCommand == QLatin1String(FRAME) ||
+ debugCommand == QLatin1String(SCOPE) ||
+ debugCommand == QLatin1String(SCOPES) ||
+ debugCommand == QLatin1String(SCRIPTS) ||
+ debugCommand == QLatin1String(SOURCE) ||
+ debugCommand == QLatin1String(SETEXCEPTIONBREAK)) {
+ emit result();
+ } else {
+ // DO NOTHING
+ }
+
+ } else if (type == QLatin1String(EVENT)) {
+ QString event(value.value(QLatin1String(EVENT)).toString());
+
+ if (event == QLatin1String("break") || event == QLatin1String("exception"))
+ emit stopped();
+ }
+ }
+ }
+}
+
+void QV4DebugClientPrivate::sendMessage(const QByteArray &command, const QJsonObject &args)
+{
+ Q_Q(QV4DebugClient);
+ const QByteArray msg = packMessage(command, args);
+ if (q->state() == QQmlDebugClient::Enabled) {
+ q->sendMessage(msg);
+ } else {
+ sendBuffer.append(msg);
+ }
+}
+
+void QV4DebugClientPrivate::flushSendBuffer()
+{
+ foreach (const QByteArray &msg, sendBuffer)
+ sendMessage(msg);
+ sendBuffer.clear();
+}
+
+QByteArray QV4DebugClientPrivate::packMessage(const QByteArray &type, const QJsonObject &object)
+{
+ QPacket rs(connection->currentDataStreamVersion());
+ QByteArray cmd = "V8DEBUG";
+ rs << cmd << type << QJsonDocument(object).toJson(QJsonDocument::Compact);
+ return rs.data();
+}
+
+QT_END_NAMESPACE
diff --git a/src/qmldebug/qv4debugclient_p.h b/src/qmldebug/qv4debugclient_p.h
new file mode 100644
index 0000000000..fdcf4284c5
--- /dev/null
+++ b/src/qmldebug/qv4debugclient_p.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 QV4DEBUGCLIENT_P_H
+#define QV4DEBUGCLIENT_P_H
+
+#include <QtQmlDebug/private/qqmldebugclient_p.h>
+#include <QtCore/qjsonvalue.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 QV4DebugClientPrivate;
+class QV4DebugClient : public QQmlDebugClient
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QV4DebugClient)
+
+public:
+ enum StepAction
+ {
+ Continue,
+ In,
+ Out,
+ Next
+ };
+
+ enum Exception
+ {
+ All,
+ Uncaught
+ };
+
+ struct Response
+ {
+ QString command;
+ QJsonValue body;
+ };
+
+ QV4DebugClient(QQmlDebugConnection *connection);
+
+ void connect();
+ void disconnect();
+
+ void interrupt();
+ void continueDebugging(StepAction stepAction);
+ void evaluate(const QString &expr, int frame = -1, int context = -1);
+ void lookup(const QList<int> &handles, bool includeSource = false);
+ void backtrace(int fromFrame = -1, int toFrame = -1, bool bottom = false);
+ void frame(int number = -1);
+ void scope(int number = -1, int frameNumber = -1);
+ void scripts(int types = 4, const QList<int> &ids = QList<int>(), bool includeSource = false);
+ void setBreakpoint(const QString &target, int line = -1, int column = -1, bool enabled = true,
+ const QString &condition = QString(), int ignoreCount = -1);
+ void clearBreakpoint(int breakpoint);
+ void changeBreakpoint(int breakpoint, bool enabled);
+ void setExceptionBreak(Exception type, bool enabled = false);
+ void version();
+
+ Response response() const;
+
+protected:
+ void messageReceived(const QByteArray &data) override;
+
+signals:
+ void connected();
+ void interrupted();
+ void result();
+ void failure();
+ void stopped();
+};
+
+QT_END_NAMESPACE
+
+#endif // QV4DEBUGCLIENT_P_H
diff --git a/src/qmldebug/qv4debugclient_p_p.h b/src/qmldebug/qv4debugclient_p_p.h
new file mode 100644
index 0000000000..993c281632
--- /dev/null
+++ b/src/qmldebug/qv4debugclient_p_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 QV4DEBUGCLIENT_P_P_H
+#define QV4DEBUGCLIENT_P_P_H
+
+#include "qv4debugclient_p.h"
+#include "qqmldebugclient_p_p.h"
+
+#include <QtCore/qjsonobject.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 QV4DebugClientPrivate : public QQmlDebugClientPrivate
+{
+ Q_DECLARE_PUBLIC(QV4DebugClient)
+
+public:
+ QV4DebugClientPrivate(QQmlDebugConnection *connection);
+
+ void sendMessage(const QByteArray &command, const QJsonObject &args = QJsonObject());
+ void flushSendBuffer();
+ QByteArray packMessage(const QByteArray &type, const QJsonObject &object);
+ void onStateChanged(QQmlDebugClient::State state);
+
+ int seq = 0;
+ QList<QByteArray> sendBuffer;
+ QByteArray response;
+};
+
+QT_END_NAMESPACE
+
+#endif // QV4DEBUGCLIENT_P_P_H