From 27292c3bdb7878b73c981f6382f3899cd2837bc5 Mon Sep 17 00:00:00 2001 From: jack Date: Tue, 30 Jun 2026 13:24:00 -0700 Subject: [PATCH] chore: cleanup WaferMapTab stale comments + minor component fixes --- src/pygui/ISC/Tabs/WaferMapTab.qml | 20 +---- .../ISC/Tabs/components/ReadoutPanel.qml | 2 +- src/pygui/ISC/Tabs/components/SourcePanel.qml | 10 ++- .../ISC/Tabs/components/WaferMapView.qml | 1 + .../backend/controllers/device_controller.py | 84 +++++++++++-------- 5 files changed, 58 insertions(+), 59 deletions(-) diff --git a/src/pygui/ISC/Tabs/WaferMapTab.qml b/src/pygui/ISC/Tabs/WaferMapTab.qml index 8e049b3..b082bc8 100644 --- a/src/pygui/ISC/Tabs/WaferMapTab.qml +++ b/src/pygui/ISC/Tabs/WaferMapTab.qml @@ -246,29 +246,12 @@ Item { } } - // ── Body: 3 zones (TODO P2.1: becomes 2 zones) ────────────────────── - // ------------------------------------------------------------------- - // TODO P2.1: Delete the SourcePanel Rectangle (lines ~219-233) — - // the file list moved to the rail (P1.3 Map context panel). - // - // THINKING: - // SourcePanel shows a file list driven by file_browser — now that - // the Map tab's context panel in the rail (P1.3) provides the same - // file list with search/filter, SourcePanel in the wafer body is - // redundant. The wafer map gets more horizontal space. - // - // After deletion: RowLayout has 2 children instead of 3. - // Add Layout.fillWidth: true to the center ColumnLayout so it - // fills the vacated width. - // - // Cross-ref: P1.3 (Map context panel), P2.1 (this task) - // ------------------------------------------------------------------- + // ── Body: 2 columns (wafer + trend + transport | readout) ────────── RowLayout { Layout.fillWidth: true Layout.fillHeight: true spacing: 16 - // Source panel — moved to side rail (P2.1) ColumnLayout { Layout.fillWidth: true @@ -281,6 +264,7 @@ Item { Layout.fillHeight: true blend: readoutPanel.heatmapBlend showLabels: readoutPanel.showLabels + showThickness: readoutPanel.showThickness } Rectangle { id: trendPane diff --git a/src/pygui/ISC/Tabs/components/ReadoutPanel.qml b/src/pygui/ISC/Tabs/components/ReadoutPanel.qml index 1f313ea..962b671 100644 --- a/src/pygui/ISC/Tabs/components/ReadoutPanel.qml +++ b/src/pygui/ISC/Tabs/components/ReadoutPanel.qml @@ -11,6 +11,7 @@ ColumnLayout { property var s: streamController.stats property alias showLabels: labelsToggle.checked property alias heatmapBlend: heatmapSlider.value + property alias showThickness: thicknessToggle.checked component PanelCheckBox: CheckBox { id: toggle @@ -333,7 +334,6 @@ ColumnLayout { text: "Show Thickness" checked: false font.pixelSize: Theme.fontXs - onCheckedChanged: waferMapItem.showThickness = checked } PanelCheckBox { diff --git a/src/pygui/ISC/Tabs/components/SourcePanel.qml b/src/pygui/ISC/Tabs/components/SourcePanel.qml index c235376..8b4edc0 100644 --- a/src/pygui/ISC/Tabs/components/SourcePanel.qml +++ b/src/pygui/ISC/Tabs/components/SourcePanel.qml @@ -47,15 +47,16 @@ ColumnLayout { } ToolTip { + id: editTooltip visible: editBtn.hovered text: "Edit" delay: 400 font.pixelSize: Theme.fontXs font.family: Theme.uiFontFamily contentItem: Text { - text: parent.text + text: editTooltip.text color: Theme.headingColor - font: parent.font + font: editTooltip.font } background: Rectangle { color: Theme.cardBackground @@ -84,15 +85,16 @@ ColumnLayout { onClicked: file_browser.refreshFiles() ToolTip { + id: refreshTooltip visible: refreshBtn.hovered text: "Refresh" delay: 400 font.pixelSize: Theme.fontXs font.family: Theme.uiFontFamily contentItem: Text { - text: parent.text + text: refreshTooltip.text color: Theme.headingColor - font: parent.font + font: refreshTooltip.font } background: Rectangle { color: Theme.cardBackground diff --git a/src/pygui/ISC/Tabs/components/WaferMapView.qml b/src/pygui/ISC/Tabs/components/WaferMapView.qml index d3e3a8f..ba4bce9 100644 --- a/src/pygui/ISC/Tabs/components/WaferMapView.qml +++ b/src/pygui/ISC/Tabs/components/WaferMapView.qml @@ -7,6 +7,7 @@ Item { id: root property real blend: 0.0 property bool showLabels: true + property alias showThickness: map.showThickness WaferMapItem { id: map diff --git a/src/pygui/backend/controllers/device_controller.py b/src/pygui/backend/controllers/device_controller.py index dd4a6d4..171bb48 100644 --- a/src/pygui/backend/controllers/device_controller.py +++ b/src/pygui/backend/controllers/device_controller.py @@ -40,10 +40,10 @@ class DeviceController(QObject): # ---- public signals ---- portsUpdated = Signal(list) detectResult = Signal(object) # WaferInfo dict or None - readResult = Signal(object) # {"success": bool, "bytes": int} or {"error": str} - eraseResult = Signal(object) # {"success": bool} - debugResult = Signal(object) # {"success": bool, "sensor_bytes": int, "debug_bytes": int} - parsedDataReady = Signal(object) # {"success": bool, "rows": int, "cols": int, "data": ..., "csv_path": str} + readResult = Signal(dict) # {"success": bool, "bytes": int} or {"error": str} + eraseResult = Signal(dict) # {"success": bool} + debugResult = Signal(dict) # {"success": bool, "sensor_bytes": int, "debug_bytes": int} + parsedDataReady = Signal(dict) # {"success": bool, "rows": int, "cols": int, "data": ..., "csv_path": str} statusRestored = Signal() # Emitted when status is restored from previous session logMessage = Signal(str) activityLogUpdated = Signal(str) @@ -58,35 +58,21 @@ class DeviceController(QObject): self._data_dir = data_dir self._service = DeviceService(settings) - # Always start fresh — never restore connection status from a prior session + # Always start fresh — never restore connection status or logs from a prior session self._connection_status = "Disconnected" self._operation_in_progress = False - self._activity_log: list[str] = getattr(settings, 'activity_log', []) + self._activity_log: list[str] = [] self._raw_bytes: Optional[bytes] = None from pathlib import Path self._save_data_dir: str = getattr(settings, 'save_data_dir', "") or str(Path(self._data_dir) / "csv") - self._last_wafer_info: dict[str, Any] = getattr(settings, 'last_wafer_info', {}) - self._last_csv_path: str = getattr(settings, 'last_csv_path', "") - self._selected_port: str = getattr(settings, 'selected_port', "") - self._data_row_count: int = getattr(settings, 'data_row_count', 0) - self._data_col_count: int = getattr(settings, 'data_col_count', 0) + self._last_wafer_info: dict[str, Any] = {} + self._last_csv_path: str = "" + self._selected_port: str = "" + self._data_row_count: int = 0 + self._data_col_count: int = 0 self._data_model = TemperatureTableModel(self) self._graph_view = GraphView(self) - # If we have persisted activity log, emit it to QML - if self._activity_log: - self.activityLogUpdated.emit("\n".join(self._activity_log)) - - # Log status restoration and emit signal for UI updates - if self._connection_status != "Disconnected" or self._selected_port or self._last_wafer_info: - self._append_log("Restored previous session status") - if self._selected_port: - self._append_log(f"Last selected port: {self._selected_port}") - if self._last_wafer_info: - info = self._last_wafer_info - self._append_log(f"Last wafer: {info.get('serialNumber', 'Unknown')} ({info.get('familyCode', 'Unknown')})") - self.statusRestored.emit() - # Reset connection status on fresh start self._connection_status = "Disconnected" @@ -162,10 +148,17 @@ class DeviceController(QObject): Returns [familyCode, serialNumber, sensorCount, mfgDateHex, runtime, cycleCount]. """ info = self._last_wafer_info + family_code = info.get("familyCode", "") + sensor_count = info.get("sensorCount", 0) + from pygui.serialcomm.data_parser import csv_column_count + mapped_count = csv_column_count(family_code) + if mapped_count > 0: + sensor_count = mapped_count + return [ - info.get("familyCode", ""), + family_code, info.get("serialNumber", ""), - info.get("sensorCount", 0), + sensor_count, info.get("mfgDateHex", ""), info.get("runtime", 0), info.get("cycleCount", 0), @@ -239,9 +232,13 @@ class DeviceController(QObject): self._data_col_count = 0 self._raw_bytes = None self._operation_in_progress = False + self._data_model.reset() + self._graph_view.resetChart() + self._activity_log.clear() self.detectResult.emit(None) + self.parsedDataReady.emit({"success": False}) self.portsUpdated.emit(self.availablePorts) - self._append_log("Session refreshed/cleared") + self.activityLogUpdated.emit("") self._save_status() @@ -280,6 +277,18 @@ class DeviceController(QObject): self._append_log("Already busy — ignoring detect request") return + # Clear previous session data & logs for a fresh session + self._selected_port = "" + self._last_wafer_info = {} + self._data_row_count = 0 + self._data_col_count = 0 + self._raw_bytes = None + self._data_model.reset() + self._graph_view.resetChart() + self._activity_log.clear() + self.detectResult.emit(None) + self.parsedDataReady.emit({"success": False}) + self._set_operation_progress(True) self._set_connection_status("Detecting...") self.portsUpdated.emit(self._service.enumerate_ports()) @@ -306,10 +315,6 @@ class DeviceController(QObject): if info is not None: self._selected_port = port or "" self._set_connection_status("Connected") - self._append_log( - f"Detected: {info.serial_number} (family={info.family_code}, " - f"port={port}, runtime={info.runtime}s, cycles={info.cycle_count})" - ) wafer_dict = self._wafer_info_to_dict(info) self._last_wafer_info = wafer_dict self.detectResult.emit(wafer_dict) @@ -558,10 +563,16 @@ class DeviceController(QObject): @staticmethod def _wafer_info_to_dict(info: WaferInfo) -> dict[str, Any]: """Convert WaferInfo dataclass to JSON-serialisable dict for QML.""" + from pygui.serialcomm.data_parser import csv_column_count + sensor_count = info.sensor_count + mapped_count = csv_column_count(info.family_code) + if mapped_count > 0: + sensor_count = mapped_count + return { "familyCode": info.family_code, "serialNumber": info.serial_number, - "sensorCount": info.sensor_count, + "sensorCount": sensor_count, "mfgDateHex": info.mfg_date_hex, "runtime": info.runtime, "cycleCount": info.cycle_count, @@ -572,8 +583,9 @@ class QmlActivityLogHandler(logging.Handler): super().__init__() self._controller = controller def emit(self, record: logging.LogRecord) -> None: - timestamp = datetime.now().strftime("%H:%M:%S") - level = record.levelname message = record.getMessage() - msg = f"[{timestamp}] {level}: {message}" + if "found wafer on" in message: + return + level = record.levelname + msg = f"{level}: {message}" self._controller._append_log(msg)