From aa267ad9efcb76edccd6812abf90ae94a5fea85f Mon Sep 17 00:00:00 2001 From: Sergey Palcheh Date: Mon, 8 Sep 2025 15:00:18 +0600 Subject: [PATCH] expanded information output in the prefix information window --- winehelper_gui.py | 223 +++++++++++++++++++++++++++------------------- 1 file changed, 131 insertions(+), 92 deletions(-) diff --git a/winehelper_gui.py b/winehelper_gui.py index d2c6d991..09a0a4ae 100644 --- a/winehelper_gui.py +++ b/winehelper_gui.py @@ -1280,16 +1280,9 @@ class WineHelperGUI(QMainWindow): self.icon_animators = {} self.previous_tab_index = 0 self.selected_wine_version_value = None - self.created_prefixes_info = {} # Хранит информацию о префиксах, созданных на вкладке self.current_managed_prefix_name = None # Имя префикса, выбранного в выпадающем списке - self.pending_prefix_info = None # Временное хранилище информации о создаваемом префиксе + self.prefixes_before_install = set() - # Добавим путь к файлу состояния - self.config_dir = os.path.join(os.path.expanduser("~"), ".config", "winehelper") - os.makedirs(self.config_dir, exist_ok=True) - self.state_file = os.path.join(self.config_dir, "gui_state.json") - - # State for command dialog log processing (specifically for prefix creation) self.command_output_buffer = "" self.command_last_line_was_progress = False # Создаем главный виджет и layout @@ -1325,7 +1318,7 @@ class WineHelperGUI(QMainWindow): self.create_help_tab() # Загружаем состояние после создания всех виджетов - self._load_state() + self._load_created_prefixes() # Инициализируем состояние, которое будет использоваться для логов self._reset_log_state() @@ -2016,69 +2009,61 @@ class WineHelperGUI(QMainWindow): self.wine_version_edit.textChanged.connect(self.update_create_prefix_button_state) self.prefix_install_path_edit.textChanged.connect(self.update_prefix_install_button_state) - def _remove_prefix_from_gui_state(self, prefix_name): - """Удаляет префикс из внутреннего состояния и пользовательского интерфейса вкладки 'Создать префикс'.""" - if prefix_name in self.created_prefixes_info: - del self.created_prefixes_info[prefix_name] + def _get_current_prefixes(self): + """Возвращает множество имен существующих префиксов.""" + prefixes_root_path = os.path.join(Var.USER_WORK_PATH, "prefixes") + if not os.path.isdir(prefixes_root_path): + return set() + try: + return { + name for name in os.listdir(prefixes_root_path) + if os.path.isdir(os.path.join(prefixes_root_path, name)) + } + except OSError as e: + print(f"Предупреждение: не удалось прочитать директорию префиксов: {e}") + return set() + def _remove_prefix_from_gui_state(self, prefix_name): + """Удаляет префикс из пользовательского интерфейса вкладки 'Создать префикс'.""" index_to_remove = self.created_prefix_selector.findText(prefix_name) if index_to_remove != -1: self.created_prefix_selector.removeItem(index_to_remove) - # Сохраняем состояние после удаления. on_created_prefix_selected также вызовет сохранение, - # но этот вызов гарантирует сохранение, даже если сигналы были заблокированы. - self._save_state() - - def _load_state(self): - """Загружает последнее состояние GUI из файла.""" - if not os.path.exists(self.state_file): + def _load_created_prefixes(self): + """Загружает список созданных префиксов, сканируя файловую систему, и восстанавливает последнее выбранное состояние.""" + prefixes_root_path = os.path.join(Var.USER_WORK_PATH, "prefixes") + if not os.path.isdir(prefixes_root_path): + self.management_container_groupbox.setVisible(False) return + try: - with open(self.state_file, 'r', encoding='utf-8') as f: - state = json.load(f) + prefix_names = sorted([ + name for name in os.listdir(prefixes_root_path) + if os.path.isdir(os.path.join(prefixes_root_path, name)) + ]) + except OSError as e: + print(f"Предупреждение: не удалось прочитать директорию префиксов: {e}") + prefix_names = [] - loaded_prefixes = state.get('created_prefixes_info', {}) - if not loaded_prefixes: - return + self.created_prefix_selector.blockSignals(True) + self.created_prefix_selector.clear() + if prefix_names: + self.created_prefix_selector.addItems(prefix_names) + self.created_prefix_selector.blockSignals(False) - # Блокируем сигналы, чтобы избежать преждевременного срабатывания - self.created_prefix_selector.blockSignals(True) - self.created_prefix_selector.clear() - self.created_prefixes_info.clear() + if not prefix_names: + self.management_container_groupbox.setVisible(False) + self.on_created_prefix_selected(-1) # Убедимся, что панель управления сброшена + return - for prefix_name, prefix_info in loaded_prefixes.items(): - prefix_path = os.path.join(Var.USER_WORK_PATH, "prefixes", prefix_name) - if os.path.isdir(prefix_path): - self.created_prefixes_info[prefix_name] = prefix_info - self.created_prefix_selector.addItem(prefix_name) + self.management_container_groupbox.setVisible(True) - self.created_prefix_selector.blockSignals(False) - - if self.created_prefix_selector.count() > 0: - self.management_container_groupbox.setVisible(True) - last_managed = state.get('current_managed_prefix_name') - index = self.created_prefix_selector.findText(last_managed) - if index != -1: - self.created_prefix_selector.setCurrentIndex(index) - else: - self.created_prefix_selector.setCurrentIndex(0) # Выбираем первый, если предыдущий не найден - else: - self.management_container_groupbox.setVisible(False) - - except (IOError, json.JSONDecodeError, TypeError) as e: - print(f"Предупреждение: не удалось загрузить состояние GUI: {e}") - - def _save_state(self): - """Сохраняет текущее состояние GUI в файл.""" - state = { - 'created_prefixes_info': self.created_prefixes_info, - 'current_managed_prefix_name': self.current_managed_prefix_name - } - try: - with open(self.state_file, 'w', encoding='utf-8') as f: - json.dump(state, f, indent=2, ensure_ascii=False) - except IOError as e: - print(f"Предупреждение: не удалось сохранить состояние GUI: {e}") + # По умолчанию выбираем первый элемент в списке, если он есть. + if self.created_prefix_selector.count() > 0: + self.created_prefix_selector.setCurrentIndex(0) + else: + # Если список пуст, убедимся, что панель управления сброшена. + self.on_created_prefix_selected(-1) def on_created_prefix_selected(self, index): """Обрабатывает выбор префикса из выпадающего списка.""" @@ -2091,7 +2076,6 @@ class WineHelperGUI(QMainWindow): self.current_managed_prefix_name = prefix_name self._setup_prefix_management_panel(prefix_name) self.delete_prefix_button.setEnabled(True) - self._save_state() def delete_selected_prefix(self): """Удаляет префикс, выбранный в выпадающем списке на вкладке 'Создать префикс'.""" @@ -2165,31 +2149,76 @@ class WineHelperGUI(QMainWindow): def _setup_prefix_management_panel(self, prefix_name): """Настраивает панель управления префиксом на основе текущего состояния.""" - if prefix_name and prefix_name in self.created_prefixes_info: - self.prefix_management_groupbox.setEnabled(True) + is_prefix_selected = bool(prefix_name) + self.prefix_management_groupbox.setEnabled(is_prefix_selected) + self.create_launcher_button.setEnabled(is_prefix_selected) + + if is_prefix_selected: self.update_prefix_info_display(prefix_name) else: - self.prefix_management_groupbox.setEnabled(False) self.prefix_info_display.clear() self.prefix_install_path_edit.clear() - # Кнопка "Создать ярлык" должна быть активна, если выбран действительный префикс - is_prefix_selected = bool(prefix_name and prefix_name in self.created_prefixes_info) - self.create_launcher_button.setEnabled(is_prefix_selected) + self.update_prefix_install_button_state() def update_prefix_info_display(self, prefix_name): - """Обновляет информационный блок для созданного префикса.""" - info = self.created_prefixes_info.get(prefix_name) - if not info: + """Обновляет информационный блок для созданного префикса, читая данные из last.conf.""" + if not prefix_name: self.prefix_info_display.clear() return - html_content = f""" -

