forked from qt-creator/qt-creator
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:
committed by
Henning Gründl
parent
c495374b13
commit
30c62e3a32
File diff suppressed because it is too large
Load Diff
@@ -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()
|
||||
}
|
||||
}
|
@@ -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()
|
||||
}
|
||||
}
|
@@ -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
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@@ -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
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@@ -4,7 +4,7 @@
|
||||
import QtQuick
|
||||
import QtQuick.Templates as T
|
||||
|
||||
import StudioTheme 1.0 as StudioTheme
|
||||
import StudioTheme as StudioTheme
|
||||
|
||||
T.Switch {
|
||||
id: control
|
||||
@@ -14,6 +14,7 @@ T.Switch {
|
||||
// This property is used to indicate the global hover state
|
||||
property bool hover: control.hovered && control.enabled
|
||||
property bool edit: false
|
||||
property bool readonly: false
|
||||
|
||||
property alias labelVisible: label.visible
|
||||
property alias labelColor: label.color
|
||||
@@ -33,6 +34,8 @@ T.Switch {
|
||||
hoverEnabled: true
|
||||
activeFocusOnTab: false
|
||||
|
||||
enabled: !control.readonly
|
||||
|
||||
indicator: Rectangle {
|
||||
id: switchBackground
|
||||
x: 0
|
||||
@@ -60,6 +63,7 @@ T.Switch {
|
||||
color: control.style.icon.idle
|
||||
border.width: 0
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
contentItem: T.Label {
|
||||
@@ -133,7 +137,7 @@ T.Switch {
|
||||
},
|
||||
State {
|
||||
name: "disable"
|
||||
when: !control.enabled && !control.checked
|
||||
when: !control.enabled && !control.checked && !control.readonly
|
||||
PropertyChanges {
|
||||
target: switchBackground
|
||||
color: control.style.background.disabled
|
||||
@@ -186,8 +190,19 @@ T.Switch {
|
||||
},
|
||||
State {
|
||||
name: "disableChecked"
|
||||
when: !control.enabled && control.checked
|
||||
when: !control.enabled && control.checked && !control.readonly
|
||||
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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@@ -1,3 +1,7 @@
|
||||
BindingIndicator 1.0 BindingIndicator.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
|
||||
TextField 1.0 TextField.qml
|
||||
|
@@ -3,27 +3,29 @@
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Templates as T
|
||||
import StudioTheme 1.0 as StudioTheme
|
||||
import StudioTheme as StudioTheme
|
||||
|
||||
T.Button {
|
||||
id: control
|
||||
|
||||
property StudioTheme.ControlStyle style: StudioTheme.Values.controlStyle
|
||||
|
||||
implicitWidth: Math.max(buttonBackground ? buttonBackground.implicitWidth : 0,
|
||||
textItem.implicitWidth + leftPadding + rightPadding)
|
||||
implicitHeight: Math.max(buttonBackground ? buttonBackground.implicitHeight : 0,
|
||||
textItem.implicitHeight + topPadding + bottomPadding)
|
||||
implicitWidth: Math.max(control.style.squareControlSize.width,
|
||||
implicitBackgroundWidth + leftInset + rightInset,
|
||||
implicitContentWidth + leftPadding + rightPadding)
|
||||
implicitHeight: Math.max(control.style.squareControlSize.height,
|
||||
implicitBackgroundHeight + topInset + bottomInset,
|
||||
implicitContentHeight + topPadding + bottomPadding)
|
||||
|
||||
leftPadding: control.style.dialogPadding
|
||||
rightPadding: control.style.dialogPadding
|
||||
|
||||
background: Rectangle {
|
||||
id: buttonBackground
|
||||
implicitWidth: 70
|
||||
implicitHeight: 20
|
||||
id: controlBackground
|
||||
color: control.style.background.idle
|
||||
border.color: control.style.border.idle
|
||||
anchors.fill: parent
|
||||
border.width: control.style.borderWidth
|
||||
radius: control.style.radius
|
||||
}
|
||||
|
||||
contentItem: Text {
|
||||
@@ -41,7 +43,7 @@ T.Button {
|
||||
when: control.enabled && !control.down && !control.hovered && !control.checked
|
||||
|
||||
PropertyChanges {
|
||||
target: buttonBackground
|
||||
target: controlBackground
|
||||
color: control.highlighted ? control.style.interaction
|
||||
: control.style.background.idle
|
||||
border.color: control.style.border.idle
|
||||
@@ -56,7 +58,7 @@ T.Button {
|
||||
when: control.enabled && control.hovered && !control.checked && !control.down
|
||||
|
||||
PropertyChanges {
|
||||
target: buttonBackground
|
||||
target: controlBackground
|
||||
color: control.style.background.hover
|
||||
border.color: control.style.border.hover
|
||||
}
|
||||
@@ -70,9 +72,9 @@ T.Button {
|
||||
when: control.enabled && (control.checked || control.down)
|
||||
|
||||
PropertyChanges {
|
||||
target: buttonBackground
|
||||
color: control.style.background.interaction
|
||||
border.color: control.style.border.interaction
|
||||
target: controlBackground
|
||||
color: control.style.interaction
|
||||
border.color: control.style.interaction
|
||||
}
|
||||
PropertyChanges {
|
||||
target: textItem
|
||||
@@ -83,7 +85,7 @@ T.Button {
|
||||
name: "disable"
|
||||
when: !control.enabled
|
||||
PropertyChanges {
|
||||
target: buttonBackground
|
||||
target: controlBackground
|
||||
color: control.style.background.disabled
|
||||
border.color: control.style.border.disabled
|
||||
}
|
||||
|
@@ -116,6 +116,11 @@ QVariant CollectionModel::headerData(int section, Qt::Orientation orientation, i
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -214,9 +219,9 @@ bool CollectionModel::setData(const QModelIndex &index, const QVariant &value, i
|
||||
p.name = propName;
|
||||
const ThemeId id = m_themeIdList[index.column()];
|
||||
if (m_collection->updateProperty(id, groupType, p)) {
|
||||
beginResetModel();
|
||||
updateCache();
|
||||
endResetModel();
|
||||
|
||||
emit dataChanged(index, index);
|
||||
}
|
||||
}
|
||||
default:
|
||||
|
@@ -25,6 +25,7 @@ public:
|
||||
ResolvedValueRole,
|
||||
PropertyValueRole
|
||||
};
|
||||
Q_ENUM(Roles)
|
||||
|
||||
Q_PROPERTY(QStringList themeNames READ themeNameList NOTIFY themeNameChanged FINAL)
|
||||
|
||||
|
@@ -16,6 +16,7 @@ DesignSystemInterface::DesignSystemInterface(DSStore *store)
|
||||
{
|
||||
qmlRegisterUncreatableMetaObject(
|
||||
QmlDesigner::staticMetaObject, "QmlDesigner.DesignSystem", 1, 0, "GroupType", "");
|
||||
qmlRegisterUncreatableType<CollectionModel>("QmlDesigner.DesignSystem", 1, 0, "CollectionModel", "");
|
||||
}
|
||||
|
||||
DesignSystemInterface::~DesignSystemInterface() {}
|
||||
|
Reference in New Issue
Block a user