QmlDesigner: Improve design system view

* Add custom SpinBox with input and indicator
* Set value on SpinBox destruction when value was changed
* Add binding indicator
* Implement binding menu and connect it to the backend
* Add readonly state to custom Switch
* Update StudioControls.DialogButton style
* Add dialogs for creating, deleting and renaming collections
* Fix crash in CollectionModel::setData
* Add themes/mode ComboBox
* Fix color editor connection
* Add overlay for header view editing

Task-number: QDS-11856
Change-Id: Ibc5fdd915a298162ed4970fb2845d7484a8f042a
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Henning Gruendl
2025-01-31 16:57:10 +01:00
committed by Henning Gründl
parent c495374b13
commit 30c62e3a32
11 changed files with 1604 additions and 170 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,62 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuick.Templates as T
import StudioTheme as StudioTheme
Item {
id: control
property StudioTheme.ControlStyle style: StudioTheme.Values.controlStyle
property alias icon: icon
property bool hover: mouseArea.containsMouse//false
property bool pressed: false
property bool forceVisible: false
implicitWidth: control.style.actionIndicatorSize.width
implicitHeight: control.style.actionIndicatorSize.height
signal clicked
z: 10
T.Label {
id: icon
anchors.fill: parent
text: StudioTheme.Constants.actionIcon
color: control.style.icon.idle
font.family: StudioTheme.Constants.iconFont.family
font.pixelSize: control.style.baseIconFontSize
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
states: [
State {
name: "hover"
when: control.hover && !control.pressed && control.enabled
PropertyChanges {
target: icon
scale: 1.2
visible: true
}
},
State {
name: "disable"
when: !control.enabled
PropertyChanges {
target: icon
color: control.style.icon.disabled
}
}
]
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
//onContainsMouseChanged: control.hover = mouseArea.containsMouse
onClicked: control.clicked()
}
}

View File

