feat: add new functionality
This commit is contained in:
1 file changed
+119
-99
@@ -1,7 +1,7 @@
|
||||
import subprocess
|
||||
import json
|
||||
import psutil
|
||||
from gi.repository import GLib, Gdk
|
||||
from gi.repository import GLib, Gdk, Gtk
|
||||
|
||||
from fabric.widgets.label import Label
|
||||
from fabric.widgets.box import Box
|
||||
@@ -18,6 +18,7 @@ class MetricsProvider:
|
||||
self.cpu = 0.0
|
||||
self.mem = 0.0
|
||||
self.swap = 0.0
|
||||
self.disk = []
|
||||
self.bat_percent = 0.0
|
||||
self.bat_charging = None
|
||||
|
||||
@@ -31,6 +32,7 @@ class MetricsProvider:
|
||||
self.mem = mem.percent
|
||||
swap = psutil.swap_memory()
|
||||
self.swap = swap.percent
|
||||
self.disk = [psutil.disk_usage(path).percent for path in data.BAR_METRICS_DISKS]
|
||||
|
||||
battery = psutil.sensors_battery()
|
||||
if battery is None:
|
||||
@@ -42,19 +44,17 @@ class MetricsProvider:
|
||||
return True
|
||||
|
||||
def get_metrics(self):
|
||||
return (self.cpu, self.mem, self.swap)
|
||||
return (self.cpu, self.mem, self.swap, self.disk)
|
||||
|
||||
def get_battery(self):
|
||||
return (self.bat_percent, self.bat_charging)
|
||||
|
||||
|
||||
|
||||
shared_provider = MetricsProvider()
|
||||
|
||||
|
||||
class SingularMetric:
|
||||
def __init__(self, id, name, icon):
|
||||
self.is_vertical_layout = data.VERTICAL
|
||||
self.name_markup = name
|
||||
self.icon_markup = icon
|
||||
|
||||
@@ -77,30 +77,28 @@ class SingularMetric:
|
||||
)
|
||||
|
||||
self.circle_button.add_events(
|
||||
Gdk.EventMask.ENTER_NOTIFY_MASK | Gdk.EventMask.LEAVE_NOTIFY_MASK
|
||||
Gdk.EventMask.ENTER_NOTIFY_MASK | Gdk.EventMask.LEAVE_NOTIFY_MASK | Gdk.EventMask.BUTTON_PRESS_MASK
|
||||
)
|
||||
self.circle_button.connect("enter-notify-event", self.on_button_enter)
|
||||
self.circle_button.connect("leave-notify-event", self.on_button_leave)
|
||||
|
||||
self.circle_button.connect("clicked", self.on_circle_clicked)
|
||||
self.circle_button.connect("button-press-event", self.on_button_press)
|
||||
|
||||
self.level = Label(
|
||||
name="metrics-level",
|
||||
style_classes=id,
|
||||
label="0%",
|
||||
style="margin: 4px 0px;" if self.is_vertical_layout else "margin: 0 4px;",
|
||||
)
|
||||
self.revealer = Revealer(
|
||||
name=f"metrics-{id}-revealer",
|
||||
transition_duration=250,
|
||||
transition_type="slide-up" if self.is_vertical_layout else "slide-left",
|
||||
transition_type="slide-left",
|
||||
child=self.level,
|
||||
child_revealed=False,
|
||||
)
|
||||
|
||||
self.box = Box(
|
||||
name=f"metrics-{id}-box",
|
||||
orientation="v" if self.is_vertical_layout else "h",
|
||||
orientation="h",
|
||||
spacing=0,
|
||||
children=[self.circle_button, self.revealer],
|
||||
)
|
||||
@@ -109,12 +107,11 @@ class SingularMetric:
|
||||
self.box.connect("enter-notify-event", self.on_button_enter)
|
||||
self.box.connect("leave-notify-event", self.on_button_leave)
|
||||
|
||||
# Set initial tooltip - moved after box is created
|
||||
# Set initial tooltip
|
||||
self.update_tooltip("0%")
|
||||
|
||||
def update_tooltip(self, value_text):
|
||||
tooltip = f"{self.icon_markup} {self.name_markup}: {value_text}"
|
||||
# self.box.set_tooltip_markup(tooltip)
|
||||
self.circle_button.set_tooltip_markup(tooltip)
|
||||
self.circle.set_tooltip_markup(tooltip)
|
||||
self.icon.set_tooltip_markup(tooltip)
|
||||
@@ -133,24 +130,31 @@ class SingularMetric:
|
||||
if window:
|
||||
window.set_cursor(None)
|
||||
|
||||
def on_circle_clicked(self, button):
|
||||
# Toggle the revealed state of the label
|
||||
current_state = self.revealer.get_child_revealed()
|
||||
self.revealer.set_reveal_child(not current_state)
|
||||
def on_button_press(self, widget, event):
|
||||
if event.button == 1: # Left click
|
||||
# Get the parent Metrics instance
|
||||
parent = self.box.get_parent()
|
||||
while parent and not isinstance(parent, Metrics):
|
||||
parent = parent.get_parent()
|
||||
if parent:
|
||||
parent.toggle_all_metrics()
|
||||
return True # Stop event propagation
|
||||
elif event.button == 3: # Right click
|
||||
# Toggle only this metric's revealer
|
||||
current_state = self.revealer.get_child_revealed()
|
||||
self.revealer.set_reveal_child(not current_state)
|
||||
return True # Stop event propagation
|
||||
return False
|
||||
|
||||
|
||||
class Metrics(Box):
|
||||
def __init__(self, **kwargs):
|
||||
# Determine if we should use vertical layout for components
|
||||
self.is_vertical_layout = data.VERTICAL
|
||||
|
||||
super().__init__(
|
||||
name="metrics",
|
||||
spacing=0,
|
||||
orientation="h" if not self.is_vertical_layout else "v",
|
||||
orientation="h",
|
||||
visible=True,
|
||||
all_visible=True,
|
||||
style="padding:4px 0px" if self.is_vertical_layout else "padding: 0px 4px;",
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
@@ -164,91 +168,103 @@ class Metrics(Box):
|
||||
self.batt_fabricator.changed.connect(self.update_battery)
|
||||
GLib.idle_add(self.update_battery, None, shared_provider.get_battery())
|
||||
|
||||
# Initialize all metrics
|
||||
disks = [
|
||||
SingularMetric(
|
||||
"disk",
|
||||
f"DISK ({path})" if len(data.BAR_METRICS_DISKS) != 1 else "DISK",
|
||||
icons.disk,
|
||||
)
|
||||
for path in data.BAR_METRICS_DISKS
|
||||
]
|
||||
|
||||
self.cpu = (
|
||||
SingularMetric("cpu", "CPU", icons.cpu)
|
||||
)
|
||||
self.ram = (
|
||||
SingularMetric("ram", "RAM", icons.memory)
|
||||
)
|
||||
self.swap = (
|
||||
SingularMetric("swap", "SWAP", icons.swap)
|
||||
)
|
||||
self.bat = (
|
||||
SingularMetric("bat", "BATTERY", icons.battery)
|
||||
)
|
||||
self.ram = SingularMetric("ram", "RAM", icons.memory)
|
||||
self.cpu = SingularMetric("cpu", "CPU", icons.cpu)
|
||||
self.swap = SingularMetric("swap", "SWAP", icons.swap)
|
||||
self.bat = SingularMetric("bat", "BATTERY", icons.battery)
|
||||
self.disk = disks
|
||||
|
||||
# Create container for all metrics
|
||||
self.metrics_container = Box(name="metrics-container", orientation="h", spacing=0)
|
||||
self.add(self.metrics_container)
|
||||
|
||||
# Add only enabled metrics
|
||||
# Create revealers for metrics
|
||||
self.cpu_revealer = Revealer(
|
||||
name="cpu-revealer",
|
||||
transition_duration=250,
|
||||
transition_type="slide-left",
|
||||
child=self.cpu.box,
|
||||
child_revealed=False,
|
||||
)
|
||||
self.swap_revealer = Revealer(
|
||||
name="swap-revealer",
|
||||
transition_duration=250,
|
||||
transition_type="slide-left",
|
||||
child=self.swap.box,
|
||||
child_revealed=False,
|
||||
)
|
||||
self.disk_revealers = [
|
||||
Revealer(
|
||||
name=f"disk-revealer-{i}",
|
||||
transition_duration=250,
|
||||
transition_type="slide-left",
|
||||
child=disk.box,
|
||||
child_revealed=False,
|
||||
)
|
||||
for i, disk in enumerate(self.disk)
|
||||
]
|
||||
|
||||
# Create permanent separator between memory and battery
|
||||
self.memory_battery_sep = Box(name="metrics-sep")
|
||||
|
||||
# Create container for revealed metrics
|
||||
self.revealed_metrics = Box(name="revealed-metrics", orientation="h", spacing=0)
|
||||
self.revealed_metrics.add(self.cpu_revealer)
|
||||
for disk_revealer in self.disk_revealers:
|
||||
self.revealed_metrics.add(disk_revealer)
|
||||
self.revealed_metrics.add(self.swap_revealer)
|
||||
|
||||
# Create container for memory and battery
|
||||
self.memory_battery_container = Box(name="memory-battery-container", orientation="h", spacing=0)
|
||||
if self.ram:
|
||||
self.add(self.ram.box)
|
||||
self.add(Box(name="metrics-sep"))
|
||||
if self.cpu:
|
||||
self.add(self.cpu.box)
|
||||
if self.swap:
|
||||
self.add(Box(name="metrics-sep"))
|
||||
self.add(self.swap.box)
|
||||
self.memory_battery_container.add(self.ram.box)
|
||||
self.memory_battery_container.add(self.memory_battery_sep)
|
||||
if self.bat:
|
||||
self.add(Box(name="metrics-sep"))
|
||||
self.add(self.bat.box)
|
||||
self.memory_battery_container.add(self.bat.box)
|
||||
|
||||
# Connect events directly to the button
|
||||
self.connect("enter-notify-event", self.on_mouse_enter)
|
||||
self.connect("leave-notify-event", self.on_mouse_leave)
|
||||
# Add metrics in the correct order
|
||||
self.metrics_container.add(self.revealed_metrics)
|
||||
self.metrics_container.add(self.memory_battery_container)
|
||||
|
||||
# Initially hide all non-visible metrics
|
||||
self.cpu_revealer.set_reveal_child(False)
|
||||
self.swap_revealer.set_reveal_child(False)
|
||||
for disk_revealer in self.disk_revealers:
|
||||
disk_revealer.set_reveal_child(False)
|
||||
|
||||
self.showing_all_metrics = False
|
||||
|
||||
GLib.timeout_add_seconds(1, self.update_metrics)
|
||||
|
||||
self.hide_timer = None
|
||||
self.hover_counter = 0
|
||||
def toggle_all_metrics(self):
|
||||
self.showing_all_metrics = not self.showing_all_metrics
|
||||
|
||||
# Toggle all revealers
|
||||
self.cpu_revealer.set_reveal_child(self.showing_all_metrics)
|
||||
self.swap_revealer.set_reveal_child(self.showing_all_metrics)
|
||||
for disk_revealer in self.disk_revealers:
|
||||
disk_revealer.set_reveal_child(self.showing_all_metrics)
|
||||
|
||||
# Toggle spacing for revealed metrics and memory-battery container
|
||||
spacing = 6 if self.showing_all_metrics else 0
|
||||
self.revealed_metrics.set_spacing(spacing)
|
||||
self.metrics_container.set_spacing(spacing)
|
||||
|
||||
def _format_percentage(self, value: int) -> str:
|
||||
return f"{value}%"
|
||||
|
||||
def on_mouse_enter(self, widget, event):
|
||||
window = widget.get_window()
|
||||
if window:
|
||||
window.set_cursor(Gdk.Cursor(Gdk.CursorType.HAND2))
|
||||
|
||||
if not data.VERTICAL:
|
||||
self.hover_counter += 1
|
||||
if self.hide_timer is not None:
|
||||
GLib.source_remove(self.hide_timer)
|
||||
self.hide_timer = None
|
||||
if self.cpu:
|
||||
self.cpu.revealer.set_reveal_child(True)
|
||||
if self.ram:
|
||||
self.ram.revealer.set_reveal_child(True)
|
||||
if self.swap:
|
||||
self.swap.revealer.set_reveal_child(True)
|
||||
if self.bat:
|
||||
self.bat.revealer.set_reveal_child(True)
|
||||
return False
|
||||
|
||||
def on_mouse_leave(self, widget, event):
|
||||
window = widget.get_window()
|
||||
if window:
|
||||
window.set_cursor(None)
|
||||
|
||||
if not data.VERTICAL:
|
||||
if self.hover_counter > 0:
|
||||
self.hover_counter -= 1
|
||||
if self.hover_counter == 0:
|
||||
if self.hide_timer is not None:
|
||||
GLib.source_remove(self.hide_timer)
|
||||
self.hide_timer = GLib.timeout_add(500, self.hide_revealer)
|
||||
return False
|
||||
|
||||
def hide_revealer(self):
|
||||
if not data.VERTICAL:
|
||||
if self.cpu:
|
||||
self.cpu.revealer.set_reveal_child(False)
|
||||
if self.ram:
|
||||
self.ram.revealer.set_reveal_child(False)
|
||||
self.hide_timer = None
|
||||
return False
|
||||
|
||||
def update_metrics(self):
|
||||
cpu, mem, swap = shared_provider.get_metrics()
|
||||
cpu, mem, swap, disk = shared_provider.get_metrics()
|
||||
if self.cpu:
|
||||
self.cpu.circle.set_value(cpu / 100.0)
|
||||
value_text = self._format_percentage(int(cpu))
|
||||
@@ -259,6 +275,12 @@ class Metrics(Box):
|
||||
value_text = self._format_percentage(int(mem))
|
||||
self.ram.level.set_label(value_text)
|
||||
self.ram.update_tooltip(value_text)
|
||||
for i, disk_metric in enumerate(self.disk):
|
||||
if i < len(disk):
|
||||
value_text = self._format_percentage(int(disk[i]))
|
||||
disk_metric.circle.set_value(disk[i] / 100.0)
|
||||
disk_metric.level.set_label(value_text)
|
||||
disk_metric.update_tooltip(value_text)
|
||||
if self.swap:
|
||||
self.swap.circle.set_value(swap / 100.0)
|
||||
value_text = self._format_percentage(int(swap))
|
||||
@@ -273,6 +295,7 @@ class Metrics(Box):
|
||||
|
||||
# Tooltip: only show enabled metrics
|
||||
tooltip_metrics = []
|
||||
if self.disk: tooltip_metrics.extend(self.disk)
|
||||
if self.swap: tooltip_metrics.append(self.swap)
|
||||
if self.bat: tooltip_metrics.append(self.bat)
|
||||
if self.ram: tooltip_metrics.append(self.ram)
|
||||
@@ -285,13 +308,10 @@ class Metrics(Box):
|
||||
return
|
||||
|
||||
value, charging = battery_data
|
||||
if value == 0:
|
||||
if self.bat:
|
||||
self.bat.box.set_visible(False)
|
||||
else:
|
||||
if self.bat:
|
||||
self.bat.box.set_visible(True)
|
||||
self.bat.circle.set_value(value / 100)
|
||||
# Always show battery, even if value is 0
|
||||
if self.bat:
|
||||
self.bat.box.set_visible(True)
|
||||
self.bat.circle.set_value(value / 100)
|
||||
percentage = int(value)
|
||||
self.bat.level.set_label(self._format_percentage(percentage))
|
||||
|
||||
|
||||
Reference in new issue
Block a user