diff options
| -rw-r--r-- | picostream/main.py | 150 |
1 files changed, 90 insertions, 60 deletions
diff --git a/picostream/main.py b/picostream/main.py index fc1b914..e7eb709 100644 --- a/picostream/main.py +++ b/picostream/main.py @@ -1,5 +1,3 @@ - - import os import re import sys @@ -15,8 +13,10 @@ from PyQt5.QtWidgets import ( QDoubleSpinBox, QFileDialog, QFormLayout, + QGroupBox, QHBoxLayout, QLabel, + QLCDNumber, QLineEdit, QMainWindow, QPushButton, @@ -134,17 +134,33 @@ class PicoStreamMainWindow(QMainWindow): ) form_layout.addRow(self.live_only_checkbox, self.max_buffer_input) - # Plot settings + settings_layout.addLayout(form_layout) + + # Start/Stop buttons + self.start_button = QPushButton("Start Acquisition") + self.stop_button = QPushButton("Stop Acquisition") + self.stop_button.setEnabled(False) + + button_layout = QHBoxLayout() + button_layout.addWidget(self.start_button) + button_layout.addWidget(self.stop_button) + settings_layout.addLayout(button_layout) + + # Plot settings group + plot_settings_group = QGroupBox("Plot Settings") + plot_settings_form = QFormLayout(plot_settings_group) + self.plot_window_input = QDoubleSpinBox() self.plot_window_input.setRange(0.01, 10.0) self.plot_window_input.setValue(0.5) self.plot_window_input.setSingleStep(0.1) self.plot_window_input.setDecimals(2) self.plot_window_input.setSuffix(" s") - form_layout.addRow("Plot Window:", self.plot_window_input) + plot_settings_form.addRow("Display Window:", self.plot_window_input) self.y_axis_auto_checkbox = QCheckBox("Auto Y-axis") self.y_axis_auto_checkbox.setChecked(True) + self.y_axis_auto_checkbox.setLayoutDirection(Qt.RightToLeft) self.y_min_input = QDoubleSpinBox() self.y_min_input.setRange(-100000, 100000) self.y_min_input.setValue(-1000) @@ -163,65 +179,59 @@ class PicoStreamMainWindow(QMainWindow): lambda state: self.y_max_input.setEnabled(state == 0) ) - form_layout.addRow(self.y_axis_auto_checkbox) + # plot_settings_form.addRow() y_limits_layout = QHBoxLayout() + y_limits_layout.addWidget(self.y_axis_auto_checkbox) y_limits_layout.addWidget(QLabel("Min:")) y_limits_layout.addWidget(self.y_min_input) y_limits_layout.addWidget(QLabel("Max:")) y_limits_layout.addWidget(self.y_max_input) - form_layout.addRow("Y-axis Limits:", y_limits_layout) - - settings_layout.addLayout(form_layout) + plot_settings_form.addRow(y_limits_layout) - self.start_button = QPushButton("Start Acquisition") - self.stop_button = QPushButton("Stop Acquisition") - self.stop_button.setEnabled(False) self.apply_plot_settings_button = QPushButton("Apply Plot Settings") + plot_settings_form.addRow(self.apply_plot_settings_button) + + settings_layout.addWidget(plot_settings_group) + + # Status display section using QGroupBox and QFormLayout + status_group = QGroupBox("Status") + status_form_layout = QFormLayout(status_group) - settings_layout.addWidget(self.start_button) - settings_layout.addWidget(self.stop_button) - settings_layout.addWidget(self.apply_plot_settings_button) - - # Add status display section - status_group = QWidget() - status_group_layout = QVBoxLayout(status_group) - status_title = QLabel("Status") - status_title.setStyleSheet("font-weight: bold; font-size: 12px;") - status_group_layout.addWidget(status_title) - - # Create status labels with initial values - self.status_heartbeat = QLabel("UI: -") - self.status_samples = QLabel("Samples: 0") - self.status_rate = QLabel("Rate: -") - self.status_latency = QLabel("Latency: -") - self.status_errors = QLabel("Errors: 0") - self.status_saturation = QLabel("Saturation: -") - self.status_acquisition = QLabel("Waiting for file...") - - # Set monospace font for status + # Create status value labels with monospace font font = QFont() font.setFamily("Monospace") font.setFixedPitch(True) font.setPointSize(9) - for label in [ - self.status_heartbeat, - self.status_samples, - self.status_rate, - self.status_latency, - self.status_errors, - self.status_saturation, - self.status_acquisition, - ]: - label.setFont(font) - label.setWordWrap(True) - status_group_layout.addWidget(self.status_heartbeat) - status_group_layout.addWidget(self.status_errors) - status_group_layout.addWidget(self.status_saturation) - status_group_layout.addWidget(self.status_samples) - status_group_layout.addWidget(self.status_latency) - status_group_layout.addWidget(self.status_rate) - status_group_layout.addWidget(self.status_acquisition) + self.status_heartbeat = QLabel("-") + self.status_heartbeat.setFont(font) + status_form_layout.addRow("UI:", self.status_heartbeat) + + self.status_errors = self._create_status_label(font) + status_form_layout.addRow("Errors:", self.status_errors) + + self.status_saturation = QLabel("-") + self.status_saturation.setFont(font) + status_form_layout.addRow("Saturation:", self.status_saturation) + + self.status_samples = QLCDNumber() + self.status_samples.setDigitCount(10) + self.status_samples.setSegmentStyle(QLCDNumber.Flat) + self.status_samples.display("0") + status_form_layout.addRow("Samples:", self.status_samples) + + self.status_latency = QLabel("-") + self.status_latency.setFont(font) + status_form_layout.addRow("Latency:", self.status_latency) + + self.status_rate = QLabel("-") + self.status_rate.setFont(font) + status_form_layout.addRow("Rate:", self.status_rate) + + self.status_acquisition = QLabel("Waiting for file...") + self.status_acquisition.setFont(font) + self.status_acquisition.setWordWrap(True) + status_form_layout.addRow("Acquisition:", self.status_acquisition) settings_layout.addWidget(status_group) settings_layout.addStretch() @@ -247,6 +257,19 @@ class PicoStreamMainWindow(QMainWindow): self.load_settings() + def _create_status_label(self, font: QFont) -> QLabel: + """Create a status label with error styling capability.""" + label = QLabel("0") + label.setFont(font) + return label + + def _set_status_error_style(self, label: QLabel, is_error: bool) -> None: + """Apply error styling (red background) to a status label.""" + if is_error: + label.setStyleSheet("background-color: #ffcccc; padding: 2px;") + else: + label.setStyleSheet("") + def select_output_file(self) -> None: """Open a dialog to select the output HDF5 file.""" file_name, _ = QFileDialog.getSaveFileName( @@ -361,17 +384,10 @@ class PicoStreamMainWindow(QMainWindow): def sync_status_from_plotter(self) -> None: """Sync status from the plotter to the main window status labels.""" try: - # Check if plotter exists and has been initialized + # Check if plotter exists and has been initialised if not hasattr(self, 'plotter') or not self.plotter: return - # Check if plotter has the required attributes - required_labels = [ - 'heartbeat_label', 'samples_label', 'rate_label', - 'plotter_latency_label', 'error_label', - 'saturation_label', 'acq_status_label' - ] - # Helper function to safely strip HTML tags def strip_html(text: str) -> str: if not text: @@ -389,10 +405,24 @@ class PicoStreamMainWindow(QMainWindow): # Update all status labels self.status_heartbeat.setText(safe_get_text('heartbeat_label')) - self.status_samples.setText(safe_get_text('samples_label')) + + # Update samples with QLCDNumber + samples_text = safe_get_text('samples_label') + try: + samples_int = int(samples_text) + self.status_samples.display(samples_int) + except (ValueError, TypeError): + self.status_samples.display(0) + self.status_rate.setText(safe_get_text('rate_label')) self.status_latency.setText(safe_get_text('plotter_latency_label')) - self.status_errors.setText(safe_get_text('error_label')) + + # Update errors with colour coding + errors_text = safe_get_text('error_label') + self.status_errors.setText(errors_text) + has_errors = errors_text != "0" and errors_text != "-" + self._set_status_error_style(self.status_errors, has_errors) + self.status_saturation.setText(safe_get_text('saturation_label')) self.status_acquisition.setText(safe_get_text('acq_status_label')) |
