diff --git a/custom_legendary/core.py b/custom_legendary/core.py index 9681bd98..c5a6efcb 100644 --- a/custom_legendary/core.py +++ b/custom_legendary/core.py @@ -293,6 +293,37 @@ class LegendaryCore: def _get_installed_game(self, app_name) -> InstalledGame: return self.lgd.get_installed_game(app_name) + def get_non_asset_library_items(self, skip_ue=True) -> (List[Game], Dict[str, List[Game]]): + """ + Gets a list of Games without assets for installation, for instance Games delivered via + third-party stores that do not have assets for installation + :param skip_ue: Ingore Unreal Marketplace entries + :return: List of Games and DLC that do not have assets + """ + _ret = [] + _dlc = defaultdict(list) + # get all the appnames we have to ignore + ignore = set(i.app_name for i in self.get_assets()) + + for libitem in self.egs.get_library_items(): + if libitem['namespace'] == 'ue' and skip_ue: + continue + if libitem['appName'] in ignore: + continue + + game = self.lgd.get_game_meta(libitem['appName']) + if not game: + eg_meta = self.egs.get_game_info(libitem['namespace'], libitem['catalogItemId']) + game = Game(app_name=libitem['appName'], app_version=None, + app_title=eg_meta['title'], asset_info=None, metadata=eg_meta) + self.lgd.set_game_meta(game.app_name, game) + if game.is_dlc: + _dlc[game.metadata['mainGameItem']['id']].append(game) + elif not any(i['path'] == 'mods' for i in game.metadata.get('categories', [])): + _ret.append(game) + + return _ret, _dlc + def get_launch_parameters(self, app_name: str, offline: bool = False, user: str = None, extra_args: list = None, wine_bin: str = None, wine_pfx: str = None, diff --git a/freeze.py b/freeze.py index 7f09deaa..356b656e 100644 --- a/freeze.py +++ b/freeze.py @@ -1,5 +1,7 @@ from cx_Freeze import setup, Executable +from rare import __version__ + # Dependencies are automatically detected, but it might need fine tuning. # "packages": ["os"] is used as example only @@ -26,7 +28,7 @@ base = "Win32GUI" setup( name="Rare", - version="1.5.0", + version=__version__, description="A GUI for Legendary", options={"build_exe": build_exe_options}, shortcutName="Rare", diff --git a/rare/components/tabs/games/__init__.py b/rare/components/tabs/games/__init__.py index 111ccc34..a8d9e353 100644 --- a/rare/components/tabs/games/__init__.py +++ b/rare/components/tabs/games/__init__.py @@ -95,7 +95,8 @@ class GameListHeadBar(QWidget): self.filter.addItems([self.tr("All"), self.tr("Installed only"), self.tr("Offline Games"), - self.tr("32 Bit Games")]) + self.tr("32 Bit Games"), + self.tr("Installable Games")]) self.filter.currentIndexChanged.connect(self.filter_changed) self.layout.addWidget(self.filter) self.layout.addStretch(1) @@ -128,4 +129,4 @@ class GameListHeadBar(QWidget): self.setLayout(self.layout) def filter_changed(self, i): - self.filter_changed_signal.emit(["", "installed", "offline", "32bit"][i]) + self.filter_changed_signal.emit(["", "installed", "offline", "32bit", "installable"][i]) diff --git a/rare/components/tabs/games/game_info/uninstalled_info.py b/rare/components/tabs/games/game_info/uninstalled_info.py index c2174283..73643fa4 100644 --- a/rare/components/tabs/games/game_info/uninstalled_info.py +++ b/rare/components/tabs/games/game_info/uninstalled_info.py @@ -45,7 +45,10 @@ class UninstalledTabInfo(QTabWidget): def update_game(self, app_name): self.info.update_game(app_name) self.model.clear() - self.model.load(json.load(open(os.path.expanduser(f"~/.config/legendary/metadata/{app_name}.json"), "r"))) + try: + self.model.load(json.load(open(os.path.expanduser(f"~/.config/legendary/metadata/{app_name}.json"), "r"))) + except: # ignore if no metadata + pass def keyPressEvent(self, e: QKeyEvent): if e.key() == Qt.Key_Escape: @@ -61,6 +64,8 @@ class UninstalledInfo(QWidget, Ui_GameInfo): self.setupUi(self) self.core = core + self.no_install_label.setVisible(False) + if platform.system() != "Windows": self.steam_worker = SteamWorker(self.core) self.steam_worker.rating_signal.connect(self.grade.setText) @@ -69,6 +74,8 @@ class UninstalledInfo(QWidget, Ui_GameInfo): self.lbl_grade.setVisible(False) self.grade.setVisible(False) + self.non_asset_games = [i.app_name for i in self.core.get_non_asset_library_items()[0]] + self.install_size.setEnabled(False) self.lbl_install_size.setEnabled(False) self.install_path.setEnabled(False) @@ -81,6 +88,7 @@ class UninstalledInfo(QWidget, Ui_GameInfo): def update_game(self, app_name): self.game = self.core.get_game(app_name) + self.game_title.setText(f"

