2025-03-12 14:37:02 +01:00

145 lines
4.9 KiB
Python

from PyQt6.QtGui import QIcon
from PyQt6.QtWidgets import QWidget, QLabel, QFormLayout, QSpinBox, QDoubleSpinBox, QLineEdit, QHBoxLayout, QPushButton, QFileDialog, QCheckBox
from PyQt6.QtCore import pyqtSignal
from cpdctrl.utility.config_file import ConfigFile
class FileSelection(QWidget):
"""
Widget allowing the user to select a file or directory.
"""
value_changed = pyqtSignal(str)
def __init__(self, init_file="", filemode=QFileDialog.FileMode.AnyFile, parent=None):
super().__init__(parent)
self.setLayout(QHBoxLayout())
self.w_edit = QLineEdit()
self.w_edit.setText(init_file)
self.w_btn = QPushButton()
self.w_btn.setIcon(QIcon.fromTheme(QIcon.ThemeIcon.FolderOpen))
self.layout().addWidget(self.w_edit)
self.layout().addWidget(self.w_btn)
# open file dialog when button is clicked
self.w_btn.clicked.connect(self._open_file_dialog)
# emit value_changed on self when w_edit emits value_changed
self.w_edit.textChanged.connect(self.value_changed)
self.file_mode = filemode
# remove all spacing and padding from the layout
self.layout().setContentsMargins(0, 0, 0, 0)
def setValue(self, value: str):
self.w_edit.setText(value)
def _open_file_dialog(self):
dialog = QFileDialog(self)
# only directories
dialog.setFileMode(self.file_mode)
if dialog.exec():
dirname = dialog.selectedFiles()[0]
self.w_edit.setText(dirname)
class SettingsForm(QWidget):
"""
Form that is connected to a config file instance
"""
def __init__(self, config_file: ConfigFile, parent=None):
super().__init__(parent)
self.setLayout(QFormLayout())
self.ws_form = {}
self.config_file = config_file
def __contains__(self, item):
return item in self.ws_form
def add_form_row(self, key: str, label: str, default_value, widget: QWidget, tooltip: str = None):
"""
Add a row to the form. Uses the value from the config file corresponding to <key> or the default value.
Parameters
----------
key
label: str
Label for the form widget
default_value
widget
Widget to add to the form
tooltip
Returns
-------
"""
if tooltip: widget.setToolTip(tooltip)
value = self.config_file.get_or(key, default_value)
# set the value depending on the type of the widget
if isinstance(widget, QSpinBox) or isinstance(widget, QDoubleSpinBox):
widget.setValue(value)
widget.valueChanged.connect(lambda v: self.value_updated(key, v))
elif isinstance(widget, QCheckBox):
widget.setChecked(value)
widget.stateChanged.connect(lambda v: self.value_updated(key, v))
elif isinstance(widget, FileSelection):
widget.setValue(value)
widget.value_changed.connect(lambda v: self.value_updated(key, v))
else:
raise ValueError(f"Unknown widget type: {type(widget)}")
self.layout().addRow(QLabel(label), widget)
self.ws_form[key] = widget
def value_updated(self, key, value):
"""
Update the value in the config file when it is updated in the widget
Parameters
----------
key
value
"""
self.config_file.set(key, value)
def set_value(self, key, value):
"""
Set the value of the widget with the given key.
""
Parameters
----------
key
value
Returns
-------
"""
if key in self.ws_form:
# set depending on widget type
if isinstance(self.ws_form[key], QSpinBox) or isinstance(self.ws_form[key], QDoubleSpinBox):
self.ws_form[key].setValue(value)
elif isinstance(self.ws_form[key], QCheckBox):
self.ws_form[key].setChecked(value)
elif isinstance(self.ws_form[key], FileSelection):
self.ws_form[key].setValue(value)
else:
raise ValueError(f"Unknown widget type: {type(self.ws_form[key])}")
else:
raise ValueError(f"Unknown key: {key}")
def get_value(self, key):
"""
Get the value of the widget with the given key.
Parameters
----------
key
Returns
-------
"""
if key in self.ws_form:
# get depending on widget type
if isinstance(self.ws_form[key], QSpinBox) or isinstance(self.ws_form[key], QDoubleSpinBox):
return self.ws_form[key].value()
elif isinstance(self.ws_form[key], QCheckBox):
return self.ws_form[key].isChecked()
else:
raise ValueError(f"Unknown widget type: {type(self.ws_form[key])}")
else:
raise ValueError(f"Unknown key: {key}")