From d0e1e2170c6429dfc262065c76dec7a5f5df57fe Mon Sep 17 00:00:00 2001 From: voidarc Date: Fri, 7 Aug 2026 20:32:01 +0100 Subject: [PATCH] battery things --- Bar.qml | 4 + Bar/Battery.qml | 173 ++++++++++++++++++++++++++++++++++++ Services/BatteryManager.qml | 85 +++++++++++++++--- 3 files changed, 252 insertions(+), 10 deletions(-) create mode 100644 Bar/Battery.qml diff --git a/Bar.qml b/Bar.qml index 73732a0..70f972d 100644 --- a/Bar.qml +++ b/Bar.qml @@ -125,6 +125,10 @@ Scope { Bluetooth { monitor: win.monitor } + + Battery { + monitor: win.monitor + } } } } diff --git a/Bar/Battery.qml b/Bar/Battery.qml new file mode 100644 index 0000000..2c344aa --- /dev/null +++ b/Bar/Battery.qml @@ -0,0 +1,173 @@ +pragma ComponentBehavior: Bound +import QtQuick +import QtQuick.Layouts +import Quickshell +import Quickshell.Hyprland + +import "../Color.js" as Colors +import "../Components/" +import "../Services/" + +Container { + id: root + + property double batteryDisplayHeight: 100 + required property HyprlandMonitor monitor + property bool opened: false + property double radius: 9 + + boxColor: Colors.green + boxHeight: 25 + boxRadius: radius + boxWidth: 55 + defaultItem: icon + exclusiveMonitor: root.monitor + + states: [ + State { + name: "closed" + when: root.hovered == false && root.opened == false + + PropertyChanges { + root.boxHeight: 25 + root.boxRadius: 9 + root.boxWidth: 55 + } + }, + State { + name: "hovered" + when: root.hovered == true && root.opened == false + + PropertyChanges { + root.boxHeight: 28 + root.boxWidth: 60 + } + }, + State { + name: "opened" + when: root.opened == true && root.hovered == true + + PropertyChanges { + root.boxHeight: root.batteryDisplayHeight + root.boxRadius: 12 + root.boxWidth: 350 + } + + StateChangeScript { + script: { + stack.replace(batteryDisplay); + } + } + } + ] + + hover.onHoveredChanged: { + if (hover.hovered == false) { + root.opened = false; + if (root.state != "icon") { + root.stack.replace(icon); + } + } + } + tap.onTapped: { + root.opened = true; + } + + Component { + id: icon + + Item { + MidpointGradient { + anchors.fill: parent + angle: -45 + blur: 0.6 + color: BatteryManager.getBatteryColor() + midpoint: 0.55 + radius: radius + } + + CenteredText { + property string component: "icon" + + propo: true + text: BatteryManager.getBatteryText() + } + } + } + + Component { + id: batteryDisplay + + Item { + id: batteryDisplayRoot + + property double innerMargin: 5 + property double outerMargin: 6 + + Rectangle { + id: batteryBackground + + anchors.fill: parent + anchors.margins: batteryDisplayRoot.outerMargin + color: Colors.surface1 + radius: 8 + + RowLayout { + anchors.fill: parent + + Rectangle { + id: percentBox + + property double percentBoxRadius: 5 + + Layout.fillHeight: true + Layout.margins: batteryDisplayRoot.innerMargin + color: Colors.text + implicitWidth: root.batteryDisplayHeight - (batteryDisplayRoot.innerMargin * 2) - ( + batteryDisplayRoot.outerMargin * 2) + radius: 5 + + Rectangle { + color: Colors.green + implicitHeight: (root.batteryDisplayHeight - (batteryDisplayRoot.innerMargin * 2) - ( + batteryDisplayRoot.outerMargin * 2)) * BatteryManager.mainBattery.percentage + radius: percentBox.percentBoxRadius + + anchors { + bottom: parent.bottom + left: parent.left + right: parent.right + } + } + + CenteredText { + fontSize: 15 + text: BatteryManager.getBatteryPercentage(BatteryManager.mainBattery) + "%" + } + } + + Column { + id: batColumn + + property var batInfo: BatteryManager.getMainBatteryInfo() + + Layout.alignment: Qt.AlignVCenter + Layout.fillWidth: true + + StyledText { + color: Colors.text + fontSize: 13 + text: "Battery - " + batColumn.batInfo["name"] + } + + StyledText { + color: Colors.text + fontSize: 13 + text: batColumn.batInfo["energy"] + " / " + batColumn.batInfo["capacity"] + "Wh" + } + } + } + } + } + } +} diff --git a/Services/BatteryManager.qml b/Services/BatteryManager.qml index c99c28c..50810e8 100644 --- a/Services/BatteryManager.qml +++ b/Services/BatteryManager.qml @@ -3,21 +3,86 @@ import QtQuick import Quickshell import Quickshell.Services.UPower +import "../Color.js" as Colors + Singleton { id: root - property UPowerDevice battery: Upower.displayDevice property bool batteryInUse: root.batteryPresent && root.batteryLaptop - property bool batteryLaptop: root.battery.isLaptopBattery - property double batteryPercentage: root.battery.percentage - property bool batteryPresent: root.battery.ready + property bool batteryLaptop: root.mainBattery.isLaptopBattery + property double batteryPercentage: root.mainBattery.percentage + property bool batteryPresent: root.mainBattery.ready + property UPowerDevice mainBattery: UPower.displayDevice - function getBatteryIcon() { - let battery = root.battery; - if (battery.state = UpowerDeviceState.Charging) { - return "󰂄"; - } - if (battery.state = UpowerDeviceState.Discharging) { + function getBatteryColor() { + let criticalLevel = 20; + let batteryPercentage = getBatteryPercentage(mainBattery); + + if (mainBattery.state == UPowerDeviceState.Charging) { + return Colors.mauve; + } else if (mainBattery.state == UPowerDeviceState.PendingCharge | mainBattery.state + == UPowerDeviceState.PendingDischarge) { + return Colors.peach; + } else if (batteryPercentage <= criticalLevel) { + return Colors.red; + } else { + return Colors.green; } } + + function getBatteryIcon(battery) { + if (battery.state == UPowerDeviceState.Charging) { + return "󰂄"; + } else if (battery.state == UPowerDeviceState.PendingCharge | battery.state + == UPowerDeviceState.PendingDischarge) { + return "󰚥"; + } else if (battery.state == UPowerDeviceState.Discharging | battery.state + == UPowerDeviceState.FullyCharged) { + let iconArr = ["󰁺", "󰁻", "󰁼", "󰁽", "󰁾", "󰁿", "󰂀", "󰂁", "󰂂", "󰁹"]; + let batteryCharge = battery.percentage; + let chargeIndex = Math.ceil(batteryCharge * iconArr.length) - 1; + return iconArr[chargeIndex]; + } + } + + function getBatteryName(battery) { + let pathsplit = battery.nativePath.split("/"); + let batteryName = pathsplit[pathsplit.length]; + return pathsplit; + } + + function getBatteryPercentage(battery) { + return battery.percentage * 100; + } + + function getBatteryText() { + let icon = getBatteryIcon(mainBattery); + let percentage = getBatteryPercentage(mainBattery); + return icon + " " + percentage + "%"; + } + + function getMainBatteryInfo() { + let battery = UPower.devices.values[0]; + let batteryState = battery.state; + let batteryName = getBatteryName(battery); + let time = 0; + let timeString = ""; + let timeToEmpty = battery.timeToEmpty; + if (timeToEmpty == 0) { + timeString = "full"; + time = battery.timeToFull; + } else { + timeString = "empty"; + time = timeToEmpty; + } + return { + "name": batteryName, + "charge": battery.percentage, + "energy": battery.energy, + "capacity": battery.energyCapacity, + "time": time, + "timeString": timeString, + "health": battery.healthPercentage + }; + } }