Polish GUI design

This commit is contained in:
Ayzen
2026-10-06 14:16:14 +03:00
parent 5bb86b7165
commit 4947d5a14e
25 changed files with 222 additions and 235 deletions
@@ -34,8 +34,9 @@ def build_data_actions_group(gui: GuiStateModel) -> DataView:
)
save_vna_json_button.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
remove_last_button = QPushButton("Remove Last Measurement")
remove_last_button.setProperty("role", "destructive")
remove_last_button.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
capture_tmp_reference_button = QPushButton("Capture Tmp Reference")
capture_tmp_reference_button = QPushButton("Capture Temporary Reference")
capture_tmp_reference_button.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
record_button = QPushButton("Start + Record to Disk")
record_button.setToolTip(
@@ -61,7 +62,7 @@ def build_data_actions_group(gui: GuiStateModel) -> DataView:
record_count_row = QHBoxLayout()
record_count_row.setSpacing(8)
record_count_row.addWidget(QLabel("Number of Sweeps to Record"))
record_count_row.addWidget(QLabel("Sweeps to record"))
record_count_row.addWidget(record_count)
record_count_row.addStretch(1)
layout.addLayout(record_count_row)
@@ -69,7 +70,7 @@ def build_data_actions_group(gui: GuiStateModel) -> DataView:
path_row = QHBoxLayout()
path_row.setSpacing(8)
save_path_input = view.add("_save_path_input", QLineEdit(str(data_defaults.save_path)))
browse_button = QPushButton("Browse")
browse_button = QPushButton("Browse…")
path_row.addWidget(QLabel("Path"))
path_row.addWidget(save_path_input, stretch=1)
path_row.addWidget(browse_button)
@@ -22,6 +22,7 @@ def build_two_column_form_widget(
form.setContentsMargins(0, 0, 0, 0)
form.setHorizontalSpacing(10)
form.setVerticalSpacing(6)
form.setRowWrapPolicy(QFormLayout.RowWrapPolicy.WrapLongRows)
form.setFieldGrowthPolicy(QFormLayout.FieldGrowthPolicy.AllNonFixedFieldsGrow)
for row in column_rows:
if isinstance(row, tuple):
@@ -20,7 +20,7 @@ def build_preprocess_summary_group() -> PreprocessView:
for key in PREPROCESS_ASSET_NAMES:
label = QLabel("<not selected>")
view.labels[key] = label
rows.append((preprocess_asset_display_name(key), label))
rows.append((preprocess_asset_display_name(key).capitalize(), label))
layout.addWidget(build_two_column_form_widget(group, rows, split_index=(len(rows) + 1) // 2))
return view
@@ -1,16 +1,18 @@
"""Pinned primary actions; controllers connect their own buttons."""
from PyQt6.QtWidgets import QGridLayout, QGroupBox, QPushButton, QSizePolicy
from PyQt6.QtWidgets import QComboBox, QFormLayout, QGridLayout, QGroupBox, QPushButton, QSizePolicy, QWidget
from python_app.gui.controllers.sections.views import PrimaryView
def build_primary_actions_group() -> PrimaryView:
def build_primary_actions_group(mode: QComboBox) -> PrimaryView:
view = PrimaryView(group=QGroupBox("Actions"), start=QPushButton("Start"),
single_capture=QPushButton("Single Capture"), stop=QPushButton("Stop"),
apply_radar=QPushButton("Apply Radar"), load=QPushButton("Load Config"),
save=QPushButton("Save Config"), preprocess=QPushButton("Preprocessing"),
apply_radar=QPushButton("Apply Radar"), load=QPushButton("Load Config…"),
save=QPushButton("Save Config…"), preprocess=QPushButton("Preprocessing…"),
clear=QPushButton("Clear Runtime History"))
view.start.setProperty("role", "primary")
view.clear.setProperty("role", "destructive")
layout = QGridLayout(view.group)
layout.setHorizontalSpacing(8)
layout.setVerticalSpacing(8)
@@ -20,4 +22,9 @@ def build_primary_actions_group() -> PrimaryView:
layout.addWidget(button, index // 3, index % 3, 1, 2 if button is view.clear else 1)
for column in range(3):
layout.setColumnStretch(column, 1)
mode_row = QWidget(view.group)
mode_form = QFormLayout(mode_row)
mode_form.setContentsMargins(0, 0, 0, 0)
mode_form.addRow("Mode", mode)
layout.addWidget(mode_row, 3, 0, 1, 3)
return view
@@ -75,8 +75,8 @@ def build_processing_group(config: RunConfigModel, gui: GuiStateModel) -> Proces
unwrap_phase_checkbox,
("Switch combos", pass_through_combo_filter_input),
pass_through_fixed_y_enabled,
("Y min dB", pass_through_y_min_db),
("Y max dB", pass_through_y_max_db),
("Y min (dB)", pass_through_y_min_db),
("Y max (dB)", pass_through_y_max_db),
],
split_index=5,
)
@@ -98,11 +98,11 @@ def build_processing_group(config: RunConfigModel, gui: GuiStateModel) -> Proces
processing_mode_pages,
[
("Axis", bscan_axis),
("Cut m", bscan_cut_m),
("Max depth m", bscan_max_depth_m),
("Cut (m)", bscan_cut_m),
("Max depth (m)", bscan_max_depth_m),
("Gain", bscan_gain),
("Start MHz", bscan_start_freq_mhz),
("Stop MHz", bscan_stop_freq_mhz),
("Start (MHz)", bscan_start_freq_mhz),
("Stop (MHz)", bscan_stop_freq_mhz),
("Scans to show (stopped)", bscan_history_window),
bscan_subtract_mean_ascan,
],
@@ -188,27 +188,27 @@ def build_processing_group(config: RunConfigModel, gui: GuiStateModel) -> Proces
[
("Input positions", gpr_input_positions_input),
("Output positions", gpr_output_positions_input),
("Min depth m", gpr_min_depth_m),
("Max depth m", gpr_max_depth_m),
("Range comp power", gpr_range_comp_power),
("Object min frac", gpr_object_min_frac),
("Min depth (m)", gpr_min_depth_m),
("Max depth (m)", gpr_max_depth_m),
("Range compensation power", gpr_range_comp_power),
("Object threshold fraction", gpr_object_min_frac),
("Score mode", gpr_score_mode),
("Motion mode", gpr_motion_mode),
("Look angle deg", gpr_look_angle_deg),
("Look angle (°)", gpr_look_angle_deg),
("Direction sign", gpr_direction_sign),
gpr_ignore_socket_speed_enabled,
("Speed m/s", gpr_speed_m_s),
("Speed (m/s)", gpr_speed_m_s),
("Render mode", gpr_render_mode),
("Max detected objects", gpr_max_detected_objects_to_draw),
("Draw top M objects", gpr_draw_top_m_objects),
("Approach min frames", gpr_object_approach_min_frames),
("Start MHz", gpr_start_freq_mhz),
("Stop MHz", gpr_stop_freq_mhz),
("Imaging plane Y m", gpr_imaging_plane_y_m),
("Visible X min m", gpr_visible_x_min_m),
("Visible X max m", gpr_visible_x_max_m),
("Visible Z min m", gpr_visible_z_min_m),
("Visible Z max m", gpr_visible_z_max_m),
("Start (MHz)", gpr_start_freq_mhz),
("Stop (MHz)", gpr_stop_freq_mhz),
("Imaging plane Y (m)", gpr_imaging_plane_y_m),
("Visible X min (m)", gpr_visible_x_min_m),
("Visible X max (m)", gpr_visible_x_max_m),
("Visible Z min (m)", gpr_visible_z_min_m),
("Visible Z max (m)", gpr_visible_z_max_m),
gpr_background_subtract_enabled,
("Mean count", gpr_background_mean_count),
gpr_remove_sidelobe_objects_enabled,
@@ -259,24 +259,24 @@ def build_processing_group(config: RunConfigModel, gui: GuiStateModel) -> Proces
("Relative permittivity", gpr_relative_permittivity),
("Input positions", legacy_gpr_input_positions_input),
("Output positions", legacy_gpr_output_positions_input),
("Min depth m", legacy_gpr_min_depth_m),
("Max depth m", legacy_gpr_max_depth_m),
("Comp power", legacy_gpr_comp_power),
("SNR thresh", legacy_gpr_snr_thresh),
("SNR comp max", legacy_gpr_snr_comp_max),
("Speed m/s", legacy_gpr_speed_m_s),
("Min depth (m)", legacy_gpr_min_depth_m),
("Max depth (m)", legacy_gpr_max_depth_m),
("Compensation power", legacy_gpr_comp_power),
("SNR threshold", legacy_gpr_snr_thresh),
("Max SNR compensation", legacy_gpr_snr_comp_max),
("Speed (m/s)", legacy_gpr_speed_m_s),
legacy_gpr_ignore_socket_speed_enabled,
("Render mode", legacy_gpr_render_mode),
("Min visible pairs", legacy_gpr_min_visible_pair_count),
("Start MHz", legacy_gpr_start_freq_mhz),
("Stop MHz", legacy_gpr_stop_freq_mhz),
("Look angle deg", legacy_gpr_look_angle_deg),
("Start (MHz)", legacy_gpr_start_freq_mhz),
("Stop (MHz)", legacy_gpr_stop_freq_mhz),
("Look angle (°)", legacy_gpr_look_angle_deg),
("Reference mode", legacy_gpr_reference_mode),
legacy_gpr_apply_freq_phase_correction,
("Visible X min m", legacy_gpr_visible_x_min_m),
("Visible X max m", legacy_gpr_visible_x_max_m),
("Visible Z min m", legacy_gpr_visible_z_min_m),
("Visible Z max m", legacy_gpr_visible_z_max_m),
("Visible X min (m)", legacy_gpr_visible_x_min_m),
("Visible X max (m)", legacy_gpr_visible_x_max_m),
("Visible Z min (m)", legacy_gpr_visible_z_min_m),
("Visible Z max (m)", legacy_gpr_visible_z_max_m),
legacy_gpr_background_subtract_enabled,
("Mean count", legacy_gpr_background_mean_count),
],
@@ -345,7 +345,6 @@ def build_processing_group(config: RunConfigModel, gui: GuiStateModel) -> Proces
)
processing_mode_pages.addWidget(sar3d_page)
form.addRow("Mode", processing_mode)
form.addRow(processing_mode_pages)
form.addRow(gpr_common_page)
@@ -39,25 +39,20 @@ def build_radar_group(config: RunConfigModel) -> RadarView:
power_input = view.add("_power_input", QLineEdit(f"{defaults.sweep.power_dbm:g}"))
power_input.setToolTip("Stimulus power configured in the active profile.")
radar_start_label = QLabel("Start Hz")
radar_stop_label = QLabel("Stop Hz")
radar_points_label = QLabel("Points")
radar_ifbw_label = QLabel("IF BW Hz")
radar_power_label = QLabel("Stimulus Power dBm")
radar_labels = tuple(QLabel(text) for text in (
"Start (Hz)", "Stop (Hz)", "Points", "IF bandwidth (Hz)", "Stimulus power (dBm)",
))
for label in radar_labels:
label.setWordWrap(True)
radar_limits_hint = QLabel("Device limits are not available.")
radar_limits_hint.setObjectName("hintLabel")
radar_limits_hint.setWordWrap(True)
vna_layout.addWidget(
build_two_column_form_widget(
group,
[
(radar_start_label, start_hz_input),
(radar_stop_label, stop_hz_input),
(radar_points_label, points_input),
(radar_ifbw_label, ifbw_input),
(radar_power_label, power_input),
],
list(zip(radar_labels, (start_hz_input, stop_hz_input, points_input, ifbw_input, power_input))),
)
)
vna_layout.addWidget(radar_limits_hint)
@@ -71,7 +66,7 @@ def build_radar_group(config: RunConfigModel) -> RadarView:
adc_radar_settings_panel.setVisible(config.is_kamil_adc)
return RadarView(group=group, fields=view.fields,
sweep_edits=(start_hz_input, stop_hz_input, points_input, ifbw_input, power_input),
sweep_labels=(radar_start_label, radar_stop_label, radar_points_label, radar_ifbw_label, radar_power_label),
sweep_labels=radar_labels,
limits_hint=radar_limits_hint, vna_panel=vna_radar_settings_panel, adc_panel=adc_radar_settings_panel,
optical_enabled=optical_enabled, optical_mode=optical_mode, optical_common=optical_common,
optical_manual=optical_manual, optical_variation=optical_variation,
@@ -144,9 +139,9 @@ def _build_adc_settings_panel(view: SectionView, config: RunConfigModel):
("TTY path", adc_tty_path_input),
("Arguments", adc_args_input),
("Environment JSON", adc_env_input),
("Startup timeout s", adc_startup_timeout_s_input),
("Read timeout s", adc_sweep_timeout_s_input),
("Stop timeout s", adc_stop_timeout_s_input),
("Startup timeout (s)", adc_startup_timeout_s_input),
("Read timeout (s)", adc_sweep_timeout_s_input),
("Stop timeout (s)", adc_stop_timeout_s_input),
("Board enabled", optical_enabled_checkbox),
("Board port", optical_port_input),
("Board mode", optical_mode_combo),
@@ -29,7 +29,7 @@ def build_switch_group(config: RunConfigModel, gui: GuiStateModel) -> SwitchView
global_form = QFormLayout()
global_form.setFieldGrowthPolicy(QFormLayout.FieldGrowthPolicy.AllNonFixedFieldsGrow)
settling_ms = view.add("_settling_ms", QLineEdit(str(config.runtime.settling_ms)))
global_form.addRow("Settling ms", settling_ms)
global_form.addRow("Settling (ms)", settling_ms)
layout.addLayout(global_form)
combos_text = view.add("_combos_text", QLineEdit(str(switch_defaults.combos_text)))
@@ -71,7 +71,7 @@ def build_switch_group(config: RunConfigModel, gui: GuiStateModel) -> SwitchView
display_combo = view.add("_display_combo", QComboBox())
display_combo.setEnabled(False)
display_row.addWidget(display_combo, stretch=1)
next_combo_button = QPushButton("Next combination")
next_combo_button = QPushButton("Next Combination")
next_combo_button.setEnabled(False)
display_row.addWidget(next_combo_button)
layout.addLayout(display_row)