@@ -7,7 +7,7 @@ logger = get_logger(__name__)
_portproton_location = None
# Пути к конфигурационным файлам
# Paths to configuration files
CONFIG_FILE = os . path . join (
os . getenv ( " XDG_CONFIG_HOME " , os . path . join ( os . path . expanduser ( " ~ " ) , " .config " ) ) ,
" PortProtonQt.conf "
@@ -18,17 +18,32 @@ PORTPROTON_CONFIG_FILE = os.path.join(
" PortProton.conf "
)
# Пути к папкам с темами
# Paths to theme directories
xdg_data_home = os . getenv ( " XDG_DATA_HOME " , os . path . join ( os . path . expanduser ( " ~ " ) , " .local " , " share " ) )
THEMES_DIRS = [
os . path . join ( xdg_data_home , " PortProtonQt " , " themes " ) ,
os . path . join ( os . path . dirname ( os . path . abspath ( __file__ ) ) , " themes " )
]
def read_config_safely ( config_file : str ) - > configparser . ConfigParser | None :
""" Safely reads a configuration file and returns a ConfigParser object or None if reading fails. """
cp = configparser . ConfigParser ( )
if not os . path . exists ( config_file ) :
logger . debug ( f " Configuration file { config_file } not found " )
return None
try :
cp . read ( config_file , encoding = " utf-8 " )
return cp
except ( configparser . DuplicateSectionError , configparser . DuplicateOptionError ) as e :
logger . warning ( f " Invalid configuration file format: { e } " )
return None
except Exception as e :
logger . warning ( f " Failed to read configuration file: { e } " )
return None
def read_config ( ) :
"""
Читает конфигурационный файл и возвращает словарь параметров.
Пример строки в конфиге (без секций):
""" Reads the configuration file and returns a dictionary of parameters.
Example line in config (no sections):
detail_level = detailed
"""
config_dict = { }
@@ -44,29 +59,17 @@ def read_config():
return config_dict
def read_theme_from_config ( ) :
""" Reads the theme from the [Appearance] section of the configuration file.
Returns ' standart ' if the parameter is not set.
"""
Читает из конфигурационного файла тему из секции [Appearance].
Если параметр не задан, возвращает " standart " .
"" "
cp = configparser . ConfigParser ( )
if os . path . exists ( CONFIG_FILE ) :
try :
cp . read ( CONFIG_FILE , encoding = " utf-8 " )
except ( configparser . DuplicateSectionError , configparser . DuplicateOptionError ) as e :
logger . error ( " Ошибка в конфигурационном файле: %s " , e )
return " standart "
cp = read_config_safely ( CONFIG_FILE )
if cp is None :
return " standart "
return cp . get ( " Appearance " , " theme " , fallback = " standart " )
def save_theme_to_config ( theme_name ) :
"""
Сохраняет имя выбранной темы в секции [Appearance] конфигурационного файла.
"""
cp = configparser . ConfigParser ( )
if os . path . exists ( CONFIG_FILE ) :
try :
cp . read ( CONFIG_FILE , encoding = " utf-8 " )
except ( configparser . DuplicateSectionError , configparser . DuplicateOptionError ) as e :
logger . error ( " Ошибка в конфигурационном файле: %s " , e )
""" Saves the selected theme name to the [Appearance] section of the configuration file. """
cp = read_config_safely ( CONFIG_FILE ) or configparser . ConfigParser ( )
if " Appearance " not in cp :
cp [ " Appearance " ] = { }
cp [ " Appearance " ] [ " theme " ] = theme_name
@@ -74,34 +77,18 @@ def save_theme_to_config(theme_name):
cp . write ( configfile )
def read_time_config ( ) :
""" Reads time settings from the [Time] section of the configuration file.
If the section or parameter is missing, saves and returns ' detailed ' as default.
"""
Читает настройки времени из секции [Time] конфигурационного файла.
Если секция или параметр отсутствуют, сохраняет и возвращает " detailed " по умолчанию.
"""
cp = configparser . ConfigParser ( )
if os . path . exists ( CONFIG_FILE ) :
try :
cp . read ( CONFIG_FILE , encoding = " utf-8 " )
except ( configparser . DuplicateSectionError , configparser . DuplicateOptionError ) as e :
logger . error ( " Ошибка в конфигурационном файле: %s " , e )
save_time_config ( " detailed " )
return " detailed "
if not cp . has_section ( " Time " ) or not cp . has_option ( " Time " , " detail_level " ) :
save_time_config ( " detailed " )
return " detailed "
return cp . get ( " Time " , " detail_level " , fallback = " detailed " ) . lower ( )
return " detailed "
cp = read_config_safely ( CONFIG_FILE )
if cp is None or not cp . has_section ( " Time " ) or not cp . has_option ( " Time " , " detail_level " ) :
save_time_config ( " detailed " )
return " detailed "
return cp . get ( " Time " , " detail_level " , fallback = " detailed " ) . lower ( )
def save_time_config ( detail_level ) :
"""
Сохраняет настройку уровня детализации времени в секции [Time].
"""
cp = configparser . ConfigParser ( )
if os . path . exists ( CONFIG_FILE ) :
try :
cp . read ( CONFIG_FILE , encoding = " utf-8 " )
except ( configparser . DuplicateSectionError , configparser . DuplicateOptionError ) as e :
logger . error ( " Ошибка в конфигурационном файле: %s " , e )
""" Saves the time detail level to the [Time] section of the configuration file. """
cp = read_config_safely ( CONFIG_FILE ) or configparser . ConfigParser ( )
if " Time " not in cp :
cp [ " Time " ] = { }
cp [ " Time " ] [ " detail_level " ] = detail_level
@@ -109,48 +96,42 @@ def save_time_config(detail_level):
cp . write ( configfile )
def read_file_content ( file_path ) :
"""
Читает содержимое файла и возвращает е г о как строку.
"""
""" Reads the content of a file and returns it as a string. """
with open ( file_path , encoding = " utf-8 " ) as f :
return f . read ( ) . strip ( )
def get_portproton_location ( ) :
"""
Возвращает путь к директории PortProton .
Сначала проверяется кэшированный путь. Если он отсутствует, проверяется
наличие пути в файле PORTPROTON_CONFIG_FILE. Если путь недоступен,
используется директория по умолчанию.
""" Returns the path to the PortProton directory.
Checks the cached path first. If not set, reads from PORTPROTON_CONFIG_FILE .
If the path is invalid, uses the default directory.
"""
global _portproton_location
if _portproton_location is not None :
return _portproton_location
# Попытка чтения пути из конфигурационного файла
if os . path . isfile ( PORTPROTON_CONFIG_FILE ) :
try :
location = read_file_content ( PORTPROTON_CONFIG_FILE ) . strip ( )
if location and os . path . isdir ( location ) :
_portproton_location = location
logger . info ( f " Путь PortProton из конфигурации : { location } " )
logger . info ( f " PortProton path from configuration : { location } " )
return _portproton_location
logger . warning ( f " Недействительный путь в конфиге PortProton: { location } " )
logger . warning ( f " Invalid PortProton path in configuration: { location } , using default path " )
except ( OSError , PermissionError ) as e :
logger . error ( f " Ошибка чтения файла конфигурации PortProton: { e } " )
logger . warning ( f " Failed to read PortProton configuration file: { e } , using default path " )
default_dir = os . path . join ( os . path . expanduser ( " ~ " ) , " .var " , " app " , " ru.linux_gaming.PortProton " )
if os . path . isdir ( default_dir ) :
_portproton_location = default_dir
logger . info ( f " Используется директория flatpak PortProton: { default_dir } " )
logger . info ( f " Using flatpak PortProton directory : { default_dir } " )
return _portproton_location
logger . warning ( " Конфигурация и директория flatpak PortProton не найдены " )
logger . warning ( " PortProton configuration and flatpak directory not found " )
return None
def parse_desktop_entry ( file_path ) :
"""
Читает и парсит .desktop файл с помощью configparser .
Если секция [Desktop Entry] отсутствует, возвращается None.
""" Reads and parses a .desktop file using configparser.
Returns None if the [Desktop Entry] section is missing .
"""
cp = configparser . ConfigParser ( interpolation = None )
cp . read ( file_path , encoding = " utf-8 " )
@@ -159,9 +140,8 @@ def parse_desktop_entry(file_path):
return cp [ " Desktop Entry " ]
def load_theme_metainfo ( theme_name ) :
"""
Загружает метаинформацию темы из файла metainfo.ini в корне папки темы .
Ожидаемые поля: author, author_link, description, name.
""" Loads theme metadata from metainfo.ini in the theme ' s root directory.
Expected fields: author, author_link, description, name .
"""
meta = { }
for themes_dir in THEMES_DIRS :
@@ -179,34 +159,18 @@ def load_theme_metainfo(theme_name):
return meta
def read_card_size ( ) :
""" Reads the card size (width) from the [Cards] section.
Returns 250 if the parameter is not set.
"""
Читает размер карточек (ширину) из секции [Cards],
Если параметр не задан, возвращает 250.
"""
cp = configparser . ConfigParser ( )
if os . path . exists ( CONFIG_FILE ) :
try :
cp . read ( CONFIG_FILE , encoding = " utf-8 " )
except ( configparser . DuplicateSectionError , configparser . DuplicateOptionError ) as e :
logger . error ( " Ошибка в конфигурационном файле: %s " , e )
save_card_size ( 250 )
return 250
if not cp . has_section ( " Cards " ) or not cp . has_option ( " Cards " , " card_width " ) :
save_card_size ( 250 )
return 250
return cp . getint ( " Cards " , " card_width " , fallback = 250 )
return 250
cp = read_config_safely ( CONFIG_FILE )
if cp is None or not cp . has_section ( " Cards " ) or not cp . has_option ( " Cards " , " card_width " ) :
save_card_size ( 250 )
return 250
return cp . getint ( " Cards " , " card_width " , fallback = 250 )
def save_card_size ( card_width ) :
"""
Сохраняет размер карточек (ширину) в секцию [Cards].
"""
cp = configparser . ConfigParser ( )
if os . path . exists ( CONFIG_FILE ) :
try :
cp . read ( CONFIG_FILE , encoding = " utf-8 " )
except ( configparser . DuplicateSectionError , configparser . DuplicateOptionError ) as e :
logger . error ( " Ошибка в конфигурационном файле: %s " , e )
""" Saves the card size (width) to the [Cards] section. """
cp = read_config_safely ( CONFIG_FILE ) or configparser . ConfigParser ( )
if " Cards " not in cp :
cp [ " Cards " ] = { }
cp [ " Cards " ] [ " card_width " ] = str ( card_width )
@@ -214,34 +178,18 @@ def save_card_size(card_width):
cp . write ( configfile )
def read_sort_method ( ) :
""" Reads the sort method from the [Games] section.
Returns ' last_launch ' if the parameter is not set.
"""
Читает метод сортировки из секции [Games].
Если параметр не задан, возвращает last_launch.
"""
cp = configparser . ConfigParser ( )
if os . path . exists ( CONFIG_FILE ) :
try :
cp . read ( CONFIG_FILE , encoding = " utf-8 " )
except ( configparser . DuplicateSectionError , configparser . DuplicateOptionError ) as e :
logger . error ( " Ошибка в конфигурационном файле: %s " , e )
save_sort_method ( " last_launch " )
return " last_launch "
if not cp . has_section ( " Games " ) or not cp . has_option ( " Games " , " sort_method " ) :
save_sort_method ( " last_launch " )
return " last_launch "
return cp . get ( " Games " , " sort_method " , fallback = " last_launch " ) . lower ( )
return " last_launch "
cp = read_config_safely ( CONFIG_FILE )
if cp is None or not cp . has_section ( " Games " ) or not cp . has_option ( " Games " , " sort_method " ) :
save_sort_method ( " last_launch " )
return " last_launch "
return cp . get ( " Games " , " sort_method " , fallback = " last_launch " ) . lower ( )
def save_sort_method ( sort_method ) :
"""
Сохраняет метод сортировки в секцию [Games].
"""
cp = configparser . ConfigParser ( )
if os . path . exists ( CONFIG_FILE ) :
try :
cp . read ( CONFIG_FILE , encoding = " utf-8 " )
except ( configparser . DuplicateSectionError , configparser . DuplicateOptionError ) as e :
logger . error ( " Ошибка в конфигурационном файле: %s " , e )
""" Saves the sort method to the [Games] section. """
cp = read_config_safely ( CONFIG_FILE ) or configparser . ConfigParser ( )
if " Games " not in cp :
cp [ " Games " ] = { }
cp [ " Games " ] [ " sort_method " ] = sort_method
@@ -249,34 +197,18 @@ def save_sort_method(sort_method):
cp . write ( configfile )
def read_display_filter ( ) :
""" Reads the display_filter parameter from the [Games] section.
Returns ' all ' if the parameter is missing.
"""
Читает параметр display_filter из секции [Games].
Если параметр отсутствует, сохраняет и возвращает значение " all " .
"""
cp = configparser . ConfigParser ( )
if os . path . exists ( CONFIG_FILE ) :
try :
cp . read ( CONFIG_FILE , encoding = " utf-8 " )
except Exception as e :
logger . error ( " Ошибка чтения конфига: %s " , e )
save_display_filter ( " all " )
return " all "
if not cp . has_section ( " Games " ) or not cp . has_option ( " Games " , " display_filter " ) :
save_display_filter ( " all " )
return " all "
return cp . get ( " Games " , " display_filter " , fallback = " all " ) . lower ( )
return " all "
cp = read_config_safely ( CONFIG_FILE )
if cp is None or not cp . has_section ( " Games " ) or not cp . has_option ( " Games " , " display_filter " ) :
save_display_filter ( " all " )
return " all "
return cp . get ( " Games " , " display_filter " , fallback = " all " ) . lower ( )
def save_display_filter ( filter_value ) :
"""
Сохраняет параметр display_filter в секцию [Games] конфигурационного файла.
"""
cp = configparser . ConfigParser ( )
if os . path . exists ( CONFIG_FILE ) :
try :
cp . read ( CONFIG_FILE , encoding = " utf-8 " )
except Exception as e :
logger . error ( " Ошибка чтения конфига: %s " , e )
""" Saves the display_filter parameter to the [Games] section. """
cp = read_config_safely ( CONFIG_FILE ) or configparser . ConfigParser ( )
if " Games " not in cp :
cp [ " Games " ] = { }
cp [ " Games " ] [ " display_filter " ] = filter_value
@@ -284,37 +216,23 @@ def save_display_filter(filter_value):
cp . write ( configfile )
def read_favorites ( ) :
""" Reads the list of favorite games from the [Favorites] section.
The list is stored as a quoted string with comma-separated names.
Returns an empty list if the section or parameter is missing.
"""
Читает список избранных игр из секции [Favorites] конфигурационного файла.
Список хранится как строка, заключённая в кавычки, с именами, разделёнными запятыми.
Если секция или параметр отсутствуют, возвращает пустой список.
"""
cp = configparser . ConfigParser ( )
if os . path . exists ( CONFIG_FILE ) :
try :
cp . read ( CONFIG_FILE , encoding = " utf-8 " )
except Exception as e :
logger . error ( " Ошибка чтения конфига: %s " , e )
return [ ]
if cp . has_section ( " Favorites " ) and cp . has_option ( " Favorites " , " games " ) :
favs = cp . get ( " Favorites " , " games " , fallback = " " ) . strip ( )
# Если строка начинается и заканчивается кавычками, удаляем их
if favs . startswith ( ' " ' ) and favs . endswith ( ' " ' ) :
favs = favs [ 1 : - 1 ]
return [ s . strip ( ) for s in favs . split ( " , " ) if s . strip ( ) ]
return [ ]
cp = read_config_safely ( CONFIG_FILE )
if cp is None or not cp . has_section ( " Favorites " ) or not cp . has_option ( " Favorites " , " games " ) :
return [ ]
favs = cp . get ( " Favorites " , " games " , fallback = " " ) . strip ( )
if favs . startswith ( ' " ' ) and favs . endswith ( ' " ' ) :
favs = favs [ 1 : - 1 ]
return [ s . strip ( ) for s in favs . split ( " , " ) if s . strip ( ) ]
def save_favorites ( favorites ) :
""" Saves the list of favorite games to the [Favorites] section.
The list is stored as a quoted string with comma-separated names.
"""
Сохраняет список избранных игр в секцию [Favorites] конфигурационного файла.
Список сохраняется как строка, заключённая в двойные кавычки, где имена игр разделены запятыми.
"""
cp = configparser . ConfigParser ( )
if os . path . exists ( CONFIG_FILE ) :
try :
cp . read ( CONFIG_FILE , encoding = " utf-8 " )
except Exception as e :
logger . error ( " Ошибка чтения конфига: %s " , e )
cp = read_config_safely ( CONFIG_FILE ) or configparser . ConfigParser ( )
if " Favorites " not in cp :
cp [ " Favorites " ] = { }
fav_str = " , " . join ( favorites )
@@ -323,34 +241,18 @@ def save_favorites(favorites):
cp . write ( configfile )
def read_rumble_config ( ) :
""" Reads the gamepad rumble setting from the [Gamepad] section.
Returns False if the parameter is missing.
"""
Читает настройку виброотдачи геймпада из секции [Gamepad].
Если параметр отсутствует, сохраняет и возвращает False по умолчанию.
"""
cp = configparser . ConfigParser ( )
if os . path . exists ( CONFIG_FILE ) :
try :
cp . read ( CONFIG_FILE , encoding = " utf-8 " )
except Exception as e :
logger . error ( " Ошибка чтения конфигурационного файла: %s " , e )
save_rumble_config ( False )
return False
if not cp . has_section ( " Gamepad " ) or not cp . has_option ( " Gamepad " , " rumble_enabled " ) :
save_rumble_config ( False )
return False
return cp . getboolean ( " Gamepad " , " rumble_enabled " , fallback = False )
return False
cp = read_config_safely ( CONFIG_FILE )
if cp is None or not cp . has_section ( " Gamepad " ) or not cp . has_option ( " Gamepad " , " rumble_enabled " ) :
save_rumble_config ( False )
return False
return cp . getboolean ( " Gamepad " , " rumble_enabled " , fallback = False )
def save_rumble_config ( rumble_enabled ) :
"""
Сохраняет настройку виброотдачи геймпада в секцию [Gamepad].
"""
cp = configparser . ConfigParser ( )
if os . path . exists ( CONFIG_FILE ) :
try :
cp . read ( CONFIG_FILE , encoding = " utf-8 " )
except ( configparser . DuplicateSectionError , configparser . DuplicateOptionError ) as e :
logger . error ( " Ошибка чтения конфигурационного файла: %s " , e )
""" Saves the gamepad rumble setting to the [Gamepad] section. """
cp = read_config_safely ( CONFIG_FILE ) or configparser . ConfigParser ( )
if " Gamepad " not in cp :
cp [ " Gamepad " ] = { }
cp [ " Gamepad " ] [ " rumble_enabled " ] = str ( rumble_enabled )
@@ -358,41 +260,28 @@ def save_rumble_config(rumble_enabled):
cp . write ( configfile )
def ensure_default_proxy_config ( ) :
""" Ensures the [Proxy] section exists in the configuration file.
Creates it with empty values if missing.
"""
Проверяет наличие секции [Proxy] в конфигурационном файле.
Если секция отсутствует, создаёт её с пустыми значениями.
"""
cp = configparser . ConfigParser ( )
if os . path . exists ( CONFIG_FILE ) :
try :
cp . read ( CONFIG_FILE , encoding = " utf-8 " )
except Exception as e:
logger . error ( " Ошибка чтения конфигурационного файла: %s " , e )
return
if not cp . has_section ( " Proxy " ) :
cp . add_section ( " Proxy " )
cp [ " Proxy " ] [ " proxy_url " ] = " "
cp [ " Proxy " ] [ " proxy_user " ] = " "
cp [ " Proxy " ] [ " proxy_password " ] = " "
with open ( CONFIG_FILE , " w " , encoding = " utf-8 " ) as configfile :
cp . write ( configfile )
cp = read_config_safely ( CONFIG_FILE ) or configparser . ConfigParser ( )
if " Proxy " not in cp :
cp . add_section ( " Proxy " )
cp [ " Proxy " ] [ " proxy_url " ] = " "
cp [ " Proxy " ] [ " proxy_user " ] = " "
cp [ " Proxy " ] [ " proxy_password " ] = " "
with open ( CONFIG_FILE , " w " , encoding = " utf-8 " ) as configfile :
cp . write ( configfil e )
def read_proxy_config ( ) :
"""
Читает настройки прокси из секции [Proxy] конфигурационного файла .
Если параметр proxy_url не задан или пустой, возвращает пустой словарь.
""" Reads proxy settings from the [Proxy] section.
Returns an empty dict if proxy_url is not set or empty .
"""
ensure_default_proxy_config ( )
cp = configparser . ConfigParser ( )
try :
cp . read ( CONFIG_FILE , encoding = " utf-8 " )
except Exception as e :
logger . error ( " Ошибка чтения конфигурационного файла: %s " , e )
cp = read_config_safely ( CONFIG_FILE )
if cp is None :
return { }
proxy_url = cp . get ( " Proxy " , " proxy_url " , fallback = " " ) . strip ( )
if proxy_url :
# Если указаны логин и пароль, добавляем их к URL
proxy_user = cp . get ( " Proxy " , " proxy_user " , fallback = " " ) . strip ( )
proxy_password = cp . get ( " Proxy " , " proxy_password " , fallback = " " ) . strip ( )
if " :// " in proxy_url and " @ " not in proxy_url and proxy_user and proxy_password :
@@ -402,16 +291,10 @@ def read_proxy_config():
return { }
def save_proxy_config ( proxy_url = " " , proxy_user = " " , proxy_password = " " ) :
""" Saves proxy settings to the [Proxy] section.
Creates the section if it does not exist.
"""
Сохраняет настройки proxy в секцию [Proxy] конфигурационного файла.
Если секция отсутствует, создаёт её.
"""
cp = configparser . ConfigParser ( )
if os . path . exists ( CONFIG_FILE ) :
try :
cp . read ( CONFIG_FILE , encoding = " utf-8 " )
except ( configparser . DuplicateSectionError , configparser . DuplicateOptionError ) as e :
logger . error ( " Ошибка чтения конфигурационного файла: %s " , e )
cp = read_config_safely ( CONFIG_FILE ) or configparser . ConfigParser ( )
if " Proxy " not in cp :
cp [ " Proxy " ] = { }
cp [ " Proxy " ] [ " proxy_url " ] = proxy_url
@@ -421,34 +304,18 @@ def save_proxy_config(proxy_url="", proxy_user="", proxy_password=""):
cp . write ( configfile )
def read_fullscreen_config ( ) :
""" Reads the fullscreen mode setting from the [Display] section.
Returns False if the parameter is missing.
"""
Читает настройку полноэкранного режима приложения из секции [Display].
Если параметр отсутствует, сохраняет и возвращает False по умолчанию.
"""
cp = configparser . ConfigParser ( )
if os . path . exists ( CONFIG_FILE ) :
try :
cp . read ( CONFIG_FILE , encoding = " utf-8 " )
except Exception as e :
logger . error ( " Ошибка чтения конфигурационного файла: %s " , e )
save_fullscreen_config ( False )
return False
if not cp . has_section ( " Display " ) or not cp . has_option ( " Display " , " fullscreen " ) :
save_fullscreen_config ( False )
return False
return cp . getboolean ( " Display " , " fullscreen " , fallback = False )
return False
cp = read_config_safely ( CONFIG_FILE )
if cp is None or not cp . has_section ( " Display " ) or not cp . has_option ( " Display " , " fullscreen " ) :
save_fullscreen_config ( False )
return False
return cp . getboolean ( " Display " , " fullscreen " , fallback = False )
def save_fullscreen_config ( fullscreen ) :
"""
Сохраняет настройку полноэкранного режима приложения в секцию [Display].
"""
cp = configparser . ConfigParser ( )
if os . path . exists ( CONFIG_FILE ) :
try :
cp . read ( CONFIG_FILE , encoding = " utf-8 " )
except ( configparser . DuplicateSectionError , configparser . DuplicateOptionError ) as e :
logger . error ( " Ошибка чтения конфигурационного файла: %s " , e )
""" Saves the fullscreen mode setting to the [Display] section. """
cp = read_config_safely ( CONFIG_FILE ) or configparser . ConfigParser ( )
if " Display " not in cp :
cp [ " Display " ] = { }
cp [ " Display " ] [ " fullscreen " ] = str ( fullscreen )
@@ -456,33 +323,19 @@ def save_fullscreen_config(fullscreen):
cp . write ( configfile )
def read_window_geometry ( ) - > tuple [ int , int ] :
""" Reads the window width and height from the [MainWindow] section.
Returns (0, 0) if the parameters are missing.
"""
Читает ширину и высоту окна из секции [MainWindow] конфигурационного файла.
Возвращает кортеж (width, height). Если данные отсутствуют, возвращает (0, 0).
"""
cp = configparser . ConfigParser ( )
if os . path . exists ( CONFIG_FILE ) :
try :
cp . read ( CONFIG_FILE , encoding = " utf-8 " )
except ( configparser . DuplicateSectionError , configparser . DuplicateOptionError ) as e :
logger . error ( " Ошибка в конфигурационном файле: %s " , e )
return ( 0 , 0 )
if cp . has_section ( " MainWindow " ) :
width = cp . getint ( " MainWindow " , " width " , fallback = 0 )
height = cp . getint ( " MainWindow " , " height " , fallback = 0 )
return ( width , height )
return ( 0 , 0 )
cp = read_config_safely ( CONFIG_FILE )
if cp is None or not cp . has_section ( " MainWindow " ) :
return ( 0 , 0 )
width = cp . getint ( " MainWindow " , " width " , fallback = 0 )
height = cp . getint ( " MainWindow " , " height " , fallback = 0 )
return ( width , height )
def save_window_geometry ( width : int , height : int ) :
"""
Сохраняет ширину и высоту окна в секцию [MainWindow] конфигурационного файла.
"""
cp = configparser . ConfigParser ( )
if os . path . exists ( CONFIG_FILE ) :
try :
cp . read ( CONFIG_FILE , encoding = " utf-8 " )
except ( configparser . DuplicateSectionError , configparser . DuplicateOptionError ) as e :
logger . error ( " Ошибка в конфигурационном файле: %s " , e )
""" Saves the window width and height to the [MainWindow] section. """
cp = read_config_safely ( CONFIG_FILE ) or configparser . ConfigParser ( )
if " MainWindow " not in cp :
cp [ " MainWindow " ] = { }
cp [ " MainWindow " ] [ " width " ] = str ( width )
@@ -491,59 +344,40 @@ def save_window_geometry(width: int, height: int):
cp . write ( configfile )
def reset_config ( ) :
"""
Сбрасывает конфигурационный файл, удаляя е г о .
После этого все настройки будут возвращены к значениям по умолчанию при следующем чтении.
""" Resets the configuration file by deleting it.
Subsequent reads will use default values .
"""
if os . path . exists ( CONFIG_FILE ) :
try :
os . remove ( CONFIG_FILE )
logger . info ( " Конфигурационный файл %s удалён " , CONFIG_FILE )
logger . info ( " Configuration file %s deleted " , CONFIG_FILE )
except Exception as e :
logger . error ( " Ошибка при удалении конфигурационного файла: %s " , e )
logger . warning ( f " Failed to delete configuration file: { e } " )
def clear_cache ( ) :
"""
Очищает кэш PortProtonQt, удаляя папку кэша.
"""
""" Clears the PortProtonQt cache by deleting the cache directory. """
xdg_cache_home = os . getenv ( " XDG_CACHE_HOME " , os . path . join ( os . path . expanduser ( " ~ " ) , " .cache " ) )
cache_dir = os . path . join ( xdg_cache_home , " PortProtonQt " )
if os . path . exists ( cache_dir ) :
try :
shutil . rmtree ( cache_dir )
logger . info ( " Кэш PortProtonQt удалён : %s " , cache_dir )
logger . info ( " PortProtonQt cache deleted : %s " , cache_dir )
except Exception as e :
logger . error ( " Ошибка при удалении кэша: %s " , e )
logger . warning ( f " Failed to delete cache: { e } " )
def read_auto_fullscreen_gamepad ( ) :
""" Reads the auto-fullscreen setting for gamepad from the [Display] section.
Returns False if the parameter is missing.
"""
Читает настройку автоматического полноэкранного режима при подключении геймпада из секции [Display].
Если параметр отсутствует, сохраняет и возвращает False по умолчанию.
"""
cp = configparser . ConfigParser ( )
if os . path . exists ( CONFIG_FILE ) :
try :
cp . read ( CONFIG_FILE , encoding = " utf-8 " )
except Exception as e :
logger . error ( " Ошибка чтения конфигурационного файла: %s " , e )
save_auto_fullscreen_gamepad ( False )
return False
if not cp . has_section ( " Display " ) or not cp . has_option ( " Display " , " auto_fullscreen_gamepad " ) :
save_auto_fullscreen_gamepad ( False )
return False
return cp . getboolean ( " Display " , " auto_fullscreen_gamepad " , fallback = False )
return False
cp = read_config_safely ( CONFIG_FILE )
if cp is None or not cp . has_section ( " Display " ) or not cp . has_option ( " Display " , " auto_fullscreen_gamepad " ) :
save_auto_fullscreen_gamepad ( False )
return False
return cp . getboolean ( " Display " , " auto_fullscreen_gamepad " , fallback = False )
def save_auto_fullscreen_gamepad ( auto_fullscreen ) :
"""
Сохраняет настройку автоматического полноэкранного режима при подключении геймпада в секцию [Display].
"""
cp = configparser . ConfigParser ( )
if os . path . exists ( CONFIG_FILE ) :
try :
cp . read ( CONFIG_FILE , encoding = " utf-8 " )
except ( configparser . DuplicateSectionError , configparser . DuplicateOptionError ) as e :
logger . error ( " Ошибка чтения конфигурационного файла: %s " , e )
""" Saves the auto-fullscreen setting for gamepad to the [Display] section. """
cp = read_config_safely ( CONFIG_FILE ) or configparser . ConfigParser ( )
if " Display " not in cp :
cp [ " Display " ] = { }
cp [ " Display " ] [ " auto_fullscreen_gamepad " ] = str ( auto_fullscreen )
@@ -551,36 +385,23 @@ def save_auto_fullscreen_gamepad(auto_fullscreen):
cp . write ( configfile )
def read_favorite_folders ( ) :
""" Reads the list of favorite folders from the [FavoritesFolders] section.
The list is stored as a quoted string with comma-separated paths.
Returns an empty list if the section or parameter is missing.
"""
Читает список избранных папок из секции [FavoritesFolders] конфигурационного файла.
Список хранится как строка, заключённая в кавычки, с путями, разделёнными запятыми.
Если секция или параметр отсутствуют, возвращает пустой список.
"""
cp = configparser . ConfigParser ( )
if os . path . exists ( CONFIG_FILE ) :
try :
cp . read ( CONFIG_FILE , encoding = " utf-8 " )
except Exception as e :
logger . error ( " Ошибка чтения конфига: %s " , e )
return [ ]
if cp . has_section ( " FavoritesFolders " ) and cp . has_option ( " FavoritesFolders " , " folders " ) :
favs = cp . get ( " FavoritesFolders " , " folders " , fallback = " " ) . strip ( )
if favs . startswith ( ' " ' ) and favs . endswith ( ' " ' ) :
favs = favs [ 1 : - 1 ]
return [ os . path . normpath ( s . strip ( ) ) for s in favs . split ( " , " ) if s . strip ( ) and os . path . isdir ( os . path . normpath ( s . strip ( ) ) ) ]
return [ ]
cp = read_config_safely ( CONFIG_FILE )
if cp is None or not cp . has_section ( " FavoritesFolders " ) or not cp . has_option ( " FavoritesFolders " , " folders " ) :
return [ ]
favs = cp . get ( " FavoritesFolders " , " folders " , fallback = " " ) . strip ( )
if favs . startswith ( ' " ' ) and favs . endswith ( ' " ' ) :
favs = favs [ 1 : - 1 ]
return [ os . path . normpath ( s . strip ( ) ) for s in favs . split ( " , " ) if s . strip ( ) and os . path . isdir ( os . path . normpath ( s . strip ( ) ) ) ]
def save_favorite_folders ( folders ) :
""" Saves the list of favorite folders to the [FavoritesFolders] section.
The list is stored as a quoted string with comma-separated paths.
"""
Сохраняет список избранных папок в секцию [FavoritesFolders] конфигурационного файла.
Список сохраняется как строка, заключённая в двойные кавычки, где пути разделены запятыми.
"""
cp = configparser . ConfigParser ( )
if os . path . exists ( CONFIG_FILE ) :
try :
cp . read ( CONFIG_FILE , encoding = " utf-8 " )
except Exception as e :
logger . error ( " Ошибка чтения конфига: %s " , e )
cp = read_config_safely ( CONFIG_FILE ) or configparser . ConfigParser ( )
if " FavoritesFolders " not in cp :
cp [ " FavoritesFolders " ] = { }
fav_str = " , " . join ( [ os . path . normpath ( folder ) for folder in folders ] )