Execute the edit callback function in a thread. By executing it in a thread we don't have to wait for longer validation procedures to finish to continue updating the UI. This is most notable in the MoveGamePopUp which is heavy on disk IO. Because we cannot use special text formatting in a thread, the indicator messages have been reworked while also becoming extensible. A dictionary of extended reasons can be specified through the `IndicatorLineEdit.extend_reasons()` method. The dictionary has to follow the following format ``` python { MyIndicatorReasons.REASON: self.tr("Reason message") MyIndicatorReasons.OTHER_REASON: self.tr("Other reason message") } ``` In the above example `MyIndicatorReasons` is a subclass of `IndicatorReasons` which should be specified as follows ``` python MyIndicatorReasons(IndicatorReasons): REASON = auto() OTHER_REASON = auto() ```
142 lines
5.3 KiB
Python
142 lines
5.3 KiB
Python
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, IndicatorReasonsCommon
|
|
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.prefix_layout.addWidget(self.proton_prefix)
|
|
|
|
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, int]:
|
|
if not text:
|
|
text = os.path.expanduser("~/.proton")
|
|
return True, text, IndicatorReasonsCommon.VALID
|
|
parent_dir = os.path.dirname(text)
|
|
return os.path.exists(parent_dir), text, IndicatorReasonsCommon.DIR_NOT_EXISTS
|
|
|
|
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
|