🔧 - 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:
14 files changed
+1596
-12
No files matched your search
@@ -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()
|
||||
Reference in new issue
Block a user