feat: add on state logic

This commit is contained in:
loner
2025-11-04 02:28:36 +08:00
parent 5c19c8433e
commit e182fe2552
4 changed files with 247 additions and 37 deletions
+28
View File
@@ -847,6 +847,34 @@
"tooltip": {
"label": "Tooltip",
"description": "The tooltip to show when hovering over the button."
},
"on-state-icon": {
"label": "On State Icon",
"description": "The icon for the button when it's in the 'on' state."
},
"on-clicked": {
"label": "Left Click Command",
"description": "Command to execute when the button is left-clicked."
},
"on-right-clicked": {
"label": "Right Click Command",
"description": "Command to execute when the button is right-clicked."
},
"on-middle-clicked": {
"label": "Middle Click Command",
"description": "Command to execute when the button is middle-clicked."
},
"on-state-command": {
"label": "On State Check Command",
"description": "Command to execute to check if the button should be in the 'on' state. Returns 0 for on, non-zero for off."
},
"general-tooltip-text": {
"label": "General Tooltip Text",
"description": "General description for the button's tooltip."
},
"enable-on-state-logic": {
"label": "Enable On-State Logic",
"description": "Enable a second icon and 'hot' state based on a check command."
}
},
"dialog": {
+90 -10
View File
@@ -1,5 +1,6 @@
import QtQuick
import Quickshell
import Quickshell.Io
import qs.Commons
import qs.Services
import qs.Widgets
@@ -10,24 +11,103 @@ Item {
// Widget properties
property string widgetId: "CustomButton"
property var widgetSettings: {} // This will be populated from settings
property var widgetSettings
// Use settings or provide defaults
readonly property string customIcon: widgetSettings.icon || "heart"
readonly property string exec: widgetSettings.exec || ""
readonly property string tooltipText: widgetSettings.tooltipText || "Custom Button"
property string onClickedCommand: ""
property string onRightClickedCommand: ""
property string onMiddleClickedCommand: ""
property string initialIcon: "heart"
property string onStateIcon: "heart"
property string onStateCommand: ""
property string generalTooltipText: "Custom Button"
property bool enableOnStateLogic: false
// Internal state
property string _currentIcon: initialIcon
property bool _isHot: false
Connections {
target: root
function _updatePropertiesFromSettings() {
onClickedCommand = widgetSettings.onClicked || ""
onRightClickedCommand = widgetSettings.onRightClicked || ""
onMiddleClickedCommand = widgetSettings.onMiddleClicked || ""
initialIcon = (widgetSettings.icon && widgetSettings.icon !== "") ? widgetSettings.icon : "heart"
onStateIcon = (widgetSettings.onStateIcon && widgetSettings.onStateIcon !== "") ? widgetSettings.onStateIcon : "heart"
onStateCommand = widgetSettings.onStateCommand || ""
generalTooltipText = widgetSettings.generalTooltipText || "Custom Button"
enableOnStateLogic = widgetSettings.enableOnStateLogic || false
updateState()
}
function onWidgetSettingsChanged() { _updatePropertiesFromSettings() }
}
Process {
id: onStateCheckProcess
running: false
command: ["sh", "-c", onStateCommand]
onExited: function(exitCode, stdout, stderr) {
if (exitCode === 0) {
_isHot = true
_currentIcon = onStateIcon || initialIcon
} else {
_isHot = false
_currentIcon = initialIcon
}
}
}
function updateState() {
if (enableOnStateLogic && onStateCommand) {
onStateCheckProcess.running = true // Start the process
} else {
_isHot = false
_currentIcon = initialIcon
}
}
function _buildTooltipText() {
let tooltip = generalTooltipText
if (onClickedCommand) {
tooltip += `\nLeft click: ${onClickedCommand}`
}
if (onRightClickedCommand) {
tooltip += `\nRight click: ${onRightClickedCommand}`
}
if (onMiddleClickedCommand) {
tooltip += `\nMiddle click: ${onMiddleClickedCommand}`
}
return tooltip
}
implicitWidth: button.implicitWidth
implicitHeight: button.implicitHeight
NIconButton {
NIconButtonHot {
id: button
icon: customIcon
tooltipText: tooltipText
icon: _currentIcon
hot: _isHot
tooltipText: _buildTooltipText()
onClicked: {
if (exec) {
Quickshell.execDetached(["sh", "-c", exec])
Logger.i("CC:CustomButton", `Executing command: ${exec}`)
if (onClickedCommand) {
Quickshell.execDetached(["sh", "-c", onClickedCommand])
updateState()
}
}
onRightClicked: {
if (onRightClickedCommand) {
Quickshell.execDetached(["sh", "-c", onRightClickedCommand])
updateState()
}
}
onMiddleClicked: {
if (onMiddleClickedCommand) {
Quickshell.execDetached(["sh", "-c", onMiddleClickedCommand])
updateState()
}
}
}
@@ -5,66 +5,163 @@ import qs.Widgets
ColumnLayout {
id: root
spacing: Style.marginM
property var widgetData: null
property var widgetMetadata: null
property string valueIcon: widgetData.icon !== undefined ? widgetData.icon : widgetMetadata.icon
property string valueTooltip: widgetData.tooltipText !== undefined ? widgetData.tooltipText : widgetMetadata.tooltipText
QtObject {
id: _settings
property string icon: (widgetData && widgetData.icon !== undefined) ? widgetData.icon : widgetMetadata.icon
property string onStateIcon: (widgetData && widgetData.onStateIcon !== undefined) ? widgetData.onStateIcon : widgetMetadata.onStateIcon
property string onClicked: (widgetData && widgetData.onClicked !== undefined) ? widgetData.onClicked : widgetMetadata.onClicked
property string onRightClicked: (widgetData && widgetData.onRightClicked !== undefined) ? widgetData.onRightClicked : widgetMetadata.onRightClicked
property string onMiddleClicked: (widgetData && widgetData.onMiddleClicked !== undefined) ? widgetData.onMiddleClicked : widgetMetadata.onMiddleClicked
property string onStateCommand: (widgetData && widgetData.onStateCommand !== undefined) ? widgetData.onStateCommand : widgetMetadata.onStateCommand
property string generalTooltipText: (widgetData && widgetData.generalTooltipText !== undefined) ? widgetData.generalTooltipText : widgetMetadata.generalTooltipText
property bool enableOnStateLogic: (widgetData && widgetData.enableOnStateLogic !== undefined) ? widgetData.enableOnStateLogic : widgetMetadata.enableOnStateLogic
}
function saveSettings() {
var settings = Object.assign({}, widgetData || {})
settings.icon = valueIcon
settings.exec = execInput.text
settings.tooltipText = tooltipInput.text
return settings
var saved = {
id: widgetData.id,
icon: _settings.icon,
onStateIcon: _settings.onStateIcon,
onClicked: _settings.onClicked,
onRightClicked: _settings.onRightClicked,
onMiddleClicked: _settings.onMiddleClicked,
onStateCommand: _settings.onStateCommand,
generalTooltipText: _settings.generalTooltipText,
enableOnStateLogic: _settings.enableOnStateLogic
}
return saved
}
RowLayout {
spacing: Style.marginM
NLabel {
label: I18n.tr("settings.control-center.shortcuts.custom-button.icon.label", "Icon")
description: I18n.tr("settings.control-center.shortcuts.custom-button.icon.description", "The icon for the button.")
label: I18n.tr("settings.control-center.shortcuts.custom-button.icon.label")
description: I18n.tr("settings.control-center.shortcuts.custom-button.icon.description")
}
NIcon {
Layout.alignment: Qt.AlignVCenter
icon: valueIcon
icon: _settings.icon || widgetMetadata.icon
pointSize: Style.fontSizeXL
visible: valueIcon !== ""
visible: (_settings.icon || widgetMetadata.icon) !== ""
}
NButton {
text: I18n.tr("settings.control-center.shortcuts.custom-button.browse", "Browse")
text: I18n.tr("settings.control-center.shortcuts.custom-button.browse")
onClicked: iconPicker.open()
}
}
NIconPicker {
id: iconPicker
initialIcon: valueIcon
initialIcon: _settings.icon
onIconSelected: function (iconName) {
valueIcon = iconName
_settings.icon = iconName
}
}
NTextInput {
id: execInput
id: generalTooltipTextInput
Layout.fillWidth: true
label: I18n.tr("settings.control-center.shortcuts.custom-button.command.label", "Command")
description: I18n.tr("settings.control-center.shortcuts.custom-button.command.description", "The command to execute when the button is clicked.")
placeholderText: I18n.tr("placeholders.enter-command")
text: widgetData?.exec || widgetMetadata.exec
label: I18n.tr("settings.control-center.shortcuts.custom-button.general-tooltip-text.label")
description: I18n.tr("settings.control-center.shortcuts.custom-button.general-tooltip-text.description")
placeholderText: I18n.tr("placeholders.enter-text")
text: _settings.generalTooltipText
onTextChanged: _settings.generalTooltipText = text
}
NTextInput {
id: tooltipInput
id: onClickedCommandInput
Layout.fillWidth: true
label: I18n.tr("settings.control-center.shortcuts.custom-button.tooltip.label", "Tooltip")
description: I18n.tr("settings.control-center.shortcuts.custom-button.tooltip.description", "The tooltip to show when hovering over the button.")
placeholderText: I18n.tr("placeholders.enter-tooltip")
text: widgetData?.tooltipText || widgetMetadata.tooltipText
label: I18n.tr("settings.control-center.shortcuts.custom-button.on-clicked.label")
description: I18n.tr("settings.control-center.shortcuts.custom-button.on-clicked.description")
placeholderText: I18n.tr("placeholders.enter-command")
text: _settings.onClicked
onTextChanged: _settings.onClicked = text
}
NTextInput {
id: onRightClickedCommandInput
Layout.fillWidth: true
label: I18n.tr("settings.control-center.shortcuts.custom-button.on-right-clicked.label")
description: I18n.tr("settings.control-center.shortcuts.custom-button.on-right-clicked.description")
placeholderText: I18n.tr("placeholders.enter-command")
text: _settings.onRightClicked
onTextChanged: _settings.onRightClicked = text
}
NTextInput {
id: onMiddleClickedCommandInput
Layout.fillWidth: true
label: I18n.tr("settings.control-center.shortcuts.custom-button.on-middle-clicked.label")
description: I18n.tr("settings.control-center.shortcuts.custom-button.on-middle-clicked.description")
placeholderText: I18n.tr("placeholders.enter-command")
text: _settings.onMiddleClicked
onTextChanged: _settings.onMiddleClicked = text
}
NDivider {}
NToggle {
id: enableOnStateLogicToggle
Layout.fillWidth: true
label: I18n.tr("settings.control-center.shortcuts.custom-button.enable-on-state-logic.label")
description: I18n.tr("settings.control-center.shortcuts.custom-button.enable-on-state-logic.description")
checked: _settings.enableOnStateLogic
onToggled: checked => _settings.enableOnStateLogic = checked
}
// On-State Icon
RowLayout {
Layout.fillWidth: true
spacing: Style.marginS
visible: _settings.enableOnStateLogic
NLabel {
label: I18n.tr("settings.control-center.shortcuts.custom-button.on-state-icon.label")
description: I18n.tr("settings.control-center.shortcuts.custom-button.on-state-icon.description")
}
NIcon {
Layout.alignment: Qt.AlignVCenter
icon: _settings.onStateIcon || widgetMetadata.onStateIcon
pointSize: Style.fontSizeXL
visible: (_settings.onStateIcon || widgetMetadata.onStateIcon) !== ""
}
NButton {
Layout.fillWidth: true
text: I18n.tr("settings.control-center.shortcuts.custom-button.browse")
onClicked: onStateIconPicker.open()
}
}
NIconPicker {
id: onStateIconPicker
initialIcon: _settings.onStateIcon
onIconSelected: function (iconName) {
_settings.onStateIcon = iconName
}
}
NTextInput {
id: onStateCommandInput
Layout.fillWidth: true
label: I18n.tr("settings.control-center.shortcuts.custom-button.on-state-command.label")
description: I18n.tr("settings.control-center.shortcuts.custom-button.on-state-command.description")
placeholderText: I18n.tr("placeholders.enter-command")
text: _settings.onStateCommand
onTextChanged: _settings.onStateCommand = text
enabled: _settings.enableOnStateLogic
visible: _settings.enableOnStateLogic
}
}
+7 -2
View File
@@ -25,8 +25,13 @@ Singleton {
"CustomButton": {
"allowUserSettings": true,
"icon": "heart",
"exec": "",
"tooltipText": "Custom Button"
"onStateIcon": "heart",
"onClicked": "",
"onRightClicked": "",
"onMiddleClicked": "",
"onStateCommand": "",
"generalTooltipText": "Custom Button",
"enableOnStateLogic": false
}
})