🔧 - This commit adds example configurations for several features and widgets, including app launcher, status bar, bluetooth widget, desktop widget, icon browser, notifications, and side panel.

This commit is contained in:
sankalp committed 2025-07-04 12:41:17 +05:45
1 parent bc11606e11
commit aeebf26b8d
14 files changed
+1596 -12

No files matched your search

+174
View File
@@ -0,0 +1,174 @@
"""side panel example, contains info about the system"""
import os
import time
import psutil
from loguru import logger
from fabric import Application
from fabric.widgets.box import Box
from fabric.widgets.label import Label
from fabric.widgets.overlay import Overlay
from fabric.widgets.datetime import DateTime
from fabric.widgets.circularprogressbar import CircularProgressBar
from fabric.widgets.wayland import WaylandWindow as Window
from fabric.utils import invoke_repeater, get_relative_path
def get_profile_picture_path() -> str | None:
path = os.path.expanduser("~/Pictures/Other/face.jpg")
if not os.path.exists(path):
path = os.path.expanduser("~/.face")
if not os.path.exists(path):
logger.warning(
"can't fetch a user profile picture, add a profile picture image at ~/.face or at ~/Pictures/Other/profile.jpg"
)
path = None
return path
class SidePanel(Window):
@staticmethod
def bake_progress_bar(name: str = "progress-bar", size: int = 64, **kwargs):
return CircularProgressBar(
name=name, min_value=0, max_value=100, size=size, **kwargs
)
@staticmethod
def bake_progress_icon(**kwargs):
return Label(**kwargs).build().add_style_class("progress-icon").unwrap()
def __init__(self, **kwargs):
super().__init__(
layer="overlay",
title="fabric-overlay",
anchor="top right",
margin="10px 10px 10px 0px",
exclusivity="none",
visible=False,
all_visible=False,
**kwargs,
)
self.profile_pic = Box(
name="profile-pic",
style=f"background-image: url(\"file://{get_profile_picture_path() or ''}\")",
)
self.uptime_label = Label(label=f"{self.get_current_uptime()}")
self.header = Box(
spacing=14,
name="header",
orientation="h",
children=[
self.profile_pic,
Box(
orientation="v",
children=[
DateTime(
name="date-time",
style="margin-top: 4px; min-width: 180px;",
),
self.uptime_label,
],
),
],
)
self.greeter_label = Label(
label=f"Good {'Morning' if time.localtime().tm_hour < 12 else 'Afternoon'}, {os.getlogin().title()}!",
style="font-size: 20px;",
)
self.cpu_progress = self.bake_progress_bar()
self.ram_progress = self.bake_progress_bar()
self.bat_circular = self.bake_progress_bar().build().set_value(42).unwrap()
self.progress_container = Box(
name="progress-bar-container",
spacing=12,
children=[
Box(
children=[
Overlay(
child=self.cpu_progress,
overlays=[
self.bake_progress_icon(
label="",
style="margin-right: 8px; text-shadow: 0 0 10px #fff, 0 0 10px #fff, 0 0 10px #fff;",
)
],
),
],
),
Box(name="progress-bar-sep"),
Box(
children=[
Overlay(
child=self.ram_progress,
overlays=[
self.bake_progress_icon(
label="󰘚",
style="margin-right: 4px; text-shadow: 0 0 10px #fff;",
)
],
)
]
),
Box(name="progress-bar-sep"),
Box(
children=[
Overlay(
child=self.bat_circular,
overlays=[
self.bake_progress_icon(
label="󱊣",
style="margin-right: 0px; text-shadow: 0 0 10px #fff, 0 0 18px #fff;",
)
],
),
],
),
],
)
self.update_status()
invoke_repeater(
15 * 60 * 1000, # every 15min
lambda: (self.uptime_label.set_label(self.get_current_uptime()), True)[1],
)
invoke_repeater(1000, self.update_status)
self.add(
Box(
name="window-inner",
orientation="v",
spacing=24,
children=[self.header, self.greeter_label, self.progress_container],
),
)
self.show_all()
def update_status(self):
self.cpu_progress.value = psutil.cpu_percent()
self.ram_progress.value = psutil.virtual_memory().percent
if not (bat_sen := psutil.sensors_battery()):
self.bat_circular.value = 42
else:
self.bat_circular.value = bat_sen.percent
return True
def get_current_uptime(self):
uptime = time.time() - psutil.boot_time()
uptime_days, remainder = divmod(uptime, 86400)
uptime_hours, remainder = divmod(remainder, 3600)
# uptime_minutes, _ = divmod(remainder, 60)
return f"{int(uptime_days)} {'days' if uptime_days > 1 else 'day'}, {int(uptime_hours)} {'hours' if uptime_hours > 1 else 'hour'}"
if __name__ == "__main__":
side_panel = SidePanel()
app = Application("side-panel", side_panel)
app.set_stylesheet_from_file(get_relative_path("./style.css"))
app.run()
+83
View File
@@ -0,0 +1,83 @@
:vars {
--background: #150d16;
--foreground: #f5dbc4;
--color0: #150d16;
--color1: #72448D;
--color2: #9C5995;
--color3: #D5719F;
--color4: #9A62F3;
--color5: #E075DF;
--color6: #F98F9F;
--color7: #f5dbc4;
--color8: #ab9989;
--color9: #72448D;
--color10: #9C5995;
--color11: #D5719F;
--color12: #9A62F3;
--color13: #E075DF;
--color14: #F98F9F;
--color15: #f5dbc4;
--window-bg: alpha(var(--background), 0.6);
--module-bg: alpha(var(--background), 0.4);
--border-color: var(--color11);
}
* {
all: unset;
font-family: "Jost*";
font-weight: 500;
font-size: 18px;
color: var(--foreground);
}
#window-inner {
border: solid 2px;
border-color: var(--color11);
background-color: var(--window-bg);
border-radius: 100px;
border-radius: 12px;
padding: 10px;
}
#date-time>label {
font-weight: 900;
font-size: 28px;
}
#header {
border: solid 1px var(--border-color);
border-radius: 8px;
box-shadow: 0px 18px 23px -6px rgba(0, 0, 0, 0.75);
background: linear-gradient(90deg,
alpha(var(--color11), 0.2),
alpha(var(--background), 0.2),
var(--module-bg));
}
#profile-pic {
background-color: alpha(var(--color11), 0.2);
background-position: center;
background-repeat: no-repeat;
background-size: cover;
border-radius: 6px;
padding: 32px;
margin: 4px;
}
#progress-bar {
color: var(--module-bg);
border: solid 10px var(--border-color);
}
#progress-bar-sep {
padding: 4px;
margin: 16px 0px;
border-radius: 100px;
background-color: var(--module-bg);
}
#progress-bar-container {
background-color: var(--module-bg);
border-radius: 100px;
padding: 8px;
}