diff --git a/Rare/Components/Launch/LaunchDialog.py b/Rare/Components/Launch/LaunchDialog.py index 8943451c..d42380e4 100644 --- a/Rare/Components/Launch/LaunchDialog.py +++ b/Rare/Components/Launch/LaunchDialog.py @@ -67,7 +67,10 @@ class LaunchDialog(QDialog): self.setLayout(self.layout) def login(self): - if not LoginDialog(core=self.core).login(): + print("Login dlg") + if LoginDialog(core=self.core).login(): + self.login_thread.start() + else: exit(0) def launch(self, core: LegendaryCore): diff --git a/Rare/Components/TabWidget.py b/Rare/Components/TabWidget.py index 97d28958..2d87f4f5 100644 --- a/Rare/Components/TabWidget.py +++ b/Rare/Components/TabWidget.py @@ -2,6 +2,7 @@ from PyQt5.QtCore import QSize from PyQt5.QtGui import QIcon, QFont from PyQt5.QtWidgets import QTabWidget, QTabBar, QWidget, QToolButton, QWidgetAction, QMenu from legendary.core import LegendaryCore +from qtawesome import icon from Rare import style_path from Rare.Components.Tabs.Account.AccountWidget import MiniWidget @@ -37,8 +38,7 @@ class TabWidget(QTabWidget): self.addTab(self.account, "") self.setTabEnabled(disabled_tab + 1, False) # self.settings = SettingsTab(core) - - self.addTab(self.settings, QIcon(style_path + "/Icons/settings.png"), None) + self.addTab(self.settings, icon("fa.gear", color='white'), None) self.setIconSize(QSize(25, 25)) self.tabBar().setTabButton(3, self.tabBar().RightSide, TabButtonWidget(core)) @@ -70,8 +70,7 @@ class TabButtonWidget(QToolButton): super(TabButtonWidget, self).__init__() self.setText("Icon") self.setPopupMode(QToolButton.InstantPopup) - - self.setIcon(QIcon(style_path + "/Icons/account.png")) + self.setIcon(icon("mdi.account-circle", color="white", scale_factor=1.25)) self.setToolTip("Account") self.setIconSize(QSize(25, 25)) self.setMenu(QMenu()) diff --git a/Rare/Components/Tabs/Games/GameInfo/GameInfo.py b/Rare/Components/Tabs/Games/GameInfo/GameInfo.py index f497d6c4..6da5d7bb 100644 --- a/Rare/Components/Tabs/Games/GameInfo/GameInfo.py +++ b/Rare/Components/Tabs/Games/GameInfo/GameInfo.py @@ -1,11 +1,12 @@ import os -from PyQt5.QtCore import Qt +from PyQt5.QtCore import Qt, pyqtSignal from PyQt5.QtGui import QPixmap -from PyQt5.QtWidgets import QWidget, QPushButton, QVBoxLayout, QLabel, QHBoxLayout, QTabWidget +from PyQt5.QtWidgets import QWidget, QPushButton, QVBoxLayout, QLabel, QHBoxLayout, QTabWidget, QMessageBox from legendary.core import LegendaryCore from legendary.models.game import InstalledGame, Game +from Rare.utils import LegendaryApi from Rare.utils.QtExtensions import SideTabBar from Rare.utils.utils import IMAGE_DIR @@ -25,7 +26,7 @@ class InfoTabs(QTabWidget): class GameInfo(QWidget): igame: InstalledGame game: Game - + update_list = pyqtSignal() def __init__(self, core: LegendaryCore): super(GameInfo, self).__init__() self.core = core @@ -63,10 +64,21 @@ class GameInfo(QWidget): top_layout.addLayout(right_layout) top_layout.addStretch() + self.game_actions = GameActions() + + self.game_actions.uninstall_button.clicked.connect(self.uninstall) + self.layout.addLayout(top_layout) + self.layout.addWidget(self.game_actions) self.layout.addStretch() self.setLayout(self.layout) + def uninstall(self): + if QMessageBox.question(self, "Uninstall", self.tr("Are you sure to uninstall " + self.game.app_title), QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes: + LegendaryApi.uninstall(self.game.app_name, self.core) + self.update_list.emit() + self.back_button.click() + def update_game(self, app_name): self.game = self.core.get_game(app_name) self.igame = self.core.get_installed_game(app_name) @@ -86,10 +98,24 @@ class GameInfo(QWidget): w = 200 pixmap = pixmap.scaled(w, int(w * 4 / 3)) self.image.setPixmap(pixmap) - self.app_name.setText("App name: "+ self.game.app_name) + self.app_name.setText("App name: " + self.game.app_name) self.version.setText("Version: " + self.game.app_version) self.dev.setText(self.tr("Developer: ") + self.game.metadata["developer"]) - self.install_size.setText(self.tr("Install size: ") + str(round(self.igame.install_size/(1024**3), 2))+ " GB") + self.install_size.setText( + self.tr("Install size: ") + str(round(self.igame.install_size / (1024 ** 3), 2)) + " GB") self.install_path.setText(self.tr("Install path: ") + self.igame.install_path) - print(self.game.__dict__) - print(self.igame.__dict__) \ No newline at end of file + + +class GameActions(QWidget): + def __init__(self): + super(GameActions, self).__init__() + self.layout = QVBoxLayout() + self.game_actions = QLabel("

