Add wallpaper mode controls

This commit is contained in:
Gabriel Brown
2026-08-18 15:00:18 -04:00
parent 1c12892252
commit c36e423890
9 changed files with 388 additions and 6 deletions
@@ -50,9 +50,16 @@ SettingsPage {
? Wallpaper.lastError
: "Applied to every display. Looked for in ~/Pictures/Wallpapers, ~/Pictures/Backgrounds, ~/.local/share/backgrounds, and /usr/share/backgrounds."
WallpaperControls {
id: wallpaperControls
width: parent.width
}
WallpaperPicker {
id: wallpapers
width: parent.width
mode: wallpaperControls.mode
selectedOutput: wallpaperControls.selectedOutput
}
ActionRow {
@@ -0,0 +1,103 @@
import QtQuick
import qs.config
import qs.services
import qs.widgets
Column {
id: root
property string mode: DesktopPreferences.get("wallpaperMode")
property var outputs: Wallpaper.outputNames()
property string selectedOutput: root.outputs.length > 0 ? root.outputs[0] : ""
property var setModeAction: function(mode) { Wallpaper.setMode(mode); }
property var setIntervalAction: function(minutes) { Wallpaper.setIntervalMinutes(minutes); }
property var setShuffleAction: function(enabled) { Wallpaper.setShuffle(enabled); }
width: parent ? parent.width : 620
spacing: 4
ChoiceGrid {
width: parent.width
label: "Wallpaper mode"
detail: "Use one image, rotate a collection, or choose per display"
options: PreferenceSchema.spec("wallpaperMode").options
current: root.mode
onPicked: value => root.setModeAction(value)
}
ChoiceGrid {
visible: root.mode === "per-monitor"
width: parent.width
label: "Display"
detail: "Choose which display the thumbnail grid assigns"
options: root.outputs.map(output => ({ value: output, label: output }))
current: root.selectedOutput
onPicked: value => root.selectedOutput = value
}
SettingRow {
visible: root.mode === "slideshow"
label: "Change background every"
detail: "Time between slideshow images"
controlWidth: 280
Item {
anchors.fill: parent
ValueSlider {
anchors.left: parent.left
anchors.right: intervalText.left
anchors.rightMargin: 10
anchors.verticalCenter: parent.verticalCenter
value: (DesktopPreferences.get("wallpaperIntervalMinutes") - 5) / 1435
onMoved: ratio => {
const raw = 5 + ratio * 1435;
root.setIntervalAction(Math.max(5, Math.min(1440, Math.round(raw / 5) * 5)));
}
}
Text {
id: intervalText
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
width: 62
text: DesktopPreferences.get("wallpaperIntervalMinutes") + " min"
color: Theme.fgDim
font.family: Theme.fontMono
font.features: Theme.tabularFigures
font.pixelSize: Theme.fontSizeSmall
horizontalAlignment: Text.AlignRight
}
}
}
SettingRow {
visible: root.mode === "slideshow"
label: "Shuffle"
detail: "Show every selected image before repeating"
divider: false
controlWidth: 48
SettingsToggle {
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
checked: DesktopPreferences.get("wallpaperShuffle") === true
onToggled: enabled => root.setShuffleAction(enabled)
}
}
Text {
width: parent.width
visible: root.mode === "slideshow"
&& (DesktopPreferences.get("wallpaperSlideshowPaths") ?? []).length === 0
text: "Select two or more images below to begin a slideshow."
color: Theme.fgDim
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
horizontalAlignment: Text.AlignHCenter
topPadding: 5
bottomPadding: 8
}
}
@@ -24,6 +24,14 @@ Item {
// unreachable without a long scroll past pictures. Two rows by default,
// all of them on request.
property bool expanded: false
property string mode: DesktopPreferences.get("wallpaperMode")
property string selectedOutput: Wallpaper.outputNames()[0] ?? ""
property var activeByOutput: Wallpaper.activeByOutput
property var slideshowPaths: DesktopPreferences.get("wallpaperSlideshowPaths") ?? []
property var assignments: DesktopPreferences.get("wallpaperPerMonitor") ?? ({})
property var setSingleAction: function(path) { Wallpaper.setSingle(path); }
property var toggleSlideshowAction: function(path) { Wallpaper.toggleSlideshowPath(path); }
property var setAssignmentAction: function(output, path) { Wallpaper.setAssignment(output, path); }
readonly property int collapsedRows: 2
readonly property var shown: root.expanded
@@ -35,6 +43,27 @@ Item {
readonly property int columns: Math.max(2, Math.floor(width / 190))
readonly property real cellWidth: columns > 0 ? (width - (columns - 1) * 10) / columns : 160
function isCurrent(path: string): bool {
return root.activeByOutput[root.selectedOutput] === path;
}
function selected(path: string): bool {
if (root.mode === "slideshow")
return root.slideshowPaths.includes(path);
if (root.mode === "per-monitor")
return root.assignments[root.selectedOutput] === path;
return root.isCurrent(path);
}
function activate(path: string): void {
if (root.mode === "slideshow")
root.toggleSlideshowAction(path);
else if (root.mode === "per-monitor")
root.setAssignmentAction(root.selectedOutput, path);
else
root.setSingleAction(path);
}
Grid {
id: grid
@@ -50,7 +79,8 @@ Item {
required property var modelData
readonly property bool current: Wallpaper.active === tile.modelData
readonly property bool current: root.isCurrent(tile.modelData)
readonly property bool member: root.mode === "slideshow" && root.selected(tile.modelData)
width: root.cellWidth
height: Math.round(root.cellWidth * 9 / 16)
@@ -114,6 +144,28 @@ Item {
border.color: Theme.accent
}
Rectangle {
anchors.top: parent.top
anchors.right: parent.right
anchors.margins: 8
width: 24
height: 24
radius: 12
visible: tile.member
color: Theme.alpha(Theme.bgDark, 0.82)
border.width: 1
border.color: Theme.alpha(Theme.fg, 0.16)
Text {
anchors.centerIn: parent
text: "✓"
color: Theme.fg
font.family: Theme.fontFamily
font.pixelSize: 14
font.weight: Font.DemiBold
}
}
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
@@ -132,7 +184,9 @@ Item {
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.margins: 7
text: tile.current ? "Current wallpaper" : Wallpaper.titleFor(tile.modelData)
text: tile.current
? "Current wallpaper"
: (tile.member ? "In slideshow" : Wallpaper.titleFor(tile.modelData))
color: tile.current ? Theme.accent : Theme.fg
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
@@ -144,7 +198,7 @@ Item {
HoverHandler { id: hover }
TapHandler {
onTapped: Wallpaper.set(tile.modelData)
onTapped: root.activate(tile.modelData)
}
}
}
@@ -34,6 +34,7 @@ PowerPage 1.0 PowerPage.qml
DateTimePage 1.0 DateTimePage.qml
AccessibilityPage 1.0 AccessibilityPage.qml
WallpaperPicker 1.0 WallpaperPicker.qml
WallpaperControls 1.0 WallpaperControls.qml
ApplicationsPage 1.0 ApplicationsPage.qml
AutostartAppPicker 1.0 AutostartAppPicker.qml
DockPinsEditor 1.0 DockPinsEditor.qml