@@ -0,0 +1,365 @@
// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuick.Templates as T
import StudioTheme as StudioTheme
import StudioQuickUtils
T.SpinBox {
id: control
property StudioTheme.ControlStyle style: StudioTheme.Values.controlStyle
property real realFrom: 0.0
property real realTo: 99.0
property real realValue: 1.0
property real realStepSize: 1.0
property alias labelColor: spinBoxInput.color
property int decimals: 0
property real minStepSize: {
var tmpMinStepSize = Number((control.realStepSize * 0.1).toFixed(control.decimals))
return (tmpMinStepSize) ? tmpMinStepSize : control.realStepSize
}
property real maxStepSize: {
var tmpMaxStepSize = Number((control.realStepSize * 10.0).toFixed(control.decimals))
return (tmpMaxStepSize < control.realTo) ? tmpMaxStepSize : control.realStepSize
}
property bool edit: spinBoxInput.activeFocus
// This property is used to indicate the global hover state
property bool hover: (spinBoxInput.hover || spinBoxIndicatorUp.hover || spinBoxIndicatorDown.hover)
&& control.enabled
property bool dirty: false // user modification flag
property bool spinBoxIndicatorVisible: true
property real __spinBoxIndicatorWidth: control.style.spinBoxIndicatorSize.width
property real __spinBoxIndicatorHeight: control.height / 2 - control.style.borderWidth
property alias compressedValueTimer: myTimer
property string preFocusText: ""
signal realValueModified
signal compressedRealValueModified
signal indicatorPressed
locale: Utils.locale
// Use custom wheel handling due to bugs
property bool __wheelEnabled: false
wheelEnabled: false
hoverEnabled: true
width: control.style.controlSize.width
height: control.style.controlSize.height
leftPadding: spinBoxIndicatorDown.x + spinBoxIndicatorDown.width
rightPadding: control.style.borderWidth
font.pixelSize: control.style.baseFontSize
editable: true
// Leave this in for now
from: -99
value: 0
to: 99
function checkAndClearFocus() {
if (!spinBoxIndicatorUp.activeFocus && !spinBoxIndicatorDown.activeFocus && !spinBoxInput.activeFocus)
control.focus = false
}
DoubleValidator {
id: doubleValidator
locale: control.locale
notation: DoubleValidator.StandardNotation
decimals: control.decimals
bottom: Math.min(control.realFrom, control.realTo)
top: Math.max(control.realFrom, control.realTo)
}
IntValidator {
id: intValidator
locale: control.locale
bottom: Math.round(Math.min(control.realFrom, control.realTo))
top: Math.round(Math.max(control.realFrom, control.realTo))
}
validator: control.decimals === 0 ? intValidator : doubleValidator
up.indicator: SpinBoxIndicator {
id: spinBoxIndicatorUp
style: control.style
parentHover: control.hover
parentEdit: control.edit
iconFlip: -1
visible: control.spinBoxIndicatorVisible
onRealPressed: control.indicatorPressed()
onRealReleased: control.realIncrease()
onRealPressAndHold: control.realIncrease()
x: control.style.borderWidth
y: control.style.borderWidth
width: control.spinBoxIndicatorVisible ? control.__spinBoxIndicatorWidth : 0
height: control.spinBoxIndicatorVisible ? control.__spinBoxIndicatorHeight : 0
realEnabled: (control.realFrom < control.realTo) ? (control.realValue < control.realTo)
: (control.realValue > control.realTo)
}
down.indicator: SpinBoxIndicator {
id: spinBoxIndicatorDown
style: control.style
parentHover: control.hover
parentEdit: control.edit
visible: control.spinBoxIndicatorVisible
onRealPressed: control.indicatorPressed()
onRealReleased: control.realDecrease()
onRealPressAndHold: control.realDecrease()
x: control.style.borderWidth
y: spinBoxIndicatorUp.y + spinBoxIndicatorUp.height
width: control.spinBoxIndicatorVisible ? control.__spinBoxIndicatorWidth : 0
height: control.spinBoxIndicatorVisible ? control.__spinBoxIndicatorHeight : 0
realEnabled: (control.realFrom < control.realTo) ? (control.realValue > control.realFrom)
: (control.realValue < control.realFrom)
}
contentItem: SpinBoxInput {
id: spinBoxInput
style: control.style
validator: control.validator
font: control.font
readOnly: !control.editable
inputMethodHints: control.inputMethodHints
function handleEditingFinished() {
control.checkAndClearFocus()
// Keep the dirty state before calling setValueFromInput(),
// it will be set to false (cleared) internally
var valueModified = control.dirty
control.setValueFromInput()
myTimer.stop()
// Only trigger the signal, if the value was modified
if (valueModified)
control.compressedRealValueModified()
}
onEditingFinished: {
spinBoxInput.focus = false
spinBoxInput.handleEditingFinished()
}
onTextEdited: control.dirty = true
}
background: Rectangle {
id: spinBoxBackground
color: control.style.background.idle
border.color: control.style.border.idle
border.width: control.style.borderWidth
x: 0
width: control.width
height: control.height
}
textFromValue: function (value, locale) {
// -128 is the value of QLocale::FloatingPointShortest
return Number(control.realValue).toLocaleString(locale, 'f', -128)
}
valueFromText: function (text, locale) {
control.setRealValue(Number.fromLocaleString(locale, spinBoxInput.text))
return 0
}
states: [
State {
name: "default"
when: control.enabled && !control.hover && !control.hovered
&& !control.edit
PropertyChanges {
target: control
__wheelEnabled: false
}
PropertyChanges {
target: spinBoxInput
selectByMouse: false
}
PropertyChanges {
target: spinBoxBackground
color: control.style.background.idle
border.color: control.style.border.idle
}
},
State {
name: "hover"
when: control.enabled && control.hover && control.hovered
&& !control.edit
PropertyChanges {
target: spinBoxBackground
border.color: control.style.border.hover
}
},
State {
name: "edit"
when: control.edit
PropertyChanges {
target: control
__wheelEnabled: true
}
PropertyChanges {
target: spinBoxInput
selectByMouse: true
}
PropertyChanges {
target: spinBoxBackground
border.color: control.style.border.interaction
}
},
State {
name: "disable"
when: !control.enabled
PropertyChanges {
target: spinBoxBackground
border.color: control.style.border.disabled
}
}
]
Timer {
id: myTimer
repeat: false
running: false
interval: 400
onTriggered: control.compressedRealValueModified()
}
onRealValueChanged: {
control.setRealValue(control.realValue) // sanitize and clamp realValue
spinBoxInput.text = control.textFromValue(control.realValue, control.locale)
control.value = 0 // Without setting value back to 0, it can happen that one of
// the indicator will be disabled due to range logic.
}
onRealValueModified: myTimer.restart()
onFocusChanged: {
if (control.focus)
control.dirty = false
}
onDisplayTextChanged: spinBoxInput.text = control.displayText
onActiveFocusChanged: {
if (control.activeFocus) { // QTBUG-75862 && mySpinBox.focusReason === Qt.TabFocusReason)
control.preFocusText = spinBoxInput.text
spinBoxInput.selectAll()
} else {
// Make sure displayed value is correct after focus loss, as onEditingFinished
// doesn't trigger when value is something validator doesn't accept.
if (spinBoxInput.text === "")
spinBoxInput.text = control.textFromValue(control.realValue, control.locale)
if (control.dirty)
spinBoxInput.handleEditingFinished()
}
}
onDecimalsChanged: spinBoxInput.text = control.textFromValue(control.realValue, control.locale)
Keys.onPressed: function(event) {
if (event.key === Qt.Key_Up || event.key === Qt.Key_Down) {
event.accepted = true
// Store current step size
var currStepSize = control.realStepSize
// Set realStepSize according to used modifier key
if (event.modifiers & Qt.ControlModifier)
control.realStepSize = control.minStepSize
if (event.modifiers & Qt.ShiftModifier)
control.realStepSize = control.maxStepSize
if (event.key === Qt.Key_Up)
control.realIncrease()
else
control.realDecrease()
// Reset realStepSize
control.realStepSize = currStepSize
}
if (event.key === Qt.Key_Escape) {
spinBoxInput.text = control.preFocusText
control.dirty = true
spinBoxInput.handleEditingFinished()
}
}
function clamp(v, lo, hi) {
return (v < lo || v > hi) ? Math.min(Math.max(lo, v), hi) : v
}
function setValueFromInput() {
if (!control.dirty)
return
// FIX: This is a temporary fix for QTBUG-74239
var currValue = control.realValue
// Call the function but don't use return value. The realValue property
// will be implicitly set inside the function/procedure.
control.valueFromText(spinBoxInput.text, control.locale)
if (control.realValue !== currValue) {
control.realValueModified()
} else {
// Check if input text differs in format from the current value
var tmpInputValue = control.textFromValue(control.realValue, control.locale)
if (tmpInputValue !== spinBoxInput.text)
spinBoxInput.text = tmpInputValue
}
control.dirty = false
}
function setRealValue(value) {
if (Number.isNaN(value))
value = 0
if (control.decimals === 0)
value = Math.round(value)
control.realValue = control.clamp(value,
control.validator.bottom,
control.validator.top)
}
function realDecrease() {
// Store the current value for comparison
var currValue = control.realValue
control.valueFromText(spinBoxInput.text, control.locale)
control.setRealValue(control.realValue - control.realStepSize)
if (control.realValue !== currValue)
control.realValueModified()
}
function realIncrease() {
// Store the current value for comparison
var currValue = control.realValue
control.valueFromText(spinBoxInput.text, control.locale)
control.setRealValue(control.realValue + control.realStepSize)
if (control.realValue !== currValue)
control.realValueModified()
}
}

