1
0
Fork 0
mirror of synced 2024-06-26 18:20:50 +12:00

Merge pull request #189 from Dummerle/change_some_settings

Change some settings
This commit is contained in:
Dummerle 2022-03-28 21:12:34 +02:00 committed by GitHub
commit ab385f334d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 1101 additions and 747 deletions

View file

@ -1,3 +1,3 @@
__version__ = "1.8.7"
__version__ = "1.8.8"
code_name = "Stellula Kakopo"

View file

@ -7,8 +7,9 @@ import sys
import time
import traceback
from argparse import Namespace
from datetime import datetime
from PyQt5.QtCore import Qt, QThreadPool, QSettings, QTranslator
from PyQt5.QtCore import Qt, QThreadPool, QSettings, QTranslator, QTimer
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QSystemTrayIcon, QMessageBox
from requests import HTTPError
@ -159,6 +160,19 @@ class App(QApplication):
self.launch_dialog.login()
dt_exp = datetime.fromisoformat(self.core.lgd.userdata['expires_at'][:-1])
dt_now = datetime.utcnow()
td = abs(dt_exp - dt_now)
self.timer = QTimer()
self.timer.timeout.connect(self.re_login)
self.timer.start(int(td.total_seconds() - 60))
def re_login(self):
logger.info("Session expires shortly. Renew session")
self.core.login()
self.timer.stop()
self.timer.deleteLater()
def show_mainwindow(self):
if self.window_launched:
self.mainwindow.show()

View file

@ -2,7 +2,7 @@ import os
import platform
from logging import getLogger
from PyQt5.QtCore import Qt, pyqtSignal, QRunnable, QObject, QThreadPool
from PyQt5.QtCore import Qt, pyqtSignal, QRunnable, QObject, QThreadPool, QSettings
from PyQt5.QtWidgets import QDialog, QApplication
from legendary.core import LegendaryCore
from requests.exceptions import ConnectionError, HTTPError
@ -40,9 +40,10 @@ class ApiRequestWorker(QRunnable):
self.signals = LaunchDialogSignals()
self.setAutoDelete(True)
self.core = LegendaryCoreSingleton()
self.settings = QSettings()
def run(self) -> None:
if platform.system() == "Darwin" or "Mac" in self.core.get_installed_platforms():
if self.settings.value("mac_meta", platform.system() == "Darwin", bool):
try:
result = self.core.get_game_and_dlc_list(True, "Mac")
except HTTPError:
@ -50,9 +51,13 @@ class ApiRequestWorker(QRunnable):
self.signals.result.emit(result, "mac")
else:
self.signals.result.emit(([], {}), "mac")
try:
result = self.core.get_game_and_dlc_list(True, "Win32")
except HTTPError:
if self.settings.value("win32_meta", False, bool):
try:
result = self.core.get_game_and_dlc_list(True, "Win32")
except HTTPError:
result = [], {}
else:
result = [], {}
self.signals.result.emit(result, "32bit")

View file

@ -27,7 +27,7 @@ class BrowserLogin(QWidget, Ui_BrowserLogin):
self.core = core
self.sid_edit = IndicatorLineEdit(
ph_text=self.tr("Insert SID here"), edit_func=self.text_changed, parent=self
placeholder=self.tr("Insert SID here"), edit_func=self.text_changed, parent=self
)
self.link_text.setText(self.login_url)
self.copy_button.setIcon(icon("mdi.content-copy", "fa.copy"))

View file

@ -43,8 +43,8 @@ class ConsoleWindow(QWidget):
def log(self, text: str, end: str = "\n"):
self.console.log(text + end)
def error(self, text):
self.console.error(text)
def error(self, text, end: str = "\n"):
self.console.error(text + end)
class Console(QPlainTextEdit):
@ -55,11 +55,13 @@ class Console(QPlainTextEdit):
self._cursor_output = self.textCursor()
def log(self, text):
self._cursor_output.insertText(text)
html = f"<p style=\"color:#999;white-space:pre\">{text}</p>"
self._cursor_output.insertHtml(html)
self.scroll_to_last_line()
def error(self, text):
self._cursor_output.insertHtml(f'<font color="Red">{text}</font>')
html = f"<p style=\"color:#eee;white-space:pre\">{text}</p>"
self._cursor_output.insertHtml(html)
self.scroll_to_last_line()
def scroll_to_last_line(self):

View file

@ -1,5 +1,4 @@
import os
import time
from logging import getLogger
from PyQt5.QtCore import Qt, QSettings, QTimer, QSize

View file

