from RWESharp.Configurable.Configurable import Configurable
from PySide6.QtCore import Slot, Signal, Qt
from PySide6.QtWidgets import QRadioButton, QAbstractButton, QSlider, QSpinBox, QComboBox, QDoubleSpinBox, QAbstractSlider
from PySide6.QtGui import QAction
import json
[docs]
class BoolConfigurable(Configurable):
from RWESharp.Configurable.QtTypes import KeyConfigurable
valueChanged = Signal(bool)
[docs]
def __init__(self, mod, name: str, default: bool = False, description: str = ""):
super().__init__(mod, name, default, description)
[docs]
def load_str_value(self, text: str) -> None:
self.value = text == "1"
self.valueChanged.emit(self.value)
[docs]
def save_str_value(self) -> str:
return "1" if self.value else "0"
[docs]
@Slot(bool)
@Slot(Qt.CheckState)
@Slot()
def update_value(self, value: bool | Qt.CheckState | None = None) -> None:
if isinstance(value, bool):
return super().update_value(value)
elif isinstance(value, Qt.CheckState):
return super().update_value(value == Qt.CheckState.Checked.value)
super().update_value(not self.value)
[docs]
@Slot()
def flip(self):
self.update_value(not self.value)
[docs]
def link_action(self, action: QAction, key: KeyConfigurable = None) -> None:
"""
Makes link between Action and Configurable, where state is synced
:param action: action to link
:param key: optional key to link to action
:return: None
"""
action.setCheckable(True)
action.setChecked(self.value)
if len(self.description) > 0:
action.setToolTip(self.description)
action.triggered.connect(self.update_value)
self.valueChanged.connect(action.setChecked)
if key is not None:
action.setShortcut(key.value)
key.valueChanged.connect(action.setShortcut)
[docs]
class StringConfigurable(Configurable):
valueChanged = Signal(str)
[docs]
def __init__(self, mod, name: str, default: str = "", description: str = ""):
super().__init__(mod, name, default, description)
[docs]
def load_str_value(self, text: str) -> None:
self.value = text
self.valueChanged.emit(self.value)
[docs]
def save_str_value(self) -> str:
return self.value
[docs]
@Slot(str)
def update_value(self, value: str):
super().update_value(value)
[docs]
def link_combobox(self, combobox: QComboBox) -> None:
"""
Links combobox with configurable
:param combobox: Combobox to link
"""
if len(self.description) > 0:
combobox.setToolTip(self.description)
combobox.setCurrentIndex(combobox.findText(self.value))
combobox.currentTextChanged.connect(lambda: self.update_value(combobox.currentText()))
self.valueChanged.connect(lambda: combobox.setCurrentIndex(combobox.findText(self.value)))
[docs]
class IntConfigurable(Configurable):
valueChanged = Signal(int)
[docs]
def __init__(self, mod, name: str, default: int = 0, description: str = ""):
self.radiolist: list[QRadioButton] = []
super().__init__(mod, name, default, description)
[docs]
def load_str_value(self, text: str) -> None:
self.value = int(text)
self.valueChanged.emit(self.value)
[docs]
def save_str_value(self) -> str:
return str(self.value)
[docs]
@Slot(int)
@Slot()
def update_value(self, value: int | None):
if value is not None:
value = int(value)
if isinstance(self.sender(), QRadioButton) and self.sender() in self.radiolist:
value = self.radiolist.index(self.sender())
if self.value == value:
return
elif value is not None:
super().update_value(value)
if 0 <= value < len(self.radiolist) and len(self.radiolist) > 0:
self.radiolist[value].setChecked(True)
[docs]
def link_radio(self, buttons: list[QRadioButton]) -> None:
"""
Links list of radio buttons to Configurable
Configurable value becomes index of pressed radio button
radio buttons will also be synced to current value
:param buttons: Buttons to press
:return: None
"""
self.radiolist = buttons
self.radiolist[self.value].setChecked(True)
if len(self.description) > 0:
for i in buttons:
i.setToolTip(self.description)
for i in self.radiolist:
i.clicked.connect(self.update_value)
[docs]
def link_slider(self, slider: QSlider, releaseonly=False) -> None:
"""
Links slider to Configurable
:param slider: slider
:param releaseonly: should configurable update only when slider is released
:return: None
"""
slider.setValue(self.value)
if len(self.description) > 0:
slider.setToolTip(self.description)
if releaseonly:
slider.sliderReleased.connect(lambda: self.update_value(slider.value()))
else:
slider.valueChanged.connect(self.update_value)
self.valueChanged.connect(slider.setValue)
[docs]
def link_spinbox(self, spin: QSpinBox, releaseonly=False) -> None:
"""
Links spin box to Configurable
:param spin: Spinbox
:param releaseonly: should configurable update only when spinbox is released
:return: None
"""
spin.setValue(self.value)
if len(self.description) > 0:
spin.setToolTip(self.description)
if releaseonly:
spin.editingFinished.connect(lambda: self.update_value(spin.value()))
else:
spin.valueChanged.connect(self.update_value)
self.valueChanged.connect(spin.setValue)
[docs]
def link_slider_spinbox(self, slider: QSlider, spinbox: QSpinBox, releaseonly=False) -> None:
"""
Links both slider and spinbox to a Configurable
:param slider: slider to link
:param spinbox: spinbox to link
:param releaseonly: should configurable update only when slider/spinbox is released
"""
self.link_slider(slider, releaseonly)
self.link_spinbox(spinbox, releaseonly)
[docs]
def link_combobox(self, combobox: QComboBox) -> None:
"""
Links combobox with configurable
:param combobox: Combobox to link
"""
if len(self.description) > 0:
combobox.setToolTip(self.description)
combobox.setCurrentIndex(self.value)
combobox.currentIndexChanged.connect(self.update_value)
self.valueChanged.connect(combobox.setCurrentIndex)
[docs]
class FloatConfigurable(Configurable):
valueChanged = Signal(float)
[docs]
def __init__(self, mod, name: str, default: float = 0, description: str = ""):
super().__init__(mod, name, default, description)
[docs]
def load_str_value(self, text: str) -> None:
self.value = float(text)
self.valueChanged.emit(self.value)
[docs]
def save_str_value(self) -> str:
return str(self.value)
[docs]
@Slot(float)
def update_value(self, value: float):
super().update_value(value)
[docs]
def link_doublespinbox(self, spin: QDoubleSpinBox, releaseonly=False) -> None:
"""
Links spin box to Configurable
:param spin: Double spinbox
:param releaseonly: should configurable update only when spinbox is released
:return: None
"""
spin.setValue(self.value)
if len(self.description) > 0:
spin.setToolTip(self.description)
if releaseonly:
spin.editingFinished.connect(lambda: self.update_value(spin.value()))
else:
spin.valueChanged.connect(self.update_value)
self.valueChanged.connect(spin.setValue)
[docs]
def link_slider(self, slider: QAbstractSlider, releaseonly=False, division=1) -> None:
"""
Links slider to Configurable
:param slider: slider
:param releaseonly: should configurable update only when slider is released
:param division: how much to divide value from slider to configurable and multiply from configurable to slider
:return: None
"""
slider.setValue(int(self.value * division))
if len(self.description) > 0:
slider.setToolTip(self.description)
if releaseonly:
slider.sliderReleased.connect(lambda: self.update_value(slider.value() / division))
else:
slider.valueChanged.connect(lambda: self.update_value(slider.value() / division))
self.valueChanged.connect(lambda x: slider.setValue(int(x * division)))
[docs]
class DictConfigurable(Configurable):
valueChanged = Signal(dict)
[docs]
def __init__(self, mod, name: str, default: dict = None, description: str = ""):
if default is None:
default = {}
super().__init__(mod, name, default, description)
[docs]
def load_str_value(self, text: str) -> None:
self.value = json.loads(text)
self.valueChanged.emit(self.value)
[docs]
def save_str_value(self) -> str:
return json.dumps(self.value)
[docs]
@Slot(dict)
def update_value(self, value: dict):
super().update_value(value)