feat(modules): restructure battery UI and add dynamic layout rebuilding

New Features
- Introduce `get_battery_icon_file` to generate battery icons based on percentage and charging state.
- Add fallback Bluetooth control using `rfkill` when Fabric Bluetooth fails.

Enhancements
- Refactor layout management with `_rebuild_layout_from_config` and dynamic indicator instantiation.
- Replace large `EnergyModeButton` class with lightweight utility functions.
- Simplify notification icon updates using `dynamic_file`.

Bug Fixes
- No explicit bug fixes; changes focus on feature additions and refactoring.
This commit is contained in:
sankalp committed 2026-02-26 06:24:44 +05:45
1 parent 15be2f3de6
commit e97311e2b0
18 files changed
+2373 -2233

No files matched your search

+31 -138
View File
@@ -1,21 +1,17 @@
"""
Enhanced System Tray Icon Handling
Simplified System Tray Icon Patch
This module provides enhanced icon loading capabilities for system tray items,
including fallback mechanisms for file paths and common icon locations.
Focuses on loading icons from absolute file paths and fixing tooltip naming.
"""
import os
from gi.repository import GdkPixbuf, Gtk
from pathlib import Path
from fabric.system_tray.widgets import SystemTrayItem
# FIX: the tooltip should show application names instead of unknown
from fabric.utils import GdkPixbuf, GLib
def patched_do_update_properties(self, *_):
# Try default GTK theme first
# Determine the icon name to use
icon_name = self._item.icon_name
attention_icon_name = self._item.attention_icon_name
@@ -24,142 +20,39 @@ def patched_do_update_properties(self, *_):
else:
preferred_icon_name = icon_name
# Try to load from default GTK theme
if preferred_icon_name:
try:
default_theme = Gtk.IconTheme.get_default()
if default_theme.has_icon(preferred_icon_name):
pixbuf = default_theme.load_icon(
preferred_icon_name, self._icon_size, Gtk.IconLookupFlags.FORCE_SIZE
# 1. Try the standard fabric/GTK implementation first
pixbuf = self._item.get_preferred_icon_pixbuf(self._icon_size)
# 2. If standard lookup fails, try your specific absolute path logic
if pixbuf is None and preferred_icon_name:
path = Path(preferred_icon_name)
if path.is_absolute() and path.exists():
try:
target_size = self._icon_size if self._icon_size else 24
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
str(path),
target_size,
target_size,
True, # Preserve aspect ratio
)
if pixbuf:
self._image.set_from_pixbuf(pixbuf)
# Set tooltip
tooltip = self._item.tooltip
self.set_tooltip_markup(
tooltip.description or tooltip.title or self._item.title.title()
if self._item.title
else "Unknown"
)
return
except:
pass
except GLib.GError:
pixbuf = None
# Enhanced fallback handling for file paths
if preferred_icon_name and self._try_load_icon_from_path(preferred_icon_name):
return
# Apply the resulting pixbuf or the fallback "missing" icon
if pixbuf:
self._image.set_from_pixbuf(pixbuf)
else:
self._image.set_from_icon_name("image-missing", self._icon_size)
# Fallback to original implementation
original_do_update_properties(self, *_)
def _try_load_icon_from_path(self, icon_path):
try:
# Check if it's a file path and handle it directly
if os.path.isabs(icon_path) or "/" in icon_path:
# Try to load as SVG from the original path if it exists
if os.path.exists(icon_path):
if icon_path.lower().endswith(".svg"):
# Load SVG directly
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(
icon_path, self._icon_size, self._icon_size
)
if pixbuf:
self._image.set_from_pixbuf(pixbuf)
self._set_tooltip()
return True
else:
# Load other image formats
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(
icon_path, self._icon_size, self._icon_size
)
if pixbuf:
self._image.set_from_pixbuf(pixbuf)
self._set_tooltip()
return True
# If it's a file path, try to extract just the filename for theme lookup
filename = os.path.basename(icon_path)
if filename:
# Remove extension for theme lookup
name_without_ext = os.path.splitext(filename)[0]
default_theme = Gtk.IconTheme.get_default()
# Try filename without extension
if default_theme.has_icon(name_without_ext):
pixbuf = default_theme.load_icon(
name_without_ext,
self._icon_size,
Gtk.IconLookupFlags.FORCE_SIZE,
)
if pixbuf:
self._image.set_from_pixbuf(pixbuf)
self._set_tooltip()
return True
# Try full filename
if default_theme.has_icon(filename):
pixbuf = default_theme.load_icon(
filename, self._icon_size, Gtk.IconLookupFlags.FORCE_SIZE
)
if pixbuf:
self._image.set_from_pixbuf(pixbuf)
self._set_tooltip()
return True
# If it looks like a file path but doesn't exist, try common icon locations
if os.path.isabs(icon_path):
common_icon_dirs = [
"/usr/share/icons",
"/usr/share/pixmaps",
"/usr/local/share/icons",
"/usr/local/share/pixmaps",
os.path.expanduser("~/.local/share/icons"),
os.path.expanduser("~/.icons"),
]
filename = os.path.basename(icon_path)
for icon_dir in common_icon_dirs:
potential_path = os.path.join(icon_dir, filename)
if os.path.exists(potential_path):
try:
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(
potential_path, self._icon_size, self._icon_size
)
if pixbuf:
self._image.set_from_pixbuf(pixbuf)
self._set_tooltip()
return True
except:
continue
except Exception:
pass
return False
def _set_tooltip(self):
tooltip = self._item.tooltip
self.set_tooltip_markup(
tooltip.description or tooltip.title or self._item.title.title()
if self._item.title
else "Unknown"
tooltip.description
or tooltip.title
or (self._item.title.title() if self._item.title else None)
or "Unknown"
)
def apply_enhanced_system_tray():
# Store original method
global original_do_update_properties
original_do_update_properties = SystemTrayItem.do_update_properties
# Attach helper methods to SystemTrayItem class
SystemTrayItem._try_load_icon_from_path = _try_load_icon_from_path
SystemTrayItem._set_tooltip = _set_tooltip
# Replace the do_update_properties method
# Replace the method on the class so all tray items use this logic
SystemTrayItem.do_update_properties = patched_do_update_properties
# Store reference to original method
original_do_update_properties = None