diff --git a/winehelper_gui.py b/winehelper_gui.py index 45bfb23..6a73e9f 100644 --- a/winehelper_gui.py +++ b/winehelper_gui.py @@ -1622,6 +1622,19 @@ class WineHelperGUI(QMainWindow): "padding-left: 10px;", "padding-left: 15px;" ) + # Стиль для кнопок тестовых программ + self.TEST_BUTTON_LIST_STYLE = """ + QPushButton { + background-color: #ffdc64; /* Более темный желтый фон */ + color: black; /* Черный цвет текста для контраста */ + text-align: left; + padding-left: 10px; + padding-right: 10px; + height: 42px; min-height: 42px; max-height: 42px; + } + QPushButton::icon { padding-left: 10px; } + """ + # Стили для оберток кнопок (для рамки выделения) self.FRAME_STYLE_DEFAULT = "QFrame { border: 2px solid transparent; border-radius: 8px; padding: 0px; }" self.FRAME_STYLE_SELECTED = "QFrame { border: 2px solid #0078d7; border-radius: 8px; padding: 0px; }" @@ -1775,8 +1788,9 @@ class WineHelperGUI(QMainWindow): if tab_name == "Автоматическая установка": title = "Автоматическая установка" html_content = ("
Скрипты из этого списка скачают, установят и настроят приложение за вас.
" - "Просто выберите программу и нажмите «Установить».
") + "Скрипты из этого списка скачают, установят и настроят приложение за вас. " + "Просто выберите программу и нажмите «Установить».
" + "Для доступа к экспериментальным скриптам установки отметьте опцию «Показать тестовые версии» внизу списка.
") show_global = False elif tab_name == "Ручная установка": title = "Ручная установка" @@ -2064,14 +2078,14 @@ class WineHelperGUI(QMainWindow): return btn - def _populate_install_grid(self, grid_layout, scripts_list, script_folder, button_list): + def _populate_install_grid(self, grid_layout, scripts_list, script_folder, button_list, start_index=None): """ Заполняет QGridLayout кнопками установщиков. Кнопки создаются только для скриптов, в которых найдена переменная PROG_NAME. :param grid_layout: QGridLayout для заполнения. :param scripts_list: Список имен скриптов. - :param script_folder: Имя папки со скриптами ('autoinstall' или 'manualinstall'). + :param script_folder: Имя папки со скриптами ('autoinstall', 'manualinstall' или 'testinstall'). :param button_list: Список для хранения созданных кнопок. """ button_index = 0 @@ -2085,7 +2099,13 @@ class WineHelperGUI(QMainWindow): icon_names = ScriptParser.extract_icons_from_script(script_path) icon_paths = [os.path.join(Var.DATA_PATH, "image", f"{name}.png") for name in icon_names] - btn = self._create_app_button(prog_name, icon_paths, self.BUTTON_LIST_STYLE) + + # Выбираем стиль в зависимости от папки + if script_folder == 'testinstall': + style_sheet = self.TEST_BUTTON_LIST_STYLE + else: + style_sheet = self.BUTTON_LIST_STYLE + btn = self._create_app_button(prog_name, icon_paths, style_sheet) # Обертка для рамки выделения frame = QFrame() @@ -2095,12 +2115,12 @@ class WineHelperGUI(QMainWindow): layout.addWidget(btn) btn.clicked.connect(lambda _, s=script, b=btn: self.show_script_info(s, b)) - row, column = divmod(button_index, 2) + row, column = divmod(len(button_list), 2) grid_layout.addWidget(frame, row, column) button_list.append(btn) button_index += 1 - def _create_searchable_grid_tab(self, placeholder_text, filter_slot): + def _create_searchable_grid_tab(self, placeholder_text, filter_slot, add_stretch=True): """ Создает стандартную вкладку с полем поиска и сеточным макетом с прокруткой. Возвращает кортеж (главный виджет вкладки, сеточный макет, поле поиска, область прокрутки). @@ -2134,11 +2154,12 @@ class WineHelperGUI(QMainWindow): grid_layout.setColumnStretch(1, 1) v_scroll_layout.addLayout(grid_layout) - v_scroll_layout.addStretch(1) + if add_stretch: + v_scroll_layout.addStretch(1) return tab_widget, grid_layout, search_edit, scroll_area - def _create_and_populate_install_tab(self, tab_title, script_folder, search_placeholder, filter_slot): + def _create_and_populate_install_tab(self, tab_title, script_folders, search_placeholder, filter_slot): """ Создает и заполняет вкладку для установки (автоматической или ручной). Возвращает кортеж со скриптами, кнопками и виджетами. @@ -2148,15 +2169,16 @@ class WineHelperGUI(QMainWindow): ) scripts = [] - script_path = os.path.join(Var.DATA_PATH, script_folder) - if os.path.isdir(script_path): - try: - scripts = sorted(os.listdir(script_path)) - except OSError as e: - print(f"Не удалось прочитать директорию {script_path}: {e}") - buttons_list = [] - self._populate_install_grid(grid_layout, scripts, script_folder, buttons_list) + for folder in script_folders: + script_path = os.path.join(Var.DATA_PATH, folder) + if os.path.isdir(script_path): + try: + folder_scripts = sorted(os.listdir(script_path)) + scripts.extend(folder_scripts) + self._populate_install_grid(grid_layout, folder_scripts, folder, buttons_list) + except OSError as e: + print(f"Не удалось прочитать директорию {script_path}: {e}") self.add_tab(tab_widget, tab_title) @@ -2168,30 +2190,89 @@ class WineHelperGUI(QMainWindow): scripts, buttons, layout, search_edit, scroll_area ) = self._create_and_populate_install_tab( - "Автоматическая установка", "autoinstall", "Поиск скрипта автоматической установки...", partial(self.filter_buttons, 'auto') + "Автоматическая установка", ["autoinstall"], "Поиск скрипта автоматической установки...", partial(self.filter_buttons, 'auto') ) self.autoinstall_scripts = scripts self.install_tabs_data['auto'] = { 'buttons': buttons, 'layout': layout, 'search_edit': search_edit, 'scroll_area': scroll_area } + # Добавляем чекбокс для тестовых версий + test_checkbox = QCheckBox("Показать тестовые версии") + test_checkbox.setToolTip("Показать/скрыть экспериментальные скрипты установки") + + # Находим layout вкладки, чтобы добавить чекбокс + tab_widget = self.stacked_widget.widget(self.stacked_widget.count() - 1) + if tab_widget and tab_widget.layout(): + tab_widget.layout().addWidget(test_checkbox) + + # Подключаем сигнал к слоту обновления + test_checkbox.stateChanged.connect(self.update_auto_install_list) + + # Сохраняем чекбокс для доступа в будущем + self.install_tabs_data['auto']['test_checkbox'] = test_checkbox + def create_manual_install_tab(self): """Создает вкладку для ручной установки программ""" ( scripts, buttons, layout, search_edit, scroll_area ) = self._create_and_populate_install_tab( - "Ручная установка", "manualinstall", "Поиск скрипта ручной установки...", partial(self.filter_buttons, 'manual') + "Ручная установка", ["manualinstall"], "Поиск скрипта ручной установки...", partial(self.filter_buttons, 'manual') ) self.manualinstall_scripts = scripts self.install_tabs_data['manual'] = { 'buttons': buttons, 'layout': layout, 'search_edit': search_edit, 'scroll_area': scroll_area } + def update_auto_install_list(self): + """Обновляет список на вкладке 'Автоматическая установка' при изменении чекбокса.""" + data = self.install_tabs_data.get('auto') + if not data: + return + + script_folders = ["autoinstall"] + if data['test_checkbox'].isChecked(): + script_folders.append("testinstall") + + # Перед удалением кнопок останавливаем все связанные с ними таймеры анимации + for btn in data['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 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 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}") + + self.autoinstall_scripts = scripts + # Применяем текущий фильтр поиска к обновленному списку + self.filter_buttons('auto') + def create_installed_tab(self): """Создает вкладку для отображения установленных программ в виде кнопок""" installed_tab, self.installed_scroll_layout, self.installed_search_edit, self.installed_scroll_area = self._create_searchable_grid_tab( - "Поиск установленной программы...", self.filter_installed_buttons + "Поиск установленной программы...", self.filter_installed_buttons, add_stretch=True ) self.add_tab(installed_tab, "Установленные") @@ -4239,6 +4320,8 @@ class WineHelperGUI(QMainWindow): if script_name in self.autoinstall_scripts: script_path = os.path.join(Var.DATA_PATH, "autoinstall", script_name) tab_type = 'auto' + if not os.path.exists(script_path): # Проверяем в testinstall, если не нашли в autoinstall + script_path = os.path.join(Var.DATA_PATH, "testinstall", script_name) self.manual_install_path_widget.setVisible(False) else: script_path = os.path.join(Var.DATA_PATH, "manualinstall", script_name) @@ -4404,7 +4487,9 @@ class WineHelperGUI(QMainWindow): winehelper_path = self.winehelper_path script_path = os.path.join(Var.DATA_PATH, - "autoinstall" if self.current_script in self.autoinstall_scripts else "manualinstall", + "autoinstall" if os.path.exists(os.path.join(Var.DATA_PATH, "autoinstall", self.current_script)) + else "testinstall" if os.path.exists(os.path.join(Var.DATA_PATH, "testinstall", self.current_script)) + else "manualinstall", self.current_script) if not os.path.exists(winehelper_path):