forked from qt-creator/qt-creator
QmlDebug: Move QmlDebugConnection into own file
Change-Id: I761658de7c19754cfaadf8cbbad7596a9bcdfbf3 Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -24,6 +24,7 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "declarativetoolsclient.h"
|
#include "declarativetoolsclient.h"
|
||||||
|
#include "qmldebugconnection.h"
|
||||||
#include <QMetaEnum>
|
#include <QMetaEnum>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
|
@@ -19,7 +19,8 @@ HEADERS += \
|
|||||||
$$PWD/declarativetoolsclient.h \
|
$$PWD/declarativetoolsclient.h \
|
||||||
$$PWD/qmltoolsclient.h \
|
$$PWD/qmltoolsclient.h \
|
||||||
$$PWD/qmlenginecontrolclient.h \
|
$$PWD/qmlenginecontrolclient.h \
|
||||||
$$PWD/qmldebugcommandlinearguments.h
|
$$PWD/qmldebugcommandlinearguments.h \
|
||||||
|
$$PWD/qmldebugconnection.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
$$PWD/qmldebugclient.cpp \
|
$$PWD/qmldebugclient.cpp \
|
||||||
@@ -31,5 +32,5 @@ SOURCES += \
|
|||||||
$$PWD/declarativetoolsclient.cpp \
|
$$PWD/declarativetoolsclient.cpp \
|
||||||
$$PWD/qmltoolsclient.cpp \
|
$$PWD/qmltoolsclient.cpp \
|
||||||
$$PWD/declarativeenginedebugclient.cpp \
|
$$PWD/declarativeenginedebugclient.cpp \
|
||||||
$$PWD/qmlenginecontrolclient.cpp
|
$$PWD/qmlenginecontrolclient.cpp \
|
||||||
|
$$PWD/qmldebugconnection.cpp
|
||||||
|
@@ -27,6 +27,8 @@ Project {
|
|||||||
"qmldebugclient.cpp",
|
"qmldebugclient.cpp",
|
||||||
"qmldebugclient.h",
|
"qmldebugclient.h",
|
||||||
"qmldebugcommandlinearguments.h",
|
"qmldebugcommandlinearguments.h",
|
||||||
|
"qmldebugconnection.cpp",
|
||||||
|
"qmldebugconnection.h",
|
||||||
"qmldebugconstants.h",
|
"qmldebugconstants.h",
|
||||||
"qmlenginecontrolclient.cpp",
|
"qmlenginecontrolclient.cpp",
|
||||||
"qmlenginecontrolclient.h",
|
"qmlenginecontrolclient.h",
|
||||||
|
@@ -24,25 +24,16 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "qmldebugclient.h"
|
#include "qmldebugclient.h"
|
||||||
|
#include "qmldebugconnection.h"
|
||||||
#include "qpacketprotocol.h"
|
#include "qpacketprotocol.h"
|
||||||
|
|
||||||
#include <qdebug.h>
|
#include <qdebug.h>
|
||||||
#include <qstringlist.h>
|
#include <qstringlist.h>
|
||||||
#include <qnetworkproxy.h>
|
|
||||||
#include <qlocalserver.h>
|
|
||||||
#include <qlocalsocket.h>
|
|
||||||
|
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
|
|
||||||
namespace QmlDebug {
|
namespace QmlDebug {
|
||||||
|
|
||||||
const int protocolVersion = 1;
|
|
||||||
const int minimumDataStreamVersion = QDataStream::Qt_4_7;
|
|
||||||
|
|
||||||
const QString serverId = QLatin1String("QDeclarativeDebugServer");
|
|
||||||
const QString clientId = QLatin1String("QDeclarativeDebugClient");
|
|
||||||
|
|
||||||
class QmlDebugClientPrivate
|
class QmlDebugClientPrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -52,387 +43,6 @@ public:
|
|||||||
QPointer<QmlDebugConnection> connection;
|
QPointer<QmlDebugConnection> connection;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QmlDebugConnectionPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QmlDebugConnectionPrivate();
|
|
||||||
QPacketProtocol *protocol;
|
|
||||||
QLocalServer *server;
|
|
||||||
QIODevice *device; // Currently a QTcpSocket or a QLocalSocket
|
|
||||||
|
|
||||||
bool gotHello;
|
|
||||||
QHash <QString, float> serverPlugins;
|
|
||||||
QHash<QString, QmlDebugClient *> plugins;
|
|
||||||
|
|
||||||
int currentDataStreamVersion;
|
|
||||||
int maximumDataStreamVersion;
|
|
||||||
|
|
||||||
void advertisePlugins();
|
|
||||||
void flush();
|
|
||||||
};
|
|
||||||
|
|
||||||
static QString socketStateToString(QAbstractSocket::SocketState state)
|
|
||||||
{
|
|
||||||
QString stateString;
|
|
||||||
QDebug(&stateString) << state;
|
|
||||||
return QmlDebugConnection::tr("Socket state changed to %1").arg(stateString);
|
|
||||||
}
|
|
||||||
|
|
||||||
static QString socketErrorToString(QAbstractSocket::SocketError error)
|
|
||||||
{
|
|
||||||
QString errorString;
|
|
||||||
QDebug(&errorString) << error;
|
|
||||||
return QmlDebugConnection::tr("Error: %1").arg(errorString);
|
|
||||||
}
|
|
||||||
|
|
||||||
QmlDebugConnectionPrivate::QmlDebugConnectionPrivate() :
|
|
||||||
protocol(0), server(0), device(0), gotHello(false),
|
|
||||||
currentDataStreamVersion(minimumDataStreamVersion),
|
|
||||||
maximumDataStreamVersion(QDataStream::Qt_DefaultCompiledVersion)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlDebugConnectionPrivate::advertisePlugins()
|
|
||||||
{
|
|
||||||
if (!gotHello)
|
|
||||||
return;
|
|
||||||
|
|
||||||
QPacket pack(currentDataStreamVersion);
|
|
||||||
pack << serverId << 1 << plugins.keys();
|
|
||||||
protocol->send(pack.data());
|
|
||||||
flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlDebugConnection::socketConnected()
|
|
||||||
{
|
|
||||||
Q_D(QmlDebugConnection);
|
|
||||||
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 QmlDebugConnection::socketDisconnected()
|
|
||||||
{
|
|
||||||
Q_D(QmlDebugConnection);
|
|
||||||
if (d->gotHello) {
|
|
||||||
d->gotHello = false;
|
|
||||||
QHash<QString, QmlDebugClient*>::iterator iter = d->plugins.begin();
|
|
||||||
for (; iter != d->plugins.end(); ++iter)
|
|
||||||
iter.value()->stateChanged(QmlDebugClient::NotConnected);
|
|
||||||
emit disconnected();
|
|
||||||
} else if (d->device) {
|
|
||||||
emit connectionFailed();
|
|
||||||
}
|
|
||||||
if (d->protocol) {
|
|
||||||
d->protocol->disconnect();
|
|
||||||
d->protocol->deleteLater();
|
|
||||||
d->protocol = 0;
|
|
||||||
}
|
|
||||||
if (d->device) {
|
|
||||||
// Don't allow any "connected()" or "disconnected()" signals to be triggered anymore.
|
|
||||||
// As the protocol is gone this would lead to crashes.
|
|
||||||
d->device->disconnect();
|
|
||||||
// Don't immediately delete it as it may do some cleanup on returning from a signal.
|
|
||||||
d->device->deleteLater();
|
|
||||||
d->device = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlDebugConnection::protocolReadyRead()
|
|
||||||
{
|
|
||||||
Q_D(QmlDebugConnection);
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pack.atEnd()) {
|
|
||||||
pack >> d->currentDataStreamVersion;
|
|
||||||
if (d->currentDataStreamVersion > d->maximumDataStreamVersion)
|
|
||||||
qWarning() << "Server returned invalid data stream version!";
|
|
||||||
}
|
|
||||||
validHello = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!validHello) {
|
|
||||||
qWarning("QML Debug Client: Invalid hello message");
|
|
||||||
close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
d->gotHello = true;
|
|
||||||
|
|
||||||
QHash<QString, QmlDebugClient *>::Iterator iter = d->plugins.begin();
|
|
||||||
for (; iter != d->plugins.end(); ++iter) {
|
|
||||||
QmlDebugClient::State newState = QmlDebugClient::Unavailable;
|
|
||||||
if (d->serverPlugins.contains(iter.key()))
|
|
||||||
newState = QmlDebugClient::Enabled;
|
|
||||||
iter.value()->stateChanged(newState);
|
|
||||||
}
|
|
||||||
emit connected();
|
|
||||||
}
|
|
||||||
|
|
||||||
while (d->protocol && 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, QmlDebugClient *>::Iterator iter = d->plugins.begin();
|
|
||||||
for (; iter != d->plugins.end(); ++iter) {
|
|
||||||
const QString pluginName = iter.key();
|
|
||||||
QmlDebugClient::State newState = QmlDebugClient::Unavailable;
|
|
||||||
if (d->serverPlugins.contains(pluginName))
|
|
||||||
newState = QmlDebugClient::Enabled;
|
|
||||||
|
|
||||||
if (oldServerPlugins.contains(pluginName)
|
|
||||||
!= d->serverPlugins.contains(pluginName)) {
|
|
||||||
iter.value()->stateChanged(newState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
qWarning() << "QML Debug Client: Unknown control message id" << op;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
QHash<QString, QmlDebugClient *>::Iterator iter = d->plugins.find(name);
|
|
||||||
if (iter == d->plugins.end()) {
|
|
||||||
qWarning() << "QML Debug Client: Message received for missing plugin" << name;
|
|
||||||
} else {
|
|
||||||
QmlDebugClient *client = *iter;
|
|
||||||
QByteArray message;
|
|
||||||
while (!pack.atEnd()) {
|
|
||||||
pack >> message;
|
|
||||||
client->messageReceived(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QmlDebugConnection::QmlDebugConnection(QObject *parent)
|
|
||||||
: QObject(parent), d_ptr(new QmlDebugConnectionPrivate)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QmlDebugConnection::~QmlDebugConnection()
|
|
||||||
{
|
|
||||||
socketDisconnected();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QmlDebugConnection::isConnected() const
|
|
||||||
{
|
|
||||||
Q_D(const QmlDebugConnection);
|
|
||||||
// gotHello can only be set if the connection is open.
|
|
||||||
return d->gotHello;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QmlDebugConnection::isConnecting() const
|
|
||||||
{
|
|
||||||
Q_D(const QmlDebugConnection);
|
|
||||||
return !d->gotHello && d->device;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlDebugConnection::close()
|
|
||||||
{
|
|
||||||
Q_D(QmlDebugConnection);
|
|
||||||
if (d->device && d->device->isOpen())
|
|
||||||
d->device->close(); // will trigger disconnected() at some point.
|
|
||||||
}
|
|
||||||
|
|
||||||
QmlDebugClient *QmlDebugConnection::client(const QString &name) const
|
|
||||||
{
|
|
||||||
Q_D(const QmlDebugConnection);
|
|
||||||
return d->plugins.value(name, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QmlDebugConnection::addClient(const QString &name, QmlDebugClient *client)
|
|
||||||
{
|
|
||||||
Q_D(QmlDebugConnection);
|
|
||||||
if (d->plugins.contains(name))
|
|
||||||
return false;
|
|
||||||
d->plugins.insert(name, client);
|
|
||||||
d->advertisePlugins();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QmlDebugConnection::removeClient(const QString &name)
|
|
||||||
{
|
|
||||||
Q_D(QmlDebugConnection);
|
|
||||||
if (!d->plugins.contains(name))
|
|
||||||
return false;
|
|
||||||
d->plugins.remove(name);
|
|
||||||
d->advertisePlugins();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
float QmlDebugConnection::serviceVersion(const QString &serviceName) const
|
|
||||||
{
|
|
||||||
Q_D(const QmlDebugConnection);
|
|
||||||
return d->serverPlugins.value(serviceName, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QmlDebugConnection::sendMessage(const QString &name, const QByteArray &message)
|
|
||||||
{
|
|
||||||
Q_D(QmlDebugConnection);
|
|
||||||
if (!d->gotHello || !d->serverPlugins.contains(name))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
QPacket pack(d->currentDataStreamVersion);
|
|
||||||
pack << name << message;
|
|
||||||
d->protocol->send(pack.data());
|
|
||||||
d->flush();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlDebugConnectionPrivate::flush()
|
|
||||||
{
|
|
||||||
if (QAbstractSocket *socket = qobject_cast<QAbstractSocket *>(device))
|
|
||||||
socket->flush();
|
|
||||||
else if (QLocalSocket *socket = qobject_cast<QLocalSocket *>(device))
|
|
||||||
socket->flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlDebugConnection::connectToHost(const QString &hostName, quint16 port)
|
|
||||||
{
|
|
||||||
Q_D(QmlDebugConnection);
|
|
||||||
socketDisconnected();
|
|
||||||
QTcpSocket *socket = new QTcpSocket(this);
|
|
||||||
socket->setProxy(QNetworkProxy::NoProxy);
|
|
||||||
d->device = socket;
|
|
||||||
d->protocol = new QPacketProtocol(socket, this);
|
|
||||||
QObject::connect(d->protocol, &QPacketProtocol::readyRead,
|
|
||||||
this, &QmlDebugConnection::protocolReadyRead);
|
|
||||||
connect(socket, &QAbstractSocket::stateChanged,
|
|
||||||
this, [this](QAbstractSocket::SocketState state) {
|
|
||||||
emit logStateChange(socketStateToString(state));
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(socket, static_cast<void (QTcpSocket::*)(QAbstractSocket::SocketError)>
|
|
||||||
(&QAbstractSocket::error), this, [this](QAbstractSocket::SocketError error) {
|
|
||||||
emit logError(socketErrorToString(error));
|
|
||||||
socketDisconnected();
|
|
||||||
});
|
|
||||||
connect(socket, &QAbstractSocket::connected, this, &QmlDebugConnection::socketConnected);
|
|
||||||
connect(socket, &QAbstractSocket::disconnected, this, &QmlDebugConnection::socketDisconnected);
|
|
||||||
socket->connectToHost(hostName.isEmpty() ? QString("localhost") : hostName, port);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlDebugConnection::startLocalServer(const QString &fileName)
|
|
||||||
{
|
|
||||||
Q_D(QmlDebugConnection);
|
|
||||||
if (d->gotHello)
|
|
||||||
close();
|
|
||||||
if (d->server)
|
|
||||||
d->server->deleteLater();
|
|
||||||
d->server = new QLocalServer(this);
|
|
||||||
// QueuedConnection so that waitForNewConnection() returns true.
|
|
||||||
connect(d->server, &QLocalServer::newConnection,
|
|
||||||
this, &QmlDebugConnection::newConnection, Qt::QueuedConnection);
|
|
||||||
if (!d->server->listen(fileName))
|
|
||||||
emit connectionFailed();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlDebugConnection::newConnection()
|
|
||||||
{
|
|
||||||
Q_D(QmlDebugConnection);
|
|
||||||
delete d->device;
|
|
||||||
QLocalSocket *socket = d->server->nextPendingConnection();
|
|
||||||
d->server->close();
|
|
||||||
d->device = socket;
|
|
||||||
delete d->protocol;
|
|
||||||
d->protocol = new QPacketProtocol(socket, this);
|
|
||||||
QObject::connect(d->protocol, &QPacketProtocol::readyRead,
|
|
||||||
this, &QmlDebugConnection::protocolReadyRead);
|
|
||||||
|
|
||||||
connect(socket, &QLocalSocket::disconnected, this, &QmlDebugConnection::socketDisconnected);
|
|
||||||
|
|
||||||
connect(socket, static_cast<void (QLocalSocket::*)(QLocalSocket::LocalSocketError)>
|
|
||||||
(&QLocalSocket::error), this, [this](QLocalSocket::LocalSocketError error) {
|
|
||||||
emit logError(socketErrorToString(static_cast<QAbstractSocket::SocketError>(error)));
|
|
||||||
socketDisconnected();
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(socket, &QLocalSocket::stateChanged,
|
|
||||||
this, [this](QLocalSocket::LocalSocketState state) {
|
|
||||||
logStateChange(socketStateToString(static_cast<QAbstractSocket::SocketState>(state)));
|
|
||||||
});
|
|
||||||
|
|
||||||
socketConnected();
|
|
||||||
}
|
|
||||||
|
|
||||||
int QmlDebugConnection::currentDataStreamVersion() const
|
|
||||||
{
|
|
||||||
Q_D(const QmlDebugConnection);
|
|
||||||
return d->currentDataStreamVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlDebugConnection::setMaximumDataStreamVersion(int maximumVersion)
|
|
||||||
{
|
|
||||||
Q_D(QmlDebugConnection);
|
|
||||||
d->maximumDataStreamVersion = maximumVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
QAbstractSocket::SocketState QmlDebugConnection::socketState() const
|
|
||||||
{
|
|
||||||
Q_D(const QmlDebugConnection);
|
|
||||||
if (QAbstractSocket *socket = qobject_cast<QAbstractSocket *>(d->device))
|
|
||||||
return socket->state();
|
|
||||||
else if (QLocalSocket *socket = qobject_cast<QLocalSocket *>(d->device))
|
|
||||||
return static_cast<QAbstractSocket::SocketState>(socket->state());
|
|
||||||
else
|
|
||||||
return QAbstractSocket::UnconnectedState;
|
|
||||||
}
|
|
||||||
|
|
||||||
QmlDebugClientPrivate::QmlDebugClientPrivate()
|
QmlDebugClientPrivate::QmlDebugClientPrivate()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -497,7 +107,8 @@ QmlDebugConnection *QmlDebugClient::connection() const
|
|||||||
int QmlDebugClient::dataStreamVersion() const
|
int QmlDebugClient::dataStreamVersion() const
|
||||||
{
|
{
|
||||||
Q_D(const QmlDebugClient);
|
Q_D(const QmlDebugClient);
|
||||||
return (d->connection ? d->connection->currentDataStreamVersion() : minimumDataStreamVersion);
|
return (d->connection ? d->connection->currentDataStreamVersion()
|
||||||
|
: QmlDebugConnection::minimumDataStreamVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlDebugClient::sendMessage(const QByteArray &message)
|
void QmlDebugClient::sendMessage(const QByteArray &message)
|
||||||
|
@@ -32,52 +32,7 @@
|
|||||||
|
|
||||||
namespace QmlDebug {
|
namespace QmlDebug {
|
||||||
|
|
||||||
class QmlDebugClient;
|
class QmlDebugConnection;
|
||||||
class QmlDebugConnectionPrivate;
|
|
||||||
class QMLDEBUG_EXPORT QmlDebugConnection : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
Q_DISABLE_COPY(QmlDebugConnection)
|
|
||||||
Q_DECLARE_PRIVATE(QmlDebugConnection)
|
|
||||||
public:
|
|
||||||
QmlDebugConnection(QObject * = 0);
|
|
||||||
~QmlDebugConnection();
|
|
||||||
|
|
||||||
void connectToHost(const QString &hostName, quint16 port);
|
|
||||||
void startLocalServer(const QString &fileName);
|
|
||||||
QAbstractSocket::SocketState socketState() const;
|
|
||||||
|
|
||||||
int currentDataStreamVersion() const;
|
|
||||||
void setMaximumDataStreamVersion(int maximumVersion);
|
|
||||||
|
|
||||||
bool isConnected() const;
|
|
||||||
bool isConnecting() const;
|
|
||||||
void close();
|
|
||||||
|
|
||||||
QmlDebugClient *client(const QString &name) const;
|
|
||||||
bool addClient(const QString &name, QmlDebugClient *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 connectionFailed();
|
|
||||||
|
|
||||||
void logError(const QString &error);
|
|
||||||
void logStateChange(const QString &state);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void newConnection();
|
|
||||||
void socketConnected();
|
|
||||||
void socketDisconnected();
|
|
||||||
void protocolReadyRead();
|
|
||||||
|
|
||||||
QScopedPointer<QmlDebugConnectionPrivate> d_ptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
class QmlDebugClientPrivate;
|
class QmlDebugClientPrivate;
|
||||||
class QMLDEBUG_EXPORT QmlDebugClient : public QObject
|
class QMLDEBUG_EXPORT QmlDebugClient : public QObject
|
||||||
{
|
{
|
||||||
|
431
src/libs/qmldebug/qmldebugconnection.cpp
Normal file
431
src/libs/qmldebug/qmldebugconnection.cpp
Normal file
@@ -0,0 +1,431 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2017 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and 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.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "qmldebugconnection.h"
|
||||||
|
#include "qmldebugclient.h"
|
||||||
|
#include "qpacketprotocol.h"
|
||||||
|
|
||||||
|
#include <utils/temporaryfile.h>
|
||||||
|
|
||||||
|
#include <QLocalServer>
|
||||||
|
#include <QLocalSocket>
|
||||||
|
#include <QNetworkProxy>
|
||||||
|
#include <QTcpServer>
|
||||||
|
#include <QTcpSocket>
|
||||||
|
|
||||||
|
namespace QmlDebug {
|
||||||
|
|
||||||
|
const int protocolVersion = 1;
|
||||||
|
|
||||||
|
const QString serverId = QLatin1String("QDeclarativeDebugServer");
|
||||||
|
const QString clientId = QLatin1String("QDeclarativeDebugClient");
|
||||||
|
|
||||||
|
class QmlDebugConnectionPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QmlDebugConnectionPrivate();
|
||||||
|
QPacketProtocol *protocol;
|
||||||
|
QLocalServer *server;
|
||||||
|
QIODevice *device; // Currently a QTcpSocket or a QLocalSocket
|
||||||
|
|
||||||
|
bool gotHello;
|
||||||
|
QHash <QString, float> serverPlugins;
|
||||||
|
QHash<QString, QmlDebugClient *> plugins;
|
||||||
|
|
||||||
|
int currentDataStreamVersion;
|
||||||
|
int maximumDataStreamVersion;
|
||||||
|
|
||||||
|
void advertisePlugins();
|
||||||
|
void flush();
|
||||||
|
};
|
||||||
|
|
||||||
|
static QString socketStateToString(QAbstractSocket::SocketState state)
|
||||||
|
{
|
||||||
|
QString stateString;
|
||||||
|
QDebug(&stateString) << state;
|
||||||
|
return QmlDebugConnection::tr("Socket state changed to %1").arg(stateString);
|
||||||
|
}
|
||||||
|
|
||||||
|
static QString socketErrorToString(QAbstractSocket::SocketError error)
|
||||||
|
{
|
||||||
|
QString errorString;
|
||||||
|
QDebug(&errorString) << error;
|
||||||
|
return QmlDebugConnection::tr("Error: %1").arg(errorString);
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlDebugConnectionPrivate::QmlDebugConnectionPrivate() :
|
||||||
|
protocol(0), server(0), device(0), gotHello(false),
|
||||||
|
currentDataStreamVersion(QmlDebugConnection::minimumDataStreamVersion()),
|
||||||
|
maximumDataStreamVersion(QDataStream::Qt_DefaultCompiledVersion)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlDebugConnectionPrivate::advertisePlugins()
|
||||||
|
{
|
||||||
|
if (!gotHello)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QPacket pack(currentDataStreamVersion);
|
||||||
|
pack << serverId << 1 << plugins.keys();
|
||||||
|
protocol->send(pack.data());
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlDebugConnection::socketConnected()
|
||||||
|
{
|
||||||
|
Q_D(QmlDebugConnection);
|
||||||
|
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 QmlDebugConnection::socketDisconnected()
|
||||||
|
{
|
||||||
|
Q_D(QmlDebugConnection);
|
||||||
|
if (d->gotHello) {
|
||||||
|
d->gotHello = false;
|
||||||
|
QHash<QString, QmlDebugClient*>::iterator iter = d->plugins.begin();
|
||||||
|
for (; iter != d->plugins.end(); ++iter)
|
||||||
|
iter.value()->stateChanged(QmlDebugClient::NotConnected);
|
||||||
|
emit disconnected();
|
||||||
|
} else if (d->device) {
|
||||||
|
emit connectionFailed();
|
||||||
|
}
|
||||||
|
if (d->protocol) {
|
||||||
|
d->protocol->disconnect();
|
||||||
|
d->protocol->deleteLater();
|
||||||
|
d->protocol = 0;
|
||||||
|
}
|
||||||
|
if (d->device) {
|
||||||
|
// Don't allow any "connected()" or "disconnected()" signals to be triggered anymore.
|
||||||
|
// As the protocol is gone this would lead to crashes.
|
||||||
|
d->device->disconnect();
|
||||||
|
// Don't immediately delete it as it may do some cleanup on returning from a signal.
|
||||||
|
d->device->deleteLater();
|
||||||
|
d->device = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlDebugConnection::protocolReadyRead()
|
||||||
|
{
|
||||||
|
Q_D(QmlDebugConnection);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pack.atEnd()) {
|
||||||
|
pack >> d->currentDataStreamVersion;
|
||||||
|
if (d->currentDataStreamVersion > d->maximumDataStreamVersion)
|
||||||
|
qWarning() << "Server returned invalid data stream version!";
|
||||||
|
}
|
||||||
|
validHello = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validHello) {
|
||||||
|
qWarning("QML Debug Client: Invalid hello message");
|
||||||
|
close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
d->gotHello = true;
|
||||||
|
|
||||||
|
QHash<QString, QmlDebugClient *>::Iterator iter = d->plugins.begin();
|
||||||
|
for (; iter != d->plugins.end(); ++iter) {
|
||||||
|
QmlDebugClient::State newState = QmlDebugClient::Unavailable;
|
||||||
|
if (d->serverPlugins.contains(iter.key()))
|
||||||
|
newState = QmlDebugClient::Enabled;
|
||||||
|
iter.value()->stateChanged(newState);
|
||||||
|
}
|
||||||
|
emit connected();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (d->protocol && 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, QmlDebugClient *>::Iterator iter = d->plugins.begin();
|
||||||
|
for (; iter != d->plugins.end(); ++iter) {
|
||||||
|
const QString pluginName = iter.key();
|
||||||
|
QmlDebugClient::State newState = QmlDebugClient::Unavailable;
|
||||||
|
if (d->serverPlugins.contains(pluginName))
|
||||||
|
newState = QmlDebugClient::Enabled;
|
||||||
|
|
||||||
|
if (oldServerPlugins.contains(pluginName)
|
||||||
|
!= d->serverPlugins.contains(pluginName)) {
|
||||||
|
iter.value()->stateChanged(newState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qWarning() << "QML Debug Client: Unknown control message id" << op;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
QHash<QString, QmlDebugClient *>::Iterator iter = d->plugins.find(name);
|
||||||
|
if (iter == d->plugins.end()) {
|
||||||
|
qWarning() << "QML Debug Client: Message received for missing plugin" << name;
|
||||||
|
} else {
|
||||||
|
QmlDebugClient *client = *iter;
|
||||||
|
QByteArray message;
|
||||||
|
while (!pack.atEnd()) {
|
||||||
|
pack >> message;
|
||||||
|
client->messageReceived(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlDebugConnection::QmlDebugConnection(QObject *parent)
|
||||||
|
: QObject(parent), d_ptr(new QmlDebugConnectionPrivate)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlDebugConnection::~QmlDebugConnection()
|
||||||
|
{
|
||||||
|
socketDisconnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QmlDebugConnection::isConnected() const
|
||||||
|
{
|
||||||
|
Q_D(const QmlDebugConnection);
|
||||||
|
// gotHello can only be set if the connection is open.
|
||||||
|
return d->gotHello;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QmlDebugConnection::isConnecting() const
|
||||||
|
{
|
||||||
|
Q_D(const QmlDebugConnection);
|
||||||
|
return !d->gotHello && d->device;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlDebugConnection::close()
|
||||||
|
{
|
||||||
|
Q_D(QmlDebugConnection);
|
||||||
|
if (d->device && d->device->isOpen())
|
||||||
|
d->device->close(); // will trigger disconnected() at some point.
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlDebugClient *QmlDebugConnection::client(const QString &name) const
|
||||||
|
{
|
||||||
|
Q_D(const QmlDebugConnection);
|
||||||
|
return d->plugins.value(name, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QmlDebugConnection::addClient(const QString &name, QmlDebugClient *client)
|
||||||
|
{
|
||||||
|
Q_D(QmlDebugConnection);
|
||||||
|
if (d->plugins.contains(name))
|
||||||
|
return false;
|
||||||
|
d->plugins.insert(name, client);
|
||||||
|
d->advertisePlugins();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QmlDebugConnection::removeClient(const QString &name)
|
||||||
|
{
|
||||||
|
Q_D(QmlDebugConnection);
|
||||||
|
if (!d->plugins.contains(name))
|
||||||
|
return false;
|
||||||
|
d->plugins.remove(name);
|
||||||
|
d->advertisePlugins();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
float QmlDebugConnection::serviceVersion(const QString &serviceName) const
|
||||||
|
{
|
||||||
|
Q_D(const QmlDebugConnection);
|
||||||
|
return d->serverPlugins.value(serviceName, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QmlDebugConnection::sendMessage(const QString &name, const QByteArray &message)
|
||||||
|
{
|
||||||
|
Q_D(QmlDebugConnection);
|
||||||
|
if (!d->gotHello || !d->serverPlugins.contains(name))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QPacket pack(d->currentDataStreamVersion);
|
||||||
|
pack << name << message;
|
||||||
|
d->protocol->send(pack.data());
|
||||||
|
d->flush();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int QmlDebugConnection::minimumDataStreamVersion()
|
||||||
|
{
|
||||||
|
return QDataStream::Qt_4_7;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlDebugConnectionPrivate::flush()
|
||||||
|
{
|
||||||
|
if (QAbstractSocket *socket = qobject_cast<QAbstractSocket *>(device))
|
||||||
|
socket->flush();
|
||||||
|
else if (QLocalSocket *socket = qobject_cast<QLocalSocket *>(device))
|
||||||
|
socket->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlDebugConnection::connectToHost(const QString &hostName, quint16 port)
|
||||||
|
{
|
||||||
|
Q_D(QmlDebugConnection);
|
||||||
|
socketDisconnected();
|
||||||
|
QTcpSocket *socket = new QTcpSocket(this);
|
||||||
|
socket->setProxy(QNetworkProxy::NoProxy);
|
||||||
|
d->device = socket;
|
||||||
|
d->protocol = new QPacketProtocol(socket, this);
|
||||||
|
QObject::connect(d->protocol, &QPacketProtocol::readyRead,
|
||||||
|
this, &QmlDebugConnection::protocolReadyRead);
|
||||||
|
connect(socket, &QAbstractSocket::stateChanged,
|
||||||
|
this, [this](QAbstractSocket::SocketState state) {
|
||||||
|
emit logStateChange(socketStateToString(state));
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(socket, static_cast<void (QTcpSocket::*)(QAbstractSocket::SocketError)>
|
||||||
|
(&QAbstractSocket::error), this, [this](QAbstractSocket::SocketError error) {
|
||||||
|
emit logError(socketErrorToString(error));
|
||||||
|
socketDisconnected();
|
||||||
|
});
|
||||||
|
connect(socket, &QAbstractSocket::connected, this, &QmlDebugConnection::socketConnected);
|
||||||
|
connect(socket, &QAbstractSocket::disconnected, this, &QmlDebugConnection::socketDisconnected);
|
||||||
|
socket->connectToHost(hostName.isEmpty() ? QString("localhost") : hostName, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlDebugConnection::startLocalServer(const QString &fileName)
|
||||||
|
{
|
||||||
|
Q_D(QmlDebugConnection);
|
||||||
|
if (d->gotHello)
|
||||||
|
close();
|
||||||
|
if (d->server)
|
||||||
|
d->server->deleteLater();
|
||||||
|
d->server = new QLocalServer(this);
|
||||||
|
// QueuedConnection so that waitForNewConnection() returns true.
|
||||||
|
connect(d->server, &QLocalServer::newConnection,
|
||||||
|
this, &QmlDebugConnection::newConnection, Qt::QueuedConnection);
|
||||||
|
if (!d->server->listen(fileName))
|
||||||
|
emit connectionFailed();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlDebugConnection::newConnection()
|
||||||
|
{
|
||||||
|
Q_D(QmlDebugConnection);
|
||||||
|
delete d->device;
|
||||||
|
QLocalSocket *socket = d->server->nextPendingConnection();
|
||||||
|
d->server->close();
|
||||||
|
d->device = socket;
|
||||||
|
delete d->protocol;
|
||||||
|
d->protocol = new QPacketProtocol(socket, this);
|
||||||
|
QObject::connect(d->protocol, &QPacketProtocol::readyRead,
|
||||||
|
this, &QmlDebugConnection::protocolReadyRead);
|
||||||
|
|
||||||
|
connect(socket, &QLocalSocket::disconnected, this, &QmlDebugConnection::socketDisconnected);
|
||||||
|
|
||||||
|
connect(socket, static_cast<void (QLocalSocket::*)(QLocalSocket::LocalSocketError)>
|
||||||
|
(&QLocalSocket::error), this, [this](QLocalSocket::LocalSocketError error) {
|
||||||
|
emit logError(socketErrorToString(static_cast<QAbstractSocket::SocketError>(error)));
|
||||||
|
socketDisconnected();
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(socket, &QLocalSocket::stateChanged,
|
||||||
|
this, [this](QLocalSocket::LocalSocketState state) {
|
||||||
|
logStateChange(socketStateToString(static_cast<QAbstractSocket::SocketState>(state)));
|
||||||
|
});
|
||||||
|
|
||||||
|
socketConnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
int QmlDebugConnection::currentDataStreamVersion() const
|
||||||
|
{
|
||||||
|
Q_D(const QmlDebugConnection);
|
||||||
|
return d->currentDataStreamVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlDebugConnection::setMaximumDataStreamVersion(int maximumVersion)
|
||||||
|
{
|
||||||
|
Q_D(QmlDebugConnection);
|
||||||
|
d->maximumDataStreamVersion = maximumVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
QAbstractSocket::SocketState QmlDebugConnection::socketState() const
|
||||||
|
{
|
||||||
|
Q_D(const QmlDebugConnection);
|
||||||
|
if (QAbstractSocket *socket = qobject_cast<QAbstractSocket *>(d->device))
|
||||||
|
return socket->state();
|
||||||
|
else if (QLocalSocket *socket = qobject_cast<QLocalSocket *>(d->device))
|
||||||
|
return static_cast<QAbstractSocket::SocketState>(socket->state());
|
||||||
|
else
|
||||||
|
return QAbstractSocket::UnconnectedState;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace QmlDebug
|
84
src/libs/qmldebug/qmldebugconnection.h
Normal file
84
src/libs/qmldebug/qmldebugconnection.h
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2017 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and 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.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "qmldebug_global.h"
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QAbstractSocket>
|
||||||
|
|
||||||
|
namespace QmlDebug {
|
||||||
|
|
||||||
|
class QmlDebugClient;
|
||||||
|
class QmlDebugConnectionPrivate;
|
||||||
|
class QMLDEBUG_EXPORT QmlDebugConnection : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_DISABLE_COPY(QmlDebugConnection)
|
||||||
|
Q_DECLARE_PRIVATE(QmlDebugConnection)
|
||||||
|
public:
|
||||||
|
QmlDebugConnection(QObject * = 0);
|
||||||
|
~QmlDebugConnection();
|
||||||
|
|
||||||
|
void connectToHost(const QString &hostName, quint16 port);
|
||||||
|
void startLocalServer(const QString &fileName);
|
||||||
|
QAbstractSocket::SocketState socketState() const;
|
||||||
|
|
||||||
|
int currentDataStreamVersion() const;
|
||||||
|
void setMaximumDataStreamVersion(int maximumVersion);
|
||||||
|
|
||||||
|
bool isConnected() const;
|
||||||
|
bool isConnecting() const;
|
||||||
|
void close();
|
||||||
|
|
||||||
|
QmlDebugClient *client(const QString &name) const;
|
||||||
|
bool addClient(const QString &name, QmlDebugClient *client);
|
||||||
|
bool removeClient(const QString &name);
|
||||||
|
|
||||||
|
float serviceVersion(const QString &serviceName) const;
|
||||||
|
bool sendMessage(const QString &name, const QByteArray &message);
|
||||||
|
|
||||||
|
static int minimumDataStreamVersion();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void connected();
|
||||||
|
void disconnected();
|
||||||
|
void connectionFailed();
|
||||||
|
|
||||||
|
void logError(const QString &error);
|
||||||
|
void logStateChange(const QString &state);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void newConnection();
|
||||||
|
void socketConnected();
|
||||||
|
void socketDisconnected();
|
||||||
|
void protocolReadyRead();
|
||||||
|
|
||||||
|
QScopedPointer<QmlDebugConnectionPrivate> d_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QmlDebug
|
@@ -24,6 +24,7 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "qmltoolsclient.h"
|
#include "qmltoolsclient.h"
|
||||||
|
#include "qmldebugconnection.h"
|
||||||
#include <qmldebug/qpacketprotocol.h>
|
#include <qmldebug/qpacketprotocol.h>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
|
@@ -52,6 +52,7 @@
|
|||||||
|
|
||||||
#include <qmljseditor/qmljseditorconstants.h>
|
#include <qmljseditor/qmljseditorconstants.h>
|
||||||
#include <qmljs/qmljsmodelmanagerinterface.h>
|
#include <qmljs/qmljsmodelmanagerinterface.h>
|
||||||
|
#include <qmldebug/qmldebugconnection.h>
|
||||||
#include <qmldebug/qpacketprotocol.h>
|
#include <qmldebug/qpacketprotocol.h>
|
||||||
|
|
||||||
#include <texteditor/textdocument.h>
|
#include <texteditor/textdocument.h>
|
||||||
|
@@ -28,6 +28,8 @@
|
|||||||
#include "qmlprofilermodelmanager.h"
|
#include "qmlprofilermodelmanager.h"
|
||||||
#include "qmlprofilerstatemanager.h"
|
#include "qmlprofilerstatemanager.h"
|
||||||
|
|
||||||
|
#include <qmldebug/qmldebugconnection.h>
|
||||||
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
#include <projectexplorer/runnables.h>
|
#include <projectexplorer/runnables.h>
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user