added the status of the stop app button
This commit is contained in:
		| @@ -1275,6 +1275,7 @@ class WineHelperGUI(QMainWindow): | ||||
|         self.current_active_button = None | ||||
|         self.installed_buttons = [] | ||||
|         self.install_tabs_data = {} | ||||
|         self.running_apps = {}  # {desktop_path: QProcess} | ||||
|         self.current_selected_app = None | ||||
|         self.icon_animators = {} | ||||
|         self.previous_tab_index = 0 | ||||
| @@ -1483,7 +1484,7 @@ class WineHelperGUI(QMainWindow): | ||||
|         # --- Верхний ряд кнопок --- | ||||
|         top_buttons_layout = QHBoxLayout() | ||||
|         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) | ||||
|         installed_action_layout.addLayout(top_buttons_layout) | ||||
|  | ||||
| @@ -2704,6 +2705,12 @@ class WineHelperGUI(QMainWindow): | ||||
|                 self.current_selected_app['name'] = name | ||||
|                 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) | ||||
|  | ||||
| @@ -2853,6 +2860,11 @@ class WineHelperGUI(QMainWindow): | ||||
|  | ||||
|     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("Да") | ||||
|         no_button = QPushButton("Нет") | ||||
| @@ -2973,23 +2985,81 @@ class WineHelperGUI(QMainWindow): | ||||
|             QMessageBox.critical(self, "Ошибка запуска", | ||||
|                                  f"Не удалось запустить команду:\n{' '.join(command)}\n\nОшибка: {str(e)}") | ||||
|  | ||||
|     def run_installed_app(self): | ||||
|         """Запускает выбранное установленное приложение""" | ||||
|     def toggle_run_stop_app(self): | ||||
|         """Запускает или останавливает выбранное приложение.""" | ||||
|         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): | ||||
|         """Внутренний метод для запуска приложения (с отладкой или без)""" | ||||
|         """Внутренний метод для запуска приложения (с отладкой или без) с использованием QProcess.""" | ||||
|         if not self.current_selected_app or 'exec' not in self.current_selected_app: | ||||
|             QMessageBox.warning(self, "Ошибка", "Сначала выберите приложение.") | ||||
|             return | ||||
|  | ||||
|         desktop_path = self.current_selected_app['desktop_path'] | ||||
|         command_str = self.current_selected_app['exec'] | ||||
|  | ||||
|         try: | ||||
|             # Используем shlex для безопасного разбора командной строки | ||||
|             command_parts = shlex.split(command_str) | ||||
|         if desktop_path in self.running_apps: | ||||
|             print(f"Приложение {self.current_selected_app.get('name')} уже запущено.") | ||||
|             return | ||||
|  | ||||
|             # Удаляем параметры (%F и подобные) | ||||
|         try: | ||||
|             command_parts = shlex.split(command_str) | ||||
|             clean_command = [part for part in command_parts if not part.startswith('%')] | ||||
|  | ||||
|             if debug: | ||||
| @@ -3011,13 +3081,39 @@ class WineHelperGUI(QMainWindow): | ||||
|                     QMessageBox.critical(self, "Ошибка", f"Не удалось модифицировать команду для отладки: {e}") | ||||
|                     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: | ||||
|                 subprocess.Popen(clean_command) | ||||
|                 print(f"Запущено: {' '.join(clean_command)}") | ||||
|                 process.start(program, arguments) | ||||
|                 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: | ||||
|                 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: | ||||
|             QMessageBox.critical(self, "Ошибка", | ||||
|                                  f"Не удалось обработать команду запуска:\n{command_str}\n\nОшибка: {str(e)}") | ||||
|   | ||||
		Reference in New Issue
	
	Block a user