diff --git a/app/ucd/service.py b/app/ucd/service.py index 3c3924e..aa16309 100644 --- a/app/ucd/service.py +++ b/app/ucd/service.py @@ -4,11 +4,18 @@ from __future__ import annotations import logging from app.ucd.domain import ( + Colorimetry, + DynamicRange, EventBus, + PatternKind, PatternSpec, SignalFormat, TimingSpec, + UcdError, UcdState, + build_signal_format, + build_signal_format_from_profile, + build_timing, image_pattern, solid_rgb_pattern, ) diff --git a/app/views/panel_manager.py b/app/views/panel_manager.py index e71b3cb..36b35d8 100644 --- a/app/views/panel_manager.py +++ b/app/views/panel_manager.py @@ -97,6 +97,12 @@ def hide_all_panels(self: "PQAutomationApp"): self.current_panel = None + if hasattr(self, "_sync_save_button_state"): + try: + self._sync_save_button_state() + except Exception: + pass + diff --git a/app/views/panels/ai_image_panel.py b/app/views/panels/ai_image_panel.py index 8462480..44aee8d 100644 --- a/app/views/panels/ai_image_panel.py +++ b/app/views/panels/ai_image_panel.py @@ -1087,12 +1087,7 @@ def _show_list_context_menu(self: "PQAutomationApp", event): _switch_to_session(self, sid, show_message=False, refresh_list=False) has_selection = self.ai_image_current is not None - ucd = getattr(self, "ucd", None) - can_send = ( - has_selection - and ucd is not None - and getattr(ucd, "status", False) - ) + can_send = has_selection and self.is_ucd_connected try: self.ai_image_menu.entryconfigure( 0, state=("normal" if can_send else "disabled") @@ -1120,8 +1115,7 @@ def _send_to_ucd(self: "PQAutomationApp"): if not os.path.isfile(rec.image_path): messagebox.showerror("错误", f"图片文件不存在:\n{rec.image_path}") return - ucd = getattr(self, "ucd", None) - if ucd is None or not getattr(ucd, "status", False): + if not self.is_ucd_connected: messagebox.showwarning("警告", "请先连接 UCD323 设备") return diff --git a/app/views/pq_debug_panel.py b/app/views/pq_debug_panel.py index 5c182a3..2f7b86a 100644 --- a/app/views/pq_debug_panel.py +++ b/app/views/pq_debug_panel.py @@ -722,7 +722,7 @@ class PQDebugPanel: test_item: gamma / eotf / accuracy / rgb """ # 检查设备连接 - if not self.app.ca or not self.app.ucd: + if not self.app.ca or not self.app.is_ucd_connected: messagebox.showerror("错误", "请先连接设备") return diff --git a/pqAutomationApp.py b/pqAutomationApp.py index c1cac03..40ec408 100644 --- a/pqAutomationApp.py +++ b/pqAutomationApp.py @@ -67,6 +67,16 @@ from app.runner.test_runner import TestRunnerMixin plt.rcParams["font.family"] = ["sans-serif"] plt.rcParams["font.sans-serif"] = ["Microsoft YaHei"] + +class _LegacyUcdConnected: + """Shim for legacy ``self.ucd.status`` checks after the UCD service refactor.""" + + status = True + + +_LEGACY_UCD_CONNECTED = _LegacyUcdConnected() + + class PQAutomationApp( ConfigIOMixin, ChartFrameMixin, @@ -207,6 +217,7 @@ class PQAutomationApp( # 创建测试类型选择区域 self.create_test_type_frame() self._setup_connection_event_handlers() + self.refresh_connection_indicators() # 创建操作按钮区域 self.create_operation_frame() # 创建结果图表区域 @@ -235,6 +246,18 @@ class PQAutomationApp( anchor=tk.E, ).pack(side=tk.RIGHT) + @property + def is_ucd_connected(self) -> bool: + """UCD323 是否已连接(统一入口,替代旧的 ``self.ucd.status``)。""" + return self.signal_service.is_connected + + @property + def ucd(self): + """Legacy UCD handle: ``None`` when disconnected, truthy object with ``.status`` when connected.""" + if not self.is_ucd_connected: + return None + return _LEGACY_UCD_CONNECTED + def _setup_connection_event_handlers(self) -> None: """订阅连接事件,驱动 UCD / CA 指示灯(替代轮询 controller.status)。""" @@ -463,19 +486,38 @@ class PQAutomationApp( self._chart_snapshots[test_type] = {} self._chart_snapshots[test_type][chart_name] = args + def _has_saveable_results(self, test_type: str) -> bool: + """判断指定测试类型是否有可保存的历史结果。""" + snapshots = self._chart_snapshots.get(test_type) or {} + return bool(snapshots) or ( + hasattr(self, "results") and self.results.has(test_type) + ) + + def _sync_save_button_state(self): + """根据当前测试类型是否有可保存结果,同步保存按钮状态。""" + if not hasattr(self, "save_btn"): + return + if getattr(self, "testing", False): + self.save_btn.config(state=tk.DISABLED) + return + test_type = self.test_type_var.get() if hasattr(self, "test_type_var") else None + if not test_type: + return + state = tk.NORMAL if self._has_saveable_results(test_type) else tk.DISABLED + self.save_btn.config(state=state) + def _restore_charts_for_type(self, test_type: str): """ 切换测试类型后恢复图表显示: - - 该类型有历史结果 → 切换活跃结果 + 重绘所有已缓存图表 + - 该类型有历史结果 → 切换活跃结果 + 重绘所有已缓存图表 + 启用保存按钮 - 该类型无历史结果 → 清空图表 + 禁用保存按钮 """ self.results.set_active(test_type) - snapshots = self._chart_snapshots.get(test_type) - if not snapshots: + if not self._has_saveable_results(test_type): self.clear_chart() - if hasattr(self, "save_btn"): - self.save_btn.config(state=tk.DISABLED) + self._sync_save_button_state() return + snapshots = self._chart_snapshots.get(test_type) or {} for chart_name, args in snapshots.items(): plot_fn = getattr(self, f"plot_{chart_name}", None) if plot_fn: @@ -483,6 +525,7 @@ class PQAutomationApp( plot_fn(*args) except Exception: pass + self._sync_save_button_state() def _check_start_preconditions(self): """检查开始测试前置条件:设备连接 & 未在测试中。""" diff --git a/settings/pq_config.json b/settings/pq_config.json index 77dfefe..8407680 100644 --- a/settings/pq_config.json +++ b/settings/pq_config.json @@ -1,5 +1,5 @@ { - "current_test_type": "screen_module", + "current_test_type": "sdr_movie", "test_types": { "screen_module": { "name": "屏模组性能测试",