Custome message box, secure code, discord, config

This commit is contained in:
2026-03-17 11:06:09 +01:00
parent de8486662e
commit 484809356f
6 changed files with 233 additions and 18 deletions

View File

@@ -16,5 +16,8 @@
"python.useEnvironmentsExtension": true,
"terminal.integrated.persistentSessionReviveProcess": "never",
"terminal.integrated.enablePersistentSessions": false,
"terminal.integrated.hideOnStartup": "always"
"terminal.integrated.hideOnStartup": "always",
"[jsonc]": {
"editor.defaultFormatter": "vscode.json-language-features"
}
}

View File

@@ -15,7 +15,7 @@ a = Analysis(
},
runtime_hooks=[],
excludes=[
# PySide6 - modules non utilisés
# PySide6 - modules non utilisés
'PySide6.Qt3DAnimation',
'PySide6.Qt3DCore',
'PySide6.Qt3DExtras',
@@ -30,7 +30,7 @@ a = Analysis(
'PySide6.QtDesigner',
'PySide6.QtHelp',
'PySide6.QtLocation',
# 'PySide6.QtMultimedia',
# 'PySide6.QtMultimedia', # Nécessaire pour l'audio
'PySide6.QtMultimediaWidgets',
# 'PySide6.QtNetwork', # Dépendance à QtMultimedia
'PySide6.QtNetworkAuth',
@@ -113,7 +113,7 @@ a = Analysis(
# REPL / terminal
"readline",
"code",
# "codeop",
# "codeop", # Nécessaire
"cmd",
# mail / network protocols non utilisés
@@ -145,7 +145,7 @@ a = Analysis(
"bz2",
"lzma",
"gzip",
#"zipfile",
#"zipfile", # Nécessaire à cause de pyinstaller
"tarfile",
"zipapp",

View File

@@ -5,8 +5,15 @@ from PySide6.QtCore import QResource
from PySide6.QtGui import QFontDatabase, QFont
from PySide6.QtWidgets import QApplication
# Imports pour la gestion de la configuration
from config.config_manager import ConfigManager
# Imports pour la vérification Discord
from tools.discord_tools import CheckDiscord
from tools.custom_message_box import CustomMessageBox
# Ne pas supprimer ! Enregistre les ressources Qt
import resources # noqa: F401 - required to register Qt resources
import resources # noqa: F401 - required to register Qt resources
from ui.main_window import MainWindow
from tools.constants import Resources
@@ -15,9 +22,9 @@ from tools.constants import Resources
# Bundle path resolution
# ---------------------------------------------------------------------------
bundle_dir = get_internal_dir()
QResource.registerResource(f"{bundle_dir}/resources.py")
# ---------------------------------------------------------------------------
# Font helper
# ---------------------------------------------------------------------------
@@ -37,12 +44,49 @@ def load_custom_font() -> str:
if __name__ == "__main__":
app = QApplication(sys.argv)
# Chargement des styles de l'application
with open(f"{bundle_dir}/styles/styles.qss", 'r') as f:
app.setStyleSheet(f.read())
# 1. Initialisation UNIQUE du gestionnaire de config
config = ConfigManager()
# Application de la font custom sur toute l'application'
app.setFont(QFont(load_custom_font(), 16))
# 2. Setup environnemental (Styles & Fonts)
try:
with open(f"{bundle_dir}/styles/styles.qss", 'r') as f:
app.setStyleSheet(f.read())
app.setFont(QFont(load_custom_font(), 16))
except Exception as e:
print(f"Erreur lors du chargement des styles : {e}")
# 3. Garde-fou Discord
if not CheckDiscord.isdiscordrunning():
msg = CustomMessageBox(
title="La Tanière: Discord non détecté",
message="Discord ne semble pas lancé.\n\n"
"Tu dois avoir démarré Discord et y être connecté pour utiliser l'application.\n\n"
"Lorsque cela sera fait, relance le launcher.",
icon_type=CustomMessageBox.WARNING,
buttons=CustomMessageBox.OK
)
msg.exec()
sys.exit(0) # On quitte proprement sans lancer MainWindow
# On récupère l'ID stocké (sera "" si absent grâce au schéma)
stored_user_id = config.get_discord_user()
if not CheckDiscord.isuserconnected():
msg = CustomMessageBox(
title="La Tanière: connexion Discord",
message="Tu n'est pas connecté à Discord\n\n"
"Assure-toi que tu es connecté à Discord.\n\n"
"Lorsque cela sera fait, relance le launcher.",
icon_type=CustomMessageBox.WARNING,
buttons=CustomMessageBox.OK
)
msg.exec()
sys.exit(0) # On quitte proprement sans lancer MainWindow
# 4. Lancement de l'application si tout est OK
window = MainWindow(bundle_dir, config)
# Note: Assure-toi que self.show() est bien dans le __init__ de MainWindow
# ou ajoute window.show() ici si tu l'en lèves du constructeur.
window = MainWindow(bundle_dir)
sys.exit(app.exec())

View File

@@ -0,0 +1,168 @@
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

View File

@@ -1,8 +1,8 @@
import psutil
from pypresence import Presence
from get_server_token import GetServerTokenForDiscord
from constants import Urls
from tools.get_server_token import GetServerTokenForDiscord
from tools.constants import Urls
class DiscordToken:
@staticmethod

View File

@@ -8,10 +8,10 @@ from PySide6.QtUiTools import QUiLoader
from PySide6.QtWidgets import QMainWindow, QSizePolicy
from config.config_manager import ConfigManager
from tools.constants import NO_DISCORD, NO_STAFF, Urls
from controllers.audio_controller import AudioController
from controllers.glow_animator import GlowAnimator
from controllers.window_dragger import WindowDragger
from tools.constants import NO_DISCORD, NO_STAFF, Urls
from fake_patch_notes import patch_note
# For Linux Wayland to authorize moving window
@@ -19,10 +19,10 @@ if platform.startswith('linux'):
environ["QT_QPA_PLATFORM"] = "xcb"
class MainWindow(QMainWindow):
def __init__(self, bundle_dir):
def __init__(self, bundle_dir: str, config_manager: ConfigManager):
super().__init__()
self.config = ConfigManager()
self.config = config_manager
# UI
self.ui = QUiLoader().load(f"{bundle_dir}/ui/mainwindow_vertical_pager.ui", self)