From be2e895c5768c3a82c329da62f9afef4bd953895 Mon Sep 17 00:00:00 2001 From: jupfi Date: Thu, 16 May 2024 15:11:31 +0200 Subject: [PATCH 1/6] Implemented editable measurement name. --- src/nqrduck_measurement/controller.py | 15 +++++ src/nqrduck_measurement/view.py | 79 +++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/src/nqrduck_measurement/controller.py b/src/nqrduck_measurement/controller.py index 7b26994..a3bd2d6 100644 --- a/src/nqrduck_measurement/controller.py +++ b/src/nqrduck_measurement/controller.py @@ -270,3 +270,18 @@ class MeasurementController(ModuleController): ) else: self.module.model.displayed_measurement = None + + def edit_measurement(self, old_measurement : Measurement, new_measurement : Measurement) -> None: + """Edit a measurement. + + Args: + old_measurement (Measurement): The measurement to edit. + new_measurement (Measurement): The new measurement. + """ + logger.debug("Editing measurement.") + # Delete the old measurement + self.delete_measurement(old_measurement) + + # Add the new measurement + self.module.model.add_measurement(new_measurement) + self.module.model.displayed_measurement = new_measurement diff --git a/src/nqrduck_measurement/view.py b/src/nqrduck_measurement/view.py index 5c1dcf6..aee586a 100644 --- a/src/nqrduck_measurement/view.py +++ b/src/nqrduck_measurement/view.py @@ -13,6 +13,7 @@ from PyQt6.QtWidgets import ( QListWidgetItem, QSizePolicy, QApplication, + QLineEdit, ) from PyQt6.QtGui import QFontMetrics from PyQt6.QtCore import pyqtSlot, Qt @@ -298,6 +299,13 @@ class MeasurementView(ModuleView): lambda: self.module.controller.delete_measurement(measurement) ) + edit_button = QPushButton() + edit_button.setIcon(Logos.Pen12x12()) + edit_button.setFixedWidth(edit_button.iconSize().width()) + edit_button.clicked.connect( + lambda: self.show_measurement_edit(measurement) + ) + name_button = QPushButton() name_button.clicked.connect( partial(self.module.controller.change_displayed_measurement, measurement) @@ -309,6 +317,7 @@ class MeasurementView(ModuleView): QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred ) # Set size policy + layout.addWidget(edit_button) layout.addWidget(name_button) layout.addWidget(delete_button) layout.addStretch() # Add stretch after delete button to ensure name button takes up space @@ -341,6 +350,23 @@ class MeasurementView(ModuleView): name_button.setText(elidedText) name_button.setToolTip(measurement.name) + def show_measurement_edit(self, measurement) -> None: + """Show the measurement dialog. + + Args: + measurement (Measurement): The measurement to edit. + """ + dialog = self.MeasurementEdit(measurement, parent=self) + result = dialog.exec() + + if result == QDialog.DialogCode.Accepted: + logger.debug("Measurement edited.") + self.module.controller.edit_measurement(measurement, dialog.measurement) + else: + logger.debug("Measurement edit canceled.") + + + class MeasurementDialog(QDialog): """This Dialog is shown when the measurement is started and therefore blocks the main window. @@ -381,3 +407,56 @@ class MeasurementView(ModuleView): continue self.spinner_movie.stop() super().hide() + + class MeasurementEdit(QDialog): + """This dialog is displayed when the measurement edit button is clicked. + + It allows the user to edit the measurement parameters (e.g. name, ...) + """ + + def __init__(self, measurement, parent = None) -> None: + super().__init__(parent) + self.setParent(parent) + + logger.debug("Edit measurement dialog started.") + + self.measurement = measurement + + self.setWindowTitle("Edit Measurement") + self.layout = QVBoxLayout(self) + self.setLayout(self.layout) + + + self.name_layout = QHBoxLayout() + self.name_label = QLabel("Name:") + self.name_edit = QLineEdit() + self.name_edit.setText(measurement.name) + self.name_edit.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred) + self.name_edit.adjustSize() + + self.name_layout.addWidget(self.name_label) + self.name_layout.addWidget(self.name_edit) + + self.ok_button = QPushButton("OK") + self.ok_button.clicked.connect(self.on_ok_button_clicked) + + self.cancel_button = QPushButton("Cancel") + self.cancel_button.clicked.connect(self.close) + + self.layout.addLayout(self.name_layout) + + button_layout = QHBoxLayout() + button_layout.addWidget(self.cancel_button) + button_layout.addWidget(self.ok_button) + + self.layout.addLayout(button_layout) + + # Resize the dialog + self.adjustSize() + + def on_ok_button_clicked(self) -> None: + """Slot for when the OK button is clicked.""" + logger.debug("OK button clicked.") + self.measurement.name = self.name_edit.text() + self.accept() + self.close() From 0cd3f915f84a0e73d3843f3bfed54a326382fbeb Mon Sep 17 00:00:00 2001 From: jupfi Date: Thu, 16 May 2024 15:14:12 +0200 Subject: [PATCH 2/6] Linting. --- src/nqrduck_measurement/controller.py | 11 +++++++++-- src/nqrduck_measurement/view.py | 3 ++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/nqrduck_measurement/controller.py b/src/nqrduck_measurement/controller.py index a3bd2d6..a7e30be 100644 --- a/src/nqrduck_measurement/controller.py +++ b/src/nqrduck_measurement/controller.py @@ -233,8 +233,13 @@ class MeasurementController(ModuleController): @pyqtSlot() def change_displayed_measurement(self, measurement=None) -> None: - """Change the displayed measurement.""" + """Change the displayed measurement. + If no measurement is provided, the displayed measurement is changed to the selected measurement in the selection box. + + Args: + measurement (Measurement, optional): The measurement to display. Defaults to None. + """ if not self.module.model.measurements: logger.debug("No measurements to display.") return @@ -271,7 +276,9 @@ class MeasurementController(ModuleController): else: self.module.model.displayed_measurement = None - def edit_measurement(self, old_measurement : Measurement, new_measurement : Measurement) -> None: + def edit_measurement( + self, old_measurement: Measurement, new_measurement: Measurement + ) -> None: """Edit a measurement. Args: diff --git a/src/nqrduck_measurement/view.py b/src/nqrduck_measurement/view.py index aee586a..e9088a1 100644 --- a/src/nqrduck_measurement/view.py +++ b/src/nqrduck_measurement/view.py @@ -409,12 +409,13 @@ class MeasurementView(ModuleView): super().hide() class MeasurementEdit(QDialog): - """This dialog is displayed when the measurement edit button is clicked. + """This dialog is displayed when the measurement edit button is clicked. It allows the user to edit the measurement parameters (e.g. name, ...) """ def __init__(self, measurement, parent = None) -> None: + """Initialize the dialog.""" super().__init__(parent) self.setParent(parent) From 136e9ab90bc06dc652c0879c7c28288bee9d5f23 Mon Sep 17 00:00:00 2001 From: jupfi Date: Thu, 16 May 2024 15:23:57 +0200 Subject: [PATCH 3/6] Improved scaling of name LineEdit. --- src/nqrduck_measurement/view.py | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/nqrduck_measurement/view.py b/src/nqrduck_measurement/view.py index e9088a1..40b4784 100644 --- a/src/nqrduck_measurement/view.py +++ b/src/nqrduck_measurement/view.py @@ -165,7 +165,7 @@ class MeasurementView(ModuleView): try: if self.module.model.displayed_measurement is None: logger.debug("No measurement data to display. Clearing plotter.") - + if self.module.model.view_mode == self.module.model.FFT_VIEW: self.change_to_fft_view() else: @@ -174,7 +174,7 @@ class MeasurementView(ModuleView): self._ui_form.plotter.canvas.draw() return - + if self.module.model.view_mode == self.module.model.FFT_VIEW: self.change_to_fft_view() y = self.module.model.displayed_measurement.fdy @@ -302,13 +302,13 @@ class MeasurementView(ModuleView): edit_button = QPushButton() edit_button.setIcon(Logos.Pen12x12()) edit_button.setFixedWidth(edit_button.iconSize().width()) - edit_button.clicked.connect( - lambda: self.show_measurement_edit(measurement) - ) + edit_button.clicked.connect(lambda: self.show_measurement_edit(measurement)) name_button = QPushButton() name_button.clicked.connect( - partial(self.module.controller.change_displayed_measurement, measurement) + partial( + self.module.controller.change_displayed_measurement, measurement + ) ) # Not sure if this is pretty @@ -365,8 +365,6 @@ class MeasurementView(ModuleView): else: logger.debug("Measurement edit canceled.") - - class MeasurementDialog(QDialog): """This Dialog is shown when the measurement is started and therefore blocks the main window. @@ -410,15 +408,17 @@ class MeasurementView(ModuleView): class MeasurementEdit(QDialog): """This dialog is displayed when the measurement edit button is clicked. - + It allows the user to edit the measurement parameters (e.g. name, ...) """ - def __init__(self, measurement, parent = None) -> None: + def __init__(self, measurement, parent=None) -> None: """Initialize the dialog.""" super().__init__(parent) self.setParent(parent) + self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) + logger.debug("Edit measurement dialog started.") self.measurement = measurement @@ -427,12 +427,13 @@ class MeasurementView(ModuleView): self.layout = QVBoxLayout(self) self.setLayout(self.layout) - self.name_layout = QHBoxLayout() self.name_label = QLabel("Name:") - self.name_edit = QLineEdit() - self.name_edit.setText(measurement.name) - self.name_edit.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred) + self.name_edit = QLineEdit(measurement.name) + font_metrics = self.name_edit.fontMetrics() + self.name_edit.setFixedWidth( + font_metrics.horizontalAdvance(self.name_edit.text()) + 10 + ) self.name_edit.adjustSize() self.name_layout.addWidget(self.name_label) From ffc8d2714983a9b3725c5cbfaf6f2aa973c91e5c Mon Sep 17 00:00:00 2001 From: jupfi Date: Fri, 17 May 2024 16:09:09 +0200 Subject: [PATCH 4/6] Improved module behaviour when changing to darkmode. --- src/nqrduck_measurement/view.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/nqrduck_measurement/view.py b/src/nqrduck_measurement/view.py index 40b4784..3889466 100644 --- a/src/nqrduck_measurement/view.py +++ b/src/nqrduck_measurement/view.py @@ -136,6 +136,11 @@ class MeasurementView(ModuleView): plotter.canvas.ax.set_title("Measurement data - Time domain") plotter.canvas.ax.grid() + @pyqtSlot() + def on_settings_changed(self) -> None: + """Redraw the plots in case the according settings have changed.""" + self.update_displayed_measurement() + def change_to_time_view(self) -> None: """Change plotter to time domain view.""" plotter = self._ui_form.plotter From f5705e4efcbaf1aa0efd558b1ec1dacf42a53944 Mon Sep 17 00:00:00 2001 From: jupfi Date: Sun, 19 May 2024 11:37:06 +0200 Subject: [PATCH 5/6] Fixed measurement dialog not showing in wayland. --- src/nqrduck_measurement/controller.py | 1 + src/nqrduck_measurement/view.py | 32 ++++++++++++++++++--------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/nqrduck_measurement/controller.py b/src/nqrduck_measurement/controller.py index a7e30be..e4f3c12 100644 --- a/src/nqrduck_measurement/controller.py +++ b/src/nqrduck_measurement/controller.py @@ -94,6 +94,7 @@ class MeasurementController(ModuleController): """Emit the start measurement signal.""" logger.debug("Start measurement clicked") self.module.view.measurement_dialog.show() + QApplication.processEvents() # Set the measurement parameters again in case the user switches spectrometer self.module.nqrduck_signal.emit( diff --git a/src/nqrduck_measurement/view.py b/src/nqrduck_measurement/view.py index 3889466..8c34d47 100644 --- a/src/nqrduck_measurement/view.py +++ b/src/nqrduck_measurement/view.py @@ -16,7 +16,7 @@ from PyQt6.QtWidgets import ( QLineEdit, ) from PyQt6.QtGui import QFontMetrics -from PyQt6.QtCore import pyqtSlot, Qt +from PyQt6.QtCore import pyqtSlot, Qt, QTimer from nqrduck.module.module_view import ModuleView from nqrduck.assets.icons import Logos from nqrduck.assets.animations import DuckAnimations @@ -55,7 +55,7 @@ class MeasurementView(ModuleView): ) # Measurement dialog - self.measurement_dialog = self.MeasurementDialog() + self.measurement_dialog = self.MeasurementDialog(self) # Connect signals self.module.model.displayed_measurement_changed.connect( @@ -379,26 +379,40 @@ class MeasurementView(ModuleView): finished (bool): True if the spinner movie is finished. """ - def __init__(self): + def __init__(self, parent=None): """Initialize the dialog.""" - super().__init__() - self.finished = True + super().__init__(parent) + self.setParent(parent) + self.finished = False self.setModal(True) self.setWindowFlag(Qt.WindowType.FramelessWindowHint) self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground) + self.setWindowFlag(Qt.WindowType.WindowStaysOnTopHint) # Ensure the window stays on top + + self.message_label = QLabel("Measuring...") + # Make label bold and text larger + font = self.message_label.font() + font.setPointSize(20) + font.setBold(True) + self.message_label.setFont(font) - self.message_label = "Measuring..." self.spinner_movie = DuckAnimations.DuckKick128x128() self.spinner_label = QLabel(self) + # Make spinner label self.spinner_label.setMovie(self.spinner_movie) self.layout = QVBoxLayout(self) - self.layout.addWidget(QLabel(self.message_label)) + self.layout.addWidget(self.message_label) self.layout.addWidget(self.spinner_label) self.spinner_movie.finished.connect(self.on_movie_finished) - self.spinner_movie.start() + def show(self) -> None: + """Show the dialog and ensure it is raised and activated.""" + super().show() + self.raise_() # Bring the dialog to the front + self.activateWindow() # Give the dialog focus + self.spinner_movie.start() # Ensure the movie starts playing def on_movie_finished(self) -> None: """Called when the spinner movie is finished.""" @@ -406,8 +420,6 @@ class MeasurementView(ModuleView): def hide(self) -> None: """Hide the dialog and stop the spinner movie.""" - while not self.finished: - continue self.spinner_movie.stop() super().hide() From 88af151b5cda2f3114b32d969d4c4fbb6c0c6eb3 Mon Sep 17 00:00:00 2001 From: jupfi Date: Mon, 20 May 2024 20:43:48 +0200 Subject: [PATCH 6/6] Version bump. --- CHANGELOG.md | 24 +++++++++++++++++------- pyproject.toml | 2 +- src/nqrduck_measurement/view.py | 2 +- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7729fcd..2b1300d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,24 @@ # Changelog -### Version 0.0.4 (05-05-2024) -- Added display of multiple measurements that can be displayed in th plot window. +## Version 0.0.5 (20-05-2024) + +- Fixed measurement dialog not showing in wayland (`f5705e4efcbaf1aa0efd558b1ec1dacf42a53944`) +- Measurement names are now editable (`be2e895c5768c3a82c329da62f9afef4bd953895`). +- Improved darkmode compatibility (`be2e895c5768c3a82c329da62f9afef4bd953895`). + +## Version 0.0.4 (05-05-2024) + +- Added display of multiple measurements that can be displayed in th plot window. - Now using the FileManager class instead of QFileManager -### Version 0.0.3 (26-04-2024) -- Switched to new formbuilder. This should make implementation of signal processing methods more robust and easier. +## Version 0.0.3 (26-04-2024) + +- Switched to new formbuilder. This should make implementation of signal processing methods more robust and easier. + +## Version 0.0.2 (17-04-2024) -### Version 0.0.2 (17-04-2024) - Deployment to PyPi via github actions -### Version 0.0.1 (15-04-2024) -- Initial release \ No newline at end of file +## Version 0.0.1 (15-04-2024) + +- Initial release diff --git a/pyproject.toml b/pyproject.toml index 5ea2dd9..b7d55ac 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ allow-direct-references = true [project] name = "nqrduck-measurement" -version = "0.0.4" +version = "0.0.5" authors = [ { name="jupfi", email="support@nqrduck.cool" }, ] diff --git a/src/nqrduck_measurement/view.py b/src/nqrduck_measurement/view.py index 8c34d47..af344d9 100644 --- a/src/nqrduck_measurement/view.py +++ b/src/nqrduck_measurement/view.py @@ -16,7 +16,7 @@ from PyQt6.QtWidgets import ( QLineEdit, ) from PyQt6.QtGui import QFontMetrics -from PyQt6.QtCore import pyqtSlot, Qt, QTimer +from PyQt6.QtCore import pyqtSlot, Qt from nqrduck.module.module_view import ModuleView from nqrduck.assets.icons import Logos from nqrduck.assets.animations import DuckAnimations