quickshell: add estimated time remaining to battery dropdown

Reads energy_now/energy_full to calculate hours remaining.
Shows "Xh Ym left" when discharging, "Xh Ym to full" when
charging, alongside the wattage draw.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
rope 2026-05-26 17:22:05 +01:00
parent dca7d49a5f
commit 1d45734a04

View file

@ -683,6 +683,9 @@ in
property bool charging: false
property string batteryIcon: "\u{f008e}"
property real powerDraw: 0.0
property real energyNow: 0.0
property real energyFull: 0.0
property string timeRemaining: ""
property string powerProfile: "balanced"
function updateIcon() {
@ -705,21 +708,38 @@ in
Process {
id: batteryProc
command: ["sh", "-c", "cat /sys/class/power_supply/BAT0/capacity; cat /sys/class/power_supply/BAT0/status; cat /sys/class/power_supply/BAT0/power_now 2>/dev/null || echo 0"]
command: ["sh", "-c", "cat /sys/class/power_supply/BAT0/capacity; cat /sys/class/power_supply/BAT0/status; cat /sys/class/power_supply/BAT0/power_now 2>/dev/null || echo 0; cat /sys/class/power_supply/BAT0/energy_now 2>/dev/null || echo 0; cat /sys/class/power_supply/BAT0/energy_full 2>/dev/null || echo 0"]
stdout: SplitParser {
property int lineNum: 0
onRead: data => {
let trimmed = data.trim();
let num = parseInt(trimmed);
lineNum++;
if (lineNum === 1) {
let num = parseInt(trimmed);
if (!isNaN(num)) batteryWidget.batteryLevel = num;
} else if (lineNum === 2) {
batteryWidget.charging = (trimmed === "Charging");
} else if (lineNum === 3) {
let uw = parseInt(trimmed);
if (!isNaN(uw)) batteryWidget.powerDraw = uw / 1000000.0;
if (!isNaN(num)) batteryWidget.powerDraw = num / 1000000.0;
} else if (lineNum === 4) {
if (!isNaN(num)) batteryWidget.energyNow = num / 1000000.0;
} else if (lineNum === 5) {
if (!isNaN(num)) batteryWidget.energyFull = num / 1000000.0;
lineNum = 0;
// Calculate time remaining
if (batteryWidget.powerDraw > 0.5) {
let hours;
if (batteryWidget.charging) {
hours = (batteryWidget.energyFull - batteryWidget.energyNow) / batteryWidget.powerDraw;
} else {
hours = batteryWidget.energyNow / batteryWidget.powerDraw;
}
let h = Math.floor(hours);
let m = Math.round((hours - h) * 60);
batteryWidget.timeRemaining = h + "h " + m + "m";
} else {
batteryWidget.timeRemaining = "";
}
}
batteryWidget.updateIcon();
}
@ -1235,6 +1255,7 @@ in
}
Text {
text: batteryWidget.powerDraw.toFixed(1) + " W"
+ (batteryWidget.timeRemaining !== "" ? " \u2022 " + batteryWidget.timeRemaining + (batteryWidget.charging ? " to full" : " left") : "")
color: "#${c.base04}"
font.family: "FiraMono Nerd Font"
font.pixelSize: 11