@ -3,6 +3,7 @@ import webbrowser
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QMessageBox, QLabel, QPushButton
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton
from rare.utils.utils import icon
class MiniWidget(QWidget):
@ -18,7 +19,7 @@ class MiniWidget(QWidget):
self.layout.addWidget(QLabel(self.tr("Logged in as {}").format(username)))
self.open_browser = QPushButton(self.tr("Account settings"))
self.open_browser = QPushButton(icon("fa.external-link"), self.tr("Account settings"))
self.open_browser.clicked.connect(
lambda: webbrowser.open(
"https://www.epicgames.com/account/personal?productName=epicgames"

View file

@ -18,7 +18,7 @@ class GameInfoTabs(SideTabWidget):
self.info = GameInfo(self, game_utils)
self.addTab(self.info, self.tr("Information"))
self.settings = GameSettings(self.core, self)
self.settings = GameSettings(self)
self.addTab(self.settings, self.tr("Settings"))
self.dlc_list = dlcs
@ -30,12 +30,12 @@ class GameInfoTabs(SideTabWidget):
def update_game(self, app_name: str):
self.setCurrentIndex(1)
self.info.update_game(app_name)
self.settings.update_game(app_name)
self.settings.load_settings(app_name)
# DLC Tab: Disable if no dlcs available
if (
len(self.dlc_list.get(self.core.get_game(app_name).catalog_item_id, []))
== 0
len(self.dlc_list.get(self.core.get_game(app_name).catalog_item_id, []))
== 0
):
self.setTabEnabled(3, False)
else:

View file

@ -1,75 +1,29 @@
import os
import platform
from logging import getLogger
from pathlib import Path
from typing import Tuple
from PyQt5.QtCore import QSettings, QThreadPool, Qt
from PyQt5.QtWidgets import (
QWidget,
QFileDialog,
QMessageBox,
QLabel,
QPushButton,
QSizePolicy
)
from legendary.core import LegendaryCore
from legendary.models.game import InstalledGame, Game
from PyQt5.QtCore import Qt, QThreadPool
from PyQt5.QtWidgets import QSizePolicy, QPushButton, QLabel, QFileDialog, QMessageBox
from legendary.models.game import Game, InstalledGame
from rare.components.tabs.settings.linux import LinuxSettings
from rare.components.tabs.settings.widgets.wrapper import WrapperSettings
from rare.ui.components.tabs.games.game_info.game_settings import Ui_GameSettings
from rare.components.tabs.settings.widgets.env_vars import EnvVars
from rare.components.tabs.settings import DefaultGameSettings
from rare.components.tabs.settings.widgets.pre_launch import PreLaunchSettings
from rare.utils import config_helper
from rare.utils.extra_widgets import PathEdit
from rare.utils.utils import WineResolver, get_raw_save_path
from rare.utils.utils import icon
from rare.utils.utils import icon, WineResolver, get_raw_save_path
logger = getLogger("GameSettings")
def find_proton_wrappers():
possible_proton_wrappers = []
compatibilitytools_dirs = [
os.path.expanduser("~/.steam/steam/steamapps/common"),
"/usr/share/steam/compatibilitytools.d",
os.path.expanduser("~/.steam/compatibilitytools.d"),
os.path.expanduser("~/.steam/root/compatibilitytools.d"),
]
for c in compatibilitytools_dirs:
if os.path.exists(c):
for i in os.listdir(c):
proton = os.path.join(c, i, "proton")
compatibilitytool = os.path.join(c, i, "compatibilitytool.vdf")
toolmanifest = os.path.join(c, i, "toolmanifest.vdf")
if os.path.exists(proton) and (
os.path.exists(compatibilitytool) or os.path.exists(toolmanifest)
):
wrapper = f'"{proton}" run'
possible_proton_wrappers.append(wrapper)
if not possible_proton_wrappers:
logger.warning("Unable to find any Proton version")
return possible_proton_wrappers
class GameSettings(QWidget, Ui_GameSettings):
class GameSettings(DefaultGameSettings):
game: Game
igame: InstalledGame
# variable to no update when changing game
change = False
def __init__(self, core: LegendaryCore, parent):
super(GameSettings, self).__init__(parent=parent)
self.setupUi(self)
self.core = core
self.settings = QSettings()
self.wrapper_settings = WrapperSettings()
def __init__(self, parent=None):
super(GameSettings, self).__init__(False, parent)
self.pre_launch_settings = PreLaunchSettings()
self.launch_settings_group.layout().addRow(
QLabel("Wrapper"), self.wrapper_settings
QLabel(self.tr("Pre launch command")), self.pre_launch_settings
)
self.cloud_save_path_edit = PathEdit(
@ -103,49 +57,15 @@ class GameSettings(QWidget, Ui_GameSettings):
f"{self.game.app_name}/auto_sync_cloud", self.cloud_sync.isChecked()
)
)
self.override_exe_edit.textChanged.connect(
lambda text: self.save_line_edit("override_exe", text)
)
self.launch_params.textChanged.connect(
lambda x: self.save_line_edit("start_params", x)
)
if platform.system() != "Windows":
self.possible_proton_wrappers = find_proton_wrappers()
self.proton_wrapper.addItems(self.possible_proton_wrappers)
self.proton_wrapper.currentIndexChanged.connect(self.change_proton)
self.proton_prefix = PathEdit(
file_type=QFileDialog.DirectoryOnly,
edit_func=self.proton_prefix_edit,
save_func=self.proton_prefix_save,
placeholder=self.tr("Please select path for proton prefix")
)
self.proton_prefix_layout.addWidget(self.proton_prefix)
self.linux_settings = LinuxAppSettings()
# FIXME: Remove the spacerItem and margins from the linux settings
# FIXME: This should be handled differently at soem point in the future
self.linux_settings.layout().setContentsMargins(0, 0, 0, 0)
for item in [
self.linux_settings.layout().itemAt(idx)
for idx in range(self.linux_settings.layout().count())
]:
if item.spacerItem():
self.linux_settings.layout().removeItem(item)
del item
# FIXME: End of FIXME
self.linux_settings_layout.addWidget(self.linux_settings)
self.linux_settings_layout.setAlignment(Qt.AlignTop)
else:
self.linux_settings_widget.setVisible(False)
self.game_settings_layout.setAlignment(Qt.AlignTop)
self.linux_settings.mangohud.set_wrapper_activated.connect(
lambda active: self.wrapper_settings.add_wrapper("mangohud")
if active else self.wrapper_settings.delete_wrapper("mangohud"))
self.env_vars = EnvVars(self)
self.game_settings_contents_layout.addWidget(self.env_vars)
def compute_save_path(self):
if (
self.core.is_installed(self.game.app_name)
@ -155,12 +75,17 @@ class GameSettings(QWidget, Ui_GameSettings):
new_path = self.core.get_save_path(self.game.app_name)
except Exception as e:
logger.warning(str(e))
resolver = WineResolver(
get_raw_save_path(self.game), self.game.app_name
)
if not resolver.wine_env.get("WINEPREFIX"):
self.cloud_save_path_edit.setText("")
QMessageBox.warning(self, "Warning", "No wine prefix selected. Please set it in settings")
return
self.cloud_save_path_edit.setText(self.tr("Loading"))
self.cloud_save_path_edit.setDisabled(True)
self.compute_save_path_button.setDisabled(True)
resolver = WineResolver(
get_raw_save_path(self.game), self.game.app_name, self.core
)
app_name = self.game.app_name[:]
resolver.signals.result_ready.connect(
lambda x: self.wine_resolver_finished(x, app_name)
@ -228,61 +153,9 @@ class GameSettings(QWidget, Ui_GameSettings):
config_helper.remove_option(self.game.app_name, option)
config_helper.save_config()
def change_proton(self, i):
if self.change:
# First combo box entry: Don't use Proton
if i == 0:
self.wrapper_settings.delete_wrapper("proton")
config_helper.remove_option(self.game.app_name, "no_wine")
config_helper.remove_option(f"{self.game.app_name}.env", "STEAM_COMPAT_DATA_PATH")
config_helper.remove_option(f"{self.game.app_name}.env", "STEAM_COMPAT_CLIENT_INSTALL_PATH")
self.proton_prefix.setEnabled(False)
# lk: TODO: This has to be fixed properly.
# lk: It happens because of the widget update. Mask it for now behind disabling the save button
self.linux_settings.wine_groupbox.setEnabled(True)
else:
self.proton_prefix.setEnabled(True)
self.linux_settings.wine_groupbox.setEnabled(False)
wrapper = self.possible_proton_wrappers[i - 1]
self.wrapper_settings.add_wrapper(wrapper)
config_helper.add_option(self.game.app_name, "no_wine", "true")
config_helper.add_option(
f"{self.game.app_name}.env",
"STEAM_COMPAT_DATA_PATH",
os.path.expanduser("~/.proton"),
)
config_helper.add_option(
f"{self.game.app_name}.env",
"STEAM_COMPAT_CLIENT_INSTALL_PATH",
str(Path.home().joinpath(".steam", "steam"))
)
self.proton_prefix.setText(os.path.expanduser("~/.proton"))
# Don't use Wine
self.linux_settings.wine_exec.setText("")
self.linux_settings.wine_prefix.setText("")
config_helper.save_config()
def proton_prefix_edit(self, text: str) -> Tuple[bool, str, str]:
if not text:
text = os.path.expanduser("~/.proton")
return True, text, ""
parent = os.path.dirname(text)
return os.path.exists(parent), text, PathEdit.reasons.dir_not_exist
def proton_prefix_save(self, text: str):
config_helper.add_option(
f"{self.game.app_name}.env", "STEAM_COMPAT_DATA_PATH", text
)
config_helper.save_config()
def update_game(self, app_name: str):
def load_settings(self, app_name):
self.change = False
super(GameSettings, self).load_settings(app_name)
self.game = self.core.get_game(app_name)
self.igame = self.core.get_installed_game(self.game.app_name)
if self.igame:
@ -314,34 +187,12 @@ class GameSettings(QWidget, Ui_GameSettings):
self.skip_update.setCurrentIndex(0)
self.title.setTitle(self.game.app_title)
self.wrapper_settings.load_settings(app_name)
if platform.system() != "Windows":
self.linux_settings.update_game(app_name)
if self.igame and self.igame.platform == "Mac":
self.linux_settings_widget.setVisible(False)
else:
self.linux_settings_widget.setVisible(True)
proton = self.wrapper_settings.wrappers.get("proton", None)
if proton:
proton = proton.text.replace('"', "")
self.proton_prefix.setEnabled(True)
self.proton_wrapper.setCurrentText(
f'"{proton.replace(" run", "")}" run'
)
proton_prefix = self.core.lgd.config.get(
f"{app_name}.env",
"STEAM_COMPAT_DATA_PATH",
fallback=Path.home().joinpath(".proton"),
)
self.proton_prefix.setText(proton_prefix)
self.linux_settings.wine_groupbox.setEnabled(False)
else:
self.proton_wrapper.setCurrentIndex(0)
self.proton_prefix.setEnabled(False)
self.linux_settings.wine_groupbox.setEnabled(True)
if not self.game.supports_cloud_saves:
self.cloud_group.setEnabled(False)
self.cloud_save_path_edit.setText("")
@ -362,21 +213,7 @@ class GameSettings(QWidget, Ui_GameSettings):
self.override_exe_edit.setText(
self.core.lgd.config.get(self.game.app_name, "override_exe", fallback="")
)
self.pre_launch_settings.load_settings(app_name)
self.change = True
self.env_vars.update_game(app_name)
class LinuxAppSettings(LinuxSettings):
def __init__(self):
super(LinuxAppSettings, self).__init__()
def update_game(self, app_name):
self.name = app_name
self.wine_prefix.setText(self.load_prefix())
self.wine_exec.setText(self.load_setting(self.name, "wine_executable"))
self.dxvk.load_settings(self.name)
self.mangohud.load_settings(self.name)

View file

@ -2,18 +2,18 @@ import datetime
import os
import platform
import shutil
import webbrowser
from dataclasses import dataclass
from logging import getLogger
from PyQt5.QtCore import QObject, QSettings, QProcess, QProcessEnvironment, pyqtSignal
from PyQt5.QtCore import QObject, QSettings, QProcess, QProcessEnvironment, pyqtSignal, QUrl
from PyQt5.QtGui import QDesktopServices
from PyQt5.QtWidgets import QMessageBox, QPushButton
from legendary.models.game import LaunchParameters, InstalledGame
from legendary.models.game import LaunchParameters
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton
from rare.components.dialogs.uninstall_dialog import UninstallDialog
from rare.components.extra.console import ConsoleWindow
from rare.components.tabs.games import CloudSaveUtils
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton, ArgumentsSingleton
from rare.utils import legendary_utils
from rare.utils.meta import RareGameMeta
@ -97,6 +97,7 @@ class GameUtils(QObject):
except ValueError:
logger.info("Cancel startup")
self.sync_finished(app_name)
return
except AssertionError:
dont_sync_after_finish = True
else:
@ -167,162 +168,32 @@ class GameUtils(QObject):
)
return
process = GameProcess(app_name)
process.setProcessChannelMode(GameProcess.MergedChannels)
def _launch_real():
process = self._get_process(app_name, env)
self.console.log("\n"*2)
if game.third_party_store != "Origin":
self._launch_game(igame, process, offline, skip_update_check, ask_always_sync)
else:
self._launch_origin(app_name, process)
if game.third_party_store != "Origin":
if not offline:
if not skip_update_check and not self.core.is_noupdate_game(app_name):
# check updates
try:
latest = self.core.get_asset(
app_name, igame.platform, update=False
)
except ValueError:
self.finished.emit(app_name, self.tr("Metadata doesn't exist"))
return
else:
if latest.build_version != igame.version:
self.finished.emit(app_name, self.tr("Please update game"))
return
params: LaunchParameters = self.core.get_launch_parameters(
app_name=app_name, offline=offline, wine_bin=wine_bin, wine_pfx=wine_pfx
)
full_params = list()
if os.environ.get("container") == "flatpak":
full_params.extend(["flatpak-spawn", "--host"])
full_params.extend(params.launch_command)
full_params.append(
os.path.join(params.game_directory, params.game_executable)
)
full_params.extend(params.game_parameters)
full_params.extend(params.egl_parameters)
full_params.extend(params.user_parameters)
process.setWorkingDirectory(params.working_directory)
environment = QProcessEnvironment()
full_env = os.environ.copy()
full_env.update(params.environment)
for env, value in full_env.items():
environment.insert(env, value)
if platform.system() != "Windows":
# wine prefixes
for env in ["STEAM_COMPAT_DATA_PATH", "WINEPREFIX"]:
if val := full_env.get(env):
if not os.path.exists(val):
try:
os.makedirs(val)
except PermissionError as e:
logger.error(str(e))
QMessageBox.warning(
None,
"Error",
self.tr(
"Error while launching {}. No permission to create {} for {}"
).format(game.app_title, val, env),
)
process.deleteLater()
return
# check wine executable
if shutil.which(full_params[0]) is None:
# wine binary does not exist
QMessageBox.warning(
None,
"Warning",
self.tr(
"'{}' does not exist. Please change it in Settings"
).format(full_params[0]),
)
process.deleteLater()
return
if shutil.which(full_params[0]) is None:
QMessageBox.warning(None, "Warning", self.tr("'{}' does not exist").format(full_params[0]))
env = self.core.get_app_environment(app_name, wine_pfx=wine_pfx)
pre_cmd, wait = self.core.get_pre_launch_command(app_name)
if pre_cmd:
pre_cmd = pre_cmd.split()
pre_proc = self._launch_pre_command(env)
self.console.log("\n"*2)
pre_proc.start(pre_cmd[0], pre_cmd[1:])
if wait:
pre_proc.finished.connect(_launch_real)
return
process.setProcessEnvironment(environment)
process.game_finished.connect(self.game_finished)
running_game = RunningGameModel(
process=process, app_name=app_name, always_ask_sync=ask_always_sync
)
process.start(full_params[0], full_params[1:])
self.game_launched.emit(app_name)
self.signals.set_discord_rpc.emit(app_name)
logger.info(f"{game.app_title} launched")
self.running_games[game.app_name] = running_game
else:
origin_uri = self.core.get_origin_uri(game.app_name, self.args.offline)
logger.info("Launch Origin Game: ")
if platform.system() == "Windows":
webbrowser.open(origin_uri)
self.finished.emit(app_name, "")
return
wine_pfx = self.core.lgd.config.get(
game.app_name, "wine_prefix", fallback=os.path.expanduser("~/.wine")
)
if not wine_bin:
wine_bin = self.core.lgd.config.get(
game.app_name, "wine_executable", fallback="/usr/bin/wine"
)
if shutil.which(wine_bin) is None:
# wine binary does not exist
QMessageBox.warning(
None,
"Warning",
self.tr(
"Wine executable '{}' does not exist. Please change it in Settings"
).format(wine_bin),
)
process.deleteLater()
return
env = self.core.get_app_environment(game.app_name, wine_pfx=wine_pfx)
if not env.get("WINEPREFIX") and not os.path.exists("/usr/bin/wine"):
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."
)
self.finished.emit(
app_name,
self.tr("No wine executable selected. Please set it in settings"),
)
return
environment = QProcessEnvironment()
for e in env:
environment.insert(e, env[e])
process.setProcessEnvironment(environment)
process.finished.connect(lambda x: self.game_finished(x, game.app_name))
process.start(wine_bin, [origin_uri])
if QSettings().value("show_console", False, bool):
self.console.show()
process.readyReadStandardOutput.connect(
lambda: self.console.log(
str(process.readAllStandardOutput().data(), "utf-8", "ignore")
)
)
process.readyReadStandardError.connect(
lambda: self.console.error(
str(process.readAllStandardError().data(), "utf-8", "ignore")
)
)
_launch_real()
def game_finished(self, exit_code, app_name):
logger.info(f"Game exited with exit code: {exit_code}")
self.console.log(f"Game exited with code: {exit_code}")
self.signals.set_discord_rpc.emit("")
is_origin = self.core.get_game(app_name).third_party_store == "Origin"
if exit_code == 53 and is_origin:
if exit_code == 1 and is_origin:
msg_box = QMessageBox()
msg_box.setText(
self.tr(
@ -334,7 +205,8 @@ class GameUtils(QObject):
resp = msg_box.exec()
# click install button
if resp == 0:
webbrowser.open("https://www.dm.origin.com/download")
QDesktopServices.openUrl(QUrl("https://www.dm.origin.com/download"))
return
if exit_code != 0:
QMessageBox.warning(
None,
@ -351,16 +223,14 @@ class GameUtils(QObject):
self.running_games.pop(app_name)
self.finished.emit(app_name, "")
if QSettings().value("show_console", False, bool):
self.console.log(f"Game exited with code: {exit_code}")
if self.core.get_game(app_name).supports_cloud_saves:
if exit_code != 0:
r = QMessageBox.question(
None,
"Question",
self.tr(
"Game exited with code {}, which is not a normal code. It could be caused by a crash. Do you want to sync cloud saves"
"Game exited with code {}, which is not a normal code. "
"It could be caused by a crash. Do you want to sync cloud saves"
).format(exit_code),
buttons=QMessageBox.Yes | QMessageBox.No,
defaultButton=QMessageBox.Yes,
@ -369,6 +239,145 @@ class GameUtils(QObject):
return
self.cloud_save_utils.game_finished(app_name, game.always_ask_sync)
def _launch_pre_command(self, env: dict):
proc = QProcess()
environment = QProcessEnvironment()
for e in env:
environment.insert(e, env[e])
proc.setProcessEnvironment(environment)
proc.readyReadStandardOutput.connect(
lambda: self.console.log(
str(proc.readAllStandardOutput().data(), "utf-8", "ignore")
)
)
proc.readyReadStandardError.connect(
lambda: self.console.error(
str(proc.readAllStandardError().data(), "utf-8", "ignore")
)
)
return proc
def _get_process(self, app_name, env):
process = GameProcess(app_name)
environment = QProcessEnvironment()
for e in env:
environment.insert(e, env[e])
process.setProcessEnvironment(environment)
process.readyReadStandardOutput.connect(
lambda: self.console.log(
str(process.readAllStandardOutput().data(), "utf-8", "ignore")
)
)
process.readyReadStandardError.connect(
lambda: self.console.error(
str(process.readAllStandardError().data(), "utf-8", "ignore")
)
)
process.finished.connect(lambda x: self.game_finished(x, app_name))
process.stateChanged.connect(
lambda state: self.console.show()
if (state == QProcess.Running
and QSettings().value("show_console", False, bool))
else None
)
return process
def _launch_origin(self, app_name, process: QProcess):
origin_uri = self.core.get_origin_uri(app_name, self.args.offline)
logger.info("Launch Origin Game: ")
if platform.system() == "Windows":
QDesktopServices.openUrl(QUrl(origin_uri))
self.finished.emit(app_name, "")
return
command = self.core.get_app_launch_command(app_name)
if not os.path.exists(command[0]) and shutil.which(command[0]) is None:
# wine binary does not exist
QMessageBox.warning(
None, "Warning",
self.tr(
"'{}' does not exist. Please change it in Settings"
).format(command[0]),
)
process.deleteLater()
return
command.append(origin_uri)
process.start(command[0], command[1:])
def _launch_game(self, igame: InstalledGame, process: QProcess, offline: bool,
skip_update_check: bool, ask_always_sync: bool):
if not offline: # skip for update
if not skip_update_check and not self.core.is_noupdate_game(igame.app_name):
# check updates
try:
latest = self.core.get_asset(
igame.app_name, igame.platform, update=False
)
except ValueError:
self.finished.emit(igame.app_name, self.tr("Metadata doesn't exist"))
return
else:
if latest.build_version != igame.version:
self.finished.emit(igame.app_name, self.tr("Please update game"))
return
params: LaunchParameters = self.core.get_launch_parameters(
app_name=igame.app_name, offline=offline
)
full_params = list()
if os.environ.get("container") == "flatpak":
full_params.extend(["flatpak-spawn", "--host"])
full_params.extend(params.launch_command)
full_params.append(
os.path.join(params.game_directory, params.game_executable)
)
full_params.extend(params.game_parameters)
full_params.extend(params.egl_parameters)
full_params.extend(params.user_parameters)
process.setWorkingDirectory(params.working_directory)
if platform.system() != "Windows":
# wine prefixes
for env in ["STEAM_COMPAT_DATA_PATH", "WINEPREFIX"]:
if val := process.processEnvironment().value(env, ""):
if not os.path.exists(val):
try:
os.makedirs(val)
except PermissionError as e:
logger.error(str(e))
QMessageBox.warning(
None,
"Error",
self.tr(
"Error while launching {}. No permission to create {} for {}"
).format(igame.title, val, env),
)
process.deleteLater()
return
# check wine executable
if shutil.which(full_params[0]) is None:
QMessageBox.warning(None, "Warning", self.tr("'{}' does not exist").format(full_params[0]))
return
running_game = RunningGameModel(
process=process, app_name=igame.app_name, always_ask_sync=ask_always_sync
)
process.start(full_params[0], full_params[1:])
self.game_launched.emit(igame.app_name)
self.signals.set_discord_rpc.emit(igame.app_name)
logger.info(f"{igame.title} launched")
self.running_games[igame.app_name] = running_game
def sync_finished(self, app_name):
if app_name in self.launch_queue.keys():
self.cloud_save_finished.emit(app_name)

View file

@ -28,7 +28,7 @@ class GameListHeadBar(QWidget):
self.filter = QComboBox()
self.filter.addItems(
[
self.tr("All"),
self.tr("All games"),
self.tr("Installed only"),
self.tr("Offline Games"),
])

View file

@ -48,7 +48,7 @@ class EGLSyncGroup(QGroupBox, Ui_EGLSyncGroup):
if not self.core.egl.programdata_path:
self.egl_path_info.setText(self.tr("Updating..."))
wine_resolver = WineResolver(
PathSpec.egl_programdata, "default", self.core
PathSpec.egl_programdata, "default"
)
wine_resolver.signals.result_ready.connect(self.wine_resolver_cb)
self.thread_pool.start(wine_resolver)

View file

@ -87,7 +87,7 @@ class ImportGroup(QGroupBox, Ui_ImportGroup):
self.path_edit_layout.addWidget(self.path_edit)
self.app_name = IndicatorLineEdit(
ph_text=self.tr("Use in case the app name was not found automatically"),
placeholder=self.tr("Use in case the app name was not found automatically"),
completer=AppNameCompleter(
app_names=[
(i.app_name, i.app_title) for i in self.api_results.game_list

View file

@ -3,22 +3,21 @@ import platform
from rare.utils.extra_widgets import SideTabWidget
from .about import About
from .legendary import LegendarySettings
from .linux import LinuxSettings
from rare.components.tabs.settings.widgets.linux import LinuxSettings
from .rare import RareSettings
from .default_game_settings import DefaultGameSettings
class SettingsTab(SideTabWidget):
def __init__(self, parent=None):
super(SettingsTab, self).__init__(parent=parent)
about_tab = 2
about_tab = 3
self.rare_settings = RareSettings()
self.addTab(self.rare_settings, "Rare")
self.addTab(LegendarySettings(), "Legendary")
if platform.system() != "Windows":
self.addTab(LinuxSettings(), "Linux")
about_tab = 3
self.addTab(DefaultGameSettings(True, self), self.tr("Games"), self.tr("Default game settings"))
self.about = About()
self.addTab(self.about, "About", "About")

View file

@ -0,0 +1,127 @@
import platform
from logging import getLogger
from PyQt5.QtCore import QSettings, Qt
from PyQt5.QtWidgets import (
QWidget,
QLabel
)
from rare.components.tabs.settings.widgets.env_vars import EnvVars
from rare.components.tabs.settings.widgets.linux import LinuxSettings
from rare.components.tabs.settings.widgets.proton import ProtonSettings
from rare.components.tabs.settings.widgets.wrapper import WrapperSettings
from rare.shared import LegendaryCoreSingleton
from rare.ui.components.tabs.games.game_info.game_settings import Ui_GameSettings
from rare.utils import config_helper
logger = getLogger("GameSettings")
class DefaultGameSettings(QWidget, Ui_GameSettings):
# variable to no update when changing game
change = False
app_name: str
def __init__(self, is_default, parent=None):
super(DefaultGameSettings, self).__init__(parent=parent)
self.setupUi(self)
self.core = LegendaryCoreSingleton()
self.settings = QSettings()
self.wrapper_settings = WrapperSettings()
self.launch_settings_group.layout().addRow(
QLabel("Wrapper"), self.wrapper_settings
)
if platform.system() != "Windows":
self.linux_settings = LinuxAppSettings()
self.proton_settings = ProtonSettings(self.linux_settings, self.wrapper_settings)
self.game_settings_layout.replaceWidget(self.proton_placeholder, self.proton_settings)
self.proton_placeholder.deleteLater()
# FIXME: Remove the spacerItem and margins from the linux settings
# FIXME: This should be handled differently at soem point in the future
self.linux_settings.layout().setContentsMargins(0, 0, 0, 0)
for item in [
self.linux_settings.layout().itemAt(idx)
for idx in range(self.linux_settings.layout().count())
]:
if item.spacerItem():
self.linux_settings.layout().removeItem(item)
del item
# FIXME: End of FIXME
self.linux_settings_layout.addWidget(self.linux_settings)
self.linux_settings_layout.setAlignment(Qt.AlignTop)
self.game_settings_layout.setAlignment(Qt.AlignTop)
self.linux_settings.mangohud.set_wrapper_activated.connect(
lambda active: self.wrapper_settings.add_wrapper("mangohud")
if active else self.wrapper_settings.delete_wrapper("mangohud"))
else:
self.linux_settings_widget.setVisible(False)
self.env_vars = EnvVars(self)
self.game_settings_layout.addWidget(self.env_vars)
if is_default:
for i in range(4): # remove some entries which are not supported by default
self.launch_settings_layout.removeRow(0)
self.cloud_group.deleteLater()
self.load_settings("default")
def save_line_edit(self, option, value):
if value:
config_helper.add_option(self.game.app_name, option, value)
else:
config_helper.remove_option(self.game.app_name, option)
config_helper.save_config()
if option == "wine_prefix":
if self.game.supports_cloud_saves:
self.compute_save_path()
def update_combobox(self, i, option):
if self.change:
# remove section
if i:
if i == 1:
config_helper.add_option(self.game.app_name, option, "true")
if i == 2:
config_helper.add_option(self.game.app_name, option, "false")
else:
config_helper.remove_option(self.game.app_name, option)
config_helper.save_config()
def load_settings(self, app_name):
self.app_name = app_name
self.wrapper_settings.load_settings(app_name)
if platform.system() != "Windows":
self.linux_settings.update_game(app_name)
proton = self.wrapper_settings.wrappers.get("proton", "")
if proton:
proton = proton.text
self.proton_settings.load_settings(app_name, proton)
if proton:
self.linux_settings.wine_groupbox.setEnabled(False)
else:
self.linux_settings.wine_groupbox.setEnabled(True)
self.env_vars.update_game(app_name)
class LinuxAppSettings(LinuxSettings):
def __init__(self):
super(LinuxAppSettings, self).__init__()
def update_game(self, app_name):
self.name = app_name
self.wine_prefix.setText(self.load_prefix())
self.wine_exec.setText(self.load_setting(self.name, "wine_executable"))
self.dxvk.load_settings(self.name)
self.mangohud.load_settings(self.name)

View file

@ -1,13 +1,14 @@
import platform
import re
from logging import getLogger
from typing import Tuple
from PyQt5.QtCore import Qt, QRunnable, QObject, pyqtSignal, QThreadPool
from PyQt5.QtCore import Qt, QRunnable, QObject, pyqtSignal, QThreadPool, QSettings
from PyQt5.QtWidgets import QSizePolicy, QWidget, QFileDialog, QMessageBox
from rare.shared import LegendaryCoreSingleton
from rare.components.tabs.settings.widgets.eos import EosWidget
from rare.components.tabs.settings.widgets.ubisoft_activation import UbiActivationHelper
from rare.shared import LegendaryCoreSingleton
from rare.ui.components.tabs.settings.legendary import Ui_LegendarySettings
from rare.utils.extra_widgets import PathEdit, IndicatorLineEdit
from rare.utils.utils import get_size
@ -38,6 +39,7 @@ class LegendarySettings(QWidget, Ui_LegendarySettings):
def __init__(self, parent=None):
super(LegendarySettings, self).__init__(parent=parent)
self.setupUi(self)
self.settings = QSettings()
self.core = LegendaryCoreSingleton()
@ -89,6 +91,12 @@ class LegendarySettings(QWidget, Ui_LegendarySettings):
self.eos_widget = EosWidget()
self.left_layout.insertWidget(3, self.eos_widget, alignment=Qt.AlignTop)
self.win32_cb.setChecked(self.settings.value("win32_meta", False, bool))
self.win32_cb.stateChanged.connect(lambda: self.settings.setValue("win32_meta", self.win32_cb.isChecked()))
self.mac_cb.setChecked(self.settings.value("mac_meta", platform.system() == "Darwin", bool))
self.mac_cb.stateChanged.connect(lambda: self.settings.setValue("mac_meta", self.mac_cb.isChecked()))
self.refresh_game_meta_btn.clicked.connect(self.refresh_game_meta)
def refresh_game_meta(self):

View file

@ -1,4 +1,5 @@
import os
import shutil
from logging import getLogger
from PyQt5.QtWidgets import QFileDialog, QWidget
@ -37,6 +38,7 @@ class LinuxSettings(QWidget, Ui_LinuxSettings):
self.load_setting(self.name, "wine_executable"),
file_type=QFileDialog.ExistingFile,
name_filter="Wine executable (wine wine64)",
edit_func=lambda text: (os.path.exists(text) or not text, text, PathEdit.reasons.dir_not_exist),
save_func=lambda text: self.save_setting(
text, section=self.name, setting="wine_executable"
),
@ -46,9 +48,15 @@ class LinuxSettings(QWidget, Ui_LinuxSettings):
# dxvk
self.dxvk = DxvkSettings()
self.overlay_layout.addWidget(self.dxvk)
self.dxvk.load_settings(self.name)
self.mangohud = MangoHudSettings()
self.overlay_layout.addWidget(self.mangohud)
self.mangohud.load_settings(self.name)
if not shutil.which("mangohud"):
self.mangohud.setDisabled(True)
self.mangohud.setToolTip(self.tr("Mangohud is not installed or not in path"))
def load_prefix(self) -> str:
return self.load_setting(

View file

@ -0,0 +1,61 @@
import os
import shutil
from typing import Tuple
from PyQt5.QtWidgets import QHBoxLayout, QCheckBox, QFileDialog
from rare.shared import LegendaryCoreSingleton
from rare.utils import config_helper
from rare.utils.extra_widgets import IndicatorLineEdit, PathEdit
class PreLaunchSettings(QHBoxLayout):
app_name: str
def __init__(self):
super(PreLaunchSettings, self).__init__()
self.core = LegendaryCoreSingleton()
self.edit = PathEdit(
path="",
placeholder=self.tr("Path to script"),
file_type=QFileDialog.ExistingFile,
edit_func=self.edit_command,
save_func=self.save_pre_launch_command,
)
self.layout().addWidget(self.edit)
self.wait_check = QCheckBox(self.tr("Wait for finish"))
self.layout().addWidget(self.wait_check)
self.wait_check.stateChanged.connect(self.save_wait_finish)
def edit_command(self, text: str) -> Tuple[bool, str, str]:
if not text.strip():
return True, text, ""
if not os.path.isfile(text.split()[0]) and not shutil.which(text.split()[0]):
return False, text, IndicatorLineEdit.reasons.file_not_exist
else:
return True, text, ""
def save_pre_launch_command(self, text):
if text:
config_helper.add_option(self.app_name, "pre_launch_command", text)
self.wait_check.setDisabled(False)
else:
config_helper.remove_option(self.app_name, "pre_launch_command")
self.wait_check.setDisabled(True)
config_helper.remove_option(self.app_name, "pre_launch_wait")
def save_wait_finish(self):
config_helper.add_option(self.app_name, "pre_launch_wait", str(self.wait_check.isChecked()).lower())
def load_settings(self, app_name):
self.app_name = app_name
command = self.core.lgd.config.get(app_name, "pre_launch_command", fallback="")
self.edit.setText(command)
wait = self.core.lgd.config.getboolean(app_name, "pre_launch_wait", fallback=False)
self.wait_check.setChecked(wait)
self.wait_check.setEnabled(bool(command))

View file

@ -0,0 +1,141 @@
import os
from logging import getLogger
from pathlib import Path
from typing import Tuple
from PyQt5.QtWidgets import QGroupBox, QFileDialog
from rare.components.tabs.settings import LinuxSettings
from .wrapper import WrapperSettings
from rare.ui.components.tabs.settings.proton import Ui_ProtonSettings
from rare.utils import config_helper
from rare.utils.extra_widgets import PathEdit
from rare.shared import LegendaryCoreSingleton
logger = getLogger("Proton")
def find_proton_combos():
possible_proton_combos = []
compatibilitytools_dirs = [
os.path.expanduser("~/.steam/steam/steamapps/common"),
"/usr/share/steam/compatibilitytools.d",
os.path.expanduser("~/.steam/compatibilitytools.d"),
os.path.expanduser("~/.steam/root/compatibilitytools.d"),
]
for c in compatibilitytools_dirs:
if os.path.exists(c):
for i in os.listdir(c):
proton = os.path.join(c, i, "proton")
compatibilitytool = os.path.join(c, i, "compatibilitytool.vdf")
toolmanifest = os.path.join(c, i, "toolmanifest.vdf")
if os.path.exists(proton) and (
os.path.exists(compatibilitytool) or os.path.exists(toolmanifest)
):
wrapper = f'"{proton}" run'
possible_proton_combos.append(wrapper)
if not possible_proton_combos:
logger.warning("Unable to find any Proton version")
return possible_proton_combos
class ProtonSettings(QGroupBox, Ui_ProtonSettings):
app_name: str
changeable = True
def __init__(self, linux_settings: LinuxSettings, wrapper_settings: WrapperSettings):
super(ProtonSettings, self).__init__()
self.setupUi(self)
self._linux_settings = linux_settings
self._wrapper_settings = wrapper_settings
self.core = LegendaryCoreSingleton()
self.possible_proton_combos = find_proton_combos()
self.proton_combo.addItems(self.possible_proton_combos)
self.proton_combo.currentIndexChanged.connect(self.change_proton)
self.proton_prefix = PathEdit(
file_type=QFileDialog.DirectoryOnly,
edit_func=self.proton_prefix_edit,
save_func=self.proton_prefix_save,
placeholder=self.tr("Please select path for proton prefix")
)
self.layout().replaceWidget(self.placeholder_prefix_edit, self.proton_prefix)
self.placeholder_prefix_edit.deleteLater()
def change_proton(self, i):
if not self.changeable:
return
# First combo box entry: Don't use Proton
if i == 0:
self._wrapper_settings.delete_wrapper("proton")
config_helper.remove_option(self.app_name, "no_wine")
config_helper.remove_option(f"{self.app_name}.env", "STEAM_COMPAT_DATA_PATH")
config_helper.remove_option(f"{self.app_name}.env", "STEAM_COMPAT_CLIENT_INSTALL_PATH")
self.proton_prefix.setEnabled(False)
# lk: TODO: This has to be fixed properly.
# lk: It happens because of the widget update. Mask it for now behind disabling the save button
self._linux_settings.wine_groupbox.setEnabled(True)
else:
self.proton_prefix.setEnabled(True)
self._linux_settings.wine_groupbox.setEnabled(False)
wrapper = self.possible_proton_combos[i - 1]
self._wrapper_settings.add_wrapper(wrapper)
config_helper.add_option(self.app_name, "no_wine", "true")
config_helper.add_option(
f"{self.app_name}.env",
"STEAM_COMPAT_DATA_PATH",
os.path.expanduser("~/.proton"),
)
config_helper.add_option(
f"{self.app_name}.env",
"STEAM_COMPAT_CLIENT_INSTALL_PATH",
str(Path.home().joinpath(".steam", "steam"))
)
self.proton_prefix.setText(os.path.expanduser("~/.proton"))
# Don't use Wine
self._linux_settings.wine_exec.setText("")
self._linux_settings.wine_prefix.setText("")
config_helper.save_config()
def proton_prefix_edit(self, text: str) -> Tuple[bool, str, str]:
if not text:
text = os.path.expanduser("~/.proton")
return True, text, ""
parent_dir = os.path.dirname(text)
return os.path.exists(parent_dir), text, PathEdit.reasons.dir_not_exist
def proton_prefix_save(self, text: str):
if not self.changeable:
return
config_helper.add_option(
f"{self.app_name}.env", "STEAM_COMPAT_DATA_PATH", text
)
config_helper.save_config()
def load_settings(self, app_name: str, proton: str):
self.changeable = False
self.app_name = app_name
proton = proton.replace('"', "")
self.proton_prefix.setEnabled(bool(proton))
if proton:
print(proton)
self.proton_combo.setCurrentText(
f'"{proton.replace(" run", "")}" run'
)
else:
self.proton_combo.setCurrentIndex(0)
proton_prefix = self.core.lgd.config.get(
f"{app_name}.env",
"STEAM_COMPAT_DATA_PATH",
fallback=str(Path.home().joinpath(".proton")),
)
self.proton_prefix.setText(proton_prefix)
self.changeable = True

View file

@ -166,6 +166,9 @@ class WrapperSettings(QWidget, Ui_WrapperSettings):
self.widget_stack.setCurrentIndex(0)
if widget := self.wrappers.get(show_text, None):
widget.deleteLater()
widget = WrapperWidget(text, show_text, self.scroll_content)
self.scroll_content.layout().addWidget(widget)
self.adjust_scrollarea(
@ -173,7 +176,6 @@ class WrapperSettings(QWidget, Ui_WrapperSettings):
self.wrapper_scroll.horizontalScrollBar().maximum()
)
widget.delete_wrapper.connect(self.delete_wrapper)
self.wrappers[show_text] = widget
if not from_load:

View file

@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_GameSettings(object):
def setupUi(self, GameSettings):
GameSettings.setObjectName("GameSettings")
GameSettings.resize(545, 348)
GameSettings.resize(558, 357)
self.game_settings_layout = QtWidgets.QVBoxLayout(GameSettings)
self.game_settings_layout.setObjectName("game_settings_layout")
self.launch_settings_group = QtWidgets.QGroupBox(GameSettings)
@ -82,30 +82,12 @@ class Ui_GameSettings(object):
self.cloud_sync.setObjectName("cloud_sync")
self.cloud_layout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.cloud_sync)
self.game_settings_layout.addWidget(self.cloud_group)
self.proton_group = QtWidgets.QGroupBox(GameSettings)
self.proton_group.setObjectName("proton_group")
self.proton_layout = QtWidgets.QFormLayout(self.proton_group)
self.proton_placeholder = QtWidgets.QWidget(GameSettings)
self.proton_placeholder.setObjectName("proton_placeholder")
self.proton_layout = QtWidgets.QFormLayout(self.proton_placeholder)
self.proton_layout.setLabelAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.proton_layout.setObjectName("proton_layout")
self.proton_wrapper_label = QtWidgets.QLabel(self.proton_group)
self.proton_wrapper_label.setObjectName("proton_wrapper_label")
self.proton_layout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.proton_wrapper_label)
self.proton_wrapper = QtWidgets.QComboBox(self.proton_group)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.proton_wrapper.sizePolicy().hasHeightForWidth())
self.proton_wrapper.setSizePolicy(sizePolicy)
self.proton_wrapper.setObjectName("proton_wrapper")
self.proton_wrapper.addItem("")
self.proton_layout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.proton_wrapper)
self.proton_prefix_label = QtWidgets.QLabel(self.proton_group)
self.proton_prefix_label.setObjectName("proton_prefix_label")
self.proton_layout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.proton_prefix_label)
self.proton_prefix_layout = QtWidgets.QVBoxLayout()
self.proton_prefix_layout.setObjectName("proton_prefix_layout")
self.proton_layout.setLayout(2, QtWidgets.QFormLayout.FieldRole, self.proton_prefix_layout)
self.game_settings_layout.addWidget(self.proton_group)
self.game_settings_layout.addWidget(self.proton_placeholder)
self.linux_settings_widget = QtWidgets.QWidget(GameSettings)
self.linux_settings_widget.setObjectName("linux_settings_widget")
self.linux_settings_layout = QtWidgets.QVBoxLayout(self.linux_settings_widget)
@ -134,10 +116,6 @@ class Ui_GameSettings(object):
self.override_exe_edit.setPlaceholderText(_translate("GameSettings", "Relative path to launch executable"))
self.cloud_group.setTitle(_translate("GameSettings", "Cloud Saves"))
self.cloud_sync_label.setText(_translate("GameSettings", "Sync with cloud"))
self.proton_group.setTitle(_translate("GameSettings", "Proton Settings"))
self.proton_wrapper_label.setText(_translate("GameSettings", "Proton"))
self.proton_wrapper.setItemText(0, _translate("GameSettings", "Don\'t use Proton"))
self.proton_prefix_label.setText(_translate("GameSettings", "Prefix"))
if __name__ == "__main__":

View file

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>545</width>
<height>348</height>
<width>558</width>
<height>357</height>
</rect>
</property>
<property name="windowTitle">
@ -157,46 +157,11 @@
</widget>
</item>
<item>
<widget class="QGroupBox" name="proton_group">
<property name="title">
<string>Proton Settings</string>
</property>
<widget class="QWidget" name="proton_placeholder" native="true">
<layout class="QFormLayout" name="proton_layout">
<property name="labelAlignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<item row="1" column="0">
<widget class="QLabel" name="proton_wrapper_label">
<property name="text">
<string>Proton</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="proton_wrapper">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Don't use Proton</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="proton_prefix_label">
<property name="text">
<string>Prefix</string>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QVBoxLayout" name="proton_prefix_layout"/>
</item>
</layout>
</widget>
</item>

View file

@ -14,10 +14,52 @@ from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_LegendarySettings(object):
def setupUi(self, LegendarySettings):
LegendarySettings.setObjectName("LegendarySettings")
LegendarySettings.resize(552, 312)
LegendarySettings.resize(654, 498)
LegendarySettings.setWindowTitle("LegendarySettings")
self.legendary_layout = QtWidgets.QHBoxLayout(LegendarySettings)
self.legendary_layout.setObjectName("legendary_layout")
self.gridLayout = QtWidgets.QGridLayout(LegendarySettings)
self.gridLayout.setObjectName("gridLayout")
self.right_layout = QtWidgets.QVBoxLayout()
self.right_layout.setObjectName("right_layout")
self.locale_group = QtWidgets.QGroupBox(LegendarySettings)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.locale_group.sizePolicy().hasHeightForWidth())
self.locale_group.setSizePolicy(sizePolicy)
self.locale_group.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
self.locale_group.setObjectName("locale_group")
self.locale_layout = QtWidgets.QVBoxLayout(self.locale_group)
self.locale_layout.setObjectName("locale_layout")
self.right_layout.addWidget(self.locale_group, 0, QtCore.Qt.AlignTop)
self.cleanup_group = QtWidgets.QGroupBox(LegendarySettings)
self.cleanup_group.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
self.cleanup_group.setObjectName("cleanup_group")
self.cleanup_layout = QtWidgets.QVBoxLayout(self.cleanup_group)
self.cleanup_layout.setObjectName("cleanup_layout")
self.clean_keep_manifests_button = QtWidgets.QPushButton(self.cleanup_group)
self.clean_keep_manifests_button.setObjectName("clean_keep_manifests_button")
self.cleanup_layout.addWidget(self.clean_keep_manifests_button)
self.clean_button = QtWidgets.QPushButton(self.cleanup_group)
self.clean_button.setObjectName("clean_button")
self.cleanup_layout.addWidget(self.clean_button)
self.right_layout.addWidget(self.cleanup_group, 0, QtCore.Qt.AlignTop)
self.meta_group = QtWidgets.QGroupBox(LegendarySettings)
self.meta_group.setObjectName("meta_group")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.meta_group)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.win32_cb = QtWidgets.QCheckBox(self.meta_group)
self.win32_cb.setObjectName("win32_cb")
self.verticalLayout_2.addWidget(self.win32_cb)
self.mac_cb = QtWidgets.QCheckBox(self.meta_group)
self.mac_cb.setObjectName("mac_cb")
self.verticalLayout_2.addWidget(self.mac_cb)
self.refresh_game_meta_btn = QtWidgets.QPushButton(self.meta_group)
self.refresh_game_meta_btn.setObjectName("refresh_game_meta_btn")
self.verticalLayout_2.addWidget(self.refresh_game_meta_btn)
self.right_layout.addWidget(self.meta_group)
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.right_layout.addItem(spacerItem)
self.gridLayout.addLayout(self.right_layout, 0, 1, 1, 1)
self.left_layout = QtWidgets.QVBoxLayout()
self.left_layout.setObjectName("left_layout")
self.install_dir_group = QtWidgets.QGroupBox(LegendarySettings)
@ -104,46 +146,23 @@ class Ui_LegendarySettings(object):
self.verticalLayout = QtWidgets.QVBoxLayout(self.ubisoft_gb)
self.verticalLayout.setObjectName("verticalLayout")
self.left_layout.addWidget(self.ubisoft_gb, 0, QtCore.Qt.AlignTop)
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.left_layout.addItem(spacerItem)
self.legendary_layout.addLayout(self.left_layout)
self.right_layout = QtWidgets.QVBoxLayout()
self.right_layout.setObjectName("right_layout")
self.locale_group = QtWidgets.QGroupBox(LegendarySettings)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.locale_group.sizePolicy().hasHeightForWidth())
self.locale_group.setSizePolicy(sizePolicy)
self.locale_group.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
self.locale_group.setObjectName("locale_group")
self.locale_layout = QtWidgets.QVBoxLayout(self.locale_group)
self.locale_layout.setObjectName("locale_layout")
self.right_layout.addWidget(self.locale_group, 0, QtCore.Qt.AlignTop)
self.cleanup_group = QtWidgets.QGroupBox(LegendarySettings)
self.cleanup_group.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
self.cleanup_group.setObjectName("cleanup_group")
self.cleanup_layout = QtWidgets.QVBoxLayout(self.cleanup_group)
self.cleanup_layout.setObjectName("cleanup_layout")
self.clean_keep_manifests_button = QtWidgets.QPushButton(self.cleanup_group)
self.clean_keep_manifests_button.setObjectName("clean_keep_manifests_button")
self.cleanup_layout.addWidget(self.clean_keep_manifests_button)
self.clean_button = QtWidgets.QPushButton(self.cleanup_group)
self.clean_button.setObjectName("clean_button")
self.cleanup_layout.addWidget(self.clean_button)
self.refresh_game_meta_btn = QtWidgets.QPushButton(self.cleanup_group)
self.refresh_game_meta_btn.setObjectName("refresh_game_meta_btn")
self.cleanup_layout.addWidget(self.refresh_game_meta_btn)
self.right_layout.addWidget(self.cleanup_group, 0, QtCore.Qt.AlignTop)
spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.right_layout.addItem(spacerItem1)
self.legendary_layout.addLayout(self.right_layout)
self.left_layout.addItem(spacerItem1)
self.gridLayout.addLayout(self.left_layout, 0, 0, 1, 1)
self.retranslateUi(LegendarySettings)
QtCore.QMetaObject.connectSlotsByName(LegendarySettings)
def retranslateUi(self, LegendarySettings):
_translate = QtCore.QCoreApplication.translate
self.locale_group.setTitle(_translate("LegendarySettings", "Locale"))
self.cleanup_group.setTitle(_translate("LegendarySettings", "Cleanup"))
self.clean_keep_manifests_button.setText(_translate("LegendarySettings", "Clean, but keep manifests"))
self.clean_button.setText(_translate("LegendarySettings", "Remove everything"))
self.meta_group.setTitle(_translate("LegendarySettings", "Game metadata"))
self.win32_cb.setText(_translate("LegendarySettings", "Load 32 bit data"))
self.mac_cb.setText(_translate("LegendarySettings", "Load MacOS data"))
self.refresh_game_meta_btn.setText(_translate("LegendarySettings", "Refresh game meta"))
self.install_dir_group.setTitle(_translate("LegendarySettings", "Default Installation Directory"))
self.download_group.setTitle(_translate("LegendarySettings", "Download Settings"))
self.max_workers_label.setText(_translate("LegendarySettings", "Max Workers"))
@ -155,11 +174,6 @@ class Ui_LegendarySettings(object):
self.preferred_cdn_line.setPlaceholderText(_translate("LegendarySettings", "Default"))
self.disable_https_label.setText(_translate("LegendarySettings", "Disable HTTPS"))
self.ubisoft_gb.setTitle(_translate("LegendarySettings", "Link Ubisoft Games"))
self.locale_group.setTitle(_translate("LegendarySettings", "Locale"))
self.cleanup_group.setTitle(_translate("LegendarySettings", "Cleanup"))
self.clean_keep_manifests_button.setText(_translate("LegendarySettings", "Clean, but keep manifests"))
self.clean_button.setText(_translate("LegendarySettings", "Remove everything"))
self.refresh_game_meta_btn.setText(_translate("LegendarySettings", "Refresh game meta"))
if __name__ == "__main__":

View file

@ -1,266 +1,323 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LegendarySettings</class>
<widget class="QWidget" name="LegendarySettings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>552</width>
<height>312</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">LegendarySettings</string>
</property>
<layout class="QHBoxLayout" name="legendary_layout">
<item>
<layout class="QVBoxLayout" name="left_layout">
<item alignment="Qt::AlignTop">
<widget class="QGroupBox" name="install_dir_group">
<property name="title">
<string>Default Installation Directory</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<layout class="QVBoxLayout" name="install_dir_layout"/>
</widget>
</item>
<item alignment="Qt::AlignTop">
<widget class="QGroupBox" name="download_group">
<property name="title">
<string>Download Settings</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<layout class="QFormLayout" name="download_layout">
<property name="labelAlignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
<class>LegendarySettings</class>
<widget class="QWidget" name="LegendarySettings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>552</width>
<height>312</height>
</rect>
</property>
<item row="0" column="0">
<widget class="QLabel" name="max_workers_label">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Max Workers</string>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="max_workers_layout">
<item>
<widget class="QSpinBox" name="max_worker_spin">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<property name="windowTitle">
<string notr="true">LegendarySettings</string>
</property>
<layout class="QHBoxLayout" name="legendary_layout">
<item>
<widget class="QPushButton" name="clean_keep_manifests_button">
<property name="text">
<string>Clean, but keep manifests</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="clean_button">
<property name="text">
<string>Remove everything</string>
</property>
</widget>
</item>
</layout>
</widget>
<item>
<widget class="QGroupBox" name="meta_group">
<property name="title">
<string>Game metadata</string>
</property>
<property name="minimum">
<number>0</number>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QCheckBox" name="win32_cb">
<property name="text">
<string>Load 32 bit data</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="mac_cb">
<property name="text">
<string>Load MacOS data</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="refresh_game_meta_btn">
<property name="text">
<string>Refresh game meta</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="right_vspacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="maximum">
<number>16</number>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="max_workers_info_label">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>Less is slower (0: Default)</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="max_memory_label">
<property name="text">
<string>Max Memory</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="max_memory_layout">
<item>
<widget class="QSpinBox" name="max_memory_spin">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="suffix">
<string>MiB</string>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>10240</number>
</property>
<property name="singleStep">
<number>128</number>
</property>
<property name="value">
<number>1024</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="max_memory_info_label">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>Less is slower (0: Default)</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QLabel" name="preferred_cdn_label">
<property name="text">
<string>Preferred CDN</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="preferred_cdn_line">
<property name="placeholderText">
<string>Default</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="disable_https_label">
<property name="text">
<string>Disable HTTPS</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="disable_https_check">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item alignment="Qt::AlignTop">
<widget class="QGroupBox" name="ubisoft_gb">
<property name="title">
<string>Link Ubisoft Games</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<layout class="QVBoxLayout" name="verticalLayout"/>
</widget>
</item>
<item>
<spacer name="left_vspacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="right_layout">
<item alignment="Qt::AlignTop">
<widget class="QGroupBox" name="locale_group">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Locale</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<layout class="QVBoxLayout" name="locale_layout"/>
</widget>
</item>
<item alignment="Qt::AlignTop">
<widget class="QGroupBox" name="cleanup_group">
<property name="title">
<string>Cleanup</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<layout class="QVBoxLayout" name="cleanup_layout">
<item>
<widget class="QPushButton" name="clean_keep_manifests_button">
<property name="text">
<string>Clean, but keep manifests</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="clean_button">
<property name="text">
<string>Remove everything</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="refresh_game_meta_btn">
<property name="text">
<string>Refresh game meta</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="right_vspacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</spacer>
</item>
<item row="0" column="0">
<layout class="QVBoxLayout" name="left_layout">
<item alignment="Qt::AlignTop">
<widget class="QGroupBox" name="install_dir_group">
<property name="title">
<string>Default Installation Directory</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<layout class="QVBoxLayout" name="install_dir_layout"/>
</widget>
</item>
<item alignment="Qt::AlignTop">
<widget class="QGroupBox" name="download_group">
<property name="title">
<string>Download Settings</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<layout class="QFormLayout" name="download_layout">
<property name="labelAlignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<item row="0" column="0">
<widget class="QLabel" name="max_workers_label">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Max Workers</string>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="max_workers_layout">
<item>
<widget class="QSpinBox" name="max_worker_spin">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>16</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="max_workers_info_label">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>Less is slower (0: Default)</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="max_memory_label">
<property name="text">
<string>Max Memory</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="max_memory_layout">
<item>
<widget class="QSpinBox" name="max_memory_spin">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="suffix">
<string>MiB</string>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>10240</number>
</property>
<property name="singleStep">
<number>128</number>
</property>
<property name="value">
<number>1024</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="max_memory_info_label">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>Less is slower (0: Default)</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QLabel" name="preferred_cdn_label">
<property name="text">
<string>Preferred CDN</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="preferred_cdn_line">
<property name="placeholderText">
<string>Default</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="disable_https_label">
<property name="text">
<string>Disable HTTPS</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="disable_https_check">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item alignment="Qt::AlignTop">
<widget class="QGroupBox" name="ubisoft_gb">
<property name="title">
<string>Link Ubisoft Games</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<layout class="QVBoxLayout" name="verticalLayout"/>
</widget>
</item>
<item>
<spacer name="left_vspacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="right_layout">
<item alignment="Qt::AlignTop">
<widget class="QGroupBox" name="locale_group">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Locale</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<layout class="QVBoxLayout" name="locale_layout"/>
</widget>
</item>
<item alignment="Qt::AlignTop">
<widget class="QGroupBox" name="cleanup_group">
<property name="title">
<string>Cleanup</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<layout class="QVBoxLayout" name="cleanup_layout">
<item>
<widget class="QPushButton" name="clean_keep_manifests_button">
<property name="text">
<string>Clean, but keep manifests</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="clean_button">
<property name="text">
<string>Remove everything</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="refresh_game_meta_btn">
<property name="text">
<string>Refresh game meta</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="right_vspacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,58 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'rare/ui/components/tabs/settings/proton.ui'
#
# Created by: PyQt5 UI code generator 5.15.6
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_ProtonSettings(object):
def setupUi(self, ProtonSettings):
ProtonSettings.setObjectName("ProtonSettings")
ProtonSettings.resize(400, 300)
ProtonSettings.setWindowTitle("GroupBox")
self.formLayout = QtWidgets.QFormLayout(ProtonSettings)
self.formLayout.setObjectName("formLayout")
self.proton_wrapper_label = QtWidgets.QLabel(ProtonSettings)
self.proton_wrapper_label.setObjectName("proton_wrapper_label")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.proton_wrapper_label)
self.proton_combo = QtWidgets.QComboBox(ProtonSettings)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.proton_combo.sizePolicy().hasHeightForWidth())
self.proton_combo.setSizePolicy(sizePolicy)
self.proton_combo.setObjectName("proton_combo")
self.proton_combo.addItem("")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.proton_combo)
self.proton_prefix_label = QtWidgets.QLabel(ProtonSettings)
self.proton_prefix_label.setObjectName("proton_prefix_label")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.proton_prefix_label)
self.placeholder_prefix_edit = QtWidgets.QLineEdit(ProtonSettings)
self.placeholder_prefix_edit.setObjectName("placeholder_prefix_edit")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.placeholder_prefix_edit)
self.retranslateUi(ProtonSettings)
QtCore.QMetaObject.connectSlotsByName(ProtonSettings)
def retranslateUi(self, ProtonSettings):
_translate = QtCore.QCoreApplication.translate
ProtonSettings.setTitle(_translate("ProtonSettings", "Proton Settings"))
self.proton_wrapper_label.setText(_translate("ProtonSettings", "Proton"))
self.proton_combo.setItemText(0, _translate("ProtonSettings", "Don\'t use Proton"))
self.proton_prefix_label.setText(_translate("ProtonSettings", "Prefix"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
ProtonSettings = QtWidgets.QGroupBox()
ui = Ui_ProtonSettings()
ui.setupUi(ProtonSettings)
ProtonSettings.show()
sys.exit(app.exec_())

View file

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ProtonSettings</class>
<widget class="QGroupBox" name="ProtonSettings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">GroupBox</string>
</property>
<property name="title">
<string>Proton Settings</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="proton_wrapper_label">
<property name="text">
<string>Proton</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="proton_combo">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Don't use Proton</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="proton_prefix_label">
<property name="text">
<string>Prefix</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="placeholder_prefix_edit"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -150,6 +150,7 @@ class IndicatorReasons:
wrong_format = QCoreApplication.translate("IndicatorReasons", "Given text has wrong format")
game_not_installed = QCoreApplication.translate("IndicatorReasons", "Game is not installed or does not exist")
dir_not_exist = QCoreApplication.translate("IndicatorReasons", "Directory does not exist")
file_not_exist = QCoreApplication.translate("IndicatorReasons", "File does not exist")
wrong_path = QCoreApplication.translate("IndicatorReasons", "Wrong Directory")
@ -161,7 +162,7 @@ class IndicatorLineEdit(QWidget):
def __init__(
self,
text: str = "",
ph_text: str = "",
placeholder: str = "",
completer: QCompleter = None,
edit_func: Callable[[str], Tuple[bool, str, str]] = None,
save_func: Callable[[str], None] = None,
@ -176,7 +177,7 @@ class IndicatorLineEdit(QWidget):
# Add line_edit
self.line_edit = QLineEdit(self)
self.line_edit.setObjectName("line_edit")
self.line_edit.setPlaceholderText(ph_text)
self.line_edit.setPlaceholderText(placeholder)
self.line_edit.setSizePolicy(horiz_policy, QSizePolicy.Fixed)
# Add hint_label to line_edit
self.line_edit.setLayout(QHBoxLayout())
@ -199,7 +200,7 @@ class IndicatorLineEdit(QWidget):
self.indicator_label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
self.layout.addWidget(self.indicator_label)
if not ph_text:
if not placeholder:
_translate = QCoreApplication.translate
self.line_edit.setPlaceholderText(
_translate(self.__class__.__name__, "Default")
@ -318,9 +319,12 @@ class PathEdit(IndicatorLineEdit):
self.compl_model.setIconProvider(PathEditIconProvider())
self.compl_model.setRootPath(path)
self.completer.setModel(self.compl_model)
edit_func = self._wrap_edit_function(edit_func)
super(PathEdit, self).__init__(
text=path,
ph_text=placeholder,
placeholder=placeholder,
completer=self.completer,
edit_func=edit_func,
save_func=save_func,
@ -357,6 +361,13 @@ class PathEdit(IndicatorLineEdit):
self.line_edit.setText(names[0])
self.compl_model.setRootPath(names[0])
def _wrap_edit_function(self, edit_function: Callable[[str], Tuple[bool, str, str]]):
if edit_function:
return lambda text: edit_function(os.path.expanduser(text)
if text.startswith("~") else text)
else:
return edit_function
class SideTabBar(QTabBar):
def __init__(self, parent=None):

View file

@ -451,14 +451,16 @@ class WineResolverSignals(QObject):
class WineResolver(QRunnable):
def __init__(self, path: str, app_name: str, core: LegendaryCore):
def __init__(self, path: str, app_name: str):
super(WineResolver, self).__init__()
self.signals = WineResolverSignals()
self.setAutoDelete(True)
self.wine_env = os.environ.copy()
core = LegendaryCoreSingleton()
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",