"""모노크롬 라인 아이콘 (Lucide 스타일) — 테마 색으로 틴팅한 QIcon 생성.
이모지를 대체하는 세련된 벡터 아이콘. QtSvg로 24x24 stroke path를 렌더링하고
(name, color, size)별로 캐시. 색은 호출 시점의 테마 색을 받으므로 테마 전환 시
재호출하면 자동으로 재틴팅된다.
사용:
from ui.icons import get_icon
btn.setIcon(get_icon('settings')) # 기본: text_secondary 색
btn.setIcon(get_icon('logout', '#FFFFFF')) # 색 지정
"""
from __future__ import annotations
from PyQt5.QtCore import QByteArray, QRectF, Qt
from PyQt5.QtGui import QIcon, QPixmap, QPainter
from PyQt5.QtSvg import QSvgRenderer
from ui.styles import ThemeColors
# 24x24 viewBox 기준 내부 path 마크업 (Lucide). stroke 기반, fill 없음.
_PATHS = {
'chart': '',
'calendar': '',
'report': '',
'award': '',
'help': '',
'settings': '',
'logout': '',
'rotate-ccw': '',
'edit': '',
'clock': '',
'trash': '',
'flame': '',
'trending-up': '',
'search': '',
'external-link': '',
'coffee': '',
'repeat': '',
'home': '',
}
_SVG_TMPL = (
''
)
_cache: dict = {}
def get_icon(name: str, color: str = None, size: int = 18) -> QIcon:
"""이름·색·크기로 틴팅된 QIcon 반환 (캐시됨). 미정의 이름은 빈 QIcon."""
if color is None:
color = ThemeColors.get('text_secondary')
key = (name, color, size)
cached = _cache.get(key)
if cached is not None:
return cached
paths = _PATHS.get(name)
if paths is None:
return QIcon()
svg = _SVG_TMPL.format(color=color, paths=paths).encode('utf-8')
renderer = QSvgRenderer(QByteArray(svg))
dpr = 2 # 2x 렌더 후 devicePixelRatio 지정 → HiDPI에서도 선명
pm = QPixmap(size * dpr, size * dpr)
pm.fill(Qt.transparent)
painter = QPainter(pm)
renderer.render(painter, QRectF(0, 0, size * dpr, size * dpr))
painter.end()
pm.setDevicePixelRatio(dpr)
icon = QIcon(pm)
_cache[key] = icon
return icon
def clear_cache() -> None:
"""테마 전환 등으로 캐시를 비울 때 사용 (보통은 키가 색을 포함하므로 불필요)."""
_cache.clear()