diff --git a/src/nqrduck_measurement/controller.py b/src/nqrduck_measurement/controller.py index 6a3e1a5..fd5e998 100644 --- a/src/nqrduck_measurement/controller.py +++ b/src/nqrduck_measurement/controller.py @@ -3,6 +3,8 @@ import json import numpy as np from decimal import Decimal from PyQt6.QtCore import pyqtSlot, pyqtSignal +from PyQt6.QtGui import QValidator +from PyQt6.QtWidgets import QApplication import nqrduck.helpers.signalprocessing as sp from nqrduck_pulseprogrammer.view import OptionsDialog from nqrduck_spectrometer.pulsesequence import PulseSequence @@ -29,11 +31,13 @@ class MeasurementController(ModuleController): Raises: ValueError: If value cannot be converted to float.""" - try: - logger.debug("Setting frequency to: %s MHz" % value) - self.module.nqrduck_signal.emit("set_frequency", float(value) * 1e6) - except ValueError: - self.set_averages_failure.emit() + + # Use validator + if self.module.model.validator_measurement_frequency.validate(value, 0) == QValidator.State.Acceptable: + self.module.model.measurement_frequency = float(value) + self.module.nqrduck_signal.emit("set_frequency", str(self.module.model.measurement_frequency)) + + self.toggle_start_button() @pyqtSlot(str) def set_averages(self, value: str) -> None: @@ -43,7 +47,12 @@ class MeasurementController(ModuleController): value (str): Number of averages. """ logger.debug("Setting averages to: " + value) - self.module.nqrduck_signal.emit("set_averages", value) + #self.module.nqrduck_signal.emit("set_averages", value) + if self.module.model.validator_averages.validate(value, 0) == QValidator.State.Acceptable: + self.module.model.averages = int(value) + self.module.nqrduck_signal.emit("set_averages", str(self.module.model.averages)) + + self.toggle_start_button() @pyqtSlot() def change_view_mode(self) -> None: @@ -57,11 +66,28 @@ class MeasurementController(ModuleController): logger.debug("View mode changed to: " + self.module.model.view_mode) def start_measurement(self) -> None: - """Emmit the start measurement signal.""" + """Emit the start measurement signal.""" logger.debug("Start measurement clicked") self.module.view.measurement_dialog.show() + self.module.nqrduck_signal.emit("start_measurement", None) + def toggle_start_button(self) -> None: + """Based on wether the Validators for frequency and averages are in an acceptable state, the start button is enabled or disabled.""" + if ( + self.module.model.validator_measurement_frequency.validate( + self.module.view._ui_form.frequencyEdit.text(), 0 + ) + == QValidator.State.Acceptable + and self.module.model.validator_averages.validate( + self.module.view._ui_form.averagesEdit.text(), 0 + ) + == QValidator.State.Acceptable + ): + self.module.view._ui_form.buttonStart.setEnabled(True) + else: + self.module.view._ui_form.buttonStart.setEnabled(False) + def process_signals(self, key: str, value: object): """Process incoming signal from the nqrduck module. diff --git a/src/nqrduck_measurement/model.py b/src/nqrduck_measurement/model.py index f3da639..3f2ab2c 100644 --- a/src/nqrduck_measurement/model.py +++ b/src/nqrduck_measurement/model.py @@ -2,6 +2,7 @@ import logging from PyQt6.QtCore import pyqtSignal from nqrduck_spectrometer.measurement import Measurement from nqrduck.module.module_model import ModuleModel +from nqrduck.helpers.validators import DuckFloatValidator, DuckIntValidator logger = logging.getLogger(__name__) @@ -16,12 +17,21 @@ class MeasurementModel(ModuleModel): measurements_changed = pyqtSignal(list) view_mode_changed = pyqtSignal(str) + measurement_frequency_changed = pyqtSignal(float) + averages_changed = pyqtSignal(int) + def __init__(self, module) -> None: super().__init__(module) self.view_mode = self.TIME_VIEW self.measurements = [] self._displayed_measurement = None + self.validator_measurement_frequency = DuckFloatValidator(self, min_value=20.0, max_value=1000.0) + self.validator_averages = DuckIntValidator(self, min_value=1, max_value=1e6) + + self.measurement_frequency = 100.0 # MHz + self.averages = 1 + @property def view_mode(self): """View mode of the measurement view. @@ -59,3 +69,24 @@ class MeasurementModel(ModuleModel): def displayed_measurement(self, value : Measurement): self._displayed_measurement = value self.displayed_measurement_changed.emit(value) + + @property + def measurement_frequency(self): + """Measurement frequency.""" + return self._measurement_frequency + + @measurement_frequency.setter + def measurement_frequency(self, value : float): + # Validator is used to check if the value is in the correct range. + self._measurement_frequency = value + self.measurement_frequency_changed.emit(value) + + @property + def averages(self): + """Number of averages.""" + return self._averages + + @averages.setter + def averages(self, value : int): + self._averages = value + self.averages_changed.emit(value) diff --git a/src/nqrduck_measurement/view.py b/src/nqrduck_measurement/view.py index ecd5980..24f43fb 100644 --- a/src/nqrduck_measurement/view.py +++ b/src/nqrduck_measurement/view.py @@ -3,7 +3,7 @@ import numpy as np from pathlib import Path import matplotlib as mpl from PyQt6.QtWidgets import QWidget, QDialog, QLabel, QVBoxLayout -from PyQt6.QtGui import QMovie +from PyQt6.QtGui import QValidator from PyQt6.QtCore import pyqtSlot, Qt from nqrduck.module.module_view import ModuleView from nqrduck.assets.icons import Logos @@ -54,19 +54,23 @@ class MeasurementView(ModuleView): self._ui_form.buttonStart.clicked.connect(self.on_measurement_start_button_clicked) self._ui_form.fftButton.clicked.connect(self.module.controller.change_view_mode) - self._ui_form.frequencyEdit.editingFinished.connect(lambda: self.on_editing_finished(self._ui_form.frequencyEdit.text())) - self._ui_form.averagesEdit.editingFinished.connect(lambda: self.on_editing_finished(self._ui_form.averagesEdit.text())) + # Measurement settings controller + self._ui_form.frequencyEdit.textChanged.connect(lambda: self.module.controller.set_frequency(self._ui_form.frequencyEdit.text())) + self._ui_form.averagesEdit.textChanged.connect(lambda: self.module.controller.set_averages(self._ui_form.averagesEdit.text())) + + # Update fields + self._ui_form.frequencyEdit.textChanged.connect(lambda: self.update_input_widgets(self._ui_form.frequencyEdit, self.module.model.validator_measurement_frequency )) + self._ui_form.averagesEdit.textChanged.connect(lambda: self.update_input_widgets(self._ui_form.averagesEdit, self.module.model.validator_averages)) self.module.controller.set_frequency_failure.connect(self.on_set_frequency_failure) self.module.controller.set_averages_failure.connect(self.on_set_averages_failure) self._ui_form.apodizationButton.clicked.connect(self.module.controller.show_apodization_dialog) - - # Call validator for buttonStart # Add logos self._ui_form.buttonStart.setIcon(Logos.Play_16x16()) self._ui_form.buttonStart.setIconSize(self._ui_form.buttonStart.size()) + self._ui_form.buttonStart.setEnabled(False) self._ui_form.exportButton.setIcon(Logos.Save16x16()) self._ui_form.exportButton.setIconSize(self._ui_form.exportButton.size()) @@ -150,19 +154,6 @@ class MeasurementView(ModuleView): logger.debug("Measurement start button clicked.") self.module.controller.start_measurement() - @pyqtSlot(str) - def on_editing_finished(self, value : str) -> None: - """Slot for when the editing of either the frequencyEdit or averagesEdit is finished. - - Args: - value (str): The value of the line edit.""" - logger.debug("Editing finished.") - self.sender().setStyleSheet("") - if self.sender() == self._ui_form.frequencyEdit: - self.module.controller.set_frequency(value) - elif self.sender() == self._ui_form.averagesEdit: - self.module.controller.set_averages(value) - @pyqtSlot() def on_set_frequency_failure(self) -> None: """Slot for when the set frequency signal fails.""" @@ -195,6 +186,26 @@ class MeasurementView(ModuleView): if file_name: self.module.controller.load_measurement(file_name) + @pyqtSlot() + def update_input_widgets(self, widget, validator) -> None: + """Update the style of the QLineEdit widget to indicate if the value is valid. + + Args: + widget (QLineEdit): The widget to update. + validator (QValidator): The validator to use for the widget.""" + if ( + validator.validate(widget.text(), 0) + == QValidator.State.Acceptable + ): + widget.setStyleSheet("QLineEdit { background-color: white; }") + elif ( + validator.validate(widget.text(), 0) + == QValidator.State.Intermediate + ): + widget.setStyleSheet("QLineEdit { background-color: yellow; }") + else: + widget.setStyleSheet("QLineEdit { background-color: red; }") + class MeasurementDialog(QDialog): """ This Dialog is shown when the measurement is started and therefore blocks the main window.