expanded information output in the prefix information window
This commit is contained in:
		| @@ -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""" | ||||
|             <p style="line-height: 1.3; font-size: 9pt;"> | ||||
|             <b>Имя:</b> {html.escape(info['name'])}<br> | ||||
|             <b>Архитектура:</b> {html.escape(info['arch'])}<br> | ||||
|             <b>Версия Wine:</b> {html.escape(info['wine_version'])}<br> | ||||
|             <b>Путь:</b> {html.escape(info['path'])}</p>""" | ||||
|         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"<p>Файл конфигурации last.conf не найден для префикса '{prefix_name}'.</p>") | ||||
|             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"<p>Ошибка чтения last.conf: {e}</p>") | ||||
|             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'<p style="line-height: 1.3; font-size: 9pt;">' | ||||
|         html_content += f"<b>Имя:</b> {html.escape(prefix_name)}<br>" | ||||
|  | ||||
|         # Отображаем известные переменные в заданном порядке | ||||
|         for key in display_order: | ||||
|             if key in all_vars: | ||||
|                 label, formatter = display_map[key] | ||||
|                 value = formatter(all_vars[key]) | ||||
|                 html_content += f"<b>{html.escape(label)}:</b> {html.escape(value)}<br>" | ||||
|  | ||||
|         # Отображаем остальные (неизвестные) переменные | ||||
|         other_vars_html = "" | ||||
|         for key, value in sorted(all_vars.items()): | ||||
|             if key not in display_map: | ||||
|                 other_vars_html += f"  <b>{html.escape(key)}:</b> {html.escape(value)}<br>" | ||||
|  | ||||
|         if other_vars_html: | ||||
|             html_content += "<br><b>Дополнительные параметры:</b><br>" | ||||
|             html_content += other_vars_html | ||||
|  | ||||
|         html_content += "</p>" | ||||
|         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_() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user