{self.game.app_title}

") pixmap = get_pixmap(app_name) @@ -94,6 +102,13 @@ class UninstalledInfo(QWidget, Ui_GameInfo): self.install_size.setText("N/A") self.install_path.setText("N/A") + if app_name in self.non_asset_games: + self.no_install_label.setVisible(True) + self.install_button.setEnabled(False) + else: + self.no_install_label.setVisible(False) + self.install_button.setEnabled(True) + if platform.system() != "Windows": self.grade.setText(self.tr("Loading")) self.steam_worker.set_app_name(app_name) diff --git a/rare/components/tabs/games/game_list.py b/rare/components/tabs/games/game_list.py index 5fafe38b..046dc06a 100644 --- a/rare/components/tabs/games/game_list.py +++ b/rare/components/tabs/games/game_list.py @@ -77,6 +77,7 @@ class GameList(QStackedWidget): if not self.offline: self.bit32 = [i.app_name for i in self.core.get_game_and_dlc_list(True, "Win32")[0]] self.mac_games = [i.app_name for i in self.core.get_game_and_dlc_list(True, "Mac")[0]] + self.no_assets = [i.app_name for i in self.core.get_non_asset_library_items()[0]] else: self.bit32 = [] self.mac_games = [] @@ -96,13 +97,13 @@ class GameList(QStackedWidget): installed = [i.app_name for i in self.core.get_installed_list()] # get Uninstalled games games, self.dlcs = self.core.get_game_and_dlc_list(update_assets=not self.offline) - for game in sorted(games, key=lambda x: x.app_title): + for game in games: if not game.app_name in installed: self.uninstalled_games.append(game) # add uninstalled games - - for game in self.uninstalled_games: + self.uninstalled_games += self.core.get_non_asset_library_items()[0] + for game in sorted(self.uninstalled_games, key=lambda x: x.app_title): icon_widget, list_widget = self.add_uninstalled_widget(game) self.icon_layout.addWidget(icon_widget) @@ -264,6 +265,8 @@ class GameList(QStackedWidget): w.setVisible(w.game.app_name in self.bit32) elif filter == "mac": w.setVisible(w.game.app_name in self.mac_games) + elif filter == "installable": + w.setVisible(w.game.app_name not in self.no_assets) else: # All visible w.setVisible(True) diff --git a/rare/ui/components/tabs/games/game_info/game_info.py b/rare/ui/components/tabs/games/game_info/game_info.py index ccfb0d78..5f75e9ad 100644 --- a/rare/ui/components/tabs/games/game_info/game_info.py +++ b/rare/ui/components/tabs/games/game_info/game_info.py @@ -14,6 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets class Ui_GameInfo(object): def setupUi(self, GameInfo): GameInfo.setObjectName("GameInfo") + GameInfo.resize(571, 326) self.layout_game_info = QtWidgets.QGridLayout(GameInfo) self.layout_game_info.setObjectName("layout_game_info") self.layout_game_info_form = QtWidgets.QGridLayout() @@ -182,15 +183,20 @@ class Ui_GameInfo(object): self.install_button.setStyleSheet("") self.install_button.setObjectName("install_button") self.uninstalled_layout.addWidget(self.install_button) + self.no_install_label = QtWidgets.QLabel(self.uninstalled_page) + self.no_install_label.setWordWrap(True) + self.no_install_label.setObjectName("no_install_label") + self.uninstalled_layout.addWidget(self.no_install_label) self.game_actions_stack.addWidget(self.uninstalled_page) - self.layout_game_info_form.addWidget(self.game_actions_stack, 6, 1, 1, 1, QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop) + self.layout_game_info_form.addWidget(self.game_actions_stack, 6, 1, 1, 1, + QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop) self.layout_game_info.addLayout(self.layout_game_info_form, 2, 1, 1, 1) self.image = QtWidgets.QLabel(GameInfo) self.image.setFrameShape(QtWidgets.QFrame.StyledPanel) self.image.setFrameShadow(QtWidgets.QFrame.Sunken) self.image.setText("") self.image.setObjectName("image") - self.layout_game_info.addWidget(self.image, 2, 0, 1, 1, QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop) + self.layout_game_info.addWidget(self.image, 2, 0, 1, 1, QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop) self.game_title = QtWidgets.QLabel(GameInfo) self.game_title.setText("error") self.game_title.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByMouse) @@ -198,7 +204,7 @@ class Ui_GameInfo(object): self.layout_game_info.addWidget(self.game_title, 0, 0, 1, 3) self.retranslateUi(GameInfo) - self.game_actions_stack.setCurrentIndex(0) + self.game_actions_stack.setCurrentIndex(1) self.verify_widget.setCurrentIndex(0) QtCore.QMetaObject.connectSlotsByName(GameInfo) @@ -216,6 +222,8 @@ class Ui_GameInfo(object): self.repair_button.setText(_translate("GameInfo", "Repair Instalation")) self.uninstall_button.setText(_translate("GameInfo", "Uninstall Game")) self.install_button.setText(_translate("GameInfo", "Install Game")) + self.no_install_label.setText( + _translate("GameInfo", "It is not possible to install the Game. It could be from a third party store")) if __name__ == "__main__": diff --git a/rare/ui/components/tabs/games/game_info/game_info.ui b/rare/ui/components/tabs/games/game_info/game_info.ui index dcc89672..a6d0fae7 100644 --- a/rare/ui/components/tabs/games/game_info/game_info.ui +++ b/rare/ui/components/tabs/games/game_info/game_info.ui @@ -2,16 +2,24 @@ GameInfo - - Game Info - - - - - - 6 + + + 0 + 0 + 571 + 326 + - + + Game Info + + + + + + 6 + + 6 @@ -248,29 +256,29 @@ - 0 + 1 - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 0 - - - + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 0 + + + 0 @@ -343,18 +351,28 @@ - - - - - - - - Install Game - - - - + + + + + + + + Install Game + + + + + + + It is not possible to install the Game. It could be from a third party store + + + true + + + + diff --git a/rare/utils/steam_grades.py b/rare/utils/steam_grades.py index 951aa385..b146935e 100644 --- a/rare/utils/steam_grades.py +++ b/rare/utils/steam_grades.py @@ -44,7 +44,9 @@ def get_rating(app_name: str, core: LegendaryCore): grades = {} if not grades.get(app_name): - steam_id = get_steam_id(core.get_game(app_name).app_title) + game = core.get_game(app_name) + + steam_id = get_steam_id(game.app_title) grade = get_grade(steam_id) grades[app_name] = { "steam_id": steam_id, diff --git a/rare/utils/utils.py b/rare/utils/utils.py index af3f74f6..90ce4268 100644 --- a/rare/utils/utils.py +++ b/rare/utils/utils.py @@ -36,7 +36,10 @@ def download_images(signal: pyqtSignal, core: LegendaryCore): dlc_list = [] for i in dlcs.values(): dlc_list.append(i[0]) - game_list = games + dlc_list + + no_assets = core.get_non_asset_library_items()[0] + + game_list = games + dlc_list + no_assets for i, game in enumerate(game_list): try: download_image(game)