feat(tabs): update all tab views, dialogs, and session controller

This commit is contained in:
jack
2026-06-29 14:58:10 -07:00
parent db21f201f6
commit 5105ab1ab6
10 changed files with 507 additions and 307 deletions
+78 -72
View File
@@ -18,12 +18,13 @@ Item {
repeat: true
running: streamController.mode === "live" && streamController.state !== "idle"
onTriggered: root._liveSecs++
onRunningChanged: if (!running) root._liveSecs = 0
onRunningChanged: if (!running)
root._liveSecs = 0
}
function fmtTime(s) {
var m = Math.floor(s / 60)
var ss = s % 60
return (m < 10 ? "0" : "") + m + ":" + (ss < 10 ? "0" : "") + ss
var m = Math.floor(s / 60);
var ss = s % 60;
return (m < 10 ? "0" : "") + m + ":" + (ss < 10 ? "0" : "") + ss;
}
// Wire streamController.trendData (Signal(str) carrying JSON list of floats)
// into the trend chart's data property. The slot parseJsonToData() is defined
@@ -32,7 +33,7 @@ Item {
Connections {
target: streamController
function onTrendData(avgsJson) {
trendChart.setDataFromJson(avgsJson)
trendChart.setDataFromJson(avgsJson);
}
}
@@ -60,7 +61,8 @@ Item {
}
TabButton {
text: "Review"
implicitWidth: 64; implicitHeight: 28
implicitWidth: 64
implicitHeight: 28
background: Rectangle {
color: parent.checked ? Theme.tabActiveBackground : "transparent"
radius: Theme.radiusSm - 1
@@ -68,7 +70,7 @@ Item {
contentItem: Text {
text: parent.text
color: parent.checked ? Theme.headingColor : Theme.bodyColor
font.pixelSize: 11
font.pixelSize: Theme.fontSm
font.weight: parent.checked ? Font.Medium : Font.Normal
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
@@ -78,7 +80,8 @@ Item {
text: "Live"
enabled: deviceController.connectionStatus === "Connected"
opacity: enabled ? 1.0 : 0.4
implicitWidth: 58; implicitHeight: 28
implicitWidth: 58
implicitHeight: 28
background: Rectangle {
color: parent.checked ? Theme.tabActiveBackground : "transparent"
radius: Theme.radiusSm - 1
@@ -86,30 +89,29 @@ Item {
contentItem: Text {
text: parent.text
color: parent.checked ? Theme.headingColor : Theme.bodyColor
font.pixelSize: 11
font.pixelSize: Theme.fontSm
font.weight: parent.checked ? Font.Medium : Font.Normal
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
onCurrentIndexChanged:
if (currentIndex === 1){
// Guard: revert to Review if not connected
if (deviceController.connectionStatus !== "Connected") {
currentIndex = 0
return
}
// Entering Live mode
streamController.setMode("live")
var fc = ""
if (deviceController.lastWaferInfo && deviceController.lastWaferInfo.length > 0) {
fc = deviceController.lastWaferInfo[0]
}
streamController.startStream(deviceController.selectedPort, fc)
} else {
// Entering Review Mode (automatically calls stopStream in backend)
streamController.setMode("review")
onCurrentIndexChanged: if (currentIndex === 1) {
// Guard: revert to Review if not connected
if (deviceController.connectionStatus !== "Connected") {
currentIndex = 0;
return;
}
// Entering Live mode
streamController.setMode("live");
var fc = "";
if (deviceController.lastWaferInfo && deviceController.lastWaferInfo.length > 0) {
fc = deviceController.lastWaferInfo[0];
}
streamController.startStream(deviceController.selectedPort, fc);
} else {
// Entering Review Mode (automatically calls stopStream in backend)
streamController.setMode("review");
}
}
// Live source info: WiFi icon + port · serial
@@ -120,33 +122,44 @@ Item {
Label {
id: liveIndicator
text: "◉"
color: (deviceController.connectionStatus === "Connected" && streamController.state !== "idle")
? Theme.liveColor : Theme.bodyColor
font.pixelSize: 13
color: (deviceController.connectionStatus === "Connected" && streamController.state !== "idle") ? Theme.liveColor : Theme.bodyColor
font.pixelSize: Theme.fontSm
SequentialAnimation on opacity {
running: deviceController.connectionStatus === "Connected" && streamController.state !== "idle"
loops: Animation.Infinite
NumberAnimation { to: 0.2; duration: 600; easing.type: Easing.InOutQuad }
NumberAnimation { to: 1.0; duration: 600; easing.type: Easing.InOutQuad }
NumberAnimation {
to: 0.2
duration: 600
easing.type: Easing.InOutQuad
}
NumberAnimation {
to: 1.0
duration: 600
easing.type: Easing.InOutQuad
}
onRunningChanged: {
if (!running) liveIndicator.opacity = 1.0
if (!running)
liveIndicator.opacity = 1.0;
}
}
}
Label {
text: "Live stream"
color: Theme.bodyColor
font.pixelSize: 11
font.pixelSize: Theme.fontXs
}
}
Item { Layout.fillWidth: true }
Item {
Layout.fillWidth: true
}
// SET badge + avg temp
Rectangle {
visible: streamController.state === "set"
height: 22; radius: Theme.radiusSm
height: 22
radius: Theme.radiusSm
color: "transparent"
border.color: Theme.liveColor
border.width: 1
@@ -154,10 +167,9 @@ Item {
Label {
id: setLabel
anchors.centerIn: parent
text: "SET " + (streamController.stats.avg !== undefined
? streamController.stats.avg + " avg" : "")
text: "SET " + (streamController.stats.avg !== undefined ? streamController.stats.avg + " avg" : "")
color: Theme.liveColor
font.pixelSize: 10
font.pixelSize: Theme.fontXs
font.weight: Font.Medium
font.letterSpacing: 0.8
}
@@ -168,19 +180,27 @@ Item {
spacing: 5
visible: streamController.recording
Rectangle {
width: 7; height: 7; radius: 4
width: 7
height: 7
radius: 4
color: Theme.recordColor
SequentialAnimation on opacity {
running: streamController.recording
loops: Animation.Infinite
NumberAnimation { to: 0.2; duration: 600 }
NumberAnimation { to: 1.0; duration: 600 }
NumberAnimation {
to: 0.2
duration: 600
}
NumberAnimation {
to: 1.0
duration: 600
}
}
}
Label {
text: "REC"
color: Theme.recordColor
font.pixelSize: 10
font.pixelSize: Theme.fontXs
font.weight: Font.Medium
font.letterSpacing: 1.2
}
@@ -197,7 +217,7 @@ Item {
// Label {
// text: "LIVE " + root.fmtTime(root._liveSecs)
// color: Theme.liveColor
// font.pixelSize: 10
// font.pixelSize: Theme.fontXs
// font.weight: Font.Medium
// font.letterSpacing: 0.8
// }
@@ -208,11 +228,11 @@ Item {
// visible: streamController.mode === "review" || streamController.state === "idle"
// text: streamController.state.toUpperCas`e`()
// color: Theme.bodyColor
// font.pixelSize: 11
// font.pixelSize: Theme.fontXs
// font.weight: Font.Medium
// font.letterSpacing: 1.2
// }
Button{
Button {
text: "Export PNG"
onClicked: exportDialog.open()
}
@@ -248,21 +268,7 @@ Item {
Layout.fillHeight: true
spacing: 16
// Source panel — bordered card
Rectangle {
Layout.preferredWidth: 220
Layout.fillHeight: true
color: Theme.cardBackground
border.color: Theme.cardBorder
border.width: 1
radius: Theme.radiusMd
clip: true
SourcePanel {
anchors.fill: parent
anchors.margins: 10
}
}
// Source panel — moved to side rail (P2.1)
ColumnLayout {
Layout.fillWidth: true
@@ -280,7 +286,7 @@ Item {
id: trendPane
Layout.fillWidth: true
implicitHeight: 160
visible: trendChart.hasData
visible: trendChart.hasData && streamController.mode === "live"
color: Theme.cardBackground
border.color: Theme.cardBorder
border.width: 1
@@ -293,28 +299,28 @@ Item {
}
}
Item { Layout.fillWidth: true; implicitHeight: 16 }
TransportBar {
Item {
Layout.fillWidth: true
implicitHeight: 16
}
TransportBar {
Layout.fillWidth: true
visible: streamController.mode !== "live" || trendChart.hasData
height: visible ? implicitHeight : 0
}
}
// Readout panel — bordered card
// Readout panel — floating wrapper box
Rectangle {
Layout.preferredWidth: 220
Layout.fillHeight: true
color: Theme.cardBackground
border.color: Theme.cardBorder
border.width: 1
radius: Theme.radiusMd
color: "transparent"
border.color: "transparent"
border.width: 0
clip: true
ReadoutPanel {
id: readoutPanel
anchors.fill: parent
anchors.margins: 10
anchors.margins: 0
}
}
}