mirror of
https://github.com/nqrduck/nqrduck-pulseprogrammer.git
synced 2025-01-03 05:08:10 +00:00
Improved duration display for individual events
Added duration field to event creation dialog Switched to DuckWidgets for event creation form Fixed check for events with identical names Linting
This commit is contained in:
parent
22a43d2d1b
commit
35590c0355
2 changed files with 275 additions and 124 deletions
|
@ -1,4 +1,5 @@
|
||||||
import logging
|
import logging
|
||||||
|
from decimal import Decimal
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from PyQt6.QtCore import pyqtSignal, pyqtSlot
|
from PyQt6.QtCore import pyqtSignal, pyqtSlot
|
||||||
from nqrduck.module.module_model import ModuleModel
|
from nqrduck.module.module_model import ModuleModel
|
||||||
|
@ -6,6 +7,7 @@ from nqrduck_spectrometer.pulsesequence import PulseSequence
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class PulseProgrammerModel(ModuleModel):
|
class PulseProgrammerModel(ModuleModel):
|
||||||
pulse_parameter_options_changed = pyqtSignal()
|
pulse_parameter_options_changed = pyqtSignal()
|
||||||
events_changed = pyqtSignal()
|
events_changed = pyqtSignal()
|
||||||
|
@ -16,15 +18,33 @@ class PulseProgrammerModel(ModuleModel):
|
||||||
self.pulse_parameter_options = OrderedDict()
|
self.pulse_parameter_options = OrderedDict()
|
||||||
self.pulse_sequence = PulseSequence("Untitled pulse sequence")
|
self.pulse_sequence = PulseSequence("Untitled pulse sequence")
|
||||||
|
|
||||||
def add_event(self, event_name):
|
def add_event(self, event_name: str, duration: Decimal = 20):
|
||||||
self.pulse_sequence.events.append(PulseSequence.Event(event_name, "20u"))
|
"""Add a new event to the current pulse sequence.
|
||||||
logger.debug("Creating event %s with object id %s", event_name, id(self.pulse_sequence.events[-1]))
|
|
||||||
|
Args:
|
||||||
|
event_name (str): A human-readable name for the event
|
||||||
|
duration (Decimal): The duration of the event in µs. Defaults to 20.
|
||||||
|
"""
|
||||||
|
self.pulse_sequence.events.append(
|
||||||
|
PulseSequence.Event(event_name, "%.16gu" % duration)
|
||||||
|
)
|
||||||
|
logger.debug(
|
||||||
|
"Creating event %s with object id %s",
|
||||||
|
event_name,
|
||||||
|
id(self.pulse_sequence.events[-1]),
|
||||||
|
)
|
||||||
|
|
||||||
# Create a default instance of the pulse parameter options and add it to the event
|
# Create a default instance of the pulse parameter options and add it to the event
|
||||||
for name, pulse_parameter_class in self.pulse_parameter_options.items():
|
for name, pulse_parameter_class in self.pulse_parameter_options.items():
|
||||||
logger.debug("Adding pulse parameter %s to event %s", name, event_name)
|
logger.debug("Adding pulse parameter %s to event %s", name, event_name)
|
||||||
self.pulse_sequence.events[-1].parameters[name] = pulse_parameter_class(name)
|
self.pulse_sequence.events[-1].parameters[name] = pulse_parameter_class(
|
||||||
logger.debug("Created pulse parameter %s with object id %s", name, id(self.pulse_sequence.events[-1].parameters[name]))
|
name
|
||||||
|
)
|
||||||
|
logger.debug(
|
||||||
|
"Created pulse parameter %s with object id %s",
|
||||||
|
name,
|
||||||
|
id(self.pulse_sequence.events[-1].parameters[name]),
|
||||||
|
)
|
||||||
|
|
||||||
logger.debug(self.pulse_sequence.to_json())
|
logger.debug(self.pulse_sequence.to_json())
|
||||||
self.events_changed.emit()
|
self.events_changed.emit()
|
||||||
|
@ -32,7 +52,7 @@ class PulseProgrammerModel(ModuleModel):
|
||||||
@property
|
@property
|
||||||
def pulse_parameter_options(self):
|
def pulse_parameter_options(self):
|
||||||
return self._pulse_parameter_options
|
return self._pulse_parameter_options
|
||||||
|
|
||||||
@pulse_parameter_options.setter
|
@pulse_parameter_options.setter
|
||||||
def pulse_parameter_options(self, value):
|
def pulse_parameter_options(self, value):
|
||||||
self._pulse_parameter_options = value
|
self._pulse_parameter_options = value
|
||||||
|
@ -42,7 +62,7 @@ class PulseProgrammerModel(ModuleModel):
|
||||||
@property
|
@property
|
||||||
def pulse_sequence(self):
|
def pulse_sequence(self):
|
||||||
return self._pulse_sequence
|
return self._pulse_sequence
|
||||||
|
|
||||||
@pulse_sequence.setter
|
@pulse_sequence.setter
|
||||||
def pulse_sequence(self, value):
|
def pulse_sequence(self, value):
|
||||||
self._pulse_sequence = value
|
self._pulse_sequence = value
|
||||||
|
|
|
@ -3,18 +3,40 @@ import functools
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from PyQt6.QtGui import QIcon
|
from PyQt6.QtGui import QIcon, QValidator
|
||||||
from PyQt6.QtWidgets import QMessageBox, QGroupBox, QFormLayout, QTableWidget, QVBoxLayout, QPushButton, QHBoxLayout, QLabel, QDialog, QLineEdit, QDialogButtonBox, QWidget, QCheckBox, QToolButton, QFileDialog, QSizePolicy
|
from PyQt6.QtWidgets import (
|
||||||
|
QMessageBox,
|
||||||
|
QGroupBox,
|
||||||
|
QFormLayout,
|
||||||
|
QTableWidget,
|
||||||
|
QVBoxLayout,
|
||||||
|
QPushButton,
|
||||||
|
QHBoxLayout,
|
||||||
|
QLabel,
|
||||||
|
QDialog,
|
||||||
|
QLineEdit,
|
||||||
|
QDialogButtonBox,
|
||||||
|
QWidget,
|
||||||
|
QCheckBox,
|
||||||
|
QToolButton,
|
||||||
|
QFileDialog,
|
||||||
|
QSizePolicy,
|
||||||
|
)
|
||||||
from PyQt6.QtCore import pyqtSlot, pyqtSignal
|
from PyQt6.QtCore import pyqtSlot, pyqtSignal
|
||||||
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 nqrduck_spectrometer.pulseparameters import BooleanOption, NumericOption, FunctionOption
|
from nqrduck.helpers.duckwidgets import DuckFloatEdit, DuckEdit
|
||||||
|
from nqrduck_spectrometer.pulseparameters import (
|
||||||
|
BooleanOption,
|
||||||
|
NumericOption,
|
||||||
|
FunctionOption,
|
||||||
|
)
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class PulseProgrammerView(ModuleView):
|
class PulseProgrammerView(ModuleView):
|
||||||
|
|
||||||
def __init__(self, module):
|
def __init__(self, module):
|
||||||
super().__init__(module)
|
super().__init__(module)
|
||||||
|
|
||||||
|
@ -22,21 +44,23 @@ class PulseProgrammerView(ModuleView):
|
||||||
|
|
||||||
self.setup_variabletables()
|
self.setup_variabletables()
|
||||||
|
|
||||||
logger.debug("Connecting pulse parameter options changed signal to on_pulse_parameter_options_changed")
|
logger.debug(
|
||||||
self.module.model.pulse_parameter_options_changed.connect(self.on_pulse_parameter_options_changed)
|
"Connecting pulse parameter options changed signal to on_pulse_parameter_options_changed"
|
||||||
|
)
|
||||||
|
self.module.model.pulse_parameter_options_changed.connect(
|
||||||
|
self.on_pulse_parameter_options_changed
|
||||||
|
)
|
||||||
|
|
||||||
def setup_variabletables(self) -> None:
|
def setup_variabletables(self) -> None:
|
||||||
"""Setup the table for the variables.
|
"""Setup the table for the variables."""
|
||||||
"""
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def setup_pulsetable(self) -> None:
|
def setup_pulsetable(self) -> None:
|
||||||
"""Setup the table for the pulse sequence. Also add buttons for saving and loading pulse sequences and editing and creation of events
|
"""Setup the table for the pulse sequence. Also add buttons for saving and loading pulse sequences and editing and creation of events"""
|
||||||
"""
|
|
||||||
# Create pulse table
|
# Create pulse table
|
||||||
self.title = QLabel("Pulse Sequence: %s" % self.module.model.pulse_sequence.name)
|
self.title = QLabel(
|
||||||
|
"Pulse Sequence: %s" % self.module.model.pulse_sequence.name
|
||||||
|
)
|
||||||
# Make title bold
|
# Make title bold
|
||||||
font = self.title.font()
|
font = self.title.font()
|
||||||
font.setBold(True)
|
font.setBold(True)
|
||||||
|
@ -44,7 +68,9 @@ class PulseProgrammerView(ModuleView):
|
||||||
|
|
||||||
# Table setup
|
# Table setup
|
||||||
self.pulse_table = QTableWidget(self)
|
self.pulse_table = QTableWidget(self)
|
||||||
self.pulse_table.setSizeAdjustPolicy(QTableWidget.SizeAdjustPolicy.AdjustToContents)
|
self.pulse_table.setSizeAdjustPolicy(
|
||||||
|
QTableWidget.SizeAdjustPolicy.AdjustToContents
|
||||||
|
)
|
||||||
self.pulse_table.setAlternatingRowColors(True)
|
self.pulse_table.setAlternatingRowColors(True)
|
||||||
layout = QVBoxLayout()
|
layout = QVBoxLayout()
|
||||||
button_layout = QHBoxLayout()
|
button_layout = QHBoxLayout()
|
||||||
|
@ -62,14 +88,16 @@ class PulseProgrammerView(ModuleView):
|
||||||
|
|
||||||
# Add button for save pulse sequence
|
# Add button for save pulse sequence
|
||||||
self.save_pulse_sequence_button = QPushButton("Save pulse sequence")
|
self.save_pulse_sequence_button = QPushButton("Save pulse sequence")
|
||||||
self.save_pulse_sequence_button.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
|
self.save_pulse_sequence_button.setSizePolicy(
|
||||||
|
QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed
|
||||||
|
)
|
||||||
# Add the Save Icon to the button
|
# Add the Save Icon to the button
|
||||||
icon = Logos.Save16x16()
|
icon = Logos.Save16x16()
|
||||||
self.save_pulse_sequence_button.setIconSize(icon.availableSizes()[0])
|
self.save_pulse_sequence_button.setIconSize(icon.availableSizes()[0])
|
||||||
self.save_pulse_sequence_button.setIcon(icon)
|
self.save_pulse_sequence_button.setIcon(icon)
|
||||||
self.save_pulse_sequence_button.clicked.connect(self.on_save_button_clicked)
|
self.save_pulse_sequence_button.clicked.connect(self.on_save_button_clicked)
|
||||||
button_layout.addWidget(self.save_pulse_sequence_button)
|
button_layout.addWidget(self.save_pulse_sequence_button)
|
||||||
|
|
||||||
# Add button for load pulse sequence
|
# Add button for load pulse sequence
|
||||||
self.load_pulse_sequence_button = QPushButton("Load pulse sequence")
|
self.load_pulse_sequence_button = QPushButton("Load pulse sequence")
|
||||||
# Add the Load Icon to the button
|
# Add the Load Icon to the button
|
||||||
|
@ -83,13 +111,12 @@ class PulseProgrammerView(ModuleView):
|
||||||
self.module.model.events_changed.connect(self.on_events_changed)
|
self.module.model.events_changed.connect(self.on_events_changed)
|
||||||
self.module.model.pulse_sequence_changed.connect(self.on_pulse_sequence_changed)
|
self.module.model.pulse_sequence_changed.connect(self.on_pulse_sequence_changed)
|
||||||
|
|
||||||
|
|
||||||
button_layout.addStretch(1)
|
button_layout.addStretch(1)
|
||||||
layout.addWidget(self.title)
|
layout.addWidget(self.title)
|
||||||
layout.addLayout(button_layout)
|
layout.addLayout(button_layout)
|
||||||
layout.addLayout(table_layout)
|
layout.addLayout(table_layout)
|
||||||
layout.addStretch(1)
|
layout.addStretch(1)
|
||||||
|
|
||||||
self.setLayout(layout)
|
self.setLayout(layout)
|
||||||
|
|
||||||
# Add layout for the event lengths
|
# Add layout for the event lengths
|
||||||
|
@ -97,20 +124,22 @@ class PulseProgrammerView(ModuleView):
|
||||||
self.layout().addWidget(self.event_widget)
|
self.layout().addWidget(self.event_widget)
|
||||||
|
|
||||||
self.on_events_changed()
|
self.on_events_changed()
|
||||||
|
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def on_pulse_sequence_changed(self) -> None:
|
def on_pulse_sequence_changed(self) -> None:
|
||||||
"""This method is called whenever the pulse sequence changes. It updates the view to reflect the changes.
|
"""This method is called whenever the pulse sequence changes. It updates the view to reflect the changes."""
|
||||||
"""
|
logger.debug(
|
||||||
logger.debug("Updating pulse sequence to %s", self.module.model.pulse_sequence.name)
|
"Updating pulse sequence to %s", self.module.model.pulse_sequence.name
|
||||||
|
)
|
||||||
self.title.setText("Pulse Sequence: %s" % self.module.model.pulse_sequence.name)
|
self.title.setText("Pulse Sequence: %s" % self.module.model.pulse_sequence.name)
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def on_pulse_parameter_options_changed(self) -> None:
|
def on_pulse_parameter_options_changed(self) -> None:
|
||||||
"""This method is called whenever the pulse parameter options change. It updates the view to reflect the changes.
|
"""This method is called whenever the pulse parameter options change. It updates the view to reflect the changes."""
|
||||||
"""
|
logger.debug(
|
||||||
logger.debug("Updating pulse parameter options to %s", self.module.model.pulse_parameter_options.keys())
|
"Updating pulse parameter options to %s",
|
||||||
|
self.module.model.pulse_parameter_options.keys(),
|
||||||
|
)
|
||||||
# We set it to the length of the pulse parameter options + 1 because we want to add a row for the parameter option buttons
|
# We set it to the length of the pulse parameter options + 1 because we want to add a row for the parameter option buttons
|
||||||
self.pulse_table.setRowCount(len(self.module.model.pulse_parameter_options) + 1)
|
self.pulse_table.setRowCount(len(self.module.model.pulse_parameter_options) + 1)
|
||||||
# Move the vertical header labels on row down
|
# Move the vertical header labels on row down
|
||||||
|
@ -120,21 +149,22 @@ class PulseProgrammerView(ModuleView):
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def on_new_event_button_clicked(self) -> None:
|
def on_new_event_button_clicked(self) -> None:
|
||||||
"""This method is called whenever the new event button is clicked. It creates a new event and adds it to the pulse sequence.
|
"""This method is called whenever the new event button is clicked. It creates a new event and adds it to the pulse sequence."""
|
||||||
"""
|
|
||||||
# Create a QDialog for the new event
|
# Create a QDialog for the new event
|
||||||
logger.debug("New event button clicked")
|
logger.debug("New event button clicked")
|
||||||
dialog = AddEventDialog(self)
|
dialog = AddEventDialog(self)
|
||||||
result = dialog.exec()
|
result = dialog.exec()
|
||||||
if result:
|
if result:
|
||||||
event_name = dialog.get_name()
|
event_name = dialog.get_name()
|
||||||
logger.debug("Adding new event with name %s", event_name)
|
duration = dialog.get_duration()
|
||||||
self.module.model.add_event(event_name)
|
logger.debug(
|
||||||
|
"Adding new event with name %s, duration %g", event_name, duration
|
||||||
|
)
|
||||||
|
self.module.model.add_event(event_name, duration)
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def on_events_changed(self) -> None:
|
def on_events_changed(self) -> None:
|
||||||
"""This method is called whenever the events in the pulse sequence change. It updates the view to reflect the changes.
|
"""This method is called whenever the events in the pulse sequence change. It updates the view to reflect the changes."""
|
||||||
"""
|
|
||||||
logger.debug("Updating events to %s", self.module.model.pulse_sequence.events)
|
logger.debug("Updating events to %s", self.module.model.pulse_sequence.events)
|
||||||
|
|
||||||
# Add label for the event lengths
|
# Add label for the event lengths
|
||||||
|
@ -145,9 +175,11 @@ class PulseProgrammerView(ModuleView):
|
||||||
for event in self.module.model.pulse_sequence.events:
|
for event in self.module.model.pulse_sequence.events:
|
||||||
logger.debug("Adding event to pulseprogrammer view: %s", event.name)
|
logger.debug("Adding event to pulseprogrammer view: %s", event.name)
|
||||||
# Create a label for the event
|
# Create a label for the event
|
||||||
event_label = QLabel("%s : %s µs" % (event.name, str(event.duration * Decimal(1e6))))
|
event_label = QLabel(
|
||||||
|
"%s : %.16g µs" % (event.name, (event.duration * Decimal(1e6)))
|
||||||
|
)
|
||||||
event_layout.addWidget(event_label)
|
event_layout.addWidget(event_label)
|
||||||
|
|
||||||
# Delete the old widget and create a new one
|
# Delete the old widget and create a new one
|
||||||
self.event_widget.deleteLater()
|
self.event_widget.deleteLater()
|
||||||
self.event_widget = QWidget()
|
self.event_widget = QWidget()
|
||||||
|
@ -155,33 +187,52 @@ class PulseProgrammerView(ModuleView):
|
||||||
self.layout().addWidget(self.event_widget)
|
self.layout().addWidget(self.event_widget)
|
||||||
|
|
||||||
self.pulse_table.setColumnCount(len(self.module.model.pulse_sequence.events))
|
self.pulse_table.setColumnCount(len(self.module.model.pulse_sequence.events))
|
||||||
self.pulse_table.setHorizontalHeaderLabels([event.name for event in self.module.model.pulse_sequence.events])
|
self.pulse_table.setHorizontalHeaderLabels(
|
||||||
|
[event.name for event in self.module.model.pulse_sequence.events]
|
||||||
|
)
|
||||||
|
|
||||||
self.set_parameter_icons()
|
self.set_parameter_icons()
|
||||||
|
|
||||||
def set_parameter_icons(self) -> None:
|
def set_parameter_icons(self) -> None:
|
||||||
"""This method sets the icons for the pulse parameter options.
|
"""This method sets the icons for the pulse parameter options."""
|
||||||
"""
|
|
||||||
for column_idx, event in enumerate(self.module.model.pulse_sequence.events):
|
for column_idx, event in enumerate(self.module.model.pulse_sequence.events):
|
||||||
for row_idx, parameter in enumerate(self.module.model.pulse_parameter_options.keys()):
|
for row_idx, parameter in enumerate(
|
||||||
|
self.module.model.pulse_parameter_options.keys()
|
||||||
|
):
|
||||||
if row_idx == 0:
|
if row_idx == 0:
|
||||||
event_options_widget = EventOptionsWidget(event)
|
event_options_widget = EventOptionsWidget(event)
|
||||||
# Connect the delete_event signal to the on_delete_event slot
|
# Connect the delete_event signal to the on_delete_event slot
|
||||||
func = functools.partial(self.module.controller.delete_event, event_name=event.name)
|
func = functools.partial(
|
||||||
|
self.module.controller.delete_event, event_name=event.name
|
||||||
|
)
|
||||||
event_options_widget.delete_event.connect(func)
|
event_options_widget.delete_event.connect(func)
|
||||||
# Connect the change_event_duration signal to the on_change_event_duration slot
|
# Connect the change_event_duration signal to the on_change_event_duration slot
|
||||||
event_options_widget.change_event_duration.connect(self.module.controller.change_event_duration)
|
event_options_widget.change_event_duration.connect(
|
||||||
|
self.module.controller.change_event_duration
|
||||||
|
)
|
||||||
# Connect the change_event_name signal to the on_change_event_name slot
|
# Connect the change_event_name signal to the on_change_event_name slot
|
||||||
event_options_widget.change_event_name.connect(self.module.controller.change_event_name)
|
event_options_widget.change_event_name.connect(
|
||||||
|
self.module.controller.change_event_name
|
||||||
|
)
|
||||||
# Connect the move_event_left signal to the on_move_event_left slot
|
# Connect the move_event_left signal to the on_move_event_left slot
|
||||||
event_options_widget.move_event_left.connect(self.module.controller.on_move_event_left)
|
event_options_widget.move_event_left.connect(
|
||||||
|
self.module.controller.on_move_event_left
|
||||||
|
)
|
||||||
# Connect the move_event_right signal to the on_move_event_right slot
|
# Connect the move_event_right signal to the on_move_event_right slot
|
||||||
event_options_widget.move_event_right.connect(self.module.controller.on_move_event_right)
|
event_options_widget.move_event_right.connect(
|
||||||
|
self.module.controller.on_move_event_right
|
||||||
|
)
|
||||||
|
|
||||||
self.pulse_table.setCellWidget(row_idx, column_idx, event_options_widget)
|
self.pulse_table.setCellWidget(
|
||||||
self.pulse_table.setRowHeight(row_idx, event_options_widget.layout().sizeHint().height())
|
row_idx, column_idx, event_options_widget
|
||||||
|
)
|
||||||
|
self.pulse_table.setRowHeight(
|
||||||
|
row_idx, event_options_widget.layout().sizeHint().height()
|
||||||
|
)
|
||||||
|
|
||||||
logger.debug("Adding button for event %s and parameter %s", event, parameter)
|
logger.debug(
|
||||||
|
"Adding button for event %s and parameter %s", event, parameter
|
||||||
|
)
|
||||||
logger.debug("Parameter object id: %s", id(event.parameters[parameter]))
|
logger.debug("Parameter object id: %s", id(event.parameters[parameter]))
|
||||||
button = QPushButton()
|
button = QPushButton()
|
||||||
icon = event.parameters[parameter].get_pixmap()
|
icon = event.parameters[parameter].get_pixmap()
|
||||||
|
@ -189,18 +240,24 @@ class PulseProgrammerView(ModuleView):
|
||||||
button.setIcon(icon)
|
button.setIcon(icon)
|
||||||
button.setIconSize(icon.availableSizes()[0])
|
button.setIconSize(icon.availableSizes()[0])
|
||||||
button.setFixedSize(icon.availableSizes()[0])
|
button.setFixedSize(icon.availableSizes()[0])
|
||||||
|
|
||||||
# We add 1 to the row index because the first row is used for the event options
|
# We add 1 to the row index because the first row is used for the event options
|
||||||
self.pulse_table.setCellWidget(row_idx + 1, column_idx, button)
|
self.pulse_table.setCellWidget(row_idx + 1, column_idx, button)
|
||||||
self.pulse_table.setRowHeight(row_idx + 1, icon.availableSizes()[0].height())
|
self.pulse_table.setRowHeight(
|
||||||
self.pulse_table.setColumnWidth(column_idx, icon.availableSizes()[0].width())
|
row_idx + 1, icon.availableSizes()[0].height()
|
||||||
|
)
|
||||||
|
self.pulse_table.setColumnWidth(
|
||||||
|
column_idx, icon.availableSizes()[0].width()
|
||||||
|
)
|
||||||
|
|
||||||
# Connect the button to the on_button_clicked slot
|
# Connect the button to the on_button_clicked slot
|
||||||
func = functools.partial(self.on_table_button_clicked, event=event, parameter=parameter)
|
func = functools.partial(
|
||||||
|
self.on_table_button_clicked, event=event, parameter=parameter
|
||||||
|
)
|
||||||
button.clicked.connect(func)
|
button.clicked.connect(func)
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def on_table_button_clicked(self, event , parameter) -> None:
|
def on_table_button_clicked(self, event, parameter) -> None:
|
||||||
"""This method is called whenever a button in the pulse table is clicked. It opens a dialog to set the options for the parameter."""
|
"""This method is called whenever a button in the pulse table is clicked. It opens a dialog to set the options for the parameter."""
|
||||||
logger.debug("Button for event %s and parameter %s clicked", event, parameter)
|
logger.debug("Button for event %s and parameter %s clicked", event, parameter)
|
||||||
# Create a QDialog to set the options for the parameter.
|
# Create a QDialog to set the options for the parameter.
|
||||||
|
@ -209,9 +266,15 @@ class PulseProgrammerView(ModuleView):
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
for option, function in dialog.return_functions.items():
|
for option, function in dialog.return_functions.items():
|
||||||
logger.debug("Setting option %s of parameter %s in event %s to %s", option, parameter, event, function())
|
logger.debug(
|
||||||
|
"Setting option %s of parameter %s in event %s to %s",
|
||||||
|
option,
|
||||||
|
parameter,
|
||||||
|
event,
|
||||||
|
function(),
|
||||||
|
)
|
||||||
option.set_value(function())
|
option.set_value(function())
|
||||||
|
|
||||||
self.set_parameter_icons()
|
self.set_parameter_icons()
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
|
@ -232,8 +295,9 @@ class PulseProgrammerView(ModuleView):
|
||||||
if file_name:
|
if file_name:
|
||||||
self.module.controller.load_pulse_sequence(file_name)
|
self.module.controller.load_pulse_sequence(file_name)
|
||||||
|
|
||||||
|
|
||||||
class EventOptionsWidget(QWidget):
|
class EventOptionsWidget(QWidget):
|
||||||
""" This class is a widget that can be used to set the options for a pulse parameter.
|
"""This class is a widget that can be used to set the options for a pulse parameter.
|
||||||
This widget is then added to the the first row of the according event column in the pulse table.
|
This widget is then added to the the first row of the according event column in the pulse table.
|
||||||
It has a edit button that opens a dialog that allows the user to change the options for the event (name and duration).
|
It has a edit button that opens a dialog that allows the user to change the options for the event (name and duration).
|
||||||
Furthermore it has a delete button that deletes the event from the pulse sequence.
|
Furthermore it has a delete button that deletes the event from the pulse sequence.
|
||||||
|
@ -258,7 +322,7 @@ class EventOptionsWidget(QWidget):
|
||||||
self.edit_button.setIconSize(icon.availableSizes()[0])
|
self.edit_button.setIconSize(icon.availableSizes()[0])
|
||||||
self.edit_button.setFixedSize(icon.availableSizes()[0])
|
self.edit_button.setFixedSize(icon.availableSizes()[0])
|
||||||
self.edit_button.clicked.connect(self.edit_event)
|
self.edit_button.clicked.connect(self.edit_event)
|
||||||
|
|
||||||
# Delete button
|
# Delete button
|
||||||
self.delete_button = QToolButton()
|
self.delete_button = QToolButton()
|
||||||
icon = Logos.Garbage12x12()
|
icon = Logos.Garbage12x12()
|
||||||
|
@ -269,7 +333,7 @@ class EventOptionsWidget(QWidget):
|
||||||
|
|
||||||
upper_layout.addWidget(self.edit_button)
|
upper_layout.addWidget(self.edit_button)
|
||||||
upper_layout.addWidget(self.delete_button)
|
upper_layout.addWidget(self.delete_button)
|
||||||
|
|
||||||
lower_layout = QHBoxLayout()
|
lower_layout = QHBoxLayout()
|
||||||
# Move left button
|
# Move left button
|
||||||
self.move_left_button = QToolButton()
|
self.move_left_button = QToolButton()
|
||||||
|
@ -292,16 +356,17 @@ class EventOptionsWidget(QWidget):
|
||||||
|
|
||||||
layout.addLayout(upper_layout)
|
layout.addLayout(upper_layout)
|
||||||
layout.addLayout(lower_layout)
|
layout.addLayout(lower_layout)
|
||||||
|
|
||||||
self.setLayout(layout)
|
self.setLayout(layout)
|
||||||
self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
|
self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def edit_event(self) -> None:
|
def edit_event(self) -> None:
|
||||||
"""This method is called when the edit button is clicked. It opens a dialog that allows the user to change the event name and duration.
|
"""This method is called when the edit button is clicked. It opens a dialog that allows the user to change the event name and duration.
|
||||||
If the user clicks ok, the change_event_name and change_event_duration signals are emitted."""
|
If the user clicks ok, the change_event_name and change_event_duration signals are emitted.
|
||||||
|
"""
|
||||||
logger.debug("Edit button clicked for event %s", self.event.name)
|
logger.debug("Edit button clicked for event %s", self.event.name)
|
||||||
|
|
||||||
# Create a QDialog to edit the event
|
# Create a QDialog to edit the event
|
||||||
dialog = QDialog(self)
|
dialog = QDialog(self)
|
||||||
dialog.setWindowTitle("Edit event")
|
dialog.setWindowTitle("Edit event")
|
||||||
|
@ -309,7 +374,7 @@ class EventOptionsWidget(QWidget):
|
||||||
label = QLabel("Edit event %s" % self.event.name)
|
label = QLabel("Edit event %s" % self.event.name)
|
||||||
layout.addWidget(label)
|
layout.addWidget(label)
|
||||||
|
|
||||||
# Create the inputs for event name, duration
|
# Create the inputs for event name, duration
|
||||||
event_form_layout = QFormLayout()
|
event_form_layout = QFormLayout()
|
||||||
name_label = QLabel("Name:")
|
name_label = QLabel("Name:")
|
||||||
name_lineedit = QLineEdit(self.event.name)
|
name_lineedit = QLineEdit(self.event.name)
|
||||||
|
@ -325,7 +390,9 @@ class EventOptionsWidget(QWidget):
|
||||||
event_form_layout.addRow(duration_layout)
|
event_form_layout.addRow(duration_layout)
|
||||||
layout.addLayout(event_form_layout)
|
layout.addLayout(event_form_layout)
|
||||||
|
|
||||||
buttons = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
|
buttons = QDialogButtonBox(
|
||||||
|
QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
|
||||||
|
)
|
||||||
buttons.accepted.connect(dialog.accept)
|
buttons.accepted.connect(dialog.accept)
|
||||||
buttons.rejected.connect(dialog.reject)
|
buttons.rejected.connect(dialog.reject)
|
||||||
layout.addWidget(buttons)
|
layout.addWidget(buttons)
|
||||||
|
@ -336,8 +403,9 @@ class EventOptionsWidget(QWidget):
|
||||||
if name_lineedit.text() != self.event.name:
|
if name_lineedit.text() != self.event.name:
|
||||||
self.change_event_name.emit(self.event.name, name_lineedit.text())
|
self.change_event_name.emit(self.event.name, name_lineedit.text())
|
||||||
if duration_lineedit.text() != str(self.event.duration):
|
if duration_lineedit.text() != str(self.event.duration):
|
||||||
self.change_event_duration.emit(self.event.name, duration_lineedit.text())
|
self.change_event_duration.emit(
|
||||||
|
self.event.name, duration_lineedit.text()
|
||||||
|
)
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def create_delete_event_dialog(self) -> None:
|
def create_delete_event_dialog(self) -> None:
|
||||||
|
@ -351,7 +419,9 @@ class EventOptionsWidget(QWidget):
|
||||||
layout = QVBoxLayout()
|
layout = QVBoxLayout()
|
||||||
label = QLabel("Are you sure you want to delete event %s?" % self.event.name)
|
label = QLabel("Are you sure you want to delete event %s?" % self.event.name)
|
||||||
layout.addWidget(label)
|
layout.addWidget(label)
|
||||||
buttons = QDialogButtonBox(QDialogButtonBox.StandardButton.Yes | QDialogButtonBox.StandardButton.No)
|
buttons = QDialogButtonBox(
|
||||||
|
QDialogButtonBox.StandardButton.Yes | QDialogButtonBox.StandardButton.No
|
||||||
|
)
|
||||||
buttons.accepted.connect(dialog.accept)
|
buttons.accepted.connect(dialog.accept)
|
||||||
buttons.rejected.connect(dialog.reject)
|
buttons.rejected.connect(dialog.reject)
|
||||||
layout.addWidget(buttons)
|
layout.addWidget(buttons)
|
||||||
|
@ -370,11 +440,12 @@ class EventOptionsWidget(QWidget):
|
||||||
"""This method is called when the move right button is clicked."""
|
"""This method is called when the move right button is clicked."""
|
||||||
logger.debug("Move event right: %s", self.event.name)
|
logger.debug("Move event right: %s", self.event.name)
|
||||||
self.move_event_right.emit(self.event.name)
|
self.move_event_right.emit(self.event.name)
|
||||||
|
|
||||||
|
|
||||||
class OptionsDialog(QDialog):
|
class OptionsDialog(QDialog):
|
||||||
""" This dialog is created whenever the edit button for a pulse option is clicked.
|
"""This dialog is created whenever the edit button for a pulse option is clicked.
|
||||||
It allows the user to change the options for the pulse parameter and creates the dialog in accordance to what can be set."""
|
It allows the user to change the options for the pulse parameter and creates the dialog in accordance to what can be set.
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, event, parameter, parent=None):
|
def __init__(self, event, parameter, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
@ -395,7 +466,7 @@ class OptionsDialog(QDialog):
|
||||||
# If the parameter is a string, we first need to get the parameter object from the according event
|
# If the parameter is a string, we first need to get the parameter object from the according event
|
||||||
if isinstance(parameter, str):
|
if isinstance(parameter, str):
|
||||||
parameter = event.parameters[parameter]
|
parameter = event.parameters[parameter]
|
||||||
|
|
||||||
options = parameter.get_options()
|
options = parameter.get_options()
|
||||||
|
|
||||||
# Based on these options we will now create our selection widget
|
# Based on these options we will now create our selection widget
|
||||||
|
@ -422,7 +493,7 @@ class OptionsDialog(QDialog):
|
||||||
numeric_lineedit = QLineEdit(str(option.value))
|
numeric_lineedit = QLineEdit(str(option.value))
|
||||||
numeric_lineedit.setMaximumWidth(300)
|
numeric_lineedit.setMaximumWidth(300)
|
||||||
numeric_layout.addRow(numeric_label, numeric_lineedit)
|
numeric_layout.addRow(numeric_label, numeric_lineedit)
|
||||||
|
|
||||||
self.return_functions[option] = numeric_lineedit.text
|
self.return_functions[option] = numeric_lineedit.text
|
||||||
|
|
||||||
# If the options are a string we will create a QLineEdit
|
# If the options are a string we will create a QLineEdit
|
||||||
|
@ -432,7 +503,7 @@ class OptionsDialog(QDialog):
|
||||||
elif isinstance(option, FunctionOption):
|
elif isinstance(option, FunctionOption):
|
||||||
function_option = FunctionOptionWidget(option, event, parent)
|
function_option = FunctionOptionWidget(option, event, parent)
|
||||||
self.layout.addWidget(function_option)
|
self.layout.addWidget(function_option)
|
||||||
|
|
||||||
logger.debug("Return functions are: %s" % self.return_functions.items())
|
logger.debug("Return functions are: %s" % self.return_functions.items())
|
||||||
|
|
||||||
self.buttons = QDialogButtonBox(
|
self.buttons = QDialogButtonBox(
|
||||||
|
@ -444,9 +515,10 @@ class OptionsDialog(QDialog):
|
||||||
|
|
||||||
self.layout.addWidget(self.buttons)
|
self.layout.addWidget(self.buttons)
|
||||||
|
|
||||||
|
|
||||||
class FunctionOptionWidget(QWidget):
|
class FunctionOptionWidget(QWidget):
|
||||||
"""This class is a widget that can be used to set the options for a pulse parameter.
|
"""This class is a widget that can be used to set the options for a pulse parameter.
|
||||||
It plots the given function in time and frequency domain.
|
It plots the given function in time and frequency domain.
|
||||||
One can also select the function from a list of functions represented as buttons."""
|
One can also select the function from a list of functions represented as buttons."""
|
||||||
|
|
||||||
def __init__(self, function_option, event, parent=None):
|
def __init__(self, function_option, event, parent=None):
|
||||||
|
@ -459,19 +531,23 @@ class FunctionOptionWidget(QWidget):
|
||||||
inner_layout = QHBoxLayout()
|
inner_layout = QHBoxLayout()
|
||||||
for function in function_option.functions:
|
for function in function_option.functions:
|
||||||
button = QPushButton(function.name)
|
button = QPushButton(function.name)
|
||||||
button.clicked.connect(functools.partial(self.on_functionbutton_clicked, function=function))
|
button.clicked.connect(
|
||||||
|
functools.partial(self.on_functionbutton_clicked, function=function)
|
||||||
|
)
|
||||||
inner_layout.addWidget(button)
|
inner_layout.addWidget(button)
|
||||||
|
|
||||||
layout.addLayout(inner_layout)
|
layout.addLayout(inner_layout)
|
||||||
self.setLayout(layout)
|
self.setLayout(layout)
|
||||||
|
|
||||||
# Add Advanced settings button
|
# Add Advanced settings button
|
||||||
self.advanced_settings_button = QPushButton("Show Advanced settings")
|
self.advanced_settings_button = QPushButton("Show Advanced settings")
|
||||||
self.advanced_settings_button.clicked.connect(self.on_advanced_settings_button_clicked)
|
self.advanced_settings_button.clicked.connect(
|
||||||
|
self.on_advanced_settings_button_clicked
|
||||||
|
)
|
||||||
layout.addWidget(self.advanced_settings_button)
|
layout.addWidget(self.advanced_settings_button)
|
||||||
|
|
||||||
# Add advanced settings widget
|
# Add advanced settings widget
|
||||||
self.advanced_settings = QGroupBox('Advanced Settings')
|
self.advanced_settings = QGroupBox("Advanced Settings")
|
||||||
self.advanced_settings.setHidden(True)
|
self.advanced_settings.setHidden(True)
|
||||||
self.advanced_settings_layout = QFormLayout()
|
self.advanced_settings_layout = QFormLayout()
|
||||||
self.advanced_settings.setLayout(self.advanced_settings_layout)
|
self.advanced_settings.setLayout(self.advanced_settings_layout)
|
||||||
|
@ -521,7 +597,7 @@ class FunctionOptionWidget(QWidget):
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def on_replot_button_clicked(self) -> None:
|
def on_replot_button_clicked(self) -> None:
|
||||||
"""This function is called when the replot button is clicked.
|
"""This function is called when the replot button is clicked.
|
||||||
It will update the parameters of the function and replots the function.
|
It will update the parameters of the function and replots the function.
|
||||||
"""
|
"""
|
||||||
logger.debug("Replot button clicked")
|
logger.debug("Replot button clicked")
|
||||||
|
@ -535,12 +611,13 @@ class FunctionOptionWidget(QWidget):
|
||||||
logger.debug("Invalid expression: %s", self.expr_lineedit.text())
|
logger.debug("Invalid expression: %s", self.expr_lineedit.text())
|
||||||
self.expr_lineedit.setText(str(self.function_option.value.expr))
|
self.expr_lineedit.setText(str(self.function_option.value.expr))
|
||||||
# Create message box that tells the user that the expression is invalid
|
# Create message box that tells the user that the expression is invalid
|
||||||
self.create_message_box("Invalid expression", "The expression you entered is invalid. Please enter a valid expression.")
|
self.create_message_box(
|
||||||
|
"Invalid expression",
|
||||||
|
"The expression you entered is invalid. Please enter a valid expression.",
|
||||||
|
)
|
||||||
|
|
||||||
self.delete_active_function()
|
self.delete_active_function()
|
||||||
self.load_active_function()
|
self.load_active_function()
|
||||||
|
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def on_advanced_settings_button_clicked(self) -> None:
|
def on_advanced_settings_button_clicked(self) -> None:
|
||||||
|
@ -549,11 +626,10 @@ class FunctionOptionWidget(QWidget):
|
||||||
"""
|
"""
|
||||||
if self.advanced_settings.isHidden():
|
if self.advanced_settings.isHidden():
|
||||||
self.advanced_settings.setHidden(False)
|
self.advanced_settings.setHidden(False)
|
||||||
self.advanced_settings_button.setText('Hide Advanced Settings')
|
self.advanced_settings_button.setText("Hide Advanced Settings")
|
||||||
else:
|
else:
|
||||||
self.advanced_settings.setHidden(True)
|
self.advanced_settings.setHidden(True)
|
||||||
self.advanced_settings_button.setText('Show Advanced Settings')
|
self.advanced_settings_button.setText("Show Advanced Settings")
|
||||||
|
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def on_functionbutton_clicked(self, function) -> None:
|
def on_functionbutton_clicked(self, function) -> None:
|
||||||
|
@ -583,11 +659,11 @@ class FunctionOptionWidget(QWidget):
|
||||||
# New QWidget for the active function
|
# New QWidget for the active function
|
||||||
active_function_Widget = QWidget()
|
active_function_Widget = QWidget()
|
||||||
active_function_Widget.setObjectName("active_function")
|
active_function_Widget.setObjectName("active_function")
|
||||||
|
|
||||||
function_layout = QVBoxLayout()
|
function_layout = QVBoxLayout()
|
||||||
|
|
||||||
plot_layout = QHBoxLayout()
|
plot_layout = QHBoxLayout()
|
||||||
|
|
||||||
# Add plot for time domain
|
# Add plot for time domain
|
||||||
time_domain_layout = QVBoxLayout()
|
time_domain_layout = QVBoxLayout()
|
||||||
time_domain_label = QLabel("Time domain:")
|
time_domain_label = QLabel("Time domain:")
|
||||||
|
@ -613,7 +689,9 @@ class FunctionOptionWidget(QWidget):
|
||||||
parameter_label = QLabel(parameter.name)
|
parameter_label = QLabel(parameter.name)
|
||||||
parameter_lineedit = QLineEdit(str(parameter.value))
|
parameter_lineedit = QLineEdit(str(parameter.value))
|
||||||
# Add the parameter_lineedit editingFinished signal to the paramter.set_value slot
|
# Add the parameter_lineedit editingFinished signal to the paramter.set_value slot
|
||||||
parameter_lineedit.editingFinished.connect(lambda: parameter.set_value(parameter_lineedit.text()))
|
parameter_lineedit.editingFinished.connect(
|
||||||
|
lambda: parameter.set_value(parameter_lineedit.text())
|
||||||
|
)
|
||||||
|
|
||||||
# Create a QHBoxLayout
|
# Create a QHBoxLayout
|
||||||
hbox = QHBoxLayout()
|
hbox = QHBoxLayout()
|
||||||
|
@ -636,9 +714,9 @@ class FunctionOptionWidget(QWidget):
|
||||||
self.end_x_lineedit.setText(str(self.function_option.value.end_x))
|
self.end_x_lineedit.setText(str(self.function_option.value.end_x))
|
||||||
self.expr_lineedit.setText(str(self.function_option.value.expr))
|
self.expr_lineedit.setText(str(self.function_option.value.expr))
|
||||||
|
|
||||||
def create_message_box(self, message : str, information : str) -> None:
|
def create_message_box(self, message: str, information: str) -> None:
|
||||||
"""Creates a message box with the given message and information and shows it.
|
"""Creates a message box with the given message and information and shows it.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
message (str): The message to be shown in the message box
|
message (str): The message to be shown in the message box
|
||||||
information (str): The information to be shown in the message box"""
|
information (str): The information to be shown in the message box"""
|
||||||
|
@ -648,66 +726,118 @@ class FunctionOptionWidget(QWidget):
|
||||||
msg.setInformativeText(information)
|
msg.setInformativeText(information)
|
||||||
msg.setWindowTitle("Warning")
|
msg.setWindowTitle("Warning")
|
||||||
msg.exec()
|
msg.exec()
|
||||||
|
|
||||||
|
|
||||||
class AddEventDialog(QDialog):
|
class AddEventDialog(QDialog):
|
||||||
"""This dialog is created whenever a new event is added to the pulse sequence. It allows the user to enter a name for the event."""
|
"""This dialog is created whenever a new event is added to the pulse sequence. It allows the user to enter a name for the event."""
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
self.setWindowTitle("Add Event")
|
self.setWindowTitle("Add Event")
|
||||||
|
|
||||||
self.layout = QVBoxLayout(self)
|
self.layout = QFormLayout(self)
|
||||||
|
|
||||||
|
self.name_layout = QHBoxLayout()
|
||||||
|
|
||||||
self.label = QLabel("Enter event name:")
|
self.label = QLabel("Enter event name:")
|
||||||
self.name_input = QLineEdit()
|
self.name_input = DuckEdit()
|
||||||
|
self.name_input.validator = self.NameInputValidator(self)
|
||||||
|
|
||||||
|
self.name_layout.addWidget(self.label)
|
||||||
|
self.name_layout.addWidget(self.name_input)
|
||||||
|
|
||||||
|
self.layout.addRow(self.name_layout)
|
||||||
|
|
||||||
|
self.duration_layout = QHBoxLayout()
|
||||||
|
|
||||||
|
self.duration_label = QLabel("Duration:")
|
||||||
|
self.duration_lineedit = DuckFloatEdit(min_value=0)
|
||||||
|
self.duration_lineedit.setText("20")
|
||||||
|
self.unit_label = QLabel("µs")
|
||||||
|
|
||||||
|
self.duration_layout.addWidget(self.duration_label)
|
||||||
|
self.duration_layout.addWidget(self.duration_lineedit)
|
||||||
|
|
||||||
|
self.duration_layout.addWidget(self.unit_label)
|
||||||
|
|
||||||
|
self.layout.addRow(self.duration_layout)
|
||||||
|
|
||||||
self.buttons = QDialogButtonBox(
|
self.buttons = QDialogButtonBox(
|
||||||
QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel,
|
QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel,
|
||||||
self,
|
self,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.buttons.accepted.connect(self.check_input)
|
self.buttons.accepted.connect(self.check_input)
|
||||||
self.buttons.rejected.connect(self.reject)
|
self.buttons.rejected.connect(self.reject)
|
||||||
|
|
||||||
self.layout.addWidget(self.label)
|
|
||||||
self.layout.addWidget(self.name_input)
|
|
||||||
self.layout.addWidget(self.buttons)
|
self.layout.addWidget(self.buttons)
|
||||||
|
|
||||||
def get_name(self) -> str:
|
def get_name(self) -> str:
|
||||||
"""Returns the name entered by the user.
|
"""Returns the name entered by the user.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
str: The name entered by the user"""
|
str: The name entered by the user"""
|
||||||
return self.name_input.text()
|
return self.name_input.text()
|
||||||
|
|
||||||
def check_input(self) -> None:
|
def get_duration(self) -> Decimal:
|
||||||
"""Checks if the name entered by the user is valid. If it is, the dialog is accepted. If not, the user is informed of the error.
|
"""Returns the duration entered by the user, or a fallback value."
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Decimal: The duration value provided by the user, or 20"""
|
||||||
|
return Decimal(self.duration_lineedit.text() or 20)
|
||||||
|
|
||||||
|
class NameInputValidator(QValidator):
|
||||||
|
"""A validator for the name input field.
|
||||||
|
|
||||||
|
This is used to validate the input of the QLineEdit widget.
|
||||||
"""
|
"""
|
||||||
# Make sure that name is not empty and that event name doesn't already exist.
|
def validate(self, value, position):
|
||||||
if self.name_input.text() == "":
|
"""Validates the input value.
|
||||||
self.label.setText("Please enter a name for the event.")
|
|
||||||
elif self.name_input.text() in self.parent().module.model.pulse_sequence.events:
|
Args:
|
||||||
self.label.setText("Event name already exists. Please enter a different name.")
|
value (str): The input value
|
||||||
else:
|
position (int): The position of the cursor
|
||||||
self.accept()
|
|
||||||
|
Returns:
|
||||||
|
Tuple[QValidator.State, str, int]: The validation state, the fixed value, and the position
|
||||||
|
"""
|
||||||
|
if not value:
|
||||||
|
return (QValidator.State.Intermediate, value, position)
|
||||||
|
|
||||||
|
if any(
|
||||||
|
[
|
||||||
|
event.name == value
|
||||||
|
for event in self.parent()
|
||||||
|
.parent()
|
||||||
|
.module.model.pulse_sequence.events
|
||||||
|
]
|
||||||
|
):
|
||||||
|
return (QValidator.State.Invalid, value, position)
|
||||||
|
|
||||||
|
return (QValidator.State.Acceptable, value, position)
|
||||||
|
|
||||||
|
|
||||||
# This class should be refactored in the module view so it can be used by all modules
|
# This class should be refactored in the module view so it can be used by all modules
|
||||||
class QFileManager:
|
class QFileManager:
|
||||||
"""This class provides methods for opening and saving files."""
|
"""This class provides methods for opening and saving files."""
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
|
|
||||||
def loadFileDialog(self) -> str:
|
def loadFileDialog(self) -> str:
|
||||||
"""Opens a file dialog for the user to select a file to open.
|
"""Opens a file dialog for the user to select a file to open.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
str: The path of the file selected by the user.
|
str: The path of the file selected by the user.
|
||||||
"""
|
"""
|
||||||
fileName, _ = QFileDialog.getOpenFileName(self.parent,
|
fileName, _ = QFileDialog.getOpenFileName(
|
||||||
"QFileManager - Open File",
|
self.parent,
|
||||||
"",
|
"QFileManager - Open File",
|
||||||
"Quack Files (*.quack);;All Files (*)",
|
"",
|
||||||
options = QFileDialog.Option.ReadOnly)
|
"Quack Files (*.quack);;All Files (*)",
|
||||||
|
options=QFileDialog.Option.ReadOnly,
|
||||||
|
)
|
||||||
if fileName:
|
if fileName:
|
||||||
return fileName
|
return fileName
|
||||||
else:
|
else:
|
||||||
|
@ -715,20 +845,21 @@ class QFileManager:
|
||||||
|
|
||||||
def saveFileDialog(self) -> str:
|
def saveFileDialog(self) -> str:
|
||||||
"""Opens a file dialog for the user to select a file to save.
|
"""Opens a file dialog for the user to select a file to save.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
str: The path of the file selected by the user.
|
str: The path of the file selected by the user.
|
||||||
"""
|
"""
|
||||||
fileName, _ = QFileDialog.getSaveFileName(self.parent,
|
fileName, _ = QFileDialog.getSaveFileName(
|
||||||
"QFileManager - Save File",
|
self.parent,
|
||||||
"",
|
"QFileManager - Save File",
|
||||||
"Quack Files (*.quack);;All Files (*)",
|
"",
|
||||||
options=QFileDialog.Option.DontUseNativeDialog)
|
"Quack Files (*.quack);;All Files (*)",
|
||||||
|
options=QFileDialog.Option.DontUseNativeDialog,
|
||||||
|
)
|
||||||
if fileName:
|
if fileName:
|
||||||
# Append the .quack extension if not present
|
# Append the .quack extension if not present
|
||||||
if not fileName.endswith('.quack'):
|
if not fileName.endswith(".quack"):
|
||||||
fileName += '.quack'
|
fileName += ".quack"
|
||||||
return fileName
|
return fileName
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
Loading…
Reference in a new issue