Rework radar system
This commit is contained in:
@@ -0,0 +1,165 @@
|
||||
"""Typed section widgets and the scalar Qt boundary shared by GUI settings."""
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass, field
|
||||
from typing import TypeAlias, TypeVar
|
||||
|
||||
from PyQt6.QtWidgets import (
|
||||
QCheckBox, QComboBox, QDoubleSpinBox, QGroupBox, QLineEdit, QPlainTextEdit,
|
||||
QSpinBox, QWidget, QLabel, QPushButton, QStackedWidget,
|
||||
)
|
||||
|
||||
from python_app.gui.antenna_geometry_editor import AntennaGeometryEditor
|
||||
from python_app.models.setting_fields import Scalar
|
||||
|
||||
ScalarWidget: TypeAlias = QLineEdit | QPlainTextEdit | QComboBox | QCheckBox | QSpinBox | QDoubleSpinBox
|
||||
SettingWidget: TypeAlias = ScalarWidget | AntennaGeometryEditor
|
||||
_Widget = TypeVar("_Widget", bound=SettingWidget)
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class SectionView:
|
||||
group: QGroupBox
|
||||
fields: dict[str, SettingWidget] = field(default_factory=dict)
|
||||
|
||||
def add(self, name: str, widget: _Widget) -> _Widget:
|
||||
self.fields[name] = widget
|
||||
return widget
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class PreprocessView(SectionView):
|
||||
labels: dict[str, QLabel]
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class PrimaryView(SectionView):
|
||||
start: QPushButton
|
||||
single_capture: QPushButton
|
||||
stop: QPushButton
|
||||
apply_radar: QPushButton
|
||||
load: QPushButton
|
||||
save: QPushButton
|
||||
preprocess: QPushButton
|
||||
clear: QPushButton
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class DataView(SectionView):
|
||||
save: QPushButton
|
||||
save_json: QPushButton
|
||||
remove_last: QPushButton
|
||||
capture_tmp: QPushButton
|
||||
record: QPushButton
|
||||
browse: QPushButton
|
||||
save_path: QLineEdit
|
||||
save_name: QLineEdit
|
||||
record_count: QSpinBox
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class SwitchView(SectionView):
|
||||
select_text: QPushButton
|
||||
select_single: QPushButton
|
||||
combos: QLineEdit
|
||||
single_input: QLineEdit
|
||||
single_output: QLineEdit
|
||||
display_combo: QComboBox
|
||||
next_combo: QPushButton
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class ProcessingView(SectionView):
|
||||
mode: QComboBox
|
||||
pages: QStackedWidget
|
||||
geometry_page: QWidget
|
||||
geometries: tuple[AntennaGeometryEditor, AntennaGeometryEditor]
|
||||
fixed_y: QCheckBox
|
||||
y_bounds: tuple[QDoubleSpinBox, QDoubleSpinBox]
|
||||
speed_controls: tuple[tuple[QCheckBox, QDoubleSpinBox], ...]
|
||||
trace_controls: tuple[ScalarWidget, ...]
|
||||
visual_controls: tuple[ScalarWidget, ...]
|
||||
locator_controls: tuple[ScalarWidget, ...]
|
||||
frequency_controls: tuple[QDoubleSpinBox, ...]
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class RadarView(SectionView):
|
||||
sweep_edits: tuple[QLineEdit, ...]
|
||||
sweep_labels: tuple[QLabel, ...]
|
||||
limits_hint: QLabel
|
||||
vna_panel: QWidget
|
||||
adc_panel: QWidget
|
||||
optical_enabled: QCheckBox
|
||||
optical_mode: QComboBox
|
||||
optical_common: tuple[ScalarWidget, ...]
|
||||
optical_manual: tuple[ScalarWidget, ...]
|
||||
optical_variation: tuple[ScalarWidget, ...]
|
||||
manual_panel: QWidget
|
||||
variation_panel: QWidget
|
||||
|
||||
|
||||
def read_setting(widget: ScalarWidget) -> Scalar:
|
||||
if isinstance(widget, QCheckBox):
|
||||
return widget.isChecked()
|
||||
if isinstance(widget, (QSpinBox, QDoubleSpinBox)):
|
||||
return widget.value()
|
||||
if isinstance(widget, QComboBox):
|
||||
return widget.currentText()
|
||||
if isinstance(widget, QPlainTextEdit):
|
||||
return widget.toPlainText()
|
||||
return widget.text()
|
||||
|
||||
|
||||
def write_setting(widget: ScalarWidget, value: Scalar) -> None:
|
||||
if isinstance(widget, QCheckBox):
|
||||
widget.setChecked(bool(value))
|
||||
elif isinstance(widget, QSpinBox):
|
||||
widget.setValue(int(value))
|
||||
elif isinstance(widget, QDoubleSpinBox):
|
||||
widget.setValue(float(value))
|
||||
elif isinstance(widget, QComboBox):
|
||||
text = str(value)
|
||||
index = widget.findText(text)
|
||||
if index < 0:
|
||||
widget.addItem(text)
|
||||
index = widget.count() - 1
|
||||
widget.setCurrentIndex(index)
|
||||
elif isinstance(widget, QPlainTextEdit):
|
||||
widget.setPlainText(str(value))
|
||||
else:
|
||||
widget.setText(str(value))
|
||||
|
||||
|
||||
def connect_setting(widget: ScalarWidget, callback: Callable[..., object]) -> None:
|
||||
if isinstance(widget, QCheckBox):
|
||||
signal = widget.toggled
|
||||
elif isinstance(widget, (QSpinBox, QDoubleSpinBox)):
|
||||
signal = widget.valueChanged
|
||||
elif isinstance(widget, QComboBox):
|
||||
signal = widget.currentTextChanged
|
||||
elif isinstance(widget, QPlainTextEdit):
|
||||
signal = widget.textChanged
|
||||
else:
|
||||
signal = widget.editingFinished
|
||||
signal.connect(callback)
|
||||
|
||||
|
||||
def double_spin(minimum: float, maximum: float, decimals: int, step: float) -> QDoubleSpinBox:
|
||||
widget = QDoubleSpinBox()
|
||||
widget.setDecimals(decimals)
|
||||
widget.setRange(minimum, maximum)
|
||||
widget.setSingleStep(step)
|
||||
return widget
|
||||
|
||||
|
||||
def integer_spin(minimum: int, maximum: int) -> QSpinBox:
|
||||
widget = QSpinBox()
|
||||
widget.setRange(minimum, maximum)
|
||||
return widget
|
||||
|
||||
|
||||
def choice(options: list[str]) -> QComboBox:
|
||||
widget = QComboBox()
|
||||
widget.addItems(options)
|
||||
return widget
|
||||
Reference in New Issue
Block a user