142 lines
4.5 KiB
Python
142 lines
4.5 KiB
Python
"""Icon loader utility for host icons with fallback support."""
|
|
|
|
import os
|
|
from pathlib import Path
|
|
import gi
|
|
gi.require_version('Gtk', '3.0')
|
|
from gi.repository import Gtk, GdkPixbuf
|
|
from models import HostType
|
|
|
|
|
|
class IconLoader:
|
|
"""Manages loading of host icons with fallback to Material Icons."""
|
|
|
|
# Default icon size
|
|
ICON_SIZE = 20
|
|
|
|
# Project root directory
|
|
PROJECT_ROOT = Path(__file__).parent.parent
|
|
ICONS_DIR = PROJECT_ROOT / "assets" / "icons"
|
|
|
|
# Material Icons fallback mapping for host types
|
|
HOST_TYPE_ICONS = {
|
|
HostType.LINUX: "computer",
|
|
HostType.WINDOWS: "desktop_windows",
|
|
HostType.WINDOWS_SERVER: "dns",
|
|
HostType.PROXMOX: "developer_board",
|
|
HostType.ESXI: "developer_board",
|
|
HostType.ROUTER: "router",
|
|
HostType.SWITCH: "device_hub"
|
|
}
|
|
|
|
@classmethod
|
|
def get_host_icon_widget(cls, host, size=None) -> Gtk.Widget:
|
|
"""Get an icon widget for a host, either custom SVG or Material Icon fallback.
|
|
|
|
Args:
|
|
host: Host object with optional icon field
|
|
size: Icon size in pixels (default: ICON_SIZE)
|
|
|
|
Returns:
|
|
Gtk.Image if custom icon exists, Gtk.Label with Material Icon otherwise
|
|
"""
|
|
if size is None:
|
|
size = cls.ICON_SIZE
|
|
|
|
# Try custom icon first
|
|
if host.icon:
|
|
icon_widget = cls._load_custom_icon(host.icon, size)
|
|
if icon_widget:
|
|
return icon_widget
|
|
|
|
# Fallback to Material Icons based on host type
|
|
return cls._create_material_icon(host.host_type, size)
|
|
|
|
@classmethod
|
|
def _load_custom_icon(cls, icon_name: str, size: int) -> Gtk.Image:
|
|
"""Load a custom SVG icon from assets/icons directory.
|
|
|
|
Args:
|
|
icon_name: Name of the icon file without extension (e.g., 'ubuntu')
|
|
size: Icon size in pixels
|
|
|
|
Returns:
|
|
Gtk.Image if icon exists, None otherwise
|
|
"""
|
|
# Try SVG first, then PNG
|
|
for extension in ['.svg', '.png']:
|
|
icon_path = cls.ICONS_DIR / f"{icon_name}{extension}"
|
|
|
|
if icon_path.exists():
|
|
try:
|
|
# Load and scale the icon
|
|
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(
|
|
str(icon_path), size, size
|
|
)
|
|
image = Gtk.Image.new_from_pixbuf(pixbuf)
|
|
return image
|
|
except Exception as e:
|
|
print(f"Failed to load icon {icon_path}: {e}")
|
|
|
|
return None
|
|
|
|
@classmethod
|
|
def _create_material_icon(cls, host_type: HostType, size: int) -> Gtk.Label:
|
|
"""Create a Material Icon label for a host type.
|
|
|
|
Args:
|
|
host_type: HostType enum value
|
|
size: Icon size in pixels
|
|
|
|
Returns:
|
|
Gtk.Label with Material Icon
|
|
"""
|
|
icon_name = cls.HOST_TYPE_ICONS.get(host_type, "computer")
|
|
|
|
label = Gtk.Label()
|
|
label.set_text(icon_name)
|
|
label.get_style_context().add_class("material-icons")
|
|
|
|
# Apply custom CSS for size
|
|
css = f"""
|
|
#{label.get_name()} {{
|
|
font-size: {size}px;
|
|
}}
|
|
"""
|
|
|
|
return label
|
|
|
|
@classmethod
|
|
def get_service_icon(cls, service_type: str, is_accessible: bool) -> Gtk.Label:
|
|
"""Get a Material Icon for a service with color coding.
|
|
|
|
Args:
|
|
service_type: Service type string (e.g., 'SSH', 'Web GUI')
|
|
is_accessible: Whether the service is currently accessible
|
|
|
|
Returns:
|
|
Gtk.Label with colored Material Icon
|
|
"""
|
|
# Service type to Material Icons mapping
|
|
service_icons = {
|
|
'SSH': 'terminal',
|
|
'Web GUI': 'language',
|
|
'RDP': 'desktop_windows',
|
|
'VNC': 'monitor',
|
|
'SMB': 'folder_shared',
|
|
'Database': 'storage',
|
|
'FTP': 'cloud_upload'
|
|
}
|
|
|
|
icon_name = service_icons.get(service_type, 'settings')
|
|
|
|
label = Gtk.Label()
|
|
label.set_text(icon_name)
|
|
|
|
# Apply color based on accessibility
|
|
if is_accessible:
|
|
label.get_style_context().add_class("service-icon-accessible")
|
|
else:
|
|
label.get_style_context().add_class("service-icon-inaccessible")
|
|
|
|
return label |