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 @@
+
+
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 @@
+
+
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 @@
+
+
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 @@
+
+
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 @@
+
+
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 @@
+
+
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 @@
+
+
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 @@
+
+
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():