feat(panels): redesign ReadoutPanel and SourcePanel to match mockup
ReadoutPanel: - Move section headers inside card containers - Redesign readout table with uppercase labels, code fonts, color mapping - Add full-width dividers, fix vertical spacing with fillHeight spacer - Unify typography with Theme tokens SourcePanel: - Bump font sizes to new standard (fontMd primary, fontSm secondary) - Replace unicode button text with edit.svg/refresh.svg IconImages - Add styled hover tooltips on edit and refresh buttons
This commit is contained in:
@@ -3,8 +3,11 @@ import QtQuick.Controls
|
|||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import ISC
|
import ISC
|
||||||
|
|
||||||
|
// ===== Readout Panel =====
|
||||||
|
// Right-rail panel with three bordered sections: READOUT, DISPLAY, THRESHOLDS.
|
||||||
|
// Cards match the left-rail SOURCE / CONNECTION FLOW style.
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
spacing: 0
|
spacing: 6
|
||||||
property var s: streamController.stats
|
property var s: streamController.stats
|
||||||
property alias showLabels: labelsToggle.checked
|
property alias showLabels: labelsToggle.checked
|
||||||
property alias heatmapBlend: heatmapSlider.value
|
property alias heatmapBlend: heatmapSlider.value
|
||||||
@@ -21,13 +24,23 @@ ColumnLayout {
|
|||||||
border.width: Theme.borderThin
|
border.width: Theme.borderThin
|
||||||
border.color: toggle.checked ? Theme.primaryAccent : Theme.fieldBorder
|
border.color: toggle.checked ? Theme.primaryAccent : Theme.fieldBorder
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation { duration: Theme.durationFast }
|
||||||
|
}
|
||||||
|
Behavior on border.color {
|
||||||
|
ColorAnimation { duration: Theme.durationFast }
|
||||||
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: "✓"
|
text: "✓"
|
||||||
font.pixelSize: 13
|
font.pixelSize: Theme.fontSm
|
||||||
font.bold: true
|
font.bold: true
|
||||||
color: Theme.panelBackground
|
color: Theme.panelBackground
|
||||||
visible: toggle.checked
|
opacity: toggle.checked ? 1.0 : 0.0
|
||||||
|
Behavior on opacity {
|
||||||
|
NumberAnimation { duration: Theme.durationFast }
|
||||||
|
}
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
}
|
}
|
||||||
@@ -36,268 +49,462 @@ ColumnLayout {
|
|||||||
contentItem: Text {
|
contentItem: Text {
|
||||||
text: toggle.text
|
text: toggle.text
|
||||||
color: Theme.headingColor
|
color: Theme.headingColor
|
||||||
|
font.family: Theme.uiFontFamily
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
leftPadding: toggle.indicator.width + toggle.spacing
|
leftPadding: toggle.indicator.width + toggle.spacing
|
||||||
font.pixelSize: toggle.font.pixelSize || 11
|
font.pixelSize: toggle.font.pixelSize || Theme.fontXs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── READOUT ───────────────────────────────────────────────────────────
|
component BadgePill: Rectangle {
|
||||||
Label {
|
implicitWidth: badgeLabel.implicitWidth + 10
|
||||||
text: "READOUT"
|
implicitHeight: 10
|
||||||
color: Theme.bodyColor
|
radius: 9
|
||||||
font.pixelSize: 10
|
color: Theme.fieldBackground
|
||||||
font.letterSpacing: 1.8
|
border.color: Theme.cardBorder
|
||||||
font.weight: Font.Medium
|
border.width: 1
|
||||||
topPadding: 6
|
|
||||||
bottomPadding: 8
|
property alias text: badgeLabel.text
|
||||||
|
Label {
|
||||||
|
id: badgeLabel
|
||||||
|
anchors.centerIn: parent
|
||||||
|
color: Theme.bodyColor
|
||||||
|
font.pixelSize: Theme.font2xs
|
||||||
|
font.weight: Font.Medium
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
implicitHeight: statsLayout.implicitHeight + 20
|
implicitHeight: readoutCard.implicitHeight + 24
|
||||||
color: Theme.subtleSectionBackground
|
color: Theme.sidePanelBackground
|
||||||
radius: Theme.radiusSm
|
radius: Theme.sidePanelRadius
|
||||||
border.color: Theme.cardBorder
|
border.color: Theme.sideBorder
|
||||||
border.width: 1
|
border.width: 1
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: statsLayout
|
id: readoutCard
|
||||||
anchors { fill: parent; margins: 10 }
|
anchors {
|
||||||
spacing: 8
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
top: parent.top
|
||||||
|
topMargin: 12
|
||||||
|
}
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
// Header Inside the Box
|
||||||
|
Label {
|
||||||
|
text: "READOUT"
|
||||||
|
color: Theme.sideMutedText
|
||||||
|
font.family: Theme.uiFontFamily
|
||||||
|
font.pixelSize: Theme.fontXs
|
||||||
|
font.letterSpacing: 1.5
|
||||||
|
font.bold: true
|
||||||
|
Layout.leftMargin: 14
|
||||||
|
Layout.rightMargin: 14
|
||||||
|
Layout.topMargin: 2
|
||||||
|
Layout.bottomMargin: 10
|
||||||
|
}
|
||||||
|
|
||||||
// Min Temp Row
|
// Min Temp Row
|
||||||
RowLayout {
|
RowLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Label { text: "Min Temp"; color: Theme.bodyColor; font.pixelSize: 11 }
|
Layout.leftMargin: 14
|
||||||
|
Layout.rightMargin: 14
|
||||||
|
Layout.preferredHeight: 32
|
||||||
|
Label {
|
||||||
|
text: "MIN TEMP"
|
||||||
|
color: Theme.sideMutedText
|
||||||
|
font.family: Theme.uiFontFamily
|
||||||
|
font.pixelSize: Theme.fontXs
|
||||||
|
font.bold: true
|
||||||
|
}
|
||||||
Item { Layout.fillWidth: true }
|
Item { Layout.fillWidth: true }
|
||||||
RowLayout {
|
RowLayout {
|
||||||
spacing: 4
|
spacing: 4
|
||||||
Label {
|
Label {
|
||||||
text: s.min !== undefined ? s.min : "—"
|
text: s.min !== undefined ? s.min : "—"
|
||||||
color: Theme.sensorLow
|
color: Theme.sensorLow
|
||||||
font.pixelSize: 13; font.weight: Font.Bold
|
font.family: Theme.codeFontFamily
|
||||||
|
font.pixelSize: Theme.fontMd
|
||||||
|
font.bold: true
|
||||||
}
|
}
|
||||||
Label {
|
Label {
|
||||||
text: s.minIndex !== undefined ? "#" + s.minIndex : ""
|
visible: (s.minIndex !== undefined) && s.minIndex >= 0
|
||||||
color: Theme.bodyColor
|
text: "#" + (s.minIndex !== undefined ? s.minIndex : "")
|
||||||
font.pixelSize: 10
|
color: Theme.sideMutedText
|
||||||
|
font.family: Theme.uiFontFamily
|
||||||
|
font.pixelSize: Theme.font2xs
|
||||||
|
Layout.alignment: Qt.AlignBottom
|
||||||
|
bottomPadding: 3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
height: 1
|
||||||
|
color: Theme.cardBorder
|
||||||
|
}
|
||||||
|
|
||||||
// Max Temp Row
|
// Max Temp Row
|
||||||
RowLayout {
|
RowLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Label { text: "Max Temp"; color: Theme.bodyColor; font.pixelSize: 11 }
|
Layout.leftMargin: 14
|
||||||
|
Layout.rightMargin: 14
|
||||||
|
Layout.preferredHeight: 32
|
||||||
|
Label {
|
||||||
|
text: "MAX TEMP"
|
||||||
|
color: Theme.sideMutedText
|
||||||
|
font.family: Theme.uiFontFamily
|
||||||
|
font.pixelSize: Theme.fontXs
|
||||||
|
font.bold: true
|
||||||
|
}
|
||||||
Item { Layout.fillWidth: true }
|
Item { Layout.fillWidth: true }
|
||||||
RowLayout {
|
RowLayout {
|
||||||
spacing: 4
|
spacing: 4
|
||||||
Label {
|
Label {
|
||||||
text: s.max !== undefined ? s.max : "—"
|
text: s.max !== undefined ? s.max : "—"
|
||||||
color: Theme.sensorHigh
|
color: Theme.sensorHigh
|
||||||
font.pixelSize: 13; font.weight: Font.Bold
|
font.family: Theme.codeFontFamily
|
||||||
|
font.pixelSize: Theme.fontMd
|
||||||
|
font.bold: true
|
||||||
}
|
}
|
||||||
Label {
|
Label {
|
||||||
text: s.maxIndex !== undefined ? "#" + s.maxIndex : ""
|
visible: (s.maxIndex !== undefined) && s.maxIndex >= 0
|
||||||
color: Theme.bodyColor
|
text: "#" + (s.maxIndex !== undefined ? s.maxIndex : "")
|
||||||
font.pixelSize: 10
|
color: Theme.sideMutedText
|
||||||
|
font.family: Theme.uiFontFamily
|
||||||
|
font.pixelSize: Theme.font2xs
|
||||||
|
Layout.alignment: Qt.AlignBottom
|
||||||
|
bottomPadding: 3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle { Layout.fillWidth: true; height: 1; color: Theme.cardBorder }
|
Rectangle {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
height: 1
|
||||||
|
color: Theme.cardBorder
|
||||||
|
}
|
||||||
|
|
||||||
// Differential Row
|
// Differential Row
|
||||||
RowLayout {
|
RowLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Label { text: "Differential"; color: Theme.bodyColor; font.pixelSize: 11 }
|
Layout.leftMargin: 14
|
||||||
|
Layout.rightMargin: 14
|
||||||
|
Layout.preferredHeight: 32
|
||||||
|
Label {
|
||||||
|
text: "DIFF"
|
||||||
|
color: Theme.sideMutedText
|
||||||
|
font.family: Theme.uiFontFamily
|
||||||
|
font.pixelSize: Theme.fontXs
|
||||||
|
font.bold: true
|
||||||
|
}
|
||||||
Item { Layout.fillWidth: true }
|
Item { Layout.fillWidth: true }
|
||||||
Label {
|
Label {
|
||||||
text: s.diff !== undefined ? s.diff : "—"
|
text: s.diff !== undefined ? s.diff : "—"
|
||||||
color: Theme.headingColor
|
color: Theme.isDarkMode ? "#A78BFA" : "#8B5CF6"
|
||||||
font.pixelSize: 13; font.weight: Font.Bold
|
font.family: Theme.codeFontFamily
|
||||||
|
font.pixelSize: Theme.fontMd
|
||||||
|
font.bold: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
height: 1
|
||||||
|
color: Theme.cardBorder
|
||||||
|
}
|
||||||
|
|
||||||
// Average Row
|
// Average Row
|
||||||
RowLayout {
|
RowLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Label { text: "Average"; color: Theme.bodyColor; font.pixelSize: 11 }
|
Layout.leftMargin: 14
|
||||||
|
Layout.rightMargin: 14
|
||||||
|
Layout.preferredHeight: 32
|
||||||
|
Label {
|
||||||
|
text: "AVERAGE"
|
||||||
|
color: Theme.sideMutedText
|
||||||
|
font.family: Theme.uiFontFamily
|
||||||
|
font.pixelSize: Theme.fontXs
|
||||||
|
font.bold: true
|
||||||
|
}
|
||||||
Item { Layout.fillWidth: true }
|
Item { Layout.fillWidth: true }
|
||||||
Label {
|
Label {
|
||||||
text: s.avg !== undefined ? s.avg : "—"
|
text: s.avg !== undefined ? s.avg : "—"
|
||||||
color: Theme.headingColor
|
color: Theme.headingColor
|
||||||
font.pixelSize: 13; font.weight: Font.Bold
|
font.family: Theme.codeFontFamily
|
||||||
|
font.pixelSize: Theme.fontMd
|
||||||
|
font.bold: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle { Layout.fillWidth: true; height: 1; color: Theme.cardBorder }
|
Rectangle {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
height: 1
|
||||||
|
color: Theme.cardBorder
|
||||||
|
}
|
||||||
|
|
||||||
// Sigma Row
|
// Sigma Row
|
||||||
RowLayout {
|
RowLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Label { text: "Sigma (σ)"; color: Theme.bodyColor; font.pixelSize: 11 }
|
Layout.leftMargin: 14
|
||||||
|
Layout.rightMargin: 14
|
||||||
|
Layout.preferredHeight: 32
|
||||||
|
Label {
|
||||||
|
text: "SIGMA (Σ)"
|
||||||
|
color: Theme.sideMutedText
|
||||||
|
font.family: Theme.uiFontFamily
|
||||||
|
font.pixelSize: Theme.fontXs
|
||||||
|
font.bold: true
|
||||||
|
}
|
||||||
Item { Layout.fillWidth: true }
|
Item { Layout.fillWidth: true }
|
||||||
Label {
|
Label {
|
||||||
text: s.sigma !== undefined ? s.sigma : "—"
|
text: s.sigma !== undefined ? s.sigma : "—"
|
||||||
color: Theme.headingColor
|
color: Theme.headingColor
|
||||||
font.pixelSize: 13; font.weight: Font.Bold
|
font.family: Theme.codeFontFamily
|
||||||
|
font.pixelSize: Theme.fontMd
|
||||||
|
font.bold: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
height: 1
|
||||||
|
color: Theme.cardBorder
|
||||||
|
}
|
||||||
|
|
||||||
// 3-Sigma Row
|
// 3-Sigma Row
|
||||||
RowLayout {
|
RowLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Label { text: "3σ Value"; color: Theme.bodyColor; font.pixelSize: 11 }
|
Layout.leftMargin: 14
|
||||||
|
Layout.rightMargin: 14
|
||||||
|
Layout.preferredHeight: 32
|
||||||
|
Label {
|
||||||
|
text: "3Σ VALUE"
|
||||||
|
color: Theme.sideMutedText
|
||||||
|
font.family: Theme.uiFontFamily
|
||||||
|
font.pixelSize: Theme.fontXs
|
||||||
|
font.bold: true
|
||||||
|
}
|
||||||
Item { Layout.fillWidth: true }
|
Item { Layout.fillWidth: true }
|
||||||
Label {
|
Label {
|
||||||
text: s.threeSigma !== undefined ? s.threeSigma : "—"
|
text: s.threeSigma !== undefined ? s.threeSigma : "—"
|
||||||
color: Theme.bodyColor
|
color: Theme.headingColor
|
||||||
font.pixelSize: 12; font.weight: Font.Medium
|
font.family: Theme.codeFontFamily
|
||||||
|
font.pixelSize: Theme.fontMd
|
||||||
|
font.bold: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Item { height: 12 }
|
Rectangle {
|
||||||
Rectangle { Layout.fillWidth: true; height: 1; color: Theme.cardBorder }
|
|
||||||
Item { height: 12 }
|
|
||||||
|
|
||||||
// ── DISPLAY ───────────────────────────────────────────────────────────
|
|
||||||
Label {
|
|
||||||
text: "DISPLAY"
|
|
||||||
color: Theme.bodyColor
|
|
||||||
font.pixelSize: 10
|
|
||||||
font.letterSpacing: 1.8
|
|
||||||
font.weight: Font.Medium
|
|
||||||
topPadding: 6
|
|
||||||
bottomPadding: 8
|
|
||||||
}
|
|
||||||
|
|
||||||
PanelCheckBox {
|
|
||||||
id: thicknessToggle
|
|
||||||
text: "Show Thickness"
|
|
||||||
checked: false
|
|
||||||
font.pixelSize: 11
|
|
||||||
onCheckedChanged: waferMapItem.showThickness = checked
|
|
||||||
}
|
|
||||||
|
|
||||||
PanelCheckBox {
|
|
||||||
id: labelsToggle
|
|
||||||
text: "Labels"
|
|
||||||
checked: true
|
|
||||||
font.pixelSize: 11
|
|
||||||
}
|
|
||||||
|
|
||||||
PanelCheckBox {
|
|
||||||
id: clusterAverageToggle
|
|
||||||
text: "Average Clusters"
|
|
||||||
checked: streamController.clusterAveragingEnabled
|
|
||||||
font.pixelSize: 11
|
|
||||||
onCheckedChanged: streamController.clusterAveragingEnabled = checked
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
spacing: 6
|
implicitHeight: displayCard.implicitHeight + 24
|
||||||
Label {
|
color: Theme.sidePanelBackground
|
||||||
text: "Heatmap"
|
radius: Theme.sidePanelRadius
|
||||||
color: Theme.bodyColor
|
border.color: Theme.sideBorder
|
||||||
font.pixelSize: 11
|
border.width: 1
|
||||||
Layout.preferredWidth: 52
|
|
||||||
}
|
ColumnLayout {
|
||||||
Slider {
|
id: displayCard
|
||||||
id: heatmapSlider
|
anchors {
|
||||||
from: 0; to: 1; value: 0
|
left: parent.left
|
||||||
Layout.fillWidth: true
|
right: parent.right
|
||||||
ToolTip.visible: hovered
|
top: parent.top
|
||||||
ToolTip.text: Math.round(value * 100) + "%"
|
margins: 12
|
||||||
|
}
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: "DISPLAY"
|
||||||
|
color: Theme.sideMutedText
|
||||||
|
font.family: Theme.uiFontFamily
|
||||||
|
font.pixelSize: Theme.fontXs
|
||||||
|
font.letterSpacing: 1.5
|
||||||
|
font.bold: true
|
||||||
|
Layout.bottomMargin: 4
|
||||||
|
}
|
||||||
|
|
||||||
|
PanelCheckBox {
|
||||||
|
id: thicknessToggle
|
||||||
|
text: "Show Thickness"
|
||||||
|
checked: false
|
||||||
|
font.pixelSize: Theme.fontXs
|
||||||
|
onCheckedChanged: waferMapItem.showThickness = checked
|
||||||
|
}
|
||||||
|
|
||||||
|
PanelCheckBox {
|
||||||
|
id: labelsToggle
|
||||||
|
text: "Labels"
|
||||||
|
checked: true
|
||||||
|
font.pixelSize: Theme.fontXs
|
||||||
|
}
|
||||||
|
|
||||||
|
PanelCheckBox {
|
||||||
|
id: clusterAverageToggle
|
||||||
|
text: "Average Clusters"
|
||||||
|
checked: streamController.clusterAveragingEnabled
|
||||||
|
font.pixelSize: Theme.fontXs
|
||||||
|
onCheckedChanged: streamController.clusterAveragingEnabled = checked
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
height: 1
|
||||||
|
color: Theme.cardBorder
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: 6
|
||||||
|
Label {
|
||||||
|
text: "Heatmap"
|
||||||
|
color: Theme.bodyColor
|
||||||
|
font.pixelSize: Theme.fontXs
|
||||||
|
Layout.preferredWidth: 52
|
||||||
|
}
|
||||||
|
Slider {
|
||||||
|
id: heatmapSlider
|
||||||
|
from: 0
|
||||||
|
to: 1
|
||||||
|
value: 0
|
||||||
|
Layout.fillWidth: true
|
||||||
|
ToolTip.visible: hovered
|
||||||
|
ToolTip.text: Math.round(value * 100) + "%"
|
||||||
|
|
||||||
|
handle: Rectangle {
|
||||||
|
x: heatmapSlider.leftPadding + heatmapSlider.visualPosition * (heatmapSlider.availableWidth - width)
|
||||||
|
y: heatmapSlider.topPadding + heatmapSlider.availableHeight / 2 - height / 2
|
||||||
|
implicitWidth: 18
|
||||||
|
implicitHeight: 18
|
||||||
|
radius: 9
|
||||||
|
color: Theme.primaryAccent
|
||||||
|
scale: heatmapSlider.pressed ? 1.15 : 1.0
|
||||||
|
Behavior on scale {
|
||||||
|
NumberAnimation { duration: Theme.durationFast; easing.type: Theme.easeStandard }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
text: Math.round(heatmapSlider.value * 100) + "%"
|
||||||
|
color: Theme.bodyColor
|
||||||
|
font.pixelSize: Theme.fontXs
|
||||||
|
font.weight: Font.Medium
|
||||||
|
Layout.preferredWidth: 32
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Item { height: 12 }
|
Rectangle {
|
||||||
Rectangle { Layout.fillWidth: true; height: 1; color: Theme.cardBorder }
|
|
||||||
Item { height: 12 }
|
|
||||||
|
|
||||||
// ── THRESHOLDS ────────────────────────────────────────────────────────
|
|
||||||
Label {
|
|
||||||
text: "THRESHOLDS"
|
|
||||||
color: Theme.bodyColor
|
|
||||||
font.pixelSize: 10
|
|
||||||
font.letterSpacing: 1.8
|
|
||||||
font.weight: Font.Medium
|
|
||||||
topPadding: 6
|
|
||||||
bottomPadding: 8
|
|
||||||
}
|
|
||||||
|
|
||||||
Label {
|
|
||||||
text: "Set Point (°C)"
|
|
||||||
color: Theme.bodyColor
|
|
||||||
font.pixelSize: 11
|
|
||||||
bottomPadding: 3
|
|
||||||
}
|
|
||||||
TextField {
|
|
||||||
id: spField
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
text: "149.0"
|
implicitHeight: thresholdCard.implicitHeight + 24
|
||||||
font.pixelSize: 12
|
color: Theme.sidePanelBackground
|
||||||
inputMethodHints: Qt.ImhFormattedNumbersOnly
|
radius: Theme.sidePanelRadius
|
||||||
color: Theme.fieldText
|
border.color: Theme.sideBorder
|
||||||
placeholderTextColor: Theme.fieldPlaceholder
|
border.width: 1
|
||||||
selectedTextColor: Theme.fieldBackground
|
|
||||||
selectionColor: Theme.fieldText
|
ColumnLayout {
|
||||||
background: Rectangle {
|
id: thresholdCard
|
||||||
radius: Theme.radiusXs
|
anchors {
|
||||||
color: Theme.fieldBackground
|
left: parent.left
|
||||||
border.width: spField.activeFocus ? Theme.borderStrong : Theme.borderThin
|
right: parent.right
|
||||||
border.color: spField.activeFocus ? Theme.fieldBorderFocus : Theme.fieldBorder
|
top: parent.top
|
||||||
|
margins: 12
|
||||||
|
}
|
||||||
|
spacing: 6
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: "THRESHOLDS"
|
||||||
|
color: Theme.sideMutedText
|
||||||
|
font.family: Theme.uiFontFamily
|
||||||
|
font.pixelSize: Theme.fontXs
|
||||||
|
font.letterSpacing: 1.5
|
||||||
|
font.bold: true
|
||||||
|
Layout.bottomMargin: 4
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: "Set Point (°C)"
|
||||||
|
color: Theme.bodyColor
|
||||||
|
font.pixelSize: Theme.fontXs
|
||||||
|
}
|
||||||
|
TextField {
|
||||||
|
id: spField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: "149.0"
|
||||||
|
font.pixelSize: Theme.fontSm
|
||||||
|
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
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation { duration: Theme.durationFast }
|
||||||
|
}
|
||||||
|
Behavior on border.color {
|
||||||
|
ColorAnimation { duration: Theme.durationFast }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onEditingFinished: pushThresholds()
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: "Margin (±°C)"
|
||||||
|
color: Theme.bodyColor
|
||||||
|
font.pixelSize: Theme.fontXs
|
||||||
|
}
|
||||||
|
TextField {
|
||||||
|
id: mgField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: "1.0"
|
||||||
|
font.pixelSize: Theme.fontSm
|
||||||
|
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
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation { duration: Theme.durationFast }
|
||||||
|
}
|
||||||
|
Behavior on border.color {
|
||||||
|
ColorAnimation { duration: Theme.durationFast }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onEditingFinished: pushThresholds()
|
||||||
|
}
|
||||||
|
|
||||||
|
PanelCheckBox {
|
||||||
|
id: autoCheck
|
||||||
|
text: "Auto range (mean ± 1σ)"
|
||||||
|
checked: true
|
||||||
|
font.pixelSize: Theme.fontXs
|
||||||
|
onCheckedChanged: pushThresholds()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onEditingFinished: pushThresholds()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Item { height: 10 }
|
Item {
|
||||||
|
Layout.fillHeight: true
|
||||||
Label {
|
|
||||||
text: "Margin (±°C)"
|
|
||||||
color: Theme.bodyColor
|
|
||||||
font.pixelSize: 11
|
|
||||||
bottomPadding: 3
|
|
||||||
}
|
}
|
||||||
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: 10 }
|
|
||||||
|
|
||||||
PanelCheckBox {
|
|
||||||
id: autoCheck
|
|
||||||
text: "Auto range (mean ± 1σ)"
|
|
||||||
checked: true
|
|
||||||
font.pixelSize: 11
|
|
||||||
onCheckedChanged: pushThresholds()
|
|
||||||
}
|
|
||||||
|
|
||||||
Item { Layout.fillHeight: true }
|
|
||||||
|
|
||||||
function pushThresholds() {
|
function pushThresholds() {
|
||||||
var sp = parseFloat(spField.text) || 149.0
|
var sp = parseFloat(spField.text) || 149.0;
|
||||||
var mg = parseFloat(mgField.text) || 1.0
|
var mg = parseFloat(mgField.text) || 1.0;
|
||||||
streamController.setThresholds(sp, mg, autoCheck.checked)
|
streamController.setThresholds(sp, mg, autoCheck.checked);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
|
import QtQuick.Controls.impl
|
||||||
import ISC
|
import ISC
|
||||||
import ".."
|
import ".."
|
||||||
|
|
||||||
@@ -14,10 +15,11 @@ ColumnLayout {
|
|||||||
|
|
||||||
Label {
|
Label {
|
||||||
text: "SOURCE"
|
text: "SOURCE"
|
||||||
color: Theme.bodyColor
|
color: Theme.sideMutedText
|
||||||
font.pixelSize: 10
|
font.family: Theme.uiFontFamily
|
||||||
font.letterSpacing: 1.8
|
font.pixelSize: Theme.fontSm
|
||||||
font.weight: Font.Medium
|
font.letterSpacing: 1.5
|
||||||
|
font.bold: true
|
||||||
topPadding: 6
|
topPadding: 6
|
||||||
bottomPadding: 8
|
bottomPadding: 8
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
@@ -26,51 +28,79 @@ ColumnLayout {
|
|||||||
|
|
||||||
Button {
|
Button {
|
||||||
id: editBtn
|
id: editBtn
|
||||||
text: "✎"
|
implicitWidth: 28
|
||||||
implicitWidth: 26
|
implicitHeight: 28
|
||||||
implicitHeight: 26
|
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
font.pixelSize: 14
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
color: editBtn.pressed ? Theme.buttonPressed
|
color: editBtn.pressed ? Theme.buttonPressed : editBtn.hovered ? Theme.buttonNeutralHover : "transparent"
|
||||||
: editBtn.hovered ? Theme.buttonNeutralHover
|
|
||||||
: "transparent"
|
|
||||||
radius: Theme.radiusSm
|
radius: Theme.radiusSm
|
||||||
}
|
}
|
||||||
contentItem: Text {
|
contentItem: IconImage {
|
||||||
text: parent.text
|
source: "../icons/edit.svg"
|
||||||
|
sourceSize.width: 16
|
||||||
|
sourceSize.height: 16
|
||||||
color: Theme.bodyColor
|
color: Theme.bodyColor
|
||||||
font: parent.font
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
}
|
}
|
||||||
onClicked: {
|
onClicked: {
|
||||||
file_browser.refreshFiles()
|
file_browser.refreshFiles();
|
||||||
csvEditorDialog.open()
|
csvEditorDialog.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
ToolTip {
|
||||||
|
visible: editBtn.hovered
|
||||||
|
text: "Edit"
|
||||||
|
delay: 400
|
||||||
|
font.pixelSize: Theme.fontXs
|
||||||
|
font.family: Theme.uiFontFamily
|
||||||
|
contentItem: Text {
|
||||||
|
text: parent.text
|
||||||
|
color: Theme.headingColor
|
||||||
|
font: parent.font
|
||||||
|
}
|
||||||
|
background: Rectangle {
|
||||||
|
color: Theme.cardBackground
|
||||||
|
border.color: Theme.sideBorder
|
||||||
|
border.width: 1
|
||||||
|
radius: Theme.radiusXs
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
id: refreshBtn
|
id: refreshBtn
|
||||||
text: "⟳"
|
implicitWidth: 28
|
||||||
implicitWidth: 26
|
implicitHeight: 28
|
||||||
implicitHeight: 26
|
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
font.pixelSize: 14
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
color: refreshBtn.pressed ? Theme.buttonPressed
|
color: refreshBtn.pressed ? Theme.buttonPressed : refreshBtn.hovered ? Theme.buttonNeutralHover : "transparent"
|
||||||
: refreshBtn.hovered ? Theme.buttonNeutralHover
|
|
||||||
: "transparent"
|
|
||||||
radius: Theme.radiusSm
|
radius: Theme.radiusSm
|
||||||
}
|
}
|
||||||
contentItem: Text {
|
contentItem: IconImage {
|
||||||
text: parent.text
|
source: "../icons/refresh.svg"
|
||||||
|
sourceSize.width: 16
|
||||||
|
sourceSize.height: 16
|
||||||
color: Theme.bodyColor
|
color: Theme.bodyColor
|
||||||
font: parent.font
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
}
|
}
|
||||||
onClicked: file_browser.refreshFiles()
|
onClicked: file_browser.refreshFiles()
|
||||||
|
|
||||||
|
ToolTip {
|
||||||
|
visible: refreshBtn.hovered
|
||||||
|
text: "Refresh"
|
||||||
|
delay: 400
|
||||||
|
font.pixelSize: Theme.fontXs
|
||||||
|
font.family: Theme.uiFontFamily
|
||||||
|
contentItem: Text {
|
||||||
|
text: parent.text
|
||||||
|
color: Theme.headingColor
|
||||||
|
font: parent.font
|
||||||
|
}
|
||||||
|
background: Rectangle {
|
||||||
|
color: Theme.cardBackground
|
||||||
|
border.color: Theme.sideBorder
|
||||||
|
border.width: 1
|
||||||
|
radius: Theme.radiusXs
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,14 +109,12 @@ ColumnLayout {
|
|||||||
id: dirBtn
|
id: dirBtn
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
implicitHeight: 32
|
implicitHeight: 36
|
||||||
leftPadding: 8
|
leftPadding: 8
|
||||||
rightPadding: 8
|
rightPadding: 8
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
radius: Theme.radiusSm
|
radius: Theme.radiusSm
|
||||||
color: dirBtn.pressed ? Theme.buttonNeutralPressed
|
color: dirBtn.pressed ? Theme.buttonNeutralPressed : dirBtn.hovered ? Theme.buttonNeutralHover : Theme.buttonNeutralBackground
|
||||||
: dirBtn.hovered ? Theme.buttonNeutralHover
|
|
||||||
: Theme.buttonNeutralBackground
|
|
||||||
border.width: Theme.borderThin
|
border.width: Theme.borderThin
|
||||||
border.color: Theme.fieldBorder
|
border.color: Theme.fieldBorder
|
||||||
}
|
}
|
||||||
@@ -95,12 +123,12 @@ ColumnLayout {
|
|||||||
Label {
|
Label {
|
||||||
text: "▤"
|
text: "▤"
|
||||||
color: Theme.bodyColor
|
color: Theme.bodyColor
|
||||||
font.pixelSize: 12
|
font.pixelSize: Theme.fontSm
|
||||||
}
|
}
|
||||||
Label {
|
Label {
|
||||||
text: file_browser.currentDirectory.split("/").pop() || file_browser.currentDirectory
|
text: file_browser.currentDirectory.split("/").pop() || file_browser.currentDirectory
|
||||||
color: Theme.headingColor
|
color: Theme.headingColor
|
||||||
font.pixelSize: 11
|
font.pixelSize: Theme.fontSm
|
||||||
elide: Text.ElideMiddle
|
elide: Text.ElideMiddle
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
@@ -113,7 +141,7 @@ ColumnLayout {
|
|||||||
id: filter
|
id: filter
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
placeholderText: "Filter…"
|
placeholderText: "Filter…"
|
||||||
font.pixelSize: 11
|
font.pixelSize: Theme.fontSm
|
||||||
color: Theme.fieldText
|
color: Theme.fieldText
|
||||||
placeholderTextColor: Theme.fieldPlaceholder
|
placeholderTextColor: Theme.fieldPlaceholder
|
||||||
selectedTextColor: Theme.fieldBackground
|
selectedTextColor: Theme.fieldBackground
|
||||||
@@ -123,6 +151,12 @@ ColumnLayout {
|
|||||||
color: Theme.fieldBackground
|
color: Theme.fieldBackground
|
||||||
border.width: filter.activeFocus ? Theme.borderStrong : Theme.borderThin
|
border.width: filter.activeFocus ? Theme.borderStrong : Theme.borderThin
|
||||||
border.color: filter.activeFocus ? Theme.fieldBorderFocus : Theme.fieldBorder
|
border.color: filter.activeFocus ? Theme.fieldBorderFocus : Theme.fieldBorder
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation { duration: Theme.durationFast }
|
||||||
|
}
|
||||||
|
Behavior on border.color {
|
||||||
|
ColorAnimation { duration: Theme.durationFast }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,17 +180,14 @@ ColumnLayout {
|
|||||||
focusPolicy: Qt.NoFocus
|
focusPolicy: Qt.NoFocus
|
||||||
|
|
||||||
readonly property bool matchesFilter: {
|
readonly property bool matchesFilter: {
|
||||||
if (filter.text === "") return true
|
if (filter.text === "")
|
||||||
var q = filter.text.toLowerCase()
|
return true;
|
||||||
return (modelData.baseName + modelData.waferType + modelData.date)
|
var q = filter.text.toLowerCase();
|
||||||
.toLowerCase().indexOf(q) >= 0
|
return (modelData.baseName + modelData.waferType + modelData.date).toLowerCase().indexOf(q) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Active only in review mode; no highlight during live streaming
|
// Active only in review mode; no highlight during live streaming
|
||||||
readonly property bool isActive:
|
readonly property bool isActive: streamController.mode === "review" && streamController.loadedFile !== "" && modelData.fileName === streamController.loadedFile
|
||||||
streamController.mode === "review" &&
|
|
||||||
streamController.loadedFile !== "" &&
|
|
||||||
modelData.fileName === streamController.loadedFile
|
|
||||||
|
|
||||||
visible: matchesFilter
|
visible: matchesFilter
|
||||||
height: matchesFilter ? implicitHeight : 0
|
height: matchesFilter ? implicitHeight : 0
|
||||||
@@ -164,10 +195,11 @@ ColumnLayout {
|
|||||||
onClicked: streamController.loadFile(modelData.fileName)
|
onClicked: streamController.loadFile(modelData.fileName)
|
||||||
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
color: fileItem.isActive
|
color: fileItem.isActive ? Qt.rgba(1, 1, 1, 0.06) : fileItem.hovered ? Qt.rgba(1, 1, 1, 0.04) : "transparent"
|
||||||
? Qt.rgba(1, 1, 1, 0.06)
|
|
||||||
: fileItem.hovered ? Qt.rgba(1, 1, 1, 0.04) : "transparent"
|
|
||||||
radius: Theme.radiusSm
|
radius: Theme.radiusSm
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation { duration: Theme.durationFast }
|
||||||
|
}
|
||||||
|
|
||||||
// Left accent bar — shown only when active
|
// Left accent bar — shown only when active
|
||||||
Rectangle {
|
Rectangle {
|
||||||
@@ -175,15 +207,21 @@ ColumnLayout {
|
|||||||
width: 3
|
width: 3
|
||||||
radius: 1.5
|
radius: 1.5
|
||||||
anchors {
|
anchors {
|
||||||
top: parent.top; bottom: parent.bottom; left: parent.left
|
top: parent.top
|
||||||
topMargin: 5; bottomMargin: 5
|
bottom: parent.bottom
|
||||||
|
left: parent.left
|
||||||
|
topMargin: 5
|
||||||
|
bottomMargin: 5
|
||||||
}
|
}
|
||||||
color: {
|
color: {
|
||||||
var t = modelData.waferType
|
var t = modelData.waferType;
|
||||||
if (t === "A" || t === "E" || t === "P") return "#3B82F6"
|
if (t === "A" || t === "E" || t === "P")
|
||||||
if (t === "B" || t === "C" || t === "D") return "#10B981"
|
return "#3B82F6";
|
||||||
if (t === "Z") return "#8B5CF6"
|
if (t === "B" || t === "C" || t === "D")
|
||||||
return Theme.headingColor
|
return "#10B981";
|
||||||
|
if (t === "Z")
|
||||||
|
return "#8B5CF6";
|
||||||
|
return Theme.headingColor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -193,22 +231,26 @@ ColumnLayout {
|
|||||||
|
|
||||||
// Wafer-type avatar (circle)
|
// Wafer-type avatar (circle)
|
||||||
Rectangle {
|
Rectangle {
|
||||||
implicitWidth: 28; implicitHeight: 28
|
implicitWidth: 28
|
||||||
|
implicitHeight: 28
|
||||||
Layout.preferredWidth: 28
|
Layout.preferredWidth: 28
|
||||||
Layout.preferredHeight: 28
|
Layout.preferredHeight: 28
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
radius: 14
|
radius: 14
|
||||||
color: {
|
color: {
|
||||||
var t = modelData.waferType
|
var t = modelData.waferType;
|
||||||
if (t === "A" || t === "E" || t === "P") return "#1D4ED8"
|
if (t === "A" || t === "E" || t === "P")
|
||||||
if (t === "B" || t === "C" || t === "D") return "#065F46"
|
return "#1D4ED8";
|
||||||
if (t === "Z") return "#7C3AED"
|
if (t === "B" || t === "C" || t === "D")
|
||||||
return "#374151"
|
return "#065F46";
|
||||||
|
if (t === "Z")
|
||||||
|
return "#7C3AED";
|
||||||
|
return "#374151";
|
||||||
}
|
}
|
||||||
Label {
|
Label {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: modelData.waferType || "?"
|
text: modelData.waferType || "?"
|
||||||
font.pixelSize: 12
|
font.pixelSize: Theme.fontMd
|
||||||
font.weight: Font.Bold
|
font.weight: Font.Bold
|
||||||
color: "#FFFFFF"
|
color: "#FFFFFF"
|
||||||
}
|
}
|
||||||
@@ -223,7 +265,7 @@ ColumnLayout {
|
|||||||
Label {
|
Label {
|
||||||
text: modelData.serialNumber ? (modelData.waferType + modelData.serialNumber) : modelData.baseName
|
text: modelData.serialNumber ? (modelData.waferType + modelData.serialNumber) : modelData.baseName
|
||||||
color: Theme.headingColor
|
color: Theme.headingColor
|
||||||
font.pixelSize: 13
|
font.pixelSize: Theme.fontMd
|
||||||
font.weight: Font.Bold
|
font.weight: Font.Bold
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
@@ -235,24 +277,24 @@ ColumnLayout {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Label {
|
Label {
|
||||||
text: {
|
text: {
|
||||||
var d = modelData.date || ""
|
var d = modelData.date || "";
|
||||||
return d.length >= 10 ? d.substring(0, 10) : (d || "—")
|
return d.length >= 10 ? d.substring(0, 10) : (d || "—");
|
||||||
}
|
}
|
||||||
color: Theme.bodyColor
|
color: Theme.bodyColor
|
||||||
font.pixelSize: 10
|
font.pixelSize: Theme.fontSm
|
||||||
}
|
}
|
||||||
Label {
|
Label {
|
||||||
visible: (modelData.timeStr || "") !== ""
|
visible: (modelData.timeStr || "") !== ""
|
||||||
text: "·"
|
text: "·"
|
||||||
color: Theme.bodyColor
|
color: Theme.bodyColor
|
||||||
font.pixelSize: 10
|
font.pixelSize: Theme.fontSm
|
||||||
opacity: 0.45
|
opacity: 0.45
|
||||||
}
|
}
|
||||||
Label {
|
Label {
|
||||||
visible: (modelData.timeStr || "") !== ""
|
visible: (modelData.timeStr || "") !== ""
|
||||||
text: modelData.timeStr || ""
|
text: modelData.timeStr || ""
|
||||||
color: Theme.bodyColor
|
color: Theme.bodyColor
|
||||||
font.pixelSize: 10
|
font.pixelSize: Theme.fontSm
|
||||||
opacity: 0.65
|
opacity: 0.65
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -260,18 +302,20 @@ ColumnLayout {
|
|||||||
// Tertiary: edited metadata (chamber · notes) if any
|
// Tertiary: edited metadata (chamber · notes) if any
|
||||||
Label {
|
Label {
|
||||||
visible: {
|
visible: {
|
||||||
var c = modelData.chamber || ""
|
var c = modelData.chamber || "";
|
||||||
var n = modelData.notes || ""
|
var n = modelData.notes || "";
|
||||||
return c !== "" || n !== ""
|
return c !== "" || n !== "";
|
||||||
}
|
}
|
||||||
text: {
|
text: {
|
||||||
var parts = []
|
var parts = [];
|
||||||
if (modelData.chamber) parts.push(modelData.chamber)
|
if (modelData.chamber)
|
||||||
if (modelData.notes) parts.push(modelData.notes)
|
parts.push(modelData.chamber);
|
||||||
return parts.join(" · ")
|
if (modelData.notes)
|
||||||
|
parts.push(modelData.notes);
|
||||||
|
return parts.join(" · ");
|
||||||
}
|
}
|
||||||
color: Theme.bodyColor
|
color: Theme.bodyColor
|
||||||
font.pixelSize: 9
|
font.pixelSize: Theme.fontXs
|
||||||
opacity: 0.7
|
opacity: 0.7
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
@@ -285,7 +329,7 @@ ColumnLayout {
|
|||||||
Label {
|
Label {
|
||||||
text: file_browser.files.length + " files · CSV only"
|
text: file_browser.files.length + " files · CSV only"
|
||||||
color: Theme.bodyColor
|
color: Theme.bodyColor
|
||||||
font.pixelSize: 10
|
font.pixelSize: Theme.fontSm
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectFileDialog {
|
SelectFileDialog {
|
||||||
|
|||||||
Reference in New Issue
Block a user