Add recursive wallpaper setting in WallpaperTab (implements #568)

This commit is contained in:
Ly-sec
2025-10-27 17:04:24 +01:00
parent 1067ffe7a3
commit f30d1d3ea1
11 changed files with 123 additions and 8 deletions
+4
View File
@@ -445,6 +445,10 @@
"description": "Pfad zu Ihrem Haupt-Hintergrundbild-Ordner.",
"tooltip": "Nach Hintergrundbild-Ordner suchen"
},
"recursive-search": {
"label": "Unterordner durchsuchen",
"description": "Auch nach Hintergrundbildern in Unterordnern des Hintergrundbild-Verzeichnisses suchen."
},
"monitor-specific": {
"label": "Monitor-spezifische Verzeichnisse",
"description": "Unterschiedlichen Hintergrundbild-Ordner für jeden Monitor festlegen.",
+4
View File
@@ -445,6 +445,10 @@
"description": "Path to your main wallpaper folder.",
"tooltip": "Browse for wallpaper folder"
},
"recursive-search": {
"label": "Search subfolders",
"description": "Also search for wallpapers in subfolders of the wallpaper directory."
},
"monitor-specific": {
"label": "Monitor-specific directories",
"description": "Set a different wallpaper folder for each monitor.",
+4
View File
@@ -445,6 +445,10 @@
"description": "Ruta a tu carpeta principal de fondos de pantalla.",
"tooltip": "Buscar carpeta de fondos de pantalla"
},
"recursive-search": {
"label": "Buscar en subcarpetas",
"description": "Buscar fondos de pantalla también en subcarpetas del directorio de fondos de pantalla."
},
"monitor-specific": {
"label": "Directorios específicos por monitor",
"description": "Establece una carpeta de fondos de pantalla diferente para cada monitor.",
+4
View File
@@ -445,6 +445,10 @@
"description": "Chemin vers votre dossier principal de fonds d'écran.",
"tooltip": "Parcourir le dossier des fonds d'écran"
},
"recursive-search": {
"label": "Rechercher dans les sous-dossiers",
"description": "Rechercher également des fonds d'écran dans les sous-dossiers du répertoire des fonds d'écran."
},
"monitor-specific": {
"label": "Dossiers spécifiques au moniteur",
"description": "Définissez un dossier de fond d'écran différent pour chaque moniteur.",
+4
View File
@@ -407,6 +407,10 @@
"description": "Caminho para a sua pasta principal de papéis de parede.",
"tooltip": "Procurar pasta de papéis de parede"
},
"recursive-search": {
"label": "Buscar em subpastas",
"description": "Também buscar papéis de parede em subpastas do diretório de papéis de parede."
},
"monitor-specific": {
"label": "Diretórios específicos por monitor",
"description": "Defina uma pasta de papel de parede diferente para cada monitor.",
+4
View File
@@ -445,6 +445,10 @@
"description": "您的主壁纸文件夹路径。",
"tooltip": "浏览壁纸文件夹"
},
"recursive-search": {
"label": "搜索子文件夹",
"description": "同时在壁纸目录的子文件夹中搜索壁纸。"
},
"monitor-specific": {
"label": "显示器特定目录",
"description": "为每个显示器设置不同的壁纸文件夹。",
+1
View File
@@ -93,6 +93,7 @@
"enabled": true,
"directory": "",
"enableMultiMonitorDirectories": false,
"recursiveSearch": false,
"setWallpaperOnAllMonitors": true,
"defaultWallpaper": "",
"fillMode": "crop",
+1
View File
@@ -224,6 +224,7 @@ Singleton {
property bool enabled: true
property string directory: ""
property bool enableMultiMonitorDirectories: false
property bool recursiveSearch: false
property bool setWallpaperOnAllMonitors: true
property string defaultWallpaper: ""
property string fillMode: "crop"
+8
View File
@@ -44,6 +44,14 @@ ColumnLayout {
onButtonClicked: mainFolderPicker.open()
}
// Recursive search
NToggle {
label: I18n.tr("settings.wallpaper.settings.recursive-search.label")
description: I18n.tr("settings.wallpaper.settings.recursive-search.description")
checked: Settings.data.wallpaper.recursiveSearch
onToggled: checked => Settings.data.wallpaper.recursiveSearch = checked
}
// Monitor-specific directories
NToggle {
label: I18n.tr("settings.wallpaper.settings.monitor-specific.label")
+4
View File
@@ -291,6 +291,10 @@ NPanel {
return
}
wallpapersList = WallpaperService.getWallpapersList(targetScreen.name)
Logger.i("WallpaperPanel", "Got", wallpapersList.length, "wallpapers for screen", targetScreen.name)
if (wallpapersList.length > 0) {
Logger.d("WallpaperPanel", "First 5 wallpapers:", wallpapersList.slice(0, 5))
}
// Pre-compute basenames once for better performance
wallpapersWithNames = wallpapersList.map(function (p) {
+85 -8
View File
@@ -72,6 +72,9 @@ Singleton {
function onRandomIntervalSecChanged() {
root.restartRandomWallpaperTimer()
}
function onRecursiveSearchChanged() {
root.refreshWallpapersList()
}
}
// -------------------------------------------------
@@ -355,20 +358,94 @@ Singleton {
// -------------------------------------------------------------------
function refreshWallpapersList() {
Logger.d("Wallpaper", "refreshWallpapersList")
Logger.d("Wallpaper", "refreshWallpapersList", "recursive:", Settings.data.wallpaper.recursiveSearch)
scanningCount = 0
// Force refresh by toggling the folder property on each FolderListModel
for (var i = 0; i < wallpaperScanners.count; i++) {
var scanner = wallpaperScanners.objectAt(i)
if (scanner) {
var currentFolder = scanner.folder
scanner.folder = ""
scanner.folder = currentFolder
if (Settings.data.wallpaper.recursiveSearch) {
// Use Process-based recursive search for all screens
for (var i = 0; i < Quickshell.screens.length; i++) {
var screenName = Quickshell.screens[i].name
var directory = getMonitorDirectory(screenName)
scanDirectoryRecursive(screenName, directory)
}
} else {
// Use FolderListModel (non-recursive)
for (var i = 0; i < wallpaperScanners.count; i++) {
var scanner = wallpaperScanners.objectAt(i)
if (scanner) {
var currentFolder = scanner.folder
scanner.folder = ""
scanner.folder = currentFolder
}
}
}
}
// Process instances for recursive scanning (one per screen)
property var recursiveProcesses: ({})
// -------------------------------------------------------------------
function scanDirectoryRecursive(screenName, directory) {
if (!directory || directory === "") {
Logger.w("Wallpaper", "Empty directory for", screenName)
wallpaperLists[screenName] = []
wallpaperListChanged(screenName, 0)
return
}
scanningCount++
Logger.i("Wallpaper", "Starting recursive scan for", screenName, "in", directory)
// Create Process component inline
var processComponent = Qt.createComponent("", root)
var processString = `
import QtQuick
import Quickshell.Io
Process {
id: process
command: ["find", "` + directory + `", "-type", "f", "(", "-iname", "*.jpg", "-o", "-iname", "*.jpeg", "-o", "-iname", "*.png", "-o", "-iname", "*.gif", "-o", "-iname", "*.pnm", "-o", "-iname", "*.bmp", ")"]
stdout: StdioCollector {}
stderr: StdioCollector {}
}
`
var processObject = Qt.createQmlObject(processString, root, "RecursiveScan_" + screenName)
// Store reference to avoid garbage collection
recursiveProcesses[screenName] = processObject
var handler = function (exitCode) {
scanningCount--
Logger.d("Wallpaper", "Process exited with code", exitCode, "for", screenName)
if (exitCode === 0) {
var lines = processObject.stdout.text.split('\n')
var files = []
for (var i = 0; i < lines.length; i++) {
var line = lines[i].trim()
if (line !== '') {
files.push(line)
}
}
// Sort files for consistent ordering
files.sort()
wallpaperLists[screenName] = files
Logger.i("Wallpaper", "Recursive scan completed for", screenName, "found", files.length, "files")
wallpaperListChanged(screenName, files.length)
} else {
Logger.e("Wallpaper", "Recursive scan failed for", screenName, "exit code:", exitCode, "stderr:", processObject.stderr.text)
wallpaperLists[screenName] = []
wallpaperListChanged(screenName, 0)
}
// Clean up
delete recursiveProcesses[screenName]
processObject.destroy()
}
processObject.exited.connect(handler)
Logger.d("Wallpaper", "Starting process for", screenName)
processObject.running = true
}
// -------------------------------------------------------------------
// -------------------------------------------------------------------
// -------------------------------------------------------------------