diff --git a/src/nqrduck_pulseprogrammer/model.py b/src/nqrduck_pulseprogrammer/model.py index d36f897..abab789 100644 --- a/src/nqrduck_pulseprogrammer/model.py +++ b/src/nqrduck_pulseprogrammer/model.py @@ -12,10 +12,14 @@ class PulseProgrammerModel(ModuleModel): def __init__(self, module): super().__init__(module) self.pulse_parameter_options = OrderedDict() - self.events = [] + self.events = OrderedDict() def add_event(self, event_name): - self.events.append(event_name) + self.events[event_name] = OrderedDict() + # 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(): + self.events[event_name][name] = pulse_parameter_class("name") + self.events_changed.emit() @property diff --git a/src/nqrduck_pulseprogrammer/view.py b/src/nqrduck_pulseprogrammer/view.py index d75c2f2..a6c0962 100644 --- a/src/nqrduck_pulseprogrammer/view.py +++ b/src/nqrduck_pulseprogrammer/view.py @@ -1,6 +1,8 @@ import logging +import functools from collections import OrderedDict -from PyQt6.QtWidgets import QTableWidget, QVBoxLayout, QPushButton, QHBoxLayout, QLabel, QDialog, QLineEdit, QDialogButtonBox +from PyQt6.QtGui import QIcon +from PyQt6.QtWidgets import QTableWidget, QVBoxLayout, QPushButton, QHBoxLayout, QLabel, QDialog, QLineEdit, QDialogButtonBox, QTableWidgetItem, QCheckBox from PyQt6.QtCore import pyqtSlot from nqrduck.module.module_view import ModuleView @@ -27,6 +29,7 @@ class PulseProgrammerView(ModuleView): self.pulse_table = QTableWidget(self) self.pulse_table.setSizeAdjustPolicy(QTableWidget.SizeAdjustPolicy.AdjustToContents) + self.pulse_table.setAlternatingRowColors(True) layout = QVBoxLayout() button_layout = QHBoxLayout() table_layout = QHBoxLayout() @@ -44,13 +47,16 @@ class PulseProgrammerView(ModuleView): layout.addWidget(title) layout.addLayout(button_layout) layout.addLayout(table_layout) - + layout.addStretch(1) + # Add label for the event lengths + self.event_layout = QVBoxLayout() event_parameters_label = QLabel("Event lengths:") event_parameters_label.setFont(font) - layout.addStretch(1) - layout.addWidget(event_parameters_label) - + self.event_layout.addWidget(event_parameters_label) + # self.event_layout.addStretch(1) + + layout.addLayout(self.event_layout) self.setLayout(layout) @@ -67,37 +73,118 @@ class PulseProgrammerView(ModuleView): dialog = AddEventDialog(self) result = dialog.exec() if result: - event_name = dialog.get_length() + event_name = dialog.get_name() logger.debug("Adding new event with name %s", event_name) self.module.model.add_event(event_name) @pyqtSlot() def on_events_changed(self): logger.debug("Updating events to %s", self.module.model.events) - layout = self.layout() - event = self.module.model.events[-1] - logger.debug("Adding event to pulseprogrammer view: %s", event) - # Create a label for the setting - label = QLabel(event) - label.setMinimumWidth(70) - # Add an QLineEdit for the setting - line_edit = QLineEdit(str(0)) - line_edit.setMinimumWidth(100) - # Connect the editingFinished signal to the on_value_changed slot of the setting - # line_edit.editingFinished.connect(lambda: setting.on_value_changed(line_edit.text())) - # Add the label and the line edit to the layout - event_layout = QHBoxLayout() - event_layout.addWidget(label) - event_layout.addWidget(line_edit) - event_layout.addStretch(1) - layout.addLayout(event_layout) + for event in self.module.model.events: + logger.debug("Adding event to pulseprogrammer view: %s", event) + # Create a label for the setting + event_name = QLabel(event) + event_name.setMinimumWidth(70) + # Add an QLineEdit for the setting + line_edit = QLineEdit(str(0)) + line_edit.setMinimumWidth(30) + # Add a label for the unit + unit_label = QLabel("µs") + # Connect the editingFinished signal to the on_value_changed slot of the setting + # line_edit.editingFinished.connect(lambda: setting.on_value_changed(line_edit.text())) + # Add the label and the line edit to the layout + event_layout = QHBoxLayout() + event_layout.addWidget(event_name) + event_layout.addWidget(line_edit) + event_layout.addWidget(unit_label) + event_layout.addStretch(1) + + self.layout().addLayout(event_layout) self.pulse_table.setColumnCount(len(self.module.model.events)) self.pulse_table.setHorizontalHeaderLabels(self.module.model.events) - - + self.set_parameter_icons() + + def set_parameter_icons(self): + for i, parameter in enumerate(self.module.model.pulse_parameter_options.keys()): + for j, event in enumerate(self.module.model.events): + logger.debug("Adding button for event %s and parameter %s", event, parameter) + button = QPushButton() + icon = QIcon(self.module.model.events[event][parameter].get_pixmap()) + logger.debug("Icon size: %s", icon.availableSizes()) + button.setIcon(icon) + button.setIconSize(icon.availableSizes()[0]) + button.setFixedSize(icon.availableSizes()[0]) + self.pulse_table.setCellWidget(i, j, button) + self.pulse_table.setRowHeight(i, icon.availableSizes()[0].height()) + self.pulse_table.setColumnWidth(j, icon.availableSizes()[0].width()) + + # Connect the button to the on_button_clicked slot + func = functools.partial(self.on_button_clicked, event=event, parameter=parameter) + button.clicked.connect(func) + + @pyqtSlot() + def on_button_clicked(self, event, parameter): + logger.debug("Button for event %s and parameter %s clicked", event, parameter) + # Create a QDialog to set the options for the parameter. + dialog = OptionsDialog(event, parameter, self) + result = dialog.exec() + + if result: + selection = dialog.return_func() + logger.debug("Setting parameter %s of event %s to %s", parameter, event, selection) + self.module.model.events[event][parameter].set_options(selection) + self.set_parameter_icons() + +class OptionsDialog(QDialog): + def __init__(self, event, parameter, parent=None): + super().__init__(parent) + + self.setWindowTitle("Options") + + self.layout = QVBoxLayout(self) + + self.label = QLabel("Change options for the pulse parameter: %s" % parameter) + self.layout.addWidget(self.label) + parameter = parent.module.model.events[event][parameter] + + options = parameter.get_options() + + # Based on these options we will now create our selection widget + + # If the options are a list , we will create a QComboBox + if options[0] == list: + pass + # If the options are boolean, we will create a QCheckBox + elif options[0] == bool: + check_box = QCheckBox() + + def checkbox_result(): + return check_box.isChecked() + + check_box.setChecked(options[1]) + self.layout.addWidget(check_box) + self.return_func = checkbox_result + # If the options are a float/int we will create a QSpinBox + elif options[0] == float or options[0] == int: + pass + # If the options are a string we will create a QLineEdit + elif options[0] == str: + pass + + self.buttons = QDialogButtonBox( + QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel, + self, + ) + self.buttons.accepted.connect(self.accept) + self.buttons.rejected.connect(self.reject) + + self.layout.addWidget(self.buttons) + + def return_func(self): + return self.return_func class AddEventDialog(QDialog): def __init__(self, parent=None): @@ -108,7 +195,7 @@ class AddEventDialog(QDialog): self.layout = QVBoxLayout(self) self.label = QLabel("Enter event name:") - self.length_input = QLineEdit() + self.name_input = QLineEdit() self.buttons = QDialogButtonBox( QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel, @@ -118,10 +205,10 @@ class AddEventDialog(QDialog): self.buttons.rejected.connect(self.reject) self.layout.addWidget(self.label) - self.layout.addWidget(self.length_input) + self.layout.addWidget(self.name_input) self.layout.addWidget(self.buttons) - def get_length(self): - return self.length_input.text() + def get_name(self): + return self.name_input.text()