From bc94d8ae3b83fa3ac5463bd29a454fc4ca4d60a8 Mon Sep 17 00:00:00 2001 From: AlanRockefeller Date: Fri, 10 Apr 2026 20:58:14 -0700 Subject: [PATCH 1/3] Redo sort menu --- .gitignore | 2 + faststack/qml/Main.qml | 162 +++++++++++++++++++++++++++-------------- 2 files changed, 111 insertions(+), 53 deletions(-) diff --git a/.gitignore b/.gitignore index 0b985ab..975488b 100644 --- a/.gitignore +++ b/.gitignore @@ -94,3 +94,5 @@ test_image* **/*fail*.txt **/*final*.txt green.txt + +OpenFocus/ diff --git a/faststack/qml/Main.qml b/faststack/qml/Main.qml index 4d1a283..c6b3da7 100644 --- a/faststack/qml/Main.qml +++ b/faststack/qml/Main.qml @@ -909,23 +909,55 @@ ApplicationWindow { } ItemDelegate { + id: sortPhotosLauncher width: 220 height: 36 - text: "Sort: Default" + hoverEnabled: true + background: Rectangle { + color: parent.hovered ? (root.isDarkTheme ? "#555555" : "#e0e0e0") : "transparent" + } + contentItem: Item { + Text { + anchors.left: parent.left + anchors.leftMargin: 10 + anchors.verticalCenter: parent.verticalCenter + text: "Sort Photos" + color: root.currentTextColor + verticalAlignment: Text.AlignVCenter + } + Text { + anchors.right: parent.right + anchors.rightMargin: 10 + anchors.verticalCenter: parent.verticalCenter + text: "\u25B6" // Right-pointing triangle + font.pixelSize: 10 + color: root.currentTextColor + opacity: 0.6 + verticalAlignment: Text.AlignVCenter + } + } + onHoveredChanged: { + if (hovered) { + sortSubMenu.popup(sortPhotosLauncher, sortPhotosLauncher.width - 4, 0) + } + } + } + + // Clear Filename Filter (from old Main.qml) + ItemDelegate { + width: 220 + height: 36 + text: "Clear Filename Filter" onClicked: { - if (controller) controller.set_sort_mode("default") + if (controller) controller.clear_filter() actionsMenu.close() } background: Rectangle { - color: parent.hovered ? (root.isDarkTheme ? "#555555" : "#e0e0e0") - : ((uiState && uiState.sortMode === "default") - ? (root.isDarkTheme ? "#505050" : "#d0ffd0") - : "transparent") + color: parent.hovered ? (root.isDarkTheme ? "#555555" : "#e0e0e0") : "transparent" } contentItem: Text { text: parent.text color: root.currentTextColor - font.bold: uiState && uiState.sortMode === "default" verticalAlignment: Text.AlignVCenter leftPadding: 10 } @@ -933,21 +965,17 @@ ApplicationWindow { ItemDelegate { width: 220 height: 36 - text: "Sort: By Filename" + text: "Add Favorites to Batch" onClicked: { - if (controller) controller.set_sort_mode("filename") + if (uiState) uiState.addFavoritesToBatch() actionsMenu.close() } background: Rectangle { - color: parent.hovered ? (root.isDarkTheme ? "#555555" : "#e0e0e0") - : ((uiState && uiState.sortMode === "filename") - ? (root.isDarkTheme ? "#505050" : "#d0ffd0") - : "transparent") + color: parent.hovered ? (root.isDarkTheme ? "#555555" : "#e0e0e0") : "transparent" } contentItem: Text { text: parent.text color: root.currentTextColor - font.bold: uiState && uiState.sortMode === "filename" verticalAlignment: Text.AlignVCenter leftPadding: 10 } @@ -955,33 +983,27 @@ ApplicationWindow { ItemDelegate { width: 220 height: 36 - text: "Sort: By Date (Newest)" + text: "Add Uploaded to Batch" onClicked: { - if (controller) controller.set_sort_mode("date") + if (uiState) uiState.addUploadedToBatch() actionsMenu.close() } background: Rectangle { - color: parent.hovered ? (root.isDarkTheme ? "#555555" : "#e0e0e0") - : ((uiState && uiState.sortMode === "date") - ? (root.isDarkTheme ? "#505050" : "#d0ffd0") - : "transparent") + color: parent.hovered ? (root.isDarkTheme ? "#555555" : "#e0e0e0") : "transparent" } contentItem: Text { text: parent.text color: root.currentTextColor - font.bold: uiState && uiState.sortMode === "date" verticalAlignment: Text.AlignVCenter leftPadding: 10 } } - - // Clear Filename Filter (from old Main.qml) ItemDelegate { width: 220 height: 36 - text: "Clear Filename Filter" + text: "Jump to Last Uploaded" onClicked: { - if (controller) controller.clear_filter() + if (uiState) uiState.jumpToLastUploaded() actionsMenu.close() } background: Rectangle { @@ -997,9 +1019,9 @@ ApplicationWindow { ItemDelegate { width: 220 height: 36 - text: "Add Favorites to Batch" + text: "Auto-Level Batch" onClicked: { - if (uiState) uiState.addFavoritesToBatch() + if (uiState) uiState.batchAutoLevels() actionsMenu.close() } background: Rectangle { @@ -1015,9 +1037,10 @@ ApplicationWindow { ItemDelegate { width: 220 height: 36 - text: "Add Uploaded to Batch" + text: "Stack Source RAWs" + enabled: uiState ? uiState.isStackedJpg : false onClicked: { - if (uiState) uiState.addUploadedToBatch() + if (uiState) uiState.stack_source_raws(); actionsMenu.close() } background: Rectangle { @@ -1030,12 +1053,21 @@ ApplicationWindow { leftPadding: 10 } } + + // Separator before grid view toggle + Rectangle { + width: 220 + height: 1 + color: root.isDarkTheme ? "#666666" : "#cccccc" + } + + // Toggle Grid/Loupe View ItemDelegate { width: 220 height: 36 - text: "Jump to Last Uploaded" + text: uiState && uiState.isGridViewActive ? "Single Image View" : "Thumbnail View" onClicked: { - if (uiState) uiState.jumpToLastUploaded() + if (uiState) uiState.toggleGridView(); actionsMenu.close() } background: Rectangle { @@ -1048,66 +1080,90 @@ ApplicationWindow { leftPadding: 10 } } + } + } + + Menu { + id: sortSubMenu + parent: Overlay.overlay + implicitWidth: 180 + + background: Rectangle { + implicitWidth: 180 + implicitHeight: sortSubMenuColumn.implicitHeight + color: root.currentBackgroundColor + border.color: root.isDarkTheme ? "#666666" : "#cccccc" + radius: 4 + } + + contentItem: Column { + id: sortSubMenuColumn + ItemDelegate { - width: 220 + width: 180 height: 36 - text: "Auto-Level Batch" + text: "Default" onClicked: { - if (uiState) uiState.batchAutoLevels() + if (controller) controller.set_sort_mode("default") + sortSubMenu.close() actionsMenu.close() } background: Rectangle { - color: parent.hovered ? (root.isDarkTheme ? "#555555" : "#e0e0e0") : "transparent" + color: parent.hovered ? (root.isDarkTheme ? "#555555" : "#e0e0e0") + : ((uiState && uiState.sortMode === "default") + ? (root.isDarkTheme ? "#505050" : "#d0ffd0") + : "transparent") } contentItem: Text { text: parent.text color: root.currentTextColor + font.bold: uiState && uiState.sortMode === "default" verticalAlignment: Text.AlignVCenter leftPadding: 10 } } ItemDelegate { - width: 220 + width: 180 height: 36 - text: "Stack Source RAWs" - enabled: uiState ? uiState.isStackedJpg : false + text: "By Filename" onClicked: { - if (uiState) uiState.stack_source_raws(); + if (controller) controller.set_sort_mode("filename") + sortSubMenu.close() actionsMenu.close() } background: Rectangle { - color: parent.hovered ? (root.isDarkTheme ? "#555555" : "#e0e0e0") : "transparent" + color: parent.hovered ? (root.isDarkTheme ? "#555555" : "#e0e0e0") + : ((uiState && uiState.sortMode === "filename") + ? (root.isDarkTheme ? "#505050" : "#d0ffd0") + : "transparent") } contentItem: Text { text: parent.text color: root.currentTextColor + font.bold: uiState && uiState.sortMode === "filename" verticalAlignment: Text.AlignVCenter leftPadding: 10 } } - - // Separator before grid view toggle - Rectangle { - width: 220 - height: 1 - color: root.isDarkTheme ? "#666666" : "#cccccc" - } - - // Toggle Grid/Loupe View ItemDelegate { - width: 220 + width: 180 height: 36 - text: uiState && uiState.isGridViewActive ? "Single Image View" : "Thumbnail View" + text: "By Date" onClicked: { - if (uiState) uiState.toggleGridView(); + if (controller) controller.set_sort_mode("date") + sortSubMenu.close() actionsMenu.close() } background: Rectangle { - color: parent.hovered ? (root.isDarkTheme ? "#555555" : "#e0e0e0") : "transparent" + color: parent.hovered ? (root.isDarkTheme ? "#555555" : "#e0e0e0") + : ((uiState && uiState.sortMode === "date") + ? (root.isDarkTheme ? "#505050" : "#d0ffd0") + : "transparent") } contentItem: Text { text: parent.text color: root.currentTextColor + font.bold: uiState && uiState.sortMode === "date" verticalAlignment: Text.AlignVCenter leftPadding: 10 } From 57bb2f4fa8c940763672b72090119cec8ce1f651 Mon Sep 17 00:00:00 2001 From: AlanRockefeller Date: Fri, 10 Apr 2026 20:59:41 -0700 Subject: [PATCH 2/3] format with black --- faststack/app.py | 7 +++---- lightroom-catalog-import/inspect_lrcat_photo.py | 6 ++---- lightroom-catalog-import/lrcat_diff.py | 6 ++---- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/faststack/app.py b/faststack/app.py index 3daf36a..7d7d21b 100644 --- a/faststack/app.py +++ b/faststack/app.py @@ -101,7 +101,6 @@ UIStateRestoration, ) - # AWB thresholds on the -1..+1 normalised slider range. # NOOP: skip applying correction entirely (≈ 0.64 Lab units — below perceptible). # LABEL: below this the direction word becomes "neutral" in the status message. @@ -5347,9 +5346,9 @@ def undo_delete(self): if action_type == "delete": try: - (jpg_pair, raw_pair) = action_data - (jpg_src, jpg_bin) = jpg_pair - (raw_src, raw_bin) = raw_pair + jpg_pair, raw_pair = action_data + jpg_src, jpg_bin = jpg_pair + raw_src, raw_bin = raw_pair except Exception: self.update_status_message("Undo failed: unexpected undo record format") log.exception("Unexpected undo record format: %r", action_data) diff --git a/lightroom-catalog-import/inspect_lrcat_photo.py b/lightroom-catalog-import/inspect_lrcat_photo.py index eac9ce9..c620b2b 100644 --- a/lightroom-catalog-import/inspect_lrcat_photo.py +++ b/lightroom-catalog-import/inspect_lrcat_photo.py @@ -69,15 +69,13 @@ def connect_ro(path: str) -> sqlite3.Connection: def get_tables(conn: sqlite3.Connection) -> list[str]: """Return all user table names in the database, sorted.""" - rows = conn.execute( - """ + rows = conn.execute(""" SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name - """ - ).fetchall() + """).fetchall() return [row["name"] for row in rows] diff --git a/lightroom-catalog-import/lrcat_diff.py b/lightroom-catalog-import/lrcat_diff.py index 53adfe5..21dd107 100644 --- a/lightroom-catalog-import/lrcat_diff.py +++ b/lightroom-catalog-import/lrcat_diff.py @@ -81,14 +81,12 @@ def connect_ro(path: str) -> sqlite3.Connection: def get_tables(conn: sqlite3.Connection) -> set[str]: """Return all user table names in the database.""" - rows = conn.execute( - """ + rows = conn.execute(""" SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%' - """ - ).fetchall() + """).fetchall() return {row["name"] for row in rows} From 1e74bd8d012f9c0ac2fc2008dc748130174e9c92 Mon Sep 17 00:00:00 2001 From: AlanRockefeller Date: Fri, 10 Apr 2026 22:08:20 -0700 Subject: [PATCH 3/3] Fix sort menu --- faststack/qml/Main.qml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/faststack/qml/Main.qml b/faststack/qml/Main.qml index c6b3da7..0bc176f 100644 --- a/faststack/qml/Main.qml +++ b/faststack/qml/Main.qml @@ -732,6 +732,7 @@ ApplicationWindow { id: actionsMenu parent: Overlay.overlay implicitWidth: 220 + onClosed: sortSubMenu.close() background: Rectangle { implicitWidth: 220 @@ -755,7 +756,7 @@ ApplicationWindow { actionsMenu.close() } background: Rectangle { - color: parent.hovered ? (root.isDarkTheme ? "#555555" : "#e0e0e0") : "transparent" + color: (parent.enabled && parent.hovered) ? (root.isDarkTheme ? "#555555" : "#e0e0e0") : "transparent" } contentItem: Text { text: parent.text @@ -941,6 +942,13 @@ ApplicationWindow { sortSubMenu.popup(sortPhotosLauncher, sortPhotosLauncher.width - 4, 0) } } + onClicked: { + sortSubMenu.popup(sortPhotosLauncher, sortPhotosLauncher.width - 4, 0) + } + // Ensure keyboard activation works reliably + Keys.onReturnPressed: clicked() + Keys.onEnterPressed: clicked() + Keys.onSpacePressed: clicked() } // Clear Filename Filter (from old Main.qml) @@ -1044,11 +1052,12 @@ ApplicationWindow { actionsMenu.close() } background: Rectangle { - color: parent.hovered ? (root.isDarkTheme ? "#555555" : "#e0e0e0") : "transparent" + color: (parent.enabled && parent.hovered) ? (root.isDarkTheme ? "#555555" : "#e0e0e0") : "transparent" } contentItem: Text { text: parent.text - color: root.currentTextColor + color: parent.enabled ? root.currentTextColor : (root.isDarkTheme ? "#666666" : "#999999") + opacity: parent.enabled ? 1.0 : 0.6 verticalAlignment: Text.AlignVCenter leftPadding: 10 }