Files
PyQt6_LaTaniere/src/tools/custom_message_box.py

169 lines
6.1 KiB
Python
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import sys
from PySide6.QtWidgets import (QDialog, QVBoxLayout, QHBoxLayout,
QLabel, QPushButton, QWidget, QGraphicsDropShadowEffect)
from PySide6.QtCore import Qt, QPropertyAnimation, QEasingCurve
from PySide6.QtGui import QColor
class CustomMessageBox(QDialog):
# Enums pour la configuration
INFO = "info"
WARNING = "warning"
OK = "ok"
OK_CANCEL = "ok_cancel"
def __init__(self, title="Notification", message="", icon_type="info", buttons="ok", parent=None):
super().__init__(parent)
# --- CONFIGURATION FENÊTRE ---
self.setWindowFlags(Qt.FramelessWindowHint | Qt.Dialog)
self.setAttribute(Qt.WA_TranslucentBackground)
self.setMinimumWidth(400)
color_main = "#101624"
color_accent = "#248277" if icon_type == self.INFO else "#cf5b16"
# --- ANIMATION DE FONDU ---
self.setWindowOpacity(0)
self.fade_anim = QPropertyAnimation(self, b"windowOpacity")
self.fade_anim.setDuration(350)
self.fade_anim.setStartValue(0)
self.fade_anim.setEndValue(1)
self.fade_anim.setEasingCurve(QEasingCurve.OutCubic)
# --- UI SETUP ---
self.container = QWidget(self)
self.container.setObjectName("MainContainer")
self.container.setStyleSheet(f"""
QWidget#MainContainer {{
background: qlineargradient(x1:0, y1:0, x2:1, y2:1,
stop:0 {color_main}, stop:1 {color_accent});
border-radius: 15px;
border: 1px solid rgba(255, 255, 255, 0.1);
}}
QLabel {{ color: white; font-family: 'Segoe UI'; }}
""")
# LAYOUT PRINCIPAL DU CONTAINER (Marges à 0 pour coller le bouton au bord)
layout = QVBoxLayout(self.container)
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0)
# 1. Barre de titre (Contenu collé en haut et à droite)
title_bar_layout = QHBoxLayout()
title_bar_layout.setContentsMargins(15, 0, 0, 0)
title_bar_layout.setSpacing(0)
title_label = QLabel(title.upper())
title_label.setStyleSheet(
"font-weight: bold; font-size: 10px; color: rgba(255,255,255,0.7); letter-spacing: 1px;")
self.close_btn = QPushButton("")
self.close_btn.setFixedSize(45, 35)
self.close_btn.clicked.connect(self.reject)
self.close_btn.setCursor(Qt.PointingHandCursor)
self.close_btn.setStyleSheet("""
QPushButton {
background: transparent;
color: white;
border: none;
font-size: 14px;
/* Rayon identique au container (15px) pour épouser parfaitement le coin */
border-top-right-radius: 15px;
border-bottom-left-radius: 10px;
}
QPushButton:hover {
background-color: #e74c3c;
color: white;
}
""")
title_bar_layout.addWidget(title_label)
title_bar_layout.addStretch()
title_bar_layout.addWidget(self.close_btn)
layout.addLayout(title_bar_layout)
# 2. SOUS-LAYOUT POUR LE CONTENU (Ici on remet des marges pour le texte)
body_layout = QVBoxLayout()
body_layout.setContentsMargins(20, 10, 20, 20)
body_layout.setSpacing(15)
# Contenu central (Icône + Message)
content_layout = QHBoxLayout()
icon_label = QLabel()
icon_text = "" if icon_type == self.INFO else "⚠️"
icon_label.setText(icon_text)
icon_label.setStyleSheet("font-size: 35px; margin-right: 10px;")
msg_label = QLabel(message)
msg_label.setStyleSheet("font-size: 14px; color: #f0f0f0;")
msg_label.setWordWrap(True)
content_layout.addWidget(icon_label)
content_layout.addWidget(msg_label, 1)
body_layout.addLayout(content_layout)
# Boutons d'action
btn_layout = QHBoxLayout()
btn_layout.setSpacing(10)
btn_layout.addStretch()
style_btn_base = """
QPushButton {
background: #2a313d; border-radius: 6px; color: white;
padding: 8px 20px; font-weight: bold; font-size: 12px;
border: 1px solid rgba(255,255,255,0.05);
}
QPushButton:hover { background: #363d4a; border: 1px solid white; }
"""
if buttons == self.OK_CANCEL:
self.btn_cancel = QPushButton("ANNULER")
self.btn_cancel.setStyleSheet(style_btn_base)
self.btn_cancel.clicked.connect(self.reject)
btn_layout.addWidget(self.btn_cancel)
self.btn_ok = QPushButton("COMPRIS")
style_btn_ok = style_btn_base.replace("#2a313d", "#248277")
self.btn_ok.setStyleSheet(style_btn_ok)
self.btn_ok.setCursor(Qt.PointingHandCursor)
self.btn_ok.clicked.connect(self.accept)
btn_layout.addWidget(self.btn_ok)
body_layout.addLayout(btn_layout)
# Ajout du body_layout dans le layout principal
layout.addLayout(body_layout)
# --- OMBRE PORTÉE ---
shadow = QGraphicsDropShadowEffect(self)
shadow.setBlurRadius(20)
shadow.setXOffset(0)
shadow.setYOffset(8)
shadow.setColor(QColor(0, 0, 0, 180))
self.container.setGraphicsEffect(shadow)
final_layout = QVBoxLayout(self)
final_layout.addWidget(self.container)
self.old_pos = None
def showEvent(self, event):
super().showEvent(event)
self.fade_anim.start()
def mousePressEvent(self, e):
# On permet le déplacement uniquement si on clique sur la barre de titre
# ou n'importe où sauf sur les boutons
if e.button() == Qt.LeftButton:
self.old_pos = e.globalPosition().toPoint()
def mouseMoveEvent(self, e):
if self.old_pos:
delta = e.globalPosition().toPoint() - self.old_pos
self.move(self.x() + delta.x(), self.y() + delta.y())
self.old_pos = e.globalPosition().toPoint()
def mouseReleaseEvent(self, e):
self.old_pos = None