huge updates but idk what i update
This commit is contained in:
1 parent
5d88e059d9
commit
4350f7459e
19 files changed
+563
-617
No files matched your search
+134
-50
@@ -1,3 +1,4 @@
|
||||
from typing import Literal
|
||||
from fabric.hyprland.widgets import Language
|
||||
from fabric.system_tray.widgets import SystemTray
|
||||
from fabric.utils import (
|
||||
@@ -5,24 +6,76 @@ from fabric.utils import (
|
||||
bulk_replace,
|
||||
exec_shell_command_async,
|
||||
get_relative_path,
|
||||
bulk_connect,
|
||||
)
|
||||
from fabric.widgets.shapes import Corner
|
||||
from fabric.widgets.box import Box
|
||||
from fabric.widgets.button import Button
|
||||
from fabric.widgets.centerbox import CenterBox
|
||||
from fabric.widgets.datetime import DateTime
|
||||
from fabric.widgets.label import Label
|
||||
from fabric.widgets.revealer import Revealer
|
||||
from fabric.widgets.wayland import WaylandWindow as Window
|
||||
from gi.repository import GLib
|
||||
from modules.bar.components import (
|
||||
BatteryLabel,
|
||||
SystemInfo,
|
||||
TaskBar,
|
||||
Battery,
|
||||
Metrics,
|
||||
workspace,
|
||||
Indicators,
|
||||
SystemIndicators,
|
||||
UpdatesWidget,
|
||||
)
|
||||
from services import sc
|
||||
import snippets.iconss as icons
|
||||
import utils.icons as icons
|
||||
|
||||
|
||||
class StatusBarCorner(Box):
|
||||
def __init__(self, corner: Literal["top-right", "top-left"]):
|
||||
super().__init__(
|
||||
style="margin-bottom: 15px;",
|
||||
name="bar-corner",
|
||||
children=Corner(
|
||||
orientation=corner,
|
||||
size=15,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class Tray(Box):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.tray = Box(
|
||||
name="left-tray",
|
||||
children=[SystemTray(name="tray", icon_size=16, spacing=4)],
|
||||
)
|
||||
self.profile = Button(
|
||||
child=Label(name="tray-revealer", markup=icons.chevron_left)
|
||||
)
|
||||
self.revealer = Revealer(transition_type="slide-left", transition_duration=1000)
|
||||
self.revealer.add(self.tray)
|
||||
|
||||
bulk_connect(
|
||||
self.profile,
|
||||
{
|
||||
"enter-notify-event": self._on_enter,
|
||||
"leave-notify-event": self._on_leave,
|
||||
"button-press-event": self.toggle_revealer,
|
||||
},
|
||||
)
|
||||
|
||||
self.add(self.profile)
|
||||
self.add(self.revealer)
|
||||
|
||||
def _on_enter(self, *args):
|
||||
self.profile.set_cursor("pointer")
|
||||
|
||||
def _on_leave(self, *args):
|
||||
self.profile.set_cursor("default")
|
||||
|
||||
def toggle_revealer(self, *args):
|
||||
new_state = not self.revealer.get_reveal_child()
|
||||
self.revealer.set_reveal_child(new_state)
|
||||
new_icon = icons.chevron_right if new_state else icons.chevron_left
|
||||
self.profile.get_child().set_markup(new_icon)
|
||||
|
||||
|
||||
class Bar(Window):
|
||||
@@ -39,7 +92,7 @@ class Bar(Window):
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
self.bar_content = CenterBox(name="center-bar")
|
||||
self.recording_indicator = Button(
|
||||
name="recording-indicator",
|
||||
child=Label(name="recorder", markup=icons.record),
|
||||
@@ -47,16 +100,10 @@ class Bar(Window):
|
||||
on_clicked=lambda *_: sc.screencast_stop(),
|
||||
)
|
||||
|
||||
sc.connect(
|
||||
"recording", lambda _, status: self.on_recording_status_change(status)
|
||||
)
|
||||
sc.connect("recording", self.on_recording_status_change)
|
||||
|
||||
self.date_time = DateTime(formatters=["%-I:%M %a %d %b"], name="datetime")
|
||||
|
||||
self.battery = BatteryLabel()
|
||||
self.taskbar = TaskBar()
|
||||
self.stats = SystemInfo()
|
||||
self.tray = SystemTray(name="tray", icon_size=16, spacing=4)
|
||||
self.battery = Battery()
|
||||
self.launcher = Button(
|
||||
name="logo",
|
||||
child=Label(name="logo-name", label=" "),
|
||||
@@ -64,8 +111,6 @@ class Bar(Window):
|
||||
"fabric-cli exec modus 'launcher.open(\"launcher\")'"
|
||||
),
|
||||
)
|
||||
self.updates = UpdatesWidget()
|
||||
self.indicators = Indicators()
|
||||
self.button_config = Button(
|
||||
name="button-bar",
|
||||
on_clicked=lambda *_: exec_shell_command_async(
|
||||
@@ -73,35 +118,22 @@ class Bar(Window):
|
||||
),
|
||||
child=Label(name="button-bar-label", markup=icons.config),
|
||||
)
|
||||
|
||||
self.stats = Metrics()
|
||||
self.updates = UpdatesWidget()
|
||||
self.tray = Tray()
|
||||
self.indicators = SystemIndicators()
|
||||
self.applets = Box(
|
||||
name="applets",
|
||||
name="system-indicators",
|
||||
spacing=4,
|
||||
orientation="h",
|
||||
children=[
|
||||
self.language,
|
||||
self.indicators,
|
||||
],
|
||||
children=[self.language, self.indicators],
|
||||
)
|
||||
|
||||
self.bar = CenterBox(
|
||||
name="bar",
|
||||
start_children=Box(
|
||||
name="start-container",
|
||||
spacing=8,
|
||||
orientation="h",
|
||||
children=[self.launcher, self.workspaces, self.stats, self.updates],
|
||||
),
|
||||
center_children=Box(
|
||||
name="center-container",
|
||||
spacing=8,
|
||||
orientation="h",
|
||||
children=self.taskbar,
|
||||
),
|
||||
end_children=Box(
|
||||
name="end-container",
|
||||
spacing=8,
|
||||
orientation="h",
|
||||
self.bar_content.end_children = [
|
||||
StatusBarCorner("top-right"),
|
||||
Box(
|
||||
name="bar",
|
||||
spacing=4,
|
||||
children=[
|
||||
self.recording_indicator,
|
||||
self.tray,
|
||||
@@ -110,27 +142,79 @@ class Bar(Window):
|
||||
self.date_time,
|
||||
self.button_config,
|
||||
],
|
||||
style_classes="end-container",
|
||||
),
|
||||
)
|
||||
]
|
||||
|
||||
self.bar_content.start_children = [
|
||||
Box(
|
||||
name="bar",
|
||||
spacing=4,
|
||||
children=[self.launcher, self.workspaces, self.stats, self.updates],
|
||||
style_classes="start-container",
|
||||
),
|
||||
StatusBarCorner("top-left"),
|
||||
]
|
||||
|
||||
super().__init__(
|
||||
layer="top",
|
||||
anchor="left bottom right",
|
||||
anchor="left top right",
|
||||
exclusivity="auto",
|
||||
visible=True,
|
||||
child=self.bar,
|
||||
child=self.bar_content,
|
||||
)
|
||||
|
||||
self.hidden = False
|
||||
|
||||
def on_recording_status_change(self, status):
|
||||
print(f"Recording status changed: {status}")
|
||||
def on_recording_status_change(self, _, status):
|
||||
self.recording_indicator.set_visible(status)
|
||||
|
||||
def toggle_hidden(self):
|
||||
self.hidden = not self.hidden
|
||||
if self.hidden:
|
||||
self.bar.remove_style_class("visible")
|
||||
self.bar.add_style_class("hidden")
|
||||
self.bar_content.add_style_class("hidden")
|
||||
self.bar_content.remove_style_class("visible")
|
||||
self.set_property("visible", False)
|
||||
else:
|
||||
self.bar.remove_style_class("hidden")
|
||||
self.bar.add_style_class("visible")
|
||||
self.bar_content.add_style_class("visible")
|
||||
self.bar_content.remove_style_class("hidden")
|
||||
self.set_property("visible", True)
|
||||
|
||||
|
||||
class ScreenCorners(Window):
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
layer="top",
|
||||
anchor="top left bottom right",
|
||||
pass_through=True,
|
||||
child=Box(
|
||||
orientation="vertical",
|
||||
children=[
|
||||
Box(
|
||||
children=[
|
||||
self.make_corner("top-left"),
|
||||
Box(h_expand=True),
|
||||
self.make_corner("top-right"),
|
||||
]
|
||||
),
|
||||
Box(v_expand=True),
|
||||
Box(
|
||||
children=[
|
||||
self.make_corner("bottom-left"),
|
||||
Box(h_expand=True),
|
||||
self.make_corner("bottom-right"),
|
||||
]
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
def make_corner(self, orientation) -> Box:
|
||||
return Box(
|
||||
h_expand=False,
|
||||
v_expand=False,
|
||||
name="bar-corner",
|
||||
children=Corner(
|
||||
orientation=orientation,
|
||||
size=15,
|
||||
),
|
||||
)
|
||||
@@ -1,6 +1,5 @@
|
||||
from .battery import *
|
||||
from .stats import *
|
||||
from .taskbar import *
|
||||
from .metric import *
|
||||
from .workspace import *
|
||||
from .indicators import *
|
||||
from .system_indicators import *
|
||||
from .updates import *
|
||||
@@ -10,10 +10,10 @@ from fabric.widgets.revealer import Revealer
|
||||
from fabric.core.fabricator import Fabricator
|
||||
from fabric.utils.helpers import exec_shell_command_async
|
||||
from gi.repository import GLib
|
||||
import snippets.iconss as icons
|
||||
import utils.icons as icons
|
||||
|
||||
|
||||
class BatteryLabel(Box):
|
||||
class Battery(Box):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(
|
||||
name="battery",
|
||||
@@ -59,8 +59,8 @@ class BatteryLabel(Box):
|
||||
value=0,
|
||||
size=28,
|
||||
line_width=2,
|
||||
start_angle=180,
|
||||
end_angle=360,
|
||||
start_angle=150,
|
||||
end_angle=390,
|
||||
)
|
||||
|
||||
self.bat_overlay = Overlay(
|
||||
|
||||
@@ -5,11 +5,10 @@ from fabric.widgets.label import Label
|
||||
from fabric.widgets.box import Box
|
||||
from fabric.widgets.overlay import Overlay
|
||||
from fabric.widgets.circularprogressbar import CircularProgressBar
|
||||
|
||||
import snippets.iconss as icons
|
||||
import utils.icons as icons
|
||||
|
||||
|
||||
class SystemInfo(Box):
|
||||
class Metrics(Box):
|
||||
ICONS = {
|
||||
"CPU": icons.cpu,
|
||||
"RAM": icons.memory,
|
||||
@@ -20,7 +19,7 @@ class SystemInfo(Box):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(
|
||||
name="system-info",
|
||||
name="metrics",
|
||||
spacing=8,
|
||||
h_align="center",
|
||||
v_align="fill",
|
||||
@@ -30,14 +29,12 @@ class SystemInfo(Box):
|
||||
|
||||
self.progress_bars = {
|
||||
system: CircularProgressBar(
|
||||
name="stats-progress",
|
||||
name="metric-circle",
|
||||
line_style="round",
|
||||
line_width=3,
|
||||
line_width=2,
|
||||
size=28,
|
||||
start_at=0,
|
||||
end_at=0.5,
|
||||
start_angle=0,
|
||||
end_angle=180,
|
||||
start_angle=150,
|
||||
end_angle=390,
|
||||
)
|
||||
for system in self.ICONS
|
||||
}
|
||||
@@ -45,7 +42,7 @@ class SystemInfo(Box):
|
||||
for system, icon_name in self.ICONS.items():
|
||||
overlay = Overlay(
|
||||
child=self.progress_bars[system],
|
||||
overlays=[Label(name="stats-icons", markup=icon_name)],
|
||||
overlays=[Label(name="metric-icon", markup=icon_name)],
|
||||
)
|
||||
self.add(overlay)
|
||||
|
||||
@@ -55,14 +52,17 @@ class SystemInfo(Box):
|
||||
ram_usage = psutil.virtual_memory().percent
|
||||
swap_usage = psutil.swap_memory().percent
|
||||
disk_usage = psutil.disk_usage("/").percent
|
||||
cpu = psutil.cpu_percent(interval=0)
|
||||
cpu_usage = psutil.cpu_percent(interval=0)
|
||||
|
||||
temp = self._get_device_temperature()
|
||||
temp_usage = temp if temp is not None else 0
|
||||
|
||||
usages = {
|
||||
"CPU": cpu,
|
||||
"CPU": cpu_usage,
|
||||
"RAM": ram_usage,
|
||||
"Swap": swap_usage,
|
||||
"Disk": disk_usage,
|
||||
"Temp": self._get_device_temperature(),
|
||||
"Temp": temp_usage,
|
||||
}
|
||||
|
||||
for system, usage in usages.items():
|
||||
@@ -76,7 +76,7 @@ class SystemInfo(Box):
|
||||
try:
|
||||
temps = psutil.sensors_temperatures()
|
||||
for key in ("coretemp", "cpu_thermal"):
|
||||
if key in temps:
|
||||
if key in temps and temps[key]:
|
||||
return round(temps[key][0].current, 1)
|
||||
except Exception:
|
||||
pass
|
||||
+10
-10
@@ -4,19 +4,19 @@ from fabric.widgets.label import Label
|
||||
from fabric.widgets.box import Box
|
||||
from fabric.bluetooth import BluetoothClient
|
||||
from services import NetworkClient, audio
|
||||
import snippets.iconss as icons
|
||||
import utils.icons as icons
|
||||
|
||||
|
||||
class Indicators(Box):
|
||||
class SystemIndicators(Box):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(orientation="h", spacing=2, **kwargs)
|
||||
|
||||
self.bluetooth_icon = Label(name="indicator-icon")
|
||||
self.wifi_icon = Label(name="indicator-icon")
|
||||
self.volume_icon_button = Label(name="indicator-icon")
|
||||
self.microphone_icon = Label(name="indicator-icon")
|
||||
self.idle_label = Label(name="indicator-icon")
|
||||
self.night_label = Label(name="indicator-icon")
|
||||
self.bluetooth_icon = Label(name="system-indicator-icon")
|
||||
self.wifi_icon = Label(name="system-indicator-icon")
|
||||
self.volume_icon_button = Label(name="system-indicator-icon")
|
||||
self.microphone_icon = Label(name="system-indicator-icon")
|
||||
self.idle_label = Label(name="system-indicator-icon")
|
||||
self.night_label = Label(name="system-indicator-icon")
|
||||
|
||||
for widget in [
|
||||
self.bluetooth_icon,
|
||||
@@ -86,8 +86,8 @@ class Indicators(Box):
|
||||
if stream.muted
|
||||
else (
|
||||
icons.vol_mute
|
||||
if volume_level == 0
|
||||
else (icons.vol_medium if volume_level <= 50 else icons.vol_high)
|
||||
if volume_level < 1
|
||||
else (icons.vol_medium if volume_level >= 1 else icons.vol_high)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
import json
|
||||
import os
|
||||
from typing import TypedDict
|
||||
|
||||
from fabric.hyprland.widgets import get_hyprland_connection
|
||||
from fabric.utils import exec_shell_command_async
|
||||
from fabric.widgets.box import Box
|
||||
from fabric.widgets.button import Button
|
||||
from fabric.widgets.image import Image
|
||||
from gi.repository import GdkPixbuf, GLib, Gtk
|
||||
from loguru import logger
|
||||
|
||||
|
||||
class PagerClient(TypedDict):
|
||||
title: str
|
||||
initialClass: str
|
||||
mapped: bool
|
||||
hidden: bool
|
||||
address: str
|
||||
|
||||
|
||||
class TaskBar(Box):
|
||||
def __init__(self, icon_size: int = 22, **kwargs):
|
||||
super().__init__(
|
||||
orientation="h",
|
||||
spacing=7,
|
||||
name="taskbar",
|
||||
**kwargs,
|
||||
)
|
||||
self.connection = get_hyprland_connection()
|
||||
self.icon_size = icon_size
|
||||
self.icon_theme = Gtk.IconTheme.get_default()
|
||||
|
||||
self.set_visible(False)
|
||||
|
||||
if self.connection.ready:
|
||||
self.render_with_delay()
|
||||
else:
|
||||
self.connection.connect("event::ready", lambda *_: self.render_with_delay())
|
||||
|
||||
for event in (
|
||||
"activewindow",
|
||||
"openwindow",
|
||||
"closewindow",
|
||||
"changefloatingmode",
|
||||
):
|
||||
self.connection.connect("event::" + event, lambda *_: self.render(None))
|
||||
|
||||
def render_with_delay(self, *_):
|
||||
GLib.timeout_add(101, self.render)
|
||||
|
||||
def render(self, *_):
|
||||
self.children = []
|
||||
|
||||
clients = self.fetch_clients()
|
||||
active_window_address = self.get_active_window_address()
|
||||
|
||||
visible_clients = [
|
||||
client for client in clients if client["mapped"] and not client["hidden"]
|
||||
]
|
||||
|
||||
if visible_clients:
|
||||
for client in visible_clients:
|
||||
window_class = client["initialClass"].lower()
|
||||
icon = self.bake_window_icon(window_class)
|
||||
|
||||
button = Button(image=icon, tooltip_text=client["title"])
|
||||
if client["address"] == active_window_address:
|
||||
button.add_style_class("activated")
|
||||
button.connect(
|
||||
"button-press-event",
|
||||
self.on_icon_click,
|
||||
client["address"],
|
||||
)
|
||||
|
||||
self.add(button)
|
||||
self.set_visible(True)
|
||||
self.show_all()
|
||||
else:
|
||||
self.set_visible(False)
|
||||
|
||||
self.set_visible(len(self.children) > 0)
|
||||
if self.children:
|
||||
self.show_all()
|
||||
|
||||
def get_active_window_address(self) -> str:
|
||||
active_window_info = json.loads(
|
||||
self.connection.send_command("j/activewindow").reply.decode()
|
||||
)
|
||||
return active_window_info.get("address", "")
|
||||
|
||||
def on_icon_click(self, widget, event, address):
|
||||
exec_shell_command_async(
|
||||
f"hyprctl dispatch focuswindow address:{address}", lambda *_: None
|
||||
)
|
||||
|
||||
def fetch_clients(self) -> list[PagerClient]:
|
||||
return json.loads(self.connection.send_command("j/clients").reply.decode())
|
||||
|
||||
def bake_window_icon(
|
||||
self,
|
||||
window_class: str,
|
||||
fallback_icon: str = "image-missing",
|
||||
) -> Image:
|
||||
icon_name = self.get_icon_from_desktop_entry(window_class)
|
||||
|
||||
if icon_name:
|
||||
pixbuf = self.load_icon(icon_name)
|
||||
else:
|
||||
pixbuf = self.load_icon(window_class, fallback_icon)
|
||||
|
||||
return Image(pixbuf=pixbuf, size=self.icon_size)
|
||||
|
||||
def get_icon_from_desktop_entry(self, window_class: str) -> str:
|
||||
for data_dir in GLib.get_system_data_dirs():
|
||||
applications_dir = os.path.join(data_dir, "applications")
|
||||
|
||||
if os.path.isdir(applications_dir):
|
||||
for desktop_file in os.listdir(applications_dir):
|
||||
if desktop_file.endswith(".desktop"):
|
||||
file_path = os.path.join(applications_dir, desktop_file)
|
||||
try:
|
||||
with open(file_path) as f:
|
||||
app_name = None
|
||||
icon_name = None
|
||||
for line in f:
|
||||
if line.startswith("Name="):
|
||||
app_name = line.split("=", 2)[1].strip().lower()
|
||||
elif line.startswith("Icon=") and app_name:
|
||||
icon_name = line.split("=", 2)[1].strip()
|
||||
if window_class in app_name:
|
||||
return icon_name
|
||||
except Exception as e:
|
||||
logger.error(f"Error reading {file_path}: {e}")
|
||||
return None
|
||||
|
||||
def load_icon(
|
||||
self,
|
||||
icon_name: str,
|
||||
fallback_icon: str = "image-missing",
|
||||
) -> GdkPixbuf.Pixbuf:
|
||||
try:
|
||||
pixbuf = self.icon_theme.load_icon(
|
||||
icon_name,
|
||||
self.icon_size,
|
||||
Gtk.IconLookupFlags.FORCE_SIZE,
|
||||
)
|
||||
except Exception:
|
||||
pixbuf = self.icon_theme.load_icon(
|
||||
fallback_icon,
|
||||
self.icon_size,
|
||||
Gtk.IconLookupFlags.FORCE_SIZE,
|
||||
)
|
||||
return pixbuf
|
||||
@@ -3,11 +3,11 @@ from fabric.utils import exec_shell_command_async, get_relative_path, invoke_rep
|
||||
from fabric.widgets.box import Box
|
||||
from fabric.widgets.centerbox import CenterBox
|
||||
from fabric.widgets.label import Label
|
||||
from fabric.widgets.button import Button
|
||||
from fabric.widgets.stack import Stack
|
||||
import snippets.iconss as icons
|
||||
from loguru import logger
|
||||
from gi.repository import Gtk
|
||||
from fabric.widgets.button import Button
|
||||
import utils.icons as icons
|
||||
|
||||
|
||||
class UpdatesWidget(Button):
|
||||
|
||||
Reference in new issue
Block a user