From 110bbdf7a3da5b7705121f677e20ecc6678d6d45 Mon Sep 17 00:00:00 2001 From: loner <2788892716@qq.com> Date: Wed, 5 Nov 2025 07:16:59 +0800 Subject: [PATCH 01/11] fix(custom button): Adjust the custom button text display when the bar is vertical --- Modules/Bar/Extras/BarPillVertical.qml | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/Modules/Bar/Extras/BarPillVertical.qml b/Modules/Bar/Extras/BarPillVertical.qml index ea1001a7..421d8402 100644 --- a/Modules/Bar/Extras/BarPillVertical.qml +++ b/Modules/Bar/Extras/BarPillVertical.qml @@ -48,8 +48,8 @@ Item { readonly property int pillHeight: buttonSize readonly property int pillPaddingVertical: 3 * 2 // Very precise adjustment don't replace by Style.margin readonly property int pillOverlap: Math.round(buttonSize * 0.5) - readonly property int maxPillWidth: buttonSize - readonly property int maxPillHeight: Math.max(1, Math.round(textItem.implicitHeight + pillPaddingVertical * 4)) + readonly property int maxPillWidth: Math.max(buttonSize, Math.round(textItem.implicitHeight + pillPaddingVertical * 2)) + readonly property int maxPillHeight: Math.max(1, Math.round(textItem.implicitWidth + pillPaddingVertical * 2 + Math.round(iconCircle.height / 4))) readonly property real iconSize: { switch (root.density) { @@ -109,14 +109,8 @@ Item { id: textItem anchors.horizontalCenter: parent.horizontalCenter anchors.verticalCenter: parent.verticalCenter - anchors.verticalCenterOffset: { - var offset = openDownward ? Math.round(pillPaddingVertical * 0.75) : -Math.round(pillPaddingVertical * 0.75) - if (forceOpen) { - // If its force open, the icon disc background is the same color as the bg pill move text slightly - offset += oppositeDirection ? -Style.marginXXS : Style.marginXXS - } - return offset - } + anchors.verticalCenterOffset: Math.round(iconCircle.height / 4) + rotation: -90 text: root.text + root.suffix family: Settings.data.ui.fontFixed pointSize: textSize @@ -127,7 +121,6 @@ Item { color: forceOpen ? Color.mOnSurface : Color.mPrimary visible: revealed } - Behavior on width { enabled: showAnim.running || hideAnim.running NumberAnimation { From 2f853e3eca2f34cbbdcafccea8a2c34efce29c6d Mon Sep 17 00:00:00 2001 From: loner <2788892716@qq.com> Date: Wed, 5 Nov 2025 07:39:40 +0800 Subject: [PATCH 02/11] feat(bar): Add option to hide CustomButton text in vertical bar --- Assets/Translations/en.json | 4 ++++ Modules/Bar/Widgets/CustomButton.qml | 12 ++++++++---- .../Bar/WidgetSettings/CustomButtonSettings.qml | 9 +++++++++ Services/UI/BarWidgetRegistry.qml | 3 ++- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 818438cc..e258290e 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -119,6 +119,10 @@ "stream-description": "Enter a command to run continuously." }, "dynamic-text": "Dynamic text", + "hide-vertical": { + "description": "If enabled, the text from the command output will not be shown when the bar is in a vertical layout (left or right).", + "label": "Hide text in vertical bar" + }, "icon": { "description": "Select an icon from the library.", "label": "Icon" diff --git a/Modules/Bar/Widgets/CustomButton.qml b/Modules/Bar/Widgets/CustomButton.qml index 7e474fde..1d59f329 100644 --- a/Modules/Bar/Widgets/CustomButton.qml +++ b/Modules/Bar/Widgets/CustomButton.qml @@ -30,7 +30,8 @@ Item { return {} } - // Use settings or defaults from BarWidgetRegistry + readonly property bool isVerticalBar: Settings.data.bar.position === "left" || Settings.data.bar.position === "right" + readonly property string customIcon: widgetSettings.icon || widgetMetadata.icon readonly property string leftClickExec: widgetSettings.leftClickExec || widgetMetadata.leftClickExec readonly property string rightClickExec: widgetSettings.rightClickExec || widgetMetadata.rightClickExec @@ -40,8 +41,11 @@ Item { readonly property int textIntervalMs: widgetSettings.textIntervalMs !== undefined ? widgetSettings.textIntervalMs : (widgetMetadata.textIntervalMs || 3000) readonly property string textCollapse: widgetSettings.textCollapse !== undefined ? widgetSettings.textCollapse : (widgetMetadata.textCollapse || "") readonly property bool parseJson: widgetSettings.parseJson !== undefined ? widgetSettings.parseJson : (widgetMetadata.parseJson || false) + readonly property bool hideTextInVerticalBar: widgetSettings.hideTextInVerticalBar !== undefined ? widgetSettings.hideTextInVerticalBar : (widgetMetadata.hideTextInVerticalBar || false) readonly property bool hasExec: (leftClickExec || rightClickExec || middleClickExec) + readonly property bool shouldShowText: !isVerticalBar || !hideTextInVerticalBar + implicitWidth: pill.width implicitHeight: pill.height @@ -50,7 +54,7 @@ Item { oppositeDirection: BarService.getPillDirection(root) icon: _dynamicIcon !== "" ? _dynamicIcon : customIcon - text: _dynamicText + text: shouldShowText ? _dynamicText : "" density: Settings.data.bar.density autoHide: false forceOpen: _dynamicText !== "" @@ -86,7 +90,7 @@ Item { id: refreshTimer interval: Math.max(250, textIntervalMs) repeat: true - running: !textStream && textCommand && textCommand.length > 0 + running: shouldShowText && !textStream && textCommand && textCommand.length > 0 triggeredOnStart: true onTriggered: root.runTextCommand() } @@ -95,7 +99,7 @@ Item { Timer { id: restartTimer interval: 1000 - running: textStream && !textProc.running + running: shouldShowText && textStream && !textProc.running onTriggered: root.runTextCommand() } diff --git a/Modules/Panels/Settings/Bar/WidgetSettings/CustomButtonSettings.qml b/Modules/Panels/Settings/Bar/WidgetSettings/CustomButtonSettings.qml index 5d11c8de..715e4ef9 100644 --- a/Modules/Panels/Settings/Bar/WidgetSettings/CustomButtonSettings.qml +++ b/Modules/Panels/Settings/Bar/WidgetSettings/CustomButtonSettings.qml @@ -15,6 +15,7 @@ ColumnLayout { property string valueIcon: widgetData.icon !== undefined ? widgetData.icon : widgetMetadata.icon property bool valueTextStream: widgetData.textStream !== undefined ? widgetData.textStream : widgetMetadata.textStream property bool valueParseJson: widgetData.parseJson !== undefined ? widgetData.parseJson : widgetMetadata.parseJson + property bool valueHideTextInVerticalBar: widgetData.hideTextInVerticalBar !== undefined ? widgetData.hideTextInVerticalBar : widgetMetadata.hideTextInVerticalBar function saveSettings() { var settings = Object.assign({}, widgetData || {}) @@ -26,6 +27,7 @@ ColumnLayout { settings.textCollapse = textCollapseInput.text settings.textStream = valueTextStream settings.parseJson = valueParseJson + settings.hideTextInVerticalBar = valueHideTextInVerticalBar settings.textIntervalMs = parseInt(textIntervalInput.text || textIntervalInput.placeholderText, 10) return settings } @@ -94,6 +96,13 @@ ColumnLayout { label: I18n.tr("bar.widget-settings.custom-button.dynamic-text") } + NToggle { + label: I18n.tr("bar.widget-settings.custom-button.hide-vertical.label", "Hide text in vertical bar") + description: I18n.tr("bar.widget-settings.custom-button.hide-vertical.description", "If enabled, the text from the command output will not be shown when the bar is in a vertical layout (left or right).") + checked: valueHideTextInVerticalBar + onToggled: checked => valueHideTextInVerticalBar = checked + } + NToggle { id: textStreamInput label: I18n.tr("bar.widget-settings.custom-button.text-stream.label") diff --git a/Services/UI/BarWidgetRegistry.qml b/Services/UI/BarWidgetRegistry.qml index 5cd91190..89ac49c1 100644 --- a/Services/UI/BarWidgetRegistry.qml +++ b/Services/UI/BarWidgetRegistry.qml @@ -98,7 +98,8 @@ Singleton { "textStream": false, "textIntervalMs": 3000, "textCollapse": "", - "parseJson": false + "parseJson": false, + "hideTextInVerticalBar": false }, "KeyboardLayout": { "allowUserSettings": true, From 0c0e3533083e204ef3f675060861a390dc88ab60 Mon Sep 17 00:00:00 2001 From: loner <2788892716@qq.com> Date: Wed, 5 Nov 2025 07:44:34 +0800 Subject: [PATCH 03/11] i18n(de): Translate CustomButton settings --- Assets/Translations/de.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index a7f33d97..1354ab71 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -119,6 +119,10 @@ "stream-description": "Geben Sie einen Befehl ein, der kontinuierlich ausgeführt werden soll." }, "dynamic-text": "Dynamischer Text", + "hide-vertical": { + "description": "Wenn aktiviert, wird der Text aus der Befehlsausgabe nicht angezeigt, wenn sich die Leiste in einem vertikalen Layout befindet (links oder rechts).", + "label": "Text in vertikaler Leiste ausblenden" + }, "icon": { "description": "Symbol aus der Bibliothek auswählen.", "label": "Symbol" From ba38031b5fa1b28829a07b10a320c99c309f921b Mon Sep 17 00:00:00 2001 From: loner <2788892716@qq.com> Date: Wed, 5 Nov 2025 07:46:29 +0800 Subject: [PATCH 04/11] i18n(es): Translate CustomButton settings --- Assets/Translations/es.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Assets/Translations/es.json b/Assets/Translations/es.json index c5ad8291..36c0dbd8 100644 --- a/Assets/Translations/es.json +++ b/Assets/Translations/es.json @@ -119,6 +119,10 @@ "stream-description": "Introduce un comando para ejecutar continuamente." }, "dynamic-text": "Texto dinámico", + "hide-vertical": { + "description": "Si está activado, el texto de la salida del comando no se mostrará cuando la barra esté en un diseño vertical (izquierda o derecha).", + "label": "Ocultar texto en barra vertical" + }, "icon": { "description": "Selecciona un icono de la biblioteca.", "label": "Icono" From 0432ef7b9bbf1a4676292fe8a704b89cb942fded Mon Sep 17 00:00:00 2001 From: loner <2788892716@qq.com> Date: Wed, 5 Nov 2025 07:48:11 +0800 Subject: [PATCH 05/11] i18n(fr): Translate CustomButton settings --- Assets/Translations/fr.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Assets/Translations/fr.json b/Assets/Translations/fr.json index 937d7299..be8c1eda 100644 --- a/Assets/Translations/fr.json +++ b/Assets/Translations/fr.json @@ -119,6 +119,10 @@ "stream-description": "Entrez une commande à exécuter en continu." }, "dynamic-text": "Texte dynamique", + "hide-vertical": { + "description": "Si activé, le texte de la sortie de la commande ne sera pas affiché lorsque la barre est en disposition verticale (gauche ou droite).", + "label": "Masquer le texte dans la barre verticale" + }, "icon": { "description": "Sélectionnez une icône dans la bibliothèque.", "label": "Icône" From 10b694596640195ea4e1d042efbc9658566eb918 Mon Sep 17 00:00:00 2001 From: loner <2788892716@qq.com> Date: Wed, 5 Nov 2025 07:52:08 +0800 Subject: [PATCH 06/11] i18n(pt): Translate CustomButton settings --- Assets/Translations/pt.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Assets/Translations/pt.json b/Assets/Translations/pt.json index fc3283bf..081a52ba 100644 --- a/Assets/Translations/pt.json +++ b/Assets/Translations/pt.json @@ -119,6 +119,10 @@ "stream-description": "Insira um comando para executar continuamente." }, "dynamic-text": "Texto dinâmico", + "hide-vertical": { + "description": "Se ativado, o texto da saída do comando não será exibido quando a barra estiver em um layout vertical (esquerda ou direita).", + "label": "Ocultar texto na barra vertical" + }, "icon": { "description": "Selecione um ícone da biblioteca.", "label": "Ícone" From 97a9e5a184f857f8f19b58e186b64322d0ec8f3a Mon Sep 17 00:00:00 2001 From: loner <2788892716@qq.com> Date: Wed, 5 Nov 2025 07:53:48 +0800 Subject: [PATCH 07/11] i18n(tr): Translate CustomButton settings --- Assets/Translations/tr.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Assets/Translations/tr.json b/Assets/Translations/tr.json index e235b715..eafc3472 100644 --- a/Assets/Translations/tr.json +++ b/Assets/Translations/tr.json @@ -119,6 +119,10 @@ "stream-description": "Sürekli çalıştırılacak bir komut girin." }, "dynamic-text": "Dinamik metin", + "hide-vertical": { + "description": "Etkinleştirilirse, komut çıktısındaki metin, çubuk dikey düzende (sol veya sağ) olduğunda gösterilmeyecektir.", + "label": "Dikey çubukta metni gizle" + }, "icon": { "description": "Kütüphaneden bir ikon seçin.", "label": "İkon" From 8a5704ab824330f668eebf6daf8365b77e9751f8 Mon Sep 17 00:00:00 2001 From: loner <2788892716@qq.com> Date: Wed, 5 Nov 2025 07:55:16 +0800 Subject: [PATCH 08/11] i18n(uk-UA): Translate CustomButton settings --- Assets/Translations/uk-UA.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Assets/Translations/uk-UA.json b/Assets/Translations/uk-UA.json index 009bf24d..3b35e3d6 100644 --- a/Assets/Translations/uk-UA.json +++ b/Assets/Translations/uk-UA.json @@ -119,6 +119,10 @@ "stream-description": "Введіть команду для безперервного запуску." }, "dynamic-text": "Динамічний текст", + "hide-vertical": { + "description": "Якщо увімкнено, текст з виводу команди не відображатиметься, коли панель знаходиться у вертикальному розташуванні (ліворуч або праворуч).", + "label": "Приховати текст у вертикальній панелі" + }, "icon": { "description": "Вибрати значок з бібліотеки.", "label": "Значок" From ebfd50b20ad47c6fd66e33c128bda68c6fddcecc Mon Sep 17 00:00:00 2001 From: loner <2788892716@qq.com> Date: Wed, 5 Nov 2025 07:56:13 +0800 Subject: [PATCH 09/11] i18n(zh-CN): Translate CustomButton settings --- Assets/Translations/zh-CN.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Assets/Translations/zh-CN.json b/Assets/Translations/zh-CN.json index 71c9b99f..d0d2d154 100644 --- a/Assets/Translations/zh-CN.json +++ b/Assets/Translations/zh-CN.json @@ -119,6 +119,10 @@ "stream-description": "输入一个要持续运行的命令。" }, "dynamic-text": "动态文本", + "hide-vertical": { + "description": "如果启用,当栏处于垂直布局(左或右)时,将不显示命令输出的文本。", + "label": "在垂直栏中隐藏文本" + }, "icon": { "description": "从库中选择图标。", "label": "图标" From b37f4d4268bd90ca23ce95a4612241a753753377 Mon Sep 17 00:00:00 2001 From: loner <2788892716@qq.com> Date: Sat, 8 Nov 2025 08:27:35 +0800 Subject: [PATCH 10/11] feat: Add dynamic tooltip parsing to CustomButton --- Modules/Bar/Widgets/CustomButton.qml | 55 ++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/Modules/Bar/Widgets/CustomButton.qml b/Modules/Bar/Widgets/CustomButton.qml index 1d59f329..741eb786 100644 --- a/Modules/Bar/Widgets/CustomButton.qml +++ b/Modules/Bar/Widgets/CustomButton.qml @@ -59,20 +59,31 @@ Item { autoHide: false forceOpen: _dynamicText !== "" tooltipText: { - if (!hasExec) { - return "Custom button, configure in settings." - } else { - var lines = [] + var tooltipLines = [] + + if (hasExec) { if (leftClickExec !== "") { - lines.push(`Left click: ${leftClickExec}.`) + tooltipLines.push(`Left click: ${leftClickExec}.`) } if (rightClickExec !== "") { - lines.push(`Right click: ${rightClickExec}.`) + tooltipLines.push(`Right click: ${rightClickExec}.`) } if (middleClickExec !== "") { - lines.push(`Middle click: ${middleClickExec}.`) + tooltipLines.push(`Middle click: ${middleClickExec}.`) } - return lines.join("\n") + } + + if (_dynamicTooltip !== "") { + if (tooltipLines.length > 0) { + tooltipLines.push("") + } + tooltipLines.push(_dynamicTooltip) + } + + if (tooltipLines.length === 0) { + return "Custom button, configure in settings." + } else { + return tooltipLines.join("\n") } } @@ -84,6 +95,7 @@ Item { // Internal state for dynamic text property string _dynamicText: "" property string _dynamicIcon: "" + property string _dynamicTooltip: "" // Periodically run the text command (if set) Timer { @@ -127,38 +139,49 @@ Item { function parseDynamicContent(content) { var contentStr = String(content || "").trim() - if (contentStr.indexOf("\n") !== -1) { - contentStr = contentStr.split("\n")[0] - } if (parseJson) { + var lineToParse = contentStr + + if (!textStream && contentStr.includes('\n')) { + const lines = contentStr.split('\n').filter(line => line.trim() !== '') + if (lines.length > 0) { + lineToParse = lines[lines.length - 1] + } + } + try { - var parsed = JSON.parse(contentStr) - var text = parsed.text || "" + const parsed = JSON.parse(lineToParse) + const text = parsed.text || "" + const icon = parsed.icon || "" + const tooltip = parsed.tooltip || "" if (checkCollapse(text)) { _dynamicText = "" _dynamicIcon = "" + _dynamicTooltip = "" return } _dynamicText = text - _dynamicIcon = parsed.icon || "" + _dynamicIcon = icon + _dynamicTooltip = tooltip return } catch (e) { - - // Not a valid JSON, treat as plain text + Logger.w("CustomButton", `Failed to parse JSON. Content: "${lineToParse}"`) } } if (checkCollapse(contentStr)) { _dynamicText = "" _dynamicIcon = "" + _dynamicTooltip = "" return } _dynamicText = contentStr _dynamicIcon = "" + _dynamicTooltip = "" } function checkCollapse(text) { From 54dad12a70bf0ff00e212cac2a5872585f53fca0 Mon Sep 17 00:00:00 2001 From: loner <2788892716@qq.com> Date: Sat, 8 Nov 2025 12:13:18 +0800 Subject: [PATCH 11/11] feat(bar): Add conditional text rotation for BarPillVertical --- Modules/Bar/Extras/BarPill.qml | 2 ++ Modules/Bar/Extras/BarPillVertical.qml | 17 +++++++++++++---- Modules/Bar/Widgets/CustomButton.qml | 1 + 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Modules/Bar/Extras/BarPill.qml b/Modules/Bar/Extras/BarPill.qml index d5befb21..a8c097cf 100644 --- a/Modules/Bar/Extras/BarPill.qml +++ b/Modules/Bar/Extras/BarPill.qml @@ -17,6 +17,7 @@ Item { property bool forceClose: false property bool oppositeDirection: false property bool hovered: false + property bool rotateText: false readonly property string barPosition: Settings.data.bar.position readonly property bool isVerticalBar: barPosition === "left" || barPosition === "right" @@ -52,6 +53,7 @@ Item { oppositeDirection: root.oppositeDirection hovered: root.hovered density: root.density + rotateText: root.rotateText onShown: root.shown() onHidden: root.hidden() onEntered: root.entered() diff --git a/Modules/Bar/Extras/BarPillVertical.qml b/Modules/Bar/Extras/BarPillVertical.qml index 421d8402..ecd170f1 100644 --- a/Modules/Bar/Extras/BarPillVertical.qml +++ b/Modules/Bar/Extras/BarPillVertical.qml @@ -18,6 +18,7 @@ Item { property bool forceClose: false property bool oppositeDirection: false property bool hovered: false + property bool rotateText: false // Bar position detection for pill direction readonly property string barPosition: Settings.data.bar.position @@ -48,8 +49,8 @@ Item { readonly property int pillHeight: buttonSize readonly property int pillPaddingVertical: 3 * 2 // Very precise adjustment don't replace by Style.margin readonly property int pillOverlap: Math.round(buttonSize * 0.5) - readonly property int maxPillWidth: Math.max(buttonSize, Math.round(textItem.implicitHeight + pillPaddingVertical * 2)) - readonly property int maxPillHeight: Math.max(1, Math.round(textItem.implicitWidth + pillPaddingVertical * 2 + Math.round(iconCircle.height / 4))) + readonly property int maxPillWidth: rotateText ? Math.max(buttonSize, Math.round(textItem.implicitHeight + pillPaddingVertical * 2)) : buttonSize + readonly property int maxPillHeight: rotateText ? Math.max(1, Math.round(textItem.implicitWidth + pillPaddingVertical * 2 + Math.round(iconCircle.height / 4))) : Math.max(1, Math.round(textItem.implicitHeight + pillPaddingVertical * 4)) readonly property real iconSize: { switch (root.density) { @@ -109,8 +110,8 @@ Item { id: textItem anchors.horizontalCenter: parent.horizontalCenter anchors.verticalCenter: parent.verticalCenter - anchors.verticalCenterOffset: Math.round(iconCircle.height / 4) - rotation: -90 + anchors.verticalCenterOffset: rotateText ? Math.round(iconCircle.height / 4) : getVerticalCenterOffset() + rotation: rotateText ? -90 : 0 text: root.text + root.suffix family: Settings.data.ui.fontFixed pointSize: textSize @@ -120,6 +121,14 @@ Item { verticalAlignment: Text.AlignVCenter color: forceOpen ? Color.mOnSurface : Color.mPrimary visible: revealed + + function getVerticalCenterOffset() { + var offset = openDownward ? Math.round(pillPaddingVertical * 0.75) : -Math.round(pillPaddingVertical * 0.75) + if (forceOpen) { + offset += oppositeDirection ? -Style.marginXXS : Style.marginXXS + } + return offset + } } Behavior on width { enabled: showAnim.running || hideAnim.running diff --git a/Modules/Bar/Widgets/CustomButton.qml b/Modules/Bar/Widgets/CustomButton.qml index 741eb786..3e67fb0c 100644 --- a/Modules/Bar/Widgets/CustomButton.qml +++ b/Modules/Bar/Widgets/CustomButton.qml @@ -56,6 +56,7 @@ Item { icon: _dynamicIcon !== "" ? _dynamicIcon : customIcon text: shouldShowText ? _dynamicText : "" density: Settings.data.bar.density + rotateText: isVerticalBar && !hideTextInVerticalBar autoHide: false forceOpen: _dynamicText !== "" tooltipText: {