From e2604e2163d2d61a994de2f5e16585843173caca Mon Sep 17 00:00:00 2001 From: S4NKALP Date: Fri, 23 May 2025 09:55:16 +0545 Subject: [PATCH] feat: add new functionality --- modules/bar/components/metrics.py | 218 ++++++++++++++++-------------- 1 file changed, 119 insertions(+), 99 deletions(-) diff --git a/modules/bar/components/metrics.py b/modules/bar/components/metrics.py index b8150d6..685efa3 100644 --- a/modules/bar/components/metrics.py +++ b/modules/bar/components/metrics.py @@ -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))