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