QmlDesigner: Fix QML for bindings/properties

* Ensure a "node" is added to the model if missing, for e.g. Singletons
* Expose targetNode of property

Change-Id: Ifbb131c1d6efaaceb15a6e630ce56023ace63311
Reviewed-by: Henning Gründl <henning.gruendl@qt.io>
Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io>
This commit is contained in:
Thomas Hartmann
2023-09-01 17:29:07 +02:00
parent a2d801ac0e
commit 5907e480a0
7 changed files with 178 additions and 117 deletions

View File

@@ -2,12 +2,38 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick import QtQuick
import StudioTheme 1.0 as StudioTheme
PopupDialog { PopupDialog {
property alias backend: form.backend property alias backend: form.backend
titleBar: Row {
spacing: 30 // TODO
anchors.fill: parent
Text {
color: StudioTheme.Values.themeTextColor
text: qsTr("Owner")
font.pixelSize: StudioTheme.Values.myFontSize
anchors.verticalCenter: parent.verticalCenter
ToolTipArea {
anchors.fill: parent
tooltip: qsTr("The owner of the property")
}
}
Text {
color: StudioTheme.Values.themeTextColor
font.pixelSize: StudioTheme.Values.myFontSize
anchors.verticalCenter: parent.verticalCenter
text: form.backend.targetNode
}
}
BindingsDialogForm { BindingsDialogForm {
id: form id: form
y: 32 y: 32
height: 160
} }
} }

View File

@@ -3,86 +3,71 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import StudioControls import StudioControls as StudioControls
import StudioTheme as StudioTheme
Item { Column {
width: 400 id: root
height: 800
readonly property real horizontalSpacing: 10
readonly property real verticalSpacing: 16
readonly property real columnWidth: (root.width - root.horizontalSpacing) / 2
property var backend property var backend
PopupLabel { y: StudioTheme.Values.popupMargin
x: 10 width: parent.width
y: 25 spacing: root.verticalSpacing
text: qsTr("Target")
Row {
spacing: root.horizontalSpacing
PopupLabel { text: qsTr("From") ; tooltip: qsTr("The Property to assign from.")}
PopupLabel { text: qsTr("To"); tooltip: qsTr("The Property to assign to.") }
} }
PopupLabel { Row {
id: text111 spacing: root.horizontalSpacing
x: 80
y: 25 StudioControls.TopLevelComboBox {
text: backend.targetNode id: sourceNode
font.pixelSize: 15 style: StudioTheme.Values.connectionPopupControlStyle
width: root.columnWidth
model: backend.sourceNode.model ?? []
onModelChanged: sourceNode.currentIndex = sourceNode.currentTypeIndex
onActivated: backend.sourceNode.activateIndex(sourceNode.currentIndex)
property int currentTypeIndex: backend.sourceNode.currentIndex ?? 0
onCurrentTypeIndexChanged: sourceNode.currentIndex = sourceNode.currentTypeIndex
}
PopupLabel {
width: root.columnWidth
text: backend.targetNode
}
} }
TopLevelComboBox { Row {
id: target spacing: root.horizontalSpacing
x: 101
width: 210
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: -335
model: backend.property.model ?? []
enabled: false
//I see no use case to actually change the property name
//onActivated: backend.targetNode.activateIndex(target.currentIndex)
property int currentTypeIndex: backend.property.currentIndex ?? 0
onCurrentTypeIndexChanged: target.currentIndex = target.currentTypeIndex
}
PopupLabel { StudioControls.TopLevelComboBox {
x: 13 id: sourceProperty
y: 111 style: StudioTheme.Values.connectionPopupControlStyle
text: qsTr("Source Propety") width: root.columnWidth
}
TopLevelComboBox { model: backend.sourceProperty.model ?? []
id: sourceNode onModelChanged: sourceProperty.currentIndex = sourceProperty.currentTypeIndex
x: 135 onActivated: backend.sourceProperty.activateIndex(
y: 98 sourceProperty.currentIndex)
width: 156 property int currentTypeIndex: backend.sourceProperty.currentIndex ?? 0
onCurrentTypeIndexChanged: sourceProperty.currentIndex = sourceProperty.currentTypeIndex
}
model: backend.sourceNode.model ?? [] PopupLabel {
width: root.columnWidth
text: backend.property.currentText
}
onModelChanged: sourceNode.currentIndex = sourceNode.currentTypeIndex
onActivated: backend.sourceNode.activateIndex(sourceNode.currentIndex)
property int currentTypeIndex: backend.sourceNode.currentIndex ?? 0
onCurrentTypeIndexChanged: sourceNode.currentIndex = sourceNode.currentTypeIndex
}
PopupLabel {
x: 13
y: 88
text: qsTr("Source Node")
}
TopLevelComboBox {
id: sourceProperty
x: 140
y: 121
width: 156
model: backend.sourceProperty.model ?? []
onModelChanged: sourceProperty.currentIndex = sourceProperty.currentTypeIndex
onActivated: backend.sourceProperty.activateIndex(
sourceProperty.currentIndex)
property int currentTypeIndex: backend.sourceProperty.currentIndex ?? 0
onCurrentTypeIndexChanged: sourceProperty.currentIndex = sourceProperty.currentTypeIndex
}
PopupLabel {
x: 10
y: 55
text: qsTr("Property")
} }
} }

