From f6c1ae701e0f1b4e63bb8ae6d970b4336f571d86 Mon Sep 17 00:00:00 2001 From: Ari Sulistiono Date: Sat, 17 Oct 2026 09:40:51 +0700 Subject: [PATCH 1/3] ux(studio): consolidate timing status into footer and bound phasor density --- apps/arstack_studio/qml/Main.qml | 9 ++++--- apps/arstack_studio/qml/ModernRibbon.qml | 2 +- apps/arstack_studio/qml/StudioTimingTray.qml | 27 +++---------------- .../tests/check_operator_workspace.py | 9 +++++++ 4 files changed, 20 insertions(+), 27 deletions(-) diff --git a/apps/arstack_studio/qml/Main.qml b/apps/arstack_studio/qml/Main.qml index ec67055e2..e1ace674b 100644 --- a/apps/arstack_studio/qml/Main.qml +++ b/apps/arstack_studio/qml/Main.qml @@ -1039,8 +1039,8 @@ ApplicationWindow { StudioTimingTray { objectName: "studioTimingTray" Layout.fillWidth: true - Layout.preferredHeight: 84 - Layout.minimumHeight: 84 + Layout.preferredHeight: 57 + Layout.minimumHeight: 57 theme: studioTheme controller: root device: device @@ -1107,7 +1107,9 @@ ApplicationWindow { SplitView.fillWidth: true SplitView.fillHeight: true SplitView.minimumHeight: 170 - SplitView.preferredHeight: 238 + SplitView.preferredHeight: 225 + SplitView.maximumHeight: 265 + SplitView.fillHeight: false theme: studioTheme titleText: "Phasor" statusText: "" @@ -1147,6 +1149,7 @@ ApplicationWindow { SplitView.fillHeight: true SplitView.minimumHeight: 170 SplitView.preferredHeight: 328 + SplitView.fillHeight: true theme: studioTheme titleText: "Waveform" statusText: root.signalFrequency.toFixed(3) + " Hz" diff --git a/apps/arstack_studio/qml/ModernRibbon.qml b/apps/arstack_studio/qml/ModernRibbon.qml index 0c8034d14..d6dc4baea 100644 --- a/apps/arstack_studio/qml/ModernRibbon.qml +++ b/apps/arstack_studio/qml/ModernRibbon.qml @@ -94,8 +94,8 @@ Rectangle { toolTipText: "Start" onClicked: { if (!bar.device.deviceVerified) { + // The footer already identifies preview-only operation. bar.controller.offlinePreviewRunning = true - bar.controller.showMessage("Offline waveform preview · no network SV output.", false) } else bar.workflow.requestStart() } } diff --git a/apps/arstack_studio/qml/StudioTimingTray.qml b/apps/arstack_studio/qml/StudioTimingTray.qml index 08708d47d..09ff2c46f 100644 --- a/apps/arstack_studio/qml/StudioTimingTray.qml +++ b/apps/arstack_studio/qml/StudioTimingTray.qml @@ -61,30 +61,11 @@ Rectangle { ColumnLayout { anchors.fill: parent - anchors.margins: tray.compact ? 9 : 11 - spacing: tray.compact ? 5 : 7 - - RowLayout { - Layout.fillWidth: true - spacing: 8 - Rectangle { width: 3; height: 14; radius: 2; color: tray.theme.accent } - Label { - text: "TIME SYNC / SV SIMULATION" - color: tray.theme.textSoft - font.family: tray.uiFont - font.pixelSize: 10 - font.weight: Font.DemiBold - font.letterSpacing: 0.45 - } - Item { Layout.fillWidth: true } - StateBadge { - theme: tray.theme - monoFont: tray.monoFont - state: tray.stateText - stateColor: tray.stateColor - } - } + anchors.margins: tray.compact ? 7 : 9 + spacing: 0 + // The only global PTP/device status lives in the footer. + // This is an action strip, not a second diagnostic/status card. RowLayout { Layout.fillWidth: true spacing: tray.compact ? 7 : 10 diff --git a/apps/arstack_studio/tests/check_operator_workspace.py b/apps/arstack_studio/tests/check_operator_workspace.py index e04a09245..8e5073185 100644 --- a/apps/arstack_studio/tests/check_operator_workspace.py +++ b/apps/arstack_studio/tests/check_operator_workspace.py @@ -104,6 +104,15 @@ def main() -> None: assert "width: 212" in menu and "commandRows * 29" in menu assert "text: \"Generated setpoint · not independent on-wire proof\"" not in preview assert "No ESP32 board detected · Preview mode only" in main_qml + require("Layout.preferredHeight: 57" in main_qml + and "SplitView.maximumHeight: 265" in main_qml + and "SplitView.fillHeight: false" in main_qml, + "compact timing strip and bounded phasor panel must avoid dead space") + require("TIME SYNC / SV SIMULATION" not in tray + and "StateBadge {" not in tray, + "device/PTP status must not be duplicated in the control tray") + require("Offline waveform preview · no network SV output." not in ribbon, + "offline Start should not duplicate preview status with a toast") assert "Layout.preferredHeight: 78" in main_qml device_src = (STUDIO / "src/DeviceController.cpp").read_text(encoding="utf-8") session_src = (STUDIO / "src/SmartSessionController.cpp").read_text(encoding="utf-8") From 3ceb9b30199c1d1c6b5034159efba2a2559eeb6a Mon Sep 17 00:00:00 2001 From: Ari Sulistiono Date: Sat, 17 Oct 2026 09:44:11 +0700 Subject: [PATCH 2/3] fix(studio): remove duplicate phasor SplitView fillHeight binding --- apps/arstack_studio/qml/Main.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/arstack_studio/qml/Main.qml b/apps/arstack_studio/qml/Main.qml index e1ace674b..5f799bc7f 100644 --- a/apps/arstack_studio/qml/Main.qml +++ b/apps/arstack_studio/qml/Main.qml @@ -1105,7 +1105,6 @@ ApplicationWindow { DockFrame { visible: root.phasorDockVisible && !root.phasorDetached SplitView.fillWidth: true - SplitView.fillHeight: true SplitView.minimumHeight: 170 SplitView.preferredHeight: 225 SplitView.maximumHeight: 265 From 6fdd5488db7909a2ea23f98e928fb761d5926a9b Mon Sep 17 00:00:00 2001 From: Ari Sulistiono Date: Sat, 17 Oct 2026 09:46:47 +0700 Subject: [PATCH 3/3] fix(studio): deduplicate waveform SplitView sizing property --- apps/arstack_studio/qml/Main.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/arstack_studio/qml/Main.qml b/apps/arstack_studio/qml/Main.qml index 5f799bc7f..b419ddd7c 100644 --- a/apps/arstack_studio/qml/Main.qml +++ b/apps/arstack_studio/qml/Main.qml @@ -1145,7 +1145,6 @@ ApplicationWindow { DockFrame { visible: root.waveformDockVisible && !root.waveformDetached SplitView.fillWidth: true - SplitView.fillHeight: true SplitView.minimumHeight: 170 SplitView.preferredHeight: 328 SplitView.fillHeight: true