QmlDesigner: Fix editable ComboBox focus issue

This patch fixes an issue were a temporary value wasn't properly
written to the backend, when another item was selected in the form
view.

 * Add a dirty flag to track user modifications
 * Utilize onEditingFinished and onTextEdited from internal TextInput
 * Add full qualification to a few property and function usages

Change-Id: I9afcc17018a03549504b8d38b83fac221145794e
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Henning Gruendl
2019-08-27 09:55:37 +02:00
committed by Thomas Hartmann
parent e5bfbbd1fc
commit 1d319876c8
3 changed files with 43 additions and 36 deletions

View File

@@ -57,21 +57,21 @@ StudioControls.ComboBox {
actionIndicator.icon.text: extFuncLogic.glyph actionIndicator.icon.text: extFuncLogic.glyph
actionIndicator.onClicked: extFuncLogic.show() actionIndicator.onClicked: extFuncLogic.show()
actionIndicator.visible: showExtendedFunctionButton actionIndicator.visible: comboBox.showExtendedFunctionButton
ColorLogic { ColorLogic {
id: colorLogic id: colorLogic
backendValue: comboBox.backendValue backendValue: comboBox.backendValue
onValueFromBackendChanged: invalidate() onValueFromBackendChanged: colorLogic.invalidate()
function invalidate() { function invalidate() {
if (block) if (comboBox.block)
return return
block = true comboBox.block = true
if (manualMapping) { if (comboBox.manualMapping) {
comboBox.valueFromBackendChanged() comboBox.valueFromBackendChanged()
} else if (!comboBox.useInteger) { } else if (!comboBox.useInteger) {
var enumString = comboBox.backendValue.enumeration var enumString = comboBox.backendValue.enumeration
@@ -88,33 +88,33 @@ StudioControls.ComboBox {
comboBox.currentIndex = index comboBox.currentIndex = index
} else { } else {
if (comboBox.currentIndex !== backendValue.value) if (comboBox.currentIndex !== comboBox.backendValue.value)
comboBox.currentIndex = backendValue.value comboBox.currentIndex = comboBox.backendValue.value
} }
block = false comboBox.block = false
} }
} }
onActivated: { onCompressedActivated: {
if (!__isCompleted) if (!comboBox.__isCompleted)
return return
if (backendValue === undefined) if (comboBox.backendValue === undefined)
return return
if (manualMapping) if (comboBox.manualMapping)
return return
if (!comboBox.useInteger) { if (!comboBox.useInteger) {
backendValue.setEnumeration(comboBox.scope, comboBox.currentText) comboBox.backendValue.setEnumeration(comboBox.scope, comboBox.currentText)
} else { } else {
backendValue.value = comboBox.currentIndex comboBox.backendValue.value = comboBox.currentIndex
} }
} }
Component.onCompleted: { Component.onCompleted: {
colorLogic.invalidate() colorLogic.invalidate()
__isCompleted = true comboBox.__isCompleted = true
} }
} }

View File

@@ -110,7 +110,7 @@ RowLayout {
comboBox.handleActivate(comboBox.currentIndex) comboBox.handleActivate(comboBox.currentIndex)
} }
onActivated: comboBox.handleActivate(index) onCompressedActivated: comboBox.handleActivate(index)
function handleActivate(index) function handleActivate(index)
{ {

View File

@@ -1,3 +1,5 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2019 The Qt Company Ltd.
@@ -22,7 +24,6 @@
** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
** **
****************************************************************************/ ****************************************************************************/
import QtQuick 2.12 import QtQuick 2.12
import QtQuick.Window 2.12 import QtQuick.Window 2.12
import QtQuick.Templates 2.12 as T import QtQuick.Templates 2.12 as T
@@ -37,17 +38,19 @@ T.ComboBox {
property bool hover: false // This property is used to indicate the global hover state property bool hover: false // This property is used to indicate the global hover state
property bool edit: myComboBox.activeFocus property bool edit: myComboBox.activeFocus
property bool dirty: false // user modification flag
property alias actionIndicatorVisible: actionIndicator.visible property alias actionIndicatorVisible: actionIndicator.visible
property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth
property real __actionIndicatorHeight: StudioTheme.Values.height property real __actionIndicatorHeight: StudioTheme.Values.height
property string __lastAcceptedText: "" signal compressedActivated(int index)
signal compressedActivated
width: StudioTheme.Values.squareComponentWidth * 5 width: StudioTheme.Values.squareComponentWidth * 5
height: StudioTheme.Values.height height: StudioTheme.Values.height
leftPadding: actionIndicator.width - (actionIndicatorVisible ? StudioTheme.Values.border : 0) leftPadding: actionIndicator.width
- (myComboBox.actionIndicatorVisible ? StudioTheme.Values.border : 0)
rightPadding: popupIndicator.width - StudioTheme.Values.border rightPadding: popupIndicator.width - StudioTheme.Values.border
font.pixelSize: StudioTheme.Values.myFontSize font.pixelSize: StudioTheme.Values.myFontSize
wheelEnabled: false wheelEnabled: false
@@ -62,14 +65,24 @@ T.ComboBox {
myControl: myComboBox myControl: myComboBox
x: 0 x: 0
y: 0 y: 0
width: actionIndicator.visible ? __actionIndicatorWidth : 0 width: actionIndicator.visible ? myComboBox.__actionIndicatorWidth : 0
height: actionIndicator.visible ? __actionIndicatorHeight : 0 height: actionIndicator.visible ? myComboBox.__actionIndicatorHeight : 0
} }
contentItem: ComboBoxInput { contentItem: ComboBoxInput {
id: comboBoxInput id: comboBoxInput
myControl: myComboBox myControl: myComboBox
text: myComboBox.editText text: myComboBox.editText
onEditingFinished: {
// Only trigger the signal, if the value was modified
if (myComboBox.dirty) {
myTimer.stop()
myComboBox.dirty = false
myComboBox.compressedActivated(myComboBox.find(myComboBox.editText))
}
}
onTextEdited: myComboBox.dirty = true
} }
indicator: CheckIndicator { indicator: CheckIndicator {
@@ -87,31 +100,25 @@ T.ComboBox {
color: StudioTheme.Values.themeControlOutline color: StudioTheme.Values.themeControlOutline
border.color: StudioTheme.Values.themeControlOutline border.color: StudioTheme.Values.themeControlOutline
border.width: StudioTheme.Values.border border.width: StudioTheme.Values.border
x: actionIndicator.width - (actionIndicatorVisible ? StudioTheme.Values.border : 0) x: actionIndicator.width
- (myComboBox.actionIndicatorVisible ? StudioTheme.Values.border : 0)
width: myComboBox.width - actionIndicator.width width: myComboBox.width - actionIndicator.width
height: myComboBox.height height: myComboBox.height
} }
// Set the initial value for __lastAcceptedText
Component.onCompleted: __lastAcceptedText = myComboBox.editText
onAccepted: {
if (myComboBox.editText != __lastAcceptedText) {
var pos = find(myComboBox.editText)
activated(pos)
}
__lastAcceptedText = myComboBox.editText
}
Timer { Timer {
id: myTimer id: myTimer
property int activatedIndex
repeat: false repeat: false
running: false running: false
interval: 100 interval: 100
onTriggered: myComboBox.compressedActivated() onTriggered: myComboBox.compressedActivated(myTimer.activatedIndex)
} }
onActivated: myTimer.restart() onActivated: {
myTimer.activatedIndex = index
myTimer.restart()
}
delegate: ItemDelegate { delegate: ItemDelegate {
id: myItemDelegate id: myItemDelegate