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.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)}") | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user