EU-Utility/core/icon_manager.py

167 lines
5.9 KiB
Python

"""
EU-Utility - Icon Manager
Manages actual icon files (SVG/PNG) - NO emojis.
Integrates with Icon Extractor for TGA conversion.
"""
from pathlib import Path
from PyQt6.QtGui import QIcon, QPixmap, QPainter
from PyQt6.QtCore import Qt, QSize
from PyQt6.QtSvg import QSvgRenderer
class IconManager:
"""Manages icons for EU-Utility - no emojis, only real icons."""
_instance = None
# Default icon fallback (gear/settings icon)
DEFAULT_ICON = """<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>"""
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance._initialized = False
return cls._instance
def __init__(self, icons_dir="assets/icons"):
if self._initialized:
return
self.icons_dir = Path(icons_dir)
self.svg_cache = {}
self._initialized = True
def get_icon(self, name, size=24, color="white"):
"""Get icon by name. Returns QIcon."""
# Try SVG file first
svg_path = self.icons_dir / f"{name}.svg"
if svg_path.exists():
return self._svg_to_icon(svg_path, size, color)
# Try PNG
png_path = self.icons_dir / f"{name}.png"
if png_path.exists():
return QIcon(str(png_path))
# Return default icon
return self._get_default_icon(size, color)
def get_pixmap(self, name, size=24, color="white"):
"""Get icon as QPixmap."""
# Try SVG
svg_path = self.icons_dir / f"{name}.svg"
if svg_path.exists():
return self._svg_to_pixmap(svg_path, size, color)
# Try PNG
png_path = self.icons_dir / f"{name}.png"
if png_path.exists():
return QPixmap(str(png_path)).scaled(size, size, Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation)
# Return default
return self._get_default_pixmap(size, color)
def _svg_to_icon(self, svg_path, size, color):
"""Convert SVG to QIcon."""
pixmap = self._svg_to_pixmap(svg_path, size, color)
return QIcon(pixmap) if pixmap else self._get_default_icon(size, color)
def _svg_to_pixmap(self, svg_path, size, color):
"""Convert SVG to QPixmap."""
try:
renderer = QSvgRenderer(str(svg_path))
pixmap = QPixmap(size, size)
pixmap.fill(Qt.GlobalColor.transparent)
painter = QPainter(pixmap)
renderer.render(painter)
painter.end()
return pixmap
except Exception as e:
print(f"[IconManager] Error loading SVG {svg_path}: {e}")
return None
def _get_default_icon(self, size, color):
"""Get default gear icon."""
pixmap = self._get_default_pixmap(size, color)
return QIcon(pixmap)
def _get_default_pixmap(self, size, color):
"""Render default SVG as pixmap."""
try:
from PyQt6.QtCore import QByteArray
svg_data = self.DEFAULT_ICON.encode('utf-8')
renderer = QSvgRenderer(QByteArray(svg_data))
pixmap = QPixmap(size, size)
pixmap.fill(Qt.GlobalColor.transparent)
painter = QPainter(pixmap)
renderer.render(painter)
painter.end()
return pixmap
except Exception as e:
print(f"[IconManager] Error rendering default icon: {e}")
# Return empty pixmap as last resort
return QPixmap(size, size)
def icon_exists(self, name):
"""Check if icon exists."""
svg_path = self.icons_dir / f"{name}.svg"
png_path = self.icons_dir / f"{name}.png"
return svg_path.exists() or png_path.exists()
# Plugin icon mappings - using actual icon names (no emojis)
PLUGIN_ICONS = {
# Core
"Dashboard": "grid",
"Universal Search": "search",
"Calculator": "calculator",
"Spotify": "music",
"Nexus Search": "globe",
"Game Reader": "camera",
"Skill Scanner": "trending-up",
"Settings": "settings",
"Plugin Store": "shopping-bag",
# Hunting/Mining
"Loot Tracker": "package",
"Mining Helper": "pickaxe",
"Global Tracker": "award",
"Codex Tracker": "book",
# Economy/Crafting
"Auction Tracker": "dollar-sign",
"DPP Calculator": "crosshair",
"Enhancer Calc": "zap",
"Inventory": "archive",
"Crafting Calc": "tool",
# Utilities
"Chat Logger": "message-square",
"Mission Tracker": "map",
"TP Runner": "navigation",
}
def get_plugin_icon_name(plugin_name):
"""Get icon name for a plugin."""
return PLUGIN_ICONS.get(plugin_name, "settings") # Default to settings/gear
# Singleton instance
_icon_manager = None
def get_icon_manager():
"""Get global icon manager instance."""
global _icon_manager
if _icon_manager is None:
_icon_manager = IconManager()
return _icon_manager