From 47b474a31abb32374aa845766818d8dec4deff8c Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Tue, 25 Oct 2022 16:00:26 +0300 Subject: [PATCH 01/14] StyleSheets: Remove last use of custom `noBorder` property Instead, use `QFrame.NoFrame` as `FrameShape` to set `0px` border width. --- misc/qrc2py.sh | 52 ++++++++++++++---- .../tabs/games/import_sync/egl_sync_group.py | 49 ++++++++--------- .../stylesheets/ChildOfMetropolis/__init__.py | Bin 27021 -> 26935 bytes .../ChildOfMetropolis/stylesheet.qss | 13 +++-- .../stylesheets/RareStyle/__init__.py | Bin 27087 -> 27001 bytes .../stylesheets/RareStyle/stylesheet.qss | 13 +++-- 6 files changed, 80 insertions(+), 47 deletions(-) diff --git a/misc/qrc2py.sh b/misc/qrc2py.sh index 3eb738b9..04a74082 100755 --- a/misc/qrc2py.sh +++ b/misc/qrc2py.sh @@ -1,16 +1,48 @@ -#!/bin/sh +#!/bin/bash cwd="$(pwd)" cd "$(dirname "$0")"/../ || exit -pyrcc5 -compress 6 \ - rare/resources/resources.qrc \ - -o rare/resources/resources.py -pyrcc5 -compress 6 \ - rare/resources/stylesheets/RareStyle/stylesheet.qrc \ - -o rare/resources/stylesheets/RareStyle/__init__.py -pyrcc5 -compress 6 \ - rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qrc \ - -o rare/resources/stylesheets/ChildOfMetropolis/__init__.py +resources=( + "rare/resources/images/" + "rare/resources/colors/" + "rare/resources/resources.qrc" +) + +resources_changed=0 + +for r in "${resources[@]}" +do + if [[ $(git diff --name-only HEAD "$r") ]] + then + resources_changed=1 + fi +done + +if [[ $resources_changed -eq 1 ]] +then + echo "Re-compiling main resources" + pyrcc5 -compress 6 \ + rare/resources/resources.qrc \ + -o rare/resources/resources.py +fi + +if [[ $(git diff --name-only HEAD "rare/resources/stylesheets/RareStyle/") ]] +then + echo "Re-compiling RareStyle stylesheet resources" + pyrcc5 -compress 6 \ + rare/resources/stylesheets/RareStyle/stylesheet.qrc \ + -o rare/resources/stylesheets/RareStyle/__init__.py +fi + + +if [[ $(git diff --name-only HEAD "rare/resources/stylesheets/ChildOfMetropolis/") ]] +then + echo "Re-compiling ChildOfMetropolis stylesheet resources" + pyrcc5 -compress 6 \ + rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qrc \ + -o rare/resources/stylesheets/ChildOfMetropolis/__init__.py +fi + cd "$cwd" || exit diff --git a/rare/components/tabs/games/import_sync/egl_sync_group.py b/rare/components/tabs/games/import_sync/egl_sync_group.py index 79d3ab4d..e4c40f96 100644 --- a/rare/components/tabs/games/import_sync/egl_sync_group.py +++ b/rare/components/tabs/games/import_sync/egl_sync_group.py @@ -4,7 +4,7 @@ from logging import getLogger from typing import Tuple, Iterable, List from PyQt5.QtCore import Qt, QThreadPool, QRunnable, pyqtSlot, pyqtSignal -from PyQt5.QtWidgets import QGroupBox, QListWidgetItem, QFileDialog, QMessageBox +from PyQt5.QtWidgets import QGroupBox, QListWidgetItem, QFileDialog, QMessageBox, QFrame from rare.lgndr.api_exception import LgndrException from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton @@ -207,51 +207,50 @@ class EGLSyncListItem(QListWidgetItem): return self.game.app_title -class EGLSyncListGroup(QGroupBox, Ui_EGLSyncListGroup): +class EGLSyncListGroup(QGroupBox): action_errors = pyqtSignal(list) def __init__(self, export: bool, parent=None): super(EGLSyncListGroup, self).__init__(parent=parent) - self.setupUi(self) + self.ui = Ui_EGLSyncListGroup() + self.ui.setupUi(self) + self.ui.list.setFrameShape(QFrame.NoFrame) self.core = LegendaryCoreSingleton() self.signals = GlobalSignalsSingleton() - self.list.setProperty("noBorder", 1) - # TODO: Convert the CSS and the code to adhere to NoFrame - # self.list.setFrameShape(self.list.NoFrame) self.export = export if export: self.setTitle(self.tr("Exportable games")) - self.label.setText(self.tr("No games to export to EGL")) - self.action_button.setText(self.tr("Export")) + self.ui.label.setText(self.tr("No games to export to EGL")) + self.ui.action_button.setText(self.tr("Export")) self.list_func = self.core.egl_get_exportable else: self.setTitle(self.tr("Importable games")) - self.label.setText(self.tr("No games to import from EGL")) - self.action_button.setText(self.tr("Import")) + self.ui.label.setText(self.tr("No games to import from EGL")) + self.ui.action_button.setText(self.tr("Import")) self.list_func = self.core.egl_get_importable - self.list.itemDoubleClicked.connect( + self.ui.list.itemDoubleClicked.connect( lambda item: item.setCheckState(Qt.Unchecked) if item.checkState() != Qt.Unchecked else item.setCheckState(Qt.Checked) ) - self.list.itemChanged.connect(self.has_selected) + self.ui.list.itemChanged.connect(self.has_selected) - self.select_all_button.clicked.connect(lambda: self.mark(Qt.Checked)) - self.select_none_button.clicked.connect(lambda: self.mark(Qt.Unchecked)) + self.ui.select_all_button.clicked.connect(lambda: self.mark(Qt.Checked)) + self.ui.select_none_button.clicked.connect(lambda: self.mark(Qt.Unchecked)) - self.action_button.clicked.connect(self.action) + self.ui.action_button.clicked.connect(self.action) self.action_errors.connect(self.show_errors) def has_selected(self): for item in self.items: if item.is_checked(): - self.action_button.setEnabled(True) + self.ui.action_button.setEnabled(True) return - self.action_button.setEnabled(False) + self.ui.action_button.setEnabled(False) def mark(self, state): for item in self.items: @@ -259,17 +258,17 @@ class EGLSyncListGroup(QGroupBox, Ui_EGLSyncListGroup): def populate(self, enabled: bool): if enabled: - self.list.clear() + self.ui.list.clear() for item in self.list_func(): try: - i = EGLSyncListItem(item, self.export, self.list) + i = EGLSyncListItem(item, self.export, self.ui.list) except AttributeError: logger.error(f"{item.app_name} does not work. Ignoring") else: - self.list.addItem(i) - self.label.setVisible(not enabled or not bool(self.list.count())) - self.list.setVisible(enabled and bool(self.list.count())) - self.buttons_widget.setVisible(enabled and bool(self.list.count())) + self.ui.list.addItem(i) + self.ui.label.setVisible(not enabled or not bool(self.ui.list.count())) + self.ui.list.setVisible(enabled and bool(self.ui.list.count())) + self.ui.buttons_widget.setVisible(enabled and bool(self.ui.list.count())) def action(self): imported: List = [] @@ -280,7 +279,7 @@ class EGLSyncListGroup(QGroupBox, Ui_EGLSyncListGroup): errors.append(e) else: imported.append(item.app_name) - self.list.takeItem(self.list.row(item)) + self.ui.list.takeItem(self.ui.list.row(item)) if not self.export and imported: self.signals.update_gamelist.emit(imported) self.populate(True) @@ -301,7 +300,7 @@ class EGLSyncListGroup(QGroupBox, Ui_EGLSyncListGroup): def items(self) -> Iterable[EGLSyncListItem]: # for i in range(self.list.count()): # yield self.list.item(i) - return [self.list.item(i) for i in range(self.list.count())] + return [self.ui.list.item(i) for i in range(self.ui.list.count())] class EGLSyncWorker(QRunnable): diff --git a/rare/resources/stylesheets/ChildOfMetropolis/__init__.py b/rare/resources/stylesheets/ChildOfMetropolis/__init__.py index 0fc74bf6693bf0d69c3420d4b7009a82fb885cbe..bc76ced3784c42e6d3179c24115cba88b7e95c0c 100644 GIT binary patch literal 26935 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 literal 27021 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 diff --git a/rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss b/rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss index 8d84174f..73a61f00 100644 --- a/rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss +++ b/rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss @@ -115,15 +115,12 @@ QPushButton { QToolButton { height: 1.10em; } +QFrame[frameShape="0"] { + border-width: 0px; +} QFrame[frameShape="6"] { border-radius: 4px; } -QFrame[noBorder="1"], -QListView[noBorder="1"], -QScrollArea[noBorder="1"], -QStackedWidget[noBorder="1"] { - border-color: transparent; -} QComboBox { background-color: #DADDDE; } @@ -383,6 +380,7 @@ QTableView::indicator { border-style: solid; background-color: #C2C4C5; } +QGroupBox::indicator, QCheckBox::indicator, QRadioButton::indicator, QListView::indicator, @@ -391,6 +389,9 @@ QTableView::indicator { width: 11px; height: 11px; } +QGroupBox::indicator { + padding: 0px; +} QGroupBox::indicator:disabled, QCheckBox::indicator:disabled, QRadioButton::indicator:disabled, diff --git a/rare/resources/stylesheets/RareStyle/__init__.py b/rare/resources/stylesheets/RareStyle/__init__.py index 63d76ed08f1b45ef0a2f14d49c33a201644e0644..f1cfbb3e85e9b637a61894e022fbbf4b2adab6e9 100644 GIT binary patch literal 27001 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 T4f2oH|F75ge?JcPML+mI4t08h literal 27087 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 diff --git a/rare/resources/stylesheets/RareStyle/stylesheet.qss b/rare/resources/stylesheets/RareStyle/stylesheet.qss index e04063c3..3b06c0e3 100644 --- a/rare/resources/stylesheets/RareStyle/stylesheet.qss +++ b/rare/resources/stylesheets/RareStyle/stylesheet.qss @@ -115,15 +115,12 @@ QPushButton { QToolButton { height: 1.10em; } +QFrame[frameShape="0"] { + border-width: 0px; +} QFrame[frameShape="6"] { border-radius: 4px; } -QFrame[noBorder="1"], -QListView[noBorder="1"], -QScrollArea[noBorder="1"], -QStackedWidget[noBorder="1"] { - border-color: transparent; -} QComboBox { background-color: rgb( 51, 54, 59); } @@ -383,6 +380,7 @@ QTableView::indicator { border-style: solid; background-color: rgb( 32, 34, 37); } +QGroupBox::indicator, QCheckBox::indicator, QRadioButton::indicator, QListView::indicator, @@ -391,6 +389,9 @@ QTableView::indicator { width: 11px; height: 11px; } +QGroupBox::indicator { + padding: 0px; +} QGroupBox::indicator:disabled, QCheckBox::indicator:disabled, QRadioButton::indicator:disabled, From 9fcb924ae8a0eaf86f95aff630f953fcdd603322 Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Tue, 25 Oct 2022 16:31:00 +0300 Subject: [PATCH 02/14] Widgets: Correct CollapsibleWidget name --- rare/components/dialogs/install_dialog.py | 4 ++-- rare/widgets/{collabsible_widget.py => collapsible_widget.py} | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) rename rare/widgets/{collabsible_widget.py => collapsible_widget.py} (97%) diff --git a/rare/components/dialogs/install_dialog.py b/rare/components/dialogs/install_dialog.py index d9cbf953..d95dc3c5 100644 --- a/rare/components/dialogs/install_dialog.py +++ b/rare/components/dialogs/install_dialog.py @@ -21,7 +21,7 @@ from rare.ui.components.dialogs.install_dialog import Ui_InstallDialog from rare.utils import config_helper from rare.utils.extra_widgets import PathEdit from rare.utils.misc import get_size -from rare.widgets.collabsible_widget import CollabsibleWidget +from rare.widgets.collapsible_widget import CollapsibleWidget class InstallDialog(QDialog): @@ -44,7 +44,7 @@ class InstallDialog(QDialog): else Game(app_name=self.app_name, app_title="Epic Overlay") ) self.ui.advanced_layout.setParent(None) - self.advanced_widget = CollabsibleWidget( + self.advanced_widget = CollapsibleWidget( child_layout=self.ui.advanced_layout, title=self.tr("Advanced options"), parent=self ) self.ui.collapsible_layout.addWidget(self.advanced_widget) diff --git a/rare/widgets/collabsible_widget.py b/rare/widgets/collapsible_widget.py similarity index 97% rename from rare/widgets/collabsible_widget.py rename to rare/widgets/collapsible_widget.py index f9f2280e..32cc0343 100644 --- a/rare/widgets/collabsible_widget.py +++ b/rare/widgets/collapsible_widget.py @@ -6,7 +6,7 @@ from rare.utils.misc import icon # https://newbedev.com/how-to-make-an-expandable-collapsable-section-widget-in-qt -class CollabsibleWidget(QWidget): +class CollapsibleWidget(QWidget): def __init__( self, child_layout: QLayout = None, title: str = "", animation_duration: int = 200, parent=None ): @@ -15,7 +15,7 @@ class CollabsibleWidget(QWidget): # Adapted from c++ version https://stackoverflow.com/questions/32476006/how-to-make-an-expandable-collapsable-section-widget-in-qt """ - super(CollabsibleWidget, self).__init__(parent=parent) + super(CollapsibleWidget, self).__init__(parent=parent) self.animationDuration = animation_duration self.toggleAnimation = QParallelAnimationGroup() From a5c8d92e24645165b78514881fafbfc74516786d Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Wed, 26 Oct 2022 01:33:49 +0300 Subject: [PATCH 03/14] Application: set HiDPi scaling attribute --- rare/app.py | 4 +++- rare/game_launch_helper/__init__.py | 6 +++++- rare/widgets/rare_app.py | 4 +--- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/rare/app.py b/rare/app.py index b3bc055e..f343052c 100644 --- a/rare/app.py +++ b/rare/app.py @@ -8,7 +8,7 @@ from datetime import datetime from typing import Optional import requests.exceptions -from PyQt5.QtCore import QThreadPool, QTimer, pyqtSlot +from PyQt5.QtCore import QThreadPool, QTimer, pyqtSlot, Qt from PyQt5.QtWidgets import QApplication, QMessageBox from requests import HTTPError @@ -128,6 +128,8 @@ def start(args): sys.excepthook = excepthook while True: + QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True) + QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps, True) app = App(args) exit_code = app.exec_() # if not restart diff --git a/rare/game_launch_helper/__init__.py b/rare/game_launch_helper/__init__.py index f684ed56..e7ed0224 100644 --- a/rare/game_launch_helper/__init__.py +++ b/rare/game_launch_helper/__init__.py @@ -7,9 +7,10 @@ from argparse import Namespace from logging import getLogger from typing import Union, Optional -from PyQt5.QtCore import QObject, QProcess, pyqtSignal, QUrl, QRunnable, QThreadPool, QSettings +from PyQt5.QtCore import QObject, QProcess, pyqtSignal, QUrl, QRunnable, QThreadPool, QSettings, Qt from PyQt5.QtGui import QDesktopServices from PyQt5.QtNetwork import QLocalServer, QLocalSocket +from PyQt5.QtWidgets import QApplication from rare.lgndr.core import LegendaryCore from rare.widgets.rare_app import RareApp @@ -217,6 +218,9 @@ class GameProcessApp(RareApp): def start_game(args: Namespace): args = InitArgs.from_argparse(args) + QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True) + QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps, True) + app = GameProcessApp(args) app.setQuitOnLastWindowClosed(True) diff --git a/rare/widgets/rare_app.py b/rare/widgets/rare_app.py index 86097096..f0c5df91 100644 --- a/rare/widgets/rare_app.py +++ b/rare/widgets/rare_app.py @@ -6,7 +6,7 @@ import time from argparse import Namespace import legendary -from PyQt5.QtCore import Qt, QSettings, QTranslator, QT_VERSION_STR, PYQT_VERSION_STR +from PyQt5.QtCore import QSettings, QTranslator, QT_VERSION_STR, PYQT_VERSION_STR from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import QApplication @@ -21,8 +21,6 @@ class RareApp(QApplication): def __init__(self, args: Namespace, log_file: str): super(RareApp, self).__init__(sys.argv) self.setQuitOnLastWindowClosed(False) - if hasattr(Qt, "AA_UseHighDpiPixmaps"): - self.setAttribute(Qt.AA_UseHighDpiPixmaps) self.setApplicationName("Rare") self.setOrganizationName("Rare") From e6ff2bb41ea3dd0da3e96a57f7290c7aa47deefa Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Wed, 26 Oct 2022 05:12:36 +0300 Subject: [PATCH 04/14] ImportGroup: Enable the button when "Import DLCs" changes --- .../tabs/games/import_sync/import_group.py | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/rare/components/tabs/games/import_sync/import_group.py b/rare/components/tabs/games/import_sync/import_group.py index 29a17ff5..13d3d148 100644 --- a/rare/components/tabs/games/import_sync/import_group.py +++ b/rare/components/tabs/games/import_sync/import_group.py @@ -173,7 +173,7 @@ class ImportGroup(QGroupBox): self.path_edit = PathEdit( self.core.get_default_install_dir(), QFileDialog.DirectoryOnly, - edit_func=self.path_edit_cb, + edit_func=self.path_edit_callback, parent=self, ) self.path_edit.textChanged.connect(self.path_changed) @@ -184,7 +184,7 @@ class ImportGroup(QGroupBox): completer=AppNameCompleter( app_names=[(i.app_name, i.app_title) for i in self.api_results.game_list] ), - edit_func=self.app_name_edit_cb, + edit_func=self.app_name_edit_callback, parent=self, ) self.app_name_edit.textChanged.connect(self.app_name_changed) @@ -192,6 +192,7 @@ class ImportGroup(QGroupBox): self.ui.import_folder_check.stateChanged.connect(self.import_folder_changed) self.ui.import_dlcs_check.setEnabled(False) + self.ui.import_dlcs_check.stateChanged.connect(self.import_dlcs_changed) self.ui.import_button.setEnabled(False) self.ui.import_button.clicked.connect( @@ -203,7 +204,7 @@ class ImportGroup(QGroupBox): self.threadpool = QThreadPool.globalInstance() - def path_edit_cb(self, path) -> Tuple[bool, str, str]: + def path_edit_callback(self, path) -> Tuple[bool, str, str]: if os.path.exists(path): if os.path.exists(os.path.join(path, ".egstore")): return True, path, "" @@ -213,7 +214,8 @@ class ImportGroup(QGroupBox): return False, path, PathEdit.reasons.dir_not_exist return False, path, "" - def path_changed(self, path): + @pyqtSlot(str) + def path_changed(self, path: str): self.info_label.setText("") self.ui.import_folder_check.setCheckState(Qt.Unchecked) if self.path_edit.is_valid: @@ -221,7 +223,7 @@ class ImportGroup(QGroupBox): else: self.app_name_edit.setText("") - def app_name_edit_cb(self, text) -> Tuple[bool, str, str]: + def app_name_edit_callback(self, text) -> Tuple[bool, str, str]: if not text: return False, text, "" if text in self.app_name_list: @@ -229,6 +231,7 @@ class ImportGroup(QGroupBox): else: return False, text, IndicatorLineEdit.reasons.game_not_installed + @pyqtSlot(str) def app_name_changed(self, app_name: str): self.info_label.setText("") self.ui.import_dlcs_check.setCheckState(Qt.Unchecked) @@ -241,7 +244,8 @@ class ImportGroup(QGroupBox): self.ui.import_dlcs_check.setEnabled(False) self.ui.import_button.setEnabled(False) - def import_folder_changed(self, state): + @pyqtSlot(int) + def import_folder_changed(self, state: Qt.CheckState): self.app_name_edit.setEnabled(not state) self.ui.import_dlcs_check.setCheckState(Qt.Unchecked) self.ui.import_dlcs_check.setEnabled( @@ -250,6 +254,10 @@ class ImportGroup(QGroupBox): ) self.ui.import_button.setEnabled(state or (not state and self.app_name_edit.is_valid)) + @pyqtSlot(int) + def import_dlcs_changed(self, state: Qt.CheckState): + self.ui.import_button.setEnabled(self.ui.import_folder_check.isChecked() or self.app_name_edit.is_valid) + def import_pressed(self, path=None): if not path: path = self.path_edit.text() From 5370355e5dfae9cab99da4f079a04e7487a3a928 Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Thu, 27 Oct 2022 04:00:48 +0300 Subject: [PATCH 05/14] Lgndr: Restructure module to follow legendary's file hierarchy Move overloaded class files into the folders following legendary's structure. Move Rare's integration classes into their own subfolder. --- rare/components/dialogs/install_dialog.py | 6 +++--- rare/components/tabs/downloads/__init__.py | 2 +- rare/components/tabs/downloads/download_thread.py | 4 ++-- rare/components/tabs/games/game_info/__init__.py | 2 +- rare/components/tabs/games/import_sync/egl_sync_group.py | 4 ++-- rare/components/tabs/games/import_sync/import_group.py | 4 ++-- rare/lgndr/cli.py | 8 ++++---- rare/lgndr/core.py | 5 ++--- rare/lgndr/downloader/__init__.py | 0 rare/lgndr/downloader/mp/__init__.py | 0 rare/lgndr/{ => downloader/mp}/manager.py | 4 ++-- rare/lgndr/glue/__init__.py | 0 rare/lgndr/{api_arguments.py => glue/arguments.py} | 4 ++-- rare/lgndr/{api_exception.py => glue/exception.py} | 2 +- rare/lgndr/{api_monkeys.py => glue/monkeys.py} | 0 rare/lgndr/models/__init__.py | 0 rare/lgndr/{ => models}/downloading.py | 0 rare/models/install.py | 2 +- rare/utils/legendary_utils.py | 4 ++-- 19 files changed, 25 insertions(+), 26 deletions(-) create mode 100644 rare/lgndr/downloader/__init__.py create mode 100644 rare/lgndr/downloader/mp/__init__.py rename rare/lgndr/{ => downloader/mp}/manager.py (98%) create mode 100644 rare/lgndr/glue/__init__.py rename rare/lgndr/{api_arguments.py => glue/arguments.py} (97%) rename rare/lgndr/{api_exception.py => glue/exception.py} (98%) rename rare/lgndr/{api_monkeys.py => glue/monkeys.py} (100%) create mode 100644 rare/lgndr/models/__init__.py rename rare/lgndr/{ => models}/downloading.py (100%) diff --git a/rare/components/dialogs/install_dialog.py b/rare/components/dialogs/install_dialog.py index d95dc3c5..e41dbd33 100644 --- a/rare/components/dialogs/install_dialog.py +++ b/rare/components/dialogs/install_dialog.py @@ -10,11 +10,11 @@ from legendary.models.downloading import ConditionCheckResult from legendary.models.game import Game from legendary.utils.selective_dl import get_sdl_appname -from rare.lgndr.api_arguments import LgndrInstallGameArgs -from rare.lgndr.api_exception import LgndrException -from rare.lgndr.api_monkeys import LgndrIndirectStatus from rare.lgndr.cli import LegendaryCLI from rare.lgndr.core import LegendaryCore +from rare.lgndr.glue.arguments import LgndrInstallGameArgs +from rare.lgndr.glue.exception import LgndrException +from rare.lgndr.glue.monkeys import LgndrIndirectStatus from rare.models.install import InstallDownloadModel, InstallQueueItemModel from rare.shared import LegendaryCoreSingleton, ApiResultsSingleton, ArgumentsSingleton from rare.ui.components.dialogs.install_dialog import Ui_InstallDialog diff --git a/rare/components/tabs/downloads/__init__.py b/rare/components/tabs/downloads/__init__.py index d08ce848..952935ce 100644 --- a/rare/components/tabs/downloads/__init__.py +++ b/rare/components/tabs/downloads/__init__.py @@ -17,7 +17,7 @@ from legendary.models.game import Game, InstalledGame from rare.components.dialogs.install_dialog import InstallDialog from rare.components.tabs.downloads.dl_queue_widget import DlQueueWidget, DlWidget from rare.components.tabs.downloads.download_thread import DownloadThread -from rare.lgndr.downloading import UIUpdate +from rare.lgndr.models.downloading import UIUpdate from rare.models.install import InstallOptionsModel, InstallQueueItemModel from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton from rare.ui.components.tabs.downloads.downloads_tab import Ui_DownloadsTab diff --git a/rare/components/tabs/downloads/download_thread.py b/rare/components/tabs/downloads/download_thread.py index 923dd775..6933b2f4 100644 --- a/rare/components/tabs/downloads/download_thread.py +++ b/rare/components/tabs/downloads/download_thread.py @@ -10,9 +10,9 @@ from typing import List, Optional, Dict from PyQt5.QtCore import QThread, pyqtSignal, QProcess from legendary.core import LegendaryCore -from rare.lgndr.api_monkeys import DLManagerSignals from rare.lgndr.cli import LegendaryCLI -from rare.lgndr.downloading import UIUpdate +from rare.lgndr.glue.monkeys import DLManagerSignals +from rare.lgndr.models.downloading import UIUpdate from rare.models.install import InstallQueueItemModel from rare.shared import GlobalSignalsSingleton, ArgumentsSingleton diff --git a/rare/components/tabs/games/game_info/__init__.py b/rare/components/tabs/games/game_info/__init__.py index ec3b1c82..0ebec2a4 100644 --- a/rare/components/tabs/games/game_info/__init__.py +++ b/rare/components/tabs/games/game_info/__init__.py @@ -1,12 +1,12 @@ from PyQt5.QtCore import Qt from PyQt5.QtGui import QKeyEvent +from rare.components.tabs.games.game_utils import GameUtils from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton from rare.utils.extra_widgets import SideTabWidget from .game_dlc import GameDlc from .game_info import GameInfo from .game_settings import GameSettings -from ..game_utils import GameUtils class GameInfoTabs(SideTabWidget): diff --git a/rare/components/tabs/games/import_sync/egl_sync_group.py b/rare/components/tabs/games/import_sync/egl_sync_group.py index e4c40f96..ca2ee94e 100644 --- a/rare/components/tabs/games/import_sync/egl_sync_group.py +++ b/rare/components/tabs/games/import_sync/egl_sync_group.py @@ -6,15 +6,15 @@ from typing import Tuple, Iterable, List from PyQt5.QtCore import Qt, QThreadPool, QRunnable, pyqtSlot, pyqtSignal from PyQt5.QtWidgets import QGroupBox, QListWidgetItem, QFileDialog, QMessageBox, QFrame -from rare.lgndr.api_exception import LgndrException +from rare.lgndr.glue.exception import LgndrException from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton from rare.ui.components.tabs.games.import_sync.egl_sync_group import Ui_EGLSyncGroup from rare.ui.components.tabs.games.import_sync.egl_sync_list_group import ( Ui_EGLSyncListGroup, ) from rare.utils.extra_widgets import PathEdit -from rare.utils.models import PathSpec from rare.utils.misc import WineResolver +from rare.utils.models import PathSpec logger = getLogger("EGLSync") diff --git a/rare/components/tabs/games/import_sync/import_group.py b/rare/components/tabs/games/import_sync/import_group.py index 13d3d148..bd629c11 100644 --- a/rare/components/tabs/games/import_sync/import_group.py +++ b/rare/components/tabs/games/import_sync/import_group.py @@ -10,9 +10,9 @@ from PyQt5.QtCore import Qt, QModelIndex, pyqtSignal, QRunnable, QObject, QThrea from PyQt5.QtGui import QStandardItemModel from PyQt5.QtWidgets import QFileDialog, QGroupBox, QCompleter, QTreeView, QHeaderView, QMessageBox -from rare.lgndr.api_arguments import LgndrImportGameArgs -from rare.lgndr.api_monkeys import LgndrIndirectStatus from rare.lgndr.cli import LegendaryCLI +from rare.lgndr.glue.arguments import LgndrImportGameArgs +from rare.lgndr.glue.monkeys import LgndrIndirectStatus from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ApiResultsSingleton from rare.ui.components.tabs.games.import_sync.import_group import Ui_ImportGroup from rare.utils.extra_widgets import IndicatorLineEdit, PathEdit diff --git a/rare/lgndr/cli.py b/rare/lgndr/cli.py index 1baa1094..a4216807 100644 --- a/rare/lgndr/cli.py +++ b/rare/lgndr/cli.py @@ -11,7 +11,9 @@ from legendary.models.game import Game, InstalledGame, VerifyResult from legendary.lfs.utils import validate_files from legendary.utils.selective_dl import get_sdl_appname -from .api_arguments import ( +from rare.lgndr.core import LegendaryCore +from rare.lgndr.downloader.mp.manager import DLManager +from rare.lgndr.glue.arguments import ( LgndrInstallGameArgs, LgndrImportGameArgs, LgndrVerifyGameArgs, @@ -19,9 +21,7 @@ from .api_arguments import ( LgndrInstallGameRealArgs, LgndrInstallGameRealRet, ) -from .api_monkeys import LgndrIndirectStatus, LgndrIndirectLogger -from .core import LegendaryCore -from .manager import DLManager +from rare.lgndr.glue.monkeys import LgndrIndirectStatus, LgndrIndirectLogger # fmt: off diff --git a/rare/lgndr/core.py b/rare/lgndr/core.py index b12d66ae..52fb26dc 100644 --- a/rare/lgndr/core.py +++ b/rare/lgndr/core.py @@ -1,4 +1,3 @@ -from hashlib import sha1 from multiprocessing import Queue # On Windows the monkeypatching of `run_real` below doesn't work like on Linux @@ -10,8 +9,8 @@ from legendary.models.downloading import AnalysisResult from legendary.models.game import Game, InstalledGame from legendary.models.manifest import ManifestMeta -from .api_exception import LgndrException, LgndrCoreLogHandler -from .manager import DLManager +from rare.lgndr.downloader.mp.manager import DLManager +from rare.lgndr.glue.exception import LgndrException, LgndrCoreLogHandler legendary.core.DLManager = DLManager diff --git a/rare/lgndr/downloader/__init__.py b/rare/lgndr/downloader/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/rare/lgndr/downloader/mp/__init__.py b/rare/lgndr/downloader/mp/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/rare/lgndr/manager.py b/rare/lgndr/downloader/mp/manager.py similarity index 98% rename from rare/lgndr/manager.py rename to rare/lgndr/downloader/mp/manager.py index b9eb32d2..9a783668 100644 --- a/rare/lgndr/manager.py +++ b/rare/lgndr/downloader/mp/manager.py @@ -11,8 +11,8 @@ from legendary.downloader.mp.manager import DLManager as DLManagerReal from legendary.downloader.mp.workers import DLWorker, FileWorker from legendary.models.downloading import ChunkTask, SharedMemorySegment, TerminateWorkerTask -from .downloading import UIUpdate -from .api_monkeys import DLManagerSignals +from rare.lgndr.glue.monkeys import DLManagerSignals +from rare.lgndr.models.downloading import UIUpdate # fmt: off diff --git a/rare/lgndr/glue/__init__.py b/rare/lgndr/glue/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/rare/lgndr/api_arguments.py b/rare/lgndr/glue/arguments.py similarity index 97% rename from rare/lgndr/api_arguments.py rename to rare/lgndr/glue/arguments.py index 03a28942..5bc6d0d2 100644 --- a/rare/lgndr/api_arguments.py +++ b/rare/lgndr/glue/arguments.py @@ -2,14 +2,14 @@ from dataclasses import dataclass from enum import IntEnum from typing import Callable, List, Optional, Dict -from .api_monkeys import ( +from rare.lgndr.glue.monkeys import ( LgndrIndirectStatus, GetBooleanChoiceProtocol, get_boolean_choice, verify_stdout, DLManagerSignals ) -from .downloading import UIUpdate +from rare.lgndr.models.downloading import UIUpdate """ @dataclass(kw_only=True) diff --git a/rare/lgndr/api_exception.py b/rare/lgndr/glue/exception.py similarity index 98% rename from rare/lgndr/api_exception.py rename to rare/lgndr/glue/exception.py index 11779f79..34c24c27 100644 --- a/rare/lgndr/api_exception.py +++ b/rare/lgndr/glue/exception.py @@ -1,5 +1,5 @@ import logging -import warnings +# import warnings class LgndrException(RuntimeError): diff --git a/rare/lgndr/api_monkeys.py b/rare/lgndr/glue/monkeys.py similarity index 100% rename from rare/lgndr/api_monkeys.py rename to rare/lgndr/glue/monkeys.py diff --git a/rare/lgndr/models/__init__.py b/rare/lgndr/models/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/rare/lgndr/downloading.py b/rare/lgndr/models/downloading.py similarity index 100% rename from rare/lgndr/downloading.py rename to rare/lgndr/models/downloading.py diff --git a/rare/models/install.py b/rare/models/install.py index d9a487c9..6b5d6122 100644 --- a/rare/models/install.py +++ b/rare/models/install.py @@ -6,7 +6,7 @@ from typing import List, Optional, Callable, Dict from legendary.models.downloading import AnalysisResult, ConditionCheckResult from legendary.models.game import Game, InstalledGame -from rare.lgndr.manager import DLManager +from rare.lgndr.downloader.mp.manager import DLManager @dataclass diff --git a/rare/utils/legendary_utils.py b/rare/utils/legendary_utils.py index 77fccfe6..f8d0523f 100644 --- a/rare/utils/legendary_utils.py +++ b/rare/utils/legendary_utils.py @@ -5,9 +5,9 @@ from logging import getLogger from PyQt5.QtCore import pyqtSignal, QObject, QRunnable, QStandardPaths from legendary.core import LegendaryCore -from rare.lgndr.api_arguments import LgndrVerifyGameArgs, LgndrUninstallGameArgs -from rare.lgndr.api_monkeys import LgndrIndirectStatus from rare.lgndr.cli import LegendaryCLI +from rare.lgndr.glue.arguments import LgndrVerifyGameArgs, LgndrUninstallGameArgs +from rare.lgndr.glue.monkeys import LgndrIndirectStatus from rare.shared import LegendaryCoreSingleton, ArgumentsSingleton from rare.utils import config_helper From eae2bdaa8a3535e79e4c7ce3af1931ddca009f1c Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Thu, 27 Oct 2022 04:14:29 +0300 Subject: [PATCH 06/14] StyleSheets: Add padding to checkable QGroupBox to align it --- .../stylesheets/ChildOfMetropolis/__init__.py | Bin 26935 -> 26935 bytes .../ChildOfMetropolis/stylesheet.qss | 2 +- .../stylesheets/RareStyle/__init__.py | Bin 27001 -> 27005 bytes .../stylesheets/RareStyle/stylesheet.qss | 2 +- 4 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rare/resources/stylesheets/ChildOfMetropolis/__init__.py b/rare/resources/stylesheets/ChildOfMetropolis/__init__.py index bc76ced3784c42e6d3179c24115cba88b7e95c0c..579682c6075c6fccd6265f855470e617400ffb50 100644 GIT binary patch literal 26935 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 literal 26935 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 diff --git a/rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss b/rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss index 73a61f00..161f0628 100644 --- a/rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss +++ b/rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss @@ -390,7 +390,7 @@ QTableView::indicator { height: 11px; } QGroupBox::indicator { - padding: 0px; + padding: 1px; } QGroupBox::indicator:disabled, QCheckBox::indicator:disabled, diff --git a/rare/resources/stylesheets/RareStyle/__init__.py b/rare/resources/stylesheets/RareStyle/__init__.py index f1cfbb3e85e9b637a61894e022fbbf4b2adab6e9..5eaf4146c214f95e2affb8578afd169c70270c63 100644 GIT binary patch delta 5608 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 S(>_mdocy1iFMjXo)Bga8hJKv@ delta 5576 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 diff --git a/rare/resources/stylesheets/RareStyle/stylesheet.qss b/rare/resources/stylesheets/RareStyle/stylesheet.qss index 3b06c0e3..3a89b202 100644 --- a/rare/resources/stylesheets/RareStyle/stylesheet.qss +++ b/rare/resources/stylesheets/RareStyle/stylesheet.qss @@ -390,7 +390,7 @@ QTableView::indicator { height: 11px; } QGroupBox::indicator { - padding: 0px; + padding: 1px; } QGroupBox::indicator:disabled, QCheckBox::indicator:disabled, From ae43fd7ea3da21048250a6824a1bd11fd8fc452f Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Thu, 27 Oct 2022 16:34:53 +0300 Subject: [PATCH 07/14] StyleSheets: Apply padding to QGroupBox --- .../stylesheets/ChildOfMetropolis/__init__.py | Bin 26935 -> 26969 bytes .../ChildOfMetropolis/stylesheet.qss | 2 ++ .../stylesheets/RareStyle/__init__.py | Bin 27005 -> 27029 bytes .../stylesheets/RareStyle/stylesheet.qss | 4 +++- 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/rare/resources/stylesheets/ChildOfMetropolis/__init__.py b/rare/resources/stylesheets/ChildOfMetropolis/__init__.py index 579682c6075c6fccd6265f855470e617400ffb50..5e825b3c64e7ef53d31ef05d94959d682f13fe0a 100644 GIT binary patch literal 26969 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 literal 26935 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 diff --git a/rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss b/rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss index 161f0628..c0d0defa 100644 --- a/rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss +++ b/rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss @@ -65,6 +65,7 @@ QTableView::item, QHeaderView::section, QTableView QTableCornerButton::section, QFrame[frameShape="6"], +QGroupBox, QLineEdit, QTextEdit, QTimeEdit, @@ -483,6 +484,7 @@ QGroupBox::title { */ background-color: #B2D3DE; } +QToolBox::tab:disabled, QGroupBox::title:disabled { border-color: #767778; background-color: #A8AAAB; diff --git a/rare/resources/stylesheets/RareStyle/__init__.py b/rare/resources/stylesheets/RareStyle/__init__.py index 5eaf4146c214f95e2affb8578afd169c70270c63..c1f610f04fcfde0e9343f8e2dcb8927a03a96bbb 100644 GIT binary patch literal 27029 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 literal 27005 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 Z+sjv9elf^D;Qt@5-u(R}*jN4Fe*r0}aDD&) diff --git a/rare/resources/stylesheets/RareStyle/stylesheet.qss b/rare/resources/stylesheets/RareStyle/stylesheet.qss index 3a89b202..1fdef16d 100644 --- a/rare/resources/stylesheets/RareStyle/stylesheet.qss +++ b/rare/resources/stylesheets/RareStyle/stylesheet.qss @@ -65,6 +65,7 @@ QTableView::item, QHeaderView::section, QTableView QTableCornerButton::section, QFrame[frameShape="6"], +QGroupBox, QLineEdit, QTextEdit, QTimeEdit, @@ -390,7 +391,7 @@ QTableView::indicator { height: 11px; } QGroupBox::indicator { - padding: 1px; + padding: 0px; } QGroupBox::indicator:disabled, QCheckBox::indicator:disabled, @@ -483,6 +484,7 @@ QGroupBox::title { */ background-color: rgb( 42, 40, 63); } +QToolBox::tab:disabled, QGroupBox::title:disabled { border-color: rgb( 67, 71, 77); background-color: rgb( 41, 43, 47); From 435d560b5c5fa89973a33da43aaf40e3f2b79b88 Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Mon, 31 Oct 2022 16:54:40 +0200 Subject: [PATCH 08/14] InstallDialog: Update the collapsible widget to take a widget instead of a layout This change makes it more inline with how QScrollArea operates on a central widget. Other changes include using a QFrame instead of a QWidget as a base and adding a QLabel for the title instead of the horizontal line. The advanced options were split into their own separate widget. Right now their class operates only as a container with the logic remaining in the InstallDialog. --- rare/components/dialogs/install_dialog.py | 128 +++++---- rare/ui/components/dialogs/install_dialog.py | 135 +--------- rare/ui/components/dialogs/install_dialog.ui | 233 +---------------- .../dialogs/install_dialog_advanced.py | 30 +-- .../dialogs/install_dialog_advanced.ui | 8 +- rare/widgets/collapsible_widget.py | 247 +++++++++++++----- 6 files changed, 289 insertions(+), 492 deletions(-) diff --git a/rare/components/dialogs/install_dialog.py b/rare/components/dialogs/install_dialog.py index e41dbd33..7d2becf2 100644 --- a/rare/components/dialogs/install_dialog.py +++ b/rare/components/dialogs/install_dialog.py @@ -5,7 +5,7 @@ from typing import Tuple, List, Union, Optional from PyQt5.QtCore import Qt, QObject, QRunnable, QThreadPool, pyqtSignal, pyqtSlot, QSettings from PyQt5.QtGui import QCloseEvent, QKeyEvent -from PyQt5.QtWidgets import QDialog, QFileDialog, QCheckBox, QLayout +from PyQt5.QtWidgets import QDialog, QFileDialog, QCheckBox, QLayout, QWidget, QVBoxLayout, QApplication from legendary.models.downloading import ConditionCheckResult from legendary.models.game import Game from legendary.utils.selective_dl import get_sdl_appname @@ -18,10 +18,20 @@ from rare.lgndr.glue.monkeys import LgndrIndirectStatus from rare.models.install import InstallDownloadModel, InstallQueueItemModel from rare.shared import LegendaryCoreSingleton, ApiResultsSingleton, ArgumentsSingleton from rare.ui.components.dialogs.install_dialog import Ui_InstallDialog +from rare.ui.components.dialogs.install_dialog_advanced import Ui_InstallDialogAdvanced from rare.utils import config_helper from rare.utils.extra_widgets import PathEdit from rare.utils.misc import get_size -from rare.widgets.collapsible_widget import CollapsibleWidget +from rare.widgets.collapsible_widget import CollapsibleFrame + + +class InstallDialogAdvanced(CollapsibleFrame): + def __init__(self, parent=None): + widget = QWidget() + title = widget.tr("Advanced Options") + self.ui = Ui_InstallDialogAdvanced() + self.ui.setupUi(widget) + super(InstallDialogAdvanced, self).__init__(widget=widget, title=title, parent=parent) class InstallDialog(QDialog): @@ -43,11 +53,12 @@ class InstallDialog(QDialog): if not self.dl_item.options.overlay else Game(app_name=self.app_name, app_title="Epic Overlay") ) - self.ui.advanced_layout.setParent(None) - self.advanced_widget = CollapsibleWidget( - child_layout=self.ui.advanced_layout, title=self.tr("Advanced options"), parent=self - ) - self.ui.collapsible_layout.addWidget(self.advanced_widget) + + self.advanced = InstallDialogAdvanced(parent=self) + self.ui.advanced_layout.addWidget(self.advanced) + + self.selectable = CollapsibleFrame(widget=None, title=self.tr("Optional downloads"), parent=self) + self.ui.selectable_layout.addWidget(self.selectable) self.game_path = self.game.metadata.get("customAttributes", {}).get("FolderName", {}).get("value", "") @@ -64,7 +75,7 @@ class InstallDialog(QDialog): header = self.tr("Update") if update else self.tr("Install") self.ui.install_dialog_label.setText(f'

