diff --git a/roles/quickshell/files/bar/Bar.qml b/roles/quickshell/files/bar/Bar.qml index 9f8823c..f95ac15 100644 --- a/roles/quickshell/files/bar/Bar.qml +++ b/roles/quickshell/files/bar/Bar.qml @@ -59,6 +59,9 @@ PanelWindow { anchors.verticalCenter: parent.verticalCenter barWindow: root } + Battery { + anchors.verticalCenter: parent.verticalCenter + } NetworkStatus { anchors.verticalCenter: parent.verticalCenter } diff --git a/roles/quickshell/files/bar/Battery.qml b/roles/quickshell/files/bar/Battery.qml new file mode 100644 index 0000000..7f9e9b2 --- /dev/null +++ b/roles/quickshell/files/bar/Battery.qml @@ -0,0 +1,84 @@ +import Quickshell +import Quickshell.Io +import QtQuick +import "../components" + +Item { + id: root + implicitWidth: hasBattery ? row.implicitWidth + 10 : 0 + implicitHeight: 24 + visible: hasBattery + + property bool hasBattery: false + property int percent: 0 + property string status: "Unknown" // "Charging", "Discharging", "Full", "Unknown" + + // \uf0e7 = bolt (charging), \uf240-\uf244 = FA battery full…empty + readonly property string battIcon: { + if (status === "Charging" || status === "Full") return "\uf0e7" + if (percent <= 10) return "\uf244" + if (percent <= 25) return "\uf243" + if (percent <= 50) return "\uf242" + if (percent <= 75) return "\uf241" + return "\uf240" + } + + readonly property bool isLow: percent <= 20 && status === "Discharging" + + Timer { + interval: 30000 + running: true + repeat: true + triggeredOnStart: true + onTriggered: battProc.running = true + } + + Process { + id: battProc + // Find first BAT* supply; print "NONE" if none exists + command: ["sh", "-c", + "BAT=$(ls /sys/class/power_supply/ 2>/dev/null | grep -m1 '^BAT'); " + + "[ -z \"$BAT\" ] && echo NONE && exit 0; " + + "echo \"$(cat /sys/class/power_supply/$BAT/capacity):$(cat /sys/class/power_supply/$BAT/status)\"" + ] + stdout: SplitParser { + splitMarker: "\n" + onRead: data => { + const line = data.trim() + if (line === "" || line === "NONE") { + root.hasBattery = false + return + } + const sep = line.indexOf(":") + if (sep < 0) return + root.percent = parseInt(line.substring(0, sep)) || 0 + root.status = line.substring(sep + 1) + root.hasBattery = true + } + } + onExited: running = false + } + + Row { + id: row + anchors.centerIn: parent + spacing: 5 + + Text { + anchors.verticalCenter: parent.verticalCenter + text: root.battIcon + font.family: "JetBrainsMono Nerd Font Mono" + font.pixelSize: 14 + color: root.status === "Charging" ? Theme.accent + : root.isLow ? "#cc3333" + : Theme.text + } + + Text { + anchors.verticalCenter: parent.verticalCenter + text: root.percent + "%" + font.pixelSize: 11 + color: root.isLow ? "#cc3333" : Theme.textDim + } + } +} diff --git a/roles/quickshell/files/bar/qmldir b/roles/quickshell/files/bar/qmldir index b284364..94f9643 100644 --- a/roles/quickshell/files/bar/qmldir +++ b/roles/quickshell/files/bar/qmldir @@ -1,4 +1,5 @@ Bar 1.0 Bar.qml +Battery 1.0 Battery.qml PopoutWindow 1.0 PopoutWindow.qml CalendarContent 1.0 CalendarContent.qml Clock 1.0 Clock.qml diff --git a/roles/quickshell/tasks/main.yml b/roles/quickshell/tasks/main.yml index 07255af..27ce261 100644 --- a/roles/quickshell/tasks/main.yml +++ b/roles/quickshell/tasks/main.yml @@ -36,6 +36,7 @@ - { src: components/qmldir, dest: components/qmldir } # Bar module (imported as "bar" in shell.qml) - { src: bar/Bar.qml, dest: bar/Bar.qml } + - { src: bar/Battery.qml, dest: bar/Battery.qml } - { src: bar/CalendarContent.qml, dest: bar/CalendarContent.qml } - { src: bar/Clock.qml, dest: bar/Clock.qml } - { src: bar/MusicPlayer.qml, dest: bar/MusicPlayer.qml }