feat: add new functionality

This commit is contained in:
sankalp committed 2025-05-23 09:55:16 +05:45
1 parent 38ce0049b2
commit e2604e2163
1 file changed
+119 -99
+119 -99
View File
@@ -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))