added the status of the stop app button

This commit is contained in:
Sergey Palcheh
2025-09-08 14:10:45 +06:00
parent 5571f74125
commit 3e91bcf241

View File

@@ -1275,6 +1275,7 @@ class WineHelperGUI(QMainWindow):
self.current_active_button = None self.current_active_button = None
self.installed_buttons = [] self.installed_buttons = []
self.install_tabs_data = {} self.install_tabs_data = {}
self.running_apps = {} # {desktop_path: QProcess}
self.current_selected_app = None self.current_selected_app = None
self.icon_animators = {} self.icon_animators = {}
self.previous_tab_index = 0 self.previous_tab_index = 0
@@ -1483,7 +1484,7 @@ class WineHelperGUI(QMainWindow):
# --- Верхний ряд кнопок --- # --- Верхний ряд кнопок ---
top_buttons_layout = QHBoxLayout() top_buttons_layout = QHBoxLayout()
self.run_button = QPushButton("Запустить") self.run_button = QPushButton("Запустить")
self.run_button.clicked.connect(self.run_installed_app) self.run_button.clicked.connect(self.toggle_run_stop_app)
top_buttons_layout.addWidget(self.run_button) top_buttons_layout.addWidget(self.run_button)
installed_action_layout.addLayout(top_buttons_layout) installed_action_layout.addLayout(top_buttons_layout)
@@ -2704,6 +2705,12 @@ class WineHelperGUI(QMainWindow):
self.current_selected_app['name'] = name self.current_selected_app['name'] = name
self.current_selected_app['exec'] = exec_cmd self.current_selected_app['exec'] = exec_cmd
# Состояния кнопки
if desktop_path in self.running_apps:
self.run_button.setText("Остановить")
else:
self.run_button.setText("Запустить")
# Показываем панель информации # Показываем панель информации
self.info_panel.setVisible(True) self.info_panel.setVisible(True)
@@ -2853,6 +2860,11 @@ class WineHelperGUI(QMainWindow):
def run_installed_app_with_debug(self): def run_installed_app_with_debug(self):
"""Запускает выбранное установленное приложение с созданием лога""" """Запускает выбранное установленное приложение с созданием лога"""
if self.current_selected_app and self.current_selected_app.get('desktop_path') in self.running_apps:
QMessageBox.information(self, "Приложение запущено",
"Приложение уже запущено. Остановите его, прежде чем запускать с отладкой.")
return
# Создаем кастомные кнопки # Создаем кастомные кнопки
yes_button = QPushButton("Да") yes_button = QPushButton("Да")
no_button = QPushButton("Нет") no_button = QPushButton("Нет")
@@ -2973,23 +2985,81 @@ class WineHelperGUI(QMainWindow):
QMessageBox.critical(self, "Ошибка запуска", QMessageBox.critical(self, "Ошибка запуска",
f"Не удалось запустить команду:\n{' '.join(command)}\n\nОшибка: {str(e)}") f"Не удалось запустить команду:\n{' '.join(command)}\n\nОшибка: {str(e)}")
def run_installed_app(self): def toggle_run_stop_app(self):
"""Запускает выбранное установленное приложение""" """Запускает или останавливает выбранное приложение."""
self._run_app_launcher(debug=False) if not self.current_selected_app or 'desktop_path' not in self.current_selected_app:
QMessageBox.warning(self, "Ошибка", "Сначала выберите приложение.")
return
desktop_path = self.current_selected_app['desktop_path']
# Если приложение запущено, останавливаем его
if desktop_path in self.running_apps:
process = self.running_apps.get(desktop_path)
if process and process.state() != QProcess.NotRunning:
prefix_name = self._get_prefix_name_for_selected_app()
if not prefix_name:
QMessageBox.warning(self, "Ошибка", "Не удалось определить префикс для остановки приложения.\n"
"Попробуйте закрыть приложение вручную.")
# Fallback to killing the wrapper script, though it might not work
process.terminate()
if not process.waitForFinished(1000):
process.kill()
return
prefix_path = os.path.join(Var.USER_WORK_PATH, "prefixes", prefix_name)
wine_executable = self._get_wine_executable_for_prefix(prefix_name)
wineserver_path = os.path.join(os.path.dirname(wine_executable), "wineserver")
if not shutil.which(wineserver_path):
wineserver_path = "wineserver"
kill_proc = QProcess(self)
kill_env = QProcessEnvironment.systemEnvironment()
kill_env.insert("WINEPREFIX", prefix_path)
kill_proc.setProcessEnvironment(kill_env)
print(f"Остановка приложений в префиксе '{prefix_name}'...")
kill_proc.start(wineserver_path, ["-k"])
kill_proc.waitForFinished(5000) # Даем до 5 секунд на выполнение.
else:
# Состояние не совпадает, убираем из словаря
print(f"Процесс для {desktop_path} уже не запущен, очистка.")
self._on_app_process_finished(desktop_path)
# Если приложение не запущено, запускаем его
else:
# Запускаем без отладки. Кнопка отладки отдельная.
self._run_app_launcher(debug=False)
def _on_app_process_finished(self, desktop_path):
"""Обрабатывает завершение процесса запущенного приложения."""
if desktop_path in self.running_apps:
process = self.running_apps.pop(desktop_path)
process.deleteLater() # Clean up the QProcess object
print(f"Процесс для {desktop_path} завершен.")
# Если текущее выбранное приложение - то, что только что завершилось, обновляем кнопку
if self.current_selected_app and self.current_selected_app.get('desktop_path') == desktop_path:
self.run_button.setText("Запустить")
else:
print(f"Предупреждение: получен сигнал finished для неизвестного процесса {desktop_path}")
def _run_app_launcher(self, debug=False): def _run_app_launcher(self, debug=False):
"""Внутренний метод для запуска приложения (с отладкой или без)""" """Внутренний метод для запуска приложения (с отладкой или без) с использованием QProcess."""
if not self.current_selected_app or 'exec' not in self.current_selected_app: if not self.current_selected_app or 'exec' not in self.current_selected_app:
QMessageBox.warning(self, "Ошибка", "Сначала выберите приложение.") QMessageBox.warning(self, "Ошибка", "Сначала выберите приложение.")
return return
desktop_path = self.current_selected_app['desktop_path']
command_str = self.current_selected_app['exec'] command_str = self.current_selected_app['exec']
try: if desktop_path in self.running_apps:
# Используем shlex для безопасного разбора командной строки print(f"Приложение {self.current_selected_app.get('name')} уже запущено.")
command_parts = shlex.split(command_str) return
# Удаляем параметры (%F и подобные) try:
command_parts = shlex.split(command_str)
clean_command = [part for part in command_parts if not part.startswith('%')] clean_command = [part for part in command_parts if not part.startswith('%')]
if debug: if debug:
@@ -3011,13 +3081,39 @@ class WineHelperGUI(QMainWindow):
QMessageBox.critical(self, "Ошибка", f"Не удалось модифицировать команду для отладки: {e}") QMessageBox.critical(self, "Ошибка", f"Не удалось модифицировать команду для отладки: {e}")
return return
# Удаление префикса process = QProcess(self)
env = QProcessEnvironment.systemEnvironment()
cmd_start_index = 0
if clean_command and clean_command[0] == 'env':
cmd_start_index = 1
while cmd_start_index < len(clean_command) and '=' in clean_command[cmd_start_index]:
key, value = clean_command[cmd_start_index].split('=', 1)
env.insert(key, value.strip('"\''))
cmd_start_index += 1
if cmd_start_index >= len(clean_command):
raise ValueError("Не найдена команда для выполнения в строке Exec.")
program = clean_command[cmd_start_index]
arguments = clean_command[cmd_start_index + 1:]
process.setProcessEnvironment(env)
process.finished.connect(lambda: self._on_app_process_finished(desktop_path))
try: try:
subprocess.Popen(clean_command) process.start(program, arguments)
print(f"Запущено: {' '.join(clean_command)}") if not process.waitForStarted(3000):
raise RuntimeError(f"Не удалось запустить процесс: {process.errorString()}")
self.running_apps[desktop_path] = process
self.run_button.setText("Остановить")
print(f"Запущено: {program} {' '.join(arguments)}")
except Exception as e: except Exception as e:
QMessageBox.critical(self, "Ошибка запуска", QMessageBox.critical(self, "Ошибка запуска",
f"Не удалось запустить команду:\n{' '.join(clean_command)}\n\nОшибка: {str(e)}") f"Не удалось запустить команду:\n{command_str}\n\nОшибка: {str(e)}")
if desktop_path in self.running_apps:
del self.running_apps[desktop_path]
except Exception as e: except Exception as e:
QMessageBox.critical(self, "Ошибка", QMessageBox.critical(self, "Ошибка",
f"Не удалось обработать команду запуска:\n{command_str}\n\nОшибка: {str(e)}") f"Не удалось обработать команду запуска:\n{command_str}\n\nОшибка: {str(e)}")