feat(shell): wallpaper grid picker (Plasma-style)#5
Merged
Conversation
Replaces the bare FileDialog from PR #4 with a Plasma System Settings-style grid: thumbnails of every wallpaper found in /usr/share/wallpapers/ and ~/.local/share/wallpapers/, plus a "Browse…" fallback for arbitrary files. This is what the user flagged after PR #4: bypassing the XDG portal lost the Plasma file picker's thumbnail preview, leaving Qt's spartan QML dialog. Core addition: WallpaperLibrary, a QAbstractListModel that scans the search paths in a single pass and handles two layout conventions: - Package wallpapers — <root>/<name>/contents/images/*.<ext>, the convention KPackage and /usr/share/wallpapers ship. Picks the alphabetically-first image inside contents/images/ for both thumbnail and apply target (Plasma's image renderer consumes any single resolution from a package). - Flat image files dropped directly under <root>, useful for the user's quick-drop spot at ~/.local/share/wallpapers/. Same-name entries across multiple search paths are deduplicated first-wins, so a user override at ~/.local/share/wallpapers/<Name> shadows the same-name system package. QML: WallpaperPicker.qml is a Kirigami.Dialog with a GridView bound to the new wallpaperLibrary context property. Each tile is a clickable ItemDelegate that emits wallpaperPicked(url) on click and closes the dialog. customFooterActions adds the "Browse…" action, which opens an embedded FileDialog (same DontUseNativeDialog flag as before for the same portal-bypass reason). Main.qml: the page header "Pick image…" action becomes "Choose wallpaper…" and opens the new picker instead of the FileDialog directly. The wallpaperPicked signal sets window.pickedImage, so the rest of the apply flow is unchanged. WallpaperLibrary stays in src/core/ — QtCore-only, no GUI/Kirigami deps, no plasma-isolation breach. 6 new tst_WallpaperLibrary assertions cover empty paths, package detection, flat-file fallback, role-name strings (must match QML required-property names), dedup across paths, and reload() picking up filesystem changes. 7/7 test suites pass (DesktopSurface, LockscreenSurface, LoginSurface, SyncEngine, WallpaperLibrary, PlasmaReloader, appstreamtest). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The picker came up empty on a real machine because neither pattern
the initial implementation supported matched what the user actually
has on disk:
- ~/.local/share/wallpapers/Personal/{sunset.jpg, forest.png, …}
is just a folder of flat images, not a KPackage structure with
contents/images/. The package-detection pass returned nothing,
and the flat-files pass only looked at the search root itself.
- /usr/share/wallpapers/ is shipped on the Bazzite host (Altai,
Autumn, BytheWater, …) but the org.kde.Platform//6.10 Flatpak
runtime does not bundle them at the same path inside the
sandbox — surprisingly enough — so the system-defaults default
search path resolved to /run/build/... nothing.
Two fixes:
1. WallpaperLibrary gains a third scan pattern: for each subdir that
isn't already classified as a package (no contents/images/), list
its top-level image files and add each as its own entry. The
subdir name itself doesn't surface — the user picks an image, not
a folder. New tst_WallpaperLibrary case
picksFlatImagesInsideOneLevelSubdir locks in the behavior.
2. Manifest grants --filesystem=/usr/share/wallpapers:ro so the
sandbox can see the host's system wallpapers. Read-only — the
sandbox-review checklist for Flathub (v3 evolution) considers
read access to a system config dir routine.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ifact Three follow-ups to PR #5 round 1: 1. System wallpapers were missing from the grid because Flatpak silently rejects --filesystem=/usr/share/wallpapers ("Path /usr is reserved"). The supported route is --filesystem=host:ro and reading through /run/host/. Manifest now grants host:ro and WallpaperLibrary's default search paths include /run/host/usr/share/wallpapers (non-existent on a native install, skipped silently). 2. Desktop apply only hit the first containment, so on dual-monitor setups the wallpaper synced on one screen but not the other. findAllDesktopContainmentIds() now returns every containment whose Wallpaper/org.kde.image/General subgroup carries an Image entry, and apply() writes to all of them — that's literally what "sync" should do here. New tst_DesktopSurface case applyWritesToEveryDesktopContainment locks the behavior in, with a sample-desktop-appletsrc-multi fixture that mirrors a real two-screen install. 3. Ultra-wide / panoramic wallpapers (the user's uwp5030806.png is 5K-class) overflowed the tile bounds in the picker grid because ItemDelegate doesn't clip its contents by default. clip: true on the delegate root closes that off without touching the layout. 7/7 test suites still pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Kirigami.Dialog renders as a fixed-size modal panel inside the parent window — it's designed for short-form prompts (confirm / cancel), not for long-form content like a wallpaper grid. The user flagged the inability to resize the picker, which has more entries than the default size shows. QtQuick.Window with transientParent: applicationWindow() and modality: Qt.WindowModal gives a real top-level window the user can resize freely via the OS-native decoration handle, while keeping focus tied to the main app window — the WM treats it as a modal of the parent rather than a peer. Footer buttons replace customFooterActions: a plain RowLayout with a spacer + Browse / Cancel buttons, since Window has no built-in standardButtons API. Same FileDialog inside, same wallpaperPicked signal contract, so Main.qml only needed s/wallpaperPicker.open/ .show/. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Addresses the UX feedback after PR #4: "on n'a plus d'aperçu des images, idéalement avec le bouton Pick image j'aurais aimé retrouver la vue qu'on a dans les réglages KDE".
Replaces the spartan QtQuick FileDialog with a Plasma System Settings-style grid:
`WallpaperLibrary` stays in src/core/ — QtCore + KConfig only, no GUI/Kirigami/DBus/KAuth. The layering guard still passes.
Test plan