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