diff --git a/crates/qbz-qt/qml/shell/AppShell.qml b/crates/qbz-qt/qml/shell/AppShell.qml index 9f9806163..885c04551 100644 --- a/crates/qbz-qt/qml/shell/AppShell.qml +++ b/crates/qbz-qt/qml/shell/AppShell.qml @@ -244,10 +244,11 @@ Rectangle { // in-view QML JS (library_bulk.rs:8: "select-all / clear never reach // Rust"), so the QbzShell signals route to the mounted view's // duck-typed interface: selectAll() / exitMultiSelectMode() / - // multiSelectOn. Implemented by LibraryView, LocalLibraryView and - // LocalAlbumView (MyQbzDetailView is EXIT-ONLY — its selection lives in - // Rust with no select-all arm); views without multi-select (Artist, - // Playlist, Mix, Label, Offline) match nothing — PARITY-DEBT (K4). + // multiSelectOn. Implemented by every view with a multi-select list: + // Library, Local Library, Local Album, Album, Artist, Playlist, Mix, + // Label and the Offline manager. MyQbzDetailView is EXIT-ONLY — its + // selection lives in Rust and its bar has no select-all arm (the Slint + // never had one there either). Connections { target: QbzShell function onSelectAllRequested() { diff --git a/crates/qbz-qt/qml/views/MixView.qml b/crates/qbz-qt/qml/views/MixView.qml index 294fbd1dd..a936422f3 100644 --- a/crates/qbz-qt/qml/views/MixView.qml +++ b/crates/qbz-qt/qml/views/MixView.qml @@ -124,7 +124,10 @@ Rectangle { if (action !== "add-to-playlist" && action !== "add-to-mixtape") root.selected = ({}) } - // Ctrl+A / Escape hotkey seam (AppShell duck-types these). + // Ctrl+A / Escape hotkey seam (AppShell duck-types these). Without + // `multiSelectOn` the Escape stack never saw this view in select mode, so + // Escape did not leave it here while it did on every other track list. + readonly property bool multiSelectOn: root.multiSelect function selectAll() { if (!root.multiSelect) root.setMultiSelect(true) root.bulkAction("select-all") diff --git a/crates/qbz-qt/qml/views/OfflineManagerView.qml b/crates/qbz-qt/qml/views/OfflineManagerView.qml index 1c71de716..952f80d15 100644 --- a/crates/qbz-qt/qml/views/OfflineManagerView.qml +++ b/crates/qbz-qt/qml/views/OfflineManagerView.qml @@ -119,6 +119,18 @@ Rectangle { mods === undefined ? Qt.NoModifier : mods) } + // Ctrl+A / Escape hotkey seam (AppShell duck-types these). The selection + // here is always on (no select mode), so Ctrl+A ticks every track — as + // the Slint's select_all_active_surface did for this view — and Escape + // drops a non-empty selection. + readonly property bool multiSelectOn: Object.keys(root.selected).length > 0 + function selectAll() { + root.bulkAction("select-all") + } + function exitMultiSelectMode() { + root.bulkAction("clear") + } + function bulkAction(id) { if (id === "clear") { root.selected = ({})