fixed commetn from songxiao

This commit is contained in:
ykcheungab
2026-09-25 17:46:37 +08:00
parent 6effe74172
commit 12781854ca
56 changed files with 4935 additions and 419 deletions
+180 -23
View File
@@ -225,10 +225,10 @@ def test_a_hung_connect_can_be_cancelled_immediately(make_window, cancel_via):
assert window._session_phase == "connecting"
try:
if cancel_via == "toolbar":
assert window.toolbar.btn_run.isEnabled(), "Stop is disabled while connecting"
assert window.toolbar.btn_run.text() == t("toolbar.cancel_label")
assert window.toolbar.btn_stop.isEnabled(), "Stop is disabled while connecting"
assert window.toolbar.btn_stop.text() == t("toolbar.cancel_label")
assert window.act_stop.isEnabled()
cancel = lambda: window.toolbar.btn_run.setChecked(False)
cancel = window.toolbar.btn_stop.click
else:
assert window.act_stop.shortcut().toString() == "Esc"
cancel = window._on_stop_shortcut
@@ -1062,7 +1062,12 @@ def test_idle_run_is_the_only_filled_action(make_window):
def test_connecting_cancel_stays_filled(make_window):
"""Cancel is the way out of a hung device open, so it keeps the weight."""
"""Cancel is the way out of a hung device open, so it keeps the weight.
It lives on the rail's Stop button now (the transport is a play/pause toggle in
both views, so it can no longer be the stop), which is why the filled danger is
checked there.
"""
from PySide6.QtWidgets import QApplication
window = _show(make_window(), (1440, 880))
@@ -1073,8 +1078,8 @@ def test_connecting_cancel_stays_filled(make_window):
window.toolbar.btn_run.setChecked(True)
QApplication.processEvents()
assert window._session_phase == "connecting"
assert window.toolbar.btn_run.objectName() == "dangerButton"
window.toolbar.btn_run.setChecked(False)
assert window.toolbar.btn_stop.objectName() == "dangerButton"
window.toolbar.btn_stop.click()
stuck.release()
@@ -1088,26 +1093,86 @@ def test_exactly_one_filled_action_while_acquiring(make_window):
window.toolbar.btn_run.setChecked(True)
window._run_timer.stop()
assert window._session_phase == "connecting"
assert window.toolbar.btn_run.objectName() == "dangerButton", (
assert window.toolbar.btn_stop.objectName() == "dangerButton", (
"Cancel lost its weight while a connect can hang"
)
stuck.emit(ui_check._fake_packet(1))
window._on_run_tick()
assert window._session_phase == "running"
assert window.toolbar.btn_run.objectName() == "dangerOutline", (
assert window.toolbar.btn_stop.objectName() == "dangerOutline", (
"Stop is still the filled action while a session merely acquires"
)
assert window.toolbar.btn_record.objectName() == "primaryButton"
assert window.toolbar.btn_run.objectName() == "ghostButton", (
"the transport competes with the filled record action"
)
window.toolbar.set_record_checked(True)
assert window.toolbar.btn_record.objectName() == "dangerButton"
assert window.toolbar.btn_run.objectName() == "dangerOutline", (
assert window.toolbar.btn_stop.objectName() == "dangerOutline", (
"two filled actions share the rail while recording"
)
window.toolbar.set_record_checked(False)
window.toolbar.btn_stop.click()
stuck.release()
def test_the_live_rail_is_a_play_pause_toggle_with_its_own_stop(make_window):
"""Slot 1 means the same thing in both views: play/pause, and Stop beside it.
The live view used to fill that slot with a stop toggle and keep a second,
icon-only pause button next to it, so the same position meant two different
things depending on which view was on screen.
"""
from PySide6.QtWidgets import QApplication
from orisys_app_shared.i18n import t
window = _show(make_window(), (1440, 880))
stuck = ui_check._StuckWorker()
window._ensure_workers = lambda: None
window._box_worker = stuck
window._finger_worker = stuck
# Idle: the transport starts the session, and Stop has nothing to end.
assert window.toolbar.btn_run.text() == t("toolbar.run_label")
assert not window.toolbar.btn_stop.isEnabled()
# Connecting: still a pause toggle, and Stop is the way out of a hung open.
window.toolbar.btn_run.setChecked(True)
window._run_timer.stop()
QApplication.processEvents()
assert window._session_phase == "connecting"
assert window.toolbar.btn_run.text() == t("toolbar.pause")
assert window.toolbar.btn_stop.text() == t("toolbar.cancel_label")
assert window.toolbar.btn_stop.isEnabled()
stuck.emit(ui_check._fake_packet(1))
window._on_run_tick()
QApplication.processEvents()
assert window._session_phase == "running"
assert window.toolbar.btn_run.text() == t("toolbar.pause")
# Unchecked *with* a session is paused, not stopped.
window.toolbar.btn_run.setChecked(False)
QApplication.processEvents()
assert window._session_phase == "running", "the transport stopped instead of pausing"
assert window.toolbar.btn_run.text() == t("toolbar.resume_label")
assert stuck.is_paused is True, "the worker was not asked to pause"
assert window.toolbar.btn_stop.isEnabled(), "the way out vanished while paused"
window.toolbar.btn_run.setChecked(True)
QApplication.processEvents()
assert stuck.is_paused is False, "the worker was not asked to resume"
# Stop ends it; the transport goes back to idle.
window.toolbar.btn_stop.click()
QApplication.processEvents()
assert window._session_phase == "idle"
assert not window.toolbar.btn_run.isChecked()
assert window.toolbar.btn_run.text() == t("toolbar.run_label")
stuck.release()
@@ -1590,9 +1655,16 @@ def test_a_late_calibration_does_not_plot_raw_counts_on_the_newton_axis(make_win
assert peak < 5.0, f"a raw count is still drawn on the newton axis (peak {peak})"
# The sample that caused the switch still reaches the readouts; the early
# return used to leave the cards showing the previous sample.
# return used to leave the cards showing the previous sample. The number on
# the card is the *display* copy of it: this fake FN is a slow 2.0…2.4 N ramp
# with no contact flagged, which is exactly the resting drift the display
# baseline holds at zero. What matters here is that the card is not a raw
# count, not the previous sample and not a dash.
assert abs(plots._last_values[0] - (2.0 + 39 * 0.01)) < 1e-9
assert plots.value_labels[0].text() == "2.390", plots.value_labels[0].text()
assert plots.presentation.display_quality != "none", (
"the display policy was not applied to the freshly shown newton unit"
)
assert plots.value_labels[0].text() == "0.000", plots.value_labels[0].text()
assert plots.value_labels[0].text() != t("chart.value_unavailable")
_finish(window, stuck)
@@ -1926,8 +1998,10 @@ def test_the_replay_view_offers_a_stop_that_always_works(make_window, replay_rec
"""The operator must not have to work out *what* is stuck before stopping it.
The transport is a play/pause toggle, which is ambiguous exactly when something is
wrong. So the rail's second button becomes an unconditional stop in this view, and
it covers both things that can run there: plain playback and a recompute pass.
wrong. So the rail's Stop button — the same one the live view uses to end a session
— is an unconditional stop in this view, and it covers both things that can run
there: plain playback and a recompute pass. The tracker reset owns no device here,
so it is disabled rather than repurposed.
"""
from PySide6.QtWidgets import QApplication
@@ -1939,11 +2013,12 @@ def test_the_replay_view_offers_a_stop_that_always_works(make_window, replay_rec
assert window._load_recording(replay_recording)
QApplication.processEvents()
assert window.toolbar.reset_role() == "stop", (
"the replay view kept the tracker reset button instead of a stop"
)
assert window.toolbar.btn_reset.text() == t("toolbar.stop_playback")
assert not window.toolbar.btn_reset.isEnabled(), (
"the replay view offers to zero a device tracker it has not got"
)
assert window.toolbar.btn_reset.text() == t("toolbar.reset")
assert window.toolbar.btn_stop.text() == t("toolbar.stop_label")
assert not window.toolbar.btn_stop.isEnabled(), (
"a stop is offered while nothing is running"
)
@@ -1951,8 +2026,8 @@ def test_the_replay_view_offers_a_stop_that_always_works(make_window, replay_rec
window.toolbar.btn_run.setChecked(True)
QApplication.processEvents()
assert window._play_timer.isActive()
assert window.toolbar.btn_reset.isEnabled(), "no stop offered while playing"
window.toolbar.btn_reset.click()
assert window.toolbar.btn_stop.isEnabled(), "no stop offered while playing"
window.toolbar.btn_stop.click()
QApplication.processEvents()
assert not window._play_timer.isActive(), "the stop did not stop the playback"
assert not window.toolbar.btn_run.isChecked(), "the transport still shows playing"
@@ -1965,8 +2040,8 @@ def test_the_replay_view_offers_a_stop_that_always_works(make_window, replay_rec
window._stop_run = lambda **kwargs: stopped.append(kwargs.get("reason"))
window._recompute_running = True
window._update_run_enabled()
assert window.toolbar.btn_reset.isEnabled(), "no stop offered while a pass runs"
window.toolbar.btn_reset.click()
assert window.toolbar.btn_stop.isEnabled(), "no stop offered while a pass runs"
window.toolbar.btn_stop.click()
QApplication.processEvents()
assert stopped == ["user_stop"], stopped
assert t("toolbar.stopped_pass") in window.statusBar().currentMessage(), (
@@ -1976,7 +2051,7 @@ def test_the_replay_view_offers_a_stop_that_always_works(make_window, replay_rec
# Nothing running: it says so instead of doing nothing at all.
# (The pass is over, so the stop button is correctly disabled — the escape hatch is
# therefore exercised the way Esc reaches it, through the controller.)
assert not window.toolbar.btn_reset.isEnabled(), (
assert not window.toolbar.btn_stop.isEnabled(), (
"a stop is still offered after the pass was stopped"
)
window.replay_ctl.stop_activity()
@@ -2009,10 +2084,14 @@ def test_escape_stops_the_replay_too(make_window, replay_recording):
def test_the_live_view_keeps_the_tracker_reset(make_window):
from PySide6.QtWidgets import QApplication
from orisys_app_shared.i18n import t
window = _show(make_window(), (1440, 880))
window.brand_bar.btn_live.click()
QApplication.processEvents()
assert window.toolbar.reset_role() == "reset"
assert window.toolbar.btn_reset.text() == t("toolbar.reset"), (
"the rail's reset slot is not the tracker reset in the live view"
)
window.close()
@@ -2549,6 +2628,84 @@ def test_the_dialog_writes_the_keys_the_session_reads_back(qt_app):
assert read_back.describe() == "flowEMA(0.5) + median(3) + lowpass(10Hz,order2)"
def test_the_plot_dialog_carries_the_ranges_and_the_zero_threshold(qt_app):
"""FN has a lower bound (which may be negative); both units a deadband."""
from orisys_studio.ui.plot_settings_dialog import PlotSettingsDialog
dialog = PlotSettingsDialog(
units="newton", fn_min=-2.0, fn_max=6.0, deadband_n=0.25, deadband_raw=2000.0
)
assert dialog.settings()["fn_min"] == -2.0
assert dialog.settings()["fn_max"] == 6.0
assert dialog.deadbands() == {"deadband_n": 0.25, "deadband_raw": 2000.0}
# Only the half that belongs to the unit being shown can be edited.
assert dialog.fn_min_spin.isEnabled() and not dialog.fn_raw_min_spin.isEnabled()
assert dialog.deadband_n_spin.isEnabled()
assert not dialog.deadband_raw_spin.isEnabled()
raw = PlotSettingsDialog(units="raw")
assert raw.fn_raw_min_spin.isEnabled() and not raw.fn_min_spin.isEnabled()
assert raw.deadband_raw_spin.isEnabled() and not raw.deadband_n_spin.isEnabled()
raw.fn_raw_min_spin.setValue(-50000.0)
raw.deadband_raw_spin.setValue(5000.0)
assert raw.settings()["fn_raw_min"] == -50000.0
raw._reset_defaults()
assert raw.settings()["fn_raw_min"] == 0.0
assert raw.settings()["fn_min"] == 0.0
assert raw.settings()["window_sec"] == 4.0
assert raw.deadbands() == {"deadband_n": 0.0, "deadband_raw": 0.0}, (
"the shipped deadband answer is 'auto'"
)
def test_the_plot_dialog_values_reach_the_chart(make_window):
"""Dialog -> controller -> panel: where an operator's range actually lands."""
from orisys_studio.ui.plot_settings_dialog import PlotSettingsDialog
window = make_window()
dialog = PlotSettingsDialog(
units="newton",
window_sec=6.0,
fn_min=-2.0,
fn_max=6.0,
shear_max=3.0,
fn_raw_min=-1000.0,
fn_raw_max=5e5,
shear_raw_max=2e5,
deadband_n=0.25,
deadband_raw=3000.0,
)
window.display_ctl.apply_plot_settings(dialog.settings())
plots = window.force_plots
assert (plots._fn_min, plots._fn_max, plots._shear_max) == (-2.0, 6.0, 3.0)
assert (plots._fn_raw_min, plots._fn_raw_max, plots._shear_raw_max) == (
-1000.0, 5e5, 2e5,
)
assert plots.presentation.min_deadband_for("N") == 0.25
assert plots.presentation.min_deadband_for("raw") == 3000.0
assert window.prefs["plot_fn_min"] == -2.0
assert window.prefs["plot_deadband_raw"] == 3000.0
assert plots.history.window_sec == 6.0
# And the dialog would open on the same numbers next time.
assert window.display_ctl.plot_settings()["fn_min"] == -2.0
window.close()
def test_the_display_baseline_is_on_for_every_sensor_by_default(make_window):
"""It used to be Finger-raw only; an idle box sensor drifts just as much."""
window, stuck = _running_window(make_window) # sensor_type="box"
plots = window.force_plots
assert plots._presentation_enabled is True, "a box sensor lost its baseline"
assert plots.presentation.enabled is True
# The per-unit floors came from the preferences, not from a sensor type.
assert plots.presentation.min_deadband_for("raw") == 50.0
assert plots.presentation.min_deadband_for("N") == 0.0
_finish(window, stuck)