Merge pull request #4 from nqrduck/category-settings

Category settings
This commit is contained in:
Julia P 2024-03-02 21:01:12 +01:00 committed by GitHub
commit cb5df0a9af
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 174 additions and 50 deletions

View file

@ -2,6 +2,7 @@ import logging
from collections import OrderedDict from collections import OrderedDict
from PyQt6.QtCore import pyqtSlot, pyqtSignal, QObject from PyQt6.QtCore import pyqtSlot, pyqtSignal, QObject
from nqrduck.module.module_model import ModuleModel from nqrduck.module.module_model import ModuleModel
from.settings import Setting
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -19,34 +20,6 @@ class BaseSpectrometerModel(ModuleModel):
settings : OrderedDict settings : OrderedDict
pulse_parameter_options : OrderedDict pulse_parameter_options : OrderedDict
class Setting(QObject):
"""A setting for the spectrometer is a value that is the same for all events in a pulse sequence.
E.g. the number of averages or the number of points in a spectrum.
"""
settings_changed = pyqtSignal()
def __init__(self, name : str, default : str, description : str) -> None:
"""Initializes the setting.
Arguments:
name (str) -- The name of the setting
default (str) -- The default value of the setting
description (str) -- The description of the setting
"""
super().__init__()
self.name = name
self.value = default
self.description = description
@pyqtSlot(str)
def on_value_changed(self, value):
logger.debug("Setting %s changed to %s", self.name, value)
self.value = value
self.settings_changed.emit()
def get_setting(self):
return float(self.value)
class PulseParameter: class PulseParameter:
"""A pulse parameter is a value that can be different for each event in a pulse sequence. """A pulse parameter is a value that can be different for each event in a pulse sequence.
E.g. the transmit pulse power or the phase of the transmit pulse. E.g. the transmit pulse power or the phase of the transmit pulse.
@ -115,18 +88,11 @@ class BaseSpectrometerModel(ModuleModel):
self.settings = OrderedDict() self.settings = OrderedDict()
self.pulse_parameter_options = OrderedDict() self.pulse_parameter_options = OrderedDict()
def add_setting(self, name : str, value: str, description : str, category : str) -> None: def add_setting(self, setting : Setting, category : str) -> None:
"""Adds a setting to the spectrometer.
Arguments:
name (str) -- The name of the setting
value (str) -- The default value of the setting
description (str) -- The description of the setting
category (str) -- The category of the setting
"""
if category not in self.settings.keys(): if category not in self.settings.keys():
self.settings[category] = [] self.settings[category] = []
self.settings[category].append(self.Setting(name, value, description)) self.settings[category].append(setting)
def get_setting_by_name(self, name : str) -> Setting: def get_setting_by_name(self, name : str) -> Setting:
"""Gets a setting by its name. """Gets a setting by its name.

View file

