fix: QMessageBox on context menu
Signed-off-by: Boris Yumankulov <boria138@altlinux.org>
This commit is contained in:
		| @@ -12,7 +12,7 @@ from PySide6.QtCore import QUrl, QPoint, QObject, Signal, Qt | ||||
| from PySide6.QtGui import QDesktopServices | ||||
| from portprotonqt.config_utils import parse_desktop_entry, read_favorites, save_favorites | ||||
| from portprotonqt.localization import _ | ||||
| from portprotonqt.steam_api import is_game_in_steam, add_to_steam, remove_from_steam | ||||
| from portprotonqt.steam_api import is_game_in_steam, add_to_steam, remove_from_steam, get_steam_home, get_last_steam_user, convert_steam_id | ||||
| from portprotonqt.dialogs import AddGameDialog | ||||
| from portprotonqt.egs_api import add_egs_to_steam, get_egs_executable | ||||
| import vdf | ||||
| @@ -23,6 +23,7 @@ class ContextMenuSignals(QObject): | ||||
|     """Signals for thread-safe UI updates from worker threads.""" | ||||
|     show_status_message = Signal(str, int) | ||||
|     show_warning_dialog = Signal(str, str) | ||||
|     show_info_dialog = Signal(str, str) | ||||
|  | ||||
| class ContextMenuManager: | ||||
|     """Manages context menu actions for game management in PortProtonQt.""" | ||||
| @@ -65,12 +66,21 @@ class ContextMenuManager: | ||||
|             self._show_warning_dialog, | ||||
|             Qt.ConnectionType.QueuedConnection | ||||
|         ) | ||||
|         self.signals.show_info_dialog.connect( | ||||
|             self._show_info_dialog, | ||||
|             Qt.ConnectionType.QueuedConnection | ||||
|         ) | ||||
|  | ||||
|     def _show_warning_dialog(self, title: str, message: str): | ||||
|         """Show a warning dialog in the main thread.""" | ||||
|         logger.debug("Showing warning dialog: %s - %s", title, message) | ||||
|         QMessageBox.warning(self.parent, title, message) | ||||
|  | ||||
|     def _show_info_dialog(self, title: str, message: str): | ||||
|         """Show an info dialog in the main thread.""" | ||||
|         logger.debug("Showing info dialog: %s - %s", title, message) | ||||
|         QMessageBox.information(self.parent, title, message) | ||||
|  | ||||
|     def _is_egs_game_installed(self, app_name: str) -> bool: | ||||
|         """ | ||||
|         Check if an EGS game is installed by reading installed.json. | ||||
| @@ -123,10 +133,6 @@ class ContextMenuManager: | ||||
|             ) | ||||
|             # Show other actions only if the game is installed | ||||
|             if self._is_egs_game_installed(game_card.appid): | ||||
|                 uninstall_action = menu.addAction(_("Uninstall Game")) | ||||
|                 uninstall_action.triggered.connect( | ||||
|                     lambda: self.uninstall_egs_game(game_card.name, game_card.appid) | ||||
|                 ) | ||||
|                 is_in_steam = is_game_in_steam(game_card.name) | ||||
|                 if is_in_steam: | ||||
|                     remove_steam_action = menu.addAction(_("Remove from Steam")) | ||||
| @@ -227,23 +233,22 @@ class ContextMenuManager: | ||||
|             return | ||||
|  | ||||
|         if not os.path.exists(self.legendary_path): | ||||
|             self._show_warning_dialog(_("Error"), _("Legendary executable not found at {0}").format(self.legendary_path)) | ||||
|             self.signals.show_warning_dialog.emit( | ||||
|                 _("Error"), _("Legendary executable not found at {0}").format(self.legendary_path) | ||||
|             ) | ||||
|             return | ||||
|  | ||||
|         def on_add_to_steam_result(result: tuple[bool, str]): | ||||
|             success, message = result | ||||
|             if success: | ||||
|                 self.signals.show_status_message.emit( | ||||
|                     _("The game was added successfully. Please restart Steam for changes to take effect."), 5000 | ||||
|                 self.signals.show_info_dialog.emit( | ||||
|                     _("Success"), | ||||
|                     _("'{0}' was added to Steam. Please restart Steam for changes to take effect.").format(game_name) | ||||
|                 ) | ||||
|             else: | ||||
|                 self.signals.show_warning_dialog.emit(_("Error"), message) | ||||
|  | ||||
|         if self.parent.statusBar(): | ||||
|             self.parent.statusBar().showMessage(_("Adding '{0}' to Steam...").format(game_name), 0) | ||||
|             logger.debug("Direct status message: Adding '%s' to Steam", game_name) | ||||
|         else: | ||||
|             logger.warning("Status bar not available when adding '%s' to Steam", game_name) | ||||
|         logger.debug("Adding '%s' to Steam", game_name) | ||||
|         add_egs_to_steam(app_name, game_name, self.legendary_path, on_add_to_steam_result) | ||||
|  | ||||
|     def open_egs_game_folder(self, app_name: str): | ||||
| @@ -258,7 +263,7 @@ class ContextMenuManager: | ||||
|  | ||||
|         exe_path = get_egs_executable(app_name, self.legendary_config_path) | ||||
|         if not exe_path or not os.path.exists(exe_path): | ||||
|             self._show_warning_dialog( | ||||
|             self.signals.show_warning_dialog.emit( | ||||
|                 _("Error"), | ||||
|                 _("Executable file not found for game: {0}").format(app_name) | ||||
|             ) | ||||
| @@ -275,7 +280,7 @@ class ContextMenuManager: | ||||
|             else: | ||||
|                 logger.warning("Status bar not available when opening folder for '%s'", app_name) | ||||
|         except Exception as e: | ||||
|             self._show_warning_dialog( | ||||
|             self.signals.show_warning_dialog.emit( | ||||
|                 _("Error"), | ||||
|                 _("Failed to open game folder: {0}").format(str(e)) | ||||
|             ) | ||||
| @@ -305,7 +310,7 @@ class ContextMenuManager: | ||||
|             return | ||||
|  | ||||
|         if not os.path.exists(self.legendary_path): | ||||
|             self._show_warning_dialog( | ||||
|             self.signals.show_warning_dialog.emit( | ||||
|                 _("Error"), | ||||
|                 _("Legendary executable not found at {0}").format(self.legendary_path) | ||||
|             ) | ||||
| @@ -329,81 +334,6 @@ class ContextMenuManager: | ||||
|             logger.warning("Status bar not available when importing '%s'", game_name) | ||||
|         threading.Thread(target=run_import, daemon=True).start() | ||||
|  | ||||
|     def uninstall_egs_game(self, game_name: str, app_name: str): | ||||
|         """ | ||||
|         Uninstalls an Epic Games Store game using Legendary asynchronously. | ||||
|  | ||||
|         Args: | ||||
|             game_name: The display name of the game. | ||||
|             app_name: The Legendary app_name (unique identifier for the game). | ||||
|         """ | ||||
|         if not self._check_portproton(): | ||||
|             return | ||||
|  | ||||
|         if not os.path.exists(self.legendary_path): | ||||
|             self._show_warning_dialog( | ||||
|                 _("Error"), | ||||
|                 _("Legendary executable not found at {0}").format(self.legendary_path) | ||||
|             ) | ||||
|             return | ||||
|  | ||||
|         reply = QMessageBox.question( | ||||
|             self.parent, | ||||
|             _("Confirm Uninstallation"), | ||||
|             _("Are you sure you want to uninstall '{0}'? This will remove the game files.").format(game_name), | ||||
|             QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, | ||||
|             QMessageBox.StandardButton.No | ||||
|         ) | ||||
|         if reply != QMessageBox.StandardButton.Yes: | ||||
|             return | ||||
|  | ||||
|         def run_uninstall(): | ||||
|             cmd = [self.legendary_path, "uninstall", app_name, "--skip-uninstaller"] | ||||
|             try: | ||||
|                 subprocess.run( | ||||
|                     cmd, | ||||
|                     capture_output=True, | ||||
|                     text=True, | ||||
|                     check=True, | ||||
|                     env={"LEGENDARY_CONFIG_PATH": self.legendary_config_path} | ||||
|                 ) | ||||
|                 self.signals.show_status_message.emit( | ||||
|                     _("Successfully uninstalled '{0}'").format(game_name), 3000 | ||||
|                 ) | ||||
|             except subprocess.CalledProcessError as e: | ||||
|                 self.signals.show_status_message.emit( | ||||
|                     _("Failed to uninstall '{0}'").format(game_name), 3000 | ||||
|                 ) | ||||
|                 self.signals.show_warning_dialog.emit( | ||||
|                     _("Error"), | ||||
|                     _("Failed to uninstall '{0}': {1}").format(game_name, e.stderr) | ||||
|                 ) | ||||
|             except FileNotFoundError: | ||||
|                 self.signals.show_status_message.emit( | ||||
|                     _("Legendary executable not found"), 3000 | ||||
|                 ) | ||||
|                 self.signals.show_warning_dialog.emit( | ||||
|                     _("Error"), | ||||
|                     _("Legendary executable not found") | ||||
|                 ) | ||||
|             except Exception as e: | ||||
|                 self.signals.show_status_message.emit( | ||||
|                     _("Unexpected error during uninstall"), 3000 | ||||
|                 ) | ||||
|                 self.signals.show_warning_dialog.emit( | ||||
|                     _("Error"), | ||||
|                     _("Unexpected error during uninstall: {0}").format(str(e)) | ||||
|                 ) | ||||
|  | ||||
|         if self.parent.statusBar(): | ||||
|             self.parent.statusBar().showMessage( | ||||
|                 _("Uninstalling '{0}'...").format(game_name), 0 | ||||
|             ) | ||||
|             logger.debug("Direct status message: Uninstalling '%s'", game_name) | ||||
|         else: | ||||
|             logger.warning("Status bar not available when uninstalling '%s'", game_name) | ||||
|         threading.Thread(target=run_uninstall, daemon=True).start() | ||||
|  | ||||
|     def toggle_favorite(self, game_card, add: bool): | ||||
|         """ | ||||
|         Toggle the favorite status of a game and update its icon. | ||||
| @@ -439,7 +369,7 @@ class ContextMenuManager: | ||||
|     def _check_portproton(self): | ||||
|         """Check if PortProton is available.""" | ||||
|         if self.portproton_location is None: | ||||
|             self._show_warning_dialog( | ||||
|             self.signals.show_warning_dialog.emit( | ||||
|                 _("Error"), | ||||
|                 _("PortProton is not found.") | ||||
|             ) | ||||
| @@ -474,7 +404,7 @@ class ContextMenuManager: | ||||
|             return False | ||||
|  | ||||
|         if not os.path.exists(self.legendary_path): | ||||
|             self._show_warning_dialog( | ||||
|             self.signals.show_warning_dialog.emit( | ||||
|                 _("Error"), | ||||
|                 _("Legendary executable not found at {0}").format(self.legendary_path) | ||||
|             ) | ||||
| @@ -486,7 +416,7 @@ class ContextMenuManager: | ||||
|         if self.portproton_location and ".var" not in self.portproton_location: | ||||
|             wrapper = start_sh_path | ||||
|             if not os.path.exists(start_sh_path): | ||||
|                 self._show_warning_dialog( | ||||
|                 self.signals.show_warning_dialog.emit( | ||||
|                     _("Error"), | ||||
|                     _("start.sh not found at {0}").format(start_sh_path) | ||||
|                 ) | ||||
| @@ -509,10 +439,10 @@ class ContextMenuManager: | ||||
|         desktop_entry = f"""[Desktop Entry] | ||||
| Type=Application | ||||
| Name={game_name} | ||||
| Exec="{self.legendary_path}" launch {app_name} --no-wine --wrapper "env START_FROM_STEAM=1 {wrapper}" "$@" | ||||
| Exec="{self.legendary_path}" launch {app_name} --no-wine --wrapper "env START_FROM_STEAM=1 {wrapper}" | ||||
| Icon={icon_path} | ||||
| Terminal=false | ||||
| Categories=Game; | ||||
| Categories=Game | ||||
| """ | ||||
|         try: | ||||
|             with open(desktop_path, "w", encoding="utf-8") as f: | ||||
| @@ -521,7 +451,7 @@ Categories=Game; | ||||
|             logger.info(f"Created .desktop file for EGS game: {desktop_path}") | ||||
|             return True | ||||
|         except Exception as e: | ||||
|             self._show_warning_dialog( | ||||
|             self.signals.show_warning_dialog.emit( | ||||
|                 _("Error"), | ||||
|                 _("Failed to create .desktop file: {0}").format(str(e)) | ||||
|             ) | ||||
| @@ -555,13 +485,13 @@ Categories=Game; | ||||
|                 self.parent.statusBar().showMessage( | ||||
|                     _("Game '{0}' added to desktop").format(game_name), 3000 | ||||
|                 ) | ||||
|                 logger.debug("Direct status message: Game '%s' added to desktop", game_name) | ||||
|                 logger.debug("Direct status message: Game '{0}' added to desktop", game_name) | ||||
|             else: | ||||
|                 logger.warning("Status bar not available when adding '%s' to desktop", game_name) | ||||
|                 logger.warning("Status bar not available when adding '{0}' to desktop", game_name) | ||||
|         except OSError as e: | ||||
|             self._show_warning_dialog( | ||||
|             self.signals.show_warning_dialog.emit( | ||||
|                 _("Error"), | ||||
|                 _("Failed to add game to desktop: {0}").format(str(e)) | ||||
|                 _("Failed to add game to desktop: {0}").format(game_name, str(e)) | ||||
|             ) | ||||
|  | ||||
|     def remove_egs_from_desktop(self, game_name: str): | ||||
| @@ -575,8 +505,8 @@ Categories=Game; | ||||
|         desktop_path = os.path.join(desktop_dir, f"{game_name}.desktop") | ||||
|         self._remove_file( | ||||
|             desktop_path, | ||||
|             _("Failed to remove game from Desktop: {0}"), | ||||
|             _("Game '{0}' removed from Desktop"), | ||||
|             _("Failed to remove game '{0}' from Desktop: {{0}}").format(game_name), | ||||
|             _("Successfully removed game '{0}' from Desktop").format(game_name), | ||||
|             game_name | ||||
|         ) | ||||
|  | ||||
| @@ -608,13 +538,13 @@ Categories=Game; | ||||
|                 self.parent.statusBar().showMessage( | ||||
|                     _("Game '{0}' added to menu").format(game_name), 3000 | ||||
|                 ) | ||||
|                 logger.debug("Direct status message: Game '%s' added to menu", game_name) | ||||
|                 logger.debug("Direct status message: Game '{0}' added to menu", game_name) | ||||
|             else: | ||||
|                 logger.warning("Status bar not available when adding '%s' to menu", game_name) | ||||
|                 logger.warning("Status bar not available when adding '{0}' to menu", game_name) | ||||
|         except OSError as e: | ||||
|             self._show_warning_dialog( | ||||
|             self.signals.show_warning_dialog.emit( | ||||
|                 _("Error"), | ||||
|                 _("Failed to add game to menu: {0}").format(str(e)) | ||||
|                 _("Failed to add game '{0}' to menu: {1}").format(game_name, str(e)) | ||||
|             ) | ||||
|  | ||||
|     def remove_egs_from_menu(self, game_name: str): | ||||
| @@ -628,8 +558,8 @@ Categories=Game; | ||||
|         desktop_path = os.path.join(applications_dir, f"{game_name}.desktop") | ||||
|         self._remove_file( | ||||
|             desktop_path, | ||||
|             _("Failed to remove game from menu: {0}"), | ||||
|             _("Game '{0}' removed from menu"), | ||||
|             _("Failed to remove game '{0}' from menu: {{0}}").format(game_name), | ||||
|             _("Successfully removed game '{0}' from menu").format(game_name), | ||||
|             game_name | ||||
|         ) | ||||
|  | ||||
| @@ -645,21 +575,21 @@ Categories=Game; | ||||
|                 if entry: | ||||
|                     exec_line = entry.get("Exec", entry.get("exec", "")).strip() | ||||
|                     if not exec_line: | ||||
|                         self._show_warning_dialog( | ||||
|                         self.signals.show_warning_dialog.emit( | ||||
|                             _("Error"), | ||||
|                             _("No executable command found in .desktop for game: {0}").format(game_name) | ||||
|                             _("No executable command found in .desktop file for game: {0}").format(game_name) | ||||
|                         ) | ||||
|                         return None | ||||
|                 else: | ||||
|                     self._show_warning_dialog( | ||||
|                     self.signals.show_warning_dialog.emit( | ||||
|                         _("Error"), | ||||
|                         _("Failed to parse .desktop file for game: {0}").format(game_name) | ||||
|                     ) | ||||
|                     return None | ||||
|             except Exception as e: | ||||
|                 self._show_warning_dialog( | ||||
|                 self.signals.show_warning_dialog.emit( | ||||
|                     _("Error"), | ||||
|                     _("Error reading .desktop file: {0}").format(e) | ||||
|                     _("Failed to read .desktop file: {0}").format(str(e)) | ||||
|                 ) | ||||
|                 return None | ||||
|         else: | ||||
| @@ -669,7 +599,7 @@ Categories=Game; | ||||
|                     exec_line = entry.get("Exec", entry.get("exec", "")).strip() | ||||
|                     if exec_line: | ||||
|                         return exec_line | ||||
|             self._show_warning_dialog( | ||||
|             self.signals.show_warning_dialog.emit( | ||||
|                 _("Error"), | ||||
|                 _(".desktop file not found for game: {0}").format(game_name) | ||||
|             ) | ||||
| @@ -681,7 +611,7 @@ Categories=Game; | ||||
|         try: | ||||
|             entry_exec_split = shlex.split(exec_line) | ||||
|             if not entry_exec_split: | ||||
|                 self._show_warning_dialog( | ||||
|                 self.signals.show_warning_dialog.emit( | ||||
|                     _("Error"), | ||||
|                     _("Invalid executable command: {0}").format(exec_line) | ||||
|                 ) | ||||
| @@ -693,16 +623,16 @@ Categories=Game; | ||||
|             else: | ||||
|                 exe_path = entry_exec_split[-1] | ||||
|             if not exe_path or not os.path.exists(exe_path): | ||||
|                 self._show_warning_dialog( | ||||
|                 self.signals.show_warning_dialog.emit( | ||||
|                     _("Error"), | ||||
|                     _("Executable file not found: {0}").format(exe_path or "None") | ||||
|                 ) | ||||
|                 return None | ||||
|             return exe_path | ||||
|         except Exception as e: | ||||
|             self._show_warning_dialog( | ||||
|             self.signals.show_warning_dialog.emit( | ||||
|                 _("Error"), | ||||
|                 _("Failed to parse executable command: {0}").format(e) | ||||
|                 _("Failed to parse executable command: {0}").format(str(e)) | ||||
|             ) | ||||
|             return None | ||||
|  | ||||
| @@ -717,9 +647,9 @@ Categories=Game; | ||||
|                 logger.warning("Status bar not available when removing file for '%s'", game_name) | ||||
|             return True | ||||
|         except OSError as e: | ||||
|             self._show_warning_dialog( | ||||
|             self.signals.show_warning_dialog.emit( | ||||
|                 _("Error"), | ||||
|                 error_message.format(e) | ||||
|                 error_message.format(str(e)) | ||||
|             ) | ||||
|             return False | ||||
|  | ||||
| @@ -741,9 +671,9 @@ Categories=Game; | ||||
|  | ||||
|         desktop_path = self._get_desktop_path(game_name) | ||||
|         if not os.path.exists(desktop_path): | ||||
|             self._show_warning_dialog( | ||||
|             self.signals.show_warning_dialog.emit( | ||||
|                 _("Error"), | ||||
|                 _("Could not locate .desktop file for '{0}'").format(game_name) | ||||
|                 _("Could not locate .desktop file for game: {0}").format(game_name) | ||||
|             ) | ||||
|             return | ||||
|  | ||||
| @@ -772,9 +702,9 @@ Categories=Game; | ||||
|                 try: | ||||
|                     shutil.rmtree(custom_folder) | ||||
|                 except OSError as e: | ||||
|                     self._show_warning_dialog( | ||||
|                     self.signals.show_warning_dialog.emit( | ||||
|                         _("Error"), | ||||
|                         _("Failed to delete custom data: {0}").format(e) | ||||
|                         _("Failed to delete custom data: {0}").format(str(e)) | ||||
|                     ) | ||||
|  | ||||
|     def add_to_menu(self, game_name, exec_line): | ||||
| @@ -784,9 +714,9 @@ Categories=Game; | ||||
|  | ||||
|         desktop_path = self._get_desktop_path(game_name) | ||||
|         if not os.path.exists(desktop_path): | ||||
|             self._show_warning_dialog( | ||||
|             self.signals.show_warning_dialog.emit( | ||||
|                 _("Error"), | ||||
|                 _("Could not locate .desktop file for '{0}'").format(game_name) | ||||
|                 _("Could not locate .desktop file for game: {0}").format(game_name) | ||||
|             ) | ||||
|             return | ||||
|  | ||||
| @@ -801,13 +731,13 @@ Categories=Game; | ||||
|                 self.parent.statusBar().showMessage( | ||||
|                     _("Game '{0}' added to menu").format(game_name), 3000 | ||||
|                 ) | ||||
|                 logger.debug("Direct status message: Game '%s' added to menu", game_name) | ||||
|                 logger.debug("Direct status message: Game '{0}' added to menu", game_name) | ||||
|             else: | ||||
|                 logger.warning("Status bar not available when adding '%s' to menu", game_name) | ||||
|                 logger.warning("Status bar not available when adding '{0}' to menu", game_name) | ||||
|         except OSError as e: | ||||
|             self._show_warning_dialog( | ||||
|             self.signals.show_warning_dialog.emit( | ||||
|                 _("Error"), | ||||
|                 _("Failed to add game to menu: {0}").format(str(e)) | ||||
|                 _("Failed to add game '{0}' to menu: {1}").format(game_name, str(e)) | ||||
|             ) | ||||
|  | ||||
|     def remove_from_menu(self, game_name): | ||||
| @@ -816,8 +746,8 @@ Categories=Game; | ||||
|         desktop_path = os.path.join(applications_dir, f"{game_name}.desktop") | ||||
|         self._remove_file( | ||||
|             desktop_path, | ||||
|             _("Failed to remove game from menu: {0}"), | ||||
|             _("Game '{0}' removed from menu"), | ||||
|             _("Failed to remove game '{0}' from menu: {{0}}").format(game_name), | ||||
|             _("Successfully removed game '{0}' from menu").format(game_name), | ||||
|             game_name | ||||
|         ) | ||||
|  | ||||
| @@ -828,9 +758,9 @@ Categories=Game; | ||||
|  | ||||
|         desktop_path = self._get_desktop_path(game_name) | ||||
|         if not os.path.exists(desktop_path): | ||||
|             self._show_warning_dialog( | ||||
|             self.signals.show_warning_dialog.emit( | ||||
|                 _("Error"), | ||||
|                 _("Could not locate .desktop file for '{0}'").format(game_name) | ||||
|                 _("Could not locate .desktop file for game: {0}").format(game_name) | ||||
|             ) | ||||
|             return | ||||
|  | ||||
| @@ -845,13 +775,13 @@ Categories=Game; | ||||
|                 self.parent.statusBar().showMessage( | ||||
|                     _("Game '{0}' added to desktop").format(game_name), 3000 | ||||
|                 ) | ||||
|                 logger.debug("Direct status message: Game '%s' added to desktop", game_name) | ||||
|                 logger.debug("Direct status message: Game '{0}' added to desktop", game_name) | ||||
|             else: | ||||
|                 logger.warning("Status bar not available when adding '%s' to desktop", game_name) | ||||
|                 logger.warning("Status bar not available when adding '{0}' to desktop", game_name) | ||||
|         except OSError as e: | ||||
|             self._show_warning_dialog( | ||||
|             self.signals.show_warning_dialog.emit( | ||||
|                 _("Error"), | ||||
|                 _("Failed to add game to desktop: {0}").format(str(e)) | ||||
|                 _("Failed to add game '{0}' to desktop: {1}").format(game_name, str(e)) | ||||
|             ) | ||||
|  | ||||
|     def remove_from_desktop(self, game_name): | ||||
| @@ -860,8 +790,8 @@ Categories=Game; | ||||
|         desktop_path = os.path.join(desktop_dir, f"{game_name}.desktop") | ||||
|         self._remove_file( | ||||
|             desktop_path, | ||||
|             _("Failed to remove game from Desktop: {0}"), | ||||
|             _("Game '{0}' removed from Desktop"), | ||||
|             _("Failed to remove game '{0}' from Desktop: {{0}}").format(game_name), | ||||
|             _("Successfully removed game '{0}' from Desktop").format(game_name), | ||||
|             game_name | ||||
|         ) | ||||
|  | ||||
| @@ -893,7 +823,7 @@ Categories=Game; | ||||
|             new_cover_path = dialog.coverEdit.text().strip() | ||||
|  | ||||
|             if not new_name or not new_exe_path: | ||||
|                 self._show_warning_dialog( | ||||
|                 self.signals.show_warning_dialog.emit( | ||||
|                     _("Error"), | ||||
|                     _("Game name and executable path are required.") | ||||
|                 ) | ||||
| @@ -901,7 +831,7 @@ Categories=Game; | ||||
|  | ||||
|             desktop_entry, new_desktop_path = dialog.getDesktopEntryData() | ||||
|             if not desktop_entry or not new_desktop_path: | ||||
|                 self._show_warning_dialog( | ||||
|                 self.signals.show_warning_dialog.emit( | ||||
|                     _("Error"), | ||||
|                     _("Failed to generate .desktop file data.") | ||||
|                 ) | ||||
| @@ -921,9 +851,9 @@ Categories=Game; | ||||
|                     f.write(desktop_entry) | ||||
|                     os.chmod(new_desktop_path, 0o755) | ||||
|             except OSError as e: | ||||
|                 self._show_warning_dialog( | ||||
|                 self.signals.show_warning_dialog.emit( | ||||
|                     _("Error"), | ||||
|                     _("Failed to save .desktop file: {0}").format(e) | ||||
|                     _("Failed to save .desktop file: {0}").format(str(e)) | ||||
|                 ) | ||||
|                 return | ||||
|  | ||||
| @@ -941,9 +871,9 @@ Categories=Game; | ||||
|                     try: | ||||
|                         shutil.copyfile(new_cover_path, os.path.join(custom_folder, f"cover{ext}")) | ||||
|                     except OSError as e: | ||||
|                         self._show_warning_dialog( | ||||
|                         self.signals.show_warning_dialog.emit( | ||||
|                             _("Error"), | ||||
|                             _("Failed to copy cover image: {0}").format(e) | ||||
|                             _("Failed to copy cover image: {0}").format(str(e)) | ||||
|                         ) | ||||
|                         return | ||||
|  | ||||
| @@ -960,23 +890,19 @@ Categories=Game; | ||||
|         if not exe_path: | ||||
|             return | ||||
|  | ||||
|         def on_add_to_steam_result(result: tuple[bool, str]): | ||||
|             success, message = result | ||||
|             if success: | ||||
|                 self.signals.show_status_message.emit( | ||||
|                     _("The game was added successfully. Please restart Steam for changes to take effect."), 5000 | ||||
|                 ) | ||||
|             else: | ||||
|                 self.signals.show_warning_dialog.emit(_("Error"), message) | ||||
|         logger.debug("Adding '{0}' to Steam", game_name) | ||||
|  | ||||
|         if self.parent.statusBar(): | ||||
|             self.parent.statusBar().showMessage( | ||||
|                 _("Adding '{0}' to Steam...").format(game_name), 0 | ||||
|         try: | ||||
|             add_to_steam(game_name, exec_line, cover_path) | ||||
|             self.signals.show_info_dialog.emit( | ||||
|                 _("Success"), | ||||
|                 _("'{0}' was added to Steam. Please restart Steam for changes to take effect.").format(game_name) | ||||
|             ) | ||||
|         except Exception as e: | ||||
|             self.signals.show_warning_dialog.emit( | ||||
|                 _("Error"), | ||||
|                 _("Failed to add game '{0}' to Steam: {1}").format(game_name, str(e)) | ||||
|             ) | ||||
|             logger.debug("Direct status message: Adding '%s' to Steam", game_name) | ||||
|         else: | ||||
|             logger.warning("Status bar not available when adding '%s' to Steam", game_name) | ||||
|         add_to_steam(game_name, exec_line, cover_path) | ||||
|  | ||||
|     def remove_from_steam(self, game_name, exec_line, game_source): | ||||
|         """Handle removing a game from Steam via steam_api, supporting both EGS and non-EGS games.""" | ||||
| @@ -986,8 +912,9 @@ Categories=Game; | ||||
|         def on_remove_from_steam_result(result: tuple[bool, str]): | ||||
|             success, message = result | ||||
|             if success: | ||||
|                 self.signals.show_status_message.emit( | ||||
|                     _("The game was removed successfully. Please restart Steam for changes to take effect."), 5000 | ||||
|                 self.signals.show_info_dialog.emit( | ||||
|                     _("Success"), | ||||
|                     _("'{0}' was removed from Steam. Please restart Steam for changes to take effect.").format(game_name) | ||||
|                 ) | ||||
|             else: | ||||
|                 self.signals.show_warning_dialog.emit(_("Error"), message) | ||||
| @@ -995,7 +922,7 @@ Categories=Game; | ||||
|         if game_source == "epic": | ||||
|             # For EGS games, construct the script path used in Steam shortcuts.vdf | ||||
|             if not self.portproton_location: | ||||
|                 self._show_warning_dialog( | ||||
|                 self.signals.show_warning_dialog.emit( | ||||
|                     _("Error"), | ||||
|                     _("PortProton directory not found") | ||||
|                 ) | ||||
| @@ -1007,15 +934,14 @@ Categories=Game; | ||||
|  | ||||
|             # Directly remove the shortcut by matching AppName and Exe | ||||
|             try: | ||||
|                 from portprotonqt.steam_api import get_steam_home, get_last_steam_user, convert_steam_id | ||||
|                 steam_home = get_steam_home() | ||||
|                 if not steam_home: | ||||
|                     self._show_warning_dialog(_("Error"), _("Steam directory not found")) | ||||
|                     self.signals.show_warning_dialog.emit(_("Error"), _("Steam directory not found")) | ||||
|                     return | ||||
|  | ||||
|                 last_user = get_last_steam_user(steam_home) | ||||
|                 if not last_user or 'SteamID' not in last_user: | ||||
|                     self._show_warning_dialog(_("Error"), _("Failed to get Steam user ID")) | ||||
|                     self.signals.show_warning_dialog.emit(_("Error"), _("Failed to get Steam user ID")) | ||||
|                     return | ||||
|  | ||||
|                 userdata_dir = os.path.join(steam_home, "userdata") | ||||
| @@ -1026,7 +952,7 @@ Categories=Game; | ||||
|                 backup_path = f"{steam_shortcuts_path}.backup" | ||||
|  | ||||
|                 if not os.path.exists(steam_shortcuts_path): | ||||
|                     self._show_warning_dialog( | ||||
|                     self.signals.show_warning_dialog.emit( | ||||
|                         _("Error"), | ||||
|                         _("Steam shortcuts file not found") | ||||
|                     ) | ||||
| @@ -1037,9 +963,9 @@ Categories=Game; | ||||
|                     shutil.copy2(steam_shortcuts_path, backup_path) | ||||
|                     logger.info(f"Created backup of shortcuts.vdf at {backup_path}") | ||||
|                 except Exception as e: | ||||
|                     self._show_warning_dialog( | ||||
|                     self.signals.show_warning_dialog.emit( | ||||
|                         _("Error"), | ||||
|                         _("Failed to create backup of shortcuts.vdf: {0}").format(e) | ||||
|                         _("Failed to create backup of shortcuts.vdf: {0}").format(str(e)) | ||||
|                     ) | ||||
|                     return | ||||
|  | ||||
| @@ -1048,9 +974,9 @@ Categories=Game; | ||||
|                     with open(steam_shortcuts_path, 'rb') as f: | ||||
|                         shortcuts_data = vdf.binary_load(f) | ||||
|                 except Exception as e: | ||||
|                     self._show_warning_dialog( | ||||
|                     self.signals.show_warning_dialog.emit( | ||||
|                         _("Error"), | ||||
|                         _("Failed to load shortcuts.vdf: {0}").format(e) | ||||
|                         _("Failed to load shortcuts.vdf: {0}").format(str(e)) | ||||
|                     ) | ||||
|                     return | ||||
|  | ||||
| @@ -1068,7 +994,7 @@ Categories=Game; | ||||
|                     index += 1 | ||||
|  | ||||
|                 if not modified: | ||||
|                     self._show_warning_dialog( | ||||
|                     self.signals.show_warning_dialog.emit( | ||||
|                         _("Error"), | ||||
|                         _("Game '{0}' not found in Steam shortcuts").format(game_name) | ||||
|                     ) | ||||
| @@ -1081,9 +1007,9 @@ Categories=Game; | ||||
|                     logger.info(f"Updated shortcuts.vdf, removed '{game_name}'") | ||||
|                     on_remove_from_steam_result((True, f"Game '{game_name}' removed from Steam")) | ||||
|                 except Exception as e: | ||||
|                     self._show_warning_dialog( | ||||
|                     self.signals.show_warning_dialog.emit( | ||||
|                         _("Error"), | ||||
|                         _("Failed to update shortcuts.vdf: {0}").format(e) | ||||
|                         _("Failed to update shortcuts.vdf: {0}").format(str(e)) | ||||
|                     ) | ||||
|                     if os.path.exists(backup_path): | ||||
|                         try: | ||||
| @@ -1098,20 +1024,20 @@ Categories=Game; | ||||
|                 if os.path.exists(script_path): | ||||
|                     try: | ||||
|                         os.remove(script_path) | ||||
|                         logger.info(f"Removed EGS script file: {script_path}") | ||||
|                         logger.info(f"Removed EGS script: {script_path}") | ||||
|                     except Exception as e: | ||||
|                         logger.warning(f"Failed to remove EGS script file {script_path}: {e}") | ||||
|                         logger.warning(f"Failed to remove EGS script {script_path}: {e}") | ||||
|  | ||||
|             except Exception as e: | ||||
|                 self._show_warning_dialog( | ||||
|                 self.signals.show_warning_dialog.emit( | ||||
|                     _("Error"), | ||||
|                     _("Failed to remove EGS game from Steam: {0}").format(e) | ||||
|                     _("Failed to remove EGS game '{0}' from Steam: {1}").format(game_name, str(e)) | ||||
|                 ) | ||||
|                 on_remove_from_steam_result((False, f"Failed to remove EGS game from Steam: {e}")) | ||||
|                 on_remove_from_steam_result((False, f"Failed to remove EGS game '{game_name}' from Steam: {str(e)}")) | ||||
|                 return | ||||
|  | ||||
|         else: | ||||
|             # For non-EGS games, use the existing logic | ||||
|             # For non-EGS games, use the existing logic without callback | ||||
|             exec_line = self._get_exec_line(game_name, exec_line) | ||||
|             if not exec_line: | ||||
|                 return | ||||
| @@ -1121,13 +1047,21 @@ Categories=Game; | ||||
|                 return | ||||
|  | ||||
|             if self.parent.statusBar(): | ||||
|                 self.parent.statusBar().showMessage( | ||||
|                     _("Removing '{0}' from Steam...").format(game_name), 0 | ||||
|                 ) | ||||
|                 logger.debug("Direct status message: Removing '%s' from Steam", game_name) | ||||
|                 logger.debug("Direct status message: Removing '{0}' from Steam", game_name) | ||||
|             else: | ||||
|                 logger.warning("Status bar not available when removing '%s' from Steam", game_name) | ||||
|             remove_from_steam(game_name, exec_line) | ||||
|                 logger.warning("Status bar not available when removing '{0}' from Steam", game_name) | ||||
|  | ||||
|             try: | ||||
|                 remove_from_steam(game_name, exec_line) | ||||
|                 self.signals.show_info_dialog.emit( | ||||
|                     _("Success"), | ||||
|                     _("'{0}' was removed from Steam. Please restart Steam for changes to take effect.").format(game_name) | ||||
|                 ) | ||||
|             except Exception as e: | ||||
|                 self.signals.show_warning_dialog.emit( | ||||
|                     _("Error"), | ||||
|                     _("Failed to remove game '{0}' from Steam: {1}").format(game_name, str(e)) | ||||
|                 ) | ||||
|  | ||||
|     def open_game_folder(self, game_name, exec_line): | ||||
|         """Open the folder containing the game's executable.""" | ||||
| @@ -1147,13 +1081,13 @@ Categories=Game; | ||||
|             QDesktopServices.openUrl(QUrl.fromLocalFile(folder_path)) | ||||
|             if self.parent.statusBar(): | ||||
|                 self.parent.statusBar().showMessage( | ||||
|                     _("Opened folder for '{0}'").format(game_name), 3000 | ||||
|                     _("Successfully opened folder for '{0}'").format(game_name), 3000 | ||||
|                 ) | ||||
|                 logger.debug("Direct status message: Opened folder for '%s'", game_name) | ||||
|                 logger.debug("Direct status message: Opened folder for '{0}'", game_name) | ||||
|             else: | ||||
|                 logger.warning("Status bar not available when opening folder for '%s'", game_name) | ||||
|                 logger.warning("Status bar not available when opening folder for '{0}'", game_name) | ||||
|         except Exception as e: | ||||
|             self._show_warning_dialog( | ||||
|             self.signals.show_warning_dialog.emit( | ||||
|                 _("Error"), | ||||
|                 _("Failed to open game folder: {0}").format(str(e)) | ||||
|             ) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user