200 lines
6.9 KiB
Python
200 lines
6.9 KiB
Python
from PyQt6.QtGui import QIcon
|
|
from PyQt6.QtWidgets import QWidget, QLabel, QFormLayout, QSpinBox, QDoubleSpinBox, QLineEdit, QHBoxLayout, QPushButton, \
|
|
QFileDialog, QCheckBox, QVBoxLayout, QGroupBox
|
|
from PyQt6.QtCore import pyqtSignal, Qt
|
|
from cpdctrl.utility.config_file import ConfigFile
|
|
|
|
|
|
class FileSelection(QWidget):
|
|
"""
|
|
Widget allowing the user to select a file or directory.
|
|
"""
|
|
valueChanged = 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.valueChanged)
|
|
|
|
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 value(self) -> str:
|
|
return self.w_edit.text()
|
|
|
|
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(QVBoxLayout())
|
|
self.ws_form: dict[str, QWidget] = {}
|
|
self.ls_form: dict[str, QLabel] = {}
|
|
self.ws_groups: dict[str, QFormLayout] = {}
|
|
self.config_file = config_file
|
|
w_default = QWidget()
|
|
w_default.setLayout(QFormLayout())
|
|
self.ws_groups["default"] = w_default.layout()
|
|
self.layout().addWidget(w_default)
|
|
|
|
def __contains__(self, item):
|
|
return item in self.ws_form
|
|
|
|
def add_group(self, key, name):
|
|
"""
|
|
Add a group box
|
|
Parameters
|
|
----------
|
|
key
|
|
The key to be used with add_form_row
|
|
name
|
|
The name to display
|
|
"""
|
|
w_group = QGroupBox(parent=None, title=name)
|
|
w_group.setLayout(QFormLayout())
|
|
self.layout().addWidget(w_group)
|
|
self.ws_groups[key] = w_group.layout()
|
|
|
|
def add_form_row(self, key: str, label: str, default_value, widget: QWidget, tooltip: str = None, group:str="default"):
|
|
"""
|
|
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:
|
|
The default value to use for the widget
|
|
widget: QWidget
|
|
Widget to add to the form
|
|
tooltip: str
|
|
Tooltip for the widget
|
|
group: str
|
|
Group to add the row to.
|
|
|
|
Returns
|
|
-------
|
|
|
|
"""
|
|
if not group in self.ws_groups:
|
|
raise ValueError(f"Can not add form row '{key}': Group '{group}' does not exist.")
|
|
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.valueChanged.connect(lambda v: self.value_updated(key, v))
|
|
elif isinstance(widget, QLineEdit):
|
|
widget.setText(value)
|
|
widget.textChanged.connect(lambda v: self.value_updated(key, v))
|
|
else:
|
|
raise ValueError(f"Unknown widget type: {type(widget)}")
|
|
l_label = QLabel(label)
|
|
self.ws_groups[group].addRow(l_label, widget)
|
|
self.ws_form[key] = widget
|
|
self.ls_form[key] = l_label
|
|
|
|
|
|
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)
|
|
elif isinstance(self.ws_form[key], QLineEdit):
|
|
self.ws_form[key].setText(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) or isinstance(self.ws_form, FileSelection):
|
|
return self.ws_form[key].value()
|
|
elif isinstance(self.ws_form[key], QCheckBox):
|
|
return self.ws_form[key].isChecked()
|
|
elif isinstance(self.ws_form[key], QLineEdit):
|
|
return self.ws_form[key].text()
|
|
else:
|
|
raise ValueError(f"Unknown widget type: {type(self.ws_form[key])}")
|
|
else:
|
|
raise ValueError(f"Unknown key: {key}")
|
|
|
|
def update_alignment(self):
|
|
"""
|
|
Give all labels the min width of the widest label,
|
|
so that all forms are aligned even when in different group boxes
|
|
"""
|
|
max_width = 0
|
|
for _, l in self.ls_form.items():
|
|
w = l.minimumSizeHint().width()
|
|
if w > max_width:
|
|
max_width = w
|
|
for _, l in self.ls_form.items():
|
|
l.setMinimumWidth(max_width)
|
|
|
|
|