feat: Add Wafer Map tab and associated components
- Introduced a new Wafer Map tab in the HomePage.qml, which loads WaferMapTab.qml when selected. - Created WaferMapTab.qml to display wafer map with live data and controls. - Added ReadoutPanel.qml for displaying sensor statistics and thresholds. - Implemented SourcePanel.qml for file selection and filtering. - Developed TransportBar.qml for playback controls. - Added WaferMapView.qml to visualize wafer data with interactive features. - Created ReplaceSensorDialog.qml for sensor value overrides. - Updated Theme.qml for new color schemes and UI adjustments. - Modified qmldir files to include new components in the ISC.Tabs and ISC.Tabs.components modules.
This commit is contained in:
@@ -0,0 +1,240 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import ISC
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 0
|
||||
property var s: streamController.stats
|
||||
property alias showLabels: labelsToggle.checked
|
||||
property alias heatmapBlend: heatmapSlider.value
|
||||
|
||||
// ── READOUT ───────────────────────────────────────────────────────────
|
||||
Label {
|
||||
text: "READOUT"
|
||||
color: Theme.bodyColor
|
||||
font.pixelSize: 10
|
||||
font.letterSpacing: 1.8
|
||||
font.weight: Font.Medium
|
||||
bottomPadding: 4
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
columns: 2
|
||||
rowSpacing: 4
|
||||
columnSpacing: 4
|
||||
Layout.fillWidth: true
|
||||
|
||||
// MIN TEMP
|
||||
Rectangle {
|
||||
Layout.fillWidth: true; height: 52
|
||||
color: Theme.subtleSectionBackground; radius: Theme.radiusSm
|
||||
border.color: Theme.cardBorder; border.width: 1
|
||||
ColumnLayout {
|
||||
anchors { fill: parent; margins: 7 }
|
||||
spacing: 1
|
||||
Label { text: "MIN TEMP"; color: Theme.bodyColor; font.pixelSize: 9; font.letterSpacing: 1 }
|
||||
Label {
|
||||
text: s.min !== undefined ? s.min + " #" + s.minIndex : "—"
|
||||
color: Theme.sensorLow
|
||||
font.pixelSize: 15; font.weight: Font.Bold
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MAX TEMP
|
||||
Rectangle {
|
||||
Layout.fillWidth: true; height: 52
|
||||
color: Theme.subtleSectionBackground; radius: Theme.radiusSm
|
||||
border.color: Theme.cardBorder; border.width: 1
|
||||
ColumnLayout {
|
||||
anchors { fill: parent; margins: 7 }
|
||||
spacing: 1
|
||||
Label { text: "MAX TEMP"; color: Theme.bodyColor; font.pixelSize: 9; font.letterSpacing: 1 }
|
||||
Label {
|
||||
text: s.max !== undefined ? s.max + " #" + s.maxIndex : "—"
|
||||
color: Theme.sensorHigh
|
||||
font.pixelSize: 15; font.weight: Font.Bold
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DIFFERENTIAL
|
||||
Rectangle {
|
||||
Layout.fillWidth: true; height: 52
|
||||
color: Theme.subtleSectionBackground; radius: Theme.radiusSm
|
||||
border.color: Theme.cardBorder; border.width: 1
|
||||
ColumnLayout {
|
||||
anchors { fill: parent; margins: 7 }
|
||||
spacing: 1
|
||||
Label { text: "DIFFERENTIAL"; color: Theme.bodyColor; font.pixelSize: 9; font.letterSpacing: 1 }
|
||||
Label {
|
||||
text: s.diff !== undefined ? s.diff : "—"
|
||||
color: Theme.headingColor
|
||||
font.pixelSize: 15; font.weight: Font.Bold
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// AVERAGE
|
||||
Rectangle {
|
||||
Layout.fillWidth: true; height: 52
|
||||
color: Theme.subtleSectionBackground; radius: Theme.radiusSm
|
||||
border.color: Theme.cardBorder; border.width: 1
|
||||
ColumnLayout {
|
||||
anchors { fill: parent; margins: 7 }
|
||||
spacing: 1
|
||||
Label { text: "AVERAGE"; color: Theme.bodyColor; font.pixelSize: 9; font.letterSpacing: 1 }
|
||||
Label {
|
||||
text: s.avg !== undefined ? s.avg : "—"
|
||||
color: Theme.headingColor
|
||||
font.pixelSize: 15; font.weight: Font.Bold
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SIGMA — full-width
|
||||
Rectangle {
|
||||
Layout.fillWidth: true; height: 44
|
||||
color: Theme.subtleSectionBackground; radius: Theme.radiusSm
|
||||
border.color: Theme.cardBorder; border.width: 1
|
||||
RowLayout {
|
||||
anchors { fill: parent; leftMargin: 7; rightMargin: 7; topMargin: 4; bottomMargin: 4 }
|
||||
ColumnLayout {
|
||||
spacing: 1
|
||||
Label { text: "SIGMA (σ)"; color: Theme.bodyColor; font.pixelSize: 9; font.letterSpacing: 1 }
|
||||
Label { text: "3σ"; color: Theme.bodyColor; font.pixelSize: 9; font.letterSpacing: 1 }
|
||||
}
|
||||
Item { Layout.fillWidth: true }
|
||||
ColumnLayout {
|
||||
spacing: 1
|
||||
Label {
|
||||
text: s.sigma !== undefined ? s.sigma : "—"
|
||||
color: Theme.headingColor
|
||||
font.pixelSize: 15; font.weight: Font.Bold
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
Label {
|
||||
text: s.threeSigma !== undefined ? s.threeSigma : "—"
|
||||
color: Theme.bodyColor
|
||||
font.pixelSize: 12; font.weight: Font.Medium
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item { height: 8 }
|
||||
Rectangle { Layout.fillWidth: true; height: 1; color: Theme.cardBorder }
|
||||
Item { height: 8 }
|
||||
|
||||
// ── DISPLAY ───────────────────────────────────────────────────────────
|
||||
Label {
|
||||
text: "DISPLAY"
|
||||
color: Theme.bodyColor
|
||||
font.pixelSize: 10
|
||||
font.letterSpacing: 1.8
|
||||
font.weight: Font.Medium
|
||||
bottomPadding: 4
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
id: labelsToggle
|
||||
text: "Labels"
|
||||
checked: true
|
||||
font.pixelSize: 11
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: 6
|
||||
Label {
|
||||
text: "Heatmap"
|
||||
color: Theme.bodyColor
|
||||
font.pixelSize: 11
|
||||
Layout.preferredWidth: 52
|
||||
}
|
||||
Slider {
|
||||
id: heatmapSlider
|
||||
from: 0; to: 1; value: 0
|
||||
Layout.fillWidth: true
|
||||
ToolTip.visible: hovered
|
||||
ToolTip.text: Math.round(value * 100) + "%"
|
||||
}
|
||||
}
|
||||
|
||||
Item { height: 8 }
|
||||
Rectangle { Layout.fillWidth: true; height: 1; color: Theme.cardBorder }
|
||||
Item { height: 8 }
|
||||
|
||||
// ── THRESHOLDS ────────────────────────────────────────────────────────
|
||||
Label {
|
||||
text: "THRESHOLDS"
|
||||
color: Theme.bodyColor
|
||||
font.pixelSize: 10
|
||||
font.letterSpacing: 1.8
|
||||
font.weight: Font.Medium
|
||||
bottomPadding: 4
|
||||
}
|
||||
|
||||
Label { text: "Set Point (°C)"; color: Theme.bodyColor; font.pixelSize: 11 }
|
||||
TextField {
|
||||
id: spField
|
||||
Layout.fillWidth: true
|
||||
text: "149.0"
|
||||
font.pixelSize: 12
|
||||
inputMethodHints: Qt.ImhFormattedNumbersOnly
|
||||
color: Theme.fieldText
|
||||
placeholderTextColor: Theme.fieldPlaceholder
|
||||
selectedTextColor: Theme.fieldBackground
|
||||
selectionColor: Theme.fieldText
|
||||
background: Rectangle {
|
||||
radius: Theme.radiusXs
|
||||
color: Theme.fieldBackground
|
||||
border.width: spField.activeFocus ? Theme.borderStrong : Theme.borderThin
|
||||
border.color: spField.activeFocus ? Theme.fieldBorderFocus : Theme.fieldBorder
|
||||
}
|
||||
onEditingFinished: pushThresholds()
|
||||
}
|
||||
|
||||
Item { height: 4 }
|
||||
|
||||
Label { text: "Margin (±°C)"; color: Theme.bodyColor; font.pixelSize: 11 }
|
||||
TextField {
|
||||
id: mgField
|
||||
Layout.fillWidth: true
|
||||
text: "1.0"
|
||||
font.pixelSize: 12
|
||||
inputMethodHints: Qt.ImhFormattedNumbersOnly
|
||||
color: Theme.fieldText
|
||||
placeholderTextColor: Theme.fieldPlaceholder
|
||||
selectedTextColor: Theme.fieldBackground
|
||||
selectionColor: Theme.fieldText
|
||||
background: Rectangle {
|
||||
radius: Theme.radiusXs
|
||||
color: Theme.fieldBackground
|
||||
border.width: mgField.activeFocus ? Theme.borderStrong : Theme.borderThin
|
||||
border.color: mgField.activeFocus ? Theme.fieldBorderFocus : Theme.fieldBorder
|
||||
}
|
||||
onEditingFinished: pushThresholds()
|
||||
}
|
||||
|
||||
Item { height: 4 }
|
||||
|
||||
CheckBox {
|
||||
id: autoCheck
|
||||
text: "Auto range (mean ± 1σ)"
|
||||
checked: true
|
||||
font.pixelSize: 11
|
||||
onCheckedChanged: pushThresholds()
|
||||
}
|
||||
|
||||
Item { Layout.fillHeight: true }
|
||||
|
||||
function pushThresholds() {
|
||||
var sp = parseFloat(spField.text) || 149.0
|
||||
var mg = parseFloat(mgField.text) || 1.0
|
||||
streamController.setThresholds(sp, mg, autoCheck.checked)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user