From e4113994dc8f134917f3f48a38ef6dd0eaf4df8b Mon Sep 17 00:00:00 2001 From: zach Date: Sun, 3 May 2026 18:09:55 +0200 Subject: [PATCH 1/3] start of rework --- .../Settings/Controls/SettingBarEntryList.qml | 405 ++++++++++-------- 1 file changed, 236 insertions(+), 169 deletions(-) diff --git a/Modules/Settings/Controls/SettingBarEntryList.qml b/Modules/Settings/Controls/SettingBarEntryList.qml index 8104d15..58e8801 100644 --- a/Modules/Settings/Controls/SettingBarEntryList.qml +++ b/Modules/Settings/Controls/SettingBarEntryList.qml @@ -11,87 +11,129 @@ import qs.Helpers Item { id: root + property var boxEntries: [[], [], []] property bool dragActive: false property real dragHeight: 0 + property real dragPointerStartX: 0 + property real dragPointerStartY: 0 property real dragStartX: 0 property real dragStartY: 0 property real dragX: 0 property real dragY: 0 - property var draggedModelData: null - property string draggedUid: "" + property int draggedBox: -1 + property int draggedIndex: -1 + property var draggedItemData: null property bool dropAnimating: false readonly property bool highlighted: SettingsHighlight.highlightedSetting === name required property string name required property var object - property var pendingCommitEntries: [] + property var pendingCommitBoxes: [] required property string setting - property int uidCounter: 0 - property var visualEntries: [] + property var spacerEntries: [] - function beginVisualDrag(uid, modelData, item) { + function beginVisualDrag(wrapper, item, pointerX, pointerY) { const pos = item.mapToItem(root, 0, 0); + const loc = root.locateEntry(wrapper.entry); + + root.draggedItemData = wrapper; + + if (loc) { + root.draggedBox = loc.box; + root.draggedIndex = loc.index; + } else { + root.draggedBox = -1; + root.draggedIndex = -1; + } - root.draggedUid = uid; - root.draggedModelData = modelData; root.dragHeight = item.height; root.dragStartX = pos.x; root.dragStartY = pos.y; + root.dragPointerStartX = pointerX; + root.dragPointerStartY = pointerY; root.dragX = pos.x; root.dragY = pos.y; root.dragActive = true; root.dropAnimating = false; - root.pendingCommitEntries = []; + root.pendingCommitBoxes = []; } - function commitVisualOrder(entries) { - const list = []; + function cloneAndUpdateEnabled(entry, value) { + const list = root.object[root.setting].slice(); - for (let i = 0; i < entries.length; i++) - list.push(entries[i].entry); + for (let i = 0; i < list.length; i++) { + if (list[i] === entry) { + list[i] = { + id: list[i].id, + enabled: value + }; + break; + } + } root.object[root.setting] = list; Config.save(); - root.rebuildVisualEntries(); + root.rebuildBoxEntries(); + } + + function commitBoxEntries(boxes) { + const spacers = root.spacerEntries.length === 2 ? root.spacerEntries : (root.object[root.setting] ?? []).filter(e => root.isSpacer(e)); + + const next = []; + next.push(...boxes[0].map(w => w.entry)); + next.push(spacers[0]); + next.push(...boxes[1].map(w => w.entry)); + next.push(spacers[1]); + next.push(...boxes[2].map(w => w.entry)); + + root.object[root.setting] = next; + Config.save(); + root.rebuildBoxEntries(); } function endVisualDrag() { - const entries = root.visualEntries.slice(); - const finalIndex = root.indexForUid(root.draggedUid); - const finalItem = listView.itemAtIndex(finalIndex); + if (!root.draggedItemData) + return; + + const boxes = root.boxEntries.map(box => box.slice()); + const loc = root.locateEntry(root.draggedItemData.entry); root.dragActive = false; - if (!finalItem) { - root.pendingCommitEntries = entries; + if (!loc) { + root.pendingCommitBoxes = boxes; root.finishVisualDrag(); return; } - const pos = finalItem.mapToItem(root, 0, 0); + const view = [boxView0, boxView1, boxView2][loc.box]; + const item = view ? view.itemAtIndex(loc.index) : null; - root.pendingCommitEntries = entries; + root.pendingCommitBoxes = boxes; + + if (!item) { + root.finishVisualDrag(); + return; + } + + const pos = item.mapToItem(root, 0, 0); root.dropAnimating = true; settleX.to = pos.x; settleY.to = pos.y; settleAnim.start(); } - function ensureVisualEntries() { - if (!root.dragActive && !root.dropAnimating) - root.rebuildVisualEntries(); - } - function finishVisualDrag() { - const entries = root.pendingCommitEntries.slice(); + const boxes = root.pendingCommitBoxes.slice(); root.dragActive = false; root.dropAnimating = false; - root.draggedUid = ""; - root.draggedModelData = null; - root.pendingCommitEntries = []; + root.draggedItemData = null; + root.draggedBox = -1; + root.draggedIndex = -1; + root.pendingCommitBoxes = []; root.dragHeight = 0; - root.commitVisualOrder(entries); + root.commitBoxEntries(boxes); } function iconForId(id) { @@ -122,18 +164,15 @@ Item { return "schedule"; case "notifBell": return "notifications"; + case "hyprsunset": + return "wb_twilight"; default: return "drag_indicator"; } } - function indexForUid(uid) { - for (let i = 0; i < root.visualEntries.length; i++) { - if (root.visualEntries[i].uid === uid) - return i; - } - - return -1; + function isSpacer(entry) { + return entry && entry.id === "spacer"; } function labelForId(id) { @@ -164,74 +203,101 @@ Item { return qsTr("Clock"); case "notifBell": return qsTr("Notification bell"); + case "hyprsunset": + return qsTr("Sunset"); default: return id; } } + function locateEntry(entry) { + for (let b = 0; b < root.boxEntries.length; b++) { + for (let i = 0; i < root.boxEntries[b].length; i++) { + if (root.boxEntries[b][i].entry === entry) { + return { + box: b, + index: i + }; + } + } + } + + return null; + } + function moveArrayItem(list, from, to) { const next = list.slice(); - const [item] = next.splice(from, 1); + const item = next.splice(from, 1)[0]; next.splice(to, 0, item); return next; } - function previewVisualMove(from, hovered, before) { - let to = hovered + (before ? 0 : 1); + function previewMoveToBox(sourceEntry, targetBox, targetIndex, before) { + const current = root.boxEntries.map(box => box.slice()); + const loc = root.locateEntry(sourceEntry); - if (to > from) - to -= 1; - - to = Math.max(0, Math.min(visualModel.items.count - 1, to)); - - if (from === to) + if (!loc) return; - visualModel.items.move(from, to); - root.visualEntries = root.moveArrayItem(root.visualEntries, from, to); + const moved = current[loc.box].splice(loc.index, 1)[0]; + + let insertAt = targetIndex + (before ? 0 : 1); + + if (loc.box === targetBox && insertAt > loc.index) + insertAt -= 1; + + insertAt = Math.max(0, Math.min(current[targetBox].length, insertAt)); + current[targetBox].splice(insertAt, 0, moved); + + root.boxEntries = current; } - function rebuildVisualEntries() { - const entries = root.object[root.setting] ?? []; - const next = []; + function rebuildBoxEntries() { + const list = root.object[root.setting] ?? []; + const next = [[], [], []]; + const spacers = []; + let box = 0; - for (let i = 0; i < entries.length; i++) { - const entry = entries[i]; - let existing = null; + for (let i = 0; i < list.length; i++) { + const entry = list[i]; - for (let j = 0; j < root.visualEntries.length; j++) { - if (root.visualEntries[j].entry === entry) { - existing = root.visualEntries[j]; - break; - } + if (root.isSpacer(entry)) { + spacers.push(entry); + box = Math.min(2, box + 1); + continue; } - if (existing) - next.push(existing); - else - next.push({ - uid: `entry-${root.uidCounter++}`, - entry - }); + next[box].push({ + entry: entry + }); } - root.visualEntries = next; + root.spacerEntries = spacers; + root.boxEntries = next; } - function updateEntry(index, value) { - const list = [...root.object[root.setting]]; - const entry = list[index]; - entry.enabled = value; - list[index] = entry; + function updateEntry(entry, value) { + const list = root.object[root.setting].slice(); + + for (let i = 0; i < list.length; i++) { + if (list[i] === entry) { + list[i] = { + id: list[i].id, + enabled: value + }; + break; + } + } + root.object[root.setting] = list; Config.save(); - root.ensureVisualEntries(); + root.rebuildBoxEntries(); } Layout.fillWidth: true - implicitHeight: layout.implicitHeight + implicitHeight: mainLayout.implicitHeight - Component.onCompleted: root.rebuildVisualEntries() + Component.onCompleted: root.rebuildBoxEntries() Rectangle { anchors.fill: parent @@ -271,7 +337,7 @@ Item { } ColumnLayout { - id: layout + id: mainLayout anchors.fill: parent spacing: Appearance.spacing.smaller @@ -282,58 +348,64 @@ Item { text: root.name } - DelegateModel { - id: visualModel - - delegate: entryDelegate - - model: ScriptModel { - objectProp: "uid" - values: root.visualEntries - } - } - - ListView { - id: listView - + RowLayout { Layout.fillWidth: true - Layout.preferredHeight: contentHeight - boundsBehavior: Flickable.StopAtBounds - clip: false - implicitHeight: contentHeight - implicitWidth: width - interactive: !(root.dragActive || root.dropAnimating) - model: visualModel - spacing: Appearance.spacing.small + spacing: Appearance.spacing.normal - add: Transition { - Anim { - properties: "opacity,scale" - to: 1 + CustomRect { + Layout.fillWidth: true + Layout.preferredHeight: 260 + color: DynamicColors.tPalette.m3surface + radius: Appearance.rounding.normal + + ListView { + id: boxView0 + + anchors.fill: parent + anchors.margins: Appearance.padding.small + clip: false + delegate: entryDelegate + interactive: false + model: root.boxEntries[0] + spacing: Appearance.spacing.small } } - addDisplaced: Transition { - Anim { - duration: Appearance.anim.durations.normal - property: "y" + + CustomRect { + Layout.fillWidth: true + Layout.preferredHeight: 260 + color: DynamicColors.tPalette.m3surface + radius: Appearance.rounding.normal + + ListView { + id: boxView1 + + anchors.fill: parent + anchors.margins: Appearance.padding.small + clip: false + delegate: entryDelegate + interactive: false + model: root.boxEntries[1] + spacing: Appearance.spacing.small } } - displaced: Transition { - Anim { - duration: Appearance.anim.durations.normal - property: "y" - } - } - move: Transition { - Anim { - duration: Appearance.anim.durations.normal - property: "y" - } - } - removeDisplaced: Transition { - Anim { - duration: Appearance.anim.durations.normal - property: "y" + + CustomRect { + Layout.fillWidth: true + Layout.preferredHeight: 260 + color: DynamicColors.tPalette.m3surface + radius: Appearance.rounding.normal + + ListView { + id: boxView2 + + anchors.fill: parent + anchors.margins: Appearance.padding.small + clip: false + delegate: entryDelegate + interactive: false + model: root.boxEntries[2] + spacing: Appearance.spacing.small } } } @@ -344,21 +416,19 @@ Item { asynchronous: false sourceComponent: Item { + property real listWidth: boxView0.width + Drag.active: root.dragActive Drag.hotSpot.x: width / 2 Drag.hotSpot.y: height / 2 height: proxyRect.implicitHeight - implicitHeight: proxyRect.implicitHeight - implicitWidth: listView.width - visible: root.draggedModelData !== null - width: listView.width + width: listWidth x: root.dragX y: root.dragY z: 100 Drag.source: QtObject { - property string uid: root.draggedUid - property int visualIndex: root.indexForUid(root.draggedUid) + property var entry: root.draggedItemData ? root.draggedItemData.entry : null } CustomRect { @@ -393,17 +463,17 @@ Item { MaterialIcon { color: DynamicColors.palette.m3onSurfaceVariant - text: root.iconForId(root.draggedModelData?.entry?.id ?? "") + text: root.iconForId(root.draggedItemData?.entry?.id ?? "") } CustomText { Layout.fillWidth: true font.pointSize: Appearance.font.size.larger - text: root.labelForId(root.draggedModelData?.entry?.id ?? "") + text: root.labelForId(root.draggedItemData?.entry?.id ?? "") } CustomSwitch { - checked: root.draggedModelData?.entry?.enabled ?? true + checked: root.draggedItemData?.entry?.enabled ?? true enabled: false } } @@ -417,28 +487,23 @@ Item { DropArea { id: slot + readonly property int boxIndex: ListView.view === boxView0 ? 0 : ListView.view === boxView1 ? 1 : 2 readonly property var entryData: modelData.entry + required property int index required property var modelData - readonly property string uid: modelData.uid function previewReorder(drag) { const source = drag.source; - if (!source || !source.uid || source.uid === slot.uid) + if (!source || !source.entry || source.entry === slot.entryData) return; - const from = source.visualIndex; - const hovered = slot.DelegateModel.itemsIndex; - - if (from < 0 || hovered < 0) - return; - - root.previewVisualMove(from, hovered, drag.y < height / 2); + root.previewMoveToBox(source.entry, slot.boxIndex, slot.index, drag.y < height / 2); } height: entryRow.implicitHeight implicitHeight: entryRow.implicitHeight - implicitWidth: listView.width - width: ListView.view ? ListView.view.width : listView.width + implicitWidth: ListView.view ? ListView.view.width : 0 + width: ListView.view ? ListView.view.width : 0 onEntered: drag => previewReorder(drag) onPositionChanged: drag => previewReorder(drag) @@ -449,8 +514,7 @@ Item { anchors.fill: parent color: DynamicColors.tPalette.m3surface implicitHeight: entryLayout.implicitHeight + Appearance.padding.small * 2 - implicitWidth: parent.width - opacity: root.draggedUid === slot.uid ? 0 : 1 + opacity: root.draggedItemData?.entry === slot.entryData ? 0 : 1 radius: Appearance.rounding.full Behavior on opacity { @@ -468,7 +532,7 @@ Item { CustomRect { id: handle - color: Qt.alpha(DynamicColors.palette.m3onSurface, handleDrag.active ? 0.12 : handleHover.hovered ? 0.09 : 0.06) + color: Qt.alpha(DynamicColors.palette.m3onSurface, handleMouse.pressed ? 0.12 : handleMouse.containsMouse ? 0.09 : 0.06) implicitHeight: 32 implicitWidth: implicitHeight radius: Appearance.rounding.full @@ -484,34 +548,37 @@ Item { text: "drag_indicator" } - HoverHandler { - id: handleHover + MouseArea { + id: handleMouse - cursorShape: handleDrag.active ? Qt.ClosedHandCursor : Qt.OpenHandCursor - } + acceptedButtons: Qt.LeftButton + anchors.fill: parent + cursorShape: pressed ? Qt.ClosedHandCursor : containsMouse ? Qt.OpenHandCursor : Qt.ArrowCursor + hoverEnabled: true + preventStealing: true - DragHandler { - id: handleDrag - - enabled: true - grabPermissions: PointerHandler.CanTakeOverFromAnything - target: null - xAxis.enabled: false - yAxis.enabled: true - - onActiveChanged: { - if (active) { - root.beginVisualDrag(slot.uid, slot.modelData, entryRow); - } else if (root.draggedUid === slot.uid) { + onCanceled: { + if (root.draggedItemData && root.draggedItemData.entry === slot.entryData) root.endVisualDrag(); - } } - onActiveTranslationChanged: { - if (!active || root.draggedUid !== slot.uid) + onPositionChanged: mouse => { + if (!pressed || !root.dragActive || !root.draggedItemData || root.draggedItemData.entry !== slot.entryData) return; - root.dragX = root.dragStartX; - root.dragY = root.dragStartY + activeTranslation.y; + const pointer = handle.mapToItem(root, mouse.x, mouse.y); + const offsetX = root.dragPointerStartX - root.dragStartX; + const offsetY = root.dragPointerStartY - root.dragStartY; + + root.dragX = pointer.x - offsetX; + root.dragY = pointer.y - offsetY; + } + onPressed: mouse => { + const pointer = handle.mapToItem(root, mouse.x, mouse.y); + root.beginVisualDrag(slot.modelData, entryRow, pointer.x, pointer.y); + } + onReleased: { + if (root.draggedItemData && root.draggedItemData.entry === slot.entryData) + root.endVisualDrag(); } } } @@ -531,7 +598,7 @@ Item { Layout.rightMargin: Appearance.padding.small checked: slot.entryData.enabled ?? true - onToggled: root.updateEntry(slot.DelegateModel.itemsIndex, checked) + onToggled: root.cloneAndUpdateEnabled(slot.entryData, checked) } } } From 8fa447c63dfe9cc5cf6066bcf73a88a346cc99ec Mon Sep 17 00:00:00 2001 From: zach Date: Tue, 5 May 2026 12:14:06 +0200 Subject: [PATCH 2/3] end of rework, uses horizontal icon buttons instead of drag handlers and vertical views --- Config/BarConfig.qml | 12 - .../Settings/Controls/SettingBarEntryList.qml | 533 +++--------------- 2 files changed, 72 insertions(+), 473 deletions(-) diff --git a/Config/BarConfig.qml b/Config/BarConfig.qml index 9a13008..a57ed14 100644 --- a/Config/BarConfig.qml +++ b/Config/BarConfig.qml @@ -8,10 +8,6 @@ JsonObject { id: "workspaces", enabled: true }, - { - id: "audio", - enabled: true - }, { id: "media", enabled: true @@ -24,10 +20,6 @@ JsonObject { id: "updates", enabled: true }, - { - id: "dash", - enabled: true - }, { id: "spacer", enabled: true @@ -48,10 +40,6 @@ JsonObject { id: "tray", enabled: true }, - { - id: "upower", - enabled: false - }, { id: "network", enabled: false diff --git a/Modules/Settings/Controls/SettingBarEntryList.qml b/Modules/Settings/Controls/SettingBarEntryList.qml index 58e8801..496e605 100644 --- a/Modules/Settings/Controls/SettingBarEntryList.qml +++ b/Modules/Settings/Controls/SettingBarEntryList.qml @@ -11,129 +11,26 @@ import qs.Helpers Item { id: root - property var boxEntries: [[], [], []] property bool dragActive: false property real dragHeight: 0 - property real dragPointerStartX: 0 - property real dragPointerStartY: 0 property real dragStartX: 0 property real dragStartY: 0 property real dragX: 0 property real dragY: 0 - property int draggedBox: -1 - property int draggedIndex: -1 - property var draggedItemData: null + property var draggedModelData: null + property string draggedUid: "" property bool dropAnimating: false readonly property bool highlighted: SettingsHighlight.highlightedSetting === name required property string name required property var object - property var pendingCommitBoxes: [] + property var pendingCommitEntries: [] required property string setting - property var spacerEntries: [] + property int uidCounter: 0 + property var visualEntries: [] - function beginVisualDrag(wrapper, item, pointerX, pointerY) { - const pos = item.mapToItem(root, 0, 0); - const loc = root.locateEntry(wrapper.entry); - - root.draggedItemData = wrapper; - - if (loc) { - root.draggedBox = loc.box; - root.draggedIndex = loc.index; - } else { - root.draggedBox = -1; - root.draggedIndex = -1; - } - - root.dragHeight = item.height; - root.dragStartX = pos.x; - root.dragStartY = pos.y; - root.dragPointerStartX = pointerX; - root.dragPointerStartY = pointerY; - root.dragX = pos.x; - root.dragY = pos.y; - root.dragActive = true; - root.dropAnimating = false; - root.pendingCommitBoxes = []; - } - - function cloneAndUpdateEnabled(entry, value) { - const list = root.object[root.setting].slice(); - - for (let i = 0; i < list.length; i++) { - if (list[i] === entry) { - list[i] = { - id: list[i].id, - enabled: value - }; - break; - } - } - - root.object[root.setting] = list; - Config.save(); - root.rebuildBoxEntries(); - } - - function commitBoxEntries(boxes) { - const spacers = root.spacerEntries.length === 2 ? root.spacerEntries : (root.object[root.setting] ?? []).filter(e => root.isSpacer(e)); - - const next = []; - next.push(...boxes[0].map(w => w.entry)); - next.push(spacers[0]); - next.push(...boxes[1].map(w => w.entry)); - next.push(spacers[1]); - next.push(...boxes[2].map(w => w.entry)); - - root.object[root.setting] = next; - Config.save(); - root.rebuildBoxEntries(); - } - - function endVisualDrag() { - if (!root.draggedItemData) - return; - - const boxes = root.boxEntries.map(box => box.slice()); - const loc = root.locateEntry(root.draggedItemData.entry); - - root.dragActive = false; - - if (!loc) { - root.pendingCommitBoxes = boxes; - root.finishVisualDrag(); - return; - } - - const view = [boxView0, boxView1, boxView2][loc.box]; - const item = view ? view.itemAtIndex(loc.index) : null; - - root.pendingCommitBoxes = boxes; - - if (!item) { - root.finishVisualDrag(); - return; - } - - const pos = item.mapToItem(root, 0, 0); - root.dropAnimating = true; - settleX.to = pos.x; - settleY.to = pos.y; - settleAnim.start(); - } - - function finishVisualDrag() { - const boxes = root.pendingCommitBoxes.slice(); - - root.dragActive = false; - root.dropAnimating = false; - root.draggedItemData = null; - root.draggedBox = -1; - root.draggedIndex = -1; - root.pendingCommitBoxes = []; - root.dragHeight = 0; - - root.commitBoxEntries(boxes); + function ensureVisualEntries() { + if (!root.dragActive && !root.dropAnimating) + root.rebuildVisualEntries(); } function iconForId(id) { @@ -164,15 +61,18 @@ Item { return "schedule"; case "notifBell": return "notifications"; - case "hyprsunset": - return "wb_twilight"; default: return "drag_indicator"; } } - function isSpacer(entry) { - return entry && entry.id === "spacer"; + function indexForUid(uid) { + for (let i = 0; i < root.visualEntries.length; i++) { + if (root.visualEntries[i].uid === uid) + return i; + } + + return -1; } function labelForId(id) { @@ -203,103 +103,53 @@ Item { return qsTr("Clock"); case "notifBell": return qsTr("Notification bell"); - case "hyprsunset": - return qsTr("Sunset"); default: return id; } } - function locateEntry(entry) { - for (let b = 0; b < root.boxEntries.length; b++) { - for (let i = 0; i < root.boxEntries[b].length; i++) { - if (root.boxEntries[b][i].entry === entry) { - return { - box: b, - index: i - }; + function rebuildVisualEntries() { + const entries = root.object[root.setting] ?? []; + const next = []; + + for (let i = 0; i < entries.length; i++) { + const entry = entries[i]; + let existing = null; + + for (let j = 0; j < root.visualEntries.length; j++) { + if (root.visualEntries[j].entry === entry) { + existing = root.visualEntries[j]; + break; } } + + if (existing) + next.push(existing); + else + next.push({ + uid: `entry-${root.uidCounter++}`, + entry + }); } - return null; + root.visualEntries = next; } - function moveArrayItem(list, from, to) { - const next = list.slice(); - const item = next.splice(from, 1)[0]; - next.splice(to, 0, item); - return next; - } - - function previewMoveToBox(sourceEntry, targetBox, targetIndex, before) { - const current = root.boxEntries.map(box => box.slice()); - const loc = root.locateEntry(sourceEntry); - - if (!loc) - return; - - const moved = current[loc.box].splice(loc.index, 1)[0]; - - let insertAt = targetIndex + (before ? 0 : 1); - - if (loc.box === targetBox && insertAt > loc.index) - insertAt -= 1; - - insertAt = Math.max(0, Math.min(current[targetBox].length, insertAt)); - current[targetBox].splice(insertAt, 0, moved); - - root.boxEntries = current; - } - - function rebuildBoxEntries() { - const list = root.object[root.setting] ?? []; - const next = [[], [], []]; - const spacers = []; - let box = 0; - - for (let i = 0; i < list.length; i++) { - const entry = list[i]; - - if (root.isSpacer(entry)) { - spacers.push(entry); - box = Math.min(2, box + 1); - continue; - } - - next[box].push({ - entry: entry - }); - } - - root.spacerEntries = spacers; - root.boxEntries = next; - } - - function updateEntry(entry, value) { - const list = root.object[root.setting].slice(); - - for (let i = 0; i < list.length; i++) { - if (list[i] === entry) { - list[i] = { - id: list[i].id, - enabled: value - }; - break; - } - } - + function updateEntry(index, value) { + const list = [...root.object[root.setting]]; + const entry = list[index]; + entry.enabled = value; + list[index] = entry; root.object[root.setting] = list; Config.save(); - root.rebuildBoxEntries(); } Layout.fillWidth: true - implicitHeight: mainLayout.implicitHeight + implicitHeight: layout.implicitHeight - Component.onCompleted: root.rebuildBoxEntries() + Component.onCompleted: root.rebuildVisualEntries() - Rectangle { + CustomRect { anchors.fill: parent anchors.margins: -Appearance.padding.smaller color: DynamicColors.palette.m3primaryContainer @@ -314,294 +164,55 @@ Item { } } - ParallelAnimation { - id: settleAnim - - onFinished: root.finishVisualDrag() - - Anim { - id: settleX - - duration: Appearance.anim.durations.normal - property: "dragX" - target: root - } - - Anim { - id: settleY - - duration: Appearance.anim.durations.normal - property: "dragY" - target: root - } - } - - ColumnLayout { - id: mainLayout + RowLayout { + id: layout anchors.fill: parent spacing: Appearance.spacing.smaller - CustomText { - Layout.fillWidth: true - font.pointSize: Appearance.font.size.larger - text: root.name - } + DelegateModel { + id: visualModel - RowLayout { - Layout.fillWidth: true - spacing: Appearance.spacing.normal + delegate: entryDelegate - CustomRect { - Layout.fillWidth: true - Layout.preferredHeight: 260 - color: DynamicColors.tPalette.m3surface - radius: Appearance.rounding.normal - - ListView { - id: boxView0 - - anchors.fill: parent - anchors.margins: Appearance.padding.small - clip: false - delegate: entryDelegate - interactive: false - model: root.boxEntries[0] - spacing: Appearance.spacing.small - } - } - - CustomRect { - Layout.fillWidth: true - Layout.preferredHeight: 260 - color: DynamicColors.tPalette.m3surface - radius: Appearance.rounding.normal - - ListView { - id: boxView1 - - anchors.fill: parent - anchors.margins: Appearance.padding.small - clip: false - delegate: entryDelegate - interactive: false - model: root.boxEntries[1] - spacing: Appearance.spacing.small - } - } - - CustomRect { - Layout.fillWidth: true - Layout.preferredHeight: 260 - color: DynamicColors.tPalette.m3surface - radius: Appearance.rounding.normal - - ListView { - id: boxView2 - - anchors.fill: parent - anchors.margins: Appearance.padding.small - clip: false - delegate: entryDelegate - interactive: false - model: root.boxEntries[2] - spacing: Appearance.spacing.small - } + model: ScriptModel { + objectProp: "uid" + values: root.visualEntries } } - } - Loader { - active: root.dragActive || root.dropAnimating - asynchronous: false - - sourceComponent: Item { - property real listWidth: boxView0.width - - Drag.active: root.dragActive - Drag.hotSpot.x: width / 2 - Drag.hotSpot.y: height / 2 - height: proxyRect.implicitHeight - width: listWidth - x: root.dragX - y: root.dragY - z: 100 - - Drag.source: QtObject { - property var entry: root.draggedItemData ? root.draggedItemData.entry : null - } - - CustomRect { - id: proxyRect - - color: DynamicColors.tPalette.m3surface - implicitHeight: proxyRow.implicitHeight + Appearance.padding.small * 2 - implicitWidth: parent.width - opacity: 0.95 - radius: Appearance.rounding.normal - width: parent.width - - RowLayout { - id: proxyRow - - anchors.fill: parent - anchors.margins: Appearance.padding.small - spacing: Appearance.spacing.normal - - CustomRect { - color: Qt.alpha(DynamicColors.palette.m3onSurface, 0.12) - implicitHeight: 32 - implicitWidth: implicitHeight - radius: Appearance.rounding.small - - MaterialIcon { - anchors.centerIn: parent - color: DynamicColors.palette.m3onSurfaceVariant - text: "drag_indicator" - } - } - - MaterialIcon { - color: DynamicColors.palette.m3onSurfaceVariant - text: root.iconForId(root.draggedItemData?.entry?.id ?? "") - } - - CustomText { - Layout.fillWidth: true - font.pointSize: Appearance.font.size.larger - text: root.labelForId(root.draggedItemData?.entry?.id ?? "") - } - - CustomSwitch { - checked: root.draggedItemData?.entry?.enabled ?? true - enabled: false - } - } - } + Repeater { + delegate: entryDelegate + model: visualModel } } Component { id: entryDelegate - DropArea { - id: slot - - readonly property int boxIndex: ListView.view === boxView0 ? 0 : ListView.view === boxView1 ? 1 : 2 - readonly property var entryData: modelData.entry + IconButton { required property int index required property var modelData - function previewReorder(drag) { - const source = drag.source; - if (!source || !source.entry || source.entry === slot.entryData) - return; + Layout.fillWidth: true + Layout.preferredWidth: implicitWidth + (stateLayer.pressed ? 18 : internalChecked ? 7 : 0) + checked: modelData.entry.enabled ?? true + icon: root.iconForId(modelData.entry.id) + inactiveColour: DynamicColors.layer(DynamicColors.palette.m3surfaceContainerHighest, 2) + radius: stateLayer.pressed ? 6 / 2 : internalChecked ? 6 : 8 + radiusAnim.duration: MaterialEasing.expressiveEffectsTime + radiusAnim.easing.bezierCurve: MaterialEasing.expressiveEffects + toggle: true + visible: !["spacer", "upower", "dash", "audio"].some(prefix => modelData.entry.id.startsWith(prefix)) - root.previewMoveToBox(source.entry, slot.boxIndex, slot.index, drag.y < height / 2); - } - - height: entryRow.implicitHeight - implicitHeight: entryRow.implicitHeight - implicitWidth: ListView.view ? ListView.view.width : 0 - width: ListView.view ? ListView.view.width : 0 - - onEntered: drag => previewReorder(drag) - onPositionChanged: drag => previewReorder(drag) - - CustomRect { - id: entryRow - - anchors.fill: parent - color: DynamicColors.tPalette.m3surface - implicitHeight: entryLayout.implicitHeight + Appearance.padding.small * 2 - opacity: root.draggedItemData?.entry === slot.entryData ? 0 : 1 - radius: Appearance.rounding.full - - Behavior on opacity { - Anim { - } - } - - RowLayout { - id: entryLayout - - anchors.fill: parent - anchors.margins: Appearance.padding.small - spacing: Appearance.spacing.normal - - CustomRect { - id: handle - - color: Qt.alpha(DynamicColors.palette.m3onSurface, handleMouse.pressed ? 0.12 : handleMouse.containsMouse ? 0.09 : 0.06) - implicitHeight: 32 - implicitWidth: implicitHeight - radius: Appearance.rounding.full - - Behavior on color { - CAnim { - } - } - - MaterialIcon { - anchors.centerIn: parent - color: DynamicColors.palette.m3onSurfaceVariant - text: "drag_indicator" - } - - MouseArea { - id: handleMouse - - acceptedButtons: Qt.LeftButton - anchors.fill: parent - cursorShape: pressed ? Qt.ClosedHandCursor : containsMouse ? Qt.OpenHandCursor : Qt.ArrowCursor - hoverEnabled: true - preventStealing: true - - onCanceled: { - if (root.draggedItemData && root.draggedItemData.entry === slot.entryData) - root.endVisualDrag(); - } - onPositionChanged: mouse => { - if (!pressed || !root.dragActive || !root.draggedItemData || root.draggedItemData.entry !== slot.entryData) - return; - - const pointer = handle.mapToItem(root, mouse.x, mouse.y); - const offsetX = root.dragPointerStartX - root.dragStartX; - const offsetY = root.dragPointerStartY - root.dragStartY; - - root.dragX = pointer.x - offsetX; - root.dragY = pointer.y - offsetY; - } - onPressed: mouse => { - const pointer = handle.mapToItem(root, mouse.x, mouse.y); - root.beginVisualDrag(slot.modelData, entryRow, pointer.x, pointer.y); - } - onReleased: { - if (root.draggedItemData && root.draggedItemData.entry === slot.entryData) - root.endVisualDrag(); - } - } - } - - MaterialIcon { - color: DynamicColors.palette.m3onSurfaceVariant - text: root.iconForId(slot.entryData.id) - } - - CustomText { - Layout.fillWidth: true - font.pointSize: Appearance.font.size.larger - text: root.labelForId(slot.entryData.id) - } - - CustomSwitch { - Layout.rightMargin: Appearance.padding.small - checked: slot.entryData.enabled ?? true - - onToggled: root.cloneAndUpdateEnabled(slot.entryData, checked) - } + Behavior on Layout.preferredWidth { + Anim { + duration: MaterialEasing.expressiveEffectsTime + easing.bezierCurve: MaterialEasing.expressiveEffects } } + + onClicked: root.updateEntry(index, internalChecked) } } } From bcc75abc5440d53f3d08edcce8c1df5324bb3212 Mon Sep 17 00:00:00 2001 From: zach Date: Fri, 8 May 2026 19:27:36 +0200 Subject: [PATCH 3/3] labels instead of icons for bar entries --- Modules/Settings/Controls/SettingBarEntryList.qml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Modules/Settings/Controls/SettingBarEntryList.qml b/Modules/Settings/Controls/SettingBarEntryList.qml index 496e605..47ac184 100644 --- a/Modules/Settings/Controls/SettingBarEntryList.qml +++ b/Modules/Settings/Controls/SettingBarEntryList.qml @@ -92,7 +92,7 @@ Item { case "spacer": return qsTr("Spacer"); case "activeWindow": - return qsTr("Active window"); + return qsTr("Title"); case "tray": return qsTr("Tray"); case "upower": @@ -102,7 +102,9 @@ Item { case "clock": return qsTr("Clock"); case "notifBell": - return qsTr("Notification bell"); + return qsTr("Notifs"); + case "hyprsunset": + return qsTr("Night light"); default: return id; } @@ -168,7 +170,8 @@ Item { id: layout anchors.fill: parent - spacing: Appearance.spacing.smaller + + // spacing: Appearance.spacing.smaller DelegateModel { id: visualModel @@ -197,7 +200,9 @@ Item { Layout.fillWidth: true Layout.preferredWidth: implicitWidth + (stateLayer.pressed ? 18 : internalChecked ? 7 : 0) checked: modelData.entry.enabled ?? true - icon: root.iconForId(modelData.entry.id) + font: Appearance.font.family.sans + // icon: root.iconForId(modelData.entry.id) + icon: root.labelForId(modelData.entry.id) inactiveColour: DynamicColors.layer(DynamicColors.palette.m3surfaceContainerHighest, 2) radius: stateLayer.pressed ? 6 / 2 : internalChecked ? 6 : 8 radiusAnim.duration: MaterialEasing.expressiveEffectsTime