Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
10ca3b3c98 |
@@ -2743,36 +2743,18 @@ class WineHelperGUI(QMainWindow):
|
||||
QMessageBox.warning(self, "Ошибка", "Указан неверный путь к установочному файлу.")
|
||||
return
|
||||
|
||||
self.command_dialog = QDialog(self)
|
||||
self.command_dialog.setWindowTitle(f"Установка в префикс: {prefix_name}")
|
||||
self.command_dialog.setMinimumSize(750, 400)
|
||||
self.command_dialog.setModal(True)
|
||||
self.command_dialog.setWindowFlags(self.command_dialog.windowFlags() & ~Qt.WindowCloseButtonHint)
|
||||
|
||||
layout = QVBoxLayout()
|
||||
self.command_log_output = QTextEdit()
|
||||
self.command_log_output.setReadOnly(True)
|
||||
self.command_log_output.setFont(QFont('DejaVu Sans Mono', 10))
|
||||
layout.addWidget(self.command_log_output)
|
||||
|
||||
self.command_close_button = QPushButton("Закрыть")
|
||||
self.command_close_button.setEnabled(False)
|
||||
self.command_close_button.clicked.connect(self.command_dialog.close)
|
||||
layout.addWidget(self.command_close_button)
|
||||
self.command_dialog.setLayout(layout)
|
||||
|
||||
self.command_process = QProcess(self.command_dialog)
|
||||
self.command_process.setProcessChannelMode(QProcess.MergedChannels)
|
||||
self.command_process.readyReadStandardOutput.connect(self._handle_command_output)
|
||||
self.command_process.finished.connect(self._handle_prefix_install_finished)
|
||||
|
||||
# Окружение полностью настраивается скриптом winehelper
|
||||
self.command_process.setProcessEnvironment(QProcessEnvironment.systemEnvironment())
|
||||
|
||||
args = ["install-to-prefix", prefix_name, installer_path]
|
||||
self.command_log_output.append(f"Выполнение: {shlex.quote(self.winehelper_path)} {' '.join(shlex.quote(a) for a in args)}")
|
||||
self.command_process.start(self.winehelper_path, args)
|
||||
self.command_dialog.exec_()
|
||||
dialog, process, log_output, close_button = self._create_command_dialog(
|
||||
f"Установка в префикс: {prefix_name}",
|
||||
self.winehelper_path,
|
||||
["install-to-prefix", prefix_name, installer_path],
|
||||
finished_callback=self._handle_prefix_install_finished
|
||||
)
|
||||
# Сохраняем ссылки для обратной совместимости с существующим кодом
|
||||
self.command_dialog = dialog
|
||||
self.command_process = process
|
||||
self.command_log_output = log_output
|
||||
self.command_close_button = close_button
|
||||
dialog.exec_()
|
||||
|
||||
def _get_prefix_component_version(self, prefix_name, component_key):
|
||||
"""
|
||||
@@ -3035,41 +3017,22 @@ class WineHelperGUI(QMainWindow):
|
||||
|
||||
prefix_path = os.path.join(Var.USER_WORK_PATH, "prefixes", prefix_name)
|
||||
|
||||
self.command_dialog = QDialog(self)
|
||||
self.command_dialog.setWindowTitle("Обновление ассоциаций файлов")
|
||||
self.command_dialog.setMinimumSize(750, 400)
|
||||
self.command_dialog.setModal(True)
|
||||
self.command_dialog.setWindowFlags(self.command_dialog.windowFlags() & ~Qt.WindowCloseButtonHint)
|
||||
def on_finished(exit_code, exit_status):
|
||||
self._handle_component_install_finished(prefix_name, exit_code, exit_status)
|
||||
|
||||
layout = QVBoxLayout()
|
||||
self.command_log_output = QTextEdit()
|
||||
self.command_log_output.setReadOnly(True)
|
||||
self.command_log_output.setFont(QFont('DejaVu Sans Mono', 10))
|
||||
layout.addWidget(self.command_log_output)
|
||||
|
||||
self.command_close_button = QPushButton("Закрыть")
|
||||
self.command_close_button.setEnabled(False)
|
||||
self.command_close_button.clicked.connect(self.command_dialog.close)
|
||||
layout.addWidget(self.command_close_button)
|
||||
self.command_dialog.setLayout(layout)
|
||||
|
||||
self.command_process = QProcess(self.command_dialog)
|
||||
self.command_process.setProcessChannelMode(QProcess.MergedChannels)
|
||||
self.command_process.readyReadStandardOutput.connect(self._handle_command_output)
|
||||
self.command_process.finished.connect(
|
||||
lambda exit_code, exit_status: self._handle_component_install_finished(
|
||||
prefix_name, exit_code, exit_status))
|
||||
|
||||
env = QProcessEnvironment.systemEnvironment()
|
||||
env.insert("WINEPREFIX", prefix_path)
|
||||
# Переменная WH_XDG_OPEN теперь читается из измененного last.conf
|
||||
self.command_process.setProcessEnvironment(env)
|
||||
|
||||
# Вызываем init-prefix, который теперь прочитает правильное значение из last.conf
|
||||
args = ["init-prefix"]
|
||||
self.command_log_output.append(f"Выполнение: {shlex.quote(self.winehelper_path)} {' '.join(shlex.quote(a) for a in args)}")
|
||||
self.command_process.start(self.winehelper_path, args)
|
||||
self.command_dialog.exec_()
|
||||
dialog, process, log_output, close_button = self._create_command_dialog(
|
||||
"Обновление ассоциаций файлов",
|
||||
self.winehelper_path,
|
||||
["init-prefix"],
|
||||
env_vars={"WINEPREFIX": prefix_path},
|
||||
finished_callback=on_finished
|
||||
)
|
||||
# Сохраняем ссылки для обратной совместимости с существующим кодом
|
||||
self.command_dialog = dialog
|
||||
self.command_process = process
|
||||
self.command_log_output = log_output
|
||||
self.command_close_button = close_button
|
||||
dialog.exec_()
|
||||
|
||||
def create_launcher_for_prefix(self):
|
||||
"""
|
||||
@@ -3111,38 +3074,19 @@ class WineHelperGUI(QMainWindow):
|
||||
return # Пользователь отменил или ввел пустое имя
|
||||
|
||||
# 3. Вызываем winehelper.sh create-desktop
|
||||
self.command_dialog = QDialog(self)
|
||||
self.command_dialog.setWindowTitle(f"Создание ярлыка для: {app_name}")
|
||||
self.command_dialog.setMinimumSize(750, 400)
|
||||
self.command_dialog.setModal(True)
|
||||
self.command_dialog.setWindowFlags(self.command_dialog.windowFlags() & ~Qt.WindowCloseButtonHint)
|
||||
|
||||
layout = QVBoxLayout()
|
||||
self.command_log_output = QTextEdit()
|
||||
self.command_log_output.setReadOnly(True)
|
||||
self.command_log_output.setFont(QFont('DejaVu Sans Mono', 10))
|
||||
layout.addWidget(self.command_log_output)
|
||||
|
||||
self.command_close_button = QPushButton("Закрыть")
|
||||
self.command_close_button.setEnabled(False)
|
||||
self.command_close_button.clicked.connect(self.command_dialog.close)
|
||||
layout.addWidget(self.command_close_button)
|
||||
self.command_dialog.setLayout(layout)
|
||||
|
||||
self.command_process = QProcess(self.command_dialog)
|
||||
self.command_process.setProcessChannelMode(QProcess.MergedChannels)
|
||||
self.command_process.readyReadStandardOutput.connect(self._handle_command_output)
|
||||
self.command_process.finished.connect(self._handle_launcher_creation_finished)
|
||||
|
||||
env = QProcessEnvironment.systemEnvironment()
|
||||
env.insert("WINEPREFIX", prefix_path)
|
||||
self.command_process.setProcessEnvironment(env)
|
||||
|
||||
args = ["desktop", app_name, exe_path, "auto"]
|
||||
|
||||
self.command_log_output.append(f"Выполнение: {shlex.quote(self.winehelper_path)} {' '.join(shlex.quote(a) for a in args)}")
|
||||
self.command_process.start(self.winehelper_path, args)
|
||||
self.command_dialog.exec_()
|
||||
dialog, process, log_output, close_button = self._create_command_dialog(
|
||||
f"Создание ярлыка для: {app_name}",
|
||||
self.winehelper_path,
|
||||
["desktop", app_name, exe_path, "auto"],
|
||||
env_vars={"WINEPREFIX": prefix_path},
|
||||
finished_callback=self._handle_launcher_creation_finished
|
||||
)
|
||||
# Сохраняем ссылки для обратной совместимости с существующим кодом
|
||||
self.command_dialog = dialog
|
||||
self.command_process = process
|
||||
self.command_log_output = log_output
|
||||
self.command_close_button = close_button
|
||||
dialog.exec_()
|
||||
|
||||
def create_help_tab(self):
|
||||
"""Создает вкладку 'Справка' с подвкладками"""
|
||||
@@ -3439,16 +3383,26 @@ class WineHelperGUI(QMainWindow):
|
||||
|
||||
def _handle_prefix_install_finished(self, exit_code, exit_status):
|
||||
"""Обрабатывает завершение установки в префикс."""
|
||||
if exit_code == 0:
|
||||
self.command_log_output.append("\n=== Установка успешно завершена ===")
|
||||
self.create_launcher_button.setEnabled(True) # Активируем кнопку создания ярлыка
|
||||
else:
|
||||
self.command_log_output.append(f"\n=== Ошибка выполнения (код: {exit_code}) ===")
|
||||
# Используем старый API для обратной совместимости
|
||||
log_output = getattr(self, 'command_log_output', None)
|
||||
process = getattr(self, 'command_process', None)
|
||||
close_button = getattr(self, 'command_close_button', None)
|
||||
|
||||
if log_output:
|
||||
if exit_code == 0:
|
||||
log_output.append("\n=== Установка успешно завершена ===")
|
||||
self.create_launcher_button.setEnabled(True) # Активируем кнопку создания ярлыка
|
||||
else:
|
||||
log_output.append(f"\n=== Ошибка выполнения (код: {exit_code}) ===")
|
||||
|
||||
if process:
|
||||
process.deleteLater()
|
||||
if hasattr(self, 'command_process') and self.command_process == process:
|
||||
self.command_process = None
|
||||
|
||||
if close_button:
|
||||
close_button.setEnabled(True)
|
||||
|
||||
if self.command_process:
|
||||
self.command_process.deleteLater()
|
||||
self.command_process = None
|
||||
self.command_close_button.setEnabled(True)
|
||||
self.update_installed_apps()
|
||||
|
||||
def _set_active_button(self, button_widget):
|
||||
@@ -3609,37 +3563,29 @@ class WineHelperGUI(QMainWindow):
|
||||
|
||||
if msg_box.clickedButton() != yes_button:
|
||||
return # Отмена, если нажато "Нет" или крестик
|
||||
# Используем модальный диалог для отображения процесса резервного копирования (бэкап)
|
||||
self.command_dialog = QDialog(self)
|
||||
self.command_dialog.setWindowTitle(f"Резервное копирование: {prefix_name}")
|
||||
self.command_dialog.setMinimumSize(750, 400)
|
||||
self.command_dialog.setModal(True)
|
||||
self.command_dialog.setWindowFlags(self.command_dialog.windowFlags() & ~Qt.WindowCloseButtonHint)
|
||||
|
||||
layout = QVBoxLayout()
|
||||
self.command_log_output = QTextEdit()
|
||||
self.command_log_output.setReadOnly(True)
|
||||
self.command_log_output.setFont(QFont('DejaVu Sans Mono', 10))
|
||||
layout.addWidget(self.command_log_output)
|
||||
dialog, process, log, close_btn = self._create_command_dialog(
|
||||
f"Резервное копирование: {prefix_name}",
|
||||
self.winehelper_path,
|
||||
["backup-prefix", prefix_name]
|
||||
)
|
||||
# Сохраняем ссылки для обратной совместимости с существующим кодом
|
||||
self.command_dialog = dialog
|
||||
self.command_process = process
|
||||
self.command_log_output = log
|
||||
self.command_close_button = close_btn
|
||||
|
||||
self.command_close_button = QPushButton("Закрыть")
|
||||
self.command_close_button.setEnabled(False)
|
||||
self.command_close_button.clicked.connect(self.command_dialog.close)
|
||||
layout.addWidget(self.command_close_button)
|
||||
self.command_dialog.setLayout(layout)
|
||||
# Устанавливаем родителя, чтобы избежать утечек памяти
|
||||
self.command_process = QProcess(self.command_dialog)
|
||||
self.command_process.setProcessChannelMode(QProcess.MergedChannels)
|
||||
self.command_process.readyReadStandardOutput.connect(self._handle_command_output)
|
||||
self.command_process.finished.connect(self._handle_command_finished)
|
||||
self.command_process.finished.connect(self.update_open_log_dir_button_visibility)
|
||||
# Создаем callback после сохранения ссылок
|
||||
def on_finished(exit_code, exit_status):
|
||||
self._handle_command_finished(exit_code, exit_status, close_btn, process, log)
|
||||
if exit_code == 0:
|
||||
self.update_open_log_dir_button_visibility()
|
||||
|
||||
winehelper_path = self.winehelper_path
|
||||
args = ["backup-prefix", prefix_name]
|
||||
# Заменяем стандартный обработчик на наш
|
||||
process.finished.disconnect()
|
||||
process.finished.connect(on_finished)
|
||||
|
||||
self.command_log_output.append(f"Выполнение: {shlex.quote(winehelper_path)} {' '.join(shlex.quote(a) for a in args)}")
|
||||
self.command_process.start(winehelper_path, args)
|
||||
self.command_dialog.exec_()
|
||||
dialog.exec_()
|
||||
|
||||
def restore_prefix(self):
|
||||
"""Восстанавливает префикс из резервной копии."""
|
||||
@@ -3653,36 +3599,21 @@ class WineHelperGUI(QMainWindow):
|
||||
if not backup_path:
|
||||
return
|
||||
|
||||
# Используем модальный диалог для отображения процесса восстановления из бэкапа
|
||||
self.command_dialog = QDialog(self)
|
||||
self.command_dialog.setWindowTitle(f"Восстановление из: {os.path.basename(backup_path)}")
|
||||
self.command_dialog.setMinimumSize(600, 400)
|
||||
self.command_dialog.setModal(True)
|
||||
self.command_dialog.setWindowFlags(self.command_dialog.windowFlags() & ~Qt.WindowCloseButtonHint)
|
||||
def on_finished(exit_code, exit_status):
|
||||
self._handle_restore_finished(exit_code, exit_status)
|
||||
|
||||
layout = QVBoxLayout()
|
||||
self.command_log_output = QTextEdit()
|
||||
self.command_log_output.setReadOnly(True)
|
||||
self.command_log_output.setFont(QFont('DejaVu Sans Mono', 10))
|
||||
layout.addWidget(self.command_log_output)
|
||||
|
||||
self.command_close_button = QPushButton("Закрыть")
|
||||
self.command_close_button.setEnabled(False)
|
||||
self.command_close_button.clicked.connect(self.command_dialog.close)
|
||||
layout.addWidget(self.command_close_button)
|
||||
self.command_dialog.setLayout(layout)
|
||||
# Устанавливаем родителя, чтобы избежать утечек памяти
|
||||
self.command_process = QProcess(self.command_dialog)
|
||||
self.command_process.setProcessChannelMode(QProcess.MergedChannels)
|
||||
self.command_process.readyReadStandardOutput.connect(self._handle_command_output)
|
||||
self.command_process.finished.connect(self._handle_restore_finished)
|
||||
|
||||
winehelper_path = self.winehelper_path
|
||||
args = ["restore-prefix", backup_path]
|
||||
|
||||
self.command_log_output.append(f"Выполнение: {shlex.quote(winehelper_path)} {' '.join(shlex.quote(a) for a in args)}")
|
||||
self.command_process.start(winehelper_path, args)
|
||||
self.command_dialog.exec_()
|
||||
dialog, process, log_output, close_button = self._create_command_dialog(
|
||||
f"Восстановление из: {os.path.basename(backup_path)}",
|
||||
self.winehelper_path,
|
||||
["restore-prefix", backup_path],
|
||||
finished_callback=on_finished
|
||||
)
|
||||
# Сохраняем ссылки для обратной совместимости с существующим кодом
|
||||
self.command_dialog = dialog
|
||||
self.command_process = process
|
||||
self.command_log_output = log_output
|
||||
self.command_close_button = close_button
|
||||
dialog.exec_()
|
||||
|
||||
def run_installed_app_with_debug(self):
|
||||
"""Запускает выбранное установленное приложение с созданием лога"""
|
||||
@@ -4718,6 +4649,74 @@ class WineHelperGUI(QMainWindow):
|
||||
self.installation_cancelled = True
|
||||
self.install_process.terminate()
|
||||
|
||||
def _create_command_dialog(self, title, command, args, env_vars=None, finished_callback=None,
|
||||
min_width=750, min_height=400):
|
||||
"""
|
||||
Создает стандартный модальный диалог для выполнения команд winehelper.
|
||||
|
||||
Args:
|
||||
title: Заголовок диалога
|
||||
command: Путь к исполняемому файлу
|
||||
args: Список аргументов команды
|
||||
env_vars: Словарь дополнительных переменных окружения (опционально)
|
||||
finished_callback: Функция обратного вызова при завершении (exit_code, exit_status)
|
||||
min_width: Минимальная ширина диалога
|
||||
min_height: Минимальная высота диалога
|
||||
|
||||
Returns:
|
||||
Кортеж (dialog, process, log_output, close_button)
|
||||
"""
|
||||
dialog = QDialog(self)
|
||||
dialog.setWindowTitle(title)
|
||||
dialog.setMinimumSize(min_width, min_height)
|
||||
dialog.setModal(True)
|
||||
dialog.setWindowFlags(dialog.windowFlags() & ~Qt.WindowCloseButtonHint)
|
||||
|
||||
layout = QVBoxLayout()
|
||||
log_output = QTextEdit()
|
||||
log_output.setReadOnly(True)
|
||||
log_output.setFont(QFont('DejaVu Sans Mono', 10))
|
||||
layout.addWidget(log_output)
|
||||
|
||||
close_button = QPushButton("Закрыть")
|
||||
close_button.setEnabled(False)
|
||||
close_button.clicked.connect(dialog.close)
|
||||
layout.addWidget(close_button)
|
||||
dialog.setLayout(layout)
|
||||
|
||||
process = QProcess(dialog)
|
||||
process.setProcessChannelMode(QProcess.MergedChannels)
|
||||
process.readyReadStandardOutput.connect(
|
||||
lambda: self._append_command_output(process, log_output)
|
||||
)
|
||||
|
||||
if finished_callback:
|
||||
process.finished.connect(finished_callback)
|
||||
else:
|
||||
process.finished.connect(
|
||||
lambda exit_code, exit_status: self._handle_command_finished(
|
||||
exit_code, exit_status, close_button, process, log_output)
|
||||
)
|
||||
|
||||
env = QProcessEnvironment.systemEnvironment()
|
||||
if env_vars:
|
||||
for key, value in env_vars.items():
|
||||
env.insert(key, value)
|
||||
process.setProcessEnvironment(env)
|
||||
|
||||
log_output.append(f"Выполнение: {shlex.quote(command)} {' '.join(shlex.quote(a) for a in args)}")
|
||||
process.start(command, args)
|
||||
|
||||
return dialog, process, log_output, close_button
|
||||
|
||||
def _append_command_output(self, process, log_output):
|
||||
"""Добавляет вывод процесса в лог."""
|
||||
output_bytes = process.readAll()
|
||||
output = output_bytes.data().decode('utf-8', errors='ignore').strip()
|
||||
if output:
|
||||
log_output.append(output)
|
||||
QApplication.processEvents()
|
||||
|
||||
def _handle_command_output(self):
|
||||
"""Обрабатывает вывод для общих команд в модальном диалоге."""
|
||||
if hasattr(self, 'command_process') and self.command_process:
|
||||
@@ -4735,20 +4734,34 @@ class WineHelperGUI(QMainWindow):
|
||||
self.command_process.readyReadStandardOutput.connect(self._handle_command_output)
|
||||
self.command_process.finished.connect(self._handle_command_finished)
|
||||
self.command_process.start(self.winehelper_path, [command] + (args or []))
|
||||
def _handle_command_finished(self, exit_code, exit_status):
|
||||
def _handle_command_finished(self, exit_code, exit_status, close_button=None, process=None, log_output=None):
|
||||
"""Обрабатывает завершение для диалога команды"""
|
||||
if exit_code == 0:
|
||||
self.command_log_output.append(f"\n=== Команда успешно завершена ===")
|
||||
else:
|
||||
self.command_log_output.append(f"\n=== Ошибка выполнения (код: {exit_code}) ===")
|
||||
if self.command_process:
|
||||
self.command_process.deleteLater()
|
||||
self.command_process = None
|
||||
self.command_close_button.setEnabled(True)
|
||||
self.command_log_output.ensureCursorVisible()
|
||||
# Поддержка старого API для обратной совместимости
|
||||
if close_button is None:
|
||||
close_button = getattr(self, 'command_close_button', None)
|
||||
if process is None:
|
||||
process = getattr(self, 'command_process', None)
|
||||
if log_output is None:
|
||||
log_output = getattr(self, 'command_log_output', None)
|
||||
|
||||
if log_output:
|
||||
if exit_code == 0:
|
||||
log_output.append(f"\n=== Команда успешно завершена ===")
|
||||
else:
|
||||
log_output.append(f"\n=== Ошибка выполнения (код: {exit_code}) ===")
|
||||
log_output.ensureCursorVisible()
|
||||
|
||||
if process:
|
||||
process.deleteLater()
|
||||
if hasattr(self, 'command_process') and self.command_process == process:
|
||||
self.command_process = None
|
||||
|
||||
if close_button:
|
||||
close_button.setEnabled(True)
|
||||
|
||||
def _handle_launcher_creation_finished(self, exit_code, exit_status):
|
||||
"""Обрабатывает завершение создания ярлыка."""
|
||||
# Используем старый API для обратной совместимости
|
||||
self._handle_command_finished(exit_code, exit_status)
|
||||
if exit_code == 0:
|
||||
self.update_installed_apps()
|
||||
@@ -4760,17 +4773,27 @@ class WineHelperGUI(QMainWindow):
|
||||
|
||||
def _handle_restore_finished(self, exit_code, exit_status):
|
||||
"""Обрабатывает завершение для диалога команды восстановления."""
|
||||
if exit_code == 0:
|
||||
self.command_log_output.append(f"\n=== Восстановление успешно завершено ===")
|
||||
self.update_installed_apps()
|
||||
self._load_created_prefixes()
|
||||
self.filter_installed_buttons()
|
||||
else:
|
||||
self.command_log_output.append(f"\n=== Ошибка выполнения (код: {exit_code}) ===")
|
||||
if self.command_process:
|
||||
self.command_process.deleteLater()
|
||||
self.command_process = None
|
||||
self.command_close_button.setEnabled(True)
|
||||
# Используем старый API для обратной совместимости
|
||||
log_output = getattr(self, 'command_log_output', None)
|
||||
if log_output:
|
||||
if exit_code == 0:
|
||||
log_output.append(f"\n=== Восстановление успешно завершено ===")
|
||||
self.update_installed_apps()
|
||||
self._load_created_prefixes()
|
||||
self.filter_installed_buttons()
|
||||
else:
|
||||
log_output.append(f"\n=== Ошибка выполнения (код: {exit_code}) ===")
|
||||
|
||||
close_button = getattr(self, 'command_close_button', None)
|
||||
process = getattr(self, 'command_process', None)
|
||||
|
||||
if process:
|
||||
process.deleteLater()
|
||||
if hasattr(self, 'command_process') and self.command_process == process:
|
||||
self.command_process = None
|
||||
|
||||
if close_button:
|
||||
close_button.setEnabled(True)
|
||||
|
||||
def cleanup_process(self):
|
||||
"""Очищает ресурсы процесса, принудительно завершая его, если он активен."""
|
||||
|
||||
Reference in New Issue
Block a user