1
0
Fork 0
mirror of synced 2024-07-03 05:31:23 +12:00
Rare/rare/components/tabs/games/__init__.py

517 lines
21 KiB
Python
Raw Normal View History

2021-09-27 03:43:56 +13:00
from logging import getLogger
2021-12-20 09:32:18 +13:00
from typing import Tuple, Dict, Union, List
2021-10-15 10:05:00 +13:00
from PyQt5.QtCore import QSettings, QObjectCleanupHandler
2021-09-27 03:43:56 +13:00
from PyQt5.QtWidgets import QStackedWidget, QVBoxLayout, QWidget
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton, ApiResultsSingleton
2021-12-20 09:32:18 +13:00
from legendary.models.game import InstalledGame, Game
2021-09-27 03:43:56 +13:00
from rare.ui.components.tabs.games.games_tab import Ui_GamesTab
from rare.utils.extra_widgets import FlowLayout
from rare.utils.utils import get_pixmap, download_image, get_uninstalled_pixmap
from .cloud_save_utils import CloudSaveUtils
2021-11-13 12:28:27 +13:00
from .cloud_save_utils import CloudSaveUtils
from .game_info import GameInfoTabs
from .game_info.uninstalled_info import UninstalledInfoTabs
from .game_utils import GameUtils
from .game_widgets.base_installed_widget import BaseInstalledWidget
from .game_widgets.base_uninstalled_widget import BaseUninstalledWidget
from .game_widgets.installed_icon_widget import InstalledIconWidget
from .game_widgets.installed_list_widget import InstalledListWidget
from .game_widgets.installing_game_widget import InstallingGameWidget
from .game_widgets.uninstalled_icon_widget import IconWidgetUninstalled
from .game_widgets.uninstalled_list_widget import ListWidgetUninstalled
from .head_bar import GameListHeadBar
from .import_sync import ImportSyncTabs
2021-09-27 03:43:56 +13:00
logger = getLogger("GamesTab")
2021-09-27 03:43:56 +13:00
class GamesTab(QStackedWidget, Ui_GamesTab):
2021-12-20 09:32:18 +13:00
widgets: Dict[str, Tuple[
Union[InstalledIconWidget, IconWidgetUninstalled], Union[InstalledListWidget, ListWidgetUninstalled]]] = dict()
running_games = list()
updates = set()
2021-11-02 08:39:47 +13:00
active_filter = 0
2021-09-27 03:43:56 +13:00
def __init__(self, parent=None):
super(GamesTab, self).__init__(parent=parent)
2021-09-27 03:43:56 +13:00
self.setupUi(self)
self.core = LegendaryCoreSingleton()
self.signals = GlobalSignalsSingleton()
self.args = ArgumentsSingleton()
self.api_results = ApiResultsSingleton()
2021-09-27 03:43:56 +13:00
self.settings = QSettings()
self.game_list: List[Game] = self.api_results.game_list
self.dlcs = self.api_results.dlcs
self.bit32 = self.api_results.bit32_games
self.mac_games = self.api_results.mac_games
self.no_assets = self.api_results.no_asset_games
2021-10-11 08:52:11 +13:00
2021-11-17 10:54:23 +13:00
self.game_utils = GameUtils(parent=self)
self.head_bar = GameListHeadBar(self)
self.head_bar.import_clicked.connect(self.show_import)
self.head_bar.egl_sync_clicked.connect(self.show_egl_sync)
2021-09-27 03:43:56 +13:00
self.games.layout().insertWidget(0, self.head_bar)
self.game_info_tabs = GameInfoTabs(self.dlcs, self.game_utils, self)
self.game_info_tabs.back_clicked.connect(lambda: self.setCurrentIndex(0))
self.addWidget(self.game_info_tabs)
2021-12-24 22:09:50 +13:00
self.game_info_tabs.info.verification_finished.connect(
self.verification_finished
)
2021-11-17 10:54:23 +13:00
self.game_info_tabs.info.uninstalled.connect(lambda x: self.setCurrentIndex(0))
self.import_sync_tabs = ImportSyncTabs(self)
self.import_sync_tabs.back_clicked.connect(lambda: self.setCurrentIndex(0))
self.addWidget(self.import_sync_tabs)
self.uninstalled_info_tabs = UninstalledInfoTabs(self)
self.uninstalled_info_tabs.back_clicked.connect(lambda: self.setCurrentIndex(0))
self.addWidget(self.uninstalled_info_tabs)
2021-09-27 03:43:56 +13:00
# navigation
self.head_bar.import_game.clicked.connect(lambda: self.setCurrentIndex(2))
2021-10-04 08:29:33 +13:00
self.no_asset_names = []
if not self.args.offline:
2021-10-04 08:29:33 +13:00
for game in self.no_assets:
self.no_asset_names.append(game.app_name)
else:
self.no_assets = []
2021-12-20 09:32:18 +13:00
for i in self.game_list:
if i.app_name.startswith("UE_4"):
pixmap = get_pixmap(i.app_name)
if pixmap.isNull():
continue
2021-12-20 09:32:18 +13:00
self.ue_name = i.app_name
logger.debug(f"Found Unreal AppName {self.ue_name}")
2021-12-20 09:32:18 +13:00
break
else:
logger.warning("No Unreal engine in library found")
self.ue_name = ""
2021-11-29 13:23:33 +13:00
self.installed = self.core.get_installed_list()
2021-09-27 03:43:56 +13:00
self.setup_game_list()
if not self.settings.value("icon_view", True, bool):
self.scroll_widget.layout().insertWidget(1, self.list_view)
self.head_bar.view.list()
else:
self.scroll_widget.layout().insertWidget(1, self.icon_view)
2021-11-02 08:39:47 +13:00
self.head_bar.search_bar.textChanged.connect(lambda x: self.filter_games("", x))
self.head_bar.filterChanged.connect(self.filter_games)
2021-09-27 03:43:56 +13:00
self.head_bar.refresh_list.clicked.connect(self.update_list)
self.head_bar.view.toggled.connect(self.toggle_view)
2021-11-02 08:39:47 +13:00
f = self.settings.value("filter", 0, int)
if f >= len(self.head_bar.available_filters):
f = 0
2021-11-02 08:39:47 +13:00
self.active_filter = self.head_bar.available_filters[f]
self.filter_games(self.active_filter)
2021-09-30 10:22:47 +13:00
2021-10-15 10:05:00 +13:00
# signals
self.signals.dl_progress.connect(self.installing_widget.set_status)
self.signals.installation_started.connect(self.installation_started)
self.signals.update_gamelist.connect(self.update_list)
2021-12-24 22:09:50 +13:00
self.signals.installation_finished.connect(
self.installation_finished
2021-12-24 22:09:50 +13:00
)
2021-11-26 09:54:34 +13:00
self.signals.game_uninstalled.connect(lambda name: self.update_list([name]))
2021-10-15 10:05:00 +13:00
2021-11-17 10:54:23 +13:00
self.game_utils.update_list.connect(self.update_list)
self.game_list_scroll_area.horizontalScrollBar().setDisabled(True)
def installation_finished(self, app_name: str):
self.installing_widget.setVisible(False)
self.installing_widget.set_game("")
self.filter_games("")
def installation_started(self, app_name: str):
game = self.core.get_game(app_name, False)
if not game:
return
2021-10-15 10:05:00 +13:00
if game.is_dlc:
return
self.installing_widget.set_game(app_name)
2021-10-15 10:05:00 +13:00
self.installing_widget.setVisible(True)
i_widget, l_widget = self.widgets.get(app_name, (None, None))
if not i_widget or not l_widget:
return
i_widget.setVisible(False)
l_widget.setVisible(False)
2021-10-15 10:05:00 +13:00
def verification_finished(self, igame: InstalledGame):
# only if igame needs verification
i_widget, l_widget = self.widgets[igame.app_name]
i_widget.igame = igame
l_widget.igame = igame
i_widget.leaveEvent(None)
l_widget.update_text()
2021-10-15 10:05:00 +13:00
def show_import(self):
self.setCurrentIndex(2)
self.import_sync_tabs.show_import()
def show_egl_sync(self, idx):
self.setCurrentIndex(2)
self.import_sync_tabs.show_egl_sync()
def show_game_info(self, app_name):
self.game_info_tabs.update_game(app_name)
2021-09-27 03:43:56 +13:00
self.setCurrentIndex(1)
def show_uninstalled_info(self, game):
self.uninstalled_info_tabs.update_game(game)
2021-09-27 03:43:56 +13:00
self.setCurrentIndex(3)
2021-09-27 03:43:56 +13:00
def setup_game_list(self):
self.icon_view = QWidget()
self.icon_view.setLayout(FlowLayout())
self.list_view = QWidget()
self.list_view.setLayout(QVBoxLayout())
2021-09-27 03:43:56 +13:00
self.update_count_games_label()
2021-09-27 03:43:56 +13:00
# add installing game widget for icon view: List view not supported
self.installing_widget = InstallingGameWidget()
self.icon_view.layout().addWidget(self.installing_widget)
self.installing_widget.setVisible(False)
2021-09-27 03:43:56 +13:00
# add installed games
2021-11-29 13:23:33 +13:00
for igame in sorted(self.core.get_installed_list(), key=lambda x: x.title):
2021-10-24 12:47:49 +13:00
icon_widget, list_widget = self.add_installed_widget(igame.app_name)
2021-09-27 03:43:56 +13:00
self.icon_view.layout().addWidget(icon_widget)
self.list_view.layout().addWidget(list_widget)
2021-09-27 03:43:56 +13:00
for game in self.no_assets:
2021-10-24 12:47:49 +13:00
icon_widget, list_widget = self.add_installed_widget(game.app_name)
2022-03-17 05:46:57 +13:00
if not icon_widget or not list_widget:
logger.warning(f"Ignoring {game.app_name} in game list")
continue
2021-09-27 03:43:56 +13:00
self.icon_view.layout().addWidget(icon_widget)
self.list_view.layout().addWidget(list_widget)
2021-10-04 08:29:33 +13:00
self.uninstalled_games = []
for game in sorted(self.game_list, key=lambda x: x.app_title):
2021-11-29 13:23:33 +13:00
if not self.core.is_installed(game.app_name):
2021-10-04 08:29:33 +13:00
self.uninstalled_games.append(game)
2021-09-27 03:43:56 +13:00
icon_widget, list_widget = self.add_uninstalled_widget(game)
self.icon_view.layout().addWidget(icon_widget)
self.list_view.layout().addWidget(list_widget)
2021-09-27 03:43:56 +13:00
def update_count_games_label(self):
2021-12-24 22:09:50 +13:00
self.count_games_label.setText(
self.tr("Installed Games: {} Available Games: {}").format(
len(self.core.get_installed_list()), len(self.game_list)
)
)
2021-09-27 03:43:56 +13:00
2021-10-24 12:47:49 +13:00
def add_installed_widget(self, app_name):
pixmap = get_pixmap(app_name)
2021-12-27 11:03:50 +13:00
try:
2021-12-20 09:32:18 +13:00
if pixmap.isNull():
logger.info(f"{app_name} has a corrupt image.")
2021-12-20 09:32:18 +13:00
if app_name in self.no_asset_names and self.core.get_asset(app_name).namespace != "ue":
download_image(self.core.get_game(app_name), force=True)
pixmap = get_pixmap(app_name)
elif self.ue_name:
pixmap = get_pixmap(self.ue_name)
2021-12-27 11:03:50 +13:00
icon_widget = InstalledIconWidget(app_name, pixmap, self.game_utils)
list_widget = InstalledListWidget(app_name, pixmap, self.game_utils)
except Exception as e:
logger.error(f"{app_name} is broken. Don't add it to game list: {e}")
2022-03-17 05:46:57 +13:00
return None, None
2021-10-24 12:47:49 +13:00
self.widgets[app_name] = (icon_widget, list_widget)
2021-09-27 03:43:56 +13:00
icon_widget.show_info.connect(self.show_game_info)
list_widget.show_info.connect(self.show_game_info)
if icon_widget.update_available:
2021-10-24 12:47:49 +13:00
self.updates.add(app_name)
2021-09-27 03:43:56 +13:00
return icon_widget, list_widget
def add_uninstalled_widget(self, game):
pixmap = get_uninstalled_pixmap(game.app_name)
2021-12-27 11:03:50 +13:00
try:
2021-12-20 09:32:18 +13:00
if pixmap.isNull():
if self.core.get_asset(game.app_name).namespace != "ue":
logger.warning(f"{game.app_title} has a corrupt image. Reloading...")
2021-12-20 09:32:18 +13:00
download_image(game, force=True)
pixmap = get_uninstalled_pixmap(game.app_name)
elif self.ue_name:
pixmap = get_uninstalled_pixmap(self.ue_name)
2021-12-27 11:03:50 +13:00
icon_widget = IconWidgetUninstalled(game, self.core, pixmap)
list_widget = ListWidgetUninstalled(self.core, game, pixmap)
except Exception as e:
logger.error(f"{game.app_name} is broken. Don't add it to game list: {e}")
2022-03-17 05:46:57 +13:00
return None, None
2021-09-27 03:43:56 +13:00
icon_widget.show_uninstalled_info.connect(self.show_uninstalled_info)
list_widget.show_uninstalled_info.connect(self.show_uninstalled_info)
self.widgets[game.app_name] = (icon_widget, list_widget)
return icon_widget, list_widget
def filter_games(self, filter_name="all", search_text: str = ""):
2021-11-02 08:39:47 +13:00
if not search_text and (t := self.head_bar.search_bar.text()):
search_text = t
if filter_name:
self.active_filter = filter_name
if not filter_name and (t := self.active_filter):
filter_name = t
2021-09-27 03:43:56 +13:00
def get_visibility(widget):
app_name = widget.game.app_name
if not isinstance(widget,
InstallingGameWidget) and self.installing_widget.game and self.installing_widget.game.app_name == app_name:
visible = False
elif filter_name == "installed":
2021-12-20 09:32:18 +13:00
visible = self.core.is_installed(app_name)
elif filter_name == "offline":
if self.core.is_installed(app_name) and not isinstance(widget, InstallingGameWidget):
visible = widget.igame.can_run_offline
else:
2021-11-02 08:39:47 +13:00
visible = False
2021-12-20 09:32:18 +13:00
elif filter_name == "32bit" and self.bit32:
visible = app_name in self.bit32
elif filter_name == "mac" and self.mac_games:
visible = app_name in self.mac_games
elif filter_name == "installable":
visible = app_name not in self.no_asset_names
elif filter_name == "include_ue":
visible = True
elif filter_name == "all":
# All visible except ue
try:
visible = self.core.get_asset(app_name, update=False).namespace != "ue"
except ValueError:
visible = True
else:
visible = True
if (
search_text.lower() not in app_name.lower()
and search_text.lower() not in widget.game.app_title.lower()
2021-12-20 09:32:18 +13:00
):
visible = False
return visible
for t in self.widgets.values():
visible = get_visibility(t[0])
2021-12-20 09:32:18 +13:00
for w in t:
2021-11-02 08:39:47 +13:00
w.setVisible(visible)
2021-09-27 03:43:56 +13:00
if self.installing_widget.game:
self.installing_widget.setVisible(get_visibility(self.installing_widget))
def update_list(self, app_names: list = None):
logger.debug(f"Updating list for {app_names}")
if app_names:
update_list = False
for app_name in app_names:
if widgets := self.widgets.get(app_name):
# from update
2021-12-24 22:09:50 +13:00
if self.core.is_installed(widgets[0].game.app_name) and isinstance(
widgets[0], BaseInstalledWidget
2021-12-24 22:09:50 +13:00
):
logger.debug(f"Update Gamelist: Updated: {app_name}")
igame = self.core.get_installed_game(app_name)
for w in widgets:
w.igame = igame
2021-12-24 22:09:50 +13:00
w.update_available = (
self.core.get_asset(
w.game.app_name, w.igame.platform, False
).build_version
!= igame.version
2021-12-24 22:09:50 +13:00
)
widgets[0].leaveEvent(None)
# new installed
2021-12-24 22:09:50 +13:00
elif self.core.is_installed(app_name) and isinstance(
widgets[0], BaseUninstalledWidget
2021-12-24 22:09:50 +13:00
):
logger.debug(f"Update Gamelist: New installed {app_name}")
self.widgets[app_name][0].deleteLater()
self.widgets[app_name][1].deleteLater()
self.widgets.pop(app_name)
2021-10-24 12:47:49 +13:00
self.add_installed_widget(app_name)
update_list = True
# uninstalled
2021-12-24 22:09:50 +13:00
elif not self.core.is_installed(
widgets[0].game.app_name
2021-12-24 22:09:50 +13:00
) and isinstance(widgets[0], BaseInstalledWidget):
logger.debug(f"Update list: Uninstalled: {app_name}")
self.widgets[app_name][0].deleteLater()
self.widgets[app_name][1].deleteLater()
self.widgets.pop(app_name)
game = self.core.get_game(app_name, False)
2022-03-17 05:46:57 +13:00
try:
self.add_uninstalled_widget(game)
except Exception:
pass
update_list = True
2021-10-24 12:47:49 +13:00
# do not update, if only update finished
if update_list:
self._update_games()
2021-09-27 03:43:56 +13:00
else:
installed_names = [i.app_name for i in self.core.get_installed_list()]
# get Uninstalled games
uninstalled_names = []
games = self.core.get_game_list(True)
for game in sorted(games, key=lambda x: x.app_title):
if not game.app_name in installed_names:
uninstalled_names.append(game.app_name)
2021-12-24 22:09:50 +13:00
new_installed_games = list(
set(installed_names) - set([i.app_name for i in self.installed])
)
new_uninstalled_games = list(
set(uninstalled_names)
- set([i.app_name for i in self.uninstalled_games])
)
2021-09-27 03:43:56 +13:00
if (not new_uninstalled_games) and (not new_installed_games):
return
if new_installed_games:
for name in new_installed_games:
self.widgets[name][0].deleteLater()
self.widgets[name][1].deleteLater()
self.widgets.pop(name)
self.add_installed_widget(name)
2021-09-27 03:43:56 +13:00
for name in new_uninstalled_games:
self.icon_view.layout().removeWidget(self.widgets[name][0])
self.list_view.layout().removeWidget(self.widgets[name][1])
2021-09-27 03:43:56 +13:00
self.widgets[name][0].deleteLater()
self.widgets[name][1].deleteLater()
self.widgets.pop(name)
game = self.core.get_game(name, False)
2022-03-17 05:46:57 +13:00
try:
self.add_uninstalled_widget(game)
except Exception:
pass
2021-09-27 03:43:56 +13:00
2021-12-24 22:09:50 +13:00
for igame in sorted(
self.core.get_installed_list(), key=lambda x: x.title
2021-12-24 22:09:50 +13:00
):
2021-09-27 03:43:56 +13:00
i_widget, list_widget = self.widgets[igame.app_name]
self.icon_view.layout().addWidget(i_widget)
self.list_view.layout().addWidget(list_widget)
2021-11-29 13:23:33 +13:00
self.installed = self.core.get_installed_list()
2021-09-27 03:43:56 +13:00
for game in self.no_assets:
i_widget, list_widget = self.widgets[game.app_name]
self.icon_view.layout().addWidget(i_widget)
self.list_view.layout().addWidget(list_widget)
2021-09-27 03:43:56 +13:00
# get Uninstalled games
2021-11-29 13:23:33 +13:00
self.uninstalled_games = []
2021-09-27 03:43:56 +13:00
games, self.dlcs = self.core.get_game_and_dlc_list()
for game in sorted(games, key=lambda x: x.app_title):
2021-12-24 22:09:50 +13:00
if (
not self.core.is_installed(game.app_name)
and game.app_name not in self.no_asset_names
2021-12-24 22:09:50 +13:00
):
i_widget, list_widget = self.widgets[game.app_name]
self.icon_view.layout().addWidget(i_widget)
self.list_view.layout().addWidget(list_widget)
2021-11-29 13:23:33 +13:00
self.uninstalled_games.append(game)
2021-09-27 03:43:56 +13:00
self.update_count_games_label()
def _update_games(self):
icon_layout = FlowLayout()
list_layout = QVBoxLayout()
icon_layout.addWidget(self.installing_widget)
for igame in sorted(self.core.get_installed_list(), key=lambda x: x.title) + self.no_assets:
i_widget, l_widget = self.widgets.get(igame.app_name, (None, None))
if i_widget and l_widget:
icon_layout.addWidget(i_widget)
list_layout.addWidget(l_widget)
else:
logger.warning("Found installed game, without widget. Generating widget... ")
try:
i_widget, l_widget = self.add_installed_widget(igame.app_name)
icon_layout.addWidget(i_widget)
list_layout.addWidget(l_widget)
except Exception as e:
logger.error(str(e))
continue
2021-09-27 03:43:56 +13:00
# get Uninstalled games
self.game_list, self.dlcs = self.core.get_game_and_dlc_list(update_assets=False)
2021-09-27 03:43:56 +13:00
# add uninstalled games
for game in sorted(self.game_list, key=lambda x: x.app_title):
if self.core.is_installed(game.app_name) or game.app_name in self.no_asset_names:
continue
i_widget, list_widget = self.widgets.get(game.app_name, (None, None))
if i_widget and list_widget:
icon_layout.addWidget(i_widget)
list_layout.addWidget(list_widget)
else:
logger.warning("Found installed game, without widget. Generating widget... ")
try:
i_widget, l_widget = self.add_uninstalled_widget(game)
2022-03-17 05:46:57 +13:00
if not i_widget or not l_widget:
logger.warning(f"Ignoring {game.app_name}")
continue
icon_layout.addWidget(i_widget)
list_layout.addWidget(l_widget)
except Exception as e:
logger.error(str(e))
continue
QObjectCleanupHandler().add(self.icon_view.layout())
QObjectCleanupHandler().add(self.list_view.layout())
2021-09-27 03:43:56 +13:00
self.icon_view.setLayout(icon_layout)
self.list_view.setLayout(list_layout)
self.icon_view.setParent(None)
self.list_view.setParent(None)
# insert widget in layout
2021-12-24 22:09:50 +13:00
self.scroll_widget.layout().insertWidget(
1, self.icon_view if self.head_bar.view.isChecked() else self.list_view
)
2021-09-27 03:43:56 +13:00
def toggle_view(self):
self.settings.setValue("icon_view", not self.head_bar.view.isChecked())
if not self.head_bar.view.isChecked():
self.scroll_widget.layout().replaceWidget(self.list_view, self.icon_view)
self.list_view.setParent(None)
else:
self.scroll_widget.layout().replaceWidget(self.icon_view, self.list_view)
self.icon_view.setParent(None)
self.game_list_scroll_area.verticalScrollBar().setValue(0)