refactor(modules): simplify SVG asset handling across modules

Enhancements:
- Add optimized night‑variant detection for weather icons using a predefined list
- Replace `Svg` usage with direct `svg_file` calls throughout the todo widget, removing redundant relative‑path logic
- Update dock and battery modules to load assets via direct paths, eliminating unnecessary `get_relative_path` calls- Introduce `WEATHER_CACHE_TIMEOUT` constant and tidy up unused imports (`WEATHER_EMOJI_MAP` removed)
- Minor formatting and structural clean‑ups that improve code readability

Bug Fixes:
- Remove dead import of `WEATHER_EMOJI_MAP` and unused constant `WEATHER_EMOJI_MAP`
- Correct syntax of `condition_em` initialization to avoid potential rendering issues

New Features:
- None.
This commit is contained in:
sankalp committed 2026-04-02 23:13:47 +05:45
1 parent 017c127a44
commit c22ea5dfda
10 files changed
+60 -79

No files matched your search

+1 -1
View File
@@ -31,7 +31,7 @@ def get_battery_icon_file(
clamped = max(0, min(100, percentage)) clamped = max(0, min(100, percentage))
step = (clamped // 10) * 10 step = (clamped // 10) * 10
filename = f"battery-{step:03d}{'-charging' if is_charging else ''}.svg" filename = f"battery-{step:03d}{'-charging' if is_charging else ''}.svg"
return svg_file(f"battery/{filename}") return f"battery/{filename}"
def set_bluetooth_enabled_with_fallback(client, enabled: bool): def set_bluetooth_enabled_with_fallback(client, enabled: bool):
+22 -10
View File
@@ -22,8 +22,8 @@ from modules.desktop.constants import (
LOCATION_APIS, LOCATION_APIS,
LOCATION_CACHE_TIMEOUT, LOCATION_CACHE_TIMEOUT,
SYSTEM_UPDATE_INTERVAL, SYSTEM_UPDATE_INTERVAL,
WEATHER_CACHE_TIMEOUT,
WEATHER_DESC_MAP, WEATHER_DESC_MAP,
WEATHER_EMOJI_MAP,
WEATHER_ICON_MAP, WEATHER_ICON_MAP,
WEATHER_GRADIENT_MAP, WEATHER_GRADIENT_MAP,
WEATHER_UPDATE_INTERVAL, WEATHER_UPDATE_INTERVAL,
@@ -114,18 +114,28 @@ def format_weather_data(weather_data: Dict[str, Any], city: str) -> List[str]:
weather_code = current["weathercode"] weather_code = current["weathercode"]
is_day = current.get("is_day", 1) # Default to day if missing is_day = current.get("is_day", 1) # Default to day if missing
base_icon = WEATHER_ICON_MAP.get(weather_code, "weather-none-available") base_icon = WEATHER_ICON_MAP.get(weather_code, "weather-none-available")
# Determine day/night variant if applicable # Determine day/night variant if applicable
icon_name = base_icon icon_name = base_icon
if not is_day: if not is_day:
night_variant = f"{base_icon}-night" night_variant = f"{base_icon}-night"
import os
# Fast check if night variant exists using predefined list or checking the path # Fast check if night variant exists using predefined list or checking the path
# Since we know the variants from earlier, let's just optimistically build it # Since we know the variants from earlier, let's just optimistically build it
# then logic in svg_file will handle resolution seamlessly (fallbacks can be tricky, but we assume it's correct) # then logic in svg_file will handle resolution seamlessly (fallbacks can be tricky, but we assume it's correct)
if base_icon in ["weather-clear", "weather-clouds", "weather-few-clouds", "weather-overcast", "weather-showers", "weather-showers-scattered", "weather-snow", "weather-snow-scattered", "weather-storm"]: if base_icon in [
"weather-clear",
"weather-clouds",
"weather-few-clouds",
"weather-overcast",
"weather-showers",
"weather-showers-scattered",
"weather-snow",
"weather-snow-scattered",
"weather-storm",
]:
icon_name = night_variant icon_name = night_variant
condition = WEATHER_DESC_MAP.get(weather_code, "Unknown") condition = WEATHER_DESC_MAP.get(weather_code, "Unknown")
@@ -226,7 +236,9 @@ class Weather(Box):
ellipsization="end", ellipsization="end",
) )
self.temperature = Label(name="temperature", label="--°", h_align="start") self.temperature = Label(name="temperature", label="--°", h_align="start")
self.condition_em = svg_file("weather/weather-none-available.svg", size=(48, 48), name="condition-emoji") self.condition_em = svg_file(
"weather/weather-none-available.svg", size=(48, 48), name="condition-emoji"
)
self.condition = Label( self.condition = Label(
name="condition", name="condition",
label="Loading...", label="Loading...",
@@ -251,16 +263,16 @@ class Weather(Box):
return return
icon_name, temp, condition, location, maxtemp, mintemp, _ = weather_info icon_name, temp, condition, location, maxtemp, mintemp, _ = weather_info
maxmin = f"H:{maxtemp} L:{mintemp}" maxmin = f"H:{maxtemp} L:{mintemp}"
self.city.set_label(location) self.city.set_label(location)
self.temperature.set_label(temp) self.temperature.set_label(temp)
# update SVG File # update SVG File
self.condition_em.dynamic_file(f"weather/{icon_name}.svg") self.condition_em.dynamic_file(f"weather/{icon_name}.svg")
self.condition.set_label(condition) self.condition.set_label(condition)
self.feels_like.set_label(maxmin) self.feels_like.set_label(maxmin)
self.parent.set_visible(True) self.parent.set_visible(True)
+2 -4
View File
@@ -3,7 +3,7 @@ import os
import re import re
import subprocess import subprocess
from fabric.utils.helpers import get_desktop_applications, get_relative_path from fabric.utils import get_desktop_applications, get_relative_path, logger, GLib, Gtk
from fabric.widgets.box import Box from fabric.widgets.box import Box
from fabric.widgets.button import Button from fabric.widgets.button import Button
from fabric.widgets.eventbox import EventBox from fabric.widgets.eventbox import EventBox
@@ -11,15 +11,13 @@ from fabric.widgets.image import Image
from fabric.widgets.label import Label from fabric.widgets.label import Label
from fabric.widgets.overlay import Overlay from fabric.widgets.overlay import Overlay
from fabric.widgets.revealer import Revealer from fabric.widgets.revealer import Revealer
from gi.repository import GLib, Gtk
from loguru import logger
import config.data as data import config.data as data
from services.modus import modus_service from services.modus import modus_service
from utils.functions import read_json_file, write_json_file, is_special_workspace_id from utils.functions import read_json_file, write_json_file, is_special_workspace_id
from utils.icon_resolver import IconResolver from utils.icon_resolver import IconResolver
from utils.occlusion import check_occlusion from utils.occlusion import check_occlusion
from widgets.wayland import WaylandWindow as Window from fabric.widgets.wayland import WaylandWindow as Window
# Pinned apps file # Pinned apps file
PINNED_APPS_FILE = get_relative_path("../config/assets/dock.json") PINNED_APPS_FILE = get_relative_path("../config/assets/dock.json")
+5 -6
View File
@@ -10,7 +10,6 @@ from typing import Dict, List, Optional
from loguru import logger from loguru import logger
from gi.repository import GdkPixbuf from gi.repository import GdkPixbuf
from PIL import Image
import config.data as data import config.data as data
from fabric.utils.helpers import exec_shell_command_async from fabric.utils.helpers import exec_shell_command_async
@@ -179,10 +178,10 @@ class WallpaperPlugin(PluginBase):
if not os.path.exists(cache_path): if not os.path.exists(cache_path):
try: try:
with Image.open(full_path) as img: pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
# Use faster thumbnail creation with smaller size for better performance full_path, 32, 32, True
img.thumbnail((32, 32), Image.Resampling.LANCZOS) )
img.save(cache_path, "PNG", optimize=True) pixbuf.savev(cache_path, "png", [], [])
except Exception as e: except Exception as e:
logger.error(f"Error creating thumbnail for {filename}: {e}") logger.error(f"Error creating thumbnail for {filename}: {e}")
return None return None
@@ -289,7 +288,7 @@ class WallpaperPlugin(PluginBase):
# Always set the wallpaper image # Always set the wallpaper image
exec_shell_command_async( exec_shell_command_async(
f'swww img "{ f'awww img "{
full_path full_path
}" -t outer --transition-duration 1.5 --transition-step 255 --transition-fps 60 -f Nearest' }" -t outer --transition-duration 1.5 --transition-step 255 --transition-fps 60 -f Nearest'
) )
+4 -9
View File
@@ -1,7 +1,6 @@
import math import math
from fabric.audio import Audio from fabric.audio import Audio
from fabric.utils import get_relative_path from utils.utils import svg_file
from fabric.widgets.svg import Svg
from fabric.widgets.scale import ScaleMark from fabric.widgets.scale import ScaleMark
from .animated_scale import AnimatedScale from .animated_scale import AnimatedScale
from .base import BaseOSDContainer from .base import BaseOSDContainer
@@ -17,8 +16,8 @@ class AudioOSDContainer(BaseOSDContainer):
self._connect_specific_signals() self._connect_specific_signals()
def _setup_specific_components(self): def _setup_specific_components(self):
self.osd_window_image = Svg( self.osd_window_image = svg_file(
get_relative_path("../../../config/assets/icons/volume/audio-volume.svg"), "volume/audio-volume.svg",
size=(100, 100), size=(100, 100),
name="osd-image", name="osd-image",
h_align="center", h_align="center",
@@ -87,11 +86,7 @@ class AudioOSDContainer(BaseOSDContainer):
0 if display_volume == 0 else min(int(math.ceil(display_volume / 33)), 3) 0 if display_volume == 0 else min(int(math.ceil(display_volume / 33)), 3)
) )
self.osd_window_image.set_from_file( self.osd_window_image.set_from_file(f"volume/audio-volume-{level}.svg")
get_relative_path(
f"../../../config/assets/icons/volume/audio-volume-{level}.svg"
)
)
if muted or volume == 0: if muted or volume == 0:
self.scale.add_style_class("muted") self.scale.add_style_class("muted")
+4 -9
View File
@@ -1,7 +1,6 @@
import math import math
from services.brightness import Brightness from services.brightness import Brightness
from fabric.utils import get_relative_path from utils.utils import svg_file
from fabric.widgets.svg import Svg
from fabric.widgets.scale import ScaleMark from fabric.widgets.scale import ScaleMark
from .animated_scale import AnimatedScale from .animated_scale import AnimatedScale
from .base import BaseOSDContainer from .base import BaseOSDContainer
@@ -15,8 +14,8 @@ class BrightnessOSDContainer(BaseOSDContainer):
self._connect_specific_signals() self._connect_specific_signals()
def _setup_specific_components(self): def _setup_specific_components(self):
self.osd_window_image = Svg( self.osd_window_image = svg_file(
get_relative_path("../../../config/assets/icons/brightness/brightness.svg"), "brightness/brightness.svg",
size=(100, 100), size=(100, 100),
name="osd-image", name="osd-image",
h_align="center", h_align="center",
@@ -51,11 +50,7 @@ class BrightnessOSDContainer(BaseOSDContainer):
normalized = self._get_normalized_brightness() normalized = self._get_normalized_brightness()
level = 0 if normalized == 0 else min(int(math.ceil(normalized / 33)), 3) level = 0 if normalized == 0 else min(int(math.ceil(normalized / 33)), 3)
self.osd_window_image.set_from_file( self.osd_window_image.set_from_file(f"brightness/brightness-{level}.svg")
get_relative_path(
f"../../../config/assets/icons/brightness/brightness-{level}.svg"
)
)
self.scale.animate_value(normalized) self.scale.animate_value(normalized)
+4 -7
View File
@@ -1,6 +1,5 @@
from fabric.widgets.label import Label from fabric.widgets.label import Label
from fabric.widgets.svg import Svg from utils.utils import svg_file
from fabric.utils import get_relative_path
from .base import BaseOSDContainer from .base import BaseOSDContainer
from services.capslock import CapsLock from services.capslock import CapsLock
@@ -13,8 +12,8 @@ class CapsLockOSDContainer(BaseOSDContainer):
self._connect_specific_signals() self._connect_specific_signals()
def _setup_specific_components(self): def _setup_specific_components(self):
self.osd_image = Svg( self.osd_image = svg_file(
get_relative_path("../../../assets/icons/misc/caps-lock.svg"), "misc/caps-lock.svg",
size=(100, 100), size=(100, 100),
name="osd-image", name="osd-image",
h_align="center", h_align="center",
@@ -35,9 +34,7 @@ class CapsLockOSDContainer(BaseOSDContainer):
def _update_display(self, is_on: bool): def _update_display(self, is_on: bool):
icon_path = "caps-lock.svg" if is_on else "caps-lock-off.svg" icon_path = "caps-lock.svg" if is_on else "caps-lock-off.svg"
self.osd_image.set_from_file( self.osd_image.set_from_file(f"misc/{icon_path}")
get_relative_path(f"../../../assets/icons/misc/{icon_path}")
)
if is_on: if is_on:
self.add_style_class("capslock-on") self.add_style_class("capslock-on")
self.remove_style_class("capslock-off") self.remove_style_class("capslock-off")
+3 -4
View File
@@ -1,6 +1,5 @@
from fabric.widgets.label import Label from fabric.widgets.label import Label
from fabric.widgets.svg import Svg from utils.utils import svg_file
from fabric.utils import get_relative_path
from .base import BaseOSDContainer from .base import BaseOSDContainer
from services.keyboard_layout import KeyboardLayout from services.keyboard_layout import KeyboardLayout
@@ -13,8 +12,8 @@ class KeyboardLayoutOSDContainer(BaseOSDContainer):
self._connect_specific_signals() self._connect_specific_signals()
def _setup_specific_components(self): def _setup_specific_components(self):
self.osd_image = Svg( self.osd_image = svg_file(
get_relative_path("../../../assets/icons/misc/keyboard-layout.svg"), "misc/keyboard-layout.svg",
size=(100, 100), size=(100, 100),
name="osd-image", name="osd-image",
h_align="center", h_align="center",
+4 -9
View File
@@ -1,7 +1,6 @@
import math import math
from fabric.audio import Audio from fabric.audio import Audio
from fabric.utils import get_relative_path from utils.utils import svg_file
from fabric.widgets.svg import Svg
from fabric.widgets.scale import ScaleMark from fabric.widgets.scale import ScaleMark
from .animated_scale import AnimatedScale from .animated_scale import AnimatedScale
from .base import BaseOSDContainer from .base import BaseOSDContainer
@@ -17,8 +16,8 @@ class MicrophoneOSDContainer(BaseOSDContainer):
self._connect_specific_signals() self._connect_specific_signals()
def _setup_specific_components(self): def _setup_specific_components(self):
self.osd_window_image = Svg( self.osd_window_image = svg_file(
get_relative_path("../../../config/assets/icons/mic/microphone.svg"), "mic/microphone.svg",
size=(100, 100), size=(100, 100),
name="osd-image", name="osd-image",
h_align="center", h_align="center",
@@ -87,11 +86,7 @@ class MicrophoneOSDContainer(BaseOSDContainer):
0 if display_volume == 0 else min(int(math.ceil(display_volume / 33)), 3) 0 if display_volume == 0 else min(int(math.ceil(display_volume / 33)), 3)
) )
self.osd_window_image.set_from_file( self.osd_window_image.set_from_file(f"mic/microphone-{level}.svg")
get_relative_path(
f"../../../config/assets/icons/mic/microphone-{level}.svg"
)
)
if muted or volume == 0: if muted or volume == 0:
self.scale.add_style_class("muted") self.scale.add_style_class("muted")
+11 -20
View File
@@ -2,16 +2,15 @@
from datetime import datetime from datetime import datetime
# Fabric imports # Fabric imports
from fabric.utils import get_relative_path
from fabric.widgets.box import Box from fabric.widgets.box import Box
from fabric.widgets.button import Button from fabric.widgets.button import Button
from fabric.widgets.entry import Entry from fabric.widgets.entry import Entry
from fabric.widgets.label import Label from fabric.widgets.label import Label
from fabric.widgets.scrolledwindow import ScrolledWindow from fabric.widgets.scrolledwindow import ScrolledWindow
from fabric.widgets.svg import Svg
from gi.repository import GLib from gi.repository import GLib
# Local imports # Local imports
from utils.utils import svg_file
from services.todo import get_todo_service from services.todo import get_todo_service
from widgets.mousecapture import MouseCapture from widgets.mousecapture import MouseCapture
from widgets.wayland import WaylandWindow as Window from widgets.wayland import WaylandWindow as Window
@@ -43,12 +42,10 @@ class TodoItem(Box):
if self.todo_data["completed"] if self.todo_data["completed"]
else "checkbox-uncheck.svg" else "checkbox-uncheck.svg"
) )
self.checkbox_icon = Svg( self.checkbox_icon = svg_file(
"todo/" + checkbox_icon,
name="todo-checkbox-icon", name="todo-checkbox-icon",
size=24, size=24,
svg_file=get_relative_path(
"../../config/assets/icons/todo/" + checkbox_icon
),
) )
self.checkbox = Button( self.checkbox = Button(
name="todo-checkbox", name="todo-checkbox",
@@ -108,10 +105,10 @@ class TodoItem(Box):
# ) # )
# #
# Edit button - using SVG icon # Edit button - using SVG icon
self.edit_icon = Svg( self.edit_icon = svg_file(
"todo/edit.svg",
name="todo-edit-icon", name="todo-edit-icon",
size=12, size=12,
svg_file=get_relative_path("../../config/assets/icons/todo/edit.svg"),
) )
self.edit_button = Button( self.edit_button = Button(
name="todo-edit", name="todo-edit",
@@ -120,12 +117,10 @@ class TodoItem(Box):
) )
# Delete button - using SVG icon # Delete button - using SVG icon
self.delete_icon = Svg( self.delete_icon = svg_file(
"todo/delete-symbolic.svg",
name="todo-delete-icon", name="todo-delete-icon",
size=12, size=12,
svg_file=get_relative_path(
"../../config/assets/icons/todo/delete-symbolic.svg"
),
) )
self.delete_button = Button( self.delete_button = Button(
name="todo-delete", name="todo-delete",
@@ -208,12 +203,10 @@ class TodoItem(Box):
checkbox_icon = ( checkbox_icon = (
"checkbox-check.svg" if todo_data["completed"] else "checkbox-uncheck.svg" "checkbox-check.svg" if todo_data["completed"] else "checkbox-uncheck.svg"
) )
new_checkbox_icon = Svg( new_checkbox_icon = svg_file(
"todo/" + checkbox_icon,
name="todo-checkbox-icon", name="todo-checkbox-icon",
size=20, size=20,
svg_file=get_relative_path(
"../../config/assets/icons/todo/" + checkbox_icon
),
) )
self.checkbox.set_child(new_checkbox_icon) self.checkbox.set_child(new_checkbox_icon)
self.checkbox_icon = new_checkbox_icon self.checkbox_icon = new_checkbox_icon
@@ -293,12 +286,10 @@ class TodoListWidget(Window):
self.new_todo_entry.connect("activate", self._add_todo) self.new_todo_entry.connect("activate", self._add_todo)
# Add button - using SVG icon # Add button - using SVG icon
self.add_icon = Svg( self.add_icon = svg_file(
"todo/plus-symbolic.svg",
name="add-todo-icon", name="add-todo-icon",
size=12, size=12,
svg_file=get_relative_path(
"../../config/assets/icons/todo/plus-symbolic.svg"
),
) )
self.add_button = Button( self.add_button = Button(
name="add-todo-button", name="add-todo-button",