controlcenter: refined connected button groups

This commit is contained in:
ATMDA 2025-11-17 10:36:17 -05:00
parent 3f3f3a7d78
commit 388cb0e373
2 changed files with 168 additions and 163 deletions

View file

@ -12,9 +12,10 @@ StyledRect {
property var options: [] // Array of {label: string, propertyName: string, onToggled: function} property var options: [] // Array of {label: string, propertyName: string, onToggled: function}
property var rootItem: null // The root item that contains the properties we want to bind to property var rootItem: null // The root item that contains the properties we want to bind to
property string title: "" // Optional title text
Layout.fillWidth: true Layout.fillWidth: true
implicitHeight: buttonRow.implicitHeight + Appearance.padding.large * 2 implicitHeight: layout.implicitHeight + Appearance.padding.large * 2
radius: Appearance.rounding.normal radius: Appearance.rounding.normal
color: Colours.layer(Colours.palette.m3surfaceContainer, 2) color: Colours.layer(Colours.palette.m3surfaceContainer, 2)
clip: true clip: true
@ -23,116 +24,126 @@ StyledRect {
Anim {} Anim {}
} }
RowLayout { ColumnLayout {
id: buttonRow id: layout
anchors.left: parent.left
anchors.right: parent.right anchors.fill: parent
anchors.verticalCenter: parent.verticalCenter
anchors.margins: Appearance.padding.large anchors.margins: Appearance.padding.large
spacing: Appearance.spacing.small spacing: Appearance.spacing.normal
Repeater { StyledText {
id: repeater visible: root.title !== ""
model: root.options text: root.title
font.pointSize: Appearance.font.size.normal
}
delegate: TextButton { RowLayout {
id: button id: buttonRow
required property int index Layout.alignment: Qt.AlignHCenter
required property var modelData spacing: Appearance.spacing.small
Layout.fillWidth: true Repeater {
text: modelData.label id: repeater
model: root.options
property bool isChecked: false delegate: TextButton {
id: button
required property int index
required property var modelData
// Initialize from root property Layout.fillWidth: true
Component.onCompleted: { text: modelData.label
if (root.rootItem && modelData.propertyName) {
isChecked = root.rootItem[modelData.propertyName];
}
}
checked: isChecked property bool isChecked: false
toggle: false
type: TextButton.Tonal
// Listen for property changes on rootItem // Initialize from root property
Connections { Component.onCompleted: {
target: root.rootItem if (root.rootItem && modelData.propertyName) {
enabled: root.rootItem !== null && modelData.propertyName !== undefined isChecked = root.rootItem[modelData.propertyName];
function onShowAudioChanged() {
if (modelData.propertyName === "showAudio") {
button.isChecked = root.rootItem.showAudio;
} }
} }
function onShowMicrophoneChanged() { checked: isChecked
if (modelData.propertyName === "showMicrophone") { toggle: false
button.isChecked = root.rootItem.showMicrophone; type: TextButton.Tonal
// Listen for property changes on rootItem
Connections {
target: root.rootItem
enabled: root.rootItem !== null && modelData.propertyName !== undefined
function onShowAudioChanged() {
if (modelData.propertyName === "showAudio") {
button.isChecked = root.rootItem.showAudio;
}
}
function onShowMicrophoneChanged() {
if (modelData.propertyName === "showMicrophone") {
button.isChecked = root.rootItem.showMicrophone;
}
}
function onShowKbLayoutChanged() {
if (modelData.propertyName === "showKbLayout") {
button.isChecked = root.rootItem.showKbLayout;
}
}
function onShowNetworkChanged() {
if (modelData.propertyName === "showNetwork") {
button.isChecked = root.rootItem.showNetwork;
}
}
function onShowBluetoothChanged() {
if (modelData.propertyName === "showBluetooth") {
button.isChecked = root.rootItem.showBluetooth;
}
}
function onShowBatteryChanged() {
if (modelData.propertyName === "showBattery") {
button.isChecked = root.rootItem.showBattery;
}
}
function onShowLockStatusChanged() {
if (modelData.propertyName === "showLockStatus") {
button.isChecked = root.rootItem.showLockStatus;
}
} }
} }
function onShowKbLayoutChanged() { // Match utilities Toggles radius styling
if (modelData.propertyName === "showKbLayout") { // Each button has full rounding (not connected) since they have spacing
button.isChecked = root.rootItem.showKbLayout; radius: stateLayer.pressed ? Appearance.rounding.small / 2 : internalChecked ? Appearance.rounding.small : Appearance.rounding.normal
// Match utilities Toggles inactive color
inactiveColour: Colours.layer(Colours.palette.m3surfaceContainerHighest, 2)
// Adjust width similar to utilities toggles
Layout.preferredWidth: implicitWidth + (stateLayer.pressed ? Appearance.padding.large : internalChecked ? Appearance.padding.smaller : 0)
onClicked: {
if (modelData.onToggled) {
modelData.onToggled(!checked);
} }
} }
function onShowNetworkChanged() { Behavior on Layout.preferredWidth {
if (modelData.propertyName === "showNetwork") { Anim {
button.isChecked = root.rootItem.showNetwork; duration: Appearance.anim.durations.expressiveFastSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
} }
} }
function onShowBluetoothChanged() { Behavior on radius {
if (modelData.propertyName === "showBluetooth") { Anim {
button.isChecked = root.rootItem.showBluetooth; duration: Appearance.anim.durations.expressiveFastSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
} }
} }
function onShowBatteryChanged() {
if (modelData.propertyName === "showBattery") {
button.isChecked = root.rootItem.showBattery;
}
}
function onShowLockStatusChanged() {
if (modelData.propertyName === "showLockStatus") {
button.isChecked = root.rootItem.showLockStatus;
}
}
}
// Match utilities Toggles radius styling
// Each button has full rounding (not connected) since they have spacing
radius: stateLayer.pressed ? Appearance.rounding.small / 2 : internalChecked ? Appearance.rounding.small : Appearance.rounding.normal
// Match utilities Toggles inactive color
inactiveColour: Colours.layer(Colours.palette.m3surfaceContainerHighest, 2)
// Adjust width similar to utilities toggles
Layout.preferredWidth: implicitWidth + (stateLayer.pressed ? Appearance.padding.large : internalChecked ? Appearance.padding.smaller : 0)
onClicked: {
if (modelData.onToggled) {
modelData.onToggled(!checked);
}
}
Behavior on Layout.preferredWidth {
Anim {
duration: Appearance.anim.durations.expressiveFastSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
}
}
Behavior on radius {
Anim {
duration: Appearance.anim.durations.expressiveFastSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
}
} }
} }
} }

View file

@ -164,7 +164,6 @@ Item {
readonly property bool allSectionsExpanded: readonly property bool allSectionsExpanded:
clockSection.expanded && clockSection.expanded &&
barBehaviorSection.expanded && barBehaviorSection.expanded &&
statusIconsSection.expanded &&
traySettingsSection.expanded && traySettingsSection.expanded &&
workspacesSection.expanded workspacesSection.expanded
@ -189,13 +188,76 @@ Item {
const shouldExpand = !sidebarLayout.allSectionsExpanded; const shouldExpand = !sidebarLayout.allSectionsExpanded;
clockSection.expanded = shouldExpand; clockSection.expanded = shouldExpand;
barBehaviorSection.expanded = shouldExpand; barBehaviorSection.expanded = shouldExpand;
statusIconsSection.expanded = shouldExpand;
traySettingsSection.expanded = shouldExpand; traySettingsSection.expanded = shouldExpand;
workspacesSection.expanded = shouldExpand; workspacesSection.expanded = shouldExpand;
} }
} }
} }
ConnectedButtonGroup {
rootItem: root
title: qsTr("Status Icons")
options: [
{
label: qsTr("Audio"),
propertyName: "showAudio",
onToggled: function(checked) {
root.showAudio = checked;
root.saveConfig();
}
},
{
label: qsTr("Mic"),
propertyName: "showMicrophone",
onToggled: function(checked) {
root.showMicrophone = checked;
root.saveConfig();
}
},
{
label: qsTr("KB"),
propertyName: "showKbLayout",
onToggled: function(checked) {
root.showKbLayout = checked;
root.saveConfig();
}
},
{
label: qsTr("Network"),
propertyName: "showNetwork",
onToggled: function(checked) {
root.showNetwork = checked;
root.saveConfig();
}
},
{
label: qsTr("BT"),
propertyName: "showBluetooth",
onToggled: function(checked) {
root.showBluetooth = checked;
root.saveConfig();
}
},
{
label: qsTr("Battery"),
propertyName: "showBattery",
onToggled: function(checked) {
root.showBattery = checked;
root.saveConfig();
}
},
{
label: qsTr("Lock"),
propertyName: "showLockStatus",
onToggled: function(checked) {
root.showLockStatus = checked;
root.saveConfig();
}
}
]
}
CollapsibleSection { CollapsibleSection {
id: clockSection id: clockSection
title: qsTr("Clock") title: qsTr("Clock")
@ -332,74 +394,6 @@ Item {
} }
} }
CollapsibleSection {
id: statusIconsSection
title: qsTr("Status Icons")
ConnectedButtonGroup {
rootItem: root
options: [
{
label: qsTr("Audio"),
propertyName: "showAudio",
onToggled: function(checked) {
root.showAudio = checked;
root.saveConfig();
}
},
{
label: qsTr("Mic"),
propertyName: "showMicrophone",
onToggled: function(checked) {
root.showMicrophone = checked;
root.saveConfig();
}
},
{
label: qsTr("KB"),
propertyName: "showKbLayout",
onToggled: function(checked) {
root.showKbLayout = checked;
root.saveConfig();
}
},
{
label: qsTr("Network"),
propertyName: "showNetwork",
onToggled: function(checked) {
root.showNetwork = checked;
root.saveConfig();
}
},
{
label: qsTr("BT"),
propertyName: "showBluetooth",
onToggled: function(checked) {
root.showBluetooth = checked;
root.saveConfig();
}
},
{
label: qsTr("Battery"),
propertyName: "showBattery",
onToggled: function(checked) {
root.showBattery = checked;
root.saveConfig();
}
},
{
label: qsTr("Lock"),
propertyName: "showLockStatus",
onToggled: function(checked) {
root.showLockStatus = checked;
root.saveConfig();
}
}
]
}
}
CollapsibleSection { CollapsibleSection {
id: traySettingsSection id: traySettingsSection
title: qsTr("Tray Settings") title: qsTr("Tray Settings")