3c43da1594
* Add options in settings to not request non-asset games and entitlements. This greatly improves startup time but reduces functionality a bit. Both options are disabled by default. * Remove the old options to exclude Win32 and Mac games as they were no longer relevant. * Add a performance context manager to log execution time when used. * Fixed an issue with UbisoftGroup where multiple threads would spawn.
245 lines
10 KiB
Python
245 lines
10 KiB
Python
import platform as pf
|
|
import re
|
|
from logging import getLogger
|
|
from typing import Tuple, List
|
|
|
|
from PyQt5.QtCore import QObject, pyqtSignal, QThreadPool, QSettings
|
|
from PyQt5.QtWidgets import QSizePolicy, QWidget, QFileDialog, QMessageBox
|
|
|
|
from rare.shared import LegendaryCoreSingleton
|
|
from rare.shared.workers.worker import Worker
|
|
from rare.ui.components.tabs.settings.legendary import Ui_LegendarySettings
|
|
from rare.utils.misc import format_size
|
|
from rare.widgets.indicator_edit import PathEdit, IndicatorLineEdit, IndicatorReasonsCommon
|
|
|
|
logger = getLogger("LegendarySettings")
|
|
|
|
|
|
class RefreshGameMetaWorker(Worker):
|
|
class Signals(QObject):
|
|
finished = pyqtSignal()
|
|
|
|
def __init__(self, platforms: List[str], include_unreal: bool):
|
|
super(RefreshGameMetaWorker, self).__init__()
|
|
self.signals = RefreshGameMetaWorker.Signals()
|
|
self.core = LegendaryCoreSingleton()
|
|
if platforms:
|
|
self.platforms = platforms
|
|
else:
|
|
self.platforms = ["Windows"]
|
|
self.skip_ue = not include_unreal
|
|
|
|
def run_real(self) -> None:
|
|
for platform in self.platforms:
|
|
self.core.get_game_and_dlc_list(
|
|
True, platform=platform, force_refresh=True, skip_ue=self.skip_ue
|
|
)
|
|
self.signals.finished.emit()
|
|
|
|
|
|
class LegendarySettings(QWidget, Ui_LegendarySettings):
|
|
def __init__(self, parent=None):
|
|
super(LegendarySettings, self).__init__(parent=parent)
|
|
self.setupUi(self)
|
|
self.settings = QSettings(self)
|
|
|
|
self.core = LegendaryCoreSingleton()
|
|
|
|
# Platform specific installation directory for macOS games
|
|
if pf.system() == "Darwin":
|
|
self.mac_install_dir = PathEdit(
|
|
self.core.get_default_install_dir("Mac"),
|
|
placeholder=self.tr("Default installation folder for macOS games"),
|
|
file_mode=QFileDialog.DirectoryOnly,
|
|
save_func=self.__mac_path_save,
|
|
)
|
|
self.install_dir_layout.addWidget(self.mac_install_dir)
|
|
|
|
# Platform-independent installation directory
|
|
self.install_dir = PathEdit(
|
|
self.core.get_default_install_dir(),
|
|
placeholder=self.tr("Default installation folder for Windows games"),
|
|
file_mode=QFileDialog.DirectoryOnly,
|
|
save_func=self.__win_path_save,
|
|
)
|
|
self.install_dir_layout.addWidget(self.install_dir)
|
|
|
|
# Max Workers
|
|
max_workers = self.core.lgd.config["Legendary"].getint(
|
|
"max_workers", fallback=0
|
|
)
|
|
self.max_worker_spin.setValue(max_workers)
|
|
self.max_worker_spin.valueChanged.connect(self.max_worker_save)
|
|
# Max memory
|
|
max_memory = self.core.lgd.config["Legendary"].getint("max_memory", fallback=0)
|
|
self.max_memory_spin.setValue(max_memory)
|
|
self.max_memory_spin.valueChanged.connect(self.max_memory_save)
|
|
# Preferred CDN
|
|
preferred_cdn = self.core.lgd.config["Legendary"].get(
|
|
"preferred_cdn", fallback=""
|
|
)
|
|
self.preferred_cdn_line.setText(preferred_cdn)
|
|
self.preferred_cdn_line.textChanged.connect(self.preferred_cdn_save)
|
|
# Disable HTTPS
|
|
disable_https = self.core.lgd.config["Legendary"].getboolean(
|
|
"disable_https", fallback=False
|
|
)
|
|
self.disable_https_check.setChecked(disable_https)
|
|
self.disable_https_check.stateChanged.connect(self.disable_https_save)
|
|
|
|
# Cleanup
|
|
self.clean_button.clicked.connect(lambda: self.cleanup(False))
|
|
self.clean_keep_manifests_button.clicked.connect(lambda: self.cleanup(True))
|
|
|
|
self.locale_edit = IndicatorLineEdit(
|
|
f"{self.core.language_code}-{self.core.country_code}",
|
|
edit_func=self.locale_edit_cb,
|
|
save_func=self.locale_save_cb,
|
|
horiz_policy=QSizePolicy.Minimum,
|
|
parent=self,
|
|
)
|
|
self.locale_layout.addWidget(self.locale_edit)
|
|
|
|
self.fetch_win32_check.setChecked(self.settings.value("win32_meta", False, bool))
|
|
self.fetch_win32_check.stateChanged.connect(
|
|
lambda: self.settings.setValue("win32_meta", self.fetch_win32_check.isChecked())
|
|
)
|
|
|
|
self.fetch_macos_check.setChecked(self.settings.value("macos_meta", pf.system() == "Darwin", bool))
|
|
self.fetch_macos_check.stateChanged.connect(
|
|
lambda: self.settings.setValue("macos_meta", self.fetch_macos_check.isChecked())
|
|
)
|
|
self.fetch_macos_check.setDisabled(pf.system() == "Darwin")
|
|
|
|
self.fetch_unreal_check.setChecked(self.settings.value("unreal_meta", False, bool))
|
|
self.fetch_unreal_check.stateChanged.connect(
|
|
lambda: self.settings.setValue("unreal_meta", self.fetch_unreal_check.isChecked())
|
|
)
|
|
|
|
self.exclude_non_asset_check.setChecked(
|
|
self.settings.value("exclude_non_asset", False, bool)
|
|
)
|
|
self.exclude_non_asset_check.stateChanged.connect(
|
|
lambda: self.settings.setValue("exclude_non_asset", self.exclude_non_asset_check.isChecked())
|
|
)
|
|
self.exclude_entitlements_check.setChecked(
|
|
self.settings.value("exclude_entitlements", False, bool)
|
|
)
|
|
self.exclude_entitlements_check.stateChanged.connect(
|
|
lambda: self.settings.setValue("exclude_entitlements", self.exclude_entitlements_check.isChecked())
|
|
)
|
|
|
|
self.refresh_metadata_button.clicked.connect(self.refresh_metadata)
|
|
# FIXME: Disable the button for now because it interferes with RareCore
|
|
self.refresh_metadata_button.setEnabled(False)
|
|
self.refresh_metadata_button.setVisible(False)
|
|
|
|
def refresh_metadata(self):
|
|
self.refresh_metadata_button.setDisabled(True)
|
|
platforms = []
|
|
if self.fetch_win32_check.isChecked():
|
|
platforms.append("Win32")
|
|
if self.fetch_macos_check.isChecked():
|
|
platforms.append("Mac")
|
|
worker = RefreshGameMetaWorker(platforms, self.fetch_unreal_check.isChecked())
|
|
worker.signals.finished.connect(lambda: self.refresh_metadata_button.setDisabled(False))
|
|
QThreadPool.globalInstance().start(worker)
|
|
|
|
@staticmethod
|
|
def locale_edit_cb(text: str) -> Tuple[bool, str, int]:
|
|
if text:
|
|
if re.match("^[a-zA-Z]{2,3}[-_][a-zA-Z]{2,3}$", text):
|
|
language, country = text.replace("_", "-").split("-")
|
|
text = "-".join([language.lower(), country.upper()])
|
|
if bool(re.match("^[a-z]{2,3}-[A-Z]{2,3}$", text)):
|
|
return True, text, IndicatorReasonsCommon.VALID
|
|
else:
|
|
return False, text, IndicatorReasonsCommon.WRONG_FORMAT
|
|
else:
|
|
return True, text, IndicatorReasonsCommon.VALID
|
|
|
|
def locale_save_cb(self, text: str):
|
|
if text:
|
|
self.core.egs.language_code, self.core.egs.country_code = text.split("-")
|
|
self.core.lgd.config.set("Legendary", "locale", text)
|
|
else:
|
|
if self.core.lgd.config.has_option("Legendary", "locale"):
|
|
self.core.lgd.config.remove_option("Legendary", "locale")
|
|
self.core.lgd.save_config()
|
|
|
|
def __mac_path_save(self, text: str) -> None:
|
|
self.__path_save(text, "mac_install_dir")
|
|
|
|
def __win_path_save(self, text: str) -> None:
|
|
self.__path_save(text, "install_dir")
|
|
if pf.system() != "Darwin":
|
|
self.__mac_path_save(text)
|
|
|
|
def __path_save(self, text: str, option: str = "Windows"):
|
|
self.core.lgd.config["Legendary"][option] = text
|
|
if not text and option in self.core.lgd.config["Legendary"].keys():
|
|
self.core.lgd.config["Legendary"].pop(option)
|
|
else:
|
|
logger.debug(f"Set %s option in config to %s", option, text)
|
|
self.core.lgd.save_config()
|
|
|
|
def max_worker_save(self, workers: str):
|
|
if workers := int(workers):
|
|
self.core.lgd.config.set("Legendary", "max_workers", str(workers))
|
|
else:
|
|
self.core.lgd.config.remove_option("Legendary", "max_workers")
|
|
self.core.lgd.save_config()
|
|
|
|
def max_memory_save(self, memory: str):
|
|
if memory := int(memory):
|
|
self.core.lgd.config.set("Legendary", "max_memory", str(memory))
|
|
else:
|
|
self.core.lgd.config.remove_option("Legendary", "max_memory")
|
|
self.core.lgd.save_config()
|
|
|
|
def preferred_cdn_save(self, cdn: str):
|
|
if cdn:
|
|
self.core.lgd.config.set("Legendary", "preferred_cdn", cdn.strip())
|
|
else:
|
|
self.core.lgd.config.remove_option("Legendary", "preferred_cdn")
|
|
self.core.lgd.save_config()
|
|
|
|
def disable_https_save(self, checked: int):
|
|
self.core.lgd.config.set(
|
|
"Legendary", "disable_https", str(bool(checked)).lower()
|
|
)
|
|
self.core.lgd.save_config()
|
|
|
|
def cleanup(self, keep_manifests: bool):
|
|
before = self.core.lgd.get_dir_size()
|
|
logger.debug("Removing app metadata...")
|
|
app_names = set(g.app_name for g in self.core.get_assets(update_assets=False))
|
|
self.core.lgd.clean_metadata(app_names)
|
|
|
|
if not keep_manifests:
|
|
logger.debug("Removing manifests...")
|
|
installed = [
|
|
(ig.app_name, ig.version, ig.platform) for ig in self.core.get_installed_list()
|
|
]
|
|
installed.extend(
|
|
(ig.app_name, ig.version, ig.platform) for ig in self.core.get_installed_dlc_list()
|
|
)
|
|
self.core.lgd.clean_manifests(installed)
|
|
|
|
logger.debug("Removing tmp data")
|
|
self.core.lgd.clean_tmp_data()
|
|
|
|
after = self.core.lgd.get_dir_size()
|
|
logger.info(
|
|
f"Cleanup complete! Removed {(before - after) / 1024 / 1024:.02f} MiB."
|
|
)
|
|
if (before - after) > 0:
|
|
QMessageBox.information(
|
|
self,
|
|
"Cleanup",
|
|
self.tr("Cleanup complete! Successfully removed {}").format(
|
|
format_size(before - after)
|
|
),
|
|
)
|
|
else:
|
|
QMessageBox.information(self, "Cleanup", "Nothing to clean")
|