Game actions

") + self.layout.addWidget(self.game_actions) + uninstall_layout = QHBoxLayout() + self.uninstall_game = QLabel(self.tr("Uninstall game")) + uninstall_layout.addWidget(self.uninstall_game) + self.uninstall_button = QPushButton("Uninstall") + uninstall_layout.addWidget(self.uninstall_button) + self.layout.addLayout(uninstall_layout) + self.setLayout(self.layout) \ No newline at end of file diff --git a/Rare/Components/Tabs/Games/GameList.py b/Rare/Components/Tabs/Games/GameList.py index 914ae176..d12b60ee 100644 --- a/Rare/Components/Tabs/Games/GameList.py +++ b/Rare/Components/Tabs/Games/GameList.py @@ -6,13 +6,15 @@ from Rare.Components.Tabs.Games.GameWidgetInstalled import GameWidgetInstalled from Rare.Components.Tabs.Games.GameWidgetListUninstalled import UninstalledGameWidget from Rare.Components.Tabs.Games.GameWidgetUninstalled import GameWidgetUninstalled from Rare.Components.Tabs.Games.InstalledListWidget import GameWidget +from Rare.utils.Models import InstallOptions from Rare.utils.QtExtensions import FlowLayout class GameList(QScrollArea): - install_game = pyqtSignal(dict) + install_game = pyqtSignal(InstallOptions) show_game_info = pyqtSignal(str) update_game = pyqtSignal() + def __init__(self, core: LegendaryCore): super(GameList, self).__init__() self.core = core @@ -49,8 +51,6 @@ class GameList(QScrollArea): self.layout.addWidget(widget) widget.update_list.connect(self.update_list) - - uninstalled_games = [] installed = [i.app_name for i in self.core.get_installed_list()] # get Uninstalled games diff --git a/Rare/Components/Tabs/Games/GameWidgetInstalled.py b/Rare/Components/Tabs/Games/GameWidgetInstalled.py index 2b0a511d..e53188d7 100644 --- a/Rare/Components/Tabs/Games/GameWidgetInstalled.py +++ b/Rare/Components/Tabs/Games/GameWidgetInstalled.py @@ -1,13 +1,13 @@ import os from logging import getLogger -from PyQt5.QtCore import QEvent, pyqtSignal, QSettings -from PyQt5.QtGui import QPixmap, QIcon +from PyQt5.QtCore import QEvent, pyqtSignal, QSettings, QSize +from PyQt5.QtGui import QPixmap from PyQt5.QtWidgets import * from legendary.core import LegendaryCore from legendary.models.game import InstalledGame +from qtawesome import icon -from Rare import style_path from Rare.utils import LegendaryApi from Rare.utils.QtExtensions import ClickableLabel @@ -59,14 +59,22 @@ class GameWidgetInstalled(QWidget): minilayout = QHBoxLayout() self.title_label.setObjectName("game_widget") minilayout.addWidget(self.title_label) - # minilayout.addStretch(1) + + # Info Button self.menu_btn = QPushButton() - self.menu_btn.setIcon(QIcon(style_path + "/Icons/menu.png")) - self.menu_btn.setObjectName("installed_menu_button") - self.menu = Menu() - self.menu.action.connect(self.menu_action) - self.menu_btn.setMenu(self.menu) - self.menu_btn.setObjectName("menu") + self.menu_btn.setIcon(icon("ei.info-circle", color="white")) + # self.menu_btn.setObjectName("installed_menu_button") + self.menu_btn.setIconSize(QSize(18, 18)) + self.menu_btn.enterEvent = lambda x: self.info_label.setText("Information") + self.menu_btn.leaveEvent = lambda x: self.info_label.setText( + "Please update Game") if self.update_available else self.info_label.setText("Start Game") + # remove Border + self.menu_btn.setStyleSheet(""" + QPushButton{ + border: none; + } + """) + self.menu_btn.clicked.connect(lambda: self.show_info.emit(self.game.app_name)) self.menu_btn.setFixedWidth(17) minilayout.addWidget(self.menu_btn) minilayout.addStretch(1) @@ -81,7 +89,7 @@ class GameWidgetInstalled(QWidget): def enterEvent(self, a0: QEvent) -> None: if self.update_available: - self.info_label.setText("Please update Game") + self.info_label.setText(self.tr("Please update Game")) elif not self.running: self.info_label.setText("Start Game") @@ -107,22 +115,3 @@ class GameWidgetInstalled(QWidget): def finished(self): self.info_label.setText("") self.running = False - - def menu_action(self, action: str): - if action == "uninstall": - if QMessageBox.question(self, "Uninstall", self.tr("Do you want to uninstall") + self.game.title, - QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes: - logger.info("Uninstalling " + self.game.title) - self.core.uninstall_game(self.game) - self.update_list.emit() - elif action == "info": - self.show_info.emit(self.game.app_name) - - -class Menu(QMenu): - action = pyqtSignal(str) - - def __init__(self): - super(Menu, self).__init__() - self.addAction(self.tr("Game info"), lambda: self.action.emit("info")) - self.addAction(self.tr("Uninstall"), lambda: self.action.emit("uninstall")) diff --git a/Rare/Components/Tabs/Games/GameWidgetUninstalled.py b/Rare/Components/Tabs/Games/GameWidgetUninstalled.py index e1f1e733..de1cf79a 100644 --- a/Rare/Components/Tabs/Games/GameWidgetUninstalled.py +++ b/Rare/Components/Tabs/Games/GameWidgetUninstalled.py @@ -8,6 +8,7 @@ from legendary.core import LegendaryCore from legendary.models.game import Game from Rare.Components.Dialogs.InstallDialog import InstallDialog +from Rare.utils.Models import InstallOptions from Rare.utils.QtExtensions import ClickableLabel from Rare.utils.utils import download_image @@ -15,7 +16,7 @@ logger = getLogger("Uninstalled") class GameWidgetUninstalled(QWidget): - install_game = pyqtSignal(dict) + install_game = pyqtSignal(InstallOptions) def __init__(self, core: LegendaryCore, game: Game): super(GameWidgetUninstalled, self).__init__() @@ -68,11 +69,5 @@ class GameWidgetUninstalled(QWidget): infos = InstallDialog().get_information() if infos != 0: path, max_workers = infos - self.install_game.emit({ - "app_name": self.game.app_name, - "options": { - "path": path, - "max_workers": max_workers - } - }) + self.install_game.emit(InstallOptions(app_name=self.game.app_name, max_workers=max_workers, path=path)) # wait for update of legendary to get progress diff --git a/Rare/Components/Tabs/Games/GamesTab.py b/Rare/Components/Tabs/Games/GamesTab.py index 85a0af95..309581a0 100644 --- a/Rare/Components/Tabs/Games/GamesTab.py +++ b/Rare/Components/Tabs/Games/GamesTab.py @@ -1,6 +1,7 @@ from PyQt5.QtCore import QSettings from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QCheckBox, QLineEdit, QLabel, QPushButton, QStyle, \ QStackedLayout +from qtawesome import icon from Rare.Components.Tabs.Games.GameInfo.GameInfo import InfoTabs from Rare.Components.Tabs.Games.GameList import GameList @@ -16,6 +17,8 @@ class GameTab(QWidget): self.layout.addWidget(self.default_widget) self.game_info = InfoTabs(core) self.game_info.info.back_button.clicked.connect(lambda: self.layout.setCurrentIndex(0)) + self.game_info.info.update_list.connect( + lambda: self.default_widget.game_list.update_list(not self.default_widget.head_bar.view.isChecked())) self.layout.addWidget(self.game_info) self.setLayout(self.layout) @@ -40,7 +43,7 @@ class Games(QWidget): self.head_bar.installed_only.stateChanged.connect(lambda: self.game_list.installed_only( self.head_bar.installed_only.isChecked())) - self.head_bar.refresh_list.clicked.connect(lambda: self.game_list.update_list()) + self.head_bar.refresh_list.clicked.connect(lambda: self.game_list.update_list(not self.head_bar.view.isChecked())) self.layout.addWidget(self.head_bar) self.layout.addWidget(self.game_list) # self.layout.addStretch(1) @@ -76,7 +79,7 @@ class GameListHeadBar(QWidget): self.layout.addWidget(self.list_view) self.refresh_list = QPushButton() - self.refresh_list.setIcon(self.style().standardIcon(getattr(QStyle, "SP_BrowserReload"))) # Reload icon + self.refresh_list.setIcon(icon("fa.refresh", color="white")) # Reload icon self.layout.addWidget(self.refresh_list) self.setLayout(self.layout) diff --git a/Rare/Styles/Icons/account.png b/Rare/Styles/Icons/account.png deleted file mode 100644 index b718b8f7..00000000 Binary files a/Rare/Styles/Icons/account.png and /dev/null differ diff --git a/Rare/Styles/Icons/menu.png b/Rare/Styles/Icons/menu.png deleted file mode 100644 index 902bd2e4..00000000 Binary files a/Rare/Styles/Icons/menu.png and /dev/null differ diff --git a/Rare/Styles/Icons/settings.png b/Rare/Styles/Icons/settings.png deleted file mode 100644 index 3d83d9f2..00000000 Binary files a/Rare/Styles/Icons/settings.png and /dev/null differ diff --git a/Rare/utils/LegendaryApi.py b/Rare/utils/LegendaryApi.py index 6bf9c5df..773ea6ad 100644 --- a/Rare/utils/LegendaryApi.py +++ b/Rare/utils/LegendaryApi.py @@ -1,7 +1,10 @@ import os +from logging import getLogger from PyQt5.QtCore import QProcess, QProcessEnvironment +logger = getLogger("Legendary Utils") + def launch_game(core, app_name: str, offline: bool = False, skip_version_check: bool = False): game = core.get_installed_game(app_name) @@ -36,3 +39,21 @@ def launch_game(core, app_name: str, offline: bool = False, skip_version_check: process.setProcessEnvironment(environment) process.start(params[0], params[1:]) return process + + +def uninstall(app_name: str, core): + igame = core.get_installed_game(app_name) + try: + # Remove DLC first so directory is empty when game uninstall runs + dlcs = core.get_dlc_for_game(app_name) + for dlc in dlcs: + if (idlc := core.get_installed_game(dlc.app_name)) is not None: + logger.info(f'Uninstalling DLC "{dlc.app_name}"...') + core.uninstall_game(idlc, delete_files=True) + + logger.info(f'Removing "{igame.title}" from "{igame.install_path}"...') + core.uninstall_game(igame, delete_files=True, delete_root_directory=True) + logger.info('Game has been uninstalled.') + + except Exception as e: + logger.warning(f'Removing game failed: {e!r}, please remove {igame.install_path} manually.') diff --git a/Rare/utils/QtExtensions.py b/Rare/utils/QtExtensions.py index 06b6caa4..bb4d53ba 100644 --- a/Rare/utils/QtExtensions.py +++ b/Rare/utils/QtExtensions.py @@ -229,10 +229,10 @@ class SwitchPrivate(QObject): button = self.mPointer.palette().color(QPalette.Button) painter.setPen(Qt.NoPen) - self.mGradient.setColorAt(0, shadow.darker(130)) - self.mGradient.setColorAt(1, light.darker(130)) - self.mGradient.setStart(0, r.height()) - self.mGradient.setFinalStop(0, 0) + #self.mGradient.setColorAt(0, shadow.darker(130)) + #self.mGradient.setColorAt(1, light.darker(130)) + #self.mGradient.setStart(0, r.height()) + #self.mGradient.setFinalStop(0, 0) painter.setBrush(self.mGradient) painter.drawRoundedRect(r, r.height()/2, r.height()/2) diff --git a/requirements.txt b/requirements.txt index c9422518..b5a2644d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ legendary-gl requests Pillow PyQt5 +QtAwesome \ No newline at end of file