{header} "{self.game.app_title}"

') - self.setWindowTitle(f'{self.windowTitle()} - {header} "{self.game.app_title}"') + self.setWindowTitle(f'{QApplication.instance().applicationName()} - {header} "{self.game.app_title}"') if not self.dl_item.options.base_path: self.dl_item.options.base_path = self.core.lgd.config.get( @@ -112,19 +123,23 @@ class InstallDialog(QDialog): if pf.system() == "Darwin" and "Mac" in platforms: self.ui.platform_combo.setCurrentIndex(platforms.index("Mac")) - self.ui.max_workers_spin.setValue(self.core.lgd.config.getint("Legendary", "max_workers", fallback=0)) - self.ui.max_workers_spin.valueChanged.connect(self.option_changed) + self.advanced.ui.max_workers_spin.setValue(self.core.lgd.config.getint("Legendary", "max_workers", fallback=0)) + self.advanced.ui.max_workers_spin.valueChanged.connect(self.option_changed) - self.ui.max_memory_spin.setValue(self.core.lgd.config.getint("Legendary", "max_memory", fallback=0)) - self.ui.max_memory_spin.valueChanged.connect(self.option_changed) + self.advanced.ui.max_memory_spin.setValue(self.core.lgd.config.getint("Legendary", "max_memory", fallback=0)) + self.advanced.ui.max_memory_spin.valueChanged.connect(self.option_changed) - self.ui.dl_optimizations_check.stateChanged.connect(self.option_changed) - self.ui.force_download_check.stateChanged.connect(self.option_changed) - self.ui.ignore_space_check.stateChanged.connect(self.option_changed) - self.ui.download_only_check.stateChanged.connect(lambda: self.non_reload_option_changed("download_only")) - self.ui.shortcut_check.stateChanged.connect(lambda: self.non_reload_option_changed("shortcut")) + self.advanced.ui.dl_optimizations_check.stateChanged.connect(self.option_changed) + self.advanced.ui.force_download_check.stateChanged.connect(self.option_changed) + self.advanced.ui.ignore_space_check.stateChanged.connect(self.option_changed) + self.advanced.ui.download_only_check.stateChanged.connect( + lambda: self.non_reload_option_changed("download_only") + ) + self.ui.shortcut_check.stateChanged.connect( + lambda: self.non_reload_option_changed("shortcut") + ) - self.sdl_list_cbs: List[TagCheckBox] = [] + self.selectable_checks: List[TagCheckBox] = [] self.config_tags: Optional[List[str]] = None self.setup_sdl_list("Mac" if pf.system() == "Darwin" and "Mac" in platforms else "Windows") @@ -133,23 +148,24 @@ class InstallDialog(QDialog): if self.dl_item.options.overlay: self.ui.platform_label.setVisible(False) self.ui.platform_combo.setVisible(False) - self.ui.ignore_space_label.setVisible(False) - self.ui.ignore_space_check.setVisible(False) - self.ui.download_only_label.setVisible(False) - self.ui.download_only_check.setVisible(False) + self.advanced.ui.ignore_space_label.setVisible(False) + self.advanced.ui.ignore_space_check.setVisible(False) + self.advanced.ui.download_only_label.setVisible(False) + self.advanced.ui.download_only_check.setVisible(False) self.ui.shortcut_label.setVisible(False) self.ui.shortcut_check.setVisible(False) - self.ui.sdl_list_label.setVisible(False) - self.ui.sdl_list_frame.setVisible(False) + self.selectable.setVisible(False) if pf.system() == "Darwin": self.ui.shortcut_check.setDisabled(True) self.ui.shortcut_check.setChecked(False) self.ui.shortcut_check.setToolTip(self.tr("Creating a shortcut is not supported on MacOS")) - self.ui.install_prereqs_label.setEnabled(False) - self.ui.install_prereqs_check.setEnabled(False) - self.ui.install_prereqs_check.stateChanged.connect(lambda: self.non_reload_option_changed("install_prereqs")) + self.advanced.ui.install_prereqs_label.setEnabled(False) + self.advanced.ui.install_prereqs_check.setEnabled(False) + self.advanced.ui.install_prereqs_check.stateChanged.connect( + lambda: self.non_reload_option_changed("install_prereqs") + ) self.non_reload_option_changed("shortcut") @@ -157,7 +173,7 @@ class InstallDialog(QDialog): self.ui.verify_button.clicked.connect(self.verify_clicked) self.ui.install_button.clicked.connect(self.install_clicked) - self.ui.install_prereqs_check.setChecked(self.dl_item.options.install_prereqs) + self.advanced.ui.install_prereqs_check.setChecked(self.dl_item.options.install_prereqs) self.ui.install_dialog_layout.setSizeConstraint(QLayout.SetFixedSize) @@ -171,20 +187,22 @@ class InstallDialog(QDialog): @pyqtSlot(str) def setup_sdl_list(self, platform="Windows"): - for cb in self.sdl_list_cbs: + for cb in self.selectable_checks: cb.disconnect() cb.deleteLater() - self.sdl_list_cbs.clear() + self.selectable_checks.clear() if config_tags := self.core.lgd.config.get(self.game.app_name, 'install_tags', fallback=None): self.config_tags = config_tags.split(",") config_disable_sdl = self.core.lgd.config.getboolean(self.game.app_name, 'disable_sdl', fallback=False) sdl_name = get_sdl_appname(self.game.app_name) if not config_disable_sdl and sdl_name is not None: - self.ui.sdl_list_text.hide() # FIXME: this should be updated whenever platform changes sdl_data = self.core.get_sdl_data(sdl_name, platform=platform) if sdl_data: + widget = QWidget(self.selectable) + layout = QVBoxLayout(widget) + layout.setSpacing(0) for tag, info in sdl_data.items(): cb = TagCheckBox(info["name"], info["tags"]) if tag == "__required": @@ -193,30 +211,29 @@ class InstallDialog(QDialog): if self.config_tags is not None: if all(elem in self.config_tags for elem in info["tags"]): cb.setChecked(True) - self.ui.sdl_list_layout.addWidget(cb) - self.sdl_list_cbs.append(cb) - for cb in self.sdl_list_cbs: + layout.addWidget(cb) + self.selectable_checks.append(cb) + for cb in self.selectable_checks: cb.stateChanged.connect(self.option_changed) + self.selectable.setWidget(widget) else: - self.ui.sdl_list_text.show() - self.ui.sdl_list_label.setEnabled(False) - self.ui.sdl_list_frame.setEnabled(False) + self.selectable.setDisabled(True) def get_options(self): self.dl_item.options.base_path = self.install_dir_edit.text() if not self.update else None - self.dl_item.options.max_workers = self.ui.max_workers_spin.value() - self.dl_item.options.shared_memory = self.ui.max_memory_spin.value() - self.dl_item.options.order_opt = self.ui.dl_optimizations_check.isChecked() - self.dl_item.options.force = self.ui.force_download_check.isChecked() - self.dl_item.options.ignore_space = self.ui.ignore_space_check.isChecked() - self.dl_item.options.no_install = self.ui.download_only_check.isChecked() + self.dl_item.options.max_workers = self.advanced.ui.max_workers_spin.value() + self.dl_item.options.shared_memory = self.advanced.ui.max_memory_spin.value() + self.dl_item.options.order_opt = self.advanced.ui.dl_optimizations_check.isChecked() + self.dl_item.options.force = self.advanced.ui.force_download_check.isChecked() + self.dl_item.options.ignore_space = self.advanced.ui.ignore_space_check.isChecked() + self.dl_item.options.no_install = self.advanced.ui.download_only_check.isChecked() self.dl_item.options.platform = self.ui.platform_combo.currentText() - self.dl_item.options.install_prereqs = self.ui.install_prereqs_check.isChecked() + self.dl_item.options.install_prereqs = self.advanced.ui.install_prereqs_check.isChecked() self.dl_item.options.create_shortcut = self.ui.shortcut_check.isChecked() - if self.sdl_list_cbs: + if self.selectable_checks: self.dl_item.options.install_tag = [""] - for cb in self.sdl_list_cbs: + for cb in self.selectable_checks: if data := cb.isChecked(): # noinspection PyTypeChecker self.dl_item.options.install_tag.extend(data) @@ -253,12 +270,12 @@ class InstallDialog(QDialog): def non_reload_option_changed(self, option: str): if option == "download_only": - self.dl_item.options.no_install = self.ui.download_only_check.isChecked() + self.dl_item.options.no_install = self.advanced.ui.download_only_check.isChecked() elif option == "shortcut": QSettings().setValue("create_shortcut", self.ui.shortcut_check.isChecked()) self.dl_item.options.create_shortcut = self.ui.shortcut_check.isChecked() elif option == "install_prereqs": - self.dl_item.options.install_prereqs = self.ui.install_prereqs_check.isChecked() + self.dl_item.options.install_prereqs = self.advanced.ui.install_prereqs_check.isChecked() def cancel_clicked(self): if self.config_tags: @@ -292,13 +309,13 @@ class InstallDialog(QDialog): self.ui.cancel_button.setEnabled(True) if pf.system() == "Windows" or ArgumentsSingleton().debug: if dl_item.igame.prereq_info and not dl_item.igame.prereq_info.get("installed", False): - self.ui.install_prereqs_check.setEnabled(True) - self.ui.install_prereqs_label.setEnabled(True) - self.ui.install_prereqs_check.setChecked(True) + self.advanced.ui.install_prereqs_check.setEnabled(True) + self.advanced.ui.install_prereqs_label.setEnabled(True) + self.advanced.ui.install_prereqs_check.setChecked(True) prereq_name = dl_item.igame.prereq_info.get("name", "") prereq_path = os.path.split(dl_item.igame.prereq_info.get("path", ""))[-1] prereq_desc = prereq_name if prereq_name else prereq_path - self.ui.install_prereqs_check.setText( + self.advanced.ui.install_prereqs_check.setText( self.tr("Also install: {}").format(prereq_desc) ) if self.silent: @@ -333,7 +350,7 @@ class InstallDialog(QDialog): self.threadpool.clear() self.threadpool.waitForDone() self.result_ready.emit(self.dl_item) - a0.accept() + super(InstallDialog, self).closeEvent(a0) def keyPressEvent(self, e: QKeyEvent) -> None: if e.key() == Qt.Key_Escape: @@ -403,7 +420,4 @@ class TagCheckBox(QCheckBox): self.tags = tags def isChecked(self) -> Union[bool, List[str]]: - if super(TagCheckBox, self).isChecked(): - return self.tags - else: - return False + return self.tags if super(TagCheckBox, self).isChecked() else False diff --git a/rare/ui/components/dialogs/install_dialog.py b/rare/ui/components/dialogs/install_dialog.py index 01c1a99a..389a42f1 100644 --- a/rare/ui/components/dialogs/install_dialog.py +++ b/rare/ui/components/dialogs/install_dialog.py @@ -14,8 +14,8 @@ from PyQt5 import QtCore, QtGui, QtWidgets class Ui_InstallDialog(object): def setupUi(self, InstallDialog): InstallDialog.setObjectName("InstallDialog") - InstallDialog.resize(383, 438) - InstallDialog.setWindowTitle("Rare") + InstallDialog.resize(324, 224) + InstallDialog.setWindowTitle("InstallDialog") self.install_dialog_layout = QtWidgets.QFormLayout(InstallDialog) self.install_dialog_layout.setLabelAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) self.install_dialog_layout.setObjectName("install_dialog_layout") @@ -47,119 +47,12 @@ class Ui_InstallDialog(object): self.shortcut_check.setText("") self.shortcut_check.setObjectName("shortcut_check") self.install_dialog_layout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.shortcut_check) - self.sdl_list_label = QtWidgets.QLabel(InstallDialog) - self.sdl_list_label.setObjectName("sdl_list_label") - self.install_dialog_layout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.sdl_list_label) - self.sdl_list_frame = QtWidgets.QFrame(InstallDialog) - self.sdl_list_frame.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.sdl_list_frame.setFrameShadow(QtWidgets.QFrame.Raised) - self.sdl_list_frame.setObjectName("sdl_list_frame") - self.sdl_list_layout = QtWidgets.QVBoxLayout(self.sdl_list_frame) - self.sdl_list_layout.setSizeConstraint(QtWidgets.QLayout.SetFixedSize) - self.sdl_list_layout.setContentsMargins(-1, 0, -1, 0) - self.sdl_list_layout.setSpacing(0) - self.sdl_list_layout.setObjectName("sdl_list_layout") - self.sdl_list_text = QtWidgets.QLabel(self.sdl_list_frame) - self.sdl_list_text.setObjectName("sdl_list_text") - self.sdl_list_layout.addWidget(self.sdl_list_text) - self.install_dialog_layout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.sdl_list_frame) - self.collapsible_layout = QtWidgets.QVBoxLayout() - self.collapsible_layout.setObjectName("collapsible_layout") - self.advanced_layout = QtWidgets.QFormLayout() - self.advanced_layout.setLabelAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.selectable_layout = QtWidgets.QVBoxLayout() + self.selectable_layout.setObjectName("selectable_layout") + self.install_dialog_layout.setLayout(4, QtWidgets.QFormLayout.SpanningRole, self.selectable_layout) + self.advanced_layout = QtWidgets.QVBoxLayout() self.advanced_layout.setObjectName("advanced_layout") - self.max_workers_label = QtWidgets.QLabel(InstallDialog) - self.max_workers_label.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.max_workers_label.setObjectName("max_workers_label") - self.advanced_layout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.max_workers_label) - self.max_workers_layout = QtWidgets.QHBoxLayout() - self.max_workers_layout.setObjectName("max_workers_layout") - self.max_workers_spin = QtWidgets.QSpinBox(InstallDialog) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.max_workers_spin.sizePolicy().hasHeightForWidth()) - self.max_workers_spin.setSizePolicy(sizePolicy) - self.max_workers_spin.setObjectName("max_workers_spin") - self.max_workers_layout.addWidget(self.max_workers_spin) - self.max_workers_info_label = QtWidgets.QLabel(InstallDialog) - font = QtGui.QFont() - font.setItalic(True) - self.max_workers_info_label.setFont(font) - self.max_workers_info_label.setObjectName("max_workers_info_label") - self.max_workers_layout.addWidget(self.max_workers_info_label) - self.advanced_layout.setLayout(0, QtWidgets.QFormLayout.FieldRole, self.max_workers_layout) - self.max_memory_label = QtWidgets.QLabel(InstallDialog) - self.max_memory_label.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) - self.max_memory_label.setObjectName("max_memory_label") - self.advanced_layout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.max_memory_label) - self.max_memory_layout = QtWidgets.QHBoxLayout() - self.max_memory_layout.setObjectName("max_memory_layout") - self.max_memory_spin = QtWidgets.QSpinBox(InstallDialog) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.max_memory_spin.sizePolicy().hasHeightForWidth()) - self.max_memory_spin.setSizePolicy(sizePolicy) - self.max_memory_spin.setMinimum(0) - self.max_memory_spin.setMaximum(10240) - self.max_memory_spin.setSingleStep(128) - self.max_memory_spin.setProperty("value", 1024) - self.max_memory_spin.setObjectName("max_memory_spin") - self.max_memory_layout.addWidget(self.max_memory_spin) - self.max_memory_info_label = QtWidgets.QLabel(InstallDialog) - font = QtGui.QFont() - font.setItalic(True) - self.max_memory_info_label.setFont(font) - self.max_memory_info_label.setObjectName("max_memory_info_label") - self.max_memory_layout.addWidget(self.max_memory_info_label) - self.advanced_layout.setLayout(1, QtWidgets.QFormLayout.FieldRole, self.max_memory_layout) - self.install_prereqs_label = QtWidgets.QLabel(InstallDialog) - self.install_prereqs_label.setObjectName("install_prereqs_label") - self.advanced_layout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.install_prereqs_label) - self.install_prereqs_check = QtWidgets.QCheckBox(InstallDialog) - font = QtGui.QFont() - font.setItalic(True) - self.install_prereqs_check.setFont(font) - self.install_prereqs_check.setText("") - self.install_prereqs_check.setChecked(False) - self.install_prereqs_check.setObjectName("install_prereqs_check") - self.advanced_layout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.install_prereqs_check) - self.dl_optimizations_label = QtWidgets.QLabel(InstallDialog) - self.dl_optimizations_label.setObjectName("dl_optimizations_label") - self.advanced_layout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.dl_optimizations_label) - self.dl_optimizations_check = QtWidgets.QCheckBox(InstallDialog) - self.dl_optimizations_check.setText("") - self.dl_optimizations_check.setChecked(False) - self.dl_optimizations_check.setObjectName("dl_optimizations_check") - self.advanced_layout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.dl_optimizations_check) - self.force_download_label = QtWidgets.QLabel(InstallDialog) - self.force_download_label.setObjectName("force_download_label") - self.advanced_layout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.force_download_label) - self.force_download_check = QtWidgets.QCheckBox(InstallDialog) - self.force_download_check.setText("") - self.force_download_check.setObjectName("force_download_check") - self.advanced_layout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.force_download_check) - self.ignore_space_label = QtWidgets.QLabel(InstallDialog) - self.ignore_space_label.setObjectName("ignore_space_label") - self.advanced_layout.setWidget(5, QtWidgets.QFormLayout.LabelRole, self.ignore_space_label) - self.ignore_space_check = QtWidgets.QCheckBox(InstallDialog) - font = QtGui.QFont() - font.setItalic(True) - self.ignore_space_check.setFont(font) - self.ignore_space_check.setObjectName("ignore_space_check") - self.advanced_layout.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.ignore_space_check) - self.download_only_label = QtWidgets.QLabel(InstallDialog) - self.download_only_label.setObjectName("download_only_label") - self.advanced_layout.setWidget(6, QtWidgets.QFormLayout.LabelRole, self.download_only_label) - self.download_only_check = QtWidgets.QCheckBox(InstallDialog) - font = QtGui.QFont() - font.setItalic(True) - self.download_only_check.setFont(font) - self.download_only_check.setObjectName("download_only_check") - self.advanced_layout.setWidget(6, QtWidgets.QFormLayout.FieldRole, self.download_only_check) - self.collapsible_layout.addLayout(self.advanced_layout) - self.install_dialog_layout.setLayout(5, QtWidgets.QFormLayout.SpanningRole, self.collapsible_layout) + self.install_dialog_layout.setLayout(5, QtWidgets.QFormLayout.SpanningRole, self.advanced_layout) self.download_size_label = QtWidgets.QLabel(InstallDialog) self.download_size_label.setObjectName("download_size_label") self.install_dialog_layout.setWidget(6, QtWidgets.QFormLayout.LabelRole, self.download_size_label) @@ -215,20 +108,6 @@ class Ui_InstallDialog(object): self.install_dir_label.setText(_translate("InstallDialog", "Install directory")) self.platform_label.setText(_translate("InstallDialog", "Platform")) self.shortcut_label.setText(_translate("InstallDialog", "Create shortcut")) - self.sdl_list_label.setText(_translate("InstallDialog", "Optional packs")) - self.sdl_list_text.setText(_translate("InstallDialog", "None")) - self.max_workers_label.setText(_translate("InstallDialog", "Max workers")) - self.max_workers_info_label.setText(_translate("InstallDialog", "Less is slower. (0: Default)")) - self.max_memory_label.setText(_translate("InstallDialog", "Max shared memory")) - self.max_memory_spin.setSuffix(_translate("InstallDialog", "MiB")) - self.max_memory_info_label.setText(_translate("InstallDialog", "Less is slower (0: Default)")) - self.install_prereqs_label.setText(_translate("InstallDialog", "Install prerequisites")) - self.dl_optimizations_label.setText(_translate("InstallDialog", "Enable reordering")) - self.force_download_label.setText(_translate("InstallDialog", "Force redownload")) - self.ignore_space_label.setText(_translate("InstallDialog", "Ignore free space")) - self.ignore_space_check.setText(_translate("InstallDialog", "Use with caution!")) - self.download_only_label.setText(_translate("InstallDialog", "Download only")) - self.download_only_check.setText(_translate("InstallDialog", "Do not try to install.")) self.download_size_label.setText(_translate("InstallDialog", "Download size")) self.download_size_text.setText(_translate("InstallDialog", "Click verify...")) self.install_size_label.setText(_translate("InstallDialog", "Total install size")) diff --git a/rare/ui/components/dialogs/install_dialog.ui b/rare/ui/components/dialogs/install_dialog.ui index 4111ce79..fb100a69 100644 --- a/rare/ui/components/dialogs/install_dialog.ui +++ b/rare/ui/components/dialogs/install_dialog.ui @@ -6,12 +6,12 @@ 0 0 - 383 - 438 + 324 + 224 - Rare + InstallDialog @@ -68,232 +68,11 @@ - - - - Optional packs - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - 0 - - - QLayout::SetFixedSize - - - 0 - - - 0 - - - - - None - - - - - + + - - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - Max workers - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - - - - 0 - 0 - - - - - - - - - true - - - - Less is slower. (0: Default) - - - - - - - - - Max shared memory - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - - - - 0 - 0 - - - - MiB - - - 0 - - - 10240 - - - 128 - - - 1024 - - - - - - - - true - - - - Less is slower (0: Default) - - - - - - - - - Install prerequisites - - - - - - - - true - - - - - - - false - - - - - - - Enable reordering - - - - - - - - - - false - - - - - - - Force redownload - - - - - - - - - - - - - - Ignore free space - - - - - - - - true - - - - Use with caution! - - - - - - - Download only - - - - - - - - true - - - - Do not try to install. - - - - - - + diff --git a/rare/ui/components/dialogs/install_dialog_advanced.py b/rare/ui/components/dialogs/install_dialog_advanced.py index c853bb74..736b6d10 100644 --- a/rare/ui/components/dialogs/install_dialog_advanced.py +++ b/rare/ui/components/dialogs/install_dialog_advanced.py @@ -15,6 +15,7 @@ class Ui_InstallDialogAdvanced(object): def setupUi(self, InstallDialogAdvanced): InstallDialogAdvanced.setObjectName("InstallDialogAdvanced") InstallDialogAdvanced.resize(379, 208) + InstallDialogAdvanced.setWindowTitle("InstallDialogAdvanced") self.install_dialog_advanced_layout = QtWidgets.QFormLayout(InstallDialogAdvanced) self.install_dialog_advanced_layout.setObjectName("install_dialog_advanced_layout") self.max_workers_label = QtWidgets.QLabel(InstallDialogAdvanced) @@ -31,12 +32,12 @@ class Ui_InstallDialogAdvanced(object): self.max_workers_spin.setSizePolicy(sizePolicy) self.max_workers_spin.setObjectName("max_workers_spin") self.max_workers_layout.addWidget(self.max_workers_spin) - self.max_workers_info_label = QtWidgets.QLabel(InstallDialogAdvanced) + self.max_workers_info = QtWidgets.QLabel(InstallDialogAdvanced) font = QtGui.QFont() font.setItalic(True) - self.max_workers_info_label.setFont(font) - self.max_workers_info_label.setObjectName("max_workers_info_label") - self.max_workers_layout.addWidget(self.max_workers_info_label) + self.max_workers_info.setFont(font) + self.max_workers_info.setObjectName("max_workers_info") + self.max_workers_layout.addWidget(self.max_workers_info) self.install_dialog_advanced_layout.setLayout(0, QtWidgets.QFormLayout.FieldRole, self.max_workers_layout) self.max_memory_label = QtWidgets.QLabel(InstallDialogAdvanced) self.max_memory_label.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) @@ -56,16 +57,16 @@ class Ui_InstallDialogAdvanced(object): self.max_memory_spin.setProperty("value", 1024) self.max_memory_spin.setObjectName("max_memory_spin") self.max_memory_layout.addWidget(self.max_memory_spin) - self.max_memory_info_label = QtWidgets.QLabel(InstallDialogAdvanced) + self.max_memory_info = QtWidgets.QLabel(InstallDialogAdvanced) font = QtGui.QFont() font.setItalic(True) - self.max_memory_info_label.setFont(font) - self.max_memory_info_label.setObjectName("max_memory_info_label") - self.max_memory_layout.addWidget(self.max_memory_info_label) + self.max_memory_info.setFont(font) + self.max_memory_info.setObjectName("max_memory_info") + self.max_memory_layout.addWidget(self.max_memory_info) self.install_dialog_advanced_layout.setLayout(1, QtWidgets.QFormLayout.FieldRole, self.max_memory_layout) - self.install_prereqs_lbl = QtWidgets.QLabel(InstallDialogAdvanced) - self.install_prereqs_lbl.setObjectName("install_prereqs_lbl") - self.install_dialog_advanced_layout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.install_prereqs_lbl) + self.install_prereqs_label = QtWidgets.QLabel(InstallDialogAdvanced) + self.install_prereqs_label.setObjectName("install_prereqs_label") + self.install_dialog_advanced_layout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.install_prereqs_label) self.install_prereqs_check = QtWidgets.QCheckBox(InstallDialogAdvanced) font = QtGui.QFont() font.setItalic(True) @@ -113,13 +114,12 @@ class Ui_InstallDialogAdvanced(object): def retranslateUi(self, InstallDialogAdvanced): _translate = QtCore.QCoreApplication.translate - InstallDialogAdvanced.setWindowTitle(_translate("InstallDialogAdvanced", "Form")) self.max_workers_label.setText(_translate("InstallDialogAdvanced", "Max workers")) - self.max_workers_info_label.setText(_translate("InstallDialogAdvanced", "Less is slower. (0: Default)")) + self.max_workers_info.setText(_translate("InstallDialogAdvanced", "Less is slower. (0: Default)")) self.max_memory_label.setText(_translate("InstallDialogAdvanced", "Max shared memory")) self.max_memory_spin.setSuffix(_translate("InstallDialogAdvanced", "MiB")) - self.max_memory_info_label.setText(_translate("InstallDialogAdvanced", "Less is slower (0: Default)")) - self.install_prereqs_lbl.setText(_translate("InstallDialogAdvanced", "Install prerequisites")) + self.max_memory_info.setText(_translate("InstallDialogAdvanced", "Less is slower (0: Default)")) + self.install_prereqs_label.setText(_translate("InstallDialogAdvanced", "Install prerequisites")) self.dl_optimizations_label.setText(_translate("InstallDialogAdvanced", "Enable reordering")) self.force_download_label.setText(_translate("InstallDialogAdvanced", "Force redownload")) self.ignore_space_label.setText(_translate("InstallDialogAdvanced", "Ignore free space")) diff --git a/rare/ui/components/dialogs/install_dialog_advanced.ui b/rare/ui/components/dialogs/install_dialog_advanced.ui index 160c386f..6298e45b 100644 --- a/rare/ui/components/dialogs/install_dialog_advanced.ui +++ b/rare/ui/components/dialogs/install_dialog_advanced.ui @@ -11,7 +11,7 @@ - Form + InstallDialogAdvanced @@ -37,7 +37,7 @@ - + true @@ -88,7 +88,7 @@ - + true @@ -102,7 +102,7 @@ - + Install prerequisites diff --git a/rare/widgets/collapsible_widget.py b/rare/widgets/collapsible_widget.py index 32cc0343..be4b2302 100644 --- a/rare/widgets/collapsible_widget.py +++ b/rare/widgets/collapsible_widget.py @@ -1,85 +1,210 @@ from PyQt5.QtCore import QParallelAnimationGroup, Qt, QPropertyAnimation, QAbstractAnimation -from PyQt5.QtWidgets import QWidget, QFrame, QToolButton, QGridLayout, QSizePolicy, QLayout +from PyQt5.QtWidgets import QApplication, QWidget, QFrame, QToolButton, QGridLayout, QSizePolicy, QGroupBox, QSpacerItem, QLabel from rare.utils.misc import icon # https://newbedev.com/how-to-make-an-expandable-collapsable-section-widget-in-qt -class CollapsibleWidget(QWidget): +class CollapsibleFrame(QFrame): def __init__( - self, child_layout: QLayout = None, title: str = "", animation_duration: int = 200, parent=None + self, widget: QWidget = None, title: str = "", button_text: str = "", animation_duration: int = 200, parent=None ): """ References: # Adapted from c++ version https://stackoverflow.com/questions/32476006/how-to-make-an-expandable-collapsable-section-widget-in-qt """ - super(CollapsibleWidget, self).__init__(parent=parent) + super(CollapsibleFrame, self).__init__(parent=parent) + self.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken) - self.animationDuration = animation_duration - self.toggleAnimation = QParallelAnimationGroup() - self.contentArea = QWidget() - self.headerLine = QFrame() - self.toggleButton = QToolButton() - self.mainLayout = QGridLayout() + self.content_area = None + self.animation_duration = animation_duration - toggleButton = self.toggleButton - toggleButton.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) - toggleButton.setIcon(icon("fa.arrow-right")) - toggleButton.setText(str(title)) - toggleButton.setCheckable(True) - toggleButton.setChecked(False) + self.toggle_button = QToolButton(self) + self.toggle_button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) + self.toggle_button.setIcon(icon("fa.arrow-right")) + self.toggle_button.setText(button_text) + self.toggle_button.setCheckable(True) + self.toggle_button.setChecked(False) - headerLine = self.headerLine - headerLine.setFrameShape(QFrame.StyledPanel) - headerLine.setFrameShadow(QFrame.Plain) - headerLine.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum) + self.spacer_label = QLabel(title) + font = self.spacer_label.font() + font.setBold(True) + self.spacer_label.setFont(font) + self.spacer_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) - self.contentArea.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) - # start out collapsed - self.contentArea.setMaximumHeight(0) - self.contentArea.setMinimumHeight(0) # let the entire widget grow and shrink with its content - toggleAnimation = self.toggleAnimation - toggleAnimation.addAnimation(QPropertyAnimation(self, b"minimumHeight")) - toggleAnimation.addAnimation(QPropertyAnimation(self, b"maximumHeight")) - toggleAnimation.addAnimation(QPropertyAnimation(self.contentArea, b"maximumHeight")) + self.toggle_animation = QParallelAnimationGroup(self) + self.toggle_animation.addAnimation(QPropertyAnimation(self, b"minimumHeight")) + self.toggle_animation.addAnimation(QPropertyAnimation(self, b"maximumHeight")) + # don't waste space - mainLayout = self.mainLayout - mainLayout.setVerticalSpacing(0) - mainLayout.setContentsMargins(0, 0, 0, 0) - row = 0 - mainLayout.addWidget(self.toggleButton, row, 0, 1, 1, Qt.AlignLeft) - mainLayout.addWidget(self.headerLine, row, 2, 1, 1) - row += 1 - mainLayout.addWidget(self.contentArea, row, 0, 1, 3) - self.setLayout(self.mainLayout) + self.main_layout = QGridLayout(self) + self.main_layout.setVerticalSpacing(0) + self.main_layout.setContentsMargins(0, 0, 0, 0) + self.main_layout.addWidget(self.toggle_button, 0, 0, 1, 1, Qt.AlignLeft) + self.main_layout.addWidget(self.spacer_label, 0, 1, 1, 1) + self.main_layout.setColumnStretch(1, 1) + self.main_layout.setRowStretch(0, 0) + self.main_layout.setRowStretch(1, 1) + self.setLayout(self.main_layout) - def start_animation(checked): - arrow_type = icon("fa.arrow-down") if checked else icon("fa.arrow-right") - direction = QAbstractAnimation.Forward if checked else QAbstractAnimation.Backward - toggleButton.setIcon(arrow_type) - self.toggleAnimation.setDirection(direction) - self.toggleAnimation.start() + self.toggle_button.clicked.connect(self.animationStart) - self.toggleButton.clicked.connect(start_animation) + if widget is not None: + self.setWidget(widget) - if child_layout: - self.setContentLayout(child_layout) + def animationStart(self, checked): + arrow_type = icon("fa.arrow-down") if checked else icon("fa.arrow-right") + direction = QAbstractAnimation.Forward if checked else QAbstractAnimation.Backward + self.toggle_button.setIcon(arrow_type) + self.toggle_animation.setDirection(direction) + self.toggle_animation.start() + + def setWidget(self, widget: QWidget): + if widget is None or widget is self.content_area: + return + if self.content_area is not None: + # Collapse the parent before replacing the child + if self.toggle_button.isChecked(): + self.toggle_button.click() + self.toggle_animation.removeAnimation(self.content_toggle_animation) + self.content_area.setParent(None) + self.content_area.deleteLater() + + self.content_area = widget + self.content_area.setParent(self) + self.content_area.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + self.adjustSize() + + # start out collapsed + if not self.toggle_button.isChecked(): + self.content_area.setMaximumHeight(0) + self.content_area.setMinimumHeight(0) + + self.content_toggle_animation = QPropertyAnimation(self.content_area, b"maximumHeight") + self.toggle_animation.addAnimation(self.content_toggle_animation) + self.main_layout.addWidget(self.content_area, 1, 0, 1, 2) + collapsed_height = self.sizeHint().height() - self.content_area.maximumHeight() + content_height = self.content_area.sizeHint().height() + for i in range(self.toggle_animation.animationCount() - 1): + spoiler_animation = self.toggle_animation.animationAt(i) + spoiler_animation.setDuration(self.animation_duration) + spoiler_animation.setStartValue(collapsed_height) + spoiler_animation.setEndValue(collapsed_height + content_height) + content_animation = self.toggle_animation.animationAt(self.toggle_animation.animationCount() - 1) + content_animation.setDuration(self.animation_duration) + content_animation.setStartValue(0) + content_animation.setEndValue(content_height) + + +class CollapsibleGroupBox(QGroupBox): + def __init__( + self, widget: QWidget = None, title: str = "", animation_duration: int = 200, parent=None + ): + """ + References: + # Adapted from c++ version + https://stackoverflow.com/questions/32476006/how-to-make-an-expandable-collapsable-section-widget-in-qt + """ + super(CollapsibleGroupBox, self).__init__(parent=parent) + self.setTitle(title) + self.setCheckable(True) + + self.content_area = None + self.animation_duration = animation_duration + + # let the entire widget grow and shrink with its content + self.toggle_animation = QParallelAnimationGroup(self) + self.toggle_animation.addAnimation(QPropertyAnimation(self, b"minimumHeight")) + self.toggle_animation.addAnimation(QPropertyAnimation(self, b"maximumHeight")) + # don't waste space + self.main_layout = QVBoxLayout(self) + self.main_layout.setSpacing(0) + self.main_layout.setContentsMargins(0, 0, 0, -1) + self.setLayout(self.main_layout) + + self.clicked.connect(self.animationStart) + + if widget is not None: + self.setWidget(widget) + + def animationStart(self, checked): + direction = QAbstractAnimation.Forward if checked else QAbstractAnimation.Backward + self.toggle_animation.setDirection(direction) + self.toggle_animation.start() + + def setWidget(self, widget: QWidget): + if widget is None or widget is self.content_area: + return + if self.content_area is not None: + self.content_area.deleteLater() + self.content_area = widget + self.content_area.setParent(self) + self.content_area.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + # start out collapsed + self.setChecked(False) + self.content_area.setMaximumHeight(0) + self.content_area.setMinimumHeight(0) + self.toggle_animation.addAnimation(QPropertyAnimation(self.content_area, b"maximumHeight")) + self.main_layout.addWidget(self.content_area) + collapsed_height = self.sizeHint().height() - self.content_area.maximumHeight() + content_height = self.content_area.sizeHint().height() + for i in range(self.toggle_animation.animationCount() - 1): + spoiler_animation = self.toggle_animation.animationAt(i) + spoiler_animation.setDuration(self.animation_duration) + spoiler_animation.setStartValue(collapsed_height) + spoiler_animation.setEndValue(collapsed_height + content_height) + content_animation = self.toggle_animation.animationAt(self.toggle_animation.animationCount() - 1) + content_animation.setDuration(self.animation_duration) + content_animation.setStartValue(0) + content_animation.setEndValue(content_height) + + +if __name__ == "__main__": + import sys + from PyQt5.QtWidgets import QApplication, QDialog, QVBoxLayout, QPushButton + from rare.ui.components.dialogs.install_dialog_advanced import Ui_InstallDialogAdvanced + import rare.resources.stylesheets.RareStyle + from rare.utils.misc import set_color_pallete, set_style_sheet + app = QApplication(sys.argv) + + set_style_sheet("RareStyle") + + ui_frame = Ui_InstallDialogAdvanced() + widget_frame = QWidget() + ui_frame.setupUi(widget_frame) + collapsible_frame = CollapsibleFrame(widget_frame, title="Frame me!") + collapsible_frame.setDisabled(False) + + def replace_func(state): + widget2_frame = QWidget() + ui2_frame = Ui_InstallDialogAdvanced() + ui2_frame.setupUi(widget2_frame) + if state: + ui2_frame.install_dialog_advanced_layout.removeRow(3) + ui2_frame.install_dialog_advanced_layout.removeRow(4) + collapsible_frame.setWidget(widget2_frame) + + replace_button = QToolButton() + replace_button.setText("Replace me!") + replace_button.setCheckable(True) + replace_button.setChecked(False) + replace_button.clicked.connect(replace_func) + + ui_group = Ui_InstallDialogAdvanced() + widget_group = QWidget() + ui_group.setupUi(widget_group) + collapsible_group = CollapsibleGroupBox(widget_group, title="Group me!") + collapsible_group.setDisabled(False) + + dialog = QDialog() + dialog.setLayout(QVBoxLayout()) + dialog.layout().addWidget(replace_button) + dialog.layout().addWidget(collapsible_frame) + dialog.layout().addWidget(collapsible_group) + dialog.layout().setSizeConstraint(QVBoxLayout.SetFixedSize) + dialog.show() + sys.exit(app.exec_()) - def setContentLayout(self, content_layout: QLayout): - # Not sure if this is equivalent to self.contentArea.destroy() - self.contentArea.destroy() - self.contentArea.setLayout(content_layout) - collapsedHeight = self.sizeHint().height() - self.contentArea.maximumHeight() - contentHeight = content_layout.sizeHint().height() - for i in range(self.toggleAnimation.animationCount() - 1): - spoilerAnimation = self.toggleAnimation.animationAt(i) - spoilerAnimation.setDuration(self.animationDuration) - spoilerAnimation.setStartValue(collapsedHeight) - spoilerAnimation.setEndValue(collapsedHeight + contentHeight) - contentAnimation = self.toggleAnimation.animationAt(self.toggleAnimation.animationCount() - 1) - contentAnimation.setDuration(self.animationDuration) - contentAnimation.setStartValue(0) - contentAnimation.setEndValue(contentHeight) From 891804ae377205ec6d56d95464ee3b4671cac8de Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Mon, 31 Oct 2022 16:57:35 +0200 Subject: [PATCH 09/14] AccountWidget: Remove dead signals after the offline mode fix Signals, if they carry the same datatype, can be chained simply with `signal.connect(othersignal)` without the need to use a `lambda` expression and `emit()` TabWidget: Fix error because the `exit_app` signal was called directly --- rare/components/tabs/__init__.py | 10 ++++------ rare/components/tabs/account/__init__.py | 8 ++------ 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/rare/components/tabs/__init__.py b/rare/components/tabs/__init__.py index b6710a9e..71a24cb5 100644 --- a/rare/components/tabs/__init__.py +++ b/rare/components/tabs/__init__.py @@ -1,4 +1,4 @@ -from PyQt5.QtCore import QSize, pyqtSignal +from PyQt5.QtCore import QSize, pyqtSignal, pyqtSlot from PyQt5.QtWidgets import QMenu, QTabWidget, QWidget, QWidgetAction, QShortcut, QMessageBox from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton @@ -23,9 +23,7 @@ class TabWidget(QTabWidget): self.args = ArgumentsSingleton() disabled_tab = 3 if not self.args.offline else 1 self.setTabBar(MainTabBar(disabled_tab)) - # lk: Figure out why this adds a white line at the top - # lk: despite setting qproperty-drawBase to 0 in the stylesheet - # self.setDocumentMode(True) + # Generate Tabs self.games_tab = GamesTab() self.addTab(self.games_tab, self.tr("Games")) @@ -58,7 +56,6 @@ class TabWidget(QTabWidget): self.setTabEnabled(disabled_tab + 1, False) self.account_widget = AccountWidget(self) - self.account_widget.exit_app.connect(self.exit_app) self.account_widget.logout.connect(self.logout) account_action = QWidgetAction(self) account_action.setDefaultWidget(self.account_widget) @@ -115,6 +112,7 @@ class TabWidget(QTabWidget): self.tabBar().setMinimumWidth(self.width()) super(TabWidget, self).resizeEvent(event) + @pyqtSlot() def logout(self): # FIXME: Don't allow logging out if there are active downloads if self.downloads_tab.is_download_active: @@ -135,4 +133,4 @@ class TabWidget(QTabWidget): if reply == QMessageBox.Yes: self.core.lgd.invalidate_userdata() - self.exit_app(-133742) # restart exit code + self.exit_app.emit(-133742) # restart exit code diff --git a/rare/components/tabs/account/__init__.py b/rare/components/tabs/account/__init__.py index a5b6e1e5..5aa48f1d 100644 --- a/rare/components/tabs/account/__init__.py +++ b/rare/components/tabs/account/__init__.py @@ -8,16 +8,12 @@ from rare.utils.misc import icon class AccountWidget(QWidget): - # int: exit code - exit_app: pyqtSignal = pyqtSignal(int) - logout = pyqtSignal() + logout: pyqtSignal = pyqtSignal() def __init__(self, parent): super(AccountWidget, self).__init__(parent=parent) self.core = LegendaryCoreSingleton() self.signals = GlobalSignalsSingleton() - # FIXME: This is why widgets should be decoupled from procedures. - # FIXME: pass downloads tab as argument to check if there are active downloads username = self.core.lgd.userdata.get("display_name") if not username: @@ -30,7 +26,7 @@ class AccountWidget(QWidget): ) ) self.logout_button = QPushButton(self.tr("Logout")) - self.logout_button.clicked.connect(lambda: self.logout.emit()) + self.logout_button.clicked.connect(self.logout) layout = QVBoxLayout(self) layout.addWidget(QLabel(self.tr("Account"))) From da79519e80c80d8397789a6ba551841af0b28ec9 Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Thu, 3 Nov 2022 14:53:58 +0200 Subject: [PATCH 10/14] GameListHeadBar: Combine the "Import" and "EGL Sync" buttons into a menu The "EOS and Ubisoft" tab is currently empy --- rare/components/tabs/__init__.py | 3 +- rare/components/tabs/games/__init__.py | 14 +++++-- rare/components/tabs/games/head_bar.py | 37 +++++++++++++------ .../tabs/games/import_sync/__init__.py | 12 +++++- 4 files changed, 48 insertions(+), 18 deletions(-) diff --git a/rare/components/tabs/__init__.py b/rare/components/tabs/__init__.py index 71a24cb5..03c245a9 100644 --- a/rare/components/tabs/__init__.py +++ b/rare/components/tabs/__init__.py @@ -51,8 +51,7 @@ class TabWidget(QTabWidget): self.addTab(QWidget(), "") self.setTabEnabled(disabled_tab, False) # Button - self.account = QWidget() - self.addTab(self.account, "") + self.addTab(QWidget(), "") self.setTabEnabled(disabled_tab + 1, False) self.account_widget = AccountWidget(self) diff --git a/rare/components/tabs/games/__init__.py b/rare/components/tabs/games/__init__.py index 835c1289..3be4ee0a 100644 --- a/rare/components/tabs/games/__init__.py +++ b/rare/components/tabs/games/__init__.py @@ -60,8 +60,9 @@ class GamesTab(QStackedWidget): self.addWidget(self.games) self.head_bar = GameListHeadBar(parent=self.games) - self.head_bar.import_clicked.connect(self.show_import) - self.head_bar.egl_sync_clicked.connect(self.show_egl_sync) + self.head_bar.goto_import.connect(self.show_import) + self.head_bar.goto_egl_sync.connect(self.show_egl_sync) + self.head_bar.goto_eos_ubisoft.connect(self.show_eos_ubisoft) self.games.layout().addWidget(self.head_bar) self.game_info_tabs = GameInfoTabs(self.dlcs, self.game_utils, self) @@ -193,14 +194,21 @@ class GamesTab(QStackedWidget): i_widget.leaveEvent(None) l_widget.update_text() + @pyqtSlot() def show_import(self): self.setCurrentWidget(self.import_sync_tabs) self.import_sync_tabs.show_import() - def show_egl_sync(self, idx): + @pyqtSlot() + def show_egl_sync(self): self.setCurrentWidget(self.import_sync_tabs) self.import_sync_tabs.show_egl_sync() + @pyqtSlot() + def show_eos_ubisoft(self): + self.setCurrentWidget(self.import_sync_tabs) + self.import_sync_tabs.show_eos_ubisoft() + def show_game_info(self, app_name): self.game_info_tabs.update_game(app_name) self.setCurrentWidget(self.game_info_tabs) diff --git a/rare/components/tabs/games/head_bar.py b/rare/components/tabs/games/head_bar.py index e22ca957..a33b6f2d 100644 --- a/rare/components/tabs/games/head_bar.py +++ b/rare/components/tabs/games/head_bar.py @@ -4,7 +4,7 @@ from PyQt5.QtWidgets import ( QPushButton, QWidget, QHBoxLayout, - QComboBox, + QComboBox, QToolButton, QMenu, QAction, ) from qtawesome import IconWidget @@ -14,7 +14,10 @@ from rare.utils.misc import icon class GameListHeadBar(QWidget): - filterChanged = pyqtSignal(str) + filterChanged: pyqtSignal = pyqtSignal(str) + goto_import: pyqtSignal = pyqtSignal() + goto_egl_sync: pyqtSignal = pyqtSignal() + goto_eos_ubisoft: pyqtSignal = pyqtSignal() def __init__(self, parent=None): super(GameListHeadBar, self).__init__(parent=parent) @@ -58,13 +61,24 @@ class GameListHeadBar(QWidget): self.filter.currentIndexChanged.connect(self.filter_changed) - self.import_game = QPushButton(icon("mdi.import", "fa.arrow-down"), self.tr("Import Game")) - self.import_clicked = self.import_game.clicked + integrations_menu = QMenu(self) + import_action = QAction(icon("mdi.import", "fa.arrow-down"), self.tr("Import Game"), integrations_menu) - self.egl_sync = QPushButton(icon("mdi.sync", "fa.refresh"), self.tr("Sync with EGL")) - self.egl_sync_clicked = self.egl_sync.clicked - # FIXME: Until it is ready - # self.egl_sync.setEnabled(False) + import_action.triggered.connect(self.goto_import) + egl_sync_action = QAction(icon("mdi.sync", "fa.refresh"), self.tr("Sync with EGL"), integrations_menu) + egl_sync_action.triggered.connect(self.goto_egl_sync) + + eos_ubisoft_action = QAction(icon("mdi.rocket", "fa.rocket"), self.tr("EOS and Ubisoft"), integrations_menu) + eos_ubisoft_action.triggered.connect(self.goto_eos_ubisoft) + + integrations_menu.addAction(import_action) + integrations_menu.addAction(egl_sync_action) + integrations_menu.addAction(eos_ubisoft_action) + + integrations = QToolButton(self) + integrations.setText(self.tr("Integrations")) + integrations.setMenu(integrations_menu) + integrations.setPopupMode(QToolButton.InstantPopup) self.search_bar = ButtonLineEdit("fa.search", placeholder_text=self.tr("Search Game")) self.search_bar.setObjectName("search_bar") @@ -97,10 +111,9 @@ class GameListHeadBar(QWidget): layout = QHBoxLayout() layout.setContentsMargins(0, 5, 0, 5) layout.addWidget(self.filter) - layout.addStretch(1) - layout.addWidget(self.import_game) - layout.addWidget(self.egl_sync) - layout.addStretch(2) + layout.addStretch(0) + layout.addWidget(integrations) + layout.addStretch(5) layout.addWidget(self.search_bar) layout.addStretch(2) layout.addWidget(self.installed_icon) diff --git a/rare/components/tabs/games/import_sync/__init__.py b/rare/components/tabs/games/import_sync/__init__.py index cba2a520..16274705 100644 --- a/rare/components/tabs/games/import_sync/__init__.py +++ b/rare/components/tabs/games/import_sync/__init__.py @@ -22,6 +22,13 @@ class ImportSyncTabs(SideTabWidget): ) self.addTab(self.egl_sync_widget, self.tr("Sync with EGL")) + self.egl_eos_ubisoft = ImportSyncWidget( + QWidget(self), + self.tr("To import EGL games from directories, please use Import Game."), + self, + ) + self.addTab(self.egl_eos_ubisoft, self.tr("EOS and Ubisoft")) + self.tabBar().setCurrentIndex(1) def show_import(self): @@ -30,11 +37,14 @@ class ImportSyncTabs(SideTabWidget): def show_egl_sync(self): self.setCurrentIndex(2) + def show_eos_ubisoft(self): + self.setCurrentIndex(3) + class ImportSyncWidget(QWidget): def __init__(self, widget: QWidget, info: str, parent=None): super(ImportSyncWidget, self).__init__(parent=parent) - self.info = QLabel(f"

