From b267b74e8be45ae6a3737cc0b9c04be5280a227f Mon Sep 17 00:00:00 2001 From: EinBowser <146022965+EinBowser@users.noreply.github.com> Date: Sat, 1 Nov 2025 20:50:39 +0100 Subject: [PATCH 01/10] Added battery health and made it configurable --- .../ii/modules/bar/BatteryPopup.qml | 23 +++++++++++++++++++ .../quickshell/ii/modules/common/Config.qml | 1 + .../ii/scripts/battery/calculate_health.sh | 11 +++++++++ .../quickshell/ii/services/Battery.qml | 23 +++++++++++++++++++ 4 files changed, 58 insertions(+) create mode 100644 dots/.config/quickshell/ii/scripts/battery/calculate_health.sh diff --git a/dots/.config/quickshell/ii/modules/bar/BatteryPopup.qml b/dots/.config/quickshell/ii/modules/bar/BatteryPopup.qml index 5bc07d18c..72523393d 100644 --- a/dots/.config/quickshell/ii/modules/bar/BatteryPopup.qml +++ b/dots/.config/quickshell/ii/modules/bar/BatteryPopup.qml @@ -63,6 +63,29 @@ StyledPopup { text: Battery.isCharging ? Translation.tr("Time to full:") : Translation.tr("Time to empty:") color: Appearance.colors.colOnSurfaceVariant } + RowLayout { + spacing: 5 + visible: Config.options.battery.showHealth + Layout.fillWidth: true + + MaterialSymbol { + text: "healing" + color: Appearance.colors.colOnSurfaceVariant + iconSize: Appearance.font.pixelSize.large + } + + StyledText { + text: Translation.tr("Health:") + color: Appearance.colors.colOnSurfaceVariant + } + + StyledText { + Layout.fillWidth: true + horizontalAlignment: Text.AlignRight + color: Appearance.colors.colOnSurfaceVariant + text: `${(Battery.health).toFixed(1)}%` + } + } StyledText { Layout.fillWidth: true horizontalAlignment: Text.AlignRight diff --git a/dots/.config/quickshell/ii/modules/common/Config.qml b/dots/.config/quickshell/ii/modules/common/Config.qml index 39c0ef131..854a059ab 100644 --- a/dots/.config/quickshell/ii/modules/common/Config.qml +++ b/dots/.config/quickshell/ii/modules/common/Config.qml @@ -257,6 +257,7 @@ Singleton { property int full: 101 property bool automaticSuspend: true property int suspend: 3 + property bool showHealth: true } property JsonObject conflictKiller: JsonObject { diff --git a/dots/.config/quickshell/ii/scripts/battery/calculate_health.sh b/dots/.config/quickshell/ii/scripts/battery/calculate_health.sh new file mode 100644 index 000000000..58a4b1d4d --- /dev/null +++ b/dots/.config/quickshell/ii/scripts/battery/calculate_health.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +# This just guesses that the BAT0 is the actuall battery +full=$(cat /sys/class/power_supply/BAT0/charge_full) +design=$(cat /sys/class/power_supply/BAT0/charge_full_design) + +if [ "$design" -gt 0 ]; then # basically if design > 0 + awk "BEGIN { printf \"%.1f\n\", ($full/$design)*100 }" +else + echo "Error" +fi \ No newline at end of file diff --git a/dots/.config/quickshell/ii/services/Battery.qml b/dots/.config/quickshell/ii/services/Battery.qml index b07bd5305..8ff75da10 100644 --- a/dots/.config/quickshell/ii/services/Battery.qml +++ b/dots/.config/quickshell/ii/services/Battery.qml @@ -31,6 +31,29 @@ Singleton { property real timeToEmpty: UPower.displayDevice.timeToEmpty property real timeToFull: UPower.displayDevice.timeToFull + property real health: 0 + Process { + id: batteryProcess + running: Config.options.battery.showHealth + command: [ + "bash", + `${FileUtils.trimFileProtocol(Directories.scriptPath)}/battery/calculate-health.sh` + ] + + stdout: StdioCollector { + onStreamFinished: { + const output = text.trim() + const value = Number(output) + if (!isNaN(value)) { + root.health = value + console.log("Battery health:", value) + } else { + console.warn("Battery script output invalid:", output) + } + } + } + } + onIsLowAndNotChargingChanged: { if (!root.available || !isLowAndNotCharging) return; Quickshell.execDetached([ From ca7d6c8ae0ded1b5678c0baeb55f5503bcc69ef2 Mon Sep 17 00:00:00 2001 From: EinBowser <146022965+EinBowser@users.noreply.github.com> Date: Sat, 1 Nov 2025 22:11:39 +0100 Subject: [PATCH 02/10] Added config toggle to settings --- .../quickshell/ii/modules/settings/GeneralConfig.qml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dots/.config/quickshell/ii/modules/settings/GeneralConfig.qml b/dots/.config/quickshell/ii/modules/settings/GeneralConfig.qml index c2ea1f930..3be552b9c 100644 --- a/dots/.config/quickshell/ii/modules/settings/GeneralConfig.qml +++ b/dots/.config/quickshell/ii/modules/settings/GeneralConfig.qml @@ -127,6 +127,14 @@ ContentPage { } } } + ConfigSwitch { + buttonIcon: "healing" + text: Translation.tr('Show battery health in popup') + checked: Config.options.battery.showHealth + onCheckedChanged: { + Config.options.battery.showHealth = checked; + } + } } ContentSection { From 6676d5844bd5db542e491c1027ccebce30efc293 Mon Sep 17 00:00:00 2001 From: EinBowser <146022965+EinBowser@users.noreply.github.com> Date: Sat, 1 Nov 2025 22:22:58 +0100 Subject: [PATCH 03/10] changed the script to the right name, added some info and removed unnecesary debug --- .../battery/{calculate_health.sh => calculate-health.sh} | 7 ++++++- dots/.config/quickshell/ii/services/Battery.qml | 1 - 2 files changed, 6 insertions(+), 2 deletions(-) rename dots/.config/quickshell/ii/scripts/battery/{calculate_health.sh => calculate-health.sh} (53%) diff --git a/dots/.config/quickshell/ii/scripts/battery/calculate_health.sh b/dots/.config/quickshell/ii/scripts/battery/calculate-health.sh similarity index 53% rename from dots/.config/quickshell/ii/scripts/battery/calculate_health.sh rename to dots/.config/quickshell/ii/scripts/battery/calculate-health.sh index 58a4b1d4d..83b52a5a0 100644 --- a/dots/.config/quickshell/ii/scripts/battery/calculate_health.sh +++ b/dots/.config/quickshell/ii/scripts/battery/calculate-health.sh @@ -1,6 +1,7 @@ #!/bin/bash # This just guesses that the BAT0 is the actuall battery +# because BAT0 is the default for modern systems full=$(cat /sys/class/power_supply/BAT0/charge_full) design=$(cat /sys/class/power_supply/BAT0/charge_full_design) @@ -8,4 +9,8 @@ if [ "$design" -gt 0 ]; then # basically if design > 0 awk "BEGIN { printf \"%.1f\n\", ($full/$design)*100 }" else echo "Error" -fi \ No newline at end of file +fi + +# If you have any issues try to find your "real" battery. +# Run 'ls /sys/class/power_supply'. You may see BATM or BAT1 and no BAT0 +# You can check what is what my running 'cat /sys/class/power_supply/{whatever_you_got}/model_name' diff --git a/dots/.config/quickshell/ii/services/Battery.qml b/dots/.config/quickshell/ii/services/Battery.qml index 8ff75da10..caa0ab9fe 100644 --- a/dots/.config/quickshell/ii/services/Battery.qml +++ b/dots/.config/quickshell/ii/services/Battery.qml @@ -46,7 +46,6 @@ Singleton { const value = Number(output) if (!isNaN(value)) { root.health = value - console.log("Battery health:", value) } else { console.warn("Battery script output invalid:", output) } From 0e63e698f26a3c8afc22a8f0708a6c3895a46944 Mon Sep 17 00:00:00 2001 From: EinBowser <146022965+EinBowser@users.noreply.github.com> Date: Sat, 1 Nov 2025 23:26:36 +0100 Subject: [PATCH 04/10] Wrong position and forgot an import --- .../ii/modules/bar/BatteryPopup.qml | 43 ++++++++++--------- .../quickshell/ii/services/Battery.qml | 1 + 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/bar/BatteryPopup.qml b/dots/.config/quickshell/ii/modules/bar/BatteryPopup.qml index 72523393d..bba4c422c 100644 --- a/dots/.config/quickshell/ii/modules/bar/BatteryPopup.qml +++ b/dots/.config/quickshell/ii/modules/bar/BatteryPopup.qml @@ -63,7 +63,28 @@ StyledPopup { text: Battery.isCharging ? Translation.tr("Time to full:") : Translation.tr("Time to empty:") color: Appearance.colors.colOnSurfaceVariant } - RowLayout { + StyledText { + Layout.fillWidth: true + horizontalAlignment: Text.AlignRight + color: Appearance.colors.colOnSurfaceVariant + text: { + function formatTime(seconds) { + var h = Math.floor(seconds / 3600); + var m = Math.floor((seconds % 3600) / 60); + if (h > 0) + return `${h}h, ${m}m`; + else + return `${m}m`; + } + if (Battery.isCharging) + return formatTime(Battery.timeToFull); + else + return formatTime(Battery.timeToEmpty); + } + } + } + + RowLayout { spacing: 5 visible: Config.options.battery.showHealth Layout.fillWidth: true @@ -86,26 +107,6 @@ StyledPopup { text: `${(Battery.health).toFixed(1)}%` } } - StyledText { - Layout.fillWidth: true - horizontalAlignment: Text.AlignRight - color: Appearance.colors.colOnSurfaceVariant - text: { - function formatTime(seconds) { - var h = Math.floor(seconds / 3600); - var m = Math.floor((seconds % 3600) / 60); - if (h > 0) - return `${h}h, ${m}m`; - else - return `${m}m`; - } - if (Battery.isCharging) - return formatTime(Battery.timeToFull); - else - return formatTime(Battery.timeToEmpty); - } - } - } RowLayout { spacing: 5 diff --git a/dots/.config/quickshell/ii/services/Battery.qml b/dots/.config/quickshell/ii/services/Battery.qml index caa0ab9fe..a3f45ac77 100644 --- a/dots/.config/quickshell/ii/services/Battery.qml +++ b/dots/.config/quickshell/ii/services/Battery.qml @@ -6,6 +6,7 @@ import Quickshell import Quickshell.Services.UPower import QtQuick import Quickshell.Io +import qs.modules.common.functions Singleton { id: root From 8a208242663868464e696ecfce0e0520adf7b86a Mon Sep 17 00:00:00 2001 From: EinBowser <146022965+EinBowser@users.noreply.github.com> Date: Sat, 1 Nov 2025 23:32:08 +0100 Subject: [PATCH 05/10] Disabled by default --- dots/.config/quickshell/ii/modules/common/Config.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dots/.config/quickshell/ii/modules/common/Config.qml b/dots/.config/quickshell/ii/modules/common/Config.qml index 854a059ab..7e82e87d0 100644 --- a/dots/.config/quickshell/ii/modules/common/Config.qml +++ b/dots/.config/quickshell/ii/modules/common/Config.qml @@ -257,7 +257,7 @@ Singleton { property int full: 101 property bool automaticSuspend: true property int suspend: 3 - property bool showHealth: true + property bool showHealth: false } property JsonObject conflictKiller: JsonObject { From a323e32a4290b2e861f1d1a65dc581f03c5a5ef0 Mon Sep 17 00:00:00 2001 From: EinBowser <146022965+EinBowser@users.noreply.github.com> Date: Mon, 3 Nov 2025 20:53:40 +0100 Subject: [PATCH 06/10] Removed helper script and made workaround in qml --- .../ii/scripts/battery/calculate-health.sh | 16 --------- .../quickshell/ii/services/Battery.qml | 34 ++++++++++--------- 2 files changed, 18 insertions(+), 32 deletions(-) delete mode 100644 dots/.config/quickshell/ii/scripts/battery/calculate-health.sh diff --git a/dots/.config/quickshell/ii/scripts/battery/calculate-health.sh b/dots/.config/quickshell/ii/scripts/battery/calculate-health.sh deleted file mode 100644 index 83b52a5a0..000000000 --- a/dots/.config/quickshell/ii/scripts/battery/calculate-health.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -# This just guesses that the BAT0 is the actuall battery -# because BAT0 is the default for modern systems -full=$(cat /sys/class/power_supply/BAT0/charge_full) -design=$(cat /sys/class/power_supply/BAT0/charge_full_design) - -if [ "$design" -gt 0 ]; then # basically if design > 0 - awk "BEGIN { printf \"%.1f\n\", ($full/$design)*100 }" -else - echo "Error" -fi - -# If you have any issues try to find your "real" battery. -# Run 'ls /sys/class/power_supply'. You may see BATM or BAT1 and no BAT0 -# You can check what is what my running 'cat /sys/class/power_supply/{whatever_you_got}/model_name' diff --git a/dots/.config/quickshell/ii/services/Battery.qml b/dots/.config/quickshell/ii/services/Battery.qml index a3f45ac77..0875bbe70 100644 --- a/dots/.config/quickshell/ii/services/Battery.qml +++ b/dots/.config/quickshell/ii/services/Battery.qml @@ -32,27 +32,29 @@ Singleton { property real timeToEmpty: UPower.displayDevice.timeToEmpty property real timeToFull: UPower.displayDevice.timeToFull - property real health: 0 - Process { - id: batteryProcess - running: Config.options.battery.showHealth - command: [ - "bash", - `${FileUtils.trimFileProtocol(Directories.scriptPath)}/battery/calculate-health.sh` - ] + property real health: (function() { + if (!Config.options.battery.showHealth) { + return 0; + } - stdout: StdioCollector { - onStreamFinished: { - const output = text.trim() - const value = Number(output) - if (!isNaN(value)) { - root.health = value + const devList = UPower.devices.values; + for (let i = 0; i < devList.length; ++i) { + const dev = devList[i]; + if (dev.isLaptopBattery && dev.healthSupported) { + const health = dev.healthPercentage; + if (health === 0) { + return 0; + } else if (health < 1) { + return health * 100; } else { - console.warn("Battery script output invalid:", output) + return health; } } } - } + return 0; + })() + + onIsLowAndNotChargingChanged: { if (!root.available || !isLowAndNotCharging) return; From c0d64c463037f59cbc95b06a4c5e8c38cc15534c Mon Sep 17 00:00:00 2001 From: EinBowser <146022965+EinBowser@users.noreply.github.com> Date: Mon, 3 Nov 2025 20:55:17 +0100 Subject: [PATCH 07/10] Forgot to delete unnecessary import --- dots/.config/quickshell/ii/services/Battery.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/dots/.config/quickshell/ii/services/Battery.qml b/dots/.config/quickshell/ii/services/Battery.qml index 0875bbe70..39aa720ab 100644 --- a/dots/.config/quickshell/ii/services/Battery.qml +++ b/dots/.config/quickshell/ii/services/Battery.qml @@ -6,7 +6,6 @@ import Quickshell import Quickshell.Services.UPower import QtQuick import Quickshell.Io -import qs.modules.common.functions Singleton { id: root From c1ff57c3d043d995a1f9a4b85451b9d7ee09e42f Mon Sep 17 00:00:00 2001 From: EinBowser <146022965+EinBowser@users.noreply.github.com> Date: Tue, 4 Nov 2025 14:20:23 +0100 Subject: [PATCH 08/10] Don't display when unsupported --- dots/.config/quickshell/ii/modules/bar/BatteryPopup.qml | 2 +- dots/.config/quickshell/ii/services/Battery.qml | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/bar/BatteryPopup.qml b/dots/.config/quickshell/ii/modules/bar/BatteryPopup.qml index bba4c422c..6e4bf1c9e 100644 --- a/dots/.config/quickshell/ii/modules/bar/BatteryPopup.qml +++ b/dots/.config/quickshell/ii/modules/bar/BatteryPopup.qml @@ -86,7 +86,7 @@ StyledPopup { RowLayout { spacing: 5 - visible: Config.options.battery.showHealth + visible: Config.options.battery.showHealth && Battery.health > 0 Layout.fillWidth: true MaterialSymbol { diff --git a/dots/.config/quickshell/ii/services/Battery.qml b/dots/.config/quickshell/ii/services/Battery.qml index 39aa720ab..849870cd2 100644 --- a/dots/.config/quickshell/ii/services/Battery.qml +++ b/dots/.config/quickshell/ii/services/Battery.qml @@ -35,14 +35,13 @@ Singleton { if (!Config.options.battery.showHealth) { return 0; } - const devList = UPower.devices.values; for (let i = 0; i < devList.length; ++i) { const dev = devList[i]; if (dev.isLaptopBattery && dev.healthSupported) { const health = dev.healthPercentage; if (health === 0) { - return 0; + return 0.01; } else if (health < 1) { return health * 100; } else { @@ -54,7 +53,6 @@ Singleton { })() - onIsLowAndNotChargingChanged: { if (!root.available || !isLowAndNotCharging) return; Quickshell.execDetached([ From 31f2184dc67984fd127041c02e0d32acb472ae86 Mon Sep 17 00:00:00 2001 From: EinBowser <146022965+EinBowser@users.noreply.github.com> Date: Tue, 4 Nov 2025 15:58:01 +0100 Subject: [PATCH 09/10] Removed settings and configs for battery health --- dots/.config/quickshell/ii/modules/bar/BatteryPopup.qml | 2 +- dots/.config/quickshell/ii/modules/common/Config.qml | 1 - .../quickshell/ii/modules/settings/GeneralConfig.qml | 8 -------- dots/.config/quickshell/ii/services/Battery.qml | 3 --- 4 files changed, 1 insertion(+), 13 deletions(-) diff --git a/dots/.config/quickshell/ii/modules/bar/BatteryPopup.qml b/dots/.config/quickshell/ii/modules/bar/BatteryPopup.qml index 6e4bf1c9e..47345ee1f 100644 --- a/dots/.config/quickshell/ii/modules/bar/BatteryPopup.qml +++ b/dots/.config/quickshell/ii/modules/bar/BatteryPopup.qml @@ -86,7 +86,7 @@ StyledPopup { RowLayout { spacing: 5 - visible: Config.options.battery.showHealth && Battery.health > 0 + visible: Battery.health > 0 Layout.fillWidth: true MaterialSymbol { diff --git a/dots/.config/quickshell/ii/modules/common/Config.qml b/dots/.config/quickshell/ii/modules/common/Config.qml index 7e82e87d0..39c0ef131 100644 --- a/dots/.config/quickshell/ii/modules/common/Config.qml +++ b/dots/.config/quickshell/ii/modules/common/Config.qml @@ -257,7 +257,6 @@ Singleton { property int full: 101 property bool automaticSuspend: true property int suspend: 3 - property bool showHealth: false } property JsonObject conflictKiller: JsonObject { diff --git a/dots/.config/quickshell/ii/modules/settings/GeneralConfig.qml b/dots/.config/quickshell/ii/modules/settings/GeneralConfig.qml index 3be552b9c..c2ea1f930 100644 --- a/dots/.config/quickshell/ii/modules/settings/GeneralConfig.qml +++ b/dots/.config/quickshell/ii/modules/settings/GeneralConfig.qml @@ -127,14 +127,6 @@ ContentPage { } } } - ConfigSwitch { - buttonIcon: "healing" - text: Translation.tr('Show battery health in popup') - checked: Config.options.battery.showHealth - onCheckedChanged: { - Config.options.battery.showHealth = checked; - } - } } ContentSection { diff --git a/dots/.config/quickshell/ii/services/Battery.qml b/dots/.config/quickshell/ii/services/Battery.qml index 849870cd2..f368b8203 100644 --- a/dots/.config/quickshell/ii/services/Battery.qml +++ b/dots/.config/quickshell/ii/services/Battery.qml @@ -32,9 +32,6 @@ Singleton { property real timeToFull: UPower.displayDevice.timeToFull property real health: (function() { - if (!Config.options.battery.showHealth) { - return 0; - } const devList = UPower.devices.values; for (let i = 0; i < devList.length; ++i) { const dev = devList[i]; From 2f1c66570f5ed0135b368cba5bf9b6e81f8e70f4 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Thu, 6 Nov 2025 21:14:51 +0100 Subject: [PATCH 10/10] Change battery health icon from 'healing' to 'heart_check' --- dots/.config/quickshell/ii/modules/bar/BatteryPopup.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dots/.config/quickshell/ii/modules/bar/BatteryPopup.qml b/dots/.config/quickshell/ii/modules/bar/BatteryPopup.qml index 47345ee1f..037313e3f 100644 --- a/dots/.config/quickshell/ii/modules/bar/BatteryPopup.qml +++ b/dots/.config/quickshell/ii/modules/bar/BatteryPopup.qml @@ -90,7 +90,7 @@ StyledPopup { Layout.fillWidth: true MaterialSymbol { - text: "healing" + text: "heart_check" color: Appearance.colors.colOnSurfaceVariant iconSize: Appearance.font.pixelSize.large }