style(ui): minor styling adjustments for AboutDialog and OverlapMapCard
CI / preflight (push) Waiting to run
CI / preflight (push) Waiting to run
This commit is contained in:
@@ -3,6 +3,7 @@ import QtQuick.Controls
|
||||
import QtQuick.Dialogs
|
||||
import QtQuick.Layouts
|
||||
import ISC
|
||||
import ISC.Tabs.components
|
||||
|
||||
Popup {
|
||||
id: root
|
||||
@@ -133,13 +134,28 @@ Popup {
|
||||
Label { text: modelData.mfgDate; font.pixelSize: Theme.fontMd; color: Theme.bodyColor; Layout.preferredWidth: 120 }
|
||||
Label { text: modelData.level; font.pixelSize: Theme.fontMd; color: Theme.bodyColor; Layout.preferredWidth: 80 }
|
||||
Label { text: modelData.licDate; font.pixelSize: Theme.fontMd; color: Theme.bodyColor; Layout.fillWidth: true }
|
||||
ToolButton {
|
||||
Button {
|
||||
id: removeLicenseBtn
|
||||
Layout.preferredWidth: 28
|
||||
text: "✕"
|
||||
font.pixelSize: Theme.fontSm
|
||||
ToolTip.visible: hovered
|
||||
ToolTip.text: "Remove license"
|
||||
implicitHeight: 28
|
||||
hoverEnabled: true
|
||||
background: Rectangle {
|
||||
color: removeLicenseBtn.pressed ? Theme.buttonPressed : removeLicenseBtn.hovered ? Theme.buttonNeutralHover : "transparent"
|
||||
radius: Theme.radiusSm
|
||||
}
|
||||
contentItem: Text {
|
||||
text: "✕"
|
||||
font.pixelSize: Theme.fontSm
|
||||
color: Theme.bodyColor
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
onClicked: licenseModel.removeLicense(modelData.serial, modelData.level)
|
||||
|
||||
AppToolTip {
|
||||
visible: removeLicenseBtn.hovered
|
||||
text: "Remove license"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,16 +124,22 @@ Rectangle {
|
||||
licenseModel.startReplayTrial()
|
||||
}
|
||||
}
|
||||
function onParsedDataReady(result) {
|
||||
if (result.success && result.csv_path) {
|
||||
streamController.loadFile(result.csv_path)
|
||||
// Fires while still on Status(0), before the tab switch below —
|
||||
// the generic per-tab tracker only attributes picks made while
|
||||
// already on Map/Graph, so record this one explicitly.
|
||||
root.mapReviewFile = result.csv_path
|
||||
if (root.selectedTabIndex === 0 && licenseModel.licenses.length > 0) {
|
||||
}
|
||||
Connections {
|
||||
// Deferred until the post-read metadata dialog (StatusTab.qml) closes —
|
||||
// jumping tabs from onParsedDataReady directly would deactivate the
|
||||
// Status Loader (StackLayout.index !== selectedTabIndex) and tear down
|
||||
// the dialog before the technician could see or use it.
|
||||
target: statusTabLoader.item
|
||||
function onCsvMetadataDialogClosed(csvPath) {
|
||||
if (!csvPath) return
|
||||
streamController.loadFile(csvPath)
|
||||
// Fires while still on Status(0), before the tab switch below —
|
||||
// the generic per-tab tracker only attributes picks made while
|
||||
// already on Map/Graph, so record this one explicitly.
|
||||
root.mapReviewFile = csvPath
|
||||
if (root.selectedTabIndex === 0 && licenseModel.licenses.length > 0) {
|
||||
root.selectedTabIndex = 2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -764,6 +770,7 @@ Rectangle {
|
||||
currentIndex: root.selectedTabIndex
|
||||
|
||||
Loader {
|
||||
id: statusTabLoader
|
||||
source: "Tabs/StatusTab.qml"
|
||||
active: StackLayout.index === root.selectedTabIndex
|
||||
}
|
||||
|
||||
@@ -15,6 +15,12 @@ ColumnLayout {
|
||||
anchors.margins: Theme.panelPadding
|
||||
spacing: 8
|
||||
|
||||
// Fired once the post-read metadata dialog is dismissed (Save or Cancel),
|
||||
// so HomePage can defer its auto-jump-to-Map until after the technician
|
||||
// has had a chance to edit metadata — jumping tabs immediately would
|
||||
// deactivate this Loader's item and kill the dialog mid-display.
|
||||
signal csvMetadataDialogClosed(string csvPath)
|
||||
|
||||
// ── Reusable Inline Components ──
|
||||
component StatCard : Rectangle {
|
||||
property alias value: valueText.text
|
||||
@@ -147,31 +153,127 @@ ColumnLayout {
|
||||
id: editCsvDialog
|
||||
parent: Overlay.overlay
|
||||
modal: true
|
||||
title: "Edit CSV Metadata"
|
||||
width: 460
|
||||
anchors.centerIn: parent
|
||||
standardButtons: Dialog.Save | Dialog.Cancel
|
||||
standardButtons: Dialog.NoButton
|
||||
padding: 20
|
||||
onAccepted: file_browser.saveMetadata(root.csvPath, metaWafer.text, metaDate.text, metaChamber.text, metaNotes.text, false, "")
|
||||
onClosed: root.csvMetadataDialogClosed(root.csvPath)
|
||||
|
||||
background: Rectangle {
|
||||
radius: Theme.radiusLg
|
||||
color: Theme.cardBackground
|
||||
border.color: Theme.cardBorder
|
||||
border.width: Theme.borderThin
|
||||
}
|
||||
|
||||
component MetaField: TextField {
|
||||
id: metaField
|
||||
Layout.fillWidth: true
|
||||
color: Theme.fieldText
|
||||
placeholderTextColor: Theme.fieldPlaceholder
|
||||
selectedTextColor: Theme.fieldBackground
|
||||
selectionColor: Theme.fieldText
|
||||
font.pixelSize: Theme.fontMd
|
||||
background: Rectangle {
|
||||
radius: Theme.radiusXs
|
||||
color: Theme.fieldBackground
|
||||
border.width: metaField.activeFocus ? Theme.borderStrong : Theme.borderThin
|
||||
border.color: metaField.activeFocus ? Theme.fieldBorderFocus : Theme.fieldBorder
|
||||
Behavior on border.color {
|
||||
ColorAnimation { duration: Theme.durationFast }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 6
|
||||
|
||||
// ── header ───────────────────────────────────────────────
|
||||
Label {
|
||||
text: "EDIT CSV METADATA"
|
||||
color: Theme.headingColor
|
||||
font.pixelSize: Theme.fontLg
|
||||
font.bold: true
|
||||
font.letterSpacing: 1
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Text {
|
||||
text: root.csvPath.split("/").pop()
|
||||
color: Theme.sideMutedText
|
||||
font.pixelSize: Theme.fontXs
|
||||
elide: Text.ElideMiddle
|
||||
Layout.fillWidth: true
|
||||
Layout.bottomMargin: 4
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.bottomMargin: 8
|
||||
height: 1
|
||||
color: Theme.cardBorder
|
||||
}
|
||||
|
||||
Label { text: "Wafer"; color: Theme.bodyColor; font.pixelSize: Theme.fontXs }
|
||||
MetaField { id: metaWafer }
|
||||
Label { text: "Date"; color: Theme.bodyColor; font.pixelSize: Theme.fontXs; Layout.topMargin: 6 }
|
||||
MetaField { id: metaDate }
|
||||
Label { text: "Chamber"; color: Theme.bodyColor; font.pixelSize: Theme.fontXs; Layout.topMargin: 6 }
|
||||
MetaField { id: metaChamber }
|
||||
Label { text: "Notes"; color: Theme.bodyColor; font.pixelSize: Theme.fontXs; Layout.topMargin: 6 }
|
||||
MetaField { id: metaNotes }
|
||||
|
||||
// ── buttons ───────────────────────────────────────────────
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 14
|
||||
spacing: 8
|
||||
|
||||
Button {
|
||||
id: cancelCsvBtn
|
||||
text: "Cancel"
|
||||
Layout.fillWidth: true
|
||||
hoverEnabled: true
|
||||
background: Rectangle {
|
||||
radius: Theme.radiusSm
|
||||
color: cancelCsvBtn.down ? Theme.buttonNeutralPressed : cancelCsvBtn.hovered ? Theme.buttonNeutralHover : Theme.buttonNeutralBackground
|
||||
border.width: Theme.borderThin
|
||||
border.color: Theme.fieldBorder
|
||||
}
|
||||
contentItem: Text {
|
||||
text: cancelCsvBtn.text
|
||||
color: Theme.buttonNeutralText
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font.bold: true
|
||||
font.pixelSize: Theme.fontSm
|
||||
}
|
||||
onClicked: editCsvDialog.reject()
|
||||
}
|
||||
Button {
|
||||
id: saveCsvBtn
|
||||
text: "Save"
|
||||
Layout.fillWidth: true
|
||||
hoverEnabled: true
|
||||
background: Rectangle {
|
||||
radius: Theme.radiusSm
|
||||
color: saveCsvBtn.hovered ? Qt.lighter(Theme.primaryAccent, 1.1) : Theme.primaryAccent
|
||||
border.width: Theme.borderThin
|
||||
border.color: Theme.primaryAccent
|
||||
}
|
||||
contentItem: Text {
|
||||
text: saveCsvBtn.text
|
||||
color: Theme.tone100
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
font.bold: true
|
||||
font.pixelSize: Theme.fontSm
|
||||
}
|
||||
onClicked: editCsvDialog.accept()
|
||||
}
|
||||
}
|
||||
Label { text: "Wafer" }
|
||||
TextField { id: metaWafer; Layout.fillWidth: true }
|
||||
Label { text: "Date" }
|
||||
TextField { id: metaDate; Layout.fillWidth: true }
|
||||
Label { text: "Chamber" }
|
||||
TextField { id: metaChamber; Layout.fillWidth: true }
|
||||
Label { text: "Notes" }
|
||||
TextField { id: metaNotes; Layout.fillWidth: true }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,74 +316,74 @@ ColumnLayout {
|
||||
|
||||
Item { Layout.fillHeight: true }
|
||||
|
||||
RowLayout {
|
||||
// Badge cluster centers on the full card width; port name overlays
|
||||
// the right edge independently so a long port string can't drag
|
||||
// the centered badge off-center (was sharing width via RowLayout).
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
spacing: 8
|
||||
Layout.preferredHeight: 22
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: 22
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: 5
|
||||
|
||||
Repeater {
|
||||
model: 4
|
||||
Rectangle {
|
||||
width: 4; height: 4; radius: 2
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: root.isConnected ? Theme.statusSuccessColor : (root.isBusy ? Theme.statusWarningColor : Theme.sideMutedText)
|
||||
opacity: (root.isConnected || root.isBusy) ? 1.0 : 0.3
|
||||
|
||||
SequentialAnimation on opacity {
|
||||
running: root.isConnected || root.isBusy
|
||||
loops: Animation.Infinite
|
||||
NumberAnimation { to: 0.3; duration: 1400 }
|
||||
NumberAnimation { to: 1.0; duration: 1400 }
|
||||
}
|
||||
}
|
||||
}
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: 5
|
||||
|
||||
Repeater {
|
||||
model: 4
|
||||
Rectangle {
|
||||
width: 4; height: 4; radius: 2
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: statusPillText.implicitWidth + 16
|
||||
height: 20
|
||||
radius: 10
|
||||
color: root.isConnected ? Theme.statusSuccessColor : (root.isBusy ? Theme.statusWarningColor : Theme.statusErrorColor)
|
||||
color: root.isConnected ? Theme.statusSuccessColor : (root.isBusy ? Theme.statusWarningColor : Theme.sideMutedText)
|
||||
opacity: (root.isConnected || root.isBusy) ? 1.0 : 0.3
|
||||
|
||||
Text {
|
||||
id: statusPillText
|
||||
anchors.centerIn: parent
|
||||
text: root.isConnected ? "ACTIVE" : (root.isBusy ? deviceController.connectionStatus.replace("...", "").toUpperCase() : "INACTIVE")
|
||||
color: Theme.statusBadgeText
|
||||
font.pixelSize: Theme.fontXs
|
||||
font.weight: Font.Bold
|
||||
font.family: Theme.uiFontFamily
|
||||
font.letterSpacing: 0.6
|
||||
SequentialAnimation on opacity {
|
||||
running: root.isConnected || root.isBusy
|
||||
loops: Animation.Infinite
|
||||
NumberAnimation { to: 0.3; duration: 1400 }
|
||||
NumberAnimation { to: 1.0; duration: 1400 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: 4
|
||||
Rectangle {
|
||||
width: 4; height: 4; radius: 2
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: root.isConnected ? Theme.statusSuccessColor : (root.isBusy ? Theme.statusWarningColor : Theme.sideMutedText)
|
||||
opacity: (root.isConnected || root.isBusy) ? 1.0 : 0.3
|
||||
Rectangle {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: statusPillText.implicitWidth + 16
|
||||
height: 20
|
||||
radius: 10
|
||||
color: root.isConnected ? Theme.statusSuccessColor : (root.isBusy ? Theme.statusWarningColor : Theme.statusErrorColor)
|
||||
|
||||
SequentialAnimation on opacity {
|
||||
running: root.isConnected || root.isBusy
|
||||
loops: Animation.Infinite
|
||||
NumberAnimation { to: 0.3; duration: 1400 }
|
||||
NumberAnimation { to: 1.0; duration: 1400 }
|
||||
}
|
||||
Text {
|
||||
id: statusPillText
|
||||
anchors.centerIn: parent
|
||||
text: root.isConnected ? "ACTIVE" : (root.isBusy ? deviceController.connectionStatus.replace("...", "").toUpperCase() : "INACTIVE")
|
||||
color: Theme.statusBadgeText
|
||||
font.pixelSize: Theme.fontXs
|
||||
font.weight: Font.Bold
|
||||
font.family: Theme.uiFontFamily
|
||||
font.letterSpacing: 0.6
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: 4
|
||||
Rectangle {
|
||||
width: 4; height: 4; radius: 2
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: root.isConnected ? Theme.statusSuccessColor : (root.isBusy ? Theme.statusWarningColor : Theme.sideMutedText)
|
||||
opacity: (root.isConnected || root.isBusy) ? 1.0 : 0.3
|
||||
|
||||
SequentialAnimation on opacity {
|
||||
running: root.isConnected || root.isBusy
|
||||
loops: Animation.Infinite
|
||||
NumberAnimation { to: 0.3; duration: 1400 }
|
||||
NumberAnimation { to: 1.0; duration: 1400 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: root.portName
|
||||
color: root.isConnected ? Theme.statusSuccessColor : Theme.headingColor
|
||||
font.pixelSize: Theme.fontMd
|
||||
@@ -612,7 +714,7 @@ ColumnLayout {
|
||||
root.dataCols = 0;
|
||||
root.csvPath = "";
|
||||
if (result && result.success === true)
|
||||
saveDirDialog.open();
|
||||
root.parseAndSavePendingRead();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ PanelBox {
|
||||
margin: 1.0
|
||||
blend: card.blendAmount / 100
|
||||
showLabels: true
|
||||
showExtremes: false
|
||||
ringColor: Theme.waferRingColor
|
||||
axisColor: Theme.waferAxisColor
|
||||
lowColor: Theme.sensorLow
|
||||
|
||||
Reference in New Issue
Block a user