diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 00000000..a04c5174
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,11 @@
+[tool.black]
+line-length = 110
+target-version = ['py39', 'py310']
+include = '\.py$'
+force-exclude = '''
+/(
+ | rare/ui
+ | rare/legendary
+ | rare/resources
+)/
+'''
diff --git a/rare/app.py b/rare/app.py
index a8db08dd..d78fd3b5 100644
--- a/rare/app.py
+++ b/rare/app.py
@@ -68,7 +68,7 @@ class App(QApplication):
# init Legendary
try:
- self.core = LegendaryCoreSingleton()
+ self.core = LegendaryCoreSingleton(init=True)
except configparser.MissingSectionHeaderError as e:
logger.warning(f"Config is corrupt: {e}")
if config_path := os.environ.get("XDG_CONFIG_HOME"):
@@ -77,7 +77,7 @@ class App(QApplication):
path = os.path.expanduser("~/.config/legendary")
with open(os.path.join(path, "config.ini"), "w") as config_file:
config_file.write("[Legendary]")
- self.core = LegendaryCoreSingleton()
+ self.core = LegendaryCoreSingleton(init=True)
if "Legendary" not in self.core.lgd.config.sections():
self.core.lgd.config.add_section("Legendary")
self.core.lgd.save_config()
@@ -101,7 +101,7 @@ class App(QApplication):
self.setOrganizationName("Rare")
self.settings = QSettings()
- self.signals = GlobalSignalsSingleton()
+ self.signals = GlobalSignalsSingleton(init=True)
self.signals.exit_app.connect(self.exit_app)
self.signals.send_notification.connect(
diff --git a/rare/components/dialogs/install_dialog.py b/rare/components/dialogs/install_dialog.py
index ca3496bd..fb99f448 100644
--- a/rare/components/dialogs/install_dialog.py
+++ b/rare/components/dialogs/install_dialog.py
@@ -141,11 +141,9 @@ class InstallDialog(QDialog, Ui_InstallDialog):
if self.dl_item.options.overlay:
self.platform_label.setVisible(False)
self.platform_combo_box.setVisible(False)
- self.ignore_space_info_label.setVisible(False)
self.ignore_space_check.setVisible(False)
self.ignore_space_label.setVisible(False)
self.download_only_check.setVisible(False)
- self.download_only_info_label.setVisible(False)
self.download_only_label.setVisible(False)
self.shortcut_cb.setVisible(False)
self.shortcut_lbl.setVisible(False)
@@ -306,16 +304,16 @@ class InstallDialog(QDialog, Ui_InstallDialog):
self.cancel_clicked()
-class InstallInfoSignals(QObject):
- result = pyqtSignal(InstallDownloadModel)
- failed = pyqtSignal(str)
- finished = pyqtSignal()
-
-
class InstallInfoWorker(QRunnable):
+
+ class Signals(QObject):
+ result = pyqtSignal(InstallDownloadModel)
+ failed = pyqtSignal(str)
+ finished = pyqtSignal()
+
def __init__(self, core: LegendaryCore, dl_item: InstallQueueItemModel, game: Game = None):
super(InstallInfoWorker, self).__init__()
- self.signals = InstallInfoSignals()
+ self.signals = InstallInfoWorker.Signals()
self.core = core
self.dl_item = dl_item
self.is_overlay_install = self.dl_item.options.overlay
diff --git a/rare/components/dialogs/launch_dialog.py b/rare/components/dialogs/launch_dialog.py
index 4a903dfe..b79acdc1 100644
--- a/rare/components/dialogs/launch_dialog.py
+++ b/rare/components/dialogs/launch_dialog.py
@@ -23,11 +23,11 @@ class LaunchDialogSignals(QObject):
class ImageWorker(QRunnable):
- def __init__(self, core: LegendaryCore):
+ def __init__(self):
super(ImageWorker, self).__init__()
self.signals = LaunchDialogSignals()
self.setAutoDelete(True)
- self.core = core
+ self.core = LegendaryCoreSingleton()
def run(self):
download_images(self.signals.image_progress, self.signals.result, self.core)
@@ -45,16 +45,16 @@ class ApiRequestWorker(QRunnable):
def run(self) -> None:
if self.settings.value("mac_meta", platform.system() == "Darwin", bool):
try:
- result = self.core.get_game_and_dlc_list(True, "Mac")
+ result = self.core.get_game_and_dlc_list(update_assets=True, platform="Mac")
except HTTPError:
result = [], {}
- self.signals.result.emit(result, "mac")
else:
- self.signals.result.emit(([], {}), "mac")
+ result = [], {}
+ self.signals.result.emit(result, "mac")
if self.settings.value("win32_meta", False, bool):
try:
- result = self.core.get_game_and_dlc_list(True, "Win32")
+ result = self.core.get_game_and_dlc_list(update_assets=True, platform="Win32")
except HTTPError:
result = [], {}
else:
@@ -65,7 +65,7 @@ class ApiRequestWorker(QRunnable):
class LaunchDialog(QDialog, Ui_LaunchDialog):
quit_app = pyqtSignal(int)
start_app = pyqtSignal()
- finished = 0
+ completed = 0
def __init__(self, parent=None):
super(LaunchDialog, self).__init__(parent=parent)
@@ -76,8 +76,7 @@ class LaunchDialog(QDialog, Ui_LaunchDialog):
self.core = LegendaryCoreSingleton()
self.args = ArgumentsSingleton()
- self.thread_pool = QThreadPool()
- self.thread_pool.setMaxThreadCount(2)
+ self.thread_pool = QThreadPool().globalInstance()
self.api_results = ApiResults()
def login(self):
@@ -113,15 +112,15 @@ class LaunchDialog(QDialog, Ui_LaunchDialog):
if not self.args.offline:
self.image_info.setText(self.tr("Downloading Images"))
- image_worker = ImageWorker(self.core)
+ image_worker = ImageWorker()
image_worker.signals.image_progress.connect(self.update_image_progbar)
image_worker.signals.result.connect(self.handle_api_worker_result)
self.thread_pool.start(image_worker)
# gamelist and no_asset games are from Image worker
- worker = ApiRequestWorker()
- worker.signals.result.connect(self.handle_api_worker_result)
- self.thread_pool.start(worker)
+ api_worker = ApiRequestWorker()
+ api_worker.signals.result.connect(self.handle_api_worker_result)
+ self.thread_pool.start(api_worker)
# cloud save from another worker, because it is used in cloud_save_utils too
cloud_worker = CloudWorker()
@@ -131,7 +130,7 @@ class LaunchDialog(QDialog, Ui_LaunchDialog):
self.thread_pool.start(cloud_worker)
else:
- self.finished = 2
+ self.completed = 2
if self.core.lgd.assets:
(
self.api_results.game_list,
@@ -183,10 +182,10 @@ class LaunchDialog(QDialog, Ui_LaunchDialog):
self.finish()
def finish(self):
- if self.finished == 1:
+ if self.completed == 1:
logger.info("App starting")
self.image_info.setText(self.tr("Starting..."))
ApiResultsSingleton(self.api_results)
self.start_app.emit()
else:
- self.finished += 1
+ self.completed += 1
diff --git a/rare/components/extra/console.py b/rare/components/extra/console.py
index 70551efb..c24f83a1 100644
--- a/rare/components/extra/console.py
+++ b/rare/components/extra/console.py
@@ -1,32 +1,52 @@
+from PyQt5.QtCore import QProcessEnvironment
from PyQt5.QtGui import QTextCursor, QFont
from PyQt5.QtWidgets import (
QPlainTextEdit,
- QWidget,
+ QDialog,
QPushButton,
QFileDialog,
QVBoxLayout,
+ QHBoxLayout,
+ QSpacerItem,
+ QSizePolicy, QTableWidgetItem, QHeaderView,
)
+from rare.ui.components.extra.console_env import Ui_ConsoleEnv
-class ConsoleWindow(QWidget):
- def __init__(self):
- super(ConsoleWindow, self).__init__()
- self.layout = QVBoxLayout()
- self.setWindowTitle("Rare Console")
+
+class Console(QDialog):
+ env: QProcessEnvironment
+
+ def __init__(self, parent=None):
+ super(Console, self).__init__(parent=parent)
+ self.setWindowTitle("Rare - Console")
self.setGeometry(0, 0, 600, 400)
+ layout = QVBoxLayout()
- self.console = Console()
- self.layout.addWidget(self.console)
+ self.console = ConsoleEdit(self)
+ layout.addWidget(self.console)
+
+ button_layout = QHBoxLayout()
+ button_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Fixed))
+
+ self.env_button = QPushButton(self.tr("Show environment"))
+ button_layout.addWidget(self.env_button)
+ self.env_button.clicked.connect(self.show_env)
self.save_button = QPushButton(self.tr("Save output to file"))
- self.layout.addWidget(self.save_button)
+ button_layout.addWidget(self.save_button)
self.save_button.clicked.connect(self.save)
- self.clear_button = QPushButton(self.tr("Clear"))
- self.layout.addWidget(self.clear_button)
+ self.clear_button = QPushButton(self.tr("Clear console"))
+ button_layout.addWidget(self.clear_button)
self.clear_button.clicked.connect(self.console.clear)
- self.setLayout(self.layout)
+ layout.addLayout(button_layout)
+
+ self.setLayout(layout)
+
+ self.env_variables = ConsoleEnv(self)
+ self.env_variables.hide()
def save(self):
file, ok = QFileDialog.getSaveFileName(
@@ -40,6 +60,13 @@ class ConsoleWindow(QWidget):
f.close()
self.save_button.setText(self.tr("Saved"))
+ def set_env(self, env: QProcessEnvironment):
+ self.env = env
+
+ def show_env(self):
+ self.env_variables.setTable(self.env)
+ self.env_variables.show()
+
def log(self, text: str, end: str = "\n"):
self.console.log(text + end)
@@ -47,9 +74,27 @@ class ConsoleWindow(QWidget):
self.console.error(text + end)
-class Console(QPlainTextEdit):
- def __init__(self):
- super().__init__()
+class ConsoleEnv(QDialog):
+
+ def __init__(self, parent=None):
+ super(ConsoleEnv, self).__init__(parent=parent)
+ self.ui = Ui_ConsoleEnv()
+ self.ui.setupUi(self)
+
+ def setTable(self, env: QProcessEnvironment):
+ self.ui.table.clearContents()
+ self.ui.table.setRowCount(len(env.keys()))
+
+ for idx, key in enumerate(env.keys()):
+ self.ui.table.setItem(idx, 0, QTableWidgetItem(env.keys()[idx]))
+ self.ui.table.setItem(idx, 1, QTableWidgetItem(env.value(env.keys()[idx])))
+
+ self.ui.table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
+
+
+class ConsoleEdit(QPlainTextEdit):
+ def __init__(self, parent=None):
+ super(ConsoleEdit, self).__init__(parent=parent)
self.setReadOnly(True)
self.setFont(QFont("monospace"))
self._cursor_output = self.textCursor()
diff --git a/rare/components/tabs/games/game_utils.py b/rare/components/tabs/games/game_utils.py
index f6412334..b5f22b92 100644
--- a/rare/components/tabs/games/game_utils.py
+++ b/rare/components/tabs/games/game_utils.py
@@ -11,7 +11,7 @@ from PyQt5.QtWidgets import QMessageBox, QPushButton
from legendary.models.game import LaunchParameters, InstalledGame
from rare.components.dialogs.uninstall_dialog import UninstallDialog
-from rare.components.extra.console import ConsoleWindow
+from rare.components.extra.console import Console
from rare.components.tabs.games import CloudSaveUtils
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton
from rare.utils import legendary_utils
@@ -58,7 +58,7 @@ class GameUtils(QObject):
self.signals = GlobalSignalsSingleton()
self.args = ArgumentsSingleton()
- self.console = ConsoleWindow()
+ self.console = Console()
self.cloud_save_utils = CloudSaveUtils()
self.cloud_save_utils.sync_finished.connect(self.sync_finished)
self.game_meta = RareGameMeta()
@@ -245,7 +245,7 @@ class GameUtils(QObject):
def _launch_pre_command(self, env: dict):
proc = QProcess()
- environment = QProcessEnvironment()
+ environment = QProcessEnvironment().systemEnvironment()
for e in env:
environment.insert(e, env[e])
proc.setProcessEnvironment(environment)
@@ -260,12 +260,13 @@ class GameUtils(QObject):
str(proc.readAllStandardError().data(), "utf-8", "ignore")
)
)
+ self.console.set_env(environment)
return proc
def _get_process(self, app_name, env):
process = GameProcess(app_name)
- environment = QProcessEnvironment()
+ environment = QProcessEnvironment().systemEnvironment()
for e in env:
environment.insert(e, env[e])
process.setProcessEnvironment(environment)
@@ -287,6 +288,7 @@ class GameUtils(QObject):
and QSettings().value("show_console", False, bool))
else None
)
+ self.console.set_env(environment)
return process
def _launch_origin(self, app_name, process: QProcess):
diff --git a/rare/components/tabs/games/head_bar.py b/rare/components/tabs/games/head_bar.py
index ba104333..77085442 100644
--- a/rare/components/tabs/games/head_bar.py
+++ b/rare/components/tabs/games/head_bar.py
@@ -19,7 +19,6 @@ class GameListHeadBar(QWidget):
def __init__(self, parent=None):
super(GameListHeadBar, self).__init__(parent=parent)
self.api_results = ApiResultsSingleton()
- self.setLayout(QHBoxLayout())
# self.installed_only = QCheckBox(self.tr("Installed only"))
self.settings = QSettings()
# self.installed_only.setChecked(self.settings.value("installed_only", False, bool))
@@ -32,7 +31,6 @@ class GameListHeadBar(QWidget):
self.tr("Installed only"),
self.tr("Offline Games"),
])
- self.layout().addWidget(self.filter)
self.available_filters = [
"all",
@@ -61,40 +59,43 @@ class GameListHeadBar(QWidget):
self.filter.setCurrentIndex(0)
self.filter.currentIndexChanged.connect(self.filter_changed)
- self.layout().addStretch(1)
self.import_game = QPushButton(icon("mdi.import", "fa.arrow-down"), self.tr("Import Game"))
self.import_clicked = self.import_game.clicked
- self.layout().addWidget(self.import_game)
self.egl_sync = QPushButton(icon("mdi.sync", "fa.refresh"), self.tr("Sync with EGL"))
self.egl_sync_clicked = self.egl_sync.clicked
- self.layout().addWidget(self.egl_sync)
# FIXME: Until it is ready
# self.egl_sync.setEnabled(False)
- self.layout().addStretch(1)
-
icon_label = QLabel()
icon_label.setPixmap(icon("fa.search").pixmap(QSize(20, 20)))
- self.layout().addWidget(icon_label)
self.search_bar = QLineEdit()
self.search_bar.setObjectName("search_bar")
self.search_bar.setFrame(False)
self.search_bar.setMinimumWidth(200)
self.search_bar.setPlaceholderText(self.tr("Search Game"))
- self.layout().addWidget(self.search_bar)
- self.layout().addStretch(2)
checked = QSettings().value("icon_view", True, bool)
self.view = SelectViewWidget(checked)
- self.layout().addWidget(self.view)
- self.layout().addStretch(1)
self.refresh_list = QPushButton()
self.refresh_list.setIcon(icon("fa.refresh")) # Reload icon
- self.layout().addWidget(self.refresh_list)
+
+ layout = QHBoxLayout()
+ layout.addWidget(self.filter)
+ layout.addStretch(1)
+ layout.addWidget(self.import_game)
+ layout.addWidget(self.egl_sync)
+ layout.addStretch(1)
+ layout.addWidget(icon_label)
+ layout.addWidget(self.search_bar)
+ layout.addStretch(3)
+ layout.addWidget(self.view)
+ layout.addStretch(1)
+ layout.addWidget(self.refresh_list)
+ self.setLayout(layout)
def filter_changed(self, i):
self.filterChanged.emit(self.available_filters[i])
diff --git a/rare/components/tabs/games/import_sync/import_group.py b/rare/components/tabs/games/import_sync/import_group.py
index e296d6e7..fa5e52a1 100644
--- a/rare/components/tabs/games/import_sync/import_group.py
+++ b/rare/components/tabs/games/import_sync/import_group.py
@@ -1,7 +1,8 @@
import json
import os
from logging import getLogger
-from typing import List, Tuple
+from pathlib import Path
+from typing import List, Tuple, Optional
from PyQt5.QtCore import Qt, QModelIndex, pyqtSignal
from PyQt5.QtGui import QStandardItemModel
@@ -21,9 +22,7 @@ class AppNameCompleter(QCompleter):
def __init__(self, app_names: List, parent=None):
super(AppNameCompleter, self).__init__(parent)
# pylint: disable=E1136
- super(AppNameCompleter, self).activated[QModelIndex].connect(
- self.__activated_idx
- )
+ super(AppNameCompleter, self).activated[QModelIndex].connect(self.__activated_idx)
model = QStandardItemModel(len(app_names), 2)
for idx, game in enumerate(app_names):
@@ -52,18 +51,17 @@ class AppNameCompleter(QCompleter):
# lk: Note to self, the completer and popup models are different.
# lk: Getting the index from the popup and trying to use it in the completer will return invalid results
if isinstance(idx, QModelIndex):
- self.activated.emit(
- self.popup().model().data(self.popup().model().index(idx.row(), 1))
- )
+ self.activated.emit(self.popup().model().data(self.popup().model().index(idx.row(), 1)))
# TODO: implement conversion from app_name to app_title (signal loop here)
# if isinstance(idx_str, str):
# self.activated.emit(idx_str)
-class ImportGroup(QGroupBox, Ui_ImportGroup):
+class ImportGroup(QGroupBox):
def __init__(self, parent=None):
super(ImportGroup, self).__init__(parent=parent)
- self.setupUi(self)
+ self.ui = Ui_ImportGroup()
+ self.ui.setupUi(self)
self.core = LegendaryCoreSingleton()
self.signals = GlobalSignalsSingleton()
self.api_results = ApiResultsSingleton()
@@ -84,23 +82,32 @@ class ImportGroup(QGroupBox, Ui_ImportGroup):
parent=self,
)
self.path_edit.textChanged.connect(self.path_changed)
- self.path_edit_layout.addWidget(self.path_edit)
+ self.ui.path_edit_layout.addWidget(self.path_edit)
- self.app_name = IndicatorLineEdit(
+ self.app_name_edit = IndicatorLineEdit(
placeholder=self.tr("Use in case the app name was not found automatically"),
completer=AppNameCompleter(
- app_names=[
- (i.app_name, i.app_title) for i in self.api_results.game_list
- ]
+ app_names=[(i.app_name, i.app_title) for i in self.api_results.game_list]
),
edit_func=self.app_name_edit_cb,
parent=self,
)
- self.app_name.textChanged.connect(self.app_name_changed)
- self.app_name_layout.addWidget(self.app_name)
+ self.app_name_edit.textChanged.connect(self.app_name_changed)
+ self.ui.app_name_layout.addWidget(self.app_name_edit)
- self.import_button.setEnabled(False)
- self.import_button.clicked.connect(self.import_game)
+ self.ui.import_button.setEnabled(False)
+ self.ui.import_button.clicked.connect(
+ lambda: self.import_games(self.path_edit.text())
+ if self.ui.import_folder_check.isChecked()
+ else self.import_game(self.path_edit.text())
+ )
+
+ self.ui.import_folder_check.stateChanged.connect(
+ lambda s: self.ui.import_button.setEnabled(s or (not s and self.app_name_edit.is_valid))
+ )
+ self.ui.import_folder_check.stateChanged.connect(
+ lambda s: self.app_name_edit.setEnabled(not s)
+ )
def path_edit_cb(self, path) -> Tuple[bool, str, str]:
if os.path.exists(path):
@@ -113,11 +120,12 @@ class ImportGroup(QGroupBox, Ui_ImportGroup):
return False, path, ""
def path_changed(self, path):
- self.info_label.setText(str())
+ self.ui.info_label.setText(str())
+ self.ui.import_folder_check.setChecked(False)
if self.path_edit.is_valid:
- self.app_name.setText(self.find_app_name(path))
+ self.app_name_edit.setText(self.find_app_name(path))
else:
- self.app_name.setText(str())
+ self.app_name_edit.setText(str())
def app_name_edit_cb(self, text) -> Tuple[bool, str, str]:
if not text:
@@ -128,56 +136,59 @@ class ImportGroup(QGroupBox, Ui_ImportGroup):
return False, text, IndicatorLineEdit.reasons.game_not_installed
def app_name_changed(self, text):
- self.info_label.setText(str())
- if self.app_name.is_valid:
- self.import_button.setEnabled(True)
+ self.ui.info_label.setText(str())
+ if self.app_name_edit.is_valid:
+ self.ui.import_button.setEnabled(True)
else:
- self.import_button.setEnabled(False)
+ self.ui.import_button.setEnabled(False)
- def find_app_name(self, path):
- if not os.path.exists(os.path.join(path, ".egstore")):
- return None
- for i in os.listdir(os.path.join(path, ".egstore")):
- if i.endswith(".mancpn"):
- file = os.path.join(path, ".egstore", i)
- return json.load(open(file, "r")).get("AppName")
+ def find_app_name(self, path: str) -> Optional[str]:
+ if os.path.exists(os.path.join(path, ".egstore")):
+ for i in os.listdir(os.path.join(path, ".egstore")):
+ if i.endswith(".mancpn"):
+ file = os.path.join(path, ".egstore", i)
+ return json.load(open(file, "r")).get("AppName")
+ elif app_name := legendary_utils.resolve_aliases(
+ self.core, os.path.basename(os.path.normpath(path))):
+ return app_name
else:
- logger.warning("File was not found")
- return None
+ logger.warning(f"Could not find AppName for {path}")
+ return None
def import_game(self, path=None):
- app_name = self.app_name.text()
if not path:
path = self.path_edit.text()
- if not app_name:
+ if not (app_name := self.app_name_edit.text()):
# try to find app name
if a_n := self.find_app_name(path):
app_name = a_n
else:
- self.info_label.setText(self.tr("Could not find app name"))
+ self.ui.info_label.setText(self.tr("Could not find AppName"))
return
+ self.__import_game(app_name, path)
- if not (
- err := legendary_utils.import_game(self.core, app_name=app_name, path=path)
- ):
+ def import_games(self, path=None):
+ if not path:
+ path = self.path_edit.text()
+ path = Path(path)
+ for child in path.iterdir():
+ if child.is_dir():
+ if (app_name := self.find_app_name(str(child))) is not None:
+ self.__import_game(app_name, str(child))
+
+ def __import_game(self, app_name, path):
+ if not (err := legendary_utils.import_game(self.core, app_name=app_name, path=path)):
igame = self.core.get_installed_game(app_name)
- self.info_label.setText(
- self.tr("Successfully imported {}").format(igame.title)
- )
- self.app_name.setText(str())
+ logger.info(f"Successfully imported {igame.title}")
+ self.ui.info_label.setText(self.tr("Successfully imported {}").format(igame.title))
self.signals.update_gamelist.emit([app_name])
- if (
- igame.version
- != self.core.get_asset(app_name, igame.platform, False).build_version
- ):
+ if igame.version != self.core.get_asset(app_name, igame.platform, False).build_version:
# update available
self.signals.add_download.emit(igame.app_name)
self.signals.update_download_tab_text.emit()
else:
logger.warning(f'Failed to import "{app_name}"')
- self.info_label.setText(
- self.tr("Could not import {}: {}").format(app_name, err)
- )
+ self.ui.info_label.setText(self.tr("Could not import {}: {}").format(app_name, err))
return
diff --git a/rare/components/tabs/settings/widgets/eos.py b/rare/components/tabs/settings/widgets/eos.py
index 28bbad87..81cfb762 100644
--- a/rare/components/tabs/settings/widgets/eos.py
+++ b/rare/components/tabs/settings/widgets/eos.py
@@ -202,9 +202,11 @@ class EosWidget(QGroupBox, Ui_EosWidget):
def install_overlay(self, update=False):
if platform.system() != "Windows":
- if QMessageBox.No == QMessageBox.question(self, "Warning",
- self.tr("Epic overlay is currently not supported by wine, so it won't work. Install anyway? "),
- QMessageBox.Yes | QMessageBox.No, QMessageBox.No):
+ if QMessageBox.No == QMessageBox.question(
+ self,
+ self.tr("Warning"),
+ self.tr("Epic overlay is currently not supported by wine, so it won't work. Install anyway? "),
+ QMessageBox.Yes | QMessageBox.No, QMessageBox.No):
return
base_path = os.path.expanduser("~/legendary/.overlay")
diff --git a/rare/resources/resources.py b/rare/resources/resources.py
index 391f9176..3f35740f 100644
Binary files a/rare/resources/resources.py and b/rare/resources/resources.py differ
diff --git a/rare/resources/stylesheets/RareStyle/stylesheet.qss b/rare/resources/stylesheets/RareStyle/stylesheet.qss
index 5683ae8d..25a94baa 100644
--- a/rare/resources/stylesheets/RareStyle/stylesheet.qss
+++ b/rare/resources/stylesheets/RareStyle/stylesheet.qss
@@ -1,42 +1,44 @@
/*
[Text]
-normal: #eeeeee -- main font color
-disabled: #43474d -- disabled font color
-
+normal: #eeeeee rgb(238, 238, 238) -- main font color
+disabled: #43474d rgb( 67, 71, 77) -- disabled font color
+ rgba( 67, 71, 77, 55%) == rgb( 51, 54, 59)
+ rgba( 67, 71, 77, 25%) == rgb( 41, 43, 47)
[Background]
-normal: #202225 -- main background color
-editable: #333344 -- background color for reactive/editable widgets (TextEdits, ProgressBars etc)
-hover: #222233 -- background color when hovering over reactive widgets (Buttons, Headers)
-selection: #2f4f4f -- background color for selectable widgets
-alternate: #282a2e -- background color for alternating rows in List/Tree/TableViews and for ScrollBars
+normal: #202225 rgb( 32, 34, 37) -- main background color
+editable: #333344 rgb( 51, 51, 68) -- background color for reactive/editable widgets (TextEdits, ProgressBars etc)
+hover: #222233 rgb( 34, 34, 51) -- background color when hovering over reactive widgets (Buttons, Headers)
+selection: #2f4f4f rgb( 47, 79, 79) -- background color for selectable widgets
+alternate: #282a2e rgb( 40, 42, 46) -- background color for alternating rows in List/Tree/TableViews and for ScrollBars
[Border]
-normal: #483d8b -- border color for most widgets
-editable: #2f4f4f -- border color for editable widgets (TextEdits, ProgressBars etc)
-highlight: #5246a0 -- border color for dropdown widgets, a bit lighter than border for more separation
-disabled: #43474d -- border for disabled widgets
-alternate: #3c3f41 -- border color for gradient backgrounds on widgets like Tabs and Popups
+normal: #483d8b rgb( 72, 61, 139) -- border color for most widgets
+ rgba( 72, 61, 139, 25%) == rgb( 42, 40, 63)
+editable: #2f4f4f rgb( 47, 79, 79) -- border color for editable widgets (TextEdits, ProgressBars etc)
+highlight: #5246a0 rgb( 82, 70, 160) -- border color for dropdown widgets, a bit lighter than border for more separation
+disabled: #43474d rgb( 67, 71, 77) -- border for disabled widgets
+alternate: #3c3f41 rgb( 60, 63, 65) -- border color for gradient backgrounds on widgets like Tabs and Popups
[Special]
-info-normal: #bbb -- infoLabel
-install-normal: #090 -- install
-install-hover: #060 -- install
-install-disabled: #020 -- install
-uninstall-normal: #900 -- uninstall
-uninstall-hover: #600 -- uninstall
-uninstall-disabled: #200 -- uninstall
+info-normal: #bbb rgb(187, 187, 187) -- infoLabel
+install-normal: #070 rgb( 0, 119, 0) -- install
+install-hover: #050 rgb( 0, 85, 0) -- install
+install-disabled: #020 rgb( 0, 34, 0) -- install
+uninstall-normal: #700 rgb(119, 0, 0) -- uninstall
+uninstall-hover: #500 rgb( 85, 0, 0) -- uninstall
+uninstall-disabled: #200 rgb( 34, 0, 0) -- uninstall
*/
* {
- color: #eeeeee;
- border-color: #483d8b;
- background-color: #202225;
+ color: rgb(238, 238, 238);
+ border-color: rgb( 72, 61, 139);
+ background-color: rgb( 32, 34, 37);
}
*:disabled,
*:editable:disabled {
- color: #43474d;
- border-color: #43474d;
- background-color: #202225;
+ color: rgb( 67, 71, 77);
+ border-color: rgb( 67, 71, 77);
+ background-color: rgb( 32, 34, 37);
}
QLabel,
@@ -44,10 +46,10 @@ QLabel:disabled {
border-width: 0px;
background-color: transparent;
padding: 0px;
- selection-background-color: #2f4f4f;
+ selection-background-color: rgb( 47, 79, 79);
}
QLabel[infoLabel="1"] {
- color: #bbb;
+ color: rgb(187, 187, 187);
font-style: italic;
font-weight: normal;
}
@@ -94,9 +96,9 @@ QSpinBox,
QDoubleSpinBox,
QProgressBar,
QScrollBar {
- border-color: #2f4f4f;
- background-color: #333344;
- selection-background-color: #2f4f4f;
+ border-color: rgb( 47, 79, 79);
+ background-color: rgb( 51, 51, 68);
+ selection-background-color: rgb( 47, 79, 79);
}
QLineEdit,
QTextEdit,
@@ -123,17 +125,17 @@ QStackedWidget[noBorder="1"] {
border-color: transparent;
}
QComboBox {
- background-color: rgba(67, 71, 77, 55%);
+ background-color: rgb( 51, 54, 59);
}
QComboBox:disabled {
- background-color: rgba(67, 71, 77, 25%);
+ background-color: rgb( 41, 43, 47);
}
QComboBox:!editable:hover {
- background-color: #222233;
+ background-color: rgb( 34, 34, 51);
}
*::item:selected,
QComboBox QAbstractItemView {
- selection-background-color: #2f4f4f;
+ selection-background-color: rgb( 47, 79, 79);
}
*::drop-down,
*::drop-down:editable,
@@ -150,19 +152,19 @@ QComboBox QAbstractItemView {
*::drop-down:editable:disabled,
*::up-button:disabled,
*::down-button:disabled {
- border-color: #43474d;
+ border-color: rgb( 67, 71, 77);
background-color: transparent;
}
*::drop-down {
subcontrol-position: top right;
- border-color: #483d8b;
- border-left-color: #5246a0; /* #483d8b lighter */
+ border-color: rgb( 72, 61, 139);
+ border-left-color: rgb( 82, 70, 160); /* rgb( 72, 61, 139) lighter */
}
*::drop-down:editable,
*::up-button,
*::down-button {
- border-color: #2f4f4f;
- background-color: #3c3f41;
+ border-color: rgb( 47, 79, 79);
+ background-color: rgb( 60, 63, 65);
}
*::drop-down,
*::drop-down:editable {
@@ -189,12 +191,12 @@ QProgressBar {
QProgressBar::chunk {
width: 2%;
margin: 0%;
- background-color: #2f4f4f;
+ background-color: rgb( 47, 79, 79);
}
QScrollBar {
border-radius: 4px;
padding: 1px;
- background-color: #282a2e;
+ background-color: rgb( 40, 42, 46);
}
QScrollBar:vertical {
width: 11px;
@@ -229,8 +231,8 @@ QScrollBar::sub-line:horizontal {
QScrollBar::handle {
border-width: 1px;
border-style: solid;
- border-color: #483d8b;
- background-color: #333344;
+ border-color: rgb( 72, 61, 139);
+ background-color: rgb( 51, 51, 68);
border-radius: 2px;
min-height: 30px;
min-width: 30px;
@@ -259,11 +261,11 @@ QListView,
QTreeView,
QTableView {
outline: 0;
- gridline-color: #282a2e;
+ gridline-color: rgb( 40, 42, 46);
show-decoration-selected: 0;
selection-background-color: transparent;
- background-color: #202225;
- alternate-background-color: #282a2e;
+ background-color: rgb( 32, 34, 37);
+ alternate-background-color: rgb( 40, 42, 46);
}
QListView::item,
@@ -282,28 +284,28 @@ QTableView[currentRow="0"]::item {
QListView::item:hover,
QTreeView::item:hover,
QTableView::item:hover {
- border-color: #483d8b;
- background-color: #222233;
+ border-color: rgb( 72, 61, 139);
+ background-color: rgb( 34, 34, 51);
}
QListView::item:selected,
QTreeView::item:selected,
QTableView::item:selected {
- border-color: #483d8b;
- background-color: #2f4f4f;
+ border-color: rgb( 72, 61, 139);
+ background-color: rgb( 47, 79, 79);
}
QPushButton,
QToolButton {
- background-color: rgba(67, 71, 77, 55%);
+ background-color: rgb( 51, 54, 59);
}
QPushButton:disabled,
QToolButton:disabled {
- background-color: rgba(67, 71, 77, 25%);
+ background-color: rgb( 41, 43, 47);
}
QPushButton:hover,
QToolButton:hover,
QHeaderView::section:hover {
- background-color: #222233;
+ background-color: rgb( 34, 34, 51);
}
QPushButton,
QToolButton {
@@ -327,36 +329,36 @@ QPushButton#menu {
}
QPushButton#menu_button {
border-width: 0px;
- background-color: #3c3f41;
+ background-color: rgb( 60, 63, 65);
width: 18px;
height: 18px;
}
QPushButton#menu_button:hover {
- background-color: "#333344";
+ background-color: rgb( 51, 51, 68);
}
QPushButton[install="1"],
QPushButton#install_button {
- background-color: "#070";
+ background-color: rgb( 0, 119, 0);
}
QPushButton[install="1"]:hover,
QPushButton#install_button:hover {
- background-color: "#050";
+ background-color: rgb( 0, 85, 0);
}
QPushButton[install="1"]:disabled,
QPushButton#install_button:disabled {
- background-color: "#020";
+ background-color: rgb( 0, 34, 0);
}
QPushButton[uninstall="1"],
QPushButton#uninstall_button {
- background-color: "#900";
+ background-color: rgb(119, 0, 0);
}
QPushButton[uninstall="1"]:hover,
QPushButton#uninstall_button:hover {
- background-color: "#600";
+ background-color: rgb( 85, 0, 0);
}
QPushButton[uninstall="1"]:disabled,
QPushButton#uninstall_button:disabled {
- background-color: "#200";
+ background-color: rgb( 34, 0, 0);
}
QPushButton#success{
background-color: lime;
@@ -376,10 +378,10 @@ QRadioButton::indicator,
QListView::indicator,
QTreeView::indicator,
QTableView::indicator {
- border-color: #2f4f4f;
+ border-color: rgb( 47, 79, 79);
border-width: 1px;
border-style: solid;
- background-color: #202225;
+ background-color: rgb( 32, 34, 37);
}
QCheckBox::indicator,
QRadioButton::indicator,
@@ -395,7 +397,7 @@ QRadioButton::indicator:disabled,
QListView::indicator:disabled,
QTreeView::indicator:disabled,
QTableView::indicator:disabled {
- border-color: #43474d;
+ border-color: rgb( 67, 71, 77);
}
QRadioButton::indicator {
border-radius: 5%;
@@ -469,17 +471,20 @@ QGroupBox::title {
border-style: solid;
border-top-left-radius: 4px;
border-bottom-right-radius: 4px;
- border-color: #483d8b;
+ border-color: rgb( 72, 61, 139);
padding: 1px;
/*
background: qlineargradient(
- x1: -2, y1: 0, x2: 1, y2: 1, stop: 0 #483d8b, stop: 1 #202225);
+ x1: -2, y1: 0,
+ x2: 1, y2: 1,
+ stop: 0 rgb( 72, 61, 139),
+ stop: 1 rgb( 32, 34, 37));
*/
- background-color: rgba(72, 61, 139, 25%);
+ background-color: rgb( 42, 40, 63);
}
QGroupBox::title:disabled {
- border-color: #43474d;
- background-color: rgba(67, 71, 77, 25%);
+ border-color: rgb( 67, 71, 77);
+ background-color: rgb( 41, 43, 47);
}
QSizeGrip {
@@ -495,7 +500,7 @@ QSizeGrip {
#search_bar {
padding: 3px;
border-radius: 5px;
- background-color: "#333344";
+ background-color: rgb( 51, 51, 68);
}
QTabWidget::pane {
@@ -519,54 +524,66 @@ QTabBar::tab:bottom {
}
QTabBar::tab:top:hover,
QTabBar::tab:bottom:hover {
- border-color: #483d8b;
+ border-color: rgb( 72, 61, 139);
border-left-color: transparent;
border-right-color: transparent;
}
QTabBar::tab:top {
border-top-width: 3px;
- border-top-color: #3c3f41;
- border-bottom-color: #483d8b;
+ border-top-color: rgb( 60, 63, 65);
+ border-bottom-color: rgb( 72, 61, 139);
background: qlineargradient(
- x1: 0, y1: -1, x2: 0, y2: 1, stop: 0 #3c3f41, stop: 1 #202225);
+ x1: 0, y1: -1,
+ x2: 0, y2: 1,
+ stop: 0 rgb( 60, 63, 65),
+ stop: 1 rgb( 32, 34, 37));
}
QTabBar::tab:bottom {
border-bottom-width: 3px;
- border-top-color: #483d8b;
- border-bottom-color: #3c3f41;
+ border-top-color: rgb( 72, 61, 139);
+ border-bottom-color: rgb( 60, 63, 65);
background: qlineargradient(
- x1: 0, y1: 2, x2: 0, y2: 0, stop: 0 #3c3f41, stop: 1 #202225);
+ x1: 0, y1: 2,
+ x2: 0, y2: 0,
+ stop: 0 rgb( 60, 63, 65),
+ stop: 1 rgb( 32, 34, 37));
}
QTabBar::tab:top:hover {
background: qlineargradient(
- x1: 0, y1: -1, x2: 0, y2: 1, stop: 0 #483d8b, stop: 1 #202225);
+ x1: 0, y1: -1,
+ x2: 0, y2: 1,
+ stop: 0 rgb( 72, 61, 139),
+ stop: 1 rgb( 32, 34, 37));
}
QTabBar::tab:bottom:hover {
background: qlineargradient(
- x1: 0, y1: 2, x2: 0, y2: 0, stop: 0 #483d8b, stop: 1 #202225);
+ x1: 0, y1: 2,
+ x2: 0, y2: 0,
+ stop: 0 rgb( 72, 61, 139),
+ stop: 1 rgb( 32, 34, 37));
}
QTabBar::tab:top:selected {
- border-color: #483d8b;
+ border-color: rgb( 72, 61, 139);
border-bottom-color: transparent;
- background: #202225;
+ background: rgb( 32, 34, 37);
}
QTabBar::tab:bottom:selected {
- border-color: #483d8b;
+ border-color: rgb( 72, 61, 139);
border-top-color: transparent;
- background: #202225;
+ background: rgb( 32, 34, 37);
}
QTabBar::tab:top:disabled {
- border-bottom-color: #3c3f41;
+ border-bottom-color: rgb( 60, 63, 65);
}
QTabBar::tab:bottom:disabled {
- border-top-color: #3c3f41;
+ border-top-color: rgb( 60, 63, 65);
}
QTabBar::tab:top:selected:disabled {
- border-color: #3c3f41;
+ border-color: rgb( 60, 63, 65);
border-bottom-color: transparent;
}
QTabBar::tab:bottom:selected:disabled {
- border-color: #3c3f41;
+ border-color: rgb( 60, 63, 65);
border-top-color: transparent;
}
QTabBar::tab:left,
@@ -576,54 +593,66 @@ QTabBar::tab:right {
}
QTabBar::tab:left:hover,
QTabBar::tab:right:hover {
- border-color: #483d8b;
+ border-color: rgb( 72, 61, 139);
border-top-color: transparent;
border-bottom-color: transparent;
}
QTabBar::tab:left {
border-left-width: 3px;
- border-left-color: #3c3f41;
- border-right-color: #483d8b;
+ border-left-color: rgb( 60, 63, 65);
+ border-right-color: rgb( 72, 61, 139);
background: qlineargradient(
- x1: -1, y1: 0, x2: 1, y2: 0, stop: 0 #3c3f41, stop: 1 #202225);
+ x1: -1, y1: 0,
+ x2: 1, y2: 0,
+ stop: 0 rgb( 60, 63, 65),
+ stop: 1 rgb( 32, 34, 37));
}
QTabBar::tab:right {
border-right-width: 3px;
- border-right-color: #3c3f41;
- border-left-color: #483d8b;
+ border-right-color: rgb( 60, 63, 65);
+ border-left-color: rgb( 72, 61, 139);
background: qlineargradient(
- x1: 2, y1: 0, x2: 0, y2: 0, stop: 0 #3c3f41, stop: 1 #202225);
+ x1: 2, y1: 0,
+ x2: 0, y2: 0,
+ stop: 0 rgb( 60, 63, 65),
+ stop: 1 rgb( 32, 34, 37));
}
QTabBar::tab:left:hover {
background: qlineargradient(
- x1: -1, y1: 0, x2: 1, y2: 0, stop: 0 #483d8b, stop: 1 #202225);
+ x1: -1, y1: 0,
+ x2: 1, y2: 0,
+ stop: 0 rgb( 72, 61, 139),
+ stop: 1 rgb( 32, 34, 37));
}
QTabBar::tab:right:hover {
background: qlineargradient(
- x1: 2, y1: 0, x2: 0, y2: 0, stop: 0 #483d8b, stop: 1 #202225);
+ x1: 2, y1: 0,
+ x2: 0, y2: 0,
+ stop: 0 rgb( 72, 61, 139),
+ stop: 1 rgb( 32, 34, 37));
}
QTabBar::tab:left:selected {
- border-color: #483d8b;
+ border-color: rgb( 72, 61, 139);
border-right-color: transparent;
- background: #202225;
+ background: rgb( 32, 34, 37);
}
QTabBar::tab:right:selected {
- border-color: #483d8b;
+ border-color: rgb( 72, 61, 139);
border-left-color: transparent;
- background: #202225;
+ background: rgb( 32, 34, 37);
}
QTabBar::tab:left:disabled {
- border-right-color: #3c3f41;
+ border-right-color: rgb( 60, 63, 65);
}
QTabBar::tab:right:disabled {
- border-left-color: #3c3f41;
+ border-left-color: rgb( 60, 63, 65);
}
QTabBar::tab:left:selected:disabled {
- border-color: #3c3f41;
+ border-color: rgb( 60, 63, 65);
border-right-color: transparent;
}
QTabBar::tab:right:selected:disabled {
- border-color: #3c3f41;
+ border-color: rgb( 60, 63, 65);
border-left-color: transparent;
}
@@ -631,21 +660,24 @@ QTabBar#MainTabBar {
border-width: 1px;
border-style: solid;
border-color: transparent;
- border-bottom-color: #483d8b;
+ border-bottom-color: rgb( 72, 61, 139);
/*
background: qlineargradient(
- x1: 0, y1: -3, x2: 0, y2: 1, stop: 0 #3c3f41, stop: 1 #202225);
+ x1: 0, y1: -3,
+ x2: 0, y2: 1,
+ stop: 0 rgb( 60, 63, 65),
+ stop: 1 rgb( 32, 34, 37));
*/
}
QTabBar#MainTabBar:disabled {
border-color: transparent;
- border-bottom-color: #3c3f41;
+ border-bottom-color: rgb( 60, 63, 65);
}
QTabBar#MainTabBar::tab {
margin-left: 3px;
margin-right: 3px;
border-top-color: transparent;
- border-bottom-color: #483d8b;
+ border-bottom-color: rgb( 72, 61, 139);
padding: 5px;
}/*
QTabBar#MainTabBar::tab:top:first,
@@ -659,25 +691,28 @@ QTabBar#MainTabBar::tab:bottom:last {
border-right: transparent;
}*/
QTabBar#MainTabBar::tab:top:hover {
- border-top-color: #483d8b;
+ border-top-color: rgb( 72, 61, 139);
}
QTabBar#MainTabBar::tab:top:selected {
- border-color: #483d8b;
- border-bottom-color: #202225;
+ border-color: rgb( 72, 61, 139);
+ border-bottom-color: rgb( 32, 34, 37);
}
QTabBar#SideTabBar {
border-width: 1px;
border-style: solid;
border-color: transparent;
- border-right-color: #483d8b;
+ border-right-color: rgb( 72, 61, 139);
/*
background: qlineargradient(
- x1: -3, y1: 0, x2: 1, y2: 0, stop: 0 #3c3f41, stop: 1 #202225);
+ x1: -3, y1: 0,
+ x2: 1, y2: 0,
+ stop: 0 rgb( 60, 63, 65),
+ stop: 1 rgb( 32, 34, 37));
*/
}
QTabBar#SideTabBar:disabled {
border-color: transparent;
- border-right-color: #3c3f41;
+ border-right-color: rgb( 60, 63, 65);
}
QTabBar#SideTabBar::tab {
margin-top: 3px;
@@ -703,44 +738,47 @@ QStatusBar {
border-width: 1px;
border-style: solid;
border-color: transparent;
- border-top-color: #483d8b;
- border-bottom-color: #3c3f41;
+ border-top-color: rgb( 72, 61, 139);
+ border-bottom-color: rgb( 60, 63, 65);
background: qlineargradient(
- x1: 0, y1: 3, x2: 0, y2: 0, stop: 0 #3c3f41, stop: 1 #202225);
+ x1: 0, y1: 3,
+ x2: 0, y2: 0,
+ stop: 0 rgb( 60, 63, 65),
+ stop: 1 rgb( 32, 34, 37));
}
QToolTip {
border-width: 1px;
border-style: solid;
- border-color: #483d8b;
+ border-color: rgb( 72, 61, 139);
border-radius: 4px;
padding: 1px;
opacity: 200;
}
QBalloonTip {
- color: #eeeeee;
- background-color: #202225;
+ color: rgb(238, 238, 238);
+ background-color: rgb( 32, 34, 37);
border-width: 1px;
border-style: solid;
- border-color: #483d8b;
+ border-color: rgb( 72, 61, 139);
border-radius: 4px;
padding: 1px;
}
/* Wrapper settings styling */
QPushButton#WrapperWidgetButton {
- border-color: rgba(67, 71, 77, 55%);
+ border-color: rgb( 51, 54, 59);
}
QPushButton#WrapperWidgetButton:disabled {
- border-color: rgba(67, 71, 77, 25%);
+ border-color: rgb( 41, 43, 47);
}
QScrollArea#WrapperSettingsScroll {
- border-color: #2f4f4f;
- background-color: #282a2e;
+ border-color: rgb( 47, 79, 79);
+ background-color: rgb( 40, 42, 46);
}
QScrollBar#WrapperSettingsScrollBar {
- background-color: #282a2e;
+ background-color: rgb( 40, 42, 46);
}
QLabel#WrapperSettingsLabel {
border-width: 1px;
@@ -748,6 +786,6 @@ QLabel#WrapperSettingsLabel {
border-radius: 2px;
padding: 2px;
color: #999;
- border-color: #2f4f4f;
- background-color: #282a2e;
+ border-color: rgb( 47, 79, 79);
+ background-color: rgb( 40, 42, 46);
}
diff --git a/rare/shared.py b/rare/shared.py
index 5de855fd..33ce579f 100644
--- a/rare/shared.py
+++ b/rare/shared.py
@@ -1,37 +1,47 @@
from argparse import Namespace
+from typing import Optional
from legendary.core import LegendaryCore
+
from rare.utils.models import ApiResults, GlobalSignals
-_legendary_core_singleton: LegendaryCore = None
-_global_signals_singleton: GlobalSignals = None
-_arguments_singleton: Namespace = None
-_api_results_singleton: ApiResults = None
+_legendary_core_singleton: Optional[LegendaryCore] = None
+_global_signals_singleton: Optional[GlobalSignals] = None
+_arguments_singleton: Optional[Namespace] = None
+_api_results_singleton: Optional[ApiResults] = None
-def LegendaryCoreSingleton() -> LegendaryCore:
+def LegendaryCoreSingleton(init: bool = False) -> LegendaryCore:
global _legendary_core_singleton
+ if _legendary_core_singleton is None and not init:
+ raise RuntimeError("Uninitialized use of LegendaryCoreSingleton")
if _legendary_core_singleton is None:
_legendary_core_singleton = LegendaryCore()
return _legendary_core_singleton
-def GlobalSignalsSingleton() -> GlobalSignals:
+def GlobalSignalsSingleton(init: bool = False) -> GlobalSignals:
global _global_signals_singleton
+ if _global_signals_singleton is None and not init:
+ raise RuntimeError("Uninitialized use of GlobalSignalsSingleton")
if _global_signals_singleton is None:
_global_signals_singleton = GlobalSignals()
return _global_signals_singleton
-def ArgumentsSingleton(args: Namespace = None) -> Namespace:
+def ArgumentsSingleton(args: Namespace = None) -> Optional[Namespace]:
global _arguments_singleton
+ if _arguments_singleton is None and args is None:
+ raise RuntimeError("Uninitialized use of ArgumentsSingleton")
if _arguments_singleton is None:
_arguments_singleton = args
return _arguments_singleton
-def ApiResultsSingleton(res: ApiResults = None) -> ApiResults:
+def ApiResultsSingleton(res: ApiResults = None) -> Optional[ApiResults]:
global _api_results_singleton
+ if _api_results_singleton is None and res is None:
+ raise RuntimeError("Uninitialized use of ApiResultsSingleton")
if _api_results_singleton is None:
_api_results_singleton = res
return _api_results_singleton
diff --git a/rare/ui/components/dialogs/install_dialog.py b/rare/ui/components/dialogs/install_dialog.py
index c8bb87dd..80927028 100644
--- a/rare/ui/components/dialogs/install_dialog.py
+++ b/rare/ui/components/dialogs/install_dialog.py
@@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_InstallDialog(object):
def setupUi(self, InstallDialog):
InstallDialog.setObjectName("InstallDialog")
- InstallDialog.resize(324, 347)
+ InstallDialog.resize(337, 372)
InstallDialog.setWindowTitle("Rare")
self.install_dialog_layout = QtWidgets.QFormLayout(InstallDialog)
self.install_dialog_layout.setSizeConstraint(QtWidgets.QLayout.SetFixedSize)
@@ -58,6 +58,7 @@ class Ui_InstallDialog(object):
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.force_download_check.sizePolicy().hasHeightForWidth())
self.force_download_check.setSizePolicy(sizePolicy)
+ self.force_download_check.setText("")
self.force_download_check.setObjectName("force_download_check")
self.install_dialog_layout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.force_download_check)
self.platform_label = QtWidgets.QLabel(InstallDialog)
@@ -74,50 +75,14 @@ class Ui_InstallDialog(object):
self.ignore_space_label = QtWidgets.QLabel(InstallDialog)
self.ignore_space_label.setObjectName("ignore_space_label")
self.install_dialog_layout.setWidget(5, QtWidgets.QFormLayout.LabelRole, self.ignore_space_label)
- self.ignore_space_layout = QtWidgets.QHBoxLayout()
- self.ignore_space_layout.setObjectName("ignore_space_layout")
- self.ignore_space_check = QtWidgets.QCheckBox(InstallDialog)
- sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
- sizePolicy.setHorizontalStretch(0)
- sizePolicy.setVerticalStretch(0)
- sizePolicy.setHeightForWidth(self.ignore_space_check.sizePolicy().hasHeightForWidth())
- self.ignore_space_check.setSizePolicy(sizePolicy)
- self.ignore_space_check.setObjectName("ignore_space_check")
- self.ignore_space_layout.addWidget(self.ignore_space_check)
- self.ignore_space_info_label = QtWidgets.QLabel(InstallDialog)
- font = QtGui.QFont()
- font.setItalic(True)
- self.ignore_space_info_label.setFont(font)
- self.ignore_space_info_label.setObjectName("ignore_space_info_label")
- self.ignore_space_layout.addWidget(self.ignore_space_info_label)
- self.install_dialog_layout.setLayout(5, QtWidgets.QFormLayout.FieldRole, self.ignore_space_layout)
self.download_only_label = QtWidgets.QLabel(InstallDialog)
self.download_only_label.setObjectName("download_only_label")
self.install_dialog_layout.setWidget(6, QtWidgets.QFormLayout.LabelRole, self.download_only_label)
- self.download_only_layout = QtWidgets.QHBoxLayout()
- self.download_only_layout.setObjectName("download_only_layout")
- self.download_only_check = QtWidgets.QCheckBox(InstallDialog)
- sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
- sizePolicy.setHorizontalStretch(0)
- sizePolicy.setVerticalStretch(0)
- sizePolicy.setHeightForWidth(self.download_only_check.sizePolicy().hasHeightForWidth())
- self.download_only_check.setSizePolicy(sizePolicy)
- self.download_only_check.setText("")
- self.download_only_check.setObjectName("download_only_check")
- self.download_only_layout.addWidget(self.download_only_check)
- self.download_only_info_label = QtWidgets.QLabel(InstallDialog)
- font = QtGui.QFont()
- font.setItalic(True)
- self.download_only_info_label.setFont(font)
- self.download_only_info_label.setObjectName("download_only_info_label")
- self.download_only_layout.addWidget(self.download_only_info_label)
- self.install_dialog_layout.setLayout(6, QtWidgets.QFormLayout.FieldRole, self.download_only_layout)
self.shortcut_lbl = QtWidgets.QLabel(InstallDialog)
self.shortcut_lbl.setObjectName("shortcut_lbl")
self.install_dialog_layout.setWidget(7, QtWidgets.QFormLayout.LabelRole, self.shortcut_lbl)
self.shortcut_cb = QtWidgets.QCheckBox(InstallDialog)
self.shortcut_cb.setText("")
- self.shortcut_cb.setChecked(True)
self.shortcut_cb.setObjectName("shortcut_cb")
self.install_dialog_layout.setWidget(7, QtWidgets.QFormLayout.FieldRole, self.shortcut_cb)
self.sdl_list_label = QtWidgets.QLabel(InstallDialog)
@@ -181,6 +146,28 @@ class Ui_InstallDialog(object):
self.install_preqs_check.setText("")
self.install_preqs_check.setObjectName("install_preqs_check")
self.install_dialog_layout.setWidget(8, QtWidgets.QFormLayout.FieldRole, self.install_preqs_check)
+ self.ignore_space_check = QtWidgets.QCheckBox(InstallDialog)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.ignore_space_check.sizePolicy().hasHeightForWidth())
+ self.ignore_space_check.setSizePolicy(sizePolicy)
+ font = QtGui.QFont()
+ font.setItalic(True)
+ self.ignore_space_check.setFont(font)
+ self.ignore_space_check.setObjectName("ignore_space_check")
+ self.install_dialog_layout.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.ignore_space_check)
+ self.download_only_check = QtWidgets.QCheckBox(InstallDialog)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.download_only_check.sizePolicy().hasHeightForWidth())
+ self.download_only_check.setSizePolicy(sizePolicy)
+ font = QtGui.QFont()
+ font.setItalic(True)
+ self.download_only_check.setFont(font)
+ self.download_only_check.setObjectName("download_only_check")
+ self.install_dialog_layout.setWidget(6, QtWidgets.QFormLayout.FieldRole, self.download_only_check)
self.retranslateUi(InstallDialog)
QtCore.QMetaObject.connectSlotsByName(InstallDialog)
@@ -194,9 +181,7 @@ class Ui_InstallDialog(object):
self.force_download_label.setText(_translate("InstallDialog", "Force redownload"))
self.platform_label.setText(_translate("InstallDialog", "Platform"))
self.ignore_space_label.setText(_translate("InstallDialog", "Ignore free space"))
- self.ignore_space_info_label.setText(_translate("InstallDialog", "Use with caution!"))
self.download_only_label.setText(_translate("InstallDialog", "Download only"))
- self.download_only_info_label.setText(_translate("InstallDialog", "Do not try to install."))
self.shortcut_lbl.setText(_translate("InstallDialog", "Create shortcut"))
self.sdl_list_label.setText(_translate("InstallDialog", "Optional packs"))
self.download_size_label.setText(_translate("InstallDialog", "Download size"))
@@ -209,6 +194,8 @@ class Ui_InstallDialog(object):
self.verify_button.setText(_translate("InstallDialog", "Verify"))
self.install_button.setText(_translate("InstallDialog", "Install"))
self.install_preqs_lbl.setText(_translate("InstallDialog", "Install prerequisites"))
+ self.ignore_space_check.setText(_translate("InstallDialog", "Use with caution!"))
+ self.download_only_check.setText(_translate("InstallDialog", "Do not try to install."))
if __name__ == "__main__":
diff --git a/rare/ui/components/dialogs/install_dialog.ui b/rare/ui/components/dialogs/install_dialog.ui
index 908d2a6f..5c43d499 100644
--- a/rare/ui/components/dialogs/install_dialog.ui
+++ b/rare/ui/components/dialogs/install_dialog.ui
@@ -6,8 +6,8 @@
0
0
- 324
- 347
+ 337
+ 372
@@ -85,6 +85,9 @@
0
+
+
+
-
@@ -111,32 +114,6 @@
- -
-
-
-
-
-
-
- 0
- 0
-
-
-
-
- -
-
-
-
- true
-
-
-
- Use with caution!
-
-
-
-
-
-
@@ -144,35 +121,6 @@
- -
-
-
-
-
-
-
- 0
- 0
-
-
-
-
-
-
-
- -
-
-
-
- true
-
-
-
- Do not try to install.
-
-
-
-
-
-
@@ -185,9 +133,6 @@
-
- true
-
-
@@ -323,7 +268,43 @@
-
-
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ true
+
+
+
+ Use with caution!
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ true
+
+
+
+ Do not try to install.
diff --git a/rare/ui/components/dialogs/login/login_dialog.py b/rare/ui/components/dialogs/login/login_dialog.py
index e5e5b84b..b7650abd 100644
--- a/rare/ui/components/dialogs/login/login_dialog.py
+++ b/rare/ui/components/dialogs/login/login_dialog.py
@@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'rare/ui/components/dialogs/login/login_dialog.ui'
#
-# Created by: PyQt5 UI code generator 5.15.4
+# 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.
@@ -14,16 +14,17 @@ from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_LoginDialog(object):
def setupUi(self, LoginDialog):
LoginDialog.setObjectName("LoginDialog")
- LoginDialog.resize(498, 269)
- self.verticalLayout = QtWidgets.QVBoxLayout(LoginDialog)
- self.verticalLayout.setObjectName("verticalLayout")
- spacerItem = QtWidgets.QSpacerItem(477, 17, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
- self.verticalLayout.addItem(spacerItem)
+ LoginDialog.resize(492, 267)
+ self.login_layout = QtWidgets.QVBoxLayout(LoginDialog)
+ self.login_layout.setSizeConstraint(QtWidgets.QLayout.SetFixedSize)
+ self.login_layout.setObjectName("login_layout")
+ spacerItem = QtWidgets.QSpacerItem(0, 17, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+ self.login_layout.addItem(spacerItem)
self.welcome_label = QtWidgets.QLabel(LoginDialog)
self.welcome_label.setObjectName("welcome_label")
- self.verticalLayout.addWidget(self.welcome_label)
- spacerItem1 = QtWidgets.QSpacerItem(477, 17, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
- self.verticalLayout.addItem(spacerItem1)
+ self.login_layout.addWidget(self.welcome_label)
+ spacerItem1 = QtWidgets.QSpacerItem(0, 17, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+ self.login_layout.addItem(spacerItem1)
self.login_stack = QtWidgets.QStackedWidget(LoginDialog)
self.login_stack.setEnabled(True)
self.login_stack.setMinimumSize(QtCore.QSize(480, 135))
@@ -73,7 +74,7 @@ class Ui_LoginDialog(object):
self.login_browser_radio.setObjectName("login_browser_radio")
self.login_page_layout.addWidget(self.login_browser_radio, 1, 0, 1, 1)
self.login_stack.addWidget(self.login_page)
- self.verticalLayout.addWidget(self.login_stack)
+ self.login_layout.addWidget(self.login_stack)
self.button_layout = QtWidgets.QHBoxLayout()
self.button_layout.setObjectName("button_layout")
spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
@@ -87,7 +88,7 @@ class Ui_LoginDialog(object):
self.next_button = QtWidgets.QPushButton(LoginDialog)
self.next_button.setObjectName("next_button")
self.button_layout.addWidget(self.next_button)
- self.verticalLayout.addLayout(self.button_layout)
+ self.login_layout.addLayout(self.button_layout)
self.retranslateUi(LoginDialog)
self.login_stack.setCurrentIndex(0)
diff --git a/rare/ui/components/dialogs/login/login_dialog.ui b/rare/ui/components/dialogs/login/login_dialog.ui
index d4051943..2adbb98a 100644
--- a/rare/ui/components/dialogs/login/login_dialog.ui
+++ b/rare/ui/components/dialogs/login/login_dialog.ui
@@ -6,25 +6,22 @@
0
0
- 498
- 269
+ 492
+ 267
Rare Login
-
+
+
+ QLayout::SetFixedSize
+
-
-
- Qt::Vertical
-
-
- QSizePolicy::Fixed
-
- 477
+ 0
17
@@ -39,15 +36,9 @@
-
-
- Qt::Vertical
-
-
- QSizePolicy::Fixed
-
- 477
+ 0
17
diff --git a/rare/ui/components/extra/__init__.py b/rare/ui/components/extra/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/rare/ui/components/extra/console_env.py b/rare/ui/components/extra/console_env.py
new file mode 100644
index 00000000..51c88559
--- /dev/null
+++ b/rare/ui/components/extra/console_env.py
@@ -0,0 +1,67 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'rare/ui/components/extra/console_env.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_ConsoleEnv(object):
+ def setupUi(self, ConsoleEnv):
+ ConsoleEnv.setObjectName("ConsoleEnv")
+ ConsoleEnv.resize(600, 400)
+ self.layout = QtWidgets.QVBoxLayout(ConsoleEnv)
+ self.layout.setObjectName("layout")
+ self.table = QtWidgets.QTableWidget(ConsoleEnv)
+ font = QtGui.QFont()
+ font.setFamily("Monospace")
+ self.table.setFont(font)
+ self.table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
+ self.table.setAlternatingRowColors(True)
+ self.table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
+ self.table.setCornerButtonEnabled(True)
+ self.table.setColumnCount(2)
+ self.table.setObjectName("table")
+ self.table.setRowCount(0)
+ item = QtWidgets.QTableWidgetItem()
+ self.table.setHorizontalHeaderItem(0, item)
+ item = QtWidgets.QTableWidgetItem()
+ self.table.setHorizontalHeaderItem(1, item)
+ self.table.horizontalHeader().setVisible(True)
+ self.table.horizontalHeader().setStretchLastSection(True)
+ self.table.verticalHeader().setVisible(False)
+ self.layout.addWidget(self.table)
+ self.buttons = QtWidgets.QDialogButtonBox(ConsoleEnv)
+ self.buttons.setOrientation(QtCore.Qt.Horizontal)
+ self.buttons.setStandardButtons(QtWidgets.QDialogButtonBox.Close)
+ self.buttons.setObjectName("buttons")
+ self.layout.addWidget(self.buttons)
+
+ self.retranslateUi(ConsoleEnv)
+ self.buttons.accepted.connect(ConsoleEnv.accept) # type: ignore
+ self.buttons.rejected.connect(ConsoleEnv.reject) # type: ignore
+ QtCore.QMetaObject.connectSlotsByName(ConsoleEnv)
+
+ def retranslateUi(self, ConsoleEnv):
+ _translate = QtCore.QCoreApplication.translate
+ ConsoleEnv.setWindowTitle(_translate("ConsoleEnv", "Rare - Console Environment"))
+ self.table.setSortingEnabled(True)
+ item = self.table.horizontalHeaderItem(0)
+ item.setText(_translate("ConsoleEnv", "Variable"))
+ item = self.table.horizontalHeaderItem(1)
+ item.setText(_translate("ConsoleEnv", "Value"))
+
+
+if __name__ == "__main__":
+ import sys
+ app = QtWidgets.QApplication(sys.argv)
+ ConsoleEnv = QtWidgets.QDialog()
+ ui = Ui_ConsoleEnv()
+ ui.setupUi(ConsoleEnv)
+ ConsoleEnv.show()
+ sys.exit(app.exec_())
diff --git a/rare/ui/components/extra/console_env.ui b/rare/ui/components/extra/console_env.ui
new file mode 100644
index 00000000..91283242
--- /dev/null
+++ b/rare/ui/components/extra/console_env.ui
@@ -0,0 +1,110 @@
+
+
+ ConsoleEnv
+
+
+
+ 0
+ 0
+ 600
+ 400
+
+
+
+ Rare - Console Environment
+
+
+
-
+
+
+
+ Monospace
+
+
+
+ QAbstractItemView::NoEditTriggers
+
+
+ true
+
+
+ QAbstractItemView::SelectRows
+
+
+ true
+
+
+ true
+
+
+ 2
+
+
+ true
+
+
+ true
+
+
+ false
+
+
+
+ Variable
+
+
+
+
+ Value
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Close
+
+
+
+
+
+
+
+
+ buttons
+ accepted()
+ ConsoleEnv
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttons
+ rejected()
+ ConsoleEnv
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
diff --git a/rare/ui/components/tabs/games/game_info/game_info.py b/rare/ui/components/tabs/games/game_info/game_info.py
index b5a57ee4..755b0a2f 100644
--- a/rare/ui/components/tabs/games/game_info/game_info.py
+++ b/rare/ui/components/tabs/games/game_info/game_info.py
@@ -16,7 +16,6 @@ class Ui_GameInfo(object):
GameInfo.setObjectName("GameInfo")
GameInfo.resize(791, 583)
self.layout_game_info = QtWidgets.QHBoxLayout(GameInfo)
- self.layout_game_info.setSizeConstraint(QtWidgets.QLayout.SetFixedSize)
self.layout_game_info.setObjectName("layout_game_info")
self.image = QtWidgets.QLabel(GameInfo)
self.image.setFrameShape(QtWidgets.QFrame.StyledPanel)
diff --git a/rare/ui/components/tabs/games/game_info/game_info.ui b/rare/ui/components/tabs/games/game_info/game_info.ui
index 73b9be19..a97bfa66 100644
--- a/rare/ui/components/tabs/games/game_info/game_info.ui
+++ b/rare/ui/components/tabs/games/game_info/game_info.ui
@@ -14,9 +14,6 @@
Game Info
-
- QLayout::SetFixedSize
-
-
diff --git a/rare/ui/components/tabs/games/import_sync/import_group.py b/rare/ui/components/tabs/games/import_sync/import_group.py
index 7b13f92d..f1e8222e 100644
--- a/rare/ui/components/tabs/games/import_sync/import_group.py
+++ b/rare/ui/components/tabs/games/import_sync/import_group.py
@@ -8,30 +8,37 @@
# run again. Do not edit this file unless you know what you are doing.
-from PyQt5 import QtCore, QtWidgets
+from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_ImportGroup(object):
def setupUi(self, ImportGroup):
ImportGroup.setObjectName("ImportGroup")
- ImportGroup.resize(235, 127)
+ ImportGroup.resize(501, 154)
ImportGroup.setWindowTitle("ImportGroup")
ImportGroup.setWindowFilePath("")
self.import_layout = QtWidgets.QFormLayout(ImportGroup)
- self.import_layout.setLabelAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter)
+ self.import_layout.setLabelAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.import_layout.setObjectName("import_layout")
self.path_edit_label = QtWidgets.QLabel(ImportGroup)
self.path_edit_label.setObjectName("path_edit_label")
self.import_layout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.path_edit_label)
- self.app_name_label = QtWidgets.QLabel(ImportGroup)
- self.app_name_label.setObjectName("app_name_label")
- self.import_layout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.app_name_label)
self.path_edit_layout = QtWidgets.QHBoxLayout()
self.path_edit_layout.setObjectName("path_edit_layout")
self.import_layout.setLayout(0, QtWidgets.QFormLayout.FieldRole, self.path_edit_layout)
+ self.app_name_label = QtWidgets.QLabel(ImportGroup)
+ self.app_name_label.setObjectName("app_name_label")
+ self.import_layout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.app_name_label)
self.app_name_layout = QtWidgets.QHBoxLayout()
self.app_name_layout.setObjectName("app_name_layout")
self.import_layout.setLayout(1, QtWidgets.QFormLayout.FieldRole, self.app_name_layout)
+ self.import_folder_label = QtWidgets.QLabel(ImportGroup)
+ self.import_folder_label.setObjectName("import_folder_label")
+ self.import_layout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.import_folder_label)
+ self.info_label = QtWidgets.QLabel(ImportGroup)
+ self.info_label.setText("")
+ self.info_label.setObjectName("info_label")
+ self.import_layout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.info_label)
self.import_button = QtWidgets.QPushButton(ImportGroup)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
@@ -39,11 +46,13 @@ class Ui_ImportGroup(object):
sizePolicy.setHeightForWidth(self.import_button.sizePolicy().hasHeightForWidth())
self.import_button.setSizePolicy(sizePolicy)
self.import_button.setObjectName("import_button")
- self.import_layout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.import_button)
- self.info_label = QtWidgets.QLabel(ImportGroup)
- self.info_label.setText("")
- self.info_label.setObjectName("info_label")
- self.import_layout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.info_label)
+ self.import_layout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.import_button)
+ self.import_folder_check = QtWidgets.QCheckBox(ImportGroup)
+ font = QtGui.QFont()
+ font.setItalic(True)
+ self.import_folder_check.setFont(font)
+ self.import_folder_check.setObjectName("import_folder_check")
+ self.import_layout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.import_folder_check)
self.retranslateUi(ImportGroup)
QtCore.QMetaObject.connectSlotsByName(ImportGroup)
@@ -53,7 +62,9 @@ class Ui_ImportGroup(object):
ImportGroup.setTitle(_translate("ImportGroup", "Import EGL game from a directory"))
self.path_edit_label.setText(_translate("ImportGroup", "Installation path"))
self.app_name_label.setText(_translate("ImportGroup", "Override app name"))
+ self.import_folder_label.setText(_translate("ImportGroup", "Import all folders"))
self.import_button.setText(_translate("ImportGroup", "Import Game"))
+ self.import_folder_check.setText(_translate("ImportGroup", "Scan the installation path for game folders and import them"))
if __name__ == "__main__":
diff --git a/rare/ui/components/tabs/games/import_sync/import_group.ui b/rare/ui/components/tabs/games/import_sync/import_group.ui
index 9e156c41..0545451f 100644
--- a/rare/ui/components/tabs/games/import_sync/import_group.ui
+++ b/rare/ui/components/tabs/games/import_sync/import_group.ui
@@ -6,8 +6,8 @@
0
0
- 235
- 127
+ 501
+ 154
@@ -30,6 +30,9 @@
+ -
+
+
-
@@ -37,13 +40,24 @@
- -
-
-
-
+ -
+
+
+ Import all folders
+
+
+
-
+
+
+
+
+
+
+ -
@@ -57,9 +71,14 @@
-
-
+
+
+
+ true
+
+
-
+ Scan the installation path for game folders and import them
diff --git a/rare/utils/extra_widgets.py b/rare/utils/extra_widgets.py
index 117f0516..ba880244 100644
--- a/rare/utils/extra_widgets.py
+++ b/rare/utils/extra_widgets.py
@@ -4,6 +4,7 @@ from typing import Callable, Tuple
from PyQt5.QtCore import (
Qt,
+ QEvent,
QCoreApplication,
QRect,
QSize,
@@ -49,6 +50,7 @@ class FlowLayout(QLayout):
self._vspacing = vspacing
self._items = []
self.setContentsMargins(margin, margin, margin, margin)
+ self.setObjectName(type(self).__name__)
def __del__(self):
del self._items[:]
@@ -148,7 +150,9 @@ class FlowLayout(QLayout):
class IndicatorReasons:
dir_not_empty = QCoreApplication.translate("IndicatorReasons", "Directory is not empty")
wrong_format = QCoreApplication.translate("IndicatorReasons", "Given text has wrong format")
- game_not_installed = QCoreApplication.translate("IndicatorReasons", "Game is not installed or does not exist")
+ game_not_installed = QCoreApplication.translate(
+ "IndicatorReasons", "Game is not installed or does not exist"
+ )
dir_not_exist = QCoreApplication.translate("IndicatorReasons", "Directory does not exist")
file_not_exist = QCoreApplication.translate("IndicatorReasons", "File does not exist")
wrong_path = QCoreApplication.translate("IndicatorReasons", "Wrong Directory")
@@ -160,29 +164,29 @@ class IndicatorLineEdit(QWidget):
reasons = IndicatorReasons()
def __init__(
- self,
- text: str = "",
- placeholder: str = "",
- completer: QCompleter = None,
- edit_func: Callable[[str], Tuple[bool, str, str]] = None,
- save_func: Callable[[str], None] = None,
- horiz_policy: QSizePolicy = QSizePolicy.Expanding,
- parent=None,
+ self,
+ text: str = "",
+ placeholder: str = "",
+ completer: QCompleter = None,
+ edit_func: Callable[[str], Tuple[bool, str, str]] = None,
+ save_func: Callable[[str], None] = None,
+ horiz_policy: QSizePolicy = QSizePolicy.Expanding,
+ parent=None,
):
super(IndicatorLineEdit, self).__init__(parent=parent)
- self.setObjectName("IndicatorLineEdit")
- self.layout = QHBoxLayout(self)
- self.layout.setObjectName("layout")
- self.layout.setContentsMargins(0, 0, 0, 0)
+ self.setObjectName(type(self).__name__)
+ layout = QHBoxLayout(self)
+ layout.setObjectName(f"{self.objectName()}Layout")
+ layout.setContentsMargins(0, 0, 0, 0)
# Add line_edit
self.line_edit = QLineEdit(self)
- self.line_edit.setObjectName("line_edit")
+ self.line_edit.setObjectName(f"{type(self).__name__}Edit")
self.line_edit.setPlaceholderText(placeholder)
self.line_edit.setSizePolicy(horiz_policy, QSizePolicy.Fixed)
# Add hint_label to line_edit
self.line_edit.setLayout(QHBoxLayout())
self.hint_label = QLabel()
- self.hint_label.setObjectName("HintLabel")
+ self.hint_label.setObjectName(f"{type(self).__name__}Label")
self.hint_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
self.line_edit.layout().setContentsMargins(0, 0, 10, 0)
self.line_edit.layout().addWidget(self.hint_label)
@@ -191,20 +195,16 @@ class IndicatorLineEdit(QWidget):
completer.popup().setItemDelegate(QStyledItemDelegate(self))
completer.popup().setAlternatingRowColors(True)
self.line_edit.setCompleter(completer)
- self.layout.addWidget(self.line_edit)
+ layout.addWidget(self.line_edit)
if edit_func is not None:
self.indicator_label = QLabel()
- self.indicator_label.setPixmap(
- qta_icon("ei.info-circle", color="gray").pixmap(16, 16)
- )
+ self.indicator_label.setPixmap(qta_icon("ei.info-circle", color="gray").pixmap(16, 16))
self.indicator_label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
- self.layout.addWidget(self.indicator_label)
+ layout.addWidget(self.indicator_label)
if not placeholder:
_translate = QCoreApplication.translate
- self.line_edit.setPlaceholderText(
- _translate(self.__class__.__name__, "Default")
- )
+ self.line_edit.setPlaceholderText(_translate(self.__class__.__name__, "Default"))
self.edit_func = edit_func
self.save_func = save_func
@@ -233,9 +233,7 @@ class IndicatorLineEdit(QWidget):
def __indicator(self, res, reason=None):
color = "green" if res else "red"
- self.indicator_label.setPixmap(
- qta_icon("ei.info-circle", color=color).pixmap(16, 16)
- )
+ self.indicator_label.setPixmap(qta_icon("ei.info-circle", color=color).pixmap(16, 16))
if reason:
self.indicator_label.setToolTip(reason)
else:
@@ -297,16 +295,16 @@ class PathEdit(IndicatorLineEdit):
compl_model = QFileSystemModel()
def __init__(
- self,
- path: str = "",
- file_type: QFileDialog.FileType = QFileDialog.AnyFile,
- type_filter: str = "",
- name_filter: str = "",
- placeholder: str = "",
- edit_func: Callable[[str], Tuple[bool, str, str]] = None,
- save_func: Callable[[str], None] = None,
- horiz_policy: QSizePolicy = QSizePolicy.Expanding,
- parent=None,
+ self,
+ path: str = "",
+ file_type: QFileDialog.FileType = QFileDialog.AnyFile,
+ type_filter: str = "",
+ name_filter: str = "",
+ placeholder: str = "",
+ edit_func: Callable[[str], Tuple[bool, str, str]] = None,
+ save_func: Callable[[str], None] = None,
+ horiz_policy: QSizePolicy = QSizePolicy.Expanding,
+ parent=None,
):
try:
self.compl_model.setOptions(
@@ -320,7 +318,7 @@ class PathEdit(IndicatorLineEdit):
self.compl_model.setRootPath(path)
self.completer.setModel(self.compl_model)
- edit_func = self._wrap_edit_function(edit_func)
+ edit_func = self.__wrap_edit_function(edit_func)
super(PathEdit, self).__init__(
text=path,
@@ -331,11 +329,12 @@ class PathEdit(IndicatorLineEdit):
horiz_policy=horiz_policy,
parent=parent,
)
- self.setObjectName("PathEdit")
- self.line_edit.setMinimumSize(QSize(300, 0))
+ self.setObjectName(type(self).__name__)
+ self.line_edit.setMinimumSize(QSize(250, 0))
self.path_select = QToolButton(self)
- self.path_select.setObjectName("path_select")
- self.layout.addWidget(self.path_select)
+ self.path_select.setObjectName(f"{type(self).__name__}Button")
+ layout = self.layout()
+ layout.addWidget(self.path_select)
_translate = QCoreApplication.translate
self.path_select.setText(_translate("PathEdit", "Browse..."))
@@ -361,7 +360,7 @@ class PathEdit(IndicatorLineEdit):
self.line_edit.setText(names[0])
self.compl_model.setRootPath(names[0])
- def _wrap_edit_function(self, edit_function: Callable[[str], Tuple[bool, str, str]]):
+ def __wrap_edit_function(self, edit_function: Callable[[str], Tuple[bool, str, str]]):
if edit_function:
return lambda text: edit_function(os.path.expanduser(text)
if text.startswith("~") else text)
@@ -478,9 +477,7 @@ class SelectViewWidget(QWidget):
def __init__(self, icon_view: bool):
super(SelectViewWidget, self).__init__()
self.icon_view = icon_view
- self.setStyleSheet(
- """QPushButton{border: none; background-color: transparent}"""
- )
+ self.setStyleSheet("""QPushButton{border: none; background-color: transparent}""")
self.icon_view_button = QPushButton()
self.list_view = QPushButton()
if icon_view:
@@ -505,7 +502,9 @@ class SelectViewWidget(QWidget):
return self.icon_view
def icon(self):
- self.icon_view_button.setIcon(qta_icon("mdi.view-grid-outline", "ei.th-large", color="orange"))
+ self.icon_view_button.setIcon(
+ qta_icon("mdi.view-grid-outline", "ei.th-large", color="orange")
+ )
self.list_view.setIcon(qta_icon("fa5s.list", "ei.th-list"))
self.icon_view = False
self.toggled.emit()
@@ -589,9 +588,7 @@ class ButtonLineEdit(QLineEdit):
"QLineEdit {padding-right: %dpx; }" % (buttonSize.width() + frameWidth + 1)
)
self.setMinimumSize(
- max(
- self.minimumSizeHint().width(), buttonSize.width() + frameWidth * 2 + 2
- ),
+ max(self.minimumSizeHint().width(), buttonSize.width() + frameWidth * 2 + 2),
max(
self.minimumSizeHint().height(),
buttonSize.height() + frameWidth * 2 + 2,
diff --git a/rare/utils/legendary_utils.py b/rare/utils/legendary_utils.py
index 77e09788..a32de593 100644
--- a/rare/utils/legendary_utils.py
+++ b/rare/utils/legendary_utils.py
@@ -157,6 +157,19 @@ class VerifyWorker(QRunnable):
self.signals.summary.emit(len(failed), len(missing), self.app_name)
+# FIXME: lk: ah ef me sideways, we can't even import this thing properly
+# FIXME: lk: so copy it here
+def resolve_aliases(core: LegendaryCore, name):
+ # make sure aliases exist if not yet created
+ core.update_aliases(force=False)
+ name = name.strip()
+ # resolve alias (if any) to real app name
+ return core.lgd.config.get(
+ section='Legendary.aliases', option=name,
+ fallback=core.lgd.aliases.get(name.lower(), name)
+ )
+
+
def import_game(core: LegendaryCore, app_name: str, path: str) -> str:
_tr = QCoreApplication.translate
logger.info(f"Import {app_name}")
diff --git a/rare/utils/models.py b/rare/utils/models.py
index 37b152ec..54743e4e 100644
--- a/rare/utils/models.py
+++ b/rare/utils/models.py
@@ -2,7 +2,7 @@ import os
import platform
from dataclasses import field, dataclass
from multiprocessing import Queue
-from typing import Union, List
+from typing import Union, List, Optional
from PyQt5.QtCore import QObject, pyqtSignal
@@ -46,9 +46,9 @@ class InstallDownloadModel:
@dataclass
class InstallQueueItemModel:
- status_q: Queue = None
- download: InstallDownloadModel = None
- options: InstallOptionsModel = None
+ status_q: Optional[Queue] = None
+ download: Optional[InstallDownloadModel] = None
+ options: Optional[InstallOptionsModel] = None
def __bool__(self):
return (
@@ -105,12 +105,12 @@ class PathSpec:
@dataclass
class ApiResults:
- game_list: list = None
- dlcs: dict = None
- bit32_games: list = None
- mac_games: list = None
- no_asset_games: list = None
- saves: list = None
+ game_list: Optional[list] = None
+ dlcs: Optional[dict] = None
+ bit32_games: Optional[list] = None
+ mac_games: Optional[list] = None
+ no_asset_games: Optional[list] = None
+ saves: Optional[list] = None
def __bool__(self):
return (
diff --git a/rare/utils/paths.py b/rare/utils/paths.py
index 971d60f0..ef9284d0 100644
--- a/rare/utils/paths.py
+++ b/rare/utils/paths.py
@@ -1,13 +1,13 @@
-import os
-import pathlib
+from pathlib import Path
+
from PyQt5.QtCore import QStandardPaths
-resources_path = pathlib.Path(__file__).absolute().parent.parent.joinpath("resources")
-data_dir = os.path.join(QStandardPaths.writableLocation(QStandardPaths.DataLocation), "rare")
-cache_dir = os.path.join(QStandardPaths.writableLocation(QStandardPaths.CacheLocation), "rare")
-image_dir = os.path.join(data_dir, "images")
-tmp_dir = os.path.join(cache_dir, "tmp")
+resources_path = Path(__file__).absolute().parent.parent.joinpath("resources")
+data_dir = Path(QStandardPaths.writableLocation(QStandardPaths.DataLocation), "rare")
+cache_dir = Path(QStandardPaths.writableLocation(QStandardPaths.CacheLocation), "rare")
+image_dir = data_dir.joinpath("images")
+tmp_dir = cache_dir.joinpath("tmp")
for path in (data_dir, cache_dir, image_dir, tmp_dir):
- if not os.path.exists(path):
- os.makedirs(path)
+ if not path.exists():
+ path.mkdir(parents=True)
diff --git a/setup.py b/setup.py
index 9e2aac2b..7870e58c 100644
--- a/setup.py
+++ b/setup.py
@@ -13,13 +13,13 @@ requirements = [
"QtAwesome",
"psutil",
"pypresence",
- 'pywin32; platform_system == "Windows"'
+ 'pywin32; platform_system == "Windows"',
]
optional_reqs = dict(
webview=[
'pywebview[gtk]; platform_system == "Linux"',
- 'pywebview[cef]; platform_system == "Windows"'
+ 'pywebview[cef]; platform_system == "Windows"',
]
)