from typing import Tuple, List, Union, Optional from PyQt5.QtCore import QObject, pyqtSlot from PyQt5.QtWidgets import QWidget from rare.lgndr.core import LegendaryCore from rare.models.game import RareGame from rare.models.signals import GlobalSignals from rare.shared import RareCore from .icon_game_widget import IconGameWidget from .list_game_widget import ListGameWidget class LibraryWidgetController(QObject): def __init__(self, icon_container: QWidget, list_container: QWidget, parent: QWidget = None): super(LibraryWidgetController, self).__init__(parent=parent) self._icon_container: QWidget = icon_container self._list_container: QWidget = list_container self.rcore = RareCore.instance() self.core: LegendaryCore = self.rcore.core() self.signals: GlobalSignals = self.rcore.signals() self.signals.game.installed.connect(self.sort_list) self.signals.game.uninstalled.connect(self.sort_list) def add_game(self, rgame: RareGame): return self.add_widgets(rgame) def add_widgets(self, rgame: RareGame) -> Tuple[IconGameWidget, ListGameWidget]: icon_widget = IconGameWidget(rgame, self._icon_container) list_widget = ListGameWidget(rgame, self._list_container) return icon_widget, list_widget @staticmethod def __visibility(widget: Union[IconGameWidget,ListGameWidget], filter_name, search_text) -> Tuple[bool, float]: if filter_name == "hidden": visible = "hidden" in widget.rgame.metadata.tags elif "hidden" in widget.rgame.metadata.tags: visible = False elif filter_name == "installed": visible = widget.rgame.is_installed and not widget.rgame.is_unreal elif filter_name == "offline": visible = widget.rgame.can_run_offline and not widget.rgame.is_unreal elif filter_name == "32bit": visible = widget.rgame.is_win32 and not widget.rgame.is_unreal elif filter_name == "mac": visible = widget.rgame.is_mac and not widget.rgame.is_unreal elif filter_name == "installable": visible = not widget.rgame.is_non_asset and not widget.rgame.is_unreal elif filter_name == "include_ue": visible = True elif filter_name == "all": visible = not widget.rgame.is_unreal else: visible = True if ( search_text not in widget.rgame.app_name.lower() and search_text not in widget.rgame.app_title.lower() ): opacity = 0.25 else: opacity = 1.0 return visible, opacity def filter_list(self, filter_name="all", search_text: str = ""): icon_widgets = self._icon_container.findChildren(IconGameWidget) list_widgets = self._list_container.findChildren(ListGameWidget) for iw in icon_widgets: visibility, opacity = self.__visibility(iw, filter_name, search_text) iw.setOpacity(opacity) iw.setVisible(visibility) for lw in list_widgets: visibility, opacity = self.__visibility(lw, filter_name, search_text) lw.setOpacity(opacity) lw.setVisible(visibility) self.sort_list(search_text) @pyqtSlot() def sort_list(self, sort_by: str = ""): # lk: this is the existing sorting implemenation # lk: it sorts by installed then by title if sort_by: self._icon_container.layout().sort(lambda x: (sort_by not in x.widget().rgame.app_title.lower(),)) else: self._icon_container.layout().sort( key=lambda x: ( # Sort by grant date # x.widget().rgame.is_installed, # not x.widget().rgame.is_non_asset, # x.widget().rgame.grant_date(), # ), reverse=True not x.widget().rgame.is_installed, x.widget().rgame.is_non_asset, x.widget().rgame.app_title, ) ) list_widgets = self._list_container.findChildren(ListGameWidget) if sort_by: list_widgets.sort(key=lambda x: (sort_by not in x.rgame.app_title.lower(),)) else: list_widgets.sort( # Sort by grant date # key=lambda x: (x.rgame.is_installed, not x.rgame.is_non_asset, x.rgame.grant_date()), reverse=True key=lambda x: (not x.rgame.is_installed, x.rgame.is_non_asset, x.rgame.app_title) ) for idx, wl in enumerate(list_widgets): self._list_container.layout().insertWidget(idx, wl) @pyqtSlot() @pyqtSlot(list) def update_list(self, app_names: List[str] = None): if not app_names: # lk: base it on icon widgets, the two lists should be identical icon_widgets = self._icon_container.findChildren(IconGameWidget) list_widgets = self._list_container.findChildren(ListGameWidget) icon_app_names = set([iw.rgame.app_name for iw in icon_widgets]) list_app_names = set([lw.rgame.app_name for lw in list_widgets]) games = list(self.rcore.games) game_app_names = set([g.app_name for g in games]) new_icon_app_names = game_app_names.difference(icon_app_names) new_list_app_names = game_app_names.difference(list_app_names) for app_name in new_icon_app_names: game = self.rcore.get_game(app_name) iw = IconGameWidget(game) self._icon_container.layout().addWidget(iw) for app_name in new_list_app_names: game = self.rcore.get_game(app_name) lw = ListGameWidget(game) self._list_container.layout().addWidget(lw) self.sort_list() def __find_widget(self, app_name: str) -> Tuple[Union[IconGameWidget, None], Union[ListGameWidget, None]]: iw = self._icon_container.findChild(IconGameWidget, app_name) lw = self._list_container.findChild(ListGameWidget, app_name) return iw, lw