2021-04-14 02:56:44 +12:00
|
|
|
import os
|
2021-06-21 07:55:31 +12:00
|
|
|
import platform
|
2021-09-14 08:27:37 +12:00
|
|
|
import webbrowser
|
2021-03-25 23:49:27 +13:00
|
|
|
from logging import getLogger
|
|
|
|
|
2021-09-14 08:27:37 +12:00
|
|
|
from PyQt5.QtCore import pyqtSignal, QProcess, QSettings, Qt, QByteArray, QProcessEnvironment
|
2021-09-09 05:22:45 +12:00
|
|
|
from PyQt5.QtGui import QPixmap
|
2021-09-16 08:16:50 +12:00
|
|
|
from PyQt5.QtWidgets import QGroupBox, QMessageBox, QAction, QLabel, QPushButton
|
2021-03-25 23:49:27 +13:00
|
|
|
|
2021-09-07 07:10:18 +12:00
|
|
|
from legendary.core import LegendaryCore
|
2021-09-14 08:27:37 +12:00
|
|
|
from legendary.models.game import InstalledGame, Game
|
2021-04-13 21:15:14 +12:00
|
|
|
from rare.components.dialogs.uninstall_dialog import UninstallDialog
|
2021-08-25 10:01:53 +12:00
|
|
|
from rare.components.extra.console import ConsoleWindow
|
2021-09-09 05:22:45 +12:00
|
|
|
from rare.utils import legendary_utils, utils
|
2021-04-14 02:56:44 +12:00
|
|
|
from rare.utils.utils import create_desktop_link
|
2021-03-25 23:49:27 +13:00
|
|
|
|
|
|
|
logger = getLogger("Game")
|
|
|
|
|
|
|
|
|
2021-03-27 01:29:26 +13:00
|
|
|
class BaseInstalledWidget(QGroupBox):
|
2021-03-25 23:49:27 +13:00
|
|
|
launch_signal = pyqtSignal(str)
|
2021-09-16 08:16:50 +12:00
|
|
|
show_info = pyqtSignal(Game)
|
2021-03-27 00:50:57 +13:00
|
|
|
finish_signal = pyqtSignal(str)
|
2021-04-13 21:15:14 +12:00
|
|
|
update_list = pyqtSignal()
|
2021-03-25 23:49:27 +13:00
|
|
|
proc: QProcess()
|
|
|
|
|
2021-09-14 08:27:37 +12:00
|
|
|
def __init__(self, igame: InstalledGame, core: LegendaryCore, pixmap: QPixmap, offline, is_origin: bool = False, game: Game = None):
|
2021-03-25 23:49:27 +13:00
|
|
|
super(BaseInstalledWidget, self).__init__()
|
2021-03-26 00:14:34 +13:00
|
|
|
self.igame = igame
|
2021-09-14 08:27:37 +12:00
|
|
|
self.is_origin = is_origin
|
2021-03-25 23:49:27 +13:00
|
|
|
self.core = core
|
2021-09-14 08:27:37 +12:00
|
|
|
if not game:
|
|
|
|
self.game = self.core.get_game(self.igame.app_name)
|
|
|
|
else:
|
|
|
|
self.game = game
|
2021-09-09 05:22:45 +12:00
|
|
|
self.image = QLabel()
|
2021-09-09 05:43:49 +12:00
|
|
|
self.image.setPixmap(pixmap.scaled(200, int(200 * 4 / 3), transformMode=Qt.SmoothTransformation))
|
2021-03-25 23:49:27 +13:00
|
|
|
self.game_running = False
|
2021-04-20 01:44:28 +12:00
|
|
|
self.offline = offline
|
2021-09-14 08:27:37 +12:00
|
|
|
if is_origin:
|
|
|
|
self.update_available = False
|
|
|
|
else:
|
|
|
|
self.update_available = self.core.get_asset(self.game.app_name, True).build_version != igame.version
|
2021-06-30 10:03:03 +12:00
|
|
|
self.data = QByteArray()
|
2021-03-27 06:23:22 +13:00
|
|
|
self.setContentsMargins(0, 0, 0, 0)
|
2021-08-14 08:51:36 +12:00
|
|
|
self.settings = QSettings()
|
2021-03-27 01:29:26 +13:00
|
|
|
|
2021-04-14 02:56:44 +12:00
|
|
|
self.setContextMenuPolicy(Qt.ActionsContextMenu)
|
|
|
|
launch = QAction(self.tr("Launch"), self)
|
|
|
|
launch.triggered.connect(self.launch)
|
|
|
|
self.addAction(launch)
|
|
|
|
|
2021-09-14 08:27:37 +12:00
|
|
|
if os.path.exists(os.path.expanduser(f"~/Desktop/{self.game.app_title}.desktop")) \
|
|
|
|
or os.path.exists(os.path.expanduser(f"~/Desktop/{self.game.app_title}.lnk")):
|
2021-04-14 05:08:49 +12:00
|
|
|
self.create_desktop = QAction(self.tr("Remove Desktop link"))
|
|
|
|
else:
|
|
|
|
self.create_desktop = QAction(self.tr("Create Desktop link"))
|
2021-04-14 04:01:25 +12:00
|
|
|
|
2021-04-14 05:08:49 +12:00
|
|
|
self.create_desktop.triggered.connect(lambda: self.create_desktop_link("desktop"))
|
|
|
|
self.addAction(self.create_desktop)
|
|
|
|
|
2021-06-21 07:55:31 +12:00
|
|
|
if platform.system() == "Linux":
|
2021-09-14 08:27:37 +12:00
|
|
|
start_menu_file = os.path.expanduser(f"~/.local/share/applications/{self.game.app_title}.desktop")
|
2021-06-21 07:55:31 +12:00
|
|
|
elif platform.system() == "Windows":
|
2021-05-12 03:29:35 +12:00
|
|
|
start_menu_file = os.path.expandvars("%appdata%/Microsoft/Windows/Start Menu")
|
|
|
|
else:
|
|
|
|
start_menu_file = ""
|
|
|
|
if os.path.exists(start_menu_file):
|
|
|
|
self.create_start_menu = QAction(self.tr("Remove start menu link"))
|
|
|
|
else:
|
|
|
|
self.create_start_menu = QAction(self.tr("Create start menu link"))
|
2021-04-14 02:56:44 +12:00
|
|
|
|
2021-05-12 03:29:35 +12:00
|
|
|
self.create_start_menu.triggered.connect(lambda: self.create_desktop_link("start_menu"))
|
|
|
|
self.addAction(self.create_start_menu)
|
2021-04-14 02:56:44 +12:00
|
|
|
|
2021-09-09 05:22:45 +12:00
|
|
|
reload_image = QAction(self.tr("Reload Image"), self)
|
|
|
|
reload_image.triggered.connect(self.reload_image)
|
|
|
|
self.addAction(reload_image)
|
|
|
|
|
2021-04-14 02:56:44 +12:00
|
|
|
uninstall = QAction(self.tr("Uninstall"), self)
|
|
|
|
uninstall.triggered.connect(self.uninstall)
|
|
|
|
self.addAction(uninstall)
|
|
|
|
|
2021-09-09 05:22:45 +12:00
|
|
|
def reload_image(self):
|
|
|
|
utils.download_image(self.game, True)
|
|
|
|
pm = utils.get_pixmap(self.game.app_name)
|
2021-09-09 05:43:49 +12:00
|
|
|
self.image.setPixmap(pm.scaled(200, int(200 * 4 / 3), transformMode=Qt.SmoothTransformation))
|
2021-09-09 05:22:45 +12:00
|
|
|
|
2021-04-14 04:01:25 +12:00
|
|
|
def create_desktop_link(self, type_of_link):
|
2021-06-21 08:03:14 +12:00
|
|
|
if platform.system() not in ["Windows", "Linux"]:
|
|
|
|
QMessageBox.warning(self, "Warning",
|
|
|
|
f"Create a Desktop link is currently not supported on {platform.system()}")
|
|
|
|
return
|
2021-04-14 04:01:25 +12:00
|
|
|
if type_of_link == "desktop":
|
|
|
|
path = os.path.expanduser(f"~/Desktop/")
|
|
|
|
elif type_of_link == "start_menu":
|
|
|
|
path = os.path.expanduser("~/.local/share/applications/")
|
2021-04-14 02:56:44 +12:00
|
|
|
else:
|
2021-04-14 04:01:25 +12:00
|
|
|
return
|
2021-09-14 08:27:37 +12:00
|
|
|
if not (os.path.exists(os.path.expanduser(f"{path}{self.game.app_title}.desktop"))
|
|
|
|
or os.path.exists(os.path.expanduser(f"{path}{self.game.app_title}.lnk"))):
|
|
|
|
if not create_desktop_link(self.game.app_name, self.core, type_of_link):
|
2021-06-21 07:55:31 +12:00
|
|
|
return
|
2021-04-14 04:01:25 +12:00
|
|
|
if type_of_link == "desktop":
|
|
|
|
self.create_desktop.setText(self.tr("Remove Desktop link"))
|
|
|
|
elif type_of_link == "start_menu":
|
|
|
|
self.create_start_menu.setText(self.tr("Remove Start menu link"))
|
|
|
|
else:
|
2021-09-14 08:27:37 +12:00
|
|
|
if os.path.exists(os.path.expanduser(f"{path}{self.game.app_title}.desktop")):
|
|
|
|
os.remove(os.path.expanduser(f"{path}{self.game.app_title}.desktop"))
|
|
|
|
elif os.path.exists(os.path.expanduser(f"{path}{self.game.app_title}.lnk")):
|
|
|
|
os.remove(os.path.expanduser(f"{path}{self.game.app_title}.lnk"))
|
2021-04-14 04:01:25 +12:00
|
|
|
|
|
|
|
if type_of_link == "desktop":
|
|
|
|
self.create_desktop.setText(self.tr("Create Desktop link"))
|
|
|
|
elif type_of_link == "start_menu":
|
|
|
|
self.create_start_menu.setText(self.tr("Create Start menu link"))
|
2021-04-14 02:56:44 +12:00
|
|
|
|
2021-03-25 23:49:27 +13:00
|
|
|
def launch(self, offline=False, skip_version_check=False):
|
2021-03-28 05:51:38 +13:00
|
|
|
if QSettings().value("confirm_start", False, bool):
|
|
|
|
if not QMessageBox.question(self, "Launch", self.tr("Do you want to launch {}").format(self.game.app_title),
|
|
|
|
QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes:
|
|
|
|
logger.info("Cancel Startup")
|
|
|
|
return 1
|
2021-09-14 08:27:37 +12:00
|
|
|
logger.info("Launching " + self.game.app_title)
|
|
|
|
if self.is_origin:
|
|
|
|
self.offline = offline = False
|
2021-04-20 01:44:28 +12:00
|
|
|
if offline or self.offline:
|
|
|
|
if not self.igame.can_run_offline:
|
2021-04-23 00:34:06 +12:00
|
|
|
QMessageBox.warning(self, "Offline",
|
|
|
|
self.tr("Game cannot run offline. Please start game in Online mode"))
|
2021-04-20 01:44:28 +12:00
|
|
|
return
|
2021-09-14 08:27:37 +12:00
|
|
|
if not self.is_origin:
|
|
|
|
try:
|
|
|
|
self.proc, params = legendary_utils.launch_game(self.core, self.game.app_name, offline,
|
|
|
|
skip_version_check=skip_version_check)
|
|
|
|
except Exception as e:
|
|
|
|
logger.error(e)
|
|
|
|
QMessageBox.warning(self, "Error",
|
|
|
|
str(e))
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
origin_uri = self.core.get_origin_uri(self.game.app_name, self.offline)
|
|
|
|
logger.info("Launch Origin Game: ")
|
|
|
|
if platform.system() == "Windows":
|
|
|
|
webbrowser.open(origin_uri)
|
|
|
|
return
|
|
|
|
wine_pfx = self.core.lgd.config.get(self.game.app_name, 'wine_prefix', fallback=os.path.expanduser("~/.wine"))
|
|
|
|
wine_binary = self.core.lgd.config.get(self.game.app_name, 'wine_executable', fallback="/usr/bin/wine")
|
|
|
|
env = self.core.get_app_environment(self.game.app_name, wine_pfx=wine_pfx)
|
2021-04-20 01:44:28 +12:00
|
|
|
|
2021-09-14 08:27:37 +12:00
|
|
|
if not wine_binary or not env.get('WINEPREFIX'):
|
|
|
|
logger.error(f'In order to launch Origin correctly you must specify the wine binary and prefix '
|
|
|
|
f'to use in the configuration file or command line. See the README for details.')
|
|
|
|
return
|
|
|
|
|
|
|
|
self.proc = QProcess()
|
|
|
|
self.proc.setProcessChannelMode(QProcess.MergedChannels)
|
|
|
|
# process.setWorkingDirectory()
|
|
|
|
environment = QProcessEnvironment()
|
|
|
|
for e in env:
|
|
|
|
environment.insert(e, env[e])
|
|
|
|
self.proc.setProcessEnvironment(environment)
|
|
|
|
|
|
|
|
params = [wine_binary, origin_uri]
|
2021-04-15 00:30:36 +12:00
|
|
|
|
2021-03-25 23:49:27 +13:00
|
|
|
if not self.proc:
|
|
|
|
logger.error("Could not start process")
|
|
|
|
return 1
|
|
|
|
self.proc.finished.connect(self.finished)
|
2021-08-14 08:51:36 +12:00
|
|
|
|
|
|
|
if self.settings.value("show_console", False, bool):
|
|
|
|
self.console = ConsoleWindow()
|
|
|
|
self.console.show()
|
|
|
|
self.proc.readyReadStandardOutput.connect(lambda: self.console.log(
|
|
|
|
bytes(self.proc.readAllStandardOutput()).decode("utf-8", errors="ignore")))
|
|
|
|
self.proc.readyReadStandardError.connect(lambda: self.console.error(
|
|
|
|
bytes(self.proc.readAllStandardOutput()).decode("utf-8", errors="ignore")))
|
|
|
|
|
|
|
|
else:
|
|
|
|
self.proc.readyReadStandardOutput.connect(self.stdout)
|
|
|
|
self.proc.readyReadStandardError.connect(self.stderr)
|
|
|
|
|
2021-03-27 06:23:22 +13:00
|
|
|
self.proc.start(params[0], params[1:])
|
2021-09-14 08:27:37 +12:00
|
|
|
self.launch_signal.emit(self.game.app_name)
|
2021-03-25 23:49:27 +13:00
|
|
|
self.game_running = True
|
2021-06-30 10:03:03 +12:00
|
|
|
|
2021-03-25 23:49:27 +13:00
|
|
|
return 0
|
2021-03-27 00:50:57 +13:00
|
|
|
|
2021-04-23 00:11:12 +12:00
|
|
|
def stdout(self):
|
|
|
|
data = self.proc.readAllStandardOutput()
|
2021-06-30 10:03:03 +12:00
|
|
|
stdout = bytes(data).decode("utf-8", errors="ignore")
|
2021-08-14 08:51:36 +12:00
|
|
|
print(stdout)
|
2021-04-23 00:11:12 +12:00
|
|
|
|
|
|
|
def stderr(self):
|
2021-06-30 10:03:03 +12:00
|
|
|
stderr = bytes(self.proc.readAllStandardError()).decode("utf-8", errors="ignore")
|
2021-08-14 08:51:36 +12:00
|
|
|
print(stderr)
|
2021-08-23 08:43:08 +12:00
|
|
|
logger.error(stderr)
|
2021-08-14 08:51:36 +12:00
|
|
|
# QMessageBox.warning(self, "Warning", stderr + "\nSee ~/.cache/rare/logs/")
|
2021-04-23 00:11:12 +12:00
|
|
|
|
2021-03-27 07:22:54 +13:00
|
|
|
def finished(self, exit_code):
|
2021-03-28 05:51:38 +13:00
|
|
|
logger.info("Game exited with exit code: " + str(exit_code))
|
2021-09-14 08:27:37 +12:00
|
|
|
if exit_code == 53 and self.is_origin:
|
2021-09-16 08:16:50 +12:00
|
|
|
msg_box = QMessageBox()
|
|
|
|
msg_box.setText(self.tr("Origin is not installed. Do you want to download installer file? "))
|
|
|
|
msg_box.addButton(QPushButton("Download"), QMessageBox.YesRole)
|
|
|
|
msg_box.addButton(QPushButton("Cancel"), QMessageBox.RejectRole)
|
|
|
|
resp = msg_box.exec()
|
|
|
|
# click install button
|
|
|
|
if resp == 0:
|
|
|
|
webbrowser.open("https://www.dm.origin.com/download")
|
|
|
|
|
2021-03-27 00:50:57 +13:00
|
|
|
self.finish_signal.emit(self.game.app_name)
|
2021-03-25 23:49:27 +13:00
|
|
|
self.game_running = False
|
2021-08-14 08:51:36 +12:00
|
|
|
if self.settings.value("show_console", False, bool):
|
|
|
|
self.console.log(f"Game exited with code: {exit_code}")
|
2021-04-13 21:15:14 +12:00
|
|
|
|
|
|
|
def uninstall(self):
|
|
|
|
infos = UninstallDialog(self.game).get_information()
|
|
|
|
if infos == 0:
|
|
|
|
print("Cancel Uninstall")
|
|
|
|
return
|
|
|
|
legendary_utils.uninstall(self.game.app_name, self.core, infos)
|
2021-05-18 06:22:29 +12:00
|
|
|
self.update_list.emit(self.game.app_name)
|