summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorATMDA <atdma2600@gmail.com>2025-11-20 21:58:55 -0500
committerATMDA <atdma2600@gmail.com>2025-11-20 21:58:55 -0500
commit7779de55bbcc87ad4af7bcc4b0f4da6e0fe65847 (patch)
treecf283a5b0d39380d0a0e97deb7dfe5949a38bb66
parentcontrolcenter: corrected taskbar panel container margins/padding (diff)
downloadcaelestia-shell-7779de55bbcc87ad4af7bcc4b0f4da6e0fe65847.tar.gz
caelestia-shell-7779de55bbcc87ad4af7bcc4b0f4da6e0fe65847.tar.bz2
caelestia-shell-7779de55bbcc87ad4af7bcc4b0f4da6e0fe65847.zip
controlcenter: refactor SliderInput and StyledInputFields to use qt components and consolidated SliderInputs to single component
-rw-r--r--components/controls/StyledInputField.qml80
-rw-r--r--modules/controlcenter/audio/AudioPane.qml158
-rw-r--r--modules/controlcenter/components/SliderInput.qml106
-rw-r--r--modules/controlcenter/components/controls/SliderInput.qml179
4 files changed, 172 insertions, 351 deletions
diff --git a/components/controls/StyledInputField.qml b/components/controls/StyledInputField.qml
new file mode 100644
index 0000000..fcd0a33
--- /dev/null
+++ b/components/controls/StyledInputField.qml
@@ -0,0 +1,80 @@
+pragma ComponentBehavior: Bound
+
+import ".."
+import qs.components
+import qs.services
+import qs.config
+import QtQuick
+
+Item {
+ id: root
+
+ property string text: ""
+ property var validator: null
+ property bool readOnly: false
+ property int horizontalAlignment: TextInput.AlignHCenter
+ property int implicitWidth: 70
+ property bool enabled: true
+
+ // Expose activeFocus through alias to avoid FINAL property override
+ readonly property alias hasFocus: inputField.activeFocus
+
+ signal textEdited(string text)
+ signal editingFinished()
+
+ implicitHeight: inputField.implicitHeight + Appearance.padding.small * 2
+
+ StyledRect {
+ id: container
+
+ anchors.fill: parent
+ color: inputHover.containsMouse || inputField.activeFocus
+ ? Colours.layer(Colours.palette.m3surfaceContainer, 3)
+ : Colours.layer(Colours.palette.m3surfaceContainer, 2)
+ radius: Appearance.rounding.small
+ border.width: 1
+ border.color: inputField.activeFocus
+ ? Colours.palette.m3primary
+ : Qt.alpha(Colours.palette.m3outline, 0.3)
+ opacity: root.enabled ? 1 : 0.5
+
+ Behavior on color { CAnim {} }
+ Behavior on border.color { CAnim {} }
+
+ MouseArea {
+ id: inputHover
+ anchors.fill: parent
+ hoverEnabled: true
+ cursorShape: Qt.IBeamCursor
+ acceptedButtons: Qt.NoButton
+ enabled: root.enabled
+ }
+
+ StyledTextField {
+ id: inputField
+ anchors.centerIn: parent
+ width: parent.width - Appearance.padding.normal
+ horizontalAlignment: root.horizontalAlignment
+ validator: root.validator
+ readOnly: root.readOnly
+ enabled: root.enabled
+
+ Binding {
+ target: inputField
+ property: "text"
+ value: root.text
+ when: !inputField.activeFocus
+ }
+
+ onTextChanged: {
+ root.text = text;
+ root.textEdited(text);
+ }
+
+ onEditingFinished: {
+ root.editingFinished();
+ }
+ }
+ }
+}
+
diff --git a/modules/controlcenter/audio/AudioPane.qml b/modules/controlcenter/audio/AudioPane.qml
index 694e178..76122f9 100644
--- a/modules/controlcenter/audio/AudioPane.qml
+++ b/modules/controlcenter/audio/AudioPane.qml
@@ -263,67 +263,40 @@ Item {
Layout.fillWidth: true
}
- StyledRect {
+ StyledInputField {
+ id: outputVolumeInput
Layout.preferredWidth: 70
- implicitHeight: outputVolumeInput.implicitHeight + Appearance.padding.small * 2
- color: outputVolumeInputHover.containsMouse || outputVolumeInput.activeFocus
- ? Colours.layer(Colours.palette.m3surfaceContainer, 3)
- : Colours.layer(Colours.palette.m3surfaceContainer, 2)
- radius: Appearance.rounding.small
- border.width: 1
- border.color: outputVolumeInput.activeFocus
- ? Colours.palette.m3primary
- : Qt.alpha(Colours.palette.m3outline, 0.3)
+ validator: IntValidator { bottom: 0; top: 100 }
enabled: !Audio.muted
- opacity: enabled ? 1 : 0.5
-
- Behavior on color { CAnim {} }
- Behavior on border.color { CAnim {} }
-
- MouseArea {
- id: outputVolumeInputHover
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.IBeamCursor
- acceptedButtons: Qt.NoButton
+
+ Component.onCompleted: {
+ text = Math.round(Audio.volume * 100).toString();
}
-
- StyledTextField {
- id: outputVolumeInput
- anchors.centerIn: parent
- width: parent.width - Appearance.padding.normal
- horizontalAlignment: TextInput.AlignHCenter
- validator: IntValidator { bottom: 0; top: 100 }
- enabled: !Audio.muted
-
- Component.onCompleted: {
- text = Math.round(Audio.volume * 100).toString();
- }
-
- Connections {
- target: Audio
- function onVolumeChanged() {
- if (!outputVolumeInput.activeFocus) {
- outputVolumeInput.text = Math.round(Audio.volume * 100).toString();
- }
+
+ Connections {
+ target: Audio
+ function onVolumeChanged() {
+ if (!outputVolumeInput.hasFocus) {
+ outputVolumeInput.text = Math.round(Audio.volume * 100).toString();
}
}
-
- onTextChanged: {
- if (activeFocus) {
- const val = parseInt(text);
- if (!isNaN(val) && val >= 0 && val <= 100) {
- Audio.setVolume(val / 100);
- }
- }
- }
- onEditingFinished: {
+ }
+
+ onTextEdited: (text) => {
+ if (hasFocus) {
const val = parseInt(text);
- if (isNaN(val) || val < 0 || val > 100) {
- text = Math.round(Audio.volume * 100).toString();
+ if (!isNaN(val) && val >= 0 && val <= 100) {
+ Audio.setVolume(val / 100);
}
}
}
+
+ onEditingFinished: {
+ const val = parseInt(text);
+ if (isNaN(val) || val < 0 || val > 100) {
+ text = Math.round(Audio.volume * 100).toString();
+ }
+ }
}
StyledText {
@@ -368,7 +341,7 @@ Item {
opacity: enabled ? 1 : 0.5
onMoved: {
Audio.setVolume(value);
- if (!outputVolumeInput.activeFocus) {
+ if (!outputVolumeInput.hasFocus) {
outputVolumeInput.text = Math.round(value * 100).toString();
}
}
@@ -402,67 +375,40 @@ Item {
Layout.fillWidth: true
}
- StyledRect {
+ StyledInputField {
+ id: inputVolumeInput
Layout.preferredWidth: 70
- implicitHeight: inputVolumeInput.implicitHeight + Appearance.padding.small * 2
- color: inputVolumeInputHover.containsMouse || inputVolumeInput.activeFocus
- ? Colours.layer(Colours.palette.m3surfaceContainer, 3)
- : Colours.layer(Colours.palette.m3surfaceContainer, 2)
- radius: Appearance.rounding.small
- border.width: 1
- border.color: inputVolumeInput.activeFocus
- ? Colours.palette.m3primary
- : Qt.alpha(Colours.palette.m3outline, 0.3)
+ validator: IntValidator { bottom: 0; top: 100 }
enabled: !Audio.sourceMuted
- opacity: enabled ? 1 : 0.5
-
- Behavior on color { CAnim {} }
- Behavior on border.color { CAnim {} }
-
- MouseArea {
- id: inputVolumeInputHover
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.IBeamCursor
- acceptedButtons: Qt.NoButton
+
+ Component.onCompleted: {
+ text = Math.round(Audio.sourceVolume * 100).toString();
}
-
- StyledTextField {
- id: inputVolumeInput
- anchors.centerIn: parent
- width: parent.width - Appearance.padding.normal
- horizontalAlignment: TextInput.AlignHCenter
- validator: IntValidator { bottom: 0; top: 100 }
- enabled: !Audio.sourceMuted
-
- Component.onCompleted: {
- text = Math.round(Audio.sourceVolume * 100).toString();
- }
-
- Connections {
- target: Audio
- function onSourceVolumeChanged() {
- if (!inputVolumeInput.activeFocus) {
- inputVolumeInput.text = Math.round(Audio.sourceVolume * 100).toString();
- }
+
+ Connections {
+ target: Audio
+ function onSourceVolumeChanged() {
+ if (!inputVolumeInput.hasFocus) {
+ inputVolumeInput.text = Math.round(Audio.sourceVolume * 100).toString();
}
}
-
- onTextChanged: {
- if (activeFocus) {
- const val = parseInt(text);
- if (!isNaN(val) && val >= 0 && val <= 100) {
- Audio.setSourceVolume(val / 100);
- }
- }
- }
- onEditingFinished: {
+ }
+
+ onTextEdited: (text) => {
+ if (hasFocus) {
const val = parseInt(text);
- if (isNaN(val) || val < 0 || val > 100) {
- text = Math.round(Audio.sourceVolume * 100).toString();
+ if (!isNaN(val) && val >= 0 && val <= 100) {
+ Audio.setSourceVolume(val / 100);
}
}
}
+
+ onEditingFinished: {
+ const val = parseInt(text);
+ if (isNaN(val) || val < 0 || val > 100) {
+ text = Math.round(Audio.sourceVolume * 100).toString();
+ }
+ }
}
StyledText {
@@ -507,7 +453,7 @@ Item {
opacity: enabled ? 1 : 0.5
onMoved: {
Audio.setSourceVolume(value);
- if (!inputVolumeInput.activeFocus) {
+ if (!inputVolumeInput.hasFocus) {
inputVolumeInput.text = Math.round(value * 100).toString();
}
}
diff --git a/modules/controlcenter/components/SliderInput.qml b/modules/controlcenter/components/SliderInput.qml
index 3d7cd4d..7348368 100644
--- a/modules/controlcenter/components/SliderInput.qml
+++ b/modules/controlcenter/components/SliderInput.qml
@@ -76,79 +76,53 @@ ColumnLayout {
Layout.fillWidth: true
}
- StyledRect {
+ StyledInputField {
+ id: inputField
Layout.preferredWidth: 70
- implicitHeight: inputField.implicitHeight + Appearance.padding.small * 2
- color: inputHover.containsMouse || inputField.activeFocus
- ? Colours.layer(Colours.palette.m3surfaceContainer, 3)
- : Colours.layer(Colours.palette.m3surfaceContainer, 2)
- radius: Appearance.rounding.small
- border.width: 1
- border.color: inputField.activeFocus
- ? Colours.palette.m3primary
- : Qt.alpha(Colours.palette.m3outline, 0.3)
-
- Behavior on color { CAnim {} }
- Behavior on border.color { CAnim {} }
-
- MouseArea {
- id: inputHover
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.IBeamCursor
- acceptedButtons: Qt.NoButton
+ validator: root.validator
+
+ Component.onCompleted: {
+ // Initialize text without triggering valueModified signal
+ text = root.formatValue(root.value);
}
-
- StyledTextField {
- id: inputField
- anchors.centerIn: parent
- width: parent.width - Appearance.padding.normal
- horizontalAlignment: TextInput.AlignHCenter
- validator: root.validator
-
- Component.onCompleted: {
- // Initialize text without triggering valueModified signal
- text = root.formatValue(root.value);
- }
-
- onTextChanged: {
- if (activeFocus) {
- const val = root.parseValue(text);
- if (!isNaN(val)) {
- // Validate against validator bounds if available
- let isValid = true;
- if (root.validator) {
- if (root.validator.bottom !== undefined && val < root.validator.bottom) {
- isValid = false;
- }
- if (root.validator.top !== undefined && val > root.validator.top) {
- isValid = false;
- }
+
+ onTextEdited: (text) => {
+ if (hasFocus) {
+ const val = root.parseValue(text);
+ if (!isNaN(val)) {
+ // Validate against validator bounds if available
+ let isValid = true;
+ if (root.validator) {
+ if (root.validator.bottom !== undefined && val < root.validator.bottom) {
+ isValid = false;
}
-
- if (isValid) {
- root.valueModified(val);
+ if (root.validator.top !== undefined && val > root.validator.top) {
+ isValid = false;
}
}
+
+ if (isValid) {
+ root.valueModified(val);
+ }
}
}
-
- onEditingFinished: {
- const val = root.parseValue(text);
- let isValid = true;
- if (root.validator) {
- if (root.validator.bottom !== undefined && val < root.validator.bottom) {
- isValid = false;
- }
- if (root.validator.top !== undefined && val > root.validator.top) {
- isValid = false;
- }
+ }
+
+ onEditingFinished: {
+ const val = root.parseValue(text);
+ let isValid = true;
+ if (root.validator) {
+ if (root.validator.bottom !== undefined && val < root.validator.bottom) {
+ isValid = false;
}
-
- if (isNaN(val) || !isValid) {
- text = root.formatValue(root.value);
+ if (root.validator.top !== undefined && val > root.validator.top) {
+ isValid = false;
}
}
+
+ if (isNaN(val) || !isValid) {
+ text = root.formatValue(root.value);
+ }
}
}
@@ -181,7 +155,7 @@ ColumnLayout {
onValueChanged: {
// Update input field text in real-time as slider moves during dragging
// Always update when slider value changes (during dragging or external updates)
- if (!inputField.activeFocus) {
+ if (!inputField.hasFocus) {
const newValue = root.stepSize > 0 ? Math.round(value / root.stepSize) * root.stepSize : value;
inputField.text = root.formatValue(newValue);
}
@@ -190,7 +164,7 @@ ColumnLayout {
onMoved: {
const newValue = root.stepSize > 0 ? Math.round(value / root.stepSize) * root.stepSize : value;
root.valueModified(newValue);
- if (!inputField.activeFocus) {
+ if (!inputField.hasFocus) {
inputField.text = root.formatValue(newValue);
}
}
@@ -199,7 +173,7 @@ ColumnLayout {
// Update input field when value changes externally (slider is already bound)
onValueChanged: {
// Only update if component is initialized to avoid issues during creation
- if (root._initialized && !inputField.activeFocus) {
+ if (root._initialized && !inputField.hasFocus) {
inputField.text = root.formatValue(root.value);
}
}
diff --git a/modules/controlcenter/components/controls/SliderInput.qml b/modules/controlcenter/components/controls/SliderInput.qml
deleted file mode 100644
index a114f7f..0000000
--- a/modules/controlcenter/components/controls/SliderInput.qml
+++ /dev/null
@@ -1,179 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import qs.components
-import qs.components.controls
-import qs.components.effects
-import QtQuick
-import QtQuick.Layouts
-
-ColumnLayout {
- id: root
-
- property string label: ""
- property real value: 0
- property real from: 0
- property real to: 100
- property real stepSize: 0
- property var validator: null
- property string suffix: "" // Optional suffix text (e.g., "×", "px")
- property var formatValueFunction: null // Optional custom format function
- property var parseValueFunction: null // Optional custom parse function
-
- function formatValue(val: real): string {
- if (formatValueFunction) {
- return formatValueFunction(val);
- }
- // Default format function
- if (validator && validator.bottom !== undefined) {
- // Check if it's an integer validator
- if (validator.top !== undefined && validator.top === Math.floor(validator.top)) {
- return Math.round(val).toString();
- }
- }
- return val.toFixed(1);
- }
-
- function parseValue(text: string): real {
- if (parseValueFunction) {
- return parseValueFunction(text);
- }
- // Default parse function
- if (validator && validator.bottom !== undefined) {
- // Check if it's an integer validator
- if (validator.top !== undefined && validator.top === Math.floor(validator.top)) {
- return parseInt(text);
- }
- }
- return parseFloat(text);
- }
-
- signal valueChanged(real newValue)
-
- spacing: Appearance.spacing.small
-
- RowLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.normal
-
- StyledText {
- visible: root.label !== ""
- text: root.label
- font.pointSize: Appearance.font.size.normal
- }
-
- Item {
- Layout.fillWidth: true
- }
-
- StyledRect {
- Layout.preferredWidth: 70
- implicitHeight: inputField.implicitHeight + Appearance.padding.small * 2
- color: inputHover.containsMouse || inputField.activeFocus
- ? Colours.layer(Colours.palette.m3surfaceContainer, 3)
- : Colours.layer(Colours.palette.m3surfaceContainer, 2)
- radius: Appearance.rounding.small
- border.width: 1
- border.color: inputField.activeFocus
- ? Colours.palette.m3primary
- : Qt.alpha(Colours.palette.m3outline, 0.3)
-
- Behavior on color { CAnim {} }
- Behavior on border.color { CAnim {} }
-
- MouseArea {
- id: inputHover
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.IBeamCursor
- acceptedButtons: Qt.NoButton
- }
-
- StyledTextField {
- id: inputField
- anchors.centerIn: parent
- width: parent.width - Appearance.padding.normal
- horizontalAlignment: TextInput.AlignHCenter
- validator: root.validator
-
- Component.onCompleted: {
- text = root.formatValue(root.value);
- }
-
- onTextChanged: {
- if (activeFocus) {
- const val = root.parseValue(text);
- if (!isNaN(val)) {
- // Validate against validator bounds if available
- let isValid = true;
- if (root.validator) {
- if (root.validator.bottom !== undefined && val < root.validator.bottom) {
- isValid = false;
- }
- if (root.validator.top !== undefined && val > root.validator.top) {
- isValid = false;
- }
- }
-
- if (isValid) {
- root.valueChanged(val);
- }
- }
- }
- }
-
- onEditingFinished: {
- const val = root.parseValue(text);
- let isValid = true;
- if (root.validator) {
- if (root.validator.bottom !== undefined && val < root.validator.bottom) {
- isValid = false;
- }
- if (root.validator.top !== undefined && val > root.validator.top) {
- isValid = false;
- }
- }
-
- if (isNaN(val) || !isValid) {
- text = root.formatValue(root.value);
- }
- }
- }
- }
-
- StyledText {
- visible: root.suffix !== ""
- text: root.suffix
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.normal
- }
- }
-
- StyledSlider {
- id: slider
-
- Layout.fillWidth: true
- implicitHeight: Appearance.padding.normal * 3
-
- from: root.from
- to: root.to
- stepSize: root.stepSize
- value: root.value
-
- onMoved: {
- const newValue = root.stepSize > 0 ? Math.round(value / root.stepSize) * root.stepSize : value;
- root.valueChanged(newValue);
- if (!inputField.activeFocus) {
- inputField.text = root.formatValue(newValue);
- }
- }
- }
-
- // Update input field when value changes externally (slider is already bound)
- onValueChanged: {
- if (!inputField.activeFocus) {
- inputField.text = root.formatValue(root.value);
- }
- }
-}
-