View File

@@ -0,0 +1,247 @@
// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuick.Templates as T
import StudioTheme as StudioTheme
Rectangle {
id: control
property StudioTheme.ControlStyle style: StudioTheme.Values.controlStyle
property bool hover: spinBoxIndicatorMouseArea.containsMouse
property bool pressed: spinBoxIndicatorMouseArea.containsPress
property bool released: false
property bool realEnabled: true
property bool parentHover: false
property bool parentEdit: false
signal realPressed
signal realPressAndHold
signal realReleased
property alias iconFlip: spinBoxIndicatorIconScale.yScale
color: control.style.background.idle
border.width: 0
onEnabledChanged: control.syncEnabled()
onRealEnabledChanged: {
control.syncEnabled()
if (control.realEnabled === false) {
pressAndHoldTimer.stop()
spinBoxIndicatorMouseArea.pressedAndHeld = false
}
}
// This function is meant to synchronize enabled with realEnabled to avoid
// the internal logic messing with the actual state.
function syncEnabled() {
control.enabled = control.realEnabled
}
Timer {
id: pressAndHoldTimer
repeat: true
running: false
interval: 100
onTriggered: control.realPressAndHold()
}
// This MouseArea is a workaround to avoid some hover state related bugs
// when using the actual signal 'up.hovered'. QTBUG-74688
MouseArea {
id: spinBoxIndicatorMouseArea
property bool pressedAndHeld: false
anchors.fill: parent
hoverEnabled: true
pressAndHoldInterval: 500
onPressed: function(mouse) {
//if (control.__parentControl.activeFocus)
// control.forceActiveFocus()
control.realPressed()
mouse.accepted = true
}
onPressAndHold: {
pressAndHoldTimer.restart()
spinBoxIndicatorMouseArea.pressedAndHeld = true
}
onReleased: function(mouse) {
// Only trigger real released when pressAndHold isn't active
if (!pressAndHoldTimer.running && containsMouse)
control.realReleased()
pressAndHoldTimer.stop()
mouse.accepted = true
spinBoxIndicatorMouseArea.pressedAndHeld = false
}
onEntered: {
if (spinBoxIndicatorMouseArea.pressedAndHeld)
pressAndHoldTimer.restart()
}
onExited: {
if (pressAndHoldTimer.running)
pressAndHoldTimer.stop()
}
}
T.Label {
id: spinBoxIndicatorIcon
text: StudioTheme.Constants.upDownSquare2
color: control.style.icon.idle
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.pixelSize: control.style.smallIconFontSize
font.family: StudioTheme.Constants.iconFont.family
anchors.fill: parent
transform: Scale {
id: spinBoxIndicatorIconScale
origin.x: 0
origin.y: spinBoxIndicatorIcon.height / 2
yScale: 1
}
states: [
State {
name: "default"
when: control.enabled && !control.hover && !control.parentEdit && !control.parentHover
PropertyChanges {
target: spinBoxIndicatorIcon
color: control.style.icon.idle
}
},
State {
name: "globalHover"
when: control.enabled && !control.hover && !control.parentEdit && control.parentHover
PropertyChanges {
target: spinBoxIndicatorIcon
color: control.style.icon.idle
}
},
State {
name: "hover"
when: control.enabled && control.hover && !control.pressed && control.parentHover
PropertyChanges {
target: spinBoxIndicatorIcon
color: control.style.icon.hover
}
},
State {
name: "press"
when: control.enabled && control.pressed
PropertyChanges {
target: spinBoxIndicatorIcon
color: control.style.icon.idle
}
},
State {
name: "parentEdit"
when: control.parentEdit && control.enabled
PropertyChanges {
target: spinBoxIndicatorIcon
color: control.style.icon.idle
}
},
State {
name: "disable"
when: !control.enabled
PropertyChanges {
target: spinBoxIndicatorIcon
color: control.style.icon.disabled
}
}
]
}
states: [
State {
name: "default"
when: !control.parentEdit && !control.hover && !control.parentHover
PropertyChanges {
target: spinBoxIndicatorIcon
visible: false
}
PropertyChanges {
target: control
color: control.style.background.idle
}
},
State {
name: "globalHover"
when: control.enabled && !control.hover && !control.parentEdit && control.parentHover
PropertyChanges {
target: spinBoxIndicatorIcon
visible: true
}
PropertyChanges {
target: control
color: control.style.background.globalHover
}
},
State {
name: "hover"
when: control.enabled && control.hover && !control.pressed && control.parentHover
PropertyChanges {
target: spinBoxIndicatorIcon
visible: true
}
PropertyChanges {
target: control
color: control.style.background.hover
}
},
State {
name: "press"
when: control.enabled && control.pressed
PropertyChanges {
target: spinBoxIndicatorIcon
visible: true
}
PropertyChanges {
target: control
color: control.style.interaction
}
},
State {
name: "parentEdit"
when: control.parentEdit && control.enabled
PropertyChanges {
target: spinBoxIndicatorIcon
visible: true
}
PropertyChanges {
target: control
color: control.style.background.idle
}
},
State {
name: "disable"
when: !control.enabled
PropertyChanges {
target: spinBoxIndicatorIcon
visible: false
}
PropertyChanges {
target: control
color: control.style.background.disabled
}
},
State {
name: "limit"
when: !control.enabled && !control.realEnabled && control.parentHover
PropertyChanges {
target: spinBoxIndicatorIcon
visible: true
}
PropertyChanges {
target: control
color: control.style.background.idle
}
}
]
}

