forked from CastroFidel/winehelper
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