From 3d8b448f2b95f06deaa4fe1c6b59a0de5e484d7c Mon Sep 17 00:00:00 2001 From: Ari Sulistiono Date: Fri, 16 Oct 2026 17:04:22 +0700 Subject: [PATCH 1/3] fix(studio): unified dark expert controls and phasor-branded Qt/Inno icon --- apps/arstack_studio/CMakeLists.txt | 31 +++++++------ apps/arstack_studio/qml/DeviceExpertPanel.qml | 4 +- apps/arstack_studio/qml/ProfileInspector.qml | 8 +++- apps/arstack_studio/qml/PtpExpertPanel.qml | 8 ++-- .../arstack_studio/qml/StudioDarkCheckBox.qml | 41 ++++++++++++++++++ .../arstack_studio/qml/StudioDarkComboBox.qml | 4 +- .../qml/WaveformExpertPanel.qml | 2 +- apps/arstack_studio/src/main.cpp | 5 +++ assets/studio_icon/ARStackStudio.ico | Bin 0 -> 51880 bytes 9 files changed, 81 insertions(+), 22 deletions(-) create mode 100644 apps/arstack_studio/qml/StudioDarkCheckBox.qml create mode 100644 assets/studio_icon/ARStackStudio.ico diff --git a/apps/arstack_studio/CMakeLists.txt b/apps/arstack_studio/CMakeLists.txt index 0d660fb43..62fc6b5c3 100644 --- a/apps/arstack_studio/CMakeLists.txt +++ b/apps/arstack_studio/CMakeLists.txt @@ -98,6 +98,7 @@ qt_add_qml_module(arstack_studio qml/ConfigurationHub.qml qml/PtpExpertPanel.qml qml/StudioDarkComboBox.qml + qml/StudioDarkCheckBox.qml qml/DeviceExpertPanel.qml qml/FirmwarePanel.qml qml/WaveformExpertPanel.qml @@ -171,23 +172,25 @@ target_compile_definitions(arstack_session_harness PRIVATE ARSTACK_STUDIO_VERSION="${PROJECT_VERSION}" ) +# Use the existing Studio-specific artwork for every branding surface. +# This is intentionally separate from root assets/ used by Workbench. +set(ARSTACK_STUDIO_BRAND_DIR "${CMAKE_CURRENT_LIST_DIR}/../../assets/studio_icon") +qt_add_resources(arstack_studio "studio_branding" + PREFIX "/studio" + BASE "${ARSTACK_STUDIO_BRAND_DIR}" + FILES + "${ARSTACK_STUDIO_BRAND_DIR}/android-chrome-192x192.png" + "${ARSTACK_STUDIO_BRAND_DIR}/android-chrome-512x512.png" +) + if(WIN32) - # One deterministic icon shared by executable, installer and shortcuts. - # Python is already available on supported Windows CI hosts. The icon is - # generated at configure time so RC.exe sees its file before compilation. - find_package(Python3 COMPONENTS Interpreter REQUIRED) + # The exact same embedded icon is copied to stage/ for Inno Setup. + # No Python icon generation or alternative branding paths. set(ARSTACK_STUDIO_ICON "${CMAKE_CURRENT_BINARY_DIR}/ARStackStudio.ico") - execute_process( - COMMAND "${Python3_EXECUTABLE}" - "${CMAKE_CURRENT_LIST_DIR}/assets/make_studio_icon.py" - "${ARSTACK_STUDIO_ICON}" - RESULT_VARIABLE icon_result - ) - if(NOT icon_result EQUAL 0) - message(FATAL_ERROR "Could not generate native ARStack Studio icon") - endif() + configure_file("${ARSTACK_STUDIO_BRAND_DIR}/ARStackStudio.ico" + "${ARSTACK_STUDIO_ICON}" COPYONLY) file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/ARStackStudio.rc" - "IDI_ARSTACK ICON \"${ARSTACK_STUDIO_ICON}\"\n") + "IDI_ARSTACK ICON \\"${ARSTACK_STUDIO_ICON}\\"\\n") target_sources(arstack_studio PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/ARStackStudio.rc") set_target_properties(arstack_studio PROPERTIES WIN32_EXECUTABLE TRUE) diff --git a/apps/arstack_studio/qml/DeviceExpertPanel.qml b/apps/arstack_studio/qml/DeviceExpertPanel.qml index 0470ddf30..84631a638 100644 --- a/apps/arstack_studio/qml/DeviceExpertPanel.qml +++ b/apps/arstack_studio/qml/DeviceExpertPanel.qml @@ -53,7 +53,9 @@ SurfacePanel { RowLayout { Layout.fillWidth: true - ComboBox { + StudioDarkComboBox { + theme: panel.theme + uiFont: panel.uiFont id: recoveryPort Layout.preferredWidth: 170 model: panel.device.ports diff --git a/apps/arstack_studio/qml/ProfileInspector.qml b/apps/arstack_studio/qml/ProfileInspector.qml index cff19bbce..61889cd37 100644 --- a/apps/arstack_studio/qml/ProfileInspector.qml +++ b/apps/arstack_studio/qml/ProfileInspector.qml @@ -117,7 +117,9 @@ SurfacePanel { font.letterSpacing: 1.0 } - ComboBox { + StudioDarkComboBox { + theme: panel.theme + uiFont: panel.uiFont Layout.fillWidth: true model: panel.profiles textRole: "control" @@ -308,7 +310,9 @@ SurfacePanel { wrapMode: Text.WordWrap } - ComboBox { + StudioDarkComboBox { + theme: panel.theme + uiFont: panel.uiFont id: profileFamilySelector Layout.fillWidth: true enabled: panel.session && panel.session.engineeringEditable diff --git a/apps/arstack_studio/qml/PtpExpertPanel.qml b/apps/arstack_studio/qml/PtpExpertPanel.qml index 93870c7db..d473953d4 100644 --- a/apps/arstack_studio/qml/PtpExpertPanel.qml +++ b/apps/arstack_studio/qml/PtpExpertPanel.qml @@ -279,7 +279,9 @@ SurfacePanel { } } Item { Layout.fillWidth: true } - CheckBox { + StudioDarkCheckBox { + theme: panel.theme + uiFont: panel.uiFont text: "Advanced settings" checked: panel.advancedVisible onToggled: panel.advancedVisible = checked @@ -376,11 +378,11 @@ SurfacePanel { NumericField { id: announceField; theme: panel.theme; monoFont: panel.uiFont; text: "1000"; validator: IntValidator { bottom: 100; top: 10000 } } Label { text: "Sync interval (ms)"; color: panel.theme.muted; font.family: panel.uiFont; font.pixelSize: 9 } NumericField { id: syncField; theme: panel.theme; monoFont: panel.uiFont; text: "1000"; validator: IntValidator { bottom: 20; top: 5000 } } - CheckBox { id: vlanCheck; text: "VLAN"; font.family: panel.uiFont; font.pixelSize: 10; palette.windowText: panel.theme.text } + StudioDarkCheckBox { id: vlanCheck; theme: panel.theme; uiFont: panel.uiFont; text: "VLAN" } NumericField { id: vlanField; enabled: vlanCheck.checked; theme: panel.theme; monoFont: panel.uiFont; text: "100"; validator: IntValidator { bottom: 1; top: 4094 } } Label { text: "VLAN PCP"; color: panel.theme.muted; font.family: panel.uiFont; font.pixelSize: 9 } NumericField { id: pcpField; enabled: vlanCheck.checked; theme: panel.theme; monoFont: panel.uiFont; text: "4"; validator: IntValidator { bottom: 0; top: 7 } } - CheckBox { id: pdelayCheck; text: "Peer-delay response"; checked: true; font.family: panel.uiFont; font.pixelSize: 10; palette.windowText: panel.theme.text } + StudioDarkCheckBox { id: pdelayCheck; theme: panel.theme; uiFont: panel.uiFont; text: "Peer-delay response"; checked: true } CalmButton { theme: panel.theme uiFont: panel.uiFont diff --git a/apps/arstack_studio/qml/StudioDarkCheckBox.qml b/apps/arstack_studio/qml/StudioDarkCheckBox.qml new file mode 100644 index 000000000..eedfce586 --- /dev/null +++ b/apps/arstack_studio/qml/StudioDarkCheckBox.qml @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// One dark, legible checkbox shared across all Studio engineering panels. +import QtQuick +import QtQuick.Controls + +CheckBox { + id: control + property var theme + property string uiFont: "Inter" + implicitHeight: 30 + spacing: 9 + font.family: uiFont + font.pixelSize: 11 + indicator: Rectangle { + implicitWidth: 18 + implicitHeight: 18 + x: control.leftPadding + y: (control.height - height) / 2 + radius: 5 + color: control.checked ? control.theme.accent : control.theme.surface2 + border.width: 1 + border.color: control.checked ? control.theme.accent + : control.activeFocus ? control.theme.textSoft : control.theme.line + Text { + anchors.centerIn: parent + visible: control.checked + text: "\u2713" + color: control.theme.bg + font.pixelSize: 13 + font.weight: Font.Bold + } + } + contentItem: Text { + leftPadding: control.indicator.width + control.spacing + text: control.text + font: control.font + color: control.enabled ? control.theme.textSoft : control.theme.muted + verticalAlignment: Text.AlignVCenter + elide: Text.ElideRight + } +} diff --git a/apps/arstack_studio/qml/StudioDarkComboBox.qml b/apps/arstack_studio/qml/StudioDarkComboBox.qml index 4becf2c49..60f7afb00 100644 --- a/apps/arstack_studio/qml/StudioDarkComboBox.qml +++ b/apps/arstack_studio/qml/StudioDarkComboBox.qml @@ -47,11 +47,13 @@ ComboBox { } delegate: ItemDelegate { + id: choice + required property int index width: combo.width - 8 implicitHeight: 36 highlighted: combo.highlightedIndex === index contentItem: Text { - text: modelData + text: combo.textAt(choice.index) color: combo.theme.text font: combo.font verticalAlignment: Text.AlignVCenter diff --git a/apps/arstack_studio/qml/WaveformExpertPanel.qml b/apps/arstack_studio/qml/WaveformExpertPanel.qml index fdc888d96..cce81ce14 100644 --- a/apps/arstack_studio/qml/WaveformExpertPanel.qml +++ b/apps/arstack_studio/qml/WaveformExpertPanel.qml @@ -35,7 +35,7 @@ SurfacePanel { RowLayout { anchors.fill: parent anchors.margins: 12 - CheckBox { id: enabledCheck; checked: panel.controller.ctSaturationEnabled; text: "Enable CT saturation stress"; font.family: panel.uiFont; font.pixelSize: 10 } + StudioDarkCheckBox { id: enabledCheck; theme: panel.theme; uiFont: panel.uiFont; checked: panel.controller.ctSaturationEnabled; text: "Enable CT saturation stress" } Item { Layout.fillWidth: true } Label { text: panel.controller.ctSaturationEnabled ? "ACTIVE" : "CLEAN SINE"; color: panel.controller.ctSaturationEnabled ? panel.theme.amber : panel.theme.muted; font.family: panel.uiFont; font.pixelSize: 8; font.weight: Font.Bold } } diff --git a/apps/arstack_studio/src/main.cpp b/apps/arstack_studio/src/main.cpp index f208cd705..b74c177f0 100644 --- a/apps/arstack_studio/src/main.cpp +++ b/apps/arstack_studio/src/main.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -438,6 +439,10 @@ int main(int argc, char* argv[]) { QGuiApplication app(argc, argv); app.setQuitOnLastWindowClosed(true); + QIcon studioIcon; + studioIcon.addFile(QStringLiteral(":/studio/android-chrome-192x192.png")); + studioIcon.addFile(QStringLiteral(":/studio/android-chrome-512x512.png")); + app.setWindowIcon(studioIcon); QCoreApplication::setOrganizationName(QStringLiteral("ARStack61850")); #ifdef ARSTACK_STUDIO_ENGINEERING_PREVIEW QCoreApplication::setApplicationName(QStringLiteral("ARStack Studio Preview")); diff --git a/assets/studio_icon/ARStackStudio.ico b/assets/studio_icon/ARStackStudio.ico new file mode 100644 index 0000000000000000000000000000000000000000..b8289491cf945d0b873291d7eaaabeb13a3a3c6a GIT binary patch literal 51880 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 literal 0 HcmV?d00001 From 3fe3128be0808edd176bba29c41964d97e9c7daa Mon Sep 17 00:00:00 2001 From: Ari Sulistiono Date: Fri, 16 Oct 2026 17:05:10 +0700 Subject: [PATCH 2/3] fix(windows): quote native icon RC resource path without double escaping --- apps/arstack_studio/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/arstack_studio/CMakeLists.txt b/apps/arstack_studio/CMakeLists.txt index 62fc6b5c3..4a9fa7112 100644 --- a/apps/arstack_studio/CMakeLists.txt +++ b/apps/arstack_studio/CMakeLists.txt @@ -190,7 +190,7 @@ if(WIN32) configure_file("${ARSTACK_STUDIO_BRAND_DIR}/ARStackStudio.ico" "${ARSTACK_STUDIO_ICON}" COPYONLY) file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/ARStackStudio.rc" - "IDI_ARSTACK ICON \\"${ARSTACK_STUDIO_ICON}\\"\\n") + "IDI_ARSTACK ICON \"${ARSTACK_STUDIO_ICON}\"\n") target_sources(arstack_studio PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/ARStackStudio.rc") set_target_properties(arstack_studio PROPERTIES WIN32_EXECUTABLE TRUE) From 4280d028df1ab6260f9dd378d218c51dd72e0a8a Mon Sep 17 00:00:00 2001 From: Ari Sulistiono Date: Fri, 16 Oct 2026 17:06:56 +0700 Subject: [PATCH 3/3] feat(studio): optimistic-proof PTP on/off switch bound to verified board state --- apps/arstack_studio/qml/PtpExpertPanel.qml | 47 ++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/apps/arstack_studio/qml/PtpExpertPanel.qml b/apps/arstack_studio/qml/PtpExpertPanel.qml index d473953d4..7cb838094 100644 --- a/apps/arstack_studio/qml/PtpExpertPanel.qml +++ b/apps/arstack_studio/qml/PtpExpertPanel.qml @@ -109,6 +109,53 @@ SurfacePanel { } } Item { Layout.fillWidth: true } + Switch { + id: ptpPower + text: "PTP" + checked: Boolean(panel.device.ptpRunning) + enabled: panel.session && panel.device.ptpAvailable + && !panel.startPending && !panel.session.updatingFirmware + font.family: panel.uiFont + font.pixelSize: 11 + ToolTip.visible: hovered + ToolTip.text: "Start the selected lab PTP role, or stop PTP. State follows verified board telemetry." + onClicked: { + // A Switch flips locally before asynchronous firmware ACK. + // Restore its binding to the sole device-owned state first; + // rejected START/STOP must never advertise the wrong status. + const wantsRunning = checked + checked = Qt.binding(function() { return Boolean(panel.device.ptpRunning) }) + if (wantsRunning) panel.startSelectedMode() + else if (panel.session && !panel.session.requestStopPtp() && panel.controller) + panel.controller.showMessage("PTP stop was not accepted. Copy diagnostics.", true) + } + indicator: Rectangle { + implicitWidth: 46 + implicitHeight: 24 + x: ptpPower.leftPadding + y: (ptpPower.height - height) / 2 + radius: 12 + color: ptpPower.checked ? "#195b44" : panel.theme.surface2 + border.width: 1 + border.color: ptpPower.checked ? panel.theme.green : panel.theme.line + Rectangle { + width: 16 + height: 16 + y: 4 + x: ptpPower.checked ? parent.width - width - 4 : 4 + radius: 8 + color: ptpPower.checked ? panel.theme.green : panel.theme.textSoft + Behavior on x { NumberAnimation { duration: 120 } } + } + } + contentItem: Text { + text: ptpPower.text + color: ptpPower.enabled ? panel.theme.text : panel.theme.muted + font: ptpPower.font + leftPadding: ptpPower.indicator.width + ptpPower.spacing + verticalAlignment: Text.AlignVCenter + } + } StateBadge { theme: panel.theme monoFont: panel.uiFont