QmlDesigner: Update ConnectionModel

Change-Id: I5be9117284a5eae2437b0a4fc9452694098713f3
Reviewed-by: Henning Gründl <henning.gruendl@qt.io>
This commit is contained in:
Thomas Hartmann
2023-08-29 18:10:37 +02:00
parent 0af20575c1
commit 34cef91983
10 changed files with 1760 additions and 86 deletions

View File

@@ -6,6 +6,9 @@ import StudioControls 1.0 as StudioControls
import StudioTheme 1.0 as StudioTheme
PopupDialog {
property alias backend: form.backend
titleBar: Row {
spacing: 30 // TODO
anchors.fill: parent
@@ -22,9 +25,16 @@ PopupDialog {
style: StudioTheme.Values.connectionPopupControlStyle
width: 180
anchors.verticalCenter: parent.verticalCenter
model: ["mySpinbox", "foo", "backendObject"]
}
model: backend.signal.id.model ?? 0
onActivated: backend.signal.id.activateIndex(target.currentIndex)
property int currentTypeIndex: backend.signal.id.currentIndex ?? 0
onCurrentTypeIndexChanged: target.currentIndex = target.currentTypeIndex
}
ConnectionsDialogForm {}
}
ConnectionsDialogForm {
id: form
}
}

View File

