aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenning Gruendl <[email protected]>2025-03-28 13:05:42 +0100
committerThomas Hartmann <[email protected]>2025-03-28 15:05:56 +0000
commit23143191029dc1a029744cff5c34447b947935be (patch)
tree14aff4570f289c1b8f51e2c214871e3ef5f287a9
parent7ccf5bf72026b2a07d904d54f584d823e6a0b66e (diff)
QmlDesigner: Add invalid input notificationqds/v4.7.1
* Add notifications that show the user when invalid was made and automatically reverted by the backend * Rename Design System to Design Tokens * Show warning for cyclic dependencies * Fix invalid binding not being able to reset Change-Id: I6effc9bf47e086dd3007f96c15b083a972ee79b5 Reviewed-by: Henning Gründl <[email protected]>
-rw-r--r--share/qtcreator/qmldesigner/designsystem/Main.qml232
-rw-r--r--share/qtcreator/qmldesigner/designsystem/imports/DesignSystemControls/BindingIndicator.qml4
-rw-r--r--share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ToolTip.qml3
-rw-r--r--src/plugins/qmldesigner/components/designsystemview/designsystemview.cpp4
-rw-r--r--src/plugins/qmldesigner/components/designsystemview/designsystemwidget.cpp2
5 files changed, 223 insertions, 22 deletions
diff --git a/share/qtcreator/qmldesigner/designsystem/Main.qml b/share/qtcreator/qmldesigner/designsystem/Main.qml
index ffcffe81dd0..e499de3d09d 100644
--- a/share/qtcreator/qmldesigner/designsystem/Main.qml
+++ b/share/qtcreator/qmldesigner/designsystem/Main.qml
@@ -81,10 +81,193 @@ Rectangle {
}
function setValue(value: var, row: int, column: int, isBinding: bool): bool {
- console.log("setValue(", value, row, column, isBinding, ")")
- return tableView.model.setData(tableView.index(row, column),
+ //console.log("setValue(", value, row, column, isBinding, ")")
+ let result = tableView.model.setData(tableView.index(row, column),
DesignSystemBackend.dsInterface.createThemeProperty("", value, isBinding),
Qt.EditRole)
+
+ if (!result)
+ overlayInvalid.showData(row, column)
+
+ return result
+ }
+
+ function dismissInvalidOverlay() {
+ overlayInvalid.hide()
+ notification.visible = false
+ }
+
+ Rectangle {
+ id: overlayInvalid
+
+ property Item cellItem
+
+ color: "transparent"
+ border {
+ width: StudioTheme.Values.border
+ color: StudioTheme.Values.themeAmberLight
+ }
+
+ visible: false
+ z: 112
+
+ function show() {
+ //tableView.closeEditor() // Close all currently visible edit delegates
+
+ overlayInvalid.visible = true
+ overlayInvalid.layout()
+ notification.visible = true
+
+ notification.forceActiveFocus()
+ }
+
+ function showData(row: int, column: int) {
+ overlayInvalid.parent = tableView.contentItem
+ overlayInvalid.cellItem = tableView.itemAtCell(Qt.point(column, row))
+
+ notification.message = qsTr("Invalid binding. Please use a valid non-cyclic binding.")
+
+ overlayInvalid.show()
+ }
+
+ function showHeaderData(section: int, orientation: var) {
+ if (orientation === Qt.Horizontal) {
+ overlayInvalid.parent = horizontalHeaderView.contentItem
+ overlayInvalid.cellItem = horizontalHeaderView.itemAtCell(Qt.point(overlay.section, 0))
+ } else {
+ overlayInvalid.parent = verticalHeaderView.contentItem
+ overlayInvalid.cellItem = verticalHeaderView.itemAtCell(Qt.point(0, overlay.section))
+ }
+
+ notification.message = qsTr("This name is already in use, please use a different name.")
+
+ overlayInvalid.show()
+ }
+
+ function hide() {
+ overlayInvalid.visible = false
+ }
+
+ function layout() {
+ if (!overlayInvalid.visible)
+ return
+
+ if (overlayInvalid.cellItem !== null) {
+ overlayInvalid.x = overlayInvalid.cellItem.x + 1
+ overlayInvalid.y = overlayInvalid.cellItem.y + 1
+ overlayInvalid.width = overlayInvalid.cellItem.width - 2
+ overlayInvalid.height = overlayInvalid.cellItem.height - 2
+ }
+ }
+
+ Connections {
+ target: tableView
+
+ function onLayoutChanged() { overlayInvalid.layout() }
+ }
+ }
+
+ Rectangle {
+ id: notification
+
+ property alias message: contentItemText.text
+
+ width: 260
+ height: 78
+ z: 666
+
+ visible: false
+
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ anchors.margins: 20
+
+ color: StudioTheme.Values.themePopoutBackground
+ border.color: "#636363"
+ border.width: StudioTheme.Values.border
+
+ onActiveFocusChanged: {
+ if (!notification.activeFocus)
+ root.dismissInvalidOverlay()
+ }
+
+ Column {
+ id: column
+ anchors.fill: parent
+ anchors.margins: StudioTheme.Values.border
+
+ Item {
+ id: titleBarItem
+ width: parent.width
+ height: StudioTheme.Values.height
+
+ Row {
+ id: row
+ anchors.fill: parent
+ anchors.leftMargin: 8
+ anchors.rightMargin: 4
+ spacing: 4
+
+ Item {
+ id: titleBarContent
+ width: row.width - row.spacing - closeIndicator.width
+ height: row.height
+
+ Row {
+ anchors.fill: parent
+ spacing: 10
+
+ T.Label {
+ anchors.verticalCenter: parent.verticalCenter
+ font.pixelSize: root.customStyle.mediumIconFontSize
+ text: StudioTheme.Constants.warning2_medium
+ font.family: StudioTheme.Constants.iconFont.family
+ color: StudioTheme.Values.themeAmberLight
+ }
+
+ Text {
+ anchors.verticalCenter: parent.verticalCenter
+ text: qsTr("Warning")
+ color: StudioTheme.Values.themeTextColor
+ }
+ }
+ }
+
+ StudioControls.IconIndicator {
+ id: closeIndicator
+ anchors.verticalCenter: parent.verticalCenter
+ icon: StudioTheme.Constants.colorPopupClose
+ pixelSize: StudioTheme.Values.myIconFontSize
+ onClicked: root.dismissInvalidOverlay()
+ }
+ }
+ }
+
+ Item {
+ id: contentItem
+ width: parent.width
+ height: parent.height - titleBarItem.height
+
+ Column {
+ anchors.fill: parent
+ anchors.margins: 8
+ anchors.topMargin: 4
+
+ Item {
+ width: parent.width
+ height: parent.height
+
+ Text {
+ id: contentItemText
+ anchors.fill: parent
+ wrapMode: Text.Wrap
+ elide: Text.ElideRight
+ color: StudioTheme.Values.themeTextColor
+ }
+ }
+ }
+ }
+ }
}
Connections {
@@ -154,7 +337,7 @@ Rectangle {
StudioControls.Dialog {
id: createCollectionDialog
- property alias newCollectionName: createCollectionTextField.text;
+ property alias newCollectionName: createCollectionTextField.text
title: qsTr("Create collection")
width: Math.min(300, root.width)
closePolicy: Popup.CloseOnEscape
@@ -318,7 +501,7 @@ Rectangle {
StudioControls.MenuItem {
text: qsTr("Create collection")
onTriggered: {
- createCollectionDialog.newCollectionName = DesignSystemBackend.dsInterface.generateCollectionName(qsTr("NewCollection"));
+ createCollectionDialog.newCollectionName = DesignSystemBackend.dsInterface.generateCollectionName(qsTr("NewCollection"))
createCollectionDialog.open()
}
}
@@ -338,10 +521,7 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter
buttonIcon: StudioTheme.Constants.updateContent_medium
tooltip: qsTr("Refresh")
- onClicked: {
- DesignSystemBackend.dsInterface.loadDesignSystem()
- //root.loadModel(DesignSystemBackend.dsInterface.collections[0])
- }
+ onClicked: DesignSystemBackend.dsInterface.loadDesignSystem()
}
}
}
@@ -361,6 +541,7 @@ Rectangle {
required property var propertyValue
readonly property bool bindingEditor: cell.isBinding || tableView.model.editableOverride
+ readonly property bool isValid: cell.resolvedValue !== undefined
color: root.backgroundColor
implicitWidth: root.cellWidth
@@ -377,10 +558,13 @@ Rectangle {
HoverHandler { id: cellHoverHandler }
DSC.BindingIndicator {
- icon.text: dataCell.isBinding ? StudioTheme.Constants.actionIconBinding
- : StudioTheme.Constants.actionIcon
- icon.color: dataCell.isBinding ? StudioTheme.Values.themeInteraction
- : StudioTheme.Values.themeTextColor
+ id: bindingIndicator
+ icon.text: !dataCell.isValid ? StudioTheme.Constants.warning2_medium
+ : dataCell.isBinding ? StudioTheme.Constants.actionIconBinding
+ : StudioTheme.Constants.actionIcon
+ icon.color: !dataCell.isValid ? StudioTheme.Values.themeAmberLight
+ : dataCell.isBinding ? StudioTheme.Values.themeInteraction
+ : StudioTheme.Values.themeTextColor
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
@@ -391,9 +575,24 @@ Rectangle {
tableView.closeEditor()
menu.show(dataCell.row, dataCell.column)
}
+
+ onHoverChanged: {
+ if (dataCell.isValid)
+ return
+
+ if (bindingIndicator.hover)
+ toolTipInvalid.showText(dataCell,
+ Qt.point(bindingIndicator.x + bindingIndicator.width,
+ bindingIndicator.y),
+ qsTr("Invalid binding. Cyclic binding is not allowed."))
+ else
+ toolTipInvalid.hideText()
+ }
}
}
+ StudioControls.ToolTipExt { id: toolTipInvalid }
+
DelegateChooser {
id: chooser
role: "group"
@@ -783,7 +982,7 @@ Rectangle {
}
text: qsTr("Reset")
onTriggered: {
- let data = tableView.model.data(menu.modelIndex, CollectionModel.ResolvedValueRole)
+ let data = tableView.model.data(menu.modelIndex, CollectionModel.ResolvedValueRole) ?? ""
var prop = DesignSystemBackend.dsInterface.createThemeProperty("", data, false)
let result = tableView.model.setData(menu.modelIndex, prop, Qt.EditRole)
}
@@ -895,6 +1094,10 @@ Rectangle {
// Revoke active focus from text field by forcing active focus on another item
tableView.forceActiveFocus()
+
+
+ if (!result)
+ overlayInvalid.showHeaderData(overlay.section, overlay.orientation)
}
Text {
@@ -929,8 +1132,7 @@ Rectangle {
}
function show(section, orientation) {
- // Close all currently visible edit delegates
- tableView.closeEditor()
+ tableView.closeEditor() // Close all currently visible edit delegates
if (orientation === Qt.Horizontal)
overlay.parent = horizontalHeaderView.contentItem
diff --git a/share/qtcreator/qmldesigner/designsystem/imports/DesignSystemControls/BindingIndicator.qml b/share/qtcreator/qmldesigner/designsystem/imports/DesignSystemControls/BindingIndicator.qml
index 096b639e246..0ce33472abd 100644
--- a/share/qtcreator/qmldesigner/designsystem/imports/DesignSystemControls/BindingIndicator.qml
+++ b/share/qtcreator/qmldesigner/designsystem/imports/DesignSystemControls/BindingIndicator.qml
@@ -11,7 +11,7 @@ Item {
property StudioTheme.ControlStyle style: StudioTheme.Values.controlStyle
property alias icon: icon
- property bool hover: mouseArea.containsMouse//false
+ property bool hover: mouseArea.containsMouse
property bool pressed: false
property bool forceVisible: false
@@ -19,6 +19,7 @@ Item {
implicitHeight: control.style.actionIndicatorSize.height
signal clicked
+
z: 10
T.Label {
@@ -56,7 +57,6 @@ Item {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
- //onContainsMouseChanged: control.hover = mouseArea.containsMouse
onClicked: control.clicked()
}
}
diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ToolTip.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ToolTip.qml
index b39fb6881ce..8185edaaf6c 100644
--- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ToolTip.qml
+++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/StudioControls/ToolTip.qml
@@ -3,7 +3,7 @@
import QtQuick
import QtQuick.Templates as T
-import StudioTheme 1.0 as StudioTheme
+import StudioTheme as StudioTheme
T.ToolTip {
id: control
@@ -38,4 +38,3 @@ T.ToolTip {
border.color: control.style.toolTip.border
}
}
-
diff --git a/src/plugins/qmldesigner/components/designsystemview/designsystemview.cpp b/src/plugins/qmldesigner/components/designsystemview/designsystemview.cpp
index 77532f284f2..29e8cf49f49 100644
--- a/src/plugins/qmldesigner/components/designsystemview/designsystemview.cpp
+++ b/src/plugins/qmldesigner/components/designsystemview/designsystemview.cpp
@@ -53,8 +53,8 @@ WidgetInfo DesignSystemView::widgetInfo()
return createWidgetInfo(m_designSystemWidget,
"DesignSystemView",
WidgetInfo::RightPane,
- Tr::tr("Design System"),
- Tr::tr("Design System view"),
+ Tr::tr("Design Tokens"),
+ Tr::tr("Design Tokens view"),
DesignerWidgetFlags::IgnoreErrors);
}
diff --git a/src/plugins/qmldesigner/components/designsystemview/designsystemwidget.cpp b/src/plugins/qmldesigner/components/designsystemview/designsystemwidget.cpp
index fe34a8fd0e5..9a70ecfe62b 100644
--- a/src/plugins/qmldesigner/components/designsystemview/designsystemwidget.cpp
+++ b/src/plugins/qmldesigner/components/designsystemview/designsystemwidget.cpp
@@ -62,7 +62,7 @@ DesignSystemWidget::DesignSystemWidget(DesignSystemView *view, DesignSystemInter
Theme::setupTheme(engine());
- setWindowTitle(tr("Design System", "Title of Editor widget"));
+ setWindowTitle(tr("Design Tokens", "Title of Editor widget"));
setMinimumSize(QSize(195, 195));
// init the first load of the QML UI elements