ee5adce18b
The indirect return is stored in a `LgndrIndirectStatus` object that provides checking and unpacking features Lgndr: `LgndrInstallGameArgs.install_tag` default to None Lgndr: add default `move` method. Lgndr: monkeypatch `dlm.status_queue` after preparing a download to reduce `InstallQueueItemModel` InstallOptionsModel: implement `as_install_kwargs` to pass only relevant arguments to `LgndrInstallGameArgs` in InstallDialog InstallOptionsModel: rename `sdl_list` to `install_tag` as they were the same thing LegendaryUtils: Update to use `LgndrIndirectStatus` UninstallDialog: Add option to keep configuration decoupled from keeping game data GameUtils: Add messagebox to show error messages from legendary after uninstalling a game InstallDialog: Update to use `LgndrIndirectStatus` InstallDialog: Update selectable download handling to match legendary's DownloadThread: Remove multiple instance variables, instead reference them directly from `InstallQueueItemModel` instance ImportGroup: Replace `info_label` with an `ElideLabel` for displaying long messages ImportGroup: Don't translate message strings in the `ImportWorker` GameInfo: Call `repair()` if needed after verification instead of handling it locally GamesTab: Fix string matching for capitalized strings and scroll to top on when searching
106 lines
3.5 KiB
Python
106 lines
3.5 KiB
Python
import os
|
|
import platform as pf
|
|
from dataclasses import field, dataclass
|
|
from multiprocessing import Queue
|
|
from typing import Union, List, Optional, Callable, Dict
|
|
|
|
from legendary.core import LegendaryCore
|
|
from legendary.downloader.mp.manager import DLManager
|
|
from legendary.models.downloading import AnalysisResult, ConditionCheckResult
|
|
from legendary.models.game import Game, InstalledGame
|
|
|
|
|
|
@dataclass
|
|
class InstallOptionsModel:
|
|
app_name: str
|
|
base_path: str = ""
|
|
shared_memory: int = 1024
|
|
max_workers: int = os.cpu_count() * 2
|
|
force: bool = False
|
|
platform: str = "Windows"
|
|
install_tag: Optional[List[str]] = None
|
|
order_opt: bool = False
|
|
repair_mode: bool = False
|
|
repair_and_update: bool = False
|
|
no_install: bool = False
|
|
ignore_space: bool = False
|
|
# Rare's internal arguments
|
|
# FIXME: Do we really need all of these?
|
|
create_shortcut: bool = True
|
|
overlay: bool = False
|
|
update: bool = False
|
|
silent: bool = False
|
|
install_preqs: bool = pf.system() == "Windows"
|
|
|
|
def __post_init__(self):
|
|
self.sdl_prompt: Callable[[str, str], list] = lambda app_name, title: self.install_tag
|
|
|
|
def as_install_kwargs(self) -> Dict:
|
|
return {
|
|
k: getattr(self, k)
|
|
for k in self.__dict__
|
|
if k not in ["update", "silent", "create_shortcut", "overlay", "install_preqs"]
|
|
}
|
|
|
|
|
|
@dataclass
|
|
class InstallDownloadModel:
|
|
dlmanager: DLManager
|
|
analysis: AnalysisResult
|
|
igame: InstalledGame
|
|
game: Game
|
|
repair: bool
|
|
repair_file: str
|
|
res: ConditionCheckResult
|
|
|
|
|
|
@dataclass
|
|
class InstallQueueItemModel:
|
|
download: Optional[InstallDownloadModel] = None
|
|
options: Optional[InstallOptionsModel] = None
|
|
|
|
def __bool__(self):
|
|
return (self.download is not None) and (self.options is not None)
|
|
|
|
|
|
class PathSpec:
|
|
__egl_path_vars = {
|
|
"{appdata}": os.path.expandvars("%LOCALAPPDATA%"),
|
|
"{userdir}": os.path.expandvars("%USERPROFILE%/Documents"),
|
|
# '{userprofile}': os.path.expandvars('%userprofile%'), # possibly wrong
|
|
"{usersavedgames}": os.path.expandvars("%USERPROFILE%/Saved Games"),
|
|
}
|
|
egl_appdata: str = r"%LOCALAPPDATA%\EpicGamesLauncher\Saved\Config\Windows"
|
|
egl_programdata: str = r"%PROGRAMDATA%\Epic\EpicGamesLauncher\Data\Manifests"
|
|
wine_programdata: str = r"dosdevices/c:/ProgramData"
|
|
|
|
def __init__(self, core: LegendaryCore = None, app_name: str = "default"):
|
|
if core is not None:
|
|
self.__egl_path_vars.update({"{epicid}": core.lgd.userdata["account_id"]})
|
|
self.app_name = app_name
|
|
|
|
def cook(self, path: str) -> str:
|
|
cooked_path = [self.__egl_path_vars.get(p.lower(), p) for p in path.split("/")]
|
|
return os.path.join(*cooked_path)
|
|
|
|
@property
|
|
def wine_egl_programdata(self):
|
|
return self.egl_programdata.replace("\\", "/").replace("%PROGRAMDATA%", self.wine_programdata)
|
|
|
|
def wine_egl_prefixes(self, results: int = 0) -> Union[List[str], str]:
|
|
possible_prefixes = [
|
|
os.path.expanduser("~/.wine"),
|
|
os.path.expanduser("~/Games/epic-games-store"),
|
|
]
|
|
prefixes = []
|
|
for prefix in possible_prefixes:
|
|
if os.path.exists(os.path.join(prefix, self.wine_egl_programdata)):
|
|
prefixes.append(prefix)
|
|
if not prefixes:
|
|
return str()
|
|
if not results:
|
|
return prefixes
|
|
elif results == 1:
|
|
return prefixes[0]
|
|
else:
|
|
return prefixes[:results]
|