feat(tabs): update all tab views, dialogs, and session controller
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user