mirror of
https://github.com/nqrduck/nqrduck-measurement.git
synced 2024-11-09 11:50:01 +00:00
commit
6124ee80fd
4 changed files with 152 additions and 21 deletions
18
CHANGELOG.md
18
CHANGELOG.md
|
@ -1,14 +1,24 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
### Version 0.0.4 (05-05-2024)
|
## 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.
|
- Added display of multiple measurements that can be displayed in th plot window.
|
||||||
- Now using the FileManager class instead of QFileManager
|
- Now using the FileManager class instead of QFileManager
|
||||||
|
|
||||||
### Version 0.0.3 (26-04-2024)
|
## Version 0.0.3 (26-04-2024)
|
||||||
|
|
||||||
- Switched to new formbuilder. This should make implementation of signal processing methods more robust and easier.
|
- 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
|
- Deployment to PyPi via github actions
|
||||||
|
|
||||||
### Version 0.0.1 (15-04-2024)
|
## Version 0.0.1 (15-04-2024)
|
||||||
|
|
||||||
- Initial release
|
- Initial release
|
|
@ -7,7 +7,7 @@ allow-direct-references = true
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "nqrduck-measurement"
|
name = "nqrduck-measurement"
|
||||||
version = "0.0.4"
|
version = "0.0.5"
|
||||||
authors = [
|
authors = [
|
||||||
{ name="jupfi", email="support@nqrduck.cool" },
|
{ name="jupfi", email="support@nqrduck.cool" },
|
||||||
]
|
]
|
||||||
|
|
|
@ -94,6 +94,7 @@ class MeasurementController(ModuleController):
|
||||||
"""Emit the start measurement signal."""
|
"""Emit the start measurement signal."""
|
||||||
logger.debug("Start measurement clicked")
|
logger.debug("Start measurement clicked")
|
||||||
self.module.view.measurement_dialog.show()
|
self.module.view.measurement_dialog.show()
|
||||||
|
QApplication.processEvents()
|
||||||
|
|
||||||
# Set the measurement parameters again in case the user switches spectrometer
|
# Set the measurement parameters again in case the user switches spectrometer
|
||||||
self.module.nqrduck_signal.emit(
|
self.module.nqrduck_signal.emit(
|
||||||
|
@ -233,8 +234,13 @@ class MeasurementController(ModuleController):
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def change_displayed_measurement(self, measurement=None) -> None:
|
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:
|
if not self.module.model.measurements:
|
||||||
logger.debug("No measurements to display.")
|
logger.debug("No measurements to display.")
|
||||||
return
|
return
|
||||||
|
@ -270,3 +276,20 @@ class MeasurementController(ModuleController):
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.module.model.displayed_measurement = None
|
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
|
||||||
|
|
|
@ -13,6 +13,7 @@ from PyQt6.QtWidgets import (
|
||||||
QListWidgetItem,
|
QListWidgetItem,
|
||||||
QSizePolicy,
|
QSizePolicy,
|
||||||
QApplication,
|
QApplication,
|
||||||
|
QLineEdit,
|
||||||
)
|
)
|
||||||
from PyQt6.QtGui import QFontMetrics
|
from PyQt6.QtGui import QFontMetrics
|
||||||
from PyQt6.QtCore import pyqtSlot, Qt
|
from PyQt6.QtCore import pyqtSlot, Qt
|
||||||
|
@ -54,7 +55,7 @@ class MeasurementView(ModuleView):
|
||||||
)
|
)
|
||||||
|
|
||||||
# Measurement dialog
|
# Measurement dialog
|
||||||
self.measurement_dialog = self.MeasurementDialog()
|
self.measurement_dialog = self.MeasurementDialog(self)
|
||||||
|
|
||||||
# Connect signals
|
# Connect signals
|
||||||
self.module.model.displayed_measurement_changed.connect(
|
self.module.model.displayed_measurement_changed.connect(
|
||||||
|
@ -135,6 +136,11 @@ class MeasurementView(ModuleView):
|
||||||
plotter.canvas.ax.set_title("Measurement data - Time domain")
|
plotter.canvas.ax.set_title("Measurement data - Time domain")
|
||||||
plotter.canvas.ax.grid()
|
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:
|
def change_to_time_view(self) -> None:
|
||||||
"""Change plotter to time domain view."""
|
"""Change plotter to time domain view."""
|
||||||
plotter = self._ui_form.plotter
|
plotter = self._ui_form.plotter
|
||||||
|
@ -298,9 +304,16 @@ class MeasurementView(ModuleView):
|
||||||
lambda: self.module.controller.delete_measurement(measurement)
|
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 = QPushButton()
|
||||||
name_button.clicked.connect(
|
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
|
# Not sure if this is pretty
|
||||||
|
@ -309,6 +322,7 @@ class MeasurementView(ModuleView):
|
||||||
QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred
|
QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred
|
||||||
) # Set size policy
|
) # Set size policy
|
||||||
|
|
||||||
|
layout.addWidget(edit_button)
|
||||||
layout.addWidget(name_button)
|
layout.addWidget(name_button)
|
||||||
layout.addWidget(delete_button)
|
layout.addWidget(delete_button)
|
||||||
layout.addStretch() # Add stretch after delete button to ensure name button takes up space
|
layout.addStretch() # Add stretch after delete button to ensure name button takes up space
|
||||||
|
@ -341,6 +355,21 @@ class MeasurementView(ModuleView):
|
||||||
name_button.setText(elidedText)
|
name_button.setText(elidedText)
|
||||||
name_button.setToolTip(measurement.name)
|
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):
|
class MeasurementDialog(QDialog):
|
||||||
"""This Dialog is shown when the measurement is started and therefore blocks the main window.
|
"""This Dialog is shown when the measurement is started and therefore blocks the main window.
|
||||||
|
|
||||||
|
@ -350,26 +379,40 @@ class MeasurementView(ModuleView):
|
||||||
finished (bool): True if the spinner movie is finished.
|
finished (bool): True if the spinner movie is finished.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, parent=None):
|
||||||
"""Initialize the dialog."""
|
"""Initialize the dialog."""
|
||||||
super().__init__()
|
super().__init__(parent)
|
||||||
self.finished = True
|
self.setParent(parent)
|
||||||
|
self.finished = False
|
||||||
self.setModal(True)
|
self.setModal(True)
|
||||||
self.setWindowFlag(Qt.WindowType.FramelessWindowHint)
|
self.setWindowFlag(Qt.WindowType.FramelessWindowHint)
|
||||||
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
|
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_movie = DuckAnimations.DuckKick128x128()
|
||||||
self.spinner_label = QLabel(self)
|
self.spinner_label = QLabel(self)
|
||||||
|
# Make spinner label
|
||||||
self.spinner_label.setMovie(self.spinner_movie)
|
self.spinner_label.setMovie(self.spinner_movie)
|
||||||
|
|
||||||
self.layout = QVBoxLayout(self)
|
self.layout = QVBoxLayout(self)
|
||||||
self.layout.addWidget(QLabel(self.message_label))
|
self.layout.addWidget(self.message_label)
|
||||||
self.layout.addWidget(self.spinner_label)
|
self.layout.addWidget(self.spinner_label)
|
||||||
|
|
||||||
self.spinner_movie.finished.connect(self.on_movie_finished)
|
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:
|
def on_movie_finished(self) -> None:
|
||||||
"""Called when the spinner movie is finished."""
|
"""Called when the spinner movie is finished."""
|
||||||
|
@ -377,7 +420,62 @@ class MeasurementView(ModuleView):
|
||||||
|
|
||||||
def hide(self) -> None:
|
def hide(self) -> None:
|
||||||
"""Hide the dialog and stop the spinner movie."""
|
"""Hide the dialog and stop the spinner movie."""
|
||||||
while not self.finished:
|
|
||||||
continue
|
|
||||||
self.spinner_movie.stop()
|
self.spinner_movie.stop()
|
||||||
super().hide()
|
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:
|
||||||
|
"""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
|
||||||
|
|
||||||
|
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(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)
|
||||||
|
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()
|
||||||
|
|
Loading…
Reference in a new issue