aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qmldebug/qmldebug.pro3
-rw-r--r--src/qmldebug/qqmlenginecontrolclient.cpp147
-rw-r--r--src/qmldebug/qqmlenginecontrolclient_p.h80
-rw-r--r--src/qmldebug/qqmlenginecontrolclient_p_p.h85
-rw-r--r--tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp110
5 files changed, 343 insertions, 82 deletions
diff --git a/src/qmldebug/qmldebug.pro b/src/qmldebug/qmldebug.pro
index 295701eee3..e5f6de3314 100644
--- a/src/qmldebug/qmldebug.pro
+++ b/src/qmldebug/qmldebug.pro
@@ -7,12 +7,15 @@ 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/qqmlenginecontrolclient.cpp b/src/qmldebug/qqmlenginecontrolclient.cpp
new file mode 100644
index 0000000000..b45e4e1f14
--- /dev/null
+++ b/src/qmldebug/qqmlenginecontrolclient.cpp
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $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..601f8a871d
--- /dev/null
+++ b/src/qmldebug/qqmlenginecontrolclient_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $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..7e99c35948
--- /dev/null
+++ b/src/qmldebug/qqmlenginecontrolclient_p_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $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/tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp b/tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp
index 0a6c6c9a92..fb4d46b8c8 100644
--- a/tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp
+++ b/tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp
@@ -37,6 +37,7 @@
#include <private/qqmldebugclient_p.h>
#include <private/qqmldebugconnection_p.h>
#include <private/qpacket_p.h>
+#include <private/qqmlenginecontrolclient_p.h>
#include <QtTest/qtest.h>
#include <QtCore/qlibraryinfo.h>
@@ -44,49 +45,29 @@
#define STR_PORT_FROM "13773"
#define STR_PORT_TO "13783"
-class QQmlEngineControlClient : public QQmlDebugClient
+class QQmlEngineBlocker : public QObject
{
Q_OBJECT
public:
- enum MessageType {
- EngineAboutToBeAdded,
- EngineAdded,
- EngineAboutToBeRemoved,
- EngineRemoved,
+ QQmlEngineBlocker(QQmlEngineControlClient *parent);
- MaximumMessageType
- };
-
- enum CommandType {
- StartWaitingEngine,
- StopWaitingEngine,
-
- MaximumCommandType
- };
-
- QQmlEngineControlClient(QQmlDebugConnection *connection)
- : QQmlDebugClient(QLatin1String("EngineControl"), connection)
- {}
-
-
- void command(CommandType command, int engine) {
- QPacket stream(connection()->currentDataStreamVersion());
- stream << (int)command << engine;
- sendMessage(stream.data());
- }
-
- QList<int> startingEngines;
- QList<int> stoppingEngines;
+public slots:
+ void blockEngine(int engineId, const QString &name);
+};
-signals:
- void engineAboutToBeAdded();
- void engineAdded();
- void engineAboutToBeRemoved();
- void engineRemoved();
+QQmlEngineBlocker::QQmlEngineBlocker(QQmlEngineControlClient *parent): QObject(parent)
+{
+ connect(parent, &QQmlEngineControlClient::engineAboutToBeAdded,
+ this, &QQmlEngineBlocker::blockEngine);
+ connect(parent, &QQmlEngineControlClient::engineAboutToBeRemoved,
+ this, &QQmlEngineBlocker::blockEngine);
+}
-protected:
- void messageReceived(const QByteArray &message);
-};
+void QQmlEngineBlocker::blockEngine(int engineId, const QString &name)
+{
+ Q_UNUSED(name);
+ static_cast<QQmlEngineControlClient *>(parent())->blockEngine(engineId);
+}
class tst_QQmlEngineControl : public QQmlDataTest
{
@@ -99,7 +80,6 @@ public:
, m_client(0)
{}
-
private:
QQmlDebugProcess *m_process;
QQmlDebugConnection *m_connection;
@@ -117,41 +97,6 @@ private slots:
void stopEngine();
};
-void QQmlEngineControlClient::messageReceived(const QByteArray &message)
-{
- QPacket stream(connection()->currentDataStreamVersion(), message);
-
- int messageType;
- int engineId;
- stream >> messageType >> engineId;
-
- switch (messageType) {
- case EngineAboutToBeAdded:
- startingEngines.append(engineId);
- emit engineAboutToBeAdded();
- break;
- case EngineAdded:
- QVERIFY(startingEngines.contains(engineId));
- startingEngines.removeOne(engineId);
- emit engineAdded();
- break;
- case EngineAboutToBeRemoved:
- stoppingEngines.append(engineId);
- emit engineAboutToBeRemoved();
- break;
- case EngineRemoved:
- QVERIFY(stoppingEngines.contains(engineId));
- stoppingEngines.removeOne(engineId);
- emit engineRemoved();
- break;
- default:
- QString failMsg = QString("Unknown message type:") + messageType;
- QFAIL(qPrintable(failMsg));
- break;
- }
- QVERIFY(stream.atEnd());
-}
-
void tst_QQmlEngineControl::connect(const QString &testFile, bool restrictServices)
{
const QString executable = QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmlscene";
@@ -168,6 +113,7 @@ void tst_QQmlEngineControl::connect(const QString &testFile, bool restrictServic
m_connection = new QQmlDebugConnection();
m_client = new QQmlEngineControlClient(m_connection);
+ new QQmlEngineBlocker(m_client);
QList<QQmlDebugClient *> others = QQmlDebugTest::createOtherClients(m_connection);
const int port = m_process->debugPort();
@@ -214,10 +160,10 @@ void tst_QQmlEngineControl::startEngine()
connect("test.qml", restrictMode);
- QTRY_VERIFY(!m_client->startingEngines.empty());
- m_client->command(QQmlEngineControlClient::StartWaitingEngine, m_client->startingEngines.last());
+ QTRY_VERIFY(!m_client->blockedEngines().empty());
+ m_client->releaseEngine(m_client->blockedEngines().last());
- QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(engineAdded())),
+ QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(engineAdded(int,QString))),
"No engine start message received in time.");
}
@@ -232,16 +178,16 @@ void tst_QQmlEngineControl::stopEngine()
connect("exit.qml", restrictMode);
- QTRY_VERIFY(!m_client->startingEngines.empty());
- m_client->command(QQmlEngineControlClient::StartWaitingEngine, m_client->startingEngines.last());
+ QTRY_VERIFY(!m_client->blockedEngines().empty());
+ m_client->releaseEngine(m_client->blockedEngines().last());
- QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(engineAdded())),
+ QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(engineAdded(int,QString))),
"No engine start message received in time.");
- QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(engineAboutToBeRemoved())),
+ QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(engineAboutToBeRemoved(int,QString))),
"No engine about to stop message received in time.");
- m_client->command(QQmlEngineControlClient::StopWaitingEngine, m_client->stoppingEngines.last());
- QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(engineRemoved())),
+ m_client->releaseEngine(m_client->blockedEngines().last());
+ QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(engineRemoved(int,QString))),
"No engine stop message received in time.");
}