feat(bar): add context menu for CustomButton right-click

- Show context menu instead of directly opening settings when no command is set
- Context menu includes widget-settings option
- Matches behavior of other bar widgets
This commit is contained in:
loner
2026-04-06 09:14:00 +08:00
parent b8a7c2f77d
commit cfc96dd3e7
4 changed files with 55 additions and 32 deletions
+31 -8
View File
@@ -12,6 +12,27 @@ import qs.Widgets
Item {
id: root
NPopupContextMenu {
id: contextMenu
model: [
{
"label": I18n.tr("actions.widget-settings"),
"action": "widget-settings",
"icon": "settings"
},
]
onTriggered: action => {
contextMenu.close();
PanelService.closeContextMenu(screen);
if (action === "widget-settings") {
BarService.openWidgetSettings(screen, section, sectionWidgetIndex, widgetId, widgetSettings);
}
}
}
property ShellScreen screen
// Widget properties passed from Bar.qml for per-instance settings
@@ -425,21 +446,23 @@ Item {
const text = parsed.text || "";
const icon = parsed.icon || "";
let tooltip = parsed.tooltip || "";
// Support both "color" (legacy) and "iconColor"/"textColor" (new)
const legacyColor = parsed.color || "";
const iconColorKey = parsed.iconColor || "";
const textColorKey = parsed.textColor || "";
const validColors = ["primary", "secondary", "tertiary", "error", "none"];
// Helper to resolve color: legacy > specific > none
function resolveColor(legacy, specific) {
if (legacy && validColors.includes(legacy)) return legacy;
if (specific && validColors.includes(specific)) return specific;
if (legacy && validColors.includes(legacy))
return legacy;
if (specific && validColors.includes(specific))
return specific;
return "";
}
const resolvedIconColor = resolveColor(legacyColor, iconColorKey);
const resolvedTextColor = resolveColor(legacyColor, textColorKey);
@@ -553,8 +576,8 @@ Item {
if (rightClickExec) {
Quickshell.execDetached(["sh", "-lc", rightClickExec]);
Logger.i("CustomButton", `Executing command: ${rightClickExec}`);
} else if (!rightClickUpdateText) {
BarService.openWidgetSettings(screen, section, sectionWidgetIndex, widgetId, widgetSettings);
} else {
PanelService.showContextMenu(contextMenu, pill, screen);
}
if (!textStream && rightClickUpdateText) {
runTextCommand();
+1 -1
View File
@@ -74,7 +74,7 @@ SmartPanel {
id: playerContent
anchors.fill: parent
property real contentPreferredHeight: mainLayout.implicitHeight + Style.margin2L;
property real contentPreferredHeight: mainLayout.implicitHeight + Style.margin2L
property Component visualizerSource: {
switch (root.visualizerType) {
@@ -122,29 +122,29 @@ ColumnLayout {
label: I18n.tr("bar.custom-button.icon-position-label")
description: I18n.tr("bar.custom-button.icon-position-description")
model: barIsVertical ? [
{
name: I18n.tr("bar.custom-button.icon-position-top"),
key: "left"
},
{
name: I18n.tr("bar.custom-button.icon-position-bottom"),
key: "right"
}
] : [
{
name: I18n.tr("bar.custom-button.icon-position-left"),
key: "left"
},
{
name: I18n.tr("bar.custom-button.icon-position-right"),
key: "right"
}
]
{
name: I18n.tr("bar.custom-button.icon-position-top"),
key: "left"
},
{
name: I18n.tr("bar.custom-button.icon-position-bottom"),
key: "right"
}
] : [
{
name: I18n.tr("bar.custom-button.icon-position-left"),
key: "left"
},
{
name: I18n.tr("bar.custom-button.icon-position-right"),
key: "right"
}
]
currentKey: valueIconPosition
onSelected: key => {
valueIconPosition = key;
saveSettings();
}
valueIconPosition = key;
saveSettings();
}
defaultValue: widgetMetadata.iconPosition
}