diff --git a/rare/components/tabs/__init__.py b/rare/components/tabs/__init__.py index 7686eb21..1bb950fc 100644 --- a/rare/components/tabs/__init__.py +++ b/rare/components/tabs/__init__.py @@ -1,7 +1,7 @@ from PyQt5.QtCore import QSize, pyqtSignal, pyqtSlot from PyQt5.QtWidgets import QMenu, QTabWidget, QWidget, QWidgetAction, QShortcut, QMessageBox -from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton +from rare.shared import RareCore, LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton from rare.components.tabs.account import AccountWidget from rare.components.tabs.downloads import DownloadsTab from rare.components.tabs.games import GamesTab @@ -18,6 +18,7 @@ class TabWidget(QTabWidget): def __init__(self, parent): super(TabWidget, self).__init__(parent=parent) + self.rcore = RareCore.instance() self.core = LegendaryCoreSingleton() self.signals = GlobalSignalsSingleton() self.args = ArgumentsSingleton() @@ -28,17 +29,13 @@ class TabWidget(QTabWidget): self.games_tab = GamesTab(self) self.addTab(self.games_tab, self.tr("Games")) + # Downloads Tab after Games Tab to use populated RareCore games list if not self.args.offline: - # updates = self.games_tab.default_widget.game_list.updates - self.downloads_tab = DownloadsTab(self.games_tab.game_updates, self) + self.downloads_tab = DownloadsTab(self) + updates = list(self.rcore.updates) self.addTab( self.downloads_tab, - "Downloads" - + ( - " (" + str(len(self.games_tab.game_updates)) + ")" - if len(self.games_tab.game_updates) != 0 - else "" - ), + self.tr("Downloads {}").format(f"({len(updates) if updates else 0})"), ) self.store = Shop(self.core) self.addTab(self.store, self.tr("Store (Beta)")) diff --git a/rare/components/tabs/downloads/__init__.py b/rare/components/tabs/downloads/__init__.py index 21bf744b..c829a5de 100644 --- a/rare/components/tabs/downloads/__init__.py +++ b/rare/components/tabs/downloads/__init__.py @@ -20,7 +20,7 @@ from rare.components.tabs.downloads.download_thread import DownloadThread from rare.lgndr.models.downloading import UIUpdate from rare.models.game import RareGame from rare.models.install import InstallOptionsModel, InstallQueueItemModel -from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton +from rare.shared import RareCore, LegendaryCoreSingleton, GlobalSignalsSingleton from rare.ui.components.tabs.downloads.downloads_tab import Ui_DownloadsTab from rare.utils.misc import get_size, create_desktop_link @@ -32,9 +32,10 @@ class DownloadsTab(QWidget, Ui_DownloadsTab): dl_queue: List[InstallQueueItemModel] = [] dl_status = pyqtSignal(int) - def __init__(self, game_updates: Set[RareGame], parent=None): + def __init__(self, parent=None): super(DownloadsTab, self).__init__(parent=parent) self.setupUi(self) + self.rcore = RareCore.instance() self.core = LegendaryCoreSingleton() self.signals = GlobalSignalsSingleton() @@ -56,9 +57,10 @@ class DownloadsTab(QWidget, Ui_DownloadsTab): self.update_text = QLabel(self.tr("No updates available")) self.update_layout.addWidget(self.update_text) - self.update_text.setVisible(len(game_updates) == 0) - for rgame in game_updates: + has_updates = False + for rgame in self.rcore.updates: + has_updates = True self.add_update(rgame) self.queue_widget.item_removed.connect(self.queue_item_removed) diff --git a/rare/components/tabs/games/__init__.py b/rare/components/tabs/games/__init__.py index 7f1dd0c8..99ae1ec9 100644 --- a/rare/components/tabs/games/__init__.py +++ b/rare/components/tabs/games/__init__.py @@ -14,6 +14,7 @@ from rare.shared import ( ApiResultsSingleton, ImageManagerSingleton, ) +from rare.shared import RareCore from rare.shared.game_utils import GameUtils from rare.widgets.library_layout import LibraryLayout from rare.widgets.sliding_stack import SlidingStackedWidget @@ -30,6 +31,7 @@ logger = getLogger("GamesTab") class GamesTab(QStackedWidget): def __init__(self, parent=None): super(GamesTab, self).__init__(parent=parent) + self.rcore = RareCore.instance() self.core = LegendaryCoreSingleton() self.signals = GlobalSignalsSingleton() self.args = ArgumentsSingleton() @@ -195,6 +197,7 @@ class GamesTab(QStackedWidget): self.update_count_games_label() for game in self.game_list + self.no_assets: rgame = self.__create_game_with_dlcs(game) + self.rcore.add_game(rgame) icon_widget, list_widget = self.add_library_widget(rgame) if not icon_widget or not list_widget: logger.warning(f"Excluding {rgame.app_name} from the game list") diff --git a/rare/components/tabs/games/game_info/game_info.py b/rare/components/tabs/games/game_info/game_info.py index fa3be475..b51afabc 100644 --- a/rare/components/tabs/games/game_info/game_info.py +++ b/rare/components/tabs/games/game_info/game_info.py @@ -116,7 +116,7 @@ class GameInfo(QWidget): 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)) + self.rgame.install() @pyqtSlot() def uninstall(self): diff --git a/rare/models/game.py b/rare/models/game.py index f99e02db..e1a8b9ad 100644 --- a/rare/models/game.py +++ b/rare/models/game.py @@ -346,6 +346,11 @@ class RareGame(QObject): """ return not self.game.asset_infos + def install(self): + self.signals.game.install.emit( + InstallOptionsModel(app_name=self.game.app_name) + ) + @property def is_origin(self) -> bool: return self.game.metadata.get("customAttributes", {}).get("ThirdPartyManagedApp", {}).get("value") == "Origin" diff --git a/rare/shared/rare_core.py b/rare/shared/rare_core.py index def6af99..eed993c3 100644 --- a/rare/shared/rare_core.py +++ b/rare/shared/rare_core.py @@ -1,13 +1,16 @@ import configparser import os from argparse import Namespace +from itertools import chain from logging import getLogger -from typing import Optional +from typing import Optional, Dict, Iterator, Callable from PyQt5.QtCore import QObject +from legendary.models.game import Game, SaveGameFile from rare.lgndr.core import LegendaryCore from rare.models.apiresults import ApiResults +from rare.models.game import RareGame from rare.models.signals import GlobalSignals from .image_manager import ImageManager @@ -32,6 +35,8 @@ class RareCore(QObject): self.core(init=True) self.image_manager(init=True) + self.__games: Dict[str, RareGame] = {} + RareCore._instance = self @staticmethod @@ -131,3 +136,80 @@ class RareCore(QObject): super(RareCore, self).deleteLater() + def get_game(self, app_name: str) -> RareGame: + return self.__games[app_name] + + def add_game(self, rgame: RareGame) -> None: + rgame.signals.game.install.connect(self._signals.game.install) + self.__games[rgame.app_name] = rgame + + def __filter_games(self, condition: Callable[[RareGame], bool]) -> Iterator[RareGame]: + return filter(condition, self.__games.values()) + + @property + def games_and_dlcs(self) -> Iterator[RareGame]: + for app_name in self.__games: + yield self.__games[app_name] + + @property + def games(self) -> Iterator[RareGame]: + return self.__filter_games(lambda game: not game.is_dlc) + + @property + def installed_games(self) -> Iterator[RareGame]: + return self.__filter_games(lambda game: game.is_installed and not game.is_dlc) + + @property + def game_list(self) -> Iterator[Game]: + for game in self.games: + yield game.game + + @property + def dlcs(self) -> Dict[str, Game]: + """! + RareGames that ARE DLCs themselves + """ + return {game.game.catalog_item_id: game.owned_dlcs for game in self.has_dlcs} + # return self.__filter_games(lambda game: game.is_dlc) + + @property + def has_dlcs(self) -> Iterator[RareGame]: + """! + RareGames that HAVE DLCs associated with them + """ + return self.__filter_games(lambda game: bool(game.owned_dlcs)) + + @property + def bit32_games(self) -> Iterator[RareGame]: + return self.__filter_games(lambda game: game.is_win32) + + @property + def mac_games(self) -> Iterator[RareGame]: + return self.__filter_games(lambda game: game.is_mac) + + @property + def no_asset_games(self) -> Iterator[RareGame]: + return self.__filter_games(lambda game: game.is_non_asset) + + @property + def unreal_engine(self) -> Iterator[RareGame]: + return self.__filter_games(lambda game: game.is_unreal) + + @property + def updates(self) -> Iterator[RareGame]: + return self.__filter_games(lambda game: game.has_update) + + @property + def saves(self) -> Iterator[SaveGameFile]: + """! + SaveGameFiles across games + """ + return chain.from_iterable([game.saves for game in self.has_saves]) + + @property + def has_saves(self) -> Iterator[RareGame]: + """! + RareGames that have SaveGameFiles associated with them + """ + return self.__filter_games(lambda game: bool(game.saves)) +