diff --git a/share/qtcreator/qmldesigner/connectionseditor/ConnectionsDialogForm.qml b/share/qtcreator/qmldesigner/connectionseditor/ConnectionsDialogForm.qml
index 5ca4ed28d25..5e40aaa446c 100644
--- a/share/qtcreator/qmldesigner/connectionseditor/ConnectionsDialogForm.qml
+++ b/share/qtcreator/qmldesigner/connectionseditor/ConnectionsDialogForm.qml
@@ -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
}
diff --git a/share/qtcreator/qmldesigner/connectionseditor/StatementEditor.qml b/share/qtcreator/qmldesigner/connectionseditor/StatementEditor.qml
index f198d84a103..0783f3cb7a0 100644
--- a/share/qtcreator/qmldesigner/connectionseditor/StatementEditor.qml
+++ b/share/qtcreator/qmldesigner/connectionseditor/StatementEditor.qml
@@ -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 Target component's Signal.")
}
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 Signal of the Target 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
diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt
index 0ba34894e2a..1c58e2ba88f 100644
--- a/src/plugins/qmldesigner/CMakeLists.txt
+++ b/src/plugins/qmldesigner/CMakeLists.txt
@@ -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
diff --git a/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.cpp b/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.cpp
index 4ef8a4ed378..4b4e59cfe00 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/bindingmodel.cpp
@@ -3,10 +3,11 @@
#include "bindingmodel.h"
#include "bindingmodelitem.h"
-#include "connectioneditorutils.h"
+#include "connectioneditorlogging.h"
#include "connectionview.h"
#include "modelfwd.h"
+#include
#include
#include
#include
diff --git a/src/plugins/qmldesigner/components/connectioneditor/bindingmodelitem.cpp b/src/plugins/qmldesigner/components/connectioneditor/bindingmodelitem.cpp
index e5e1372dd65..a0976564e90 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/bindingmodelitem.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/bindingmodelitem.cpp
@@ -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
#include
#include
diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectioneditorlogging.cpp b/src/plugins/qmldesigner/components/connectioneditor/connectioneditorlogging.cpp
new file mode 100644
index 00000000000..0ed91b33ab3
--- /dev/null
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectioneditorlogging.cpp
@@ -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
diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectioneditorlogging.h b/src/plugins/qmldesigner/components/connectioneditor/connectioneditorlogging.h
new file mode 100644
index 00000000000..673a5b1a32f
--- /dev/null
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectioneditorlogging.h
@@ -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
+
+namespace QmlDesigner {
+
+Q_DECLARE_LOGGING_CATEGORY(ConnectionEditorLog)
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp b/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp
index f4462f911f5..c0a13a788e8 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.cpp
@@ -2,41 +2,22 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "connectionmodel.h"
-#include "connectioneditorutils.h"
+#include "connectioneditorlogging.h"
#include "connectionview.h"
-#include "utils/algorithm.h"
-#include
-#include
-#include
-#include
-#include
#include
-#include
#include
-#include
#include
#include
#include
#include
-#include
+#include
+#include
#include
-#include
-
-#include
#include
-#include
-#include
-#include
-#include
-#include
-#include
namespace {
-
-const char defaultCondition[] = "condition";
-
QStringList propertyNameListToStringList(const QmlDesigner::PropertyNameList &propertyNameList)
{
QStringList stringList;
@@ -308,8 +289,7 @@ void ConnectionModel::updateCustomData(QStandardItem *item, const SignalHandlerP
//anything else is assignment
// e.g. foo.bal = foo2.bula ; foo.bal = "literal" ; goo.gal = true
- item->setData(tr(ConnectionEditorEvaluator::getDisplayStringForType(
- signalHandlerProperty.source())
+ item->setData(tr(ScriptEditorEvaluator::getDisplayStringForType(signalHandlerProperty.source())
.toLatin1()),
UserRoles::ActionTypeRole);
}
@@ -344,21 +324,6 @@ ModelNode ConnectionModel::getTargetNodeForConnection(const ModelNode &connectio
return result;
}
-static 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;
-}
-
static PropertyName getFirstSignalForTarget(const NodeMetaInfo &target)
{
PropertyName ret = "clicked";
@@ -738,208 +703,22 @@ QHash ConnectionModel::roleNames() const
return roleNames;
}
-ConnectionModelBackendDelegate::ConnectionModelBackendDelegate(ConnectionModel *model)
- : m_signalDelegate(model->connectionView())
- , m_okStatementDelegate(model)
- , m_koStatementDelegate(model)
- , m_conditionListModel(model)
- , m_propertyTreeModel(model->connectionView())
- , m_propertyListProxyModel(&m_propertyTreeModel)
- , m_model(model)
-{
- connect(&m_signalDelegate, &PropertyTreeModelDelegate::commitData, this, [this] {
- handleTargetChanged();
- });
-
- connect(&m_okStatementDelegate,
- &ConnectionModelStatementDelegate::statementChanged,
- this,
- [this] { handleOkStatementChanged(); });
-
- connect(&m_koStatementDelegate,
- &ConnectionModelStatementDelegate::statementChanged,
- this,
- [this] { handleKOStatementChanged(); });
-
- connect(&m_conditionListModel, &ConditionListModel::conditionChanged, this, [this] {
- handleConditionChanged();
- });
-
- m_signalDelegate.setPropertyType(PropertyTreeModel::SignalType);
-}
-
-QString generateDefaultStatement(ConnectionModelBackendDelegate::ActionType actionType,
- const QString &rootId)
-{
- switch (actionType) {
- case ConnectionModelStatementDelegate::CallFunction:
- return "Qt.quit()";
- case ConnectionModelStatementDelegate::Assign:
- return QString("%1.visible = %1.visible").arg(rootId);
- case ConnectionModelStatementDelegate::ChangeState:
- return QString("%1.state = \"\"").arg(rootId);
- case ConnectionModelStatementDelegate::SetProperty:
- return QString("%1.visible = true").arg(rootId);
- case ConnectionModelStatementDelegate::PrintMessage:
- return QString("console.log(\"test\")").arg(rootId);
- case ConnectionModelStatementDelegate::Custom:
- return {};
- };
-
- //Qt.quit()
- //console.log("test")
- //root.state = ""
- //root.visible = root.visible
- //root.visible = true
-
- return {};
-}
-
-void ConnectionModelBackendDelegate::changeActionType(ActionType actionType)
-{
- QTC_ASSERT(actionType != ConnectionModelStatementDelegate::Custom, return );
-
- ConnectionModel *model = m_model;
-
- QTC_ASSERT(model, return );
- QTC_ASSERT(model->connectionView()->isAttached(), return );
-
- const QString validId = model->connectionView()->rootModelNode().validId();
-
- SignalHandlerProperty signalHandlerProperty = model->signalHandlerPropertyForRow(currentRow());
-
- // Do not take ko into account for now
-
- model->connectionView()
- ->executeInTransaction("ConnectionModelBackendDelegate::removeCondition", [&]() {
- ConnectionEditorStatements::MatchedStatement &okStatement
- = ConnectionEditorStatements::okStatement(m_handler);
-
- ConnectionEditorStatements::MatchedStatement &koStatement
- = ConnectionEditorStatements::koStatement(m_handler);
-
- koStatement = ConnectionEditorStatements::EmptyBlock();
-
- //We expect a valid id on the root node
- const QString validId = model->connectionView()->rootModelNode().validId();
- QString statementSource = generateDefaultStatement(actionType, validId);
-
- auto tempHandler = ConnectionEditorEvaluator::parseStatement(statementSource);
-
- auto newOkStatement = ConnectionEditorStatements::okStatement(tempHandler);
-
- QTC_ASSERT(!ConnectionEditorStatements::isEmptyStatement(newOkStatement), return );
-
- okStatement = newOkStatement;
-
- QString newSource = ConnectionEditorStatements::toJavascript(m_handler);
-
- signalHandlerProperty.setSource(newSource);
- });
-
- setSource(signalHandlerProperty.source());
-
- setupHandlerAndStatements();
- setupCondition();
-}
-
-void ConnectionModelBackendDelegate::addCondition()
-{
- ConnectionEditorStatements::MatchedStatement okStatement
- = ConnectionEditorStatements::okStatement(m_handler);
-
- ConnectionEditorStatements::MatchedCondition newCondition;
-
- ConnectionEditorStatements::Variable variable;
- variable.nodeId = defaultCondition;
- newCondition.statements.append(variable);
-
- ConnectionEditorStatements::ConditionalStatement conditionalStatement;
-
- conditionalStatement.ok = okStatement;
- conditionalStatement.condition = newCondition;
-
- m_handler = conditionalStatement;
-
- QString newSource = ConnectionEditorStatements::toJavascript(m_handler);
-
- commitNewSource(newSource);
-
- setupHandlerAndStatements();
- setupCondition();
-}
-
-void ConnectionModelBackendDelegate::removeCondition()
-{
- ConnectionEditorStatements::MatchedStatement okStatement
- = ConnectionEditorStatements::okStatement(m_handler);
-
- m_handler = okStatement;
-
- QString newSource = ConnectionEditorStatements::toJavascript(m_handler);
-
- commitNewSource(newSource);
-
- setupHandlerAndStatements();
- setupCondition();
-}
-
-void ConnectionModelBackendDelegate::addElse()
-{
- ConnectionEditorStatements::MatchedStatement okStatement
- = ConnectionEditorStatements::okStatement(m_handler);
-
- auto &condition = ConnectionEditorStatements::conditionalStatement(m_handler);
- condition.ko = condition.ok;
-
- QString newSource = ConnectionEditorStatements::toJavascript(m_handler);
-
-
- commitNewSource(newSource);
- setupHandlerAndStatements();
-}
-
-void ConnectionModelBackendDelegate::removeElse()
-{
- ConnectionEditorStatements::MatchedStatement okStatement
- = ConnectionEditorStatements::okStatement(m_handler);
-
- auto &condition = ConnectionEditorStatements::conditionalStatement(m_handler);
- condition.ko = ConnectionEditorStatements::EmptyBlock();
-
- QString newSource = ConnectionEditorStatements::toJavascript(m_handler);
-
-
- commitNewSource(newSource);
- setupHandlerAndStatements();
-}
-
-void ConnectionModelBackendDelegate::setNewSource(const QString &newSource)
-{
- setSource(newSource);
- commitNewSource(newSource);
- setupHandlerAndStatements();
- setupCondition();
-}
-
int ConnectionModelBackendDelegate::currentRow() const
{
return m_currentRow;
}
-static QString removeOnFromSignalName(const QString &signal)
+ConnectionModelBackendDelegate::ConnectionModelBackendDelegate(ConnectionModel *model)
+ : ScriptEditorBackend(model->connectionView())
+ , m_signalDelegate(model->connectionView())
+ , m_model(model)
{
- if (signal.isEmpty())
- return {};
+ connect(&m_signalDelegate,
+ &PropertyTreeModelDelegate::commitData,
+ this,
+ &ConnectionModelBackendDelegate::handleTargetChanged);
- 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;
+ m_signalDelegate.setPropertyType(PropertyTreeModel::SignalType);
}
void ConnectionModelBackendDelegate::setCurrentRow(int i)
@@ -954,22 +733,22 @@ void ConnectionModelBackendDelegate::setCurrentRow(int i)
void ConnectionModelBackendDelegate::update()
{
- if (m_blockReflection)
- return;
-
if (m_currentRow == -1)
return;
- m_propertyTreeModel.resetModel();
- m_propertyListProxyModel.setRowAndInternalId(0, internalRootIndex);
+ if (blockReflection()) {
+ return;
+ }
+
+ ScriptEditorBackend::update();
ConnectionModel *model = m_model;
- QTC_ASSERT(model, return );
+ QTC_ASSERT(model, return);
if (!model->connectionView()->isAttached())
return;
- SignalHandlerProperty signalHandlerProperty = model->signalHandlerPropertyForRow(currentRow());
+ auto signalHandlerProperty = model->signalHandlerPropertyForRow(currentRow());
QStringList targetNodes;
@@ -988,65 +767,8 @@ void ConnectionModelBackendDelegate::update()
if (!targetNodes.contains(targetNodeName))
targetNodes.append(targetNodeName);
- setSource(signalHandlerProperty.source());
-
m_signalDelegate.setup(targetNodeName,
removeOnFromSignalName(QString::fromUtf8(signalHandlerProperty.name())));
-
- setupHandlerAndStatements();
-
- setupCondition();
-
- QTC_ASSERT(model, return );
-}
-
-void ConnectionModelBackendDelegate::jumpToCode()
-{
- ConnectionModel *model = m_model;
-
- QTC_ASSERT(model, return );
- QTC_ASSERT(model->connectionView()->isAttached(), return );
- SignalHandlerProperty signalHandlerProperty = model->signalHandlerPropertyForRow(currentRow());
-
- ModelNodeOperations::jumpToCode(signalHandlerProperty.parentModelNode());
-}
-
-void ConnectionModelBackendDelegate::handleException()
-{
- QMessageBox::warning(nullptr, tr("Error"), m_exceptionError);
-}
-
-bool ConnectionModelBackendDelegate::hasCondition() const
-{
- return m_hasCondition;
-}
-
-bool ConnectionModelBackendDelegate::hasElse() const
-{
- return m_hasElse;
-}
-
-void ConnectionModelBackendDelegate::setHasCondition(bool b)
-{
- if (b == m_hasCondition)
- return;
-
- m_hasCondition = b;
- emit hasConditionChanged();
-}
-
-void ConnectionModelBackendDelegate::setHasElse(bool b)
-{
- if (b == m_hasElse)
- return;
-
- m_hasElse = b;
- emit hasElseChanged();
-}
-
-ConnectionModelBackendDelegate::ActionType ConnectionModelBackendDelegate::actionType() const
-{
- return m_actionType;
}
PropertyTreeModelDelegate *ConnectionModelBackendDelegate::signal()
@@ -1054,135 +776,21 @@ PropertyTreeModelDelegate *ConnectionModelBackendDelegate::signal()
return &m_signalDelegate;
}
-ConnectionModelStatementDelegate *ConnectionModelBackendDelegate::okStatement()
-{
- return &m_okStatementDelegate;
-}
-
-ConnectionModelStatementDelegate *ConnectionModelBackendDelegate::koStatement()
-{
- return &m_koStatementDelegate;
-}
-
-ConditionListModel *ConnectionModelBackendDelegate::conditionListModel()
-{
- return &m_conditionListModel;
-}
-
-QString ConnectionModelBackendDelegate::indentedSource() const
-{
- if (m_source.isEmpty())
- return {};
-
- QTextDocument doc(m_source);
- IndentingTextEditModifier mod(&doc);
-
- mod.indent(0, m_source.length() - 1);
- return mod.text();
-}
-
-QString ConnectionModelBackendDelegate::source() const
-{
- return m_source;
-}
-
-void ConnectionModelBackendDelegate::setSource(const QString &source)
-{
- if (source == m_source)
- return;
-
- m_source = source;
- emit sourceChanged();
-}
-
-PropertyTreeModel *ConnectionModelBackendDelegate::propertyTreeModel()
-{
- return &m_propertyTreeModel;
-}
-
-PropertyListProxyModel *ConnectionModelBackendDelegate::propertyListProxyModel()
-{
- return &m_propertyListProxyModel;
-}
-
-void ConnectionModelBackendDelegate::setupCondition()
-{
- auto &condition = ConnectionEditorStatements::matchedCondition(m_handler);
- m_conditionListModel.setCondition(ConnectionEditorStatements::matchedCondition(m_handler));
- setHasCondition(!condition.statements.isEmpty());
-}
-
-void ConnectionModelBackendDelegate::setupHandlerAndStatements()
-{
- ConnectionModel *model = m_model;
- QTC_ASSERT(model, return );
- SignalHandlerProperty signalHandlerProperty = model->signalHandlerPropertyForRow(currentRow());
-
- if (signalHandlerProperty.source().isEmpty()) {
- m_actionType = ConnectionModelStatementDelegate::Custom;
- m_handler = ConnectionEditorStatements::EmptyBlock();
- } else {
- m_handler = ConnectionEditorEvaluator::parseStatement(signalHandlerProperty.source());
-
- const QString statementType = QmlDesigner::ConnectionEditorStatements::toDisplayName(
- m_handler);
-
- if (statementType == ConnectionEditorStatements::EMPTY_DISPLAY_NAME) {
- m_actionType = ConnectionModelStatementDelegate::Custom;
- } else if (statementType == ConnectionEditorStatements::ASSIGNMENT_DISPLAY_NAME) {
- m_actionType = ConnectionModelStatementDelegate::Assign;
- //setupAssignment();
- } else if (statementType == ConnectionEditorStatements::SETPROPERTY_DISPLAY_NAME) {
- m_actionType = ConnectionModelStatementDelegate::SetProperty;
- //setupSetProperty();
- } else if (statementType == ConnectionEditorStatements::FUNCTION_DISPLAY_NAME) {
- m_actionType = ConnectionModelStatementDelegate::CallFunction;
- //setupCallFunction();
- } else if (statementType == ConnectionEditorStatements::SETSTATE_DISPLAY_NAME) {
- m_actionType = ConnectionModelStatementDelegate::ChangeState;
- //setupChangeState();
- } else if (statementType == ConnectionEditorStatements::LOG_DISPLAY_NAME) {
- m_actionType = ConnectionModelStatementDelegate::PrintMessage;
- //setupPrintMessage();
- } else {
- m_actionType = ConnectionModelStatementDelegate::Custom;
- }
- }
-
- ConnectionEditorStatements::MatchedStatement &okStatement
- = ConnectionEditorStatements::okStatement(m_handler);
- m_okStatementDelegate.setStatement(okStatement);
- m_okStatementDelegate.setActionType(m_actionType);
-
- ConnectionEditorStatements::MatchedStatement &koStatement
- = ConnectionEditorStatements::koStatement(m_handler);
-
- if (!ConnectionEditorStatements::isEmptyStatement(koStatement)) {
- m_koStatementDelegate.setStatement(koStatement);
- m_koStatementDelegate.setActionType(m_actionType);
- }
-
- ConnectionEditorStatements::isEmptyStatement(koStatement);
- setHasElse(!ConnectionEditorStatements::isEmptyStatement(koStatement));
-
- emit actionTypeChanged();
-}
-
void ConnectionModelBackendDelegate::handleTargetChanged()
{
ConnectionModel *model = m_model;
- QTC_ASSERT(model, return );
+ QTC_ASSERT(model, return);
- QTC_ASSERT(model->connectionView()->isAttached(), return );
+ QTC_ASSERT(model->connectionView()->isAttached(), return);
- SignalHandlerProperty signalHandlerProperty = model->signalHandlerPropertyForRow(currentRow());
+ SignalHandlerProperty signalHandlerProperty = getSignalHandlerProperty();
const PropertyName handlerName = addOnToSignalName(m_signalDelegate.name()).toUtf8();
const auto parentModelNode = signalHandlerProperty.parentModelNode();
- QTC_ASSERT(parentModelNode.isValid(), return );
+ QTC_ASSERT(parentModelNode.isValid(), return);
const auto newId = m_signalDelegate.id();
@@ -1190,8 +798,9 @@ void ConnectionModelBackendDelegate::handleTargetChanged()
model->connectionView()
->executeInTransaction("ConnectionModelBackendDelegate::handleTargetChanged", [&]() {
- const auto oldTargetNodeName
- = parentModelNode.bindingProperty("target").resolveToModelNode().id();
+ const auto oldTargetNodeName = parentModelNode.bindingProperty("target")
+ .resolveToModelNode()
+ .id();
if (signalHandlerProperty.name() != handlerName) {
const auto expression = signalHandlerProperty.source();
@@ -1212,996 +821,38 @@ void ConnectionModelBackendDelegate::handleTargetChanged()
}
});
- model->selectProperty(model->connectionView()
- ->modelNodeForInternalId(internalId)
- .signalHandlerProperty(handlerName));
+ model->selectProperty(
+ model->connectionView()->modelNodeForInternalId(internalId).signalHandlerProperty(handlerName));
}
-void ConnectionModelBackendDelegate::handleOkStatementChanged()
+AbstractProperty ConnectionModelBackendDelegate::getSourceProperty() const
{
- ConnectionEditorStatements::MatchedStatement &okStatement
- = ConnectionEditorStatements::okStatement(m_handler);
-
- okStatement = m_okStatementDelegate.statement(); //TODO why?
-
- QString newSource = ConnectionEditorStatements::toJavascript(m_handler);
-
- commitNewSource(newSource);
+ return getSignalHandlerProperty();
}
-void ConnectionModelBackendDelegate::handleKOStatementChanged()
+void ConnectionModelBackendDelegate::setPropertySource(const QString &source)
{
- ConnectionEditorStatements::MatchedStatement &koStatement
- = ConnectionEditorStatements::koStatement(m_handler);
+ auto property = getSourceProperty();
- koStatement = m_koStatementDelegate.statement(); //TODO why?
+ QTC_ASSERT(property.isValid(), return);
- QString newSource = ConnectionEditorStatements::toJavascript(m_handler);
-
- commitNewSource(newSource);
-}
-
-void ConnectionModelBackendDelegate::handleConditionChanged()
-{
- ConnectionModel *model = m_model;
-
- QTC_ASSERT(model, return );
- QTC_ASSERT(model->connectionView()->isAttached(), return );
-
- ConnectionEditorStatements::MatchedCondition &condition
- = ConnectionEditorStatements::matchedCondition(m_handler);
- condition = m_conditionListModel.condition(); //why?
- QString newSource = ConnectionEditorStatements::toJavascript(m_handler);
-
- commitNewSource(newSource);
-}
-
-void ConnectionModelBackendDelegate::commitNewSource(const QString &source)
-{
- ConnectionModel *model = m_model;
-
- QTC_ASSERT(model, return );
-
- QTC_ASSERT(model->connectionView()->isAttached(), return );
-
- SignalHandlerProperty signalHandlerProperty = model->signalHandlerPropertyForRow(currentRow());
-
- m_blockReflection = true;
- model->connectionView()->executeInTransaction("ConnectionModelBackendDelegate::commitNewSource",
- [&]() {
- signalHandlerProperty.setSource(source);
- });
-
- setSource(signalHandlerProperty.source());
- m_blockReflection = false;
-}
-
-static ConnectionEditorStatements::MatchedStatement emptyStatement;
-
-ConnectionModelStatementDelegate::ConnectionModelStatementDelegate(ConnectionModel *model)
- : m_functionDelegate(model->connectionView())
- , m_lhsDelegate(model->connectionView())
- , m_rhsAssignmentDelegate(model->connectionView())
- , m_statement(emptyStatement)
- , m_model(model)
-{
- m_functionDelegate.setPropertyType(PropertyTreeModel::SlotType);
-
- connect(&m_functionDelegate, &PropertyTreeModelDelegate::commitData, this, [this] {
- handleFunctionChanged();
- });
-
- connect(&m_rhsAssignmentDelegate, &PropertyTreeModelDelegate::commitData, this, [this] {
- handleRhsAssignmentChanged();
- });
-
- connect(&m_lhsDelegate, &PropertyTreeModelDelegate::commitData, this, [this] {
- handleLhsChanged();
- });
-
- connect(&m_stringArgument, &StudioQmlTextBackend::activated, this, [this] {
- handleStringArgumentChanged();
- });
-
- connect(&m_states, &StudioQmlComboBoxBackend::activated, this, [this] {
- handleStateChanged();
- });
-
- connect(&m_stateTargets, &StudioQmlComboBoxBackend::activated, this, [this] {
- handleStateTargetsChanged();
- });
-}
-
-void ConnectionModelStatementDelegate::setActionType(ActionType type)
-{
- if (m_actionType == type)
+ if (source.isEmpty())
return;
- m_actionType = type;
- emit actionTypeChanged();
- setup();
-}
-
-void ConnectionModelStatementDelegate::setup()
-{
- switch (m_actionType) {
- case CallFunction:
- setupCallFunction();
- break;
- case Assign:
- setupAssignment();
- break;
- case ChangeState:
- setupChangeState();
- break;
- case SetProperty:
- setupSetProperty();
- break;
- case PrintMessage:
- setupPrintMessage();
- break;
- case Custom:
- break;
- };
-}
-
-void ConnectionModelStatementDelegate::setStatement(
- ConnectionEditorStatements::MatchedStatement &statement)
-{
- m_statement = statement;
- setup();
-}
-
-ConnectionEditorStatements::MatchedStatement &ConnectionModelStatementDelegate::statement()
-{
- return m_statement;
-}
-
-ConnectionModelStatementDelegate::ActionType ConnectionModelStatementDelegate::actionType() const
-{
- return m_actionType;
-}
-
-PropertyTreeModelDelegate *ConnectionModelStatementDelegate::function()
-{
- return &m_functionDelegate;
-}
-
-PropertyTreeModelDelegate *ConnectionModelStatementDelegate::lhs()
-{
- return &m_lhsDelegate;
-}
-
-PropertyTreeModelDelegate *ConnectionModelStatementDelegate::rhsAssignment()
-{
- return &m_rhsAssignmentDelegate;
-}
-
-StudioQmlTextBackend *ConnectionModelStatementDelegate::stringArgument()
-{
- return &m_stringArgument;
-}
-
-StudioQmlComboBoxBackend *ConnectionModelStatementDelegate::stateTargets()
-{
- return &m_stateTargets;
-}
-
-StudioQmlComboBoxBackend *ConnectionModelStatementDelegate::states()
-{
- return &m_states;
-}
-
-void ConnectionModelStatementDelegate::handleFunctionChanged()
-{
- QTC_ASSERT(std::holds_alternative(m_statement),
- return );
-
- ConnectionEditorStatements::MatchedFunction &functionStatement
- = std::get(m_statement);
-
- functionStatement.functionName = m_functionDelegate.name();
- functionStatement.nodeId = m_functionDelegate.id();
-
- emit statementChanged();
-}
-
-void ConnectionModelStatementDelegate::handleLhsChanged()
-{
- if (m_actionType == Assign) {
- QTC_ASSERT(std::holds_alternative(m_statement),
- return );
-
- ConnectionEditorStatements::Assignment &assignmentStatement
- = std::get(m_statement);
-
- assignmentStatement.lhs.nodeId = m_lhsDelegate.id();
- assignmentStatement.lhs.propertyName = m_lhsDelegate.name();
-
- } else if (m_actionType == SetProperty) {
- QTC_ASSERT(std::holds_alternative(m_statement),
- return );
-
- ConnectionEditorStatements::PropertySet &setPropertyStatement
- = std::get(m_statement);
-
- setPropertyStatement.lhs.nodeId = m_lhsDelegate.id();
- setPropertyStatement.lhs.propertyName = m_lhsDelegate.name();
- } else {
- QTC_ASSERT(false, return );
- }
-
- emit statementChanged();
-}
-
-void ConnectionModelStatementDelegate::handleRhsAssignmentChanged()
-{
- QTC_ASSERT(std::holds_alternative(m_statement), return );
-
- ConnectionEditorStatements::Assignment &assignmentStatement
- = std::get(m_statement);
-
- assignmentStatement.rhs.nodeId = m_rhsAssignmentDelegate.id();
- assignmentStatement.rhs.propertyName = m_rhsAssignmentDelegate.name();
-
- setupPropertyType();
-
- emit statementChanged();
-}
-
-static ConnectionEditorStatements::Literal parseTextArgument(const QString &text)
-{
- if (text.startsWith("\"") && text.endsWith("\"")) {
- QString ret = text;
- ret.remove(0, 1);
- ret.chop(1);
- return ret;
- }
-
- if (text == "true")
- return true;
-
- if (text == "false")
- return false;
-
- bool ok = true;
- double d = text.toDouble(&ok);
- if (ok)
- return d;
-
- return text;
-}
-
-static ConnectionEditorStatements::ComparativeStatement parseTextArgumentComparativeStatement(
- const QString &text)
-{
- if (text.startsWith("\"") && text.endsWith("\"")) {
- QString ret = text;
- ret.remove(0, 1);
- ret.chop(1);
- return ret;
- }
-
- if (text == "true")
- return true;
-
- if (text == "false")
- return false;
-
- bool ok = true;
- double d = text.toDouble(&ok);
- if (ok)
- return d;
-
- return text;
-}
-
-static ConnectionEditorStatements::RightHandSide parseLogTextArgument(const QString &text)
-{
- if (text.startsWith("\"") && text.endsWith("\"")) {
- QString ret = text;
- ret.remove(0, 1);
- ret.chop(1);
- return ret;
- }
-
- if (text == "true")
- return true;
-
- if (text == "false")
- return true;
-
- bool ok = true;
- double d = text.toDouble(&ok);
- if (ok)
- return d;
-
- //TODO variables and function calls
- return text;
-}
-
-void ConnectionModelStatementDelegate::handleStringArgumentChanged()
-{
- if (m_actionType == SetProperty) {
- QTC_ASSERT(std::holds_alternative(m_statement),
- return );
-
- ConnectionEditorStatements::PropertySet &propertySet
- = std::get(m_statement);
-
- propertySet.rhs = parseTextArgument(m_stringArgument.text());
-
- } else if (m_actionType == PrintMessage) {
- QTC_ASSERT(std::holds_alternative(m_statement),
- return );
-
- ConnectionEditorStatements::ConsoleLog &consoleLog
- = std::get(m_statement);
-
- consoleLog.argument = parseLogTextArgument(m_stringArgument.text());
- } else {
- QTC_ASSERT(false, return );
- }
-
- emit statementChanged();
-}
-
-void ConnectionModelStatementDelegate::handleStateChanged()
-{
- QTC_ASSERT(std::holds_alternative(m_statement), return );
-
- ConnectionEditorStatements::StateSet &stateSet = std::get(
- m_statement);
-
- QString stateName = m_states.currentText();
- if (stateName == baseStateName())
- stateName = "";
- stateSet.stateName = "\"" + stateName + "\"";
-
- emit statementChanged();
-}
-
-void ConnectionModelStatementDelegate::handleStateTargetsChanged()
-{
- QTC_ASSERT(std::holds_alternative(m_statement), return );
-
- ConnectionEditorStatements::StateSet &stateSet = std::get(
- m_statement);
-
- stateSet.nodeId = m_stateTargets.currentText();
- stateSet.stateName = "\"\"";
-
- setupStates();
-
- emit statementChanged();
-}
-
-void ConnectionModelStatementDelegate::setupAssignment()
-{
- QTC_ASSERT(std::holds_alternative(m_statement), return );
-
- const auto assignment = std::get(m_statement);
- m_lhsDelegate.setup(assignment.lhs.nodeId, assignment.lhs.propertyName);
- m_rhsAssignmentDelegate.setup(assignment.rhs.nodeId, assignment.rhs.propertyName);
- setupPropertyType();
-}
-
-void ConnectionModelStatementDelegate::setupSetProperty()
-{
- QTC_ASSERT(std::holds_alternative(m_statement),
- return );
-
- const auto propertySet = std::get(m_statement);
- m_lhsDelegate.setup(propertySet.lhs.nodeId, propertySet.lhs.propertyName);
- m_stringArgument.setText(ConnectionEditorStatements::toString(propertySet.rhs));
-}
-
-void ConnectionModelStatementDelegate::setupCallFunction()
-{
- QTC_ASSERT(std::holds_alternative(m_statement),
- return );
-
- const auto functionStatement = std::get(
- m_statement);
- m_functionDelegate.setup(functionStatement.nodeId, functionStatement.functionName);
-}
-
-void ConnectionModelStatementDelegate::setupChangeState()
-{
- QTC_ASSERT(std::holds_alternative(m_statement), return );
-
- QTC_ASSERT(m_model->connectionView()->isAttached(), return );
-
- auto model = m_model->connectionView()->model();
- const auto items = Utils::filtered(m_model->connectionView()->allModelNodesOfType(
- model->qtQuickItemMetaInfo()),
- [](const ModelNode &node) {
- QmlItemNode item(node);
- return node.hasId() && item.isValid()
- && !item.allStateNames().isEmpty();
- });
-
- QStringList itemIds = Utils::transform(items, &ModelNode::id);
- const auto groups = m_model->connectionView()->allModelNodesOfType(
- model->qtQuickStateGroupMetaInfo());
-
- const auto rootId = m_model->connectionView()->rootModelNode().id();
- itemIds.removeAll(rootId);
-
- QStringList groupIds = Utils::transform(groups, &ModelNode::id);
-
- Utils::sort(itemIds);
- Utils::sort(groupIds);
-
- if (!rootId.isEmpty())
- groupIds.prepend(rootId);
-
- const QStringList stateGroupModel = groupIds + itemIds;
- m_stateTargets.setModel(stateGroupModel);
-
- const auto stateSet = std::get(m_statement);
-
- m_stateTargets.setCurrentText(stateSet.nodeId);
- setupStates();
-}
-QString stripQuotesFromState(const QString &input)
-{
- if (input.startsWith("\"") && input.endsWith("\"")) {
- QString ret = input;
- ret.remove(0, 1);
- ret.chop(1);
- return ret;
- }
- return input;
-}
-void ConnectionModelStatementDelegate::setupStates()
-{
- QTC_ASSERT(std::holds_alternative(m_statement), return );
- QTC_ASSERT(m_model->connectionView()->isAttached(), return );
-
- const auto stateSet = std::get(m_statement);
-
- const QString nodeId = m_stateTargets.currentText();
-
- const ModelNode node = m_model->connectionView()->modelNodeForId(nodeId);
-
- QStringList states;
- if (node.metaInfo().isQtQuickItem()) {
- QmlItemNode item(node);
- QTC_ASSERT(item.isValid(), return );
- if (item.isRootNode())
- states = item.states().names(); //model
- else
- states = item.allStateNames(); //instances
- } else {
- QmlModelStateGroup group(node);
- states = group.names(); //model
- }
-
- const QString stateName = stripQuotesFromState(stateSet.stateName);
-
- states.prepend(baseStateName());
- m_states.setModel(states);
- if (stateName.isEmpty())
- m_states.setCurrentText(baseStateName());
+ auto normalizedSource = QmlDesigner::SignalHandlerProperty::normalizedSourceWithBraces(source);
+ if (property.exists())
+ property.toSignalHandlerProperty().setSource(normalizedSource);
else
- m_states.setCurrentText(stateName);
+ property.parentModelNode().signalHandlerProperty(property.name()).setSource(normalizedSource);
}
-void ConnectionModelStatementDelegate::setupPrintMessage()
+SignalHandlerProperty ConnectionModelBackendDelegate::getSignalHandlerProperty() const
{
- QTC_ASSERT(std::holds_alternative(m_statement), return );
+ ConnectionModel *model = m_model;
+ QTC_ASSERT(model, return {});
+ QTC_ASSERT(model->connectionView()->isAttached(), return {});
- const auto consoleLog = std::get(m_statement);
- m_stringArgument.setText(ConnectionEditorStatements::toString(consoleLog.argument));
-}
-
-void ConnectionModelStatementDelegate::setupPropertyType()
-{
- PropertyTreeModel::PropertyTypes type = PropertyTreeModel::AllTypes;
-
- const NodeMetaInfo metaInfo = m_rhsAssignmentDelegate.propertyMetaInfo();
-
- if (metaInfo.isBool())
- type = PropertyTreeModel::BoolType;
- else if (metaInfo.isNumber())
- type = PropertyTreeModel::NumberType;
- else if (metaInfo.isColor())
- type = PropertyTreeModel::ColorType;
- else if (metaInfo.isString())
- type = PropertyTreeModel::StringType;
- else if (metaInfo.isUrl())
- type = PropertyTreeModel::UrlType;
-
- m_lhsDelegate.setPropertyType(type);
-}
-
-QString ConnectionModelStatementDelegate::baseStateName() const
-{
- return tr("Base State");
-}
-
-static ConnectionEditorStatements::MatchedCondition emptyCondition;
-
-ConditionListModel::ConditionListModel(ConnectionModel *model)
- : m_connectionModel(model)
- , m_condition(emptyCondition)
-{}
-
-int ConditionListModel::rowCount(const QModelIndex & /*parent*/) const
-{
- return m_tokens.size();
-}
-
-QHash ConditionListModel::roleNames() const
-{
- static QHash roleNames{{Qt::UserRole + 1, "type"}, {Qt::UserRole + 2, "value"}};
- return roleNames;
-}
-
-QVariant ConditionListModel::data(const QModelIndex &index, int role) const
-{
- if (index.isValid() && index.row() < rowCount()) {
- if (role == Qt::UserRole + 1) {
- return m_tokens.at(index.row()).type;
- } else if (role == Qt::UserRole + 2) {
- return m_tokens.at(index.row()).value;
- }
-
- qCWarning(ConnectionEditorLog) << __FUNCTION__ << "invalid role";
- } else {
- qCWarning(ConnectionEditorLog) << __FUNCTION__ << "invalid index";
- }
-
- return QVariant();
-}
-
-void ConditionListModel::setup()
-{
- m_tokens.clear();
-
- internalSetup();
-
- emit validChanged();
- emit emptyChanged();
-
- beginResetModel();
- endResetModel();
-}
-
-void ConditionListModel::setCondition(ConnectionEditorStatements::MatchedCondition &condition)
-{
- m_condition = condition;
- setup();
-}
-
-ConnectionEditorStatements::MatchedCondition &ConditionListModel::condition()
-{
- return m_condition;
-}
-
-ConditionListModel::ConditionToken ConditionListModel::tokenFromConditionToken(
- const ConnectionEditorStatements::ConditionToken &token)
-{
- ConditionToken ret;
- ret.type = Operator;
- ret.value = ConnectionEditorStatements::toJavascript(token);
-
- return ret;
-}
-
-ConditionListModel::ConditionToken ConditionListModel::tokenFromComparativeStatement(
- const ConnectionEditorStatements::ComparativeStatement &token)
-{
- ConditionToken ret;
-
- if (auto *variable = std::get_if(&token)) {
- ret.type = Variable;
- ret.value = variable->expression();
- return ret;
- } else if (auto *literal = std::get_if(&token)) {
- ret.type = Literal;
- ret.value = "\"" + *literal + "\"";
- return ret;
- } else if (auto *literal = std::get_if(&token)) {
- ret.type = Literal;
- if (*literal)
- ret.value = "true";
- else
- ret.value = "false";
- return ret;
- } else if (auto *literal = std::get_if(&token)) {
- ret.type = Literal;
- ret.value = QString::number(*literal);
- return ret;
- }
-
- ret.type = Invalid;
- ret.value = "invalid";
- return {};
-}
-
-void ConditionListModel::insertToken(int index, const QString &value)
-{
- beginInsertRows({}, index, index);
-
- m_tokens.insert(index, valueToToken(value));
- validateAndRebuildTokens();
-
- endInsertRows();
- //resetModel();
-}
-
-void ConditionListModel::updateToken(int index, const QString &value)
-{
- m_tokens[index] = valueToToken(value);
- validateAndRebuildTokens();
-
- dataChanged(createIndex(index, 0), createIndex(index, 0));
- //resetModel();
-}
-
-void ConditionListModel::appendToken(const QString &value)
-{
- beginInsertRows({}, rowCount() - 1, rowCount() - 1);
-
- insertToken(rowCount(), value);
- validateAndRebuildTokens();
-
- endInsertRows();
- //resetModel();
-}
-
-void ConditionListModel::removeToken(int index)
-{
- QTC_ASSERT(index < m_tokens.count(), return );
- beginRemoveRows({}, index, index);
-
- m_tokens.remove(index, 1);
- validateAndRebuildTokens();
-
- endRemoveRows();
-
- //resetModel();
-}
-
-void ConditionListModel::insertIntermediateToken(int index, const QString &value)
-{
- beginInsertRows({}, index, index);
-
- ConditionToken token;
- token.type = Intermediate;
- token.value = value;
-
- m_tokens.insert(index, token);
-
- endInsertRows();
- //resetModel();
-}
-
-void ConditionListModel::insertShadowToken(int index, const QString &value)
-{
- beginInsertRows({}, index, index);
-
- ConditionToken token;
- token.type = Shadow;
- token.value = value;
-
- m_tokens.insert(index, token);
-
- endInsertRows();
-
- //resetModel();
-}
-
-void ConditionListModel::setShadowToken(int index, const QString &value)
-{
- m_tokens[index].type = Shadow;
- m_tokens[index].value = value;
-
- dataChanged(createIndex(index, 0), createIndex(index, 0));
- //resetModel();
-}
-
-bool ConditionListModel::valid() const
-{
- return m_valid;
-}
-
-bool ConditionListModel::empty() const
-{
- return m_tokens.isEmpty();
-}
-
-void ConditionListModel::command(const QString &string)
-{
- //TODO remove from prodcution code
- QStringList list = string.split("%", Qt::SkipEmptyParts);
-
- if (list.size() < 2)
- return;
-
- if (list.size() == 2) {
- if (list.first() == "A") {
- appendToken(list.last());
- } else if (list.first() == "R") {
- bool ok = true;
- int index = list.last().toInt(&ok);
-
- if (ok)
- removeToken(index);
- }
- }
-
- if (list.size() == 3) {
- if (list.first() == "U") {
- bool ok = true;
- int index = list.at(1).toInt(&ok);
-
- if (ok)
- updateToken(index, list.last());
- } else if (list.first() == "I") {
- bool ok = true;
- int index = list.at(1).toInt(&ok);
-
- if (ok)
- insertToken(index, list.last());
- }
- }
-}
-
-void ConditionListModel::setInvalid(const QString &errorMessage, int index)
-{
- m_valid = false;
- m_errorMessage = errorMessage;
-
- emit errorChanged();
- emit validChanged();
-
- if (index != -1) {
- m_errorIndex = index;
- emit errorIndexChanged();
- }
-}
-
-void ConditionListModel::setValid()
-{
- m_valid = true;
- m_errorMessage.clear();
- m_errorIndex = -1;
-
- emit errorChanged();
- emit validChanged();
- emit errorIndexChanged();
-}
-
-QString ConditionListModel::error() const
-{
- return m_errorMessage;
-}
-
-int ConditionListModel::errorIndex() const
-{
- return m_errorIndex;
-}
-
-bool ConditionListModel::operatorAllowed(int cursorPosition)
-{
- if (m_tokens.empty())
- return false;
-
- int tokenIdx = cursorPosition - 1;
-
- if (tokenIdx >= 0 && tokenIdx < m_tokens.length() && m_tokens[tokenIdx].type != Operator)
- return true;
-
- return false;
-}
-
-void ConditionListModel::internalSetup()
-{
- setInvalid(tr("No Valid Condition"));
- if (!m_condition.statements.size() && !m_condition.tokens.size())
- return;
-
- if (m_condition.statements.size() != m_condition.tokens.size() + 1)
- return;
-
- if (m_condition.statements.size() == 1 && m_condition.tokens.isEmpty()) {
- auto token = tokenFromComparativeStatement(m_condition.statements.first());
- if (token.value == defaultCondition)
- return;
- }
-
- auto s_it = m_condition.statements.begin();
- auto o_it = m_condition.tokens.begin();
-
- while (o_it != m_condition.tokens.end()) {
- m_tokens.append(tokenFromComparativeStatement(*s_it));
- m_tokens.append(tokenFromConditionToken(*o_it));
-
- s_it++;
- o_it++;
- }
- m_tokens.append(tokenFromComparativeStatement(*s_it));
-
- setValid();
-}
-
-ConditionListModel::ConditionToken ConditionListModel::valueToToken(const QString &value)
-{
- const QStringList operators = {"&&", "||", "===", "!==", ">", ">=", "<", "<="};
-
- if (operators.contains(value)) {
- ConditionToken token;
- token.type = Operator;
- token.value = value;
- return token;
- }
-
- bool ok = false;
- value.toDouble(&ok);
-
- if (value == "true" || value == "false" || ok
- || (value.startsWith("\"") && value.endsWith("\""))) {
- ConditionToken token;
- token.type = Literal;
- token.value = value;
- return token;
- }
-
- static QRegularExpression regexp("^[a-z_]\\w*|^[A-Z]\\w*\\.{1}([a-z_]\\w*\\.?)+");
- QRegularExpressionMatch match = regexp.match(value);
-
- if (match.hasMatch()) { //variable
- ConditionToken token;
- token.type = Variable;
- token.value = value;
- return token;
- }
-
- ConditionToken token;
- token.type = Invalid;
- token.value = value;
-
- return token;
-}
-
-void ConditionListModel::resetModel()
-{
- beginResetModel();
- endResetModel();
-}
-
-int ConditionListModel::checkOrder() const
-{
- auto it = m_tokens.begin();
-
- bool wasOperator = true;
-
- int ret = 0;
- while (it != m_tokens.end()) {
- if (wasOperator && it->type == Operator)
- return ret;
- if (!wasOperator && it->type == Literal)
- return ret;
- if (!wasOperator && it->type == Variable)
- return ret;
- wasOperator = it->type == Operator;
- it++;
- ret++;
- }
-
- if (wasOperator)
- return ret;
-
- return -1;
-}
-
-void ConditionListModel::validateAndRebuildTokens()
-{
- /// NEW
- auto it = m_tokens.begin();
-
- while (it != m_tokens.end()) {
- if (it->type == Intermediate)
- *it = valueToToken(it->value);
-
- it++;
- }
- // NEW
-
- QString invalidValue;
- const bool invalidToken = Utils::contains(m_tokens,
- [&invalidValue](const ConditionToken &token) {
- if (token.type == Invalid)
- invalidValue = token.value;
- return token.type == Invalid;
- });
-
- if (invalidToken) {
- setInvalid(tr("Invalid token %1").arg(invalidValue));
- return;
- }
-
- if (int firstError = checkOrder() != -1) {
- setInvalid(tr("Invalid order at %1").arg(firstError), firstError);
- return;
- }
-
- setValid();
-
- rebuildTokens();
-}
-
-void ConditionListModel::rebuildTokens()
-{
- QTC_ASSERT(m_valid, return );
-
- m_condition.statements.clear();
- m_condition.tokens.clear();
-
- auto it = m_tokens.begin();
-
- while (it != m_tokens.end()) {
- QTC_ASSERT(it->type != Invalid, return );
- if (it->type == Operator)
- m_condition.tokens.append(toOperatorStatement(*it));
- else if (it->type == Literal || it->type == Variable)
- m_condition.statements.append(toStatement(*it));
-
- it++;
- }
-
- emit conditionChanged();
-}
-
-ConnectionEditorStatements::ConditionToken ConditionListModel::toOperatorStatement(
- const ConditionToken &token)
-{
- if (token.value == "&&")
- return ConnectionEditorStatements::ConditionToken::And;
-
- if (token.value == "||")
- return ConnectionEditorStatements::ConditionToken::Or;
-
- if (token.value == "===")
- return ConnectionEditorStatements::ConditionToken::Equals;
-
- if (token.value == "!==")
- return ConnectionEditorStatements::ConditionToken::Not;
-
- if (token.value == ">")
- return ConnectionEditorStatements::ConditionToken::LargerThan;
-
- if (token.value == ">=")
- return ConnectionEditorStatements::ConditionToken::LargerEqualsThan;
-
- if (token.value == "<")
- return ConnectionEditorStatements::ConditionToken::SmallerThan;
-
- if (token.value == "<=")
- return ConnectionEditorStatements::ConditionToken::SmallerEqualsThan;
-
- return ConnectionEditorStatements::ConditionToken::Unknown;
-}
-
-ConnectionEditorStatements::ComparativeStatement ConditionListModel::toStatement(
- const ConditionToken &token)
-{
- if (token.type == Variable) {
- QStringList list = token.value.split(".");
- ConnectionEditorStatements::Variable variable;
-
- variable.nodeId = list.first();
- if (list.count() > 1)
- variable.propertyName = list.last();
- return variable;
- } else if (token.type == Literal) {
- return parseTextArgumentComparativeStatement(token.value);
- }
-
- return {};
+ return model->signalHandlerPropertyForRow(currentRow());
}
void QmlDesigner::ConnectionModel::modelAboutToBeDetached()
diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.h b/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.h
index 017cf676843..8767dac4134 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.h
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectionmodel.h
@@ -3,15 +3,11 @@
#pragma once
-#include
-#include
+#include
#include
-#include
#include
-#include
-
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 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 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 m_model = nullptr;
};
diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp b/src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp
index a60edca67b9..007116105b0 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/connectionview.cpp
@@ -83,10 +83,8 @@ public:
0,
"DynamicPropertiesModelBackendDelegate");
- qmlRegisterType("ConnectionsEditorEditorBackend",
- 1,
- 0,
- "ConnectionModelStatementDelegate");
+ // TODO: register in the property editor along with the ScriptEditorBackend
+ qmlRegisterType("ScriptEditorBackend", 1, 0, "StatementDelegate");
qmlRegisterType("ConnectionsEditorEditorBackend", 1, 0, "ConditionListModel");
diff --git a/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesitem.cpp b/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesitem.cpp
index a45b0e115d8..1694231630c 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesitem.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesitem.cpp
@@ -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
#include
#include
diff --git a/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp b/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp
index 687752b8c98..c4307a07182 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp
+++ b/src/plugins/qmldesigner/components/connectioneditor/dynamicpropertiesmodel.cpp
@@ -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
#include
#include
-#include
-#include
-#include
-#include
-#include
#include
#include
#include
#include
#include
+#include
+#include
+#include
+#include
+#include
+#include
#include
diff --git a/src/plugins/qmldesigner/components/propertyeditor/dynamicpropertiesproxymodel.cpp b/src/plugins/qmldesigner/components/propertyeditor/dynamicpropertiesproxymodel.cpp
index 8ba6b22ac0f..8c6f272fa91 100644
--- a/src/plugins/qmldesigner/components/propertyeditor/dynamicpropertiesproxymodel.cpp
+++ b/src/plugins/qmldesigner/components/propertyeditor/dynamicpropertiesproxymodel.cpp
@@ -27,7 +27,7 @@
#include "bindingproperty.h"
#include "propertyeditorvalue.h"
-#include "connectioneditorutils.h"
+#include
#include
diff --git a/src/plugins/qmldesigner/components/connectioneditor/propertytreemodel.cpp b/src/plugins/qmldesigner/components/scripteditor/propertytreemodel.cpp
similarity index 98%
rename from src/plugins/qmldesigner/components/connectioneditor/propertytreemodel.cpp
rename to src/plugins/qmldesigner/components/scripteditor/propertytreemodel.cpp
index 463286e6956..b1892c9b557 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/propertytreemodel.cpp
+++ b/src/plugins/qmldesigner/components/scripteditor/propertytreemodel.cpp
@@ -163,8 +163,8 @@ std::vector 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 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 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] {
diff --git a/src/plugins/qmldesigner/components/connectioneditor/propertytreemodel.h b/src/plugins/qmldesigner/components/scripteditor/propertytreemodel.h
similarity index 97%
rename from src/plugins/qmldesigner/components/connectioneditor/propertytreemodel.h
rename to src/plugins/qmldesigner/components/scripteditor/propertytreemodel.h
index 39af4857654..bb7dab533db 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/propertytreemodel.h
+++ b/src/plugins/qmldesigner/components/scripteditor/propertytreemodel.h
@@ -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 m_indexCache;
mutable std::vector 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);
diff --git a/src/plugins/qmldesigner/components/scripteditor/scripteditorbackend.cpp b/src/plugins/qmldesigner/components/scripteditor/scripteditorbackend.cpp
new file mode 100644
index 00000000000..4846f149ddf
--- /dev/null
+++ b/src/plugins/qmldesigner/components/scripteditor/scripteditorbackend.cpp
@@ -0,0 +1,1373 @@
+// 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 "scripteditorbackend.h"
+#include "scripteditorevaluator.h"
+#include "scripteditorutils.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+namespace {
+const char defaultCondition[] = "condition";
+
+QString getSourceFromProperty(const QmlDesigner::AbstractProperty &property)
+{
+ QTC_ASSERT(property.isValid(), return {});
+
+ if (!property.exists())
+ return {};
+
+ if (property.isSignalHandlerProperty())
+ return property.toSignalHandlerProperty().source();
+ if (property.isBindingProperty())
+ return property.toBindingProperty().expression();
+
+ return {};
+}
+} // namespace
+
+namespace QmlDesigner {
+static ScriptEditorStatements::MatchedCondition emptyCondition;
+
+ConditionListModel::ConditionListModel(AbstractView *view)
+ : m_view(view)
+ , m_condition(emptyCondition)
+{}
+
+int ConditionListModel::rowCount(const QModelIndex & /*parent*/) const
+{
+ return m_tokens.size();
+}
+
+QHash ConditionListModel::roleNames() const
+{
+ static QHash roleNames{{Qt::UserRole + 1, "type"}, {Qt::UserRole + 2, "value"}};
+ return roleNames;
+}
+
+QVariant ConditionListModel::data(const QModelIndex &index, int role) const
+{
+ if (index.isValid() && index.row() < rowCount()) {
+ if (role == Qt::UserRole + 1) {
+ return m_tokens.at(index.row()).type;
+ } else if (role == Qt::UserRole + 2) {
+ return m_tokens.at(index.row()).value;
+ }
+
+ qCWarning(ScriptEditorLog) << __FUNCTION__ << "invalid role";
+ } else {
+ qCWarning(ScriptEditorLog) << __FUNCTION__ << "invalid index";
+ }
+
+ return QVariant();
+}
+
+void ConditionListModel::setup()
+{
+ m_tokens.clear();
+
+ internalSetup();
+
+ emit validChanged();
+ emit emptyChanged();
+
+ beginResetModel();
+ endResetModel();
+}
+
+void ConditionListModel::setCondition(ScriptEditorStatements::MatchedCondition &condition)
+{
+ m_condition = condition;
+ setup();
+}
+
+ScriptEditorStatements::MatchedCondition &ConditionListModel::condition()
+{
+ return m_condition;
+}
+
+ConditionListModel::ConditionToken ConditionListModel::tokenFromConditionToken(
+ const ScriptEditorStatements::ConditionToken &token)
+{
+ ConditionToken ret;
+ ret.type = Operator;
+ ret.value = ScriptEditorStatements::toJavascript(token);
+
+ return ret;
+}
+
+ConditionListModel::ConditionToken ConditionListModel::tokenFromComparativeStatement(
+ const ScriptEditorStatements::ComparativeStatement &token)
+{
+ ConditionToken ret;
+
+ if (auto *variable = std::get_if(&token)) {
+ ret.type = Variable;
+ ret.value = variable->expression();
+ return ret;
+ } else if (auto *literal = std::get_if(&token)) {
+ ret.type = Literal;
+ ret.value = "\"" + *literal + "\"";
+ return ret;
+ } else if (auto *literal = std::get_if(&token)) {
+ ret.type = Literal;
+ if (*literal)
+ ret.value = "true";
+ else
+ ret.value = "false";
+ return ret;
+ } else if (auto *literal = std::get_if(&token)) {
+ ret.type = Literal;
+ ret.value = QString::number(*literal);
+ return ret;
+ }
+
+ ret.type = Invalid;
+ ret.value = "invalid";
+ return {};
+}
+
+void ConditionListModel::insertToken(int index, const QString &value)
+{
+ beginInsertRows({}, index, index);
+
+ m_tokens.insert(index, valueToToken(value));
+ validateAndRebuildTokens();
+
+ endInsertRows();
+}
+
+void ConditionListModel::updateToken(int index, const QString &value)
+{
+ m_tokens[index] = valueToToken(value);
+ validateAndRebuildTokens();
+
+ emit dataChanged(createIndex(index, 0), createIndex(index, 0));
+}
+
+void ConditionListModel::appendToken(const QString &value)
+{
+ beginInsertRows({}, rowCount() - 1, rowCount() - 1);
+
+ insertToken(rowCount(), value);
+ validateAndRebuildTokens();
+
+ endInsertRows();
+}
+
+void ConditionListModel::removeToken(int index)
+{
+ QTC_ASSERT(index < m_tokens.count(), return);
+ beginRemoveRows({}, index, index);
+
+ m_tokens.remove(index, 1);
+ validateAndRebuildTokens();
+
+ endRemoveRows();
+}
+
+void ConditionListModel::insertIntermediateToken(int index, const QString &value)
+{
+ beginInsertRows({}, index, index);
+
+ ConditionToken token;
+ token.type = Intermediate;
+ token.value = value;
+
+ m_tokens.insert(index, token);
+
+ endInsertRows();
+}
+
+void ConditionListModel::insertShadowToken(int index, const QString &value)
+{
+ beginInsertRows({}, index, index);
+
+ ConditionToken token;
+ token.type = Shadow;
+ token.value = value;
+
+ m_tokens.insert(index, token);
+
+ endInsertRows();
+}
+
+void ConditionListModel::setShadowToken(int index, const QString &value)
+{
+ m_tokens[index].type = Shadow;
+ m_tokens[index].value = value;
+
+ emit dataChanged(createIndex(index, 0), createIndex(index, 0));
+}
+
+bool ConditionListModel::valid() const
+{
+ return m_valid;
+}
+
+bool ConditionListModel::empty() const
+{
+ return m_tokens.isEmpty();
+}
+
+void ConditionListModel::command(const QString &string)
+{
+ //TODO remove from prodcution code
+ QStringList list = string.split("%", Qt::SkipEmptyParts);
+
+ if (list.size() < 2)
+ return;
+
+ if (list.size() == 2) {
+ if (list.first() == "A") {
+ appendToken(list.last());
+ } else if (list.first() == "R") {
+ bool ok = true;
+ int index = list.last().toInt(&ok);
+
+ if (ok)
+ removeToken(index);
+ }
+ }
+
+ if (list.size() == 3) {
+ if (list.first() == "U") {
+ bool ok = true;
+ int index = list.at(1).toInt(&ok);
+
+ if (ok)
+ updateToken(index, list.last());
+ } else if (list.first() == "I") {
+ bool ok = true;
+ int index = list.at(1).toInt(&ok);
+
+ if (ok)
+ insertToken(index, list.last());
+ }
+ }
+}
+
+void ConditionListModel::setInvalid(const QString &errorMessage, int index)
+{
+ m_valid = false;
+ m_errorMessage = errorMessage;
+
+ emit errorChanged();
+ emit validChanged();
+
+ if (index != -1) {
+ m_errorIndex = index;
+ emit errorIndexChanged();
+ }
+}
+
+void ConditionListModel::setValid()
+{
+ m_valid = true;
+ m_errorMessage.clear();
+ m_errorIndex = -1;
+
+ emit errorChanged();
+ emit validChanged();
+ emit errorIndexChanged();
+}
+
+QString ConditionListModel::error() const
+{
+ return m_errorMessage;
+}
+
+int ConditionListModel::errorIndex() const
+{
+ return m_errorIndex;
+}
+
+bool ConditionListModel::operatorAllowed(int cursorPosition)
+{
+ if (m_tokens.empty())
+ return false;
+
+ int tokenIdx = cursorPosition - 1;
+
+ if (tokenIdx >= 0 && tokenIdx < m_tokens.length() && m_tokens[tokenIdx].type != Operator)
+ return true;
+
+ return false;
+}
+
+void ConditionListModel::internalSetup()
+{
+ setInvalid(tr("No Valid Condition"));
+ if (!m_condition.statements.size() && !m_condition.tokens.size())
+ return;
+
+ if (m_condition.statements.size() != m_condition.tokens.size() + 1)
+ return;
+
+ if (m_condition.statements.size() == 1 && m_condition.tokens.isEmpty()) {
+ auto token = tokenFromComparativeStatement(m_condition.statements.first());
+ if (token.value == defaultCondition)
+ return;
+ }
+
+ auto s_it = m_condition.statements.begin();
+ auto o_it = m_condition.tokens.begin();
+
+ while (o_it != m_condition.tokens.end()) {
+ m_tokens.append(tokenFromComparativeStatement(*s_it));
+ m_tokens.append(tokenFromConditionToken(*o_it));
+
+ s_it++;
+ o_it++;
+ }
+ m_tokens.append(tokenFromComparativeStatement(*s_it));
+
+ setValid();
+}
+
+ConditionListModel::ConditionToken ConditionListModel::valueToToken(const QString &value)
+{
+ const QStringList operators = {"&&", "||", "===", "!==", ">", ">=", "<", "<="};
+
+ if (operators.contains(value)) {
+ ConditionToken token;
+ token.type = Operator;
+ token.value = value;
+ return token;
+ }
+
+ bool ok = false;
+ value.toDouble(&ok);
+
+ if (value == "true" || value == "false" || ok || (value.startsWith("\"") && value.endsWith("\""))) {
+ ConditionToken token;
+ token.type = Literal;
+ token.value = value;
+ return token;
+ }
+
+ static QRegularExpression regexp("^[a-z_]\\w*|^[A-Z]\\w*\\.{1}([a-z_]\\w*\\.?)+");
+ QRegularExpressionMatch match = regexp.match(value);
+
+ if (match.hasMatch()) { //variable
+ ConditionToken token;
+ token.type = Variable;
+ token.value = value;
+ return token;
+ }
+
+ ConditionToken token;
+ token.type = Invalid;
+ token.value = value;
+
+ return token;
+}
+
+void ConditionListModel::resetModel()
+{
+ beginResetModel();
+ endResetModel();
+}
+
+int ConditionListModel::checkOrder() const
+{
+ auto it = m_tokens.begin();
+
+ bool wasOperator = true;
+
+ int ret = 0;
+ while (it != m_tokens.end()) {
+ if (wasOperator && it->type == Operator)
+ return ret;
+ if (!wasOperator && it->type == Literal)
+ return ret;
+ if (!wasOperator && it->type == Variable)
+ return ret;
+ wasOperator = it->type == Operator;
+ it++;
+ ret++;
+ }
+
+ if (wasOperator)
+ return ret;
+
+ return -1;
+}
+
+void ConditionListModel::validateAndRebuildTokens()
+{
+ /// NEW
+ auto it = m_tokens.begin();
+
+ while (it != m_tokens.end()) {
+ if (it->type == Intermediate)
+ *it = valueToToken(it->value);
+
+ it++;
+ }
+ // NEW
+
+ QString invalidValue;
+ const bool invalidToken = Utils::contains(m_tokens, [&invalidValue](const ConditionToken &token) {
+ if (token.type == Invalid)
+ invalidValue = token.value;
+ return token.type == Invalid;
+ });
+
+ if (invalidToken) {
+ setInvalid(tr("Invalid token %1").arg(invalidValue));
+ return;
+ }
+
+ if (int firstError = checkOrder() != -1) {
+ setInvalid(tr("Invalid order at %1").arg(firstError), firstError);
+ return;
+ }
+
+ setValid();
+
+ rebuildTokens();
+}
+
+ScriptEditorStatements::ConditionToken ConditionListModel::toOperatorStatement(const ConditionToken &token)
+{
+ if (token.value == "&&")
+ return ScriptEditorStatements::ConditionToken::And;
+
+ if (token.value == "||")
+ return ScriptEditorStatements::ConditionToken::Or;
+
+ if (token.value == "===")
+ return ScriptEditorStatements::ConditionToken::Equals;
+
+ if (token.value == "!==")
+ return ScriptEditorStatements::ConditionToken::Not;
+
+ if (token.value == ">")
+ return ScriptEditorStatements::ConditionToken::LargerThan;
+
+ if (token.value == ">=")
+ return ScriptEditorStatements::ConditionToken::LargerEqualsThan;
+
+ if (token.value == "<")
+ return ScriptEditorStatements::ConditionToken::SmallerThan;
+
+ if (token.value == "<=")
+ return ScriptEditorStatements::ConditionToken::SmallerEqualsThan;
+
+ return ScriptEditorStatements::ConditionToken::Unknown;
+}
+
+static ScriptEditorStatements::ComparativeStatement parseTextArgumentComparativeStatement(
+ const QString &text)
+{
+ if (text.startsWith("\"") && text.endsWith("\"")) {
+ QString ret = text;
+ ret.remove(0, 1);
+ ret.chop(1);
+ return ret;
+ }
+
+ if (text == "true")
+ return true;
+
+ if (text == "false")
+ return false;
+
+ bool ok = true;
+ double d = text.toDouble(&ok);
+ if (ok)
+ return d;
+
+ return text;
+}
+
+ScriptEditorStatements::ComparativeStatement ConditionListModel::toStatement(const ConditionToken &token)
+{
+ if (token.type == Variable) {
+ QStringList list = token.value.split(".");
+ ScriptEditorStatements::Variable variable;
+
+ variable.nodeId = list.first();
+ if (list.count() > 1)
+ variable.propertyName = list.last();
+ return variable;
+ } else if (token.type == Literal) {
+ return parseTextArgumentComparativeStatement(token.value);
+ }
+
+ return {};
+}
+
+void ConditionListModel::rebuildTokens()
+{
+ QTC_ASSERT(m_valid, return);
+
+ m_condition.statements.clear();
+ m_condition.tokens.clear();
+
+ auto it = m_tokens.begin();
+
+ while (it != m_tokens.end()) {
+ QTC_ASSERT(it->type != Invalid, return);
+ if (it->type == Operator)
+ m_condition.tokens.append(toOperatorStatement(*it));
+ else if (it->type == Literal || it->type == Variable)
+ m_condition.statements.append(toStatement(*it));
+
+ it++;
+ }
+
+ emit conditionChanged();
+}
+
+static ScriptEditorStatements::MatchedStatement emptyStatement;
+
+StatementDelegate::StatementDelegate(AbstractView *view)
+ : m_functionDelegate(view)
+ , m_lhsDelegate(view)
+ , m_rhsAssignmentDelegate(view)
+ , m_statement(emptyStatement)
+ , m_view(view)
+{
+ m_functionDelegate.setPropertyType(PropertyTreeModel::SlotType);
+
+ connect(&m_functionDelegate, &PropertyTreeModelDelegate::commitData, this, [this] {
+ handleFunctionChanged();
+ });
+
+ connect(&m_rhsAssignmentDelegate, &PropertyTreeModelDelegate::commitData, this, [this] {
+ handleRhsAssignmentChanged();
+ });
+
+ connect(&m_lhsDelegate, &PropertyTreeModelDelegate::commitData, this, [this] {
+ handleLhsChanged();
+ });
+
+ connect(&m_stringArgument, &StudioQmlTextBackend::activated, this, [this] {
+ handleStringArgumentChanged();
+ });
+
+ connect(&m_states, &StudioQmlComboBoxBackend::activated, this, [this] { handleStateChanged(); });
+
+ connect(&m_stateTargets, &StudioQmlComboBoxBackend::activated, this, [this] {
+ handleStateTargetsChanged();
+ });
+}
+
+void StatementDelegate::setActionType(ActionType type)
+{
+ if (m_actionType == type)
+ return;
+
+ m_actionType = type;
+ emit actionTypeChanged();
+ setup();
+}
+
+void StatementDelegate::setup()
+{
+ switch (m_actionType) {
+ case CallFunction:
+ setupCallFunction();
+ break;
+ case Assign:
+ setupAssignment();
+ break;
+ case ChangeState:
+ setupChangeState();
+ break;
+ case SetProperty:
+ setupSetProperty();
+ break;
+ case PrintMessage:
+ setupPrintMessage();
+ break;
+ case Custom:
+ break;
+ };
+}
+
+void StatementDelegate::setStatement(ScriptEditorStatements::MatchedStatement &statement)
+{
+ m_statement = statement;
+ setup();
+}
+
+ScriptEditorStatements::MatchedStatement &StatementDelegate::statement()
+{
+ return m_statement;
+}
+
+StatementDelegate::ActionType StatementDelegate::actionType() const
+{
+ return m_actionType;
+}
+
+PropertyTreeModelDelegate *StatementDelegate::function()
+{
+ return &m_functionDelegate;
+}
+
+PropertyTreeModelDelegate *StatementDelegate::lhs()
+{
+ return &m_lhsDelegate;
+}
+
+PropertyTreeModelDelegate *StatementDelegate::rhsAssignment()
+{
+ return &m_rhsAssignmentDelegate;
+}
+
+StudioQmlTextBackend *StatementDelegate::stringArgument()
+{
+ return &m_stringArgument;
+}
+
+StudioQmlComboBoxBackend *StatementDelegate::stateTargets()
+{
+ return &m_stateTargets;
+}
+
+StudioQmlComboBoxBackend *StatementDelegate::states()
+{
+ return &m_states;
+}
+
+void StatementDelegate::handleFunctionChanged()
+{
+ QTC_ASSERT(std::holds_alternative(m_statement), return);
+
+ ScriptEditorStatements::MatchedFunction &functionStatement = std::get(
+ m_statement);
+
+ functionStatement.functionName = m_functionDelegate.name();
+ functionStatement.nodeId = m_functionDelegate.id();
+
+ emit statementChanged();
+}
+
+void StatementDelegate::handleLhsChanged()
+{
+ if (m_actionType == Assign) {
+ QTC_ASSERT(std::holds_alternative(m_statement), return);
+
+ ScriptEditorStatements::Assignment &assignmentStatement = std::get(
+ m_statement);
+
+ assignmentStatement.lhs.nodeId = m_lhsDelegate.id();
+ assignmentStatement.lhs.propertyName = m_lhsDelegate.name();
+
+ } else if (m_actionType == SetProperty) {
+ QTC_ASSERT(std::holds_alternative(m_statement), return);
+
+ ScriptEditorStatements::PropertySet &setPropertyStatement = std::get(
+ m_statement);
+
+ setPropertyStatement.lhs.nodeId = m_lhsDelegate.id();
+ setPropertyStatement.lhs.propertyName = m_lhsDelegate.name();
+ } else {
+ QTC_ASSERT(false, return);
+ }
+
+ emit statementChanged();
+}
+
+void StatementDelegate::handleRhsAssignmentChanged()
+{
+ QTC_ASSERT(std::holds_alternative(m_statement), return);
+
+ ScriptEditorStatements::Assignment &assignmentStatement = std::get(
+ m_statement);
+
+ assignmentStatement.rhs.nodeId = m_rhsAssignmentDelegate.id();
+ assignmentStatement.rhs.propertyName = m_rhsAssignmentDelegate.name();
+
+ setupPropertyType();
+
+ emit statementChanged();
+}
+
+static ScriptEditorStatements::Literal parseTextArgument(const QString &text)
+{
+ if (text.startsWith("\"") && text.endsWith("\"")) {
+ QString ret = text;
+ ret.remove(0, 1);
+ ret.chop(1);
+ return ret;
+ }
+
+ if (text == "true")
+ return true;
+
+ if (text == "false")
+ return false;
+
+ bool ok = true;
+ double d = text.toDouble(&ok);
+ if (ok)
+ return d;
+
+ return text;
+}
+
+static ScriptEditorStatements::RightHandSide parseLogTextArgument(const QString &text)
+{
+ if (text.startsWith("\"") && text.endsWith("\"")) {
+ QString ret = text;
+ ret.remove(0, 1);
+ ret.chop(1);
+ return ret;
+ }
+
+ if (text == "true")
+ return true;
+
+ if (text == "false")
+ return true;
+
+ bool ok = true;
+ double d = text.toDouble(&ok);
+ if (ok)
+ return d;
+
+ //TODO variables and function calls
+ return text;
+}
+
+void StatementDelegate::handleStringArgumentChanged()
+{
+ if (m_actionType == SetProperty) {
+ QTC_ASSERT(std::holds_alternative(m_statement), return);
+
+ ScriptEditorStatements::PropertySet &propertySet = std::get(
+ m_statement);
+
+ propertySet.rhs = parseTextArgument(m_stringArgument.text());
+
+ } else if (m_actionType == PrintMessage) {
+ QTC_ASSERT(std::holds_alternative(m_statement), return);
+
+ ScriptEditorStatements::ConsoleLog &consoleLog = std::get(
+ m_statement);
+
+ consoleLog.argument = parseLogTextArgument(m_stringArgument.text());
+ } else {
+ QTC_ASSERT(false, return);
+ }
+
+ emit statementChanged();
+}
+
+void StatementDelegate::handleStateChanged()
+{
+ QTC_ASSERT(std::holds_alternative(m_statement), return);
+
+ ScriptEditorStatements::StateSet &stateSet = std::get(
+ m_statement);
+
+ QString stateName = m_states.currentText();
+ if (stateName == baseStateName())
+ stateName = "";
+ stateSet.stateName = "\"" + stateName + "\"";
+
+ emit statementChanged();
+}
+
+void StatementDelegate::handleStateTargetsChanged()
+{
+ QTC_ASSERT(std::holds_alternative(m_statement), return);
+
+ ScriptEditorStatements::StateSet &stateSet = std::get(
+ m_statement);
+
+ stateSet.nodeId = m_stateTargets.currentText();
+ stateSet.stateName = "\"\"";
+
+ setupStates();
+
+ emit statementChanged();
+}
+
+void StatementDelegate::setupAssignment()
+{
+ QTC_ASSERT(std::holds_alternative(m_statement), return);
+
+ const auto assignment = std::get(m_statement);
+ m_lhsDelegate.setup(assignment.lhs.nodeId, assignment.lhs.propertyName);
+ m_rhsAssignmentDelegate.setup(assignment.rhs.nodeId, assignment.rhs.propertyName);
+ setupPropertyType();
+}
+
+void StatementDelegate::setupSetProperty()
+{
+ QTC_ASSERT(std::holds_alternative(m_statement), return);
+
+ const auto propertySet = std::get(m_statement);
+ m_lhsDelegate.setup(propertySet.lhs.nodeId, propertySet.lhs.propertyName);
+ m_stringArgument.setText(ScriptEditorStatements::toString(propertySet.rhs));
+}
+
+void StatementDelegate::setupCallFunction()
+{
+ QTC_ASSERT(std::holds_alternative(m_statement), return);
+
+ const auto functionStatement = std::get(m_statement);
+ m_functionDelegate.setup(functionStatement.nodeId, functionStatement.functionName);
+}
+
+void StatementDelegate::setupChangeState()
+{
+ QTC_ASSERT(std::holds_alternative(m_statement), return);
+
+ QTC_ASSERT(m_view->isAttached(), return);
+
+ auto model = m_view->model();
+ const auto items = Utils::filtered(m_view->allModelNodesOfType(model->qtQuickItemMetaInfo()),
+ [](const ModelNode &node) {
+ QmlItemNode item(node);
+ return node.hasId() && item.isValid()
+ && !item.allStateNames().isEmpty();
+ });
+
+ QStringList itemIds = Utils::transform(items, &ModelNode::id);
+ const auto groups = m_view->allModelNodesOfType(model->qtQuickStateGroupMetaInfo());
+
+ const auto rootId = m_view->rootModelNode().id();
+ itemIds.removeAll(rootId);
+
+ QStringList groupIds = Utils::transform(groups, &ModelNode::id);
+
+ Utils::sort(itemIds);
+ Utils::sort(groupIds);
+
+ if (!rootId.isEmpty())
+ groupIds.prepend(rootId);
+
+ const QStringList stateGroupModel = groupIds + itemIds;
+ m_stateTargets.setModel(stateGroupModel);
+
+ const auto stateSet = std::get(m_statement);
+
+ m_stateTargets.setCurrentText(stateSet.nodeId);
+ setupStates();
+}
+
+static QString stripQuotesFromState(const QString &input)
+{
+ if (input.startsWith("\"") && input.endsWith("\"")) {
+ QString ret = input;
+ ret.remove(0, 1);
+ ret.chop(1);
+ return ret;
+ }
+ return input;
+}
+
+void StatementDelegate::setupStates()
+{
+ QTC_ASSERT(std::holds_alternative(m_statement), return);
+ QTC_ASSERT(m_view->isAttached(), return);
+
+ const auto stateSet = std::get(m_statement);
+
+ const QString nodeId = m_stateTargets.currentText();
+
+ const ModelNode node = m_view->modelNodeForId(nodeId);
+
+ QStringList states;
+ if (node.metaInfo().isQtQuickItem()) {
+ QmlItemNode item(node);
+ QTC_ASSERT(item.isValid(), return);
+ if (item.isRootNode())
+ states = item.states().names(); //model
+ else
+ states = item.allStateNames(); //instances
+ } else {
+ QmlModelStateGroup group(node);
+ states = group.names(); //model
+ }
+
+ const QString stateName = stripQuotesFromState(stateSet.stateName);
+
+ states.prepend(baseStateName());
+ m_states.setModel(states);
+ if (stateName.isEmpty())
+ m_states.setCurrentText(baseStateName());
+ else
+ m_states.setCurrentText(stateName);
+}
+
+void StatementDelegate::setupPrintMessage()
+{
+ QTC_ASSERT(std::holds_alternative(m_statement), return);
+
+ const auto consoleLog = std::get(m_statement);
+ m_stringArgument.setText(ScriptEditorStatements::toString(consoleLog.argument));
+}
+
+void StatementDelegate::setupPropertyType()
+{
+ PropertyTreeModel::PropertyTypes type = PropertyTreeModel::AllTypes;
+
+ const NodeMetaInfo metaInfo = m_rhsAssignmentDelegate.propertyMetaInfo();
+
+ if (metaInfo.isBool())
+ type = PropertyTreeModel::BoolType;
+ else if (metaInfo.isNumber())
+ type = PropertyTreeModel::NumberType;
+ else if (metaInfo.isColor())
+ type = PropertyTreeModel::ColorType;
+ else if (metaInfo.isString())
+ type = PropertyTreeModel::StringType;
+ else if (metaInfo.isUrl())
+ type = PropertyTreeModel::UrlType;
+
+ m_lhsDelegate.setPropertyType(type);
+}
+
+QString StatementDelegate::baseStateName() const
+{
+ return tr("Base State");
+}
+
+ScriptEditorBackend::ScriptEditorBackend(AbstractView *view)
+ : m_okStatementDelegate(view)
+ , m_koStatementDelegate(view)
+ , m_conditionListModel(view)
+ , m_propertyTreeModel(view)
+ , m_propertyListProxyModel(&m_propertyTreeModel)
+ , m_view(view)
+{
+ connect(&m_okStatementDelegate, &StatementDelegate::statementChanged, this, [this] {
+ handleOkStatementChanged();
+ });
+
+ connect(&m_koStatementDelegate, &StatementDelegate::statementChanged, this, [this] {
+ handleKOStatementChanged();
+ });
+
+ connect(&m_conditionListModel, &ConditionListModel::conditionChanged, this, [this] {
+ handleConditionChanged();
+ });
+}
+
+static QString generateDefaultStatement(ScriptEditorBackend::ActionType actionType,
+ const QString &rootId)
+{
+ switch (actionType) {
+ case StatementDelegate::CallFunction:
+ return "Qt.quit()";
+ case StatementDelegate::Assign:
+ return QString("%1.visible = %1.visible").arg(rootId);
+ case StatementDelegate::ChangeState:
+ return QString("%1.state = \"\"").arg(rootId);
+ case StatementDelegate::SetProperty:
+ return QString("%1.visible = true").arg(rootId);
+ case StatementDelegate::PrintMessage:
+ return QString("console.log(\"test\")").arg(rootId);
+ case StatementDelegate::Custom:
+ return {};
+ };
+
+ return {};
+}
+
+void ScriptEditorBackend::changeActionType(ActionType actionType)
+{
+ QTC_ASSERT(actionType != StatementDelegate::Custom, return);
+
+ AbstractView *view = m_view;
+
+ QTC_ASSERT(view, return);
+ QTC_ASSERT(view->isAttached(), return);
+
+ view->executeInTransaction("ScriptEditorBackend::removeCondition", [&]() {
+ ScriptEditorStatements::MatchedStatement &okStatement = ScriptEditorStatements::okStatement(
+ m_handler);
+
+ ScriptEditorStatements::MatchedStatement &koStatement = ScriptEditorStatements::koStatement(
+ m_handler);
+
+ koStatement = ScriptEditorStatements::EmptyBlock();
+
+ //We expect a valid id on the root node
+ const QString validId = view->rootModelNode().validId();
+ QString statementSource = generateDefaultStatement(actionType, validId);
+
+ auto tempHandler = ScriptEditorEvaluator::parseStatement(statementSource); //what's that?
+
+ auto newOkStatement = ScriptEditorStatements::okStatement(tempHandler);
+
+ QTC_ASSERT(!ScriptEditorStatements::isEmptyStatement(newOkStatement), return);
+
+ okStatement = newOkStatement;
+
+ QString newSource = ScriptEditorStatements::toJavascript(m_handler);
+
+ setPropertySource(newSource);
+ });
+
+ setSource(getSourceFromProperty(getSourceProperty()));
+
+ setupHandlerAndStatements();
+ setupCondition();
+}
+
+void ScriptEditorBackend::addCondition()
+{
+ ScriptEditorStatements::MatchedStatement okStatement = ScriptEditorStatements::okStatement(
+ m_handler);
+
+ ScriptEditorStatements::MatchedCondition newCondition;
+
+ ScriptEditorStatements::Variable variable;
+ variable.nodeId = defaultCondition;
+ newCondition.statements.append(variable);
+
+ ScriptEditorStatements::ConditionalStatement conditionalStatement;
+
+ conditionalStatement.ok = okStatement;
+ conditionalStatement.condition = newCondition;
+
+ m_handler = conditionalStatement;
+
+ QString newSource = ScriptEditorStatements::toJavascript(m_handler);
+
+ commitNewSource(newSource);
+
+ setupHandlerAndStatements();
+ setupCondition();
+}
+
+void ScriptEditorBackend::removeCondition()
+{
+ ScriptEditorStatements::MatchedStatement okStatement = ScriptEditorStatements::okStatement(
+ m_handler);
+
+ m_handler = okStatement;
+
+ QString newSource = ScriptEditorStatements::toJavascript(m_handler);
+
+ commitNewSource(newSource);
+
+ setupHandlerAndStatements();
+ setupCondition();
+}
+
+void ScriptEditorBackend::addElse()
+{
+ ScriptEditorStatements::MatchedStatement okStatement = ScriptEditorStatements::okStatement(
+ m_handler);
+
+ auto &condition = ScriptEditorStatements::conditionalStatement(m_handler);
+ condition.ko = condition.ok;
+
+ QString newSource = ScriptEditorStatements::toJavascript(m_handler);
+
+ commitNewSource(newSource);
+ setupHandlerAndStatements();
+}
+
+void ScriptEditorBackend::removeElse()
+{
+ ScriptEditorStatements::MatchedStatement okStatement = ScriptEditorStatements::okStatement(
+ m_handler);
+
+ auto &condition = ScriptEditorStatements::conditionalStatement(m_handler);
+ condition.ko = ScriptEditorStatements::EmptyBlock();
+
+ QString newSource = ScriptEditorStatements::toJavascript(m_handler);
+
+ commitNewSource(newSource);
+ setupHandlerAndStatements();
+}
+
+void ScriptEditorBackend::setNewSource(const QString &newSource)
+{
+ setSource(newSource);
+ commitNewSource(newSource);
+ setupHandlerAndStatements();
+ setupCondition();
+}
+
+void ScriptEditorBackend::update()
+{
+ if (m_blockReflection)
+ return;
+
+ m_propertyTreeModel.resetModel();
+ m_propertyListProxyModel.setRowAndInternalId(0, internalRootIndex);
+
+ AbstractView *view = m_view;
+
+ QTC_ASSERT(view, return);
+ if (!view->isAttached())
+ return;
+
+ // setup print message as default action if property does not exists
+ auto sourceProperty = getSourceProperty();
+ if (sourceProperty.exists())
+ setSource(getSourceFromProperty(sourceProperty));
+ else
+ setSource(QStringLiteral("console.log(\"%1\")").arg(sourceProperty.parentModelNode().id()));
+
+ setupHandlerAndStatements();
+
+ setupCondition();
+}
+
+void ScriptEditorBackend::jumpToCode()
+{
+ AbstractView *view = m_view;
+
+ QTC_ASSERT(view, return);
+ QTC_ASSERT(view->isAttached(), return);
+ auto sourceProperty = getSourceProperty();
+
+ ModelNodeOperations::jumpToCode(sourceProperty.parentModelNode());
+}
+
+bool ScriptEditorBackend::blockReflection() const
+{
+ return m_blockReflection;
+}
+
+BindingProperty ScriptEditorBackend::getBindingProperty() const
+{
+ AbstractView *view = m_view;
+
+ QTC_ASSERT(view, return {});
+ QTC_ASSERT(view->isAttached(), return {});
+
+ return SelectionContext{view}.currentSingleSelectedNode().bindingProperty("script");
+}
+
+void ScriptEditorBackend::handleException()
+{
+ QMessageBox::warning(nullptr, tr("Error"), m_exceptionError);
+}
+
+bool ScriptEditorBackend::hasCondition() const
+{
+ return m_hasCondition;
+}
+
+bool ScriptEditorBackend::hasElse() const
+{
+ return m_hasElse;
+}
+
+void ScriptEditorBackend::setHasCondition(bool b)
+{
+ if (b == m_hasCondition)
+ return;
+
+ m_hasCondition = b;
+ emit hasConditionChanged();
+}
+
+void ScriptEditorBackend::setHasElse(bool b)
+{
+ if (b == m_hasElse)
+ return;
+
+ m_hasElse = b;
+ emit hasElseChanged();
+}
+
+ScriptEditorBackend::ActionType ScriptEditorBackend::actionType() const
+{
+ return m_actionType;
+}
+
+AbstractProperty ScriptEditorBackend::getSourceProperty() const
+{
+ return getBindingProperty();
+}
+
+StatementDelegate *ScriptEditorBackend::okStatement()
+{
+ return &m_okStatementDelegate;
+}
+
+StatementDelegate *ScriptEditorBackend::koStatement()
+{
+ return &m_koStatementDelegate;
+}
+
+ConditionListModel *ScriptEditorBackend::conditionListModel()
+{
+ return &m_conditionListModel;
+}
+
+QString ScriptEditorBackend::indentedSource() const
+{
+ if (m_source.isEmpty())
+ return {};
+
+ QTextDocument doc(m_source);
+ IndentingTextEditModifier mod(&doc);
+
+ mod.indent(0, m_source.length() - 1);
+ return mod.text();
+}
+
+QString ScriptEditorBackend::source() const
+{
+ return m_source;
+}
+
+void ScriptEditorBackend::setSource(const QString &source)
+{
+ if (source == m_source)
+ return;
+
+ m_source = source;
+ emit sourceChanged();
+}
+
+PropertyTreeModel *ScriptEditorBackend::propertyTreeModel()
+{
+ return &m_propertyTreeModel;
+}
+
+PropertyListProxyModel *ScriptEditorBackend::propertyListProxyModel()
+{
+ return &m_propertyListProxyModel;
+}
+
+void ScriptEditorBackend::setupCondition()
+{
+ auto &condition = ScriptEditorStatements::matchedCondition(m_handler);
+ m_conditionListModel.setCondition(ScriptEditorStatements::matchedCondition(m_handler));
+ setHasCondition(!condition.statements.isEmpty());
+}
+
+void ScriptEditorBackend::setupHandlerAndStatements()
+{
+ AbstractView *view = m_view;
+ QTC_ASSERT(view, return);
+
+ if (m_source.isEmpty()) {
+ m_actionType = StatementDelegate::Custom;
+ m_handler = ScriptEditorStatements::EmptyBlock();
+ } else {
+ m_handler = ScriptEditorEvaluator::parseStatement(m_source);
+ const QString statementType = QmlDesigner::ScriptEditorStatements::toDisplayName(m_handler);
+ if (statementType == ScriptEditorStatements::EMPTY_DISPLAY_NAME) {
+ m_actionType = StatementDelegate::Custom;
+ } else if (statementType == ScriptEditorStatements::ASSIGNMENT_DISPLAY_NAME) {
+ m_actionType = StatementDelegate::Assign;
+ } else if (statementType == ScriptEditorStatements::SETPROPERTY_DISPLAY_NAME) {
+ m_actionType = StatementDelegate::SetProperty;
+ } else if (statementType == ScriptEditorStatements::FUNCTION_DISPLAY_NAME) {
+ m_actionType = StatementDelegate::CallFunction;
+ } else if (statementType == ScriptEditorStatements::SETSTATE_DISPLAY_NAME) {
+ m_actionType = StatementDelegate::ChangeState;
+ } else if (statementType == ScriptEditorStatements::LOG_DISPLAY_NAME) {
+ m_actionType = StatementDelegate::PrintMessage;
+ } else {
+ m_actionType = StatementDelegate::Custom;
+ }
+ }
+
+ ScriptEditorStatements::MatchedStatement &okStatement = ScriptEditorStatements::okStatement(
+ m_handler);
+ m_okStatementDelegate.setStatement(okStatement);
+ m_okStatementDelegate.setActionType(m_actionType);
+
+ ScriptEditorStatements::MatchedStatement &koStatement = ScriptEditorStatements::koStatement(
+ m_handler);
+
+ if (!ScriptEditorStatements::isEmptyStatement(koStatement)) {
+ m_koStatementDelegate.setStatement(koStatement);
+ m_koStatementDelegate.setActionType(m_actionType);
+ }
+
+ setHasElse(!ScriptEditorStatements::isEmptyStatement(koStatement));
+
+ emit actionTypeChanged();
+}
+
+void ScriptEditorBackend::handleOkStatementChanged()
+{
+ ScriptEditorStatements::MatchedStatement &okStatement = ScriptEditorStatements::okStatement(
+ m_handler);
+
+ okStatement = m_okStatementDelegate.statement(); //TODO why?
+
+ QString newSource = ScriptEditorStatements::toJavascript(m_handler);
+
+ commitNewSource(newSource);
+}
+
+void ScriptEditorBackend::handleKOStatementChanged()
+{
+ ScriptEditorStatements::MatchedStatement &koStatement = ScriptEditorStatements::koStatement(
+ m_handler);
+
+ koStatement = m_koStatementDelegate.statement(); //TODO why?
+
+ QString newSource = ScriptEditorStatements::toJavascript(m_handler);
+
+ commitNewSource(newSource);
+}
+
+void ScriptEditorBackend::handleConditionChanged()
+{
+ AbstractView *view = m_view;
+
+ QTC_ASSERT(view, return);
+ QTC_ASSERT(view->isAttached(), return);
+
+ ScriptEditorStatements::MatchedCondition &condition = ScriptEditorStatements::matchedCondition(
+ m_handler);
+ condition = m_conditionListModel.condition(); //why?
+ QString newSource = ScriptEditorStatements::toJavascript(m_handler);
+
+ commitNewSource(newSource);
+}
+
+void ScriptEditorBackend::setPropertySource(const QString &source)
+{
+ auto property = getSourceProperty();
+
+ QTC_ASSERT(property.isValid(), return);
+
+ if (source.isEmpty())
+ return;
+
+ auto normalizedSource = QmlDesigner::SignalHandlerProperty::normalizedSourceWithBraces(source);
+ if (property.exists())
+ property.toBindingProperty().setExpression(normalizedSource);
+ else
+ property.parentModelNode().bindingProperty(property.name()).setExpression(normalizedSource);
+}
+
+void ScriptEditorBackend::commitNewSource(const QString &source)
+{
+ AbstractView *view = m_view;
+
+ QTC_ASSERT(view, return);
+ QTC_ASSERT(view->isAttached(), return);
+
+ m_blockReflection = true;
+ view->executeInTransaction("ScriptEditorBackend::commitNewSource",
+ [&]() { setPropertySource(source); });
+ setSource(getSourceFromProperty(getSourceProperty()));
+ m_blockReflection = false;
+}
+
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/scripteditor/scripteditorbackend.h b/src/plugins/qmldesigner/components/scripteditor/scripteditorbackend.h
new file mode 100644
index 00000000000..496c4d198a0
--- /dev/null
+++ b/src/plugins/qmldesigner/components/scripteditor/scripteditorbackend.h
@@ -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 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 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 m_view = nullptr;
+};
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectioneditorevaluator.cpp b/src/plugins/qmldesigner/components/scripteditor/scripteditorevaluator.cpp
similarity index 80%
rename from src/plugins/qmldesigner/components/connectioneditor/connectioneditorevaluator.cpp
rename to src/plugins/qmldesigner/components/scripteditor/scripteditorevaluator.cpp
index 7bea5cd2cdd..2f6d8ba6c2f 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/connectioneditorevaluator.cpp
+++ b/src/plugins/qmldesigner/components/scripteditor/scripteditorevaluator.cpp
@@ -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
@@ -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(m_rhs);
+ return std::holds_alternative(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(&m_rhs))
+ if (auto rhs = std::get_if(&m_rhs))
return *rhs;
return {};
}
- ConnectionEditorStatements::Variable variable() const
+ ScriptEditorStatements::Variable variable() const
{
if (!isValid())
return {};
- if (auto rhs = std::get_if(&m_rhs))
+ if (auto rhs = std::get_if(&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,22 +513,23 @@ private:
int m_depth = 0;
QString m_identifier;
QStringList m_fields;
- ConnectionEditorStatements::RightHandSide m_rhs;
+ ScriptEditorStatements::RightHandSide m_rhs;
};
MatchedStatement checkForStateSet(const MatchedStatement ¤tState)
{
- using namespace ConnectionEditorStatements;
- return std::visit(
- Overload{[](const PropertySet &propertySet) -> MatchedStatement {
- if (propertySet.lhs.nodeId.size() && propertySet.lhs.propertyName == u"state"
- && std::holds_alternative(propertySet.rhs))
- return StateSet{propertySet.lhs.nodeId,
- ConnectionEditorStatements::toString(propertySet.rhs)};
- return propertySet;
- },
- [](const auto &pSet) -> MatchedStatement { return pSet; }},
- currentState);
+ using namespace ScriptEditorStatements;
+ return std::visit(Overload{[](const PropertySet &propertySet) -> MatchedStatement {
+ if (propertySet.lhs.nodeId.size()
+ && propertySet.lhs.propertyName == u"state"
+ && std::holds_alternative(propertySet.rhs))
+ return StateSet{propertySet.lhs.nodeId,
+ ScriptEditorStatements::toString(
+ propertySet.rhs)};
+ return propertySet;
+ },
+ [](const auto &pSet) -> MatchedStatement { return pSet; }},
+ currentState);
}
class ConsoleLogEvaluator : public QmlJS::AST::Visitor
@@ -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 m_nodeHierarchy;
- ConnectionEditorStatements::Handler m_handler;
+ ScriptEditorStatements::Handler m_handler;
};
-ConnectionEditorEvaluator::ConnectionEditorEvaluator()
- : d(std::make_unique())
+ScriptEditorEvaluator::ScriptEditorEvaluator()
+ : d(std::make_unique())
{}
-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(
""),
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(
""),
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(&rhs))
+ ScriptEditorStatements::RightHandSide rhs = callVisitor.rhs();
+ if (auto rhs_ = std::get_if(&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);
diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectioneditorevaluator.h b/src/plugins/qmldesigner/components/scripteditor/scripteditorevaluator.h
similarity index 77%
rename from src/plugins/qmldesigner/components/connectioneditor/connectioneditorevaluator.h
rename to src/plugins/qmldesigner/components/scripteditor/scripteditorevaluator.h
index 2cc285ed6c5..33cae4b7e6d 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/connectioneditorevaluator.h
+++ b/src/plugins/qmldesigner/components/scripteditor/scripteditorevaluator.h
@@ -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 d;
+ std::unique_ptr d;
};
} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectioneditorstatements.cpp b/src/plugins/qmldesigner/components/scripteditor/scripteditorstatements.cpp
similarity index 71%
rename from src/plugins/qmldesigner/components/connectioneditor/connectioneditorstatements.cpp
rename to src/plugins/qmldesigner/components/scripteditor/scripteditorstatements.cpp
index 5fbad9acadb..cc8c2872b98 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/connectioneditorstatements.cpp
+++ b/src/plugins/qmldesigner/components/scripteditor/scripteditorstatements.cpp
@@ -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
using namespace QmlDesigner;
-using namespace ConnectionEditorStatements;
+using namespace ScriptEditorStatements;
namespace {
template
@@ -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(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(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(&handler))
+ if (auto *statement = std::get_if(&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(&handler))
+ if (auto *statement = std::get_if(&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(&handler))
+ if (auto *statement = std::get_if(&handler))
return *statement;
return block;
}
-QString ConnectionEditorStatements::toJavascript(const ConditionToken &token)
+QString ScriptEditorStatements::toJavascript(const ConditionToken &token)
{
switch (token) {
case ConditionToken::Not:
diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectioneditorstatements.h b/src/plugins/qmldesigner/components/scripteditor/scripteditorstatements.h
similarity index 77%
rename from src/plugins/qmldesigner/components/connectioneditor/connectioneditorstatements.h
rename to src/plugins/qmldesigner/components/scripteditor/scripteditorstatements.h
index 06e6434b5ab..34f046b117f 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/connectioneditorstatements.h
+++ b/src/plugins/qmldesigner/components/scripteditor/scripteditorstatements.h
@@ -7,22 +7,22 @@
#include
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
diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectioneditorutils.cpp b/src/plugins/qmldesigner/components/scripteditor/scripteditorutils.cpp
similarity index 92%
rename from src/plugins/qmldesigner/components/connectioneditor/connectioneditorutils.cpp
rename to src/plugins/qmldesigner/components/scripteditor/scripteditorutils.cpp
index fcedbc9876c..36c5ed54d7c 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/connectioneditorutils.cpp
+++ b/src/plugins/qmldesigner/components/scripteditor/scripteditorutils.cpp
@@ -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
#include
@@ -8,11 +8,11 @@
#include
#include
#include
+#include
#include
#include
#include
#include
-#include
#include
#include
@@ -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 &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
diff --git a/src/plugins/qmldesigner/components/connectioneditor/connectioneditorutils.h b/src/plugins/qmldesigner/components/scripteditor/scripteditorutils.h
similarity index 93%
rename from src/plugins/qmldesigner/components/connectioneditor/connectioneditorutils.h
rename to src/plugins/qmldesigner/components/scripteditor/scripteditorutils.h
index 220fdc9e11d..9d5d170381c 100644
--- a/src/plugins/qmldesigner/components/connectioneditor/connectioneditorutils.h
+++ b/src/plugins/qmldesigner/components/scripteditor/scripteditorutils.h
@@ -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);