mirror of
https://github.com/nqrduck/nqrduck-spectrometer.git
synced 2024-11-09 12:30:01 +00:00
Implemented input validation.
This commit is contained in:
parent
837524b69f
commit
e314f51ae4
2 changed files with 83 additions and 35 deletions
|
@ -53,7 +53,7 @@ class BaseSpectrometerView(ModuleView):
|
|||
setting_label = QLabel(setting.name)
|
||||
setting_label.setMinimumWidth(200)
|
||||
|
||||
edit_widget = setting.get_widget()
|
||||
edit_widget = setting.widget
|
||||
logger.debug("Setting widget: %s", edit_widget)
|
||||
|
||||
# Add a icon that can be used as a tooltip
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import logging
|
||||
import ipaddress
|
||||
from PyQt6.QtCore import QObject, pyqtSignal, pyqtSlot
|
||||
from PyQt6.QtCore import QObject, pyqtSignal, pyqtSlot, QRegularExpression
|
||||
from PyQt6.QtWidgets import QLineEdit, QComboBox, QCheckBox
|
||||
from PyQt6.QtGui import QValidator, QRegularExpressionValidator
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -10,10 +11,21 @@ class Setting(QObject):
|
|||
E.g. the number of averages or the number of points in a spectrum."""
|
||||
settings_changed = pyqtSignal()
|
||||
|
||||
def __init__(self, name, description) -> None:
|
||||
def __init__(self, name : str, description : str, default = None) -> None:
|
||||
""" Create a new setting.
|
||||
|
||||
Args:
|
||||
name (str): The name of the setting.
|
||||
description (str): A description of the setting.
|
||||
"""
|
||||
super().__init__()
|
||||
self.name = name
|
||||
self.description = description
|
||||
if default is not None:
|
||||
self.value = default
|
||||
|
||||
# This can be overriden by subclasses
|
||||
self.widget = self.get_widget()
|
||||
|
||||
@pyqtSlot(str)
|
||||
def on_value_changed(self, value):
|
||||
|
@ -38,11 +50,34 @@ class Setting(QObject):
|
|||
widget.editingFinished.connect(lambda x=widget, s=self: s.on_value_changed(x.text()))
|
||||
return widget
|
||||
|
||||
def update_widget_style(self):
|
||||
""" Update the style of the QLineEdit widget to indicate if the value is valid."""
|
||||
logger.debug("Updating widget style")
|
||||
if self.validator.validate(self.widget.text(), 0)[0] == QValidator.State.Acceptable:
|
||||
self.widget.setStyleSheet("QLineEdit { background-color: white; }")
|
||||
elif self.validator.validate(self.widget.text(), 0)[0] == QValidator.State.Intermediate:
|
||||
self.widget.setStyleSheet("QLineEdit { background-color: yellow; }")
|
||||
else:
|
||||
self.widget.setStyleSheet("QLineEdit { background-color: red; }")
|
||||
|
||||
class FloatSetting(Setting):
|
||||
""" A setting that is a Float. """
|
||||
def __init__(self, name : str, default : float, description : str) -> None:
|
||||
super().__init__(name, description)
|
||||
self.value = default
|
||||
DEFAULT_LENGTH = 100
|
||||
def __init__(self, name : str, default : float, description : str, validator : QValidator = None) -> None:
|
||||
super().__init__(name, description, default)
|
||||
|
||||
# If a validator is given, set it for the QLineEdit widget
|
||||
if validator:
|
||||
self.validator = validator
|
||||
else:
|
||||
# Create a regex validator that only allows floats
|
||||
regex = "[-+]?[0-9]*\.?[0-9]+"
|
||||
self.validator = QRegularExpressionValidator(QRegularExpression(regex))
|
||||
|
||||
self.widget = self.get_widget()
|
||||
# self.widget.setValidator(self.validator)
|
||||
# Connect the update_widget_style method to the textChanged signal
|
||||
self.widget.textChanged.connect(self.update_widget_style)
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
|
@ -51,16 +86,33 @@ class FloatSetting(Setting):
|
|||
@value.setter
|
||||
def value(self, value):
|
||||
try:
|
||||
if self.validator.validate(value, 0)[0] == QValidator.State.Acceptable:
|
||||
self._value = float(value)
|
||||
self.settings_changed.emit()
|
||||
# This should never be reached because the validator should prevent this
|
||||
except ValueError:
|
||||
raise ValueError("Value must be a float")
|
||||
# This happens when the validator has not yet been set
|
||||
except AttributeError:
|
||||
self._value = float(value)
|
||||
self.settings_changed.emit()
|
||||
|
||||
class IntSetting(Setting):
|
||||
""" A setting that is an Integer."""
|
||||
def __init__(self, name : str, default : int, description : str) -> None:
|
||||
super().__init__(name, description)
|
||||
self.value = default
|
||||
def __init__(self, name : str, default : int, description : str, validator : QValidator = None) -> None:
|
||||
super().__init__(name, description, default)
|
||||
|
||||
# If a validator is given, set it for the QLineEdit widget
|
||||
if validator:
|
||||
self.validator = validator
|
||||
else:
|
||||
# Create a regex validator that only allows integers
|
||||
regex = "[-+]?[0-9]+"
|
||||
self.validator = QRegularExpressionValidator(QRegularExpression(regex))
|
||||
|
||||
self.widget = self.get_widget()
|
||||
# Connect the update_widget_style method to the textChanged signal
|
||||
self.widget.textChanged.connect(self.update_widget_style)
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
|
@ -78,8 +130,10 @@ class BooleanSetting(Setting):
|
|||
""" A setting that is a Boolean."""
|
||||
|
||||
def __init__(self, name : str, default : bool, description : str) -> None:
|
||||
super().__init__(name, description)
|
||||
self.value = default
|
||||
super().__init__(name, description, default)
|
||||
|
||||
# Overrides the default widget
|
||||
self.widget = self.get_widget()
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
|
@ -109,13 +163,15 @@ class BooleanSetting(Setting):
|
|||
class SelectionSetting(Setting):
|
||||
""" A setting that is a selection from a list of options."""
|
||||
def __init__(self, name : str, options : list, default : str, description : str) -> None:
|
||||
super().__init__(name, description)
|
||||
super().__init__(name, description, default)
|
||||
# Check if default is in options
|
||||
if default not in options:
|
||||
raise ValueError("Default value must be one of the options")
|
||||
|
||||
self.options = options
|
||||
self.value = default
|
||||
|
||||
# Overrides the default widget
|
||||
self.widget = self.get_widget()
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
|
@ -123,10 +179,16 @@ class SelectionSetting(Setting):
|
|||
|
||||
@value.setter
|
||||
def value(self, value):
|
||||
try:
|
||||
if value in self.options:
|
||||
self._value = value
|
||||
else:
|
||||
raise ValueError("Value must be one of the options")
|
||||
# This fixes a bug when creating the widget when the options are not yet set
|
||||
except AttributeError:
|
||||
self._value = value
|
||||
self.options = [value]
|
||||
|
||||
self.settings_changed.emit()
|
||||
|
||||
def get_widget(self):
|
||||
|
@ -164,8 +226,7 @@ class IPSetting(Setting):
|
|||
class StringSetting(Setting):
|
||||
""" A setting that is a string."""
|
||||
def __init__(self, name : str, default : str, description : str) -> None:
|
||||
super().__init__(name, description)
|
||||
self.value = default
|
||||
super().__init__(name, description, default)
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
|
@ -179,16 +240,3 @@ class StringSetting(Setting):
|
|||
raise ValueError("Value must be a string")
|
||||
|
||||
self.settings_changed.emit()
|
||||
|
||||
def get_widget(self):
|
||||
"""Return a widget for the setting.
|
||||
The default widget is simply a QLineEdit.
|
||||
This method can be overwritten by subclasses to return a different widget.
|
||||
|
||||
Returns:
|
||||
QLineEdit: A QLineEdit widget that can be used to change the setting.
|
||||
"""
|
||||
widget = QLineEdit(str(self.value))
|
||||
widget.setMinimumWidth(100)
|
||||
widget.editingFinished.connect(lambda x=widget, s=self: s.on_value_changed(x.text()))
|
||||
return widget
|
Loading…
Reference in a new issue