把 Studio 主机协议改成单向端口,并让「从视频重算」走分析入口
控制器经 AcquireGate / ImageSink / ShellNotes 与信号接线,采集 tick 用 acquire_presenter 上屏;三维测试证明分析结果已喂 3D 后,重算并入 on_analysis_requested。 验证:apps/studio 下相关 pytest 与 tools/ui_check.py(634 checks)通过。
This commit is contained in:
@@ -3220,11 +3220,57 @@ def main() -> int:
|
||||
app.processEvents()
|
||||
other_window.brand_bar.btn_playback.click()
|
||||
app.processEvents()
|
||||
check(
|
||||
other_window._load_replay_video(bare_video) is True,
|
||||
"a playable video with no recording beside it was refused",
|
||||
)
|
||||
app.processEvents()
|
||||
|
||||
# A video that is not a recording is asked *how* to analyse it before anything runs
|
||||
# (the setup prompt). These checks answer it and read its defaults back; the prompt is
|
||||
# modal, so a check that opens a bare video without answering would wait for a person.
|
||||
from orisys_studio.ui import video_analysis_dialog as _prompt_module
|
||||
from PySide6.QtWidgets import QDialog as _QDialog
|
||||
|
||||
_prompts: list = []
|
||||
_original_exec = _prompt_module.VideoAnalysisDialog.exec
|
||||
|
||||
def _answer_prompt(dialog_self):
|
||||
_prompts.append(dialog_self)
|
||||
dialog_self.select_profile("shipped/box")
|
||||
return _QDialog.DialogCode.Rejected
|
||||
|
||||
_prompt_module.VideoAnalysisDialog.exec = _answer_prompt
|
||||
try:
|
||||
check(
|
||||
other_window._load_replay_video(bare_video) is True,
|
||||
"a playable video with no recording beside it was refused",
|
||||
)
|
||||
app.processEvents()
|
||||
check(bool(_prompts), "opening a bare video did not ask how to analyse it")
|
||||
if _prompts:
|
||||
_prompt = _prompts[-1]
|
||||
check(
|
||||
_prompt.profile_combo.count() >= 1,
|
||||
"the setup prompt offers no processing profile",
|
||||
)
|
||||
check(
|
||||
"flow" in _prompt.capability_label.text(),
|
||||
f"the profile row does not say what it can do: "
|
||||
f"{_prompt.capability_label.text()!r}",
|
||||
)
|
||||
check(
|
||||
_prompt.calibration_combo.currentData() == "default",
|
||||
f"the calibration did not default to the profile's own: "
|
||||
f"{_prompt.calibration_combo.currentData()!r}",
|
||||
)
|
||||
check(
|
||||
_prompt.reference_spin.value() == 1,
|
||||
f"the reference frame did not default to the first: "
|
||||
f"{_prompt.reference_spin.value()}",
|
||||
)
|
||||
check(
|
||||
_prompt.select_profile("shipped/box") and _prompt.choice() is not None,
|
||||
"the shipped box profile cannot be set up for a video",
|
||||
)
|
||||
finally:
|
||||
_prompt_module.VideoAnalysisDialog.exec = _original_exec
|
||||
|
||||
check(
|
||||
other_window.replay.has_video() and other_window.replay.is_video_only(),
|
||||
"the video is not playable as a video",
|
||||
@@ -3268,7 +3314,7 @@ def main() -> int:
|
||||
other_window.act_recompute.isEnabled(),
|
||||
"a chosen video cannot be recomputed either: the operator has no way to view it",
|
||||
)
|
||||
other_window._stop_replay_activity()
|
||||
other_window.replay_ctl.stop_activity()
|
||||
app.processEvents()
|
||||
other_window.close()
|
||||
app.processEvents()
|
||||
@@ -3569,41 +3615,39 @@ def main() -> int:
|
||||
f"{replay_window.arrow_panel.view_modes()}",
|
||||
)
|
||||
|
||||
# The recompute mode: off (default) the charts read the recorded CSV; on, the
|
||||
# recorded video is run through the pipeline instead. The run itself is not
|
||||
# started here (that needs the SDK), only the wiring around it.
|
||||
# 「从视频重算」 shares on_analysis_requested with opening a recording — no
|
||||
# acquisition chain. Charts keep the recorded CSV; analysis feeds 2D/3D.
|
||||
started: list = []
|
||||
asked: list = []
|
||||
replay_window._start_run = lambda: started.append(True)
|
||||
original_analysis = replay_window.replay_ctl.on_analysis_requested
|
||||
|
||||
def _spy_analysis() -> None:
|
||||
asked.append(True)
|
||||
return original_analysis()
|
||||
|
||||
replay_window.replay_ctl.on_analysis_requested = _spy_analysis
|
||||
replay_window.act_recompute.setChecked(True)
|
||||
for _ in range(3):
|
||||
app.processEvents()
|
||||
check(asked == [True], "the recompute switch did not ask for analysis")
|
||||
check(started == [], "the recompute switch opened an acquisition chain")
|
||||
check(
|
||||
started == [True],
|
||||
"the recompute mode did not hand the video to the pipeline",
|
||||
replay_plots.is_recording_source(),
|
||||
"analysis must not replace the recorded CSV on the charts",
|
||||
)
|
||||
check(
|
||||
not replay_plots.is_recording_source(),
|
||||
"the charts still read the CSV while recomputing",
|
||||
)
|
||||
check(
|
||||
replay_window.toolbar.source_mode() == "video"
|
||||
and replay_window.toolbar.video_path().endswith(".mp4"),
|
||||
f"the recompute mode did not select the video: "
|
||||
f"{replay_window.toolbar.source_mode()!r} / "
|
||||
f"{replay_window.toolbar.video_path()!r}",
|
||||
)
|
||||
replay_window._recompute_running = True
|
||||
replay_window.act_recompute.setChecked(False)
|
||||
for _ in range(3):
|
||||
app.processEvents()
|
||||
check(
|
||||
replay_plots.is_recording_source(),
|
||||
"turning the recompute off did not restore the recorded curves",
|
||||
"turning the recompute off did not keep the recorded curves",
|
||||
)
|
||||
check(
|
||||
replay_window.toolbar.source_mode() == "camera" or not replay_window._running,
|
||||
"the recompute pass was left running",
|
||||
not replay_window._running,
|
||||
"an acquisition session was left running after recompute",
|
||||
)
|
||||
replay_window.replay_ctl.on_analysis_requested = original_analysis
|
||||
|
||||
# Leaving the replay view returns the charts to the live session and hides
|
||||
# the bar: the replay stays available, it just stops being on screen.
|
||||
|
||||
Reference in New Issue
Block a user