QmlDesigner: Close the color editor popup before adding

Fixes: QDS-12498
Change-Id: Id3c565ffb9fca7f186ebeb0cf8051194c7944d4d
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io>
This commit is contained in:
Ali Kianian
2024-05-15 16:48:28 +03:00
parent 92120273b1
commit 51a27f3a12
2 changed files with 173 additions and 238 deletions

View File

@@ -90,7 +90,7 @@ Rectangle {
property int order: Qt.AscendingOrder property int order: Qt.AscendingOrder
onClicked: { onClicked: {
order = (order == Qt.AscendingOrder) ? Qt.DescendingOrder : Qt.AscendingOrder; order = (order == Qt.AscendingOrder) ? Qt.DescendingOrder : Qt.AscendingOrder;
tableView.closeEditor() tableView.closeEditors()
tableView.model.sort(-1, order) tableView.model.sort(-1, order)
} }
} }
@@ -173,7 +173,7 @@ Rectangle {
StudioControls.MenuItem { StudioControls.MenuItem {
text: qsTr("Sort Ascending") text: qsTr("Sort Ascending")
onTriggered: { onTriggered: {
tableView.closeEditor() tableView.closeEditors()
tableView.model.sort(headerMenu.clickedHeaderIndex, Qt.AscendingOrder) tableView.model.sort(headerMenu.clickedHeaderIndex, Qt.AscendingOrder)
} }
} }
@@ -181,7 +181,7 @@ Rectangle {
StudioControls.MenuItem { StudioControls.MenuItem {
text: qsTr("Sort Descending") text: qsTr("Sort Descending")
onTriggered: { onTriggered: {
tableView.closeEditor() tableView.closeEditors()
tableView.model.sort(headerMenu.clickedHeaderIndex, Qt.DescendingOrder) tableView.model.sort(headerMenu.clickedHeaderIndex, Qt.DescendingOrder)
} }
} }
@@ -235,6 +235,8 @@ Rectangle {
property int targetRow property int targetRow
property int targetColumn property int targetColumn
property Item popupEditingItem
Layout.alignment: Qt.AlignTop + Qt.AlignLeft Layout.alignment: Qt.AlignTop + Qt.AlignLeft
Layout.preferredWidth: tableView.contentWidth Layout.preferredWidth: tableView.contentWidth
Layout.preferredHeight: tableView.contentHeight Layout.preferredHeight: tableView.contentHeight
@@ -261,6 +263,24 @@ Rectangle {
return Math.max(h, StudioTheme.Values.collectionCellMinimumHeight) return Math.max(h, StudioTheme.Values.collectionCellMinimumHeight)
} }
function closePopupEditor() {
if (tableView.popupEditingItem)
tableView.popupEditingItem.closeEditor()
tableView.popupEditingItem = null
}
function openNewPopupEditor(item, editor) {
if (tableView.popupEditingItem !== item) {
closePopupEditor()
tableView.popupEditingItem = item
}
}
function closeEditors() {
closeEditor()
closePopupEditor()
}
function ensureRowIsVisible(row) { function ensureRowIsVisible(row) {
let rows = tableView.model.rowCount() let rows = tableView.model.rowCount()
let rowIsLoaded = tableView.isRowLoaded(row) let rowIsLoaded = tableView.isRowLoaded(row)
@@ -381,7 +401,36 @@ Rectangle {
Component { Component {
id: colorEditorComponent id: colorEditorComponent
ColorViewDelegate {} ColorViewDelegate {
id: colorEditorItem
readonly property color editValue: edit
readonly property color displayValue: display
property string _frontColorStr
property string _backendColorStr
actionIndicatorVisible: false
onColorChanged: {
_frontColorStr = colorEditorItem.color.toString()
if (_frontColorStr != _backendColorStr)
edit = colorEditorItem.color
}
Component.onCompleted: {
colorEditorItem.color = display
}
onDisplayValueChanged: {
_backendColorStr = colorEditorItem.displayValue.toString()
if (_frontColorStr != _backendColorStr)
colorEditorItem.color = colorEditorItem.displayValue
}
onEditorOpened: (item, editor) => {
tableView.openNewPopupEditor(item, editor)
}
}
} }
function resetSource() { function resetSource() {
@@ -441,13 +490,13 @@ Rectangle {
} }
function onRowsInserted(parent, first, last) { function onRowsInserted(parent, first, last) {
tableView.closeEditor() tableView.closeEditors()
tableView.model.selectRow(first) tableView.model.selectRow(first)
tableView.ensureRowIsVisible(first) tableView.ensureRowIsVisible(first)
} }
function onColumnsInserted(parent, first, last) { function onColumnsInserted(parent, first, last) {
tableView.closeEditor() tableView.closeEditors()
tableView.model.selectColumn(first) tableView.model.selectColumn(first)
tableView.ensureColumnIsVisible(first) tableView.ensureColumnIsVisible(first)
} }
@@ -503,7 +552,7 @@ Rectangle {
tooltip: "Add Column" tooltip: "Add Column"
onClicked: { onClicked: {
tableView.closeEditor() tableView.closeEditors()
toolbar.addNewColumn() toolbar.addNewColumn()
} }
} }
@@ -521,7 +570,7 @@ Rectangle {
tooltip: "Add Row" tooltip: "Add Row"
onClicked: { onClicked: {
tableView.closeEditor() tableView.closeEditors()
toolbar.addNewRow() toolbar.addNewRow()
} }
} }

View File

@@ -10,170 +10,59 @@ import StudioTheme as StudioTheme
import StudioControls as StudioControls import StudioControls as StudioControls
import QtQuickDesignerTheme import QtQuickDesignerTheme
import QtQuickDesignerColorPalette import QtQuickDesignerColorPalette
import StudioHelpers
Row { Item {
id: colorEditor id: root
property color color property StudioTheme.ControlStyle style: StudioTheme.Values.controlStyle
property bool supportGradient: false
property QtObject backendValue: QtObject { property alias color: colorBackend.color
property color value: edit
readonly property color editColor: edit
function resetValue() { property alias actionIndicatorVisible: actionIndicator.visible
if (value) property real __actionIndicatorWidth: root.style.actionIndicatorSize.width
value = "" property real __actionIndicatorHeight: root.style.actionIndicatorSize.height
property alias showHexTextField: hexTextField.visible
readonly property real padding: 2
readonly property real innerItemsHeight: root.height - 2 * root.padding
width: root.style.controlSize.width
height: root.style.controlSize.height
clip: true
signal editorOpened(var item, var editorPopup)
function closeEditor() {
loader.close()
} }
onValueChanged: { ColorBackend {
if (editColor !== value) id: colorBackend
edit = value
}
} }
property variant value: { StudioControls.ActionIndicator {
if (!colorEditor.backendValue || !colorEditor.backendValue.value) id: actionIndicator
return "white" // default color for Rectangle style: root.style
__parentControl: root
if (colorEditor.isVector3D) { x: root.padding
return Qt.rgba(colorEditor.backendValue.value.x, y: root.padding
colorEditor.backendValue.value.y, width: actionIndicator.visible ? root.__actionIndicatorWidth : 0
colorEditor.backendValue.value.z, 1) height: actionIndicator.visible ? root.__actionIndicatorHeight : 0
}
return colorEditor.backendValue.value
}
property alias gradientPropertyName: popupDialog.gradientPropertyName
property alias gradientThumbnail: gradientThumbnail
property alias shapeGradientThumbnail: shapeGradientThumbnail
property bool shapeGradients: false
property bool isVector3D: false
property color originalColor
property bool __block: false
function resetShapeColor() {
colorEditor.backendValue.resetValue()
}
function writeColor() {
if (colorEditor.isVector3D) {
colorEditor.backendValue.value = Qt.vector3d(colorEditor.color.r,
colorEditor.color.g,
colorEditor.color.b)
} else {
colorEditor.backendValue.value = colorEditor.color
}
}
function initEditor() {
colorEditor.syncColor()
}
// Syncing color from backend to frontend and block reflection
function syncColor() {
colorEditor.__block = true
colorEditor.color = colorEditor.value
hexTextField.syncColor()
colorEditor.__block = false
}
Connections {
id: backendConnection
target: colorEditor
function onValueChanged() {
if (popupDialog.isSolid())
colorEditor.syncColor()
}
function onBackendValueChanged() {
if (popupDialog.isSolid())
colorEditor.syncColor()
}
}
Timer {
id: colorEditorTimer
repeat: false
interval: 100
running: false
onTriggered: {
backendConnection.enabled = false
colorEditor.writeColor()
hexTextField.syncColor()
backendConnection.enabled = true
}
}
onColorChanged: {
if (colorEditor.__block)
return
if (!popupDialog.isInValidState)
return
popupDialog.commitToGradient()
// Delay setting the color to keep ui responsive
if (popupDialog.isSolid())
colorEditorTimer.restart()
} }
Rectangle { Rectangle {
id: preview id: preview
x: root.padding + actionIndicator.width
implicitWidth: StudioTheme.Values.twoControlColumnWidth y: root.padding
implicitHeight: StudioTheme.Values.height z: previewMouseArea.containsMouse ? 10 : 0
color: colorEditor.color implicitWidth: root.innerItemsHeight
border.color: StudioTheme.Values.themeControlOutline implicitHeight: root.innerItemsHeight
border.width: StudioTheme.Values.border color: root.color
border.color: previewMouseArea.containsMouse ? root.style.border.hover : root.style.border.idle
Rectangle { border.width: root.style.borderWidth
id: gradientThumbnail
anchors.fill: parent
anchors.margins: StudioTheme.Values.border
visible: !popupDialog.isSolid()
&& !colorEditor.shapeGradients
&& popupDialog.isLinearGradient()
}
Shape {
id: shape
anchors.fill: parent
anchors.margins: StudioTheme.Values.border
visible: !popupDialog.isSolid() && colorEditor.shapeGradients
ShapePath {
id: shapeGradientThumbnail
startX: shape.x - 1
startY: shape.y - 1
strokeWidth: -1
strokeColor: "green"
PathLine {
x: shape.x - 1
y: shape.height
}
PathLine {
x: shape.width
y: shape.height
}
PathLine {
x: shape.width
y: shape.y - 1
}
}
}
Image { Image {
anchors.fill: parent anchors.fill: parent
@@ -183,114 +72,111 @@ Row {
} }
MouseArea { MouseArea {
id: previewMouseArea
anchors.fill: parent anchors.fill: parent
hoverEnabled: true
onClicked: { onClicked: {
popupDialog.visibility ? popupDialog.close() : popupDialog.open() loader.toggle()
forceActiveFocus() previewMouseArea.forceActiveFocus()
} }
} }
StudioControls.PopupDialog {
id: popupDialog
property bool isInValidState: loader.active ? popupDialog.loaderItem.isInValidState : true
property QtObject loaderItem: loader.item
property string gradientPropertyName
keepOpen: loader.item?.eyeDropperActive ?? false
width: 260
function commitToGradient() {
if (!loader.active)
return
if (colorEditor.supportGradient && popupDialog.loaderItem.gradientModel.hasGradient) {
var hexColor = convertColorToString(colorEditor.color)
hexTextField.text = hexColor
colorEditor.backendValue.value = hexColor
popupDialog.loaderItem.commitGradientColor()
}
}
function isSolid() {
if (!loader.active)
return true
return popupDialog.loaderItem.isSolid()
}
function isLinearGradient(){
if (!loader.active)
return false
return popupDialog.loaderItem.isLinearGradient()
}
function ensureLoader() {
if (!loader.active)
loader.active = true
}
function open() {
popupDialog.ensureLoader()
popupDialog.loaderItem.initEditor()
popupDialog.show(preview)
}
function determineActiveColorMode() {
if (loader.active && popupDialog.loaderItem)
popupDialog.loaderItem.determineActiveColorMode()
else
colorEditor.syncColor()
}
Loader { Loader {
id: loader id: loader
active: colorEditor.supportGradient function ensureLoader() {
if (!loader.active)
loader.active = true
if (loader.sourceComponent === null)
loader.sourceComponent = popupDialogComponent
}
sourceComponent: HelperWidgets.ColorEditorPopup { function open() {
shapeGradients: colorEditor.shapeGradients loader.ensureLoader()
supportGradient: colorEditor.supportGradient loader.item.show(preview)
if (loader.status === Loader.Ready)
loader.item.originalColor = root.color
}
function close() {
if (loader.item)
loader.item.close()
}
function toggle() {
if (loader.item)
loader.close()
else
loader.open()
}
Component {
id: popupDialogComponent
StudioControls.PopupDialog {
id: popupDialog
property alias color: popup.color
property alias originalColor: popup.originalColor
titleBar: popup.titleBarContent
width: 260
StudioControls.ColorEditorPopup {
id: popup
width: popupDialog.contentWidth width: popupDialog.contentWidth
onActivateColor: function(color) {
colorBackend.activateColor(color)
}
}
onClosing: {
loader.sourceComponent = null
}
}
}
sourceComponent: null
Binding {
target: loader.item
property: "color"
value: root.color
when: loader.status === Loader.Ready
} }
onLoaded: { onLoaded: {
popupDialog.loaderItem.initEditor() loader.item.originalColor = root.color
popupDialog.titleBar = loader.item.titleBarContent root.editorOpened(root, loader.item)
}
} }
} }
} }
HelperWidgets.LineEdit { StudioControls.TextField {
id: hexTextField id: hexTextField
implicitWidth: StudioTheme.Values.twoControlColumnWidth style: root.style
+ StudioTheme.Values.actionIndicatorWidth x: root.padding + actionIndicator.width + preview.width - preview.border.width
width: hexTextField.implicitWidth y: root.padding
enabled: popupDialog.isSolid() width: root.width - hexTextField.x - 2 * root.padding
writeValueManually: true height: root.innerItemsHeight
text: root.color
actionIndicatorVisible: false
translationIndicatorVisible: false
indicatorVisible: true
indicator.icon.text: StudioTheme.Constants.copy_small
indicator.onClicked: {
hexTextField.selectAll()
hexTextField.copy()
hexTextField.deselect()
}
validator: RegularExpressionValidator { validator: RegularExpressionValidator {
regularExpression: /#[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?/g regularExpression: /#[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?/g
} }
showTranslateCheckBox: false
showExtendedFunctionButton: false
indicatorVisible: false
onAccepted: colorEditor.color = hexTextField.text onAccepted: colorBackend.activateColor(colorFromString(hexTextField.text))
onCommitData: {
colorEditor.color = hexTextField.text
if (popupDialog.isSolid())
colorEditor.writeColor()
}
function syncColor() {
hexTextField.text = colorEditor.color
} }
} }
Component.onCompleted: popupDialog.determineActiveColorMode()
onBackendValueChanged: popupDialog.determineActiveColorMode()
}