diff --git a/app/core/alert_manager.py b/app/core/alert_manager.py index 944abe0..c969486 100644 --- a/app/core/alert_manager.py +++ b/app/core/alert_manager.py @@ -7,6 +7,11 @@ class AlertManager: self.language_manager = language_manager self.theme_manager = theme_manager + def show_info(self, info_text: str, parent=None) -> None: + info_title = self.language_manager.get_text("information") + + QMessageBox.information(parent, info_title, info_text) + def show_success(self, success_key: str, parent=None) -> None: success_title = self.language_manager.get_text("success") success_text = self.language_manager.get_text(success_key) @@ -64,7 +69,7 @@ class AlertManager: box.buttonClicked.connect(on_button_clicked) while True: - result = box.exec() + box.exec() clicked_button = box.clickedButton() # Si c'est le bouton détails, on continue la boucle sans fermer diff --git a/app/core/theme_manager.py b/app/core/theme_manager.py index 4b1f79f..5d05d52 100644 --- a/app/core/theme_manager.py +++ b/app/core/theme_manager.py @@ -31,15 +31,19 @@ class ThemeManager: def get_theme(self) -> Theme: return self.current_theme - + def get_themes(self) -> List[Theme]: + return self.themes def get_sheet(self) -> str: return f""" QWidget {{ - background-color: {self.current_theme.get_color("background")}; + background-color: {self.current_theme.get_color("background2")}; color: {self.current_theme.get_color("font_color")}; }} + #tab_bar {{ + background-color: {self.current_theme.get_color("background")}; + }} QPushButton {{ - background-color: #0A84FF; + background-color: {self.current_theme.get_color("interactive")}; color: {self.current_theme.get_color("font_color")}; border-radius: 8px; font-size: 16px; @@ -47,43 +51,36 @@ class ThemeManager: border: none; }} QPushButton:hover {{ - background-color: #007AFF; + background-color: {self.current_theme.get_color("interactive_hover")}; }} QLabel {{ color: {self.current_theme.get_color("font_color")}; font-size: 20px; }} QProgressBar {{ - border: 1px solid #3C3C3E; + border: 1px solid {self.current_theme.get_color("border")}; border-radius: 5px; background-color: {self.current_theme.get_color("background2")}; text-align: center; color: {self.current_theme.get_color("font_color")}; }} QProgressBar::chunk {{ - background-color: #0A84FF; + background-color: {self.current_theme.get_color("interactive")}; border-radius: 3px; }} - QFrame {{ - background-color: {self.current_theme.get_color("background2")}; - border: none; - }} - QFrame#indicator_bar {{ - background-color: #0A84FF; - }} QScrollBar:vertical {{ border: none; - background: #E0E0E0; + background: {self.current_theme.get_color("background3")}; width: 8px; margin: 0px; }} QScrollBar::handle:vertical {{ - background: #0A84FF; + background: {self.current_theme.get_color("interactive")}; border-radius: 4px; min-height: 20px; }} QScrollBar::handle:vertical:hover {{ - background: #3B9CFF; + background: {self.current_theme.get_color("interactive_hover")}; }} QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {{ border: none; @@ -93,17 +90,14 @@ class ThemeManager: QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {{ background: none; }} - #drag_area {{ - border: 2px dashed #3498db; border-radius: 10px; - }} QSlider::groove:horizontal {{ - border: 1px solid #3a9bdc; + border: 1px solid {self.current_theme.get_color("interactive")}; height: 10px; background: transparent; border-radius: 5px; }} QSlider::sub-page:horizontal {{ - background: #3a9bdc; + background: {self.current_theme.get_color("interactive")}; border-radius: 5px; }} QSlider::add-page:horizontal {{ @@ -112,7 +106,7 @@ class ThemeManager: }} QSlider::handle:horizontal {{ background: white; - border: 2px solid #3a9bdc; + border: 2px solid {self.current_theme.get_color("interactive")}; width: 14px; margin: -4px 0; border-radius: 7px; @@ -171,6 +165,6 @@ class ThemeManager: /* Optionnel: indicateur visuel au hover */ QComboBox:hover {{ - border-color: #0078d4; + border-color: {self.current_theme.get_color("interactive_hover")}; }} """ \ No newline at end of file diff --git a/app/core/update_manager.py b/app/core/update_manager.py index 7a3164b..9f863ce 100644 --- a/app/core/update_manager.py +++ b/app/core/update_manager.py @@ -71,8 +71,7 @@ class UpdateManager: if choice: folder = QFileDialog.getExistingDirectory(parent, self.language_manager.get_text("choose_update_folder")) if folder: - self.download(release["download_url"], release["tag_name"], folder, parent) - return True + return self.download(release["download_url"], release["tag_name"], folder, parent) return False def download(self, download_url, version, folder, parent=None): @@ -89,18 +88,48 @@ class UpdateManager: loading_bar = LoadingBar(self.language_manager.get_text("downloading_update"), dialog) layout.addWidget(loading_bar) dialog.setModal(True) + + # Variable pour tracker si le téléchargement a été annulé + download_cancelled = False + + def on_dialog_rejected(): + nonlocal download_cancelled + download_cancelled = True + + dialog.rejected.connect(on_dialog_rejected) dialog.show() downloaded = 0 with open(local_path, "wb") as f: for chunk in resp.iter_content(chunk_size=8192): + QApplication.processEvents() + if download_cancelled: + break + if chunk: f.write(chunk) downloaded += len(chunk) percent = int(downloaded * 100 / total) if total else 0 loading_bar.set_progress(percent) - QApplication.processEvents() + dialog.close() + + # Gérer l'annulation après la fermeture du fichier + if download_cancelled: + # Attendre un peu pour s'assurer que le fichier n'est plus utilisé + QApplication.processEvents() + import time + time.sleep(0.1) # Attendre 100ms pour libérer le handle + try: + if os.path.exists(local_path): + os.remove(local_path) + except (OSError, PermissionError): + # Si on ne peut pas supprimer le fichier, on continue sans erreur + pass + self.alert_manager.show_info(self.language_manager.get_text("update_aborted"), parent=parent) + return False + + # Téléchargement réussi msg = self.language_manager.get_text("update_downloaded").replace("{local_path}", local_path) self.alert_manager.show_success(msg, parent=parent) # Ouvre le fichier téléchargé @@ -109,8 +138,11 @@ class UpdateManager: else: subprocess.Popen(["chmod", "+x", local_path]) subprocess.Popen([local_path]) - except Exception: + return True + except Exception as e: + print(e) self.alert_manager.show_error("update_download_error", parent=parent) + return False def show_update_dialog(self, releases: List[Dict], current_version: str, parent=None) -> bool: """ @@ -125,7 +157,7 @@ class UpdateManager: parent=parent, details_callback=lambda: self.show_details_dialog(releases, current_version, parent) ) - print(choice) + return choice def show_details_dialog(self, releases: List[Dict], current_version: str, parent=None) -> None: diff --git a/app/ui/widgets/tabs_widget.py b/app/ui/widgets/tabs_widget.py index 901a610..606def5 100644 --- a/app/ui/widgets/tabs_widget.py +++ b/app/ui/widgets/tabs_widget.py @@ -99,6 +99,7 @@ class TabsWidget(QWidget): self.stacked_widget = QStackedWidget() # Create button container widget self.button_container = QWidget() + self.button_container.setObjectName("tab_bar") self.button_container.setLayout(self.button_layout) # Remove all margins from button container diff --git a/app/ui/windows/settings_window.py b/app/ui/windows/settings_window.py index 6057509..50b8d13 100644 --- a/app/ui/windows/settings_window.py +++ b/app/ui/windows/settings_window.py @@ -9,7 +9,8 @@ class SettingsWindow(QWidget): self.main_manager: MainManager = MainManager.get_instance() self.language_manager = self.main_manager.get_language_manager() self.settings_manager = self.main_manager.get_settings_manager() - + self.theme_manager = self.main_manager.get_theme_manager() + self.observer_manager = self.main_manager.get_observer_manager() self.observer_manager.subscribe(NotificationType.LANGUAGE, self.update_language) @@ -57,6 +58,7 @@ class SettingsWindow(QWidget): layout.addLayout(self.theme_layout) layout.addStretch() + def createLanguageSelector(self) -> QComboBox: combo: QComboBox = QComboBox() # Ajouter toutes les langues disponibles @@ -72,11 +74,10 @@ class SettingsWindow(QWidget): def createThemeSelector(self) -> QComboBox: combo: QComboBox = QComboBox() - - # Ajouter les options de thème - combo.addItem(self.language_manager.get_text("light_theme"), "light") - combo.addItem(self.language_manager.get_text("dark_theme"), "dark") - + # Ajouter toutes les options de thème disponibles + for theme in self.theme_manager.get_themes(): + combo.addItem(self.language_manager.get_text(theme.name+"_theme"), theme.name) + # Sélectionner le thème actuel currentIndex = combo.findData(self.settings_manager.get_theme()) combo.setCurrentIndex(currentIndex) diff --git a/config.json b/config.json index c51be8f..ca6a66c 100644 --- a/config.json +++ b/config.json @@ -1,9 +1,9 @@ { - "app_name": "Application", + "app_name": "HoDA", "app_os": "Windows", "app_version": "1.0.0", "architecture": "x64", "icon_path": "data/assets/icon.ico", "main_script": "main.py", - "git_repo": "https://gitea.louismazin.ovh/LouisMazin/PythonApplicationTemplate" + "git_repo": "https://gitea.louismazin.ovh/LouisMazin/HoDA" } \ No newline at end of file diff --git a/data/lang/en.json b/data/lang/en.json index 547050b..76aad1e 100644 --- a/data/lang/en.json +++ b/data/lang/en.json @@ -28,5 +28,7 @@ "details": "Details", "version": "Version", "update_details": "Update Details", - "close": "Close" + "close": "Close", + "update_aborted": "Update aborted by user", + "information": "Information" } \ No newline at end of file diff --git a/data/lang/fr.json b/data/lang/fr.json index c6f2e02..72132eb 100644 --- a/data/lang/fr.json +++ b/data/lang/fr.json @@ -28,5 +28,7 @@ "details": "Détails", "version": "Version", "update_details": "Détails de la mise à jour", - "close": "Fermer" + "close": "Fermer", + "update_aborted": "Mise à jour annulée par l'utilisateur", + "information": "Information" } \ No newline at end of file diff --git a/data/themes/dark.json b/data/themes/dark.json index b90e08b..93a6fd7 100644 --- a/data/themes/dark.json +++ b/data/themes/dark.json @@ -1,6 +1,8 @@ { "theme_name": "dark", "colors": { + "interactive": "#0A84FF", + "interactive_hover": "#007AFF", "border": "#3C3C3E", "background": "#212121", "background2": "#2C2C2E", diff --git a/data/themes/light.json b/data/themes/light.json index 9b6aa63..1c7fc33 100644 --- a/data/themes/light.json +++ b/data/themes/light.json @@ -1,6 +1,8 @@ { "theme_name": "light", "colors": { + "interactive": "#0A84FF", + "interactive_hover": "#007AFF", "border": "#1f1f20", "background": "#FFFFFF", "background2": "#F5F5F5",