Custome message box, secure code, discord, config
This commit is contained in:
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@@ -16,5 +16,8 @@
|
|||||||
"python.useEnvironmentsExtension": true,
|
"python.useEnvironmentsExtension": true,
|
||||||
"terminal.integrated.persistentSessionReviveProcess": "never",
|
"terminal.integrated.persistentSessionReviveProcess": "never",
|
||||||
"terminal.integrated.enablePersistentSessions": false,
|
"terminal.integrated.enablePersistentSessions": false,
|
||||||
"terminal.integrated.hideOnStartup": "always"
|
"terminal.integrated.hideOnStartup": "always",
|
||||||
|
"[jsonc]": {
|
||||||
|
"editor.defaultFormatter": "vscode.json-language-features"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ a = Analysis(
|
|||||||
},
|
},
|
||||||
runtime_hooks=[],
|
runtime_hooks=[],
|
||||||
excludes=[
|
excludes=[
|
||||||
# PySide6 - modules non utilisés
|
# PySide6 - modules non utilisés
|
||||||
'PySide6.Qt3DAnimation',
|
'PySide6.Qt3DAnimation',
|
||||||
'PySide6.Qt3DCore',
|
'PySide6.Qt3DCore',
|
||||||
'PySide6.Qt3DExtras',
|
'PySide6.Qt3DExtras',
|
||||||
@@ -30,7 +30,7 @@ a = Analysis(
|
|||||||
'PySide6.QtDesigner',
|
'PySide6.QtDesigner',
|
||||||
'PySide6.QtHelp',
|
'PySide6.QtHelp',
|
||||||
'PySide6.QtLocation',
|
'PySide6.QtLocation',
|
||||||
# 'PySide6.QtMultimedia',
|
# 'PySide6.QtMultimedia', # Nécessaire pour l'audio
|
||||||
'PySide6.QtMultimediaWidgets',
|
'PySide6.QtMultimediaWidgets',
|
||||||
# 'PySide6.QtNetwork', # Dépendance à QtMultimedia
|
# 'PySide6.QtNetwork', # Dépendance à QtMultimedia
|
||||||
'PySide6.QtNetworkAuth',
|
'PySide6.QtNetworkAuth',
|
||||||
@@ -113,7 +113,7 @@ a = Analysis(
|
|||||||
# REPL / terminal
|
# REPL / terminal
|
||||||
"readline",
|
"readline",
|
||||||
"code",
|
"code",
|
||||||
# "codeop",
|
# "codeop", # Nécessaire
|
||||||
"cmd",
|
"cmd",
|
||||||
|
|
||||||
# mail / network protocols non utilisés
|
# mail / network protocols non utilisés
|
||||||
@@ -145,7 +145,7 @@ a = Analysis(
|
|||||||
"bz2",
|
"bz2",
|
||||||
"lzma",
|
"lzma",
|
||||||
"gzip",
|
"gzip",
|
||||||
#"zipfile",
|
#"zipfile", # Nécessaire à cause de pyinstaller
|
||||||
"tarfile",
|
"tarfile",
|
||||||
"zipapp",
|
"zipapp",
|
||||||
|
|
||||||
|
|||||||
60
src/main.py
60
src/main.py
@@ -5,8 +5,15 @@ from PySide6.QtCore import QResource
|
|||||||
from PySide6.QtGui import QFontDatabase, QFont
|
from PySide6.QtGui import QFontDatabase, QFont
|
||||||
from PySide6.QtWidgets import QApplication
|
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
|
# 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 ui.main_window import MainWindow
|
||||||
from tools.constants import Resources
|
from tools.constants import Resources
|
||||||
@@ -15,9 +22,9 @@ from tools.constants import Resources
|
|||||||
# Bundle path resolution
|
# Bundle path resolution
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
bundle_dir = get_internal_dir()
|
bundle_dir = get_internal_dir()
|
||||||
|
|
||||||
QResource.registerResource(f"{bundle_dir}/resources.py")
|
QResource.registerResource(f"{bundle_dir}/resources.py")
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Font helper
|
# Font helper
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
@@ -37,12 +44,49 @@ def load_custom_font() -> str:
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app = QApplication(sys.argv)
|
app = QApplication(sys.argv)
|
||||||
|
|
||||||
# Chargement des styles de l'application
|
# 1. Initialisation UNIQUE du gestionnaire de config
|
||||||
with open(f"{bundle_dir}/styles/styles.qss", 'r') as f:
|
config = ConfigManager()
|
||||||
app.setStyleSheet(f.read())
|
|
||||||
|
|
||||||
# Application de la font custom sur toute l'application'
|
# 2. Setup environnemental (Styles & Fonts)
|
||||||
app.setFont(QFont(load_custom_font(), 16))
|
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())
|
sys.exit(app.exec())
|
||||||
|
|||||||
168
src/tools/custom_message_box.py
Normal file
168
src/tools/custom_message_box.py
Normal 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
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import psutil
|
import psutil
|
||||||
|
|
||||||
from pypresence import Presence
|
from pypresence import Presence
|
||||||
from get_server_token import GetServerTokenForDiscord
|
from tools.get_server_token import GetServerTokenForDiscord
|
||||||
from constants import Urls
|
from tools.constants import Urls
|
||||||
|
|
||||||
class DiscordToken:
|
class DiscordToken:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ from PySide6.QtUiTools import QUiLoader
|
|||||||
from PySide6.QtWidgets import QMainWindow, QSizePolicy
|
from PySide6.QtWidgets import QMainWindow, QSizePolicy
|
||||||
|
|
||||||
from config.config_manager import ConfigManager
|
from config.config_manager import ConfigManager
|
||||||
from tools.constants import NO_DISCORD, NO_STAFF, Urls
|
|
||||||
from controllers.audio_controller import AudioController
|
from controllers.audio_controller import AudioController
|
||||||
from controllers.glow_animator import GlowAnimator
|
from controllers.glow_animator import GlowAnimator
|
||||||
from controllers.window_dragger import WindowDragger
|
from controllers.window_dragger import WindowDragger
|
||||||
|
from tools.constants import NO_DISCORD, NO_STAFF, Urls
|
||||||
from fake_patch_notes import patch_note
|
from fake_patch_notes import patch_note
|
||||||
|
|
||||||
# For Linux Wayland to authorize moving window
|
# For Linux Wayland to authorize moving window
|
||||||
@@ -19,10 +19,10 @@ if platform.startswith('linux'):
|
|||||||
environ["QT_QPA_PLATFORM"] = "xcb"
|
environ["QT_QPA_PLATFORM"] = "xcb"
|
||||||
|
|
||||||
class MainWindow(QMainWindow):
|
class MainWindow(QMainWindow):
|
||||||
def __init__(self, bundle_dir):
|
def __init__(self, bundle_dir: str, config_manager: ConfigManager):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
self.config = ConfigManager()
|
self.config = config_manager
|
||||||
|
|
||||||
# UI
|
# UI
|
||||||
self.ui = QUiLoader().load(f"{bundle_dir}/ui/mainwindow_vertical_pager.ui", self)
|
self.ui = QUiLoader().load(f"{bundle_dir}/ui/mainwindow_vertical_pager.ui", self)
|
||||||
|
|||||||
Reference in New Issue
Block a user