Initial commit: Add playlist downloader project with UI and core functionality

This commit is contained in:
2026-06-28 10:34:48 +02:00
commit 605dede363
49 changed files with 8300 additions and 0 deletions
+138
View File
@@ -0,0 +1,138 @@
"""
LoadingModal pour PyQt6 - Modal de chargement avec barre de progression.
"""
from PyQt6.QtWidgets import QDialog, QVBoxLayout, QLabel, QProgressBar
from PyQt6.QtCore import Qt, QTimer
from PyQt6.QtGui import QFont
class LoadingModal(QDialog):
"""Modal de chargement avec barre de progression déterminée ou indéterminée."""
def __init__(self, parent, title: str = "Loading", message: str = "Please wait...", determinate: bool = False):
"""
Créer une modal de chargement.
Args:
parent: Widget parent
title: Titre
message: Message de chargement
determinate: Si True, barre de progression déterminée (0→100). Sinon, indéterminée
"""
super().__init__(parent)
self.setWindowTitle(title)
self.setModal(False)
self.setFixedSize(500, 250)
self.setStyleSheet("""
QDialog {
background-color: #212121;
border-radius: 8px;
}
QLabel {
color: #ffffff;
}
""")
# Layout
layout = QVBoxLayout()
layout.setContentsMargins(30, 30, 30, 30)
layout.setSpacing(15)
# Titre
title_label = QLabel(title)
title_font = QFont()
title_font.setPointSize(16)
title_font.setBold(True)
title_label.setFont(title_font)
layout.addWidget(title_label)
# Message
self._msg_label = QLabel(message)
msg_font = QFont()
msg_font.setPointSize(11)
self._msg_label.setFont(msg_font)
layout.addWidget(self._msg_label)
# Progress bar
self._progress = QProgressBar()
self._progress.setStyleSheet("""
QProgressBar {
background-color: #3a3a3a;
border: none;
border-radius: 5px;
height: 8px;
}
QProgressBar::chunk {
background-color: #2196F3;
border-radius: 5px;
}
""")
if determinate:
self._progress.setMinimum(0)
self._progress.setMaximum(100)
self._progress.setValue(0)
self._determinate = True
else:
self._progress.setMinimum(0)
self._progress.setMaximum(0)
self._determinate = False
self._animation_timer = QTimer()
self._animation_timer.timeout.connect(self._animate_progress)
self._animation_timer.start(50)
layout.addWidget(self._progress)
layout.addStretch()
self.setLayout(layout)
# Centre la modal
self.move(parent.x() + parent.width() // 2 - 250,
parent.y() + parent.height() // 2 - 125)
def update_message(self, message: str):
"""Mettre à jour le message."""
try:
self._msg_label.setText(message)
self.repaint()
except Exception:
pass
def set_progress(self, value: float):
"""Définir la progression (0.0 à 1.0) si en mode déterminé."""
try:
if self._determinate:
percent = max(0, min(100, int(value * 100)))
self._progress.setValue(percent)
self.repaint()
except Exception:
pass
def _animate_progress(self):
"""Animation pour la barre indéterminée."""
try:
if not self._determinate:
current = self._progress.value()
self._progress.setValue((current + 5) % 100)
except Exception:
pass
def close(self):
"""Fermer la modal."""
try:
if hasattr(self, '_animation_timer'):
self._animation_timer.stop()
self.hide()
self.deleteLater()
except Exception:
pass
def closeEvent(self, event):
"""Gérer la fermeture."""
try:
if hasattr(self, '_animation_timer'):
self._animation_timer.stop()
except Exception:
pass
event.accept()