View File

@@ -0,0 +1,100 @@
// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick
import QtQuick.Templates as T
import StudioTheme as StudioTheme
TextInput {
id: control
property StudioTheme.ControlStyle style: StudioTheme.Values.controlStyle
property bool edit: control.activeFocus
property bool drag: false
property bool hover: hoverHandler.hovered && control.enabled
z: 2
color: control.style.text.idle
selectionColor: control.style.text.selection
selectedTextColor: control.style.text.selectedText
horizontalAlignment: Qt.AlignLeft
verticalAlignment: Qt.AlignVCenter
leftPadding: control.style.inputHorizontalPadding
rightPadding: control.style.inputHorizontalPadding
selectByMouse: false
activeFocusOnPress: false
clip: true
// TextInput focus needs to be set to activeFocus whenever it changes,
// otherwise TextInput will get activeFocus whenever the parent SpinBox gets
// activeFocus. This will lead to weird side effects.
onActiveFocusChanged: control.focus = control.activeFocus
HoverHandler { id: hoverHandler }
Rectangle {
id: textInputBackground
x: 0
y: control.style.borderWidth
z: -1
width: control.width
height: control.height - (control.style.borderWidth * 2)
color: control.style.background.idle
border.width: 0
}
// Ensure that we get Up and Down key press events first
Keys.onShortcutOverride: function(event) {
event.accepted = (event.key === Qt.Key_Up || event.key === Qt.Key_Down)
}
states: [
State {
name: "default"
when: control.enabled && !control.edit && !control.hover
PropertyChanges {
target: textInputBackground
color: control.style.background.idle
}
},
State {
name: "globalHover"
when: !control.hover && !control.edit
PropertyChanges {
target: textInputBackground
color: control.style.background.globalHover
}
},
State {
name: "hover"
when: control.hover && !control.edit
PropertyChanges {
target: textInputBackground
color: control.style.background.hover
}
},
State {
name: "edit"
when: control.edit
PropertyChanges {
target: textInputBackground
color: control.style.background.interaction
}
},
State {
name: "disable"
when: !control.enabled
PropertyChanges {
target: textInputBackground
color: control.style.background.disabled
}
PropertyChanges {
target: control
color: control.style.text.disabled
}
}
]
}

