167 lines
5.9 KiB
Python
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
|