1
0
Fork 0
mirror of synced 2024-06-26 10:11:19 +12:00

WineResolver and PathSpec (#117)

Add it, but not use it
This commit is contained in:
Stelios Tsampas 2021-10-24 22:23:31 +03:00 committed by GitHub
parent 2b7a12db0d
commit 35240bcd6a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 92 additions and 2 deletions

View file

@ -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

View file

@ -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)