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/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/components/dialogs/install_dialog.py b/rare/components/dialogs/install_dialog.py
index d9cbf953..7d2becf2 100644
--- a/rare/components/dialogs/install_dialog.py
+++ b/rare/components/dialogs/install_dialog.py
@@ -5,23 +5,33 @@ 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
-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
+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.collabsible_widget import CollabsibleWidget
+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 = CollabsibleWidget(
- 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/components/tabs/__init__.py b/rare/components/tabs/__init__.py
index b6710a9e..03c245a9 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"))
@@ -53,12 +51,10 @@ 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)
- 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 +111,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 +132,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")))
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/__init__.py b/rare/components/tabs/games/__init__.py
index 835c1289..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")
@@ -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)
@@ -73,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"):
@@ -193,13 +194,20 @@ 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()
+ self.setCurrentWidget(self.integrations_tabs)
+ self.integrations_tabs.show_import()
- def show_egl_sync(self, idx):
- self.setCurrentWidget(self.import_sync_tabs)
- self.import_sync_tabs.show_egl_sync()
+ @pyqtSlot()
+ def show_egl_sync(self):
+ self.setCurrentWidget(self.integrations_tabs)
+ self.integrations_tabs.show_egl_sync()
+
+ @pyqtSlot()
+ def show_eos_ubisoft(self):
+ 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/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/head_bar.py b/rare/components/tabs/games/head_bar.py
index e22ca957..06fe1627 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("Epic Overlay 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
deleted file mode 100644
index cba2a520..00000000
--- a/rare/components/tabs/games/import_sync/__init__.py
+++ /dev/null
@@ -1,45 +0,0 @@
-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
-
-
-class ImportSyncTabs(SideTabWidget):
- def __init__(self, parent=None):
- super(ImportSyncTabs, self).__init__(show_back=True, parent=parent)
- self.import_widget = ImportSyncWidget(
- 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(
- 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.tabBar().setCurrentIndex(1)
-
- def show_import(self):
- self.setCurrentIndex(1)
-
- def show_egl_sync(self):
- self.setCurrentIndex(2)
-
-
-class ImportSyncWidget(QWidget):
- def __init__(self, widget: QWidget, info: str, parent=None):
- super(ImportSyncWidget, self).__init__(parent=parent)
- self.info = QLabel(f"{info}
")
-
- layout = QVBoxLayout()
- layout.addWidget(widget)
- layout.addWidget(self.info)
- layout.addItem(
- QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
- )
- self.setLayout(layout)
diff --git a/rare/components/tabs/games/integrations/__init__.py b/rare/components/tabs/games/integrations/__init__.py
new file mode 100644
index 00000000..8f0c5485
--- /dev/null
+++ b/rare/components/tabs/games/integrations/__init__.py
@@ -0,0 +1,66 @@
+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 IntegrationsTabs(SideTabWidget):
+ def __init__(self, parent=None):
+ 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 = 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.eos_ubisoft = IntegrationsWidget(
+ None,
+ self.tr(""),
+ self,
+ )
+ self.eos_ubisoft.addWidget(UbisoftGroup(self.eos_ubisoft))
+ self.eos_ubisoft.addWidget(EOSGroup(self.eos_ubisoft))
+ self.addTab(self.eos_ubisoft, self.tr("Epic Overlay and Ubisoft"))
+
+ self.tabBar().setCurrentIndex(1)
+
+ def show_import(self):
+ self.setCurrentIndex(1)
+
+ def show_egl_sync(self):
+ self.setCurrentIndex(2)
+
+ def show_eos_ubisoft(self):
+ self.setCurrentIndex(3)
+
+
+class IntegrationsWidget(QWidget):
+ def __init__(self, widget: Optional[QWidget], info: str, parent=None):
+ super(IntegrationsWidget, self).__init__(parent=parent)
+ self.info = QLabel(f"{info}")
+
+ layout = QVBoxLayout()
+ 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/games/import_sync/egl_sync_group.py b/rare/components/tabs/games/integrations/egl_sync_group.py
similarity index 87%
rename from rare/components/tabs/games/import_sync/egl_sync_group.py
rename to rare/components/tabs/games/integrations/egl_sync_group.py
index 79d3ab4d..f1ecdc97 100644
--- a/rare/components/tabs/games/import_sync/egl_sync_group.py
+++ b/rare/components/tabs/games/integrations/egl_sync_group.py
@@ -4,17 +4,17 @@ 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.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
-from rare.utils.models import PathSpec
from rare.utils.misc import WineResolver
+from rare.utils.models import PathSpec
logger = getLogger("EGLSync")
@@ -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/components/tabs/settings/widgets/eos.py b/rare/components/tabs/games/integrations/eos_group.py
similarity index 89%
rename from rare/components/tabs/settings/widgets/eos.py
rename to rare/components/tabs/games/integrations/eos_group.py
index 45a5b96a..30f7a034 100644
--- a/rare/components/tabs/settings/widgets/eos.py
+++ b/rare/components/tabs/games/integrations/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 rare.ui.components.tabs.games.integrations.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/games/import_sync/import_group.py b/rare/components/tabs/games/integrations/import_group.py
similarity index 93%
rename from rare/components/tabs/games/import_sync/import_group.py
rename to rare/components/tabs/games/integrations/import_group.py
index 29a17ff5..806b74fc 100644
--- a/rare/components/tabs/games/import_sync/import_group.py
+++ b/rare/components/tabs/games/integrations/import_group.py
@@ -10,11 +10,11 @@ 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.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
@@ -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()
diff --git a/rare/components/tabs/settings/widgets/ubisoft_activation.py b/rare/components/tabs/games/integrations/ubisoft_group.py
similarity index 92%
rename from rare/components/tabs/settings/widgets/ubisoft_activation.py
rename to rare/components/tabs/games/integrations/ubisoft_group.py
index 028d3c5c..f58a7431 100644
--- a/rare/components/tabs/settings/widgets/ubisoft_activation.py
+++ b/rare/components/tabs/games/integrations/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/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/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/ui/components/tabs/games/import_sync/__init__.py b/rare/lgndr/downloader/__init__.py
similarity index 100%
rename from rare/ui/components/tabs/games/import_sync/__init__.py
rename to rare/lgndr/downloader/__init__.py
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/resources/stylesheets/ChildOfMetropolis/__init__.py b/rare/resources/stylesheets/ChildOfMetropolis/__init__.py
index 0fc74bf6..5e825b3c 100644
Binary files a/rare/resources/stylesheets/ChildOfMetropolis/__init__.py and b/rare/resources/stylesheets/ChildOfMetropolis/__init__.py differ
diff --git a/rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss b/rare/resources/stylesheets/ChildOfMetropolis/stylesheet.qss
index 8d84174f..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,
@@ -115,15 +116,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 +381,7 @@ QTableView::indicator {
border-style: solid;
background-color: #C2C4C5;
}
+QGroupBox::indicator,
QCheckBox::indicator,
QRadioButton::indicator,
QListView::indicator,
@@ -391,6 +390,9 @@ QTableView::indicator {
width: 11px;
height: 11px;
}
+QGroupBox::indicator {
+ padding: 1px;
+}
QGroupBox::indicator:disabled,
QCheckBox::indicator:disabled,
QRadioButton::indicator:disabled,
@@ -482,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 63d76ed0..c1f610f0 100644
Binary files a/rare/resources/stylesheets/RareStyle/__init__.py and b/rare/resources/stylesheets/RareStyle/__init__.py differ
diff --git a/rare/resources/stylesheets/RareStyle/stylesheet.qss b/rare/resources/stylesheets/RareStyle/stylesheet.qss
index e04063c3..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,
@@ -115,15 +116,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 +381,7 @@ QTableView::indicator {
border-style: solid;
background-color: rgb( 32, 34, 37);
}
+QGroupBox::indicator,
QCheckBox::indicator,
QRadioButton::indicator,
QListView::indicator,
@@ -391,6 +390,9 @@ QTableView::indicator {
width: 11px;
height: 11px;
}
+QGroupBox::indicator {
+ padding: 0px;
+}
QGroupBox::indicator:disabled,
QCheckBox::indicator:disabled,
QRadioButton::indicator:disabled,
@@ -482,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);
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/ui/components/tabs/games/integrations/__init__.py b/rare/ui/components/tabs/games/integrations/__init__.py
new file mode 100644
index 00000000..e69de29b
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/integrations/eos_widget.py b/rare/ui/components/tabs/games/integrations/eos_widget.py
new file mode 100644
index 00000000..666d5a87
--- /dev/null
+++ b/rare/ui/components/tabs/games/integrations/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/integrations/eos_widget.ui b/rare/ui/components/tabs/games/integrations/eos_widget.ui
new file mode 100644
index 00000000..7a70d318
--- /dev/null
+++ b/rare/ui/components/tabs/games/integrations/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/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
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
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
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
diff --git a/rare/widgets/collabsible_widget.py b/rare/widgets/collabsible_widget.py
deleted file mode 100644
index f9f2280e..00000000
--- a/rare/widgets/collabsible_widget.py
+++ /dev/null
@@ -1,85 +0,0 @@
-from PyQt5.QtCore import QParallelAnimationGroup, Qt, QPropertyAnimation, QAbstractAnimation
-from PyQt5.QtWidgets import QWidget, QFrame, QToolButton, QGridLayout, QSizePolicy, QLayout
-
-from rare.utils.misc import icon
-
-# https://newbedev.com/how-to-make-an-expandable-collapsable-section-widget-in-qt
-
-
-class CollabsibleWidget(QWidget):
- def __init__(
- self, child_layout: QLayout = 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(CollabsibleWidget, self).__init__(parent=parent)
-
- self.animationDuration = animation_duration
- self.toggleAnimation = QParallelAnimationGroup()
- self.contentArea = QWidget()
- self.headerLine = QFrame()
- self.toggleButton = QToolButton()
- self.mainLayout = QGridLayout()
-
- toggleButton = self.toggleButton
- toggleButton.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
- toggleButton.setIcon(icon("fa.arrow-right"))
- toggleButton.setText(str(title))
- toggleButton.setCheckable(True)
- toggleButton.setChecked(False)
-
- headerLine = self.headerLine
- headerLine.setFrameShape(QFrame.StyledPanel)
- headerLine.setFrameShadow(QFrame.Plain)
- headerLine.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum)
-
- 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"))
- # 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)
-
- 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.toggleButton.clicked.connect(start_animation)
-
- if child_layout:
- self.setContentLayout(child_layout)
-
- 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)
diff --git a/rare/widgets/collapsible_widget.py b/rare/widgets/collapsible_widget.py
new file mode 100644
index 00000000..dd0c7cae
--- /dev/null
+++ b/rare/widgets/collapsible_widget.py
@@ -0,0 +1,238 @@
+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
+
+
+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, CollapsibleBase):
+ def __init__(
+ self, widget: QWidget = None, title: str = "", button_text: str = "", animation_duration: int = 200, parent=None
+ ):
+ super(CollapsibleFrame, self).__init__(parent=parent)
+ self.setup(animation_duration)
+ self.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)
+
+ 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)
+
+ self.title_label = QLabel(title)
+ font = self.title_label.font()
+ font.setBold(True)
+ 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.title_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)
+
+ self.toggle_button.clicked.connect(self.animationStart)
+
+ 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")
+ self.toggle_button.setIcon(arrow_type)
+ super(CollapsibleFrame, self).animationStart(checked)
+
+
+class CollapsibleGroupBox(QGroupBox, CollapsibleBase):
+ def __init__(
+ self, widget: QWidget = None, title: str = "", animation_duration: int = 200, parent=None
+ ):
+ super(CollapsibleGroupBox, self).__init__(parent=parent)
+ self.setup(animation_duration)
+ self.setTitle(title)
+ self.setCheckable(True)
+ self.setChecked(False)
+
+ # 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.toggled.connect(self.animationStart)
+
+ if widget is not None:
+ self.setWidget(widget)
+
+ def isChecked(self) -> bool:
+ return super(CollapsibleGroupBox, self).isChecked()
+
+ 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
+ from rare.ui.components.dialogs.install_dialog_advanced import Ui_InstallDialogAdvanced
+ from rare.utils.misc import set_style_sheet
+ from rare.resources.stylesheets import RareStyle
+ 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_frame(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)
+
+ 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)
+ dialog.layout().addWidget(collapsible_frame)
+ dialog.layout().addWidget(collapsible_group)
+ dialog.layout().setSizeConstraint(QVBoxLayout.SetFixedSize)
+ dialog.show()
+ sys.exit(app.exec_())
+
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")