View File

@@ -2,12 +2,38 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick import QtQuick
import StudioTheme 1.0 as StudioTheme
PopupDialog { PopupDialog {
property alias backend: form.backend property alias backend: form.backend
titleBar: Row {
spacing: 30 // TODO
anchors.fill: parent
Text {
color: StudioTheme.Values.themeTextColor
text: qsTr("Owner")
font.pixelSize: StudioTheme.Values.myFontSize
anchors.verticalCenter: parent.verticalCenter
ToolTipArea {
anchors.fill: parent
tooltip: qsTr("The owner of the property")
}
}
Text {
color: StudioTheme.Values.themeTextColor
font.pixelSize: StudioTheme.Values.myFontSize
anchors.verticalCenter: parent.verticalCenter
text: form.backend.targetNode
}
}
PropertiesDialogForm { PropertiesDialogForm {
id: form id: form
y: 32 y: 32
height: 180
} }
} }

View File

@@ -1,68 +1,73 @@
// Copyright (C) 2023 The Qt Company Ltd. // Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick 2.15 import QtQuick
import QtQuick.Controls 2.15 import QtQuick.Controls
import StudioControls as StudioControls
import StudioTheme as StudioTheme
import StudioControls Column {
id: root
Item { readonly property real horizontalSpacing: 10
width: 400 readonly property real verticalSpacing: 16
height: 800 readonly property real columnWidth: (root.width - root.horizontalSpacing) / 2
property var backend property var backend
y: StudioTheme.Values.popupMargin
width: parent.width
spacing: root.verticalSpacing
PopupLabel { PopupLabel {
x: 10 text: qsTr("Type")
y: 25 tooltip: qsTr("The type of the property")
text: qsTr("Type:")
} }
StudioControls.TopLevelComboBox {
id: type
style: StudioTheme.Values.connectionPopupControlStyle
width: root.columnWidth
//width: root.width
TopLevelComboBox {
id: target
x: 95
width: 210
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: -367
model: backend.type.model ?? [] model: backend.type.model ?? []
onActivated: backend.type.activateIndex(target.currentIndex) onActivated: backend.type.activateIndex(type.currentIndex)
property int currentTypeIndex: backend.type.currentIndex ?? 0 property int currentTypeIndex: backend.type.currentIndex ?? 0
onCurrentTypeIndexChanged: target.currentIndex = target.currentTypeIndex onCurrentTypeIndexChanged: type.currentIndex = type.currentTypeIndex
} }
PopupLabel { Row {
x: 10 spacing: root.horizontalSpacing
y: 131
text: qsTr("Name") PopupLabel { text: qsTr("Name") ; tooltip: qsTr("The name of the property.")}
PopupLabel { text: qsTr("Value"); tooltip: qsTr("The value of the property.") }
} }
TextInput { Row {
id: name spacing: root.horizontalSpacing
x: 70 StudioControls.TextField {
y: 131 id: name
width: 156
text: backend.name.text ?? "" width: root.columnWidth
onEditingFinished: { actionIndicatorVisible: false
backend.name.activateText(name.text) translationIndicatorVisible: false
text: backend.name.text ?? ""
onEditingFinished: {
backend.name.activateText(name.text)
}
} }
} StudioControls.TextField {
id: value
PopupLabel { width: root.columnWidth
x: 10 actionIndicatorVisible: false
y: 81 translationIndicatorVisible: false
text: qsTr("Value")
}
TextInput {
id: value text: backend.value.text ?? ""
x: 70 onEditingFinished: {
y: 81 backend.value.activateText(value.text)
width: 156 }
text: backend.value.text ?? ""
onEditingFinished: {
backend.value.activateText(value.text)
} }
} }
} }

View File