@ -1,10 +1,11 @@
import logging import logging
from pathlib import Path from pathlib import Path
from PyQt6.QtWidgets import QWidget, QLabel, QLineEdit, QHBoxLayout, QSizePolicy, QSpacerItem, QVBoxLayout from PyQt6.QtWidgets import QWidget, QLabel, QLineEdit, QHBoxLayout, QSizePolicy, QSpacerItem, QVBoxLayout, QCheckBox, QComboBox
from PyQt6.QtGui import QIcon from PyQt6.QtGui import QIcon
from PyQt6.QtCore import Qt, pyqtSlot from PyQt6.QtCore import Qt, pyqtSlot
from nqrduck.module.module_view import ModuleView from nqrduck.module.module_view import ModuleView
from nqrduck.assets.icons import Logos from nqrduck.assets.icons import Logos
from .settings import FloatSetting, IntSetting, BooleanSetting, SelectionSetting, StringSetting
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -51,13 +52,26 @@ class BaseSpectrometerView(ModuleView):
# Create a label for the setting # Create a label for the setting
setting_label = QLabel(setting.name) setting_label = QLabel(setting.name)
setting_label.setMinimumWidth(200) setting_label.setMinimumWidth(200)
# Add an QLineEdit for the setting
line_edit = QLineEdit(str(setting.value)) # Depending on the setting type we add different widgets to the view
line_edit.setMinimumWidth(100) if isinstance(setting, FloatSetting) or isinstance(setting, IntSetting) or isinstance(setting, StringSetting):
# Add a horizontal layout for the setting edit_widget = QLineEdit(str(setting.value))
layout = QHBoxLayout() edit_widget.setMinimumWidth(100)
# Connect the editingFinished signal to the on_value_changed slot of the setting # Connect the editingFinished signal to the on_value_changed slot of the setting
line_edit.editingFinished.connect(lambda x=line_edit, s=setting: s.on_value_changed(x.text())) edit_widget.editingFinished.connect(lambda x=edit_widget, s=setting: s.on_value_changed(x.text()))
elif isinstance(setting, BooleanSetting):
edit_widget = QCheckBox()
edit_widget.setChecked(setting.value)
edit_widget.stateChanged.connect(lambda x=edit_widget, s=setting: s.on_value_changed(x))
elif isinstance(setting, SelectionSetting):
edit_widget = QComboBox()
edit_widget.addItems(setting.options)
edit_widget.setCurrentText(setting.value)
edit_widget.currentTextChanged.connect(lambda x=edit_widget, s=setting: s.on_value_changed(x))
# Add a icon that can be used as a tooltip # Add a icon that can be used as a tooltip
if setting.description is not None: if setting.description is not None:
logger.debug("Adding tooltip to setting: %s", setting.name) logger.debug("Adding tooltip to setting: %s", setting.name)
@ -69,10 +83,12 @@ class BaseSpectrometerView(ModuleView):
icon_label.setToolTip(setting.description) icon_label.setToolTip(setting.description)
# Add a horizontal layout for the setting
layout = QHBoxLayout()
# Add the label and the line edit to the layout # Add the label and the line edit to the layout
layout.addItem(spacer) layout.addItem(spacer)
layout.addWidget(setting_label) layout.addWidget(setting_label)
layout.addWidget(line_edit) layout.addWidget(edit_widget)
layout.addWidget(icon_label) layout.addWidget(icon_label)
layout.addStretch(1) layout.addStretch(1)
# Add the layout to the vertical layout of the widget # Add the layout to the vertical layout of the widget
@ -85,3 +101,4 @@ class BaseSpectrometerView(ModuleView):
# Push all the settings to the top of the widget # Push all the settings to the top of the widget
self._ui_form.verticalLayout.addStretch(1) self._ui_form.verticalLayout.addStretch(1)

View file

@ -0,0 +1,141 @@
import logging
import ipaddress
from PyQt6.QtCore import QObject, pyqtSignal, pyqtSlot
logger = logging.getLogger(__name__)
class Setting(QObject):
"""A setting for the spectrometer is a value that is the same for all events in a pulse sequence.
E.g. the number of averages or the number of points in a spectrum."""
settings_changed = pyqtSignal()
def __init__(self, name, description) -> None:
super().__init__()
self.name = name
self.description = description
@pyqtSlot(str)
def on_value_changed(self, value):
logger.debug("Setting %s changed to %s", self.name, value)
self.value = value
self.settings_changed.emit()
def get_setting(self):
return float(self.value)
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
@property
def value(self):
return self._value
@value.setter
def value(self, value):
try:
self._value = float(value)
except ValueError:
raise ValueError("Value must be a float")
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
@property
def value(self):
return self._value
@value.setter
def value(self, value):
try:
self._value = int(value)
except ValueError:
raise ValueError("Value must be an int")
self.settings_changed.emit()
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
@property
def value(self):
return self._value
@value.setter
def value(self, value):
try:
self._value = bool(value)
except ValueError:
raise ValueError("Value must be a bool")
self.settings_changed.emit()
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)
# 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
@property
def value(self):
return self._value
@value.setter
def value(self, value):
if value in self.options:
self._value = value
else:
raise ValueError("Value must be one of the options")
self.settings_changed.emit()
class IPSetting(Setting):
""" A setting that is an IP address."""
def __init__(self, name : str, default : str, description : str) -> None:
super().__init__(name, description)
self.value = default
@property
def value(self):
return self._value
@value.setter
def value(self, value):
try:
ipaddress.ip_address(value)
self._value = value
except ValueError:
raise ValueError("Value must be a valid IP address")
self.settings_changed.emit()
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
@property
def value(self):
return self._value
@value.setter
def value(self, value):
try:
self._value = str(value)
except ValueError:
raise ValueError("Value must be a string")
self.settings_changed.emit()