Files
pyGUI/src/pygui/ISC/Tabs/GraphTab.qml
T

220 lines
7.8 KiB
QML

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import ISC
import ISC.Wafer
// ===== Graph Tab =====
// Displays sensor temperature line charts using GraphQuickItem.
// Gets data from deviceController.getChartData() (parsed CSV, batch read)
// or from streamController.trendData (live streaming trend).
Item {
id: root
anchors.fill: parent
property var _chartData: null // cached result from getChartData()
ColumnLayout {
anchors.fill: parent
anchors.margins: Theme.panelPadding
spacing: Theme.rightPaneGap
// ── Toolbar ───────────────────────────────────────────────────────────
RowLayout {
Layout.fillWidth: true
spacing: 10
Label {
text: "Line Chart"
color: Theme.headingColor
font.pixelSize: 13
font.bold: true
Layout.alignment: Qt.AlignVCenter
}
Item { Layout.fillWidth: true }
// Refresh button — pulls data from deviceController
Button {
id: refreshBtn
text: "REFRESH"
font.pixelSize: 10
font.weight: Font.Medium
implicitHeight: 26
implicitWidth: 72
hoverEnabled: true
background: Rectangle {
color: parent.hovered ? Theme.buttonNeutralHover : Theme.buttonNeutralBackground
border.color: Theme.cardBorder
border.width: 1
radius: Theme.radiusSm
}
contentItem: Text {
text: parent.text
color: Theme.headingColor
font: parent.font
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
onClicked: reloadData()
}
}
// ── Mode selector (Trend / Full chart) ─────────────────────────────
RowLayout {
Layout.fillWidth: true
spacing: 8
Label {
text: "Source:"
color: Theme.bodyColor
font.pixelSize: 10
Layout.alignment: Qt.AlignVCenter
}
ComboBox {
id: sourceSelector
model: ["Parsed Data", "Live Trend"]
currentIndex: 0
implicitHeight: 26
font.pixelSize: 11
background: Rectangle {
color: Theme.fieldBackground
border.color: Theme.fieldBorder
border.width: 1
radius: Theme.radiusSm
}
contentItem: Text {
text: sourceSelector.displayText
color: Theme.fieldText
font: sourceSelector.font
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
leftPadding: 8
}
onCurrentIndexChanged: reloadData()
}
Item { Layout.fillWidth: true }
Label {
id: statusLabel
text: "Ready"
color: Theme.bodyColor
font.pixelSize: 10
font.italic: true
Layout.alignment: Qt.AlignVCenter
}
}
// ── Chart Area ─────────────────────────────────────────────────────────
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
color: Theme.cardBackground
border.color: Theme.cardBorder
border.width: 1
radius: Theme.radiusMd
clip: true
GraphQuickItem {
id: graph
anchors.fill: parent
anchors.margins: 2
backgroundColor: Theme.cardBackground
gridColor: Theme.softBorder
axisColor: Theme.bodyColor
textColor: Theme.headingColor
seriesColors: [Theme.sensorLow, Theme.sensorHigh, Theme.sensorInRange,
"#FFA726", "#AB47BC", "#00BCD4"]
showLegend: true
}
}
}
// ── Data Loading ────────────────────────────────────────────────────────────
function reloadData() {
if (sourceSelector.currentIndex === 0) {
// Parsed data from DeviceController
loadParsedData()
} else {
// Live trend from SessionController
loadLiveTrend()
}
}
function loadParsedData() {
statusLabel.text = "Loading..."
var result = deviceController.getChartData()
if (!result || !result.success) {
graph.seriesData = []
graph.sensorNames = []
graph.title = "Sensor Temperature Over Time"
statusLabel.text = "No data — read a wafer first"
return
}
graph.seriesData = result.series || []
graph.sensorNames = result.sensor_names || []
graph.title = "Sensor Temperature Over Time"
statusLabel.text = (result.series ? result.series.length : 0) + " sensors loaded"
}
function loadLiveTrend() {
// Live trend: connects to streamController.trendData
// The trend data comes as a JSON array of per-frame averages
statusLabel.text = "Connecting to live trend..."
// We need at least one data point
if (streamController.stats && streamController.stats.avg !== undefined) {
// Build a single-series graph from the trend buffer
// For now show a placeholder — the trendData signal handles updates
graph.title = "Live Average Temperature"
graph.yLabel = "Avg Temperature (°C)"
graph.xLabel = "Time (s)"
statusLabel.text = "Live trend — waiting for data..."
} else {
statusLabel.text = "No live data — start a stream on the Wafer Map tab"
}
}
// ── Connections ─────────────────────────────────────────────────────────────
Connections {
target: deviceController
function onParsedDataReady(result) {
if (sourceSelector.currentIndex === 0) {
root.reloadData()
}
}
}
Connections {
target: streamController
function onTrendData(avgsJson) {
if (sourceSelector.currentIndex === 1) {
try {
var avgs = JSON.parse(avgsJson)
if (avgs && avgs.length > 0) {
graph.seriesData = [avgs]
graph.sensorNames = ["Average"]
graph.title = "Live Average Temperature"
graph.yLabel = "Avg Temperature (°C)"
graph.xLabel = "Frame"
statusLabel.text = "Live: " + avgs.length + " data points"
}
} catch (e) {
// ignore parse errors
}
}
}
}
// On startup, try to load parsed data if available
Component.onCompleted: {
if (deviceController.dataRowCount > 0) {
reloadData()
}
}
}