From 4a758f3b3c3bbbbaa48d511943228b76964eb791 Mon Sep 17 00:00:00 2001 From: Boris Yumankulov Date: Mon, 27 Oct 2025 23:13:48 +0500 Subject: [PATCH] chore: use flatpak run for flatpak not start.sh Signed-off-by: Boris Yumankulov --- portprotonqt/app.py | 10 ++---- portprotonqt/config_utils.py | 66 +++++++++++++++++++++++++--------- portprotonqt/main_window.py | 53 +++++++++------------------ portprotonqt/portproton_api.py | 2 +- 4 files changed, 71 insertions(+), 60 deletions(-) diff --git a/portprotonqt/app.py b/portprotonqt/app.py index 5be0984..f4d0e8f 100644 --- a/portprotonqt/app.py +++ b/portprotonqt/app.py @@ -19,7 +19,6 @@ __app_id__ = "ru.linux_gaming.PortProtonQt" __app_name__ = "PortProtonQt" __app_version__ = "0.1.8" - def get_version(): try: commit = subprocess.check_output( @@ -30,18 +29,16 @@ def get_version(): except (subprocess.CalledProcessError, FileNotFoundError, OSError): return __app_version__ - def main(): os.environ["PW_CLI"] = "1" os.environ["PROCESS_LOG"] = "1" os.environ["START_FROM_STEAM"] = "1" - portproton_path = get_portproton_location() - if portproton_path is None: + portproton_path, start_sh = get_portproton_location() + if portproton_path is None or start_sh is None: return - script_path = os.path.join(portproton_path, "data", "scripts", "start.sh") - subprocess.run([script_path, "cli", "--initial"]) + subprocess.run(start_sh + ["cli", "--initial"]) app = QApplication(sys.argv) app.setWindowIcon(QIcon.fromTheme(__app_id__)) @@ -161,6 +158,5 @@ def main(): sys.exit(app.exec()) - if __name__ == "__main__": main() diff --git a/portprotonqt/config_utils.py b/portprotonqt/config_utils.py index b424289..f922856 100644 --- a/portprotonqt/config_utils.py +++ b/portprotonqt/config_utils.py @@ -1,11 +1,13 @@ import os import configparser import shutil +import subprocess from portprotonqt.logger import get_logger logger = get_logger(__name__) _portproton_location = None +_portproton_start_sh = None # Paths to configuration files CONFIG_FILE = os.path.join( @@ -101,33 +103,65 @@ def read_file_content(file_path): return f.read().strip() def get_portproton_location(): - """Returns the path to the PortProton directory. + """Returns the path to the PortProton directory and start.sh command list. + Checks the cached path first. If not set, reads from PORTPROTON_CONFIG_FILE. - If the path is invalid, uses the default directory. + If the path is invalid, uses the default flatpak directory. + If Flatpak package ru.linux_gaming.PortProton is installed, returns the Flatpak run command list. """ - global _portproton_location - if _portproton_location is not None: - return _portproton_location + global _portproton_location, _portproton_start_sh + + if '_portproton_location' in globals() and _portproton_location is not None: + return _portproton_location, _portproton_start_sh + + location = None if os.path.isfile(PORTPROTON_CONFIG_FILE): try: location = read_file_content(PORTPROTON_CONFIG_FILE).strip() if location and os.path.isdir(location): - _portproton_location = location logger.info(f"PortProton path from configuration: {location}") - return _portproton_location - logger.warning(f"Invalid PortProton path in configuration: {location}, using default path") + else: + logger.warning(f"Invalid PortProton path in configuration: {location}, using defaults") + location = None except (OSError, PermissionError) as e: - logger.warning(f"Failed to read PortProton configuration file: {e}, using default path") + logger.warning(f"Failed to read PortProton configuration file: {e}") + location = None - default_dir = os.path.join(os.path.expanduser("~"), ".var", "app", "ru.linux_gaming.PortProton") - if os.path.isdir(default_dir): - _portproton_location = default_dir - logger.info(f"Using flatpak PortProton directory: {default_dir}") - return _portproton_location + default_flatpak_dir = os.path.join(os.path.expanduser("~"), ".var", "app", "ru.linux_gaming.PortProton") + is_flatpak_installed = False + try: + result = subprocess.run( + ["flatpak", "list"], + capture_output=True, + text=True, + check=False + ) + if "ru.linux_gaming.PortProton" in result.stdout: + is_flatpak_installed = True + except Exception: + pass - logger.warning("PortProton configuration and flatpak directory not found") - return None + if is_flatpak_installed: + _portproton_location = default_flatpak_dir if os.path.isdir(default_flatpak_dir) else None + _portproton_start_sh = ["flatpak", "run", "ru.linux_gaming.PortProton"] + logger.info("Detected Flatpak installation: using 'flatpak run ru.linux_gaming.PortProton'") + elif location: + _portproton_location = location + start_sh_path = os.path.join(location, "data", "scripts", "start.sh") + _portproton_start_sh = [start_sh_path] if os.path.exists(start_sh_path) else None + logger.info(f"Using PortProton installation from config path: {_portproton_location}") + elif os.path.isdir(default_flatpak_dir): + _portproton_location = default_flatpak_dir + start_sh_path = os.path.join(default_flatpak_dir, "data", "scripts", "start.sh") + _portproton_start_sh = [start_sh_path] if os.path.exists(start_sh_path) else None + logger.info(f"Using Flatpak PortProton directory: {_portproton_location}") + else: + logger.warning("PortProton configuration and Flatpak directory not found") + _portproton_location = None + _portproton_start_sh = None + + return _portproton_location, _portproton_start_sh def parse_desktop_entry(file_path): """Reads and parses a .desktop file using configparser. diff --git a/portprotonqt/main_window.py b/portprotonqt/main_window.py index 7608fa3..ad9f6c4 100644 --- a/portprotonqt/main_window.py +++ b/portprotonqt/main_window.py @@ -73,7 +73,7 @@ class MainWindow(QMainWindow): self.game_processes = [] self.target_exe = None self.current_running_button = None - self.portproton_location = get_portproton_location() + self.portproton_location, self.start_sh = get_portproton_location() self.game_library_manager = GameLibraryManager(self, self.theme, None) @@ -458,11 +458,11 @@ class MainWindow(QMainWindow): self.current_install_script = script_name self.seen_progress = False self.current_percent = 0.0 - start_sh = os.path.join(self.portproton_location or "", "data", "scripts", "start.sh") if self.portproton_location else "" - if not os.path.exists(start_sh): + start_sh = self.start_sh + if not start_sh: self.installing = False return - cmd = [start_sh, "cli", "--autoinstall", script_name] + cmd = start_sh + ["cli", "--autoinstall", script_name] self.install_process = QProcess(self) self.install_process.finished.connect(self.on_install_finished) self.install_process.errorOccurred.connect(self.on_install_error) @@ -1424,12 +1424,10 @@ class MainWindow(QMainWindow): prefix = self.prefixCombo.currentText() if not wine or not prefix: return - if not self.portproton_location: + if not self.portproton_location or not self.start_sh: return - start_sh = os.path.join(self.portproton_location, "data", "scripts", "start.sh") - if not os.path.exists(start_sh): - return - cmd = [start_sh, "cli", cli_arg, wine, prefix] + start_sh = self.start_sh + cmd = start_sh + ["cli", cli_arg, wine, prefix] # Показываем прогресс-бар перед запуском self.wine_progress_bar.setVisible(True) @@ -1514,7 +1512,7 @@ class MainWindow(QMainWindow): if not selected_prefix or not selected_wine: return - if not self.portproton_location: + if not self.portproton_location or not self.start_sh: return reply = QMessageBox.question( @@ -1527,10 +1525,7 @@ class MainWindow(QMainWindow): if reply != QMessageBox.StandardButton.Yes: return - start_sh = os.path.join(self.portproton_location, "data", "scripts", "start.sh") - if not os.path.exists(start_sh): - QMessageBox.warning(self, _("Error"), _("Missing start.sh script.")) - return + start_sh = self.start_sh self.wine_progress_bar.setVisible(True) self.update_status_message.emit(_("Clearing prefix..."), 0) @@ -1538,7 +1533,7 @@ class MainWindow(QMainWindow): self.clear_process = QProcess(self) self.clear_process.finished.connect(lambda exitCode, exitStatus: self._on_clear_prefix_finished(exitCode)) self.clear_process.errorOccurred.connect(lambda error: self._on_clear_prefix_error(error)) - cmd = [start_sh, "cli", "--clear_pfx", selected_wine, selected_prefix] + cmd = start_sh + ["cli", "--clear_pfx", selected_wine, selected_prefix] self.clear_process.start(cmd[0], cmd[1:]) if not self.clear_process.waitForStarted(5000): @@ -1570,14 +1565,12 @@ class MainWindow(QMainWindow): def _perform_backup(self, backup_dir, prefix_name): os.makedirs(backup_dir, exist_ok=True) - if not self.portproton_location: - return - start_sh = os.path.join(self.portproton_location, "data", "scripts", "start.sh") - if not os.path.exists(start_sh): + if not self.portproton_location or not self.start_sh: return + start_sh = self.start_sh self.backup_process = QProcess(self) self.backup_process.finished.connect(lambda exitCode, exitStatus: self._on_backup_finished(exitCode)) - cmd = [start_sh, "--backup-prefix", prefix_name, backup_dir] + cmd = start_sh + ["--backup-prefix", prefix_name, backup_dir] self.backup_process.start(cmd[0], cmd[1:]) if not self.backup_process.waitForStarted(): QMessageBox.warning(self, _("Error"), _("Failed to start backup process.")) @@ -1590,14 +1583,12 @@ class MainWindow(QMainWindow): def _perform_restore(self, file_path): if not file_path or not os.path.exists(file_path): return - if not self.portproton_location: - return - start_sh = os.path.join(self.portproton_location, "data", "scripts", "start.sh") - if not os.path.exists(start_sh): + if not self.portproton_location or not self.start_sh: return + start_sh = self.start_sh self.restore_process = QProcess(self) self.restore_process.finished.connect(lambda exitCode, exitStatus: self._on_restore_finished(exitCode)) - cmd = [start_sh, "--restore-prefix", file_path] + cmd = start_sh + ["--restore-prefix", file_path] self.restore_process.start(cmd[0], cmd[1:]) if not self.restore_process.waitForStarted(): QMessageBox.warning(self, _("Error"), _("Failed to start restore process.")) @@ -2890,10 +2881,7 @@ class MainWindow(QMainWindow): env_vars = os.environ.copy() env_vars['LEGENDARY_CONFIG_PATH'] = self.legendary_config_path - wrapper = "flatpak run ru.linux_gaming.PortProton" - if self.portproton_location is not None and ".var" not in self.portproton_location: - start_sh = os.path.join(self.portproton_location, "data", "scripts", "start.sh") - wrapper = start_sh + wrapper = self.start_sh or "" cmd = [wrapper, game_exe] @@ -2987,13 +2975,6 @@ class MainWindow(QMainWindow): exe_name = os.path.splitext(current_exe)[0] env_vars = os.environ.copy() - if entry_exec_split[0] == "env" and len(entry_exec_split) > 1 and 'data/scripts/start.sh' in entry_exec_split[1]: - env_vars['START_FROM_STEAM'] = '1' - env_vars['PROCESS_LOG'] = '1' - elif entry_exec_split[0] == "flatpak": - env_vars['START_FROM_STEAM'] = '1' - env_vars['PROCESS_LOG'] = '1' - # Запускаем игру try: process = subprocess.Popen(entry_exec_split, env=env_vars, shell=False, preexec_fn=os.setsid) diff --git a/portprotonqt/portproton_api.py b/portprotonqt/portproton_api.py index efbb8da..8937302 100644 --- a/portprotonqt/portproton_api.py +++ b/portprotonqt/portproton_api.py @@ -58,7 +58,7 @@ class PortProtonAPI: self.xdg_data_home = os.getenv("XDG_DATA_HOME", os.path.join(os.path.expanduser("~"), ".local", "share")) self.custom_data_dir = os.path.join(self.xdg_data_home, "PortProtonQt", "custom_data") os.makedirs(self.custom_data_dir, exist_ok=True) - self.portproton_location = get_portproton_location() + self.portproton_location, self.portproton_start_sh = get_portproton_location() self.repo_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) self.builtin_custom_folder = os.path.join(self.repo_root, "custom_data") self._topics_data = None