Refacto en sous fichiers pour la maintenabilité
This commit is contained in:
18
src/constants.py
Normal file
18
src/constants.py
Normal file
@@ -0,0 +1,18 @@
|
||||
from PySide6.QtGui import QColor
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Constants
|
||||
# ---------------------------------------------------------------------------
|
||||
URLS = {
|
||||
"discord": "https://discord.gg/A7eanmSkp2",
|
||||
"intranet": "https://la-taniere.fun/connexion/",
|
||||
}
|
||||
|
||||
GLOW_COLOR = QColor(255, 140, 0, 255)
|
||||
GLOW_BLUR_BASE = 15
|
||||
GLOW_BLUR_PEAK = 70
|
||||
GLOW_ANIM_DURATION = 1200
|
||||
|
||||
MP3_PATH = ":/assets/the-beat-of-nature.mp3"
|
||||
|
||||
NO_STAFF = True
|
||||
85
src/controllers/audio_controller.py
Normal file
85
src/controllers/audio_controller.py
Normal file
@@ -0,0 +1,85 @@
|
||||
from PySide6.QtCore import QFile, QBuffer, QByteArray, QIODevice
|
||||
from PySide6.QtMultimedia import QMediaPlayer, QAudioOutput
|
||||
|
||||
from config.config_manager import ConfigManager, VOLUME_KEY
|
||||
|
||||
from src.constants import MP3_PATH
|
||||
|
||||
class AudioController:
|
||||
# Encapsule toute la logique audio : lecture, volume, mute.
|
||||
|
||||
def __init__(self, config: ConfigManager, slider, mute_btn):
|
||||
self._config = config
|
||||
self._slider = slider
|
||||
self._mute_btn = mute_btn
|
||||
|
||||
# Lecteur
|
||||
self._player = QMediaPlayer()
|
||||
self._output = QAudioOutput()
|
||||
self._player.setAudioOutput(self._output)
|
||||
self._player.setLoops(-1)
|
||||
|
||||
# Chargement du MP3 depuis les ressources Qt
|
||||
mp3file = QFile(MP3_PATH)
|
||||
mp3file.open(QFile.ReadOnly)
|
||||
mp3data = mp3file.readAll()
|
||||
mp3file.close()
|
||||
|
||||
self._buffer = QBuffer()
|
||||
self._buffer.setData(QByteArray(mp3data))
|
||||
self._buffer.open(QIODevice.ReadOnly)
|
||||
self._player.setSourceDevice(self._buffer)
|
||||
|
||||
# État initial
|
||||
volume = config.get_volume()
|
||||
self._is_muted = volume == 0
|
||||
self._previous_volume = volume if volume != 0 else config.get_default(VOLUME_KEY)
|
||||
|
||||
self._apply_volume(volume, save=False)
|
||||
self._refresh_mute_btn()
|
||||
self._player.play()
|
||||
|
||||
# Connexions
|
||||
self._slider.valueChanged.connect(self._on_slider_changed)
|
||||
self._mute_btn.clicked.connect(self.toggle_mute)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Public API
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def toggle_mute(self) -> None:
|
||||
if not self._is_muted:
|
||||
self._previous_volume = self._slider.value()
|
||||
self._apply_volume(0)
|
||||
self._is_muted = True
|
||||
else:
|
||||
self._apply_volume(self._previous_volume)
|
||||
self._is_muted = False
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Private helpers
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def _on_slider_changed(self, value: int) -> None:
|
||||
self._is_muted = value == 0
|
||||
self._output.setVolume(value / 100.0)
|
||||
self._config.set_volume(value)
|
||||
self._refresh_mute_btn()
|
||||
|
||||
def _apply_volume(self, value: int, save: bool = True) -> None:
|
||||
self._slider.blockSignals(True)
|
||||
self._slider.setValue(value)
|
||||
self._slider.blockSignals(False)
|
||||
|
||||
self._output.setVolume(value / 100.0)
|
||||
|
||||
if save:
|
||||
self._config.set_volume(value)
|
||||
|
||||
self._refresh_mute_btn()
|
||||
|
||||
def _refresh_mute_btn(self) -> None:
|
||||
muted = self._slider.value() == 0
|
||||
self._mute_btn.setProperty("muted", muted)
|
||||
self._mute_btn.style().unpolish(self._mute_btn)
|
||||
self._mute_btn.style().polish(self._mute_btn)
|
||||
32
src/controllers/glow_animator.py
Normal file
32
src/controllers/glow_animator.py
Normal file
@@ -0,0 +1,32 @@
|
||||
from PySide6.QtCore import QPropertyAnimation, QEasingCurve
|
||||
from PySide6.QtWidgets import QGraphicsDropShadowEffect
|
||||
|
||||
from src.constants import GLOW_COLOR, GLOW_BLUR_BASE, GLOW_BLUR_PEAK, GLOW_ANIM_DURATION
|
||||
|
||||
|
||||
class GlowAnimator:
|
||||
# Gère l'effet de lueur pulsée sur un widget.
|
||||
|
||||
def __init__(self, widget):
|
||||
self._widget = widget
|
||||
|
||||
self._effect = QGraphicsDropShadowEffect(widget)
|
||||
self._effect.setBlurRadius(GLOW_BLUR_BASE)
|
||||
self._effect.setOffset(0, 0)
|
||||
self._effect.setColor(GLOW_COLOR)
|
||||
|
||||
self._anim = QPropertyAnimation(self._effect, b"blurRadius")
|
||||
self._anim.setDuration(GLOW_ANIM_DURATION)
|
||||
self._anim.setStartValue(GLOW_BLUR_BASE)
|
||||
self._anim.setKeyValueAt(0.5, GLOW_BLUR_PEAK)
|
||||
self._anim.setEndValue(GLOW_BLUR_BASE)
|
||||
self._anim.setEasingCurve(QEasingCurve.InOutQuad)
|
||||
self._anim.setLoopCount(-1)
|
||||
|
||||
def start(self) -> None:
|
||||
self._widget.setGraphicsEffect(self._effect)
|
||||
self._anim.start()
|
||||
|
||||
def stop(self) -> None:
|
||||
self._anim.stop()
|
||||
self._widget.setGraphicsEffect(None)
|
||||
25
src/controllers/window_dragger.py
Normal file
25
src/controllers/window_dragger.py
Normal file
@@ -0,0 +1,25 @@
|
||||
from PySide6 import QtGui
|
||||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtWidgets import QMainWindow
|
||||
|
||||
|
||||
class WindowDragger:
|
||||
# Permet de déplacer une fenêtre sans barre de titre.
|
||||
|
||||
def __init__(self, window: QMainWindow):
|
||||
self._window = window
|
||||
self._drag_pos = None
|
||||
|
||||
def mouse_press(self, event: QtGui.QMouseEvent) -> None:
|
||||
if event.button() == Qt.MouseButton.LeftButton:
|
||||
self._drag_pos = (
|
||||
event.globalPosition().toPoint()
|
||||
- self._window.frameGeometry().topLeft()
|
||||
)
|
||||
|
||||
def mouse_move(self, event: QtGui.QMouseEvent) -> None:
|
||||
if event.buttons() & Qt.MouseButton.LeftButton and self._drag_pos is not None:
|
||||
self._window.move(event.globalPosition().toPoint() - self._drag_pos)
|
||||
|
||||
def mouse_release(self, _event) -> None:
|
||||
self._drag_pos = None
|
||||
52
src/main.py
Normal file
52
src/main.py
Normal file
@@ -0,0 +1,52 @@
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from PySide6.QtCore import QResource
|
||||
from PySide6.QtGui import QFontDatabase, QFont
|
||||
from PySide6.QtWidgets import QApplication
|
||||
|
||||
import resources as resources # noqa: F401
|
||||
|
||||
from ui.main_window import MainWindow
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Bundle path resolution
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
|
||||
bundle_dir = Path(sys._MEIPASS)
|
||||
else:
|
||||
bundle_dir = Path(__file__).resolve().parent.parent
|
||||
|
||||
QResource.registerResource(f"{bundle_dir}/resources.py")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Font helper
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def load_custom_font() -> str:
|
||||
font_id = QFontDatabase.addApplicationFont(":/assets/Avocado-Cake-Demo.otf")
|
||||
if font_id == -1:
|
||||
raise RuntimeError("Failed to load font from resources.")
|
||||
font_families = QFontDatabase.applicationFontFamilies(font_id)
|
||||
if not font_families:
|
||||
raise RuntimeError("No font families found in the loaded font.")
|
||||
return font_families[0]
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Entry point
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = QApplication(sys.argv)
|
||||
|
||||
with open(f"{bundle_dir}/styles/styles.qss", 'r') as f:
|
||||
app.setStyleSheet(f.read())
|
||||
|
||||
app.setFont(QFont(load_custom_font(), 16))
|
||||
|
||||
window = MainWindow(bundle_dir)
|
||||
sys.exit(app.exec())
|
||||
@@ -1,321 +0,0 @@
|
||||
import sys
|
||||
import webbrowser
|
||||
from pathlib import Path
|
||||
from PySide6 import QtGui
|
||||
from PySide6.QtCore import Qt, QPropertyAnimation, QEasingCurve, QResource, QFile, QBuffer, QByteArray, QIODevice
|
||||
from PySide6.QtGui import QFontDatabase, QFont, QColor
|
||||
from PySide6.QtUiTools import QUiLoader
|
||||
from PySide6.QtWidgets import QMainWindow, QApplication, QGraphicsDropShadowEffect
|
||||
from PySide6.QtMultimedia import QMediaPlayer, QAudioOutput
|
||||
|
||||
from config.config_manager import ConfigManager, VOLUME_KEY
|
||||
|
||||
# Compile resources.qrc into resources_rc.py
|
||||
# rcc -g python .\resources.qrc -o .\src\resources_rc.py
|
||||
|
||||
# import utilisé pour la font custom
|
||||
import resources as resources # This is generated from the .qrc file # noqa: F401
|
||||
|
||||
# Remove this into final release
|
||||
from fake_patch_notes import patch_note
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Constants
|
||||
# ---------------------------------------------------------------------------
|
||||
URLS = {
|
||||
"discord": "https://discord.gg/A7eanmSkp2",
|
||||
"intranet": "https://la-taniere.fun/connexion/",
|
||||
}
|
||||
|
||||
GLOW_COLOR = QColor(255, 140, 0, 255)
|
||||
GLOW_BLUR_BASE = 15
|
||||
GLOW_BLUR_PEAK = 70
|
||||
GLOW_ANIM_DURATION = 1200
|
||||
|
||||
NO_STAFF = True
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Bundle path resolution
|
||||
# ---------------------------------------------------------------------------
|
||||
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
|
||||
bundle_dir = Path(sys._MEIPASS)
|
||||
else:
|
||||
bundle_dir = Path(__file__).resolve().parent.parent
|
||||
|
||||
# charger le fichier rcc compilé
|
||||
QResource.registerResource(f"{bundle_dir}/resources.py")
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Font helper
|
||||
# ---------------------------------------------------------------------------
|
||||
def load_custom_font() -> str:
|
||||
# Load font from Qt resource
|
||||
font_id = QFontDatabase.addApplicationFont(":/assets/Avocado-Cake-Demo.otf")
|
||||
if font_id == -1:
|
||||
raise RuntimeError("Failed to load font from resources.")
|
||||
|
||||
# Get the family name of the loaded font
|
||||
font_families = QFontDatabase.applicationFontFamilies(font_id)
|
||||
if not font_families:
|
||||
raise RuntimeError("No font families found in the loaded font.")
|
||||
return font_families[0]
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# AudioController
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class AudioController:
|
||||
# Encapsule toute la logique audio : lecture, volume, mute.
|
||||
|
||||
def __init__(self, config: ConfigManager, slider, mute_btn):
|
||||
self._config = config
|
||||
self._slider = slider
|
||||
self._mute_btn = mute_btn
|
||||
|
||||
# Lecteur
|
||||
self._player = QMediaPlayer()
|
||||
self._output = QAudioOutput()
|
||||
self._player.setAudioOutput(self._output)
|
||||
self._player.setLoops(-1)
|
||||
|
||||
# Chargement du MP3 depuis les ressources Qt
|
||||
mp3file = QFile(":/assets/the-beat-of-nature.mp3")
|
||||
mp3file.open(QFile.ReadOnly)
|
||||
mp3data = mp3file.readAll()
|
||||
mp3file.close()
|
||||
|
||||
self._buffer = QBuffer()
|
||||
self._buffer.setData(QByteArray(mp3data))
|
||||
self._buffer.open(QIODevice.ReadOnly)
|
||||
self._player.setSourceDevice(self._buffer)
|
||||
|
||||
# État initial
|
||||
volume = config.get_volume()
|
||||
self._is_muted = volume == 0
|
||||
self._previous_volume = (
|
||||
volume if volume != 0 else config.get_default(VOLUME_KEY)
|
||||
)
|
||||
|
||||
self._apply_volume(volume, save=False)
|
||||
self._refresh_mute_btn()
|
||||
self._player.play()
|
||||
|
||||
# Connexions
|
||||
self._slider.valueChanged.connect(self._on_slider_changed)
|
||||
self._mute_btn.clicked.connect(self.toggle_mute)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Public API
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def toggle_mute(self) -> None:
|
||||
if not self._is_muted:
|
||||
self._previous_volume = self._slider.value()
|
||||
self._apply_volume(0)
|
||||
self._is_muted = True
|
||||
else:
|
||||
self._apply_volume(self._previous_volume)
|
||||
self._is_muted = False
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Private helpers
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def _on_slider_changed(self, value: int) -> None:
|
||||
# Appelé quand l'utilisateur bouge le slider directement.
|
||||
self._is_muted = (value == 0)
|
||||
self._output.setVolume(value / 100.0)
|
||||
self._config.set_volume(value)
|
||||
self._refresh_mute_btn()
|
||||
|
||||
def _apply_volume(self, value: int, save: bool = True) -> None:
|
||||
# Applique le volume sur le slider, l'output et la config.
|
||||
# Bloquer le signal pour éviter une double mise à jour
|
||||
self._slider.blockSignals(True)
|
||||
self._slider.setValue(value)
|
||||
self._slider.blockSignals(False)
|
||||
|
||||
self._output.setVolume(value / 100.0)
|
||||
|
||||
if save:
|
||||
self._config.set_volume(value)
|
||||
|
||||
self._refresh_mute_btn()
|
||||
|
||||
def _refresh_mute_btn(self) -> None:
|
||||
muted = self._slider.value() == 0
|
||||
self._mute_btn.setProperty("muted", muted)
|
||||
self._mute_btn.style().unpolish(self._mute_btn)
|
||||
self._mute_btn.style().polish(self._mute_btn)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# GlowAnimator
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class GlowAnimator:
|
||||
# Gère l'effet de lueur pulsée sur un widget.
|
||||
|
||||
def __init__(self, widget):
|
||||
self._widget = widget
|
||||
|
||||
self._effect = QGraphicsDropShadowEffect(widget)
|
||||
self._effect.setBlurRadius(GLOW_BLUR_BASE)
|
||||
self._effect.setOffset(0, 0)
|
||||
self._effect.setColor(GLOW_COLOR)
|
||||
|
||||
self._anim = QPropertyAnimation(self._effect, b"blurRadius")
|
||||
self._anim.setDuration(GLOW_ANIM_DURATION)
|
||||
self._anim.setStartValue(GLOW_BLUR_BASE)
|
||||
self._anim.setKeyValueAt(0.5, GLOW_BLUR_PEAK)
|
||||
self._anim.setEndValue(GLOW_BLUR_BASE)
|
||||
self._anim.setEasingCurve(QEasingCurve.InOutQuad)
|
||||
self._anim.setLoopCount(-1)
|
||||
|
||||
def start(self) -> None:
|
||||
self._widget.setGraphicsEffect(self._effect)
|
||||
self._anim.start()
|
||||
|
||||
def stop(self) -> None:
|
||||
self._anim.stop()
|
||||
self._widget.setGraphicsEffect(None)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# WindowDragger
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
class WindowDragger:
|
||||
# Permet de déplacer une fenêtre sans barre de titre.
|
||||
|
||||
def __init__(self, window: QMainWindow):
|
||||
self._window = window
|
||||
self._drag_pos = None
|
||||
|
||||
def mouse_press(self, event: QtGui.QMouseEvent) -> None:
|
||||
if event.button() == Qt.MouseButton.LeftButton:
|
||||
self._drag_pos = (
|
||||
event.globalPosition().toPoint()
|
||||
- self._window.frameGeometry().topLeft()
|
||||
)
|
||||
|
||||
def mouse_move(self, event: QtGui.QMouseEvent) -> None:
|
||||
if event.buttons() & Qt.MouseButton.LeftButton and self._drag_pos is not None:
|
||||
self._window.move(event.globalPosition().toPoint() - self._drag_pos)
|
||||
|
||||
def mouse_release(self, _event) -> None:
|
||||
self._drag_pos = None
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# MainWindow
|
||||
# ---------------------------------------------------------------------------
|
||||
class MainWindow(QMainWindow):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
# Initialisation de la configuration
|
||||
self.config = ConfigManager()
|
||||
|
||||
# UI
|
||||
self.ui = QUiLoader().load(f"{bundle_dir}/ui/mainwindow.ui", self)
|
||||
self.setCentralWidget(self.ui.centralWidget())
|
||||
self.setWindowFlags(Qt.WindowType.FramelessWindowHint | Qt.WindowType.Window)
|
||||
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
|
||||
|
||||
if NO_STAFF:
|
||||
self.ui.staff_btn.hide()
|
||||
self.ui.spacer_substitution.hide()
|
||||
|
||||
self.ui.info_text.setMarkdown(patch_note)
|
||||
|
||||
# Sous-systèmes
|
||||
self._audio = AudioController(self.config, self.ui.audio_volume_adjust, self.ui.mute_btn)
|
||||
self._glow = GlowAnimator(self.ui.connexion_btn)
|
||||
self._dragger = WindowDragger(self)
|
||||
|
||||
self._connect_signals()
|
||||
self._center_window()
|
||||
self.show()
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Setup
|
||||
# ------------------------------------------------------------------
|
||||
def _connect_signals(self) -> None:
|
||||
|
||||
self.ui.close_btn.clicked.connect(self.close)
|
||||
self.ui.minimize_btn.clicked.connect(self.showMinimized)
|
||||
|
||||
self.ui.connexion_btn.clicked.connect(self._on_connexion)
|
||||
self.ui.discord_btn.clicked.connect(self._on_discord)
|
||||
self.ui.intranet_btn.clicked.connect(self._on_intranet)
|
||||
# Le bouton mute est connecté dans la classe AudioController
|
||||
#self.ui.mute_btn.clicked.connect(self.mute_btn_link)
|
||||
|
||||
def _center_window(self) -> None:
|
||||
# On s'assure que la fenêtre a calculé sa taille
|
||||
self.adjustSize()
|
||||
screen = QtGui.QGuiApplication.screenAt(QtGui.QCursor.pos()) \
|
||||
or QtGui.QGuiApplication.primaryScreen()
|
||||
rect = self.frameGeometry()
|
||||
rect.moveCenter(screen.availableGeometry().center())
|
||||
self.move(rect.topLeft())
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Button handlers
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
@staticmethod
|
||||
def _on_connexion():
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def _on_discord():
|
||||
webbrowser.open(URLS["discord"])
|
||||
|
||||
def _on_intranet(self):
|
||||
webbrowser.open(URLS["intranet"])
|
||||
self._glow.start()
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Mouse events → délégués au WindowDragger
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
# Mouse press event to start dragging
|
||||
def mousePressEvent(self, event: QtGui.QMouseEvent) -> None:
|
||||
if event.button() == Qt.MouseButton.LeftButton:
|
||||
self._drag_pos = event.globalPosition().toPoint() - self.frameGeometry().topLeft()
|
||||
super().mousePressEvent(event)
|
||||
|
||||
# Mouse move event to drag window
|
||||
def mouseMoveEvent(self, event: QtGui.QMouseEvent) -> None:
|
||||
if event.buttons() & Qt.MouseButton.LeftButton and self._drag_pos is not None:
|
||||
self.move(event.globalPosition().toPoint() - self._drag_pos)
|
||||
super().mouseMoveEvent(event)
|
||||
|
||||
# Mouse release event to stop dragging
|
||||
def mouseReleaseEvent(self, event):
|
||||
self._drag_pos = None
|
||||
super().mouseReleaseEvent(event)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Close
|
||||
# ------------------------------------------------------------------
|
||||
def closeEvent(self, event):
|
||||
self.config.save()
|
||||
super().closeEvent(event)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Entry point
|
||||
# ---------------------------------------------------------------------------
|
||||
if __name__ == "__main__":
|
||||
app = QApplication(sys.argv)
|
||||
|
||||
# Set the stylesheet of the application
|
||||
with open(f"{bundle_dir}/styles/styles.qss", 'r') as f:
|
||||
app.setStyleSheet(f.read())
|
||||
|
||||
# Load and set the global font
|
||||
app.setFont(QFont(load_custom_font(), 16))
|
||||
|
||||
window = MainWindow()
|
||||
|
||||
sys.exit(app.exec())
|
||||
101
src/ui/main_window.py
Normal file
101
src/ui/main_window.py
Normal file
@@ -0,0 +1,101 @@
|
||||
import webbrowser
|
||||
|
||||
from PySide6 import QtGui
|
||||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtUiTools import QUiLoader
|
||||
from PySide6.QtWidgets import QMainWindow
|
||||
|
||||
from config.config_manager import ConfigManager
|
||||
from src.constants import URLS, NO_STAFF
|
||||
from controllers.audio_controller import AudioController
|
||||
from controllers.glow_animator import GlowAnimator
|
||||
from controllers.window_dragger import WindowDragger
|
||||
from fake_patch_notes import patch_note
|
||||
|
||||
|
||||
class MainWindow(QMainWindow):
|
||||
def __init__(self, bundle_dir):
|
||||
super().__init__()
|
||||
|
||||
self.config = ConfigManager()
|
||||
|
||||
# UI
|
||||
self.ui = QUiLoader().load(f"{bundle_dir}/ui/mainwindow.ui", self)
|
||||
self.setCentralWidget(self.ui.centralWidget())
|
||||
self.setWindowFlags(Qt.WindowType.FramelessWindowHint | Qt.WindowType.Window)
|
||||
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
|
||||
|
||||
if NO_STAFF:
|
||||
self.ui.staff_btn.hide()
|
||||
self.ui.spacer_substitution.hide()
|
||||
|
||||
self.ui.info_text.setMarkdown(patch_note)
|
||||
|
||||
# Sous-systèmes
|
||||
self._audio = AudioController(self.config, self.ui.audio_volume_adjust, self.ui.mute_btn)
|
||||
self._glow = GlowAnimator(self.ui.connexion_btn)
|
||||
self._dragger = WindowDragger(self)
|
||||
|
||||
self._connect_signals()
|
||||
self._center_window()
|
||||
self.show()
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Setup
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def _connect_signals(self) -> None:
|
||||
self.ui.close_btn.clicked.connect(self.close)
|
||||
self.ui.minimize_btn.clicked.connect(self.showMinimized)
|
||||
self.ui.connexion_btn.clicked.connect(self._on_connexion)
|
||||
self.ui.discord_btn.clicked.connect(self._on_discord)
|
||||
self.ui.intranet_btn.clicked.connect(self._on_intranet)
|
||||
|
||||
def _center_window(self) -> None:
|
||||
self.adjustSize()
|
||||
screen = (
|
||||
QtGui.QGuiApplication.screenAt(QtGui.QCursor.pos())
|
||||
or QtGui.QGuiApplication.primaryScreen()
|
||||
)
|
||||
rect = self.frameGeometry()
|
||||
rect.moveCenter(screen.availableGeometry().center())
|
||||
self.move(rect.topLeft())
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Button handlers
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def _on_connexion(self) -> None:
|
||||
pass # à implémenter
|
||||
|
||||
@staticmethod
|
||||
def _on_discord() -> None:
|
||||
webbrowser.open(URLS["discord"])
|
||||
|
||||
def _on_intranet(self) -> None:
|
||||
webbrowser.open(URLS["intranet"])
|
||||
self._glow.start()
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Mouse events → délégués au WindowDragger
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def mousePressEvent(self, event: QtGui.QMouseEvent) -> None:
|
||||
self._dragger.mouse_press(event)
|
||||
super().mousePressEvent(event)
|
||||
|
||||
def mouseMoveEvent(self, event: QtGui.QMouseEvent) -> None:
|
||||
self._dragger.mouse_move(event)
|
||||
super().mouseMoveEvent(event)
|
||||
|
||||
def mouseReleaseEvent(self, event: QtGui.QMouseEvent) -> None:
|
||||
self._dragger.mouse_release(event)
|
||||
super().mouseReleaseEvent(event)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Close
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def closeEvent(self, event) -> None:
|
||||
self.config.save()
|
||||
super().closeEvent(event)
|
||||
Reference in New Issue
Block a user