@@ -14,12 +14,15 @@ Column {
readonly property real verticalSpacing: 16
readonly property real columnWidth: (root.width - root.horizontalSpacing) / 2
property var backend
component PopupLabel : Text {
width: root.columnWidth
color: StudioTheme.Values.themeTextColor
font.pixelSize: StudioTheme.Values.myFontSize
}
/* replaced by ConnectionModelStatementDelegate defined in C++
enum ActionType {
CallFunction,
Assign,
@@ -27,7 +30,7 @@ Column {
SetProperty,
PrintMessage,
Custom
}
} */
y: StudioTheme.Values.popupMargin
width: parent.width
@@ -47,7 +50,12 @@ Column {
id: signal
style: StudioTheme.Values.connectionPopupControlStyle
width: root.columnWidth
model: ["Clicked", "Pressed", "Released"]
model: backend.signal.name.model ?? 0
onActivated: backend.signal.name.activateIndex(signal.currentIndex)
property int currentTypeIndex: backend.signal.name.currentIndex ?? 0
onCurrentTypeIndexChanged: signal.currentIndex = signal.currentTypeIndex
}
StudioControls.TopLevelComboBox {
@@ -56,21 +64,25 @@ Column {
width: root.columnWidth
textRole: "text"
valueRole: "value"
///model.getData(currentIndex, "role")
property int indexFromBackend: indexOfValue(backend.actionType)
onIndexFromBackendChanged: action.currentIndex = action.indexFromBackend
onActivated: backend.changeActionType(action.currentValue)
model: [
{ value: ConnectionsDialogForm.CallFunction, text: qsTr("Call Function") },
{ value: ConnectionsDialogForm.Assign, text: qsTr("Assign") },
{ value: ConnectionsDialogForm.ChangeState, text: qsTr("Change State") },
{ value: ConnectionsDialogForm.SetProperty, text: qsTr("Set Property") },
{ value: ConnectionsDialogForm.PrintMessage, text: qsTr("Print Message") },
{ value: ConnectionsDialogForm.Custom, text: qsTr("Custom") }
{ value: ConnectionModelStatementDelegate.CallFunction, text: qsTr("Call Function") },
{ value: ConnectionModelStatementDelegate.Assign, text: qsTr("Assign") },
{ value: ConnectionModelStatementDelegate.ChangeState, text: qsTr("Change State") },
{ value: ConnectionModelStatementDelegate.SetProperty, text: qsTr("Set Property") },
{ value: ConnectionModelStatementDelegate.PrintMessage, text: qsTr("Print Message") },
{ value: ConnectionModelStatementDelegate.Custom, text: qsTr("Custom") }
]
}
}
// Call Function
Row {
visible: action.currentValue === ConnectionsDialogForm.CallFunction
visible: action.currentValue === ConnectionModelStatementDelegate.CallFunction
spacing: root.horizontalSpacing
PopupLabel { text: qsTr("Item") }
@@ -78,25 +90,36 @@ Column {
}
Row {
visible: action.currentValue === ConnectionsDialogForm.CallFunction
visible: action.currentValue === ConnectionModelStatementDelegate.CallFunction
spacing: root.horizontalSpacing
StudioControls.TopLevelComboBox {
id: functionId
style: StudioTheme.Values.connectionPopupControlStyle
width: root.columnWidth
model: ["mySpinBox", "myAnimation", "myCustomComponent"]
model: backend.okStatement.function.id.model ?? 0
onActivated: backend.okStatement.function.id.activateIndex(functionId.currentIndex)
property int currentTypeIndex: backend.okStatement.function.id.currentIndex ?? 0
onCurrentTypeIndexChanged: functionId.currentIndex = functionId.currentTypeIndex
}
StudioControls.TopLevelComboBox {
id: functionName
style: StudioTheme.Values.connectionPopupControlStyle
width: root.columnWidth
model: ["start", "stop", "reset"]
model: backend.okStatement.function.name.model ?? 0
onActivated: backend.okStatement.function.name.activateIndex(functionName.currentIndex)
property int currentTypeIndex: backend.okStatement.function.name.currentIndex ?? 0
onCurrentTypeIndexChanged: functionName.currentIndex = functionName.currentTypeIndex
}
}
// Assign
Row {
visible: action.currentValue === ConnectionsDialogForm.Assign
visible: action.currentValue === ConnectionModelStatementDelegate.Assign
spacing: root.horizontalSpacing
PopupLabel { text: qsTr("From") }
@@ -104,25 +127,68 @@ Column {
}
Row {
visible: action.currentValue === ConnectionsDialogForm.Assign
visible: action.currentValue === ConnectionModelStatementDelegate.Assign
spacing: root.horizontalSpacing
StudioControls.TopLevelComboBox {
id: rhsAssignmentId
style: StudioTheme.Values.connectionPopupControlStyle
width: root.columnWidth
model: ["value", "foo", "bar"]
//from - rhs - id
model: backend.okStatement.rhsAssignment.id.model ?? 0
onActivated: backend.okStatement.rhsAssignment.id.activateIndex(rhsAssignmentId.currentIndex)
property int currentTypeIndex: backend.okStatement.rhsAssignment.id.currentIndex ?? 0
onCurrentTypeIndexChanged: rhsAssignmentId.currentIndex = rhsAssignmentId.currentTypeIndex
}
StudioControls.TopLevelComboBox {
id: lhsAssignmentId
style: StudioTheme.Values.connectionPopupControlStyle
width: root.columnWidth
model: ["myValue", "yourValue", "ourValue"]
//to lhs - id
model: backend.okStatement.lhs.id.model ?? 0
onActivated: backend.okStatement.lhs.id.activateIndex(lhsAssignmentId.currentIndex)
property int currentTypeIndex: backend.okStatement.lhs.id.currentIndex ?? 0
onCurrentTypeIndexChanged: lhsAssignmentId.currentIndex = lhsAssignmentId.currentTypeIndex
}
}
Row {
visible: action.currentValue === ConnectionModelStatementDelegate.Assign
spacing: root.horizontalSpacing
StudioControls.TopLevelComboBox {
id: rhsAssignmentName
style: StudioTheme.Values.connectionPopupControlStyle
width: root.columnWidth
//from - rhs - name
model: backend.okStatement.rhsAssignment.name.model ?? 0
onActivated: backend.okStatement.rhsAssignment.name.activateIndex(rhsAssignmentName.currentIndex)
property int currentTypeIndex: backend.okStatement.rhsAssignment.name.currentIndex ?? 0
onCurrentTypeIndexChanged: rhsAssignmentName.currentIndex = rhsAssignmentName.currentTypeIndex
}
StudioControls.TopLevelComboBox {
id: lhsAssignmentName
style: StudioTheme.Values.connectionPopupControlStyle
width: root.columnWidth
//to lhs - name
model: backend.okStatement.lhs.name.model ?? 0
onActivated: backend.okStatement.lhs.name.activateIndex(lhsAssignmentName.currentIndex)
property int currentTypeIndex: backend.okStatement.lhs.name.currentIndex ?? 0
onCurrentTypeIndexChanged: lhsAssignmentName.currentIndex = lhsAssignmentName.currentTypeIndex
}
}
// Change State
Row {
visible: action.currentValue === ConnectionsDialogForm.ChangeState
visible: action.currentValue === ConnectionModelStatementDelegate.ChangeState
spacing: root.horizontalSpacing
PopupLabel { text: qsTr("State Group") }
@@ -130,25 +196,36 @@ Column {
}
Row {
visible: action.currentValue === ConnectionsDialogForm.ChangeState
visible: action.currentValue === ConnectionModelStatementDelegate.ChangeState
spacing: root.horizontalSpacing
StudioControls.TopLevelComboBox {
id: stateGroups
style: StudioTheme.Values.connectionPopupControlStyle
width: root.columnWidth
model: ["main", "group1", "group2"]
model: backend.okStatement.stateTargets.model ?? 0
onActivated: backend.okStatement.stateTargets.activateIndex(stateGroups.currentIndex)
property int currentTypeIndex: backend.okStatement.stateTargets.currentIndex ?? 0
onCurrentTypeIndexChanged: stateGroups.currentIndex = stateGroups.currentTypeIndex
}
StudioControls.TopLevelComboBox {
id: states
style: StudioTheme.Values.connectionPopupControlStyle
width: root.columnWidth
model: ["state1", "state2", "state3", "state4"]
model: backend.okStatement.states.model ?? 0
onActivated: backend.okStatement.states.activateIndex(states.currentIndex)
property int currentTypeIndex: backend.okStatement.states.currentIndex ?? 0
onCurrentTypeIndexChanged: states.currentIndex = states.currentTypeIndex
}
}
// Set Property
Row {
visible: action.currentValue === ConnectionsDialogForm.SetProperty
visible: action.currentValue === ConnectionModelStatementDelegate.SetProperty
spacing: root.horizontalSpacing
PopupLabel { text: qsTr("Item") }
@@ -156,52 +233,73 @@ Column {
}
Row {
visible: action.currentValue === ConnectionsDialogForm.SetProperty
visible: action.currentValue === ConnectionModelStatementDelegate.SetProperty
spacing: root.horizontalSpacing
StudioControls.TopLevelComboBox {
id: lhsPropertyId
style: StudioTheme.Values.connectionPopupControlStyle
width: root.columnWidth
model: ["value", "foo", "bar"]
model: backend.okStatement.lhs.id.model ?? 0
onActivated: backend.okStatement.lhs.id.activateIndex(lhsPropertyId.currentIndex)
property int currentTypeIndex: backend.okStatement.lhs.id.currentIndex ?? 0
onCurrentTypeIndexChanged: lhsPropertyId.currentIndex = lhsPropertyId.currentTypeIndex
}
StudioControls.TopLevelComboBox {
id: lhsPropertyName
style: StudioTheme.Values.connectionPopupControlStyle
width: root.columnWidth
model: ["myValue", "yourValue", "ourValue"]
model: backend.okStatement.lhs.name.model ?? 0
onActivated: backend.okStatement.lhs.name.activateIndex(lhsPropertyName.currentIndex)
property int currentTypeIndex: backend.okStatement.lhs.name.currentIndex ?? 0
onCurrentTypeIndexChanged: lhsPropertyName.currentIndex = lhsPropertyName.currentTypeIndex
}
}
PopupLabel {
visible: action.currentValue === ConnectionsDialogForm.SetProperty
visible: action.currentValue === ConnectionModelStatementDelegate.SetProperty
text: qsTr("Value")
}
StudioControls.TextField {
visible: action.currentValue === ConnectionsDialogForm.SetProperty
id: setPropertyArgument
visible: action.currentValue === ConnectionModelStatementDelegate.SetProperty
width: root.width
text: "This is a test"
actionIndicatorVisible: false
translationIndicatorVisible: false
text: backend.okStatement.stringArgument.text ?? ""
onEditingFinished: {
backend.okStatement.stringArgument.activateText(setPropertyArgument.text)
}
}
// Print Message
PopupLabel {
visible: action.currentValue === ConnectionsDialogForm.PrintMessage
visible: action.currentValue === ConnectionModelStatementDelegate.PrintMessage
text: qsTr("Message")
}
StudioControls.TextField {
visible: action.currentValue === ConnectionsDialogForm.PrintMessage
id: messageString
visible: action.currentValue === ConnectionModelStatementDelegate.PrintMessage
width: root.width
text: "my value is"
actionIndicatorVisible: false
translationIndicatorVisible: false
text: backend.okStatement.stringArgument.text ?? ""
onEditingFinished: {
backend.okStatement.stringArgument.activateText(messageString.text)
}
}
// Custom
PopupLabel {
visible: action.currentValue === ConnectionsDialogForm.Custom
visible: action.currentValue === ConnectionModelStatementDelegate.Custom
text: qsTr("Custom Connections can only be edited with the binding editor")
anchors.left: parent.left
anchors.right: parent.right
@@ -217,9 +315,60 @@ Column {
iconSize: StudioTheme.Values.baseFontSize
iconFont: StudioTheme.Constants.font
anchors.horizontalCenter: parent.horizontalCenter
visible: action.currentValue !== ConnectionsDialogForm.Custom
visible: action.currentValue !== ConnectionModelStatementDelegate.Custom && !backend.hasCondition
onClicked: console.log("ADD CONDITION")
onClicked: backend.addCondition()
}
HelperWidgets.AbstractButton {
style: StudioTheme.Values.connectionPopupButtonStyle
width: 160
buttonIcon: qsTr("Remove Condition")
iconSize: StudioTheme.Values.baseFontSize
iconFont: StudioTheme.Constants.font
anchors.horizontalCenter: parent.horizontalCenter
visible: action.currentValue !== ConnectionModelStatementDelegate.Custom && backend.hasCondition
onClicked: backend.removeCondition()
}
Flow {
spacing: root.horizontalSpacing
width: root.width
Repeater {
model: backend.conditionListModel
Text {
text: value
color: "white"
Rectangle {
z: -1
opacity: 0.2
color: {
if (type === ConditionListModel.Invalid)
return "red"
if (type === ConditionListModel.Operator)
return "blue"
if (type === ConditionListModel.Literal)
return "green"
if (type === ConditionListModel.Variable)
return "yellow"
}
anchors.fill: parent
}
}
}
}
TextInput {
id: commandInput
width: root.width
onAccepted: backend.conditionListModel.command(commandInput.text)
}
Text {
text: "invalid " + backend.conditionListModel.error
visible: !backend.conditionListModel.valid
}
// Editor
@@ -231,7 +380,7 @@ Column {
Text {
anchors.centerIn: parent
text: "backend.myValue = mySpinbox.value"
text: backend.source
color: StudioTheme.Values.themeTextColor
font.pixelSize: StudioTheme.Values.myFontSize
}

View File

@@ -38,12 +38,14 @@ ListView {
onCurrentIndexChanged: {
root.currentIndex = root.model.currentIndex
dialog.backend.currentRow = root.currentIndex
}
data: [
ConnectionsDialog {
id: dialog
visible: false
backend: root.model.delegate
}
]
@@ -79,6 +81,8 @@ ListView {
onClicked: {
root.model.currentIndex = index
root.currentIndex = index
dialog.backend.currentRow = index
dialog.popup(mouseArea)
}
}

View File

@@ -187,29 +187,7 @@ struct JSOverload
return "console.log(" + std::visit(JSOverload{}, consoleLog.argument) + ")";
}
QString operator()(const ConditionToken &token)
{
switch (token) {
case ConditionToken::Not:
return "!==";
case ConditionToken::And:
return "&&";
case ConditionToken::Or:
return "||";
case ConditionToken::LargerThan:
return ">";
case ConditionToken::LargerEqualsThan:
return ">=";
case ConditionToken::SmallerThan:
return "<";
case ConditionToken::SmallerEqualsThan:
return "<=";
case ConditionToken::Equals:
return "===";
default:
return {};
};
}
QString operator()(const ConditionToken &token) { return toJavascript(token); }
QString operator()(const ConnectionEditorStatements::MatchedCondition &matched)
{
@@ -236,7 +214,7 @@ struct JSOverload
if (isEmptyStatement(statement))
return {};
return std::visit(JSOverload{}, statement) + ";\n";
return std::visit(JSOverload{}, statement);
}
QString operator()(const ConnectionEditorStatements::ConditionalStatement &conditional)
@@ -334,20 +312,60 @@ QString ConnectionEditorStatements::toDisplayName(const Handler &handler)
return toDisplayName(statement);
}
MatchedStatement ConnectionEditorStatements::okStatement(const ConnectionEditorStatements::Handler &handler)
MatchedStatement &ConnectionEditorStatements::okStatement(
ConnectionEditorStatements::Handler &handler)
{
return std::visit(Overload{[](const ConnectionEditorStatements::MatchedStatement &var) { return var; },
[](const ConnectionEditorStatements::ConditionalStatement &statement) {
return statement.ok;
}},
MatchedStatement statement;
std::visit([statement](auto &test) { return statement; }, handler);
return std::visit(Overload{[](ConnectionEditorStatements::MatchedStatement &var)
-> MatchedStatement & { return var; },
[](ConnectionEditorStatements::ConditionalStatement &statement)
-> MatchedStatement & { return statement.ok; }},
handler);
}
MatchedStatement ConnectionEditorStatements::koStatement(const ConnectionEditorStatements::Handler &handler)
MatchedStatement &ConnectionEditorStatements::koStatement(
ConnectionEditorStatements::Handler &handler)
{
return std::visit(Overload{[](const ConnectionEditorStatements::ConditionalStatement &statement) {
return statement.ko;
},
[](const auto &) -> ConnectionEditorStatements::MatchedStatement { return {}; }},
handler);
static MatchedStatement block;
if (auto *statement = std::get_if<ConnectionEditorStatements::ConditionalStatement>(&handler))
return statement->ko;
return block;
}
MatchedCondition &ConnectionEditorStatements::matchedCondition(Handler &handler)
{
static MatchedCondition block;
if (auto *statement = std::get_if<ConnectionEditorStatements::ConditionalStatement>(&handler))
return statement->condition;
return block;
}
QString ConnectionEditorStatements::toJavascript(const ConditionToken &token)
{
switch (token) {
case ConditionToken::Not:
return "!==";
case ConditionToken::And:
return "&&";
case ConditionToken::Or:
return "||";
case ConditionToken::LargerThan:
return ">";
case ConditionToken::LargerEqualsThan:
return ">=";
case ConditionToken::SmallerThan:
return "<";
case ConditionToken::SmallerEqualsThan:
return "<=";
case ConditionToken::Equals:
return "===";
default:
return {};
};
}

View File

@@ -115,9 +115,12 @@ QMLDESIGNER_EXPORT QString toString(const Handler &handler);
QMLDESIGNER_EXPORT QString toJavascript(const Handler &handler);
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(const ConnectionEditorStatements::Handler &handler);
QMLDESIGNER_EXPORT MatchedStatement koStatement(const ConnectionEditorStatements::Handler &handler);
QMLDESIGNER_EXPORT MatchedStatement &okStatement(ConnectionEditorStatements::Handler &handler);
QMLDESIGNER_EXPORT MatchedStatement &koStatement(ConnectionEditorStatements::Handler &handler);
QMLDESIGNER_EXPORT MatchedCondition &matchedCondition(ConnectionEditorStatements::Handler &handler);
} // namespace ConnectionEditorStatements

View File

@@ -3,6 +3,11 @@
#pragma once
#include <connectioneditorstatements.h>
#include <propertytreemodel.h>
#include <studioquickwidget.h>
#include <QAbstractListModel>
#include <QStandardItemModel>
namespace QmlDesigner {
@@ -14,10 +19,14 @@ class SignalHandlerProperty;
class VariantProperty;
class ConnectionView;
class ConnectionModelBackendDelegate;
class ConnectionModel : public QStandardItemModel
{
Q_OBJECT
Q_PROPERTY(ConnectionModelBackendDelegate *delegate READ delegate CONSTANT)
public:
enum ColumnRoles {
TargetModelNodeRow = 0,
@@ -71,11 +80,217 @@ protected:
private:
void handleDataChanged(const QModelIndex &topLeft, const QModelIndex& bottomRight);
void handleException();
ConnectionModelBackendDelegate *delegate() const;
private:
ConnectionView *m_connectionView;
bool m_lock = false;
QString m_exceptionError;
ConnectionModelBackendDelegate *m_delegate = nullptr;
};
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)
public:
enum ConditionType { Invalid, Operator, Literal, Variable };
Q_ENUM(ConditionType)
struct ConditionToken
{
ConditionType type;
QString value;
};
ConditionListModel(ConnectionModel *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QHash<int, QByteArray> roleNames() const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
void setup();
void setCondition(ConnectionEditorStatements::MatchedCondition &condition);
ConnectionEditorStatements::MatchedCondition &condition();
static ConditionToken tokenFromConditionToken(
const ConnectionEditorStatements::ConditionToken &token);
static ConditionToken tokenFromComparativeStatement(
const ConnectionEditorStatements::ComparativeStatement &token);
Q_INVOKABLE void insertToken(int index, const QString &value);
Q_INVOKABLE void updateToken(int index, const QString &value);
Q_INVOKABLE void appendToken(const QString &value);
Q_INVOKABLE void removeToken(int index);
bool valid() const;
bool empty() const;
//for debugging
Q_INVOKABLE void command(const QString &string);
void setInvalid(const QString &errorMessage);
void setValid();
QString error() const;
signals:
void validChanged();
void emptyChanged();
void conditionChanged();
void errorChanged();
private:
void internalSetup();
ConditionToken valueToToken(const QString &value);
void resetModel();
int checkOrder() const;
void validateAndRebuildTokens();
void rebuildTokens();
ConnectionEditorStatements::ConditionToken toOperatorStatement(const ConditionToken &token);
ConnectionEditorStatements::ComparativeStatement toStatement(const ConditionToken &token);
ConnectionModel *m_connectionModel = nullptr;
ConnectionEditorStatements::MatchedCondition &m_condition;
QList<ConditionToken> m_tokens;
bool m_valid = false;
QString m_errorMessage;
};
class ConnectionModelStatementDelegate : public QObject
{
Q_OBJECT
public:
explicit ConnectionModelStatementDelegate(ConnectionModel *parent = nullptr);
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();
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(QString source READ source NOTIFY sourceChanged)
public:
explicit ConnectionModelBackendDelegate(ConnectionModel *parent = nullptr);
using ActionType = ConnectionModelStatementDelegate::ActionType;
Q_INVOKABLE void changeActionType(
QmlDesigner::ConnectionModelStatementDelegate::ActionType actionType);
Q_INVOKABLE void addCondition();
Q_INVOKABLE void removeCondition();
signals:
void currentRowChanged();
void actionTypeChanged();
void hasConditionChanged();
void sourceChanged();
private:
int currentRow() const;
void setCurrentRow(int i);
void handleException();
bool hasCondition() const;
void setHasCondition(bool b);
ActionType actionType() const;
PropertyTreeModelDelegate *signal();
ConnectionModelStatementDelegate *okStatement();
ConnectionModelStatementDelegate *koStatement();
ConditionListModel *conditionListModel();
QString source() const;
void setSource(const QString &source);
void setupCondition();
void setupHandlerAndStatements();
void handleTargetChanged();
void handleOkStatementChanged();
void handleConditionChanged();
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;
QString m_source;
};
} // namespace QmlDesigner

View File

@@ -8,6 +8,7 @@
#include "bindingmodel.h"
#include "connectionmodel.h"
#include "dynamicpropertiesmodel.h"
#include "propertytreemodel.h"
#include "theme.h"
#include <bindingproperty.h>
@@ -73,6 +74,21 @@ public:
{"dynamicPropertiesModel",
QVariant::fromValue(m_connectionEditorView->dynamicPropertiesModel())}});
qmlRegisterType<ConnectionModelBackendDelegate>("ConnectionsEditorEditorBackend",
1,
0,
"DynamicPropertiesModelBackendDelegate");
qmlRegisterType<ConnectionModelStatementDelegate>("ConnectionsEditorEditorBackend",
1,
0,
"ConnectionModelStatementDelegate");
qmlRegisterType<ConditionListModel>("ConnectionsEditorEditorBackend",
1,
0,
"ConditionListModel");
Theme::setupTheme(engine());
setMinimumWidth(195);

View File

@@ -21,6 +21,8 @@ class ConnectionModel;
class DynamicPropertiesModel;
class BackendModel;
class ConnectionViewQuickWidget;
class PropertyTreeModel;
class PropertyListProxyModel;
class ConnectionView : public AbstractView
{
@@ -88,6 +90,8 @@ private: //variables
BindingModel *m_bindingModel;
DynamicPropertiesModel *m_dynamicPropertiesModel;
BackendModel *m_backendModel;
PropertyTreeModel *m_propertyTreeModel;
PropertyListProxyModel *m_propertyListProxyModel;
int m_currentIndex = 0;
QPointer<ConnectionViewQuickWidget> m_connectionViewQuickWidget;

View File

@@ -106,10 +106,10 @@ private:
class QMLDESIGNERCORE_EXPORT QmlModelStateGroup
{
friend class QmlObjectNode;
friend class StatesEditorView;
public:
QmlModelStateGroup() = default;
QmlModelStateGroup(const ModelNode &modelNode) : m_modelNode(modelNode) {}
explicit operator bool() const { return m_modelNode.isValid(); }
@@ -120,9 +120,6 @@ public:
QmlModelState addState(const QString &name);
void removeState(const QString &name);
protected:
QmlModelStateGroup(const ModelNode &modelNode) : m_modelNode(modelNode) {}
private:
ModelNode m_modelNode;
};