2025-07-01 22:48:58 +05:30
# --- Standard Library Imports ---
import os
2025-07-15 21:08:11 -07:00
import json
2025-07-01 22:48:58 +05:30
# --- PyQt5 Imports ---
from PyQt5 . QtCore import Qt , QStandardPaths
from PyQt5 . QtWidgets import (
QApplication , QDialog , QHBoxLayout , QLabel , QPushButton , QVBoxLayout ,
2025-07-22 07:00:34 -07:00
QGroupBox , QComboBox , QMessageBox , QGridLayout , QCheckBox
2025-07-01 22:48:58 +05:30
)
# --- Local Application Imports ---
from . . . i18n . translator import get_translation
2025-07-15 06:54:31 -07:00
from . . . utils . resolution import get_dark_theme
2025-07-01 22:48:58 +05:30
from . . main_window import get_app_icon_object
from . . . config . constants import (
2025-07-15 21:08:11 -07:00
THEME_KEY , LANGUAGE_KEY , DOWNLOAD_LOCATION_KEY ,
2025-07-27 06:32:15 -07:00
RESOLUTION_KEY , UI_SCALE_KEY , SAVE_CREATOR_JSON_KEY ,
COOKIE_TEXT_KEY , USE_COOKIE_KEY
2025-07-01 22:48:58 +05:30
)
class FutureSettingsDialog ( QDialog ) :
"""
A dialog for managing application - wide settings like theme , language ,
2025-07-15 21:08:11 -07:00
and display options , with an organized layout .
2025-07-01 22:48:58 +05:30
"""
def __init__ ( self , parent_app_ref , parent = None ) :
super ( ) . __init__ ( parent )
self . parent_app = parent_app_ref
self . setModal ( True )
app_icon = get_app_icon_object ( )
if app_icon and not app_icon . isNull ( ) :
self . setWindowIcon ( app_icon )
2025-07-15 21:08:11 -07:00
screen_height = QApplication . primaryScreen ( ) . availableGeometry ( ) . height ( ) if QApplication . primaryScreen ( ) else 800
scale_factor = screen_height / 800.0
2025-07-22 07:00:34 -07:00
base_min_w , base_min_h = 420 , 360 # Adjusted height for new layout
2025-07-01 22:48:58 +05:30
scaled_min_w = int ( base_min_w * scale_factor )
scaled_min_h = int ( base_min_h * scale_factor )
self . setMinimumSize ( scaled_min_w , scaled_min_h )
self . _init_ui ( )
self . _retranslate_ui ( )
self . _apply_theme ( )
def _init_ui ( self ) :
""" Initializes all UI components and layouts for the dialog. """
2025-07-15 21:08:11 -07:00
main_layout = QVBoxLayout ( self )
2025-07-01 22:48:58 +05:30
2025-07-15 21:08:11 -07:00
# --- Group 1: Interface Settings ---
self . interface_group_box = QGroupBox ( )
interface_layout = QGridLayout ( self . interface_group_box )
# Theme
self . theme_label = QLabel ( )
2025-07-01 22:48:58 +05:30
self . theme_toggle_button = QPushButton ( )
self . theme_toggle_button . clicked . connect ( self . _toggle_theme )
2025-07-15 21:08:11 -07:00
interface_layout . addWidget ( self . theme_label , 0 , 0 )
interface_layout . addWidget ( self . theme_toggle_button , 0 , 1 )
2025-07-01 22:48:58 +05:30
2025-07-15 21:08:11 -07:00
# UI Scale
self . ui_scale_label = QLabel ( )
self . ui_scale_combo_box = QComboBox ( )
self . ui_scale_combo_box . currentIndexChanged . connect ( self . _display_setting_changed )
interface_layout . addWidget ( self . ui_scale_label , 1 , 0 )
interface_layout . addWidget ( self . ui_scale_combo_box , 1 , 1 )
# Language
2025-07-01 22:48:58 +05:30
self . language_label = QLabel ( )
self . language_combo_box = QComboBox ( )
self . language_combo_box . currentIndexChanged . connect ( self . _language_selection_changed )
2025-07-15 21:08:11 -07:00
interface_layout . addWidget ( self . language_label , 2 , 0 )
interface_layout . addWidget ( self . language_combo_box , 2 , 1 )
main_layout . addWidget ( self . interface_group_box )
# --- Group 2: Download & Window Settings ---
self . download_window_group_box = QGroupBox ( )
download_window_layout = QGridLayout ( self . download_window_group_box )
# Window Size (Resolution)
self . window_size_label = QLabel ( )
self . resolution_combo_box = QComboBox ( )
self . resolution_combo_box . currentIndexChanged . connect ( self . _display_setting_changed )
download_window_layout . addWidget ( self . window_size_label , 0 , 0 )
download_window_layout . addWidget ( self . resolution_combo_box , 0 , 1 )
# Default Path
self . default_path_label = QLabel ( )
2025-07-01 22:48:58 +05:30
self . save_path_button = QPushButton ( )
2025-07-27 06:32:15 -07:00
# --- START: MODIFIED LOGIC ---
self . save_path_button . clicked . connect ( self . _save_cookie_and_path )
# --- END: MODIFIED LOGIC ---
2025-07-15 21:08:11 -07:00
download_window_layout . addWidget ( self . default_path_label , 1 , 0 )
download_window_layout . addWidget ( self . save_path_button , 1 , 1 )
2025-07-01 22:48:58 +05:30
2025-07-22 07:00:34 -07:00
# Save Creator.json Checkbox
self . save_creator_json_checkbox = QCheckBox ( )
self . save_creator_json_checkbox . stateChanged . connect ( self . _creator_json_setting_changed )
download_window_layout . addWidget ( self . save_creator_json_checkbox , 2 , 0 , 1 , 2 )
2025-07-15 21:08:11 -07:00
main_layout . addWidget ( self . download_window_group_box )
main_layout . addStretch ( 1 )
2025-07-01 22:48:58 +05:30
# --- OK Button ---
self . ok_button = QPushButton ( )
self . ok_button . clicked . connect ( self . accept )
2025-07-15 21:08:11 -07:00
main_layout . addWidget ( self . ok_button , 0 , Qt . AlignRight | Qt . AlignBottom )
2025-07-01 22:48:58 +05:30
2025-07-22 07:00:34 -07:00
def _load_checkbox_states ( self ) :
""" Loads the initial state for all checkboxes from settings. """
self . save_creator_json_checkbox . blockSignals ( True )
# Default to True so the feature is on by default for users
should_save = self . parent_app . settings . value ( SAVE_CREATOR_JSON_KEY , True , type = bool )
self . save_creator_json_checkbox . setChecked ( should_save )
self . save_creator_json_checkbox . blockSignals ( False )
def _creator_json_setting_changed ( self , state ) :
""" Saves the state of the ' Save Creator.json ' checkbox. """
is_checked = state == Qt . Checked
self . parent_app . settings . setValue ( SAVE_CREATOR_JSON_KEY , is_checked )
self . parent_app . settings . sync ( )
2025-07-01 22:48:58 +05:30
def _tr ( self , key , default_text = " " ) :
if callable ( get_translation ) and self . parent_app :
return get_translation ( self . parent_app . current_selected_language , key , default_text )
return default_text
def _retranslate_ui ( self ) :
self . setWindowTitle ( self . _tr ( " settings_dialog_title " , " Settings " ) )
2025-07-15 21:08:11 -07:00
# Group Box Titles
self . interface_group_box . setTitle ( self . _tr ( " interface_group_title " , " Interface Settings " ) )
self . download_window_group_box . setTitle ( self . _tr ( " download_window_group_title " , " Download & Window Settings " ) )
# Interface Group Labels
self . theme_label . setText ( self . _tr ( " theme_label " , " Theme: " ) )
self . ui_scale_label . setText ( self . _tr ( " ui_scale_label " , " UI Scale: " ) )
2025-07-01 22:48:58 +05:30
self . language_label . setText ( self . _tr ( " language_label " , " Language: " ) )
2025-07-15 21:08:11 -07:00
# Download & Window Group Labels
self . window_size_label . setText ( self . _tr ( " window_size_label " , " Window Size: " ) )
self . default_path_label . setText ( self . _tr ( " default_path_label " , " Default Path: " ) )
2025-07-22 07:00:34 -07:00
self . save_creator_json_checkbox . setText ( self . _tr ( " save_creator_json_label " , " Save Creator.json file " ) )
2025-07-15 21:08:11 -07:00
2025-07-27 06:32:15 -07:00
# --- START: MODIFIED LOGIC ---
2025-07-15 21:08:11 -07:00
# Buttons and Controls
self . _update_theme_toggle_button_text ( )
2025-07-27 06:32:15 -07:00
self . save_path_button . setText ( self . _tr ( " settings_save_cookie_path_button " , " Save Cookie + Download Path " ) )
self . save_path_button . setToolTip ( self . _tr ( " settings_save_cookie_path_tooltip " , " Save the current ' Download Location ' and Cookie settings for future sessions. " ) )
2025-07-01 22:48:58 +05:30
self . ok_button . setText ( self . _tr ( " ok_button " , " OK " ) )
2025-07-27 06:32:15 -07:00
# --- END: MODIFIED LOGIC ---
2025-07-01 22:48:58 +05:30
2025-07-15 21:08:11 -07:00
# Populate dropdowns
self . _populate_display_combo_boxes ( )
self . _populate_language_combo_box ( )
2025-07-22 07:00:34 -07:00
self . _load_checkbox_states ( )
2025-07-15 21:08:11 -07:00
2025-07-01 22:48:58 +05:30
def _apply_theme ( self ) :
2025-07-15 06:54:31 -07:00
if self . parent_app and self . parent_app . current_theme == " dark " :
scale = getattr ( self . parent_app , ' scale_factor ' , 1 )
self . setStyleSheet ( get_dark_theme ( scale ) )
2025-07-01 22:48:58 +05:30
else :
self . setStyleSheet ( " " )
def _update_theme_toggle_button_text ( self ) :
if self . parent_app . current_theme == " dark " :
self . theme_toggle_button . setText ( self . _tr ( " theme_toggle_light " , " Switch to Light Mode " ) )
else :
self . theme_toggle_button . setText ( self . _tr ( " theme_toggle_dark " , " Switch to Dark Mode " ) )
def _toggle_theme ( self ) :
new_theme = " light " if self . parent_app . current_theme == " dark " else " dark "
2025-07-15 21:08:11 -07:00
self . parent_app . settings . setValue ( THEME_KEY , new_theme )
self . parent_app . settings . sync ( )
self . parent_app . current_theme = new_theme
2025-07-01 22:48:58 +05:30
self . _apply_theme ( )
2025-07-15 21:08:11 -07:00
if hasattr ( self . parent_app , ' _apply_theme_and_restart_prompt ' ) :
self . parent_app . _apply_theme_and_restart_prompt ( )
def _populate_display_combo_boxes ( self ) :
self . resolution_combo_box . blockSignals ( True )
self . resolution_combo_box . clear ( )
resolutions = [
( " Auto " , self . _tr ( " auto_resolution " , " Auto (System Default) " ) ) ,
( " 1280x720 " , " 1280 x 720 " ) ,
( " 1600x900 " , " 1600 x 900 " ) ,
( " 1920x1080 " , " 1920 x 1080 (Full HD) " ) ,
( " 2560x1440 " , " 2560 x 1440 (2K) " ) ,
( " 3840x2160 " , " 3840 x 2160 (4K) " )
]
current_res = self . parent_app . settings . value ( RESOLUTION_KEY , " Auto " )
for res_key , res_name in resolutions :
self . resolution_combo_box . addItem ( res_name , res_key )
if current_res == res_key :
self . resolution_combo_box . setCurrentIndex ( self . resolution_combo_box . count ( ) - 1 )
self . resolution_combo_box . blockSignals ( False )
self . ui_scale_combo_box . blockSignals ( True )
self . ui_scale_combo_box . clear ( )
scales = [
( 0.5 , " 50 % " ) ,
( 0.7 , " 70 % " ) ,
( 0.9 , " 90 % " ) ,
( 1.0 , " 100 % (Default) " ) ,
( 1.25 , " 125 % " ) ,
( 1.50 , " 150 % " ) ,
( 1.75 , " 175 % " ) ,
( 2.0 , " 200 % " )
]
current_scale = float ( self . parent_app . settings . value ( UI_SCALE_KEY , 1.0 ) )
for scale_val , scale_name in scales :
self . ui_scale_combo_box . addItem ( scale_name , scale_val )
if abs ( current_scale - scale_val ) < 0.01 :
self . ui_scale_combo_box . setCurrentIndex ( self . ui_scale_combo_box . count ( ) - 1 )
self . ui_scale_combo_box . blockSignals ( False )
def _display_setting_changed ( self ) :
selected_res = self . resolution_combo_box . currentData ( )
selected_scale = self . ui_scale_combo_box . currentData ( )
self . parent_app . settings . setValue ( RESOLUTION_KEY , selected_res )
self . parent_app . settings . setValue ( UI_SCALE_KEY , selected_scale )
self . parent_app . settings . sync ( )
msg_box = QMessageBox ( self )
msg_box . setIcon ( QMessageBox . Information )
msg_box . setWindowTitle ( self . _tr ( " display_change_title " , " Display Settings Changed " ) )
msg_box . setText ( self . _tr ( " language_change_message " , " A restart is required for these changes to take effect. " ) )
msg_box . setInformativeText ( self . _tr ( " language_change_informative " , " Would you like to restart now? " ) )
restart_button = msg_box . addButton ( self . _tr ( " restart_now_button " , " Restart Now " ) , QMessageBox . ApplyRole )
ok_button = msg_box . addButton ( self . _tr ( " ok_button " , " OK " ) , QMessageBox . AcceptRole )
msg_box . setDefaultButton ( ok_button )
msg_box . exec_ ( )
if msg_box . clickedButton ( ) == restart_button :
self . parent_app . _request_restart_application ( )
2025-07-01 22:48:58 +05:30
def _populate_language_combo_box ( self ) :
self . language_combo_box . blockSignals ( True )
self . language_combo_box . clear ( )
languages = [
2025-07-15 21:08:11 -07:00
( " en " , " English " ) , ( " ja " , " 日本語 (Japanese) " ) , ( " fr " , " Français (French) " ) ,
( " de " , " Deutsch (German) " ) , ( " es " , " Español (Spanish) " ) , ( " pt " , " Português (Portuguese) " ) ,
( " ru " , " Русский (Russian) " ) , ( " zh_CN " , " 简体中文 (Simplified Chinese) " ) ,
( " zh_TW " , " 繁體中文 (Traditional Chinese) " ) , ( " ko " , " 한국어 (Korean) " )
2025-07-01 22:48:58 +05:30
]
2025-07-15 21:08:11 -07:00
current_lang = self . parent_app . current_selected_language
2025-07-01 22:48:58 +05:30
for lang_code , lang_name in languages :
self . language_combo_box . addItem ( lang_name , lang_code )
2025-07-15 21:08:11 -07:00
if current_lang == lang_code :
2025-07-01 22:48:58 +05:30
self . language_combo_box . setCurrentIndex ( self . language_combo_box . count ( ) - 1 )
self . language_combo_box . blockSignals ( False )
def _language_selection_changed ( self , index ) :
selected_lang_code = self . language_combo_box . itemData ( index )
if selected_lang_code and selected_lang_code != self . parent_app . current_selected_language :
self . parent_app . settings . setValue ( LANGUAGE_KEY , selected_lang_code )
self . parent_app . settings . sync ( )
2025-07-15 21:08:11 -07:00
self . parent_app . current_selected_language = selected_lang_code
2025-07-01 22:48:58 +05:30
self . _retranslate_ui ( )
2025-07-15 21:08:11 -07:00
if hasattr ( self . parent_app , ' _retranslate_main_ui ' ) :
self . parent_app . _retranslate_main_ui ( )
2025-07-01 22:48:58 +05:30
msg_box = QMessageBox ( self )
msg_box . setIcon ( QMessageBox . Information )
msg_box . setWindowTitle ( self . _tr ( " language_change_title " , " Language Changed " ) )
msg_box . setText ( self . _tr ( " language_change_message " , " A restart is required... " ) )
msg_box . setInformativeText ( self . _tr ( " language_change_informative " , " Would you like to restart now? " ) )
restart_button = msg_box . addButton ( self . _tr ( " restart_now_button " , " Restart Now " ) , QMessageBox . ApplyRole )
ok_button = msg_box . addButton ( self . _tr ( " ok_button " , " OK " ) , QMessageBox . AcceptRole )
msg_box . setDefaultButton ( ok_button )
msg_box . exec_ ( )
if msg_box . clickedButton ( ) == restart_button :
self . parent_app . _request_restart_application ( )
2025-07-27 06:32:15 -07:00
def _save_cookie_and_path ( self ) :
""" Saves the current download path and/or cookie settings from the main window. """
path_saved = False
cookie_saved = False
# --- Save Download Path Logic ---
2025-07-01 22:48:58 +05:30
if hasattr ( self . parent_app , ' dir_input ' ) and self . parent_app . dir_input :
current_path = self . parent_app . dir_input . text ( ) . strip ( )
2025-07-15 21:08:11 -07:00
if current_path and os . path . isdir ( current_path ) :
self . parent_app . settings . setValue ( DOWNLOAD_LOCATION_KEY , current_path )
2025-07-27 06:32:15 -07:00
path_saved = True
# --- Save Cookie Logic ---
if hasattr ( self . parent_app , ' use_cookie_checkbox ' ) :
use_cookie = self . parent_app . use_cookie_checkbox . isChecked ( )
cookie_content = self . parent_app . cookie_text_input . text ( ) . strip ( )
if use_cookie and cookie_content :
self . parent_app . settings . setValue ( USE_COOKIE_KEY , True )
self . parent_app . settings . setValue ( COOKIE_TEXT_KEY , cookie_content )
cookie_saved = True
else : # Also save the 'off' state
self . parent_app . settings . setValue ( USE_COOKIE_KEY , False )
self . parent_app . settings . setValue ( COOKIE_TEXT_KEY , " " )
self . parent_app . settings . sync ( )
# --- User Feedback ---
if path_saved and cookie_saved :
message = self . _tr ( " settings_save_both_success " , " Download location and cookie settings saved. " )
elif path_saved :
message = self . _tr ( " settings_save_path_only_success " , " Download location saved. No cookie settings were active to save. " )
elif cookie_saved :
message = self . _tr ( " settings_save_cookie_only_success " , " Cookie settings saved. Download location was not set. " )
2025-07-01 22:48:58 +05:30
else :
2025-07-27 06:32:15 -07:00
QMessageBox . warning ( self , self . _tr ( " settings_save_nothing_title " , " Nothing to Save " ) ,
self . _tr ( " settings_save_nothing_message " , " The download location is not a valid directory and no cookie was active. " ) )
return
QMessageBox . information ( self , self . _tr ( " settings_save_success_title " , " Settings Saved " ) , message )