diff --git a/rare/components/main_window.py b/rare/components/main_window.py index 19f1adeb..0f3f5945 100644 --- a/rare/components/main_window.py +++ b/rare/components/main_window.py @@ -36,17 +36,17 @@ class MainWindow(QMainWindow): if not args.offline: self.rpc = DiscordRPC(core) # Discord RPC on game launch - self.tab_widget.games_tab.default_widget.game_list.game_started.connect( - lambda: self.rpc.set_discord_rpc(self.tab_widget.games_tab.default_widget.game_list.running_games[0])) + #self.tab_widget.games_tab.default_widget.game_list.game_started.connect( + # lambda: self.rpc.set_discord_rpc(self.tab_widget.games_tab.default_widget.game_list.running_games[0])) # Remove RPC self.tab_widget.delete_presence.connect(self.rpc.set_discord_rpc) # Show RPC on changed rare_settings self.tab_widget.settings.rare_settings.rpc.update_settings.connect( lambda: self.rpc.changed_settings(self.tab_widget.games_tab.default_widget.game_list.running_games)) - game = self.tab_widget.games_tab.default_widget.game_list.active_game - if game != ("", 0) and not args.offline: - self.rpc.set_discord_rpc(game[0]) # Appname + #game = self.tab_widget.games_tab.default_widget.game_list.active_game + #if game != ("", 0) and not args.offline: + # self.rpc.set_discord_rpc(game[0]) # Appname if args.subparser == "launch": logger.info("Launching " + self.core.get_installed_game(args.app_name).title) diff --git a/rare/components/tabs/games/__init__.py b/rare/components/tabs/games/__init__.py index a60d71e5..289a4a34 100644 --- a/rare/components/tabs/games/__init__.py +++ b/rare/components/tabs/games/__init__.py @@ -1,134 +1,404 @@ -from PyQt5.QtCore import QSettings, QSize, pyqtSignal -from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QLineEdit, QPushButton, QStackedLayout, \ - QLabel, QComboBox -from qtawesome import icon +from logging import getLogger -from legendary.models.game import Game +from PyQt5.QtCore import pyqtSignal, QSettings +from PyQt5.QtWidgets import QStackedWidget, QVBoxLayout, QWidget + +from legendary.core import LegendaryCore +from legendary.models.game import GameAsset from rare.components.tabs.games.game_info import InfoTabs -from rare.components.tabs.games.game_info.uninstalled_info import UninstalledInfo, UninstalledTabInfo -from rare.components.tabs.games.game_list import GameList +from rare.components.tabs.games.game_info.uninstalled_info import UninstalledTabInfo +from rare.components.tabs.games.game_widgets.base_installed_widget import BaseInstalledWidget +from rare.components.tabs.games.game_widgets.base_uninstalled_widget import BaseUninstalledWidget +from rare.components.tabs.games.game_widgets.installed_icon_widget import InstalledIconWidget +from rare.components.tabs.games.game_widgets.installed_list_widget import InstalledListWidget +from rare.components.tabs.games.game_widgets.installing_game_widget import InstallingGameWidget +from rare.components.tabs.games.game_widgets.uninstalled_icon_widget import IconWidgetUninstalled +from rare.components.tabs.games.game_widgets.uninstalled_list_widget import ListWidgetUninstalled +from rare.components.tabs.games.head_bar import GameListHeadBar from rare.components.tabs.games.import_widget import ImportWidget -from rare.utils.extra_widgets import SelectViewWidget +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 + +logger = getLogger("GamesTab") -class GameTab(QWidget): - def __init__(self, core, parent, offline): - super(GameTab, self).__init__(parent=parent) - self.setLayout(QStackedLayout()) - self.default_widget = Games(core, self, offline) - # Signal to show info - self.default_widget.game_list.show_game_info.connect(self.show_info) - self.default_widget.head_bar.import_game.clicked.connect(lambda: self.layout().setCurrentIndex(2)) - self.layout().addWidget(self.default_widget) +class GamesTab(QStackedWidget, Ui_GamesTab): + updates = [] + widgets = {} + running_games = [] + game_exited = pyqtSignal(str) - self.game_info = InfoTabs(core, self) + game_started = pyqtSignal(str) + + def __init__(self, core: LegendaryCore, offline): + super(GamesTab, self).__init__() + self.setupUi(self) + self.core = core + self.offline = offline + self.settings = QSettings() + + self.head_bar = GameListHeadBar() + self.games.layout().insertWidget(0, self.head_bar) + + self.game_info = InfoTabs(self.core, self) self.game_info.info.update_list.connect(self.update_list) - self.layout().addWidget(self.game_info) - - self.default_widget.head_bar.refresh_list.clicked.connect(self.update_list) + self.addWidget(self.game_info) self.import_widget = ImportWidget(core, self) - self.layout().addWidget(self.import_widget) - self.import_widget.back_button.clicked.connect(lambda: self.layout().setCurrentIndex(0)) - self.import_widget.update_list.connect(self.update_list) + self.addWidget(self.import_widget) self.uninstalled_info_widget = UninstalledTabInfo(core, self) self.layout().addWidget(self.uninstalled_info_widget) - # self.uninstalled_info_widget.back.clicked.connect(lambda: self.layout().setCurrentIndex(0)) - def update_list(self, app_name=None): - self.default_widget.game_list.update_list(app_name) - self.layout().setCurrentIndex(0) + # navigation + self.head_bar.import_game.clicked.connect(lambda: self.setCurrentIndex(2)) + self.import_widget.back_button.clicked.connect(lambda: self.setCurrentIndex(0)) + self.uninstalled_info_widget.tabBarClicked.connect(lambda x: self.setCurrentIndex(0) if x == 0 else None) - def show_uninstalled(self, game: Game): - self.uninstalled_info_widget.update_game(game) - self.uninstalled_info_widget.setCurrentIndex(1) - self.layout().setCurrentIndex(3) - - def show_info(self, game: Game): - self.game_info.update_game(game, self.default_widget.game_list.dlcs) - self.game_info.setCurrentIndex(1) - self.layout().setCurrentIndex(1) + self.game_info.info.update_list.connect(self.update_list) -class Games(QWidget): - def __init__(self, core, parent, offline): - super(Games, self).__init__(parent=parent) - self.setLayout(QVBoxLayout()) - self.head_bar = GameListHeadBar(self) - self.head_bar.setObjectName("head_bar") + self.setup_game_list() - self.game_list = GameList(core, self, offline) + 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) - self.head_bar.search_bar.textChanged.connect( - lambda: self.game_list.search(self.head_bar.search_bar.text())) - - self.head_bar.filter_changed_signal.connect(self.game_list.filter) - self.head_bar.filter_changed(self.head_bar.filter.currentIndex()) - self.layout().addWidget(self.head_bar) - self.layout().addWidget(self.game_list) - # self.layout().addStretch(1) + self.head_bar.search_bar.textChanged.connect(self.search) + self.head_bar.filter_changed_signal.connect(self.filter) + self.head_bar.refresh_list.clicked.connect(self.update_list) self.head_bar.view.toggled.connect(self.toggle_view) + self.filter(["", "installed", "offline", "32bit", "installable"][self.settings.value("filter", 0, int)]) + + def show_game_info(self, game): + self.game_info.update_game(game, self.dlcs) + self.setCurrentIndex(1) + + def show_uninstalled_info(self, game): + self.uninstalled_info_widget.update_game(game) + self.setCurrentIndex(3) + + def setup_game_list(self): + + self.icon_view = QWidget() + self.icon_view.setLayout(FlowLayout()) + self.list_view = QWidget() + self.list_view.setLayout(QVBoxLayout()) + + # TODO move to seperate thread + if not self.offline: + self.game_list, self.dlcs = self.core.get_game_and_dlc_list(True) + 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.core.lgd.assets = [GameAsset.from_egs_json(a) for a in self.core.egs.get_game_assets()] + no_assets = self.core.get_non_asset_library_items()[0] + self.no_assets = [] + for game in no_assets: + self.no_assets.append(game) + self.no_asset_names = [] + for game in self.no_assets: + self.no_asset_names.append(game.app_name) + else: + self.bit32 = [] + self.mac_games = [] + self.dlcs = [] + + self.installed = sorted(self.core.get_installed_list(), key=lambda x: x.title) + + self.update_count_games_label() + + # 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) + + # add installed games + for igame in self.installed: + icon_widget, list_widget = self.add_installed_widget(self.core.get_game(igame.app_name)) + self.icon_view.layout().addWidget(icon_widget) + self.list_view.layout().addWidget(list_widget) + + for game in self.no_assets: + icon_widget, list_widget = self.add_installed_widget(game, is_origin=True) + self.icon_view.layout().addWidget(icon_widget) + self.list_view.layout().addWidget(list_widget) + + if not self.offline: + self.uninstalled_games = [] + installed = [i.app_name for i in self.core.get_installed_list()] + # get Uninstalled games + for game in self.game_list: + if game.app_name not in installed: + self.uninstalled_games.append(game) + + for game in sorted(self.uninstalled_games, key=lambda x: x.app_title): + icon_widget, list_widget = self.add_uninstalled_widget(game) + self.icon_view.layout().addWidget(icon_widget) + self.list_view.layout().addWidget(list_widget) + + def update_count_games_label(self): + self.count_games_label.setText(self.tr("Installed Games: {} Available Games: {}").format( + len(self.core.get_installed_list()), + len(self.game_list))) + + def add_installed_widget(self, game, is_origin=False): + pixmap = get_pixmap(game.app_name) + if pixmap.isNull(): + logger.info(game.app_title + " has a corrupt image.") + download_image(self.core.get_game(game.app_name), force=True) + pixmap = get_pixmap(game.app_name) + + if game.app_name in self.no_asset_names: + igame = None + else: + igame = self.core.get_installed_game(game.app_name) + + icon_widget = InstalledIconWidget(igame, self.core, pixmap, self.offline, is_origin, game) + + list_widget = InstalledListWidget(igame, self.core, pixmap, self.offline, is_origin, game) + + self.widgets[game.app_name] = (icon_widget, list_widget) + + icon_widget.show_info.connect(self.show_game_info) + list_widget.show_info.connect(self.show_game_info) + + icon_widget.launch_signal.connect(self.launch) + icon_widget.finish_signal.connect(self.finished) + icon_widget.update_list.connect(self.update_list) + + list_widget.launch_signal.connect(self.launch) + list_widget.finish_signal.connect(self.finished) + list_widget.update_list.connect(self.update_list) + + if icon_widget.update_available: + self.updates.append(igame) + + return icon_widget, list_widget + + def add_uninstalled_widget(self, game): + pixmap = get_uninstalled_pixmap(game.app_name) + if pixmap.isNull(): + logger.info(game.app_title + " has a corrupt image. Reloading...") + download_image(game, force=True) + pixmap = get_uninstalled_pixmap(game.app_name) + + icon_widget = IconWidgetUninstalled(game, self.core, pixmap) + icon_widget.show_uninstalled_info.connect(self.show_uninstalled_info) + + list_widget = ListWidgetUninstalled(self.core, game, pixmap) + 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 start_download(self, app_name): + self.installing_widget.set_game(self.core.get_game(app_name)) + self.installing_widget.setVisible(True) + + def finished(self, app_name): + self.running_games.remove(app_name) + self.active_game = ("", 0) + self.widgets[app_name][0].info_text = "" + self.widgets[app_name][0].info_label.setText("") + self.widgets[app_name][1].launch_button.setDisabled(False) + self.widgets[app_name][1].launch_button.setText(self.tr("Launch")) + if self.widgets[app_name][0].game.supports_cloud_saves: + if not self.settings.value(f"{app_name}/auto_sync_cloud", True, bool) \ + and not self.settings.value("auto_sync_cloud", True, bool): + logger.info("Auto saves disabled") + return + + self.widgets[app_name][0].info_text = self.tr("Sync CLoud saves") + self.widgets[app_name][0].info_label.setText(self.tr("Sync CLoud saves")) + self.widgets[app_name][1].info_label.setText(self.tr("Sync CLoud saves")) + self.game_exited.emit(app_name) + + def launch(self, app_name): + self.running_games.append(app_name) + self.game_started.emit(app_name) + self.widgets[app_name][0].info_text = self.tr("Game running") + self.widgets[app_name][0].info_label.setText(self.tr("Game running")) + self.widgets[app_name][1].launch_button.setDisabled(True) + self.widgets[app_name][1].launch_button.setText(self.tr("Game running")) + + def search(self, text: str): + for t in self.widgets.values(): + for w in t: + if text.lower() in w.game.app_title.lower() + w.game.app_name.lower(): + w.setVisible(True) + else: + w.setVisible(False) + + def filter(self, filter_name="installed"): + for t in self.widgets.values(): + # icon and list widget + for w in t: + if filter_name == "installed": + w.setVisible(self.core.is_installed(w.game.app_name)) + elif filter_name == "offline": + if self.core.is_installed(w.game.app_name): + w.setVisible(w.igame.can_run_offline) + else: + w.setVisible(False) + elif filter_name == "32bit" and self.bit32: + w.setVisible(w.game.app_name in self.bit32) + elif filter_name == "mac": + w.setVisible(w.game.app_name in self.mac_games) + elif filter_name == "installable": + w.setVisible(w.game.app_name not in self.no_asset_names) + else: + # All visible + w.setVisible(True) + + def update_list(self, app_name=None): + if app_name: + if widgets := self.widgets.get(app_name): + + # from update + if self.core.is_installed(widgets[0].game.app_name) and isinstance(widgets[0], BaseInstalledWidget): + igame = self.core.get_installed_game(app_name) + for w in widgets: + w.igame = igame + w.update_available = self.core.get_asset(w.game.app_name, True).build_version != igame.version + widgets[0].info_label.setText("") + widgets[0].info_text = "" + # new installed + elif self.core.is_installed(app_name) and isinstance(widgets[0], BaseUninstalledWidget): + logger.debug("Update Gamelist: New installed " + app_name) + self.widgets[app_name][0].deleteLater() + self.widgets[app_name][1].deleteLater() + self.widgets.pop(app_name) + + igame = self.core.get_installed_game(app_name) + self.add_installed_widget(self.core.get_game(igame.app_name)) + + self._update_games() + + # uninstalled + elif not self.core.is_installed(widgets[0].game.app_name) and isinstance(widgets[0], + BaseInstalledWidget): + logger.debug("Update list: uninstall") + 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) + self.add_uninstalled_widget(game) + + self._update_games() + + 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) + + 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])) + + if (not new_uninstalled_games) and (not new_installed_games): + return + + if new_installed_games: + for name in new_installed_games: + self.icon_view.layout().removeWidget(self.widgets[name][0]) + self.list_view.layout().removeWidget(self.widgets[name][1]) + + self.widgets[name][0].deleteLater() + self.widgets[name][1].deleteLater() + self.widgets.pop(name) + + igame = self.core.get_installed_game(name) + self.add_installed_widget(self.core.get_game(igame.app_name)) + + for name in new_uninstalled_games: + self.icon_view.layout().removeWidget(self.widgets[app_name][0]) + self.list_view.layout().removeWidget(self.widgets[app_name][1]) + + self.widgets[name][0].deleteLater() + self.widgets[name][1].deleteLater() + + self.widgets.pop(name) + + game = self.core.get_game(name, True) + self.add_uninstalled_widget(game) + + for igame in sorted(self.core.get_installed_list(), key=lambda x: x.title): + i_widget, list_widget = self.widgets[igame.app_name] + + self.icon_view.layout().addWidget(i_widget) + self.list_view.layout().addWidget(list_widget) + + # get Uninstalled games + games, self.dlcs = self.core.get_game_and_dlc_list() + for game in sorted(games, key=lambda x: x.app_title): + if not game.app_name in installed_names: + self.uninstalled_names.append(game) + for name in uninstalled_names: + i_widget, list_widget = self.widgets[name] + self.icon_view.layout().addWidget(i_widget) + self.list_view.layout().addWidget(list_widget) + self.installing_widget.setVisible(False) + 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): + i_widget, l_widget = self.widgets[igame.app_name] + icon_layout.addWidget(i_widget) + list_layout.addWidget(l_widget) + + for game in self.no_assets: + i_widget, l_widget = self.widgets[game.app_name] + icon_layout.addWidget(i_widget) + list_layout.addWidget(l_widget) + + self.uninstalled_names = [] + installed_names = [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=False) + # add uninstalled games + for game in sorted(games, key=lambda x: x.app_title): + if game.app_name not in installed_names: + self.uninstalled_names.append(game) + for game in self.uninstalled_names: + i_widget, list_widget = self.widgets[game.app_name] + icon_layout.addWidget(i_widget) + list_layout.addWidget(list_widget) + + QWidget().setLayout(self.icon_view.layout()) + QWidget().setLayout(self.list_view.layout()) + #self.icon_view.layout().deleteLater() + #self.list_view.layout().deleteLater() + + 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 + self.scroll_widget.layout().insertWidget(1, self.icon_view if self.head_bar.view.isChecked() else self.list_view) + def toggle_view(self): - self.game_list.setCurrentIndex(1 if self.head_bar.view.isChecked() else 0) - settings = QSettings() - settings.setValue("icon_view", not self.head_bar.view.isChecked()) + self.settings.setValue("icon_view", not self.head_bar.view.isChecked()) - -class GameListHeadBar(QWidget): - filter_changed_signal = pyqtSignal(str) - - def __init__(self, parent): - super(GameListHeadBar, self).__init__(parent=parent) - self.setLayout(QHBoxLayout()) - # self.installed_only = QCheckBox(self.tr("Installed only")) - self.settings = QSettings() - # self.installed_only.setChecked(self.settings.value("installed_only", False, bool)) - # self.layout.addWidget(self.installed_only) - - self.filter = QComboBox() - self.filter.addItems([self.tr("All"), - self.tr("Installed only"), - self.tr("Offline Games"), - self.tr("32 Bit Games"), - self.tr("Exclude Origin")]) - self.layout().addWidget(self.filter) - - try: - self.filter.setCurrentIndex(self.settings.value("filter", 0, int)) - except TypeError: - self.settings.setValue("filter", 0) - - self.filter.currentIndexChanged.connect(self.filter_changed) - self.layout().addStretch(1) - - self.import_game = QPushButton(icon("mdi.import"), self.tr("Import Game")) - self.layout().addWidget(self.import_game) - - self.layout().addStretch(1) - - self.search_bar = QLineEdit() - self.search_bar.setObjectName("search_bar") - self.search_bar.setFrame(False) - icon_label = QLabel() - icon_label.setPixmap(icon("fa.search").pixmap(QSize(20, 20))) - self.layout().addWidget(icon_label) - self.search_bar.setMinimumWidth(200) - self.search_bar.setPlaceholderText(self.tr("Search Game")) - self.layout().addWidget(self.search_bar) - - self.layout().addStretch(2) - checked = QSettings().value("icon_view", True, bool) - - self.view = SelectViewWidget(checked) - self.layout().addWidget(self.view) - self.layout().addStretch(1) - self.refresh_list = QPushButton() - self.refresh_list.setIcon(icon("fa.refresh")) # Reload icon - self.layout().addWidget(self.refresh_list) - - def filter_changed(self, i): - self.filter_changed_signal.emit(["", "installed", "offline", "32bit", "installable"][i]) - self.settings.setValue("filter", i) + 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) diff --git a/rare/components/tabs/games/game_info/__init__.py b/rare/components/tabs/games/game_info/__init__.py index d35f47e9..43edcedb 100644 --- a/rare/components/tabs/games/game_info/__init__.py +++ b/rare/components/tabs/games/game_info/__init__.py @@ -19,7 +19,7 @@ class InfoTabs(QTabWidget): self.setTabPosition(QTabWidget.West) self.addTab(QWidget(), icon("mdi.keyboard-backspace"), self.tr("Back")) - self.tabBarClicked.connect(lambda x: self.parent().layout().setCurrentIndex(0) if x == 0 else None) + self.tabBarClicked.connect(lambda x: self.parent().setCurrentIndex(0) if x == 0 else None) self.info = GameInfo(core, self) self.addTab(self.info, self.tr("Information")) @@ -32,7 +32,7 @@ class InfoTabs(QTabWidget): self.addTab(self.dlc, self.tr("Downloadable Content")) def update_game(self, game: Game, dlcs: list): - + self.setCurrentIndex(1) self.info.update_game(game) self.settings.update_game(game) diff --git a/rare/components/tabs/games/game_info/uninstalled_info.py b/rare/components/tabs/games/game_info/uninstalled_info.py index 3a1aa7d1..b40613b1 100644 --- a/rare/components/tabs/games/game_info/uninstalled_info.py +++ b/rare/components/tabs/games/game_info/uninstalled_info.py @@ -25,8 +25,6 @@ class UninstalledTabInfo(QTabWidget): self.setTabPosition(QTabWidget.West) self.addTab(QWidget(), icon("mdi.keyboard-backspace"), self.tr("Back")) - self.tabBarClicked.connect(lambda x: self.parent().layout.setCurrentIndex(0) if x == 0 else None) - self.info = UninstalledInfo(core, self) self.addTab(self.info, self.tr("Game Info")) @@ -42,17 +40,18 @@ class UninstalledTabInfo(QTabWidget): # self.setTabEnabled(1, False) self.setCurrentIndex(1) - def update_game(self, app_name): + def update_game(self, app_name: Game): + self.setCurrentIndex(1) self.info.update_game(app_name) self.model.clear() try: - self.model.load(json.load(open(os.path.expanduser(f"~/.config/legendary/metadata/{app_name}.json"), "r"))) + self.model.load(app_name.__dict__) except: # ignore if no metadata pass def keyPressEvent(self, e: QKeyEvent): if e.key() == Qt.Key_Escape: - self.parent().layout.setCurrentIndex(0) + self.parent().setCurrentIndex(0) class UninstalledInfo(QWidget, Ui_GameInfo): diff --git a/rare/components/tabs/games/game_list.py b/rare/components/tabs/games/game_list.py deleted file mode 100644 index c28a991c..00000000 --- a/rare/components/tabs/games/game_list.py +++ /dev/null @@ -1,440 +0,0 @@ -from logging import getLogger - -import psutil -from PyQt5.QtCore import Qt, pyqtSignal, QSettings, QTimer -from PyQt5.QtWidgets import QScrollArea, QWidget, QLabel, QVBoxLayout, QStackedWidget - -from legendary.core import LegendaryCore -from legendary.models.game import Game, GameAsset -from rare.components.tabs.games.game_widgets.base_installed_widget import BaseInstalledWidget -from rare.components.tabs.games.game_widgets.installed_icon_widget import InstalledIconWidget -from rare.components.tabs.games.game_widgets.installed_list_widget import InstalledListWidget -from rare.components.tabs.games.game_widgets.installing_game_widget import InstallingGameWidget -from rare.components.tabs.games.game_widgets.uninstalled_icon_widget import IconWidgetUninstalled -from rare.components.tabs.games.game_widgets.uninstalled_list_widget import ListWidgetUninstalled -from rare.utils.extra_widgets import FlowLayout -from rare.utils.models import InstallOptionsModel -from rare.utils.utils import download_image, get_uninstalled_pixmap, get_pixmap - -logger = getLogger("Game list") - - -class GameList(QStackedWidget): - install_game = pyqtSignal(InstallOptionsModel) - show_game_info = pyqtSignal(Game) - update_game = pyqtSignal() - game_exited = pyqtSignal(str) - game_started = pyqtSignal(str) - show_uninstalled_info = pyqtSignal(Game) - - running_games = [] - active_game = ("", 0) - - def __init__(self, core: LegendaryCore, parent, offline): - super(GameList, self).__init__(parent=parent) - self.core = core - self.setObjectName("list_widget") - self.offline = offline - self.installing_widget = InstallingGameWidget() - self.settings = QSettings() - icon_view = self.settings.value("icon_view", True, bool) - self.procs = [] - for proc in psutil.process_iter(): - try: - self.procs.append((proc.name(), proc.pid)) - except psutil.ZombieProcess: - continue - except psutil.NoSuchProcess: - continue - except Exception: - continue - self.init_ui(icon_view) - - def init_ui(self, icon_view=True): - self.icon_scrollarea = QScrollArea(parent=self) - self.icon_widget = QWidget(parent=self.icon_scrollarea) - self.list_scrollarea = QScrollArea(parent=self) - self.list_widget = QWidget(parent=self.list_scrollarea) - - self.icon_scrollarea.setWidgetResizable(True) - self.icon_scrollarea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) - - self.list_scrollarea.setWidgetResizable(True) - self.list_scrollarea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) - - self.info_text = self.tr("Installed Games: {} Available Games: {}").format( - len(self.core.get_installed_list()), - len(self.core.get_game_list(update_assets=True))) - - self.icon_parent_layout = QVBoxLayout() - self.icon_parent_layout.addWidget(QLabel(self.info_text)) - - self.icon_layout = FlowLayout() - self.list_layout = QVBoxLayout() - self.list_layout.addWidget(QLabel(self.info_text)) - - self.updates = [] - self.widgets = {} - # api calls - if not self.offline: - self.core.lgd.assets = [GameAsset.from_egs_json(a) for a in self.core.egs.get_game_assets()] - 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]] - no_assets = self.core.get_non_asset_library_items()[0] - self.no_assets = {} - for game in no_assets: - self.no_assets[game.app_name] = game - self.no_asset_names = [] - for key in self.no_assets.keys(): - self.no_asset_names.append(key) - - else: - self.bit32 = [] - self.mac_games = [] - self.installed = sorted(self.core.get_installed_list(), key=lambda x: x.title) - - self.installing_widget = InstallingGameWidget() - self.icon_layout.addWidget(self.installing_widget) - self.installing_widget.setVisible(False) - - # Installed Games - for igame in self.installed: - icon_widget, list_widget = self.add_installed_widget(self.core.get_game(igame.app_name)) - self.icon_layout.addWidget(icon_widget) - self.list_layout.addWidget(list_widget) - - for game in self.no_assets.values(): - icon_widget, list_widget = self.add_installed_widget(game, True) - self.icon_layout.addWidget(icon_widget) - self.list_layout.addWidget(list_widget) - - if not self.offline: - self.uninstalled_games = [] - 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 games: - if not game.app_name in installed: - self.uninstalled_games.append(game) - - # add uninstalled games - 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) - self.list_layout.addWidget(list_widget) - else: - self.dlcs = [] - - self.icon_parent_layout.addLayout(self.icon_layout) - self.icon_parent_layout.addStretch(1) - self.list_layout.addStretch(1) - self.icon_widget.setLayout(self.icon_parent_layout) - self.list_widget.setLayout(self.list_layout) - - self.icon_scrollarea.setWidget(self.icon_widget) - self.list_scrollarea.setWidget(self.list_widget) - - self.addWidget(self.icon_scrollarea) - self.addWidget(self.list_scrollarea) - - if not icon_view: - self.setCurrentIndex(1) - - if filter_games := self.settings.value("filter", "", str): - self.filter(filter_games) - - def start_download(self, app_name): - self.installing_widget.set_game(self.core.get_game(app_name)) - self.installing_widget.setVisible(True) - - def add_uninstalled_widget(self, game): - pixmap = get_uninstalled_pixmap(game.app_name) - if pixmap.isNull(): - logger.info(game.app_title + " has a corrupt image. Reloading...") - download_image(game, force=True) - pixmap = get_uninstalled_pixmap(game.app_name) - - icon_widget = IconWidgetUninstalled(game, self.core, pixmap) - icon_widget.show_uninstalled_info.connect(self.show_install_info) - - list_widget = ListWidgetUninstalled(self.core, game, pixmap) - list_widget.show_uninstalled_info.connect(self.show_install_info) - - self.widgets[game.app_name] = (icon_widget, list_widget) - - return icon_widget, list_widget - - def add_installed_widget(self, game, is_origin=False): - pixmap = get_pixmap(game.app_name) - - if pixmap.isNull(): - logger.info(game.app_title + " has a corrupt image.") - download_image(self.core.get_game(game.app_name), force=True) - pixmap = get_pixmap(game.app_name) - - if game.app_name in self.no_asset_names: - igame = None - else: - igame = self.core.get_installed_game(game.app_name) - - icon_widget = InstalledIconWidget(igame, self.core, pixmap, self.offline, is_origin, game) - # self.icon_layout.addWidget(icon_widget) - - list_widget = InstalledListWidget(igame, self.core, pixmap, self.offline, is_origin, game) - # self.list_layout.addWidget(list_widget) - - self.widgets[game.app_name] = (icon_widget, list_widget) - - icon_widget.show_info.connect(self.show_game_info.emit) - list_widget.show_info.connect(self.show_game_info.emit) - - icon_widget.launch_signal.connect(self.launch) - icon_widget.finish_signal.connect(self.finished) - icon_widget.update_list.connect(self.update_list) - list_widget.launch_signal.connect(self.launch) - list_widget.finish_signal.connect(self.finished) - list_widget.update_list.connect(self.update_list) - - if icon_widget.update_available: - self.updates.append(igame) - - if igame: - active, pid = self.check_for_active_game(igame) - if active: - # Only one game works: Workaround for Satisfactory EA and Exp. - self.launch(igame.app_name) - icon_widget.game_running = True - list_widget.game_running = True - self.active_game = (igame.app_name, pid) - self.timer = QTimer() - self.timer.timeout.connect(self.is_finished) - self.timer.start(10000) - - return icon_widget, list_widget - - def is_finished(self): - if psutil.pid_exists(self.active_game[1]): - self.timer.start(10000) - else: - self.finished(self.active_game[0]) - del self.timer - - def check_for_active_game(self, igame): - executable = igame.executable.split("/")[-1].split("\\")[-1] - if executable.endswith(".exe"): - executable = executable[:-4] # remove .exe - - for i, pid in self.procs: - if executable in i: - # Workaround for Satisfactory: Check Cmdline args - if igame.app_name in ["CrabEA", "CrabTest"]: - p = psutil.Process(pid) - if not igame.install_path.split("/")[-1].split("\\")[-1] in " ".join(p.cmdline()): - return False, 0 - return True, pid - return False, 0 - - def show_install_info(self, game): - self.show_uninstalled_info.emit(game) - - def finished(self, app_name): - self.running_games.remove(app_name) - self.active_game = ("", 0) - self.widgets[app_name][0].info_text = "" - self.widgets[app_name][0].info_label.setText("") - self.widgets[app_name][1].launch_button.setDisabled(False) - self.widgets[app_name][1].launch_button.setText(self.tr("Launch")) - if self.widgets[app_name][0].game.supports_cloud_saves: - if not self.settings.value(f"{app_name}/auto_sync_cloud", True, bool) \ - and not self.settings.value("auto_sync_cloud", True, bool): - logger.info("Auto saves disabled") - return - - self.widgets[app_name][0].info_text = self.tr("Sync CLoud saves") - self.widgets[app_name][0].info_label.setText(self.tr("Sync CLoud saves")) - self.widgets[app_name][1].info_label.setText(self.tr("Sync CLoud saves")) - self.game_exited.emit(app_name) - - def launch(self, app_name): - self.running_games.append(app_name) - self.game_started.emit(app_name) - self.widgets[app_name][0].info_text = self.tr("Game running") - self.widgets[app_name][0].info_label.setText(self.tr("Game running")) - self.widgets[app_name][1].launch_button.setDisabled(True) - self.widgets[app_name][1].launch_button.setText(self.tr("Game running")) - - def search(self, text: str): - for t in self.widgets.values(): - for w in t: - if text.lower() in w.game.app_title.lower() + w.game.app_name.lower(): - w.setVisible(True) - else: - w.setVisible(False) - - def filter(self, filter="installed"): - for t in self.widgets.values(): - for w in t: - if filter == "installed": - w.setVisible(self.core.is_installed(w.game.app_name)) - elif filter == "offline": - if self.core.is_installed(w.game.app_name): - w.setVisible(w.igame.can_run_offline) - else: - w.setVisible(False) - elif filter == "32bit" and self.bit32: - 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_asset_names) - else: - # All visible - w.setVisible(True) - - def update_list(self, app_name=None): - # self.settings.setValue("icon_view", icon_view) - if app_name: - if widgets := self.widgets.get(app_name): - - # from update - if self.core.is_installed(widgets[0].game.app_name) and isinstance(widgets[0], BaseInstalledWidget): - igame = self.core.get_installed_game(app_name) - for w in widgets: - w.igame = igame - w.update_available = self.core.get_asset(w.game.app_name, True).build_version != igame.version - widgets[0].info_label.setText("") - widgets[0].info_text = "" - # new installed - elif self.core.is_installed(widgets[0].game.app_name) and not isinstance(widgets[0], - BaseInstalledWidget): - name = widgets[0].game.app_name - self.widgets[name][0].deleteLater() - self.widgets[name][1].deleteLater() - self.widgets.pop(name) - - # QWidget().setLayout(self.icon_layout) - - igame = self.core.get_installed_game(app_name) - self.add_installed_widget(self.core.get_game(igame.app_name)) - - self._update_games() - - # uninstalled - elif not self.core.is_installed(widgets[0].game.app_name) and isinstance(widgets[0], - BaseInstalledWidget): - self.list_layout.removeWidget(widgets[1]) - self.icon_layout.removeWidget(widgets[0]) - - widgets[0].deleteLater() - widgets[1].deleteLater() - - self.widgets.pop(app_name) - - game = self.core.get_game(app_name, True) - self.add_uninstalled_widget(game) - - self._update_games() - - 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) - - 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])) - - if (not new_uninstalled_games) and (not new_installed_games): - return - - if new_installed_games: - for name in new_installed_games: - self.icon_layout.removeWidget(self.widgets[app_name][0]) - self.list_layout.removeWidget(self.widgets[app_name][1]) - - self.widgets[name][0].deleteLater() - self.widgets[name][1].deleteLater() - self.widgets.pop(name) - - igame = self.core.get_installed_game(name) - self.add_installed_widget(self.core.get_game(igame.app_name)) - - for name in new_uninstalled_games: - self.icon_layout.removeWidget(self.widgets[app_name][0]) - self.list_layout.removeWidget(self.widgets[app_name][1]) - - self.widgets[name][0].deleteLater() - self.widgets[name][1].deleteLater() - - self.widgets.pop(name) - - game = self.core.get_game(name, True) - self.add_uninstalled_widget(game) - - for igame in sorted(self.core.get_installed_list(), key=lambda x: x.title): - i_widget, list_widget = self.widgets[igame.app_name] - - self.icon_layout.addWidget(i_widget) - self.list_layout.addWidget(list_widget) - - # get Uninstalled games - games, self.dlcs = self.core.get_game_and_dlc_list() - for game in sorted(games, key=lambda x: x.app_title): - if not game.app_name in installed_names: - self.uninstalled_names.append(game) - for name in uninstalled_names: - i_widget, list_widget = self.widgets[name] - self.icon_layout.addWidget(i_widget) - self.list_layout.addWidget(list_widget) - self.installing_widget.setVisible(False) - - def _update_games(self): - # new layouts to remove from old layout - icon_layout = FlowLayout() - # QWidget().setLayout(self.list_layout) - list_layout = QVBoxLayout() - - icon_layout.addWidget(self.installing_widget) - for igame in sorted(self.core.get_installed_list(), key=lambda x: x.title): - i_widget, l_widget = self.widgets[igame.app_name] - icon_layout.addWidget(i_widget) - list_layout.addWidget(l_widget) - - self.uninstalled_names = [] - installed_names = [i.app_name for i in self.core.get_installed_list()] - # get Uninstalled games - games, self.dlcs = self.core.get_game_and_dlc_list() - for game in sorted(games, key=lambda x: x.app_title): - if game.app_name not in installed_names: - self.uninstalled_names.append(game) - for game in self.uninstalled_names: - i_widget, list_widget = self.widgets[game.app_name] - icon_layout.addWidget(i_widget) - list_layout.addWidget(list_widget) - - self.icon_layout.deleteLater() - self.list_layout.deleteLater() - - self.icon_widget = QWidget() - self.list_widget = QWidget() - - self.icon_widget.setLayout(icon_layout) - self.list_widget.setLayout(list_layout) - - self.list_scrollarea.setWidget(QWidget()) - self.icon_scrollarea.setWidget(QWidget()) - - self.icon_scrollarea.setWidget(self.icon_widget) - self.list_scrollarea.setWidget(self.list_widget) - - self.icon_layout = icon_layout - self.list_layout = list_layout - - self.icon_widget.setLayout(self.icon_layout) - self.list_widget.setLayout(self.list_layout) - - self.update() diff --git a/rare/components/tabs/games/head_bar.py b/rare/components/tabs/games/head_bar.py new file mode 100644 index 00000000..958b7311 --- /dev/null +++ b/rare/components/tabs/games/head_bar.py @@ -0,0 +1,62 @@ +from PyQt5.QtCore import QSize, QSettings, pyqtSignal +from PyQt5.QtWidgets import QLineEdit, QLabel, QPushButton, QWidget, QHBoxLayout, QComboBox +from qtawesome import icon + +from rare.utils.extra_widgets import SelectViewWidget + + +class GameListHeadBar(QWidget): + filter_changed_signal = pyqtSignal(str) + + def __init__(self): + super(GameListHeadBar, self).__init__() + self.setLayout(QHBoxLayout()) + # self.installed_only = QCheckBox(self.tr("Installed only")) + self.settings = QSettings() + # self.installed_only.setChecked(self.settings.value("installed_only", False, bool)) + # self.layout.addWidget(self.installed_only) + + self.filter = QComboBox() + self.filter.addItems([self.tr("All"), + self.tr("Installed only"), + self.tr("Offline Games"), + self.tr("32 Bit Games"), + self.tr("Exclude Origin")]) + self.layout().addWidget(self.filter) + + try: + self.filter.setCurrentIndex(self.settings.value("filter", 0, int)) + except TypeError: + self.settings.setValue("filter", 0) + + self.filter.currentIndexChanged.connect(self.filter_changed) + self.layout().addStretch(1) + + self.import_game = QPushButton(icon("mdi.import"), self.tr("Import Game")) + self.layout().addWidget(self.import_game) + + self.layout().addStretch(1) + + self.search_bar = QLineEdit() + self.search_bar.setObjectName("search_bar") + self.search_bar.setFrame(False) + icon_label = QLabel() + icon_label.setPixmap(icon("fa.search").pixmap(QSize(20, 20))) + self.layout().addWidget(icon_label) + self.search_bar.setMinimumWidth(200) + self.search_bar.setPlaceholderText(self.tr("Search Game")) + self.layout().addWidget(self.search_bar) + + self.layout().addStretch(2) + checked = QSettings().value("icon_view", True, bool) + + self.view = SelectViewWidget(checked) + self.layout().addWidget(self.view) + self.layout().addStretch(1) + self.refresh_list = QPushButton() + self.refresh_list.setIcon(icon("fa.refresh")) # Reload icon + self.layout().addWidget(self.refresh_list) + + def filter_changed(self, i): + self.filter_changed_signal.emit(["", "installed", "offline", "32bit", "installable"][i]) + self.settings.setValue("filter", i) diff --git a/rare/components/tabs/tab_widget.py b/rare/components/tabs/tab_widget.py index f09c6a8b..b8180260 100644 --- a/rare/components/tabs/tab_widget.py +++ b/rare/components/tabs/tab_widget.py @@ -1,15 +1,15 @@ -from PyQt5.QtCore import QSize, pyqtSignal +from PyQt5.QtCore import QSize, pyqtSignal, QObject from PyQt5.QtWidgets import QMenu, QTabWidget, QWidget, QWidgetAction, QShortcut from qtawesome import icon from legendary.core import LegendaryCore from rare.components.dialogs.install_dialog import InstallDialog from rare.components.dialogs.uninstall_dialog import UninstallDialog +from rare.components.tabs.games.__init__ import GamesTab from rare.components.tabs.tab_utils import TabBar, TabButtonWidget from rare.components.tabs.account import MiniWidget from rare.components.tabs.cloud_saves import SyncSaves from rare.components.tabs.downloads import DownloadTab -from rare.components.tabs.games import GameTab from rare.components.tabs.settings import SettingsTab from rare.components.tabs.settings.debug_settings import DebugSettings from rare.components.tabs.shop import Shop @@ -28,12 +28,12 @@ class TabWidget(QTabWidget): self.core = core self.setTabBar(TabBar(disabled_tab)) # Generate Tabs - self.games_tab = GameTab(core, self, offline) + self.games_tab = GamesTab(core, self) self.addTab(self.games_tab, self.tr("Games")) if not offline: - updates = self.games_tab.default_widget.game_list.updates - self.downloadTab = DownloadTab(core, updates, self) - self.addTab(self.downloadTab, "Downloads" + (" (" + str(len(updates)) + ")" if len(updates) != 0 else "")) + # updates = self.games_tab.default_widget.game_list.updates + self.downloadTab = DownloadTab(core, [], self) + self.addTab(self.downloadTab, "Downloads" + (" (" + str(len([])) + ")" if len([]) != 0 else "")) self.cloud_saves = SyncSaves(core, self) self.addTab(self.cloud_saves, "Cloud Saves") self.store = Shop(self.core) @@ -65,7 +65,7 @@ class TabWidget(QTabWidget): # Signals # open download tab - self.games_tab.default_widget.game_list.update_game.connect(lambda: self.setCurrentIndex(1)) + # self.games_tab.update_game.connect(lambda: self.setCurrentIndex(1)) # uninstall self.games_tab.game_info.info.uninstall_game.connect(self.uninstall_game) @@ -76,8 +76,6 @@ class TabWidget(QTabWidget): if not offline: # Download finished self.downloadTab.finished.connect(self.dl_finished) - # show uninstalled info - self.games_tab.default_widget.game_list.show_uninstalled_info.connect(self.games_tab.show_uninstalled) # install dlc self.games_tab.game_info.dlc.install_dlc.connect( lambda app_name, update: self.install_game( @@ -100,7 +98,7 @@ class TabWidget(QTabWidget): # Finished sync self.cloud_saves.finished.connect(self.finished_sync) # Game finished - self.games_tab.default_widget.game_list.game_exited.connect(self.game_finished) + self.games_tab.game_exited.connect(self.game_finished) # Open game list on click on Games tab button self.tabBarClicked.connect(self.mouse_clicked) @@ -113,7 +111,7 @@ class TabWidget(QTabWidget): QShortcut("Alt+4", self).activated.connect(lambda: self.setCurrentIndex(5)) self.downloadTab.dl_status.connect( - self.games_tab.default_widget.game_list.installing_widget.image_widget.set_status) + self.games_tab.installing_widget.image_widget.set_status) def mouse_clicked(self, tab_num): if tab_num == 0: @@ -141,7 +139,7 @@ class TabWidget(QTabWidget): self.setTabText(1, "Downloads" + ((" (" + str(downloads) + ")") if downloads != 0 else "")) self.setCurrentIndex(1) self.downloadTab.install_game(download_item) - self.games_tab.default_widget.game_list.start_download(download_item.options.app_name) + self.games_tab.start_download(download_item.options.app_name) def game_imported(self, app_name: str): igame = self.core.get_installed_game(app_name) @@ -149,8 +147,8 @@ class TabWidget(QTabWidget): self.downloadTab.add_update(igame) downloads = len(self.downloadTab.dl_queue) + len(self.downloadTab.update_widgets.keys()) self.setTabText(1, "Downloads" + ((" (" + str(downloads) + ")") if downloads != 0 else "")) - self.games_tab.default_widget.game_list.update_list(app_name) - self.games_tab.layout().setCurrentIndex(0) + self.games_tab.update_list(app_name) + self.games_tab.setCurrentIndex(0) # Sync game and delete dc rpc def game_finished(self, app_name): @@ -165,6 +163,7 @@ class TabWidget(QTabWidget): if infos == 0: return legendary_utils.uninstall(game.app_name, self.core, infos) + self.games_tab.setCurrentIndex(0) if app_name in self.downloadTab.update_widgets.keys(): self.downloadTab.update_layout.removeWidget(self.downloadTab.update_widgets[app_name]) self.downloadTab.update_widgets.pop(app_name) @@ -175,9 +174,9 @@ class TabWidget(QTabWidget): # Update gamelist and set text of Downloads to "Downloads" def dl_finished(self, update_list): if update_list[0]: - self.games_tab.default_widget.game_list.update_list(update_list[1]) + self.games_tab.update_list(update_list[1]) self.cloud_saves.reload(update_list[1]) - self.games_tab.default_widget.game_list.installing_widget.setVisible(False) + self.games_tab.installing_widget.setVisible(False) downloads = len(self.downloadTab.dl_queue) + len(self.downloadTab.update_widgets.keys()) self.setTabText(1, "Downloads" + ((" (" + str(downloads) + ")") if downloads != 0 else "")) @@ -187,6 +186,7 @@ class TabWidget(QTabWidget): # Remove text "sync game" def finished_sync(self, app_name): - self.games_tab.default_widget.game_list.widgets[app_name][0].info_text = "" - self.games_tab.default_widget.game_list.widgets[app_name][0].info_label.setText("") - self.games_tab.default_widget.game_list.widgets[app_name][1].info_label.setText("") + if self.core.is_installed(app_name): + self.games_tab.widgets[app_name][0].info_text = "" + self.games_tab.widgets[app_name][0].info_label.setText("") + self.games_tab.widgets[app_name][1].info_label.setText("") diff --git a/rare/ui/components/tabs/games/games_tab.py b/rare/ui/components/tabs/games/games_tab.py new file mode 100644 index 00000000..f7879653 --- /dev/null +++ b/rare/ui/components/tabs/games/games_tab.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'rare/ui/components/tabs/games/games_tab.ui' +# +# Created by: PyQt5 UI code generator 5.15.4 +# +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. + + +from PyQt5 import QtCore, QtGui, QtWidgets + + +class Ui_GamesTab(object): + def setupUi(self, GamesTab): + GamesTab.setObjectName("GamesTab") + GamesTab.resize(1071, 678) + self.games = QtWidgets.QWidget() + self.games.setObjectName("games") + self.verticalLayout = QtWidgets.QVBoxLayout(self.games) + self.verticalLayout.setObjectName("verticalLayout") + self.game_list_scroll_area = QtWidgets.QScrollArea(self.games) + self.game_list_scroll_area.setWidgetResizable(True) + self.game_list_scroll_area.setObjectName("game_list_scroll_area") + self.scroll_widget = QtWidgets.QWidget() + self.scroll_widget.setGeometry(QtCore.QRect(0, 0, 1051, 658)) + self.scroll_widget.setObjectName("scroll_widget") + self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.scroll_widget) + self.verticalLayout_4.setObjectName("verticalLayout_4") + self.count_games_label = QtWidgets.QLabel(self.scroll_widget) + self.count_games_label.setText("") + self.count_games_label.setObjectName("count_games_label") + self.verticalLayout_4.addWidget(self.count_games_label) + spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout_4.addItem(spacerItem) + self.game_list_scroll_area.setWidget(self.scroll_widget) + self.verticalLayout.addWidget(self.game_list_scroll_area) + GamesTab.addWidget(self.games) + + self.retranslateUi(GamesTab) + QtCore.QMetaObject.connectSlotsByName(GamesTab) + + def retranslateUi(self, GamesTab): + _translate = QtCore.QCoreApplication.translate + GamesTab.setWindowTitle(_translate("GamesTab", "StackedWidget")) + + +if __name__ == "__main__": + import sys + app = QtWidgets.QApplication(sys.argv) + GamesTab = QtWidgets.QStackedWidget() + ui = Ui_GamesTab() + ui.setupUi(GamesTab) + GamesTab.show() + sys.exit(app.exec_()) diff --git a/rare/ui/components/tabs/games/games_tab.ui b/rare/ui/components/tabs/games/games_tab.ui new file mode 100644 index 00000000..4091e3b7 --- /dev/null +++ b/rare/ui/components/tabs/games/games_tab.ui @@ -0,0 +1,62 @@ + + + GamesTab + + + + 0 + 0 + 1071 + 678 + + + + StackedWidget + + + + + + + true + + + + + 0 + 0 + 1051 + 658 + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + diff --git a/rare/utils/extra_widgets.py b/rare/utils/extra_widgets.py index 0bcc3953..b661ec13 100644 --- a/rare/utils/extra_widgets.py +++ b/rare/utils/extra_widgets.py @@ -154,7 +154,8 @@ class PathEdit(QWidget, Ui_PathEdit): self.text_edit.setText(text) def save(self): - self.save_func() + if self.save_func: + self.save_func() def set_path(self): dlg_path = self.text_edit.text()