1
0
Fork 0
mirror of synced 2024-05-20 04:22:58 +12:00
Rare/rare/components/tabs/settings/widgets/overlay.py
loathingKernel cd1743cb92 GameSettings: Re-strucure settings widgets
The default widgets only implement the settings for the `default` "app_name"
The game specific widgets sub-class the default widgets and implement
whatever they additionally need locally.

Remove multiple calls to save config and save when the game settings gets hidden.
2024-02-12 21:52:07 +02:00

334 lines
13 KiB
Python

from abc import abstractmethod
from enum import Enum, IntEnum
from logging import getLogger
from typing import List, Dict, Tuple, Any, Union
from PyQt5.QtCore import QCoreApplication, pyqtSignal
from PyQt5.QtGui import QIntValidator, QDoubleValidator, QShowEvent
from PyQt5.QtWidgets import QGroupBox, QCheckBox, QLineEdit, QComboBox
from rare.shared import LegendaryCoreSingleton
from rare.ui.components.tabs.settings.widgets.overlay import Ui_OverlaySettings
from rare.utils import config_helper as config
logger = getLogger("GameOverlays")
class OverlayLineEdit(QLineEdit):
def __init__(self, parent=None):
super(OverlayLineEdit, self).__init__(parent=parent)
self.valueChanged = self.textChanged
self.setValue = self.setText
def setDefault(self):
self.setText("")
def getValue(self):
return self.text()
class OverlayComboBox(QComboBox):
def __init__(self, parent=None):
super(OverlayComboBox, self).__init__(parent=parent)
self.valueChanged = self.currentIndexChanged
self.getValue = self.currentText
self.setValue = self.setCurrentText
def setDefault(self):
self.setCurrentIndex(0)
class CustomOption:
option: str
widget: Union[OverlayLineEdit, OverlayComboBox]
@classmethod
def string_input(cls, option: str, placeholder: str):
tmp = cls()
tmp.option = option
tmp.widget = OverlayLineEdit()
tmp.widget.setPlaceholderText(placeholder)
return tmp
@classmethod
def number_input(cls, option: str, placeholder: Any, is_float: bool = False):
tmp = cls()
tmp.option = option
tmp.widget = OverlayLineEdit()
tmp.widget.setPlaceholderText(str(placeholder))
validator = QDoubleValidator() if is_float else QIntValidator()
tmp.widget.setValidator(validator)
return tmp
@classmethod
def select_input(cls, option: str, values: List[str]):
"""options: default value in options[0]"""
tmp = cls()
tmp.option = option
tmp.widget = OverlayComboBox()
tmp.widget.addItems(values)
return tmp
class ActivationStates(IntEnum):
DEFAULT = -1
HIDDEN = 0
ENABLED = 1
class OverlaySettings(QGroupBox):
# str: option key
environ_changed = pyqtSignal(str)
def __init__(self, parent=None):
super(OverlaySettings, self).__init__(parent=parent)
self.ui = Ui_OverlaySettings()
self.ui.setupUi(self)
self.core = LegendaryCoreSingleton()
self.envvar_name: str = None
self.force_disabled: str = None
self.app_name: str = "default"
self.checkboxes: Dict[str, QCheckBox] = {}
self.values: Dict[str, Union[OverlayLineEdit, OverlayComboBox]] = {}
self.ui.options_group.setTitle(self.tr("Custom options"))
self.ui.show_overlay_combo.currentIndexChanged.connect(self.update_settings)
def setupWidget(
self,
checkbox_map: List[Tuple[str, str]],
custom_map: List[Tuple[CustomOption, str]],
envvar_name: str,
force_disabled: str,
):
self.envvar_name = envvar_name
self.force_disabled = force_disabled
for i, (variable, text) in enumerate(checkbox_map):
checkbox = QCheckBox(text)
self.ui.options_grid.addWidget(checkbox, i // 4, i % 4)
self.checkboxes[variable] = checkbox
checkbox.stateChanged.connect(self.update_settings)
for option, text in custom_map:
widget = option.widget
self.ui.options_form.addRow(text, widget)
self.values[option.option] = widget
widget.valueChanged.connect(self.update_settings)
@abstractmethod
def set_activation_state(self, state: ActivationStates):
raise NotImplemented
def update_settings(self):
if self.ui.show_overlay_combo.currentIndex() == 0:
# System default
config.remove_envvar(self.app_name, self.envvar_name)
self.environ_changed.emit(self.envvar_name)
self.ui.options_group.setDisabled(True)
self.set_activation_state(ActivationStates.DEFAULT)
return
elif self.ui.show_overlay_combo.currentIndex() == 1:
# hidden
config.set_envvar(self.app_name, self.envvar_name, self.force_disabled)
self.environ_changed.emit(self.envvar_name)
self.ui.options_group.setDisabled(True)
self.set_activation_state(ActivationStates.HIDDEN)
return
elif self.ui.show_overlay_combo.currentIndex() == 2:
self.ui.options_group.setDisabled(False)
# custom options
var_names = []
for var_name, cb in self.checkboxes.items():
if cb.isChecked():
var_names.append(var_name)
for var_name, widget in self.values.items():
text = widget.getValue()
if text not in ["default", ""]:
var_names.append(f"{var_name}={text}")
if not var_names:
list(self.checkboxes.values())[0].setChecked(True)
var_names.append(list(self.checkboxes.keys())[0])
config.set_envvar(self.app_name, self.envvar_name, ",".join(var_names))
self.environ_changed.emit(self.envvar_name)
self.set_activation_state(ActivationStates.ENABLED)
def showEvent(self, a0: QShowEvent):
if a0.spontaneous():
return super().showEvent(a0)
for checkbox in self.checkboxes.values():
checkbox.setChecked(False)
for widget in self.values.values():
widget.setDefault()
options = config.get_envvar(self.app_name, self.envvar_name, fallback=None)
if options is None:
logger.debug(f"No Overlay settings found {self.envvar_name}")
self.ui.show_overlay_combo.setCurrentIndex(0)
self.ui.options_group.setDisabled(True)
elif options == self.force_disabled:
# not visible
self.ui.options_group.setDisabled(True)
self.ui.show_overlay_combo.setCurrentIndex(1)
else:
self.ui.show_overlay_combo.setCurrentIndex(2)
for option in options.split(","):
try:
if "=" in option:
key, value = option.split("=")
if key in self.checkboxes.keys():
self.checkboxes[key].setChecked(False)
else:
self.values[key].setValue(value)
else:
self.checkboxes[option].setChecked(True)
except Exception as e:
logger.warning(e)
self.ui.options_group.setDisabled(False)
return super().showEvent(a0)
class DxvkSettings(OverlaySettings):
def __init__(self, parent=None):
super(DxvkSettings, self).__init__(parent=parent)
self.setTitle(self.tr("DXVK Settings"))
self.setupWidget(
[
("fps", QCoreApplication.translate("DxvkSettings", "FPS")),
("frametime", QCoreApplication.translate("DxvkSettings", "Frametime")),
("memory", QCoreApplication.translate("DxvkSettings", "Memory usage")),
("gpuload", QCoreApplication.translate("DxvkSettings", "GPU usage")),
("devinfo", QCoreApplication.translate("DxvkSettings", "Show Device info")),
("version", QCoreApplication.translate("DxvkSettings", "DXVK Version")),
("api", QCoreApplication.translate("DxvkSettings", "D3D feature level")),
("compiler", QCoreApplication.translate("DxvkSettings", "Compiler activity")),
],
[
(
CustomOption.number_input("scale", 1, True),
QCoreApplication.translate("DxvkSettings", "Scale"),
)
],
"DXVK_HUD",
"0",
)
def set_activation_state(self, state: ActivationStates):
pass
mangohud_position = [
"default",
"top-left",
"top-right",
"middle-left",
"middle-right",
"bottom-left",
"bottom-right",
"top-center",
]
class MangoHudSettings(OverlaySettings):
def __init__(self, parent=None):
super(MangoHudSettings, self).__init__(parent=parent)
self.setTitle(self.tr("MangoHud Settings"))
self.setupWidget(
[
("fps", QCoreApplication.translate("MangoSettings", "FPS")),
("frame_timing", QCoreApplication.translate("MangoSettings", "Frame Time")),
("cpu_stats", QCoreApplication.translate("MangoSettings", "CPU Load")),
("gpu_stats", QCoreApplication.translate("MangoSettings", "GPU Load")),
("cpu_temp", QCoreApplication.translate("MangoSettings", "CPU Temp")),
("gpu_temp", QCoreApplication.translate("MangoSettings", "GPU Temp")),
("ram", QCoreApplication.translate("MangoSettings", "Memory usage")),
("vram", QCoreApplication.translate("MangoSettings", "VRAM usage")),
("time", QCoreApplication.translate("MangoSettings", "Local Time")),
("version", QCoreApplication.translate("MangoSettings", "MangoHud Version")),
("arch", QCoreApplication.translate("MangoSettings", "System architecture")),
("histogram", QCoreApplication.translate("MangoSettings", "FPS Graph")),
("gpu_name", QCoreApplication.translate("MangoSettings", "GPU Name")),
("cpu_power", QCoreApplication.translate("MangoSettings", "CPU Power consumption")),
("gpu_power", QCoreApplication.translate("MangoSettings", "GPU Power consumption")),
],
[
(
CustomOption.number_input("font_size", 24, is_float=False),
QCoreApplication.translate("MangoSettings", "Font size"),
),
(
CustomOption.select_input("position", mangohud_position),
QCoreApplication.translate("MangoSettings", "Position"),
),
],
"MANGOHUD_CONFIG",
"no_display",
)
def showEvent(self, a0: QShowEvent):
if a0.spontaneous():
return super().showEvent(a0)
# override
activated = bool(config.get_envvar(self.app_name, "MANGOHUD", None))
mango_config = config.get_envvar(self.app_name, "MANGOHUD_CONFIG", fallback="")
if not activated:
self.ui.options_group.setDisabled(True)
for i, checkbox in enumerate(list(self.checkboxes.values())):
checkbox.setChecked(i < 4)
self.ui.show_overlay_combo.setCurrentIndex(0)
return
self.ui.show_overlay_combo.setCurrentIndex(2)
self.ui.options_group.setDisabled(False)
for var_name, checkbox in list(self.checkboxes.items())[:4]:
checkbox.setChecked(f"{var_name}=0" not in mango_config)
return super().showEvent(a0)
def set_activation_state(self, state: IntEnum): # pylint: disable=E0202
if state == ActivationStates.DEFAULT:
config.remove_envvar(self.app_name, "MANGOHUD")
config.remove_envvar(self.app_name, "MANGOHUD_CONFIG")
self.ui.options_group.setDisabled(True)
elif state == ActivationStates.HIDDEN:
config.set_envvar(self.app_name, "MANGOHUD", "1")
config.set_envvar(self.app_name, "MANGOHUD_CONFIG", self.force_disabled)
elif state == ActivationStates.ENABLED:
mango_config = config.get_envvar(self.app_name, "MANGOHUD_CONFIG", fallback="")
split_config = mango_config.split(",")
for name in list(self.checkboxes.keys())[:4]:
if name in split_config:
split_config.remove(name)
mango_config = ",".join(split_config)
# first three are activated by default
for var_name, checkbox in list(self.checkboxes.items())[:4]:
if not checkbox.isChecked():
if mango_config:
mango_config += f",{var_name}=0"
else:
mango_config = f"{var_name}=0"
if mango_config:
config.set_envvar(self.app_name, "MANGOHUD", "1")
config.set_envvar(self.app_name, "MANGOHUD_CONFIG", mango_config)
else:
config.remove_envvar(self.app_name, "MANGOHUD")
config.remove_envvar(self.app_name, "MANGOHUD_CONFIG")
self.environ_changed.emit("MANGOHUD")
self.environ_changed.emit("MANGOHUD_CONFIG")