View File

@@ -4,7 +4,7 @@
import QtQuick import QtQuick
import QtQuick.Templates as T import QtQuick.Templates as T
import StudioTheme 1.0 as StudioTheme import StudioTheme as StudioTheme
T.Switch { T.Switch {
id: control id: control
@@ -14,6 +14,7 @@ T.Switch {
// This property is used to indicate the global hover state // This property is used to indicate the global hover state
property bool hover: control.hovered && control.enabled property bool hover: control.hovered && control.enabled
property bool edit: false property bool edit: false
property bool readonly: false
property alias labelVisible: label.visible property alias labelVisible: label.visible
property alias labelColor: label.color property alias labelColor: label.color
@@ -33,6 +34,8 @@ T.Switch {
hoverEnabled: true hoverEnabled: true
activeFocusOnTab: false activeFocusOnTab: false
enabled: !control.readonly
indicator: Rectangle { indicator: Rectangle {
id: switchBackground id: switchBackground
x: 0 x: 0
@@ -60,6 +63,7 @@ T.Switch {
color: control.style.icon.idle color: control.style.icon.idle
border.width: 0 border.width: 0
} }
} }
contentItem: T.Label { contentItem: T.Label {
@@ -133,7 +137,7 @@ T.Switch {
}, },
State { State {
name: "disable" name: "disable"
when: !control.enabled && !control.checked when: !control.enabled && !control.checked && !control.readonly
PropertyChanges { PropertyChanges {
target: switchBackground target: switchBackground
color: control.style.background.disabled color: control.style.background.disabled
@@ -186,8 +190,19 @@ T.Switch {
}, },
State { State {
name: "disableChecked" name: "disableChecked"
when: !control.enabled && control.checked when: !control.enabled && control.checked && !control.readonly
extend: "disable" extend: "disable"
},
State {
name: "readonly"
when: !control.enabled && !control.checked && control.readonly
extend: "default"
},
State {
name: "readonlyChecked"
when: !control.enabled && control.checked && control.readonly
extend: "defaultChecked"
} }
] ]
} }

View File

@@ -1,3 +1,7 @@
BindingIndicator 1.0 BindingIndicator.qml
MenuItem 1.0 MenuItem.qml MenuItem 1.0 MenuItem.qml
SpinBox 1.0 SpinBox.qml
SpinBoxIndicator 1.0 SpinBoxIndicator.qml
SpinBoxInput 1.0 SpinBoxInput.qml
Switch 1.0 Switch.qml Switch 1.0 Switch.qml
TextField 1.0 TextField.qml TextField 1.0 TextField.qml

View File

@@ -3,27 +3,29 @@
import QtQuick import QtQuick
import QtQuick.Templates as T import QtQuick.Templates as T
import StudioTheme 1.0 as StudioTheme import StudioTheme as StudioTheme
T.Button { T.Button {
id: control id: control
property StudioTheme.ControlStyle style: StudioTheme.Values.controlStyle property StudioTheme.ControlStyle style: StudioTheme.Values.controlStyle
implicitWidth: Math.max(buttonBackground ? buttonBackground.implicitWidth : 0, implicitWidth: Math.max(control.style.squareControlSize.width,
textItem.implicitWidth + leftPadding + rightPadding) implicitBackgroundWidth + leftInset + rightInset,
implicitHeight: Math.max(buttonBackground ? buttonBackground.implicitHeight : 0, implicitContentWidth + leftPadding + rightPadding)
textItem.implicitHeight + topPadding + bottomPadding) implicitHeight: Math.max(control.style.squareControlSize.height,
implicitBackgroundHeight + topInset + bottomInset,
implicitContentHeight + topPadding + bottomPadding)
leftPadding: control.style.dialogPadding leftPadding: control.style.dialogPadding
rightPadding: control.style.dialogPadding rightPadding: control.style.dialogPadding
background: Rectangle { background: Rectangle {
id: buttonBackground id: controlBackground
implicitWidth: 70
implicitHeight: 20
color: control.style.background.idle color: control.style.background.idle
border.color: control.style.border.idle border.color: control.style.border.idle
anchors.fill: parent border.width: control.style.borderWidth
radius: control.style.radius
} }
contentItem: Text { contentItem: Text {
@@ -41,7 +43,7 @@ T.Button {
when: control.enabled && !control.down && !control.hovered && !control.checked when: control.enabled && !control.down && !control.hovered && !control.checked
PropertyChanges { PropertyChanges {
target: buttonBackground target: controlBackground
color: control.highlighted ? control.style.interaction color: control.highlighted ? control.style.interaction
: control.style.background.idle : control.style.background.idle
border.color: control.style.border.idle border.color: control.style.border.idle
@@ -56,7 +58,7 @@ T.Button {
when: control.enabled && control.hovered && !control.checked && !control.down when: control.enabled && control.hovered && !control.checked && !control.down
PropertyChanges { PropertyChanges {
target: buttonBackground target: controlBackground
color: control.style.background.hover color: control.style.background.hover
border.color: control.style.border.hover border.color: control.style.border.hover
} }
@@ -70,9 +72,9 @@ T.Button {
when: control.enabled && (control.checked || control.down) when: control.enabled && (control.checked || control.down)
PropertyChanges { PropertyChanges {
target: buttonBackground target: controlBackground
color: control.style.background.interaction color: control.style.interaction
border.color: control.style.border.interaction border.color: control.style.interaction
} }
PropertyChanges { PropertyChanges {
target: textItem target: textItem
@@ -83,7 +85,7 @@ T.Button {
name: "disable" name: "disable"
when: !control.enabled when: !control.enabled
PropertyChanges { PropertyChanges {
target: buttonBackground target: controlBackground
color: control.style.background.disabled color: control.style.background.disabled
border.color: control.style.border.disabled border.color: control.style.border.disabled
} }

View File

@@ -116,6 +116,11 @@ QVariant CollectionModel::headerData(int section, Qt::Orientation orientation, i
Qt::ItemFlags CollectionModel::flags(const QModelIndex &index) const Qt::ItemFlags CollectionModel::flags(const QModelIndex &index) const
{ {
// If group type is FLAGS and not binding block editable
if (data(index, Roles::GroupRole).value<GroupType>() == GroupType::Flags
&& !data(index, Roles::BindingRole).toBool())
return QAbstractItemModel::flags(index);
return Qt::ItemIsEditable | QAbstractItemModel::flags(index); return Qt::ItemIsEditable | QAbstractItemModel::flags(index);
} }
@@ -214,9 +219,9 @@ bool CollectionModel::setData(const QModelIndex &index, const QVariant &value, i
p.name = propName; p.name = propName;
const ThemeId id = m_themeIdList[index.column()]; const ThemeId id = m_themeIdList[index.column()];
if (m_collection->updateProperty(id, groupType, p)) { if (m_collection->updateProperty(id, groupType, p)) {
beginResetModel();
updateCache(); updateCache();
endResetModel();
emit dataChanged(index, index);
} }
} }
default: default:

View File

@@ -25,6 +25,7 @@ public:
ResolvedValueRole, ResolvedValueRole,
PropertyValueRole PropertyValueRole
}; };
Q_ENUM(Roles)
Q_PROPERTY(QStringList themeNames READ themeNameList NOTIFY themeNameChanged FINAL) Q_PROPERTY(QStringList themeNames READ themeNameList NOTIFY themeNameChanged FINAL)

View File

@@ -16,6 +16,7 @@ DesignSystemInterface::DesignSystemInterface(DSStore *store)
{ {
qmlRegisterUncreatableMetaObject( qmlRegisterUncreatableMetaObject(
QmlDesigner::staticMetaObject, "QmlDesigner.DesignSystem", 1, 0, "GroupType", ""); QmlDesigner::staticMetaObject, "QmlDesigner.DesignSystem", 1, 0, "GroupType", "");
qmlRegisterUncreatableType<CollectionModel>("QmlDesigner.DesignSystem", 1, 0, "CollectionModel", "");
} }
DesignSystemInterface::~DesignSystemInterface() {} DesignSystemInterface::~DesignSystemInterface() {}