From cf3069386bd19490a9a58617c6d4c60c3b26ee15 Mon Sep 17 00:00:00 2001 From: vicrodh <103399283+vicrodh@users.noreply.github.com> Date: Mon, 14 Sep 2026 10:31:40 -0600 Subject: [PATCH] feat(qt): Shift ranges in the library folders settings table A row or checkbox click toggled one folder. Shift now adds the run over the rows the filter shows, Ctrl adds one, and the ids stay numbers for the removal action. cc --- .../qml/settings/LibraryFolderTable.qml | 30 +++++++++++++++---- scripts/qml-tests/tst_multi_select.qml | 23 ++++++++++++++ 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/crates/qbz-qt/qml/settings/LibraryFolderTable.qml b/crates/qbz-qt/qml/settings/LibraryFolderTable.qml index 08dc5c00e..6375399b2 100644 --- a/crates/qbz-qt/qml/settings/LibraryFolderTable.qml +++ b/crates/qbz-qt/qml/settings/LibraryFolderTable.qml @@ -42,10 +42,23 @@ Column { }) } function isSelected(id) { return selectedIds.indexOf(id) >= 0 } - function toggleSelected(id) { - const next = selectedIds.slice() - const at = next.indexOf(id) - if (at >= 0) next.splice(at, 1); else next.push(id) + /// A plain or Ctrl click toggles one folder; Shift adds the range from the + /// last plain click over the rows SHOWN (the filter is a view filter) — + /// the rule every multi-select list shares (controls/SelectionModel.qml). + SelectionModel { id: folderSel } + function toggleSelected(id, mods) { + const rows = root.shown() + const current = {} + for (let i = 0; i < selectedIds.length; i++) + current[String(selectedIds[i])] = true + const picked = folderSel.next(current, id, rows, + mods === undefined ? Qt.NoModifier : mods) + // Back to the ids themselves (the removal action takes them as + // numbers), keeping earlier picks the filter currently hides. + const next = selectedIds.filter(function (sid) { return picked[String(sid)] === true }) + for (let j = 0; j < rows.length; j++) + if (picked[String(rows[j].id)] === true && next.indexOf(rows[j].id) < 0) + next.push(rows[j].id) selectedIds = next } function scanLabel(ts) { @@ -118,6 +131,7 @@ Column { QbzBridge.settingsString("library-remove-folders", JSON.stringify(root.selectedIds)) root.selectedIds = [] + folderSel.anchorId = "" } } } @@ -279,7 +293,9 @@ Column { anchors.fill: parent hoverEnabled: true cursorShape: Qt.PointingHandCursor - onClicked: root.toggleSelected(folderRow.modelData.id) + onClicked: function (mouse) { + root.toggleSelected(folderRow.modelData.id, mouse.modifiers) + } } Row { @@ -292,7 +308,9 @@ Column { width: root.kioskHost ? 44 : 20 anchors.verticalCenter: parent.verticalCenter checked: root.isSelected(folderRow.modelData.id) - onToggled: root.toggleSelected(folderRow.modelData.id) + onToggled: function (mods) { + root.toggleSelected(folderRow.modelData.id, mods) + } } // FOLDER: type glyph + name. Row { diff --git a/scripts/qml-tests/tst_multi_select.qml b/scripts/qml-tests/tst_multi_select.qml index d63370c59..7b353011a 100644 --- a/scripts/qml-tests/tst_multi_select.qml +++ b/scripts/qml-tests/tst_multi_select.qml @@ -13,6 +13,7 @@ import "../../crates/qbz-qt/qml/cards" import "../../crates/qbz-qt/qml/views" as Views import "../../crates/qbz-qt/qml/views/local" as Local import "../../crates/qbz-qt/qml/views/myqbz" as MyQbz +import "../../crates/qbz-qt/qml/settings" as Settings Item { id: root @@ -156,6 +157,18 @@ Item { view: railView } + // ---- Settings > Local Library folders --------------------------------------- + Settings.LibraryFolderTable { + id: folderTable + x: 0; y: 880 + width: 1200 + lib: ({ "folders": [1, 2, 3, 4, 5].map(function (n) { + return { "id": n, "displayName": "Music " + n, "path": "/music/" + n, + "isNetwork": false, "enabled": true, "accessible": true, + "status": "active", "lastScan": 0 } + }) }) + } + TestCase { name: "MultiSelect" when: windowShown @@ -225,6 +238,7 @@ Item { QbzLocal.treeCalls = [] railView.opened = [] railView.treeSelectMode = true + folderTable.selectedIds = [] } // A point of the row with nothing drawn over it but the body: the @@ -376,6 +390,15 @@ Item { clickOn(railCheck("/m/b"), 6, 6, Qt.ShiftModifier) compare(QbzLocal.treeCalls[3], "folder:/m/b") } + + function test_settings_folder_table_shift_range() { + var first = textItem(folderTable, "Music 1") + clickOn(first, 10, first.height / 2) + var fourth = textItem(folderTable, "Music 4") + clickOn(fourth, 10, fourth.height / 2, Qt.ShiftModifier) + compare(folderTable.selectedIds.slice().sort().join(","), "1,2,3,4") + verify(folderTable.isSelected(2), "the numeric ids stay numbers") + } } // ---- the selection rule itself ---------------------------------------------