From bbe7baea5b245cc33e65d092cb567baee59c9646 Mon Sep 17 00:00:00 2001 From: "Jack.Le" Date: Tue, 5 May 2026 09:59:18 -0700 Subject: [PATCH] Refactor SelectFileDialog and SettingsTab for improved metadata handling and UI consistency - Removed unused local_settings reference from qmldir. - Enhanced SelectFileDialog to include a masterTypeFieldText property for better metadata representation. - Updated normalizedRows to merge settingsModel.masters with sidecar data for dynamic UI updates. - Adjusted column headers and removed the save button from the table model for a cleaner interface. - Modified SettingsTab to streamline CSV file handling and ensure settings are saved upon updates. --- ISC/Tabs/SelectFileDialog.qml | 159 ++++++++++++++++------------------ ISC/Tabs/SettingsTab.qml | 18 ++-- ISC/Tabs/qmldir | 3 - 3 files changed, 86 insertions(+), 94 deletions(-) diff --git a/ISC/Tabs/SelectFileDialog.qml b/ISC/Tabs/SelectFileDialog.qml index e4cb828..94a0cf9 100644 --- a/ISC/Tabs/SelectFileDialog.qml +++ b/ISC/Tabs/SelectFileDialog.qml @@ -23,6 +23,12 @@ Dialog { property var tableModel: [] property int selectedRow: -1 property int metadataEditRow: -1 + readonly property string masterTypeFieldText: { + if (metadataEditRow < 0) return ""; + const rec = tableModel[metadataEditRow]; + if (!rec) return ""; + return rec.masterType ?? ""; + } function openMetadataEditor(row) { metadataEditRow = row; @@ -34,8 +40,9 @@ Dialog { waferField.text = rec.wafer ?? ""; dateField.text = rec.date ?? ""; chamberField.text = rec.chamber ?? ""; - notesField.text = rec.notes ?? ""; - selectedField.checked = rec.selected ?? false; + if (!chamberField.text && settingsModel.chamberId) + chamberField.text = settingsModel.chamberId; + notesField.text = rec.notes ?? ""; filePathLabel.text = rec.fileName ?? ""; metadataEditDialog.open(); } @@ -48,26 +55,43 @@ Dialog { metadataEditDialog.close(); return; } - file_browser.saveMetadata(rec.fileName ?? "", waferField.text, dateField.text, chamberField.text, notesField.text, selectedField.checked); + file_browser.saveMetadata(rec.fileName ?? "", waferField.text, dateField.text, chamberField.text, notesField.text, false, ""); metadataEditDialog.close(); metadataEditRow = -1; } - readonly property var headerTitles: ["", "Wafer", "Date", "Chamber", "Notes", "File", "Edit", "Save"] - readonly property var normalizedRows: (tableModel || []).map(function (row) { - row = row || {}; - return { - select: row.selected ?? false, - wafer: row.wafer ?? "", - date: row.date ?? "", - chamber: row.chamber ?? "", - edit: "", - save: "", - notes: row.notes ?? "", - fileName: row.fileName ?? "", - highlight: row.highlight ?? false - }; - }) + readonly property var headerTitles: ["Master", "Wafer", "Date", "Chamber", "Notes", "File", "Edit"] + // Build a path→family reverse map from settingsModel.masters. + // settingsModel is a QML context property; accessing it here makes the + // binding reactive — any mastersChanged signal re-evaluates normalizedRows. + function masterFamilyForPath(filePath) { + const m = settingsModel.masters; + for (var fam in m) { + if (m[fam] && m[fam] === filePath) + return fam; + } + return ""; + } + + readonly property var normalizedRows: { + // Touch settingsModel.masters so QML tracks this dependency. + const _ = settingsModel.masters; + return (tableModel || []).map(function(row) { + row = row || {}; + // settingsModel is the authoritative source; fall back to sidecar masterType. + const masterType = root.masterFamilyForPath(row.fileName ?? "") || row.masterType || ""; + return { + masterType: masterType, + wafer: row.wafer ?? "", + date: row.date ?? "", + chamber: row.chamber ?? "", + edit: "", + notes: row.notes ?? "", + fileName: row.fileName ?? "", + highlight: row.highlight ?? false + }; + }); + } // ===== Reusable Controls ===== component DialogActionButton: Button { @@ -234,27 +258,26 @@ Dialog { flickableDirection: Flickable.VerticalFlick columnWidthProvider: function (col) { - // [select, wafer, date, chamber, notes, file (variable), edit, save] + // [master, wafer, date, chamber, notes, file (variable), edit] const fixed = { - 0: 40, + 0: 48, 1: 90, 2: 170, 3: 120, 4: 180, - 6: 56, - 7: 56 + 6: 56 }; - if (fixed.hasOwnProperty(col)) + if (col in fixed) return fixed[col]; // col 5 (File) takes remaining width const w = Math.max(400, tableView.width); - const used = 40 + 90 + 170 + 120 + 180 + 56 + 56; + const used = 48 + 90 + 170 + 120 + 180 + 56; return Math.max(120, w - used); } model: TableModel { TableModelColumn { - display: "select" + display: "masterType" } TableModelColumn { display: "wafer" @@ -274,9 +297,6 @@ Dialog { TableModelColumn { display: "edit" } - TableModelColumn { - display: "save" - } rows: root.normalizedRows } @@ -296,16 +316,24 @@ Dialog { return row % 2 === 0 ? Theme.cardBackground : Theme.tone100; } - // Checkbox (col 0) + // Master type indicator (col 0) + // Reads normalizedRows (which merges settingsModel.masters + sidecar). Loader { anchors.fill: parent active: column === 0 - sourceComponent: CheckBox { - anchors.centerIn: parent - checked: root.tableModel[row]?.selected ?? false - onCheckedChanged: { - if (root.tableModel[row]) - root.tableModel[row].selected = checked; + sourceComponent: Text { + anchors.fill: parent + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + text: { + const mt = root.normalizedRows[row]?.masterType ?? ""; + return mt || "—"; + } + font.pixelSize: 14 + font.bold: true + color: { + const mt = root.normalizedRows[row]?.masterType ?? ""; + return mt ? Theme.primaryAccent : Theme.fieldPlaceholder; } } } @@ -338,39 +366,6 @@ Dialog { } } - // Save button (col 7) - Loader { - anchors.fill: parent - anchors.margins: 4 - active: column === 7 - sourceComponent: Button { - hoverEnabled: true - text: "Save" - font.pixelSize: 12 - onClicked: { - const record = root.tableModel[row]; - if (!record) - return; - file_browser.saveMetadata(record.fileName ?? "", record.wafer ?? "", record.date ?? "", record.chamber ?? "", record.notes ?? "", record.selected ?? false); - } - - background: Rectangle { - radius: Theme.radiusXs - color: parent.down ? Theme.buttonNeutralPressed : parent.hovered ? Theme.buttonNeutralHover : Theme.buttonNeutralBackground - border.width: Theme.borderThin - border.color: Theme.fieldBorder - } - - contentItem: Text { - text: parent.text - color: Theme.buttonNeutralText - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - font.pixelSize: 12 - } - } - } - // Text columns: Wafer (1), Date (2), File (5) Loader { anchors.fill: parent @@ -386,8 +381,10 @@ Dialog { return record.wafer ?? ""; if (column === 2) return record.date ?? ""; - if (column === 5) - return record.fileName ?? ""; + if (column === 5) { + const p = record.fileName ?? ""; + return p.split("/").pop(); + } return ""; } elide: Text.ElideRight @@ -417,9 +414,9 @@ Dialog { } } - MouseArea { + MouseArea { anchors.fill: parent - enabled: column !== 0 && column !== 6 && column !== 7 + enabled: column !== 6 onClicked: { root.selectedRow = row; root.selectedPath = root.tableModel[row]?.fileName ?? ""; @@ -442,12 +439,6 @@ Dialog { } } - DialogActionButton { - text: "Cancel" - Layout.preferredWidth: 90 - onClicked: root.close() - } - Rectangle { Layout.fillWidth: true Layout.preferredHeight: 32 @@ -477,7 +468,7 @@ Dialog { id: metadataEditDialog parent: Overlay.overlay modal: true - title: qsTr("Edit File Information") + title: qsTr("Edit Metadata") width: 520 height: 520 padding: 16 @@ -527,12 +518,14 @@ Dialog { text: qsTr("File") font.bold: true color: Theme.headingColor + Layout.topMargin: 8 } Text { id: filePathLabel Layout.fillWidth: true Layout.maximumHeight: 56 + Layout.bottomMargin: 16 wrapMode: Text.WrapAnywhere maximumLineCount: 3 elide: Text.ElideRight @@ -580,14 +573,10 @@ Dialog { Layout.preferredHeight: 36 } - CheckBox { - id: selectedField - text: qsTr("Selected for processing") - } - RowLayout { Layout.fillWidth: true - Layout.topMargin: 8 + Layout.topMargin: 16 + Layout.bottomMargin: 16 spacing: 8 Item { diff --git a/ISC/Tabs/SettingsTab.qml b/ISC/Tabs/SettingsTab.qml index 4ad4158..4d35d49 100644 --- a/ISC/Tabs/SettingsTab.qml +++ b/ISC/Tabs/SettingsTab.qml @@ -23,8 +23,7 @@ Item { } function handleCsvSelected(filePath) { - console.log("Doing work with:", filePath); - // @todo: implement CSV metadata handling after file selection. + // Selection confirmed — metadata editing is handled inline inside SelectFileDialog. } // ===== Settings Data Helpers ===== @@ -136,7 +135,7 @@ Item { title: "Choose Master CSV" nameFilters: ["CSV files (*.csv)"] property string targetFamily: "" - onAccepted: settingsModel.setMaster(targetFamily, selectedFile.toLocalFile()) + onAccepted: settingsModel.setMaster(targetFamily, String(selectedFile).replace(/^file:\/\//, "")) } // ===== Settings Page Layout ===== @@ -206,7 +205,6 @@ Item { Layout.minimumWidth: Theme.settingsFieldMinWidth placeholderText: "Enter chamber ID" text: settingsModel.chamberId - onEditingFinished: settingsModel.setChamberId(text) Connections { target: settingsModel @@ -222,7 +220,10 @@ Item { text: "Set" Layout.preferredWidth: 90 Layout.preferredHeight: Theme.settingsButtonHeight - onClicked: settingsModel.setChamberId(chamberField.text) + onClicked: { + settingsModel.setChamberId(chamberField.text); + settingsModel.saveSettings(); + } } } } @@ -389,6 +390,11 @@ Item { Layout.fillWidth: true } } + + // Bottom spacer so last group isn't flush with scroll edge + Item { + Layout.preferredHeight: Theme.settingsSectionSpacing + } } } @@ -406,7 +412,7 @@ Item { } GradientStop { position: 1.0 - color: Qt.transparent + color: Qt.rgba(0, 0, 0, 0) } } diff --git a/ISC/Tabs/qmldir b/ISC/Tabs/qmldir index b3dfc04..ad1389f 100644 --- a/ISC/Tabs/qmldir +++ b/ISC/Tabs/qmldir @@ -3,6 +3,3 @@ module ISC.Tabs # ===== Tab Components ===== SettingsTab 1.0 SettingsTab.qml - -# ===== Local Python Helpers ===== -local_settings 1.0 local_settings.py