@@ -26,9 +26,11 @@ class Var:
DATA_PATH = os . environ . get ( " DATA_PATH " )
CHANGELOG_FILE = os . environ . get ( " CHANGELOG_FILE " )
WH_ICON_PATH = os . environ . get ( " WH_ICON_PATH " )
WH_ICON_TRAY = os . environ . get ( " WH_ICON_TRAY " )
LICENSE_FILE = os . environ . get ( " LICENSE_FILE " )
LICENSE_AGREEMENT_FILE = os . environ . get ( " AGREEMENT " )
THIRD_PARTY_FILE = os . environ . get ( " THIRD_PARTY_FILE " )
ACCORDANCE = os . environ . get ( " ACCORDANCE " )
class DependencyManager :
""" Класс для управления проверкой и установкой системных зависимостей. """
@@ -1745,7 +1747,7 @@ class WineHelperGUI(QMainWindow):
self . tray_icon = QSystemTrayIcon ( self )
icon_path = Var . WH_ICON_PATH
icon_path = Var . WH_ICON_TRAY
if icon_path and os . path . exists ( icon_path ) :
pixmap = QPixmap ( icon_path )
if not pixmap . isNull ( ) :
@@ -1792,10 +1794,7 @@ class WineHelperGUI(QMainWindow):
title = " Автоматическая установка "
html_content = ( " <h3>Автоматическая установка</h3> "
" <p>Скрипты из этого списка скачают, установят и настроят приложение за вас. Просто выберите программу и нажмите «Установить».</p> "
" <p>Для доступа к экспериментальным скриптам установки отметьте опцию <b>«Показать тестовые версии»</b> внизу списка.</p> "
" <br><h3>Совместимость с дистрибутивами Альт</h3> "
" <p>С полным списком совместимого ПО и сертификатами (не только для WineHelper) можно ознакомиться по следующим ссылкам:<br> "
" <a href= ' https://www.basealt.ru/fileadmin/user_upload/compatibility/P10-view2.html ' >Для 10 платформы</a> | <a href= ' https://www.basealt.ru/fileadmin/user_upload/compatibility/P11-view2.html ' >Для 11 платформы</a></p> " )
" <p>Для доступа к экспериментальным скриптам установки отметьте опцию <b>«Показать тестовые версии»</b> внизу списка.</p> " )
show_global = False
elif tab_name == " Ручная установка " :
title = " Ручная установка "
@@ -2201,6 +2200,7 @@ class WineHelperGUI(QMainWindow):
self . install_tabs_data [ ' auto ' ] = {
' buttons ' : buttons , ' layout ' : layout , ' search_edit ' : search_edit , ' scroll_area ' : scroll_area
}
self . install_tabs_data [ ' auto ' ] [ ' test_buttons ' ] = [ ]
# Добавляем чекбокс для тестовых версий
test_checkbox = QCheckBox ( " Показать тестовые версии " )
@@ -2236,43 +2236,63 @@ class WineHelperGUI(QMainWindow):
if not data :
return
script_folders = [ " autoinstall " ]
if data [ ' test_checkbox ' ] . isChecked ( ) :
script_folders . append ( " testinstall " )
is_checked = data [ ' test_checkbox ' ] . isChecked ( )
test_buttons = data . get ( ' test_buttons ' , [ ] )
# Перед удалением к нопок останавливаем все связанные с ними таймеры анимации
for btn in data [ ' buttons' ] :
if btn in self . icon_animators :
anim_d ata = self . icon_animators . pop ( btn )
if ' main_timer ' in anim_data :
anim_data [ ' main_timer ' ] . stop ( )
if ' animation ' in anim_data and anim_data [ ' animation ' ] :
anim_data [ ' animation ' ] . stop ( )
# Сбрасываем ссылку на активную кнопку, если она была удалена
if self . current_active_button in data [ ' buttons ' ] :
self . current_active_button = None
# Очищаем старые кнопки и layout
for btn in data [ ' buttons ' ] :
btn . parent ( ) . deleteLater ( )
data [ ' buttons ' ] . clear ( )
# Заполняем layout новыми кнопками
scripts = [ ]
for folder in script_folders :
script_path = os . path . join ( Var . DATA_PATH , folder )
# Если нуж но показать тестовые версии и они еще не добавлены
if is_checked and not test_ buttons:
test_script_folder = " testinstall "
script_p ath = os . path . join ( Var . DATA_PATH , test_script_folder )
if os . path . isdir ( script_path ) :
try :
folder_scripts = sorted ( os . listdir ( script_path ) )
self . _populate_install_grid ( data [ ' layout ' ] , folder_scripts , folder , data [ ' buttons ' ] )
scripts . extend ( folder_scripts )
except OSError as e :
print ( f " Н е удалось прочитать директорию { script_path } : { e } " )
# Запоминаем, какие кнопки являются тестовыми
new_test_buttons = [ ]
self . _populate_install_grid ( data [ ' layout ' ] , folder_scripts , test_script_folder , new_test_buttons )
data [ ' test_buttons ' ] = new_test_buttons
data [ ' buttons ' ] . extend ( new_test_buttons )
self . autoinstall_scripts . extend ( folder_scripts )
self . autoinstall_scripts = scripts
# Применяем текущий фильтр поиска к обновленному списку
self . filter_buttons ( ' auto ' )
# Применяем фильтр и прокручиваем к первому новому элементу
self . filter_buttons ( ' auto ' )
if new_test_buttons :
first_new_button = new_test_buttons [ 0 ]
frame = first_new_button . parent ( )
if isinstance ( frame , QFrame ) :
# Даем время на отрисовку перед прокруткой
QTimer . singleShot ( 100 , lambda : data [ ' scroll_area ' ] . ensureWidgetVisible ( frame , 50 , 50 ) )
except OSError as e :
print ( f " Н е удалось прочитать директорию { test_script_folder } : { e } " )
# Если нужно скрыть тестовые версии и они были добавлены
elif not is_checked and test_buttons :
# Останавливаем анимацию и удаляем виджеты тестовых кнопок
for btn in test_buttons :
if btn in self . icon_animators :
anim_data = self . icon_animators . pop ( btn )
if ' main_timer ' in anim_data :
anim_data [ ' main_timer ' ] . stop ( )
if ' animation ' in anim_data and anim_data [ ' animation ' ] :
anim_data [ ' animation ' ] . stop ( )
# Удаляем кнопку из основного списка
if btn in data [ ' buttons ' ] :
data [ ' buttons ' ] . remove ( btn )
# Удаляем фрейм кнопки из layout
frame = btn . parent ( )
if frame :
frame . deleteLater ( )
# Очищаем список тестовых кнопок
data [ ' test_buttons ' ] . clear ( )
# Обновляем список скриптов
self . autoinstall_scripts = [ s for s in self . autoinstall_scripts if not os . path . exists ( os . path . join ( Var . DATA_PATH , " testinstall " , s ) ) ]
# В любом случае применяем фильтр, чтобы скрыть/показать кнопки в соответствии с поиском
if data [ ' test_checkbox ' ] . isChecked ( ) :
self . filter_buttons ( ' auto ' )
def create_installed_tab ( self ) :
""" Создает вкладку для отображения установленных программ в виде кнопок """
@@ -3239,10 +3259,36 @@ class WineHelperGUI(QMainWindow):
guide_layout = QVBoxLayout ( guide_tab )
guide_text = QTextBrowser ( )
guide_text . setOpenExternalLinks ( True )
guide_text . setHtml ( """
# --- Блок Совместимость ---
accordance_html = " "
try :
accordance_file_path = Var . ACCORDANCE
if not accordance_file_path or not os . path . exists ( accordance_file_path ) :
raise FileNotFoundError
with open ( accordance_file_path , ' r ' , encoding = ' utf-8 ' ) as f_acc :
accordance_lines = f_acc . read ( ) . strip ( ) . splitlines ( )
if accordance_lines :
accordance_html + = ' <hr><h2>Совместимость ПО и сертификаты</h2> '
accordance_html + = ' <p>С полным списком совместимого ПО и сертификатами можно ознакомиться по следующим ссылкам:</p><ul> '
for line in accordance_lines :
url_match = re . search ( r ' (https?://[^ \ s]+) ' , line )
if url_match :
url = url_match . group ( 1 )
description = line [ : url_match . start ( ) ] . strip ( )
accordance_html + = f ' <li> { html . escape ( description ) } <a href= " { url } " > { url } </a></li> '
else :
accordance_html + = f ' <li> { html . escape ( line ) } </li> '
accordance_html + = ' </ul> '
except Exception as e :
print ( f " Н е удалось обработать файл ACCORDANCE: { e } " )
guide_text . setHtml ( f """
<h2>Руководство пользователя</h2>
<p>Подробное и актуальное руководство по использованию WineHelper смотрите на <a href= " https://www.altlinux.org/Winehelper " >https://www.altlinux.org/Winehelper</a></p>
""" )
<p>Подробное и актуальное руководство по использованию WineHelper смотрите на сайте: <a href= " https://www.altlinux.org/Winehelper " >https://www.altlinux.org/Winehelper</a></p>
""" + accordance_html )
guide_layout . addWidget ( guide_text )
help_subtabs . addTab ( guide_tab , " Руководство " )