diff --git a/nwg_panel/common.py b/nwg_panel/common.py index b335740..b10ef3f 100644 --- a/nwg_panel/common.py +++ b/nwg_panel/common.py @@ -20,8 +20,6 @@ app_dirs = [] dependencies = { "pyalsa": False, "psutil": False, - "upower": False, - "acpi": False, "netifaces": False, "amixer": False } @@ -29,8 +27,6 @@ dependencies = { icons_path = "" # "icons_light", "icons_dark" or "" (GTK icons) commands = { - "get_battery": "upower -i $(upower -e | grep BAT) | grep --color=never -E 'state|to\\\\ full|to\\\\ empty|percentage'", - "get_battery_alt": "acpi", "get_bt_name": "bluetoothctl show | awk '/Name/{print $2}'", "get_bt_status": "bluetoothctl show | awk '/Powered/{print $2}'", "get_brightness": "light -G", diff --git a/nwg_panel/icons_dark/battery-empty-charging-symbolic.svg b/nwg_panel/icons_dark/battery-empty-charging-symbolic.svg new file mode 100644 index 0000000..a507e02 --- /dev/null +++ b/nwg_panel/icons_dark/battery-empty-charging-symbolic.svg @@ -0,0 +1,211 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/nwg_panel/icons_dark/battery-full-charging-symbolic.svg b/nwg_panel/icons_dark/battery-full-charging-symbolic.svg new file mode 100644 index 0000000..462d5d3 --- /dev/null +++ b/nwg_panel/icons_dark/battery-full-charging-symbolic.svg @@ -0,0 +1,207 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/nwg_panel/icons_dark/battery-good-charging-symbolic.svg b/nwg_panel/icons_dark/battery-good-charging-symbolic.svg new file mode 100644 index 0000000..5fbe543 --- /dev/null +++ b/nwg_panel/icons_dark/battery-good-charging-symbolic.svg @@ -0,0 +1,207 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/nwg_panel/icons_dark/battery-low-charging-symbolic.svg b/nwg_panel/icons_dark/battery-low-charging-symbolic.svg new file mode 100644 index 0000000..766be8a --- /dev/null +++ b/nwg_panel/icons_dark/battery-low-charging-symbolic.svg @@ -0,0 +1,211 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/nwg_panel/icons_light/battery-empty-charging-symbolic.svg b/nwg_panel/icons_light/battery-empty-charging-symbolic.svg new file mode 100644 index 0000000..a962069 --- /dev/null +++ b/nwg_panel/icons_light/battery-empty-charging-symbolic.svg @@ -0,0 +1,211 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/nwg_panel/icons_light/battery-full-charging-symbolic.svg b/nwg_panel/icons_light/battery-full-charging-symbolic.svg new file mode 100644 index 0000000..2e989af --- /dev/null +++ b/nwg_panel/icons_light/battery-full-charging-symbolic.svg @@ -0,0 +1,207 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/nwg_panel/icons_light/battery-good-charging-symbolic.svg b/nwg_panel/icons_light/battery-good-charging-symbolic.svg new file mode 100644 index 0000000..5fbe543 --- /dev/null +++ b/nwg_panel/icons_light/battery-good-charging-symbolic.svg @@ -0,0 +1,207 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/nwg_panel/icons_light/battery-low-charging-symbolic.svg b/nwg_panel/icons_light/battery-low-charging-symbolic.svg new file mode 100644 index 0000000..6ed9c0b --- /dev/null +++ b/nwg_panel/icons_light/battery-low-charging-symbolic.svg @@ -0,0 +1,211 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/nwg_panel/main.py b/nwg_panel/main.py index f727300..cf0f80b 100644 --- a/nwg_panel/main.py +++ b/nwg_panel/main.py @@ -218,8 +218,6 @@ def main(): common.app_dirs = get_app_dirs() - common.dependencies["upower"] = is_command("upower") - common.dependencies["acpi"] = is_command("acpi") common.dependencies["amixer"] = is_command("amixer") config_file = os.path.join(common.config_dir, args.config) diff --git a/nwg_panel/modules/controls.py b/nwg_panel/modules/controls.py index 8bba47a..2eee644 100644 --- a/nwg_panel/modules/controls.py +++ b/nwg_panel/modules/controls.py @@ -153,8 +153,8 @@ class Controls(Gtk.EventBox): def get_bat_output(self): if "battery" in self.settings["components"]: try: - msg, value = get_battery() - GLib.idle_add(self.update_battery, value) + value, time, charging = get_battery() + GLib.idle_add(self.update_battery, value, charging) except Exception as e: print(e) @@ -165,8 +165,7 @@ class Controls(Gtk.EventBox): return True - # No point in checking battery data more often that every 5 seconds: - # `upower` / `acpi` response does not change that quickly. + # No point in checking battery data more often that every 5 seconds def refresh_bat(self): thread = threading.Thread(target=self.get_bat_output) thread.daemon = True @@ -200,8 +199,8 @@ class Controls(Gtk.EventBox): if self.bri_label: self.bri_label.set_text("{}%".format(value)) - def update_battery(self, value): - icon_name = bat_icon_name(value) + def update_battery(self, value, charging): + icon_name = bat_icon_name(value, charging) if icon_name != self.bat_icon_name: update_image(self.bat_image, icon_name, self.icon_size, self.icons_path) @@ -433,8 +432,8 @@ class PopupWindow(Gtk.Window): self.bat_icon_name = "view-refresh-symbolic" self.bat_image = Gtk.Image.new_from_icon_name(self.bat_icon_name, Gtk.IconSize.MENU) - msg, level = get_battery() - icon_name = bat_icon_name(level) + level, msg, charging = get_battery() + icon_name = bat_icon_name(level, charging) if icon_name != self.bat_icon_name: update_image(self.bat_image, icon_name, self.icon_size, self.icons_path) @@ -442,7 +441,7 @@ class PopupWindow(Gtk.Window): inner_hbox.pack_start(self.bat_image, False, False, 6) - self.bat_label = Gtk.Label(msg) + self.bat_label = Gtk.Label("{}% {}".format(level, msg)) inner_hbox.pack_start(self.bat_label, False, True, 6) if "battery" in settings["commands"] and settings["commands"]["battery"]: @@ -510,6 +509,7 @@ class PopupWindow(Gtk.Window): e_box.connect('button-press-event', self.switch_menu_box) Gdk.threads_add_timeout_seconds(GLib.PRIORITY_LOW, settings["interval"], self.refresh) + Gdk.threads_add_timeout_seconds(GLib.PRIORITY_LOW, 5, self.refresh_bat) def on_window_exit(self, w, e): self.hide() @@ -567,17 +567,22 @@ class PopupWindow(Gtk.Window): update_image(self.bt_image, icon_name, self.icon_size, self.icons_path) self.bt_icon_name = icon_name - self.bat_label.set_text(bt_name()) + self.bt_label.set_text(bt_name()) + + return True + + def refresh_bat(self): + if self.get_visible(): if "battery" in self.settings["components"]: - msg, level = get_battery() - icon_name = bat_icon_name(level) + level, msg, charging = get_battery() + icon_name = bat_icon_name(level, charging) if icon_name != self.bat_icon_name: update_image(self.bat_image, icon_name, self.icon_size, self.icons_path) self.bat_icon_name = icon_name - self.bat_label.set_text(msg) + self.bat_label.set_text("{}% {}".format(level, msg)) return True @@ -642,14 +647,22 @@ def vol_icon_name(value, switch): return icon_name -def bat_icon_name(value): +def bat_icon_name(value, is_charging): icon_name = "battery-empty-symbolic" - if value > 95: - icon_name = "battery-full-symbolic" - elif value > 50: - icon_name = "battery-good-symbolic" - elif value > 20: - icon_name = "battery-low-symbolic" + if is_charging: + if value > 95: + icon_name = "battery-full-charging-symbolic" + elif value > 50: + icon_name = "battery-good-charging-symbolic" + elif value > 20: + icon_name = "battery-low-charging-symbolic" + else: + if value > 95: + icon_name = "battery-full-symbolic" + elif value > 50: + icon_name = "battery-good-symbolic" + elif value > 20: + icon_name = "battery-low-symbolic" return icon_name diff --git a/nwg_panel/tools.py b/nwg_panel/tools.py index c1fa6db..2e1e149 100644 --- a/nwg_panel/tools.py +++ b/nwg_panel/tools.py @@ -5,6 +5,7 @@ import sys import json import subprocess import stat +import psutil import gi @@ -354,48 +355,27 @@ def set_brightness(slider): def get_battery(): - if nwg_panel.common.dependencies["upower"]: - cmd = nwg_panel.common.commands["get_battery"] - elif nwg_panel.common.dependencies["acpi"]: - cmd = nwg_panel.common.commands["get_battery_alt"] - else: - return None, None + b = psutil.sensors_battery() + percent = int(round(b.percent, 0)) + charging = b.power_plugged + time = seconds2string(b.secsleft) if not charging else "" - msg = "" - perc_val = 0 - if cmd.split()[0] == "upower": - bat = [] - try: - bat = cmd2string(cmd).splitlines() - except: - pass - state, time, percentage = "", "", "" - for line in bat: - line = line.strip() - if "time to empty" in line: - line = line.replace("time to empty", "time_to_empty") - parts = line.split() + return percent, time, charging - if "percentage:" in parts[0]: - percentage = parts[1] - perc_val = int(percentage.split("%")[0]) - if "state:" in parts[0]: - state = parts[1] - if "time_to_empty:" in parts[0]: - time = " ".join(parts[1:]) - msg = "{} {} {}".format(percentage, state, time) - elif cmd.split()[0] == "acpi": - bat = "" - try: - bat = cmd2string(cmd).splitlines()[0] - except: - pass - if bat: - parts = bat.split() - msg = " ".join(parts[2:]) - perc_val = int(parts[3].split("%")[0]) - return msg, perc_val +def seconds2string(seconds): + min, sec = divmod(seconds, 60) + hrs, min = divmod(min, 60) + + hrs = str(hrs) + if len(hrs) < 2: + hrs = "0{}".format(hrs) + + min = str(min) + if len(min) < 2: + min = "0{}".format(min) + + return "{}:{}".format(hrs, min) def list_interfaces():