Initial commit
Dieser Commit ist enthalten in:
192
views/widgets/icon_factory.py
Normale Datei
192
views/widgets/icon_factory.py
Normale Datei
@ -0,0 +1,192 @@
|
||||
"""
|
||||
Icon Factory - Zentrale Icon-Verwaltung nach Clean Architecture
|
||||
"""
|
||||
|
||||
from PyQt5.QtWidgets import QLabel
|
||||
from PyQt5.QtCore import Qt, QByteArray
|
||||
from PyQt5.QtGui import QIcon, QPixmap, QPainter, QColor
|
||||
from PyQt5.QtSvg import QSvgRenderer
|
||||
import os
|
||||
import logging
|
||||
|
||||
from config.paths import PathConfig
|
||||
|
||||
logger = logging.getLogger("icon_factory")
|
||||
|
||||
|
||||
class IconFactory:
|
||||
"""Factory für die Erstellung und Verwaltung von Icons"""
|
||||
|
||||
# Cache für geladene Icons
|
||||
_icon_cache = {}
|
||||
|
||||
# Standard SVG Icons
|
||||
ICONS = {
|
||||
"mail": '''<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3 8L8.44992 11.6333C9.73295 12.4886 10.3745 12.9163 11.0678 13.0825C11.6806 13.2293 12.3194 13.2293 12.9322 13.0825C13.6255 12.9163 14.2671 12.4886 15.5501 11.6333L21 8M6.2 19H17.8C18.9201 19 19.4802 19 19.908 18.782C20.2843 18.5903 20.5903 18.2843 20.782 17.908C21 17.4802 21 16.9201 21 15.8V8.2C21 7.0799 21 6.51984 20.782 6.09202C20.5903 5.71569 20.2843 5.40973 19.908 5.21799C19.4802 5 18.9201 5 17.8 5H6.2C5.0799 5 4.51984 5 4.09202 5.21799C3.71569 5.40973 3.40973 5.71569 3.21799 6.09202C3 6.51984 3 7.07989 3 8.2V15.8C3 16.9201 3 17.4802 3.21799 17.908C3.40973 18.2843 3.71569 18.5903 4.09202 18.782C4.51984 19 5.07989 19 6.2 19Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>''',
|
||||
|
||||
"key": '''<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12.3212 10.6852L4 19L6 21M7 16L9 18M20 7.5C20 9.98528 17.9853 12 15.5 12C13.0147 12 11 9.98528 11 7.5C11 5.01472 13.0147 3 15.5 3C17.9853 3 20 5.01472 20 7.5Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>''',
|
||||
|
||||
"calendar": '''<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3 10H21M7 3V5M17 3V5M6.2 21H17.8C18.9201 21 19.4802 21 19.908 20.782C20.2843 20.5903 20.5903 20.2843 20.782 19.908C21 19.4802 21 18.9201 21 17.8V8.2C21 7.07989 21 6.51984 20.782 6.09202C20.5903 5.71569 20.2843 5.40973 19.908 5.21799C19.4802 5 18.9201 5 17.8 5H6.2C5.0799 5 4.51984 5 4.09202 5.21799C3.71569 5.40973 3.40973 5.71569 3.21799 6.09202C3 6.51984 3 7.07989 3 8.2V17.8C3 18.9201 3 19.4802 3.21799 19.908C3.40973 20.2843 3.71569 20.5903 4.09202 20.782C4.51984 21 5.07989 21 6.2 21Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>''',
|
||||
|
||||
"copy": '''<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8 8H7.2C6.0799 8 5.51984 8 5.09202 8.21799C4.71569 8.40973 4.40973 8.71569 4.21799 9.09202C4 9.51984 4 10.0799 4 11.2V16.8C4 17.9201 4 18.4802 4.21799 18.908C4.40973 19.2843 4.71569 19.5903 5.09202 19.782C5.51984 20 6.0799 20 7.2 20H12.8C13.9201 20 14.4802 20 14.908 19.782C15.2843 19.5903 15.5903 19.2843 15.782 18.908C16 18.4802 16 17.9201 16 16.8V16M11.2 16H16.8C17.9201 16 18.4802 16 18.908 15.782C19.2843 15.5903 19.5903 15.2843 19.782 14.908C20 14.4802 20 13.9201 20 12.8V7.2C20 6.0799 20 5.51984 19.782 5.09202C19.5903 4.71569 19.2843 4.40973 18.908 4.21799C18.4802 4 17.9201 4 16.8 4H11.2C10.0799 4 9.51984 4 9.09202 4.21799C8.71569 4.40973 8.40973 4.71569 8.21799 5.09202C8 5.51984 8 6.07989 8 7.2V12.8C8 13.9201 8 14.4802 8.21799 14.908C8.40973 15.2843 8.71569 15.5903 9.09202 15.782C9.51984 16 10.0799 16 11.2 16Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>''',
|
||||
|
||||
"eye": '''<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M15.0007 12C15.0007 13.6569 13.6576 15 12.0007 15C10.3439 15 9.00073 13.6569 9.00073 12C9.00073 10.3431 10.3439 9 12.0007 9C13.6576 9 15.0007 10.3431 15.0007 12Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M12.0012 5C7.52354 5 3.73326 7.94288 2.45898 12C3.73324 16.0571 7.52354 19 12.0012 19C16.4788 19 20.2691 16.0571 21.5434 12C20.2691 7.94291 16.4788 5 12.0012 5Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>''',
|
||||
|
||||
"eye-slash": '''<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M2.99902 3L20.999 21M9.8433 9.91364C9.32066 10.4536 8.99902 11.1892 8.99902 12C8.99902 13.6569 10.3422 15 11.999 15C12.8215 15 13.5667 14.669 14.1086 14.133M6.49902 6.64715C4.59972 7.90034 3.15305 9.78394 2.45703 12C3.73128 16.0571 7.52159 19 11.9992 19C13.9881 19 15.8414 18.4194 17.3988 17.4184M10.999 5.04939C11.328 5.01673 11.6617 5 11.9992 5C16.4769 5 20.2672 7.94291 21.5414 12C21.2607 12.894 20.8577 13.7338 20.3522 14.5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>'''
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def get_icon(cls, icon_name: str, size: int = 16, color: str = "#718096") -> QIcon:
|
||||
"""
|
||||
Erstellt ein QIcon aus SVG
|
||||
|
||||
Args:
|
||||
icon_name: Name des Icons
|
||||
size: Größe des Icons
|
||||
color: Farbe des Icons (hex)
|
||||
|
||||
Returns:
|
||||
QIcon Objekt
|
||||
"""
|
||||
cache_key = f"{icon_name}_{size}_{color}"
|
||||
|
||||
if cache_key in cls._icon_cache:
|
||||
return cls._icon_cache[cache_key]
|
||||
|
||||
# Erstelle Pixmap
|
||||
pixmap = cls.get_pixmap(icon_name, size, color)
|
||||
icon = QIcon(pixmap)
|
||||
|
||||
# Cache das Icon
|
||||
cls._icon_cache[cache_key] = icon
|
||||
|
||||
return icon
|
||||
|
||||
@classmethod
|
||||
def get_pixmap(cls, icon_name: str, size: int = 16, color: str = "#718096") -> QPixmap:
|
||||
"""
|
||||
Erstellt ein QPixmap aus SVG
|
||||
|
||||
Args:
|
||||
icon_name: Name des Icons
|
||||
size: Größe des Icons
|
||||
color: Farbe des Icons (hex)
|
||||
|
||||
Returns:
|
||||
QPixmap Objekt
|
||||
"""
|
||||
# Versuche zuerst aus Datei zu laden
|
||||
icon_path = PathConfig.get_icon_path(icon_name)
|
||||
if PathConfig.file_exists(icon_path):
|
||||
pixmap = QPixmap(icon_path)
|
||||
if not pixmap.isNull():
|
||||
return pixmap.scaled(size, size, Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
||||
|
||||
# Fallback auf eingebettete SVGs
|
||||
svg_content = cls.ICONS.get(icon_name)
|
||||
if svg_content:
|
||||
# Ersetze currentColor durch die angegebene Farbe
|
||||
svg_content = svg_content.replace('currentColor', color)
|
||||
|
||||
# Erstelle SVG Renderer
|
||||
renderer = QSvgRenderer(QByteArray(svg_content.encode()))
|
||||
|
||||
# Erstelle Pixmap
|
||||
pixmap = QPixmap(size, size)
|
||||
pixmap.fill(Qt.transparent)
|
||||
|
||||
# Rendere SVG
|
||||
painter = QPainter(pixmap)
|
||||
painter.setRenderHint(QPainter.Antialiasing)
|
||||
renderer.render(painter)
|
||||
painter.end()
|
||||
|
||||
return pixmap
|
||||
|
||||
# Fallback: Erstelle einen farbigen Kreis
|
||||
logger.warning(f"Icon '{icon_name}' nicht gefunden, verwende Platzhalter")
|
||||
pixmap = QPixmap(size, size)
|
||||
pixmap.fill(Qt.transparent)
|
||||
|
||||
painter = QPainter(pixmap)
|
||||
painter.setRenderHint(QPainter.Antialiasing)
|
||||
painter.setBrush(QColor(color))
|
||||
painter.setPen(Qt.NoPen)
|
||||
painter.drawEllipse(0, 0, size, size)
|
||||
painter.end()
|
||||
|
||||
return pixmap
|
||||
|
||||
@classmethod
|
||||
def create_icon_label(cls, icon_name: str, size: int = 16, color: str = "#718096") -> QLabel:
|
||||
"""
|
||||
Erstellt ein QLabel mit Icon
|
||||
|
||||
Args:
|
||||
icon_name: Name des Icons
|
||||
size: Größe des Icons
|
||||
color: Farbe des Icons (hex)
|
||||
|
||||
Returns:
|
||||
QLabel mit Icon
|
||||
"""
|
||||
label = QLabel()
|
||||
label.setFixedSize(size, size)
|
||||
|
||||
# Prüfe ob es eine Plattform ist
|
||||
platform_names = ["instagram", "facebook", "twitter", "x", "tiktok", "vk", "ok", "gmail"]
|
||||
if icon_name.lower() in platform_names:
|
||||
# Verwende get_platform_icon für Plattformen
|
||||
icon = cls.get_platform_icon(icon_name, size)
|
||||
pixmap = icon.pixmap(size, size)
|
||||
else:
|
||||
# Normale Icons
|
||||
pixmap = cls.get_pixmap(icon_name, size, color)
|
||||
|
||||
label.setPixmap(pixmap)
|
||||
label.setScaledContents(True)
|
||||
return label
|
||||
|
||||
@classmethod
|
||||
def get_platform_icon(cls, platform: str, size: int = 18) -> QIcon:
|
||||
"""
|
||||
Gibt ein Platform-spezifisches Icon zurück
|
||||
|
||||
Args:
|
||||
platform: Name der Plattform
|
||||
size: Größe des Icons
|
||||
|
||||
Returns:
|
||||
QIcon für die Plattform
|
||||
"""
|
||||
# Spezialbehandlung für Twitter/X
|
||||
if platform.lower() == "twitter" or platform.lower() == "x":
|
||||
icon_name = "twitter"
|
||||
else:
|
||||
icon_name = platform.lower()
|
||||
|
||||
# Platform Icons haben eigene Farben
|
||||
platform_colors = {
|
||||
"instagram": "#E4405F",
|
||||
"facebook": "#1877F2",
|
||||
"twitter": "#1DA1F2",
|
||||
"x": "#000000",
|
||||
"tiktok": "#000000",
|
||||
"vk": "#0077FF"
|
||||
}
|
||||
|
||||
color = platform_colors.get(icon_name, "#718096")
|
||||
return cls.get_icon(icon_name, size, color)
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren