接入 Studio 控件与菜单构建模块

将界面构建从主窗口移出,保留现有业务回调与标定路径。验证结果和完整门禁限制见 docs/architecture/studio-window-refactor-plan.zh.md。
This commit is contained in:
ykcheungab
2026-10-19 10:14:58 +08:00
parent 22658dbfc1
commit d477a4d8b7
6 changed files with 189 additions and 260 deletions
+71 -1
View File
@@ -1,4 +1,4 @@
"""Prepared shell surfaces work without the main window or business wiring."""
"""Shell surfaces work independently and retain their behavior when wired."""
import pytest
from orisys_app_shared.i18n import get_translator, set_locale, t
@@ -164,3 +164,73 @@ def test_text_refresh_preserves_controller_owned_action_state(window):
assert ui.act_reset.text() == "context-dependent reset"
assert ui.act_pause.isChecked()
assert not ui.act_run.isEnabled()
def test_shell_uses_the_surface_widgets_and_actions(make_window):
shell = make_window()
assert shell.centralWidget() is shell.ui.central
for name in (
"brand_bar", "sensor_picker", "toolbar", "status_chip", "analysis_progress",
"content_splitter", "mesh3d_panel", "arrow_panel", "force_plots", "cal_panel",
):
assert getattr(shell, name) is getattr(shell.ui, name)
assert shell.file_menu is shell.menus.file_menu
assert shell.act_play is shell.menus.act_play
assert shell.act_reset is shell.menus.act_reset
assert shell.mesh3d_panel.view is None
assert not shell.session.is_running
def test_shell_menu_commands_dispatch_once(make_window, monkeypatch):
from orisys_studio.app_window import StudioMainWindow
calls = []
def handler(name):
return lambda self: calls.append(name)
commands = {
"run": "_on_run_shortcut",
"stop": "_on_stop_shortcut",
"preview": "_on_preview_shortcut",
"reset": "_on_reset",
"reset_view": "_on_reset_view",
}
for name, method in commands.items():
monkeypatch.setattr(StudioMainWindow, method, handler(name))
shell = make_window()
calls.clear()
for name in commands:
action = getattr(shell.menus, f"act_{name}")
# No device is attached; exercise dispatch without availability policy.
action.setEnabled(True)
action.trigger()
assert calls == list(commands)
def test_shell_appearance_actions_refresh_widgets_and_menus(make_window, qt_app):
original_locale = get_translator().locale
original_stylesheet = qt_app.styleSheet()
shell = make_window()
try:
background = shell.force_plots.plot_widget.backgroundBrush().color()
shell.menus.act_theme_light.trigger()
assert shell.prefs["theme"] == "light"
assert shell.force_plots.plot_widget.backgroundBrush().color() != background
assert shell.menus.act_theme_light.isChecked()
assert not shell.menus.act_theme_dark.isChecked()
shell.menus.act_lang_en.trigger()
assert shell.prefs["language"] == "en_US"
assert shell.file_menu.title() == t("menu.file")
assert shell.brand_bar.btn_live.text() == t("brand.nav_live")
assert shell.act_reset.text() == t("menu.reset")
assert shell.toolbar.btn_reset.text() == t("toolbar.reset_sensor")
shell.layout_ctl.apply_preset("replay")
assert shell.act_reset.text() == t("menu.reset_display")
assert shell.toolbar.btn_reset.text() == t("toolbar.reset_display")
assert shell.menus.act_lang_en.isChecked()
assert not shell.menus.act_lang_zh.isChecked()
assert shell.mesh3d_panel.view is None
finally:
set_locale(original_locale)
qt_app.setStyleSheet(original_stylesheet)