forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/4.13' into master
Conflicts: src/plugins/android/androiddeployqtstep.cpp Change-Id: Id624bad384050d567efba0700046331086cb12dd
This commit is contained in:
@@ -59,6 +59,7 @@ source_include_patterns = [
|
|||||||
# directories
|
# directories
|
||||||
r"^(?!(share|tests)/.*$)(.*/)?$", # look into all directories except under share/ and tests/
|
r"^(?!(share|tests)/.*$)(.*/)?$", # look into all directories except under share/ and tests/
|
||||||
r"^share/(qtcreator/(qml/(qmlpuppet/(.*/)?)?)?)?$", # for shared headers for qt quick designer plugins
|
r"^share/(qtcreator/(qml/(qmlpuppet/(.*/)?)?)?)?$", # for shared headers for qt quick designer plugins
|
||||||
|
r"^src/plugins/help/qlitehtml/.*\.(h|pri|cpp|c|txt|md)$", # litehtml is used by extra plugins
|
||||||
# files
|
# files
|
||||||
r"^HACKING$",
|
r"^HACKING$",
|
||||||
r"^LICENSE.*$",
|
r"^LICENSE.*$",
|
||||||
|
107
share/qtcreator/qml/qmlpuppet/commands/captureddatacommand.h
Normal file
107
share/qtcreator/qml/qmlpuppet/commands/captureddatacommand.h
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 <QMetaType>
|
||||||
|
|
||||||
|
#include "imagecontainer.h"
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class CapturedDataCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct NodeData
|
||||||
|
{
|
||||||
|
friend QDataStream &operator<<(QDataStream &out, const NodeData &data)
|
||||||
|
{
|
||||||
|
out << data.nodeId;
|
||||||
|
out << data.contentRect;
|
||||||
|
out << data.sceneTransform;
|
||||||
|
out << data.text;
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend QDataStream &operator>>(QDataStream &in, NodeData &data)
|
||||||
|
{
|
||||||
|
in >> data.nodeId;
|
||||||
|
in >> data.contentRect;
|
||||||
|
in >> data.sceneTransform;
|
||||||
|
in >> data.text;
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint32 nodeId = -1;
|
||||||
|
QRectF contentRect;
|
||||||
|
QTransform sceneTransform;
|
||||||
|
QString text;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct StateData
|
||||||
|
{
|
||||||
|
friend QDataStream &operator<<(QDataStream &out, const StateData &data)
|
||||||
|
{
|
||||||
|
out << data.image;
|
||||||
|
out << data.nodeData;
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend QDataStream &operator>>(QDataStream &in, StateData &data)
|
||||||
|
{
|
||||||
|
in >> data.image;
|
||||||
|
in >> data.nodeData;
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageContainer image;
|
||||||
|
QVector<NodeData> nodeData;
|
||||||
|
};
|
||||||
|
|
||||||
|
friend QDataStream &operator<<(QDataStream &out, const CapturedDataCommand &command)
|
||||||
|
{
|
||||||
|
out << command.stateData;
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend QDataStream &operator>>(QDataStream &in, CapturedDataCommand &command)
|
||||||
|
{
|
||||||
|
in >> command.stateData;
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
QVector<StateData> stateData;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(QmlDesigner::CapturedDataCommand)
|
@@ -1,69 +1,70 @@
|
|||||||
INCLUDEPATH += $$PWD/
|
INCLUDEPATH += $$PWD
|
||||||
|
|
||||||
HEADERS += $$PWD/synchronizecommand.h
|
HEADERS += $$PWD/synchronizecommand.h \ \
|
||||||
HEADERS += $$PWD/changepreviewimagesizecommand.h
|
$$PWD/captureddatacommand.h \
|
||||||
HEADERS += $$PWD/changelanguagecommand.h
|
$$PWD/changepreviewimagesizecommand.h \
|
||||||
HEADERS += $$PWD//debugoutputcommand.h
|
$$PWD/changelanguagecommand.h \
|
||||||
HEADERS += $$PWD/endpuppetcommand.h
|
$$PWD//debugoutputcommand.h \
|
||||||
HEADERS += $$PWD/tokencommand.h
|
$$PWD/endpuppetcommand.h \
|
||||||
HEADERS += $$PWD/componentcompletedcommand.h
|
$$PWD/tokencommand.h \
|
||||||
HEADERS += $$PWD/completecomponentcommand.h
|
$$PWD/componentcompletedcommand.h \
|
||||||
HEADERS += $$PWD/statepreviewimagechangedcommand.h
|
$$PWD/completecomponentcommand.h \
|
||||||
HEADERS += $$PWD/childrenchangedcommand.h
|
$$PWD/statepreviewimagechangedcommand.h \
|
||||||
HEADERS += $$PWD/changebindingscommand.h
|
$$PWD/childrenchangedcommand.h \
|
||||||
HEADERS += $$PWD/changefileurlcommand.h
|
$$PWD/changebindingscommand.h \
|
||||||
HEADERS += $$PWD/changeidscommand.h
|
$$PWD/changefileurlcommand.h \
|
||||||
HEADERS += $$PWD/changenodesourcecommand.h
|
$$PWD/changeidscommand.h \
|
||||||
HEADERS += $$PWD/changestatecommand.h
|
$$PWD/changenodesourcecommand.h \
|
||||||
HEADERS += $$PWD/changevaluescommand.h
|
$$PWD/changestatecommand.h \
|
||||||
HEADERS += $$PWD/createscenecommand.h
|
$$PWD/changevaluescommand.h \
|
||||||
HEADERS += $$PWD/clearscenecommand.h
|
$$PWD/createscenecommand.h \
|
||||||
HEADERS += $$PWD/createinstancescommand.h
|
$$PWD/clearscenecommand.h \
|
||||||
HEADERS += $$PWD/informationchangedcommand.h
|
$$PWD/createinstancescommand.h \
|
||||||
HEADERS += $$PWD/pixmapchangedcommand.h
|
$$PWD/informationchangedcommand.h \
|
||||||
HEADERS += $$PWD/removeinstancescommand.h
|
$$PWD/pixmapchangedcommand.h \
|
||||||
HEADERS += $$PWD/removepropertiescommand.h
|
$$PWD/removeinstancescommand.h \
|
||||||
HEADERS += $$PWD/reparentinstancescommand.h
|
$$PWD/removepropertiescommand.h \
|
||||||
HEADERS += $$PWD/valueschangedcommand.h
|
$$PWD/reparentinstancescommand.h \
|
||||||
HEADERS += $$PWD/changeauxiliarycommand.h
|
$$PWD/valueschangedcommand.h \
|
||||||
HEADERS += $$PWD/removesharedmemorycommand.h
|
$$PWD/changeauxiliarycommand.h \
|
||||||
HEADERS += $$PWD/puppetalivecommand.h
|
$$PWD/removesharedmemorycommand.h \
|
||||||
HEADERS += $$PWD/changeselectioncommand.h
|
$$PWD/puppetalivecommand.h \
|
||||||
HEADERS += $$PWD/update3dviewstatecommand.h
|
$$PWD/changeselectioncommand.h \
|
||||||
HEADERS += $$PWD/puppettocreatorcommand.h
|
$$PWD/update3dviewstatecommand.h \
|
||||||
HEADERS += $$PWD/inputeventcommand.h
|
$$PWD/puppettocreatorcommand.h \
|
||||||
HEADERS += $$PWD/view3dactioncommand.h
|
$$PWD/inputeventcommand.h \
|
||||||
|
$$PWD/view3dactioncommand.h
|
||||||
|
|
||||||
SOURCES += $$PWD/synchronizecommand.cpp
|
SOURCES += $$PWD/synchronizecommand.cpp \
|
||||||
SOURCES += $$PWD/changepreviewimagesizecommand.cpp
|
$$PWD/changepreviewimagesizecommand.cpp \
|
||||||
SOURCES += $$PWD/changelanguagecommand.cpp
|
$$PWD/changelanguagecommand.cpp \
|
||||||
SOURCES += $$PWD/debugoutputcommand.cpp
|
$$PWD/debugoutputcommand.cpp \
|
||||||
SOURCES += $$PWD/endpuppetcommand.cpp
|
$$PWD/endpuppetcommand.cpp \
|
||||||
SOURCES += $$PWD/tokencommand.cpp
|
$$PWD/tokencommand.cpp \
|
||||||
SOURCES += $$PWD/componentcompletedcommand.cpp
|
$$PWD/componentcompletedcommand.cpp \
|
||||||
SOURCES += $$PWD/completecomponentcommand.cpp
|
$$PWD/completecomponentcommand.cpp \
|
||||||
SOURCES += $$PWD/statepreviewimagechangedcommand.cpp
|
$$PWD/statepreviewimagechangedcommand.cpp \
|
||||||
SOURCES += $$PWD/childrenchangedcommand.cpp
|
$$PWD/childrenchangedcommand.cpp \
|
||||||
SOURCES += $$PWD/changebindingscommand.cpp
|
$$PWD/changebindingscommand.cpp \
|
||||||
SOURCES += $$PWD/changefileurlcommand.cpp
|
$$PWD/changefileurlcommand.cpp \
|
||||||
SOURCES += $$PWD/changeidscommand.cpp
|
$$PWD/changeidscommand.cpp \
|
||||||
SOURCES += $$PWD/changenodesourcecommand.cpp
|
$$PWD/changenodesourcecommand.cpp \
|
||||||
SOURCES += $$PWD/changestatecommand.cpp
|
$$PWD/changestatecommand.cpp \
|
||||||
SOURCES += $$PWD/changevaluescommand.cpp
|
$$PWD/changevaluescommand.cpp \
|
||||||
SOURCES += $$PWD/informationchangedcommand.cpp
|
$$PWD/informationchangedcommand.cpp \
|
||||||
SOURCES += $$PWD/removeinstancescommand.cpp
|
$$PWD/removeinstancescommand.cpp \
|
||||||
SOURCES += $$PWD/removepropertiescommand.cpp
|
$$PWD/removepropertiescommand.cpp \
|
||||||
SOURCES += $$PWD/reparentinstancescommand.cpp
|
$$PWD/reparentinstancescommand.cpp \
|
||||||
SOURCES += $$PWD/valueschangedcommand.cpp
|
$$PWD/valueschangedcommand.cpp \
|
||||||
SOURCES += $$PWD/clearscenecommand.cpp
|
$$PWD/clearscenecommand.cpp \
|
||||||
SOURCES += $$PWD/createinstancescommand.cpp
|
$$PWD/createinstancescommand.cpp \
|
||||||
SOURCES += $$PWD/createscenecommand.cpp
|
$$PWD/createscenecommand.cpp \
|
||||||
SOURCES += $$PWD/pixmapchangedcommand.cpp
|
$$PWD/pixmapchangedcommand.cpp \
|
||||||
SOURCES += $$PWD/changeauxiliarycommand.cpp
|
$$PWD/changeauxiliarycommand.cpp \
|
||||||
SOURCES += $$PWD/removesharedmemorycommand.cpp
|
$$PWD/removesharedmemorycommand.cpp \
|
||||||
SOURCES += $$PWD/puppetalivecommand.cpp
|
$$PWD/puppetalivecommand.cpp \
|
||||||
SOURCES += $$PWD/changeselectioncommand.cpp
|
$$PWD/changeselectioncommand.cpp \
|
||||||
SOURCES += $$PWD/update3dviewstatecommand.cpp
|
$$PWD/update3dviewstatecommand.cpp \
|
||||||
SOURCES += $$PWD/puppettocreatorcommand.cpp
|
$$PWD/puppettocreatorcommand.cpp \
|
||||||
SOURCES += $$PWD/inputeventcommand.cpp
|
$$PWD/inputeventcommand.cpp \
|
||||||
SOURCES += $$PWD/view3dactioncommand.cpp
|
$$PWD/view3dactioncommand.cpp
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
#include "nodeinstanceserverinterface.h"
|
#include "nodeinstanceserverinterface.h"
|
||||||
|
|
||||||
|
#include "captureddatacommand.h"
|
||||||
#include "changeauxiliarycommand.h"
|
#include "changeauxiliarycommand.h"
|
||||||
#include "changebindingscommand.h"
|
#include "changebindingscommand.h"
|
||||||
#include "changefileurlcommand.h"
|
#include "changefileurlcommand.h"
|
||||||
@@ -84,12 +85,11 @@ constexpr void (QLocalSocket::*LocalSocketErrorFunction)(QLocalSocket::LocalSock
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
NodeInstanceClientProxy::NodeInstanceClientProxy(QObject *parent)
|
NodeInstanceClientProxy::NodeInstanceClientProxy(QObject *parent)
|
||||||
: QObject(parent),
|
: QObject(parent)
|
||||||
m_inputIoDevice(nullptr),
|
, m_inputIoDevice(nullptr)
|
||||||
m_outputIoDevice(nullptr),
|
, m_outputIoDevice(nullptr)
|
||||||
m_nodeInstanceServer(nullptr),
|
, m_writeCommandCounter(0)
|
||||||
m_writeCommandCounter(0),
|
, m_synchronizeId(-1)
|
||||||
m_synchronizeId(-1)
|
|
||||||
{
|
{
|
||||||
connect(&m_puppetAliveTimer, &QTimer::timeout, this, &NodeInstanceClientProxy::sendPuppetAliveCommand);
|
connect(&m_puppetAliveTimer, &QTimer::timeout, this, &NodeInstanceClientProxy::sendPuppetAliveCommand);
|
||||||
m_puppetAliveTimer.setInterval(2000);
|
m_puppetAliveTimer.setInterval(2000);
|
||||||
@@ -174,7 +174,8 @@ bool compareCommands(const QVariant &command, const QVariant &controlCommand)
|
|||||||
else if (command.userType() == debugOutputCommandType)
|
else if (command.userType() == debugOutputCommandType)
|
||||||
return command.value<DebugOutputCommand>() == controlCommand.value<DebugOutputCommand>();
|
return command.value<DebugOutputCommand>() == controlCommand.value<DebugOutputCommand>();
|
||||||
else if (command.userType() == changeSelectionCommandType)
|
else if (command.userType() == changeSelectionCommandType)
|
||||||
return command.value<ChangeSelectionCommand>() == controlCommand.value<ChangeSelectionCommand>();
|
return command.value<ChangeSelectionCommand>()
|
||||||
|
== controlCommand.value<ChangeSelectionCommand>();
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -267,6 +268,11 @@ void NodeInstanceClientProxy::handlePuppetToCreatorCommand(const PuppetToCreator
|
|||||||
writeCommand(QVariant::fromValue(command));
|
writeCommand(QVariant::fromValue(command));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NodeInstanceClientProxy::capturedData(const CapturedDataCommand &command)
|
||||||
|
{
|
||||||
|
writeCommand(QVariant::fromValue(command));
|
||||||
|
}
|
||||||
|
|
||||||
void NodeInstanceClientProxy::flush()
|
void NodeInstanceClientProxy::flush()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -365,12 +371,13 @@ void NodeInstanceClientProxy::sendPuppetAliveCommand()
|
|||||||
|
|
||||||
NodeInstanceServerInterface *NodeInstanceClientProxy::nodeInstanceServer() const
|
NodeInstanceServerInterface *NodeInstanceClientProxy::nodeInstanceServer() const
|
||||||
{
|
{
|
||||||
return m_nodeInstanceServer;
|
return m_nodeInstanceServer.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeInstanceClientProxy::setNodeInstanceServer(NodeInstanceServerInterface *nodeInstanceServer)
|
void NodeInstanceClientProxy::setNodeInstanceServer(
|
||||||
|
std::unique_ptr<NodeInstanceServerInterface> nodeInstanceServer)
|
||||||
{
|
{
|
||||||
m_nodeInstanceServer = nodeInstanceServer;
|
m_nodeInstanceServer = std::move(nodeInstanceServer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeInstanceClientProxy::createInstances(const CreateInstancesCommand &command)
|
void NodeInstanceClientProxy::createInstances(const CreateInstancesCommand &command)
|
||||||
|
@@ -69,7 +69,7 @@ class NodeInstanceClientProxy : public QObject, public NodeInstanceClientInterfa
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NodeInstanceClientProxy(QObject *parent = nullptr);
|
NodeInstanceClientProxy(QObject *parent);
|
||||||
|
|
||||||
void informationChanged(const InformationChangedCommand &command) override;
|
void informationChanged(const InformationChangedCommand &command) override;
|
||||||
void valuesChanged(const ValuesChangedCommand &command) override;
|
void valuesChanged(const ValuesChangedCommand &command) override;
|
||||||
@@ -83,6 +83,7 @@ public:
|
|||||||
void puppetAlive(const PuppetAliveCommand &command);
|
void puppetAlive(const PuppetAliveCommand &command);
|
||||||
void selectionChanged(const ChangeSelectionCommand &command) override;
|
void selectionChanged(const ChangeSelectionCommand &command) override;
|
||||||
void handlePuppetToCreatorCommand(const PuppetToCreatorCommand &command) override;
|
void handlePuppetToCreatorCommand(const PuppetToCreatorCommand &command) override;
|
||||||
|
void capturedData(const CapturedDataCommand &capturedData) override;
|
||||||
|
|
||||||
void flush() override;
|
void flush() override;
|
||||||
void synchronizeWithClientProcess() override;
|
void synchronizeWithClientProcess() override;
|
||||||
@@ -94,7 +95,7 @@ protected:
|
|||||||
void writeCommand(const QVariant &command);
|
void writeCommand(const QVariant &command);
|
||||||
void dispatchCommand(const QVariant &command);
|
void dispatchCommand(const QVariant &command);
|
||||||
NodeInstanceServerInterface *nodeInstanceServer() const;
|
NodeInstanceServerInterface *nodeInstanceServer() const;
|
||||||
void setNodeInstanceServer(NodeInstanceServerInterface *nodeInstanceServer);
|
void setNodeInstanceServer(std::unique_ptr<NodeInstanceServerInterface> nodeInstanceServer);
|
||||||
|
|
||||||
void createInstances(const CreateInstancesCommand &command);
|
void createInstances(const CreateInstancesCommand &command);
|
||||||
void changeFileUrl(const ChangeFileUrlCommand &command);
|
void changeFileUrl(const ChangeFileUrlCommand &command);
|
||||||
@@ -130,7 +131,7 @@ private:
|
|||||||
QTimer m_puppetAliveTimer;
|
QTimer m_puppetAliveTimer;
|
||||||
QIODevice *m_inputIoDevice;
|
QIODevice *m_inputIoDevice;
|
||||||
QIODevice *m_outputIoDevice;
|
QIODevice *m_outputIoDevice;
|
||||||
NodeInstanceServerInterface *m_nodeInstanceServer;
|
std::unique_ptr<NodeInstanceServerInterface> m_nodeInstanceServer;
|
||||||
quint32 m_writeCommandCounter;
|
quint32 m_writeCommandCounter;
|
||||||
int m_synchronizeId;
|
int m_synchronizeId;
|
||||||
};
|
};
|
||||||
|
@@ -42,6 +42,7 @@ class DebugOutputCommand;
|
|||||||
class PuppetAliveCommand;
|
class PuppetAliveCommand;
|
||||||
class ChangeSelectionCommand;
|
class ChangeSelectionCommand;
|
||||||
class PuppetToCreatorCommand;
|
class PuppetToCreatorCommand;
|
||||||
|
class CapturedDataCommand;
|
||||||
|
|
||||||
class NodeInstanceClientInterface
|
class NodeInstanceClientInterface
|
||||||
{
|
{
|
||||||
@@ -57,6 +58,7 @@ public:
|
|||||||
virtual void debugOutput(const DebugOutputCommand &command) = 0;
|
virtual void debugOutput(const DebugOutputCommand &command) = 0;
|
||||||
virtual void selectionChanged(const ChangeSelectionCommand &command) = 0;
|
virtual void selectionChanged(const ChangeSelectionCommand &command) = 0;
|
||||||
virtual void handlePuppetToCreatorCommand(const PuppetToCreatorCommand &command) = 0;
|
virtual void handlePuppetToCreatorCommand(const PuppetToCreatorCommand &command) = 0;
|
||||||
|
virtual void capturedData(const CapturedDataCommand &command) = 0;
|
||||||
|
|
||||||
virtual void flush() {}
|
virtual void flush() {}
|
||||||
virtual void synchronizeWithClientProcess() {}
|
virtual void synchronizeWithClientProcess() {}
|
||||||
|
@@ -27,16 +27,17 @@
|
|||||||
#include <qmetatype.h>
|
#include <qmetatype.h>
|
||||||
|
|
||||||
#include "addimportcontainer.h"
|
#include "addimportcontainer.h"
|
||||||
|
#include "captureddatacommand.h"
|
||||||
#include "changeauxiliarycommand.h"
|
#include "changeauxiliarycommand.h"
|
||||||
#include "changebindingscommand.h"
|
#include "changebindingscommand.h"
|
||||||
#include "changefileurlcommand.h"
|
#include "changefileurlcommand.h"
|
||||||
#include "changeidscommand.h"
|
#include "changeidscommand.h"
|
||||||
#include "changelanguagecommand.h"
|
#include "changelanguagecommand.h"
|
||||||
#include "changenodesourcecommand.h"
|
#include "changenodesourcecommand.h"
|
||||||
|
#include "changepreviewimagesizecommand.h"
|
||||||
#include "changeselectioncommand.h"
|
#include "changeselectioncommand.h"
|
||||||
#include "changestatecommand.h"
|
#include "changestatecommand.h"
|
||||||
#include "changevaluescommand.h"
|
#include "changevaluescommand.h"
|
||||||
#include "changepreviewimagesizecommand.h"
|
|
||||||
#include "childrenchangedcommand.h"
|
#include "childrenchangedcommand.h"
|
||||||
#include "clearscenecommand.h"
|
#include "clearscenecommand.h"
|
||||||
#include "completecomponentcommand.h"
|
#include "completecomponentcommand.h"
|
||||||
@@ -219,6 +220,9 @@ void NodeInstanceServerInterface::registerCommands()
|
|||||||
|
|
||||||
qRegisterMetaType<ChangePreviewImageSizeCommand>("ChangePreviewImageSizeCommand");
|
qRegisterMetaType<ChangePreviewImageSizeCommand>("ChangePreviewImageSizeCommand");
|
||||||
qRegisterMetaTypeStreamOperators<ChangePreviewImageSizeCommand>("ChangePreviewImageSizeCommand");
|
qRegisterMetaTypeStreamOperators<ChangePreviewImageSizeCommand>("ChangePreviewImageSizeCommand");
|
||||||
|
|
||||||
|
qRegisterMetaType<CapturedDataCommand>("CapturedDataCommand");
|
||||||
|
qRegisterMetaTypeStreamOperators<CapturedDataCommand>("CapturedDataCommand");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -60,11 +60,6 @@ class NodeInstanceServerInterface : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
enum RunModus {
|
|
||||||
NormalModus,
|
|
||||||
TestModus // No preview images and synchronized
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit NodeInstanceServerInterface(QObject *parent = nullptr);
|
explicit NodeInstanceServerInterface(QObject *parent = nullptr);
|
||||||
|
|
||||||
virtual void createInstances(const CreateInstancesCommand &command) = 0;
|
virtual void createInstances(const CreateInstancesCommand &command) = 0;
|
||||||
|
@@ -5,54 +5,56 @@ versionAtLeast(QT_VERSION, 5.15.0):qtHaveModule(quick3d) {
|
|||||||
DEFINES *= QUICK3D_MODULE
|
DEFINES *= QUICK3D_MODULE
|
||||||
}
|
}
|
||||||
|
|
||||||
HEADERS += $$PWD/qt5nodeinstanceserver.h
|
HEADERS += $$PWD/qt5nodeinstanceserver.h \
|
||||||
HEADERS += $$PWD/qt5testnodeinstanceserver.h
|
$$PWD/qt5capturenodeinstanceserver.h \
|
||||||
HEADERS += $$PWD/qt5informationnodeinstanceserver.h
|
$$PWD/qt5testnodeinstanceserver.h \
|
||||||
HEADERS += $$PWD/qt5rendernodeinstanceserver.h
|
$$PWD/qt5informationnodeinstanceserver.h \
|
||||||
HEADERS += $$PWD/qt5previewnodeinstanceserver.h
|
$$PWD/qt5rendernodeinstanceserver.h \
|
||||||
HEADERS += $$PWD/qt5nodeinstanceclientproxy.h
|
$$PWD/qt5previewnodeinstanceserver.h \
|
||||||
HEADERS += $$PWD/quickitemnodeinstance.h
|
$$PWD/qt5nodeinstanceclientproxy.h \
|
||||||
HEADERS += $$PWD/behaviornodeinstance.h
|
$$PWD/quickitemnodeinstance.h \
|
||||||
HEADERS += $$PWD/dummycontextobject.h
|
$$PWD/behaviornodeinstance.h \
|
||||||
HEADERS += $$PWD/childrenchangeeventfilter.h
|
$$PWD/dummycontextobject.h \
|
||||||
HEADERS += $$PWD/componentnodeinstance.h
|
$$PWD/childrenchangeeventfilter.h \
|
||||||
HEADERS += $$PWD/dummynodeinstance.h
|
$$PWD/componentnodeinstance.h \
|
||||||
HEADERS += $$PWD/nodeinstanceserver.h
|
$$PWD/dummynodeinstance.h \
|
||||||
HEADERS += $$PWD/nodeinstancesignalspy.h
|
$$PWD/nodeinstanceserver.h \
|
||||||
HEADERS += $$PWD/objectnodeinstance.h
|
$$PWD/nodeinstancesignalspy.h \
|
||||||
HEADERS += $$PWD/qmlpropertychangesnodeinstance.h
|
$$PWD/objectnodeinstance.h \
|
||||||
HEADERS += $$PWD/qmlstatenodeinstance.h
|
$$PWD/qmlpropertychangesnodeinstance.h \
|
||||||
HEADERS += $$PWD/qmltransitionnodeinstance.h
|
$$PWD/qmlstatenodeinstance.h \
|
||||||
HEADERS += $$PWD/servernodeinstance.h
|
$$PWD/qmltransitionnodeinstance.h \
|
||||||
HEADERS += $$PWD/anchorchangesnodeinstance.h
|
$$PWD/servernodeinstance.h \
|
||||||
HEADERS += $$PWD/positionernodeinstance.h
|
$$PWD/anchorchangesnodeinstance.h \
|
||||||
HEADERS += $$PWD/layoutnodeinstance.h
|
$$PWD/positionernodeinstance.h \
|
||||||
HEADERS += $$PWD/qt3dpresentationnodeinstance.h
|
$$PWD/layoutnodeinstance.h \
|
||||||
HEADERS += $$PWD/quick3dnodeinstance.h
|
$$PWD/qt3dpresentationnodeinstance.h \
|
||||||
HEADERS += $$PWD/quick3dtexturenodeinstance.h
|
$$PWD/quick3dnodeinstance.h \
|
||||||
|
$$PWD/quick3dtexturenodeinstance.h
|
||||||
|
|
||||||
SOURCES += $$PWD/qt5nodeinstanceserver.cpp
|
SOURCES += $$PWD/qt5nodeinstanceserver.cpp \
|
||||||
SOURCES += $$PWD/qt5testnodeinstanceserver.cpp
|
$$PWD/qt5capturenodeinstanceserver.cpp \
|
||||||
SOURCES += $$PWD/qt5informationnodeinstanceserver.cpp
|
$$PWD/qt5testnodeinstanceserver.cpp \
|
||||||
SOURCES += $$PWD/qt5rendernodeinstanceserver.cpp
|
$$PWD/qt5informationnodeinstanceserver.cpp \
|
||||||
SOURCES += $$PWD/qt5previewnodeinstanceserver.cpp
|
$$PWD/qt5rendernodeinstanceserver.cpp \
|
||||||
SOURCES += $$PWD/qt5nodeinstanceclientproxy.cpp
|
$$PWD/qt5previewnodeinstanceserver.cpp \
|
||||||
SOURCES += $$PWD/quickitemnodeinstance.cpp
|
$$PWD/qt5nodeinstanceclientproxy.cpp \
|
||||||
SOURCES += $$PWD/behaviornodeinstance.cpp
|
$$PWD/quickitemnodeinstance.cpp \
|
||||||
SOURCES += $$PWD/dummycontextobject.cpp
|
$$PWD/behaviornodeinstance.cpp \
|
||||||
SOURCES += $$PWD/childrenchangeeventfilter.cpp
|
$$PWD/dummycontextobject.cpp \
|
||||||
SOURCES += $$PWD/componentnodeinstance.cpp
|
$$PWD/childrenchangeeventfilter.cpp \
|
||||||
SOURCES += $$PWD/dummynodeinstance.cpp
|
$$PWD/componentnodeinstance.cpp \
|
||||||
SOURCES += $$PWD/nodeinstanceserver.cpp
|
$$PWD/dummynodeinstance.cpp \
|
||||||
SOURCES += $$PWD/nodeinstancesignalspy.cpp
|
$$PWD/nodeinstanceserver.cpp \
|
||||||
SOURCES += $$PWD/objectnodeinstance.cpp
|
$$PWD/nodeinstancesignalspy.cpp \
|
||||||
SOURCES += $$PWD/qmlpropertychangesnodeinstance.cpp
|
$$PWD/objectnodeinstance.cpp \
|
||||||
SOURCES += $$PWD/qmlstatenodeinstance.cpp
|
$$PWD/qmlpropertychangesnodeinstance.cpp \
|
||||||
SOURCES += $$PWD/qmltransitionnodeinstance.cpp
|
$$PWD/qmlstatenodeinstance.cpp \
|
||||||
SOURCES += $$PWD/servernodeinstance.cpp
|
$$PWD/qmltransitionnodeinstance.cpp \
|
||||||
SOURCES += $$PWD/anchorchangesnodeinstance.cpp
|
$$PWD/servernodeinstance.cpp \
|
||||||
SOURCES += $$PWD/positionernodeinstance.cpp
|
$$PWD/anchorchangesnodeinstance.cpp \
|
||||||
SOURCES += $$PWD/layoutnodeinstance.cpp
|
$$PWD/positionernodeinstance.cpp \
|
||||||
SOURCES += $$PWD/qt3dpresentationnodeinstance.cpp
|
$$PWD/layoutnodeinstance.cpp \
|
||||||
SOURCES += $$PWD/quick3dnodeinstance.cpp
|
$$PWD/qt3dpresentationnodeinstance.cpp \
|
||||||
SOURCES += $$PWD/quick3dtexturenodeinstance.cpp
|
$$PWD/quick3dnodeinstance.cpp \
|
||||||
|
$$PWD/quick3dtexturenodeinstance.cpp
|
||||||
|
@@ -178,6 +178,8 @@ NodeInstanceServer::NodeInstanceServer(NodeInstanceClientInterface *nodeInstance
|
|||||||
m_childrenChangeEventFilter(new Internal::ChildrenChangeEventFilter(this)),
|
m_childrenChangeEventFilter(new Internal::ChildrenChangeEventFilter(this)),
|
||||||
m_nodeInstanceClient(nodeInstanceClient)
|
m_nodeInstanceClient(nodeInstanceClient)
|
||||||
{
|
{
|
||||||
|
m_idInstances.reserve(1000);
|
||||||
|
|
||||||
qmlRegisterType<DummyContextObject>("QmlDesigner", 1, 0, "DummyContextObject");
|
qmlRegisterType<DummyContextObject>("QmlDesigner", 1, 0, "DummyContextObject");
|
||||||
|
|
||||||
connect(m_childrenChangeEventFilter.data(), &Internal::ChildrenChangeEventFilter::childrenChanged, this, &NodeInstanceServer::emitParentChanged);
|
connect(m_childrenChangeEventFilter.data(), &Internal::ChildrenChangeEventFilter::childrenChanged, this, &NodeInstanceServer::emitParentChanged);
|
||||||
@@ -225,8 +227,8 @@ ServerNodeInstance NodeInstanceServer::instanceForId(qint32 id) const
|
|||||||
if (id < 0)
|
if (id < 0)
|
||||||
return ServerNodeInstance();
|
return ServerNodeInstance();
|
||||||
|
|
||||||
Q_ASSERT(m_idInstanceHash.contains(id));
|
Q_ASSERT(m_idInstances.size() > id);
|
||||||
return m_idInstanceHash.value(id);
|
return m_idInstances[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NodeInstanceServer::hasInstanceForId(qint32 id) const
|
bool NodeInstanceServer::hasInstanceForId(qint32 id) const
|
||||||
@@ -234,7 +236,7 @@ bool NodeInstanceServer::hasInstanceForId(qint32 id) const
|
|||||||
if (id < 0)
|
if (id < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return m_idInstanceHash.contains(id) && m_idInstanceHash.value(id).isValid();
|
return m_idInstances.size() > id && m_idInstances[id].isValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerNodeInstance NodeInstanceServer::instanceForObject(QObject *object) const
|
ServerNodeInstance NodeInstanceServer::instanceForObject(QObject *object) const
|
||||||
@@ -789,7 +791,7 @@ void NodeInstanceServer::removeAllInstanceRelationships()
|
|||||||
instance.makeInvalid();
|
instance.makeInvalid();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_idInstanceHash.clear();
|
m_idInstances.clear();
|
||||||
m_objectInstanceHash.clear();
|
m_objectInstanceHash.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1242,10 +1244,11 @@ void NodeInstanceServer::notifyPropertyChange(qint32 instanceid, const PropertyN
|
|||||||
void NodeInstanceServer::insertInstanceRelationship(const ServerNodeInstance &instance)
|
void NodeInstanceServer::insertInstanceRelationship(const ServerNodeInstance &instance)
|
||||||
{
|
{
|
||||||
Q_ASSERT(instance.isValid());
|
Q_ASSERT(instance.isValid());
|
||||||
Q_ASSERT(!m_idInstanceHash.contains(instance.instanceId()));
|
|
||||||
Q_ASSERT(!m_objectInstanceHash.contains(instance.internalObject()));
|
Q_ASSERT(!m_objectInstanceHash.contains(instance.internalObject()));
|
||||||
m_objectInstanceHash.insert(instance.internalObject(), instance);
|
m_objectInstanceHash.insert(instance.internalObject(), instance);
|
||||||
m_idInstanceHash.insert(instance.instanceId(), instance);
|
if (instance.instanceId() >= m_idInstances.size())
|
||||||
|
m_idInstances.resize(instance.instanceId() + 1);
|
||||||
|
m_idInstances[instance.instanceId()] = instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeInstanceServer::removeInstanceRelationsip(qint32 instanceId)
|
void NodeInstanceServer::removeInstanceRelationsip(qint32 instanceId)
|
||||||
@@ -1254,7 +1257,7 @@ void NodeInstanceServer::removeInstanceRelationsip(qint32 instanceId)
|
|||||||
ServerNodeInstance instance = instanceForId(instanceId);
|
ServerNodeInstance instance = instanceForId(instanceId);
|
||||||
if (instance.isValid())
|
if (instance.isValid())
|
||||||
instance.setId(QString());
|
instance.setId(QString());
|
||||||
m_idInstanceHash.remove(instanceId);
|
m_idInstances[instanceId] = ServerNodeInstance{};
|
||||||
m_objectInstanceHash.remove(instance.internalObject());
|
m_objectInstanceHash.remove(instance.internalObject());
|
||||||
instance.makeInvalid();
|
instance.makeInvalid();
|
||||||
}
|
}
|
||||||
@@ -1382,8 +1385,8 @@ void NodeInstanceServer::removeInstanceRelationsipForDeletedObject(QObject *obje
|
|||||||
ServerNodeInstance instance = instanceForObject(object);
|
ServerNodeInstance instance = instanceForObject(object);
|
||||||
m_objectInstanceHash.remove(object);
|
m_objectInstanceHash.remove(object);
|
||||||
|
|
||||||
if (m_idInstanceHash.contains(instance.instanceId()))
|
if (instance.instanceId() >= 0 && m_idInstances.size() > instance.instanceId())
|
||||||
m_idInstanceHash.remove(instance.instanceId());
|
m_idInstances[instance.instanceId()] = ServerNodeInstance{};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -160,6 +160,8 @@ public:
|
|||||||
ServerNodeInstance instanceForObject(QObject *object) const;
|
ServerNodeInstance instanceForObject(QObject *object) const;
|
||||||
bool hasInstanceForObject(QObject *object) const;
|
bool hasInstanceForObject(QObject *object) const;
|
||||||
|
|
||||||
|
const QVector<ServerNodeInstance> &nodeInstances() const { return m_idInstances; }
|
||||||
|
|
||||||
virtual QQmlEngine *engine() const = 0;
|
virtual QQmlEngine *engine() const = 0;
|
||||||
QQmlContext *context() const;
|
QQmlContext *context() const;
|
||||||
|
|
||||||
@@ -277,7 +279,7 @@ private:
|
|||||||
void setupOnlyWorkingImports(const QStringList &workingImportStatementList);
|
void setupOnlyWorkingImports(const QStringList &workingImportStatementList);
|
||||||
ServerNodeInstance m_rootNodeInstance;
|
ServerNodeInstance m_rootNodeInstance;
|
||||||
ServerNodeInstance m_activeStateInstance;
|
ServerNodeInstance m_activeStateInstance;
|
||||||
QHash<qint32, ServerNodeInstance> m_idInstanceHash;
|
QVector<ServerNodeInstance> m_idInstances;
|
||||||
QHash<QObject*, ServerNodeInstance> m_objectInstanceHash;
|
QHash<QObject*, ServerNodeInstance> m_objectInstanceHash;
|
||||||
QMultiHash<QString, ObjectPropertyPair> m_fileSystemWatcherHash;
|
QMultiHash<QString, ObjectPropertyPair> m_fileSystemWatcherHash;
|
||||||
QList<QPair<QString, QPointer<QObject> > > m_dummyObjectList;
|
QList<QPair<QString, QPointer<QObject> > > m_dummyObjectList;
|
||||||
|
@@ -0,0 +1,105 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "qt5capturenodeinstanceserver.h"
|
||||||
|
#include "servernodeinstance.h"
|
||||||
|
|
||||||
|
#include <captureddatacommand.h>
|
||||||
|
#include <createscenecommand.h>
|
||||||
|
#include <nodeinstanceclientinterface.h>
|
||||||
|
|
||||||
|
#include <QImage>
|
||||||
|
#include <QQuickView>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
QImage renderPreviewImage(ServerNodeInstance rootNodeInstance)
|
||||||
|
{
|
||||||
|
rootNodeInstance.updateDirtyNodeRecursive();
|
||||||
|
|
||||||
|
QSize previewImageSize = rootNodeInstance.boundingRect().size().toSize();
|
||||||
|
|
||||||
|
QImage previewImage = rootNodeInstance.renderPreviewImage(previewImageSize);
|
||||||
|
|
||||||
|
return previewImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
CapturedDataCommand::StateData collectStateData(ServerNodeInstance rootNodeInstance,
|
||||||
|
const QVector<ServerNodeInstance> &nodeInstances,
|
||||||
|
qint32 stateInstanceId)
|
||||||
|
{
|
||||||
|
CapturedDataCommand::StateData stateData;
|
||||||
|
stateData.image = ImageContainer(stateInstanceId,
|
||||||
|
QmlDesigner::renderPreviewImage(rootNodeInstance),
|
||||||
|
stateInstanceId);
|
||||||
|
|
||||||
|
for (const ServerNodeInstance &instance : nodeInstances) {
|
||||||
|
auto textProperty = instance.property("text");
|
||||||
|
if (!textProperty.isNull() && instance.holdsGraphical()) {
|
||||||
|
CapturedDataCommand::NodeData nodeData;
|
||||||
|
nodeData.nodeId = instance.instanceId();
|
||||||
|
nodeData.contentRect = instance.contentItemBoundingRect();
|
||||||
|
nodeData.sceneTransform = instance.sceneTransform();
|
||||||
|
nodeData.text = textProperty.toString();
|
||||||
|
stateData.nodeData.push_back(std::move(nodeData));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return stateData;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void Qt5CaptureNodeInstanceServer::collectItemChangesAndSendChangeCommands()
|
||||||
|
{
|
||||||
|
static bool inFunction = false;
|
||||||
|
|
||||||
|
if (!rootNodeInstance().holdsGraphical())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!inFunction) {
|
||||||
|
inFunction = true;
|
||||||
|
|
||||||
|
DesignerSupport::polishItems(quickView());
|
||||||
|
|
||||||
|
QVector<CapturedDataCommand::StateData> stateDatas;
|
||||||
|
stateDatas.push_back(collectStateData(rootNodeInstance(), nodeInstances(), 0));
|
||||||
|
|
||||||
|
for (ServerNodeInstance stateInstance : rootNodeInstance().stateInstances()) {
|
||||||
|
stateInstance.activateState();
|
||||||
|
stateDatas.push_back(
|
||||||
|
collectStateData(rootNodeInstance(), nodeInstances(), stateInstance.instanceId()));
|
||||||
|
stateInstance.deactivateState();
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeInstanceClient()->capturedData(CapturedDataCommand{stateDatas});
|
||||||
|
|
||||||
|
slowDownRenderTimer();
|
||||||
|
inFunction = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -0,0 +1,45 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 <qt5previewnodeinstanceserver.h>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class Qt5CaptureNodeInstanceServer : public Qt5PreviewNodeInstanceServer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Qt5CaptureNodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient)
|
||||||
|
: Qt5PreviewNodeInstanceServer(nodeInstanceClient)
|
||||||
|
{}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void collectItemChangesAndSendChangeCommands() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
#include "qt5capturenodeinstanceserver.h"
|
||||||
#include "qt5informationnodeinstanceserver.h"
|
#include "qt5informationnodeinstanceserver.h"
|
||||||
#include "qt5previewnodeinstanceserver.h"
|
#include "qt5previewnodeinstanceserver.h"
|
||||||
#include "qt5rendernodeinstanceserver.h"
|
#include "qt5rendernodeinstanceserver.h"
|
||||||
@@ -37,7 +38,7 @@
|
|||||||
#if defined(Q_OS_UNIX)
|
#if defined(Q_OS_UNIX)
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#elif defined(Q_OS_WIN)
|
#elif defined(Q_OS_WIN)
|
||||||
#include <windows.h>
|
#include <Windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
@@ -57,18 +58,21 @@ Qt5NodeInstanceClientProxy::Qt5NodeInstanceClientProxy(QObject *parent) :
|
|||||||
DesignerSupport::activateDesignerWindowManager();
|
DesignerSupport::activateDesignerWindowManager();
|
||||||
if (QCoreApplication::arguments().at(1) == QLatin1String("--readcapturedstream")) {
|
if (QCoreApplication::arguments().at(1) == QLatin1String("--readcapturedstream")) {
|
||||||
qputenv("DESIGNER_DONT_USE_SHARED_MEMORY", "1");
|
qputenv("DESIGNER_DONT_USE_SHARED_MEMORY", "1");
|
||||||
setNodeInstanceServer(new Qt5TestNodeInstanceServer(this));
|
setNodeInstanceServer(std::make_unique<Qt5TestNodeInstanceServer>(this));
|
||||||
initializeCapturedStream(QCoreApplication::arguments().at(2));
|
initializeCapturedStream(QCoreApplication::arguments().at(2));
|
||||||
readDataStream();
|
readDataStream();
|
||||||
QCoreApplication::exit();
|
QCoreApplication::exit();
|
||||||
} else if (QCoreApplication::arguments().at(2) == QLatin1String("previewmode")) {
|
} else if (QCoreApplication::arguments().at(2) == QLatin1String("previewmode")) {
|
||||||
setNodeInstanceServer(new Qt5PreviewNodeInstanceServer(this));
|
setNodeInstanceServer(std::make_unique<Qt5PreviewNodeInstanceServer>(this));
|
||||||
initializeSocket();
|
initializeSocket();
|
||||||
} else if (QCoreApplication::arguments().at(2) == QLatin1String("editormode")) {
|
} else if (QCoreApplication::arguments().at(2) == QLatin1String("editormode")) {
|
||||||
setNodeInstanceServer(new Qt5InformationNodeInstanceServer(this));
|
setNodeInstanceServer(std::make_unique<Qt5InformationNodeInstanceServer>(this));
|
||||||
initializeSocket();
|
initializeSocket();
|
||||||
} else if (QCoreApplication::arguments().at(2) == QLatin1String("rendermode")) {
|
} else if (QCoreApplication::arguments().at(2) == QLatin1String("rendermode")) {
|
||||||
setNodeInstanceServer(new Qt5RenderNodeInstanceServer(this));
|
setNodeInstanceServer(std::make_unique<Qt5RenderNodeInstanceServer>(this));
|
||||||
|
initializeSocket();
|
||||||
|
} else if (QCoreApplication::arguments().at(2) == QLatin1String("capturemode")) {
|
||||||
|
setNodeInstanceServer(std::make_unique<Qt5CaptureNodeInstanceServer>(this));
|
||||||
initializeSocket();
|
initializeSocket();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -84,7 +84,8 @@ void Qt5PreviewNodeInstanceServer::collectItemChangesAndSendChangeCommands()
|
|||||||
instance.deactivateState();
|
instance.deactivateState();
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeInstanceClient()->statePreviewImagesChanged(StatePreviewImageChangedCommand(imageContainerVector));
|
nodeInstanceClient()->statePreviewImagesChanged(
|
||||||
|
StatePreviewImageChangedCommand(imageContainerVector));
|
||||||
|
|
||||||
slowDownRenderTimer();
|
slowDownRenderTimer();
|
||||||
handleExtraRender();
|
handleExtraRender();
|
||||||
@@ -105,7 +106,7 @@ QImage Qt5PreviewNodeInstanceServer::renderPreviewImage()
|
|||||||
|
|
||||||
QSize previewImageSize = boundingRect.size().toSize();
|
QSize previewImageSize = boundingRect.size().toSize();
|
||||||
|
|
||||||
if (!m_previewSize.isNull())
|
if (m_previewSize.isValid() && !m_previewSize.isNull())
|
||||||
previewImageSize.scale(m_previewSize, Qt::KeepAspectRatio);
|
previewImageSize.scale(m_previewSize, Qt::KeepAspectRatio);
|
||||||
|
|
||||||
QImage previewImage = rootNodeInstance().renderPreviewImage(previewImageSize);
|
QImage previewImage = rootNodeInstance().renderPreviewImage(previewImageSize);
|
||||||
@@ -124,9 +125,6 @@ void Qt5PreviewNodeInstanceServer::changePreviewImageSize(
|
|||||||
{
|
{
|
||||||
m_previewSize = command.size;
|
m_previewSize = command.size;
|
||||||
|
|
||||||
if (!command.size.isValid())
|
|
||||||
m_previewSize = {160, 160};
|
|
||||||
|
|
||||||
collectItemChangesAndSendChangeCommands();
|
collectItemChangesAndSendChangeCommands();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -72,6 +72,7 @@ class ServerNodeInstance
|
|||||||
friend class Qt5InformationNodeInstanceServer;
|
friend class Qt5InformationNodeInstanceServer;
|
||||||
friend class Qt5NodeInstanceServer;
|
friend class Qt5NodeInstanceServer;
|
||||||
friend class Qt5PreviewNodeInstanceServer;
|
friend class Qt5PreviewNodeInstanceServer;
|
||||||
|
friend class Qt5CaptureNodeInstanceServer;
|
||||||
friend class Qt5TestNodeInstanceServer;
|
friend class Qt5TestNodeInstanceServer;
|
||||||
friend class QHash<qint32, ServerNodeInstance>;
|
friend class QHash<qint32, ServerNodeInstance>;
|
||||||
friend uint qHash(const ServerNodeInstance &instance);
|
friend uint qHash(const ServerNodeInstance &instance);
|
||||||
@@ -171,6 +172,8 @@ public:
|
|||||||
static bool isSubclassOf(QObject *object, const QByteArray &superTypeName);
|
static bool isSubclassOf(QObject *object, const QByteArray &superTypeName);
|
||||||
|
|
||||||
void setModifiedFlag(bool b);
|
void setModifiedFlag(bool b);
|
||||||
|
void updateDirtyNodeRecursive();
|
||||||
|
bool holdsGraphical() const;
|
||||||
|
|
||||||
private: // functions
|
private: // functions
|
||||||
ServerNodeInstance(const QSharedPointer<Internal::ObjectNodeInstance> &abstractInstance);
|
ServerNodeInstance(const QSharedPointer<Internal::ObjectNodeInstance> &abstractInstance);
|
||||||
@@ -197,7 +200,6 @@ private: // functions
|
|||||||
void setDeleteHeldInstance(bool deleteInstance);
|
void setDeleteHeldInstance(bool deleteInstance);
|
||||||
void reparent(const ServerNodeInstance &oldParentInstance, const PropertyName &oldParentProperty, const ServerNodeInstance &newParentInstance, const PropertyName &newParentProperty);
|
void reparent(const ServerNodeInstance &oldParentInstance, const PropertyName &oldParentProperty, const ServerNodeInstance &newParentInstance, const PropertyName &newParentProperty);
|
||||||
|
|
||||||
|
|
||||||
void setId(const QString &id);
|
void setId(const QString &id);
|
||||||
|
|
||||||
static QSharedPointer<Internal::ObjectNodeInstance> createInstance(QObject *objectToBeWrapped);
|
static QSharedPointer<Internal::ObjectNodeInstance> createInstance(QObject *objectToBeWrapped);
|
||||||
@@ -206,10 +208,6 @@ private: // functions
|
|||||||
|
|
||||||
void setNodeSource(const QString &source);
|
void setNodeSource(const QString &source);
|
||||||
|
|
||||||
bool holdsGraphical() const;
|
|
||||||
|
|
||||||
void updateDirtyNodeRecursive();
|
|
||||||
|
|
||||||
QObject *internalObject() const; // should be not used outside of the nodeinstances!!!!
|
QObject *internalObject() const; // should be not used outside of the nodeinstances!!!!
|
||||||
|
|
||||||
private: // variables
|
private: // variables
|
||||||
|
@@ -26,6 +26,8 @@
|
|||||||
import QtQuick 2.1
|
import QtQuick 2.1
|
||||||
import HelperWidgets 2.0
|
import HelperWidgets 2.0
|
||||||
import QtQuick.Layouts 1.0
|
import QtQuick.Layouts 1.0
|
||||||
|
import StudioControls 1.0 as StudioControls
|
||||||
|
import StudioTheme 1.0 as StudioTheme
|
||||||
|
|
||||||
Section {
|
Section {
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
@@ -46,11 +48,31 @@ Section {
|
|||||||
Label {
|
Label {
|
||||||
text: qsTr("Text")
|
text: qsTr("Text")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
LineEdit {
|
LineEdit {
|
||||||
backendValue: backendValues.text
|
backendValue: backendValues.text
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StudioControls.AbstractButton {
|
||||||
|
id: richTextEditorButton
|
||||||
|
buttonIcon: StudioTheme.Constants.textAlignTop
|
||||||
|
onClicked: {
|
||||||
|
richTextDialogLoader.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RichTextEditor{
|
||||||
|
onRejected: {
|
||||||
|
hideWidget()
|
||||||
|
}
|
||||||
|
onAccepted: {
|
||||||
|
hideWidget()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
visible: showVerticalAlignment
|
visible: showVerticalAlignment
|
||||||
text: qsTr("Wrap mode")
|
text: qsTr("Wrap mode")
|
||||||
@@ -219,4 +241,39 @@ Section {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: richTextDialogLoader
|
||||||
|
|
||||||
|
visible: false
|
||||||
|
active: visible
|
||||||
|
|
||||||
|
function show() {
|
||||||
|
richTextDialogLoader.visible = true
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceComponent: Item {
|
||||||
|
id: richTextEditorParent
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
richTextEditor.showWidget()
|
||||||
|
richTextEditor.richText = backendValues.text.value
|
||||||
|
}
|
||||||
|
|
||||||
|
RichTextEditor {
|
||||||
|
id: richTextEditor
|
||||||
|
|
||||||
|
onRejected: {
|
||||||
|
hideWidget()
|
||||||
|
richTextDialogLoader.visible = false
|
||||||
|
}
|
||||||
|
onAccepted: {
|
||||||
|
backendValues.text.value = richTextEditor.richText
|
||||||
|
backendValues.textFormat.setEnumeration("Text", "RichText")
|
||||||
|
hideWidget()
|
||||||
|
richTextDialogLoader.visible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2020 Uwe Kindler
|
** Copyright (C) 2020 Uwe Kindler
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
@@ -67,3 +67,5 @@ CONFIG(debug, debug|release): DEFINES += SQLITE_ENABLE_API_ARMOR
|
|||||||
OTHER_FILES += README.md
|
OTHER_FILES += README.md
|
||||||
|
|
||||||
contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols
|
contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols
|
||||||
|
|
||||||
|
CONFIG += exceptions
|
||||||
|
@@ -78,12 +78,7 @@ QDebug &operator<<(QDebug &debug, const String &string)
|
|||||||
template <uint Size>
|
template <uint Size>
|
||||||
std::ostream &operator<<(std::ostream &out, const BasicSmallString<Size> &string)
|
std::ostream &operator<<(std::ostream &out, const BasicSmallString<Size> &string)
|
||||||
{
|
{
|
||||||
BasicSmallString<Size> formatedString = string.clone();
|
out.write(string.data(), std::streamsize(string.size()));
|
||||||
|
|
||||||
formatedString.replace("\n", "\\n");
|
|
||||||
formatedString.replace("\t", "\\t");
|
|
||||||
|
|
||||||
out.write(formatedString.data(), std::streamsize(formatedString.size()));
|
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
@@ -45,6 +45,7 @@
|
|||||||
#include <projectexplorer/projectnodes.h>
|
#include <projectexplorer/projectnodes.h>
|
||||||
#include <projectexplorer/runconfiguration.h>
|
#include <projectexplorer/runconfiguration.h>
|
||||||
#include <projectexplorer/target.h>
|
#include <projectexplorer/target.h>
|
||||||
|
#include <projectexplorer/taskhub.h>
|
||||||
#include <projectexplorer/toolchain.h>
|
#include <projectexplorer/toolchain.h>
|
||||||
|
|
||||||
#include <qtsupport/qtkitinformation.h>
|
#include <qtsupport/qtkitinformation.h>
|
||||||
@@ -212,12 +213,12 @@ bool AndroidDeployQtStep::init()
|
|||||||
auto selectedAbis = buildSystem()->extraData(buildKey, Constants::ANDROID_ABIS).toStringList();
|
auto selectedAbis = buildSystem()->extraData(buildKey, Constants::ANDROID_ABIS).toStringList();
|
||||||
|
|
||||||
if (!selectedAbis.contains(info.cpuAbi.first())) {
|
if (!selectedAbis.contains(info.cpuAbi.first())) {
|
||||||
Core::MessageManager::write(
|
TaskHub::addTask(DeploymentTask(
|
||||||
|
Task::Warning,
|
||||||
tr("Android: The main ABI of the deployment device (%1) is not selected. The app "
|
tr("Android: The main ABI of the deployment device (%1) is not selected. The app "
|
||||||
"execution or debugging might not work properly. Add it from Projects > Build > "
|
"execution or debugging might not work properly. Add it from Projects > Build > "
|
||||||
"Build Steps > qmake > ABIs.")
|
"Build Steps > qmake > ABIs.")
|
||||||
.arg(info.cpuAbi.first()),
|
.arg(info.cpuAbi.first())));
|
||||||
Core::MessageManager::WithFocus);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_avdName = info.avdname;
|
m_avdName = info.avdname;
|
||||||
|
@@ -1000,6 +1000,21 @@ QVariant Project::extraData(const QString &key) const
|
|||||||
return d->m_extraData.value(key);
|
return d->m_extraData.value(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList Project::availableQmlPreviewTranslations(QString *errorMessage)
|
||||||
|
{
|
||||||
|
const auto projectDirectory = rootProjectDirectory().toFileInfo().absoluteFilePath();
|
||||||
|
const QDir languageDirectory(projectDirectory + "/i18n");
|
||||||
|
const auto qmFiles = languageDirectory.entryList({"qml_*.qm"});
|
||||||
|
if (qmFiles.isEmpty() && errorMessage)
|
||||||
|
errorMessage->append(tr("Could not find any qml_*.qm file at '%1'").arg(languageDirectory.absolutePath()));
|
||||||
|
return Utils::transform(qmFiles, [](const QString &qmFile) {
|
||||||
|
const int localeStartPosition = qmFile.lastIndexOf("_") + 1;
|
||||||
|
const int localeEndPosition = qmFile.size() - QString(".qm").size();
|
||||||
|
const QString locale = qmFile.left(localeEndPosition).mid(localeStartPosition);
|
||||||
|
return locale;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(WITH_TESTS)
|
#if defined(WITH_TESTS)
|
||||||
|
|
||||||
} // namespace ProjectExplorer
|
} // namespace ProjectExplorer
|
||||||
|
@@ -170,6 +170,8 @@ public:
|
|||||||
void setExtraData(const QString &key, const QVariant &data);
|
void setExtraData(const QString &key, const QVariant &data);
|
||||||
QVariant extraData(const QString &key) const;
|
QVariant extraData(const QString &key) const;
|
||||||
|
|
||||||
|
QStringList availableQmlPreviewTranslations(QString *errorMessage);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void projectFileIsDirty(const Utils::FilePath &path);
|
void projectFileIsDirty(const Utils::FilePath &path);
|
||||||
|
|
||||||
|
@@ -505,6 +505,12 @@ extend_qtc_plugin(QmlDesigner
|
|||||||
puppetbuildprogressdialog.cpp puppetbuildprogressdialog.h puppetbuildprogressdialog.ui
|
puppetbuildprogressdialog.cpp puppetbuildprogressdialog.h puppetbuildprogressdialog.ui
|
||||||
puppetcreator.cpp puppetcreator.h
|
puppetcreator.cpp puppetcreator.h
|
||||||
puppetdialog.cpp puppetdialog.h puppetdialog.ui
|
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
|
extend_qtc_plugin(QmlDesigner
|
||||||
|
@@ -45,14 +45,19 @@ const char DocumentNameTag[] = "name";
|
|||||||
// Layer data tags
|
// Layer data tags
|
||||||
const char ArtboardListTag[] = "artboards";
|
const char ArtboardListTag[] = "artboards";
|
||||||
|
|
||||||
|
const char NameTag[] = "name";
|
||||||
|
|
||||||
const char XPosTag[] = "x";
|
const char XPosTag[] = "x";
|
||||||
const char YPosTag[] = "y";
|
const char YPosTag[] = "y";
|
||||||
const char WidthTag[] = "width";
|
const char WidthTag[] = "width";
|
||||||
const char HeightTag[] = "height";
|
const char HeightTag[] = "height";
|
||||||
|
|
||||||
|
const char MetadataTag[] = "metadata";
|
||||||
|
const char ChildrenTag[] = "children";
|
||||||
const char QmlIdTag[] = "qmlId";
|
const char QmlIdTag[] = "qmlId";
|
||||||
const char ExportTypeTag[] = "exportType";
|
const char ExportTypeTag[] = "exportType";
|
||||||
|
const char ExportTypeComponent[] = "component";
|
||||||
|
const char ExportTypeChild[] = "child";
|
||||||
const char QmlPropertiesTag[] = "qmlProperties";
|
const char QmlPropertiesTag[] = "qmlProperties";
|
||||||
const char ImportsTag[] = "extraImports";
|
const char ImportsTag[] = "extraImports";
|
||||||
const char UuidTag[] = "uuid";
|
const char UuidTag[] = "uuid";
|
||||||
|
@@ -53,6 +53,7 @@ static void populateLineage(const QmlDesigner::ModelNode &node, QByteArrayList &
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
using namespace Constants;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<Internal::NodeParserCreatorBase>> Component::m_readers;
|
std::vector<std::unique_ptr<Internal::NodeParserCreatorBase>> Component::m_readers;
|
||||||
Component::Component(AssetExporter &exporter, const ModelNode &rootNode):
|
Component::Component(AssetExporter &exporter, const ModelNode &rootNode):
|
||||||
@@ -76,6 +77,10 @@ void Component::exportComponent()
|
|||||||
{
|
{
|
||||||
QTC_ASSERT(m_rootNode.isValid(), return);
|
QTC_ASSERT(m_rootNode.isValid(), return);
|
||||||
m_json = nodeToJson(m_rootNode);
|
m_json = nodeToJson(m_rootNode);
|
||||||
|
// Change the export type to component
|
||||||
|
QJsonObject metadata = m_json.value(MetadataTag).toObject();
|
||||||
|
metadata.insert(ExportTypeTag, ExportTypeComponent);
|
||||||
|
m_json.insert(MetadataTag, metadata);
|
||||||
addImports();
|
addImports();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,7 +129,7 @@ QJsonObject Component::nodeToJson(const ModelNode &node)
|
|||||||
children.append(nodeToJson(childnode));
|
children.append(nodeToJson(childnode));
|
||||||
|
|
||||||
if (!children.isEmpty())
|
if (!children.isEmpty())
|
||||||
jsonObject.insert("children", children);
|
jsonObject.insert(ChildrenTag, children);
|
||||||
|
|
||||||
return jsonObject;
|
return jsonObject;
|
||||||
}
|
}
|
||||||
|
@@ -58,7 +58,10 @@ QJsonObject AssetNodeParser::json(Component &component) const
|
|||||||
Utils::FilePath assetPath = component.exporter().exportAsset(objectNode(), uuid());
|
Utils::FilePath assetPath = component.exporter().exportAsset(objectNode(), uuid());
|
||||||
QJsonObject assetData;
|
QJsonObject assetData;
|
||||||
assetData.insert(AssetPathTag, assetPath.toString());
|
assetData.insert(AssetPathTag, assetPath.toString());
|
||||||
jsonObject.insert(AssetDataTag, assetData);
|
|
||||||
|
QJsonObject metadata = jsonObject.value(MetadataTag).toObject();
|
||||||
|
metadata.insert(AssetDataTag, assetData);
|
||||||
|
jsonObject.insert(MetadataTag, metadata);
|
||||||
return jsonObject;
|
return jsonObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -28,6 +28,17 @@
|
|||||||
|
|
||||||
#include "qmlitemnode.h"
|
#include "qmlitemnode.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
static QString capitalize(const QString &str)
|
||||||
|
{
|
||||||
|
if (str.isEmpty())
|
||||||
|
return {};
|
||||||
|
QString tmp = str;
|
||||||
|
tmp[0] = QChar(str[0]).toUpper().toLatin1();
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
using namespace Constants;
|
using namespace Constants;
|
||||||
ItemNodeParser::ItemNodeParser(const QByteArrayList &lineage,
|
ItemNodeParser::ItemNodeParser(const QByteArrayList &lineage,
|
||||||
@@ -47,10 +58,16 @@ QJsonObject QmlDesigner::ItemNodeParser::json(QmlDesigner::Component &component)
|
|||||||
Q_UNUSED(component);
|
Q_UNUSED(component);
|
||||||
const QmlObjectNode &qmlObjectNode = objectNode();
|
const QmlObjectNode &qmlObjectNode = objectNode();
|
||||||
QJsonObject jsonObject;
|
QJsonObject jsonObject;
|
||||||
jsonObject.insert(QmlIdTag, qmlObjectNode.id());
|
|
||||||
QmlItemNode itemNode = qmlObjectNode.toQmlItemNode();
|
const QString qmlId = qmlObjectNode.id();
|
||||||
|
QString name = m_node.simplifiedTypeName();
|
||||||
|
if (!qmlId.isEmpty())
|
||||||
|
name.append("_" + capitalize(qmlId));
|
||||||
|
|
||||||
|
jsonObject.insert(NameTag, name);
|
||||||
|
|
||||||
// Position relative to parent
|
// Position relative to parent
|
||||||
|
QmlItemNode itemNode = qmlObjectNode.toQmlItemNode();
|
||||||
QPointF pos = itemNode.instancePosition();
|
QPointF pos = itemNode.instancePosition();
|
||||||
jsonObject.insert(XPosTag, pos.x());
|
jsonObject.insert(XPosTag, pos.x());
|
||||||
jsonObject.insert(YPosTag, pos.y());
|
jsonObject.insert(YPosTag, pos.y());
|
||||||
@@ -60,10 +77,13 @@ QJsonObject QmlDesigner::ItemNodeParser::json(QmlDesigner::Component &component)
|
|||||||
jsonObject.insert(WidthTag, size.width());
|
jsonObject.insert(WidthTag, size.width());
|
||||||
jsonObject.insert(HeightTag, size.height());
|
jsonObject.insert(HeightTag, size.height());
|
||||||
|
|
||||||
jsonObject.insert(UuidTag, uuid());
|
QJsonObject metadata;
|
||||||
jsonObject.insert(ExportTypeTag, "child");
|
metadata.insert(QmlIdTag, qmlId);
|
||||||
jsonObject.insert(TypeNameTag, QString::fromLatin1(m_node.type()));
|
metadata.insert(UuidTag, uuid());
|
||||||
|
metadata.insert(ExportTypeTag, ExportTypeChild);
|
||||||
|
metadata.insert(TypeNameTag, QString::fromLatin1(m_node.type()));
|
||||||
|
|
||||||
|
jsonObject.insert(MetadataTag, metadata);
|
||||||
return jsonObject;
|
return jsonObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -81,7 +81,9 @@ QJsonObject TextNodeParser::json(Component &component) const
|
|||||||
|
|
||||||
textDetails.insert(IsMultilineTag, propertyValue("wrapMode").toString().compare("NoWrap") != 0);
|
textDetails.insert(IsMultilineTag, propertyValue("wrapMode").toString().compare("NoWrap") != 0);
|
||||||
|
|
||||||
jsonObject.insert(TextDetailsTag, textDetails);
|
QJsonObject metadata = jsonObject.value(MetadataTag).toObject();
|
||||||
|
metadata.insert(TextDetailsTag, textDetails);
|
||||||
|
jsonObject.insert(MetadataTag, metadata);
|
||||||
return jsonObject;
|
return jsonObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -363,32 +363,30 @@ public:
|
|||||||
|
|
||||||
bool isEnabled(const SelectionContext &) const override { return true; }
|
bool isEnabled(const SelectionContext &) const override { return true; }
|
||||||
|
|
||||||
static ModelNode listModelNode(const ModelNode &listViewNode)
|
|
||||||
{
|
|
||||||
if (listViewNode.hasProperty("model")) {
|
|
||||||
if (listViewNode.hasBindingProperty("model"))
|
|
||||||
return listViewNode.bindingProperty("model").resolveToModelNode();
|
|
||||||
else if (listViewNode.hasNodeProperty("model"))
|
|
||||||
return listViewNode.nodeProperty("model").modelNode();
|
|
||||||
}
|
|
||||||
|
|
||||||
ModelNode newModel = listViewNode.view()->createModelNode("QtQml.Models.ListModel", 2, 15);
|
|
||||||
listViewNode.nodeProperty("mode").reparentHere(newModel);
|
|
||||||
|
|
||||||
return newModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void openDialog(const SelectionContext &selectionState)
|
static void openDialog(const SelectionContext &selectionState)
|
||||||
{
|
{
|
||||||
ListModelEditorModel model;
|
|
||||||
|
|
||||||
ModelNode targetNode = selectionState.targetNode();
|
ModelNode targetNode = selectionState.targetNode();
|
||||||
if (!targetNode.isValid())
|
if (!targetNode.isValid())
|
||||||
targetNode = selectionState.currentSingleSelectedNode();
|
targetNode = selectionState.currentSingleSelectedNode();
|
||||||
if (!targetNode.isValid())
|
if (!targetNode.isValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
model.setListModel(listModelNode(targetNode));
|
AbstractView *view = targetNode.view();
|
||||||
|
NodeMetaInfo modelMetaInfo = view->model()->metaInfo("ListModel");
|
||||||
|
NodeMetaInfo elementMetaInfo = view->model()->metaInfo("ListElement");
|
||||||
|
|
||||||
|
ListModelEditorModel model{[&] {
|
||||||
|
return view->createModelNode(modelMetaInfo.typeName(),
|
||||||
|
modelMetaInfo.majorVersion(),
|
||||||
|
modelMetaInfo.minorVersion());
|
||||||
|
},
|
||||||
|
[&] {
|
||||||
|
return view->createModelNode(elementMetaInfo.typeName(),
|
||||||
|
elementMetaInfo.majorVersion(),
|
||||||
|
elementMetaInfo.minorVersion());
|
||||||
|
}};
|
||||||
|
|
||||||
|
model.setListView(targetNode);
|
||||||
|
|
||||||
ListModelEditorDialog dialog{Core::ICore::mainWindow()};
|
ListModelEditorDialog dialog{Core::ICore::mainWindow()};
|
||||||
dialog.setModel(&model);
|
dialog.setModel(&model);
|
||||||
|
@@ -221,6 +221,13 @@ void ConnectionModel::updateTargetNode(int rowNumber)
|
|||||||
isSingleton = true;
|
isSingleton = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else if (isAlias) {
|
||||||
|
if (data.typeName == newTarget.split(".").constFirst()) {
|
||||||
|
if (connectionView()->model()->metaInfo(data.typeName.toUtf8()).isValid()) {
|
||||||
|
isSingleton = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -229,7 +236,7 @@ void ConnectionModel::updateTargetNode(int rowNumber)
|
|||||||
if (!newTarget.isEmpty()) {
|
if (!newTarget.isEmpty()) {
|
||||||
//if it's a singleton, then let's reparent connections to rootNode,
|
//if it's a singleton, then let's reparent connections to rootNode,
|
||||||
//if it's an alias, then reparent to alias property owner:
|
//if it's an alias, then reparent to alias property owner:
|
||||||
const ModelNode parent = connectionView()->modelNodeForId(isSingleton
|
const ModelNode parent = connectionView()->modelNodeForId((isSingleton || (isSingleton && isAlias))
|
||||||
? connectionView()->rootModelNode().id()
|
? connectionView()->rootModelNode().id()
|
||||||
: isAlias
|
: isAlias
|
||||||
? newTarget.split(".").constFirst()
|
? newTarget.split(".").constFirst()
|
||||||
@@ -255,35 +262,36 @@ void ConnectionModel::updateCustomData(QStandardItem *item, const SignalHandlerP
|
|||||||
|
|
||||||
ModelNode ConnectionModel::getTargetNodeForConnection(const ModelNode &connection) const
|
ModelNode ConnectionModel::getTargetNodeForConnection(const ModelNode &connection) const
|
||||||
{
|
{
|
||||||
BindingProperty bindingProperty = connection.bindingProperty("target");
|
ModelNode result;
|
||||||
|
|
||||||
|
const BindingProperty bindingProperty = connection.bindingProperty("target");
|
||||||
|
const QString bindExpression = bindingProperty.expression();
|
||||||
|
|
||||||
if (bindingProperty.isValid()) {
|
if (bindingProperty.isValid()) {
|
||||||
bool isAlias = bindingProperty.expression().contains(".");
|
if (bindExpression == QLatin1String("parent")) {
|
||||||
|
result = connection.parentProperty().parentModelNode();
|
||||||
if (bindingProperty.expression() == QLatin1String("parent"))
|
} else if (bindExpression.contains(".")) {
|
||||||
return connection.parentProperty().parentModelNode();
|
QStringList substr = bindExpression.split(".");
|
||||||
else if (isAlias) {
|
const QString itemId = substr.constFirst();
|
||||||
QStringList substr = bindingProperty.expression().split(".");
|
|
||||||
if (substr.size() > 1) {
|
if (substr.size() > 1) {
|
||||||
ModelNode aliasParent = connectionView()->modelNodeForId(substr.constFirst());
|
const ModelNode aliasParent = (itemId == QLatin1String("parent")
|
||||||
QString aliasBody = substr.at(1);
|
? connection.parentProperty().parentModelNode()
|
||||||
if (aliasParent.hasProperty(aliasBody.toUtf8())) {
|
: connectionView()->modelNodeForId(itemId));
|
||||||
AbstractProperty abstractProp = aliasParent.property(aliasBody.toUtf8());
|
substr.removeFirst(); //remove id, only alias pieces left
|
||||||
if (abstractProp.isBindingProperty()) {
|
const QString aliasBody = substr.join(".");
|
||||||
BindingProperty binding = abstractProp.toBindingProperty();
|
if (aliasParent.isValid() && aliasParent.hasBindingProperty(aliasBody.toUtf8())) {
|
||||||
if (connectionView()->hasId(binding.expression())) {
|
const BindingProperty binding = aliasParent.bindingProperty(aliasBody.toUtf8());
|
||||||
ModelNode resolve = connectionView()->modelNodeForId(binding.expression());
|
if (binding.isValid() && connectionView()->hasId(binding.expression())) {
|
||||||
if (resolve.isValid())
|
result = connectionView()->modelNodeForId(binding.expression());
|
||||||
return resolve;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
result = connectionView()->modelNodeForId(bindExpression);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return connectionView()->modelNodeForId(bindingProperty.expression());
|
|
||||||
}
|
|
||||||
|
|
||||||
return ModelNode();
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionModel::addConnection()
|
void ConnectionModel::addConnection()
|
||||||
@@ -355,8 +363,7 @@ void ConnectionModel::deleteConnectionByRow(int currentRow)
|
|||||||
if (allSignals.size() > 1) {
|
if (allSignals.size() > 1) {
|
||||||
if (allSignals.contains(targetSignal))
|
if (allSignals.contains(targetSignal))
|
||||||
node.removeProperty(targetSignal.name());
|
node.removeProperty(targetSignal.name());
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
node.destroy();
|
node.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -448,21 +455,44 @@ QStringList ConnectionModel::getPossibleSignalsForConnection(const ModelNode &co
|
|||||||
{
|
{
|
||||||
QStringList stringList;
|
QStringList stringList;
|
||||||
|
|
||||||
if (connection.isValid()) {
|
auto getAliasMetaSignals = [&](QString aliasPart, NodeMetaInfo metaInfo) {
|
||||||
|
if (metaInfo.isValid() && metaInfo.hasProperty(aliasPart.toUtf8())) {
|
||||||
|
NodeMetaInfo propertyMetaInfo = connectionView()->model()->metaInfo(
|
||||||
|
metaInfo.propertyTypeName(aliasPart.toUtf8()));
|
||||||
|
if (propertyMetaInfo.isValid()) {
|
||||||
|
return propertyNameListToStringList(propertyMetaInfo.signalNames());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QStringList();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (connection.isValid()) {
|
||||||
//separate check for singletons
|
//separate check for singletons
|
||||||
if (connection.hasBindingProperty("target")) {
|
if (connection.hasBindingProperty("target")) {
|
||||||
BindingProperty bp = connection.bindingProperty("target");
|
const BindingProperty bp = connection.bindingProperty("target");
|
||||||
|
|
||||||
if (bp.isValid()) {
|
if (bp.isValid()) {
|
||||||
if (RewriterView *rv = connectionView()->rewriterView()) {
|
const QString bindExpression = bp.expression();
|
||||||
|
|
||||||
|
if (const RewriterView * const rv = connectionView()->rewriterView()) {
|
||||||
for (const QmlTypeData &data : rv->getQMLTypes()) {
|
for (const QmlTypeData &data : rv->getQMLTypes()) {
|
||||||
if (!data.typeName.isEmpty()) {
|
if (!data.typeName.isEmpty()) {
|
||||||
if (data.typeName == bp.expression()) {
|
if (data.typeName == bindExpression) {
|
||||||
NodeMetaInfo metaInfo = connectionView()->model()->metaInfo(data.typeName.toUtf8());
|
NodeMetaInfo metaInfo = connectionView()->model()->metaInfo(data.typeName.toUtf8());
|
||||||
if (metaInfo.isValid()) {
|
if (metaInfo.isValid()) {
|
||||||
stringList.append(propertyNameListToStringList(metaInfo.signalNames()));
|
stringList << propertyNameListToStringList(metaInfo.signalNames());
|
||||||
return stringList;
|
break;
|
||||||
|
}
|
||||||
|
} else if (bindExpression.contains(".")) {
|
||||||
|
//if it doesn't fit the same name, maybe it's an alias?
|
||||||
|
QStringList expression = bindExpression.split(".");
|
||||||
|
if ((expression.size() > 1) && (expression.constFirst() == data.typeName)) {
|
||||||
|
expression.removeFirst();
|
||||||
|
|
||||||
|
stringList << getAliasMetaSignals(
|
||||||
|
expression.join("."),
|
||||||
|
connectionView()->model()->metaInfo(data.typeName.toUtf8()));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -474,6 +504,30 @@ QStringList ConnectionModel::getPossibleSignalsForConnection(const ModelNode &co
|
|||||||
ModelNode targetNode = getTargetNodeForConnection(connection);
|
ModelNode targetNode = getTargetNodeForConnection(connection);
|
||||||
if (targetNode.isValid() && targetNode.metaInfo().isValid()) {
|
if (targetNode.isValid() && targetNode.metaInfo().isValid()) {
|
||||||
stringList.append(propertyNameListToStringList(targetNode.metaInfo().signalNames()));
|
stringList.append(propertyNameListToStringList(targetNode.metaInfo().signalNames()));
|
||||||
|
} else {
|
||||||
|
//most likely it's component's internal alias:
|
||||||
|
|
||||||
|
if (connection.hasBindingProperty("target")) {
|
||||||
|
const BindingProperty bp = connection.bindingProperty("target");
|
||||||
|
|
||||||
|
if (bp.isValid()) {
|
||||||
|
const QString bindExpression = bp.expression();
|
||||||
|
QStringList expression = bp.expression().split(".");
|
||||||
|
if (expression.size() > 1) {
|
||||||
|
const QString itemId = expression.constFirst();
|
||||||
|
if (connectionView()->hasId(itemId)) {
|
||||||
|
ModelNode parentItem = connectionView()->modelNodeForId(itemId);
|
||||||
|
if (parentItem.isValid()
|
||||||
|
&& parentItem.hasMetaInfo()
|
||||||
|
&& parentItem.metaInfo().isValid()) {
|
||||||
|
expression.removeFirst();
|
||||||
|
stringList << getAliasMetaSignals(expression.join("."),
|
||||||
|
parentItem.metaInfo());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -295,6 +295,35 @@ QWidget *ConnectionDelegate::createEditor(QWidget *parent, const QStyleOptionVie
|
|||||||
|
|
||||||
switch (index.column()) {
|
switch (index.column()) {
|
||||||
case ConnectionModel::TargetModelNodeRow: {
|
case ConnectionModel::TargetModelNodeRow: {
|
||||||
|
|
||||||
|
auto addMetaInfoProperties = [&](const NodeMetaInfo& itemMetaInfo, QString itemName){
|
||||||
|
if (itemMetaInfo.isValid()) {
|
||||||
|
for (const PropertyName &propertyName : itemMetaInfo.directPropertyNames()) {
|
||||||
|
TypeName propertyType = itemMetaInfo.propertyTypeName(propertyName);
|
||||||
|
if (!propertyType.isEmpty()) {
|
||||||
|
//first letter is a reliable item indicator
|
||||||
|
QChar firstLetter = QString::fromUtf8(propertyType).at(0);
|
||||||
|
if (firstLetter.isLetter() && firstLetter.isUpper()) {
|
||||||
|
if (!itemMetaInfo.propertyIsEnumType(propertyName)
|
||||||
|
&& !itemMetaInfo.propertyIsPrivate(propertyName)
|
||||||
|
&& !itemMetaInfo.propertyIsListProperty(propertyName)
|
||||||
|
&& !itemMetaInfo.propertyIsPointer(propertyName)) {
|
||||||
|
NodeMetaInfo propertyMetaInfo =
|
||||||
|
connectionModel->connectionView()->model()->metaInfo(propertyType);
|
||||||
|
if (propertyMetaInfo.isValid()) {
|
||||||
|
if (propertyMetaInfo.isQmlItem()) {
|
||||||
|
connectionComboBox->addItem(itemName
|
||||||
|
+ "."
|
||||||
|
+ propertyName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
for (const ModelNode &modelNode : connectionModel->connectionView()->allModelNodes()) {
|
for (const ModelNode &modelNode : connectionModel->connectionView()->allModelNodes()) {
|
||||||
if (!modelNode.id().isEmpty()) {
|
if (!modelNode.id().isEmpty()) {
|
||||||
connectionComboBox->addItem(modelNode.id());
|
connectionComboBox->addItem(modelNode.id());
|
||||||
@@ -308,25 +337,24 @@ QWidget *ConnectionDelegate::createEditor(QWidget *parent, const QStyleOptionVie
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Components
|
||||||
|
if (modelNode.isComponent()) {
|
||||||
|
NodeMetaInfo componentMetaInfo = modelNode.metaInfo();
|
||||||
|
addMetaInfoProperties(componentMetaInfo, modelNode.id());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//singletons:
|
//singletons:
|
||||||
if (RewriterView* rv = connectionModel->connectionView()->rewriterView()) {
|
if (RewriterView* rv = connectionModel->connectionView()->rewriterView()) {
|
||||||
for (const QmlTypeData &data : rv->getQMLTypes()) {
|
for (const QmlTypeData &data : rv->getQMLTypes()) {
|
||||||
if (!data.typeName.isEmpty()) {
|
if (!data.typeName.isEmpty()) {
|
||||||
|
//singleton itself
|
||||||
connectionComboBox->addItem(data.typeName);
|
connectionComboBox->addItem(data.typeName);
|
||||||
|
|
||||||
|
//its properties, mostly looking for aliases:
|
||||||
NodeMetaInfo metaInfo = connectionModel->connectionView()->model()->metaInfo(data.typeName.toUtf8());
|
NodeMetaInfo metaInfo = connectionModel->connectionView()->model()->metaInfo(data.typeName.toUtf8());
|
||||||
|
addMetaInfoProperties(metaInfo, data.typeName);
|
||||||
if (metaInfo.isValid()) {
|
|
||||||
for (const PropertyName &propertyName : metaInfo.propertyNames()) {
|
|
||||||
if (metaInfo.propertyTypeName(propertyName) == "alias") {
|
|
||||||
connectionComboBox->addItem(data.typeName
|
|
||||||
+ "."
|
|
||||||
+ QString::fromUtf8(propertyName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -283,6 +283,11 @@ bool FormEditorItem::flowHitTest(const QPointF & ) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FormEditorItem::setFrameColor(const QColor &color)
|
||||||
|
{
|
||||||
|
m_frameColor = color;
|
||||||
|
}
|
||||||
|
|
||||||
FormEditorItem::~FormEditorItem()
|
FormEditorItem::~FormEditorItem()
|
||||||
{
|
{
|
||||||
scene()->removeItemFromHash(this);
|
scene()->removeItemFromHash(this);
|
||||||
@@ -313,14 +318,21 @@ void FormEditorItem::paintBoundingRect(QPainter *painter) const
|
|||||||
pen.setJoinStyle(Qt::MiterJoin);
|
pen.setJoinStyle(Qt::MiterJoin);
|
||||||
|
|
||||||
const QColor frameColor(0xaa, 0xaa, 0xaa);
|
const QColor frameColor(0xaa, 0xaa, 0xaa);
|
||||||
static const QColor selectionColor = Utils::creatorTheme()->color(Utils::Theme::QmlDesigner_FormEditorSelectionColor);
|
static const QColor selectionColor = Utils::creatorTheme()->color(
|
||||||
|
Utils::Theme::QmlDesigner_FormEditorSelectionColor);
|
||||||
|
|
||||||
if (scene()->showBoundingRects()) {
|
if (scene()->showBoundingRects()) {
|
||||||
pen.setColor(frameColor.darker(150));
|
pen.setColor(frameColor.darker(150));
|
||||||
pen.setStyle(Qt::DotLine);
|
pen.setStyle(Qt::DotLine);
|
||||||
painter->setPen(pen);
|
painter->setPen(pen);
|
||||||
painter->drawRect(m_boundingRect.adjusted(0., 0., -1., -1.));
|
painter->drawRect(m_boundingRect.adjusted(0., 0., -1., -1.));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_frameColor.isValid()) {
|
||||||
|
pen.setColor(m_frameColor);
|
||||||
|
pen.setStyle(Qt::SolidLine);
|
||||||
|
painter->setPen(pen);
|
||||||
|
painter->drawRect(m_boundingRect.adjusted(0., 0., -1., -1.));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_highlightBoundingRect) {
|
if (m_highlightBoundingRect) {
|
||||||
|
@@ -117,6 +117,8 @@ public:
|
|||||||
|
|
||||||
virtual bool flowHitTest(const QPointF &point) const;
|
virtual bool flowHitTest(const QPointF &point) const;
|
||||||
|
|
||||||
|
void setFrameColor(const QColor &color);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
AbstractFormEditorTool* tool() const;
|
AbstractFormEditorTool* tool() const;
|
||||||
void paintBoundingRect(QPainter *painter) const;
|
void paintBoundingRect(QPainter *painter) const;
|
||||||
@@ -129,6 +131,7 @@ protected:
|
|||||||
QRectF m_boundingRect;
|
QRectF m_boundingRect;
|
||||||
QRectF m_paintedBoundingRect;
|
QRectF m_paintedBoundingRect;
|
||||||
QRectF m_selectionBoundingRect;
|
QRectF m_selectionBoundingRect;
|
||||||
|
QColor m_frameColor{0xaa, 0xaa, 0xaa};
|
||||||
|
|
||||||
private: // functions
|
private: // functions
|
||||||
void setup();
|
void setup();
|
||||||
|
@@ -633,6 +633,11 @@ void FormEditorView::auxiliaryDataChanged(const ModelNode &node, const PropertyN
|
|||||||
editorItem->update();
|
editorItem->update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (name == "FrameColor@Internal") {
|
||||||
|
if (FormEditorItem *editorItem = scene()->itemForQmlItemNode(item))
|
||||||
|
editorItem->setFrameColor(data.value<QColor>());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FormEditorView::instancesCompleted(const QVector<ModelNode> &completedNodeList)
|
void FormEditorView::instancesCompleted(const QVector<ModelNode> &completedNodeList)
|
||||||
|
@@ -86,7 +86,7 @@ void ItemLibraryAssetImporter::importQuick3D(const QStringList &inputFiles,
|
|||||||
|
|
||||||
if (!isCancelled()) {
|
if (!isCancelled()) {
|
||||||
// Wait for icon generation processes to finish
|
// Wait for icon generation processes to finish
|
||||||
if (m_qmlPuppetProcesses.isEmpty()) {
|
if (m_qmlPuppetProcesses.empty()) {
|
||||||
finalizeQuick3DImport();
|
finalizeQuick3DImport();
|
||||||
} else {
|
} else {
|
||||||
m_qmlPuppetCount = m_qmlPuppetProcesses.size();
|
m_qmlPuppetCount = m_qmlPuppetProcesses.size();
|
||||||
@@ -186,10 +186,12 @@ void ItemLibraryAssetImporter::processFinished(int exitCode, QProcess::ExitStatu
|
|||||||
|
|
||||||
auto process = qobject_cast<QProcess *>(sender());
|
auto process = qobject_cast<QProcess *>(sender());
|
||||||
if (process) {
|
if (process) {
|
||||||
m_qmlPuppetProcesses.remove(process);
|
m_qmlPuppetProcesses.erase(
|
||||||
process->deleteLater();
|
std::remove_if(m_qmlPuppetProcesses.begin(),
|
||||||
|
m_qmlPuppetProcesses.end(),
|
||||||
|
[&](const auto &entry) { return entry.get() == process; }));
|
||||||
const QString progressTitle = tr("Generating icons.");
|
const QString progressTitle = tr("Generating icons.");
|
||||||
if (m_qmlPuppetProcesses.isEmpty()) {
|
if (m_qmlPuppetProcesses.empty()) {
|
||||||
notifyProgress(100, progressTitle);
|
notifyProgress(100, progressTitle);
|
||||||
finalizeQuick3DImport();
|
finalizeQuick3DImport();
|
||||||
} else {
|
} else {
|
||||||
@@ -215,7 +217,6 @@ void ItemLibraryAssetImporter::reset()
|
|||||||
m_tempDir = new QTemporaryDir;
|
m_tempDir = new QTemporaryDir;
|
||||||
m_importFiles.clear();
|
m_importFiles.clear();
|
||||||
m_overwrittenImports.clear();
|
m_overwrittenImports.clear();
|
||||||
qDeleteAll(m_qmlPuppetProcesses);
|
|
||||||
m_qmlPuppetProcesses.clear();
|
m_qmlPuppetProcesses.clear();
|
||||||
m_qmlPuppetCount = 0;
|
m_qmlPuppetCount = 0;
|
||||||
#endif
|
#endif
|
||||||
@@ -498,16 +499,21 @@ bool ItemLibraryAssetImporter::generateComponentIcon(int size, const QString &ic
|
|||||||
puppetCreator.createQml2PuppetExecutableIfMissing();
|
puppetCreator.createQml2PuppetExecutableIfMissing();
|
||||||
QStringList puppetArgs;
|
QStringList puppetArgs;
|
||||||
puppetArgs << "--rendericon" << QString::number(size) << iconFile << iconSource;
|
puppetArgs << "--rendericon" << QString::number(size) << iconFile << iconSource;
|
||||||
QProcess *process = puppetCreator.createPuppetProcess(
|
QProcessUniquePointer process = puppetCreator.createPuppetProcess(
|
||||||
"custom", {}, this, "", SLOT(processFinished(int, QProcess::ExitStatus)), puppetArgs);
|
"custom",
|
||||||
|
{},
|
||||||
|
this,
|
||||||
|
std::function<void()>(),
|
||||||
|
[&](int exitCode, QProcess::ExitStatus exitStatus) {
|
||||||
|
processFinished(exitCode, exitStatus);
|
||||||
|
},
|
||||||
|
puppetArgs);
|
||||||
|
|
||||||
if (process->waitForStarted(5000)) {
|
if (process->waitForStarted(5000)) {
|
||||||
connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
m_qmlPuppetProcesses.push_back(std::move(process));
|
||||||
process, &QProcess::deleteLater);
|
|
||||||
m_qmlPuppetProcesses << process;
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
delete process;
|
process.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@@ -24,14 +24,16 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "import.h"
|
||||||
|
|
||||||
|
#include <qprocessuniqueptr.h>
|
||||||
|
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QtCore/qobject.h>
|
|
||||||
#include <QtCore/qstringlist.h>
|
|
||||||
#include <QtCore/qhash.h>
|
#include <QtCore/qhash.h>
|
||||||
#include <QtCore/qjsonobject.h>
|
#include <QtCore/qjsonobject.h>
|
||||||
|
#include <QtCore/qobject.h>
|
||||||
#include <QtCore/qprocess.h>
|
#include <QtCore/qprocess.h>
|
||||||
|
#include <QtCore/qstringlist.h>
|
||||||
#include "import.h"
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QSSGAssetImportManager;
|
class QSSGAssetImportManager;
|
||||||
@@ -99,7 +101,7 @@ private:
|
|||||||
bool m_cancelled = false;
|
bool m_cancelled = false;
|
||||||
QString m_importPath;
|
QString m_importPath;
|
||||||
QTemporaryDir *m_tempDir = nullptr;
|
QTemporaryDir *m_tempDir = nullptr;
|
||||||
QSet<QProcess *> m_qmlPuppetProcesses;
|
std::vector<QProcessUniquePointer> m_qmlPuppetProcesses;
|
||||||
int m_qmlPuppetCount = 0;
|
int m_qmlPuppetCount = 0;
|
||||||
};
|
};
|
||||||
} // QmlDesigner
|
} // QmlDesigner
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
#include "listmodeleditormodel.h"
|
#include "listmodeleditormodel.h"
|
||||||
|
|
||||||
#include <theme.h>
|
#include <theme.h>
|
||||||
|
#include <qmldesignericons.h>
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
@@ -71,6 +72,10 @@ ListModelEditorDialog::ListModelEditorDialog(QWidget *parent)
|
|||||||
m_addColumnAction = toolBar->addAction(getIcon(Theme::Icon::addColumnAfter), tr("Add Column"));
|
m_addColumnAction = toolBar->addAction(getIcon(Theme::Icon::addColumnAfter), tr("Add Column"));
|
||||||
m_removeColumnsAction = toolBar->addAction(getIcon(Theme::Icon::deleteColumn),
|
m_removeColumnsAction = toolBar->addAction(getIcon(Theme::Icon::deleteColumn),
|
||||||
tr("Remove Columns"));
|
tr("Remove Columns"));
|
||||||
|
m_moveDownAction = toolBar->addAction(Icons::ARROW_DOWN.icon(), tr("Move down (CTRL + Down)."));
|
||||||
|
m_moveDownAction->setShortcut(QKeySequence(Qt::Key_Down | Qt::CTRL));
|
||||||
|
m_moveUpAction = toolBar->addAction(Icons::ARROW_UP.icon(), tr("Move up (CTRL + Up)."));
|
||||||
|
m_moveDownAction->setShortcut(QKeySequence(Qt::Key_Up | Qt::CTRL));
|
||||||
}
|
}
|
||||||
|
|
||||||
ListModelEditorDialog::~ListModelEditorDialog() = default;
|
ListModelEditorDialog::~ListModelEditorDialog() = default;
|
||||||
@@ -83,6 +88,8 @@ void ListModelEditorDialog::setModel(ListModelEditorModel *model)
|
|||||||
connect(m_addColumnAction, &QAction::triggered, this, &ListModelEditorDialog::openColumnDialog);
|
connect(m_addColumnAction, &QAction::triggered, this, &ListModelEditorDialog::openColumnDialog);
|
||||||
connect(m_removeRowsAction, &QAction::triggered, this, &ListModelEditorDialog::removeRows);
|
connect(m_removeRowsAction, &QAction::triggered, this, &ListModelEditorDialog::removeRows);
|
||||||
connect(m_removeColumnsAction, &QAction::triggered, this, &ListModelEditorDialog::removeColumns);
|
connect(m_removeColumnsAction, &QAction::triggered, this, &ListModelEditorDialog::removeColumns);
|
||||||
|
connect(m_moveDownAction, &QAction::triggered, this, &ListModelEditorDialog::moveRowsDown);
|
||||||
|
connect(m_moveUpAction, &QAction::triggered, this, &ListModelEditorDialog::moveRowsUp);
|
||||||
connect(m_tableView->horizontalHeader(),
|
connect(m_tableView->horizontalHeader(),
|
||||||
&QHeaderView::sectionDoubleClicked,
|
&QHeaderView::sectionDoubleClicked,
|
||||||
this,
|
this,
|
||||||
@@ -114,40 +121,12 @@ void ListModelEditorDialog::openColumnDialog()
|
|||||||
|
|
||||||
void ListModelEditorDialog::removeRows()
|
void ListModelEditorDialog::removeRows()
|
||||||
{
|
{
|
||||||
const QList<QModelIndex> indices = m_tableView->selectionModel()->selectedRows();
|
m_model->removeRows(m_tableView->selectionModel()->selectedRows());
|
||||||
std::vector<int> rows;
|
|
||||||
rows.reserve(indices.size());
|
|
||||||
|
|
||||||
for (QModelIndex index : indices)
|
|
||||||
rows.push_back(index.row());
|
|
||||||
|
|
||||||
std::sort(rows.begin(), rows.end());
|
|
||||||
|
|
||||||
rows.erase(std::unique(rows.begin(), rows.end()), rows.end());
|
|
||||||
|
|
||||||
std::reverse(rows.begin(), rows.end());
|
|
||||||
|
|
||||||
for (int row : rows)
|
|
||||||
m_model->removeRow(row);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListModelEditorDialog::removeColumns()
|
void ListModelEditorDialog::removeColumns()
|
||||||
{
|
{
|
||||||
const QList<QModelIndex> indices = m_tableView->selectionModel()->selectedColumns();
|
m_model->removeColumns(m_tableView->selectionModel()->selectedColumns());
|
||||||
std::vector<int> columns;
|
|
||||||
columns.reserve(indices.size());
|
|
||||||
|
|
||||||
for (QModelIndex index : indices)
|
|
||||||
columns.push_back(index.column());
|
|
||||||
|
|
||||||
std::sort(columns.begin(), columns.end());
|
|
||||||
|
|
||||||
columns.erase(std::unique(columns.begin(), columns.end()), columns.end());
|
|
||||||
|
|
||||||
std::reverse(columns.begin(), columns.end());
|
|
||||||
|
|
||||||
for (int row : columns)
|
|
||||||
m_model->removeColumn(row);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListModelEditorDialog::changeHeader(int column)
|
void ListModelEditorDialog::changeHeader(int column)
|
||||||
@@ -162,4 +141,16 @@ void ListModelEditorDialog::changeHeader(int column)
|
|||||||
m_model->renameColumn(column, newPropertyName);
|
m_model->renameColumn(column, newPropertyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ListModelEditorDialog::moveRowsDown()
|
||||||
|
{
|
||||||
|
QItemSelection selection = m_model->moveRowsDown(m_tableView->selectionModel()->selectedRows());
|
||||||
|
m_tableView->selectionModel()->select(selection, QItemSelectionModel::Select);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListModelEditorDialog::moveRowsUp()
|
||||||
|
{
|
||||||
|
QItemSelection selection = m_model->moveRowsUp(m_tableView->selectionModel()->selectedRows());
|
||||||
|
m_tableView->selectionModel()->select(selection, QItemSelectionModel::Select);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -59,6 +59,8 @@ private:
|
|||||||
void removeRows();
|
void removeRows();
|
||||||
void removeColumns();
|
void removeColumns();
|
||||||
void changeHeader(int column);
|
void changeHeader(int column);
|
||||||
|
void moveRowsDown();
|
||||||
|
void moveRowsUp();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ListModelEditorModel *m_model{};
|
ListModelEditorModel *m_model{};
|
||||||
@@ -66,6 +68,8 @@ private:
|
|||||||
QAction *m_removeRowsAction{};
|
QAction *m_removeRowsAction{};
|
||||||
QAction *m_addColumnAction{};
|
QAction *m_addColumnAction{};
|
||||||
QAction *m_removeColumnsAction{};
|
QAction *m_removeColumnsAction{};
|
||||||
|
QAction *m_moveUpAction{};
|
||||||
|
QAction *m_moveDownAction{};
|
||||||
QTableView *m_tableView{};
|
QTableView *m_tableView{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -26,7 +26,9 @@
|
|||||||
#include "listmodeleditormodel.h"
|
#include "listmodeleditormodel.h"
|
||||||
|
|
||||||
#include <abstractview.h>
|
#include <abstractview.h>
|
||||||
|
#include <bindingproperty.h>
|
||||||
#include <nodelistproperty.h>
|
#include <nodelistproperty.h>
|
||||||
|
#include <nodeproperty.h>
|
||||||
#include <variantproperty.h>
|
#include <variantproperty.h>
|
||||||
|
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
@@ -49,6 +51,17 @@ public:
|
|||||||
|
|
||||||
QVariant maybeConvertToNumber(const QVariant &value)
|
QVariant maybeConvertToNumber(const QVariant &value)
|
||||||
{
|
{
|
||||||
|
if (value.type() == QVariant::Bool)
|
||||||
|
return value;
|
||||||
|
|
||||||
|
if (value.type() == QVariant::String) {
|
||||||
|
const QString text = value.toString();
|
||||||
|
if (text == "true")
|
||||||
|
return QVariant(true);
|
||||||
|
if (text == "false")
|
||||||
|
return QVariant(false);
|
||||||
|
}
|
||||||
|
|
||||||
bool canConvert = false;
|
bool canConvert = false;
|
||||||
double convertedValue = value.toDouble(&canConvert);
|
double convertedValue = value.toDouble(&canConvert);
|
||||||
if (canConvert) {
|
if (canConvert) {
|
||||||
@@ -185,6 +198,22 @@ void renameProperties(const QStandardItemModel *model,
|
|||||||
static_cast<ListModelItem *>(model->item(rowIndex, columnIndex))->renameProperty(newPropertyName);
|
static_cast<ListModelItem *>(model->item(rowIndex, columnIndex))->renameProperty(newPropertyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModelNode listModelNode(const ModelNode &listViewNode,
|
||||||
|
const std::function<ModelNode()> &createModelCallback)
|
||||||
|
{
|
||||||
|
if (listViewNode.hasProperty("model")) {
|
||||||
|
if (listViewNode.hasBindingProperty("model"))
|
||||||
|
return listViewNode.bindingProperty("model").resolveToModelNode();
|
||||||
|
else if (listViewNode.hasNodeProperty("model"))
|
||||||
|
return listViewNode.nodeProperty("model").modelNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
ModelNode newModel = createModelCallback();
|
||||||
|
listViewNode.nodeProperty("model").reparentHere(newModel);
|
||||||
|
|
||||||
|
return newModel;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void ListModelEditorModel::populateModel()
|
void ListModelEditorModel::populateModel()
|
||||||
@@ -214,9 +243,20 @@ void ListModelEditorModel::appendItems(const ModelNode &listElementNode)
|
|||||||
appendRow(row);
|
appendRow(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ListModelEditorModel::setListModel(ModelNode node)
|
||||||
|
{
|
||||||
|
m_listModelNode = node;
|
||||||
|
populateModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListModelEditorModel::setListView(ModelNode listView)
|
||||||
|
{
|
||||||
|
setListModel(listModelNode(listView, m_createModelCallback));
|
||||||
|
}
|
||||||
|
|
||||||
void ListModelEditorModel::addRow()
|
void ListModelEditorModel::addRow()
|
||||||
{
|
{
|
||||||
auto newElement = m_listModelNode.view()->createModelNode("QtQml.Models.ListElement", 2, 15);
|
auto newElement = m_createElementCallback();
|
||||||
m_listModelNode.defaultNodeListProperty().reparentHere(newElement);
|
m_listModelNode.defaultNodeListProperty().reparentHere(newElement);
|
||||||
|
|
||||||
appendItems(newElement);
|
appendItems(newElement);
|
||||||
@@ -260,6 +300,26 @@ void ListModelEditorModel::removeColumn(int column)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ListModelEditorModel::removeColumns(const QList<QModelIndex> &indices)
|
||||||
|
{
|
||||||
|
std::vector<int> columns = filterColumns(indices);
|
||||||
|
|
||||||
|
std::reverse(columns.begin(), columns.end());
|
||||||
|
|
||||||
|
for (int column : columns)
|
||||||
|
removeColumn(column);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListModelEditorModel::removeRows(const QList<QModelIndex> &indices)
|
||||||
|
{
|
||||||
|
std::vector<int> rows = filterRows(indices);
|
||||||
|
|
||||||
|
std::reverse(rows.begin(), rows.end());
|
||||||
|
|
||||||
|
for (int row : rows)
|
||||||
|
removeRow(row);
|
||||||
|
}
|
||||||
|
|
||||||
void ListModelEditorModel::removeRow(int row)
|
void ListModelEditorModel::removeRow(int row)
|
||||||
{
|
{
|
||||||
QList<QStandardItem *> rowItems = QStandardItemModel::takeRow(row);
|
QList<QStandardItem *> rowItems = QStandardItemModel::takeRow(row);
|
||||||
@@ -299,4 +359,74 @@ void ListModelEditorModel::renameColumn(int oldColumn, const QString &newColumnN
|
|||||||
setHorizontalHeaderLabels(convertToStringList(m_propertyNames));
|
setHorizontalHeaderLabels(convertToStringList(m_propertyNames));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QItemSelection ListModelEditorModel::moveRowsUp(const QList<QModelIndex> &indices)
|
||||||
|
{
|
||||||
|
std::vector<int> rows = filterRows(indices);
|
||||||
|
|
||||||
|
if (rows.empty() || rows.front() < 1)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
auto nodeListProperty = m_listModelNode.defaultNodeListProperty();
|
||||||
|
|
||||||
|
for (int row : rows) {
|
||||||
|
insertRow(row - 1, takeRow(row));
|
||||||
|
nodeListProperty.slide(row, row - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {index(rows.front() - 1, 0), index(rows.back() - 1, columnCount() - 1)};
|
||||||
|
}
|
||||||
|
|
||||||
|
QItemSelection ListModelEditorModel::moveRowsDown(const QList<QModelIndex> &indices)
|
||||||
|
{
|
||||||
|
std::vector<int> rows = filterRows(indices);
|
||||||
|
|
||||||
|
if (rows.empty() || rows.back() >= (rowCount() - 1))
|
||||||
|
return {};
|
||||||
|
|
||||||
|
auto nodeListProperty = m_listModelNode.defaultNodeListProperty();
|
||||||
|
|
||||||
|
std::reverse(rows.begin(), rows.end());
|
||||||
|
|
||||||
|
for (int row : rows) {
|
||||||
|
insertRow(row + 1, takeRow(row));
|
||||||
|
nodeListProperty.slide(row, row + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {index(rows.front() + 1, 0), index(rows.back() + 1, columnCount() - 1)};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int> ListModelEditorModel::filterColumns(const QList<QModelIndex> &indices)
|
||||||
|
{
|
||||||
|
std::vector<int> columns;
|
||||||
|
columns.reserve(indices.size());
|
||||||
|
|
||||||
|
for (QModelIndex index : indices) {
|
||||||
|
if (index.column() >= 0)
|
||||||
|
columns.push_back(index.column());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(columns.begin(), columns.end());
|
||||||
|
|
||||||
|
columns.erase(std::unique(columns.begin(), columns.end()), columns.end());
|
||||||
|
|
||||||
|
return columns;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int> ListModelEditorModel::filterRows(const QList<QModelIndex> &indices)
|
||||||
|
{
|
||||||
|
std::vector<int> rows;
|
||||||
|
rows.reserve(indices.size());
|
||||||
|
|
||||||
|
for (QModelIndex index : indices) {
|
||||||
|
if (index.row() >= 0)
|
||||||
|
rows.push_back(index.row());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(rows.begin(), rows.end());
|
||||||
|
|
||||||
|
rows.erase(std::unique(rows.begin(), rows.end()), rows.end());
|
||||||
|
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -27,19 +27,26 @@
|
|||||||
|
|
||||||
#include <modelnode.h>
|
#include <modelnode.h>
|
||||||
|
|
||||||
|
#include <QItemSelection>
|
||||||
#include <QStandardItemModel>
|
#include <QStandardItemModel>
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
class ListModelEditorModel : public QStandardItemModel
|
class ListModelEditorModel : public QStandardItemModel
|
||||||
{
|
{
|
||||||
|
using QStandardItemModel::removeColumns;
|
||||||
|
using QStandardItemModel::removeRows;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void setListModel(ModelNode node)
|
ListModelEditorModel(std::function<ModelNode()> createModelCallback,
|
||||||
{
|
std::function<ModelNode()> createElementCallback)
|
||||||
m_listModelNode = node;
|
: m_createModelCallback(std::move(createModelCallback))
|
||||||
populateModel();
|
, m_createElementCallback(std::move(createElementCallback))
|
||||||
}
|
{}
|
||||||
|
|
||||||
|
void setListModel(ModelNode node);
|
||||||
|
|
||||||
|
void setListView(ModelNode listView);
|
||||||
|
|
||||||
void addRow();
|
void addRow();
|
||||||
void addColumn(const QString &columnName);
|
void addColumn(const QString &columnName);
|
||||||
@@ -48,11 +55,18 @@ public:
|
|||||||
|
|
||||||
bool setValue(int row, int column, QVariant value, Qt::ItemDataRole role = Qt::EditRole);
|
bool setValue(int row, int column, QVariant value, Qt::ItemDataRole role = Qt::EditRole);
|
||||||
|
|
||||||
void removeColumn(int column);
|
void removeColumns(const QList<QModelIndex> &indices);
|
||||||
void removeRow(int row);
|
void removeRows(const QList<QModelIndex> &indices);
|
||||||
void renameColumn(int column, const QString &newColumnName);
|
void renameColumn(int column, const QString &newColumnName);
|
||||||
|
QItemSelection moveRowsUp(const QList<QModelIndex> &indices);
|
||||||
|
QItemSelection moveRowsDown(const QList<QModelIndex> &indices);
|
||||||
|
|
||||||
|
static std::vector<int> filterColumns(const QList<QModelIndex> &indices);
|
||||||
|
static std::vector<int> filterRows(const QList<QModelIndex> &indices);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void removeRow(int row);
|
||||||
|
void removeColumn(int column);
|
||||||
void populateModel();
|
void populateModel();
|
||||||
void createItems(const QList<ModelNode> &listElementNodes);
|
void createItems(const QList<ModelNode> &listElementNodes);
|
||||||
void appendItems(const ModelNode &listElementNode);
|
void appendItems(const ModelNode &listElementNode);
|
||||||
@@ -60,6 +74,8 @@ private:
|
|||||||
private:
|
private:
|
||||||
ModelNode m_listModelNode;
|
ModelNode m_listModelNode;
|
||||||
QList<QmlDesigner::PropertyName> m_propertyNames;
|
QList<QmlDesigner::PropertyName> m_propertyNames;
|
||||||
|
std::function<ModelNode()> m_createModelCallback;
|
||||||
|
std::function<ModelNode()> m_createElementCallback;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -40,6 +40,7 @@
|
|||||||
#include "aligndistribute.h"
|
#include "aligndistribute.h"
|
||||||
#include "propertyeditorcontextobject.h"
|
#include "propertyeditorcontextobject.h"
|
||||||
#include "tooltip.h"
|
#include "tooltip.h"
|
||||||
|
#include "richtexteditor/richtexteditorproxy.h"
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
@@ -69,6 +70,7 @@ void Quick2PropertyEditorView::registerQmlTypes()
|
|||||||
AlignDistribute::registerDeclarativeType();
|
AlignDistribute::registerDeclarativeType();
|
||||||
Tooltip::registerDeclarativeType();
|
Tooltip::registerDeclarativeType();
|
||||||
EasingCurveEditor::registerDeclarativeType();
|
EasingCurveEditor::registerDeclarativeType();
|
||||||
|
RichTextEditorProxy::registerDeclarativeType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,7 +1,9 @@
|
|||||||
HEADERS += $$PWD/richtexteditor.h
|
HEADERS += $$PWD/richtexteditor.h \
|
||||||
|
$$PWD/richtexteditorproxy.h
|
||||||
HEADERS += $$PWD/hyperlinkdialog.h
|
HEADERS += $$PWD/hyperlinkdialog.h
|
||||||
|
|
||||||
SOURCES += $$PWD/richtexteditor.cpp
|
SOURCES += $$PWD/richtexteditor.cpp \
|
||||||
|
$$PWD/richtexteditorproxy.cpp
|
||||||
SOURCES += $$PWD/hyperlinkdialog.cpp
|
SOURCES += $$PWD/hyperlinkdialog.cpp
|
||||||
|
|
||||||
FORMS += $$PWD/richtexteditor.ui
|
FORMS += $$PWD/richtexteditor.ui
|
||||||
|
@@ -0,0 +1,88 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "richtexteditorproxy.h"
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QDialogButtonBox>
|
||||||
|
#include <QGridLayout>
|
||||||
|
|
||||||
|
#include "richtexteditor.h"
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
RichTextEditorProxy::RichTextEditorProxy(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_dialog(new QDialog{})
|
||||||
|
, m_widget(new RichTextEditor{})
|
||||||
|
{
|
||||||
|
QGridLayout *layout = new QGridLayout{};
|
||||||
|
|
||||||
|
layout->addWidget(m_widget);
|
||||||
|
QDialogButtonBox *standardButtons = new QDialogButtonBox{QDialogButtonBox::Ok
|
||||||
|
| QDialogButtonBox::Cancel};
|
||||||
|
|
||||||
|
connect(standardButtons, &QDialogButtonBox::accepted, m_dialog, &QDialog::accept);
|
||||||
|
connect(standardButtons, &QDialogButtonBox::rejected, m_dialog, &QDialog::reject);
|
||||||
|
|
||||||
|
layout->addWidget(standardButtons);
|
||||||
|
|
||||||
|
m_dialog->setLayout(layout);
|
||||||
|
|
||||||
|
connect(m_dialog, &QDialog::accepted, [this]() { emit accepted(); });
|
||||||
|
connect(m_dialog, &QDialog::rejected, [this]() { emit rejected(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
RichTextEditorProxy::~RichTextEditorProxy()
|
||||||
|
{
|
||||||
|
delete m_dialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RichTextEditorProxy::registerDeclarativeType()
|
||||||
|
{
|
||||||
|
qmlRegisterType<RichTextEditorProxy>("HelperWidgets", 2, 0, "RichTextEditor");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RichTextEditorProxy::showWidget()
|
||||||
|
{
|
||||||
|
m_dialog->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RichTextEditorProxy::hideWidget()
|
||||||
|
{
|
||||||
|
m_dialog->hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString RichTextEditorProxy::richText() const
|
||||||
|
{
|
||||||
|
return m_widget->richText();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RichTextEditorProxy::setRichText(const QString &text)
|
||||||
|
{
|
||||||
|
m_widget->setRichText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -0,0 +1,65 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 <QObject>
|
||||||
|
#include <QQuickItem>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QDialog;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class RichTextEditor;
|
||||||
|
|
||||||
|
class RichTextEditorProxy : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(QString richText READ richText WRITE setRichText)
|
||||||
|
public:
|
||||||
|
explicit RichTextEditorProxy(QObject *parent = nullptr);
|
||||||
|
~RichTextEditorProxy();
|
||||||
|
|
||||||
|
static void registerDeclarativeType();
|
||||||
|
|
||||||
|
Q_INVOKABLE void showWidget();
|
||||||
|
Q_INVOKABLE void hideWidget();
|
||||||
|
|
||||||
|
QString richText() const;
|
||||||
|
void setRichText(const QString &text);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void accepted();
|
||||||
|
void rejected();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QDialog *m_dialog;
|
||||||
|
RichTextEditor *m_widget;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -103,7 +103,7 @@ static QAction *createAction(const Core::Id &id,
|
|||||||
TimelineToolBar::TimelineToolBar(QWidget *parent)
|
TimelineToolBar::TimelineToolBar(QWidget *parent)
|
||||||
: QToolBar(parent)
|
: QToolBar(parent)
|
||||||
, m_grp()
|
, m_grp()
|
||||||
, m_dialog(new AnimationCurveDialog(Core::ICore::dialogParent()))
|
, m_dialog(new AnimationCurveDialog(this))
|
||||||
, m_curveModel(new AnimationCurveEditorModel(0., 500.))
|
, m_curveModel(new AnimationCurveEditorModel(0., 500.))
|
||||||
{
|
{
|
||||||
m_dialog->setModel(m_curveModel);
|
m_dialog->setModel(m_curveModel);
|
||||||
|
@@ -62,6 +62,7 @@ class RemovePropertiesCommand;
|
|||||||
class CompleteComponentCommand;
|
class CompleteComponentCommand;
|
||||||
class InformationContainer;
|
class InformationContainer;
|
||||||
class TokenCommand;
|
class TokenCommand;
|
||||||
|
class ConnectionManagerInterface;
|
||||||
|
|
||||||
class QMLDESIGNERCORE_EXPORT NodeInstanceView : public AbstractView, public NodeInstanceClientInterface
|
class QMLDESIGNERCORE_EXPORT NodeInstanceView : public AbstractView, public NodeInstanceClientInterface
|
||||||
{
|
{
|
||||||
@@ -72,7 +73,7 @@ class QMLDESIGNERCORE_EXPORT NodeInstanceView : public AbstractView, public Node
|
|||||||
public:
|
public:
|
||||||
using Pointer = QWeakPointer<NodeInstanceView>;
|
using Pointer = QWeakPointer<NodeInstanceView>;
|
||||||
|
|
||||||
explicit NodeInstanceView(QObject *parent = nullptr, NodeInstanceServerInterface::RunModus runModus = NodeInstanceServerInterface::NormalModus);
|
explicit NodeInstanceView(ConnectionManagerInterface &connectionManager);
|
||||||
~NodeInstanceView() override;
|
~NodeInstanceView() override;
|
||||||
|
|
||||||
void modelAttached(Model *model) override;
|
void modelAttached(Model *model) override;
|
||||||
@@ -94,7 +95,7 @@ public:
|
|||||||
void auxiliaryDataChanged(const ModelNode &node, const PropertyName &name, const QVariant &data) override;
|
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 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 nodeSourceChanged(const ModelNode &modelNode, const QString &newNodeSource) override;
|
||||||
|
void capturedData(const CapturedDataCommand &capturedData) override;
|
||||||
void currentStateChanged(const ModelNode &node) override;
|
void currentStateChanged(const ModelNode &node) override;
|
||||||
|
|
||||||
QList<NodeInstance> instances() const;
|
QList<NodeInstance> instances() const;
|
||||||
@@ -142,6 +143,7 @@ protected:
|
|||||||
void timerEvent(QTimerEvent *event) override;
|
void timerEvent(QTimerEvent *event) override;
|
||||||
|
|
||||||
private: // functions
|
private: // functions
|
||||||
|
std::unique_ptr<NodeInstanceServerProxy> createNodeInstanceServerProxy();
|
||||||
void activateState(const NodeInstance &instance);
|
void activateState(const NodeInstance &instance);
|
||||||
void activateBaseState();
|
void activateBaseState();
|
||||||
|
|
||||||
@@ -161,9 +163,8 @@ private: // functions
|
|||||||
void setStateInstance(const NodeInstance &stateInstance);
|
void setStateInstance(const NodeInstance &stateInstance);
|
||||||
void clearStateInstance();
|
void clearStateInstance();
|
||||||
|
|
||||||
NodeInstanceServerInterface *nodeInstanceServer() const;
|
QMultiHash<ModelNode, InformationName> informationChanged(
|
||||||
QMultiHash<ModelNode, InformationName> informationChanged(const QVector<InformationContainer> &containerVector);
|
const QVector<InformationContainer> &containerVector);
|
||||||
|
|
||||||
|
|
||||||
CreateSceneCommand createCreateSceneCommand();
|
CreateSceneCommand createCreateSceneCommand();
|
||||||
ClearSceneCommand createClearSceneCommand() const;
|
ClearSceneCommand createClearSceneCommand() const;
|
||||||
@@ -196,16 +197,15 @@ private: // functions
|
|||||||
// puppet to creator command handlers
|
// puppet to creator command handlers
|
||||||
void handlePuppetKeyPress(int key, Qt::KeyboardModifiers modifiers);
|
void handlePuppetKeyPress(int key, Qt::KeyboardModifiers modifiers);
|
||||||
|
|
||||||
|
private:
|
||||||
NodeInstance m_rootNodeInstance;
|
NodeInstance m_rootNodeInstance;
|
||||||
NodeInstance m_activeStateInstance;
|
NodeInstance m_activeStateInstance;
|
||||||
|
|
||||||
QHash<ModelNode, NodeInstance> m_nodeInstanceHash;
|
QHash<ModelNode, NodeInstance> m_nodeInstanceHash;
|
||||||
QHash<ModelNode, QImage> m_statePreviewImage;
|
QHash<ModelNode, QImage> m_statePreviewImage;
|
||||||
|
ConnectionManagerInterface &m_connectionManager;
|
||||||
QPointer<NodeInstanceServerProxy> m_nodeInstanceServer;
|
std::unique_ptr<NodeInstanceServerProxy> m_nodeInstanceServer;
|
||||||
QImage m_baseStatePreviewImage;
|
QImage m_baseStatePreviewImage;
|
||||||
QElapsedTimer m_lastCrashTime;
|
QElapsedTimer m_lastCrashTime;
|
||||||
NodeInstanceServerInterface::RunModus m_runModus;
|
|
||||||
ProjectExplorer::Target *m_currentTarget = nullptr;
|
ProjectExplorer::Target *m_currentTarget = nullptr;
|
||||||
int m_restartProcessTimerId;
|
int m_restartProcessTimerId;
|
||||||
RewriterTransaction m_puppetTransaction;
|
RewriterTransaction m_puppetTransaction;
|
||||||
|
@@ -75,6 +75,7 @@ public:
|
|||||||
bool propertyIsListProperty(const PropertyName &propertyName) const;
|
bool propertyIsListProperty(const PropertyName &propertyName) const;
|
||||||
bool propertyIsEnumType(const PropertyName &propertyName) const;
|
bool propertyIsEnumType(const PropertyName &propertyName) const;
|
||||||
bool propertyIsPrivate(const PropertyName &propertyName) const;
|
bool propertyIsPrivate(const PropertyName &propertyName) const;
|
||||||
|
bool propertyIsPointer(const PropertyName &propertyName) const;
|
||||||
QString propertyEnumScope(const PropertyName &propertyName) const;
|
QString propertyEnumScope(const PropertyName &propertyName) const;
|
||||||
QStringList propertyKeysForEnum(const PropertyName &propertyName) const;
|
QStringList propertyKeysForEnum(const PropertyName &propertyName) const;
|
||||||
QVariant propertyCastedValue(const PropertyName &propertyName, const QVariant &value) const;
|
QVariant propertyCastedValue(const PropertyName &propertyName, const QVariant &value) const;
|
||||||
@@ -99,6 +100,7 @@ public:
|
|||||||
bool isSubclassOf(const TypeName &type, int majorVersion = -1, int minorVersion = -1) const;
|
bool isSubclassOf(const TypeName &type, int majorVersion = -1, int minorVersion = -1) const;
|
||||||
|
|
||||||
bool isGraphicalItem() const;
|
bool isGraphicalItem() const;
|
||||||
|
bool isQmlItem() const;
|
||||||
bool isLayoutable() const;
|
bool isLayoutable() const;
|
||||||
bool isView() const;
|
bool isView() const;
|
||||||
bool isTabView() const;
|
bool isTabView() const;
|
||||||
|
@@ -122,7 +122,7 @@ private: // functions
|
|||||||
const QList<QPointer<AbstractView> > standardViews() const;
|
const QList<QPointer<AbstractView> > standardViews() const;
|
||||||
|
|
||||||
private: // variables
|
private: // variables
|
||||||
ViewManagerData *d;
|
std::unique_ptr<ViewManagerData> d;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -0,0 +1,127 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
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
|
||||||
|
|
@@ -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
|
@@ -0,0 +1,65 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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>
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
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
|
@@ -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
|
||||||
|
|
@@ -0,0 +1,178 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 <QTimer>
|
||||||
|
#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
|
@@ -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
|
@@ -0,0 +1,55 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
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
|
@@ -0,0 +1,81 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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>
|
||||||
|
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
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
|
@@ -1,14 +1,25 @@
|
|||||||
INCLUDEPATH += $$PWD/
|
INCLUDEPATH += $$PWD/
|
||||||
|
|
||||||
HEADERS += $$PWD/../include/nodeinstance.h
|
HEADERS += $$PWD/../include/nodeinstance.h \
|
||||||
HEADERS += $$PWD/nodeinstanceserverproxy.h
|
$$PWD/baseconnectionmanager.h \
|
||||||
HEADERS += $$PWD/puppetcreator.h
|
$$PWD/capturingconnectionmanager.h \
|
||||||
HEADERS += $$PWD/puppetbuildprogressdialog.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/nodeinstanceserverproxy.cpp \
|
||||||
SOURCES += $$PWD/nodeinstance.cpp
|
$$PWD/baseconnectionmanager.cpp \
|
||||||
SOURCES += $$PWD/nodeinstanceview.cpp
|
$$PWD/capturingconnectionmanager.cpp \
|
||||||
SOURCES += $$PWD/puppetcreator.cpp
|
$$PWD/connectionmanager.cpp \
|
||||||
SOURCES += $$PWD/puppetbuildprogressdialog.cpp
|
$$PWD/connectionmanagerinterface.cpp \
|
||||||
|
$$PWD/interactiveconnectionmanager.cpp \
|
||||||
|
$$PWD/nodeinstance.cpp \
|
||||||
|
$$PWD/nodeinstanceview.cpp \
|
||||||
|
$$PWD/puppetcreator.cpp \
|
||||||
|
$$PWD/puppetbuildprogressdialog.cpp
|
||||||
|
|
||||||
FORMS += $$PWD/puppetbuildprogressdialog.ui
|
FORMS += $$PWD/puppetbuildprogressdialog.ui
|
||||||
|
@@ -0,0 +1,110 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
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
|
@@ -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
|
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "nodeinstanceserverproxy.h"
|
#include "nodeinstanceserverproxy.h"
|
||||||
|
|
||||||
|
#include "connectionmanagerinterface.h"
|
||||||
#include "puppetcreator.h"
|
#include "puppetcreator.h"
|
||||||
|
|
||||||
#include <changeauxiliarycommand.h>
|
#include <changeauxiliarycommand.h>
|
||||||
@@ -60,218 +61,55 @@
|
|||||||
#include <valueschangedcommand.h>
|
#include <valueschangedcommand.h>
|
||||||
#include <view3dactioncommand.h>
|
#include <view3dactioncommand.h>
|
||||||
|
|
||||||
#include <nodeinstanceview.h>
|
|
||||||
#include <import.h>
|
#include <import.h>
|
||||||
|
#include <nodeinstanceview.h>
|
||||||
#include <rewriterview.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/editormanager/editormanager.h>
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
#include <projectexplorer/kit.h>
|
#include <projectexplorer/kit.h>
|
||||||
#include <qtsupport/qtkitinformation.h>
|
#include <utils/hostosinfo.h>
|
||||||
#include <qtsupport/baseqtversion.h>
|
#include <qtsupport/baseqtversion.h>
|
||||||
|
#include <qtsupport/qtkitinformation.h>
|
||||||
#include <qtsupport/qtsupportconstants.h>
|
#include <qtsupport/qtsupportconstants.h>
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFileInfo>
|
||||||
#include <QLocalServer>
|
#include <QLocalServer>
|
||||||
#include <QLocalSocket>
|
#include <QLocalSocket>
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
#include <QProcess>
|
|
||||||
#include <QCoreApplication>
|
|
||||||
#include <QUuid>
|
|
||||||
#include <QFileInfo>
|
|
||||||
#include <QDir>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QTextStream>
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QTextStream>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QUuid>
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
static Q_LOGGING_CATEGORY(instanceViewBenchmark, "qtc.nodeinstances.init", QtWarningMsg)
|
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
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeInstanceServerProxy::NodeInstanceServerProxy(NodeInstanceView *nodeInstanceView,
|
NodeInstanceServerProxy::NodeInstanceServerProxy(NodeInstanceView *nodeInstanceView,
|
||||||
RunModus runModus,
|
ProjectExplorer::Target *target,
|
||||||
ProjectExplorer::Target *target)
|
ConnectionManagerInterface &connectionManager)
|
||||||
: NodeInstanceServerInterface(nodeInstanceView),
|
: m_nodeInstanceView(nodeInstanceView)
|
||||||
m_localServer(new QLocalServer(this)),
|
, m_connectionManager{connectionManager}
|
||||||
m_nodeInstanceView(nodeInstanceView),
|
|
||||||
m_runModus(runModus)
|
|
||||||
{
|
{
|
||||||
if (instanceViewBenchmark().isInfoEnabled())
|
if (instanceViewBenchmark().isInfoEnabled())
|
||||||
m_benchmarkTimer.start();
|
m_benchmarkTimer.start();
|
||||||
|
|
||||||
QString socketToken(QUuid::createUuid().toString());
|
m_connectionManager.setUp(this, qrcMappingString(), target);
|
||||||
m_localServer->listen(socketToken);
|
|
||||||
m_localServer->setMaxPendingConnections(3);
|
|
||||||
|
|
||||||
PuppetCreator puppetCreator(target, nodeInstanceView->model());
|
qCInfo(instanceViewBenchmark) << "puppets setup:" << m_benchmarkTimer.elapsed();
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeInstanceServerProxy::~NodeInstanceServerProxy()
|
NodeInstanceServerProxy::~NodeInstanceServerProxy()
|
||||||
{
|
{
|
||||||
m_destructing = true;
|
m_connectionManager.shutDown();
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeInstanceServerProxy::dispatchCommand(const QVariant &command, PuppetStreamType puppetStreamType)
|
void NodeInstanceServerProxy::dispatchCommand(const QVariant &command)
|
||||||
{
|
{
|
||||||
static const int informationChangedCommandType = QMetaType::type("InformationChangedCommand");
|
static const int informationChangedCommandType = QMetaType::type("InformationChangedCommand");
|
||||||
static const int valuesChangedCommandType = QMetaType::type("ValuesChangedCommand");
|
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 childrenChangedCommandType = QMetaType::type("ChildrenChangedCommand");
|
||||||
static const int statePreviewImageChangedCommandType = QMetaType::type("StatePreviewImageChangedCommand");
|
static const int statePreviewImageChangedCommandType = QMetaType::type("StatePreviewImageChangedCommand");
|
||||||
static const int componentCompletedCommandType = QMetaType::type("ComponentCompletedCommand");
|
static const int componentCompletedCommandType = QMetaType::type("ComponentCompletedCommand");
|
||||||
static const int synchronizeCommandType = QMetaType::type("SynchronizeCommand");
|
|
||||||
static const int tokenCommandType = QMetaType::type("TokenCommand");
|
static const int tokenCommandType = QMetaType::type("TokenCommand");
|
||||||
static const int debugOutputCommandType = QMetaType::type("DebugOutputCommand");
|
static const int debugOutputCommandType = QMetaType::type("DebugOutputCommand");
|
||||||
static const int puppetAliveCommandType = QMetaType::type("PuppetAliveCommand");
|
|
||||||
static const int changeSelectionCommandType = QMetaType::type("ChangeSelectionCommand");
|
static const int changeSelectionCommandType = QMetaType::type("ChangeSelectionCommand");
|
||||||
static const int puppetToCreatorCommand = QMetaType::type("PuppetToCreatorCommand");
|
static const int puppetToCreatorCommandType = QMetaType::type("PuppetToCreatorCommand");
|
||||||
|
|
||||||
if (m_destructing)
|
|
||||||
return;
|
|
||||||
|
|
||||||
qCInfo(instanceViewBenchmark) << "dispatching command" << command.userType() << command.typeName();
|
qCInfo(instanceViewBenchmark) << "dispatching command" << command.userType() << command.typeName();
|
||||||
if (command.userType() == informationChangedCommandType) {
|
if (command.userType() == informationChangedCommandType) {
|
||||||
@@ -311,13 +144,8 @@ void NodeInstanceServerProxy::dispatchCommand(const QVariant &command, PuppetStr
|
|||||||
nodeInstanceClient()->debugOutput(command.value<DebugOutputCommand>());
|
nodeInstanceClient()->debugOutput(command.value<DebugOutputCommand>());
|
||||||
} else if (command.userType() == changeSelectionCommandType) {
|
} else if (command.userType() == changeSelectionCommandType) {
|
||||||
nodeInstanceClient()->selectionChanged(command.value<ChangeSelectionCommand>());
|
nodeInstanceClient()->selectionChanged(command.value<ChangeSelectionCommand>());
|
||||||
} else if (command.userType() == puppetToCreatorCommand) {
|
} else if (command.userType() == puppetToCreatorCommandType) {
|
||||||
nodeInstanceClient()->handlePuppetToCreatorCommand(command.value<PuppetToCreatorCommand>());
|
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 {
|
} else {
|
||||||
Q_ASSERT(false);
|
Q_ASSERT(false);
|
||||||
}
|
}
|
||||||
@@ -327,33 +155,13 @@ void NodeInstanceServerProxy::dispatchCommand(const QVariant &command, PuppetStr
|
|||||||
|
|
||||||
NodeInstanceClientInterface *NodeInstanceServerProxy::nodeInstanceClient() const
|
NodeInstanceClientInterface *NodeInstanceServerProxy::nodeInstanceClient() const
|
||||||
{
|
{
|
||||||
return m_nodeInstanceView.data();
|
return m_nodeInstanceView;
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString NodeInstanceServerProxy::qrcMappingString() const
|
QString NodeInstanceServerProxy::qrcMappingString() const
|
||||||
{
|
{
|
||||||
if (m_nodeInstanceView && m_nodeInstanceView.data()->model()) {
|
if (m_nodeInstanceView && m_nodeInstanceView->model()) {
|
||||||
RewriterView *rewriterView = m_nodeInstanceView.data()->model()->rewriterView();
|
RewriterView *rewriterView = m_nodeInstanceView->model()->rewriterView();
|
||||||
if (rewriterView) {
|
if (rewriterView) {
|
||||||
QString mappingString;
|
QString mappingString;
|
||||||
|
|
||||||
@@ -374,265 +182,9 @@ QString NodeInstanceServerProxy::qrcMappingString() const
|
|||||||
return QString();
|
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)
|
void NodeInstanceServerProxy::writeCommand(const QVariant &command)
|
||||||
{
|
{
|
||||||
writeCommandToIODecive(command, m_firstSocket.data(), m_writeCommandCounter);
|
m_connectionManager.writeCommand(command);
|
||||||
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";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeInstanceServerProxy::createInstances(const CreateInstancesCommand &command)
|
void NodeInstanceServerProxy::createInstances(const CreateInstancesCommand &command)
|
||||||
|
@@ -48,21 +48,17 @@ namespace QmlDesigner {
|
|||||||
class NodeInstanceClientInterface;
|
class NodeInstanceClientInterface;
|
||||||
class NodeInstanceView;
|
class NodeInstanceView;
|
||||||
class NodeInstanceClientProxy;
|
class NodeInstanceClientProxy;
|
||||||
|
class ConnectionManagerInterface;
|
||||||
|
|
||||||
class NodeInstanceServerProxy : public NodeInstanceServerInterface
|
class NodeInstanceServerProxy : public NodeInstanceServerInterface
|
||||||
{
|
{
|
||||||
|
friend class BaseConnectionManager;
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum PuppetStreamType {
|
|
||||||
FirstPuppetStream,
|
|
||||||
SecondPuppetStream,
|
|
||||||
ThirdPuppetStream,
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit NodeInstanceServerProxy(NodeInstanceView *nodeInstanceView,
|
explicit NodeInstanceServerProxy(NodeInstanceView *nodeInstanceView,
|
||||||
RunModus runModus,
|
ProjectExplorer::Target *target,
|
||||||
ProjectExplorer::Target *target);
|
ConnectionManagerInterface &connectionManager);
|
||||||
~NodeInstanceServerProxy() override;
|
~NodeInstanceServerProxy() override;
|
||||||
void createInstances(const CreateInstancesCommand &command) override;
|
void createInstances(const CreateInstancesCommand &command) override;
|
||||||
void changeFileUrl(const ChangeFileUrlCommand &command) override;
|
void changeFileUrl(const ChangeFileUrlCommand &command) override;
|
||||||
@@ -88,52 +84,22 @@ public:
|
|||||||
void changeLanguage(const ChangeLanguageCommand &command) override;
|
void changeLanguage(const ChangeLanguageCommand &command) override;
|
||||||
void changePreviewImageSize(const ChangePreviewImageSizeCommand &command) override;
|
void changePreviewImageSize(const ChangePreviewImageSizeCommand &command) override;
|
||||||
|
|
||||||
|
NodeInstanceView *nodeInstanceView() const { return m_nodeInstanceView; }
|
||||||
|
|
||||||
|
QString qrcMappingString() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void writeCommand(const QVariant &command);
|
void writeCommand(const QVariant &command);
|
||||||
void dispatchCommand(const QVariant &command, PuppetStreamType puppetStreamType);
|
void dispatchCommand(const QVariant &command);
|
||||||
NodeInstanceClientInterface *nodeInstanceClient() const;
|
NodeInstanceClientInterface *nodeInstanceClient() const;
|
||||||
void puppetAlive(PuppetStreamType puppetStreamType);
|
|
||||||
QString qrcMappingString() const;
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void processCrashed();
|
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:
|
private:
|
||||||
QFile m_captureFileForTest;
|
NodeInstanceView *m_nodeInstanceView{};
|
||||||
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;
|
|
||||||
QElapsedTimer m_benchmarkTimer;
|
QElapsedTimer m_benchmarkTimer;
|
||||||
bool m_destructing = false;
|
ConnectionManagerInterface &m_connectionManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "abstractproperty.h"
|
#include "abstractproperty.h"
|
||||||
#include "bindingproperty.h"
|
#include "bindingproperty.h"
|
||||||
|
#include "captureddatacommand.h"
|
||||||
#include "changeauxiliarycommand.h"
|
#include "changeauxiliarycommand.h"
|
||||||
#include "changebindingscommand.h"
|
#include "changebindingscommand.h"
|
||||||
#include "changefileurlcommand.h"
|
#include "changefileurlcommand.h"
|
||||||
@@ -41,6 +42,7 @@
|
|||||||
#include "clearscenecommand.h"
|
#include "clearscenecommand.h"
|
||||||
#include "completecomponentcommand.h"
|
#include "completecomponentcommand.h"
|
||||||
#include "componentcompletedcommand.h"
|
#include "componentcompletedcommand.h"
|
||||||
|
#include "connectionmanagerinterface.h"
|
||||||
#include "createinstancescommand.h"
|
#include "createinstancescommand.h"
|
||||||
#include "createscenecommand.h"
|
#include "createscenecommand.h"
|
||||||
#include "debugoutputcommand.h"
|
#include "debugoutputcommand.h"
|
||||||
@@ -124,11 +126,10 @@ namespace QmlDesigner {
|
|||||||
|
|
||||||
\sa ~NodeInstanceView, setRenderOffScreen()
|
\sa ~NodeInstanceView, setRenderOffScreen()
|
||||||
*/
|
*/
|
||||||
NodeInstanceView::NodeInstanceView(QObject *parent, NodeInstanceServerInterface::RunModus runModus)
|
NodeInstanceView::NodeInstanceView(ConnectionManagerInterface &connectionManager)
|
||||||
: AbstractView(parent),
|
: m_connectionManager(connectionManager)
|
||||||
m_baseStatePreviewImage(QSize(100, 100), QImage::Format_ARGB32),
|
, m_baseStatePreviewImage(QSize(100, 100), QImage::Format_ARGB32)
|
||||||
m_runModus(runModus),
|
, m_restartProcessTimerId(0)
|
||||||
m_restartProcessTimerId(0)
|
|
||||||
{
|
{
|
||||||
m_baseStatePreviewImage.fill(0xFFFFFF);
|
m_baseStatePreviewImage.fill(0xFFFFFF);
|
||||||
}
|
}
|
||||||
@@ -140,7 +141,6 @@ NodeInstanceView::NodeInstanceView(QObject *parent, NodeInstanceServerInterface:
|
|||||||
NodeInstanceView::~NodeInstanceView()
|
NodeInstanceView::~NodeInstanceView()
|
||||||
{
|
{
|
||||||
removeAllInstanceNodeRelationships();
|
removeAllInstanceNodeRelationships();
|
||||||
delete nodeInstanceServer();
|
|
||||||
m_currentTarget = nullptr;
|
m_currentTarget = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,14 +191,16 @@ bool static parentTakesOverRendering(const ModelNode &modelNode)
|
|||||||
void NodeInstanceView::modelAttached(Model *model)
|
void NodeInstanceView::modelAttached(Model *model)
|
||||||
{
|
{
|
||||||
AbstractView::modelAttached(model);
|
AbstractView::modelAttached(model);
|
||||||
auto server = new NodeInstanceServerProxy(this, m_runModus, m_currentTarget);
|
m_nodeInstanceServer = createNodeInstanceServerProxy();
|
||||||
m_nodeInstanceServer = server;
|
|
||||||
m_lastCrashTime.start();
|
m_lastCrashTime.start();
|
||||||
connect(server, &NodeInstanceServerProxy::processCrashed, this, &NodeInstanceView::handleCrash);
|
connect(m_nodeInstanceServer.get(),
|
||||||
|
&NodeInstanceServerProxy::processCrashed,
|
||||||
|
this,
|
||||||
|
&NodeInstanceView::handleCrash);
|
||||||
|
|
||||||
if (!isSkippedRootNode(rootModelNode())) {
|
if (!isSkippedRootNode(rootModelNode())) {
|
||||||
nodeInstanceServer()->createScene(createCreateSceneCommand());
|
m_nodeInstanceServer->createScene(createCreateSceneCommand());
|
||||||
nodeInstanceServer()->changeSelection(createChangeSelectionCommand(model->selectedNodes(this)));
|
m_nodeInstanceServer->changeSelection(createChangeSelectionCommand(model->selectedNodes(this)));
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelNode stateNode = currentStateNode();
|
ModelNode stateNode = currentStateNode();
|
||||||
@@ -206,15 +208,14 @@ void NodeInstanceView::modelAttached(Model *model)
|
|||||||
NodeInstance newStateInstance = instanceForModelNode(stateNode);
|
NodeInstance newStateInstance = instanceForModelNode(stateNode);
|
||||||
activateState(newStateInstance);
|
activateState(newStateInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeInstanceView::modelAboutToBeDetached(Model * model)
|
void NodeInstanceView::modelAboutToBeDetached(Model * model)
|
||||||
{
|
{
|
||||||
removeAllInstanceNodeRelationships();
|
removeAllInstanceNodeRelationships();
|
||||||
if (nodeInstanceServer()) {
|
if (m_nodeInstanceServer) {
|
||||||
nodeInstanceServer()->clearScene(createClearSceneCommand());
|
m_nodeInstanceServer->clearScene(createClearSceneCommand());
|
||||||
delete nodeInstanceServer();
|
m_nodeInstanceServer.reset();
|
||||||
}
|
}
|
||||||
m_statePreviewImage.clear();
|
m_statePreviewImage.clear();
|
||||||
m_baseStatePreviewImage = QImage();
|
m_baseStatePreviewImage = QImage();
|
||||||
@@ -274,15 +275,18 @@ void NodeInstanceView::restartProcess()
|
|||||||
killTimer(m_restartProcessTimerId);
|
killTimer(m_restartProcessTimerId);
|
||||||
|
|
||||||
if (model()) {
|
if (model()) {
|
||||||
delete nodeInstanceServer();
|
m_nodeInstanceServer.reset();
|
||||||
|
m_nodeInstanceServer = createNodeInstanceServerProxy();
|
||||||
|
|
||||||
auto server = new NodeInstanceServerProxy(this, m_runModus, m_currentTarget);
|
connect(m_nodeInstanceServer.get(),
|
||||||
m_nodeInstanceServer = server;
|
&NodeInstanceServerProxy::processCrashed,
|
||||||
connect(server, &NodeInstanceServerProxy::processCrashed, this, &NodeInstanceView::handleCrash);
|
this,
|
||||||
|
&NodeInstanceView::handleCrash);
|
||||||
|
|
||||||
if (!isSkippedRootNode(rootModelNode())) {
|
if (!isSkippedRootNode(rootModelNode())) {
|
||||||
nodeInstanceServer()->createScene(createCreateSceneCommand());
|
m_nodeInstanceServer->createScene(createCreateSceneCommand());
|
||||||
nodeInstanceServer()->changeSelection(createChangeSelectionCommand(model()->selectedNodes(this)));
|
m_nodeInstanceServer->changeSelection(
|
||||||
|
createChangeSelectionCommand(model()->selectedNodes(this)));
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelNode stateNode = currentStateNode();
|
ModelNode stateNode = currentStateNode();
|
||||||
@@ -313,17 +317,19 @@ void NodeInstanceView::nodeCreated(const ModelNode &createdNode)
|
|||||||
propertyList.append(createdNode.variantProperty("y"));
|
propertyList.append(createdNode.variantProperty("y"));
|
||||||
updatePosition(propertyList);
|
updatePosition(propertyList);
|
||||||
|
|
||||||
nodeInstanceServer()->createInstances(createCreateInstancesCommand({instance}));
|
m_nodeInstanceServer->createInstances(createCreateInstancesCommand({instance}));
|
||||||
nodeInstanceServer()->changePropertyValues(createChangeValueCommand(createdNode.variantProperties()));
|
m_nodeInstanceServer->changePropertyValues(
|
||||||
nodeInstanceServer()->completeComponent(createComponentCompleteCommand({instance}));
|
createChangeValueCommand(createdNode.variantProperties()));
|
||||||
|
m_nodeInstanceServer->completeComponent(createComponentCompleteCommand({instance}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Notifies the view that \a removedNode will be removed.
|
/*! Notifies the view that \a removedNode will be removed.
|
||||||
*/
|
*/
|
||||||
void NodeInstanceView::nodeAboutToBeRemoved(const ModelNode &removedNode)
|
void NodeInstanceView::nodeAboutToBeRemoved(const ModelNode &removedNode)
|
||||||
{
|
{
|
||||||
nodeInstanceServer()->removeInstances(createRemoveInstancesCommand(removedNode));
|
m_nodeInstanceServer->removeInstances(createRemoveInstancesCommand(removedNode));
|
||||||
nodeInstanceServer()->removeSharedMemory(createRemoveSharedMemoryCommand("Image", removedNode.internalId()));
|
m_nodeInstanceServer->removeSharedMemory(
|
||||||
|
createRemoveSharedMemoryCommand("Image", removedNode.internalId()));
|
||||||
removeInstanceAndSubInstances(removedNode);
|
removeInstanceAndSubInstances(removedNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,11 +349,10 @@ void NodeInstanceView::resetHorizontalAnchors(const ModelNode &modelNode)
|
|||||||
valueList.append(modelNode.variantProperty("width"));
|
valueList.append(modelNode.variantProperty("width"));
|
||||||
|
|
||||||
if (!valueList.isEmpty())
|
if (!valueList.isEmpty())
|
||||||
nodeInstanceServer()->changePropertyValues(createChangeValueCommand(valueList));
|
m_nodeInstanceServer->changePropertyValues(createChangeValueCommand(valueList));
|
||||||
|
|
||||||
if (!bindingList.isEmpty())
|
if (!bindingList.isEmpty())
|
||||||
nodeInstanceServer()->changePropertyBindings(createChangeBindingCommand(bindingList));
|
m_nodeInstanceServer->changePropertyBindings(createChangeBindingCommand(bindingList));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeInstanceView::resetVerticalAnchors(const ModelNode &modelNode)
|
void NodeInstanceView::resetVerticalAnchors(const ModelNode &modelNode)
|
||||||
@@ -355,8 +360,8 @@ void NodeInstanceView::resetVerticalAnchors(const ModelNode &modelNode)
|
|||||||
QList<BindingProperty> bindingList;
|
QList<BindingProperty> bindingList;
|
||||||
QList<VariantProperty> valueList;
|
QList<VariantProperty> valueList;
|
||||||
|
|
||||||
if (modelNode.hasBindingProperty("yx"))
|
if (modelNode.hasBindingProperty("x"))
|
||||||
bindingList.append(modelNode.bindingProperty("yx"));
|
bindingList.append(modelNode.bindingProperty("x"));
|
||||||
else if (modelNode.hasVariantProperty("y"))
|
else if (modelNode.hasVariantProperty("y"))
|
||||||
valueList.append(modelNode.variantProperty("y"));
|
valueList.append(modelNode.variantProperty("y"));
|
||||||
|
|
||||||
@@ -366,10 +371,10 @@ void NodeInstanceView::resetVerticalAnchors(const ModelNode &modelNode)
|
|||||||
valueList.append(modelNode.variantProperty("height"));
|
valueList.append(modelNode.variantProperty("height"));
|
||||||
|
|
||||||
if (!valueList.isEmpty())
|
if (!valueList.isEmpty())
|
||||||
nodeInstanceServer()->changePropertyValues(createChangeValueCommand(valueList));
|
m_nodeInstanceServer->changePropertyValues(createChangeValueCommand(valueList));
|
||||||
|
|
||||||
if (!bindingList.isEmpty())
|
if (!bindingList.isEmpty())
|
||||||
nodeInstanceServer()->changePropertyBindings(createChangeBindingCommand(bindingList));
|
m_nodeInstanceServer->changePropertyBindings(createChangeBindingCommand(bindingList));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeInstanceView::propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList)
|
void NodeInstanceView::propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList)
|
||||||
@@ -388,10 +393,10 @@ void NodeInstanceView::propertiesAboutToBeRemoved(const QList<AbstractProperty>&
|
|||||||
RemoveInstancesCommand removeInstancesCommand = createRemoveInstancesCommand(nodeList);
|
RemoveInstancesCommand removeInstancesCommand = createRemoveInstancesCommand(nodeList);
|
||||||
|
|
||||||
if (!removeInstancesCommand.instanceIds().isEmpty())
|
if (!removeInstancesCommand.instanceIds().isEmpty())
|
||||||
nodeInstanceServer()->removeInstances(removeInstancesCommand);
|
m_nodeInstanceServer->removeInstances(removeInstancesCommand);
|
||||||
|
|
||||||
nodeInstanceServer()->removeSharedMemory(createRemoveSharedMemoryCommand("Image", nodeList));
|
m_nodeInstanceServer->removeSharedMemory(createRemoveSharedMemoryCommand("Image", nodeList));
|
||||||
nodeInstanceServer()->removeProperties(createRemovePropertiesCommand(nonNodePropertyList));
|
m_nodeInstanceServer->removeProperties(createRemovePropertiesCommand(nonNodePropertyList));
|
||||||
|
|
||||||
foreach (const AbstractProperty &property, propertyList) {
|
foreach (const AbstractProperty &property, propertyList) {
|
||||||
const PropertyName &name = property.name();
|
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*/)
|
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*/)
|
void NodeInstanceView::variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags /*propertyChange*/)
|
||||||
{
|
{
|
||||||
updatePosition(propertyList);
|
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
|
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)) {
|
if (!isSkippedNode(node)) {
|
||||||
updateChildren(newPropertyParent);
|
updateChildren(newPropertyParent);
|
||||||
nodeInstanceServer()->reparentInstances(createReparentInstancesCommand(node, newPropertyParent, oldPropertyParent));
|
m_nodeInstanceServer->reparentInstances(
|
||||||
|
createReparentInstancesCommand(node, newPropertyParent, oldPropertyParent));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeInstanceView::fileUrlChanged(const QUrl &/*oldUrl*/, const QUrl &newUrl)
|
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*/)
|
void NodeInstanceView::nodeIdChanged(const ModelNode& node, const QString& /*newId*/, const QString& /*oldId*/)
|
||||||
{
|
{
|
||||||
if (hasInstanceForModelNode(node)) {
|
if (hasInstanceForModelNode(node)) {
|
||||||
NodeInstance instance = instanceForModelNode(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*/)
|
void NodeInstanceView::importsChanged(const QList<Import> &/*addedImports*/, const QList<Import> &/*removedImports*/)
|
||||||
@@ -531,30 +537,26 @@ void NodeInstanceView::auxiliaryDataChanged(const ModelNode &node,
|
|||||||
if (value.isValid() || name == "invisible") {
|
if (value.isValid() || name == "invisible") {
|
||||||
PropertyValueContainer container(instance.instanceId(), name, value, TypeName());
|
PropertyValueContainer container(instance.instanceId(), name, value, TypeName());
|
||||||
ChangeAuxiliaryCommand changeAuxiliaryCommand({container});
|
ChangeAuxiliaryCommand changeAuxiliaryCommand({container});
|
||||||
nodeInstanceServer()->changeAuxiliaryValues(changeAuxiliaryCommand);
|
m_nodeInstanceServer->changeAuxiliaryValues(changeAuxiliaryCommand);
|
||||||
} else {
|
} else {
|
||||||
if (node.hasVariantProperty(name)) {
|
if (node.hasVariantProperty(name)) {
|
||||||
PropertyValueContainer container(instance.instanceId(), name, node.variantProperty(name).value(), TypeName());
|
PropertyValueContainer container(instance.instanceId(), name, node.variantProperty(name).value(), TypeName());
|
||||||
ChangeValuesCommand changeValueCommand({container});
|
ChangeValuesCommand changeValueCommand({container});
|
||||||
nodeInstanceServer()->changePropertyValues(changeValueCommand);
|
m_nodeInstanceServer->changePropertyValues(changeValueCommand);
|
||||||
} else if (node.hasBindingProperty(name)) {
|
} else if (node.hasBindingProperty(name)) {
|
||||||
PropertyBindingContainer container(instance.instanceId(), name, node.bindingProperty(name).expression(), TypeName());
|
PropertyBindingContainer container(instance.instanceId(), name, node.bindingProperty(name).expression(), TypeName());
|
||||||
ChangeBindingsCommand changeValueCommand({container});
|
ChangeBindingsCommand changeValueCommand({container});
|
||||||
nodeInstanceServer()->changePropertyBindings(changeValueCommand);
|
m_nodeInstanceServer->changePropertyBindings(changeValueCommand);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (node.isRootNode() && name == "language@Internal") {
|
} else if (node.isRootNode() && name == "language@Internal") {
|
||||||
const QString languageAsString = value.toString();
|
const QString languageAsString = value.toString();
|
||||||
if (m_currentTarget) {
|
if (auto multiLanguageAspect = QmlProjectManager::QmlMultiLanguageAspect::current(m_currentTarget))
|
||||||
if (auto rc = m_currentTarget->activeRunConfiguration()) {
|
multiLanguageAspect->setCurrentLocale(languageAsString);
|
||||||
if (auto multiLanguageAspect = rc->aspect<QmlProjectManager::QmlMultiLanguageAspect>())
|
m_nodeInstanceServer->changeLanguage({languageAsString});
|
||||||
multiLanguageAspect->setLastUsedLanguage(languageAsString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nodeInstanceServer()->changeLanguage({languageAsString});
|
|
||||||
} else if (node.isRootNode() && name == "previewSize@Internal") {
|
} else if (node.isRootNode() && name == "previewSize@Internal") {
|
||||||
nodeInstanceServer()->changePreviewImageSize(value.toSize());
|
m_nodeInstanceServer->changePreviewImageSize(value.toSize());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -569,10 +571,12 @@ void NodeInstanceView::nodeSourceChanged(const ModelNode &node, const QString &
|
|||||||
if (hasInstanceForModelNode(node)) {
|
if (hasInstanceForModelNode(node)) {
|
||||||
NodeInstance instance = instanceForModelNode(node);
|
NodeInstance instance = instanceForModelNode(node);
|
||||||
ChangeNodeSourceCommand changeNodeSourceCommand(instance.instanceId(), newNodeSource);
|
ChangeNodeSourceCommand changeNodeSourceCommand(instance.instanceId(), newNodeSource);
|
||||||
nodeInstanceServer()->changeNodeSource(changeNodeSourceCommand);
|
m_nodeInstanceServer->changeNodeSource(changeNodeSourceCommand);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NodeInstanceView::capturedData(const CapturedDataCommand &) {}
|
||||||
|
|
||||||
void NodeInstanceView::currentStateChanged(const ModelNode &node)
|
void NodeInstanceView::currentStateChanged(const ModelNode &node)
|
||||||
{
|
{
|
||||||
NodeInstance newStateInstance = instanceForModelNode(node);
|
NodeInstance newStateInstance = instanceForModelNode(node);
|
||||||
@@ -794,12 +798,6 @@ void NodeInstanceView::updatePosition(const QList<VariantProperty> &propertyList
|
|||||||
emitInstanceInformationsChange(informationChangeHash);
|
emitInstanceInformationsChange(informationChangeHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeInstanceServerInterface *NodeInstanceView::nodeInstanceServer() const
|
|
||||||
{
|
|
||||||
return m_nodeInstanceServer.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
NodeInstance NodeInstanceView::loadNode(const ModelNode &node)
|
NodeInstance NodeInstanceView::loadNode(const ModelNode &node)
|
||||||
{
|
{
|
||||||
NodeInstance instance(NodeInstance::create(node));
|
NodeInstance instance(NodeInstance::create(node));
|
||||||
@@ -814,12 +812,12 @@ NodeInstance NodeInstanceView::loadNode(const ModelNode &node)
|
|||||||
|
|
||||||
void NodeInstanceView::activateState(const NodeInstance &instance)
|
void NodeInstanceView::activateState(const NodeInstance &instance)
|
||||||
{
|
{
|
||||||
nodeInstanceServer()->changeState(ChangeStateCommand(instance.instanceId()));
|
m_nodeInstanceServer->changeState(ChangeStateCommand(instance.instanceId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeInstanceView::activateBaseState()
|
void NodeInstanceView::activateBaseState()
|
||||||
{
|
{
|
||||||
nodeInstanceServer()->changeState(ChangeStateCommand(-1));
|
m_nodeInstanceServer->changeState(ChangeStateCommand(-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeInstanceView::removeRecursiveChildRelationship(const ModelNode &removedNode)
|
void NodeInstanceView::removeRecursiveChildRelationship(const ModelNode &removedNode)
|
||||||
@@ -994,12 +992,8 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand()
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString lastUsedLanguage;
|
QString lastUsedLanguage;
|
||||||
if (m_currentTarget) {
|
if (auto multiLanguageAspect = QmlProjectManager::QmlMultiLanguageAspect::current(m_currentTarget))
|
||||||
if (auto rc = m_currentTarget->activeRunConfiguration()) {
|
lastUsedLanguage = multiLanguageAspect->currentLocale();
|
||||||
if (auto multiLanguageAspect = rc->aspect<QmlProjectManager::QmlMultiLanguageAspect>())
|
|
||||||
lastUsedLanguage = multiLanguageAspect->lastUsedLanguage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return CreateSceneCommand(
|
return CreateSceneCommand(
|
||||||
instanceContainerList,
|
instanceContainerList,
|
||||||
@@ -1256,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())
|
if (!valuePropertyChangeList.isEmpty())
|
||||||
emitInstancePropertyChange(valuePropertyChangeList);
|
emitInstancePropertyChange(valuePropertyChangeList);
|
||||||
@@ -1464,7 +1459,7 @@ void NodeInstanceView::sendToken(const QString &token, int number, const QVector
|
|||||||
foreach (const ModelNode &node, nodeVector)
|
foreach (const ModelNode &node, nodeVector)
|
||||||
instanceIdVector.append(node.internalId());
|
instanceIdVector.append(node.internalId());
|
||||||
|
|
||||||
nodeInstanceServer()->token(TokenCommand(token, number, instanceIdVector));
|
m_nodeInstanceServer->token(TokenCommand(token, number, instanceIdVector));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeInstanceView::selectionChanged(const ChangeSelectionCommand &command)
|
void NodeInstanceView::selectionChanged(const ChangeSelectionCommand &command)
|
||||||
@@ -1479,7 +1474,7 @@ void NodeInstanceView::selectionChanged(const ChangeSelectionCommand &command)
|
|||||||
void NodeInstanceView::handlePuppetToCreatorCommand(const PuppetToCreatorCommand &command)
|
void NodeInstanceView::handlePuppetToCreatorCommand(const PuppetToCreatorCommand &command)
|
||||||
{
|
{
|
||||||
if (command.type() == PuppetToCreatorCommand::Edit3DToolState) {
|
if (command.type() == PuppetToCreatorCommand::Edit3DToolState) {
|
||||||
if (!m_nodeInstanceServer.isNull()) {
|
if (m_nodeInstanceServer) {
|
||||||
auto data = qvariant_cast<QVariantList>(command.data());
|
auto data = qvariant_cast<QVariantList>(command.data());
|
||||||
if (data.size() == 3) {
|
if (data.size() == 3) {
|
||||||
QString qmlId = data[0].toString();
|
QString qmlId = data[0].toString();
|
||||||
@@ -1496,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,
|
void NodeInstanceView::selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
|
||||||
const QList<ModelNode> & /*lastSelectedNodeList*/)
|
const QList<ModelNode> & /*lastSelectedNodeList*/)
|
||||||
{
|
{
|
||||||
nodeInstanceServer()->changeSelection(createChangeSelectionCommand(selectedNodeList));
|
m_nodeInstanceServer->changeSelection(createChangeSelectionCommand(selectedNodeList));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeInstanceView::sendInputEvent(QInputEvent *e) const
|
void NodeInstanceView::sendInputEvent(QInputEvent *e) const
|
||||||
{
|
{
|
||||||
nodeInstanceServer()->inputEvent(InputEventCommand(e));
|
m_nodeInstanceServer->inputEvent(InputEventCommand(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeInstanceView::view3DAction(const View3DActionCommand &command)
|
void NodeInstanceView::view3DAction(const View3DActionCommand &command)
|
||||||
{
|
{
|
||||||
nodeInstanceServer()->view3DAction(command);
|
m_nodeInstanceServer->view3DAction(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeInstanceView::edit3DViewResized(const QSize &size) const
|
void NodeInstanceView::edit3DViewResized(const QSize &size) const
|
||||||
{
|
{
|
||||||
nodeInstanceServer()->update3DViewState(Update3dViewStateCommand(size));
|
m_nodeInstanceServer->update3DViewState(Update3dViewStateCommand(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeInstanceView::timerEvent(QTimerEvent *event)
|
void NodeInstanceView::timerEvent(QTimerEvent *event)
|
||||||
|
@@ -178,11 +178,12 @@ PuppetCreator::PuppetCreator(ProjectExplorer::Target *target, const Model *model
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QProcess *PuppetCreator::createPuppetProcess(const QString &puppetMode,
|
QProcessUniquePointer PuppetCreator::createPuppetProcess(
|
||||||
|
const QString &puppetMode,
|
||||||
const QString &socketToken,
|
const QString &socketToken,
|
||||||
QObject *handlerObject,
|
QObject *handlerObject,
|
||||||
const char *outputSlot,
|
std::function<void()> processOutputCallback,
|
||||||
const char *finishSlot,
|
std::function<void(int, QProcess::ExitStatus)> processFinishCallback,
|
||||||
const QStringList &customOptions) const
|
const QStringList &customOptions) const
|
||||||
{
|
{
|
||||||
return puppetProcess(qml2PuppetPath(m_availablePuppetType),
|
return puppetProcess(qml2PuppetPath(m_availablePuppetType),
|
||||||
@@ -190,27 +191,33 @@ QProcess *PuppetCreator::createPuppetProcess(const QString &puppetMode,
|
|||||||
puppetMode,
|
puppetMode,
|
||||||
socketToken,
|
socketToken,
|
||||||
handlerObject,
|
handlerObject,
|
||||||
outputSlot,
|
processOutputCallback,
|
||||||
finishSlot,
|
processFinishCallback,
|
||||||
customOptions);
|
customOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QProcessUniquePointer PuppetCreator::puppetProcess(
|
||||||
QProcess *PuppetCreator::puppetProcess(const QString &puppetPath,
|
const QString &puppetPath,
|
||||||
const QString &workingDirectory,
|
const QString &workingDirectory,
|
||||||
const QString &puppetMode,
|
const QString &puppetMode,
|
||||||
const QString &socketToken,
|
const QString &socketToken,
|
||||||
QObject *handlerObject,
|
QObject *handlerObject,
|
||||||
const char *outputSlot,
|
std::function<void()> processOutputCallback,
|
||||||
const char *finishSlot,
|
std::function<void(int, QProcess::ExitStatus)> processFinishCallback,
|
||||||
const QStringList &customOptions) const
|
const QStringList &customOptions) const
|
||||||
{
|
{
|
||||||
auto puppetProcess = new QProcess;
|
QProcessUniquePointer puppetProcess{new QProcess};
|
||||||
puppetProcess->setObjectName(puppetMode);
|
puppetProcess->setObjectName(puppetMode);
|
||||||
puppetProcess->setProcessEnvironment(processEnvironment());
|
puppetProcess->setProcessEnvironment(processEnvironment());
|
||||||
|
|
||||||
QObject::connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, puppetProcess, &QProcess::kill);
|
QObject::connect(QCoreApplication::instance(),
|
||||||
QObject::connect(puppetProcess, SIGNAL(finished(int,QProcess::ExitStatus)), handlerObject, finishSlot);
|
&QCoreApplication::aboutToQuit,
|
||||||
|
puppetProcess.get(),
|
||||||
|
&QProcess::kill);
|
||||||
|
QObject::connect(puppetProcess.get(),
|
||||||
|
static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
|
||||||
|
handlerObject,
|
||||||
|
processFinishCallback);
|
||||||
|
|
||||||
#ifndef QMLDESIGNER_TEST
|
#ifndef QMLDESIGNER_TEST
|
||||||
QString forwardOutput = m_designerSettings.value(DesignerSettingsKey::
|
QString forwardOutput = m_designerSettings.value(DesignerSettingsKey::
|
||||||
@@ -220,7 +227,7 @@ QProcess *PuppetCreator::puppetProcess(const QString &puppetPath,
|
|||||||
#endif
|
#endif
|
||||||
if (forwardOutput == puppetMode || forwardOutput == "all") {
|
if (forwardOutput == puppetMode || forwardOutput == "all") {
|
||||||
puppetProcess->setProcessChannelMode(QProcess::MergedChannels);
|
puppetProcess->setProcessChannelMode(QProcess::MergedChannels);
|
||||||
QObject::connect(puppetProcess, SIGNAL(readyRead()), handlerObject, outputSlot);
|
QObject::connect(puppetProcess.get(), &QProcess::readyRead, handlerObject, processOutputCallback);
|
||||||
}
|
}
|
||||||
puppetProcess->setWorkingDirectory(workingDirectory);
|
puppetProcess->setWorkingDirectory(workingDirectory);
|
||||||
|
|
||||||
@@ -514,13 +521,11 @@ QProcessEnvironment PuppetCreator::processEnvironment() const
|
|||||||
|
|
||||||
customFileSelectors = m_target->additionalData("CustomFileSelectorsData").toStringList();
|
customFileSelectors = m_target->additionalData("CustomFileSelectorsData").toStringList();
|
||||||
|
|
||||||
if (auto *rc = m_target->activeRunConfiguration()) {
|
if (auto multiLanguageAspect = QmlProjectManager::QmlMultiLanguageAspect::current(m_target)) {
|
||||||
if (auto multiLanguageAspect = rc->aspect<QmlProjectManager::QmlMultiLanguageAspect>()) {
|
|
||||||
if (!multiLanguageAspect->databaseFilePath().isEmpty())
|
if (!multiLanguageAspect->databaseFilePath().isEmpty())
|
||||||
environment.set("QT_MULTILANGUAGE_DATABASE", multiLanguageAspect->databaseFilePath().toString());
|
environment.set("QT_MULTILANGUAGE_DATABASE", multiLanguageAspect->databaseFilePath().toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
customFileSelectors.append("DesignMode");
|
customFileSelectors.append("DesignMode");
|
||||||
|
|
||||||
|
@@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "qprocessuniqueptr.h"
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QProcessEnvironment>
|
#include <QProcessEnvironment>
|
||||||
|
|
||||||
@@ -53,11 +55,12 @@ public:
|
|||||||
|
|
||||||
void createQml2PuppetExecutableIfMissing();
|
void createQml2PuppetExecutableIfMissing();
|
||||||
|
|
||||||
QProcess *createPuppetProcess(const QString &puppetMode,
|
QProcessUniquePointer createPuppetProcess(
|
||||||
|
const QString &puppetMode,
|
||||||
const QString &socketToken,
|
const QString &socketToken,
|
||||||
QObject *handlerObject,
|
QObject *handlerObject,
|
||||||
const char *outputSlot,
|
std::function<void()> processOutputCallback,
|
||||||
const char *finishSlot,
|
std::function<void(int, QProcess::ExitStatus)> processFinishCallback,
|
||||||
const QStringList &customOptions = {}) const;
|
const QStringList &customOptions = {}) const;
|
||||||
|
|
||||||
void setQrcMappingString(const QString qrcMapping);
|
void setQrcMappingString(const QString qrcMapping);
|
||||||
@@ -82,13 +85,13 @@ protected:
|
|||||||
|
|
||||||
bool checkPuppetIsReady(const QString &puppetPath) const;
|
bool checkPuppetIsReady(const QString &puppetPath) const;
|
||||||
bool qtIsSupported() const;
|
bool qtIsSupported() const;
|
||||||
QProcess *puppetProcess(const QString &puppetPath,
|
QProcessUniquePointer puppetProcess(const QString &puppetPath,
|
||||||
const QString &workingDirectory,
|
const QString &workingDirectory,
|
||||||
const QString &puppetMode,
|
const QString &puppetMode,
|
||||||
const QString &socketToken,
|
const QString &socketToken,
|
||||||
QObject *handlerObject,
|
QObject *handlerObject,
|
||||||
const char *outputSlot,
|
std::function<void()> processOutputCallback,
|
||||||
const char *finishSlot,
|
std::function<void(int, QProcess::ExitStatus)> processFinishCallback,
|
||||||
const QStringList &customOptions) const;
|
const QStringList &customOptions) const;
|
||||||
|
|
||||||
QProcessEnvironment processEnvironment() const;
|
QProcessEnvironment processEnvironment() const;
|
||||||
|
@@ -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
|
@@ -427,7 +427,7 @@ QVector<PropertyInfo> getQmlTypes(const CppComponentValue *objectValue, const Co
|
|||||||
PropertyMemberProcessor processor(context);
|
PropertyMemberProcessor processor(context);
|
||||||
objectValue->processMembers(&processor);
|
objectValue->processMembers(&processor);
|
||||||
|
|
||||||
foreach (const PropertyInfo &property, processor.properties()) {
|
for (const PropertyInfo &property : processor.properties()) {
|
||||||
const PropertyName name = property.first;
|
const PropertyName name = property.first;
|
||||||
const QString nameAsString = QString::fromUtf8(name);
|
const QString nameAsString = QString::fromUtf8(name);
|
||||||
if (!objectValue->isWritable(nameAsString) && objectValue->isPointer(nameAsString)) {
|
if (!objectValue->isWritable(nameAsString) && objectValue->isPointer(nameAsString)) {
|
||||||
@@ -1500,6 +1500,11 @@ bool NodeMetaInfo::propertyIsPrivate(const PropertyName &propertyName) const
|
|||||||
return propertyName.startsWith("__");
|
return propertyName.startsWith("__");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NodeMetaInfo::propertyIsPointer(const PropertyName &propertyName) const
|
||||||
|
{
|
||||||
|
return m_privateData->isPropertyPointer(propertyName);
|
||||||
|
}
|
||||||
|
|
||||||
QString NodeMetaInfo::propertyEnumScope(const PropertyName &propertyName) const
|
QString NodeMetaInfo::propertyEnumScope(const PropertyName &propertyName) const
|
||||||
{
|
{
|
||||||
return m_privateData->propertyEnumScope(propertyName);
|
return m_privateData->propertyEnumScope(propertyName);
|
||||||
@@ -1660,6 +1665,12 @@ bool NodeMetaInfo::isGraphicalItem() const
|
|||||||
|| isSubclassOf("QtQuick.Controls.Popup");
|
|| isSubclassOf("QtQuick.Controls.Popup");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NodeMetaInfo::isQmlItem() const
|
||||||
|
{
|
||||||
|
return isSubclassOf("QtQuick.QtObject")
|
||||||
|
|| isSubclassOf("QtQml.QtObject");
|
||||||
|
}
|
||||||
|
|
||||||
void NodeMetaInfo::clearCache()
|
void NodeMetaInfo::clearCache()
|
||||||
{
|
{
|
||||||
Internal::NodeMetaInfoPrivate::clearCache();
|
Internal::NodeMetaInfoPrivate::clearCache();
|
||||||
|
@@ -27,23 +27,24 @@
|
|||||||
|
|
||||||
#ifndef QMLDESIGNER_TEST
|
#ifndef QMLDESIGNER_TEST
|
||||||
|
|
||||||
#include <componentaction.h>
|
|
||||||
#include <designmodewidget.h>
|
|
||||||
#include <crumblebar.h>
|
|
||||||
#include <abstractview.h>
|
#include <abstractview.h>
|
||||||
#include <rewriterview.h>
|
#include <componentaction.h>
|
||||||
#include <nodeinstanceview.h>
|
#include <componentview.h>
|
||||||
#include <itemlibraryview.h>
|
#include <crumblebar.h>
|
||||||
#include <navigatorview.h>
|
#include <debugview.h>
|
||||||
#include <stateseditorview.h>
|
#include <designeractionmanagerview.h>
|
||||||
|
#include <designmodewidget.h>
|
||||||
#include <edit3dview.h>
|
#include <edit3dview.h>
|
||||||
#include <formeditorview.h>
|
#include <formeditorview.h>
|
||||||
#include <texteditorview.h>
|
|
||||||
#include <propertyeditorview.h>
|
|
||||||
#include <componentview.h>
|
|
||||||
#include <debugview.h>
|
|
||||||
#include <importmanagerview.h>
|
#include <importmanagerview.h>
|
||||||
#include <designeractionmanagerview.h>
|
#include <interactiveconnectionmanager.h>
|
||||||
|
#include <itemlibraryview.h>
|
||||||
|
#include <navigatorview.h>
|
||||||
|
#include <nodeinstanceview.h>
|
||||||
|
#include <propertyeditorview.h>
|
||||||
|
#include <rewriterview.h>
|
||||||
|
#include <stateseditorview.h>
|
||||||
|
#include <texteditorview.h>
|
||||||
#include <qmldesignerplugin.h>
|
#include <qmldesignerplugin.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
@@ -59,10 +60,11 @@ static Q_LOGGING_CATEGORY(viewBenchmark, "qtc.viewmanager.attach", QtWarningMsg)
|
|||||||
class ViewManagerData
|
class ViewManagerData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
InteractiveConnectionManager connectionManager;
|
||||||
QmlModelState savedState;
|
QmlModelState savedState;
|
||||||
Internal::DebugView debugView;
|
Internal::DebugView debugView;
|
||||||
DesignerActionManagerView designerActionManagerView;
|
DesignerActionManagerView designerActionManagerView;
|
||||||
NodeInstanceView nodeInstanceView;
|
NodeInstanceView nodeInstanceView{connectionManager};
|
||||||
ComponentView componentView;
|
ComponentView componentView;
|
||||||
Edit3DView edit3DView;
|
Edit3DView edit3DView;
|
||||||
FormEditorView formEditorView;
|
FormEditorView formEditorView;
|
||||||
@@ -81,7 +83,7 @@ static CrumbleBar *crumbleBar() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ViewManager::ViewManager()
|
ViewManager::ViewManager()
|
||||||
: d(new ViewManagerData)
|
: d(std::make_unique<ViewManagerData>())
|
||||||
{
|
{
|
||||||
d->formEditorView.setGotoErrorCallback([this](int line, int column) {
|
d->formEditorView.setGotoErrorCallback([this](int line, int column) {
|
||||||
d->textEditorView.gotoCursorPosition(line, column);
|
d->textEditorView.gotoCursorPosition(line, column);
|
||||||
@@ -92,10 +94,9 @@ ViewManager::ViewManager()
|
|||||||
|
|
||||||
ViewManager::~ViewManager()
|
ViewManager::~ViewManager()
|
||||||
{
|
{
|
||||||
foreach (const QPointer<AbstractView> &view, d->additionalViews)
|
for (const QPointer<AbstractView> &view : d->additionalViews)
|
||||||
delete view.data();
|
delete view.data();
|
||||||
|
|
||||||
delete d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DesignDocument *ViewManager::currentDesignDocument() const
|
DesignDocument *ViewManager::currentDesignDocument() const
|
||||||
|
@@ -134,6 +134,7 @@ Project {
|
|||||||
"commands/changestatecommand.h",
|
"commands/changestatecommand.h",
|
||||||
"commands/changevaluescommand.cpp",
|
"commands/changevaluescommand.cpp",
|
||||||
"commands/changevaluescommand.h",
|
"commands/changevaluescommand.h",
|
||||||
|
"commands/captureddatacommand.h",
|
||||||
"commands/childrenchangedcommand.cpp",
|
"commands/childrenchangedcommand.cpp",
|
||||||
"commands/childrenchangedcommand.h",
|
"commands/childrenchangedcommand.h",
|
||||||
"commands/clearscenecommand.cpp",
|
"commands/clearscenecommand.cpp",
|
||||||
@@ -321,6 +322,17 @@ Project {
|
|||||||
"instances/puppetdialog.cpp",
|
"instances/puppetdialog.cpp",
|
||||||
"instances/puppetdialog.h",
|
"instances/puppetdialog.h",
|
||||||
"instances/puppetdialog.ui",
|
"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/itemlibraryinfo.cpp",
|
||||||
"metainfo/metainfo.cpp",
|
"metainfo/metainfo.cpp",
|
||||||
"metainfo/metainforeader.cpp",
|
"metainfo/metainforeader.cpp",
|
||||||
|
@@ -212,24 +212,26 @@ void FpsAction::currentContextChanged(const SelectionContext &)
|
|||||||
SwitchLanguageComboboxAction::SwitchLanguageComboboxAction(QObject *parent)
|
SwitchLanguageComboboxAction::SwitchLanguageComboboxAction(QObject *parent)
|
||||||
: QWidgetAction(parent)
|
: QWidgetAction(parent)
|
||||||
{
|
{
|
||||||
connect(ProjectExplorer::SessionManager::instance(),
|
|
||||||
&ProjectExplorer::SessionManager::startupProjectChanged,
|
|
||||||
this,
|
|
||||||
&SwitchLanguageComboboxAction::updateProjectLocales);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget *SwitchLanguageComboboxAction::createWidget(QWidget *parent)
|
QWidget *SwitchLanguageComboboxAction::createWidget(QWidget *parent)
|
||||||
{
|
{
|
||||||
QPointer<QComboBox> comboBox = new QComboBox(parent);
|
QPointer<QComboBox> comboBox = new QComboBox(parent);
|
||||||
comboBox->setToolTip(tr("Switch the language used by preview."));
|
const QString toolTip(tr("Switch the language used by preview."));
|
||||||
|
comboBox->setToolTip(toolTip);
|
||||||
comboBox->addItem(tr("Default"));
|
comboBox->addItem(tr("Default"));
|
||||||
|
|
||||||
auto refreshComboBoxFunction = [this, comboBox] (ProjectExplorer::Project *project) {
|
auto refreshComboBoxFunction = [this, comboBox, toolTip] (ProjectExplorer::Project *project) {
|
||||||
if (comboBox) {
|
if (comboBox && project) {
|
||||||
if (updateProjectLocales(project)) {
|
QString errorMessage;
|
||||||
|
auto locales = project->availableQmlPreviewTranslations(&errorMessage);
|
||||||
|
if (!errorMessage.isEmpty())
|
||||||
|
comboBox->setToolTip(QString("%1<br/>(%2)").arg(toolTip, errorMessage));
|
||||||
|
if (m_previousLocales != locales) {
|
||||||
comboBox->clear();
|
comboBox->clear();
|
||||||
comboBox->addItem(tr("Default"));
|
comboBox->addItem(tr("Default"));
|
||||||
comboBox->addItems(m_localeStrings);
|
comboBox->addItems(locales);
|
||||||
|
m_previousLocales = locales;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -250,24 +252,6 @@ QWidget *SwitchLanguageComboboxAction::createWidget(QWidget *parent)
|
|||||||
return comboBox;
|
return comboBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SwitchLanguageComboboxAction::updateProjectLocales(Project *project)
|
|
||||||
{
|
|
||||||
if (!project)
|
|
||||||
return false;
|
|
||||||
auto previousLocales = m_localeStrings;
|
|
||||||
m_localeStrings.clear();
|
|
||||||
const auto projectDirectory = project->rootProjectDirectory().toFileInfo().absoluteFilePath();
|
|
||||||
const QDir languageDirectory(projectDirectory + "/i18n");
|
|
||||||
const auto qmFiles = languageDirectory.entryList({"qml_*.qm"});
|
|
||||||
m_localeStrings = Utils::transform(qmFiles, [](const QString &qmFile) {
|
|
||||||
const int localeStartPosition = qmFile.lastIndexOf("_") + 1;
|
|
||||||
const int localeEndPosition = qmFile.size() - QString(".qm").size();
|
|
||||||
const QString locale = qmFile.left(localeEndPosition).mid(localeStartPosition);
|
|
||||||
return locale;
|
|
||||||
});
|
|
||||||
return previousLocales != m_localeStrings;
|
|
||||||
}
|
|
||||||
|
|
||||||
SwitchLanguageAction::SwitchLanguageAction()
|
SwitchLanguageAction::SwitchLanguageAction()
|
||||||
: m_switchLanguageAction(new SwitchLanguageComboboxAction(nullptr))
|
: m_switchLanguageAction(new SwitchLanguageComboboxAction(nullptr))
|
||||||
{
|
{
|
||||||
|
@@ -113,8 +113,7 @@ signals:
|
|||||||
protected:
|
protected:
|
||||||
QWidget *createWidget(QWidget *parent) override;
|
QWidget *createWidget(QWidget *parent) override;
|
||||||
private:
|
private:
|
||||||
bool updateProjectLocales(ProjectExplorer::Project *project);
|
QStringList m_previousLocales;
|
||||||
QStringList m_localeStrings;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SwitchLanguageAction : public ActionInterface
|
class SwitchLanguageAction : public ActionInterface
|
||||||
|
@@ -9,6 +9,8 @@ add_qtc_plugin(QmlPreview
|
|||||||
qmlpreviewruncontrol.cpp qmlpreviewruncontrol.h
|
qmlpreviewruncontrol.cpp qmlpreviewruncontrol.h
|
||||||
qmldebugtranslationclient.cpp qmldebugtranslationclient.h
|
qmldebugtranslationclient.cpp qmldebugtranslationclient.h
|
||||||
qmlpreview_global.h
|
qmlpreview_global.h
|
||||||
|
projectfileselectionswidget.cpp projectfileselectionswidget.h
|
||||||
|
qmldebugtranslationwidget.cpp qmldebugtranslationwidget.h
|
||||||
)
|
)
|
||||||
|
|
||||||
extend_qtc_plugin(QmlPreview
|
extend_qtc_plugin(QmlPreview
|
||||||
|
159
src/plugins/qmlpreview/projectfileselectionswidget.cpp
Normal file
159
src/plugins/qmlpreview/projectfileselectionswidget.cpp
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "projectfileselectionswidget.h"
|
||||||
|
|
||||||
|
#include <projectexplorer/target.h>
|
||||||
|
#include <projectexplorer/project.h>
|
||||||
|
#include <projectexplorer/session.h>
|
||||||
|
|
||||||
|
#include <utils/treemodel.h>
|
||||||
|
|
||||||
|
#include <QAbstractTableModel>
|
||||||
|
#include <QBoxLayout>
|
||||||
|
#include <QHeaderView>
|
||||||
|
#include <QTreeView>
|
||||||
|
|
||||||
|
namespace QmlPreview {
|
||||||
|
|
||||||
|
class ProjectFileItem : public Utils::TreeItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ProjectFileItem() = default;
|
||||||
|
ProjectFileItem(const Utils::FilePath &f, bool d)
|
||||||
|
: filePath(f)
|
||||||
|
, disabled(d)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Qt::ItemFlags flags(int) const override
|
||||||
|
{
|
||||||
|
return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant data(int , int role) const override
|
||||||
|
{
|
||||||
|
if (role == Qt::DisplayRole)
|
||||||
|
return filePath.toUserOutput();
|
||||||
|
if (role == Qt::CheckStateRole) {
|
||||||
|
if (disabled)
|
||||||
|
return Qt::Unchecked;
|
||||||
|
else
|
||||||
|
return Qt::Checked;
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool setData(int , const QVariant &data, int role) override
|
||||||
|
{
|
||||||
|
if (role != Qt::CheckStateRole)
|
||||||
|
return false;
|
||||||
|
disabled = (data == Qt::Unchecked);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Utils::FilePath filePath;
|
||||||
|
bool disabled = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ProjectFileSelectionsWidget::ProjectFileSelectionsWidget(const QString &projectSettingsKey, ProjectExplorer::FileType fileType, QWidget *parent)
|
||||||
|
: QWidget(parent)
|
||||||
|
, m_projectSettingsKey(projectSettingsKey)
|
||||||
|
, m_fileType(fileType)
|
||||||
|
{
|
||||||
|
auto model = new Utils::TreeModel<ProjectFileItem>(this);
|
||||||
|
model->setHeader({tr("Files to test:")});
|
||||||
|
auto updateCheckedFiles = [this, model] () {
|
||||||
|
m_checkedFiles.clear();
|
||||||
|
QStringList uncheckedFiles;
|
||||||
|
model->forAllItems([&, this](ProjectFileItem *item) {
|
||||||
|
if (item->disabled)
|
||||||
|
uncheckedFiles.append(item->filePath.toString());
|
||||||
|
else
|
||||||
|
m_checkedFiles.append(item->filePath);
|
||||||
|
});
|
||||||
|
if (auto project = ProjectExplorer::SessionManager::startupProject())
|
||||||
|
project->setNamedSettings(m_projectSettingsKey, uncheckedFiles);
|
||||||
|
emit selectionChanged(m_checkedFiles);
|
||||||
|
};
|
||||||
|
|
||||||
|
connect(model, &QAbstractItemModel::dataChanged, updateCheckedFiles);
|
||||||
|
|
||||||
|
auto view = new QTreeView(this);
|
||||||
|
view->setMinimumSize(QSize(100, 100));
|
||||||
|
view->setTextElideMode(Qt::ElideMiddle);
|
||||||
|
view->setWordWrap(false);
|
||||||
|
view->setUniformRowHeights(true);
|
||||||
|
view->setModel(model);
|
||||||
|
|
||||||
|
const auto viewLayout = new QHBoxLayout;
|
||||||
|
viewLayout->addWidget(view);
|
||||||
|
|
||||||
|
auto layout = new QVBoxLayout(this);
|
||||||
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
layout->addLayout(viewLayout);
|
||||||
|
|
||||||
|
auto initModel = [this, model, updateCheckedFiles](ProjectExplorer::Project *project) {
|
||||||
|
if (!project)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto refreshModel = [this, model, updateCheckedFiles] () {
|
||||||
|
model->clear();
|
||||||
|
if (auto project = ProjectExplorer::SessionManager::startupProject()) {
|
||||||
|
const auto settingsDisabledFiles = project->namedSettings(m_projectSettingsKey).toStringList();
|
||||||
|
|
||||||
|
if (auto rootProjectNode = project->rootProjectNode()) {
|
||||||
|
rootProjectNode->forEachNode([this, settingsDisabledFiles, model](ProjectExplorer::FileNode *fileNode) {
|
||||||
|
if (fileNode->fileType() == m_fileType) {
|
||||||
|
bool isDisabled = settingsDisabledFiles.contains(fileNode->filePath().toString());
|
||||||
|
model->rootItem()->appendChild(new ProjectFileItem(fileNode->filePath(), isDisabled));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
updateCheckedFiles();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// deploymentDataChanged is only triggered if the active project changed, so it is not a
|
||||||
|
// problem that maybe many different targets are connected to refreshModel
|
||||||
|
this->connect(project->activeTarget(), &ProjectExplorer::Target::deploymentDataChanged,
|
||||||
|
model, refreshModel, Qt::UniqueConnection);
|
||||||
|
refreshModel();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (auto project = ProjectExplorer::SessionManager::startupProject()) {
|
||||||
|
initModel(project);
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(ProjectExplorer::SessionManager::instance(),
|
||||||
|
&ProjectExplorer::SessionManager::startupProjectChanged,
|
||||||
|
initModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
Utils::FilePaths ProjectFileSelectionsWidget::checkedFiles()
|
||||||
|
{
|
||||||
|
return m_checkedFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // QmlPreview
|
50
src/plugins/qmlpreview/projectfileselectionswidget.h
Normal file
50
src/plugins/qmlpreview/projectfileselectionswidget.h
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 <projectexplorer/projectnodes.h>
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
namespace QmlPreview {
|
||||||
|
|
||||||
|
class ProjectFileSelectionsWidget : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ProjectFileSelectionsWidget(const QString &projectSettingsKey, ProjectExplorer::FileType fileType, QWidget *parent = nullptr);
|
||||||
|
Utils::FilePaths checkedFiles();
|
||||||
|
signals:
|
||||||
|
void selectionChanged(const Utils::FilePaths &selectedFiles);
|
||||||
|
private:
|
||||||
|
const QString m_projectSettingsKey;
|
||||||
|
ProjectExplorer::FileType m_fileType;
|
||||||
|
|
||||||
|
Utils::FilePaths m_checkedFiles;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // QmlPreview
|
@@ -57,6 +57,14 @@ void QmlDebugTranslationClient::changeElidedTextWarningString(const QString &war
|
|||||||
sendMessage(packet.data());
|
sendMessage(packet.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QmlDebugTranslationClient::changeElideWarning(bool elideWarning)
|
||||||
|
{
|
||||||
|
if (elideWarning)
|
||||||
|
enableElidedTextWarning();
|
||||||
|
else
|
||||||
|
disableElidedTextWarning();
|
||||||
|
}
|
||||||
|
|
||||||
void QmlDebugTranslationClient::setDebugTranslationServiceLogFile(const QString &logFilePath)
|
void QmlDebugTranslationClient::setDebugTranslationServiceLogFile(const QString &logFilePath)
|
||||||
{
|
{
|
||||||
QmlDebug::QPacket packet(dataStreamVersion());
|
QmlDebug::QPacket packet(dataStreamVersion());
|
||||||
|
@@ -50,6 +50,7 @@ public:
|
|||||||
void changeLanguage(const QUrl &url, const QString &locale);
|
void changeLanguage(const QUrl &url, const QString &locale);
|
||||||
void changeWarningColor(const QColor &warningColor);
|
void changeWarningColor(const QColor &warningColor);
|
||||||
void changeElidedTextWarningString(const QString &warningString); //is QByteArray better here?
|
void changeElidedTextWarningString(const QString &warningString); //is QByteArray better here?
|
||||||
|
void changeElideWarning(bool elideWarning);
|
||||||
void setDebugTranslationServiceLogFile(const QString &logFilePath);
|
void setDebugTranslationServiceLogFile(const QString &logFilePath);
|
||||||
void enableElidedTextWarning();
|
void enableElidedTextWarning();
|
||||||
void disableElidedTextWarning();
|
void disableElidedTextWarning();
|
||||||
|
452
src/plugins/qmlpreview/qmldebugtranslationwidget.cpp
Normal file
452
src/plugins/qmlpreview/qmldebugtranslationwidget.cpp
Normal file
@@ -0,0 +1,452 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "qmldebugtranslationwidget.h"
|
||||||
|
#include "qmlpreviewruncontrol.h"
|
||||||
|
#include "qmlpreviewplugin.h"
|
||||||
|
#include "projectfileselectionswidget.h"
|
||||||
|
|
||||||
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
|
#include <coreplugin/editormanager/ieditor.h>
|
||||||
|
#include <coreplugin/outputwindow.h>
|
||||||
|
|
||||||
|
#include <projectexplorer/runcontrol.h>
|
||||||
|
#include <projectexplorer/projecttree.h>
|
||||||
|
|
||||||
|
#include <utils/outputformatter.h>
|
||||||
|
#include <utils/utilsicons.h>
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
|
#include <extensionsystem/pluginmanager.h>
|
||||||
|
#include <extensionsystem/pluginspec.h>
|
||||||
|
#include <extensionsystem/iplugin.h>
|
||||||
|
|
||||||
|
#include <projectexplorer/projectnodes.h>
|
||||||
|
#include <projectexplorer/projectexplorer.h>
|
||||||
|
#include <projectexplorer/session.h>
|
||||||
|
#include <projectexplorer/target.h>
|
||||||
|
#include <projectexplorer/project.h>
|
||||||
|
#include <projectexplorer/task.h>
|
||||||
|
#include <projectexplorer/taskhub.h>
|
||||||
|
|
||||||
|
#include <qmlprojectmanager/qmlmultilanguageaspect.h>
|
||||||
|
|
||||||
|
#include <qtsupport/qtoutputformatter.h>
|
||||||
|
|
||||||
|
#include <QIcon>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QAction>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QButtonGroup>
|
||||||
|
#include <QRadioButton>
|
||||||
|
#include <QSpacerItem>
|
||||||
|
#include <QToolButton>
|
||||||
|
#include <QTextBlock>
|
||||||
|
#include <QFileDialog>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
QObject *getPreviewPlugin()
|
||||||
|
{
|
||||||
|
auto pluginIt = std::find_if(ExtensionSystem::PluginManager::plugins().begin(),
|
||||||
|
ExtensionSystem::PluginManager::plugins().end(),
|
||||||
|
[](const ExtensionSystem::PluginSpec *p) {
|
||||||
|
return p->name() == "QmlPreview";
|
||||||
|
});
|
||||||
|
|
||||||
|
if (pluginIt != ExtensionSystem::PluginManager::plugins().constEnd())
|
||||||
|
return (*pluginIt)->plugin();
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace QmlPreview {
|
||||||
|
|
||||||
|
QmlDebugTranslationWidget::QmlDebugTranslationWidget(QWidget *parent)
|
||||||
|
: QWidget(parent)
|
||||||
|
{
|
||||||
|
auto mainLayout = new QVBoxLayout(this);
|
||||||
|
|
||||||
|
auto buttonGroup = new QButtonGroup(this);
|
||||||
|
// it gets the text from updateCurrentEditor method
|
||||||
|
m_singleFileButton = new QRadioButton();
|
||||||
|
m_singleFileButton->setChecked(true);
|
||||||
|
buttonGroup->addButton(m_singleFileButton);
|
||||||
|
|
||||||
|
const QString projectSettingsKey = "QmlPreview.DisabledDebugTranslationFiles";
|
||||||
|
const ProjectExplorer::FileType filterFileType = ProjectExplorer::FileType::QML;
|
||||||
|
auto checkableProjectFileView = new ProjectFileSelectionsWidget(projectSettingsKey, filterFileType);
|
||||||
|
checkableProjectFileView->setVisible(false);
|
||||||
|
connect(checkableProjectFileView, &ProjectFileSelectionsWidget::selectionChanged, this, &QmlDebugTranslationWidget::setFiles);
|
||||||
|
m_multipleFileButton = new QRadioButton(tr("multiple files"));
|
||||||
|
// TODO: fix multiple files issues, because it have some issues disable it for now
|
||||||
|
m_multipleFileButton->setDisabled(true);
|
||||||
|
buttonGroup->addButton(m_multipleFileButton);
|
||||||
|
connect(m_multipleFileButton, &QAbstractButton::toggled, [checkableProjectFileView, this](bool checked) {
|
||||||
|
checkableProjectFileView->setVisible(checked);
|
||||||
|
setFiles(checkableProjectFileView->checkedFiles());
|
||||||
|
});
|
||||||
|
|
||||||
|
mainLayout->addWidget(m_singleFileButton);
|
||||||
|
mainLayout->addWidget(m_multipleFileButton);
|
||||||
|
mainLayout->addWidget(checkableProjectFileView);
|
||||||
|
|
||||||
|
// language checkboxes are add in updateAvailableTranslations method
|
||||||
|
m_selectLanguageLayout = new QHBoxLayout;
|
||||||
|
mainLayout->addLayout(m_selectLanguageLayout);
|
||||||
|
|
||||||
|
auto elideWarningCheckBox = new QCheckBox(tr("Enable elide warning"));
|
||||||
|
layout()->addWidget(elideWarningCheckBox);
|
||||||
|
connect(elideWarningCheckBox, &QCheckBox::stateChanged, [this] (int state) {
|
||||||
|
m_elideWarning = (state == Qt::Checked);
|
||||||
|
});
|
||||||
|
|
||||||
|
auto controlLayout = new QHBoxLayout;
|
||||||
|
mainLayout->addLayout(controlLayout);
|
||||||
|
|
||||||
|
auto showLogButton = new QToolButton;
|
||||||
|
showLogButton->setText(tr("Show log"));
|
||||||
|
showLogButton->setCheckable(true);
|
||||||
|
controlLayout->addWidget(showLogButton);
|
||||||
|
|
||||||
|
// TODO: do we still need this buttons?
|
||||||
|
// auto pauseButton = new QToolButton;
|
||||||
|
// pauseButton->setText(tr("Pause"));
|
||||||
|
// pauseButton->setCheckable(true);
|
||||||
|
// controlLayout->addWidget(pauseButton);
|
||||||
|
|
||||||
|
// auto onTheFlyButton = new QToolButton;
|
||||||
|
// onTheFlyButton->setText(tr("On the fly"));
|
||||||
|
// controlLayout->addWidget(onTheFlyButton);
|
||||||
|
|
||||||
|
m_runTestButton = new QPushButton();
|
||||||
|
m_runTestButton->setCheckable(true);
|
||||||
|
m_runTestButton->setText(runButtonText());
|
||||||
|
connect(m_runTestButton, &QPushButton::toggled, [this](bool checked) {
|
||||||
|
m_runTestButton->setText(runButtonText(checked));
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(m_runTestButton, &QPushButton::clicked, [this](bool checked) {
|
||||||
|
if (checked)
|
||||||
|
runTest();
|
||||||
|
else {
|
||||||
|
if (m_currentRunControl)
|
||||||
|
m_currentRunControl->initiateStop();
|
||||||
|
// TODO: what happens if we already have a preview running?
|
||||||
|
// QmlPreviewPlugin::stopAllRunControls();
|
||||||
|
// qWarning() << "not implemented"; // TODO: stop still running tests
|
||||||
|
}
|
||||||
|
});
|
||||||
|
controlLayout->addWidget(m_runTestButton);
|
||||||
|
|
||||||
|
m_runOutputWindow = new Core::OutputWindow(Core::Context("QmlPreview.DebugTranslation"),
|
||||||
|
"QmlPreview/OutputWindow/Zoom");
|
||||||
|
|
||||||
|
m_runOutputWindow->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||||
|
m_runOutputWindow->setReadOnly(true);
|
||||||
|
m_runOutputWindow->setVisible(false);
|
||||||
|
mainLayout->addWidget(m_runOutputWindow);
|
||||||
|
|
||||||
|
QSpacerItem *endSpacerItem = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||||
|
mainLayout->addItem(endSpacerItem);
|
||||||
|
|
||||||
|
connect(showLogButton, &QToolButton::toggled, m_runOutputWindow, [this, mainLayout, endSpacerItem](bool checked) {
|
||||||
|
m_runOutputWindow->setVisible(checked);
|
||||||
|
if (m_runOutputWindow->isVisible())
|
||||||
|
mainLayout->takeAt(mainLayout->count() - 1);
|
||||||
|
else
|
||||||
|
mainLayout->addItem(endSpacerItem);
|
||||||
|
});
|
||||||
|
|
||||||
|
auto loadLogButton = new QToolButton;
|
||||||
|
loadLogButton->setText(tr("Load"));
|
||||||
|
controlLayout->addWidget(loadLogButton);
|
||||||
|
connect(loadLogButton, &QToolButton::clicked, this, &QmlDebugTranslationWidget::loadLogFile);
|
||||||
|
|
||||||
|
auto saveLogButton = new QToolButton;
|
||||||
|
saveLogButton->setText(tr("Save"));
|
||||||
|
controlLayout->addWidget(saveLogButton);
|
||||||
|
connect(saveLogButton, &QToolButton::clicked, this, &QmlDebugTranslationWidget::saveLogToFile);
|
||||||
|
|
||||||
|
auto clearButton = new QToolButton;
|
||||||
|
clearButton->setText(tr("Clear"));
|
||||||
|
controlLayout->addWidget(clearButton);
|
||||||
|
connect(clearButton, &QToolButton::clicked, this, &QmlDebugTranslationWidget::clear);
|
||||||
|
|
||||||
|
Core::EditorManager *editorManager = Core::EditorManager::instance();
|
||||||
|
connect(editorManager, &Core::EditorManager::currentEditorChanged, this, &QmlDebugTranslationWidget::updateCurrentEditor);
|
||||||
|
updateCurrentEditor(Core::EditorManager::currentEditor());
|
||||||
|
|
||||||
|
connect(ProjectExplorer::SessionManager::instance(), &ProjectExplorer::SessionManager::startupProjectChanged,
|
||||||
|
this, &QmlDebugTranslationWidget::updateCurrentTranslations);
|
||||||
|
|
||||||
|
updateStartupProjectTranslations();
|
||||||
|
|
||||||
|
ProjectExplorer::TaskHub::addCategory("QmlPreview.Translation", tr("Translation issues"));
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlDebugTranslationWidget::~QmlDebugTranslationWidget()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlDebugTranslationWidget::updateCurrentEditor(const Core::IEditor *editor)
|
||||||
|
{
|
||||||
|
if (editor && editor->document())
|
||||||
|
m_currentFilePath = editor->document()->filePath();
|
||||||
|
else
|
||||||
|
m_currentFilePath.clear();
|
||||||
|
m_singleFileButton->setText(singleFileButtonText(m_currentFilePath.toString()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlDebugTranslationWidget::updateStartupProjectTranslations()
|
||||||
|
{
|
||||||
|
updateCurrentTranslations(ProjectExplorer::SessionManager::startupProject());
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlDebugTranslationWidget::updateCurrentTranslations(ProjectExplorer::Project *project)
|
||||||
|
{
|
||||||
|
for (int i = m_selectLanguageLayout->count()-1; i >= 0; --i) {
|
||||||
|
auto layoutItem = m_selectLanguageLayout->takeAt(i);
|
||||||
|
delete layoutItem->widget();
|
||||||
|
delete layoutItem;
|
||||||
|
}
|
||||||
|
if (!project)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (auto multiLanguageAspect = QmlProjectManager::QmlMultiLanguageAspect::current(project)) {
|
||||||
|
connect(multiLanguageAspect, &QmlProjectManager::QmlMultiLanguageAspect::changed,
|
||||||
|
this, &QmlDebugTranslationWidget::updateStartupProjectTranslations,
|
||||||
|
Qt::UniqueConnection);
|
||||||
|
if (multiLanguageAspect->value()) {
|
||||||
|
m_selectLanguageLayout->addWidget(new QLabel(
|
||||||
|
tr("Current language is \'<b>%1</b>\' can be changed in the 'Translation' tab.")
|
||||||
|
.arg(multiLanguageAspect->currentLocale())));
|
||||||
|
m_testLanguages.clear();
|
||||||
|
} else {
|
||||||
|
m_selectLanguageLayout->addWidget(new QLabel(tr("Select which language should be tested:")));
|
||||||
|
QString errorMessage;
|
||||||
|
for (auto language : project->availableQmlPreviewTranslations(&errorMessage)) {
|
||||||
|
auto languageCheckBox = new QCheckBox(language);
|
||||||
|
m_selectLanguageLayout->addWidget(languageCheckBox);
|
||||||
|
connect(languageCheckBox, &QCheckBox::stateChanged, [this, language] (int state) {
|
||||||
|
if (state == Qt::Checked)
|
||||||
|
m_testLanguages.append(language);
|
||||||
|
else
|
||||||
|
m_testLanguages.removeAll(language);
|
||||||
|
});
|
||||||
|
languageCheckBox->setChecked(true);
|
||||||
|
}
|
||||||
|
m_selectLanguageLayout->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlDebugTranslationWidget::setFiles(const Utils::FilePaths &filePathes)
|
||||||
|
{
|
||||||
|
m_selectedFilePaths = filePathes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlDebugTranslationWidget::runTest()
|
||||||
|
{
|
||||||
|
m_runOutputWindow->grayOutOldContent();
|
||||||
|
|
||||||
|
auto runControl = new ProjectExplorer::RunControl(ProjectExplorer::Constants::QML_PREVIEW_RUN_MODE);
|
||||||
|
QTC_ASSERT(runControl, qWarning("Can not create a QmlPreviewRunner"); return;);
|
||||||
|
auto previewPlugin = qobject_cast<Internal::QmlPreviewPlugin*>(getPreviewPlugin());
|
||||||
|
|
||||||
|
connect(runControl, &ProjectExplorer::RunControl::started, [this, runControl, previewPlugin]() {
|
||||||
|
//Q_ASSERT(m_currentRunControl == nullptr); //TODO: who deletes the runcontrol
|
||||||
|
m_currentRunControl = runControl;
|
||||||
|
m_runOutputWindow->setLineParsers(
|
||||||
|
ProjectExplorer::OutputFormatterFactory::createFormatters(runControl->target()));
|
||||||
|
int timerCounter = 1;
|
||||||
|
const auto testLanguageList = m_testLanguages;
|
||||||
|
|
||||||
|
auto testLanguages = [previewPlugin, runControl, testLanguageList](int timerCounter, const QString &previewedFile) {
|
||||||
|
qDebug() << "testLanguages" << previewedFile;
|
||||||
|
for (auto language : testLanguageList) {
|
||||||
|
QTimer::singleShot(timerCounter * 1000, previewPlugin, [previewPlugin, runControl, language, previewedFile]() {
|
||||||
|
if (runControl && runControl->isRunning()) {
|
||||||
|
if (!previewedFile.isEmpty())
|
||||||
|
previewPlugin->setPreviewedFile(previewedFile);
|
||||||
|
previewPlugin->setLocale(language);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (m_multipleFileButton->isChecked()) {
|
||||||
|
for (auto filePath : m_selectedFilePaths) {
|
||||||
|
testLanguages(timerCounter++, filePath.toString());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
testLanguages(timerCounter, QString());
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
connect(runControl, &ProjectExplorer::RunControl::stopped, [this]() {
|
||||||
|
m_runTestButton->setChecked(false);
|
||||||
|
//delete m_currentRunControl; // who deletes the runcontrol?
|
||||||
|
m_currentRunControl = nullptr;
|
||||||
|
if (auto previewPlugin = qobject_cast<Internal::QmlPreviewPlugin*>(getPreviewPlugin()))
|
||||||
|
previewPlugin->setLocale(m_lastUsedLanguageBeforeTest);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(runControl, &ProjectExplorer::RunControl::appendMessage,
|
||||||
|
this, &QmlDebugTranslationWidget::appendMessage);
|
||||||
|
|
||||||
|
if (auto project = ProjectExplorer::SessionManager::startupProject()) {
|
||||||
|
if (auto target = project->activeTarget()) {
|
||||||
|
if (auto multiLanguageAspect = QmlProjectManager::QmlMultiLanguageAspect::current(target))
|
||||||
|
m_lastUsedLanguageBeforeTest = multiLanguageAspect->currentLocale();
|
||||||
|
if (auto runConfiguration = target->activeRunConfiguration()) {
|
||||||
|
runControl->setRunConfiguration(runConfiguration);
|
||||||
|
if (runControl->createMainWorker()) {
|
||||||
|
previewPlugin->setLocale(QString());
|
||||||
|
runControl->initiateStart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlDebugTranslationWidget::clear()
|
||||||
|
{
|
||||||
|
m_runOutputWindow->clear();
|
||||||
|
ProjectExplorer::TaskHub::clearTasks("QmlPreview.Translation");
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QmlDebugTranslationWidget::currentDir() const
|
||||||
|
{
|
||||||
|
return m_lastDir.isEmpty() ?
|
||||||
|
ProjectExplorer::ProjectTree::currentFilePath().parentDir().toString() : m_lastDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlDebugTranslationWidget::setCurrentDir(const QString &path)
|
||||||
|
{
|
||||||
|
m_lastDir = path;
|
||||||
|
const QString currentDir = m_lastDir.isEmpty() ?
|
||||||
|
ProjectExplorer::ProjectTree::currentFilePath().parentDir().toString() : m_lastDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlDebugTranslationWidget::loadLogFile()
|
||||||
|
{
|
||||||
|
const auto fileName = QFileDialog::getOpenFileName(this, QStringLiteral("Open File"), currentDir());
|
||||||
|
if (!fileName.isEmpty()) {
|
||||||
|
setCurrentDir(QFileInfo(fileName).absolutePath());
|
||||||
|
QFile f(fileName);
|
||||||
|
if (f.open(QFile::ReadOnly)) {
|
||||||
|
clear();
|
||||||
|
while (!f.atEnd())
|
||||||
|
appendMessage(QString::fromUtf8(f.readLine()), Utils::DebugFormat);
|
||||||
|
} else {
|
||||||
|
// TODO: maybe add this message to log and tasks
|
||||||
|
qWarning() << "Failed to open" << fileName << ":" << f.errorString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlDebugTranslationWidget::saveLogToFile()
|
||||||
|
{
|
||||||
|
const QString fileName = QFileDialog::getSaveFileName(
|
||||||
|
this, tr("Choose file to save logged issues."), currentDir());
|
||||||
|
if (!fileName.isEmpty()) {
|
||||||
|
setCurrentDir(QFileInfo(fileName).absolutePath());
|
||||||
|
QFile f(fileName);
|
||||||
|
if (f.open(QFile::WriteOnly | QFile::Text))
|
||||||
|
f.write(m_runOutputWindow->toPlainText().toUtf8());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlDebugTranslationWidget::appendMessage(const QString &message, Utils::OutputFormat format)
|
||||||
|
{
|
||||||
|
const auto newLine = QRegularExpression("[\r\n]");
|
||||||
|
const auto messages = message.split(newLine, QString::SkipEmptyParts);
|
||||||
|
|
||||||
|
if (messages.count() > 1) {
|
||||||
|
for (auto m : messages)
|
||||||
|
appendMessage(m + "\n", format);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const QString serviceSeperator = ": QQmlDebugTranslationService: ";
|
||||||
|
if (!message.contains(serviceSeperator) || message.contains("DebugTranslation service - language changed"))
|
||||||
|
return;
|
||||||
|
QString locationString = message;
|
||||||
|
locationString = locationString.split(serviceSeperator).first();
|
||||||
|
static const QRegularExpression qmlLineColumnLink("^(" QT_QML_URL_REGEXP ")" // url
|
||||||
|
":(\\d+)" // line
|
||||||
|
":(\\d+)$"); // column
|
||||||
|
const QRegularExpressionMatch qmlLineColumnMatch = qmlLineColumnLink.match(locationString);
|
||||||
|
|
||||||
|
auto fileLine = -1;
|
||||||
|
QUrl fileUrl;
|
||||||
|
if (qmlLineColumnMatch.hasMatch()) {
|
||||||
|
fileUrl = QUrl(qmlLineColumnMatch.captured(1));
|
||||||
|
fileLine = qmlLineColumnMatch.captured(2).toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_runOutputWindow->appendMessage(message, format);
|
||||||
|
|
||||||
|
|
||||||
|
auto type = ProjectExplorer::Task::TaskType::Warning;
|
||||||
|
auto description = message.split(serviceSeperator).at(1);
|
||||||
|
auto filePath = Utils::FilePath::fromString(fileUrl.toLocalFile());
|
||||||
|
auto category = "QmlPreview.Translation";
|
||||||
|
auto icon = Utils::Icons::WARNING.icon();
|
||||||
|
|
||||||
|
ProjectExplorer::TaskHub::addTask(ProjectExplorer::Task(type,
|
||||||
|
description,
|
||||||
|
filePath,
|
||||||
|
fileLine,
|
||||||
|
category,
|
||||||
|
icon,
|
||||||
|
ProjectExplorer::Task::NoOptions));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QmlDebugTranslationWidget::singleFileButtonText(const QString &filePath)
|
||||||
|
{
|
||||||
|
auto buttonText = tr("current file: %1");
|
||||||
|
if (filePath.isEmpty())
|
||||||
|
return buttonText.arg(tr("empty"));
|
||||||
|
return buttonText.arg(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QmlDebugTranslationWidget::runButtonText(bool isRunning)
|
||||||
|
{
|
||||||
|
if (isRunning) {
|
||||||
|
return tr("Stop");
|
||||||
|
}
|
||||||
|
return tr("Run language tests");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace QmlPreview
|
95
src/plugins/qmlpreview/qmldebugtranslationwidget.h
Normal file
95
src/plugins/qmlpreview/qmldebugtranslationwidget.h
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "qmlpreview_global.h"
|
||||||
|
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
#include <utils/outputformat.h>
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QRadioButton;
|
||||||
|
class QPushButton;
|
||||||
|
class QHBoxLayout;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class IEditor;
|
||||||
|
class OutputWindow;
|
||||||
|
}
|
||||||
|
namespace ProjectExplorer {
|
||||||
|
class Project;
|
||||||
|
class RunControl;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace QmlPreview {
|
||||||
|
|
||||||
|
class QMLPREVIEW_EXPORT QmlDebugTranslationWidget : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit QmlDebugTranslationWidget(QWidget *parent = nullptr);
|
||||||
|
~QmlDebugTranslationWidget() override;
|
||||||
|
|
||||||
|
void setCurrentFile(const Utils::FilePath &filepath);
|
||||||
|
void setFiles(const Utils::FilePaths &filePathes);
|
||||||
|
void updateStartupProjectTranslations();
|
||||||
|
private:
|
||||||
|
void updateCurrentEditor(const Core::IEditor *editor);
|
||||||
|
void updateCurrentTranslations(ProjectExplorer::Project *project);
|
||||||
|
void runTest();
|
||||||
|
void appendMessage(const QString &message, Utils::OutputFormat format);
|
||||||
|
void clear();
|
||||||
|
void loadLogFile();
|
||||||
|
void saveLogToFile();
|
||||||
|
QString currentDir() const;
|
||||||
|
void setCurrentDir(const QString &path);
|
||||||
|
|
||||||
|
QString singleFileButtonText(const QString &filePath);
|
||||||
|
QString runButtonText(bool isRunning = false);
|
||||||
|
|
||||||
|
QStringList m_testLanguages;
|
||||||
|
QString m_lastUsedLanguageBeforeTest;
|
||||||
|
bool m_elideWarning = false;
|
||||||
|
|
||||||
|
Core::OutputWindow *m_runOutputWindow = nullptr;
|
||||||
|
|
||||||
|
QRadioButton *m_singleFileButton = nullptr;
|
||||||
|
QRadioButton *m_multipleFileButton = nullptr;
|
||||||
|
QPushButton *m_runTestButton = nullptr;
|
||||||
|
|
||||||
|
Utils::FilePath m_currentFilePath;
|
||||||
|
Utils::FilePaths m_selectedFilePaths;
|
||||||
|
ProjectExplorer::RunControl *m_currentRunControl = nullptr;
|
||||||
|
|
||||||
|
QString m_lastDir;
|
||||||
|
|
||||||
|
QHBoxLayout *m_selectLanguageLayout;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QmlPreview
|
@@ -10,19 +10,23 @@ include(tests/tests.pri)
|
|||||||
HEADERS += \
|
HEADERS += \
|
||||||
qmlpreview_global.h \
|
qmlpreview_global.h \
|
||||||
qmldebugtranslationclient.h \
|
qmldebugtranslationclient.h \
|
||||||
|
qmldebugtranslationwidget.h \
|
||||||
qmlpreviewclient.h \
|
qmlpreviewclient.h \
|
||||||
qmlpreviewplugin.h \
|
qmlpreviewplugin.h \
|
||||||
qmlpreviewruncontrol.h \
|
qmlpreviewruncontrol.h \
|
||||||
qmlpreviewconnectionmanager.h \
|
qmlpreviewconnectionmanager.h \
|
||||||
qmlpreviewfileontargetfinder.h
|
qmlpreviewfileontargetfinder.h \
|
||||||
|
projectfileselectionswidget.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
qmlpreviewplugin.cpp \
|
qmlpreviewplugin.cpp \
|
||||||
qmldebugtranslationclient.cpp \
|
qmldebugtranslationclient.cpp \
|
||||||
|
qmldebugtranslationwidget.cpp \
|
||||||
qmlpreviewclient.cpp \
|
qmlpreviewclient.cpp \
|
||||||
qmlpreviewruncontrol.cpp \
|
qmlpreviewruncontrol.cpp \
|
||||||
qmlpreviewconnectionmanager.cpp \
|
qmlpreviewconnectionmanager.cpp \
|
||||||
qmlpreviewfileontargetfinder.cpp
|
qmlpreviewfileontargetfinder.cpp \
|
||||||
|
projectfileselectionswidget.cpp
|
||||||
|
|
||||||
OTHER_FILES += \
|
OTHER_FILES += \
|
||||||
QmlPreview.json.in
|
QmlPreview.json.in
|
||||||
|
@@ -26,6 +26,8 @@ QtcPlugin {
|
|||||||
"qmlpreviewclient.h",
|
"qmlpreviewclient.h",
|
||||||
"qmldebugtranslationclient.cpp",
|
"qmldebugtranslationclient.cpp",
|
||||||
"qmldebugtranslationclient.h",
|
"qmldebugtranslationclient.h",
|
||||||
|
"qmldebugtranslationwidget.cpp",
|
||||||
|
"qmldebugtranslationwidget.h",
|
||||||
"qmlpreviewconnectionmanager.cpp",
|
"qmlpreviewconnectionmanager.cpp",
|
||||||
"qmlpreviewconnectionmanager.h",
|
"qmlpreviewconnectionmanager.h",
|
||||||
"qmlpreviewfileontargetfinder.cpp",
|
"qmlpreviewfileontargetfinder.cpp",
|
||||||
@@ -35,6 +37,8 @@ QtcPlugin {
|
|||||||
"qmlpreviewplugin.h",
|
"qmlpreviewplugin.h",
|
||||||
"qmlpreviewruncontrol.cpp",
|
"qmlpreviewruncontrol.cpp",
|
||||||
"qmlpreviewruncontrol.h",
|
"qmlpreviewruncontrol.h",
|
||||||
|
"projectfileselectionswidget.cpp",
|
||||||
|
"projectfileselectionswidget.h"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -76,17 +76,22 @@ void QmlPreviewConnectionManager::createClients()
|
|||||||
|
|
||||||
QUrl QmlPreviewConnectionManager::findValidI18nDirectoryAsUrl(const QString &locale)
|
QUrl QmlPreviewConnectionManager::findValidI18nDirectoryAsUrl(const QString &locale)
|
||||||
{
|
{
|
||||||
|
QTC_ASSERT(!m_lastLoadedUrl.isEmpty(), return {};);
|
||||||
|
|
||||||
const QString shortLocale = locale.left(locale.indexOf("_"));
|
const QString shortLocale = locale.left(locale.indexOf("_"));
|
||||||
QString path = m_lastLoadedUrl.path();
|
QString path = m_lastLoadedUrl.path();
|
||||||
|
|
||||||
|
QString foundPath;
|
||||||
while (!path.isEmpty()) {
|
while (!path.isEmpty()) {
|
||||||
path = path.left(qMax(0, path.lastIndexOf("/")));
|
path = path.left(qMax(0, path.lastIndexOf("/")));
|
||||||
QUrl url = m_lastLoadedUrl;
|
QUrl url = m_lastLoadedUrl;
|
||||||
|
|
||||||
|
|
||||||
auto tryPath = [&](const QString &postfix) {
|
auto tryPath = [&](const QString &postfix) {
|
||||||
url.setPath(path + "/i18n/qml_" + postfix);
|
url.setPath(path + "/i18n/qml_" + postfix);
|
||||||
bool success = false;
|
bool success = false;
|
||||||
m_projectFileFinder.findFile(url, &success);
|
foundPath = m_projectFileFinder.findFile(url, &success).first().toString();
|
||||||
|
foundPath = foundPath.left(qMax(0, foundPath.lastIndexOf("/i18n")));
|
||||||
return success;
|
return success;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -101,21 +106,32 @@ QUrl QmlPreviewConnectionManager::findValidI18nDirectoryAsUrl(const QString &loc
|
|||||||
}
|
}
|
||||||
|
|
||||||
QUrl url = m_lastLoadedUrl;
|
QUrl url = m_lastLoadedUrl;
|
||||||
|
if (foundPath.isEmpty())
|
||||||
url.setPath(path);
|
url.setPath(path);
|
||||||
|
else
|
||||||
|
url.setPath(foundPath);
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlPreviewConnectionManager::createDebugTranslationClient()
|
void QmlPreviewConnectionManager::createDebugTranslationClient()
|
||||||
{
|
{
|
||||||
m_qmlDebugTranslationClient = new QmlDebugTranslationClient(connection());
|
m_qmlDebugTranslationClient = new QmlDebugTranslationClient(connection());
|
||||||
QObject::connect(this, &QmlPreviewConnectionManager::language,
|
connect(this, &QmlPreviewConnectionManager::language,
|
||||||
m_qmlDebugTranslationClient.data(), [this](const QString &locale) {
|
m_qmlDebugTranslationClient.data(), [this](const QString &locale) {
|
||||||
|
|
||||||
|
if (m_lastLoadedUrl.isEmpty()) {
|
||||||
|
// findValidI18nDirectoryAsUrl does not work if we didn't load any file
|
||||||
|
m_initLocale = locale;
|
||||||
|
} else {
|
||||||
// service expects a context URL.
|
// service expects a context URL.
|
||||||
// Search the parent directories of the last loaded URL for i18n files.
|
// Search the parent directories of the last loaded URL for i18n files.
|
||||||
m_qmlDebugTranslationClient->changeLanguage(findValidI18nDirectoryAsUrl(locale), locale);
|
m_qmlDebugTranslationClient->changeLanguage(findValidI18nDirectoryAsUrl(locale), locale);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
QObject::connect(m_qmlDebugTranslationClient.data(), &QmlDebugTranslationClient::debugServiceUnavailable,
|
connect(this, &QmlPreviewConnectionManager::changeElideWarning,
|
||||||
|
m_qmlDebugTranslationClient, &QmlDebugTranslationClient::changeElideWarning);
|
||||||
|
|
||||||
|
connect(m_qmlDebugTranslationClient.data(), &QmlDebugTranslationClient::debugServiceUnavailable,
|
||||||
this, []() {
|
this, []() {
|
||||||
QMessageBox::warning(Core::ICore::dialogParent(), "Error connect to QML DebugTranslation service",
|
QMessageBox::warning(Core::ICore::dialogParent(), "Error connect to QML DebugTranslation service",
|
||||||
"QML DebugTranslation feature is not available for this version of Qt.");
|
"QML DebugTranslation feature is not available for this version of Qt.");
|
||||||
@@ -126,8 +142,7 @@ void QmlPreviewConnectionManager::createPreviewClient()
|
|||||||
{
|
{
|
||||||
m_qmlPreviewClient = new QmlPreviewClient(connection());
|
m_qmlPreviewClient = new QmlPreviewClient(connection());
|
||||||
|
|
||||||
QObject::connect(
|
connect(this, &QmlPreviewConnectionManager::loadFile, m_qmlPreviewClient.data(),
|
||||||
this, &QmlPreviewConnectionManager::loadFile, m_qmlPreviewClient.data(),
|
|
||||||
[this](const QString &filename, const QString &changedFile,
|
[this](const QString &filename, const QString &changedFile,
|
||||||
const QByteArray &contents) {
|
const QByteArray &contents) {
|
||||||
if (!m_fileClassifier(changedFile)) {
|
if (!m_fileClassifier(changedFile)) {
|
||||||
@@ -144,23 +159,32 @@ void QmlPreviewConnectionManager::createPreviewClient()
|
|||||||
|
|
||||||
m_lastLoadedUrl = m_targetFileFinder.findUrl(filename);
|
m_lastLoadedUrl = m_targetFileFinder.findUrl(filename);
|
||||||
m_qmlPreviewClient->loadUrl(m_lastLoadedUrl);
|
m_qmlPreviewClient->loadUrl(m_lastLoadedUrl);
|
||||||
|
if (!m_initLocale.isEmpty()) {
|
||||||
|
emit language(m_initLocale);
|
||||||
|
m_initLocale.clear();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
QObject::connect(this, &QmlPreviewConnectionManager::rerun,
|
connect(this, &QmlPreviewConnectionManager::rerun,
|
||||||
m_qmlPreviewClient.data(), &QmlPreviewClient::rerun);
|
m_qmlPreviewClient.data(), &QmlPreviewClient::rerun);
|
||||||
|
|
||||||
QObject::connect(this, &QmlPreviewConnectionManager::zoom,
|
connect(this, &QmlPreviewConnectionManager::zoom,
|
||||||
m_qmlPreviewClient.data(), &QmlPreviewClient::zoom);
|
m_qmlPreviewClient.data(), &QmlPreviewClient::zoom);
|
||||||
|
|
||||||
QObject::connect(this, &QmlPreviewConnectionManager::language,
|
connect(this, &QmlPreviewConnectionManager::language,
|
||||||
m_qmlPreviewClient.data(), [this](const QString &locale) {
|
m_qmlPreviewClient.data(), [this](const QString &locale) {
|
||||||
|
|
||||||
|
if (m_lastLoadedUrl.isEmpty()) {
|
||||||
|
// findValidI18nDirectoryAsUrl does not work if we didn't load any file
|
||||||
|
m_initLocale = locale;
|
||||||
|
} else {
|
||||||
// service expects a context URL.
|
// service expects a context URL.
|
||||||
// Search the parent directories of the last loaded URL for i18n files.
|
// Search the parent directories of the last loaded URL for i18n files.
|
||||||
m_qmlPreviewClient->language(findValidI18nDirectoryAsUrl(locale), locale);
|
m_qmlPreviewClient->language(findValidI18nDirectoryAsUrl(locale), locale);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
QObject::connect(m_qmlPreviewClient.data(), &QmlPreviewClient::pathRequested,
|
connect(m_qmlPreviewClient.data(), &QmlPreviewClient::pathRequested,
|
||||||
this, [this](const QString &path) {
|
this, [this](const QString &path) {
|
||||||
const bool found = m_projectFileFinder.findFileOrDirectory(
|
const bool found = m_projectFileFinder.findFileOrDirectory(
|
||||||
path, [&](const QString &filename, int confidence) {
|
path, [&](const QString &filename, int confidence) {
|
||||||
@@ -190,13 +214,13 @@ void QmlPreviewConnectionManager::createPreviewClient()
|
|||||||
m_qmlPreviewClient->announceError(path);
|
m_qmlPreviewClient->announceError(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
QObject::connect(m_qmlPreviewClient.data(), &QmlPreviewClient::errorReported,
|
connect(m_qmlPreviewClient.data(), &QmlPreviewClient::errorReported,
|
||||||
this, [](const QString &error) {
|
this, [](const QString &error) {
|
||||||
Core::MessageManager::write("Error loading QML Live Preview:");
|
Core::MessageManager::write("Error loading QML Live Preview:");
|
||||||
Core::MessageManager::write(error);
|
Core::MessageManager::write(error);
|
||||||
});
|
});
|
||||||
|
|
||||||
QObject::connect(m_qmlPreviewClient.data(), &QmlPreviewClient::fpsReported,
|
connect(m_qmlPreviewClient.data(), &QmlPreviewClient::fpsReported,
|
||||||
this, [this](const QmlPreviewClient::FpsInfo &frames) {
|
this, [this](const QmlPreviewClient::FpsInfo &frames) {
|
||||||
if (m_fpsHandler) {
|
if (m_fpsHandler) {
|
||||||
quint16 stats[] = {
|
quint16 stats[] = {
|
||||||
@@ -207,13 +231,13 @@ void QmlPreviewConnectionManager::createPreviewClient()
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
QObject::connect(m_qmlPreviewClient.data(), &QmlPreviewClient::debugServiceUnavailable,
|
connect(m_qmlPreviewClient.data(), &QmlPreviewClient::debugServiceUnavailable,
|
||||||
this, []() {
|
this, []() {
|
||||||
QMessageBox::warning(Core::ICore::dialogParent(), "Error loading QML Live Preview",
|
QMessageBox::warning(Core::ICore::dialogParent(), "Error loading QML Live Preview",
|
||||||
"QML Live Preview is not available for this version of Qt.");
|
"QML Live Preview is not available for this version of Qt.");
|
||||||
}, Qt::QueuedConnection); // Queue it, so that it interfere with the connection timer
|
}, Qt::QueuedConnection); // Queue it, so that it interfere with the connection timer
|
||||||
|
|
||||||
QObject::connect(&m_fileSystemWatcher, &Utils::FileSystemWatcher::fileChanged,
|
connect(&m_fileSystemWatcher, &Utils::FileSystemWatcher::fileChanged,
|
||||||
m_qmlPreviewClient.data(), [this](const QString &changedFile) {
|
m_qmlPreviewClient.data(), [this](const QString &changedFile) {
|
||||||
if (!m_fileLoader || !m_lastLoadedUrl.isValid())
|
if (!m_fileLoader || !m_lastLoadedUrl.isValid())
|
||||||
return;
|
return;
|
||||||
|
@@ -57,6 +57,7 @@ signals:
|
|||||||
void loadFile(const QString &filename, const QString &changedFile, const QByteArray &contents);
|
void loadFile(const QString &filename, const QString &changedFile, const QByteArray &contents);
|
||||||
void zoom(float zoomFactor);
|
void zoom(float zoomFactor);
|
||||||
void language(const QString &locale);
|
void language(const QString &locale);
|
||||||
|
void changeElideWarning(bool elideWarning);
|
||||||
void rerun();
|
void rerun();
|
||||||
void restart();
|
void restart();
|
||||||
|
|
||||||
@@ -78,6 +79,7 @@ private:
|
|||||||
QmlPreviewFileLoader m_fileLoader = nullptr;
|
QmlPreviewFileLoader m_fileLoader = nullptr;
|
||||||
QmlPreviewFileClassifier m_fileClassifier = nullptr;
|
QmlPreviewFileClassifier m_fileClassifier = nullptr;
|
||||||
QmlPreviewFpsHandler m_fpsHandler = nullptr;
|
QmlPreviewFpsHandler m_fpsHandler = nullptr;
|
||||||
|
QString m_initLocale;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -26,11 +26,14 @@
|
|||||||
#include "qmlpreviewplugin.h"
|
#include "qmlpreviewplugin.h"
|
||||||
#include "qmlpreviewruncontrol.h"
|
#include "qmlpreviewruncontrol.h"
|
||||||
|
|
||||||
|
#include "qmldebugtranslationwidget.h"
|
||||||
|
|
||||||
#ifdef WITH_TESTS
|
#ifdef WITH_TESTS
|
||||||
#include "tests/qmlpreviewclient_test.h"
|
#include "tests/qmlpreviewclient_test.h"
|
||||||
#include "tests/qmlpreviewplugin_test.h"
|
#include "tests/qmlpreviewplugin_test.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
#include <coreplugin/actionmanager/actionmanager.h>
|
#include <coreplugin/actionmanager/actionmanager.h>
|
||||||
#include <coreplugin/actionmanager/actioncontainer.h>
|
#include <coreplugin/actionmanager/actioncontainer.h>
|
||||||
#include <coreplugin/editormanager/editormanager.h>
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
@@ -53,6 +56,12 @@
|
|||||||
#include <qmljs/qmljsmodelmanagerinterface.h>
|
#include <qmljs/qmljsmodelmanagerinterface.h>
|
||||||
#include <qmljstools/qmljstoolsconstants.h>
|
#include <qmljstools/qmljstoolsconstants.h>
|
||||||
|
|
||||||
|
#include <qmlprojectmanager/qmlmultilanguageaspect.h>
|
||||||
|
|
||||||
|
#include <qtsupport/qtkitinformation.h>
|
||||||
|
#include <qtsupport/qtversionmanager.h>
|
||||||
|
#include <qtsupport/baseqtversion.h>
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
|
|
||||||
using namespace ProjectExplorer;
|
using namespace ProjectExplorer;
|
||||||
@@ -142,6 +151,8 @@ public:
|
|||||||
float m_zoomFactor = -1.0;
|
float m_zoomFactor = -1.0;
|
||||||
QmlPreview::QmlPreviewFpsHandler m_fpsHandler = nullptr;
|
QmlPreview::QmlPreviewFpsHandler m_fpsHandler = nullptr;
|
||||||
QString m_locale;
|
QString m_locale;
|
||||||
|
bool elideWarning = false;
|
||||||
|
QPointer<QmlDebugTranslationWidget> m_qmlDebugTranslationWidget;
|
||||||
|
|
||||||
RunWorkerFactory localRunWorkerFactory{
|
RunWorkerFactory localRunWorkerFactory{
|
||||||
RunWorkerFactory::make<LocalQmlPreviewSupport>(),
|
RunWorkerFactory::make<LocalQmlPreviewSupport>(),
|
||||||
@@ -153,7 +164,7 @@ public:
|
|||||||
RunWorkerFactory runWorkerFactory{
|
RunWorkerFactory runWorkerFactory{
|
||||||
[this](RunControl *runControl) {
|
[this](RunControl *runControl) {
|
||||||
QmlPreviewRunner *runner = new QmlPreviewRunner(runControl, m_fileLoader, m_fileClassifer,
|
QmlPreviewRunner *runner = new QmlPreviewRunner(runControl, m_fileLoader, m_fileClassifer,
|
||||||
m_fpsHandler, m_zoomFactor, m_locale);
|
m_fpsHandler, m_zoomFactor);
|
||||||
connect(q, &QmlPreviewPlugin::updatePreviews,
|
connect(q, &QmlPreviewPlugin::updatePreviews,
|
||||||
runner, &QmlPreviewRunner::loadFile);
|
runner, &QmlPreviewRunner::loadFile);
|
||||||
connect(q, &QmlPreviewPlugin::rerunPreviews,
|
connect(q, &QmlPreviewPlugin::rerunPreviews,
|
||||||
@@ -164,6 +175,8 @@ public:
|
|||||||
runner, &QmlPreviewRunner::zoom);
|
runner, &QmlPreviewRunner::zoom);
|
||||||
connect(q, &QmlPreviewPlugin::localeChanged,
|
connect(q, &QmlPreviewPlugin::localeChanged,
|
||||||
runner, &QmlPreviewRunner::language);
|
runner, &QmlPreviewRunner::language);
|
||||||
|
connect(q, &QmlPreviewPlugin::elideWarningChanged,
|
||||||
|
runner, &QmlPreviewRunner::changeElideWarning);
|
||||||
|
|
||||||
connect(runner, &RunWorker::started, this, [this, runControl] {
|
connect(runner, &RunWorker::started, this, [this, runControl] {
|
||||||
addPreview(runControl);
|
addPreview(runControl);
|
||||||
@@ -192,13 +205,60 @@ QmlPreviewPluginPrivate::QmlPreviewPluginPrivate(QmlPreviewPlugin *parent)
|
|||||||
action->setEnabled(SessionManager::startupProject() != nullptr);
|
action->setEnabled(SessionManager::startupProject() != nullptr);
|
||||||
connect(SessionManager::instance(), &SessionManager::startupProjectChanged, action,
|
connect(SessionManager::instance(), &SessionManager::startupProjectChanged, action,
|
||||||
&QAction::setEnabled);
|
&QAction::setEnabled);
|
||||||
connect(action, &QAction::triggered, this, []() {
|
connect(action, &QAction::triggered, this, [this]() {
|
||||||
|
if (auto multiLanguageAspect = QmlProjectManager::QmlMultiLanguageAspect::current())
|
||||||
|
m_locale = multiLanguageAspect->currentLocale();
|
||||||
|
|
||||||
ProjectExplorerPlugin::runStartupProject(Constants::QML_PREVIEW_RUN_MODE);
|
ProjectExplorerPlugin::runStartupProject(Constants::QML_PREVIEW_RUN_MODE);
|
||||||
});
|
});
|
||||||
menu->addAction(Core::ActionManager::registerAction(action, "QmlPreview.Internal"),
|
menu->addAction(
|
||||||
|
Core::ActionManager::registerAction(action, "QmlPreview.RunPreview"),
|
||||||
Constants::G_BUILD_RUN);
|
Constants::G_BUILD_RUN);
|
||||||
|
|
||||||
Core::Context projectTreeContext(Constants::C_PROJECT_TREE);
|
action = new QAction(QmlPreviewPlugin::tr("Test translations"), this);
|
||||||
|
action->setToolTip(QLatin1String("Runs the preview with all available translations and collects all issues."));
|
||||||
|
action->setEnabled(SessionManager::startupProject() != nullptr);
|
||||||
|
connect(SessionManager::instance(), &SessionManager::startupProjectChanged, action,
|
||||||
|
&QAction::setEnabled);
|
||||||
|
connect(action, &QAction::triggered, this, [this]() {
|
||||||
|
if (SessionManager::startupProject()) {
|
||||||
|
// Deletion for this widget is taken care of in aboutToShutdown() and registerWindow()
|
||||||
|
m_qmlDebugTranslationWidget = new QmlDebugTranslationWidget();
|
||||||
|
Core::ICore::registerWindow(m_qmlDebugTranslationWidget, Core::Context("Core.DebugTranslation"));
|
||||||
|
m_qmlDebugTranslationWidget->show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
menu->addAction(
|
||||||
|
Core::ActionManager::registerAction(action, "QmlPreview.TestTranslations"),
|
||||||
|
Constants::G_BUILD_RUN);
|
||||||
|
auto updateTestTranslationAction = [action]() {
|
||||||
|
bool showTestTranslationAction = false;
|
||||||
|
bool enableTestTranslationAction = false;
|
||||||
|
QtSupport::BaseQtVersion *activeQt{};
|
||||||
|
if (auto project = SessionManager::startupProject()) {
|
||||||
|
if (auto target = project->activeTarget()) {
|
||||||
|
if (auto activeKit = target->kit())
|
||||||
|
activeQt = QtSupport::QtKitAspect::qtVersion(activeKit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto qtVersion : QtSupport::QtVersionManager::versions()) {
|
||||||
|
if (qtVersion->features().contains("QtStudio")) {
|
||||||
|
showTestTranslationAction = true;
|
||||||
|
if (qtVersion == activeQt)
|
||||||
|
enableTestTranslationAction = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
action->setVisible(showTestTranslationAction);
|
||||||
|
action->setEnabled(enableTestTranslationAction);
|
||||||
|
};
|
||||||
|
connect(ProjectExplorer::SessionManager::instance(),
|
||||||
|
&ProjectExplorer::SessionManager::startupProjectChanged,
|
||||||
|
updateTestTranslationAction);
|
||||||
|
|
||||||
|
connect(QtSupport::QtVersionManager::instance(),
|
||||||
|
&QtSupport::QtVersionManager::qtVersionsChanged,
|
||||||
|
updateTestTranslationAction);
|
||||||
|
|
||||||
menu = Core::ActionManager::actionContainer(Constants::M_FILECONTEXT);
|
menu = Core::ActionManager::actionContainer(Constants::M_FILECONTEXT);
|
||||||
action = new QAction(QmlPreviewPlugin::tr("Preview File"), this);
|
action = new QAction(QmlPreviewPlugin::tr("Preview File"), this);
|
||||||
action->setEnabled(false);
|
action->setEnabled(false);
|
||||||
@@ -207,8 +267,8 @@ QmlPreviewPluginPrivate::QmlPreviewPluginPrivate(QmlPreviewPlugin *parent)
|
|||||||
action->setEnabled(!previews.isEmpty());
|
action->setEnabled(!previews.isEmpty());
|
||||||
});
|
});
|
||||||
connect(action, &QAction::triggered, this, &QmlPreviewPluginPrivate::previewCurrentFile);
|
connect(action, &QAction::triggered, this, &QmlPreviewPluginPrivate::previewCurrentFile);
|
||||||
menu->addAction(Core::ActionManager::registerAction(action, "QmlPreview.Preview",
|
menu->addAction(
|
||||||
projectTreeContext),
|
Core::ActionManager::registerAction(action, "QmlPreview.PreviewFile", Core::Context(Constants::C_PROJECT_TREE)),
|
||||||
Constants::G_FILE_OTHER);
|
Constants::G_FILE_OTHER);
|
||||||
action->setVisible(false);
|
action->setVisible(false);
|
||||||
connect(ProjectTree::instance(), &ProjectTree::currentNodeChanged, action, [action]() {
|
connect(ProjectTree::instance(), &ProjectTree::currentNodeChanged, action, [action]() {
|
||||||
@@ -247,6 +307,7 @@ ExtensionSystem::IPlugin::ShutdownFlag QmlPreviewPlugin::aboutToShutdown()
|
|||||||
{
|
{
|
||||||
d->m_parseThread.quit();
|
d->m_parseThread.quit();
|
||||||
d->m_parseThread.wait();
|
d->m_parseThread.wait();
|
||||||
|
delete d->m_qmlDebugTranslationWidget;
|
||||||
return SynchronousShutdown;
|
return SynchronousShutdown;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,6 +394,8 @@ QString QmlPreviewPlugin::locale() const
|
|||||||
|
|
||||||
void QmlPreviewPlugin::setLocale(const QString &locale)
|
void QmlPreviewPlugin::setLocale(const QString &locale)
|
||||||
{
|
{
|
||||||
|
if (auto multiLanguageAspect = QmlProjectManager::QmlMultiLanguageAspect::current())
|
||||||
|
multiLanguageAspect->setCurrentLocale(locale);
|
||||||
if (d->m_locale == locale)
|
if (d->m_locale == locale)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -340,6 +403,16 @@ void QmlPreviewPlugin::setLocale(const QString &locale)
|
|||||||
emit localeChanged(d->m_locale);
|
emit localeChanged(d->m_locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool QmlPreviewPlugin::elideWarning() const
|
||||||
|
{
|
||||||
|
return d->elideWarning;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlPreviewPlugin::changeElideWarning(bool elideWarning)
|
||||||
|
{
|
||||||
|
d->elideWarning = elideWarning;
|
||||||
|
}
|
||||||
|
|
||||||
void QmlPreviewPlugin::setFileLoader(QmlPreviewFileLoader fileLoader)
|
void QmlPreviewPlugin::setFileLoader(QmlPreviewFileLoader fileLoader)
|
||||||
{
|
{
|
||||||
if (d->m_fileLoader == fileLoader)
|
if (d->m_fileLoader == fileLoader)
|
||||||
@@ -412,6 +485,10 @@ void QmlPreviewPluginPrivate::setDirty()
|
|||||||
void QmlPreviewPluginPrivate::addPreview(ProjectExplorer::RunControl *preview)
|
void QmlPreviewPluginPrivate::addPreview(ProjectExplorer::RunControl *preview)
|
||||||
{
|
{
|
||||||
m_runningPreviews.append(preview);
|
m_runningPreviews.append(preview);
|
||||||
|
if (auto multiLanguageAspect = preview->aspect<QmlProjectManager::QmlMultiLanguageAspect>()) {
|
||||||
|
connect(multiLanguageAspect, &QmlProjectManager::QmlMultiLanguageAspect::changed,
|
||||||
|
preview, &ProjectExplorer::RunControl::initiateStop);
|
||||||
|
}
|
||||||
emit q->runningPreviewsChanged(m_runningPreviews);
|
emit q->runningPreviewsChanged(m_runningPreviews);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -59,6 +59,7 @@ class QmlPreviewPlugin : public ExtensionSystem::IPlugin
|
|||||||
WRITE setFpsHandler NOTIFY fpsHandlerChanged)
|
WRITE setFpsHandler NOTIFY fpsHandlerChanged)
|
||||||
Q_PROPERTY(float zoomFactor READ zoomFactor WRITE setZoomFactor NOTIFY zoomFactorChanged)
|
Q_PROPERTY(float zoomFactor READ zoomFactor WRITE setZoomFactor NOTIFY zoomFactorChanged)
|
||||||
Q_PROPERTY(QString locale READ locale WRITE setLocale NOTIFY localeChanged)
|
Q_PROPERTY(QString locale READ locale WRITE setLocale NOTIFY localeChanged)
|
||||||
|
Q_PROPERTY(bool elideWarning READ elideWarning WRITE changeElideWarning NOTIFY elideWarningChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~QmlPreviewPlugin() override;
|
~QmlPreviewPlugin() override;
|
||||||
@@ -86,6 +87,9 @@ public:
|
|||||||
QString locale() const;
|
QString locale() const;
|
||||||
void setLocale(const QString &locale);
|
void setLocale(const QString &locale);
|
||||||
|
|
||||||
|
bool elideWarning() const;
|
||||||
|
void changeElideWarning(bool elideWarning);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void checkDocument(const QString &name, const QByteArray &contents,
|
void checkDocument(const QString &name, const QByteArray &contents,
|
||||||
QmlJS::Dialect::Enum dialect);
|
QmlJS::Dialect::Enum dialect);
|
||||||
@@ -100,6 +104,7 @@ signals:
|
|||||||
|
|
||||||
void zoomFactorChanged(float zoomFactor);
|
void zoomFactorChanged(float zoomFactor);
|
||||||
void localeChanged(const QString &locale);
|
void localeChanged(const QString &locale);
|
||||||
|
void elideWarningChanged(bool elideWarning);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class QmlPreviewPluginPrivate *d = nullptr;
|
class QmlPreviewPluginPrivate *d = nullptr;
|
||||||
|
@@ -27,7 +27,6 @@
|
|||||||
|
|
||||||
#include <qmlprojectmanager/qmlproject.h>
|
#include <qmlprojectmanager/qmlproject.h>
|
||||||
#include <qmlprojectmanager/qmlmainfileaspect.h>
|
#include <qmlprojectmanager/qmlmainfileaspect.h>
|
||||||
#include <qmlprojectmanager/qmlmultilanguageaspect.h>
|
|
||||||
|
|
||||||
#include <projectexplorer/projectexplorer.h>
|
#include <projectexplorer/projectexplorer.h>
|
||||||
#include <projectexplorer/session.h>
|
#include <projectexplorer/session.h>
|
||||||
@@ -50,8 +49,7 @@ QmlPreviewRunner::QmlPreviewRunner(ProjectExplorer::RunControl *runControl,
|
|||||||
QmlPreviewFileLoader fileLoader,
|
QmlPreviewFileLoader fileLoader,
|
||||||
QmlPreviewFileClassifier fileClassifier,
|
QmlPreviewFileClassifier fileClassifier,
|
||||||
QmlPreviewFpsHandler fpsHandler,
|
QmlPreviewFpsHandler fpsHandler,
|
||||||
float initialZoom,
|
float initialZoom)
|
||||||
const QString &initialLocale)
|
|
||||||
: RunWorker(runControl)
|
: RunWorker(runControl)
|
||||||
{
|
{
|
||||||
setId("QmlPreviewRunner");
|
setId("QmlPreviewRunner");
|
||||||
@@ -68,12 +66,13 @@ QmlPreviewRunner::QmlPreviewRunner(ProjectExplorer::RunControl *runControl,
|
|||||||
&m_connectionManager, &Internal::QmlPreviewConnectionManager::zoom);
|
&m_connectionManager, &Internal::QmlPreviewConnectionManager::zoom);
|
||||||
connect(this, &QmlPreviewRunner::language,
|
connect(this, &QmlPreviewRunner::language,
|
||||||
&m_connectionManager, &Internal::QmlPreviewConnectionManager::language);
|
&m_connectionManager, &Internal::QmlPreviewConnectionManager::language);
|
||||||
|
connect(this, &QmlPreviewRunner::changeElideWarning,
|
||||||
|
&m_connectionManager, &Internal::QmlPreviewConnectionManager::changeElideWarning);
|
||||||
|
|
||||||
connect(&m_connectionManager, &Internal::QmlPreviewConnectionManager::connectionOpened,
|
connect(&m_connectionManager, &Internal::QmlPreviewConnectionManager::connectionOpened,
|
||||||
this, [this, initialZoom, initialLocale]() {
|
this, [this, initialZoom]() {
|
||||||
if (initialZoom > 0)
|
if (initialZoom > 0)
|
||||||
emit zoom(initialZoom);
|
emit zoom(initialZoom);
|
||||||
if (!initialLocale.isEmpty())
|
|
||||||
emit language(initialLocale);
|
|
||||||
emit ready();
|
emit ready();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -153,11 +152,6 @@ LocalQmlPreviewSupport::LocalQmlPreviewSupport(ProjectExplorer::RunControl *runC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto multiLanguageAspect = runControl->aspect<QmlProjectManager::QmlMultiLanguageAspect>()) {
|
|
||||||
if (!multiLanguageAspect->databaseFilePath().isEmpty())
|
|
||||||
runnable.environment.set("QT_MULTILANGUAGE_DATABASE", multiLanguageAspect->databaseFilePath().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
Utils::QtcProcess::addArg(&runnable.commandLineArguments,
|
Utils::QtcProcess::addArg(&runnable.commandLineArguments,
|
||||||
QmlDebug::qmlDebugLocalArguments(QmlDebug::QmlPreviewServices,
|
QmlDebug::qmlDebugLocalArguments(QmlDebug::QmlPreviewServices,
|
||||||
serverUrl.path()));
|
serverUrl.path()));
|
||||||
|
@@ -39,7 +39,7 @@ class QmlPreviewRunner : public ProjectExplorer::RunWorker
|
|||||||
public:
|
public:
|
||||||
QmlPreviewRunner(ProjectExplorer::RunControl *runControl, QmlPreviewFileLoader fileLoader,
|
QmlPreviewRunner(ProjectExplorer::RunControl *runControl, QmlPreviewFileLoader fileLoader,
|
||||||
QmlPreviewFileClassifier fileClassifier, QmlPreviewFpsHandler fpsHandler,
|
QmlPreviewFileClassifier fileClassifier, QmlPreviewFpsHandler fpsHandler,
|
||||||
float initialZoom, const QString &initialLocale);
|
float initialZoom);
|
||||||
|
|
||||||
void setServerUrl(const QUrl &serverUrl);
|
void setServerUrl(const QUrl &serverUrl);
|
||||||
QUrl serverUrl() const;
|
QUrl serverUrl() const;
|
||||||
@@ -51,7 +51,7 @@ signals:
|
|||||||
void zoom(float zoomFactor);
|
void zoom(float zoomFactor);
|
||||||
void rerun();
|
void rerun();
|
||||||
void ready();
|
void ready();
|
||||||
|
void changeElideWarning(bool elideWarning);
|
||||||
private:
|
private:
|
||||||
void start() override;
|
void start() override;
|
||||||
void stop() override;
|
void stop() override;
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#include <projectexplorer/project.h>
|
#include <projectexplorer/project.h>
|
||||||
#include <projectexplorer/projectexplorer.h>
|
#include <projectexplorer/projectexplorer.h>
|
||||||
|
#include <projectexplorer/session.h>
|
||||||
#include <projectexplorer/target.h>
|
#include <projectexplorer/target.h>
|
||||||
|
|
||||||
static bool isMultilanguagePresent()
|
static bool isMultilanguagePresent()
|
||||||
@@ -46,7 +47,8 @@ static bool isMultilanguagePresent()
|
|||||||
static Utils::FilePath getMultilanguageDatabaseFilePath(ProjectExplorer::Target *target)
|
static Utils::FilePath getMultilanguageDatabaseFilePath(ProjectExplorer::Target *target)
|
||||||
{
|
{
|
||||||
if (target) {
|
if (target) {
|
||||||
auto filePath = target->project()->projectDirectory().pathAppended("/multilanguage-experimental-v1.db");
|
auto filePath = target->project()->projectDirectory().pathAppended(
|
||||||
|
"multilanguage-experimental-v2.db");
|
||||||
if (filePath.exists())
|
if (filePath.exists())
|
||||||
return filePath;
|
return filePath;
|
||||||
}
|
}
|
||||||
@@ -81,28 +83,24 @@ QmlMultiLanguageAspect::QmlMultiLanguageAspect(ProjectExplorer::Target *target)
|
|||||||
setDefaultValue(!databaseFilePath().isEmpty());
|
setDefaultValue(!databaseFilePath().isEmpty());
|
||||||
QVariantMap getDefaultValues;
|
QVariantMap getDefaultValues;
|
||||||
fromMap(getDefaultValues);
|
fromMap(getDefaultValues);
|
||||||
|
|
||||||
if (auto previewPlugin = getPreviewPlugin())
|
|
||||||
connect(previewPlugin, SIGNAL(localeChanged(QString)), this, SLOT(setLastUsedLanguage(QString)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QmlMultiLanguageAspect::~QmlMultiLanguageAspect()
|
QmlMultiLanguageAspect::~QmlMultiLanguageAspect()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlMultiLanguageAspect::setLastUsedLanguage(const QString &language)
|
void QmlMultiLanguageAspect::setCurrentLocale(const QString &locale)
|
||||||
{
|
{
|
||||||
|
if (m_currentLocale == locale)
|
||||||
|
return;
|
||||||
|
m_currentLocale = locale;
|
||||||
if (auto previewPlugin = getPreviewPlugin())
|
if (auto previewPlugin = getPreviewPlugin())
|
||||||
previewPlugin->setProperty("locale", language);
|
previewPlugin->setProperty("locale", locale);
|
||||||
if (m_lastUsedLanguage != language) {
|
|
||||||
m_lastUsedLanguage = language;
|
|
||||||
emit changed();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QmlMultiLanguageAspect::lastUsedLanguage() const
|
QString QmlMultiLanguageAspect::currentLocale() const
|
||||||
{
|
{
|
||||||
return m_lastUsedLanguage;
|
return m_currentLocale;
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::FilePath QmlMultiLanguageAspect::databaseFilePath() const
|
Utils::FilePath QmlMultiLanguageAspect::databaseFilePath() const
|
||||||
@@ -115,14 +113,37 @@ Utils::FilePath QmlMultiLanguageAspect::databaseFilePath() const
|
|||||||
void QmlMultiLanguageAspect::toMap(QVariantMap &map) const
|
void QmlMultiLanguageAspect::toMap(QVariantMap &map) const
|
||||||
{
|
{
|
||||||
BaseBoolAspect::toMap(map);
|
BaseBoolAspect::toMap(map);
|
||||||
if (!m_lastUsedLanguage.isEmpty())
|
if (!m_currentLocale.isEmpty())
|
||||||
map.insert(Constants::LAST_USED_LANGUAGE, m_lastUsedLanguage);
|
map.insert(Constants::LAST_USED_LANGUAGE, m_currentLocale);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlMultiLanguageAspect::fromMap(const QVariantMap &map)
|
void QmlMultiLanguageAspect::fromMap(const QVariantMap &map)
|
||||||
{
|
{
|
||||||
BaseBoolAspect::fromMap(map);
|
BaseBoolAspect::fromMap(map);
|
||||||
setLastUsedLanguage(map.value(Constants::LAST_USED_LANGUAGE, "en").toString());
|
setCurrentLocale(map.value(Constants::LAST_USED_LANGUAGE, "en").toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlMultiLanguageAspect *QmlMultiLanguageAspect::current()
|
||||||
|
{
|
||||||
|
if (auto project = ProjectExplorer::SessionManager::startupProject())
|
||||||
|
return current(project);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlMultiLanguageAspect *QmlMultiLanguageAspect::current(ProjectExplorer::Project *project)
|
||||||
|
{
|
||||||
|
if (auto target = project->activeTarget())
|
||||||
|
return current(target);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlMultiLanguageAspect *QmlMultiLanguageAspect::current(ProjectExplorer::Target *target)
|
||||||
|
{
|
||||||
|
if (auto runConfiguration = target->activeRunConfiguration()) {
|
||||||
|
if (auto multiLanguageAspect = runConfiguration->aspect<QmlProjectManager::QmlMultiLanguageAspect>())
|
||||||
|
return multiLanguageAspect;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace QmlProjectManager
|
} // namespace QmlProjectManager
|
||||||
|
@@ -40,18 +40,23 @@ public:
|
|||||||
explicit QmlMultiLanguageAspect(ProjectExplorer::Target *target);
|
explicit QmlMultiLanguageAspect(ProjectExplorer::Target *target);
|
||||||
~QmlMultiLanguageAspect() override;
|
~QmlMultiLanguageAspect() override;
|
||||||
|
|
||||||
QString lastUsedLanguage() const;
|
QString currentLocale() const;
|
||||||
|
void setCurrentLocale(const QString &locale);
|
||||||
Utils::FilePath databaseFilePath() const;
|
Utils::FilePath databaseFilePath() const;
|
||||||
void toMap(QVariantMap &map) const final;
|
void toMap(QVariantMap &map) const final;
|
||||||
void fromMap(const QVariantMap &map) final;
|
void fromMap(const QVariantMap &map) final;
|
||||||
|
|
||||||
public slots:
|
static QmlMultiLanguageAspect *current();
|
||||||
void setLastUsedLanguage(const QString &language);
|
static QmlMultiLanguageAspect *current(ProjectExplorer::Project *project);
|
||||||
|
static QmlMultiLanguageAspect *current(ProjectExplorer::Target *target);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void currentLocaleChanged(const QString &locale);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ProjectExplorer::Target *m_target = nullptr;
|
ProjectExplorer::Target *m_target = nullptr;
|
||||||
mutable Utils::FilePath m_databaseFilePath;
|
mutable Utils::FilePath m_databaseFilePath;
|
||||||
QString m_lastUsedLanguage;
|
QString m_currentLocale;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlProjectManager
|
} // namespace QmlProjectManager
|
||||||
|
@@ -372,7 +372,7 @@ void QmlBuildSystem::generateProjectTree()
|
|||||||
|
|
||||||
auto newRoot = std::make_unique<QmlProjectNode>(project());
|
auto newRoot = std::make_unique<QmlProjectNode>(project());
|
||||||
|
|
||||||
for (const QString &f : m_projectItem.data()->files()) {
|
for (const QString &f : m_projectItem->files()) {
|
||||||
const Utils::FilePath fileName = Utils::FilePath::fromString(f);
|
const Utils::FilePath fileName = Utils::FilePath::fromString(f);
|
||||||
const FileType fileType = (fileName == projectFilePath())
|
const FileType fileType = (fileName == projectFilePath())
|
||||||
? FileType::Project : FileNode::fileTypeForFileName(fileName);
|
? FileType::Project : FileNode::fileTypeForFileName(fileName);
|
||||||
|
@@ -117,7 +117,10 @@ QmlProjectRunConfiguration::QmlProjectRunConfiguration(Target *target, Id id)
|
|||||||
|
|
||||||
if (m_multiLanguageAspect && m_multiLanguageAspect->value() && !m_multiLanguageAspect->databaseFilePath().isEmpty()) {
|
if (m_multiLanguageAspect && m_multiLanguageAspect->value() && !m_multiLanguageAspect->databaseFilePath().isEmpty()) {
|
||||||
env.set("QT_MULTILANGUAGE_DATABASE", m_multiLanguageAspect->databaseFilePath().toString());
|
env.set("QT_MULTILANGUAGE_DATABASE", m_multiLanguageAspect->databaseFilePath().toString());
|
||||||
env.set("QT_MULTILANGUAGE_LANGUAGE", m_multiLanguageAspect->lastUsedLanguage());
|
env.set("QT_MULTILANGUAGE_LANGUAGE", m_multiLanguageAspect->currentLocale());
|
||||||
|
} else {
|
||||||
|
env.unset("QT_MULTILANGUAGE_DATABASE");
|
||||||
|
env.unset("QT_MULTILANGUAGE_LANGUAGE");
|
||||||
}
|
}
|
||||||
return env;
|
return env;
|
||||||
};
|
};
|
||||||
|
@@ -52,6 +52,7 @@ extend_qtc_executable(qml2puppet
|
|||||||
inputeventcommand.cpp inputeventcommand.h
|
inputeventcommand.cpp inputeventcommand.h
|
||||||
view3dactioncommand.cpp view3dactioncommand.h
|
view3dactioncommand.cpp view3dactioncommand.h
|
||||||
valueschangedcommand.cpp
|
valueschangedcommand.cpp
|
||||||
|
captureddatacommand.h
|
||||||
)
|
)
|
||||||
|
|
||||||
extend_qtc_executable(qml2puppet
|
extend_qtc_executable(qml2puppet
|
||||||
@@ -155,6 +156,7 @@ extend_qtc_executable(qml2puppet
|
|||||||
quick3dtexturenodeinstance.cpp quick3dtexturenodeinstance.h
|
quick3dtexturenodeinstance.cpp quick3dtexturenodeinstance.h
|
||||||
quickitemnodeinstance.cpp quickitemnodeinstance.h
|
quickitemnodeinstance.cpp quickitemnodeinstance.h
|
||||||
servernodeinstance.cpp servernodeinstance.h
|
servernodeinstance.cpp servernodeinstance.h
|
||||||
|
qt5capturenodeinstanceserver.cpp qt5capturenodeinstanceserver.h
|
||||||
)
|
)
|
||||||
|
|
||||||
extend_qtc_executable(qml2puppet
|
extend_qtc_executable(qml2puppet
|
||||||
|
@@ -116,6 +116,7 @@ QtcTool {
|
|||||||
"commands/inputeventcommand.h",
|
"commands/inputeventcommand.h",
|
||||||
"commands/view3dactioncommand.cpp",
|
"commands/view3dactioncommand.cpp",
|
||||||
"commands/view3dactioncommand.h",
|
"commands/view3dactioncommand.h",
|
||||||
|
"commands/captureddatacommand.h",
|
||||||
"container/addimportcontainer.cpp",
|
"container/addimportcontainer.cpp",
|
||||||
"container/addimportcontainer.h",
|
"container/addimportcontainer.h",
|
||||||
"container/idcontainer.cpp",
|
"container/idcontainer.cpp",
|
||||||
@@ -218,6 +219,8 @@ QtcTool {
|
|||||||
"instances/qt5testnodeinstanceserver.h",
|
"instances/qt5testnodeinstanceserver.h",
|
||||||
"instances/servernodeinstance.cpp",
|
"instances/servernodeinstance.cpp",
|
||||||
"instances/servernodeinstance.h",
|
"instances/servernodeinstance.h",
|
||||||
|
"instances/qt5capturenodeinstanceserver.cpp",
|
||||||
|
"instances/qt5capturenodeinstanceserver.h",
|
||||||
"editor3d/generalhelper.cpp",
|
"editor3d/generalhelper.cpp",
|
||||||
"editor3d/mousearea3d.cpp",
|
"editor3d/mousearea3d.cpp",
|
||||||
"editor3d/camerageometry.cpp",
|
"editor3d/camerageometry.cpp",
|
||||||
|
@@ -17,4 +17,5 @@ add_qtc_test(tst_qml_testcore
|
|||||||
../testview.cpp ../testview.h
|
../testview.cpp ../testview.h
|
||||||
testrewriterview.cpp testrewriterview.h
|
testrewriterview.cpp testrewriterview.h
|
||||||
tst_testcore.cpp tst_testcore.h
|
tst_testcore.cpp tst_testcore.h
|
||||||
|
../testconnectionmanager.cpp ../testconnectionmanager.h
|
||||||
)
|
)
|
||||||
|
@@ -61,11 +61,13 @@ TEMPLATE = app
|
|||||||
SOURCES += \
|
SOURCES += \
|
||||||
../testview.cpp \
|
../testview.cpp \
|
||||||
testrewriterview.cpp \
|
testrewriterview.cpp \
|
||||||
tst_testcore.cpp
|
tst_testcore.cpp \
|
||||||
|
../testconnectionmanager.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
../testview.h \
|
../testview.h \
|
||||||
testrewriterview.h \
|
testrewriterview.h \
|
||||||
tst_testcore.h
|
tst_testcore.h \
|
||||||
|
../testconnectionmanager.h
|
||||||
|
|
||||||
RESOURCES += ../data/testfiles.qrc
|
RESOURCES += ../data/testfiles.qrc
|
||||||
|
@@ -46,11 +46,12 @@
|
|||||||
#include <stylesheetmerger.h>
|
#include <stylesheetmerger.h>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
|
#include "../testconnectionmanager.h"
|
||||||
#include "../testview.h"
|
#include "../testview.h"
|
||||||
#include <variantproperty.h>
|
|
||||||
#include <abstractproperty.h>
|
#include <abstractproperty.h>
|
||||||
#include <bindingproperty.h>
|
#include <bindingproperty.h>
|
||||||
#include <nodeproperty.h>
|
#include <nodeproperty.h>
|
||||||
|
#include <variantproperty.h>
|
||||||
|
|
||||||
#include <nodelistproperty.h>
|
#include <nodelistproperty.h>
|
||||||
#include <nodeabstractproperty.h>
|
#include <nodeabstractproperty.h>
|
||||||
@@ -1999,8 +2000,9 @@ void tst_TestCore::testModelRemoveNode()
|
|||||||
QVERIFY(view.data());
|
QVERIFY(view.data());
|
||||||
model->attachView(view.data());
|
model->attachView(view.data());
|
||||||
|
|
||||||
NodeInstanceView *nodeInstanceView = new NodeInstanceView(model.data(), NodeInstanceServerInterface::TestModus);
|
TestConnectionManager connectionManager;
|
||||||
model->attachView(nodeInstanceView);
|
NodeInstanceView nodeInstanceView{connectionManager};
|
||||||
|
model->attachView(&nodeInstanceView);
|
||||||
|
|
||||||
QCOMPARE(view->rootModelNode().directSubModelNodes().count(), 0);
|
QCOMPARE(view->rootModelNode().directSubModelNodes().count(), 0);
|
||||||
|
|
||||||
@@ -2051,7 +2053,7 @@ void tst_TestCore::testModelRemoveNode()
|
|||||||
childNode = view->createModelNode("QtQuick.Item", 1, 1);
|
childNode = view->createModelNode("QtQuick.Item", 1, 1);
|
||||||
childNode.destroy();
|
childNode.destroy();
|
||||||
|
|
||||||
model->detachView(nodeInstanceView);
|
model->detachView(&nodeInstanceView);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_TestCore::reparentingNode()
|
void tst_TestCore::reparentingNode()
|
||||||
@@ -6140,17 +6142,21 @@ void tst_TestCore::testInstancesAttachToExistingModel()
|
|||||||
|
|
||||||
// Attach NodeInstanceView
|
// Attach NodeInstanceView
|
||||||
|
|
||||||
QScopedPointer<NodeInstanceView> instanceView(new NodeInstanceView(0, NodeInstanceServerInterface::TestModus));
|
TestConnectionManager connectionManager;
|
||||||
QVERIFY(instanceView.data());
|
|
||||||
model->attachView(instanceView.data());
|
|
||||||
|
|
||||||
NodeInstance rootInstance = instanceView->instanceForModelNode(rootNode);
|
NodeInstanceView instanceView{connectionManager};
|
||||||
NodeInstance rectangleInstance = instanceView->instanceForModelNode(rectangleNode);
|
|
||||||
|
model->attachView(&instanceView);
|
||||||
|
|
||||||
|
NodeInstance rootInstance = instanceView.instanceForModelNode(rootNode);
|
||||||
|
NodeInstance rectangleInstance = instanceView.instanceForModelNode(rectangleNode);
|
||||||
QVERIFY(rootInstance.isValid());
|
QVERIFY(rootInstance.isValid());
|
||||||
QVERIFY(rectangleInstance.isValid());
|
QVERIFY(rectangleInstance.isValid());
|
||||||
QCOMPARE(QVariant(100), rectangleInstance.property("width"));
|
QCOMPARE(QVariant(100), rectangleInstance.property("width"));
|
||||||
QVERIFY(rootInstance.instanceId() >= 0);
|
QVERIFY(rootInstance.instanceId() >= 0);
|
||||||
QVERIFY(rectangleInstance.instanceId() >= 0);
|
QVERIFY(rectangleInstance.instanceId() >= 0);
|
||||||
|
|
||||||
|
model->detachView(&instanceView);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_TestCore::testQmlModelAddMultipleStates()
|
void tst_TestCore::testQmlModelAddMultipleStates()
|
||||||
|
72
tests/auto/qml/qmldesigner/testconnectionmanager.cpp
Normal file
72
tests/auto/qml/qmldesigner/testconnectionmanager.cpp
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "testconnectionmanager.h"
|
||||||
|
#include "synchronizecommand.h"
|
||||||
|
|
||||||
|
#include <QLocalSocket>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
TestConnectionManager::TestConnectionManager()
|
||||||
|
{
|
||||||
|
m_connections.emplace_back("Editor", "editormode");
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestConnectionManager::writeCommand(const QVariant &command)
|
||||||
|
{
|
||||||
|
TestConnectionManager::writeCommand(command);
|
||||||
|
|
||||||
|
m_writeCommandCounter++;
|
||||||
|
|
||||||
|
static int synchronizeId = 0;
|
||||||
|
synchronizeId++;
|
||||||
|
SynchronizeCommand synchronizeCommand(synchronizeId);
|
||||||
|
|
||||||
|
QLocalSocket *socket = m_connections.front().socket.get();
|
||||||
|
|
||||||
|
writeCommandToIODevice(QVariant::fromValue(synchronizeCommand), socket, m_writeCommandCounter);
|
||||||
|
m_writeCommandCounter++;
|
||||||
|
|
||||||
|
while (socket->waitForReadyRead(100)) {
|
||||||
|
readDataStream(m_connections.front());
|
||||||
|
if (m_synchronizeId == synchronizeId)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestConnectionManager::dispatchCommand(const QVariant &command, Connection &connection)
|
||||||
|
{
|
||||||
|
static const int synchronizeCommandType = QMetaType::type("SynchronizeCommand");
|
||||||
|
|
||||||
|
if (command.userType() == synchronizeCommandType) {
|
||||||
|
SynchronizeCommand synchronizeCommand = command.value<SynchronizeCommand>();
|
||||||
|
m_synchronizeId = synchronizeCommand.synchronizeId();
|
||||||
|
} else {
|
||||||
|
ConnectionManager::dispatchCommand(command, connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
56
tests/auto/qml/qmldesigner/testconnectionmanager.h
Normal file
56
tests/auto/qml/qmldesigner/testconnectionmanager.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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>
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
#include <QPointer>
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QLocalServer;
|
||||||
|
class QLocalSocket;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class TestConnectionManager final : public ConnectionManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TestConnectionManager();
|
||||||
|
|
||||||
|
void writeCommand(const QVariant &command) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void dispatchCommand(const QVariant &command, Connection &connection) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_synchronizeId = -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -31,14 +31,17 @@
|
|||||||
|
|
||||||
#include <qmldesigner/components/listmodeleditor/listmodeleditormodel.h>
|
#include <qmldesigner/components/listmodeleditor/listmodeleditormodel.h>
|
||||||
#include <qmldesigner/designercore/include/abstractview.h>
|
#include <qmldesigner/designercore/include/abstractview.h>
|
||||||
|
#include <qmldesigner/designercore/include/bindingproperty.h>
|
||||||
#include <qmldesigner/designercore/include/model.h>
|
#include <qmldesigner/designercore/include/model.h>
|
||||||
#include <qmldesigner/designercore/include/nodelistproperty.h>
|
#include <qmldesigner/designercore/include/nodelistproperty.h>
|
||||||
|
#include <qmldesigner/designercore/include/nodeproperty.h>
|
||||||
#include <qmldesigner/designercore/include/variantproperty.h>
|
#include <qmldesigner/designercore/include/variantproperty.h>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using QmlDesigner::AbstractProperty;
|
using QmlDesigner::AbstractProperty;
|
||||||
using QmlDesigner::AbstractView;
|
using QmlDesigner::AbstractView;
|
||||||
|
using QmlDesigner::ListModelEditorModel;
|
||||||
using QmlDesigner::ModelNode;
|
using QmlDesigner::ModelNode;
|
||||||
|
|
||||||
MATCHER_P2(HasItem,
|
MATCHER_P2(HasItem,
|
||||||
@@ -93,6 +96,7 @@ public:
|
|||||||
|
|
||||||
emptyListModelNode = mockView.createModelNode("QtQml.Models.ListModel", 2, 15);
|
emptyListModelNode = mockView.createModelNode("QtQml.Models.ListModel", 2, 15);
|
||||||
|
|
||||||
|
listViewNode = mockView.createModelNode("QtQuick.ListView", 2, 15);
|
||||||
listModelNode = mockView.createModelNode("QtQml.Models.ListModel", 2, 15);
|
listModelNode = mockView.createModelNode("QtQml.Models.ListModel", 2, 15);
|
||||||
mockView.rootModelNode().defaultNodeListProperty().reparentHere(listModelNode);
|
mockView.rootModelNode().defaultNodeListProperty().reparentHere(listModelNode);
|
||||||
element1 = createElement({{"name", "foo"}, {"value", 1}, {"value2", 42}});
|
element1 = createElement({{"name", "foo"}, {"value", 1}, {"value2", 42}});
|
||||||
@@ -172,10 +176,20 @@ public:
|
|||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QModelIndex index(int row, int column) const { return model.index(row, column); }
|
||||||
|
|
||||||
|
QList<ModelNode> elements(const ModelNode &node) const
|
||||||
|
{
|
||||||
|
return node.defaultNodeListProperty().toModelNodeList();
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::unique_ptr<QmlDesigner::Model> designerModel{QmlDesigner::Model::create("QtQuick.Item", 1, 1)};
|
std::unique_ptr<QmlDesigner::Model> designerModel{QmlDesigner::Model::create("QtQuick.Item", 1, 1)};
|
||||||
NiceMock<MockListModelEditorView> mockView;
|
NiceMock<MockListModelEditorView> mockView;
|
||||||
QmlDesigner::ListModelEditorModel model;
|
QmlDesigner::ListModelEditorModel model{
|
||||||
|
[&] { return mockView.createModelNode("QtQml.Models.ListModel", 2, 15); },
|
||||||
|
[&] { return mockView.createModelNode("QtQml.Models.ListElement", 2, 15); }};
|
||||||
|
ModelNode listViewNode;
|
||||||
ModelNode listModelNode;
|
ModelNode listModelNode;
|
||||||
ModelNode emptyListModelNode;
|
ModelNode emptyListModelNode;
|
||||||
ModelNode element1;
|
ModelNode element1;
|
||||||
@@ -427,7 +441,7 @@ TEST_F(ListModelEditor, RemoveColumnRemovesDisplayValues)
|
|||||||
{
|
{
|
||||||
model.setListModel(listModelNode);
|
model.setListModel(listModelNode);
|
||||||
|
|
||||||
model.removeColumn(2);
|
model.removeColumns({index(0, 2)});
|
||||||
|
|
||||||
ASSERT_THAT(displayValues(),
|
ASSERT_THAT(displayValues(),
|
||||||
ElementsAre(ElementsAre(IsInvalid(), "foo", 42),
|
ElementsAre(ElementsAre(IsInvalid(), "foo", 42),
|
||||||
@@ -442,14 +456,14 @@ TEST_F(ListModelEditor, RemoveColumnRemovesProperties)
|
|||||||
EXPECT_CALL(mockView, propertiesRemoved(ElementsAre(IsAbstractProperty(element2, "image"))));
|
EXPECT_CALL(mockView, propertiesRemoved(ElementsAre(IsAbstractProperty(element2, "image"))));
|
||||||
EXPECT_CALL(mockView, propertiesRemoved(ElementsAre(IsAbstractProperty(element3, "image"))));
|
EXPECT_CALL(mockView, propertiesRemoved(ElementsAre(IsAbstractProperty(element3, "image"))));
|
||||||
|
|
||||||
model.removeColumn(0);
|
model.removeColumns({index(0, 0)});
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ListModelEditor, RemoveColumnRemovesPropertyName)
|
TEST_F(ListModelEditor, RemoveColumnRemovesPropertyName)
|
||||||
{
|
{
|
||||||
model.setListModel(listModelNode);
|
model.setListModel(listModelNode);
|
||||||
|
|
||||||
model.removeColumn(1);
|
model.removeColumns({index(0, 1)});
|
||||||
|
|
||||||
ASSERT_THAT(model.propertyNames(), ElementsAre("image", "value", "value2"));
|
ASSERT_THAT(model.propertyNames(), ElementsAre("image", "value", "value2"));
|
||||||
}
|
}
|
||||||
@@ -458,7 +472,7 @@ TEST_F(ListModelEditor, RemoveRowRemovesDisplayValues)
|
|||||||
{
|
{
|
||||||
model.setListModel(listModelNode);
|
model.setListModel(listModelNode);
|
||||||
|
|
||||||
model.removeRow(1);
|
model.removeRows({index(1, 0)});
|
||||||
|
|
||||||
ASSERT_THAT(displayValues(),
|
ASSERT_THAT(displayValues(),
|
||||||
ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42),
|
ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42),
|
||||||
@@ -471,7 +485,7 @@ TEST_F(ListModelEditor, RemoveRowRemovesElementInListModel)
|
|||||||
|
|
||||||
EXPECT_CALL(mockView, nodeRemoved(Eq(element2), _, _));
|
EXPECT_CALL(mockView, nodeRemoved(Eq(element2), _, _));
|
||||||
|
|
||||||
model.removeRow(1);
|
model.removeRows({index(1, 0)});
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ListModelEditor, ConvertStringFloatToFloat)
|
TEST_F(ListModelEditor, ConvertStringFloatToFloat)
|
||||||
@@ -721,7 +735,7 @@ TEST_F(ListModelEditor, RemoveColumnAfterRenameColumn)
|
|||||||
model.setListModel(listModelNode);
|
model.setListModel(listModelNode);
|
||||||
model.renameColumn(1, "mood");
|
model.renameColumn(1, "mood");
|
||||||
|
|
||||||
model.removeColumn(1);
|
model.removeColumns({index(0, 1)});
|
||||||
|
|
||||||
ASSERT_THAT(properties(),
|
ASSERT_THAT(properties(),
|
||||||
ElementsAre(UnorderedElementsAre(IsVariantProperty("value", 1),
|
ElementsAre(UnorderedElementsAre(IsVariantProperty("value", 1),
|
||||||
@@ -909,30 +923,7 @@ TEST_F(ListModelEditor, RemoveLastRow)
|
|||||||
model.addColumn("mood");
|
model.addColumn("mood");
|
||||||
model.addRow();
|
model.addRow();
|
||||||
|
|
||||||
model.removeRow(0);
|
model.removeRows({index(0, 0)});
|
||||||
|
|
||||||
ASSERT_THAT(displayValues(), IsEmpty());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(ListModelEditor, RemoveLastColumn)
|
|
||||||
{
|
|
||||||
model.setListModel(emptyListModelNode);
|
|
||||||
model.addColumn("mood");
|
|
||||||
model.addRow();
|
|
||||||
|
|
||||||
model.removeColumn(0);
|
|
||||||
|
|
||||||
ASSERT_THAT(displayValues(), ElementsAre(IsEmpty()));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(ListModelEditor, RemoveLastEmptyColumn)
|
|
||||||
{
|
|
||||||
model.setListModel(emptyListModelNode);
|
|
||||||
model.addColumn("mood");
|
|
||||||
model.addRow();
|
|
||||||
model.removeRow(0);
|
|
||||||
|
|
||||||
model.removeColumn(0);
|
|
||||||
|
|
||||||
ASSERT_THAT(displayValues(), IsEmpty());
|
ASSERT_THAT(displayValues(), IsEmpty());
|
||||||
}
|
}
|
||||||
@@ -942,11 +933,447 @@ TEST_F(ListModelEditor, RemoveLastEmptyRow)
|
|||||||
model.setListModel(emptyListModelNode);
|
model.setListModel(emptyListModelNode);
|
||||||
model.addColumn("mood");
|
model.addColumn("mood");
|
||||||
model.addRow();
|
model.addRow();
|
||||||
model.removeColumn(0);
|
model.removeColumns({index(0, 0)});
|
||||||
|
|
||||||
model.removeRow(0);
|
model.removeRows({index(0, 0)});
|
||||||
|
|
||||||
|
ASSERT_THAT(displayValues(), ElementsAre(IsEmpty()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, RemoveLastColumn)
|
||||||
|
{
|
||||||
|
model.setListModel(emptyListModelNode);
|
||||||
|
model.addColumn("mood");
|
||||||
|
model.addRow();
|
||||||
|
|
||||||
|
model.removeColumns({index(0, 0)});
|
||||||
|
|
||||||
|
ASSERT_THAT(displayValues(), ElementsAre(IsEmpty()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, RemoveLastEmptyColumn)
|
||||||
|
{
|
||||||
|
model.setListModel(emptyListModelNode);
|
||||||
|
model.addColumn("mood");
|
||||||
|
model.addRow();
|
||||||
|
model.removeRows({index(0, 0)});
|
||||||
|
|
||||||
|
model.removeColumns({index(0, 0)});
|
||||||
|
|
||||||
ASSERT_THAT(displayValues(), IsEmpty());
|
ASSERT_THAT(displayValues(), IsEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, RemoveColumns)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
model.removeColumns({index(0, 1), index(0, 3), index(1, 1), index(0, 4)});
|
||||||
|
|
||||||
|
ASSERT_THAT(properties(),
|
||||||
|
ElementsAre(UnorderedElementsAre(IsVariantProperty("value", 1)),
|
||||||
|
UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
|
||||||
|
IsVariantProperty("value", 4)),
|
||||||
|
UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
|
||||||
|
IsVariantProperty("value", 111))));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, RemoveRows)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
|
||||||
|
model.removeRows({index(1, 0), index(2, 0), index(3, 0), index(2, 0)});
|
||||||
|
|
||||||
|
ASSERT_THAT(properties(),
|
||||||
|
ElementsAre(UnorderedElementsAre(IsVariantProperty("name", "foo"),
|
||||||
|
IsVariantProperty("value", 1),
|
||||||
|
IsVariantProperty("value2", 42))));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, FilterColumns)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
QList<QModelIndex> indices = {index(0, 0), index(1, 1), index(0, 2), index(0, 1)};
|
||||||
|
|
||||||
|
auto columns = ListModelEditorModel::filterColumns(indices);
|
||||||
|
|
||||||
|
ASSERT_THAT(columns, ElementsAre(0, 1, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, FilterColumnsInvalidColumns)
|
||||||
|
{
|
||||||
|
QList<QModelIndex> indices = {index(0, 0), index(1, 1), index(0, 2), index(0, 1)};
|
||||||
|
|
||||||
|
auto columns = ListModelEditorModel::filterColumns(indices);
|
||||||
|
|
||||||
|
ASSERT_THAT(columns, IsEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, FilterColumnsEmptyInput)
|
||||||
|
{
|
||||||
|
QList<QModelIndex> indices;
|
||||||
|
|
||||||
|
auto columns = ListModelEditorModel::filterColumns(indices);
|
||||||
|
|
||||||
|
ASSERT_THAT(columns, IsEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, FilterRows)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
QList<QModelIndex> indices = {index(0, 0), index(1, 1), index(2, 2), index(0, 1)};
|
||||||
|
|
||||||
|
auto rows = ListModelEditorModel::filterRows(indices);
|
||||||
|
|
||||||
|
ASSERT_THAT(rows, ElementsAre(0, 1, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, FilterRowsInvalidColumns)
|
||||||
|
{
|
||||||
|
QList<QModelIndex> indices = {index(0, 0), index(1, 1), index(2, 2), index(0, 1)};
|
||||||
|
|
||||||
|
auto rows = ListModelEditorModel::filterRows(indices);
|
||||||
|
|
||||||
|
ASSERT_THAT(rows, IsEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, FilterRowsEmptyInput)
|
||||||
|
{
|
||||||
|
QList<QModelIndex> indices;
|
||||||
|
|
||||||
|
auto rows = ListModelEditorModel::filterRows(indices);
|
||||||
|
|
||||||
|
ASSERT_THAT(rows, IsEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, CannotMoveEmptyRowsUp)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
QList<QModelIndex> indices = {index(-1, 1)};
|
||||||
|
|
||||||
|
model.moveRowsUp(indices);
|
||||||
|
|
||||||
|
ASSERT_THAT(elements(listModelNode), ElementsAre(element1, element2, element3));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, MoveRowUp)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
QList<QModelIndex> indices = {index(1, 1), index(1, 2), index(1, 0)};
|
||||||
|
|
||||||
|
model.moveRowsUp(indices);
|
||||||
|
|
||||||
|
ASSERT_THAT(elements(listModelNode), ElementsAre(element2, element1, element3));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, MoveRowsUp)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
QList<QModelIndex> indices = {index(1, 1), index(2, 2), index(1, 0)};
|
||||||
|
|
||||||
|
model.moveRowsUp(indices);
|
||||||
|
|
||||||
|
ASSERT_THAT(elements(listModelNode), ElementsAre(element2, element3, element1));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, CannotMoveFirstRowsUp)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
QList<QModelIndex> indices = {index(0, 1), index(1, 2), index(0, 0)};
|
||||||
|
|
||||||
|
model.moveRowsUp(indices);
|
||||||
|
|
||||||
|
ASSERT_THAT(elements(listModelNode), ElementsAre(element1, element2, element3));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, CannotMoveEmptyRowsUpDisplayValues)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
QList<QModelIndex> indices = {index(-1, 1)};
|
||||||
|
|
||||||
|
model.moveRowsUp(indices);
|
||||||
|
|
||||||
|
ASSERT_THAT(displayValues(),
|
||||||
|
ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42),
|
||||||
|
ElementsAre("pic.png", "bar", 4, IsInvalid()),
|
||||||
|
ElementsAre("pic.png", "poo", 111, IsInvalid())));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, CannotMoveFirstRowUpDisplayValues)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
QList<QModelIndex> indices = {index(0, 1), index(1, 2), index(0, 0)};
|
||||||
|
|
||||||
|
model.moveRowsUp(indices);
|
||||||
|
|
||||||
|
ASSERT_THAT(displayValues(),
|
||||||
|
ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42),
|
||||||
|
ElementsAre("pic.png", "bar", 4, IsInvalid()),
|
||||||
|
ElementsAre("pic.png", "poo", 111, IsInvalid())));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, MoveRowsUpDisplayValues)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
QList<QModelIndex> indices = {index(1, 1), index(2, 2), index(1, 0)};
|
||||||
|
|
||||||
|
model.moveRowsUp(indices);
|
||||||
|
|
||||||
|
ASSERT_THAT(displayValues(),
|
||||||
|
ElementsAre(ElementsAre("pic.png", "bar", 4, IsInvalid()),
|
||||||
|
ElementsAre("pic.png", "poo", 111, IsInvalid()),
|
||||||
|
ElementsAre(IsInvalid(), "foo", 1, 42)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, NoSelectionAfterCannotMoveLastRowsDown)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
QList<QModelIndex> indices = {index(0, 1), index(1, 2), index(0, 0)};
|
||||||
|
|
||||||
|
auto selection = model.moveRowsUp(indices);
|
||||||
|
|
||||||
|
ASSERT_THAT(selection.indexes(), IsEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, NoSelectionAfterMoveEmptyRowsDown)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
QList<QModelIndex> indices = {index(-1, 1)};
|
||||||
|
|
||||||
|
auto selection = model.moveRowsUp(indices);
|
||||||
|
|
||||||
|
ASSERT_THAT(selection.indexes(), IsEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, SelectionAfterMoveRowsDown)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
QList<QModelIndex> indices = {index(1, 1), index(2, 2), index(1, 0)};
|
||||||
|
|
||||||
|
auto selection = model.moveRowsUp(indices);
|
||||||
|
|
||||||
|
ASSERT_THAT(selection.indexes(),
|
||||||
|
ElementsAre(index(0, 0),
|
||||||
|
index(0, 1),
|
||||||
|
index(0, 2),
|
||||||
|
index(0, 3),
|
||||||
|
index(1, 0),
|
||||||
|
index(1, 1),
|
||||||
|
index(1, 2),
|
||||||
|
index(1, 3)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, CannotMoveEmptyRowsDown)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
QList<QModelIndex> indices = {index(-1, 1)};
|
||||||
|
|
||||||
|
model.moveRowsDown(indices);
|
||||||
|
|
||||||
|
ASSERT_THAT(elements(listModelNode), ElementsAre(element1, element2, element3));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, MoveRowDown)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
QList<QModelIndex> indices = {index(1, 1), index(1, 2), index(1, 0)};
|
||||||
|
|
||||||
|
model.moveRowsDown(indices);
|
||||||
|
|
||||||
|
ASSERT_THAT(elements(listModelNode), ElementsAre(element1, element3, element2));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, MoveRowsDown)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
QList<QModelIndex> indices = {index(1, 1), index(0, 2), index(1, 0)};
|
||||||
|
|
||||||
|
model.moveRowsDown(indices);
|
||||||
|
|
||||||
|
ASSERT_THAT(elements(listModelNode), ElementsAre(element3, element1, element2));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, CannotMoveLastRowsDown)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
QList<QModelIndex> indices = {index(2, 1), index(1, 2), index(2, 0)};
|
||||||
|
|
||||||
|
model.moveRowsDown(indices);
|
||||||
|
|
||||||
|
ASSERT_THAT(elements(listModelNode), ElementsAre(element1, element2, element3));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, CannotMoveEmptyRowsDownDisplayValues)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
QList<QModelIndex> indices = {index(-1, 1)};
|
||||||
|
|
||||||
|
model.moveRowsDown(indices);
|
||||||
|
|
||||||
|
ASSERT_THAT(displayValues(),
|
||||||
|
ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42),
|
||||||
|
ElementsAre("pic.png", "bar", 4, IsInvalid()),
|
||||||
|
ElementsAre("pic.png", "poo", 111, IsInvalid())));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, CannotMoveLastRowDownDisplayValues)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
QList<QModelIndex> indices = {index(2, 1), index(1, 2), index(2, 0)};
|
||||||
|
|
||||||
|
model.moveRowsDown(indices);
|
||||||
|
|
||||||
|
ASSERT_THAT(displayValues(),
|
||||||
|
ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42),
|
||||||
|
ElementsAre("pic.png", "bar", 4, IsInvalid()),
|
||||||
|
ElementsAre("pic.png", "poo", 111, IsInvalid())));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, MoveRowsDownDisplayValues)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
QList<QModelIndex> indices = {index(1, 1), index(0, 2), index(1, 0)};
|
||||||
|
|
||||||
|
model.moveRowsDown(indices);
|
||||||
|
|
||||||
|
ASSERT_THAT(displayValues(),
|
||||||
|
ElementsAre(ElementsAre("pic.png", "poo", 111, IsInvalid()),
|
||||||
|
ElementsAre(IsInvalid(), "foo", 1, 42),
|
||||||
|
ElementsAre("pic.png", "bar", 4, IsInvalid())));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, NoSelectionAfterCannotMoveLastRowsUp)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
QList<QModelIndex> indices = {index(2, 1), index(1, 2), index(2, 0)};
|
||||||
|
|
||||||
|
auto selection = model.moveRowsDown(indices);
|
||||||
|
|
||||||
|
ASSERT_THAT(selection.indexes(), IsEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, NoSelectionAfterMoveEmptyRowsUp)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
QList<QModelIndex> indices = {index(-1, 1)};
|
||||||
|
|
||||||
|
auto selection = model.moveRowsDown(indices);
|
||||||
|
|
||||||
|
ASSERT_THAT(selection.indexes(), IsEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, SelectionAfterMoveRowsUp)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
QList<QModelIndex> indices = {index(1, 1), index(0, 2), index(1, 0)};
|
||||||
|
|
||||||
|
auto selection = model.moveRowsDown(indices);
|
||||||
|
|
||||||
|
ASSERT_THAT(selection.indexes(),
|
||||||
|
ElementsAre(index(1, 0),
|
||||||
|
index(1, 1),
|
||||||
|
index(1, 2),
|
||||||
|
index(1, 3),
|
||||||
|
index(2, 0),
|
||||||
|
index(2, 1),
|
||||||
|
index(2, 2),
|
||||||
|
index(2, 3)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, ListViewHasNoModel)
|
||||||
|
{
|
||||||
|
model.setListView(listViewNode);
|
||||||
|
|
||||||
|
ASSERT_THAT(listViewNode.nodeProperty("model").modelNode().type(), Eq("QtQml.Models.ListModel"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, ListViewHasModelInside)
|
||||||
|
{
|
||||||
|
listViewNode.nodeProperty("model").reparentHere(listModelNode);
|
||||||
|
|
||||||
|
model.setListView(listViewNode);
|
||||||
|
|
||||||
|
ASSERT_THAT(displayValues(),
|
||||||
|
ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42),
|
||||||
|
ElementsAre("pic.png", "bar", 4, IsInvalid()),
|
||||||
|
ElementsAre("pic.png", "poo", 111, IsInvalid())));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, ListViewHasModelBinding)
|
||||||
|
{
|
||||||
|
listModelNode.setIdWithoutRefactoring("listModel");
|
||||||
|
listViewNode.bindingProperty("model").setExpression("listModel");
|
||||||
|
|
||||||
|
model.setListView(listViewNode);
|
||||||
|
|
||||||
|
ASSERT_THAT(displayValues(),
|
||||||
|
ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42),
|
||||||
|
ElementsAre("pic.png", "bar", 4, IsInvalid()),
|
||||||
|
ElementsAre("pic.png", "poo", 111, IsInvalid())));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, AddBooleanDisplayValues)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
|
||||||
|
model.setValue(0, 1, true);
|
||||||
|
|
||||||
|
ASSERT_THAT(displayValues(),
|
||||||
|
ElementsAre(ElementsAre(IsInvalid(), true, 1, 42),
|
||||||
|
ElementsAre("pic.png", "bar", 4, IsInvalid()),
|
||||||
|
ElementsAre("pic.png", "poo", 111, IsInvalid())));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, AddBooleanProperties)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
|
||||||
|
model.setValue(0, 1, true);
|
||||||
|
|
||||||
|
ASSERT_THAT(properties(),
|
||||||
|
ElementsAre(UnorderedElementsAre(IsVariantProperty("name", "foo"),
|
||||||
|
IsVariantProperty("value", true),
|
||||||
|
IsVariantProperty("value2", 42)),
|
||||||
|
UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
|
||||||
|
IsVariantProperty("name", "bar"),
|
||||||
|
IsVariantProperty("value", 4)),
|
||||||
|
UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
|
||||||
|
IsVariantProperty("name", "poo"),
|
||||||
|
IsVariantProperty("value", 111))));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, AddTrueAsStringProperties)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
|
||||||
|
model.setValue(0, 1, "true");
|
||||||
|
|
||||||
|
ASSERT_THAT(properties(),
|
||||||
|
ElementsAre(UnorderedElementsAre(IsVariantProperty("name", true),
|
||||||
|
IsVariantProperty("value", 1),
|
||||||
|
IsVariantProperty("value2", 42)),
|
||||||
|
UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
|
||||||
|
IsVariantProperty("name", "bar"),
|
||||||
|
IsVariantProperty("value", 4)),
|
||||||
|
UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
|
||||||
|
IsVariantProperty("name", "poo"),
|
||||||
|
IsVariantProperty("value", 111))));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ListModelEditor, AddFalseAsStringProperties)
|
||||||
|
{
|
||||||
|
model.setListModel(listModelNode);
|
||||||
|
|
||||||
|
model.setValue(0, 1, "false");
|
||||||
|
|
||||||
|
ASSERT_THAT(properties(),
|
||||||
|
ElementsAre(UnorderedElementsAre(IsVariantProperty("name", false),
|
||||||
|
IsVariantProperty("value", 1),
|
||||||
|
IsVariantProperty("value2", 42)),
|
||||||
|
UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
|
||||||
|
IsVariantProperty("name", "bar"),
|
||||||
|
IsVariantProperty("value", 4)),
|
||||||
|
UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
|
||||||
|
IsVariantProperty("name", "poo"),
|
||||||
|
IsVariantProperty("value", 111))));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
Reference in New Issue
Block a user