aboutsummaryrefslogtreecommitdiffstats
path: root/desktop/modules/appearance
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-10-18 22:14:33 +0200
committerDanilo M. <danix@danix.xyz>2026-10-18 22:14:33 +0200
commit61d17788ff132fcd02d6831934cfe9beba1d49ce (patch)
tree840cfef578222690df3016f77dfb1ee29f5f1339 /desktop/modules/appearance
parent6c678fa9cd111df116b219383d396efbd48c7c34 (diff)
downloadquickshell-61d17788ff132fcd02d6831934cfe9beba1d49ce.tar.gz
quickshell-61d17788ff132fcd02d6831934cfe9beba1d49ce.zip
wallpaper: row-per-notch wheel and a sticky folder header
The thumbnail list scrolled a fraction of a thumbnail per wheel notch, which is ListView's default step and slow with rows this tall. A MouseArea over the list (acceptedButtons: Qt.NoButton, so clicks and hovers still reach the thumbnails) now moves one row per notch, and keeps a touchpad's pixel delta as it is. An open folder with many images scrolled its header out of view, so folding it meant scrolling back to the top. A copy of the header is now pinned over the list while the topmost row belongs to a folder whose own header has scrolled off; clicking it folds that folder and positions the view at its header. The header row became an inline component so the list and the pinned copy draw the same thing. Loads clean; not yet confirmed by eye. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'desktop/modules/appearance')
-rw-r--r--desktop/modules/appearance/WallpaperTab.qml116
1 files changed, 86 insertions, 30 deletions
diff --git a/desktop/modules/appearance/WallpaperTab.qml b/desktop/modules/appearance/WallpaperTab.qml
index af3c23b..3931fcb 100644
--- a/desktop/modules/appearance/WallpaperTab.qml
+++ b/desktop/modules/appearance/WallpaperTab.qml
@@ -28,6 +28,45 @@ Column {
// wallhaven-dl opens.
signal dismiss
+ // A folder's header row: chevron, name and count. The list draws one per
+ // folder, and the sticky copy over its top draws the folder in view.
+ component FolderHeader: Rectangle {
+ id: hdr
+ property string name
+ property int count
+ property bool open
+ signal clicked
+ radius: 8
+ color: Qt.alpha(Theme.surface, headerHover.hovered ? 0.8 : 0.4)
+
+ HoverHandler { id: headerHover }
+ MouseArea {
+ anchors.fill: parent
+ cursorShape: Qt.PointingHandCursor
+ onClicked: hdr.clicked()
+ }
+
+ Text {
+ id: chevron
+ anchors { left: parent.left; leftMargin: 12; verticalCenter: parent.verticalCenter }
+ text: hdr.open ? "\uf077" : "\uf078"
+ font { family: Theme.iconFamily; pixelSize: Theme.fontSize - 4 }
+ color: Theme.subtext
+ }
+ Text {
+ anchors { left: chevron.right; leftMargin: 10; verticalCenter: parent.verticalCenter }
+ text: hdr.name
+ font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2; bold: true }
+ color: Theme.text
+ }
+ Text {
+ anchors { right: parent.right; rightMargin: 12; verticalCenter: parent.verticalCenter }
+ text: hdr.count
+ font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 4 }
+ color: Theme.overlay
+ }
+ }
+
Connections {
target: Wallpapers
function onApplied(ok, message) {
@@ -234,38 +273,13 @@ Column {
width: ListView.view.width
height: start < 0 ? 40 : wallList.thumbHeight
- Rectangle {
+ FolderHeader {
visible: row.start < 0
anchors { fill: parent; topMargin: 6 }
- radius: 8
- color: Qt.alpha(Theme.surface, headerHover.hovered ? 0.8 : 0.4)
-
- HoverHandler { id: headerHover }
- MouseArea {
- anchors.fill: parent
- cursorShape: Qt.PointingHandCursor
- onClicked: wallList.toggle(row.index)
- }
-
- Text {
- id: chevron
- anchors { left: parent.left; leftMargin: 12; verticalCenter: parent.verticalCenter }
- text: row.open ? "\uf077" : "\uf078"
- font { family: Theme.iconFamily; pixelSize: Theme.fontSize - 4 }
- color: Theme.subtext
- }
- Text {
- anchors { left: chevron.right; leftMargin: 10; verticalCenter: parent.verticalCenter }
- text: row.group.name
- font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2; bold: true }
- color: Theme.text
- }
- Text {
- anchors { right: parent.right; rightMargin: 12; verticalCenter: parent.verticalCenter }
- text: row.group.files.length
- font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 4 }
- color: Theme.overlay
- }
+ name: row.group.name
+ count: row.group.files.length
+ open: row.open
+ onClicked: wallList.toggle(row.index)
}
Row {
@@ -340,6 +354,48 @@ Column {
}
}
}
+
+ // The folder of the topmost row, once its own header has
+ // scrolled off: a copy pinned over the list, so an open folder
+ // folds from anywhere in it. Folding returns to its header.
+ readonly property int topIndex: count, indexAt(0, contentY + 1)
+ readonly property int topStart: topIndex < 0 ? -1 : rows.get(topIndex).start
+ Rectangle {
+ parent: wallList
+ visible: wallList.topStart >= 0
+ width: wallList.width
+ height: 40
+ color: Theme.base
+
+ FolderHeader {
+ readonly property var group: wallList.topStart < 0 ? null
+ : wallList.group(rows.get(wallList.topIndex).key)
+ anchors { fill: parent; topMargin: 6 }
+ name: group?.name ?? ""
+ count: group?.files.length ?? 0
+ open: true
+ onClicked: {
+ let h = wallList.topIndex;
+ while (h > 0 && rows.get(h).start >= 0) h--;
+ wallList.toggle(h);
+ wallList.positionViewAtIndex(h, ListView.Beginning);
+ }
+ }
+ }
+
+ // The default wheel step moves a fraction of a thumbnail; a
+ // notch here moves one row. A touchpad's pixel delta is kept.
+ MouseArea {
+ parent: wallList
+ anchors.fill: parent
+ acceptedButtons: Qt.NoButton
+ onWheel: wheel => {
+ const d = wheel.pixelDelta.y !== 0 ? wheel.pixelDelta.y
+ : wheel.angleDelta.y / 120 * wallList.thumbHeight;
+ wallList.contentY = Math.max(wallList.originY, Math.min(
+ wallList.originY + wallList.contentHeight - wallList.height, wallList.contentY - d));
+ }
+ }
}
}
}