@@ -553,12 +553,16 @@ void BindingModelBackendDelegate::setCurrentRow(int i)
} }
std::sort(sourceNodes.begin(), sourceNodes.end()); std::sort(sourceNodes.begin(), sourceNodes.end());
m_sourceNode.setModel(sourceNodes);
QString sourceNodeName; QString sourceNodeName;
QString sourcePropertyName; QString sourcePropertyName;
model->getExpressionStrings(bindingProperty, &sourceNodeName, &sourcePropertyName); model->getExpressionStrings(bindingProperty, &sourceNodeName, &sourcePropertyName);
if (!sourceNodes.contains(sourceNodeName))
sourceNodes.append(sourceNodeName);
m_sourceNode.setModel(sourceNodes);
m_sourceNode.setCurrentText(sourceNodeName); m_sourceNode.setCurrentText(sourceNodeName);
m_sourceNodeProperty.setModel(model->possibleSourceProperties(bindingProperty)); m_sourceNodeProperty.setModel(model->possibleSourceProperties(bindingProperty));

View File

@@ -1022,6 +1022,10 @@ void DynamicPropertiesModelBackendDelegate::setCurrentRow(int i)
m_value.setText(property.toVariantProperty().value().toString()); m_value.setText(property.toVariantProperty().value().toString());
else if (property.isBindingProperty()) else if (property.isBindingProperty())
m_value.setText(property.toBindingProperty().expression()); m_value.setText(property.toBindingProperty().expression());
m_targetNode = property.parentModelNode().id();
emit targetNodeChanged();
} }
void DynamicPropertiesModelBackendDelegate::handleTypeChanged() void DynamicPropertiesModelBackendDelegate::handleTypeChanged()
@@ -1077,9 +1081,10 @@ void DynamicPropertiesModelBackendDelegate::handleNameChanged()
const QString expression = bindingProperty.expression(); const QString expression = bindingProperty.expression();
const PropertyName dynamicPropertyType = bindingProperty.dynamicTypeName(); const PropertyName dynamicPropertyType = bindingProperty.dynamicTypeName();
targetNode.removeProperty(bindingProperty.name());
targetNode.bindingProperty(newName).setDynamicTypeNameAndExpression(dynamicPropertyType, targetNode.bindingProperty(newName).setDynamicTypeNameAndExpression(dynamicPropertyType,
expression); expression);
targetNode.removeProperty(bindingProperty.name());
}); });
return; return;
@@ -1093,9 +1098,10 @@ void DynamicPropertiesModelBackendDelegate::handleNameChanged()
ModelNode targetNode = variantProperty.parentModelNode(); ModelNode targetNode = variantProperty.parentModelNode();
model->view()->executeInTransaction(__FUNCTION__, [=]() { model->view()->executeInTransaction(__FUNCTION__, [=]() {
targetNode.removeProperty(variantProperty.name());
targetNode.variantProperty(newName).setDynamicTypeNameAndValue(dynamicPropertyType, targetNode.variantProperty(newName).setDynamicTypeNameAndValue(dynamicPropertyType,
value); value);
targetNode.removeProperty(variantProperty.name());
}); });
} }
@@ -1167,6 +1173,11 @@ QVariant DynamicPropertiesModelBackendDelegate::variantValue() const
return m_value.text(); return m_value.text();
} }
QString DynamicPropertiesModelBackendDelegate::targetNode() const
{
return m_targetNode;
}
StudioQmlComboBoxBackend *DynamicPropertiesModelBackendDelegate::type() StudioQmlComboBoxBackend *DynamicPropertiesModelBackendDelegate::type()
{ {
return &m_type; return &m_type;

View File

@@ -135,6 +135,7 @@ class DynamicPropertiesModelBackendDelegate : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QString targetNode READ targetNode NOTIFY targetNodeChanged)
Q_PROPERTY(StudioQmlComboBoxBackend *type READ type CONSTANT) Q_PROPERTY(StudioQmlComboBoxBackend *type READ type CONSTANT)
Q_PROPERTY(int currentRow READ currentRow WRITE setCurrentRow NOTIFY currentRowChanged) Q_PROPERTY(int currentRow READ currentRow WRITE setCurrentRow NOTIFY currentRowChanged)
Q_PROPERTY(StudioQmlTextBackend *name READ name CONSTANT) Q_PROPERTY(StudioQmlTextBackend *name READ name CONSTANT)
@@ -148,6 +149,7 @@ signals:
void currentRowChanged(); void currentRowChanged();
void nameChanged(); void nameChanged();
void valueChanged(); void valueChanged();
void targetNodeChanged();
private: private:
int currentRow() const; int currentRow() const;
@@ -157,6 +159,7 @@ private:
void handleValueChanged(); void handleValueChanged();
void handleException(); void handleException();
QVariant variantValue() const; QVariant variantValue() const;
QString targetNode() const;
StudioQmlComboBoxBackend *type(); StudioQmlComboBoxBackend *type();
@@ -168,6 +171,7 @@ private:
StudioQmlTextBackend m_value; StudioQmlTextBackend m_value;
int m_currentRow = -1; int m_currentRow = -1;
QString m_exceptionError; QString m_exceptionError;
QString m_targetNode;
}; };
} // namespace QmlDesigner } // namespace QmlDesigner