1
0
Fork 0
mirror of synced 2024-05-18 19:42:54 +12:00
Rare/rare/components/tabs/games/game_info/game_settings.py
loathingKernel 980bac5c4e
LaunchSettings: Fix browsing the wrong directory if override exe is set
The dialog would default to CWD because the contents of the line edit
where not an absolute path.
2024-02-22 17:26:38 +02:00

201 lines
7.8 KiB
Python

import os.path
import platform as pf
from logging import getLogger
from typing import Tuple
from PyQt5.QtCore import Qt, pyqtSlot
from PyQt5.QtGui import QShowEvent
from PyQt5.QtWidgets import QFileDialog, QComboBox, QLineEdit
from legendary.models.game import Game, InstalledGame
from rare.components.tabs.settings.widgets.env_vars import EnvVars
from rare.components.tabs.settings.widgets.game import GameSettingsBase
from rare.components.tabs.settings.widgets.launch import LaunchSettingsBase
from rare.components.tabs.settings.widgets.overlay import DxvkSettings
from rare.components.tabs.settings.widgets.wrappers import WrapperSettings
from rare.models.game import RareGame
from rare.utils import config_helper as config
from rare.widgets.indicator_edit import PathEdit, IndicatorReasonsCommon
if pf.system() != "Windows":
from rare.components.tabs.settings.widgets.wine import WineSettings
if pf.system() in {"Linux", "FreeBSD"}:
from rare.components.tabs.settings.widgets.proton import ProtonSettings
from rare.components.tabs.settings.widgets.overlay import MangoHudSettings
logger = getLogger("GameSettings")
class GameWrapperSettings(WrapperSettings):
def __init__(self, parent=None):
super().__init__(parent=parent)
def load_settings(self, app_name: str):
self.app_name = app_name
class GameLaunchSettings(LaunchSettingsBase):
def __init__(self, parent=None):
super(GameLaunchSettings, self).__init__(GameWrapperSettings, parent=parent)
self.game: Game = None
self.igame: InstalledGame = None
self.skip_update_combo = QComboBox(self)
self.skip_update_combo.addItem(self.tr("Default"), None)
self.skip_update_combo.addItem(self.tr("No"), "false")
self.skip_update_combo.addItem(self.tr("Yes"), "true")
self.skip_update_combo.currentIndexChanged.connect(self.__skip_update_changed)
self.offline_combo = QComboBox(self)
self.offline_combo.addItem(self.tr("Default"), None)
self.offline_combo.addItem(self.tr("No"), "false")
self.offline_combo.addItem(self.tr("Yes"), "true")
self.offline_combo.currentIndexChanged.connect(self.__offline_changed)
self.override_exe_edit = PathEdit(
file_mode=QFileDialog.ExistingFile,
name_filters=["*.exe", "*.app"],
placeholder=self.tr("Relative path to the replacement executable"),
edit_func=self.__override_exe_edit_callback,
save_func=self.__override_exe_save_callback,
parent=self
)
self.launch_params_edit = QLineEdit(self)
self.launch_params_edit.setPlaceholderText(self.tr("Game specific command line arguments"))
self.launch_params_edit.textChanged.connect(self.__launch_params_changed)
self.main_layout.insertRow(0, self.tr("Skip update check"), self.skip_update_combo)
self.main_layout.insertRow(1, self.tr("Offline mode"), self.offline_combo)
self.main_layout.insertRow(2, self.tr("Launch parameters"), self.launch_params_edit)
self.main_layout.insertRow(3, self.tr("Override executable"), self.override_exe_edit)
def showEvent(self, a0: QShowEvent):
if a0.spontaneous():
return super().showEvent(a0)
skip_update = config.get_option(self.app_name, "skip_update_check", fallback=None)
self.skip_update_combo.setCurrentIndex(self.offline_combo.findData(skip_update, Qt.UserRole))
offline = config.get_option(self.app_name, "offline", fallback=None)
self.offline_combo.setCurrentIndex(self.offline_combo.findData(offline, Qt.UserRole))
if self.igame:
self.offline_combo.setEnabled(self.igame.can_run_offline)
self.override_exe_edit.setRootPath(self.igame.install_path)
else:
self.offline_combo.setEnabled(False)
self.override_exe_edit.setRootPath(os.path.expanduser("~/"))
launch_params = config.get_option(self.app_name, "start_params", "")
self.launch_params_edit.setText(launch_params)
override_exe = config.get_option(self.app_name, "override_exe", fallback="")
self.override_exe_edit.setText(override_exe)
return super().showEvent(a0)
@pyqtSlot(int)
def __skip_update_changed(self, index):
data = self.skip_update_combo.itemData(index, Qt.UserRole)
config.save_option(self.app_name, "skip_update_check", data)
def __override_exe_edit_callback(self, path: str) -> Tuple[bool, str, int]:
if not path or self.igame is None:
return True, path, IndicatorReasonsCommon.VALID
if not os.path.isabs(path):
path = os.path.join(self.igame.install_path, path)
# lk: Compare paths through python's commonpath because in windows we
# cannot compare as strings
# antonia disapproves of this
if os.path.commonpath([self.igame.install_path, path]) != self.igame.install_path:
return False, self.igame.install_path, IndicatorReasonsCommon.WRONG_PATH
if not os.path.exists(path):
return False, path, IndicatorReasonsCommon.WRONG_PATH
if not path.endswith(".exe") and not path.endswith(".app"):
return False, path, IndicatorReasonsCommon.WRONG_PATH
path = os.path.relpath(path, self.igame.install_path)
return True, path, IndicatorReasonsCommon.VALID
def __override_exe_save_callback(self, path: str):
config.save_option(self.app_name, "override_exe", path)
@pyqtSlot(int)
def __offline_changed(self, index):
data = self.skip_update_combo.itemData(index, Qt.UserRole)
config.save_option(self.app_name, "offline", data)
def __launch_params_changed(self, value) -> None:
config.save_option(self.app_name, "start_params", value)
def load_settings(self, rgame: RareGame):
self.game = rgame.game
self.igame = rgame.igame
self.app_name = rgame.app_name
self.wrappers_widget.load_settings(rgame.app_name)
if pf.system() != "Windows":
class GameWineSettings(WineSettings):
def load_settings(self, app_name):
self.app_name = app_name
if pf.system() in {"Linux", "FreeBSD"}:
class GameProtonSettings(ProtonSettings):
def load_settings(self, app_name: str):
self.app_name = app_name
class GameMangoHudSettings(MangoHudSettings):
def load_settings(self, app_name: str):
self.app_name = app_name
class GameDxvkSettings(DxvkSettings):
def load_settings(self, app_name: str):
self.app_name = app_name
class GameEnvVars(EnvVars):
def load_settings(self, app_name):
self.app_name = app_name
class GameSettings(GameSettingsBase):
def __init__(self, parent=None):
if pf.system() in {"Linux", "FreeBSD"}:
super(GameSettings, self).__init__(
GameLaunchSettings, GameDxvkSettings, GameEnvVars,
GameWineSettings, GameProtonSettings, GameMangoHudSettings,
parent=parent
)
elif pf.system() != "Windows":
super(GameSettings, self).__init__(
GameLaunchSettings, GameDxvkSettings, GameEnvVars,
GameWineSettings,
parent=parent
)
else:
super(GameSettings, self).__init__(
GameLaunchSettings, GameDxvkSettings, GameEnvVars,
parent=parent
)
def load_settings(self, rgame: RareGame):
self.set_title.emit(rgame.app_title)
self.app_name = rgame.app_name
self.launch.load_settings(rgame)
if pf.system() != "Windows":
self.wine.load_settings(rgame.app_name)
if pf.system() in {"Linux", "FreeBSD"}:
self.proton_tool.load_settings(rgame.app_name)
self.mangohud.load_settings(rgame.app_name)
self.dxvk.load_settings(rgame.app_name)
self.env_vars.load_settings(rgame.app_name)