aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMarco Bubke <marco.bubke@qt.io>2020-07-27 18:14:33 +0200
committerMarco Bubke <marco.bubke@qt.io>2020-08-10 12:53:30 +0000
commite43c7fdb1de786a2d5b90d68830c5308319a7dcf (patch)
treebaffab654aebea5569ae3ff408d18eb793765980 /src
parentb5d59c75a7dee830483631cd9045d5338fc25c2d (diff)
QmlDesigner: Split messaging and process for puppets
This will make it easier to implement custom puppets. The new connection manager will restucture the code and it add a mechanism to capture data too. Task-number: QDS-2529 Change-Id: I5d15c3303ef1c9a3e25ba197d350e0d561ce813a Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/qmldesigner/CMakeLists.txt6
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp28
-rw-r--r--src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.h12
-rw-r--r--src/plugins/qmldesigner/designercore/include/nodeinstanceview.h18
-rw-r--r--src/plugins/qmldesigner/designercore/include/viewmanager.h2
-rw-r--r--src/plugins/qmldesigner/designercore/instances/baseconnectionmanager.cpp126
-rw-r--r--src/plugins/qmldesigner/designercore/instances/baseconnectionmanager.h76
-rw-r--r--src/plugins/qmldesigner/designercore/instances/capturingconnectionmanager.cpp61
-rw-r--r--src/plugins/qmldesigner/designercore/instances/capturingconnectionmanager.h46
-rw-r--r--src/plugins/qmldesigner/designercore/instances/connectionmanager.cpp177
-rw-r--r--src/plugins/qmldesigner/designercore/instances/connectionmanager.h77
-rw-r--r--src/plugins/qmldesigner/designercore/instances/connectionmanagerinterface.cpp54
-rw-r--r--src/plugins/qmldesigner/designercore/instances/connectionmanagerinterface.h80
-rw-r--r--src/plugins/qmldesigner/designercore/instances/instances.pri29
-rw-r--r--src/plugins/qmldesigner/designercore/instances/interactiveconnectionmanager.cpp109
-rw-r--r--src/plugins/qmldesigner/designercore/instances/interactiveconnectionmanager.h51
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp504
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h56
-rw-r--r--src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp130
-rw-r--r--src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp49
-rw-r--r--src/plugins/qmldesigner/designercore/instances/puppetcreator.h31
-rw-r--r--src/plugins/qmldesigner/designercore/instances/qprocessuniqueptr.h53
-rw-r--r--src/plugins/qmldesigner/designercore/model/viewmanager.cpp31
-rw-r--r--src/plugins/qmldesigner/qmldesignerplugin.qbs11
-rw-r--r--src/tools/qml2puppet/CMakeLists.txt2
-rw-r--r--src/tools/qml2puppet/qml2puppet.qbs4
26 files changed, 1156 insertions, 667 deletions
diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt
index f571497016..ecec481f90 100644
--- a/src/plugins/qmldesigner/CMakeLists.txt
+++ b/src/plugins/qmldesigner/CMakeLists.txt
@@ -505,6 +505,12 @@ extend_qtc_plugin(QmlDesigner
puppetbuildprogressdialog.cpp puppetbuildprogressdialog.h puppetbuildprogressdialog.ui
puppetcreator.cpp puppetcreator.h
puppetdialog.cpp puppetdialog.h puppetdialog.ui
+ connectionmanagerinterface.cpp connectionmanagerinterface.h
+ baseconnectionmanager.cpp baseconnectionmanager.h
+ connectionmanager.cpp connectionmanager.h
+ capturingconnectionmanager.cpp capturingconnectionmanager.h
+ interactiveconnectionmanager.cpp interactiveconnectionmanager.h
+ qprocessuniqueptr.h
)
extend_qtc_plugin(QmlDesigner
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp
index 6a5edb18a3..1fc817cd01 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.cpp
@@ -86,7 +86,7 @@ void ItemLibraryAssetImporter::importQuick3D(const QStringList &inputFiles,
if (!isCancelled()) {
// Wait for icon generation processes to finish
- if (m_qmlPuppetProcesses.isEmpty()) {
+ if (m_qmlPuppetProcesses.empty()) {
finalizeQuick3DImport();
} else {
m_qmlPuppetCount = m_qmlPuppetProcesses.size();
@@ -186,10 +186,12 @@ void ItemLibraryAssetImporter::processFinished(int exitCode, QProcess::ExitStatu
auto process = qobject_cast<QProcess *>(sender());
if (process) {
- m_qmlPuppetProcesses.remove(process);
- process->deleteLater();
+ m_qmlPuppetProcesses.erase(
+ std::remove_if(m_qmlPuppetProcesses.begin(),
+ m_qmlPuppetProcesses.end(),
+ [&](const auto &entry) { return entry.get() == process; }));
const QString progressTitle = tr("Generating icons.");
- if (m_qmlPuppetProcesses.isEmpty()) {
+ if (m_qmlPuppetProcesses.empty()) {
notifyProgress(100, progressTitle);
finalizeQuick3DImport();
} else {
@@ -215,7 +217,6 @@ void ItemLibraryAssetImporter::reset()
m_tempDir = new QTemporaryDir;
m_importFiles.clear();
m_overwrittenImports.clear();
- qDeleteAll(m_qmlPuppetProcesses);
m_qmlPuppetProcesses.clear();
m_qmlPuppetCount = 0;
#endif
@@ -498,16 +499,21 @@ bool ItemLibraryAssetImporter::generateComponentIcon(int size, const QString &ic
puppetCreator.createQml2PuppetExecutableIfMissing();
QStringList puppetArgs;
puppetArgs << "--rendericon" << QString::number(size) << iconFile << iconSource;
- QProcess *process = puppetCreator.createPuppetProcess(
- "custom", {}, this, "", SLOT(processFinished(int, QProcess::ExitStatus)), puppetArgs);
+ QProcessUniquePointer process = puppetCreator.createPuppetProcess(
+ "custom",
+ {},
+ this,
+ std::function<void()>(),
+ [&](int exitCode, QProcess::ExitStatus exitStatus) {
+ processFinished(exitCode, exitStatus);
+ },
+ puppetArgs);
if (process->waitForStarted(5000)) {
- connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
- process, &QProcess::deleteLater);
- m_qmlPuppetProcesses << process;
+ m_qmlPuppetProcesses.push_back(std::move(process));
return true;
} else {
- delete process;
+ process.reset();
}
}
return false;
diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.h
index 4bdccad6af..5921144151 100644
--- a/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.h
+++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibraryassetimporter.h
@@ -24,14 +24,16 @@
****************************************************************************/
#pragma once
+#include "import.h"
+
+#include <qprocessuniqueptr.h>
+
#include <QSet>
-#include <QtCore/qobject.h>
-#include <QtCore/qstringlist.h>
#include <QtCore/qhash.h>
#include <QtCore/qjsonobject.h>
+#include <QtCore/qobject.h>
#include <QtCore/qprocess.h>
-
-#include "import.h"
+#include <QtCore/qstringlist.h>
QT_BEGIN_NAMESPACE
class QSSGAssetImportManager;
@@ -99,7 +101,7 @@ private:
bool m_cancelled = false;
QString m_importPath;
QTemporaryDir *m_tempDir = nullptr;
- QSet<QProcess *> m_qmlPuppetProcesses;
+ std::vector<QProcessUniquePointer> m_qmlPuppetProcesses;
int m_qmlPuppetCount = 0;
};
} // QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h
index 63b73cbdff..78e56d46cd 100644
--- a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h
+++ b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h
@@ -62,6 +62,7 @@ class RemovePropertiesCommand;
class CompleteComponentCommand;
class InformationContainer;
class TokenCommand;
+class ConnectionManagerInterface;
class QMLDESIGNERCORE_EXPORT NodeInstanceView : public AbstractView, public NodeInstanceClientInterface
{
@@ -72,7 +73,7 @@ class QMLDESIGNERCORE_EXPORT NodeInstanceView : public AbstractView, public Node
public:
using Pointer = QWeakPointer<NodeInstanceView>;
- explicit NodeInstanceView(QObject *parent = nullptr, NodeInstanceServerInterface::RunModus runModus = NodeInstanceServerInterface::NormalModus);
+ explicit NodeInstanceView(ConnectionManagerInterface &connectionManager);
~NodeInstanceView() override;
void modelAttached(Model *model) override;
@@ -94,7 +95,7 @@ public:
void auxiliaryDataChanged(const ModelNode &node, const PropertyName &name, const QVariant &data) override;
void customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data) override;
void nodeSourceChanged(const ModelNode &modelNode, const QString &newNodeSource) override;
-
+ void capturedData(const CapturedDataCommand &capturedData) override;
void currentStateChanged(const ModelNode &node) override;
QList<NodeInstance> instances() const;
@@ -142,6 +143,7 @@ protected:
void timerEvent(QTimerEvent *event) override;
private: // functions
+ std::unique_ptr<NodeInstanceServerProxy> createNodeInstanceServerProxy();
void activateState(const NodeInstance &instance);
void activateBaseState();
@@ -161,9 +163,8 @@ private: // functions
void setStateInstance(const NodeInstance &stateInstance);
void clearStateInstance();
- NodeInstanceServerInterface *nodeInstanceServer() const;
- QMultiHash<ModelNode, InformationName> informationChanged(const QVector<InformationContainer> &containerVector);
-
+ QMultiHash<ModelNode, InformationName> informationChanged(
+ const QVector<InformationContainer> &containerVector);
CreateSceneCommand createCreateSceneCommand();
ClearSceneCommand createClearSceneCommand() const;
@@ -196,16 +197,15 @@ private: // functions
// puppet to creator command handlers
void handlePuppetKeyPress(int key, Qt::KeyboardModifiers modifiers);
+private:
NodeInstance m_rootNodeInstance;
NodeInstance m_activeStateInstance;
-
QHash<ModelNode, NodeInstance> m_nodeInstanceHash;
QHash<ModelNode, QImage> m_statePreviewImage;
-
- QPointer<NodeInstanceServerProxy> m_nodeInstanceServer;
+ ConnectionManagerInterface &m_connectionManager;
+ std::unique_ptr<NodeInstanceServerProxy> m_nodeInstanceServer;
QImage m_baseStatePreviewImage;
QElapsedTimer m_lastCrashTime;
- NodeInstanceServerInterface::RunModus m_runModus;
ProjectExplorer::Target *m_currentTarget = nullptr;
int m_restartProcessTimerId;
RewriterTransaction m_puppetTransaction;
diff --git a/src/plugins/qmldesigner/designercore/include/viewmanager.h b/src/plugins/qmldesigner/designercore/include/viewmanager.h
index 3862d54187..cc6f5d15d0 100644
--- a/src/plugins/qmldesigner/designercore/include/viewmanager.h
+++ b/src/plugins/qmldesigner/designercore/include/viewmanager.h
@@ -122,7 +122,7 @@ private: // functions
QList<QPointer<AbstractView>> standardViews() const;
private: // variables
- ViewManagerData *d;
+ std::unique_ptr<ViewManagerData> d;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/baseconnectionmanager.cpp b/src/plugins/qmldesigner/designercore/instances/baseconnectionmanager.cpp
new file mode 100644
index 0000000000..0d4540b37f
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/baseconnectionmanager.cpp
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 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 "baseconnectionmanager.h"
+#include "endpuppetcommand.h"
+#include "nodeinstanceserverproxy.h"
+#include "nodeinstanceview.h"
+
+#include <QLocalSocket>
+
+namespace QmlDesigner {
+
+void BaseConnectionManager::setUp(NodeInstanceServerProxy *nodeInstanceServerProxy,
+ const QString &,
+ ProjectExplorer::Target *)
+{
+ m_nodeInstanceServerProxy = nodeInstanceServerProxy;
+ m_isActive = true;
+}
+
+void BaseConnectionManager::shutDown()
+{
+ m_isActive = false;
+
+ writeCommand(QVariant::fromValue(EndPuppetCommand()));
+
+ m_nodeInstanceServerProxy = nullptr;
+}
+
+bool BaseConnectionManager::isActive() const
+{
+ return m_isActive;
+}
+
+void BaseConnectionManager::showCannotConnectToPuppetWarningAndSwitchToEditMode() {}
+
+void BaseConnectionManager::processFinished()
+{
+ processFinished(-1, QProcess::CrashExit);
+}
+
+void BaseConnectionManager::writeCommandToIODevice(const QVariant &command,
+ QIODevice *ioDevice,
+ unsigned int commandCounter)
+{
+ if (ioDevice) {
+ QByteArray block;
+ QDataStream out(&block, QIODevice::WriteOnly);
+ out.setVersion(QDataStream::Qt_4_8);
+ out << quint32(0);
+ out << quint32(commandCounter);
+ out << command;
+ out.device()->seek(0);
+ out << quint32(static_cast<unsigned long long>(block.size()) - sizeof(quint32));
+
+ ioDevice->write(block);
+ }
+}
+
+void BaseConnectionManager::dispatchCommand(const QVariant &command, Connection &)
+{
+ if (!isActive())
+ return;
+
+ m_nodeInstanceServerProxy->dispatchCommand(command);
+}
+
+void BaseConnectionManager::readDataStream(Connection &connection)
+{
+ QList<QVariant> commandList;
+
+ while (!connection.socket->atEnd()) {
+ if (connection.socket->bytesAvailable() < int(sizeof(quint32)))
+ break;
+
+ QDataStream in(connection.socket.get());
+ in.setVersion(QDataStream::Qt_4_8);
+
+ if (connection.blockSize == 0)
+ in >> connection.blockSize;
+
+ if (connection.socket->bytesAvailable() < connection.blockSize)
+ break;
+
+ quint32 commandCounter = 0;
+ in >> commandCounter;
+ bool commandLost = !((connection.lastReadCommandCounter == 0 && commandCounter == 0)
+ || (connection.lastReadCommandCounter + 1 == commandCounter));
+ if (commandLost)
+ qDebug() << "server command lost: " << connection.lastReadCommandCounter << commandCounter;
+ connection.lastReadCommandCounter = commandCounter;
+
+ QVariant command;
+ in >> command;
+ connection.blockSize = 0;
+
+ commandList.append(command);
+ }
+
+ for (const QVariant &command : commandList)
+ dispatchCommand(command, connection);
+}
+} // namespace QmlDesigner
+
diff --git a/src/plugins/qmldesigner/designercore/instances/baseconnectionmanager.h b/src/plugins/qmldesigner/designercore/instances/baseconnectionmanager.h
new file mode 100644
index 0000000000..83a41a2bd8
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/baseconnectionmanager.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 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 "connectionmanagerinterface.h"
+
+#include <QProcess>
+
+QT_BEGIN_NAMESPACE
+class QLocalSocket;
+QT_END_NAMESPACE
+
+namespace ProjectExplorer {
+class Target;
+}
+
+namespace QmlDesigner {
+
+class AbstractView;
+class NodeInstanceServerProxy;
+
+class QMLDESIGNERCORE_EXPORT BaseConnectionManager : public QObject, public ConnectionManagerInterface
+{
+ Q_OBJECT
+
+public:
+ BaseConnectionManager() = default;
+
+ void setUp(NodeInstanceServerProxy *nodeInstanceServerProxy,
+ const QString &qrcMappingString,
+ ProjectExplorer::Target *target) override;
+ void shutDown() override;
+
+ bool isActive() const;
+
+protected:
+ void dispatchCommand(const QVariant &command, Connection &connection) override;
+ virtual void showCannotConnectToPuppetWarningAndSwitchToEditMode();
+ using ConnectionManagerInterface::processFinished;
+ void processFinished();
+ void writeCommandToIODevice(const QVariant &command,
+ QIODevice *ioDevice,
+ unsigned int commandCounter);
+ void readDataStream(Connection &connection);
+
+ NodeInstanceServerProxy *nodeInstanceServerProxy() const { return m_nodeInstanceServerProxy; }
+
+private:
+ NodeInstanceServerProxy *m_nodeInstanceServerProxy{};
+ bool m_isActive = false;
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/capturingconnectionmanager.cpp b/src/plugins/qmldesigner/designercore/instances/capturingconnectionmanager.cpp
new file mode 100644
index 0000000000..b6e81f1ffe
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/capturingconnectionmanager.cpp
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 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 "capturingconnectionmanager.h"
+
+#include <coreplugin/messagebox.h>
+
+namespace QmlDesigner {
+
+void CapturingConnectionManager::setUp(NodeInstanceServerProxy *nodeInstanceServerProxy,
+ const QString &qrcMappingString,
+ ProjectExplorer::Target *target)
+{
+ InteractiveConnectionManager::setUp(nodeInstanceServerProxy, qrcMappingString, target);
+
+ int indexOfCapturePuppetStream = QCoreApplication::arguments().indexOf(
+ "-capture-puppet-stream");
+ if (indexOfCapturePuppetStream > 0) {
+ m_captureFileForTest.setFileName(
+ QCoreApplication::arguments().at(indexOfCapturePuppetStream + 1));
+ bool isOpen = m_captureFileForTest.open(QIODevice::WriteOnly);
+ qDebug() << "file is open: " << isOpen;
+ }
+}
+
+void CapturingConnectionManager::processFinished(int exitCode, QProcess::ExitStatus exitStatus)
+{
+ if (m_captureFileForTest.isOpen()) {
+ m_captureFileForTest.close();
+ Core::AsynchronousMessageBox::warning(
+ tr("QML Emulation Layer (QML Puppet) Crashed"),
+ tr("You are recording a puppet stream and the emulations layer crashed. "
+ "It is recommended to reopen the Qt Quick Designer and start again."));
+ }
+
+ InteractiveConnectionManager::processFinished(exitCode, exitStatus);
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/capturingconnectionmanager.h b/src/plugins/qmldesigner/designercore/instances/capturingconnectionmanager.h
new file mode 100644
index 0000000000..de63da87fc
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/capturingconnectionmanager.h
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 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 <interactiveconnectionmanager.h>
+
+namespace QmlDesigner {
+
+class CapturingConnectionManager : public InteractiveConnectionManager
+{
+public:
+ void setUp(NodeInstanceServerProxy *nodeInstanceServerProxy,
+ const QString &qrcMappingString,
+ ProjectExplorer::Target *target) override;
+
+ void processFinished(int exitCode, QProcess::ExitStatus exitStatus) override;
+
+private:
+ QFile m_captureFileForTest;
+};
+
+} // namespace QmlDesigner
+
diff --git a/src/plugins/qmldesigner/designercore/instances/connectionmanager.cpp b/src/plugins/qmldesigner/designercore/instances/connectionmanager.cpp
new file mode 100644
index 0000000000..edf7f20b9c
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/connectionmanager.cpp
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 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 "connectionmanager.h"
+#include "endpuppetcommand.h"
+#include "nodeinstanceserverproxy.h"
+#include "nodeinstanceview.h"
+#include "puppetcreator.h"
+
+#ifndef QMLDESIGNER_TEST
+#include <qmldesignerplugin.h>
+#endif
+
+#include <projectexplorer/target.h>
+
+#include <QLocalServer>
+#include <QLocalSocket>
+#include <QUuid>
+
+namespace QmlDesigner {
+
+ConnectionManager::ConnectionManager() = default;
+
+ConnectionManager::~ConnectionManager() = default;
+
+void ConnectionManager::setUp(NodeInstanceServerProxy *nodeInstanceServerProxy,
+ const QString &qrcMappingString,
+ ProjectExplorer::Target *target)
+{
+ BaseConnectionManager::setUp(nodeInstanceServerProxy, qrcMappingString, target);
+
+ m_localServer = std::make_unique<QLocalServer>();
+ QString socketToken(QUuid::createUuid().toString());
+ m_localServer->listen(socketToken);
+ m_localServer->setMaxPendingConnections(3);
+
+ NodeInstanceView *nodeInstanceView = nodeInstanceServerProxy->nodeInstanceView();
+ PuppetCreator puppetCreator(target, nodeInstanceView->model());
+ puppetCreator.setQrcMappingString(qrcMappingString);
+
+ puppetCreator.createQml2PuppetExecutableIfMissing();
+
+ for (Connection &connection : m_connections) {
+ connection.qmlPuppetProcess = puppetCreator.createPuppetProcess(
+ connection.mode,
+ socketToken,
+ nodeInstanceView,
+ [&] { printProcessOutput(connection.qmlPuppetProcess.get(), connection.name); },
+ [&](int exitCode, QProcess::ExitStatus exitStatus) {
+ processFinished(exitCode, exitStatus);
+ });
+
+ const int second = 1000;
+ int waitConstant = 8 * second;
+
+ if (!connection.qmlPuppetProcess->waitForStarted(waitConstant)) {
+ closeSocketsAndKillProcesses();
+ showCannotConnectToPuppetWarningAndSwitchToEditMode();
+ return;
+ }
+
+ waitConstant /= 2;
+
+ bool connectedToPuppet = true;
+ if (!m_localServer->hasPendingConnections())
+ connectedToPuppet = m_localServer->waitForNewConnection(waitConstant);
+
+ if (connectedToPuppet) {
+ connection.socket.reset(m_localServer->nextPendingConnection());
+ QObject::connect(connection.socket.get(), &QIODevice::readyRead, [&] {
+ readDataStream(connection);
+ });
+ } else {
+ closeSocketsAndKillProcesses();
+ showCannotConnectToPuppetWarningAndSwitchToEditMode();
+ return;
+ }
+ }
+
+ m_localServer->close();
+
+ connect(this,
+ &ConnectionManager::processCrashed,
+ nodeInstanceServerProxy,
+ &NodeInstanceServerProxy::processCrashed);
+}
+
+void ConnectionManager::shutDown()
+{
+ BaseConnectionManager::shutDown();
+
+ closeSocketsAndKillProcesses();
+
+ m_localServer.reset();
+
+ for (Connection &connection : m_connections)
+ connection.clear();
+}
+
+void ConnectionManager::writeCommand(const QVariant &command)
+{
+ for (Connection &connection : m_connections)
+ writeCommandToIODevice(command, connection.socket.get(), m_writeCommandCounter);
+
+ m_writeCommandCounter++;
+}
+
+void ConnectionManager::processFinished(int exitCode, QProcess::ExitStatus exitStatus)
+{
+ auto finishedProcess = qobject_cast<QProcess *>(sender());
+ if (finishedProcess)
+ qWarning() << "Process" << (exitStatus == QProcess::CrashExit ? "crashed:" : "finished:")
+ << finishedProcess->arguments() << "exitCode:" << exitCode;
+ else
+ qWarning() << "Process" << (exitStatus == QProcess::CrashExit ? "crashed:" : "finished:")
+ << sender() << "exitCode:" << exitCode;
+
+ writeCommand(QVariant::fromValue(EndPuppetCommand()));
+
+ closeSocketsAndKillProcesses();
+
+ if (exitStatus == QProcess::CrashExit)
+ emit processCrashed();
+}
+
+void ConnectionManager::closeSocketsAndKillProcesses()
+{
+ for (Connection &connection : m_connections) {
+ if (connection.socket) {
+ disconnect(connection.socket.get());
+ disconnect(connection.qmlPuppetProcess.get());
+ connection.socket->waitForBytesWritten(1000);
+ connection.socket->abort();
+ }
+
+ if (connection.qmlPuppetProcess) {
+ QTimer::singleShot(3000, connection.qmlPuppetProcess.get(), &QProcess::terminate);
+ QTimer::singleShot(6000, connection.qmlPuppetProcess.get(), &QProcess::kill);
+ }
+
+ connection.clear();
+ }
+}
+
+void ConnectionManager::printProcessOutput(QProcess *process, const QString &connectionName)
+{
+ while (process && process->canReadLine()) {
+ QByteArray line = process->readLine();
+ line.chop(1);
+ qDebug().nospace() << connectionName << " Puppet: " << line;
+ }
+ qDebug() << "\n";
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/connectionmanager.h b/src/plugins/qmldesigner/designercore/instances/connectionmanager.h
new file mode 100644
index 0000000000..4bb85b5ff2
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/connectionmanager.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 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 "baseconnectionmanager.h"
+#include "nodeinstanceserverinterface.h"
+
+#include <QElapsedTimer>
+#include <QFile>
+#include <QProcess>
+
+QT_BEGIN_NAMESPACE
+class QLocalServer;
+class QLocalSocket;
+QT_END_NAMESPACE
+
+namespace QmlDesigner {
+
+class QMLDESIGNERCORE_EXPORT ConnectionManager : public BaseConnectionManager
+{
+ Q_OBJECT
+
+public:
+ ConnectionManager();
+ ~ConnectionManager() override;
+ enum PuppetStreamType { FirstPuppetStream, SecondPuppetStream, ThirdPuppetStream };
+
+ void setUp(NodeInstanceServerProxy *nodeInstanceServerProxy,
+ const QString &qrcMappingString,
+ ProjectExplorer::Target *target) override;
+ void shutDown() override;
+
+ void writeCommand(const QVariant &command) override;
+
+signals:
+ void processCrashed();
+
+protected:
+ using BaseConnectionManager::processFinished;
+ void processFinished(int exitCode, QProcess::ExitStatus exitStatus) override;
+
+private:
+ void printProcessOutput(QProcess *process, const QString &connectionName);
+ void closeSocketsAndKillProcesses();
+
+protected:
+ std::vector<Connection> m_connections;
+ quint32 m_writeCommandCounter = 0;
+
+private:
+ std::unique_ptr<QLocalServer> m_localServer;
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/connectionmanagerinterface.cpp b/src/plugins/qmldesigner/designercore/instances/connectionmanagerinterface.cpp
new file mode 100644
index 0000000000..2aa7df6be6
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/connectionmanagerinterface.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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 "connectionmanagerinterface.h"
+
+#include <QLocalSocket>
+#include <QProcess>
+
+namespace QmlDesigner {
+
+ConnectionManagerInterface::~ConnectionManagerInterface() = default;
+
+ConnectionManagerInterface::Connection::~Connection() = default;
+
+ConnectionManagerInterface::Connection::Connection(const QString &name, const QString &mode)
+ : name{name}
+ , mode{mode}
+ , timer{std::make_unique<QTimer>()}
+{}
+
+ConnectionManagerInterface::Connection::Connection(Connection &&connection) = default;
+
+void ConnectionManagerInterface::Connection::clear()
+{
+ qmlPuppetProcess.reset();
+ socket.reset();
+ blockSize = 0;
+ lastReadCommandCounter = 0;
+ timer->stop();
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/connectionmanagerinterface.h b/src/plugins/qmldesigner/designercore/instances/connectionmanagerinterface.h
new file mode 100644
index 0000000000..f3d8e6293e
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/connectionmanagerinterface.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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 "qprocessuniqueptr.h"
+#include <qmldesignercorelib_global.h>
+
+
+QT_BEGIN_NAMESPACE
+class QLocalSocket;
+QT_END_NAMESPACE
+
+namespace ProjectExplorer {
+class Target;
+}
+
+namespace QmlDesigner {
+
+class NodeInstanceServerProxy;
+
+class QMLDESIGNERCORE_EXPORT ConnectionManagerInterface
+{
+public:
+ class QMLDESIGNERCORE_EXPORT Connection final
+ {
+ public:
+ Connection(const QString &name, const QString &mode);
+ Connection(Connection &&connection);
+
+ ~Connection();
+
+ void clear();
+
+ public:
+ QString name;
+ QString mode;
+ QProcessUniquePointer qmlPuppetProcess;
+ std::unique_ptr<QLocalSocket> socket;
+ quint32 blockSize = 0;
+ quint32 lastReadCommandCounter = 0;
+ std::unique_ptr<QTimer> timer;
+ };
+
+ virtual ~ConnectionManagerInterface();
+
+ virtual void setUp(NodeInstanceServerProxy *nodeInstanceServerProxy,
+ const QString &qrcMappingString,
+ ProjectExplorer::Target *target)
+ = 0;
+ virtual void shutDown() = 0;
+
+ virtual void writeCommand(const QVariant &command) = 0;
+
+protected:
+ virtual void dispatchCommand(const QVariant &command, Connection &connection) = 0;
+ virtual void processFinished(int exitCode, QProcess::ExitStatus exitStatus) = 0;
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/instances.pri b/src/plugins/qmldesigner/designercore/instances/instances.pri
index 9856e1243f..7d6b71a080 100644
--- a/src/plugins/qmldesigner/designercore/instances/instances.pri
+++ b/src/plugins/qmldesigner/designercore/instances/instances.pri
@@ -1,14 +1,25 @@
INCLUDEPATH += $$PWD/
-HEADERS += $$PWD/../include/nodeinstance.h
-HEADERS += $$PWD/nodeinstanceserverproxy.h
-HEADERS += $$PWD/puppetcreator.h
-HEADERS += $$PWD/puppetbuildprogressdialog.h
+HEADERS += $$PWD/../include/nodeinstance.h \
+ $$PWD/baseconnectionmanager.h \
+ $$PWD/capturingconnectionmanager.h \
+ $$PWD/connectionmanager.h \
+ $$PWD/connectionmanagerinterface.h \
+ $$PWD/interactiveconnectionmanager.h \
+ $$PWD/nodeinstanceserverproxy.h \
+ $$PWD/puppetcreator.h \
+ $$PWD/puppetbuildprogressdialog.h \
+ $$PWD/qprocessuniqueptr.h
-SOURCES += $$PWD/nodeinstanceserverproxy.cpp
-SOURCES += $$PWD/nodeinstance.cpp
-SOURCES += $$PWD/nodeinstanceview.cpp
-SOURCES += $$PWD/puppetcreator.cpp
-SOURCES += $$PWD/puppetbuildprogressdialog.cpp
+SOURCES += $$PWD/nodeinstanceserverproxy.cpp \
+ $$PWD/baseconnectionmanager.cpp \
+ $$PWD/capturingconnectionmanager.cpp \
+ $$PWD/connectionmanager.cpp \
+ $$PWD/connectionmanagerinterface.cpp \
+ $$PWD/interactiveconnectionmanager.cpp \
+ $$PWD/nodeinstance.cpp \
+ $$PWD/nodeinstanceview.cpp \
+ $$PWD/puppetcreator.cpp \
+ $$PWD/puppetbuildprogressdialog.cpp
FORMS += $$PWD/puppetbuildprogressdialog.ui
diff --git a/src/plugins/qmldesigner/designercore/instances/interactiveconnectionmanager.cpp b/src/plugins/qmldesigner/designercore/instances/interactiveconnectionmanager.cpp
new file mode 100644
index 0000000000..4b6c73f19e
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/interactiveconnectionmanager.cpp
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 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 "interactiveconnectionmanager.h"
+#include "nodeinstanceserverproxy.h"
+#include "nodeinstanceview.h"
+
+#include <qmldesignerplugin.h>
+
+#include <coreplugin/messagebox.h>
+
+#include <QLocalSocket>
+
+namespace QmlDesigner {
+
+InteractiveConnectionManager::InteractiveConnectionManager()
+{
+ m_connections.emplace_back("Editor", "editormode");
+ m_connections.emplace_back("Render", "rendermode");
+ m_connections.emplace_back("Preview", "previewmode");
+}
+
+void InteractiveConnectionManager::setUp(NodeInstanceServerProxy *nodeInstanceServerProxy,
+ const QString &qrcMappingString,
+ ProjectExplorer::Target *target)
+{
+ ConnectionManager::setUp(nodeInstanceServerProxy, qrcMappingString, target);
+
+ DesignerSettings settings = QmlDesignerPlugin::instance()->settings();
+ int timeOutTime = settings.value(DesignerSettingsKey::PUPPET_KILL_TIMEOUT).toInt();
+ for (Connection &connection : m_connections)
+ connection.timer->setInterval(timeOutTime);
+
+ if (QmlDesignerPlugin::instance()
+ ->settings()
+ .value(DesignerSettingsKey::DEBUG_PUPPET)
+ .toString()
+ .isEmpty()) {
+ for (Connection &connection : m_connections) {
+ QObject::connect(connection.timer.get(), &QTimer::timeout, [&]() {
+ puppetTimeout(connection);
+ });
+ }
+ }
+}
+
+void InteractiveConnectionManager::showCannotConnectToPuppetWarningAndSwitchToEditMode()
+{
+ Core::AsynchronousMessageBox::warning(
+ tr("Cannot Connect to QML Emulation Layer (QML Puppet)"),
+ tr("The executable of the QML emulation layer (QML Puppet) may not be responding. "
+ "Switching to another kit might help."));
+
+ QmlDesignerPlugin::instance()->switchToTextModeDeferred();
+ nodeInstanceServerProxy()->nodeInstanceView()->emitDocumentMessage(
+ tr("Cannot Connect to QML Emulation Layer (QML Puppet)"));
+}
+
+void InteractiveConnectionManager::dispatchCommand(const QVariant &command, Connection &connection)
+{
+ static const int puppetAliveCommandType = QMetaType::type("PuppetAliveCommand");
+
+ if (command.userType() == puppetAliveCommandType) {
+ puppetAlive(connection);
+ } else {
+ BaseConnectionManager::dispatchCommand(command, connection);
+ }
+}
+
+void InteractiveConnectionManager::puppetTimeout(Connection &connection)
+{
+ if (connection.socket && connection.socket->waitForReadyRead(10)) {
+ connection.timer->stop();
+ connection.timer->start();
+ return;
+ }
+
+ processFinished();
+}
+
+void InteractiveConnectionManager::puppetAlive(Connection &connection)
+{
+ connection.timer->stop();
+ connection.timer->start();
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/interactiveconnectionmanager.h b/src/plugins/qmldesigner/designercore/instances/interactiveconnectionmanager.h
new file mode 100644
index 0000000000..1946620a43
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/interactiveconnectionmanager.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 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 "connectionmanager.h"
+
+namespace QmlDesigner {
+
+class InteractiveConnectionManager : public ConnectionManager
+{
+public:
+ InteractiveConnectionManager();
+
+ void setUp(NodeInstanceServerProxy *nodeInstanceServerProxy,
+ const QString &qrcMappingString,
+ ProjectExplorer::Target *target) override;
+
+ void showCannotConnectToPuppetWarningAndSwitchToEditMode() override;
+
+protected:
+ void dispatchCommand(const QVariant &command, Connection &connection) override;
+
+private:
+ void puppetTimeout(Connection &connection);
+ void puppetAlive(Connection &connection);
+};
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp
index 8db9aa3a98..026d587233 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.cpp
@@ -25,6 +25,7 @@
#include "nodeinstanceserverproxy.h"
+#include "connectionmanagerinterface.h"
#include "puppetcreator.h"
#include <changeauxiliarycommand.h>
@@ -60,218 +61,55 @@
#include <valueschangedcommand.h>
#include <view3dactioncommand.h>
-#include <nodeinstanceview.h>
#include <import.h>
+#include <nodeinstanceview.h>
#include <rewriterview.h>
-#ifndef QMLDESIGNER_TEST
-#include <qmldesignerplugin.h>
-#endif
-
-#include <coreplugin/icore.h>
-#include <utils/hostosinfo.h>
-#include <coreplugin/messagebox.h>
#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/icore.h>
#include <projectexplorer/kit.h>
-#include <qtsupport/qtkitinformation.h>
+#include <utils/hostosinfo.h>
#include <qtsupport/baseqtversion.h>
+#include <qtsupport/qtkitinformation.h>
#include <qtsupport/qtsupportconstants.h>
+#include <QCoreApplication>
+#include <QDir>
+#include <QFileInfo>
#include <QLocalServer>
#include <QLocalSocket>
#include <QLoggingCategory>
+#include <QMessageBox>
#include <QProcess>
-#include <QCoreApplication>
-#include <QUuid>
-#include <QFileInfo>
-#include <QDir>
-#include <QTimer>
#include <QTextStream>
-#include <QMessageBox>
+#include <QTimer>
+#include <QUuid>
namespace QmlDesigner {
-static Q_LOGGING_CATEGORY(instanceViewBenchmark, "qtc.nodeinstances.init", QtWarningMsg)
-
-void NodeInstanceServerProxy::showCannotConnectToPuppetWarningAndSwitchToEditMode()
-{
-#ifndef QMLDESIGNER_TEST
- Core::AsynchronousMessageBox::warning(tr("Cannot Connect to QML Emulation Layer (QML Puppet)"),
- tr("The executable of the QML emulation layer (QML Puppet) may not be responding. "
- "Switching to another kit might help."));
-
- QmlDesignerPlugin::instance()->switchToTextModeDeferred();
- m_nodeInstanceView->emitDocumentMessage(tr("Cannot Connect to QML Emulation Layer (QML Puppet)"));
-#endif
-
-}
+static Q_LOGGING_CATEGORY(instanceViewBenchmark, "qtc.nodeinstances.init", QtWarningMsg);
NodeInstanceServerProxy::NodeInstanceServerProxy(NodeInstanceView *nodeInstanceView,
- RunModus runModus,
- ProjectExplorer::Target *target)
- : NodeInstanceServerInterface(nodeInstanceView),
- m_localServer(new QLocalServer(this)),
- m_nodeInstanceView(nodeInstanceView),
- m_runModus(runModus)
+ ProjectExplorer::Target *target,
+ ConnectionManagerInterface &connectionManager)
+ : m_nodeInstanceView(nodeInstanceView)
+ , m_connectionManager{connectionManager}
+
{
if (instanceViewBenchmark().isInfoEnabled())
m_benchmarkTimer.start();
- QString socketToken(QUuid::createUuid().toString());
- m_localServer->listen(socketToken);
- m_localServer->setMaxPendingConnections(3);
-
- PuppetCreator puppetCreator(target, nodeInstanceView->model());
- puppetCreator.setQrcMappingString(qrcMappingString());
-
- puppetCreator.createQml2PuppetExecutableIfMissing();
-
- m_qmlPuppetEditorProcess = puppetCreator.createPuppetProcess("editormode",
- socketToken,
- this,
- SLOT(printEditorProcessOutput()),
- SLOT(processFinished(int,QProcess::ExitStatus)));
-
- if (runModus == NormalModus) {
- m_qmlPuppetRenderProcess = puppetCreator.createPuppetProcess("rendermode",
- socketToken,
- this,
- SLOT(printRenderProcessOutput()),
- SLOT(processFinished(int,QProcess::ExitStatus)));
- m_qmlPuppetPreviewProcess = puppetCreator.createPuppetProcess("previewmode",
- socketToken,
- this,
- SLOT(printPreviewProcessOutput()),
- SLOT(processFinished(int,QProcess::ExitStatus)));
- }
-
- const int second = 1000;
- const int waitConstant = 8 * second;
- if (m_qmlPuppetEditorProcess->waitForStarted(waitConstant)) {
- connect(m_qmlPuppetEditorProcess.data(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
- m_qmlPuppetEditorProcess.data(), &QProcess::deleteLater);
- qCInfo(instanceViewBenchmark) << "puppets started:" << m_benchmarkTimer.elapsed();
-
- if (runModus == NormalModus) {
- m_qmlPuppetPreviewProcess->waitForStarted(waitConstant / 2);
- connect(m_qmlPuppetPreviewProcess.data(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
- m_qmlPuppetPreviewProcess.data(), &QProcess::deleteLater);
-
- m_qmlPuppetRenderProcess->waitForStarted(waitConstant / 2);
- connect(m_qmlPuppetRenderProcess.data(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
- m_qmlPuppetRenderProcess.data(), &QProcess::deleteLater);
- }
-
- bool connectedToPuppet = true;
-
- if (!m_localServer->hasPendingConnections())
- connectedToPuppet = m_localServer->waitForNewConnection(waitConstant / 4);
-
- if (connectedToPuppet) {
- m_firstSocket = m_localServer->nextPendingConnection();
- connect(m_firstSocket.data(), &QIODevice::readyRead, this,
- &NodeInstanceServerProxy::readFirstDataStream);
-
- if (runModus == NormalModus) {
- if (!m_localServer->hasPendingConnections())
- connectedToPuppet = m_localServer->waitForNewConnection(waitConstant / 4);
-
- if (connectedToPuppet) {
- m_secondSocket = m_localServer->nextPendingConnection();
- connect(m_secondSocket.data(), &QIODevice::readyRead, this, &NodeInstanceServerProxy::readSecondDataStream);
-
- if (!m_localServer->hasPendingConnections())
- connectedToPuppet = m_localServer->waitForNewConnection(waitConstant / 4);
-
- qCInfo(instanceViewBenchmark) << "puppets connected:" << m_benchmarkTimer.elapsed();
- if (connectedToPuppet) {
- m_thirdSocket = m_localServer->nextPendingConnection();
- connect(m_thirdSocket.data(), &QIODevice::readyRead, this, &NodeInstanceServerProxy::readThirdDataStream);
- } else {
- showCannotConnectToPuppetWarningAndSwitchToEditMode();
- }
- } else {
- showCannotConnectToPuppetWarningAndSwitchToEditMode();
- }
- }
- } else {
- showCannotConnectToPuppetWarningAndSwitchToEditMode();
- }
-
- } else {
- showCannotConnectToPuppetWarningAndSwitchToEditMode();
- }
-
- m_localServer->close();
-
-
- int indexOfCapturePuppetStream = QCoreApplication::arguments().indexOf("-capture-puppet-stream");
- if (indexOfCapturePuppetStream > 0) {
- m_captureFileForTest.setFileName(QCoreApplication::arguments().at(indexOfCapturePuppetStream + 1));
- bool isOpen = m_captureFileForTest.open(QIODevice::WriteOnly);
- qDebug() << "file is open: " << isOpen;
- }
-
-#ifndef QMLDESIGNER_TEST
- DesignerSettings settings = QmlDesignerPlugin::instance()->settings();
- int timeOutTime = settings.value(DesignerSettingsKey::PUPPET_KILL_TIMEOUT).toInt();
- m_firstTimer.setInterval(timeOutTime);
- m_secondTimer.setInterval(timeOutTime);
- m_thirdTimer.setInterval(timeOutTime);
-
- if (QmlDesignerPlugin::instance()->settings().value(DesignerSettingsKey::
- DEBUG_PUPPET).toString().isEmpty()) {
-
- connect(&m_firstTimer, &QTimer::timeout, this,
- [this](){ NodeInstanceServerProxy::puppetTimeout(FirstPuppetStream); });
- connect(&m_secondTimer, &QTimer::timeout, this,
- [this](){ NodeInstanceServerProxy::puppetTimeout(SecondPuppetStream); });
- connect(&m_thirdTimer, &QTimer::timeout, this,
- [this](){ NodeInstanceServerProxy::puppetTimeout(ThirdPuppetStream); });
- }
-#endif
+ m_connectionManager.setUp(this, qrcMappingString(), target);
+
+ qCInfo(instanceViewBenchmark) << "puppets setup:" << m_benchmarkTimer.elapsed();
}
NodeInstanceServerProxy::~NodeInstanceServerProxy()
{
- m_destructing = true;
-
- disconnect(this, SLOT(processFinished(int,QProcess::ExitStatus)));
-
- writeCommand(QVariant::fromValue(EndPuppetCommand()));
-
- if (m_firstSocket) {
- m_firstSocket->waitForBytesWritten(1000);
- m_firstSocket->abort();
- }
-
- if (m_secondSocket) {
- m_secondSocket->waitForBytesWritten(1000);
- m_secondSocket->abort();
- }
-
- if (m_thirdSocket) {
- m_thirdSocket->waitForBytesWritten(1000);
- m_thirdSocket->abort();
- }
-
- if (m_qmlPuppetEditorProcess) {
- QTimer::singleShot(3000, m_qmlPuppetEditorProcess.data(), &QProcess::terminate);
- QTimer::singleShot(6000, m_qmlPuppetEditorProcess.data(), &QProcess::kill);
- }
-
- if (m_qmlPuppetPreviewProcess) {
- QTimer::singleShot(3000, m_qmlPuppetPreviewProcess.data(), &QProcess::terminate);
- QTimer::singleShot(6000, m_qmlPuppetPreviewProcess.data(), &QProcess::kill);
- }
-
- if (m_qmlPuppetRenderProcess) {
- QTimer::singleShot(3000, m_qmlPuppetRenderProcess.data(), &QProcess::terminate);
- QTimer::singleShot(6000, m_qmlPuppetRenderProcess.data(), &QProcess::kill);
- }
+ m_connectionManager.shutDown();
}
-void NodeInstanceServerProxy::dispatchCommand(const QVariant &command, PuppetStreamType puppetStreamType)
+void NodeInstanceServerProxy::dispatchCommand(const QVariant &command)
{
static const int informationChangedCommandType = QMetaType::type("InformationChangedCommand");
static const int valuesChangedCommandType = QMetaType::type("ValuesChangedCommand");
@@ -280,15 +118,10 @@ void NodeInstanceServerProxy::dispatchCommand(const QVariant &command, PuppetStr
static const int childrenChangedCommandType = QMetaType::type("ChildrenChangedCommand");
static const int statePreviewImageChangedCommandType = QMetaType::type("StatePreviewImageChangedCommand");
static const int componentCompletedCommandType = QMetaType::type("ComponentCompletedCommand");
- static const int synchronizeCommandType = QMetaType::type("SynchronizeCommand");
static const int tokenCommandType = QMetaType::type("TokenCommand");
static const int debugOutputCommandType = QMetaType::type("DebugOutputCommand");
- static const int puppetAliveCommandType = QMetaType::type("PuppetAliveCommand");
static const int changeSelectionCommandType = QMetaType::type("ChangeSelectionCommand");
- static const int puppetToCreatorCommand = QMetaType::type("PuppetToCreatorCommand");
-
- if (m_destructing)
- return;
+ static const int puppetToCreatorCommandType = QMetaType::type("PuppetToCreatorCommand");
qCInfo(instanceViewBenchmark) << "dispatching command" << command.userType() << command.typeName();
if (command.userType() == informationChangedCommandType) {
@@ -311,13 +144,8 @@ void NodeInstanceServerProxy::dispatchCommand(const QVariant &command, PuppetStr
nodeInstanceClient()->debugOutput(command.value<DebugOutputCommand>());
} else if (command.userType() == changeSelectionCommandType) {
nodeInstanceClient()->selectionChanged(command.value<ChangeSelectionCommand>());
- } else if (command.userType() == puppetToCreatorCommand) {
+ } else if (command.userType() == puppetToCreatorCommandType) {
nodeInstanceClient()->handlePuppetToCreatorCommand(command.value<PuppetToCreatorCommand>());
- } else if (command.userType() == puppetAliveCommandType) {
- puppetAlive(puppetStreamType);
- } else if (command.userType() == synchronizeCommandType) {
- SynchronizeCommand synchronizeCommand = command.value<SynchronizeCommand>();
- m_synchronizeId = synchronizeCommand.synchronizeId();
} else {
Q_ASSERT(false);
}
@@ -327,33 +155,13 @@ void NodeInstanceServerProxy::dispatchCommand(const QVariant &command, PuppetStr
NodeInstanceClientInterface *NodeInstanceServerProxy::nodeInstanceClient() const
{
- return m_nodeInstanceView.data();
-}
-
-void NodeInstanceServerProxy::puppetAlive(NodeInstanceServerProxy::PuppetStreamType puppetStreamType)
-{
- switch (puppetStreamType) {
- case FirstPuppetStream:
- m_firstTimer.stop();
- m_firstTimer.start();
- break;
- case SecondPuppetStream:
- m_secondTimer.stop();
- m_secondTimer.start();
- break;
- case ThirdPuppetStream:
- m_thirdTimer.stop();
- m_thirdTimer.start();
- break;
- default:
- break;
- }
+ return m_nodeInstanceView;
}
QString NodeInstanceServerProxy::qrcMappingString() const
{
- if (m_nodeInstanceView && m_nodeInstanceView.data()->model()) {
- RewriterView *rewriterView = m_nodeInstanceView.data()->model()->rewriterView();
+ if (m_nodeInstanceView && m_nodeInstanceView->model()) {
+ RewriterView *rewriterView = m_nodeInstanceView->model()->rewriterView();
if (rewriterView) {
QString mappingString;
@@ -374,265 +182,9 @@ QString NodeInstanceServerProxy::qrcMappingString() const
return QString();
}
-void NodeInstanceServerProxy::processFinished()
-{
- processFinished(-1, QProcess::CrashExit);
-}
-
-void NodeInstanceServerProxy::puppetTimeout(PuppetStreamType puppetStreamType)
-{
- switch (puppetStreamType) {
- case FirstPuppetStream:
- if (m_firstSocket->waitForReadyRead(10)) {
- m_firstTimer.stop();
- m_firstTimer.start();
- return;
- }
- break;
- case SecondPuppetStream:
- if (m_secondSocket->waitForReadyRead(10)) {
- m_secondTimer.stop();
- m_secondTimer.start();
- return;
- }
- break;
- case ThirdPuppetStream:
- if (m_thirdSocket->waitForReadyRead(10)) {
- m_thirdTimer.stop();
- m_thirdTimer.start();
- return;
- }
- break;
- default:
- break;
- }
-
- processFinished();
-}
-
-static void writeCommandToIODecive(const QVariant &command, QIODevice *ioDevice, unsigned int commandCounter)
-{
- if (ioDevice) {
- QByteArray block;
- QDataStream out(&block, QIODevice::WriteOnly);
- out.setVersion(QDataStream::Qt_4_8);
- out << quint32(0);
- out << quint32(commandCounter);
- out << command;
- out.device()->seek(0);
- out << quint32(block.size() - sizeof(quint32));
-
- ioDevice->write(block);
- }
-}
-
void NodeInstanceServerProxy::writeCommand(const QVariant &command)
{
- writeCommandToIODecive(command, m_firstSocket.data(), m_writeCommandCounter);
- writeCommandToIODecive(command, m_secondSocket.data(), m_writeCommandCounter);
- writeCommandToIODecive(command, m_thirdSocket.data(), m_writeCommandCounter);
-
- if (m_captureFileForTest.isWritable()) {
- qDebug() << "Write stream to file: " << m_captureFileForTest.fileName();
- writeCommandToIODecive(command, &m_captureFileForTest, m_writeCommandCounter);
- qDebug() << "\twrite file: " << m_captureFileForTest.pos();
- }
-
- m_writeCommandCounter++;
- if (m_runModus == TestModus) {
- static int synchronizeId = 0;
- synchronizeId++;
- SynchronizeCommand synchronizeCommand(synchronizeId);
-
- writeCommandToIODecive(QVariant::fromValue(synchronizeCommand), m_firstSocket.data(), m_writeCommandCounter);
- m_writeCommandCounter++;
-
- while (m_firstSocket->waitForReadyRead(100)) {
- readFirstDataStream();
- if (m_synchronizeId == synchronizeId)
- return;
- }
- }
-}
-
-void NodeInstanceServerProxy::processFinished(int exitCode, QProcess::ExitStatus exitStatus)
-{
- auto finishedProcess = qobject_cast<QProcess*>(sender());
- if (finishedProcess)
- qWarning() << "Process" << (exitStatus == QProcess::CrashExit ? "crashed:" : "finished:") << finishedProcess->arguments() << "exitCode:" << exitCode;
- else
- qWarning() << "Process" << (exitStatus == QProcess::CrashExit ? "crashed:" : "finished:") << sender() << "exitCode:" << exitCode;
-
- if (m_captureFileForTest.isOpen()) {
- m_captureFileForTest.close();
- Core::AsynchronousMessageBox::warning(tr("QML Emulation Layer (QML Puppet) Crashed"),
- tr("You are recording a puppet stream and the emulations layer crashed. "
- "It is recommended to reopen the Qt Quick Designer and start again."));
- }
-
-
- writeCommand(QVariant::fromValue(EndPuppetCommand()));
-
- if (m_firstSocket) {
- m_firstSocket->waitForBytesWritten(1000);
- m_firstSocket->abort();
- }
-
- if (m_secondSocket) {
- m_secondSocket->waitForBytesWritten(1000);
- m_secondSocket->abort();
- }
-
- if (m_thirdSocket) {
- m_thirdSocket->waitForBytesWritten(1000);
- m_thirdSocket->abort();
- }
-
- if (exitStatus == QProcess::CrashExit)
- emit processCrashed();
-}
-
-
-void NodeInstanceServerProxy::readFirstDataStream()
-{
- QList<QVariant> commandList;
-
- while (!m_firstSocket->atEnd()) {
- if (m_firstSocket->bytesAvailable() < int(sizeof(quint32)))
- break;
-
- QDataStream in(m_firstSocket.data());
- in.setVersion(QDataStream::Qt_4_8);
-
- if (m_firstBlockSize == 0)
- in >> m_firstBlockSize;
-
- if (m_firstSocket->bytesAvailable() < m_firstBlockSize)
- break;
-
- quint32 commandCounter;
- in >> commandCounter;
- bool commandLost = !((m_firstLastReadCommandCounter == 0 && commandCounter == 0) || (m_firstLastReadCommandCounter + 1 == commandCounter));
- if (commandLost)
- qDebug() << "server command lost: " << m_firstLastReadCommandCounter << commandCounter;
- m_firstLastReadCommandCounter = commandCounter;
-
-
- QVariant command;
- in >> command;
- m_firstBlockSize = 0;
-
- commandList.append(command);
- }
-
- foreach (const QVariant &command, commandList) {
- dispatchCommand(command, FirstPuppetStream);
- }
-}
-
-void NodeInstanceServerProxy::readSecondDataStream()
-{
- QList<QVariant> commandList;
-
- while (!m_secondSocket->atEnd()) {
- if (m_secondSocket->bytesAvailable() < int(sizeof(quint32)))
- break;
-
- QDataStream in(m_secondSocket.data());
- in.setVersion(QDataStream::Qt_4_8);
-
- if (m_secondBlockSize == 0)
- in >> m_secondBlockSize;
-
- if (m_secondSocket->bytesAvailable() < m_secondBlockSize)
- break;
-
- quint32 commandCounter;
- in >> commandCounter;
- bool commandLost = !((m_secondLastReadCommandCounter == 0 && commandCounter == 0) || (m_secondLastReadCommandCounter + 1 == commandCounter));
- if (commandLost)
- qDebug() << "server command lost: " << m_secondLastReadCommandCounter << commandCounter;
- m_secondLastReadCommandCounter = commandCounter;
-
-
- QVariant command;
- in >> command;
- m_secondBlockSize = 0;
-
- commandList.append(command);
- }
-
- foreach (const QVariant &command, commandList) {
- dispatchCommand(command, SecondPuppetStream);
- }
-}
-
-void NodeInstanceServerProxy::readThirdDataStream()
-{
- QList<QVariant> commandList;
-
- while (!m_thirdSocket->atEnd()) {
- if (m_thirdSocket->bytesAvailable() < int(sizeof(quint32)))
- break;
-
- QDataStream in(m_thirdSocket.data());
- in.setVersion(QDataStream::Qt_4_8);
-
- if (m_thirdBlockSize == 0)
- in >> m_thirdBlockSize;
-
- if (m_thirdSocket->bytesAvailable() < m_thirdBlockSize)
- break;
-
- quint32 commandCounter;
- in >> commandCounter;
- bool commandLost = !((m_thirdLastReadCommandCounter == 0 && commandCounter == 0) || (m_thirdLastReadCommandCounter + 1 == commandCounter));
- if (commandLost)
- qDebug() << "server command lost: " << m_thirdLastReadCommandCounter << commandCounter;
- m_thirdLastReadCommandCounter = commandCounter;
-
-
- QVariant command;
- in >> command;
- m_thirdBlockSize = 0;
-
- commandList.append(command);
- }
-
- foreach (const QVariant &command, commandList) {
- dispatchCommand(command, ThirdPuppetStream);
- }
-}
-
-void NodeInstanceServerProxy::printEditorProcessOutput()
-{
- while (m_qmlPuppetEditorProcess && m_qmlPuppetEditorProcess->canReadLine()) {
- QByteArray line = m_qmlPuppetEditorProcess->readLine();
- line.chop(1);
- qDebug().nospace() << "Editor Puppet: " << line;
- }
- qDebug() << "\n";
-}
-
-void NodeInstanceServerProxy::printPreviewProcessOutput()
-{
- while (m_qmlPuppetPreviewProcess && m_qmlPuppetPreviewProcess->canReadLine()) {
- QByteArray line = m_qmlPuppetPreviewProcess->readLine();
- line.chop(1);
- qDebug().nospace() << "Preview Puppet: " << line;
- }
- qDebug() << "\n";
-}
-
-void NodeInstanceServerProxy::printRenderProcessOutput()
-{
- while (m_qmlPuppetRenderProcess && m_qmlPuppetRenderProcess->canReadLine()) {
- QByteArray line = m_qmlPuppetRenderProcess->readLine();
- line.chop(1);
- qDebug().nospace() << "Render Puppet: " << line;
- }
-
- qDebug() << "\n";
+ m_connectionManager.writeCommand(command);
}
void NodeInstanceServerProxy::createInstances(const CreateInstancesCommand &command)
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h
index 4b0df0fd9a..2efc7ea8a4 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceserverproxy.h
@@ -48,21 +48,17 @@ namespace QmlDesigner {
class NodeInstanceClientInterface;
class NodeInstanceView;
class NodeInstanceClientProxy;
+class ConnectionManagerInterface;
class NodeInstanceServerProxy : public NodeInstanceServerInterface
{
+ friend class BaseConnectionManager;
Q_OBJECT
public:
- enum PuppetStreamType {
- FirstPuppetStream,
- SecondPuppetStream,
- ThirdPuppetStream,
- };
-
explicit NodeInstanceServerProxy(NodeInstanceView *nodeInstanceView,
- RunModus runModus,
- ProjectExplorer::Target *target);
+ ProjectExplorer::Target *target,
+ ConnectionManagerInterface &connectionManager);
~NodeInstanceServerProxy() override;
void createInstances(const CreateInstancesCommand &command) override;
void changeFileUrl(const ChangeFileUrlCommand &command) override;
@@ -88,52 +84,22 @@ public:
void changeLanguage(const ChangeLanguageCommand &command) override;
void changePreviewImageSize(const ChangePreviewImageSizeCommand &command) override;
+ NodeInstanceView *nodeInstanceView() const { return m_nodeInstanceView; }
+
+ QString qrcMappingString() const;
+
protected:
void writeCommand(const QVariant &command);
- void dispatchCommand(const QVariant &command, PuppetStreamType puppetStreamType);
+ void dispatchCommand(const QVariant &command);
NodeInstanceClientInterface *nodeInstanceClient() const;
- void puppetAlive(PuppetStreamType puppetStreamType);
- QString qrcMappingString() const;
signals:
void processCrashed();
-private slots:
- void processFinished();
- void puppetTimeout(PuppetStreamType puppetStreamType);
- void processFinished(int exitCode, QProcess::ExitStatus exitStatus);
- void readFirstDataStream();
- void readSecondDataStream();
- void readThirdDataStream();
-
- void printEditorProcessOutput();
- void printPreviewProcessOutput();
- void printRenderProcessOutput();
- void showCannotConnectToPuppetWarningAndSwitchToEditMode();
private:
- QFile m_captureFileForTest;
- QTimer m_firstTimer;
- QTimer m_secondTimer;
- QTimer m_thirdTimer;
- QPointer<QLocalServer> m_localServer;
- QPointer<QLocalSocket> m_firstSocket;
- QPointer<QLocalSocket> m_secondSocket;
- QPointer<QLocalSocket> m_thirdSocket;
- QPointer<NodeInstanceView> m_nodeInstanceView;
- QPointer<QProcess> m_qmlPuppetEditorProcess;
- QPointer<QProcess> m_qmlPuppetPreviewProcess;
- QPointer<QProcess> m_qmlPuppetRenderProcess;
- quint32 m_firstBlockSize = 0;
- quint32 m_secondBlockSize = 0;
- quint32 m_thirdBlockSize = 0;
- quint32 m_writeCommandCounter = 0;
- quint32 m_firstLastReadCommandCounter = 0;
- quint32 m_secondLastReadCommandCounter = 0;
- quint32 m_thirdLastReadCommandCounter = 0;
- RunModus m_runModus;
- int m_synchronizeId = -1;
+ NodeInstanceView *m_nodeInstanceView{};
QElapsedTimer m_benchmarkTimer;
- bool m_destructing = false;
+ ConnectionManagerInterface &m_connectionManager;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
index ce6412962d..8c078e29aa 100644
--- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp
@@ -27,6 +27,7 @@
#include "abstractproperty.h"
#include "bindingproperty.h"
+#include "captureddatacommand.h"
#include "changeauxiliarycommand.h"
#include "changebindingscommand.h"
#include "changefileurlcommand.h"
@@ -41,6 +42,7 @@
#include "clearscenecommand.h"
#include "completecomponentcommand.h"
#include "componentcompletedcommand.h"
+#include "connectionmanagerinterface.h"
#include "createinstancescommand.h"
#include "createscenecommand.h"
#include "debugoutputcommand.h"
@@ -124,11 +126,10 @@ namespace QmlDesigner {
\sa ~NodeInstanceView, setRenderOffScreen()
*/
-NodeInstanceView::NodeInstanceView(QObject *parent, NodeInstanceServerInterface::RunModus runModus)
- : AbstractView(parent),
- m_baseStatePreviewImage(QSize(100, 100), QImage::Format_ARGB32),
- m_runModus(runModus),
- m_restartProcessTimerId(0)
+NodeInstanceView::NodeInstanceView(ConnectionManagerInterface &connectionManager)
+ : m_connectionManager(connectionManager)
+ , m_baseStatePreviewImage(QSize(100, 100), QImage::Format_ARGB32)
+ , m_restartProcessTimerId(0)
{
m_baseStatePreviewImage.fill(0xFFFFFF);
}
@@ -140,7 +141,6 @@ NodeInstanceView::NodeInstanceView(QObject *parent, NodeInstanceServerInterface:
NodeInstanceView::~NodeInstanceView()
{
removeAllInstanceNodeRelationships();
- delete nodeInstanceServer();
m_currentTarget = nullptr;
}
@@ -191,14 +191,16 @@ bool static parentTakesOverRendering(const ModelNode &modelNode)
void NodeInstanceView::modelAttached(Model *model)
{
AbstractView::modelAttached(model);
- auto server = new NodeInstanceServerProxy(this, m_runModus, m_currentTarget);
- m_nodeInstanceServer = server;
+ m_nodeInstanceServer = createNodeInstanceServerProxy();
m_lastCrashTime.start();
- connect(server, &NodeInstanceServerProxy::processCrashed, this, &NodeInstanceView::handleCrash);
+ connect(m_nodeInstanceServer.get(),
+ &NodeInstanceServerProxy::processCrashed,
+ this,
+ &NodeInstanceView::handleCrash);
if (!isSkippedRootNode(rootModelNode())) {
- nodeInstanceServer()->createScene(createCreateSceneCommand());
- nodeInstanceServer()->changeSelection(createChangeSelectionCommand(model->selectedNodes(this)));
+ m_nodeInstanceServer->createScene(createCreateSceneCommand());
+ m_nodeInstanceServer->changeSelection(createChangeSelectionCommand(model->selectedNodes(this)));
}
ModelNode stateNode = currentStateNode();
@@ -206,15 +208,14 @@ void NodeInstanceView::modelAttached(Model *model)
NodeInstance newStateInstance = instanceForModelNode(stateNode);
activateState(newStateInstance);
}
-
}
void NodeInstanceView::modelAboutToBeDetached(Model * model)
{
removeAllInstanceNodeRelationships();
- if (nodeInstanceServer()) {
- nodeInstanceServer()->clearScene(createClearSceneCommand());
- delete nodeInstanceServer();
+ if (m_nodeInstanceServer) {
+ m_nodeInstanceServer->clearScene(createClearSceneCommand());
+ m_nodeInstanceServer.reset();
}
m_statePreviewImage.clear();
m_baseStatePreviewImage = QImage();
@@ -274,15 +275,18 @@ void NodeInstanceView::restartProcess()
killTimer(m_restartProcessTimerId);
if (model()) {
- delete nodeInstanceServer();
+ m_nodeInstanceServer.reset();
+ m_nodeInstanceServer = createNodeInstanceServerProxy();
- auto server = new NodeInstanceServerProxy(this, m_runModus, m_currentTarget);
- m_nodeInstanceServer = server;
- connect(server, &NodeInstanceServerProxy::processCrashed, this, &NodeInstanceView::handleCrash);
+ connect(m_nodeInstanceServer.get(),
+ &NodeInstanceServerProxy::processCrashed,
+ this,
+ &NodeInstanceView::handleCrash);
if (!isSkippedRootNode(rootModelNode())) {
- nodeInstanceServer()->createScene(createCreateSceneCommand());
- nodeInstanceServer()->changeSelection(createChangeSelectionCommand(model()->selectedNodes(this)));
+ m_nodeInstanceServer->createScene(createCreateSceneCommand());
+ m_nodeInstanceServer->changeSelection(
+ createChangeSelectionCommand(model()->selectedNodes(this)));
}
ModelNode stateNode = currentStateNode();
@@ -313,17 +317,19 @@ void NodeInstanceView::nodeCreated(const ModelNode &createdNode)
propertyList.append(createdNode.variantProperty("y"));
updatePosition(propertyList);
- nodeInstanceServer()->createInstances(createCreateInstancesCommand({instance}));
- nodeInstanceServer()->changePropertyValues(createChangeValueCommand(createdNode.variantProperties()));
- nodeInstanceServer()->completeComponent(createComponentCompleteCommand({instance}));
+ m_nodeInstanceServer->createInstances(createCreateInstancesCommand({instance}));
+ m_nodeInstanceServer->changePropertyValues(
+ createChangeValueCommand(createdNode.variantProperties()));
+ m_nodeInstanceServer->completeComponent(createComponentCompleteCommand({instance}));
}
/*! Notifies the view that \a removedNode will be removed.
*/
void NodeInstanceView::nodeAboutToBeRemoved(const ModelNode &removedNode)
{
- nodeInstanceServer()->removeInstances(createRemoveInstancesCommand(removedNode));
- nodeInstanceServer()->removeSharedMemory(createRemoveSharedMemoryCommand("Image", removedNode.internalId()));
+ m_nodeInstanceServer->removeInstances(createRemoveInstancesCommand(removedNode));
+ m_nodeInstanceServer->removeSharedMemory(
+ createRemoveSharedMemoryCommand("Image", removedNode.internalId()));
removeInstanceAndSubInstances(removedNode);
}
@@ -343,11 +349,10 @@ void NodeInstanceView::resetHorizontalAnchors(const ModelNode &modelNode)
valueList.append(modelNode.variantProperty("width"));
if (!valueList.isEmpty())
- nodeInstanceServer()->changePropertyValues(createChangeValueCommand(valueList));
+ m_nodeInstanceServer->changePropertyValues(createChangeValueCommand(valueList));
if (!bindingList.isEmpty())
- nodeInstanceServer()->changePropertyBindings(createChangeBindingCommand(bindingList));
-
+ m_nodeInstanceServer->changePropertyBindings(createChangeBindingCommand(bindingList));
}
void NodeInstanceView::resetVerticalAnchors(const ModelNode &modelNode)
@@ -366,10 +371,10 @@ void NodeInstanceView::resetVerticalAnchors(const ModelNode &modelNode)
valueList.append(modelNode.variantProperty("height"));
if (!valueList.isEmpty())
- nodeInstanceServer()->changePropertyValues(createChangeValueCommand(valueList));
+ m_nodeInstanceServer->changePropertyValues(createChangeValueCommand(valueList));
if (!bindingList.isEmpty())
- nodeInstanceServer()->changePropertyBindings(createChangeBindingCommand(bindingList));
+ m_nodeInstanceServer->changePropertyBindings(createChangeBindingCommand(bindingList));
}
void NodeInstanceView::propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList)
@@ -388,10 +393,10 @@ void NodeInstanceView::propertiesAboutToBeRemoved(const QList<AbstractProperty>&
RemoveInstancesCommand removeInstancesCommand = createRemoveInstancesCommand(nodeList);
if (!removeInstancesCommand.instanceIds().isEmpty())
- nodeInstanceServer()->removeInstances(removeInstancesCommand);
+ m_nodeInstanceServer->removeInstances(removeInstancesCommand);
- nodeInstanceServer()->removeSharedMemory(createRemoveSharedMemoryCommand("Image", nodeList));
- nodeInstanceServer()->removeProperties(createRemovePropertiesCommand(nonNodePropertyList));
+ m_nodeInstanceServer->removeSharedMemory(createRemoveSharedMemoryCommand("Image", nodeList));
+ m_nodeInstanceServer->removeProperties(createRemovePropertiesCommand(nonNodePropertyList));
foreach (const AbstractProperty &property, propertyList) {
const PropertyName &name = property.name();
@@ -445,7 +450,7 @@ void NodeInstanceView::nodeTypeChanged(const ModelNode &, const TypeName &, int,
void NodeInstanceView::bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags /*propertyChange*/)
{
- nodeInstanceServer()->changePropertyBindings(createChangeBindingCommand(propertyList));
+ m_nodeInstanceServer->changePropertyBindings(createChangeBindingCommand(propertyList));
}
/*!
@@ -460,7 +465,7 @@ void NodeInstanceView::bindingPropertiesChanged(const QList<BindingProperty>& pr
void NodeInstanceView::variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags /*propertyChange*/)
{
updatePosition(propertyList);
- nodeInstanceServer()->changePropertyValues(createChangeValueCommand(propertyList));
+ m_nodeInstanceServer->changePropertyValues(createChangeValueCommand(propertyList));
}
/*!
Notifies the view that the property parent of the model node \a node has
@@ -476,20 +481,21 @@ void NodeInstanceView::nodeReparented(const ModelNode &node, const NodeAbstractP
{
if (!isSkippedNode(node)) {
updateChildren(newPropertyParent);
- nodeInstanceServer()->reparentInstances(createReparentInstancesCommand(node, newPropertyParent, oldPropertyParent));
+ m_nodeInstanceServer->reparentInstances(
+ createReparentInstancesCommand(node, newPropertyParent, oldPropertyParent));
}
}
void NodeInstanceView::fileUrlChanged(const QUrl &/*oldUrl*/, const QUrl &newUrl)
{
- nodeInstanceServer()->changeFileUrl(createChangeFileUrlCommand(newUrl));
+ m_nodeInstanceServer->changeFileUrl(createChangeFileUrlCommand(newUrl));
}
void NodeInstanceView::nodeIdChanged(const ModelNode& node, const QString& /*newId*/, const QString& /*oldId*/)
{
if (hasInstanceForModelNode(node)) {
NodeInstance instance = instanceForModelNode(node);
- nodeInstanceServer()->changeIds(createChangeIdsCommand({instance}));
+ m_nodeInstanceServer->changeIds(createChangeIdsCommand({instance}));
}
}
@@ -512,7 +518,7 @@ void NodeInstanceView::nodeOrderChanged(const NodeListProperty & listProperty,
}
}
- nodeInstanceServer()->reparentInstances(ReparentInstancesCommand(containerList));
+ m_nodeInstanceServer->reparentInstances(ReparentInstancesCommand(containerList));
}
void NodeInstanceView::importsChanged(const QList<Import> &/*addedImports*/, const QList<Import> &/*removedImports*/)
@@ -531,16 +537,16 @@ void NodeInstanceView::auxiliaryDataChanged(const ModelNode &node,
if (value.isValid() || name == "invisible") {
PropertyValueContainer container(instance.instanceId(), name, value, TypeName());
ChangeAuxiliaryCommand changeAuxiliaryCommand({container});
- nodeInstanceServer()->changeAuxiliaryValues(changeAuxiliaryCommand);
+ m_nodeInstanceServer->changeAuxiliaryValues(changeAuxiliaryCommand);
} else {
if (node.hasVariantProperty(name)) {
PropertyValueContainer container(instance.instanceId(), name, node.variantProperty(name).value(), TypeName());
ChangeValuesCommand changeValueCommand({container});
- nodeInstanceServer()->changePropertyValues(changeValueCommand);
+ m_nodeInstanceServer->changePropertyValues(changeValueCommand);
} else if (node.hasBindingProperty(name)) {
PropertyBindingContainer container(instance.instanceId(), name, node.bindingProperty(name).expression(), TypeName());
ChangeBindingsCommand changeValueCommand({container});
- nodeInstanceServer()->changePropertyBindings(changeValueCommand);
+ m_nodeInstanceServer->changePropertyBindings(changeValueCommand);
}
}
}
@@ -548,9 +554,9 @@ void NodeInstanceView::auxiliaryDataChanged(const ModelNode &node,
const QString languageAsString = value.toString();
if (auto multiLanguageAspect = QmlProjectManager::QmlMultiLanguageAspect::current(m_currentTarget))
multiLanguageAspect->setCurrentLocale(languageAsString);
- nodeInstanceServer()->changeLanguage({languageAsString});
+ m_nodeInstanceServer->changeLanguage({languageAsString});
} else if (node.isRootNode() && name == "previewSize@Internal") {
- nodeInstanceServer()->changePreviewImageSize(value.toSize());
+ m_nodeInstanceServer->changePreviewImageSize(value.toSize());
}
}
@@ -565,10 +571,12 @@ void NodeInstanceView::nodeSourceChanged(const ModelNode &node, const QString &
if (hasInstanceForModelNode(node)) {
NodeInstance instance = instanceForModelNode(node);
ChangeNodeSourceCommand changeNodeSourceCommand(instance.instanceId(), newNodeSource);
- nodeInstanceServer()->changeNodeSource(changeNodeSourceCommand);
+ m_nodeInstanceServer->changeNodeSource(changeNodeSourceCommand);
}
}
+void NodeInstanceView::capturedData(const CapturedDataCommand &) {}
+
void NodeInstanceView::currentStateChanged(const ModelNode &node)
{
NodeInstance newStateInstance = instanceForModelNode(node);
@@ -790,12 +798,6 @@ void NodeInstanceView::updatePosition(const QList<VariantProperty> &propertyList
emitInstanceInformationsChange(informationChangeHash);
}
-NodeInstanceServerInterface *NodeInstanceView::nodeInstanceServer() const
-{
- return m_nodeInstanceServer.data();
-}
-
-
NodeInstance NodeInstanceView::loadNode(const ModelNode &node)
{
NodeInstance instance(NodeInstance::create(node));
@@ -810,12 +812,12 @@ NodeInstance NodeInstanceView::loadNode(const ModelNode &node)
void NodeInstanceView::activateState(const NodeInstance &instance)
{
- nodeInstanceServer()->changeState(ChangeStateCommand(instance.instanceId()));
+ m_nodeInstanceServer->changeState(ChangeStateCommand(instance.instanceId()));
}
void NodeInstanceView::activateBaseState()
{
- nodeInstanceServer()->changeState(ChangeStateCommand(-1));
+ m_nodeInstanceServer->changeState(ChangeStateCommand(-1));
}
void NodeInstanceView::removeRecursiveChildRelationship(const ModelNode &removedNode)
@@ -1248,7 +1250,8 @@ void NodeInstanceView::valuesChanged(const ValuesChangedCommand &command)
}
}
- nodeInstanceServer()->removeSharedMemory(createRemoveSharedMemoryCommand(QStringLiteral("Values"), command.keyNumber()));
+ m_nodeInstanceServer->removeSharedMemory(
+ createRemoveSharedMemoryCommand(QStringLiteral("Values"), command.keyNumber()));
if (!valuePropertyChangeList.isEmpty())
emitInstancePropertyChange(valuePropertyChangeList);
@@ -1456,7 +1459,7 @@ void NodeInstanceView::sendToken(const QString &token, int number, const QVector
foreach (const ModelNode &node, nodeVector)
instanceIdVector.append(node.internalId());
- nodeInstanceServer()->token(TokenCommand(token, number, instanceIdVector));
+ m_nodeInstanceServer->token(TokenCommand(token, number, instanceIdVector));
}
void NodeInstanceView::selectionChanged(const ChangeSelectionCommand &command)
@@ -1471,7 +1474,7 @@ void NodeInstanceView::selectionChanged(const ChangeSelectionCommand &command)
void NodeInstanceView::handlePuppetToCreatorCommand(const PuppetToCreatorCommand &command)
{
if (command.type() == PuppetToCreatorCommand::Edit3DToolState) {
- if (!m_nodeInstanceServer.isNull()) {
+ if (m_nodeInstanceServer) {
auto data = qvariant_cast<QVariantList>(command.data());
if (data.size() == 3) {
QString qmlId = data[0].toString();
@@ -1488,25 +1491,30 @@ void NodeInstanceView::handlePuppetToCreatorCommand(const PuppetToCreatorCommand
}
}
+std::unique_ptr<NodeInstanceServerProxy> NodeInstanceView::createNodeInstanceServerProxy()
+{
+ return std::make_unique<NodeInstanceServerProxy>(this, m_currentTarget, m_connectionManager);
+}
+
void NodeInstanceView::selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
const QList<ModelNode> & /*lastSelectedNodeList*/)
{
- nodeInstanceServer()->changeSelection(createChangeSelectionCommand(selectedNodeList));
+ m_nodeInstanceServer->changeSelection(createChangeSelectionCommand(selectedNodeList));
}
void NodeInstanceView::sendInputEvent(QInputEvent *e) const
{
- nodeInstanceServer()->inputEvent(InputEventCommand(e));
+ m_nodeInstanceServer->inputEvent(InputEventCommand(e));
}
void NodeInstanceView::view3DAction(const View3DActionCommand &command)
{
- nodeInstanceServer()->view3DAction(command);
+ m_nodeInstanceServer->view3DAction(command);
}
void NodeInstanceView::edit3DViewResized(const QSize &size) const
{
- nodeInstanceServer()->update3DViewState(Update3dViewStateCommand(size));
+ m_nodeInstanceServer->update3DViewState(Update3dViewStateCommand(size));
}
void NodeInstanceView::timerEvent(QTimerEvent *event)
diff --git a/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp b/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp
index 7eefa7f1bc..a26c59d792 100644
--- a/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp
+++ b/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp
@@ -176,39 +176,46 @@ PuppetCreator::PuppetCreator(ProjectExplorer::Target *target, const Model *model
{
}
-QProcess *PuppetCreator::createPuppetProcess(const QString &puppetMode,
- const QString &socketToken,
- QObject *handlerObject,
- const char *outputSlot,
- const char *finishSlot,
- const QStringList &customOptions) const
+QProcessUniquePointer PuppetCreator::createPuppetProcess(
+ const QString &puppetMode,
+ const QString &socketToken,
+ QObject *handlerObject,
+ std::function<void()> processOutputCallback,
+ std::function<void(int, QProcess::ExitStatus)> processFinishCallback,
+ const QStringList &customOptions) const
{
return puppetProcess(qml2PuppetPath(m_availablePuppetType),
qmlPuppetDirectory(m_availablePuppetType),
puppetMode,
socketToken,
handlerObject,
- outputSlot,
- finishSlot,
+ processOutputCallback,
+ processFinishCallback,
customOptions);
}
-
-QProcess *PuppetCreator::puppetProcess(const QString &puppetPath,
- const QString &workingDirectory,
- const QString &puppetMode,
- const QString &socketToken,
- QObject *handlerObject,
- const char *outputSlot,
- const char *finishSlot,
- const QStringList &customOptions) const
+QProcessUniquePointer PuppetCreator::puppetProcess(
+ const QString &puppetPath,
+ const QString &workingDirectory,
+ const QString &puppetMode,
+ const QString &socketToken,
+ QObject *handlerObject,
+ std::function<void()> processOutputCallback,
+ std::function<void(int, QProcess::ExitStatus)> processFinishCallback,
+ const QStringList &customOptions) const
{
- auto puppetProcess = new QProcess;
+ QProcessUniquePointer puppetProcess{new QProcess};
puppetProcess->setObjectName(puppetMode);
puppetProcess->setProcessEnvironment(processEnvironment());
- QObject::connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, puppetProcess, &QProcess::kill);
- QObject::connect(puppetProcess, SIGNAL(finished(int,QProcess::ExitStatus)), handlerObject, finishSlot);
+ QObject::connect(QCoreApplication::instance(),
+ &QCoreApplication::aboutToQuit,
+ puppetProcess.get(),
+ &QProcess::kill);
+ QObject::connect(puppetProcess.get(),
+ static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
+ handlerObject,
+ processFinishCallback);
#ifndef QMLDESIGNER_TEST
QString forwardOutput = m_designerSettings.value(DesignerSettingsKey::
@@ -218,7 +225,7 @@ QProcess *PuppetCreator::puppetProcess(const QString &puppetPath,
#endif
if (forwardOutput == puppetMode || forwardOutput == "all") {
puppetProcess->setProcessChannelMode(QProcess::MergedChannels);
- QObject::connect(puppetProcess, SIGNAL(readyRead()), handlerObject, outputSlot);
+ QObject::connect(puppetProcess.get(), &QProcess::readyRead, handlerObject, processOutputCallback);
}
puppetProcess->setWorkingDirectory(workingDirectory);
diff --git a/src/plugins/qmldesigner/designercore/instances/puppetcreator.h b/src/plugins/qmldesigner/designercore/instances/puppetcreator.h
index bafea8fa3e..e6083d7014 100644
--- a/src/plugins/qmldesigner/designercore/instances/puppetcreator.h
+++ b/src/plugins/qmldesigner/designercore/instances/puppetcreator.h
@@ -25,6 +25,8 @@
#pragma once
+#include "qprocessuniqueptr.h"
+
#include <QString>
#include <QProcessEnvironment>
@@ -53,12 +55,13 @@ public:
void createQml2PuppetExecutableIfMissing();
- QProcess *createPuppetProcess(const QString &puppetMode,
- const QString &socketToken,
- QObject *handlerObject,
- const char *outputSlot,
- const char *finishSlot,
- const QStringList &customOptions = {}) const;
+ QProcessUniquePointer createPuppetProcess(
+ const QString &puppetMode,
+ const QString &socketToken,
+ QObject *handlerObject,
+ std::function<void()> processOutputCallback,
+ std::function<void(int, QProcess::ExitStatus)> processFinishCallback,
+ const QStringList &customOptions = {}) const;
void setQrcMappingString(const QString qrcMapping);
@@ -82,14 +85,14 @@ protected:
bool checkPuppetIsReady(const QString &puppetPath) const;
bool qtIsSupported() const;
- QProcess *puppetProcess(const QString &puppetPath,
- const QString &workingDirectory,
- const QString &puppetMode,
- const QString &socketToken,
- QObject *handlerObject,
- const char *outputSlot,
- const char *finishSlot,
- const QStringList &customOptions) const;
+ QProcessUniquePointer puppetProcess(const QString &puppetPath,
+ const QString &workingDirectory,
+ const QString &puppetMode,
+ const QString &socketToken,
+ QObject *handlerObject,
+ std::function<void()> processOutputCallback,
+ std::function<void(int, QProcess::ExitStatus)> processFinishCallback,
+ const QStringList &customOptions) const;
QProcessEnvironment processEnvironment() const;
diff --git a/src/plugins/qmldesigner/designercore/instances/qprocessuniqueptr.h b/src/plugins/qmldesigner/designercore/instances/qprocessuniqueptr.h
new file mode 100644
index 0000000000..b03c86f772
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/instances/qprocessuniqueptr.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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 <QProcess>
+
+#include <memory>
+
+namespace QmlDesigner {
+
+class QProcessUniquePointerDeleter
+{
+public:
+ void operator()(QProcess *process)
+ {
+ process->disconnect();
+ QObject::connect(process,
+ QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
+ process,
+ &QProcess::deleteLater);
+
+ process->terminate();
+
+ process->deleteLater();
+ }
+};
+
+using QProcessUniquePointer = std::unique_ptr<QProcess, QProcessUniquePointerDeleter>;
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/model/viewmanager.cpp b/src/plugins/qmldesigner/designercore/model/viewmanager.cpp
index 3173a68abd..f5dc99bf35 100644
--- a/src/plugins/qmldesigner/designercore/model/viewmanager.cpp
+++ b/src/plugins/qmldesigner/designercore/model/viewmanager.cpp
@@ -27,23 +27,24 @@
#ifndef QMLDESIGNER_TEST
+#include <abstractview.h>
#include <componentaction.h>
-#include <designmodewidget.h>
+#include <componentview.h>
#include <crumblebar.h>
-#include <abstractview.h>
-#include <rewriterview.h>
-#include <nodeinstanceview.h>
+#include <debugview.h>
+#include <designeractionmanagerview.h>
+#include <designmodewidget.h>
+#include <edit3dview.h>
+#include <formeditorview.h>
+#include <importmanagerview.h>
+#include <interactiveconnectionmanager.h>
#include <itemlibraryview.h>
#include <navigatorview.h>
+#include <nodeinstanceview.h>
+#include <propertyeditorview.h>
+#include <rewriterview.h>
#include <stateseditorview.h>
-#include <edit3dview.h>
-#include <formeditorview.h>
#include <texteditorview.h>
-#include <propertyeditorview.h>
-#include <componentview.h>
-#include <debugview.h>
-#include <importmanagerview.h>
-#include <designeractionmanagerview.h>
#include <qmldesignerplugin.h>
#include <utils/algorithm.h>
@@ -59,10 +60,11 @@ static Q_LOGGING_CATEGORY(viewBenchmark, "qtc.viewmanager.attach", QtWarningMsg)
class ViewManagerData
{
public:
+ InteractiveConnectionManager connectionManager;
QmlModelState savedState;
Internal::DebugView debugView;
DesignerActionManagerView designerActionManagerView;
- NodeInstanceView nodeInstanceView;
+ NodeInstanceView nodeInstanceView{connectionManager};
ComponentView componentView;
Edit3DView edit3DView;
FormEditorView formEditorView;
@@ -81,7 +83,7 @@ static CrumbleBar *crumbleBar() {
}
ViewManager::ViewManager()
- : d(new ViewManagerData)
+ : d(std::make_unique<ViewManagerData>())
{
d->formEditorView.setGotoErrorCallback([this](int line, int column) {
d->textEditorView.gotoCursorPosition(line, column);
@@ -92,10 +94,9 @@ ViewManager::ViewManager()
ViewManager::~ViewManager()
{
- foreach (const QPointer<AbstractView> &view, d->additionalViews)
+ for (const QPointer<AbstractView> &view : d->additionalViews)
delete view.data();
- delete d;
}
DesignDocument *ViewManager::currentDesignDocument() const
diff --git a/src/plugins/qmldesigner/qmldesignerplugin.qbs b/src/plugins/qmldesigner/qmldesignerplugin.qbs
index dceaf8656d..971bcffb47 100644
--- a/src/plugins/qmldesigner/qmldesignerplugin.qbs
+++ b/src/plugins/qmldesigner/qmldesignerplugin.qbs
@@ -321,6 +321,17 @@ Project {
"instances/puppetdialog.cpp",
"instances/puppetdialog.h",
"instances/puppetdialog.ui",
+ "instances/connectionmanagerinterface.cpp",
+ "instances/connectionmanagerinterface.h",
+ "instances/baseconnectionmanager.cpp ",
+ "instances/baseconnectionmanager.h",
+ "instances/connectionmanager.cpp",
+ "instances/connectionmanager.h",
+ "instances/capturingconnectionmanager.cpp",
+ "instances/capturingconnectionmanager.h",
+ "instances/interactiveconnectionmanager.cpp",
+ "instances/interactiveconnectionmanager.h",
+ "instances/qprocessuniqueptr.h",
"metainfo/itemlibraryinfo.cpp",
"metainfo/metainfo.cpp",
"metainfo/metainforeader.cpp",
diff --git a/src/tools/qml2puppet/CMakeLists.txt b/src/tools/qml2puppet/CMakeLists.txt
index 9d90fd16c9..d5a6b39e06 100644
--- a/src/tools/qml2puppet/CMakeLists.txt
+++ b/src/tools/qml2puppet/CMakeLists.txt
@@ -52,6 +52,7 @@ extend_qtc_executable(qml2puppet
inputeventcommand.cpp inputeventcommand.h
view3dactioncommand.cpp view3dactioncommand.h
valueschangedcommand.cpp
+ captureddatacommand.cpp captureddatacommand.h
)
extend_qtc_executable(qml2puppet
@@ -156,6 +157,7 @@ extend_qtc_executable(qml2puppet
quick3dnodeinstance.cpp quick3dnodeinstance.h
quickitemnodeinstance.cpp quickitemnodeinstance.h
servernodeinstance.cpp servernodeinstance.h
+ qt5capturenodeinstanceserver.cpp qt5capturenodeinstanceserver.h
)
extend_qtc_executable(qml2puppet
diff --git a/src/tools/qml2puppet/qml2puppet.qbs b/src/tools/qml2puppet/qml2puppet.qbs
index 485534008c..b30ce11dc8 100644
--- a/src/tools/qml2puppet/qml2puppet.qbs
+++ b/src/tools/qml2puppet/qml2puppet.qbs
@@ -107,6 +107,8 @@ QtcTool {
"commands/inputeventcommand.h",
"commands/view3dactioncommand.cpp",
"commands/view3dactioncommand.h",
+ "commands/captureddatacommand.cpp",
+ "commands/captureddatacommand.h",
"container/addimportcontainer.cpp",
"container/addimportcontainer.h",
"container/idcontainer.cpp",
@@ -207,6 +209,8 @@ QtcTool {
"instances/qt5testnodeinstanceserver.h",
"instances/servernodeinstance.cpp",
"instances/servernodeinstance.h",
+ "instances/qt5capturenodeinstanceserver.cpp",
+ "instances/qt5capturenodeinstanceserver.h",
"editor3d/generalhelper.cpp",
"editor3d/generalhelper.h",
"editor3d/mousearea3d.cpp",