diff --git a/rare/components/dialogs/launch_dialog.py b/rare/components/dialogs/launch_dialog.py index 89eaf972..534e0466 100644 --- a/rare/components/dialogs/launch_dialog.py +++ b/rare/components/dialogs/launch_dialog.py @@ -10,8 +10,8 @@ from requests.exceptions import ConnectionError, HTTPError from rare.components.dialogs.login import LoginDialog from rare.models.apiresults import ApiResults from rare.shared import LegendaryCoreSingleton, ArgumentsSingleton, ApiResultsSingleton, ImageManagerSingleton +from rare.shared.game_utils import uninstall_game from rare.ui.components.dialogs.launch_dialog import Ui_LaunchDialog -from rare.utils import legendary_utils from rare.utils.misc import CloudWorker from rare.widgets.elide_label import ElideLabel @@ -99,7 +99,7 @@ class ImageWorker(LaunchWorker): if not os.path.exists(igame.install_path): # lk; since install_path is lost anyway, set keep_files to True # lk: to avoid spamming the log with "file not found" errors - legendary_utils.uninstall_game(self.core, igame.app_name, keep_files=True) + uninstall_game(self.core, igame.app_name, keep_files=True) logger.info(f"Uninstalled {igame.title}, because no game files exist") continue # lk: games that don't have an override and can't find their executable due to case sensitivity diff --git a/rare/components/tabs/games/__init__.py b/rare/components/tabs/games/__init__.py index d5800225..95effe63 100644 --- a/rare/components/tabs/games/__init__.py +++ b/rare/components/tabs/games/__init__.py @@ -1,10 +1,10 @@ import time from logging import getLogger -from typing import Tuple, Dict, Union, List, Set +from typing import Tuple, Dict, List, Set from PyQt5.QtCore import QSettings, Qt, pyqtSlot from PyQt5.QtWidgets import QStackedWidget, QVBoxLayout, QWidget, QScrollArea, QFrame -from legendary.models.game import InstalledGame, Game +from legendary.models.game import Game from rare.models.game import RareGame from rare.shared import ( @@ -14,11 +14,10 @@ from rare.shared import ( ApiResultsSingleton, ImageManagerSingleton, ) +from rare.shared.game_utils import GameUtils from rare.widgets.library_layout import LibraryLayout from rare.widgets.sliding_stack import SlidingStackedWidget -from .cloud_save_utils import CloudSaveUtils from .game_info import GameInfoTabs -from .game_utils import GameUtils from .game_widgets import LibraryWidgetController from .game_widgets.icon_game_widget import IconGameWidget from .game_widgets.list_game_widget import ListGameWidget diff --git a/rare/components/tabs/games/game_info/__init__.py b/rare/components/tabs/games/game_info/__init__.py index f1a967e1..7c6d8e1e 100644 --- a/rare/components/tabs/games/game_info/__init__.py +++ b/rare/components/tabs/games/game_info/__init__.py @@ -4,9 +4,9 @@ from PyQt5.QtCore import Qt from PyQt5.QtGui import QKeyEvent from PyQt5.QtWidgets import QTreeView -from rare.components.tabs.games.game_utils import GameUtils from rare.models.game import RareGame from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton +from rare.shared.game_utils import GameUtils from rare.utils.extra_widgets import SideTabWidget from rare.utils.json_formatter import QJsonModel from .game_dlc import GameDlc diff --git a/rare/components/tabs/games/game_info/game_dlc.py b/rare/components/tabs/games/game_info/game_dlc.py index d300f54d..180f09c9 100644 --- a/rare/components/tabs/games/game_info/game_dlc.py +++ b/rare/components/tabs/games/game_info/game_dlc.py @@ -3,10 +3,10 @@ from typing import Optional from PyQt5.QtCore import pyqtSignal, pyqtSlot from PyQt5.QtWidgets import QFrame, QWidget, QMessageBox -from rare.components.tabs.games.game_utils import GameUtils from rare.models.game import RareGame from rare.models.install import InstallOptionsModel from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton +from rare.shared.game_utils import GameUtils from rare.shared.image_manager import ImageSize from rare.ui.components.tabs.games.game_info.game_dlc import Ui_GameDlc from rare.ui.components.tabs.games.game_info.game_dlc_widget import Ui_GameDlcWidget diff --git a/rare/components/tabs/games/game_info/game_info.py b/rare/components/tabs/games/game_info/game_info.py index 75663d21..bd10ac65 100644 --- a/rare/components/tabs/games/game_info/game_info.py +++ b/rare/components/tabs/games/game_info/game_info.py @@ -55,6 +55,7 @@ class GameInfo(QWidget, Ui_GameInfo): self.image_manager = ImageManagerSingleton() self.game_utils = game_utils + self.rgame: Optional[RareGame] = None self.game: Optional[Game] = None self.igame: Optional[InstalledGame] = None self.verify_threads: Dict[str, QRunnable] = {} @@ -84,7 +85,7 @@ class GameInfo(QWidget, Ui_GameInfo): else: self.repair_button.clicked.connect(self.repair) - self.install_button.clicked.connect(lambda: self.game_utils.launch_game(self.game.app_name)) + self.install_button.clicked.connect(self.install) self.move_game_pop_up = MoveGamePopUp() self.move_action = QWidgetAction(self) @@ -109,10 +110,18 @@ class GameInfo(QWidget, Ui_GameInfo): self.move_game_pop_up.move_clicked.connect(self.move_button.menu().close) self.move_game_pop_up.move_clicked.connect(self.move_game) + @pyqtSlot() + def install(self): + if self.rgame.is_origin: + self.game_utils.launch_game(self.rgame.app_name) + else: + self.signals.game.install.emit(InstallOptionsModel(app_name=self.rgame.app_name)) + + @pyqtSlot() def uninstall(self): if self.game_utils.uninstall_game(self.game.app_name): self.game_utils.update_list.emit(self.game.app_name) - self.uninstalled.emit(self.game.app_name) + self.signals.game.uninstalled.emit(self.game.app_name) @pyqtSlot() def repair(self): @@ -141,7 +150,7 @@ class GameInfo(QWidget, Ui_GameInfo): "Do you want to update the game while repairing it?" ).format(igame.title, igame.version, game.app_version(igame.platform)), ) == QMessageBox.Yes - self.signals.install_game.emit( + self.signals.game.install.emit( InstallOptionsModel( app_name=igame.app_name, repair_mode=True, repair_and_update=ans, update=True ) @@ -316,6 +325,7 @@ class GameInfo(QWidget, Ui_GameInfo): def update_game(self, rgame: RareGame): # FIXME: Use RareGame for the rest of the code + self.rgame = rgame self.game = rgame.game self.igame = rgame.igame self.title.setTitle(self.game.app_title) diff --git a/rare/components/tabs/games/game_widgets/__init__.py b/rare/components/tabs/games/game_widgets/__init__.py index 2e1928d7..c09da179 100644 --- a/rare/components/tabs/games/game_widgets/__init__.py +++ b/rare/components/tabs/games/game_widgets/__init__.py @@ -3,11 +3,11 @@ from typing import Tuple, List, Union, Optional from PyQt5.QtCore import QObject, pyqtSlot from PyQt5.QtWidgets import QWidget -from rare.components.tabs.games.game_utils import GameUtils from rare.lgndr.core import LegendaryCore from rare.models.game import RareGame from rare.models.signals import GlobalSignals from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ApiResultsSingleton +from rare.shared.game_utils import GameUtils from .icon_game_widget import IconGameWidget from .list_game_widget import ListGameWidget diff --git a/rare/components/tabs/games/game_widgets/game_widget.py b/rare/components/tabs/games/game_widgets/game_widget.py index 0f0941d7..c8c4fa6c 100644 --- a/rare/components/tabs/games/game_widgets/game_widget.py +++ b/rare/components/tabs/games/game_widgets/game_widget.py @@ -1,14 +1,11 @@ import os import platform from logging import getLogger -from typing import Optional from PyQt5.QtCore import pyqtSignal, QSettings, QStandardPaths, Qt from PyQt5.QtGui import QMouseEvent from PyQt5.QtWidgets import QMessageBox, QAction -from legendary.models.game import Game, InstalledGame -from rare.components.tabs.games.game_utils import GameUtils from rare.models.game import RareGame from rare.shared import ( LegendaryCoreSingleton, @@ -16,6 +13,7 @@ from rare.shared import ( ArgumentsSingleton, ImageManagerSingleton, ) +from rare.shared.game_utils import GameUtils from rare.utils.misc import create_desktop_link from .library_widget import LibraryWidget diff --git a/rare/components/tabs/games/game_widgets/icon_game_widget.py b/rare/components/tabs/games/game_widgets/icon_game_widget.py index ffbc6984..f0fbca0f 100644 --- a/rare/components/tabs/games/game_widgets/icon_game_widget.py +++ b/rare/components/tabs/games/game_widgets/icon_game_widget.py @@ -2,8 +2,8 @@ from logging import getLogger from PyQt5.QtCore import QEvent, pyqtSignal -from rare.components.tabs.games.game_utils import GameUtils from rare.models.game import RareGame +from rare.shared.game_utils import GameUtils from rare.shared.image_manager import ImageSize from .game_widget import GameWidget from .icon_widget import IconWidget diff --git a/rare/components/tabs/games/game_widgets/list_game_widget.py b/rare/components/tabs/games/game_widgets/list_game_widget.py index 622078ab..faa2245c 100644 --- a/rare/components/tabs/games/game_widgets/list_game_widget.py +++ b/rare/components/tabs/games/game_widgets/list_game_widget.py @@ -11,8 +11,8 @@ from PyQt5.QtGui import ( QPixmap, QImage, QResizeEvent, ) -from rare.components.tabs.games.game_utils import GameUtils from rare.models.game import RareGame +from rare.shared.game_utils import GameUtils from rare.utils.misc import get_size from rare.widgets.image_widget import ImageWidget from .game_widget import GameWidget diff --git a/rare/models/game.py b/rare/models/game.py index f17ddbab..7cf34540 100644 --- a/rare/models/game.py +++ b/rare/models/game.py @@ -1,19 +1,16 @@ -import os from dataclasses import dataclass from datetime import datetime from enum import IntEnum from logging import getLogger from typing import List, Optional -from PyQt5.QtCore import QObject, pyqtSignal, QRunnable, QThreadPool, QMetaObject +from PyQt5.QtCore import QObject, pyqtSignal, QRunnable, QThreadPool from PyQt5.QtGui import QPixmap -from PyQt5.QtWidgets import QMessageBox from legendary.models.game import Game, InstalledGame, SaveGameFile -from rare.models.install import InstallOptionsModel from rare.lgndr.core import LegendaryCore +from rare.models.install import InstallOptionsModel from rare.shared.image_manager import ImageManager -# from rare.utils.legendary_utils import VerificationWorker logger = getLogger("RareGame") diff --git a/rare/components/tabs/games/cloud_save_utils.py b/rare/shared/cloud_save_utils.py similarity index 100% rename from rare/components/tabs/games/cloud_save_utils.py rename to rare/shared/cloud_save_utils.py diff --git a/rare/components/tabs/games/game_utils.py b/rare/shared/game_utils.py similarity index 84% rename from rare/components/tabs/games/game_utils.py rename to rare/shared/game_utils.py index d203dad5..dfae68d9 100644 --- a/rare/components/tabs/games/game_utils.py +++ b/rare/shared/game_utils.py @@ -1,20 +1,25 @@ import datetime import json import os +import platform from logging import getLogger from PyQt5.QtCore import QObject, QProcess, pyqtSignal, QUrl, QTimer +from PyQt5.QtCore import QStandardPaths from PyQt5.QtGui import QDesktopServices from PyQt5.QtNetwork import QLocalSocket from PyQt5.QtWidgets import QMessageBox, QPushButton +from legendary.core import LegendaryCore from rare.components.dialogs.uninstall_dialog import UninstallDialog -from rare.components.tabs.games import CloudSaveUtils from rare.game_launch_helper import message_models +from rare.lgndr.cli import LegendaryCLI +from rare.lgndr.glue.arguments import LgndrUninstallGameArgs +from rare.lgndr.glue.monkeys import LgndrIndirectStatus from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton -from rare.utils import legendary_utils -from rare.utils import misc +from rare.utils import config_helper, misc from rare.utils.meta import RareGameMeta +from .cloud_save_utils import CloudSaveUtils logger = getLogger("GameUtils") @@ -124,6 +129,50 @@ class GameProcess(QObject): self.game_finished.emit(exit_code, self.app_name) +def uninstall_game(core: LegendaryCore, app_name: str, keep_files=False, keep_config=False): + igame = core.get_installed_game(app_name) + + # remove shortcuts link + desktop = QStandardPaths.writableLocation(QStandardPaths.DesktopLocation) + applications = QStandardPaths.writableLocation(QStandardPaths.ApplicationsLocation) + if platform.system() == "Linux": + desktop_shortcut = os.path.join(desktop, f"{igame.title}.desktop") + if os.path.exists(desktop_shortcut): + os.remove(desktop_shortcut) + + applications_shortcut = os.path.join(applications, f"{igame.title}.desktop") + if os.path.exists(applications_shortcut): + os.remove(applications_shortcut) + + elif platform.system() == "Windows": + game_title = igame.title.split(":")[0] + desktop_shortcut = os.path.join(desktop, f"{game_title}.lnk") + if os.path.exists(desktop_shortcut): + os.remove(desktop_shortcut) + + start_menu_shortcut = os.path.join(applications, "..", f"{game_title}.lnk") + if os.path.exists(start_menu_shortcut): + os.remove(start_menu_shortcut) + + status = LgndrIndirectStatus() + LegendaryCLI(core).uninstall_game( + LgndrUninstallGameArgs( + app_name=app_name, + keep_files=keep_files, + indirect_status=status, + yes=True, + ) + ) + if not keep_config: + logger.info("Removing sections in config file") + config_helper.remove_section(app_name) + config_helper.remove_section(f"{app_name}.env") + + config_helper.save_config() + + return status.success, status.message + + class GameUtils(QObject): running_games = dict() finished = pyqtSignal(str, str) # app_name, error @@ -170,10 +219,10 @@ class GameUtils(QObject): proceed, keep_files, keep_config = UninstallDialog(game).get_options() if not proceed: return False - success, message = legendary_utils.uninstall_game(self.core, game.app_name, keep_files, keep_config) + success, message = uninstall_game(self.core, game.app_name, keep_files, keep_config) if not success: QMessageBox.warning(None, self.tr("Uninstall - {}").format(igame.title), message, QMessageBox.Close) - self.signals.game_uninstalled.emit(app_name) + self.signals.game.uninstalled.emit(app_name) return True def prepare_launch( diff --git a/rare/utils/legendary_utils.py b/rare/utils/legendary_utils.py deleted file mode 100644 index 54714892..00000000 --- a/rare/utils/legendary_utils.py +++ /dev/null @@ -1,57 +0,0 @@ -import os -import platform -from logging import getLogger - -from PyQt5.QtCore import QStandardPaths -from legendary.core import LegendaryCore - -from rare.lgndr.cli import LegendaryCLI -from rare.lgndr.glue.arguments import LgndrUninstallGameArgs -from rare.lgndr.glue.monkeys import LgndrIndirectStatus -from rare.utils import config_helper - -logger = getLogger("Legendary Utils") - - -def uninstall_game(core: LegendaryCore, app_name: str, keep_files=False, keep_config=False): - igame = core.get_installed_game(app_name) - - # remove shortcuts link - desktop = QStandardPaths.writableLocation(QStandardPaths.DesktopLocation) - applications = QStandardPaths.writableLocation(QStandardPaths.ApplicationsLocation) - if platform.system() == "Linux": - desktop_shortcut = os.path.join(desktop, f"{igame.title}.desktop") - if os.path.exists(desktop_shortcut): - os.remove(desktop_shortcut) - - applications_shortcut = os.path.join(applications, f"{igame.title}.desktop") - if os.path.exists(applications_shortcut): - os.remove(applications_shortcut) - - elif platform.system() == "Windows": - game_title = igame.title.split(":")[0] - desktop_shortcut = os.path.join(desktop, f"{game_title}.lnk") - if os.path.exists(desktop_shortcut): - os.remove(desktop_shortcut) - - start_menu_shortcut = os.path.join(applications, "..", f"{game_title}.lnk") - if os.path.exists(start_menu_shortcut): - os.remove(start_menu_shortcut) - - status = LgndrIndirectStatus() - LegendaryCLI(core).uninstall_game( - LgndrUninstallGameArgs( - app_name=app_name, - keep_files=keep_files, - indirect_status=status, - yes=True, - ) - ) - if not keep_config: - logger.info("Removing sections in config file") - config_helper.remove_section(app_name) - config_helper.remove_section(f"{app_name}.env") - - config_helper.save_config() - - return status.success, status.message