added the choice of a prefix to be created for management

This commit is contained in:
Sergey Palcheh
2025-08-25 15:20:57 +06:00
parent dd5d8bb657
commit d499147bdc

View File

@@ -1268,8 +1268,14 @@ class WineHelperGUI(QMainWindow):
self.icon_animators = {} self.icon_animators = {}
self.previous_tab_index = 0 self.previous_tab_index = 0
self.selected_wine_version_value = None self.selected_wine_version_value = None
self.last_created_prefix_name = None self.created_prefixes_info = {} # Хранит информацию о префиксах, созданных на вкладке
self.last_created_prefix_info = None self.current_managed_prefix_name = None # Имя префикса, выбранного в выпадающем списке
self.pending_prefix_info = None # Временное хранилище информации о создаваемом префиксе
# Добавим путь к файлу состояния
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) # State for command dialog log processing (specifically for prefix creation)
self.command_output_buffer = "" self.command_output_buffer = ""
@@ -1306,6 +1312,9 @@ class WineHelperGUI(QMainWindow):
self.create_prefix_tab() self.create_prefix_tab()
self.create_help_tab() self.create_help_tab()
# Загружаем состояние после создания всех виджетов
self._load_state()
# Инициализируем состояние, которое будет использоваться для логов # Инициализируем состояние, которое будет использоваться для логов
self._reset_log_state() self._reset_log_state()
@@ -1819,18 +1828,19 @@ class WineHelperGUI(QMainWindow):
self.prefix_name_edit.setPlaceholderText("Например: my_prefix") self.prefix_name_edit.setPlaceholderText("Например: my_prefix")
form_layout.addRow("<b>Имя нового префикса:</b>", self.prefix_name_edit) form_layout.addRow("<b>Имя нового префикса:</b>", self.prefix_name_edit)
self.arch_groupbox = QGroupBox("Архитектура") arch_widget = QWidget()
arch_layout = QHBoxLayout() arch_layout = QHBoxLayout(arch_widget)
arch_layout.setContentsMargins(0, 0, 0, 0)
self.arch_win32_radio = QRadioButton("32-bit") self.arch_win32_radio = QRadioButton("32-bit")
self.arch_win64_radio = QRadioButton("64-bit") self.arch_win64_radio = QRadioButton("64-bit")
self.arch_win64_radio.setChecked(True) self.arch_win64_radio.setChecked(True)
arch_layout.addWidget(self.arch_win32_radio) arch_layout.addWidget(self.arch_win32_radio)
arch_layout.addWidget(self.arch_win64_radio) arch_layout.addWidget(self.arch_win64_radio)
self.arch_groupbox.setLayout(arch_layout) form_layout.addRow("<b>Разрядность:</b>", arch_widget)
form_layout.addRow("<b>Разрядность:</b>", self.arch_groupbox)
self.type_groupbox = QGroupBox("Тип префикса") type_widget = QWidget()
type_layout = QHBoxLayout() type_layout = QHBoxLayout(type_widget)
type_layout.setContentsMargins(0, 0, 0, 0)
self.type_clean_radio = QRadioButton("Чистый") self.type_clean_radio = QRadioButton("Чистый")
self.type_clean_radio.setToolTip("Создает пустой префикс Wine без каких-либо дополнительных компонентов.") self.type_clean_radio.setToolTip("Создает пустой префикс Wine без каких-либо дополнительных компонентов.")
self.type_recommended_radio = QRadioButton("С рекомендуемыми библиотеками") self.type_recommended_radio = QRadioButton("С рекомендуемыми библиотеками")
@@ -1839,8 +1849,7 @@ class WineHelperGUI(QMainWindow):
self.type_clean_radio.setChecked(True) self.type_clean_radio.setChecked(True)
type_layout.addWidget(self.type_clean_radio) type_layout.addWidget(self.type_clean_radio)
type_layout.addWidget(self.type_recommended_radio) type_layout.addWidget(self.type_recommended_radio)
self.type_groupbox.setLayout(type_layout) form_layout.addRow("<b>Наполнение:</b>", type_widget)
form_layout.addRow("<b>Наполнение:</b>", self.type_groupbox)
self.wine_version_edit = QLineEdit() self.wine_version_edit = QLineEdit()
self.wine_version_edit.setReadOnly(True) self.wine_version_edit.setReadOnly(True)
@@ -1854,63 +1863,6 @@ class WineHelperGUI(QMainWindow):
version_layout.addWidget(select_version_button) version_layout.addWidget(select_version_button)
form_layout.addRow("<b>Версия Wine/Proton:</b>", version_layout) form_layout.addRow("<b>Версия Wine/Proton:</b>", version_layout)
# --- GroupBox for managing the created prefix ---
self.prefix_management_groupbox = QGroupBox("Управление префиксом")
self.prefix_management_groupbox.setEnabled(False) # Disabled by default
management_layout = QGridLayout(self.prefix_management_groupbox)
management_layout.setSpacing(5)
# --- Left side: Buttons ---
self.prefix_winetricks_button = QPushButton("Менеджер компонентов")
self.prefix_winetricks_button.clicked.connect(
lambda: self.open_winetricks_manager(prefix_name=self.last_created_prefix_name))
self.prefix_winetricks_button.setToolTip(
"Установка компонентов, библиотек и шрифтов в префикс с помощью Winetricks.")
management_layout.addWidget(self.prefix_winetricks_button, 0, 0)
self.prefix_winecfg_button = QPushButton("Редактор настроек")
self.prefix_winecfg_button.clicked.connect(
lambda: self._run_wine_util('winecfg', prefix_name=self.last_created_prefix_name))
self.prefix_winecfg_button.setToolTip(
"Запуск утилиты winecfg для настройки параметров Wine (версия Windows, диски, аудио и т.д.).")
management_layout.addWidget(self.prefix_winecfg_button, 0, 1)
self.prefix_regedit_button = QPushButton("Редактор реестра")
self.prefix_regedit_button.clicked.connect(
lambda: self._run_wine_util('regedit', prefix_name=self.last_created_prefix_name))
self.prefix_regedit_button.setToolTip(
"Запуск редактора реестра Wine (regedit) для просмотра и изменения ключей реестра в префиксе.")
management_layout.addWidget(self.prefix_regedit_button, 1, 0)
self.prefix_uninstaller_button = QPushButton("Удаление программ")
self.prefix_uninstaller_button.clicked.connect(
lambda: self._run_wine_util('uninstaller', prefix_name=self.last_created_prefix_name))
self.prefix_uninstaller_button.setToolTip(
"Запуск стандартного деинсталлятора Wine для удаления установленных в префикс Windows-программ.")
management_layout.addWidget(self.prefix_uninstaller_button, 1, 1)
self.prefix_cmd_button = QPushButton("Командная строка")
self.prefix_cmd_button.clicked.connect(lambda: self._run_wine_util('cmd', prefix_name=self.last_created_prefix_name))
self.prefix_cmd_button.setToolTip("Запуск командной строки (cmd) в окружении выбранного префикса.")
management_layout.addWidget(self.prefix_cmd_button, 2, 0)
self.prefix_winefile_button = QPushButton("Файловый менеджер")
self.prefix_winefile_button.clicked.connect(
lambda: self._run_wine_util('winefile', prefix_name=self.last_created_prefix_name))
self.prefix_winefile_button.setToolTip("Запуск файлового менеджера Wine (winefile) для просмотра файлов внутри префикса.")
management_layout.addWidget(self.prefix_winefile_button, 2, 1)
# --- Right side: Info display ---
self.prefix_info_display = QTextBrowser()
self.prefix_info_display.setReadOnly(True)
self.prefix_info_display.setFrameStyle(QFrame.StyledPanel)
management_layout.addWidget(self.prefix_info_display, 0, 2, 3, 1)
# Устанавливаем растяжение колонок, чтобы область кнопок и область информации были примерно равны
management_layout.setColumnStretch(0, 1)
management_layout.setColumnStretch(1, 1)
management_layout.setColumnStretch(2, 2)
self.create_prefix_button = QPushButton("Создать префикс") self.create_prefix_button = QPushButton("Создать префикс")
self.create_prefix_button.setFont(QFont('Arial', 12, QFont.Bold)) self.create_prefix_button.setFont(QFont('Arial', 12, QFont.Bold))
self.create_prefix_button.setStyleSheet("background-color: #0078d7; color: white;") self.create_prefix_button.setStyleSheet("background-color: #0078d7; color: white;")
@@ -1919,7 +1871,75 @@ class WineHelperGUI(QMainWindow):
layout.addLayout(form_layout) layout.addLayout(form_layout)
layout.addWidget(self.create_prefix_button) layout.addWidget(self.create_prefix_button)
layout.addWidget(self.prefix_management_groupbox)
# --- Контейнер для выбора и управления созданными префиксами ---
self.management_container_groupbox = QGroupBox("Управление созданными префиксами")
self.management_container_groupbox.setVisible(False) # Скрыт, пока нет префиксов
container_layout = QVBoxLayout(self.management_container_groupbox)
self.created_prefix_selector = QComboBox()
self.created_prefix_selector.setPlaceholderText("Выберите префикс для управления")
self.created_prefix_selector.currentIndexChanged.connect(self.on_created_prefix_selected)
container_layout.addWidget(self.created_prefix_selector)
# --- GroupBox для управления выбранным префиксом ---
self.prefix_management_groupbox = QGroupBox("Управление") # Заголовок будет меняться
self.prefix_management_groupbox.setEnabled(False)
management_layout = QGridLayout(self.prefix_management_groupbox)
management_layout.setSpacing(5)
# --- Левая сторона: Кнопки ---
self.prefix_winetricks_button = QPushButton("Менеджер компонентов")
self.prefix_winetricks_button.clicked.connect(
lambda: self.open_winetricks_manager(prefix_name=self.current_managed_prefix_name))
self.prefix_winetricks_button.setToolTip(
"Установка компонентов, библиотек и шрифтов в префикс с помощью Winetricks.")
management_layout.addWidget(self.prefix_winetricks_button, 0, 0)
self.prefix_winecfg_button = QPushButton("Редактор настроек")
self.prefix_winecfg_button.clicked.connect(
lambda: self._run_wine_util('winecfg', prefix_name=self.current_managed_prefix_name))
self.prefix_winecfg_button.setToolTip(
"Запуск утилиты winecfg для настройки параметров Wine (версия Windows, диски, аудио и т.д.).")
management_layout.addWidget(self.prefix_winecfg_button, 0, 1)
self.prefix_regedit_button = QPushButton("Редактор реестра")
self.prefix_regedit_button.clicked.connect(
lambda: self._run_wine_util('regedit', prefix_name=self.current_managed_prefix_name))
self.prefix_regedit_button.setToolTip(
"Запуск редактора реестра Wine (regedit) для просмотра и изменения ключей реестра в префиксе.")
management_layout.addWidget(self.prefix_regedit_button, 1, 0)
self.prefix_uninstaller_button = QPushButton("Удаление программ")
self.prefix_uninstaller_button.clicked.connect(
lambda: self._run_wine_util('uninstaller', prefix_name=self.current_managed_prefix_name))
self.prefix_uninstaller_button.setToolTip(
"Запуск стандартного деинсталлятора Wine для удаления установленных в префикс Windows-программ.")
management_layout.addWidget(self.prefix_uninstaller_button, 1, 1)
self.prefix_cmd_button = QPushButton("Командная строка")
self.prefix_cmd_button.clicked.connect(lambda: self._run_wine_util('cmd', prefix_name=self.current_managed_prefix_name))
self.prefix_cmd_button.setToolTip("Запуск командной строки (cmd) в окружении выбранного префикса.")
management_layout.addWidget(self.prefix_cmd_button, 2, 0)
self.prefix_winefile_button = QPushButton("Файловый менеджер")
self.prefix_winefile_button.clicked.connect(
lambda: self._run_wine_util('winefile', prefix_name=self.current_managed_prefix_name))
self.prefix_winefile_button.setToolTip("Запуск файлового менеджера Wine (winefile) для просмотра файлов внутри префикса.")
management_layout.addWidget(self.prefix_winefile_button, 2, 1)
# --- Правая сторона: Информационный блок ---
self.prefix_info_display = QTextBrowser()
self.prefix_info_display.setReadOnly(True)
self.prefix_info_display.setFrameStyle(QFrame.StyledPanel)
management_layout.addWidget(self.prefix_info_display, 0, 2, 3, 1)
management_layout.setColumnStretch(0, 1)
management_layout.setColumnStretch(1, 1)
management_layout.setColumnStretch(2, 2)
container_layout.addWidget(self.prefix_management_groupbox)
layout.addWidget(self.management_container_groupbox)
layout.addStretch() layout.addStretch()
self.add_tab(self.prefix_tab, "Создать префикс") self.add_tab(self.prefix_tab, "Создать префикс")
@@ -1928,22 +1948,92 @@ class WineHelperGUI(QMainWindow):
self.prefix_name_edit.textChanged.connect(self.on_prefix_name_edited) self.prefix_name_edit.textChanged.connect(self.on_prefix_name_edited)
self.wine_version_edit.textChanged.connect(self.update_create_prefix_button_state) self.wine_version_edit.textChanged.connect(self.update_create_prefix_button_state)
def _load_state(self):
"""Загружает последнее состояние GUI из файла."""
if not os.path.exists(self.state_file):
return
try:
with open(self.state_file, 'r', encoding='utf-8') as f:
state = json.load(f)
loaded_prefixes = state.get('created_prefixes_info', {})
if not loaded_prefixes:
return
# Блокируем сигналы, чтобы избежать преждевременного срабатывания
self.created_prefix_selector.blockSignals(True)
self.created_prefix_selector.clear()
self.created_prefixes_info.clear()
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.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}")
def on_created_prefix_selected(self, index):
"""Обрабатывает выбор префикса из выпадающего списка."""
if index == -1:
self.current_managed_prefix_name = None
self._setup_prefix_management_panel(None)
else:
prefix_name = self.created_prefix_selector.itemText(index)
self.current_managed_prefix_name = prefix_name
self._setup_prefix_management_panel(prefix_name)
self._save_state()
def on_prefix_name_edited(self, text): def on_prefix_name_edited(self, text):
"""Сбрасывает состояние управления префиксом, когда пользователь вводит новое имя.""" """Сбрасывает состояние управления префиксом, когда пользователь вводит новое имя."""
if text and self.prefix_management_groupbox.isEnabled(): if text:
if self.created_prefix_selector.currentIndex() != -1:
self.created_prefix_selector.setCurrentIndex(-1)
def _setup_prefix_management_panel(self, prefix_name):
"""Настраивает панель управления префиксом на основе текущего состояния."""
if prefix_name and prefix_name in self.created_prefixes_info:
self.prefix_management_groupbox.setTitle(f"Управление «{prefix_name}»")
self.prefix_management_groupbox.setEnabled(True)
self.update_prefix_info_display(prefix_name)
else:
self.prefix_management_groupbox.setTitle("Управление")
self.prefix_management_groupbox.setEnabled(False) self.prefix_management_groupbox.setEnabled(False)
self.prefix_management_groupbox.setTitle("Управление префиксом")
self.last_created_prefix_name = None
self.last_created_prefix_info = None
self.prefix_info_display.clear() self.prefix_info_display.clear()
def update_prefix_info_display(self): def update_prefix_info_display(self, prefix_name):
"""Обновляет информационный блок для созданного префикса.""" """Обновляет информационный блок для созданного префикса."""
if not self.last_created_prefix_info: info = self.created_prefixes_info.get(prefix_name)
if not info:
self.prefix_info_display.clear() self.prefix_info_display.clear()
return return
info = self.last_created_prefix_info
html_content = f""" html_content = f"""
<p style="line-height: 1.3; font-size: 9pt;"> <p style="line-height: 1.3; font-size: 9pt;">
<b>Имя:</b> {html.escape(info['name'])}<br> <b>Имя:</b> {html.escape(info['name'])}<br>
@@ -2083,12 +2173,9 @@ class WineHelperGUI(QMainWindow):
if not self._show_license_agreement_dialog(): if not self._show_license_agreement_dialog():
return return
# Сбрасываем состояние управления предыдущим созданным префиксом # Сбрасываем выбор в выпадающем списке, чтобы панель управления скрылась на время создания
self.last_created_prefix_name = None if self.created_prefix_selector.count() > 0:
self.last_created_prefix_info = None self.created_prefix_selector.setCurrentIndex(-1)
self.prefix_info_display.clear()
self.prefix_management_groupbox.setEnabled(False)
self.prefix_management_groupbox.setTitle("Управление префиксом")
prefix_name = self.prefix_name_edit.text().strip() prefix_name = self.prefix_name_edit.text().strip()
@@ -2111,7 +2198,7 @@ class WineHelperGUI(QMainWindow):
wine_use_display = self.wine_version_edit.text() wine_use_display = self.wine_version_edit.text()
# Сохраняем информацию для отображения после создания # Сохраняем информацию для отображения после создания
self.last_created_prefix_info = { self.pending_prefix_info = {
'name': prefix_name, 'name': prefix_name,
'path': prefix_path, 'path': prefix_path,
'arch': "32-bit" if wine_arch == "win32" else "64-bit", 'arch': "32-bit" if wine_arch == "win32" else "64-bit",
@@ -2181,14 +2268,25 @@ class WineHelperGUI(QMainWindow):
self._handle_command_finished(exit_code, exit_status) self._handle_command_finished(exit_code, exit_status)
if exit_code == 0: if exit_code == 0:
self.last_created_prefix_name = prefix_name # Добавляем новый префикс в список и выбираем его
self.prefix_management_groupbox.setTitle(f"Управление префиксом «{prefix_name}»") if self.pending_prefix_info:
self.prefix_management_groupbox.setEnabled(True) self.created_prefixes_info[prefix_name] = self.pending_prefix_info
self.update_prefix_info_display() self.pending_prefix_info = None
if self.created_prefix_selector.findText(prefix_name) == -1:
self.created_prefix_selector.addItem(prefix_name)
self.created_prefix_selector.setCurrentText(prefix_name)
if not self.management_container_groupbox.isVisible():
self.management_container_groupbox.setVisible(True)
self._save_state()
self.prefix_name_edit.clear() self.prefix_name_edit.clear()
self.wine_version_edit.clear() self.wine_version_edit.clear()
QMessageBox.information(self, "Успех", QMessageBox.information(self, "Успех",
f"Префикс '{prefix_name}' успешно создан.\nТеперь вы можете управлять им с помощью кнопок ниже.") f"Префикс '{prefix_name}' успешно создан.\n"
"Теперь вы можете управлять им, выбрав его из выпадающего списка.")
def update_installed_apps(self): def update_installed_apps(self):
"""Обновляет список установленных приложений в виде кнопок""" """Обновляет список установленных приложений в виде кнопок"""