{info}

") + self.info = QLabel(f"{info}") layout = QVBoxLayout() layout.addWidget(widget) From 692ffa99bc42d8e23ff21331cb842ba0d079668c Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Thu, 3 Nov 2022 21:23:48 +0200 Subject: [PATCH 11/14] CollapsibleWidget: Resize the widget when contents change Currently this is achieved by toggling the checked state twice in a programmatic way. This ensures correct animations until a better solution is found. In addition, now both CollapsibleFrame and CollapsibleGroupBox inherit their common methods from the abstract class CollapsibleBase. --- rare/widgets/collapsible_widget.py | 256 ++++++++++++++++------------- 1 file changed, 142 insertions(+), 114 deletions(-) diff --git a/rare/widgets/collapsible_widget.py b/rare/widgets/collapsible_widget.py index be4b2302..dd0c7cae 100644 --- a/rare/widgets/collapsible_widget.py +++ b/rare/widgets/collapsible_widget.py @@ -1,26 +1,104 @@ -from PyQt5.QtCore import QParallelAnimationGroup, Qt, QPropertyAnimation, QAbstractAnimation -from PyQt5.QtWidgets import QApplication, QWidget, QFrame, QToolButton, QGridLayout, QSizePolicy, QGroupBox, QSpacerItem, QLabel +from abc import abstractmethod +from typing import Optional + +from PyQt5.QtCore import QParallelAnimationGroup, Qt, QPropertyAnimation, QAbstractAnimation, QSize +from PyQt5.QtWidgets import QWidget, QFrame, QToolButton, QGridLayout, QSizePolicy, QGroupBox, QLabel from rare.utils.misc import icon -# https://newbedev.com/how-to-make-an-expandable-collapsable-section-widget-in-qt + +class CollapsibleBase(object): + """ + References: + # Adapted from c++ version + https://stackoverflow.com/questions/32476006/how-to-make-an-expandable-collapsable-section-widget-in-qt + # Adapted from python version + https://newbedev.com/how-to-make-an-expandable-collapsable-section-widget-in-qt + """ + def __init__(self): + self.animation_duration = None + self.toggle_animation = None + self.content_area = None + self.content_toggle_animation = None + + def setup(self, animation_duration: int = 200): + self.animation_duration = animation_duration + self.content_area: Optional[QWidget] = None + self.content_toggle_animation: Optional[QPropertyAnimation] = None + + # let the entire widget grow and shrink with its content + self.toggle_animation = QParallelAnimationGroup(self) + self.toggle_animation.addAnimation(QPropertyAnimation(self, b"minimumHeight")) + self.toggle_animation.addAnimation(QPropertyAnimation(self, b"maximumHeight")) + + @abstractmethod + def isChecked(self) -> bool: + ... + + @abstractmethod + def click(self) -> None: + ... + + @abstractmethod + def addToLayout(self, widget: QWidget) -> None: + ... + + @abstractmethod + def sizeHint(self) -> QSize: + ... + + def animationStart(self, checked): + direction = QAbstractAnimation.Forward if checked else QAbstractAnimation.Backward + self.toggle_animation.setDirection(direction) + self.toggle_animation.start() + + def setWidget(self, widget: QWidget): + if widget is None or widget is self.content_area: + return + is_checked = self.isChecked() + if self.content_area is not None: + # Collapse the parent before replacing the child + if is_checked: + self.click() + self.toggle_animation.removeAnimation(self.content_toggle_animation) + self.content_area.setParent(None) + self.content_area.deleteLater() + + self.content_area = widget + self.content_area.setParent(self) + self.content_area.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + + # start out collapsed + if not is_checked: + self.content_area.setMaximumHeight(0) + self.content_area.setMinimumHeight(0) + + self.content_toggle_animation = QPropertyAnimation(self.content_area, b"maximumHeight") + self.toggle_animation.addAnimation(self.content_toggle_animation) + self.addToLayout(self.content_area) + collapsed_height = self.sizeHint().height() + content_height = self.content_area.sizeHint().height() + for i in range(self.toggle_animation.animationCount() - 1): + spoiler_animation = self.toggle_animation.animationAt(i) + spoiler_animation.setDuration(self.animation_duration) + spoiler_animation.setStartValue(collapsed_height) + spoiler_animation.setEndValue(collapsed_height + content_height) + content_animation = self.toggle_animation.animationAt(self.toggle_animation.animationCount() - 1) + content_animation.setDuration(self.animation_duration) + content_animation.setStartValue(0) + content_animation.setEndValue(content_height) + if is_checked: + self.click() -class CollapsibleFrame(QFrame): +class CollapsibleFrame(QFrame, CollapsibleBase): def __init__( self, widget: QWidget = None, title: str = "", button_text: str = "", animation_duration: int = 200, parent=None ): - """ - References: - # Adapted from c++ version - https://stackoverflow.com/questions/32476006/how-to-make-an-expandable-collapsable-section-widget-in-qt - """ super(CollapsibleFrame, self).__init__(parent=parent) + self.setup(animation_duration) self.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken) - self.content_area = None - self.animation_duration = animation_duration - self.toggle_button = QToolButton(self) self.toggle_button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.toggle_button.setIcon(icon("fa.arrow-right")) @@ -28,23 +106,18 @@ class CollapsibleFrame(QFrame): self.toggle_button.setCheckable(True) self.toggle_button.setChecked(False) - self.spacer_label = QLabel(title) - font = self.spacer_label.font() + self.title_label = QLabel(title) + font = self.title_label.font() font.setBold(True) - self.spacer_label.setFont(font) - self.spacer_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) - - # let the entire widget grow and shrink with its content - self.toggle_animation = QParallelAnimationGroup(self) - self.toggle_animation.addAnimation(QPropertyAnimation(self, b"minimumHeight")) - self.toggle_animation.addAnimation(QPropertyAnimation(self, b"maximumHeight")) + self.title_label.setFont(font) + self.title_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) # don't waste space self.main_layout = QGridLayout(self) self.main_layout.setVerticalSpacing(0) self.main_layout.setContentsMargins(0, 0, 0, 0) self.main_layout.addWidget(self.toggle_button, 0, 0, 1, 1, Qt.AlignLeft) - self.main_layout.addWidget(self.spacer_label, 0, 1, 1, 1) + self.main_layout.addWidget(self.title_label, 0, 1, 1, 1) self.main_layout.setColumnStretch(1, 1) self.main_layout.setRowStretch(0, 0) self.main_layout.setRowStretch(1, 1) @@ -55,119 +128,64 @@ class CollapsibleFrame(QFrame): if widget is not None: self.setWidget(widget) + def isChecked(self) -> bool: + return self.toggle_button.isChecked() + + def click(self) -> None: + self.toggle_button.click() + + def addToLayout(self, widget: QWidget) -> None: + self.main_layout.addWidget(widget, 1, 0, 1, 2) + + def sizeHint(self) -> QSize: + return super(CollapsibleFrame, self).sizeHint() + def animationStart(self, checked): arrow_type = icon("fa.arrow-down") if checked else icon("fa.arrow-right") - direction = QAbstractAnimation.Forward if checked else QAbstractAnimation.Backward self.toggle_button.setIcon(arrow_type) - self.toggle_animation.setDirection(direction) - self.toggle_animation.start() - - def setWidget(self, widget: QWidget): - if widget is None or widget is self.content_area: - return - if self.content_area is not None: - # Collapse the parent before replacing the child - if self.toggle_button.isChecked(): - self.toggle_button.click() - self.toggle_animation.removeAnimation(self.content_toggle_animation) - self.content_area.setParent(None) - self.content_area.deleteLater() - - self.content_area = widget - self.content_area.setParent(self) - self.content_area.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) - self.adjustSize() - - # start out collapsed - if not self.toggle_button.isChecked(): - self.content_area.setMaximumHeight(0) - self.content_area.setMinimumHeight(0) - - self.content_toggle_animation = QPropertyAnimation(self.content_area, b"maximumHeight") - self.toggle_animation.addAnimation(self.content_toggle_animation) - self.main_layout.addWidget(self.content_area, 1, 0, 1, 2) - collapsed_height = self.sizeHint().height() - self.content_area.maximumHeight() - content_height = self.content_area.sizeHint().height() - for i in range(self.toggle_animation.animationCount() - 1): - spoiler_animation = self.toggle_animation.animationAt(i) - spoiler_animation.setDuration(self.animation_duration) - spoiler_animation.setStartValue(collapsed_height) - spoiler_animation.setEndValue(collapsed_height + content_height) - content_animation = self.toggle_animation.animationAt(self.toggle_animation.animationCount() - 1) - content_animation.setDuration(self.animation_duration) - content_animation.setStartValue(0) - content_animation.setEndValue(content_height) + super(CollapsibleFrame, self).animationStart(checked) -class CollapsibleGroupBox(QGroupBox): +class CollapsibleGroupBox(QGroupBox, CollapsibleBase): def __init__( self, widget: QWidget = None, title: str = "", animation_duration: int = 200, parent=None ): - """ - References: - # Adapted from c++ version - https://stackoverflow.com/questions/32476006/how-to-make-an-expandable-collapsable-section-widget-in-qt - """ super(CollapsibleGroupBox, self).__init__(parent=parent) + self.setup(animation_duration) self.setTitle(title) self.setCheckable(True) + self.setChecked(False) - self.content_area = None - self.animation_duration = animation_duration - - # let the entire widget grow and shrink with its content - self.toggle_animation = QParallelAnimationGroup(self) - self.toggle_animation.addAnimation(QPropertyAnimation(self, b"minimumHeight")) - self.toggle_animation.addAnimation(QPropertyAnimation(self, b"maximumHeight")) # don't waste space self.main_layout = QVBoxLayout(self) self.main_layout.setSpacing(0) self.main_layout.setContentsMargins(0, 0, 0, -1) self.setLayout(self.main_layout) - self.clicked.connect(self.animationStart) + self.toggled.connect(self.animationStart) if widget is not None: self.setWidget(widget) - def animationStart(self, checked): - direction = QAbstractAnimation.Forward if checked else QAbstractAnimation.Backward - self.toggle_animation.setDirection(direction) - self.toggle_animation.start() + def isChecked(self) -> bool: + return super(CollapsibleGroupBox, self).isChecked() - def setWidget(self, widget: QWidget): - if widget is None or widget is self.content_area: - return - if self.content_area is not None: - self.content_area.deleteLater() - self.content_area = widget - self.content_area.setParent(self) - self.content_area.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) - # start out collapsed - self.setChecked(False) - self.content_area.setMaximumHeight(0) - self.content_area.setMinimumHeight(0) - self.toggle_animation.addAnimation(QPropertyAnimation(self.content_area, b"maximumHeight")) - self.main_layout.addWidget(self.content_area) - collapsed_height = self.sizeHint().height() - self.content_area.maximumHeight() - content_height = self.content_area.sizeHint().height() - for i in range(self.toggle_animation.animationCount() - 1): - spoiler_animation = self.toggle_animation.animationAt(i) - spoiler_animation.setDuration(self.animation_duration) - spoiler_animation.setStartValue(collapsed_height) - spoiler_animation.setEndValue(collapsed_height + content_height) - content_animation = self.toggle_animation.animationAt(self.toggle_animation.animationCount() - 1) - content_animation.setDuration(self.animation_duration) - content_animation.setStartValue(0) - content_animation.setEndValue(content_height) + def click(self) -> None: + self.setChecked(not self.isChecked()) + + def addToLayout(self, widget: QWidget) -> None: + self.main_layout.addWidget(widget) + + def sizeHint(self) -> QSize: + return super(CollapsibleGroupBox, self).sizeHint() if __name__ == "__main__": import sys - from PyQt5.QtWidgets import QApplication, QDialog, QVBoxLayout, QPushButton + from PyQt5.QtWidgets import QApplication, QDialog, QVBoxLayout from rare.ui.components.dialogs.install_dialog_advanced import Ui_InstallDialogAdvanced - import rare.resources.stylesheets.RareStyle - from rare.utils.misc import set_color_pallete, set_style_sheet + from rare.utils.misc import set_style_sheet + from rare.resources.stylesheets import RareStyle app = QApplication(sys.argv) set_style_sheet("RareStyle") @@ -178,7 +196,7 @@ if __name__ == "__main__": collapsible_frame = CollapsibleFrame(widget_frame, title="Frame me!") collapsible_frame.setDisabled(False) - def replace_func(state): + def replace_func_frame(state): widget2_frame = QWidget() ui2_frame = Ui_InstallDialogAdvanced() ui2_frame.setupUi(widget2_frame) @@ -187,18 +205,28 @@ if __name__ == "__main__": ui2_frame.install_dialog_advanced_layout.removeRow(4) collapsible_frame.setWidget(widget2_frame) - replace_button = QToolButton() - replace_button.setText("Replace me!") - replace_button.setCheckable(True) - replace_button.setChecked(False) - replace_button.clicked.connect(replace_func) - ui_group = Ui_InstallDialogAdvanced() widget_group = QWidget() ui_group.setupUi(widget_group) collapsible_group = CollapsibleGroupBox(widget_group, title="Group me!") collapsible_group.setDisabled(False) + def replace_func_group(state): + widget2_group = QWidget() + ui2_group = Ui_InstallDialogAdvanced() + ui2_group.setupUi(widget2_group) + if state: + ui2_group.install_dialog_advanced_layout.removeRow(3) + ui2_group.install_dialog_advanced_layout.removeRow(4) + collapsible_group.setWidget(widget2_group) + + replace_button = QToolButton() + replace_button.setText("Replace me!") + replace_button.setCheckable(True) + replace_button.setChecked(False) + replace_button.clicked.connect(replace_func_frame) + replace_button.clicked.connect(replace_func_group) + dialog = QDialog() dialog.setLayout(QVBoxLayout()) dialog.layout().addWidget(replace_button) From 61749f9acd49cedb05ecdeb80c19eeaeab4bdf79 Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Thu, 3 Nov 2022 22:34:50 +0200 Subject: [PATCH 12/14] EOSWidget/UbiActivationHelper: Move them from Settings to ImportSync --- .../tabs/games/import_sync/__init__.py | 19 +- .../eos.py => games/import_sync/eos_group.py} | 45 ++- .../import_sync/ubisoft_group.py} | 26 +- rare/components/tabs/settings/legendary.py | 6 - .../tabs/games/import_sync/eos_widget.py | 152 ++++++++++ .../tabs/games/import_sync/eos_widget.ui | 259 +++++++++++++++++ rare/ui/components/tabs/settings/legendary.py | 9 +- rare/ui/components/tabs/settings/legendary.ui | 11 - .../tabs/settings/widgets/eos_widget.py | 170 ------------ .../tabs/settings/widgets/eos_widget.ui | 262 ------------------ 10 files changed, 462 insertions(+), 497 deletions(-) rename rare/components/tabs/{settings/widgets/eos.py => games/import_sync/eos_group.py} (89%) rename rare/components/tabs/{settings/widgets/ubisoft_activation.py => games/import_sync/ubisoft_group.py} (92%) create mode 100644 rare/ui/components/tabs/games/import_sync/eos_widget.py create mode 100644 rare/ui/components/tabs/games/import_sync/eos_widget.ui delete mode 100644 rare/ui/components/tabs/settings/widgets/eos_widget.py delete mode 100644 rare/ui/components/tabs/settings/widgets/eos_widget.ui diff --git a/rare/components/tabs/games/import_sync/__init__.py b/rare/components/tabs/games/import_sync/__init__.py index 16274705..de4bf610 100644 --- a/rare/components/tabs/games/import_sync/__init__.py +++ b/rare/components/tabs/games/import_sync/__init__.py @@ -1,8 +1,13 @@ +from typing import Optional + +from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QVBoxLayout, QWidget, QLabel, QSpacerItem, QSizePolicy from rare.utils.extra_widgets import SideTabWidget from .egl_sync_group import EGLSyncGroup from .import_group import ImportGroup +from .eos_group import EOSGroup +from .ubisoft_group import UbisoftGroup class ImportSyncTabs(SideTabWidget): @@ -23,10 +28,12 @@ class ImportSyncTabs(SideTabWidget): self.addTab(self.egl_sync_widget, self.tr("Sync with EGL")) self.egl_eos_ubisoft = ImportSyncWidget( - QWidget(self), - self.tr("To import EGL games from directories, please use Import Game."), + None, + self.tr(""), self, ) + self.egl_eos_ubisoft.addWidget(UbisoftGroup(self.egl_eos_ubisoft)) + self.egl_eos_ubisoft.addWidget(EOSGroup(self.egl_eos_ubisoft)) self.addTab(self.egl_eos_ubisoft, self.tr("EOS and Ubisoft")) self.tabBar().setCurrentIndex(1) @@ -42,14 +49,18 @@ class ImportSyncTabs(SideTabWidget): class ImportSyncWidget(QWidget): - def __init__(self, widget: QWidget, info: str, parent=None): + def __init__(self, widget: Optional[QWidget], info: str, parent=None): super(ImportSyncWidget, self).__init__(parent=parent) self.info = QLabel(f"{info}") layout = QVBoxLayout() - layout.addWidget(widget) + if widget is not None: + layout.addWidget(widget) layout.addWidget(self.info) layout.addItem( QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) ) self.setLayout(layout) + + def addWidget(self, widget: QWidget, stretch: int = 0, alignment: Qt.AlignmentFlag = Qt.Alignment()): + self.layout().insertWidget(self.layout().count() - 2, widget, stretch, alignment) diff --git a/rare/components/tabs/settings/widgets/eos.py b/rare/components/tabs/games/import_sync/eos_group.py similarity index 89% rename from rare/components/tabs/settings/widgets/eos.py rename to rare/components/tabs/games/import_sync/eos_group.py index 45a5b96a..86171474 100644 --- a/rare/components/tabs/settings/widgets/eos.py +++ b/rare/components/tabs/games/import_sync/eos_group.py @@ -5,11 +5,11 @@ from typing import List from PyQt5.QtCore import QRunnable, QObject, pyqtSignal, QThreadPool from PyQt5.QtWidgets import QGroupBox, QMessageBox - from legendary.lfs import eos -from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton -from rare.ui.components.tabs.settings.widgets.eos_widget import Ui_EosWidget + from rare.models.install import InstallOptionsModel +from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton +from ui.components.tabs.games.import_sync.eos_widget import Ui_EosWidget logger = getLogger("EOS") @@ -42,9 +42,9 @@ class CheckForUpdateWorker(QRunnable): self.signals.update_available.emit(self.core.overlay_update_available) -class EosWidget(QGroupBox, Ui_EosWidget): - def __init__(self): - super(EosWidget, self).__init__() +class EOSGroup(QGroupBox, Ui_EosWidget): + def __init__(self, parent=None): + super(EOSGroup, self).__init__(parent=parent) self.setupUi(self) self.core = LegendaryCoreSingleton() self.signals = GlobalSignalsSingleton() @@ -55,7 +55,6 @@ class EosWidget(QGroupBox, Ui_EosWidget): self.uninstall_button.clicked.connect(self.uninstall_overlay) self.update_button.setVisible(False) - self.update_info_lbl.setVisible(False) self.overlay = self.core.lgd.get_overlay_install_info() self.signals.overlay_installation_finished.connect(self.overlay_installation_finished) @@ -66,12 +65,12 @@ class EosWidget(QGroupBox, Ui_EosWidget): self.update_button.clicked.connect(lambda: self.install_overlay(True)) if self.overlay: # installed - self.installed_version_lbl.setText(self.overlay.version) - self.installed_path_lbl.setText(self.overlay.install_path) - self.info_stack.setCurrentIndex(0) + self.installed_version_lbl.setText(f"{self.overlay.version}") + self.installed_path_lbl.setText(f"{self.overlay.install_path}") + self.overlay_stack.setCurrentIndex(0) else: - self.info_stack.setCurrentIndex(1) - self.enable_gb.setDisabled(True) + self.overlay_stack.setCurrentIndex(1) + self.enable_frame.setDisabled(True) if platform.system() == "Windows": self.current_prefix = None @@ -84,7 +83,7 @@ class EosWidget(QGroupBox, Ui_EosWidget): for pfx in pfxs: self.select_pfx_combo.addItem(pfx.replace(os.path.expanduser("~/"), "~/")) if not pfxs: - self.enable_gb.setDisabled(True) + self.enable_frame.setDisabled(True) else: self.select_pfx_combo.setCurrentIndex(0) @@ -111,7 +110,6 @@ class EosWidget(QGroupBox, Ui_EosWidget): def check_for_update(self): def worker_finished(update_available): self.update_button.setVisible(update_available) - self.update_info_lbl.setVisible(update_available) self.update_check_button.setDisabled(False) if not update_available: self.update_check_button.setText(self.tr("No update available")) @@ -129,14 +127,13 @@ class EosWidget(QGroupBox, Ui_EosWidget): QMessageBox.warning(self, "Error", self.tr("Something went wrong, when installing overlay")) return - self.info_stack.setCurrentIndex(0) - self.installed_version_lbl.setText(self.overlay.version) - self.installed_path_lbl.setText(self.overlay.install_path) + self.overlay_stack.setCurrentIndex(0) + self.installed_version_lbl.setText(f"{self.overlay.version}") + self.installed_path_lbl.setText(f"{self.overlay.install_path}") self.update_button.setVisible(False) - self.update_info_lbl.setVisible(False) - self.enable_gb.setEnabled(True) + self.enable_frame.setEnabled(True) def update_select_combo(self, i: None): if i is None: @@ -215,8 +212,8 @@ class EosWidget(QGroupBox, Ui_EosWidget): base_path = os.path.expanduser("~/legendary/.overlay") if update: if not self.overlay: - self.info_stack.setCurrentIndex(1) - self.enable_gb.setDisabled(True) + self.overlay_stack.setCurrentIndex(1) + self.enable_frame.setDisabled(True) QMessageBox.warning(self, "Warning", self.tr("Overlay is not installed. Could not update")) return base_path = self.overlay.install_path @@ -229,7 +226,7 @@ class EosWidget(QGroupBox, Ui_EosWidget): def uninstall_overlay(self): if not self.core.is_overlay_installed(): logger.error('No legendary-managed overlay installation found.') - self.info_stack.setCurrentIndex(1) + self.overlay_stack.setCurrentIndex(1) return if QMessageBox.No == QMessageBox.question( @@ -248,6 +245,6 @@ class EosWidget(QGroupBox, Ui_EosWidget): logger.warning(f"{prefix}: {e}") self.core.remove_overlay_install() - self.info_stack.setCurrentIndex(1) + self.overlay_stack.setCurrentIndex(1) - self.enable_gb.setDisabled(True) + self.enable_frame.setDisabled(True) diff --git a/rare/components/tabs/settings/widgets/ubisoft_activation.py b/rare/components/tabs/games/import_sync/ubisoft_group.py similarity index 92% rename from rare/components/tabs/settings/widgets/ubisoft_activation.py rename to rare/components/tabs/games/import_sync/ubisoft_group.py index 028d3c5c..f58a7431 100644 --- a/rare/components/tabs/settings/widgets/ubisoft_activation.py +++ b/rare/components/tabs/games/import_sync/ubisoft_group.py @@ -3,7 +3,7 @@ import webbrowser from logging import getLogger from PyQt5.QtCore import QObject, pyqtSignal, QRunnable, QThreadPool, QSize -from PyQt5.QtWidgets import QWidget, QLabel, QHBoxLayout, QSizePolicy, QPushButton +from PyQt5.QtWidgets import QWidget, QLabel, QHBoxLayout, QSizePolicy, QPushButton, QGroupBox, QVBoxLayout from legendary.models.game import Game from rare.shared import LegendaryCoreSingleton, ArgumentsSingleton @@ -82,6 +82,7 @@ class UbiLinkWidget(QWidget): super(UbiLinkWidget, self).__init__() self.args = ArgumentsSingleton() layout = QHBoxLayout() + layout.setContentsMargins(0, 0, 0, 0) self.game = game self.ubi_account_id = ubi_account_id @@ -130,12 +131,13 @@ class UbiLinkWidget(QWidget): self.link_button.setDisabled(False) -class UbiActivationHelper(QObject): - def __init__(self, widget: QWidget): - super(UbiActivationHelper, self).__init__() +class UbisoftGroup(QGroupBox): + def __init__(self, parent=None): + super(UbisoftGroup, self).__init__(parent=parent) + self.setTitle(self.tr("Link Ubisoft Games")) + self.setLayout(QVBoxLayout()) self.core = LegendaryCoreSingleton() self.args = ArgumentsSingleton() - self.widget = widget self.thread_pool = QThreadPool.globalInstance() worker = UbiGetInfoWorker() @@ -147,7 +149,7 @@ class UbiActivationHelper(QObject): logger.error( "No linked ubisoft account found! Link your accounts via your browser and try again." ) - self.widget.layout().addWidget( + self.layout().addWidget( QLabel( self.tr( "Your account is not linked with Ubisoft. Please link your account first" @@ -158,10 +160,10 @@ class UbiActivationHelper(QObject): open_browser_button.clicked.connect( lambda: webbrowser.open("https://www.epicgames.com/id/link/ubisoft") ) - self.widget.layout().addWidget(open_browser_button) + self.layout().addWidget(open_browser_button) return elif ubi_account_id == "error": - self.widget.layout().addWidget(QLabel(self.tr("An error occurred"))) + self.layout().addWidget(QLabel(self.tr("An error occurred"))) return games = self.core.get_game_list(False) @@ -195,13 +197,13 @@ class UbiActivationHelper(QObject): if not uplay_games: if activated >= 1: - self.widget.layout().addWidget( + self.layout().addWidget( QLabel( self.tr("All your Ubisoft games have already been activated") ) ) else: - self.widget.layout().addWidget( + self.layout().addWidget( QLabel(self.tr("You don't own any Ubisoft games")) ) if self.args.debug: @@ -209,10 +211,10 @@ class UbiActivationHelper(QObject): Game(app_name="Test", app_title="This is a test game"), ubi_account_id, ) - self.widget.layout().addWidget(widget) + self.layout().addWidget(widget) return logger.info(f"Found {len(uplay_games)} game(s) to redeem") for game in uplay_games: widget = UbiLinkWidget(game, ubi_account_id) - self.widget.layout().addWidget(widget) + self.layout().addWidget(widget) diff --git a/rare/components/tabs/settings/legendary.py b/rare/components/tabs/settings/legendary.py index 51f22e88..996f0623 100644 --- a/rare/components/tabs/settings/legendary.py +++ b/rare/components/tabs/settings/legendary.py @@ -6,8 +6,6 @@ from typing import Tuple from PyQt5.QtCore import Qt, QRunnable, QObject, pyqtSignal, QThreadPool, QSettings from PyQt5.QtWidgets import QSizePolicy, QWidget, QFileDialog, QMessageBox -from rare.components.tabs.settings.widgets.eos import EosWidget -from rare.components.tabs.settings.widgets.ubisoft_activation import UbiActivationHelper from rare.shared import LegendaryCoreSingleton from rare.ui.components.tabs.settings.legendary import Ui_LegendarySettings from rare.utils.extra_widgets import PathEdit, IndicatorLineEdit @@ -87,10 +85,6 @@ class LegendarySettings(QWidget, Ui_LegendarySettings): ) self.locale_layout.addWidget(self.locale_edit) - self.ubi_helper = UbiActivationHelper(self.ubisoft_gb) - self.eos_widget = EosWidget() - self.left_layout.insertWidget(3, self.eos_widget, alignment=Qt.AlignTop) - self.win32_cb.setChecked(self.settings.value("win32_meta", False, bool)) self.win32_cb.stateChanged.connect(lambda: self.settings.setValue("win32_meta", self.win32_cb.isChecked())) diff --git a/rare/ui/components/tabs/games/import_sync/eos_widget.py b/rare/ui/components/tabs/games/import_sync/eos_widget.py new file mode 100644 index 00000000..666d5a87 --- /dev/null +++ b/rare/ui/components/tabs/games/import_sync/eos_widget.py @@ -0,0 +1,152 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'rare/ui/components/tabs/games/import_sync/eos_widget.ui' +# +# Created by: PyQt5 UI code generator 5.15.7 +# +# 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_EosWidget(object): + def setupUi(self, EosWidget): + EosWidget.setObjectName("EosWidget") + EosWidget.resize(586, 146) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Maximum) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(EosWidget.sizePolicy().hasHeightForWidth()) + EosWidget.setSizePolicy(sizePolicy) + EosWidget.setWindowTitle("GroupBox") + self.eos_layout = QtWidgets.QHBoxLayout(EosWidget) + self.eos_layout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint) + self.eos_layout.setObjectName("eos_layout") + self.overlay_stack = QtWidgets.QStackedWidget(EosWidget) + self.overlay_stack.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.overlay_stack.setFrameShadow(QtWidgets.QFrame.Raised) + self.overlay_stack.setObjectName("overlay_stack") + self.overlay_info_page = QtWidgets.QWidget() + self.overlay_info_page.setObjectName("overlay_info_page") + self.formLayout_3 = QtWidgets.QFormLayout(self.overlay_info_page) + self.formLayout_3.setLabelAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.formLayout_3.setFormAlignment(QtCore.Qt.AlignBottom|QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft) + self.formLayout_3.setObjectName("formLayout_3") + self.installed_version_info_lbl = QtWidgets.QLabel(self.overlay_info_page) + self.installed_version_info_lbl.setObjectName("installed_version_info_lbl") + self.formLayout_3.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.installed_version_info_lbl) + self.installed_version_lbl = QtWidgets.QLabel(self.overlay_info_page) + self.installed_version_lbl.setText("error") + self.installed_version_lbl.setObjectName("installed_version_lbl") + self.formLayout_3.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.installed_version_lbl) + self.installed_path_info_lbl = QtWidgets.QLabel(self.overlay_info_page) + self.installed_path_info_lbl.setObjectName("installed_path_info_lbl") + self.formLayout_3.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.installed_path_info_lbl) + self.installed_path_lbl = QtWidgets.QLabel(self.overlay_info_page) + self.installed_path_lbl.setText("error") + self.installed_path_lbl.setObjectName("installed_path_lbl") + self.formLayout_3.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.installed_path_lbl) + self.horizontalLayout = QtWidgets.QHBoxLayout() + self.horizontalLayout.setObjectName("horizontalLayout") + spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout.addItem(spacerItem) + self.uninstall_button = QtWidgets.QPushButton(self.overlay_info_page) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.uninstall_button.sizePolicy().hasHeightForWidth()) + self.uninstall_button.setSizePolicy(sizePolicy) + self.uninstall_button.setMaximumSize(QtCore.QSize(150, 16777215)) + self.uninstall_button.setObjectName("uninstall_button") + self.horizontalLayout.addWidget(self.uninstall_button) + self.update_check_button = QtWidgets.QPushButton(self.overlay_info_page) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.update_check_button.sizePolicy().hasHeightForWidth()) + self.update_check_button.setSizePolicy(sizePolicy) + self.update_check_button.setMaximumSize(QtCore.QSize(150, 16777215)) + self.update_check_button.setObjectName("update_check_button") + self.horizontalLayout.addWidget(self.update_check_button) + self.update_button = QtWidgets.QPushButton(self.overlay_info_page) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.update_button.sizePolicy().hasHeightForWidth()) + self.update_button.setSizePolicy(sizePolicy) + self.update_button.setMaximumSize(QtCore.QSize(150, 16777215)) + self.update_button.setObjectName("update_button") + self.horizontalLayout.addWidget(self.update_button) + self.formLayout_3.setLayout(3, QtWidgets.QFormLayout.SpanningRole, self.horizontalLayout) + spacerItem1 = QtWidgets.QSpacerItem(6, 6, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.formLayout_3.setItem(2, QtWidgets.QFormLayout.SpanningRole, spacerItem1) + self.overlay_stack.addWidget(self.overlay_info_page) + self.overlay_install_page = QtWidgets.QWidget() + self.overlay_install_page.setObjectName("overlay_install_page") + self.formLayout = QtWidgets.QFormLayout(self.overlay_install_page) + self.formLayout.setLabelAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.formLayout.setFormAlignment(QtCore.Qt.AlignBottom|QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft) + self.formLayout.setObjectName("formLayout") + self.label = QtWidgets.QLabel(self.overlay_install_page) + self.label.setObjectName("label") + self.formLayout.setWidget(0, QtWidgets.QFormLayout.SpanningRole, self.label) + self.horizontalLayout_3 = QtWidgets.QHBoxLayout() + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_3.addItem(spacerItem2) + self.install_button = QtWidgets.QPushButton(self.overlay_install_page) + self.install_button.setObjectName("install_button") + self.horizontalLayout_3.addWidget(self.install_button) + self.formLayout.setLayout(2, QtWidgets.QFormLayout.SpanningRole, self.horizontalLayout_3) + spacerItem3 = QtWidgets.QSpacerItem(6, 6, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.formLayout.setItem(1, QtWidgets.QFormLayout.SpanningRole, spacerItem3) + self.overlay_stack.addWidget(self.overlay_install_page) + self.eos_layout.addWidget(self.overlay_stack) + self.enable_frame = QtWidgets.QFrame(EosWidget) + self.enable_frame.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.enable_frame.setFrameShadow(QtWidgets.QFrame.Raised) + self.enable_frame.setObjectName("enable_frame") + self.verticalLayout = QtWidgets.QVBoxLayout(self.enable_frame) + self.verticalLayout.setObjectName("verticalLayout") + self.select_pfx_combo = QtWidgets.QComboBox(self.enable_frame) + self.select_pfx_combo.setObjectName("select_pfx_combo") + self.verticalLayout.addWidget(self.select_pfx_combo) + self.enabled_cb = QtWidgets.QCheckBox(self.enable_frame) + self.enabled_cb.setObjectName("enabled_cb") + self.verticalLayout.addWidget(self.enabled_cb) + self.enabled_info_label = QtWidgets.QLabel(self.enable_frame) + font = QtGui.QFont() + font.setItalic(True) + self.enabled_info_label.setFont(font) + self.enabled_info_label.setText("") + self.enabled_info_label.setObjectName("enabled_info_label") + self.verticalLayout.addWidget(self.enabled_info_label) + self.eos_layout.addWidget(self.enable_frame) + + self.retranslateUi(EosWidget) + self.overlay_stack.setCurrentIndex(0) + QtCore.QMetaObject.connectSlotsByName(EosWidget) + + def retranslateUi(self, EosWidget): + _translate = QtCore.QCoreApplication.translate + EosWidget.setTitle(_translate("EosWidget", "Epic Overlay")) + self.installed_version_info_lbl.setText(_translate("EosWidget", "Version")) + self.installed_path_info_lbl.setText(_translate("EosWidget", "Location")) + self.uninstall_button.setText(_translate("EosWidget", "Uninstall")) + self.update_check_button.setText(_translate("EosWidget", "Check for update")) + self.update_button.setText(_translate("EosWidget", "Update")) + self.label.setText(_translate("EosWidget", "Epic Overlay Services is not installed")) + self.install_button.setText(_translate("EosWidget", "Install")) + self.enabled_cb.setText(_translate("EosWidget", "Activated")) + + +if __name__ == "__main__": + import sys + app = QtWidgets.QApplication(sys.argv) + EosWidget = QtWidgets.QGroupBox() + ui = Ui_EosWidget() + ui.setupUi(EosWidget) + EosWidget.show() + sys.exit(app.exec_()) diff --git a/rare/ui/components/tabs/games/import_sync/eos_widget.ui b/rare/ui/components/tabs/games/import_sync/eos_widget.ui new file mode 100644 index 00000000..7a70d318 --- /dev/null +++ b/rare/ui/components/tabs/games/import_sync/eos_widget.ui @@ -0,0 +1,259 @@ + + + EosWidget + + + + 0 + 0 + 586 + 146 + + + + + 0 + 0 + + + + GroupBox + + + Epic Overlay + + + + QLayout::SetDefaultConstraint + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + 0 + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + Version + + + + + + + error + + + + + + + Location + + + + + + + error + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 150 + 16777215 + + + + Uninstall + + + + + + + + 0 + 0 + + + + + 150 + 16777215 + + + + Check for update + + + + + + + + 0 + 0 + + + + + 150 + 16777215 + + + + Update + + + + + + + + + Qt::Vertical + + + + 6 + 6 + + + + + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + Epic Overlay Services is not installed + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Install + + + + + + + + + Qt::Vertical + + + + 6 + 6 + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + Activated + + + + + + + + true + + + + + + + + + + + + + + + diff --git a/rare/ui/components/tabs/settings/legendary.py b/rare/ui/components/tabs/settings/legendary.py index 96c62572..4cd3bc7e 100644 --- a/rare/ui/components/tabs/settings/legendary.py +++ b/rare/ui/components/tabs/settings/legendary.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'rare/ui/components/tabs/settings/legendary.ui' # -# Created by: PyQt5 UI code generator 5.15.6 +# Created by: PyQt5 UI code generator 5.15.7 # # 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. @@ -98,12 +98,6 @@ class Ui_LegendarySettings(object): self.disable_https_check.setObjectName("disable_https_check") self.download_layout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.disable_https_check) self.left_layout.addWidget(self.download_group, 0, QtCore.Qt.AlignTop) - self.ubisoft_gb = QtWidgets.QGroupBox(LegendarySettings) - self.ubisoft_gb.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop) - self.ubisoft_gb.setObjectName("ubisoft_gb") - self.verticalLayout = QtWidgets.QVBoxLayout(self.ubisoft_gb) - self.verticalLayout.setObjectName("verticalLayout") - self.left_layout.addWidget(self.ubisoft_gb, 0, QtCore.Qt.AlignTop) spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) self.left_layout.addItem(spacerItem) self.legendary_layout.addLayout(self.left_layout) @@ -165,7 +159,6 @@ class Ui_LegendarySettings(object): self.preferred_cdn_label.setText(_translate("LegendarySettings", "Preferred CDN")) self.preferred_cdn_line.setPlaceholderText(_translate("LegendarySettings", "Default")) self.disable_https_label.setText(_translate("LegendarySettings", "Disable HTTPS")) - self.ubisoft_gb.setTitle(_translate("LegendarySettings", "Link Ubisoft Games")) self.locale_group.setTitle(_translate("LegendarySettings", "Locale")) self.cleanup_group.setTitle(_translate("LegendarySettings", "Cleanup")) self.clean_keep_manifests_button.setText(_translate("LegendarySettings", "Clean, but keep manifests")) diff --git a/rare/ui/components/tabs/settings/legendary.ui b/rare/ui/components/tabs/settings/legendary.ui index f3e27bd5..a69ef823 100644 --- a/rare/ui/components/tabs/settings/legendary.ui +++ b/rare/ui/components/tabs/settings/legendary.ui @@ -166,17 +166,6 @@
- - - - Link Ubisoft Games - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - diff --git a/rare/ui/components/tabs/settings/widgets/eos_widget.py b/rare/ui/components/tabs/settings/widgets/eos_widget.py deleted file mode 100644 index 947db4fd..00000000 --- a/rare/ui/components/tabs/settings/widgets/eos_widget.py +++ /dev/null @@ -1,170 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'rare/ui/components/tabs/settings/widgets/eos_widget.ui' -# -# Created by: PyQt5 UI code generator 5.15.6 -# -# 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_EosWidget(object): - def setupUi(self, EosWidget): - EosWidget.setObjectName("EosWidget") - EosWidget.resize(364, 218) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Maximum) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(EosWidget.sizePolicy().hasHeightForWidth()) - EosWidget.setSizePolicy(sizePolicy) - EosWidget.setWindowTitle("GroupBox") - self.eos_layout = QtWidgets.QHBoxLayout(EosWidget) - self.eos_layout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint) - self.eos_layout.setObjectName("eos_layout") - self.info_stack = QtWidgets.QStackedWidget(EosWidget) - self.info_stack.setObjectName("info_stack") - self.installed_info_page = QtWidgets.QWidget() - self.installed_info_page.setObjectName("installed_info_page") - self.installed_info_page_layout = QtWidgets.QVBoxLayout(self.installed_info_page) - self.installed_info_page_layout.setContentsMargins(0, 0, 0, 0) - self.installed_info_page_layout.setObjectName("installed_info_page_layout") - self.installed_info_gb = QtWidgets.QGroupBox(self.installed_info_page) - self.installed_info_gb.setObjectName("installed_info_gb") - self.installed_info_layout = QtWidgets.QFormLayout(self.installed_info_gb) - self.installed_info_layout.setLabelAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) - self.installed_info_layout.setObjectName("installed_info_layout") - self.installed_version_info_lbl = QtWidgets.QLabel(self.installed_info_gb) - self.installed_version_info_lbl.setObjectName("installed_version_info_lbl") - self.installed_info_layout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.installed_version_info_lbl) - self.installed_version_lbl = QtWidgets.QLabel(self.installed_info_gb) - self.installed_version_lbl.setText("TextLabel") - self.installed_version_lbl.setObjectName("installed_version_lbl") - self.installed_info_layout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.installed_version_lbl) - self.installed_path_info_lbl = QtWidgets.QLabel(self.installed_info_gb) - self.installed_path_info_lbl.setObjectName("installed_path_info_lbl") - self.installed_info_layout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.installed_path_info_lbl) - self.installed_path_lbl = QtWidgets.QLabel(self.installed_info_gb) - self.installed_path_lbl.setText("TextLabel") - self.installed_path_lbl.setObjectName("installed_path_lbl") - self.installed_info_layout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.installed_path_lbl) - self.update_available_info_label = QtWidgets.QLabel(self.installed_info_gb) - self.update_available_info_label.setObjectName("update_available_info_label") - self.installed_info_layout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.update_available_info_label) - self.update_check_button = QtWidgets.QPushButton(self.installed_info_gb) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.update_check_button.sizePolicy().hasHeightForWidth()) - self.update_check_button.setSizePolicy(sizePolicy) - self.update_check_button.setMaximumSize(QtCore.QSize(150, 16777215)) - self.update_check_button.setObjectName("update_check_button") - self.installed_info_layout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.update_check_button) - self.uninstall_info_label = QtWidgets.QLabel(self.installed_info_gb) - self.uninstall_info_label.setObjectName("uninstall_info_label") - self.installed_info_layout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.uninstall_info_label) - self.uninstall_button = QtWidgets.QPushButton(self.installed_info_gb) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.uninstall_button.sizePolicy().hasHeightForWidth()) - self.uninstall_button.setSizePolicy(sizePolicy) - self.uninstall_button.setMaximumSize(QtCore.QSize(150, 16777215)) - self.uninstall_button.setObjectName("uninstall_button") - self.installed_info_layout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.uninstall_button) - self.update_button = QtWidgets.QPushButton(self.installed_info_gb) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.update_button.sizePolicy().hasHeightForWidth()) - self.update_button.setSizePolicy(sizePolicy) - self.update_button.setMaximumSize(QtCore.QSize(150, 16777215)) - self.update_button.setObjectName("update_button") - self.installed_info_layout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.update_button) - self.update_info_lbl = QtWidgets.QLabel(self.installed_info_gb) - self.update_info_lbl.setObjectName("update_info_lbl") - self.installed_info_layout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.update_info_lbl) - self.installed_info_page_layout.addWidget(self.installed_info_gb, 0, QtCore.Qt.AlignTop) - self.info_stack.addWidget(self.installed_info_page) - self.install_overlay_page = QtWidgets.QWidget() - self.install_overlay_page.setObjectName("install_overlay_page") - self.install_overlay_page_layout = QtWidgets.QVBoxLayout(self.install_overlay_page) - self.install_overlay_page_layout.setContentsMargins(0, 0, 0, 0) - self.install_overlay_page_layout.setObjectName("install_overlay_page_layout") - self.install_overlay_gb = QtWidgets.QGroupBox(self.install_overlay_page) - self.install_overlay_gb.setObjectName("install_overlay_gb") - self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.install_overlay_gb) - self.verticalLayout_4.setObjectName("verticalLayout_4") - self.label = QtWidgets.QLabel(self.install_overlay_gb) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Maximum) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth()) - self.label.setSizePolicy(sizePolicy) - self.label.setObjectName("label") - self.verticalLayout_4.addWidget(self.label) - self.install_button = QtWidgets.QPushButton(self.install_overlay_gb) - self.install_button.setMinimumSize(QtCore.QSize(120, 0)) - self.install_button.setObjectName("install_button") - self.verticalLayout_4.addWidget(self.install_button, 0, QtCore.Qt.AlignRight) - self.install_overlay_page_layout.addWidget(self.install_overlay_gb, 0, QtCore.Qt.AlignTop) - self.info_stack.addWidget(self.install_overlay_page) - self.eos_layout.addWidget(self.info_stack) - self.enable_gb = QtWidgets.QGroupBox(EosWidget) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.enable_gb.sizePolicy().hasHeightForWidth()) - self.enable_gb.setSizePolicy(sizePolicy) - self.enable_gb.setObjectName("enable_gb") - self.enable_layout = QtWidgets.QVBoxLayout(self.enable_gb) - self.enable_layout.setObjectName("enable_layout") - self.select_pfx_combo = QtWidgets.QComboBox(self.enable_gb) - self.select_pfx_combo.setObjectName("select_pfx_combo") - self.enable_layout.addWidget(self.select_pfx_combo) - self.enabled_cb = QtWidgets.QCheckBox(self.enable_gb) - self.enabled_cb.setObjectName("enabled_cb") - self.enable_layout.addWidget(self.enabled_cb) - self.enabled_info_label = QtWidgets.QLabel(self.enable_gb) - font = QtGui.QFont() - font.setItalic(True) - self.enabled_info_label.setFont(font) - self.enabled_info_label.setText("") - self.enabled_info_label.setObjectName("enabled_info_label") - self.enable_layout.addWidget(self.enabled_info_label, 0, QtCore.Qt.AlignTop) - self.enable_layout.setStretch(2, 1) - self.eos_layout.addWidget(self.enable_gb) - - self.retranslateUi(EosWidget) - self.info_stack.setCurrentIndex(1) - QtCore.QMetaObject.connectSlotsByName(EosWidget) - - def retranslateUi(self, EosWidget): - _translate = QtCore.QCoreApplication.translate - EosWidget.setTitle(_translate("EosWidget", "Epic Overlay settings")) - self.installed_info_gb.setTitle(_translate("EosWidget", "Installed Info")) - self.installed_version_info_lbl.setText(_translate("EosWidget", "Installed version")) - self.installed_path_info_lbl.setText(_translate("EosWidget", "Installed path")) - self.update_available_info_label.setText(_translate("EosWidget", "Updates")) - self.update_check_button.setText(_translate("EosWidget", "Check for Update")) - self.uninstall_info_label.setText(_translate("EosWidget", "Uninstall")) - self.uninstall_button.setText(_translate("EosWidget", "Uninstall")) - self.update_button.setText(_translate("EosWidget", "Update")) - self.update_info_lbl.setText(_translate("EosWidget", "Install Update")) - self.install_overlay_gb.setTitle(_translate("EosWidget", "Install Overlay")) - self.label.setText(_translate("EosWidget", "No overlays are installed")) - self.install_button.setText(_translate("EosWidget", "Install")) - self.enable_gb.setTitle(_translate("EosWidget", "Enable / Disable")) - self.enabled_cb.setText(_translate("EosWidget", "Activated")) - - -if __name__ == "__main__": - import sys - app = QtWidgets.QApplication(sys.argv) - EosWidget = QtWidgets.QGroupBox() - ui = Ui_EosWidget() - ui.setupUi(EosWidget) - EosWidget.show() - sys.exit(app.exec_()) diff --git a/rare/ui/components/tabs/settings/widgets/eos_widget.ui b/rare/ui/components/tabs/settings/widgets/eos_widget.ui deleted file mode 100644 index 0c36b2fc..00000000 --- a/rare/ui/components/tabs/settings/widgets/eos_widget.ui +++ /dev/null @@ -1,262 +0,0 @@ - - - EosWidget - - - - 0 - 0 - 364 - 218 - - - - - 0 - 0 - - - - GroupBox - - - Epic Overlay settings - - - - QLayout::SetDefaultConstraint - - - - - 1 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Installed Info - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - Installed version - - - - - - - TextLabel - - - - - - - Installed path - - - - - - - TextLabel - - - - - - - Updates - - - - - - - - 0 - 0 - - - - - 150 - 16777215 - - - - Check for Update - - - - - - - Uninstall - - - - - - - - 0 - 0 - - - - - 150 - 16777215 - - - - Uninstall - - - - - - - - 0 - 0 - - - - - 150 - 16777215 - - - - Update - - - - - - - Install Update - - - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Install Overlay - - - - - - - 0 - 0 - - - - No overlays are installed - - - - - - - - 120 - 0 - - - - Install - - - - - - - - - - - - - - - 0 - 0 - - - - Enable / Disable - - - - - - - - - Activated - - - - - - - - true - - - - - - - - - - - - - - - From b84d8a5c67dc755842a09a841e153321a729829d Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Thu, 3 Nov 2022 22:39:48 +0200 Subject: [PATCH 13/14] ImportSync: Rename to Integrations due to expanding their use. --- rare/components/tabs/games/__init__.py | 20 +++++++++---------- .../{import_sync => integrations}/__init__.py | 20 +++++++++---------- .../egl_sync_group.py | 4 ++-- .../eos_group.py | 2 +- .../import_group.py | 2 +- .../ubisoft_group.py | 0 .../{import_sync => integrations}/__init__.py | 0 .../egl_sync_group.py | 0 .../egl_sync_group.ui | 0 .../egl_sync_list_group.py | 0 .../egl_sync_list_group.ui | 0 .../eos_widget.py | 0 .../eos_widget.ui | 0 .../import_group.py | 0 .../import_group.ui | 0 15 files changed, 24 insertions(+), 24 deletions(-) rename rare/components/tabs/games/{import_sync => integrations}/__init__.py (74%) rename rare/components/tabs/games/{import_sync => integrations}/egl_sync_group.py (98%) rename rare/components/tabs/games/{import_sync => integrations}/eos_group.py (99%) rename rare/components/tabs/games/{import_sync => integrations}/import_group.py (99%) rename rare/components/tabs/games/{import_sync => integrations}/ubisoft_group.py (100%) rename rare/ui/components/tabs/games/{import_sync => integrations}/__init__.py (100%) rename rare/ui/components/tabs/games/{import_sync => integrations}/egl_sync_group.py (100%) rename rare/ui/components/tabs/games/{import_sync => integrations}/egl_sync_group.ui (100%) rename rare/ui/components/tabs/games/{import_sync => integrations}/egl_sync_list_group.py (100%) rename rare/ui/components/tabs/games/{import_sync => integrations}/egl_sync_list_group.ui (100%) rename rare/ui/components/tabs/games/{import_sync => integrations}/eos_widget.py (100%) rename rare/ui/components/tabs/games/{import_sync => integrations}/eos_widget.ui (100%) rename rare/ui/components/tabs/games/{import_sync => integrations}/import_group.py (100%) rename rare/ui/components/tabs/games/{import_sync => integrations}/import_group.ui (100%) diff --git a/rare/components/tabs/games/__init__.py b/rare/components/tabs/games/__init__.py index 3be4ee0a..d75569e7 100644 --- a/rare/components/tabs/games/__init__.py +++ b/rare/components/tabs/games/__init__.py @@ -26,7 +26,7 @@ from .game_widgets.installing_game_widget import InstallingGameWidget from .game_widgets.uninstalled_icon_widget import UninstalledIconWidget from .game_widgets.uninstalled_list_widget import UninstalledListWidget from .head_bar import GameListHeadBar -from .import_sync import ImportSyncTabs +from .integrations import IntegrationsTabs logger = getLogger("GamesTab") @@ -74,9 +74,9 @@ class GamesTab(QStackedWidget): ) self.game_info_tabs.info.uninstalled.connect(lambda x: self.setCurrentWidget(self.games)) - self.import_sync_tabs = ImportSyncTabs(self) - self.import_sync_tabs.back_clicked.connect(lambda: self.setCurrentWidget(self.games)) - self.addWidget(self.import_sync_tabs) + self.integrations_tabs = IntegrationsTabs(self) + self.integrations_tabs.back_clicked.connect(lambda: self.setCurrentWidget(self.games)) + self.addWidget(self.integrations_tabs) for i in self.game_list: if i.app_name.startswith("UE_4"): @@ -196,18 +196,18 @@ class GamesTab(QStackedWidget): @pyqtSlot() def show_import(self): - self.setCurrentWidget(self.import_sync_tabs) - self.import_sync_tabs.show_import() + self.setCurrentWidget(self.integrations_tabs) + self.integrations_tabs.show_import() @pyqtSlot() def show_egl_sync(self): - self.setCurrentWidget(self.import_sync_tabs) - self.import_sync_tabs.show_egl_sync() + self.setCurrentWidget(self.integrations_tabs) + self.integrations_tabs.show_egl_sync() @pyqtSlot() def show_eos_ubisoft(self): - self.setCurrentWidget(self.import_sync_tabs) - self.import_sync_tabs.show_eos_ubisoft() + self.setCurrentWidget(self.integrations_tabs) + self.integrations_tabs.show_eos_ubisoft() def show_game_info(self, app_name): self.game_info_tabs.update_game(app_name) diff --git a/rare/components/tabs/games/import_sync/__init__.py b/rare/components/tabs/games/integrations/__init__.py similarity index 74% rename from rare/components/tabs/games/import_sync/__init__.py rename to rare/components/tabs/games/integrations/__init__.py index de4bf610..92602591 100644 --- a/rare/components/tabs/games/import_sync/__init__.py +++ b/rare/components/tabs/games/integrations/__init__.py @@ -10,31 +10,31 @@ from .eos_group import EOSGroup from .ubisoft_group import UbisoftGroup -class ImportSyncTabs(SideTabWidget): +class IntegrationsTabs(SideTabWidget): def __init__(self, parent=None): - super(ImportSyncTabs, self).__init__(show_back=True, parent=parent) - self.import_widget = ImportSyncWidget( + super(IntegrationsTabs, self).__init__(show_back=True, parent=parent) + self.import_widget = IntegrationsWidget( ImportGroup(self), self.tr("To import games from Epic Games Store, please enable EGL Sync."), self, ) self.addTab(self.import_widget, self.tr("Import Games")) - self.egl_sync_widget = ImportSyncWidget( + self.egl_sync_widget = IntegrationsWidget( EGLSyncGroup(self), self.tr("To import EGL games from directories, please use Import Game."), self, ) self.addTab(self.egl_sync_widget, self.tr("Sync with EGL")) - self.egl_eos_ubisoft = ImportSyncWidget( + self.eos_ubisoft = IntegrationsWidget( None, self.tr(""), self, ) - self.egl_eos_ubisoft.addWidget(UbisoftGroup(self.egl_eos_ubisoft)) - self.egl_eos_ubisoft.addWidget(EOSGroup(self.egl_eos_ubisoft)) - self.addTab(self.egl_eos_ubisoft, self.tr("EOS and Ubisoft")) + self.eos_ubisoft.addWidget(UbisoftGroup(self.eos_ubisoft)) + self.eos_ubisoft.addWidget(EOSGroup(self.eos_ubisoft)) + self.addTab(self.eos_ubisoft, self.tr("EOS and Ubisoft")) self.tabBar().setCurrentIndex(1) @@ -48,9 +48,9 @@ class ImportSyncTabs(SideTabWidget): self.setCurrentIndex(3) -class ImportSyncWidget(QWidget): +class IntegrationsWidget(QWidget): def __init__(self, widget: Optional[QWidget], info: str, parent=None): - super(ImportSyncWidget, self).__init__(parent=parent) + super(IntegrationsWidget, self).__init__(parent=parent) self.info = QLabel(f"{info}") layout = QVBoxLayout() diff --git a/rare/components/tabs/games/import_sync/egl_sync_group.py b/rare/components/tabs/games/integrations/egl_sync_group.py similarity index 98% rename from rare/components/tabs/games/import_sync/egl_sync_group.py rename to rare/components/tabs/games/integrations/egl_sync_group.py index ca2ee94e..f1ecdc97 100644 --- a/rare/components/tabs/games/import_sync/egl_sync_group.py +++ b/rare/components/tabs/games/integrations/egl_sync_group.py @@ -8,8 +8,8 @@ from PyQt5.QtWidgets import QGroupBox, QListWidgetItem, QFileDialog, QMessageBox from rare.lgndr.glue.exception import LgndrException from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton -from rare.ui.components.tabs.games.import_sync.egl_sync_group import Ui_EGLSyncGroup -from rare.ui.components.tabs.games.import_sync.egl_sync_list_group import ( +from rare.ui.components.tabs.games.integrations.egl_sync_group import Ui_EGLSyncGroup +from rare.ui.components.tabs.games.integrations.egl_sync_list_group import ( Ui_EGLSyncListGroup, ) from rare.utils.extra_widgets import PathEdit diff --git a/rare/components/tabs/games/import_sync/eos_group.py b/rare/components/tabs/games/integrations/eos_group.py similarity index 99% rename from rare/components/tabs/games/import_sync/eos_group.py rename to rare/components/tabs/games/integrations/eos_group.py index 86171474..30f7a034 100644 --- a/rare/components/tabs/games/import_sync/eos_group.py +++ b/rare/components/tabs/games/integrations/eos_group.py @@ -9,7 +9,7 @@ from legendary.lfs import eos from rare.models.install import InstallOptionsModel from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton -from ui.components.tabs.games.import_sync.eos_widget import Ui_EosWidget +from rare.ui.components.tabs.games.integrations.eos_widget import Ui_EosWidget logger = getLogger("EOS") diff --git a/rare/components/tabs/games/import_sync/import_group.py b/rare/components/tabs/games/integrations/import_group.py similarity index 99% rename from rare/components/tabs/games/import_sync/import_group.py rename to rare/components/tabs/games/integrations/import_group.py index bd629c11..806b74fc 100644 --- a/rare/components/tabs/games/import_sync/import_group.py +++ b/rare/components/tabs/games/integrations/import_group.py @@ -14,7 +14,7 @@ from rare.lgndr.cli import LegendaryCLI from rare.lgndr.glue.arguments import LgndrImportGameArgs from rare.lgndr.glue.monkeys import LgndrIndirectStatus from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ApiResultsSingleton -from rare.ui.components.tabs.games.import_sync.import_group import Ui_ImportGroup +from rare.ui.components.tabs.games.integrations.import_group import Ui_ImportGroup from rare.utils.extra_widgets import IndicatorLineEdit, PathEdit from rare.widgets.elide_label import ElideLabel diff --git a/rare/components/tabs/games/import_sync/ubisoft_group.py b/rare/components/tabs/games/integrations/ubisoft_group.py similarity index 100% rename from rare/components/tabs/games/import_sync/ubisoft_group.py rename to rare/components/tabs/games/integrations/ubisoft_group.py diff --git a/rare/ui/components/tabs/games/import_sync/__init__.py b/rare/ui/components/tabs/games/integrations/__init__.py similarity index 100% rename from rare/ui/components/tabs/games/import_sync/__init__.py rename to rare/ui/components/tabs/games/integrations/__init__.py diff --git a/rare/ui/components/tabs/games/import_sync/egl_sync_group.py b/rare/ui/components/tabs/games/integrations/egl_sync_group.py similarity index 100% rename from rare/ui/components/tabs/games/import_sync/egl_sync_group.py rename to rare/ui/components/tabs/games/integrations/egl_sync_group.py diff --git a/rare/ui/components/tabs/games/import_sync/egl_sync_group.ui b/rare/ui/components/tabs/games/integrations/egl_sync_group.ui similarity index 100% rename from rare/ui/components/tabs/games/import_sync/egl_sync_group.ui rename to rare/ui/components/tabs/games/integrations/egl_sync_group.ui diff --git a/rare/ui/components/tabs/games/import_sync/egl_sync_list_group.py b/rare/ui/components/tabs/games/integrations/egl_sync_list_group.py similarity index 100% rename from rare/ui/components/tabs/games/import_sync/egl_sync_list_group.py rename to rare/ui/components/tabs/games/integrations/egl_sync_list_group.py diff --git a/rare/ui/components/tabs/games/import_sync/egl_sync_list_group.ui b/rare/ui/components/tabs/games/integrations/egl_sync_list_group.ui similarity index 100% rename from rare/ui/components/tabs/games/import_sync/egl_sync_list_group.ui rename to rare/ui/components/tabs/games/integrations/egl_sync_list_group.ui diff --git a/rare/ui/components/tabs/games/import_sync/eos_widget.py b/rare/ui/components/tabs/games/integrations/eos_widget.py similarity index 100% rename from rare/ui/components/tabs/games/import_sync/eos_widget.py rename to rare/ui/components/tabs/games/integrations/eos_widget.py diff --git a/rare/ui/components/tabs/games/import_sync/eos_widget.ui b/rare/ui/components/tabs/games/integrations/eos_widget.ui similarity index 100% rename from rare/ui/components/tabs/games/import_sync/eos_widget.ui rename to rare/ui/components/tabs/games/integrations/eos_widget.ui diff --git a/rare/ui/components/tabs/games/import_sync/import_group.py b/rare/ui/components/tabs/games/integrations/import_group.py similarity index 100% rename from rare/ui/components/tabs/games/import_sync/import_group.py rename to rare/ui/components/tabs/games/integrations/import_group.py diff --git a/rare/ui/components/tabs/games/import_sync/import_group.ui b/rare/ui/components/tabs/games/integrations/import_group.ui similarity index 100% rename from rare/ui/components/tabs/games/import_sync/import_group.ui rename to rare/ui/components/tabs/games/integrations/import_group.ui From cb49e8b6781c9800245dfe1a186faa0afa3caa5c Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Fri, 4 Nov 2022 02:44:45 +0200 Subject: [PATCH 14/14] Integrations: EOS -> Epic Overlay --- rare/components/tabs/games/head_bar.py | 2 +- rare/components/tabs/games/integrations/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rare/components/tabs/games/head_bar.py b/rare/components/tabs/games/head_bar.py index a33b6f2d..06fe1627 100644 --- a/rare/components/tabs/games/head_bar.py +++ b/rare/components/tabs/games/head_bar.py @@ -68,7 +68,7 @@ class GameListHeadBar(QWidget): egl_sync_action = QAction(icon("mdi.sync", "fa.refresh"), self.tr("Sync with EGL"), integrations_menu) egl_sync_action.triggered.connect(self.goto_egl_sync) - eos_ubisoft_action = QAction(icon("mdi.rocket", "fa.rocket"), self.tr("EOS and Ubisoft"), integrations_menu) + eos_ubisoft_action = QAction(icon("mdi.rocket", "fa.rocket"), self.tr("Epic Overlay and Ubisoft"), integrations_menu) eos_ubisoft_action.triggered.connect(self.goto_eos_ubisoft) integrations_menu.addAction(import_action) diff --git a/rare/components/tabs/games/integrations/__init__.py b/rare/components/tabs/games/integrations/__init__.py index 92602591..8f0c5485 100644 --- a/rare/components/tabs/games/integrations/__init__.py +++ b/rare/components/tabs/games/integrations/__init__.py @@ -34,7 +34,7 @@ class IntegrationsTabs(SideTabWidget): ) self.eos_ubisoft.addWidget(UbisoftGroup(self.eos_ubisoft)) self.eos_ubisoft.addWidget(EOSGroup(self.eos_ubisoft)) - self.addTab(self.eos_ubisoft, self.tr("EOS and Ubisoft")) + self.addTab(self.eos_ubisoft, self.tr("Epic Overlay and Ubisoft")) self.tabBar().setCurrentIndex(1)