parent
2b7a12db0d
commit
35240bcd6a
2 changed files with 92 additions and 2 deletions
|
@ -1,9 +1,11 @@
|
|||
import os
|
||||
from typing import Union, List
|
||||
from dataclasses import field, dataclass
|
||||
from multiprocessing import Queue
|
||||
|
||||
from PyQt5.QtCore import QObject, pyqtSignal
|
||||
|
||||
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
|
||||
|
@ -22,6 +24,9 @@ class InstallOptionsModel:
|
|||
update: bool = False
|
||||
silent: bool = False
|
||||
|
||||
def set_no_install(self, enabled: bool) -> None:
|
||||
self.no_install = enabled
|
||||
|
||||
|
||||
@dataclass
|
||||
class InstallDownloadModel:
|
||||
|
@ -44,6 +49,49 @@ class InstallQueueItemModel:
|
|||
return (self.status_q is not None) and (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]
|
||||
|
||||
|
||||
@dataclass
|
||||
class ApiResults:
|
||||
game_list: list = None
|
||||
|
|
|
@ -3,19 +3,22 @@ import math
|
|||
import os
|
||||
import platform
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from logging import getLogger
|
||||
from typing import Tuple
|
||||
|
||||
import requests
|
||||
from PIL import Image, UnidentifiedImageError
|
||||
from PyQt5.QtCore import pyqtSignal, QSettings
|
||||
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, QRunnable, QSettings
|
||||
from PyQt5.QtGui import QPalette, QColor, QPixmap
|
||||
|
||||
from .models import PathSpec
|
||||
|
||||
# Windows
|
||||
|
||||
if platform.system() == "Windows":
|
||||
from win32com.client import Dispatch # pylint: disable=E0401
|
||||
from win32com.client import Dispatch # pylint: disable=E0401
|
||||
|
||||
from rare import languages_path, resources_path, image_dir
|
||||
# Mac not supported
|
||||
|
@ -418,3 +421,42 @@ def text_color_for_background(background: Tuple[int, int, int]) -> Tuple[int,
|
|||
return 255, 255, 255
|
||||
else:
|
||||
return 0, 0, 0
|
||||
|
||||
|
||||
class WineResolverSignals(QObject):
|
||||
result_ready = pyqtSignal(str)
|
||||
|
||||
|
||||
class WineResolver(QRunnable):
|
||||
|
||||
def __init__(self, path: str, app_name: str, core: LegendaryCore):
|
||||
super(WineResolver, self).__init__()
|
||||
self.setAutoDelete(True)
|
||||
self.signals = WineResolverSignals()
|
||||
self.wine_env = os.environ.copy()
|
||||
self.wine_env.update(core.get_app_environment(app_name))
|
||||
self.wine_env['WINEDLLOVERRIDES'] = 'winemenubuilder=d;mscoree=d;mshtml=d;'
|
||||
self.wine_env['DISPLAY'] = ''
|
||||
self.wine_binary = core.lgd.config.get(
|
||||
app_name, 'wine_executable',
|
||||
fallback=core.lgd.config.get('default', 'wine_executable', fallback='wine'))
|
||||
self.winepath_binary = os.path.join(os.path.dirname(self.wine_binary), 'winepath')
|
||||
self.path = PathSpec(core, app_name).cook(path)
|
||||
|
||||
@pyqtSlot()
|
||||
def run(self):
|
||||
path = self.path.strip().replace('/', '\\')
|
||||
cmd = 'cd {} & cd'.format(path)
|
||||
# [self.wine_binary, 'cmd', '/c', 'echo', path] if path not exists alternative
|
||||
proc = subprocess.Popen([self.wine_binary, 'cmd', '/c', cmd],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||
env=self.wine_env, shell=False, text=True)
|
||||
out, err = proc.communicate()
|
||||
# Clean wine output
|
||||
out = out.strip().strip('"')
|
||||
proc = subprocess.Popen([self.winepath_binary, '-u', out],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||
env=self.wine_env, shell=False, text=True)
|
||||
out, err = proc.communicate()
|
||||
real_path = os.path.realpath(out.strip())
|
||||
self.signals.result_ready.emit(real_path)
|
||||
|
|
Loading…
Reference in a new issue