diff --git a/bar/config.py b/bar/config.py index 782e054..a09ff08 100644 --- a/bar/config.py +++ b/bar/config.py @@ -50,3 +50,4 @@ if app_config is None: raise Exception("Config file missing") VINYL = app_config.get("vinyl", {"enable": False}) +BATTERY = app_config.get("battery", {"enable": False}) diff --git a/bar/modules/bar.py b/bar/modules/bar.py index 5a071e2..f7d36aa 100644 --- a/bar/modules/bar.py +++ b/bar/modules/bar.py @@ -6,6 +6,7 @@ from fabric.widgets.datetime import DateTime from fabric.widgets.centerbox import CenterBox from bar.modules.player import Player from bar.modules.vinyl import VinylButton +from bar.modules.battery import Battery from fabric.widgets.wayland import WaylandWindow as Window from fabric.system_tray.widgets import SystemTray from fabric.river.widgets import ( @@ -19,7 +20,7 @@ from fabric.utils import ( ) from fabric.widgets.circularprogressbar import CircularProgressBar -from bar.config import VINYL +from bar.config import VINYL, BATTERY class StatusBar(Window): @@ -80,6 +81,10 @@ class StatusBar(Window): if VINYL["enable"]: self.vinyl = VinylButton() + self.battery = None + if BATTERY["enable"]: + self.battery = Battery() + print(self.battery) self.status_container = Box( name="widgets-container", spacing=4, @@ -92,6 +97,9 @@ class StatusBar(Window): if self.vinyl: end_container_children.append(self.vinyl) + if self.battery: + end_container_children.append(self.battery) + end_container_children.append(self.status_container) if self.system_tray: end_container_children.append(self.system_tray) diff --git a/bar/modules/battery.py b/bar/modules/battery.py new file mode 100644 index 0000000..090c35e --- /dev/null +++ b/bar/modules/battery.py @@ -0,0 +1,85 @@ +import psutil +from gi.repository import GLib +from fabric.widgets.box import Box +from fabric.widgets.label import Label +from fabric.widgets.icon import Icon +from fabric import Fabricator + + +class BatteryProvider: + def __init__(self): + self.bat_percent = 0.0 + self.bat_charging = None + + GLib.timeout_add_seconds(1, self._update) + + def _update(self): + battery = psutil.sensors_battery() + if battery is None: + self.bat_percent = 0.0 + self.bat_charging = None + else: + self.bat_percent = battery.percent + self.bat_charging = battery.power_plugged + + return True + + def get_battery(self): + return (self.bat_percent, self.bat_charging) + + +class Battery(Box): + def __init__(self, **kwargs): + super().__init__(name="battery-widget", orientation="h", spacing=4, **kwargs) + self.bat_provider = BatteryProvider() + + self.bat_icon = Icon( + name="bat-icon", + icon_name="battery-full-symbolic", + icon_size=16 + ) + self.bat_label = Label( + name="bat-label", + label="100%" + ) + + self.bat_fabricator = Fabricator( + poll_from=lambda: self.bat_provider.get_battery(), + on_changed=self.update_battery, + interval=1000, + stream=False, + default_value=(100, False), + ) + + self.children = [self.bat_icon, self.bat_label] + self.show_all() + + GLib.idle_add(self.update_battery, None, self.bat_provider.get_battery()) + + def _icon_lookup(self, bat, charging): + if charging: + return "battery-charging-symbolic" + match bat: + case _ if bat > 90: + return "battery-full-symbolic" + case _ if bat > 50: + return "battery-good-symbolic" + case _ if bat >= 20: + return "battery-medium-symbolic" + case _: + return "battery-low-symbolic" + + def update_battery(self, sender, battery_data): + value, charging = battery_data + + icon_name = self._icon_lookup(value, charging) + self.bat_icon.set_property("icon-name", icon_name) + + self.bat_label.set_text(f"{int(value)}%") + + if value < 20 and not charging: + self.bat_label.add_css_class("battery-low") + else: + self.bat_label.remove_css_class("battery-low") + + return True diff --git a/bar/styles/bar.css b/bar/styles/bar.css index cc5354a..3e64cb6 100644 --- a/bar/styles/bar.css +++ b/bar/styles/bar.css @@ -15,6 +15,27 @@ font-weight: bold; } +#battery-widget { + background-color: var(--module-bg); + padding: 4px 8px; + border-radius: 4px; +} + +#bat-icon { + color: var(--blue); + margin-right: 2px; +} + +#bat-label { + color: var(--foreground); + font-size: 14px; +} + +#bat-label.battery-low { + color: var(--red); + font-weight: bold; +} + #cpu-progress-bar, #ram-progress-bar, #volume-progress-bar { diff --git a/bar/widgets/battery.py b/bar/widgets/battery.py new file mode 100644 index 0000000..e69de29 diff --git a/example.yaml b/example.yaml index ad0fcde..93093c8 100644 --- a/example.yaml +++ b/example.yaml @@ -1,2 +1,4 @@ vinyl: - enabled: true + enable: true +battery: + enable: true diff --git a/flake.nix b/flake.nix index 97c77c6..d07472a 100644 --- a/flake.nix +++ b/flake.nix @@ -76,10 +76,17 @@ default = false; }; }; + battery = { + enable = lib.mkOption { + type = lib.types.bool; + default = false; + }; + }; }; }; default = { vinyl.enable = false; + battery.enable = false; }; }; };