"""Icônes WGSecure — bouclier VPN dessiné via QPainter.""" from PyQt6.QtGui import ( QIcon, QPixmap, QPainter, QColor, QBrush, QPen, QFont, QPainterPath, QLinearGradient, ) from PyQt6.QtCore import Qt, QRect, QPointF def _shield( size: int, body_top: str, body_bot: str, dot_color: str, dot: bool = True, ) -> QPixmap: """Dessine un bouclier avec dégradé vertical et un indicateur coloré.""" pix = QPixmap(size, size) pix.fill(Qt.GlobalColor.transparent) p = QPainter(pix) p.setRenderHint(QPainter.RenderHint.Antialiasing) s = size m = s * 0.06 # marge # --- Forme bouclier --- path = QPainterPath() path.moveTo(s / 2, m) path.lineTo(s - m, s * 0.25) path.cubicTo( s - m, s * 0.65, s * 0.72, s * 0.85, s / 2, s - m, ) path.cubicTo( s * 0.28, s * 0.85, m, s * 0.65, m, s * 0.25, ) path.closeSubpath() # Dégradé vertical corps du bouclier grad = QLinearGradient(QPointF(s / 2, m), QPointF(s / 2, s - m)) grad.setColorAt(0.0, QColor(body_top)) grad.setColorAt(1.0, QColor(body_bot)) p.setBrush(QBrush(grad)) p.setPen(Qt.PenStyle.NoPen) p.drawPath(path) # Liseré blanc semi-transparent pen = QPen(QColor(255, 255, 255, 60)) pen.setWidthF(s * 0.04) p.setPen(pen) p.setBrush(Qt.BrushStyle.NoBrush) p.drawPath(path) # --- "W" centré --- p.setPen(QPen(QColor(255, 255, 255, 230))) font = QFont("Arial", max(7, int(s * 0.38)), QFont.Weight.Bold) p.setFont(font) rect = QRect(int(s * 0.08), int(s * 0.22), int(s * 0.84), int(s * 0.55)) p.drawText(rect, Qt.AlignmentFlag.AlignCenter, "W") # --- Point de statut (coin bas-droit) --- if dot: dr = s * 0.22 dx = s - m - dr * 0.5 dy = s * 0.68 # Halo blanc p.setPen(Qt.PenStyle.NoPen) p.setBrush(QBrush(QColor(255, 255, 255, 200))) p.drawEllipse(QPointF(dx, dy), dr * 0.72, dr * 0.72) # Dot coloré p.setBrush(QBrush(QColor(dot_color))) p.drawEllipse(QPointF(dx, dy), dr * 0.55, dr * 0.55) p.end() return pix def icon_connected(size: int = 32) -> QIcon: return QIcon(_shield(size, "#1a7a4a", "#0d5c35", "#2ecc71", dot=True)) def icon_disconnected(size: int = 32) -> QIcon: return QIcon(_shield(size, "#2c3e50", "#1a252f", "#e74c3c", dot=True)) def icon_connecting(size: int = 32) -> QIcon: return QIcon(_shield(size, "#7d5a00", "#4a3500", "#f39c12", dot=True)) def icon_app(size: int = 32) -> QIcon: """Icône principale multi-tailles — bouclier bleu sans point de statut. Plusieurs résolutions pour la barre des tâches, l'alt-tab et le systray.""" ico = QIcon() for s in (16, 24, 32, 48, 64, 128, 256): ico.addPixmap(_shield(s, "#2980b9", "#1a5276", "#ffffff", dot=False)) return ico def icon_admin(size: int = 32) -> QIcon: return QIcon(_shield(size, "#6c3483", "#4a235a", "#9b59b6", dot=True)) def pixmap_app(size: int = 64) -> QPixmap: return _shield(size, "#2980b9", "#1a5276", "#ffffff", dot=False)