e306db6816
- SettingsTab: chamber ID, master CSV mapping (families A-Z), wafer behavior toggle, light/dark mode toggle, Edit CSV Metadata dialog - StatusTab: connection status card, wafer info, activity log (blank until Detect Wafer fires from the side rail) - DataTab: empty state, ready for parsed data - HomePage: side rail buttons dispatch device actions and jump to Status tab; selectedSideActionIndex defaults to -1 on startup - DeviceController registered as QML context property in main.py - LocalSettings: added status persistence fields - Theme: added subheadingColor and disabledText - Added serialcomm/ package and backend data/graph modules - gitignore: restore clean version
154 lines
4.8 KiB
QML
154 lines
4.8 KiB
QML
import QtQuick
|
||
import QtQuick.Controls
|
||
import QtQuick.Layouts
|
||
import ISC
|
||
|
||
// ===== Data Tab =====
|
||
// Displays parsed temperature data in a scrollable table.
|
||
// Column 0 = Row index, remaining columns = Sensor1, Sensor2, ...
|
||
Item {
|
||
id: root
|
||
anchors.fill: parent
|
||
|
||
readonly property int rowCount: deviceController.dataRowCount
|
||
|
||
// Re-layout columns whenever the model is reset
|
||
Connections {
|
||
target: deviceController
|
||
function onParsedDataReady(result) {
|
||
if (result && result.success) {
|
||
dataTable.forceLayout()
|
||
}
|
||
}
|
||
}
|
||
|
||
// ===== Empty State =====
|
||
Column {
|
||
anchors.centerIn: parent
|
||
spacing: 16
|
||
visible: root.rowCount === 0
|
||
|
||
Label {
|
||
text: "No Data"
|
||
font.pixelSize: 24
|
||
font.bold: true
|
||
color: Theme.headingColor
|
||
anchors.horizontalCenter: parent.horizontalCenter
|
||
}
|
||
|
||
Label {
|
||
text: "Read and parse wafer data to see temperature readings here."
|
||
font.pixelSize: 14
|
||
color: Theme.bodyColor
|
||
anchors.horizontalCenter: parent.horizontalCenter
|
||
wrapMode: Text.WordWrap
|
||
}
|
||
}
|
||
|
||
// ===== Data Table =====
|
||
ColumnLayout {
|
||
anchors.fill: parent
|
||
anchors.margins: Theme.panelPadding
|
||
spacing: Theme.rightPaneGap
|
||
visible: root.rowCount > 0
|
||
|
||
// --- Header row ---
|
||
RowLayout {
|
||
Layout.fillWidth: true
|
||
spacing: Theme.rightPaneGap
|
||
|
||
Label {
|
||
text: "Temperature Data"
|
||
font.pixelSize: 18
|
||
font.bold: true
|
||
color: Theme.headingColor
|
||
}
|
||
|
||
Item { Layout.fillWidth: true }
|
||
|
||
Label {
|
||
text: deviceController.dataRowCount + " rows × " +
|
||
deviceController.dataColCount + " sensors"
|
||
font.pixelSize: 13
|
||
color: Theme.bodyColor
|
||
}
|
||
}
|
||
|
||
// --- Table container ---
|
||
Rectangle {
|
||
Layout.fillWidth: true
|
||
Layout.fillHeight: true
|
||
color: Theme.panelBackground
|
||
border.color: Theme.cardBorder
|
||
border.width: Theme.borderThin
|
||
radius: Theme.radiusSm
|
||
clip: true
|
||
|
||
ColumnLayout {
|
||
anchors.fill: parent
|
||
anchors.margins: 1
|
||
spacing: 0
|
||
|
||
// Column header strip
|
||
HorizontalHeaderView {
|
||
id: headerView
|
||
Layout.fillWidth: true
|
||
syncView: dataTable
|
||
clip: true
|
||
|
||
delegate: Rectangle {
|
||
implicitHeight: 28
|
||
color: Theme.cardBackground
|
||
border.color: Theme.cardBorder
|
||
border.width: 1
|
||
|
||
Text {
|
||
anchors.centerIn: parent
|
||
// 'display' is the Qt.DisplayRole value from headerData()
|
||
text: display !== undefined ? display : ""
|
||
color: Theme.headingColor
|
||
font.pixelSize: 11
|
||
font.bold: true
|
||
elide: Text.ElideRight
|
||
}
|
||
}
|
||
}
|
||
|
||
// Data rows
|
||
TableView {
|
||
id: dataTable
|
||
Layout.fillWidth: true
|
||
Layout.fillHeight: true
|
||
model: deviceController.dataModel
|
||
clip: true
|
||
reuseItems: true
|
||
|
||
columnWidthProvider: function(col) {
|
||
if (col === 0) return 52 // row index column
|
||
const sensorCols = Math.max(1, dataTable.columns - 1)
|
||
const available = dataTable.width - 52
|
||
return Math.max(52, Math.min(90, available / sensorCols))
|
||
}
|
||
|
||
rowHeightProvider: function() { return 24 }
|
||
|
||
delegate: Rectangle {
|
||
color: row % 2 === 0 ? Theme.panelBackground : Theme.cardBackground
|
||
|
||
Text {
|
||
anchors.centerIn: parent
|
||
text: display !== undefined ? display : ""
|
||
color: Theme.bodyColor
|
||
font.pixelSize: 11
|
||
elide: Text.ElideRight
|
||
}
|
||
}
|
||
|
||
ScrollBar.horizontal: ScrollBar { policy: ScrollBar.AsNeeded }
|
||
ScrollBar.vertical: ScrollBar { policy: ScrollBar.AsNeeded }
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|