diff --git a/src/core/ytsage_utils.py b/src/core/ytsage_utils.py index c1e2241..6f273bb 100644 --- a/src/core/ytsage_utils.py +++ b/src/core/ytsage_utils.py @@ -643,21 +643,26 @@ def check_and_update_ytdlp_auto() -> bool: def get_auto_update_settings() -> dict: """Get current auto-update settings from config.""" - config = load_config() + from src.utils.ytsage_config_manager import ConfigManager + + enabled = ConfigManager.get("auto_update_ytdlp") + frequency = ConfigManager.get("auto_update_frequency") + last_check = ConfigManager.get("last_update_check") + return { - "enabled": config.get("auto_update_ytdlp", True), - "frequency": config.get("auto_update_frequency", "daily"), - "last_check": config.get("last_update_check", 0), + "enabled": enabled if enabled is not None else True, + "frequency": frequency if frequency is not None else "daily", + "last_check": last_check if last_check is not None else 0, } def update_auto_update_settings(enabled, frequency) -> bool: """Update auto-update settings in config.""" try: - config = load_config() - config["auto_update_ytdlp"] = enabled - config["auto_update_frequency"] = frequency - save_config(config) + from src.utils.ytsage_config_manager import ConfigManager + + ConfigManager.set("auto_update_ytdlp", enabled) + ConfigManager.set("auto_update_frequency", frequency) return True except Exception as e: logger.exception(f"Error updating auto-update settings: {e}") diff --git a/src/gui/ytsage_gui_dialogs/ytsage_dialogs_custom.py b/src/gui/ytsage_gui_dialogs/ytsage_dialogs_custom.py index 75efe7a..5f14511 100644 --- a/src/gui/ytsage_gui_dialogs/ytsage_dialogs_custom.py +++ b/src/gui/ytsage_gui_dialogs/ytsage_dialogs_custom.py @@ -30,6 +30,7 @@ from PySide6.QtWidgets import ( ) from src.core.ytsage_yt_dlp import get_yt_dlp_path +from src.core.ytsage_utils import update_auto_update_settings from src.utils.ytsage_constants import YTDLP_DOCS_URL from src.utils.ytsage_config_manager import ConfigManager from src.utils.ytsage_localization import LocalizationManager, _ @@ -518,14 +519,14 @@ class CustomOptionsDialog(QDialog): language_layout.addStretch() # === Updater Tab === - updater_tab = UpdaterTabWidget(self) + self.updater_tab = UpdaterTabWidget(self) # Add tabs to the tab widget self.tab_widget.addTab(cookies_tab, _("tabs.cookies")) self.tab_widget.addTab(command_tab, _("tabs.custom_command")) self.tab_widget.addTab(proxy_tab, _("tabs.proxy")) self.tab_widget.addTab(language_tab, _("tabs.language")) - self.tab_widget.addTab(updater_tab, _("tabs.updater")) + self.tab_widget.addTab(self.updater_tab, _("tabs.updater")) # Dialog buttons button_box = QDialogButtonBox() @@ -930,6 +931,21 @@ class CustomOptionsDialog(QDialog): self.restart_notice.setVisible(True) logger.info(f"Language changed to: {selected_lang_code}") + + def accept(self) -> None: + """Override accept to save auto-update settings from the updater tab.""" + logger.info("CustomOptionsDialog.accept() called") + try: + # Save auto-update settings from the updater tab + enabled, frequency = self.updater_tab.get_auto_update_settings() + logger.info(f"Saving auto-update settings: enabled={enabled}, frequency={frequency}") + result = update_auto_update_settings(enabled, frequency) + logger.info(f"Auto-update settings save result: {result}") + except Exception as e: + logger.exception(f"Error saving auto-update settings: {e}") + + # Call the parent accept method to close the dialog + super().accept() class TimeRangeDialog(QDialog): diff --git a/src/gui/ytsage_gui_dialogs/ytsage_dialogs_settings.py b/src/gui/ytsage_gui_dialogs/ytsage_dialogs_settings.py index 585f07a..4189106 100644 --- a/src/gui/ytsage_gui_dialogs/ytsage_dialogs_settings.py +++ b/src/gui/ytsage_gui_dialogs/ytsage_dialogs_settings.py @@ -1,6 +1,6 @@ """ Settings-related dialogs for YTSage application. -Contains dialogs for configuring download settings and auto-update preferences. +Contains dialogs for configuring download settings. """ import threading @@ -27,13 +27,6 @@ from PySide6.QtWidgets import ( QVBoxLayout, ) -from src.core.ytsage_utils import ( - check_and_update_ytdlp_auto, - get_auto_update_settings, - get_ytdlp_version, - update_auto_update_settings, -) -from src.gui.ytsage_gui_dialogs.ytsage_dialogs_update import YTDLPUpdateDialog from src.utils.ytsage_logger import logger from src.utils.ytsage_localization import _ from src.utils.ytsage_config_manager import ConfigManager @@ -241,51 +234,6 @@ class DownloadSettingsDialog(QDialog): output_format_group_box.setLayout(output_format_layout) layout.addWidget(output_format_group_box) - # --- Auto-Update yt-dlp Section --- - auto_update_group_box = QGroupBox(_("settings.auto_update_ytdlp")) - auto_update_layout = QVBoxLayout() - - # Load current auto-update settings - auto_settings = get_auto_update_settings() - - # Enable/Disable auto-update checkbox - self.auto_update_enabled = QCheckBox(_("settings.enable_auto_updates")) - self.auto_update_enabled.setChecked(auto_settings["enabled"]) - auto_update_layout.addWidget(self.auto_update_enabled) - - # Frequency options - frequency_label = QLabel(_("settings.update_frequency")) - frequency_label.setStyleSheet("color: #ffffff; margin-top: 10px;") - auto_update_layout.addWidget(frequency_label) - - self.startup_radio = QRadioButton(_("settings.check_startup")) - self.daily_radio = QRadioButton(_("settings.check_daily")) - self.weekly_radio = QRadioButton(_("settings.check_weekly")) - - # Set current selection based on saved settings - current_frequency = auto_settings["frequency"] - if current_frequency == "startup": - self.startup_radio.setChecked(True) - elif current_frequency == "daily": - self.daily_radio.setChecked(True) - else: # weekly - self.weekly_radio.setChecked(True) - - auto_update_layout.addWidget(self.startup_radio) - auto_update_layout.addWidget(self.daily_radio) - auto_update_layout.addWidget(self.weekly_radio) - - # Test update button - test_update_layout = QHBoxLayout() - test_update_button = QPushButton(_("settings.check_updates_now")) - test_update_button.clicked.connect(self.test_update_check) - test_update_layout.addWidget(test_update_button) - test_update_layout.addStretch() - auto_update_layout.addLayout(test_update_layout) - - auto_update_group_box.setLayout(auto_update_layout) - layout.addWidget(auto_update_group_box) - # Dialog buttons (OK/Cancel) button_box = QDialogButtonBox() ok_button = button_box.addButton(_("buttons.ok"), QDialogButtonBox.ButtonRole.AcceptRole) @@ -364,46 +312,20 @@ class DownloadSettingsDialog(QDialog): ) return msg_box - def test_update_check(self) -> None: - """Open the yt-dlp update dialog with proper progress tracking.""" - # Create and show the update dialog (non-modal to prevent blocking) - dialog = YTDLPUpdateDialog(self) - dialog.setModal(False) # Make it non-modal - dialog.show() # Use show() instead of exec() to avoid blocking - - def get_auto_update_settings(self) -> tuple[bool, str]: - """Returns the auto-update settings from the dialog.""" - enabled = self.auto_update_enabled.isChecked() - - if self.startup_radio.isChecked(): - frequency = "startup" - elif self.daily_radio.isChecked(): - frequency = "daily" - else: # weekly_radio is checked - frequency = "weekly" - - return enabled, frequency - def accept(self) -> None: - """Override accept to save auto-update and format settings.""" + """Override accept to save format settings.""" try: - # Save auto-update settings - enabled, frequency = self.get_auto_update_settings() - # Save output format settings force_format = self.get_force_format_enabled() preferred_format = self.get_preferred_format() ConfigManager.set("force_output_format", force_format) ConfigManager.set("preferred_output_format", preferred_format) - if update_auto_update_settings(enabled, frequency): - QMessageBox.information( - self, - _("settings.settings_saved_title"), - _("settings.settings_saved_message"), - ) - else: - QMessageBox.warning(self, _("settings.error_title"), _("settings.failed_save_settings")) + QMessageBox.information( + self, + _("settings.settings_saved_title"), + _("settings.settings_saved_message"), + ) except Exception as e: QMessageBox.critical(self, _("settings.error_title"), _("settings.error_saving_settings", error=str(e))) diff --git a/src/gui/ytsage_gui_dialogs/ytsage_dialogs_updater.py b/src/gui/ytsage_gui_dialogs/ytsage_dialogs_updater.py index e3e7d2f..125142d 100644 --- a/src/gui/ytsage_gui_dialogs/ytsage_dialogs_updater.py +++ b/src/gui/ytsage_gui_dialogs/ytsage_dialogs_updater.py @@ -1,6 +1,6 @@ """ Updater tab for Custom Options dialog. -Handles checking for and installing FFmpeg updates. +Handles checking for and installing FFmpeg updates and yt-dlp auto-update settings. """ import threading @@ -8,16 +8,23 @@ from typing import TYPE_CHECKING, cast from PySide6.QtCore import QObject, Signal from PySide6.QtWidgets import ( + QCheckBox, QGroupBox, QHBoxLayout, QLabel, QProgressBar, QPushButton, + QRadioButton, QTextEdit, QVBoxLayout, QWidget, ) +from src.core.ytsage_utils import ( + get_auto_update_settings, + update_auto_update_settings, +) +from src.gui.ytsage_gui_dialogs.ytsage_dialogs_update import YTDLPUpdateDialog from src.utils.ytsage_localization import _ from src.utils.ytsage_logger import logger from src.core.ytsage_ffmpeg_updater import check_ffmpeg_update_available, update_ffmpeg @@ -66,6 +73,7 @@ class UpdaterTabWidget(QWidget): self.update_available = False self._init_ui() + self._load_auto_update_settings() def _init_ui(self) -> None: """Initialize the UI components.""" @@ -207,7 +215,8 @@ class UpdaterTabWidget(QWidget): self.log_output = QTextEdit() self.log_output.setReadOnly(True) self.log_output.setPlaceholderText("Update logs will appear here...") - self.log_output.setMinimumHeight(150) + self.log_output.setMinimumHeight(80) + self.log_output.setMaximumHeight(120) self.log_output.setStyleSheet( """ QTextEdit { @@ -224,8 +233,123 @@ class UpdaterTabWidget(QWidget): ffmpeg_layout.addWidget(self.log_output) layout.addWidget(ffmpeg_group) + + # === Auto-Update yt-dlp Section === + auto_update_group_box = QGroupBox(_("settings.auto_update_ytdlp")) + auto_update_layout = QVBoxLayout() + + # Enable/Disable auto-update checkbox + self.auto_update_enabled = QCheckBox(_("settings.enable_auto_updates")) + auto_update_layout.addWidget(self.auto_update_enabled) + + # Frequency options + frequency_label = QLabel(_("settings.update_frequency")) + frequency_label.setStyleSheet("color: #ffffff; margin-top: 10px;") + auto_update_layout.addWidget(frequency_label) + + self.startup_radio = QRadioButton(_("settings.check_startup")) + self.daily_radio = QRadioButton(_("settings.check_daily")) + self.weekly_radio = QRadioButton(_("settings.check_weekly")) + + self.startup_radio.setStyleSheet( + """ + QRadioButton { + color: #ffffff; + spacing: 5px; + } + QRadioButton::indicator { + width: 18px; + height: 18px; + border-radius: 9px; + } + QRadioButton::indicator:unchecked { + border: 2px solid #666666; + background: #15181b; + } + QRadioButton::indicator:checked { + border: 2px solid #c90000; + background: #c90000; + } + """ + ) + self.daily_radio.setStyleSheet(self.startup_radio.styleSheet()) + self.weekly_radio.setStyleSheet(self.startup_radio.styleSheet()) + + auto_update_layout.addWidget(self.startup_radio) + auto_update_layout.addWidget(self.daily_radio) + auto_update_layout.addWidget(self.weekly_radio) + + # Test update button + test_update_layout = QHBoxLayout() + test_update_button = QPushButton(_("settings.check_updates_now")) + test_update_button.clicked.connect(self.test_update_check) + test_update_button.setStyleSheet( + """ + QPushButton { + padding: 8px 15px; + background-color: #c90000; + border: none; + border-radius: 4px; + color: white; + font-weight: bold; + min-width: 120px; + } + QPushButton:hover { + background-color: #a50000; + } + QPushButton:pressed { + background-color: #800000; + } + """ + ) + test_update_layout.addWidget(test_update_button) + test_update_layout.addStretch() + auto_update_layout.addLayout(test_update_layout) + + auto_update_group_box.setLayout(auto_update_layout) + layout.addWidget(auto_update_group_box) + layout.addStretch() + def _load_auto_update_settings(self) -> None: + """Load current auto-update settings for yt-dlp.""" + try: + auto_settings = get_auto_update_settings() + + # Set checkbox + self.auto_update_enabled.setChecked(auto_settings["enabled"]) + + # Set current selection based on saved settings + current_frequency = auto_settings["frequency"] + if current_frequency == "startup": + self.startup_radio.setChecked(True) + elif current_frequency == "daily": + self.daily_radio.setChecked(True) + else: # weekly + self.weekly_radio.setChecked(True) + except Exception as e: + logger.exception(f"Error loading auto-update settings: {e}") + + def get_auto_update_settings(self) -> tuple[bool, str]: + """Returns the auto-update settings from the dialog.""" + enabled = self.auto_update_enabled.isChecked() + + if self.startup_radio.isChecked(): + frequency = "startup" + elif self.daily_radio.isChecked(): + frequency = "daily" + else: # weekly_radio is checked + frequency = "weekly" + + return enabled, frequency + + def test_update_check(self) -> None: + """Open the yt-dlp update dialog with proper progress tracking.""" + # Create and show the update dialog (non-modal to prevent blocking) + dialog = YTDLPUpdateDialog(self) + dialog.setModal(False) # Make it non-modal + dialog.show() # Use show() instead of exec() to avoid blocking + def check_for_updates(self) -> None: """Check if FFmpeg updates are available.""" self.check_button.setEnabled(False)