Connection Editor: ConnectionModelBackendDelegate refactoring

ConnectionModelBackendDelegate refactoring to extract logic responsible
for generating scripts to a reusable backend component.
ScriptEditorBackend can be used in the property editor to handle script
creation in scripting components (such as ScriptAction or
StateChangeScript) and as a base for ConnectionModelBackendDelegate.

Task-number: QDS-10449
Change-Id: Ie83f413f42bc1134ebb866aa6e7ea9d6b37da49b
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Rafal Stawarski
2025-02-20 16:37:24 +01:00
parent f8e71efc5a
commit de4b091dea
23 changed files with 1964 additions and 1844 deletions

View File

@@ -6,6 +6,7 @@ import QtQuick.Controls
import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import ScriptEditorBackend
Column {
id: root
@@ -71,32 +72,32 @@ Column {
model: ListModel {
ListElement {
value: ConnectionModelStatementDelegate.CallFunction
value: StatementDelegate.CallFunction
text: qsTr("Call Function")
enabled: true
}
ListElement {
value: ConnectionModelStatementDelegate.Assign
value: StatementDelegate.Assign
text: qsTr("Assign")
enabled: true
}
ListElement {
value: ConnectionModelStatementDelegate.ChangeState
value: StatementDelegate.ChangeState
text: qsTr("Change State")
enabled: true
}
ListElement {
value: ConnectionModelStatementDelegate.SetProperty
value: StatementDelegate.SetProperty
text: qsTr("Set Property")
enabled: true
}
ListElement {
value: ConnectionModelStatementDelegate.PrintMessage
value: StatementDelegate.PrintMessage
text: qsTr("Print Message")
enabled: true
}
ListElement {
value: ConnectionModelStatementDelegate.Custom
value: StatementDelegate.Custom
text: qsTr("Custom")
enabled: false
}
@@ -106,7 +107,7 @@ Column {
StatementEditor {
width: root.width
actionType: action.currentValue ?? ConnectionModelStatementDelegate.Custom
actionType: action.currentValue ?? StatementDelegate.Custom
horizontalSpacing: root.horizontalSpacing
columnWidth: root.columnWidth
statement: backend.okStatement
@@ -122,7 +123,7 @@ Column {
iconSize: StudioTheme.Values.baseFontSize
iconFontFamily: StudioTheme.Constants.font.family
anchors.horizontalCenter: parent.horizontalCenter
visible: action.currentValue !== ConnectionModelStatementDelegate.Custom && !backend.hasCondition
visible: action.currentValue !== StatementDelegate.Custom && !backend.hasCondition
onClicked: backend.addCondition()
}
@@ -135,7 +136,7 @@ Column {
iconSize: StudioTheme.Values.baseFontSize
iconFontFamily: StudioTheme.Constants.font.family
anchors.horizontalCenter: parent.horizontalCenter
visible: action.currentValue !== ConnectionModelStatementDelegate.Custom && backend.hasCondition
visible: action.currentValue !== StatementDelegate.Custom && backend.hasCondition
onClicked: backend.removeCondition()
}
@@ -186,7 +187,7 @@ Column {
iconSize: StudioTheme.Values.baseFontSize
iconFontFamily: StudioTheme.Constants.font.family
anchors.horizontalCenter: parent.horizontalCenter
visible: action.currentValue !== ConnectionModelStatementDelegate.Custom
visible: action.currentValue !== StatementDelegate.Custom
&& backend.hasCondition && !backend.hasElse
onClicked: backend.addElse()
@@ -200,7 +201,7 @@ Column {
iconSize: StudioTheme.Values.baseFontSize
iconFontFamily: StudioTheme.Constants.font.family
anchors.horizontalCenter: parent.horizontalCenter
visible: action.currentValue !== ConnectionModelStatementDelegate.Custom
visible: action.currentValue !== StatementDelegate.Custom
&& backend.hasCondition && backend.hasElse
onClicked: backend.removeElse()
@@ -209,13 +210,13 @@ Column {
//Else Statement
StatementEditor {
width: root.width
actionType: action.currentValue ?? ConnectionModelStatementDelegate.Custom
actionType: action.currentValue ?? StatementDelegate.Custom
horizontalSpacing: root.horizontalSpacing
columnWidth: root.columnWidth
statement: backend.koStatement
backend: root.backend
spacing: root.verticalSpacing
visible: action.currentValue !== ConnectionModelStatementDelegate.Custom
visible: action.currentValue !== StatementDelegate.Custom
&& backend.hasCondition && backend.hasElse
}

View File

@@ -7,6 +7,7 @@ import HelperWidgets as HelperWidgets
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import ConnectionsEditorEditorBackend
import ScriptEditorBackend
Column {
id: root
@@ -22,7 +23,7 @@ Column {
// Call Function
Row {
visible: root.actionType === ConnectionModelStatementDelegate.CallFunction
visible: root.actionType === StatementDelegate.CallFunction
spacing: root.horizontalSpacing
PopupLabel {
@@ -39,7 +40,7 @@ Column {
}
Row {
visible: root.actionType === ConnectionModelStatementDelegate.CallFunction
visible: root.actionType === StatementDelegate.CallFunction
spacing: root.horizontalSpacing
StudioControls.TopLevelComboBox {
@@ -68,7 +69,7 @@ Column {
// Assign
Row {
visible: root.actionType === ConnectionModelStatementDelegate.Assign
visible: root.actionType === StatementDelegate.Assign
spacing: root.horizontalSpacing
PopupLabel {
@@ -84,7 +85,7 @@ Column {
}
Row {
visible: root.actionType === ConnectionModelStatementDelegate.Assign
visible: root.actionType === StatementDelegate.Assign
spacing: root.horizontalSpacing
StudioControls.TopLevelComboBox {
@@ -114,7 +115,7 @@ Column {
}
Row {
visible: root.actionType === ConnectionModelStatementDelegate.Assign
visible: root.actionType === StatementDelegate.Assign
spacing: root.horizontalSpacing
StudioControls.TopLevelComboBox {
@@ -145,7 +146,7 @@ Column {
// Change State
Row {
visible: root.actionType === ConnectionModelStatementDelegate.ChangeState
visible: root.actionType === StatementDelegate.ChangeState
spacing: root.horizontalSpacing
PopupLabel {
@@ -162,7 +163,7 @@ Column {
}
Row {
visible: root.actionType === ConnectionModelStatementDelegate.ChangeState
visible: root.actionType === StatementDelegate.ChangeState
spacing: root.horizontalSpacing
StudioControls.TopLevelComboBox {
@@ -191,7 +192,7 @@ Column {
// Set Property
Row {
visible: root.actionType === ConnectionModelStatementDelegate.SetProperty
visible: root.actionType === StatementDelegate.SetProperty
spacing: root.horizontalSpacing
PopupLabel {
@@ -208,7 +209,7 @@ Column {
}
Row {
visible: root.actionType === ConnectionModelStatementDelegate.SetProperty
visible: root.actionType === StatementDelegate.SetProperty
spacing: root.horizontalSpacing
StudioControls.TopLevelComboBox {
@@ -238,14 +239,14 @@ Column {
PopupLabel {
width: root.columnWidth
visible: root.actionType === ConnectionModelStatementDelegate.SetProperty
visible: root.actionType === StatementDelegate.SetProperty
text: qsTr("Value")
tooltip: qsTr("Sets the value of the property of the component that is affected by the action of the <b>Target</b> component's <b>Signal</b>.")
}
StudioControls.TextField {
id: setPropertyArgument
visible: root.actionType === ConnectionModelStatementDelegate.SetProperty
visible: root.actionType === StatementDelegate.SetProperty
width: root.width
actionIndicatorVisible: false
translationIndicatorVisible: false
@@ -259,14 +260,14 @@ Column {
// Print Message
PopupLabel {
width: root.columnWidth
visible: root.actionType === ConnectionModelStatementDelegate.PrintMessage
visible: root.actionType === StatementDelegate.PrintMessage
text: qsTr("Message")
tooltip: qsTr("Sets a text that is printed when the <b>Signal</b> of the <b>Target</b> component initiates.")
}
StudioControls.TextField {
id: messageString
visible: root.actionType === ConnectionModelStatementDelegate.PrintMessage
visible: root.actionType === StatementDelegate.PrintMessage
width: root.width
actionIndicatorVisible: false
translationIndicatorVisible: false
@@ -278,7 +279,7 @@ Column {
// Custom
PopupLabel {
visible: root.actionType === ConnectionModelStatementDelegate.Custom
visible: root.actionType === StatementDelegate.Custom
text: qsTr("Custom Connections can only be edited with the binding editor")
width: root.width
horizontalAlignment: Text.AlignHCenter

View File

@@ -571,6 +571,16 @@ extend_qtc_plugin(QmlDesigner
annotationeditor.qrc
)
extend_qtc_plugin(QmlDesigner
SOURCES_PREFIX components/scripteditor
SOURCES
scripteditorstatements.cpp scripteditorstatements.h
scripteditorevaluator.cpp scripteditorevaluator.h
scripteditorutils.cpp scripteditorutils.h
propertytreemodel.cpp propertytreemodel.h
scripteditorbackend.cpp scripteditorbackend.h
)
extend_qtc_plugin(QmlDesigner
SOURCES_PREFIX components/connectioneditor
SOURCES
@@ -578,15 +588,12 @@ extend_qtc_plugin(QmlDesigner
bindingmodel.cpp bindingmodel.h
bindingmodelitem.cpp bindingmodelitem.h
connectioneditor.qrc
connectioneditorevaluator.cpp connectioneditorevaluator.h
connectioneditorstatements.cpp connectioneditorstatements.h
connectionmodel.cpp connectionmodel.h
connectionview.cpp connectionview.h
dynamicpropertiesmodel.cpp dynamicpropertiesmodel.h
dynamicpropertiesitem.cpp dynamicpropertiesitem.h
connectioneditorutils.cpp connectioneditorutils.h
selectiondynamicpropertiesproxymodel.cpp selectiondynamicpropertiesproxymodel.h
propertytreemodel.cpp propertytreemodel.h
connectioneditorlogging.cpp connectioneditorlogging.h
)
extend_qtc_plugin(QmlDesigner

View File

@@ -3,10 +3,11 @@
#include "bindingmodel.h"
#include "bindingmodelitem.h"
#include "connectioneditorutils.h"
#include "connectioneditorlogging.h"
#include "connectionview.h"
#include "modelfwd.h"
#include <scripteditorutils.h>
#include <bindingproperty.h>
#include <nodemetainfo.h>
#include <nodeproperty.h>

View File

@@ -2,7 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "bindingmodelitem.h"
#include "connectioneditorutils.h"
#include <scripteditorutils.h>
#include <modelnode.h>
#include <qmldesignertr.h>

View File

@@ -0,0 +1,10 @@
// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "connectioneditorlogging.h"
namespace QmlDesigner {
Q_LOGGING_CATEGORY(ConnectionEditorLog, "qtc.qtquickdesigner.connectioneditor", QtWarningMsg)
} // namespace QmlDesigner

View File

@@ -0,0 +1,12 @@
// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once
#include <QLoggingCategory>
namespace QmlDesigner {
Q_DECLARE_LOGGING_CATEGORY(ConnectionEditorLog)
} // namespace QmlDesigner

View File

@@ -3,15 +3,11 @@
#pragma once
#include <connectioneditorstatements.h>
#include <propertytreemodel.h>
#include <scripteditorbackend.h>
#include <studioquickwidget.h>
#include <QAbstractListModel>
#include <QStandardItemModel>
#include <memory>
namespace QmlDesigner {
class AbstractProperty;
@@ -23,247 +19,35 @@ class VariantProperty;
class ConnectionView;
class ConnectionModel;
class ConditionListModel : public QAbstractListModel
class ConnectionModelBackendDelegate : public ScriptEditorBackend
{
Q_OBJECT
Q_PROPERTY(bool valid READ valid NOTIFY validChanged)
Q_PROPERTY(bool empty READ empty NOTIFY emptyChanged)
Q_PROPERTY(QString error READ error NOTIFY errorChanged)
Q_PROPERTY(int errorIndex READ errorIndex NOTIFY errorIndexChanged)
public:
enum ConditionType { Intermediate, Invalid, Operator, Literal, Variable, Shadow };
Q_ENUM(ConditionType)
struct ConditionToken
{
ConditionType type;
QString value;
};
ConditionListModel(ConnectionModel *model);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QHash<int, QByteArray> roleNames() const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
void setup();
void setCondition(ConnectionEditorStatements::MatchedCondition &condition);
ConnectionEditorStatements::MatchedCondition &condition();
static ConditionToken tokenFromConditionToken(const ConnectionEditorStatements::ConditionToken &token);
static ConditionToken tokenFromComparativeStatement(
const ConnectionEditorStatements::ComparativeStatement &token);
Q_INVOKABLE void insertToken(int index, const QString &value);
Q_INVOKABLE void updateToken(int index, const QString &value);
Q_INVOKABLE void appendToken(const QString &value);
Q_INVOKABLE void removeToken(int index);
Q_INVOKABLE void insertIntermediateToken(int index, const QString &value);
Q_INVOKABLE void insertShadowToken(int index, const QString &value);
Q_INVOKABLE void setShadowToken(int index, const QString &value);
bool valid() const;
bool empty() const;
//for debugging
Q_INVOKABLE void command(const QString &string);
void setInvalid(const QString &errorMessage, int index = -1);
void setValid();
QString error() const;
int errorIndex() const;
Q_INVOKABLE bool operatorAllowed(int cursorPosition);
signals:
void validChanged();
void emptyChanged();
void conditionChanged();
void errorChanged();
void errorIndexChanged();
private:
void internalSetup();
ConditionToken valueToToken(const QString &value);
void resetModel();
int checkOrder() const;
void validateAndRebuildTokens();
void rebuildTokens();
ConnectionEditorStatements::ConditionToken toOperatorStatement(const ConditionToken &token);
ConnectionEditorStatements::ComparativeStatement toStatement(const ConditionToken &token);
ConnectionModel *m_connectionModel = nullptr;
ConnectionEditorStatements::MatchedCondition &m_condition;
QList<ConditionToken> m_tokens;
bool m_valid = false;
QString m_errorMessage;
int m_errorIndex = -1;
};
class ConnectionModelStatementDelegate : public QObject
{
Q_OBJECT
public:
explicit ConnectionModelStatementDelegate(ConnectionModel *model);
enum ActionType { CallFunction, Assign, ChangeState, SetProperty, PrintMessage, Custom };
Q_ENUM(ActionType)
Q_PROPERTY(ActionType actionType READ actionType NOTIFY actionTypeChanged)
Q_PROPERTY(PropertyTreeModelDelegate *function READ function CONSTANT)
Q_PROPERTY(PropertyTreeModelDelegate *lhs READ lhs CONSTANT)
Q_PROPERTY(PropertyTreeModelDelegate *rhsAssignment READ rhsAssignment CONSTANT)
Q_PROPERTY(StudioQmlTextBackend *stringArgument READ stringArgument CONSTANT)
Q_PROPERTY(StudioQmlComboBoxBackend *states READ states CONSTANT)
Q_PROPERTY(StudioQmlComboBoxBackend *stateTargets READ stateTargets CONSTANT)
void setActionType(ActionType type);
void setup();
void setStatement(ConnectionEditorStatements::MatchedStatement &statement);
ConnectionEditorStatements::MatchedStatement &statement();
signals:
void actionTypeChanged();
void statementChanged();
private:
ActionType actionType() const;
PropertyTreeModelDelegate *signal();
PropertyTreeModelDelegate *function();
PropertyTreeModelDelegate *lhs();
PropertyTreeModelDelegate *rhsAssignment();
StudioQmlTextBackend *stringArgument();
StudioQmlComboBoxBackend *stateTargets();
StudioQmlComboBoxBackend *states();
void handleFunctionChanged();
void handleLhsChanged();
void handleRhsAssignmentChanged();
void handleStringArgumentChanged();
void handleStateChanged();
void handleStateTargetsChanged();
void setupAssignment();
void setupSetProperty();
void setupCallFunction();
void setupChangeState();
void setupStates();
void setupPrintMessage();
void setupPropertyType();
QString baseStateName() const;
ActionType m_actionType;
PropertyTreeModelDelegate m_functionDelegate;
PropertyTreeModelDelegate m_lhsDelegate;
PropertyTreeModelDelegate m_rhsAssignmentDelegate;
ConnectionEditorStatements::MatchedStatement &m_statement;
ConnectionModel *m_model = nullptr;
StudioQmlTextBackend m_stringArgument;
StudioQmlComboBoxBackend m_stateTargets;
StudioQmlComboBoxBackend m_states;
};
class ConnectionModelBackendDelegate : public QObject
{
Q_OBJECT
Q_PROPERTY(int currentRow READ currentRow WRITE setCurrentRow NOTIFY currentRowChanged)
Q_PROPERTY(ActionType actionType READ actionType NOTIFY actionTypeChanged)
Q_PROPERTY(PropertyTreeModelDelegate *signal READ signal CONSTANT)
Q_PROPERTY(ConnectionModelStatementDelegate *okStatement READ okStatement CONSTANT)
Q_PROPERTY(ConnectionModelStatementDelegate *koStatement READ koStatement CONSTANT)
Q_PROPERTY(ConditionListModel *conditionListModel READ conditionListModel CONSTANT)
Q_PROPERTY(bool hasCondition READ hasCondition NOTIFY hasConditionChanged)
Q_PROPERTY(bool hasElse READ hasElse NOTIFY hasElseChanged)
Q_PROPERTY(QString source READ source NOTIFY sourceChanged)
Q_PROPERTY(QString indentedSource READ indentedSource NOTIFY sourceChanged)
Q_PROPERTY(PropertyTreeModel *propertyTreeModel READ propertyTreeModel CONSTANT)
Q_PROPERTY(PropertyListProxyModel *propertyListProxyModel READ propertyListProxyModel CONSTANT)
public:
explicit ConnectionModelBackendDelegate(ConnectionModel *model);
using ActionType = ConnectionModelStatementDelegate::ActionType;
Q_INVOKABLE void changeActionType(QmlDesigner::ConnectionModelStatementDelegate::ActionType actionType);
Q_INVOKABLE void addCondition();
Q_INVOKABLE void removeCondition();
Q_INVOKABLE void addElse();
Q_INVOKABLE void removeElse();
Q_INVOKABLE void setNewSource(const QString &newSource);
void update() override;
void setCurrentRow(int i);
void update();
Q_INVOKABLE void jumpToCode();
PropertyTreeModelDelegate *signal();
signals:
void currentRowChanged();
void actionTypeChanged();
void hasConditionChanged();
void hasElseChanged();
void sourceChanged();
void popupShouldClose();
void popupShouldOpen();
private slots:
void handleTargetChanged();
private:
AbstractProperty getSourceProperty() const override;
void setPropertySource(const QString &source) override;
SignalHandlerProperty getSignalHandlerProperty() const;
int currentRow() const;
void handleException();
bool hasCondition() const;
bool hasElse() const;
void setHasCondition(bool b);
void setHasElse(bool b);
ActionType actionType() const;
PropertyTreeModelDelegate *signal();
ConnectionModelStatementDelegate *okStatement();
ConnectionModelStatementDelegate *koStatement();
ConditionListModel *conditionListModel();
QString indentedSource() const;
QString source() const;
void setSource(const QString &source);
PropertyTreeModel *propertyTreeModel();
PropertyListProxyModel *propertyListProxyModel();
void setupCondition();
void setupHandlerAndStatements();
void handleTargetChanged();
void handleOkStatementChanged();
void handleKOStatementChanged();
void handleConditionChanged();
void commitNewSource(const QString &source);
ActionType m_actionType;
QString m_exceptionError;
int m_currentRow = -1;
ConnectionEditorStatements::Handler m_handler;
PropertyTreeModelDelegate m_signalDelegate;
ConnectionModelStatementDelegate m_okStatementDelegate;
ConnectionModelStatementDelegate m_koStatementDelegate;
ConditionListModel m_conditionListModel;
bool m_hasCondition = false;
bool m_hasElse = false;
QString m_source;
PropertyTreeModel m_propertyTreeModel;
PropertyListProxyModel m_propertyListProxyModel;
bool m_blockReflection = false;
QPointer<ConnectionModel> m_model = nullptr;
};

View File

@@ -83,10 +83,8 @@ public:
0,
"DynamicPropertiesModelBackendDelegate");
qmlRegisterType<ConnectionModelStatementDelegate>("ConnectionsEditorEditorBackend",
1,
0,
"ConnectionModelStatementDelegate");
// TODO: register in the property editor along with the ScriptEditorBackend
qmlRegisterType<StatementDelegate>("ScriptEditorBackend", 1, 0, "StatementDelegate");
qmlRegisterType<ConditionListModel>("ConnectionsEditorEditorBackend", 1, 0, "ConditionListModel");

View File

@@ -2,7 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "dynamicpropertiesitem.h"
#include "connectioneditorutils.h"
#include <scripteditorutils.h>
#include <abstractproperty.h>
#include <abstractview.h>

View File

@@ -2,22 +2,23 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "dynamicpropertiesmodel.h"
#include "connectioneditorlogging.h"
#include "dynamicpropertiesitem.h"
#include "connectioneditorutils.h"
#include <abstractproperty.h>
#include <bindingproperty.h>
#include <modelfwd.h>
#include <rewritertransaction.h>
#include <rewritingexception.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
#include <variantproperty.h>
#include <qmlchangeset.h>
#include <qmldesignerconstants.h>
#include <qmldesignerplugin.h>
#include <qmlobjectnode.h>
#include <qmltimeline.h>
#include <rewritertransaction.h>
#include <rewritingexception.h>
#include <scripteditorutils.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
#include <variantproperty.h>
#include <optional>

View File

@@ -27,7 +27,7 @@
#include "bindingproperty.h"
#include "propertyeditorvalue.h"
#include "connectioneditorutils.h"
#include <scripteditorutils.h>
#include <dynamicpropertiesmodel.h>

View File

@@ -163,8 +163,8 @@ std::vector<PropertyName> properityLists()
return result;
}
PropertyTreeModel::PropertyTreeModel(ConnectionView *view)
: m_connectionView(view)
PropertyTreeModel::PropertyTreeModel(AbstractView *view)
: m_view(view)
{}
void PropertyTreeModel::resetModel()
@@ -257,7 +257,7 @@ Qt::ItemFlags PropertyTreeModel::flags(const QModelIndex &) const
QModelIndex PropertyTreeModel::index(int row, int column, const QModelIndex &parent) const
{
auto internalId = parent.internalId();
if (!m_connectionView->isAttached())
if (!m_view->isAttached())
return {};
if (!parent.isValid())
@@ -337,7 +337,7 @@ QPersistentModelIndex PropertyTreeModel::indexForInternalIdAndRow(quintptr inter
int PropertyTreeModel::rowCount(const QModelIndex &parent) const
{
if (!m_connectionView->isAttached() || parent.column() > 0)
if (!m_view->isAttached() || parent.column() > 0)
return 0;
if (!parent.isValid())
@@ -404,10 +404,10 @@ const std::vector<PropertyName> PropertyTreeModel::getProperties(const ModelNode
ModelNode PropertyTreeModel::getModelNodeForId(const QString &id) const
{
if (!m_connectionView->isAttached())
if (!m_view->isAttached())
return {};
return m_connectionView->modelNodeForId(id);
return m_view->modelNodeForId(id);
}
QModelIndex PropertyTreeModel::ensureModelIndex(const ModelNode &node, int row) const
@@ -473,10 +473,10 @@ void PropertyTreeModel::testModel()
const QList<ModelNode> PropertyTreeModel::allModelNodesWithIdsSortedByDisplayName() const
{
if (!m_connectionView->isAttached())
if (!m_view->isAttached())
return {};
return Utils::sorted(ModelUtils::allModelNodesWithId(m_connectionView),
return Utils::sorted(ModelUtils::allModelNodesWithId(m_view),
[](const ModelNode &lhs, const ModelNode &rhs) {
return lhs.displayName() < rhs.displayName();
});
@@ -882,7 +882,7 @@ QString PropertyListProxyModel::parentName() const
return m_treeModel->data(m_parentIndex, PropertyTreeModel::UserRoles::PropertyNameRole).toString();
}
PropertyTreeModelDelegate::PropertyTreeModelDelegate(ConnectionView *view)
PropertyTreeModelDelegate::PropertyTreeModelDelegate(AbstractView *view)
: m_model(view)
{
connect(&m_nameCombboBox, &StudioQmlComboBoxBackend::activated, this, [this] {

View File

@@ -49,7 +49,8 @@ public:
BoolType
};
PropertyTreeModel(ConnectionView *view);
// PropertyTreeModel(ConnectionView *view);
PropertyTreeModel(AbstractView *view);
void resetModel();
@@ -120,7 +121,7 @@ private:
const PropertyMetaInfo &metaInfo,
bool recursive) const;
ConnectionView *m_connectionView;
AbstractView *m_view;
mutable std::set<DataCacheItem> m_indexCache;
mutable std::vector<DataCacheItem> m_indexHash;
@@ -187,7 +188,7 @@ class PropertyTreeModelDelegate : public QObject
Q_PROPERTY(StudioQmlComboBoxBackend *id READ idCombboBox CONSTANT)
public:
explicit PropertyTreeModelDelegate(ConnectionView *view);
explicit PropertyTreeModelDelegate(AbstractView *view);
void setPropertyType(PropertyTreeModel::PropertyTypes type);
void setup(const QString &id, const QString &name, bool *nameExists = nullptr);
void setupNameComboBox(const QString &id, const QString &name, bool *nameExists);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,250 @@
// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once
#include "propertytreemodel.h"
#include "scripteditorstatements.h"
namespace QmlDesigner {
class ConditionListModel : public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(bool valid READ valid NOTIFY validChanged)
Q_PROPERTY(bool empty READ empty NOTIFY emptyChanged)
Q_PROPERTY(QString error READ error NOTIFY errorChanged)
Q_PROPERTY(int errorIndex READ errorIndex NOTIFY errorIndexChanged)
public:
enum ConditionType { Intermediate, Invalid, Operator, Literal, Variable, Shadow };
Q_ENUM(ConditionType)
struct ConditionToken
{
ConditionType type;
QString value;
};
ConditionListModel(AbstractView *view);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QHash<int, QByteArray> roleNames() const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
void setup();
void setCondition(ScriptEditorStatements::MatchedCondition &condition);
ScriptEditorStatements::MatchedCondition &condition();
static ConditionToken tokenFromConditionToken(const ScriptEditorStatements::ConditionToken &token);
static ConditionToken tokenFromComparativeStatement(
const ScriptEditorStatements::ComparativeStatement &token);
Q_INVOKABLE void insertToken(int index, const QString &value);
Q_INVOKABLE void updateToken(int index, const QString &value);
Q_INVOKABLE void appendToken(const QString &value);
Q_INVOKABLE void removeToken(int index);
Q_INVOKABLE void insertIntermediateToken(int index, const QString &value);
Q_INVOKABLE void insertShadowToken(int index, const QString &value);
Q_INVOKABLE void setShadowToken(int index, const QString &value);
bool valid() const;
bool empty() const;
//for debugging
Q_INVOKABLE void command(const QString &string);
void setInvalid(const QString &errorMessage, int index = -1);
void setValid();
QString error() const;
int errorIndex() const;
Q_INVOKABLE bool operatorAllowed(int cursorPosition);
signals:
void validChanged();
void emptyChanged();
void conditionChanged();
void errorChanged();
void errorIndexChanged();
private:
void internalSetup();
ConditionToken valueToToken(const QString &value);
void resetModel();
int checkOrder() const;
void validateAndRebuildTokens();
void rebuildTokens();
ScriptEditorStatements::ConditionToken toOperatorStatement(const ConditionToken &token);
ScriptEditorStatements::ComparativeStatement toStatement(const ConditionToken &token);
AbstractView *m_view = nullptr;
ScriptEditorStatements::MatchedCondition &m_condition;
QList<ConditionToken> m_tokens;
bool m_valid = false;
QString m_errorMessage;
int m_errorIndex = -1;
};
class StatementDelegate : public QObject
{
Q_OBJECT
public:
explicit StatementDelegate(AbstractView *view);
enum ActionType { CallFunction, Assign, ChangeState, SetProperty, PrintMessage, Custom };
Q_ENUM(ActionType)
Q_PROPERTY(ActionType actionType READ actionType NOTIFY actionTypeChanged)
Q_PROPERTY(PropertyTreeModelDelegate *function READ function CONSTANT)
Q_PROPERTY(PropertyTreeModelDelegate *lhs READ lhs CONSTANT)
Q_PROPERTY(PropertyTreeModelDelegate *rhsAssignment READ rhsAssignment CONSTANT)
Q_PROPERTY(StudioQmlTextBackend *stringArgument READ stringArgument CONSTANT)
Q_PROPERTY(StudioQmlComboBoxBackend *states READ states CONSTANT)
Q_PROPERTY(StudioQmlComboBoxBackend *stateTargets READ stateTargets CONSTANT)
void setActionType(ActionType type);
void setup();
void setStatement(ScriptEditorStatements::MatchedStatement &statement);
ScriptEditorStatements::MatchedStatement &statement();
signals:
void actionTypeChanged();
void statementChanged();
private:
ActionType actionType() const;
PropertyTreeModelDelegate *function();
PropertyTreeModelDelegate *lhs();
PropertyTreeModelDelegate *rhsAssignment();
StudioQmlTextBackend *stringArgument();
StudioQmlComboBoxBackend *stateTargets();
StudioQmlComboBoxBackend *states();
void handleFunctionChanged();
void handleLhsChanged();
void handleRhsAssignmentChanged();
void handleStringArgumentChanged();
void handleStateChanged();
void handleStateTargetsChanged();
void setupAssignment();
void setupSetProperty();
void setupCallFunction();
void setupChangeState();
void setupStates();
void setupPrintMessage();
void setupPropertyType();
QString baseStateName() const;
ActionType m_actionType;
PropertyTreeModelDelegate m_functionDelegate;
PropertyTreeModelDelegate m_lhsDelegate;
PropertyTreeModelDelegate m_rhsAssignmentDelegate;
ScriptEditorStatements::MatchedStatement &m_statement;
AbstractView *m_view = nullptr;
StudioQmlTextBackend m_stringArgument;
StudioQmlComboBoxBackend m_stateTargets;
StudioQmlComboBoxBackend m_states;
};
class ScriptEditorBackend : public QObject
{
Q_OBJECT
Q_PROPERTY(ActionType actionType READ actionType NOTIFY actionTypeChanged)
Q_PROPERTY(StatementDelegate *okStatement READ okStatement CONSTANT)
Q_PROPERTY(StatementDelegate *koStatement READ koStatement CONSTANT)
Q_PROPERTY(ConditionListModel *conditionListModel READ conditionListModel CONSTANT)
Q_PROPERTY(bool hasCondition READ hasCondition NOTIFY hasConditionChanged)
Q_PROPERTY(bool hasElse READ hasElse NOTIFY hasElseChanged)
Q_PROPERTY(QString source READ source NOTIFY sourceChanged)
Q_PROPERTY(QString indentedSource READ indentedSource NOTIFY sourceChanged)
Q_PROPERTY(PropertyTreeModel *propertyTreeModel READ propertyTreeModel CONSTANT)
Q_PROPERTY(PropertyListProxyModel *propertyListProxyModel READ propertyListProxyModel CONSTANT)
public:
explicit ScriptEditorBackend(AbstractView *view);
using ActionType = StatementDelegate::ActionType;
Q_INVOKABLE void changeActionType(QmlDesigner::StatementDelegate::ActionType actionType);
Q_INVOKABLE void addCondition();
Q_INVOKABLE void removeCondition();
Q_INVOKABLE void addElse();
Q_INVOKABLE void removeElse();
Q_INVOKABLE void setNewSource(const QString &newSource);
Q_INVOKABLE virtual void update();
Q_INVOKABLE void jumpToCode();
signals:
void actionTypeChanged();
void hasConditionChanged();
void hasElseChanged();
void sourceChanged();
void popupShouldClose();
void popupShouldOpen();
protected:
bool blockReflection() const;
;
private:
virtual AbstractProperty getSourceProperty() const;
virtual void setPropertySource(const QString &source);
BindingProperty getBindingProperty() const;
void handleException();
bool hasCondition() const;
bool hasElse() const;
void setHasCondition(bool b);
void setHasElse(bool b);
ActionType actionType() const;
StatementDelegate *okStatement();
StatementDelegate *koStatement();
ConditionListModel *conditionListModel();
QString indentedSource() const;
QString source() const;
void setSource(const QString &source);
PropertyTreeModel *propertyTreeModel();
PropertyListProxyModel *propertyListProxyModel();
void setupCondition();
void setupHandlerAndStatements();
void handleOkStatementChanged();
void handleKOStatementChanged();
void handleConditionChanged();
void commitNewSource(const QString &source);
ActionType m_actionType;
QString m_exceptionError;
ScriptEditorStatements::Handler m_handler;
StatementDelegate m_okStatementDelegate;
StatementDelegate m_koStatementDelegate;
ConditionListModel m_conditionListModel;
bool m_hasCondition = false;
bool m_hasElse = false;
QString m_source;
PropertyTreeModel m_propertyTreeModel;
PropertyListProxyModel m_propertyListProxyModel;
bool m_blockReflection = false;
QPointer<AbstractView> m_view = nullptr;
};
} // namespace QmlDesigner

View File

@@ -1,10 +1,10 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "connectioneditorevaluator.h"
#include "connectioneditorutils.h"
#include "scripteditorevaluator.h"
#include "qmljs/parser/qmljsast_p.h"
#include "qmljs/qmljsdocument.h"
#include "scripteditorutils.h"
#include <utils/ranges.h>
@@ -14,10 +14,10 @@ using namespace QmlDesigner;
using QmlJS::AST::Node;
using Kind = Node::Kind;
using ConnectionEditorStatements::ConditionalStatement;
using ConnectionEditorStatements::ConditionToken;
using ConnectionEditorStatements::MatchedCondition;
using ConnectionEditorStatements::MatchedStatement;
using ScriptEditorStatements::ConditionalStatement;
using ScriptEditorStatements::ConditionToken;
using ScriptEditorStatements::MatchedCondition;
using ScriptEditorStatements::MatchedStatement;
namespace {
enum class TrackingArea { No, Condition, Ok, Ko };
@@ -255,14 +255,14 @@ protected:
void throwRecursionDepthError() override
{
checkValidityAndReturn(false, "Recursion depth problem");
qCWarning(ConnectionEditorLog) << __FUNCTION__ << "Recursion depth error";
qCWarning(ScriptEditorLog) << __FUNCTION__ << "Recursion depth error";
}
void checkAndResetVariable()
{
if (--m_depth == 0) {
m_condition.statements.push_back(
ConnectionEditorStatements::Variable{m_identifier, m_fields.join(".")});
ScriptEditorStatements::Variable{m_identifier, m_fields.join(".")});
m_identifier.clear();
m_fields.clear();
}
@@ -300,7 +300,7 @@ private:
class RightHandVisitor : public QmlJS::AST::Visitor
{
public:
ConnectionEditorStatements::RightHandSide rhs() const { return m_rhs; }
ScriptEditorStatements::RightHandSide rhs() const { return m_rhs; }
void reset()
{
@@ -318,48 +318,48 @@ public:
if (!isValid())
return false;
return ConnectionEditorStatements::isLiteralType(rhs());
return ScriptEditorStatements::isLiteralType(rhs());
}
bool couldBeLHS() const
{
if (!isValid())
return false;
return std::holds_alternative<ConnectionEditorStatements::Variable>(m_rhs);
return std::holds_alternative<ScriptEditorStatements::Variable>(m_rhs);
}
inline bool couldBeVariable() const { return couldBeLHS(); }
ConnectionEditorStatements::Literal literal() const
ScriptEditorStatements::Literal literal() const
{
if (!isLiteralType())
return {};
return std::visit(
Overload{[](const bool &var) -> ConnectionEditorStatements::Literal { return var; },
[](const double &var) -> ConnectionEditorStatements::Literal { return var; },
[](const QString &var) -> ConnectionEditorStatements::Literal { return var; },
[](const auto &) -> ConnectionEditorStatements::Literal { return false; }},
Overload{[](const bool &var) -> ScriptEditorStatements::Literal { return var; },
[](const double &var) -> ScriptEditorStatements::Literal { return var; },
[](const QString &var) -> ScriptEditorStatements::Literal { return var; },
[](const auto &) -> ScriptEditorStatements::Literal { return false; }},
m_rhs);
}
ConnectionEditorStatements::Variable lhs() const
ScriptEditorStatements::Variable lhs() const
{
if (!isValid())
return {};
if (auto rhs = std::get_if<ConnectionEditorStatements::Variable>(&m_rhs))
if (auto rhs = std::get_if<ScriptEditorStatements::Variable>(&m_rhs))
return *rhs;
return {};
}
ConnectionEditorStatements::Variable variable() const
ScriptEditorStatements::Variable variable() const
{
if (!isValid())
return {};
if (auto rhs = std::get_if<ConnectionEditorStatements::Variable>(&m_rhs))
if (auto rhs = std::get_if<ScriptEditorStatements::Variable>(&m_rhs))
return *rhs;
return {};
@@ -478,13 +478,13 @@ protected:
void throwRecursionDepthError() override
{
setFailed();
qCWarning(ConnectionEditorLog) << __FUNCTION__ << "Recursion depth error";
qCWarning(ScriptEditorLog) << __FUNCTION__ << "Recursion depth error";
}
void checkAndResetCal()
{
if (--m_depth == 0) {
m_rhs = ConnectionEditorStatements::MatchedFunction{m_identifier, m_fields.join(".")};
m_rhs = ScriptEditorStatements::MatchedFunction{m_identifier, m_fields.join(".")};
m_specified = true;
m_identifier.clear();
@@ -495,7 +495,7 @@ protected:
void checkAndResetNonCal()
{
if (--m_depth == 0) {
m_rhs = ConnectionEditorStatements::Variable{m_identifier, m_fields.join(".")};
m_rhs = ScriptEditorStatements::Variable{m_identifier, m_fields.join(".")};
m_specified = true;
m_identifier.clear();
@@ -513,18 +513,19 @@ private:
int m_depth = 0;
QString m_identifier;
QStringList m_fields;
ConnectionEditorStatements::RightHandSide m_rhs;
ScriptEditorStatements::RightHandSide m_rhs;
};
MatchedStatement checkForStateSet(const MatchedStatement &currentState)
{
using namespace ConnectionEditorStatements;
return std::visit(
Overload{[](const PropertySet &propertySet) -> MatchedStatement {
if (propertySet.lhs.nodeId.size() && propertySet.lhs.propertyName == u"state"
using namespace ScriptEditorStatements;
return std::visit(Overload{[](const PropertySet &propertySet) -> MatchedStatement {
if (propertySet.lhs.nodeId.size()
&& propertySet.lhs.propertyName == u"state"
&& std::holds_alternative<QString>(propertySet.rhs))
return StateSet{propertySet.lhs.nodeId,
ConnectionEditorStatements::toString(propertySet.rhs)};
ScriptEditorStatements::toString(
propertySet.rhs)};
return propertySet;
},
[](const auto &pSet) -> MatchedStatement { return pSet; }},
@@ -536,9 +537,9 @@ class ConsoleLogEvaluator : public QmlJS::AST::Visitor
public:
bool isValid() { return m_completed; }
ConnectionEditorStatements::ConsoleLog expression()
ScriptEditorStatements::ConsoleLog expression()
{
return ConnectionEditorStatements::ConsoleLog{m_arg};
return ScriptEditorStatements::ConsoleLog{m_arg};
}
protected:
@@ -618,14 +619,14 @@ protected:
void throwRecursionDepthError() override
{
m_failed = true;
qCWarning(ConnectionEditorLog) << __FUNCTION__ << "Recursion depth error";
qCWarning(ScriptEditorLog) << __FUNCTION__ << "Recursion depth error";
}
private:
bool m_failed = false;
bool m_completed = false;
int m_stepId = 0;
ConnectionEditorStatements::RightHandSide m_arg;
ScriptEditorStatements::RightHandSide m_arg;
};
struct StatementReply
@@ -650,10 +651,10 @@ struct StatementReply
} // namespace
class QmlDesigner::ConnectionEditorEvaluatorPrivate
class QmlDesigner::ScriptEditorEvaluatorPrivate
{
friend class ConnectionEditorEvaluator;
using Status = ConnectionEditorEvaluator::Status;
friend class ScriptEditorEvaluator;
using Status = ScriptEditorEvaluator::Status;
public:
bool checkValidityAndReturn(bool valid, const QString &parseError = {});
@@ -731,28 +732,28 @@ private:
QString m_errorString;
Status m_checkStatus = Status::UnStarted;
QList<NodeStatus> m_nodeHierarchy;
ConnectionEditorStatements::Handler m_handler;
ScriptEditorStatements::Handler m_handler;
};
ConnectionEditorEvaluator::ConnectionEditorEvaluator()
: d(std::make_unique<ConnectionEditorEvaluatorPrivate>())
ScriptEditorEvaluator::ScriptEditorEvaluator()
: d(std::make_unique<ScriptEditorEvaluatorPrivate>())
{}
ConnectionEditorEvaluator::~ConnectionEditorEvaluator() {}
ScriptEditorEvaluator::~ScriptEditorEvaluator() {}
ConnectionEditorEvaluator::Status ConnectionEditorEvaluator::status() const
ScriptEditorEvaluator::Status ScriptEditorEvaluator::status() const
{
return d->m_checkStatus;
}
ConnectionEditorStatements::Handler ConnectionEditorEvaluator::resultNode() const
ScriptEditorStatements::Handler ScriptEditorEvaluator::resultNode() const
{
return (d->m_checkStatus == Succeeded) ? d->m_handler : ConnectionEditorStatements::EmptyBlock{};
return (d->m_checkStatus == Succeeded) ? d->m_handler : ScriptEditorStatements::EmptyBlock{};
}
QString ConnectionEditorEvaluator::getDisplayStringForType(const QString &statement)
QString ScriptEditorEvaluator::getDisplayStringForType(const QString &statement)
{
ConnectionEditorEvaluator evaluator;
ScriptEditorEvaluator evaluator;
QmlJS::Document::MutablePtr newDoc = QmlJS::Document::create(Utils::FilePath::fromString(
"<expression>"),
QmlJS::Dialect::JavaScript);
@@ -761,23 +762,23 @@ QString ConnectionEditorEvaluator::getDisplayStringForType(const QString &statem
newDoc->parseJavaScript();
if (!newDoc->isParsedCorrectly())
return ConnectionEditorStatements::CUSTOM_DISPLAY_NAME;
return ScriptEditorStatements::CUSTOM_DISPLAY_NAME;
newDoc->ast()->accept(&evaluator);
const bool valid = evaluator.status() == ConnectionEditorEvaluator::Succeeded;
const bool valid = evaluator.status() == ScriptEditorEvaluator::Succeeded;
if (!valid)
return ConnectionEditorStatements::CUSTOM_DISPLAY_NAME;
return ScriptEditorStatements::CUSTOM_DISPLAY_NAME;
auto result = evaluator.resultNode();
return QmlDesigner::ConnectionEditorStatements::toDisplayName(result);
return QmlDesigner::ScriptEditorStatements::toDisplayName(result);
}
ConnectionEditorStatements::Handler ConnectionEditorEvaluator::parseStatement(const QString &statement)
ScriptEditorStatements::Handler ScriptEditorEvaluator::parseStatement(const QString &statement)
{
ConnectionEditorEvaluator evaluator;
ScriptEditorEvaluator evaluator;
QmlJS::Document::MutablePtr newDoc = QmlJS::Document::create(Utils::FilePath::fromString(
"<expression>"),
QmlJS::Dialect::JavaScript);
@@ -786,19 +787,19 @@ ConnectionEditorStatements::Handler ConnectionEditorEvaluator::parseStatement(co
newDoc->parseJavaScript();
if (!newDoc->isParsedCorrectly())
return ConnectionEditorStatements::EmptyBlock{};
return ScriptEditorStatements::EmptyBlock{};
newDoc->ast()->accept(&evaluator);
const bool valid = evaluator.status() == ConnectionEditorEvaluator::Succeeded;
const bool valid = evaluator.status() == ScriptEditorEvaluator::Succeeded;
if (!valid)
return ConnectionEditorStatements::EmptyBlock{};
return ScriptEditorStatements::EmptyBlock{};
return evaluator.resultNode();
}
bool ConnectionEditorEvaluator::preVisit(Node *node)
bool ScriptEditorEvaluator::preVisit(Node *node)
{
if (d->m_nodeHierarchy.size()) {
NodeStatus &parentNode = d->m_nodeHierarchy.last();
@@ -832,7 +833,7 @@ bool ConnectionEditorEvaluator::preVisit(Node *node)
}
}
void ConnectionEditorEvaluator::postVisit(QmlJS::AST::Node *node)
void ScriptEditorEvaluator::postVisit(QmlJS::AST::Node *node)
{
if (d->m_nodeHierarchy.isEmpty()) {
d->checkValidityAndReturn(false, "Unexpected post visiting");
@@ -859,18 +860,18 @@ void ConnectionEditorEvaluator::postVisit(QmlJS::AST::Node *node)
}
}
bool ConnectionEditorEvaluator::visit([[maybe_unused]] QmlJS::AST::Program *program)
bool ScriptEditorEvaluator::visit([[maybe_unused]] QmlJS::AST::Program *program)
{
d->setStatus(UnFinished);
d->setTrackingArea(false, 0);
d->m_ifStatement = 0;
d->m_consoleLogCount = 0;
d->m_consoleIdentifierCount = 0;
d->m_handler = ConnectionEditorStatements::EmptyBlock{};
d->m_handler = ScriptEditorStatements::EmptyBlock{};
return true;
}
bool ConnectionEditorEvaluator::visit([[maybe_unused]] QmlJS::AST::IfStatement *ifStatement)
bool ScriptEditorEvaluator::visit([[maybe_unused]] QmlJS::AST::IfStatement *ifStatement)
{
if (d->m_ifStatement++)
return d->checkValidityAndReturn(false, "Nested if conditions are not supported");
@@ -885,7 +886,7 @@ bool ConnectionEditorEvaluator::visit([[maybe_unused]] QmlJS::AST::IfStatement *
return d->checkValidityAndReturn(true);
}
bool ConnectionEditorEvaluator::visit(QmlJS::AST::IdentifierExpression *identifier)
bool ScriptEditorEvaluator::visit(QmlJS::AST::IdentifierExpression *identifier)
{
if (d->parentNodeStatus() == Kind::Kind_FieldMemberExpression)
if (d->m_consoleLogCount)
@@ -896,7 +897,7 @@ bool ConnectionEditorEvaluator::visit(QmlJS::AST::IdentifierExpression *identifi
return d->checkValidityAndReturn(true);
}
bool ConnectionEditorEvaluator::visit(QmlJS::AST::BinaryExpression *binaryExpression)
bool ScriptEditorEvaluator::visit(QmlJS::AST::BinaryExpression *binaryExpression)
{
if (d->isInIfCondition()) {
if (binaryExpression->op == QSOperator::Assign)
@@ -923,7 +924,7 @@ bool ConnectionEditorEvaluator::visit(QmlJS::AST::BinaryExpression *binaryExpres
return false;
} else {
MatchedStatement *currentStatement = d->currentStatement();
if (currentStatement && ConnectionEditorStatements::isEmptyStatement(*currentStatement)
if (currentStatement && ScriptEditorStatements::isEmptyStatement(*currentStatement)
&& d->parentNodeStatus().childId() == 0) {
if (binaryExpression->op == QSOperator::Assign) {
RightHandVisitor variableVisitor;
@@ -932,16 +933,16 @@ bool ConnectionEditorEvaluator::visit(QmlJS::AST::BinaryExpression *binaryExpres
if (!variableVisitor.couldBeLHS())
return d->checkValidityAndReturn(false, "Invalid left hand.");
ConnectionEditorStatements::Variable lhs = variableVisitor.lhs();
ScriptEditorStatements::Variable lhs = variableVisitor.lhs();
variableVisitor.reset();
binaryExpression->right->accept(&variableVisitor);
if (variableVisitor.couldBeLHS()) {
ConnectionEditorStatements::Assignment assignment{lhs, variableVisitor.variable()};
ScriptEditorStatements::Assignment assignment{lhs, variableVisitor.variable()};
*currentStatement = assignment;
} else if (variableVisitor.isLiteralType()) {
ConnectionEditorStatements::PropertySet propSet{lhs, variableVisitor.literal()};
ScriptEditorStatements::PropertySet propSet{lhs, variableVisitor.literal()};
*currentStatement = propSet;
} else {
return d->checkValidityAndReturn(false, "Invalid RHS");
@@ -955,7 +956,7 @@ bool ConnectionEditorEvaluator::visit(QmlJS::AST::BinaryExpression *binaryExpres
return d->checkValidityAndReturn(true);
}
bool ConnectionEditorEvaluator::visit(QmlJS::AST::FieldMemberExpression *fieldExpression)
bool ScriptEditorEvaluator::visit(QmlJS::AST::FieldMemberExpression *fieldExpression)
{
if (d->parentNodeStatus() == Kind::Kind_CallExpression && fieldExpression->name == u"log")
d->m_consoleLogCount++;
@@ -965,7 +966,7 @@ bool ConnectionEditorEvaluator::visit(QmlJS::AST::FieldMemberExpression *fieldEx
return d->checkValidityAndReturn(true);
}
bool ConnectionEditorEvaluator::visit(QmlJS::AST::CallExpression *callExpression)
bool ScriptEditorEvaluator::visit(QmlJS::AST::CallExpression *callExpression)
{
if (d->isInIfCondition())
return d->checkValidityAndReturn(false, "Functions are not allowd in the expressions");
@@ -974,7 +975,7 @@ bool ConnectionEditorEvaluator::visit(QmlJS::AST::CallExpression *callExpression
if (!currentStatement)
return d->checkValidityAndReturn(false, "Invalid place to call an expression");
if (ConnectionEditorStatements::isEmptyStatement(*currentStatement)) {
if (ScriptEditorStatements::isEmptyStatement(*currentStatement)) {
if (d->parentNodeStatus().childId() == 0) {
ConsoleLogEvaluator logEvaluator;
callExpression->accept(&logEvaluator);
@@ -985,8 +986,8 @@ bool ConnectionEditorEvaluator::visit(QmlJS::AST::CallExpression *callExpression
callExpression->accept(&callVisitor);
if (callVisitor.isValid()) {
ConnectionEditorStatements::RightHandSide rhs = callVisitor.rhs();
if (auto rhs_ = std::get_if<ConnectionEditorStatements::MatchedFunction>(&rhs))
ScriptEditorStatements::RightHandSide rhs = callVisitor.rhs();
if (auto rhs_ = std::get_if<ScriptEditorStatements::MatchedFunction>(&rhs))
*currentStatement = *rhs_;
else
return d->checkValidityAndReturn(false, "Invalid Matched Function type.");
@@ -999,7 +1000,7 @@ bool ConnectionEditorEvaluator::visit(QmlJS::AST::CallExpression *callExpression
return d->checkValidityAndReturn(true);
}
bool ConnectionEditorEvaluator::visit([[maybe_unused]] QmlJS::AST::Block *block)
bool ScriptEditorEvaluator::visit([[maybe_unused]] QmlJS::AST::Block *block)
{
Kind parentKind = d->parentNodeStatus();
@@ -1013,7 +1014,7 @@ bool ConnectionEditorEvaluator::visit([[maybe_unused]] QmlJS::AST::Block *block)
return d->checkValidityAndReturn(false, "Block count ptoblem");
}
bool ConnectionEditorEvaluator::visit(QmlJS::AST::ArgumentList *arguments)
bool ScriptEditorEvaluator::visit(QmlJS::AST::ArgumentList *arguments)
{
if (d->trackingArea() == TrackingArea::Condition)
return d->checkValidityAndReturn(false, "Arguments are not supported in if condition");
@@ -1022,7 +1023,7 @@ bool ConnectionEditorEvaluator::visit(QmlJS::AST::ArgumentList *arguments)
if (!currentStatement)
return d->checkValidityAndReturn(false, "No statement found for argument");
if (!ConnectionEditorStatements::isConsoleLog(*currentStatement))
if (!ScriptEditorStatements::isConsoleLog(*currentStatement))
return d->checkValidityAndReturn(false, "Arguments are only supported for console.log");
if (d->m_acceptLogArgument && !arguments->next)
@@ -1031,13 +1032,13 @@ bool ConnectionEditorEvaluator::visit(QmlJS::AST::ArgumentList *arguments)
return d->checkValidityAndReturn(false, "The only supported argument is in console.log");
}
void ConnectionEditorEvaluator::endVisit([[maybe_unused]] QmlJS::AST::Program *program)
void ScriptEditorEvaluator::endVisit([[maybe_unused]] QmlJS::AST::Program *program)
{
if (status() == UnFinished)
d->setStatus(Succeeded);
}
void ConnectionEditorEvaluator::endVisit(QmlJS::AST::FieldMemberExpression *fieldExpression)
void ScriptEditorEvaluator::endVisit(QmlJS::AST::FieldMemberExpression *fieldExpression)
{
if (status() != UnFinished)
return;
@@ -1053,12 +1054,12 @@ void ConnectionEditorEvaluator::endVisit(QmlJS::AST::FieldMemberExpression *fiel
}
}
void ConnectionEditorEvaluator::endVisit([[maybe_unused]] QmlJS::AST::CallExpression *callExpression)
void ScriptEditorEvaluator::endVisit([[maybe_unused]] QmlJS::AST::CallExpression *callExpression)
{
d->m_acceptLogArgument = false;
}
void ConnectionEditorEvaluator::endVisit(QmlJS::AST::IfStatement * /*ifStatement*/)
void ScriptEditorEvaluator::endVisit(QmlJS::AST::IfStatement * /*ifStatement*/)
{
if (status() != UnFinished)
return;
@@ -1071,7 +1072,7 @@ void ConnectionEditorEvaluator::endVisit(QmlJS::AST::IfStatement * /*ifStatement
}
}
void ConnectionEditorEvaluator::endVisit(QmlJS::AST::StatementList * /*statementList*/)
void ScriptEditorEvaluator::endVisit(QmlJS::AST::StatementList * /*statementList*/)
{
if (status() != UnFinished)
return;
@@ -1080,26 +1081,26 @@ void ConnectionEditorEvaluator::endVisit(QmlJS::AST::StatementList * /*statement
d->checkValidityAndReturn(false, "More than one statements are available.");
}
void ConnectionEditorEvaluator::throwRecursionDepthError()
void ScriptEditorEvaluator::throwRecursionDepthError()
{
d->checkValidityAndReturn(false, "Recursion depth problem");
qCWarning(ConnectionEditorLog) << __FUNCTION__ << "Recursion depth error";
qCWarning(ScriptEditorLog) << __FUNCTION__ << "Recursion depth error";
}
bool ConnectionEditorEvaluatorPrivate::checkValidityAndReturn(bool valid, const QString &parseError)
bool ScriptEditorEvaluatorPrivate::checkValidityAndReturn(bool valid, const QString &parseError)
{
if (!valid) {
if (m_checkStatus != Status::Failed) {
setStatus(Status::Failed);
m_errorString = parseError;
qCWarning(ConnectionEditorLog) << __FUNCTION__ << "Parse error" << parseError;
qCWarning(ScriptEditorLog) << __FUNCTION__ << "Parse error" << parseError;
}
}
return m_checkStatus;
}
NodeStatus ConnectionEditorEvaluatorPrivate::nodeStatus(int reverseLevel) const
NodeStatus ScriptEditorEvaluatorPrivate::nodeStatus(int reverseLevel) const
{
if (m_nodeHierarchy.size() > reverseLevel)
return m_nodeHierarchy.at(m_nodeHierarchy.size() - reverseLevel - 1);

View File

@@ -3,7 +3,7 @@
#pragma once
#include "connectioneditorstatements.h"
#include "scripteditorstatements.h"
#include "qmldesigner_global.h"
@@ -11,21 +11,21 @@
namespace QmlDesigner {
class ConnectionEditorEvaluatorPrivate;
class ScriptEditorEvaluatorPrivate;
class QMLDESIGNER_EXPORT ConnectionEditorEvaluator : public QmlJS::AST::Visitor
class QMLDESIGNER_EXPORT ScriptEditorEvaluator : public QmlJS::AST::Visitor
{
public:
enum Status { UnStarted, UnFinished, Succeeded, Failed };
ConnectionEditorEvaluator();
virtual ~ConnectionEditorEvaluator();
ScriptEditorEvaluator();
virtual ~ScriptEditorEvaluator();
Status status() const;
ConnectionEditorStatements::Handler resultNode() const;
ScriptEditorStatements::Handler resultNode() const;
static QString getDisplayStringForType(const QString &statement);
static ConnectionEditorStatements::Handler parseStatement(const QString &statement);
static ScriptEditorStatements::Handler parseStatement(const QString &statement);
protected:
bool preVisit(QmlJS::AST::Node *node) override;
@@ -49,7 +49,7 @@ protected:
void throwRecursionDepthError() override;
private:
std::unique_ptr<ConnectionEditorEvaluatorPrivate> d;
std::unique_ptr<ScriptEditorEvaluatorPrivate> d;
};
} // namespace QmlDesigner

View File

@@ -1,11 +1,11 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "connectioneditorstatements.h"
#include "scripteditorstatements.h"
#include <QHash>
using namespace QmlDesigner;
using namespace ConnectionEditorStatements;
using namespace ScriptEditorStatements;
namespace {
template<typename... Ts>
@@ -39,31 +39,31 @@ struct StringVisitor
return "Variable{" + var.nodeId + propertyName + "}";
}
QString operator()(const ConnectionEditorStatements::MatchedFunction &func)
QString operator()(const ScriptEditorStatements::MatchedFunction &func)
{
return "MatchedFunction{" + func.nodeId + "." + func.functionName + "}";
}
QString operator()(const ConnectionEditorStatements::Assignment &assignment)
QString operator()(const ScriptEditorStatements::Assignment &assignment)
{
return "Assignment{" + assignment.lhs.expression() + " = " + StringVisitor()(assignment.rhs)
+ "}";
}
QString operator()(const ConnectionEditorStatements::PropertySet &propertySet)
QString operator()(const ScriptEditorStatements::PropertySet &propertySet)
{
return "PropertySet{" + propertySet.lhs.expression() + " = "
+ std::visit(StringVisitor{}, propertySet.rhs) + "}";
}
QString operator()(const ConnectionEditorStatements::StateSet &stateSet)
QString operator()(const ScriptEditorStatements::StateSet &stateSet)
{
return "StateSet{" + stateSet.nodeId + ".state = " + stateSet.stateName + "}";
}
QString operator()(const ConnectionEditorStatements::EmptyBlock &) { return "EmptyBlock{}"; }
QString operator()(const ScriptEditorStatements::EmptyBlock &) { return "EmptyBlock{}"; }
QString operator()(const ConnectionEditorStatements::ConsoleLog &consoleLog)
QString operator()(const ScriptEditorStatements::ConsoleLog &consoleLog)
{
return "ConsoleLog{" + std::visit(StringVisitor{}, consoleLog.argument) + "}";
}
@@ -92,7 +92,7 @@ struct StringVisitor
}
}
QString operator()(const ConnectionEditorStatements::MatchedCondition &matched)
QString operator()(const ScriptEditorStatements::MatchedCondition &matched)
{
if (!matched.statements.size() && !matched.tokens.size())
return "MatchedCondition{}";
@@ -113,7 +113,7 @@ struct StringVisitor
return value;
}
QString operator()(const ConnectionEditorStatements::ConditionalStatement &conditional)
QString operator()(const ScriptEditorStatements::ConditionalStatement &conditional)
{
QString value;
value.reserve(200);
@@ -130,7 +130,7 @@ struct StringVisitor
return value;
}
QString operator()(const ConnectionEditorStatements::MatchedStatement &conditional)
QString operator()(const ScriptEditorStatements::MatchedStatement &conditional)
{
return std::visit(StringVisitor{}, conditional);
}
@@ -156,7 +156,7 @@ struct JSOverload
return var.nodeId + propertyName;
}
QString operator()(const ConnectionEditorStatements::MatchedFunction &func)
QString operator()(const ScriptEditorStatements::MatchedFunction &func)
{
QString funcName;
if (func.functionName.size())
@@ -165,31 +165,31 @@ struct JSOverload
return func.nodeId + funcName + "()";
}
QString operator()(const ConnectionEditorStatements::Assignment &assignment)
QString operator()(const ScriptEditorStatements::Assignment &assignment)
{
return JSOverload()(assignment.lhs) + " = " + JSOverload()(assignment.rhs);
}
QString operator()(const ConnectionEditorStatements::PropertySet &propertySet)
QString operator()(const ScriptEditorStatements::PropertySet &propertySet)
{
return JSOverload()(propertySet.lhs) + " = " + std::visit(JSOverload{}, propertySet.rhs);
}
QString operator()(const ConnectionEditorStatements::StateSet &stateSet)
QString operator()(const ScriptEditorStatements::StateSet &stateSet)
{
return stateSet.nodeId + ".state = " + stateSet.stateName;
}
QString operator()(const ConnectionEditorStatements::EmptyBlock &) { return "{}"; }
QString operator()(const ScriptEditorStatements::EmptyBlock &) { return "{}"; }
QString operator()(const ConnectionEditorStatements::ConsoleLog &consoleLog)
QString operator()(const ScriptEditorStatements::ConsoleLog &consoleLog)
{
return "console.log(" + std::visit(JSOverload{}, consoleLog.argument) + ")";
}
QString operator()(const ConditionToken &token) { return toJavascript(token); }
QString operator()(const ConnectionEditorStatements::MatchedCondition &matched)
QString operator()(const ScriptEditorStatements::MatchedCondition &matched)
{
if (!matched.statements.size() && !matched.tokens.size())
return {};
@@ -209,7 +209,7 @@ struct JSOverload
return value;
}
QString operator()(const ConnectionEditorStatements::MatchedStatement &statement)
QString operator()(const ScriptEditorStatements::MatchedStatement &statement)
{
if (isEmptyStatement(statement))
return {};
@@ -217,7 +217,7 @@ struct JSOverload
return std::visit(JSOverload{}, statement);
}
QString operator()(const ConnectionEditorStatements::ConditionalStatement &conditional)
QString operator()(const ScriptEditorStatements::ConditionalStatement &conditional)
{
QString value;
value.reserve(200);
@@ -240,47 +240,47 @@ struct JSOverload
} // namespace
bool ConnectionEditorStatements::isEmptyStatement(const MatchedStatement &stat)
bool ScriptEditorStatements::isEmptyStatement(const MatchedStatement &stat)
{
return std::holds_alternative<EmptyBlock>(stat);
}
QString ConnectionEditorStatements::toString(const ComparativeStatement &stat)
QString ScriptEditorStatements::toString(const ComparativeStatement &stat)
{
return std::visit(StringVisitor{}, stat);
}
QString ConnectionEditorStatements::toString(const RightHandSide &rhs)
QString ScriptEditorStatements::toString(const RightHandSide &rhs)
{
return std::visit(StringVisitor{}, rhs);
}
QString ConnectionEditorStatements::toString(const Literal &literal)
QString ScriptEditorStatements::toString(const Literal &literal)
{
return std::visit(StringVisitor{}, literal);
}
QString ConnectionEditorStatements::toString(const MatchedStatement &statement)
QString ScriptEditorStatements::toString(const MatchedStatement &statement)
{
return std::visit(StringVisitor{}, statement);
}
QString ConnectionEditorStatements::toString(const Handler &handler)
QString ScriptEditorStatements::toString(const Handler &handler)
{
return std::visit(StringVisitor{}, handler);
}
QString ConnectionEditorStatements::toJavascript(const Handler &handler)
QString ScriptEditorStatements::toJavascript(const Handler &handler)
{
return std::visit(JSOverload{}, handler);
}
bool ConnectionEditorStatements::isConsoleLog(const MatchedStatement &curState)
bool ScriptEditorStatements::isConsoleLog(const MatchedStatement &curState)
{
return std::holds_alternative<ConsoleLog>(curState);
}
bool ConnectionEditorStatements::isLiteralType(const RightHandSide &var)
bool ScriptEditorStatements::isLiteralType(const RightHandSide &var)
{
return std::visit(Overload{[](const double &) { return true; },
[](const bool &) { return true; },
@@ -289,7 +289,7 @@ bool ConnectionEditorStatements::isLiteralType(const RightHandSide &var)
var);
}
QString ConnectionEditorStatements::toDisplayName(const MatchedStatement &statement)
QString ScriptEditorStatements::toDisplayName(const MatchedStatement &statement)
{
const char *displayName = std::visit(
Overload{[](const MatchedFunction &) { return FUNCTION_DISPLAY_NAME; },
@@ -303,7 +303,7 @@ QString ConnectionEditorStatements::toDisplayName(const MatchedStatement &statem
return QString::fromLatin1(displayName);
}
QString ConnectionEditorStatements::toDisplayName(const Handler &handler)
QString ScriptEditorStatements::toDisplayName(const Handler &handler)
{
const MatchedStatement &statement = std::visit(
Overload{[](const MatchedStatement &statement) { return statement; },
@@ -312,51 +312,49 @@ QString ConnectionEditorStatements::toDisplayName(const Handler &handler)
return toDisplayName(statement);
}
MatchedStatement &ConnectionEditorStatements::okStatement(
ConnectionEditorStatements::Handler &handler)
MatchedStatement &ScriptEditorStatements::okStatement(ScriptEditorStatements::Handler &handler)
{
MatchedStatement statement;
return std::visit(Overload{[](ConnectionEditorStatements::MatchedStatement &var)
-> MatchedStatement & { return var; },
[](ConnectionEditorStatements::ConditionalStatement &statement)
return std::visit(Overload{[](ScriptEditorStatements::MatchedStatement &var) -> MatchedStatement & {
return var;
},
[](ScriptEditorStatements::ConditionalStatement &statement)
-> MatchedStatement & { return statement.ok; }},
handler);
}
MatchedStatement &ConnectionEditorStatements::koStatement(
ConnectionEditorStatements::Handler &handler)
MatchedStatement &ScriptEditorStatements::koStatement(ScriptEditorStatements::Handler &handler)
{
static MatchedStatement block;
if (auto *statement = std::get_if<ConnectionEditorStatements::ConditionalStatement>(&handler))
if (auto *statement = std::get_if<ScriptEditorStatements::ConditionalStatement>(&handler))
return statement->ko;
return block;
}
MatchedCondition &ConnectionEditorStatements::matchedCondition(Handler &handler)
MatchedCondition &ScriptEditorStatements::matchedCondition(Handler &handler)
{
static MatchedCondition block;
if (auto *statement = std::get_if<ConnectionEditorStatements::ConditionalStatement>(&handler))
if (auto *statement = std::get_if<ScriptEditorStatements::ConditionalStatement>(&handler))
return statement->condition;
return block;
}
ConditionalStatement &ConnectionEditorStatements::conditionalStatement(
ConnectionEditorStatements::Handler &handler)
ConditionalStatement &ScriptEditorStatements::conditionalStatement(ScriptEditorStatements::Handler &handler)
{
static ConditionalStatement block;
if (auto *statement = std::get_if<ConnectionEditorStatements::ConditionalStatement>(&handler))
if (auto *statement = std::get_if<ScriptEditorStatements::ConditionalStatement>(&handler))
return *statement;
return block;
}
QString ConnectionEditorStatements::toJavascript(const ConditionToken &token)
QString ScriptEditorStatements::toJavascript(const ConditionToken &token)
{
switch (token) {
case ConditionToken::Not:

View File

@@ -7,22 +7,22 @@
#include <qmljs/parser/qmljsast_p.h>
namespace QmlDesigner {
namespace ConnectionEditorStatements {
namespace ScriptEditorStatements {
inline constexpr char FUNCTION_DISPLAY_NAME[] = QT_TRANSLATE_NOOP(
"QmlDesigner::ConnectionEditorStatements", "Function");
"QmlDesigner::ScriptEditorStatements", "Function");
inline constexpr char ASSIGNMENT_DISPLAY_NAME[] = QT_TRANSLATE_NOOP(
"QmlDesigner::ConnectionEditorStatements", "Assignment");
"QmlDesigner::ScriptEditorStatements", "Assignment");
inline constexpr char SETPROPERTY_DISPLAY_NAME[] = QT_TRANSLATE_NOOP(
"QmlDesigner::ConnectionEditorStatements", "Set Property");
"QmlDesigner::ScriptEditorStatements", "Set Property");
inline constexpr char SETSTATE_DISPLAY_NAME[] = QT_TRANSLATE_NOOP(
"QmlDesigner::ConnectionEditorStatements", "Set State");
inline constexpr char LOG_DISPLAY_NAME[] = QT_TRANSLATE_NOOP(
"QmlDesigner::ConnectionEditorStatements", "Print");
"QmlDesigner::ScriptEditorStatements", "Set State");
inline constexpr char LOG_DISPLAY_NAME[] = QT_TRANSLATE_NOOP("QmlDesigner::ScriptEditorStatements",
"Print");
inline constexpr char EMPTY_DISPLAY_NAME[] = QT_TRANSLATE_NOOP(
"QmlDesigner::ConnectionEditorStatements", "Empty");
"QmlDesigner::ScriptEditorStatements", "Empty");
inline constexpr char CUSTOM_DISPLAY_NAME[] = QT_TRANSLATE_NOOP(
"QmlDesigner::ConnectionEditorStatements", "Custom");
"QmlDesigner::ScriptEditorStatements", "Custom");
struct Variable;
struct MatchedFunction;
@@ -122,13 +122,12 @@ QMLDESIGNER_EXPORT QString toDisplayName(const MatchedStatement &statement);
QMLDESIGNER_EXPORT QString toDisplayName(const Handler &handler);
QMLDESIGNER_EXPORT QString toJavascript(const ConditionToken &token);
QMLDESIGNER_EXPORT MatchedStatement &okStatement(ConnectionEditorStatements::Handler &handler);
QMLDESIGNER_EXPORT MatchedStatement &koStatement(ConnectionEditorStatements::Handler &handler);
QMLDESIGNER_EXPORT MatchedStatement &okStatement(ScriptEditorStatements::Handler &handler);
QMLDESIGNER_EXPORT MatchedStatement &koStatement(ScriptEditorStatements::Handler &handler);
QMLDESIGNER_EXPORT MatchedCondition &matchedCondition(ConnectionEditorStatements::Handler &handler);
QMLDESIGNER_EXPORT ConditionalStatement &conditionalStatement(
ConnectionEditorStatements::Handler &handler);
QMLDESIGNER_EXPORT MatchedCondition &matchedCondition(ScriptEditorStatements::Handler &handler);
QMLDESIGNER_EXPORT ConditionalStatement &conditionalStatement(ScriptEditorStatements::Handler &handler);
} // namespace ConnectionEditorStatements
} // namespace ScriptEditorStatements
} // namespace QmlDesigner

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "connectioneditorutils.h"
#include "scripteditorutils.h"
#include <abstractproperty.h>
#include <abstractview.h>
@@ -8,11 +8,11 @@
#include <modelnode.h>
#include <nodeabstractproperty.h>
#include <nodemetainfo.h>
#include <qmldesignertr.h>
#include <rewriterview.h>
#include <rewritingexception.h>
#include <type_traits>
#include <variantproperty.h>
#include <qmldesignertr.h>
#include <utils/algorithm.h>
#include <utils/qtcassert.h>
@@ -24,7 +24,7 @@
namespace QmlDesigner {
Q_LOGGING_CATEGORY(ConnectionEditorLog, "qtc.qtquickdesigner.connectioneditor", QtWarningMsg)
Q_LOGGING_CATEGORY(ScriptEditorLog, "qtc.qtquickdesigner.scripteditor", QtWarningMsg)
void callLater(const std::function<void()> &fun)
{
@@ -62,7 +62,7 @@ PropertyName uniquePropertyName(const PropertyName &suggestion, const ModelNode
NodeMetaInfo dynamicTypeNameToNodeMetaInfo(const TypeName &typeName, Model *model)
{
// Note: Uses old mechanism to create the NodeMetaInfo and supports
// only types we care about in the connection editor.
// only types we care about in the script editor.
// TODO: Support all possible AbstractProperty types and move to the
// AbstractProperty class.
if (typeName == "bool")
@@ -80,7 +80,7 @@ NodeMetaInfo dynamicTypeNameToNodeMetaInfo(const TypeName &typeName, Model *mode
else if (typeName == "var" || typeName == "variant")
return model->metaInfo("QML.variant");
else
qCWarning(ConnectionEditorLog) << __FUNCTION__ << "type" << typeName << "not found";
qCWarning(ScriptEditorLog) << __FUNCTION__ << "type" << typeName << "not found";
return {};
}
@@ -355,7 +355,7 @@ QStringList availableTargetProperties(const BindingProperty &bindingProperty)
{
const ModelNode modelNode = bindingProperty.parentModelNode();
if (!modelNode.isValid()) {
qCWarning(ConnectionEditorLog) << __FUNCTION__ << "invalid model node";
qCWarning(ScriptEditorLog) << __FUNCTION__ << "invalid model node";
return {};
}
@@ -428,7 +428,7 @@ QStringList availableSourceProperties(const QString &id,
} else if (auto metaInfo = targetProperty.parentModelNode().metaInfo(); metaInfo.isValid()) {
targetType = metaInfo.property(targetProperty.name()).propertyType();
} else
qCWarning(ConnectionEditorLog) << __FUNCTION__ << "no meta info for target node";
qCWarning(ScriptEditorLog) << __FUNCTION__ << "no meta info for target node";
QStringList possibleProperties;
if (!modelNode.isValid()) {
@@ -450,7 +450,7 @@ QStringList availableSourceProperties(const QString &id,
return possibleProperties;
}
#endif
qCWarning(ConnectionEditorLog) << __FUNCTION__ << "invalid model node:" << id;
qCWarning(ScriptEditorLog) << __FUNCTION__ << "invalid model node:" << id;
return {};
}
@@ -476,10 +476,40 @@ QStringList availableSourceProperties(const QString &id,
possibleProperties.push_back(QString::fromUtf8(property.name()));
}
} else {
qCWarning(ConnectionEditorLog) << __FUNCTION__ << "no meta info for source node";
qCWarning(ScriptEditorLog) << __FUNCTION__ << "no meta info for source node";
}
return possibleProperties;
}
QString addOnToSignalName(const QString &signal)
{
if (signal.isEmpty())
return {};
static const QRegularExpression rx("^on[A-Z]");
if (rx.match(signal).hasMatch())
return signal;
QString ret = signal;
ret[0] = ret.at(0).toUpper();
ret.prepend("on");
return ret;
}
QString removeOnFromSignalName(const QString &signal)
{
if (signal.isEmpty())
return {};
static const QRegularExpression rx("^on[A-Z]");
if (!rx.match(signal).hasMatch())
return signal;
QString ret = signal;
ret.remove(0, 2);
ret[0] = ret.at(0).toLower();
return ret;
}
} // namespace QmlDesigner

View File

@@ -13,7 +13,7 @@
namespace QmlDesigner {
Q_DECLARE_LOGGING_CATEGORY(ConnectionEditorLog)
Q_DECLARE_LOGGING_CATEGORY(ScriptEditorLog)
class AbstractView;
class AbstractProperty;
@@ -26,6 +26,8 @@ void showErrorMessage(const QString &text);
QString idOrTypeName(const ModelNode &modelNode);
PropertyName uniquePropertyName(const PropertyName &suggestion, const ModelNode &modelNode);
QString addOnToSignalName(const QString &signal);
QString removeOnFromSignalName(const QString &signal);
NodeMetaInfo dynamicTypeMetaInfo(const AbstractProperty &property);
NodeMetaInfo dynamicTypeNameToNodeMetaInfo(const TypeName &typeName, Model *model);