- Имя: {html.escape(info['name'])}
- Архитектура: {html.escape(info['arch'])}
- Версия Wine: {html.escape(info['wine_version'])}
- Путь: {html.escape(info['path'])}

""" + last_conf_path = os.path.join(Var.USER_WORK_PATH, "prefixes", prefix_name, "last.conf") + + if not os.path.exists(last_conf_path): + self.prefix_info_display.setHtml(f"

Файл конфигурации last.conf не найден для префикса '{prefix_name}'.

") + return + + # Словарь для хранения всех переменных из файла + all_vars = {} + try: + with open(last_conf_path, 'r', encoding='utf-8') as f: + for line in f: + line = line.strip() + if line.startswith('export '): + parts = line[7:].split('=', 1) + if len(parts) == 2: + key = parts[0].strip() + value = parts[1].strip().strip('"\'') + all_vars[key] = value + except IOError as e: + self.prefix_info_display.setHtml(f"

Ошибка чтения last.conf: {e}

") + return + + # Карта для красивого отображения известных переменных + display_map = { + "WINEPREFIX": ("Путь", lambda v: v), + "WINEARCH": ("Архитектура", lambda v: "64-bit" if v == "win64" else "32-bit"), + "WH_WINE_USE": ("Версия Wine", lambda v: "Системная" if v == "system" else v), + "BASE_PFX": ("Тип", lambda v: 'Чистый' if v == "none" else 'С рекомендуемыми библиотеками'), + } + display_order = ["WINEPREFIX", "WINEARCH", "WH_WINE_USE", "BASE_PFX"] + + html_content = f'

' + html_content += f"Имя: {html.escape(prefix_name)}
" + + # Отображаем известные переменные в заданном порядке + for key in display_order: + if key in all_vars: + label, formatter = display_map[key] + value = formatter(all_vars[key]) + html_content += f"{html.escape(label)}: {html.escape(value)}
" + + # Отображаем остальные (неизвестные) переменные + other_vars_html = "" + for key, value in sorted(all_vars.items()): + if key not in display_map: + other_vars_html += f"  {html.escape(key)}: {html.escape(value)}
" + + if other_vars_html: + html_content += "
Дополнительные параметры:
" + html_content += other_vars_html + + html_content += "

" self.prefix_info_display.setHtml(html_content) def browse_for_prefix_installer(self): @@ -2484,15 +2513,6 @@ class WineHelperGUI(QMainWindow): wine_use = self.selected_wine_version_value wine_use_display = self.wine_version_edit.text() - # Сохраняем информацию для отображения после создания - self.pending_prefix_info = { - 'name': prefix_name, - 'path': prefix_path, - 'arch': "32-bit" if wine_arch == "win32" else "64-bit", - 'type': 'Чистый' if base_pfx else 'С рекомендуемыми библиотеками', - 'wine_version': wine_use_display - } - self.command_dialog = QDialog(self) self.command_dialog.setWindowTitle(f"Создание префикса: {prefix_name}") self.command_dialog.setMinimumSize(750, 400) @@ -2556,10 +2576,6 @@ class WineHelperGUI(QMainWindow): self._handle_command_finished(exit_code, exit_status) if exit_code == 0: # Добавляем новый префикс в список и выбираем его - if self.pending_prefix_info: - self.created_prefixes_info[prefix_name] = self.pending_prefix_info - self.pending_prefix_info = None - if self.created_prefix_selector.findText(prefix_name) == -1: self.created_prefix_selector.addItem(prefix_name) @@ -2568,7 +2584,6 @@ class WineHelperGUI(QMainWindow): if not self.management_container_groupbox.isVisible(): self.management_container_groupbox.setVisible(True) - self._save_state() self.prefix_name_edit.clear() self.wine_version_edit.clear() QMessageBox.information(self, "Успех", @@ -3403,6 +3418,8 @@ class WineHelperGUI(QMainWindow): if not self._show_license_agreement_dialog(): return # Пользователь отклонил лицензию + self.prefixes_before_install = self._get_current_prefixes() + self.installation_cancelled = False # Создаем диалоговое окно установки @@ -3641,11 +3658,33 @@ class WineHelperGUI(QMainWindow): if exit_code == 0 and exit_status == QProcess.NormalExit: self.append_log("\n=== Установка успешно завершена ===") + + # --- Обновление списка префиксов --- + # Определяем, какой префикс был создан + prefixes_after_install = self._get_current_prefixes() + new_prefixes = prefixes_after_install - getattr(self, 'prefixes_before_install', set()) + + # Перезагружаем список префиксов на вкладке "Создать префикс" + self._load_created_prefixes() + + new_prefix_name = None + if new_prefixes: + # Обычно создается один префикс, берем первый из найденных + new_prefix_name = new_prefixes.pop() + # Находим и выбираем его в выпадающем списке + index = self.created_prefix_selector.findText(new_prefix_name) + if index != -1: + self.created_prefix_selector.setCurrentIndex(index) + # --- Конец обновления списка префиксов --- + # Создаем кастомный диалог, чтобы кнопка была на русском success_box = QMessageBox(self.install_dialog) success_box.setWindowTitle("Успех") title_name = self._get_current_app_title() - success_box.setText(f"Программа «{title_name}» установлена успешно!") + success_text = f"Программа «{title_name}» установлена успешно!" + if new_prefix_name: + success_text += f"\n\nНовый префикс '{new_prefix_name}' был автоматически выбран в списке управления на вкладке 'Создать префикс'." + success_box.setText(success_text) success_box.setIcon(QMessageBox.Information) success_box.addButton("Готово", QMessageBox.AcceptRole) success_box.exec_()