Add WallpaperSelector, add some scrolling in SettingsWindow

This commit is contained in:
Ly-sec 2025-08-12 17:26:23 +02:00
parent eff47f504f
commit 8155ef20eb
14 changed files with 1451 additions and 674 deletions

View file

@ -8,9 +8,18 @@ Variants {
delegate: PanelWindow { delegate: PanelWindow {
required property ShellScreen modelData required property ShellScreen modelData
property string wallpaperSource: Settings.data.wallpaper.current property string wallpaperSource: Wallpapers.currentWallpaper !== "" && !Settings.data.wallpaper.swww.enabled ? Wallpapers.currentWallpaper : ""
visible: wallpaperSource !== "" visible: wallpaperSource !== "" && !Settings.data.wallpaper.swww.enabled
// Force update when SWWW setting changes
onVisibleChanged: {
if (visible) {
console.log("Background: Showing wallpaper:", wallpaperSource)
} else {
console.log("Background: Hiding wallpaper (SWWW enabled)")
}
}
color: "transparent" color: "transparent"
screen: modelData screen: modelData
WlrLayershell.layer: WlrLayer.Background WlrLayershell.layer: WlrLayer.Background

View file

@ -9,9 +9,9 @@ Variants {
delegate: PanelWindow { delegate: PanelWindow {
required property ShellScreen modelData required property ShellScreen modelData
property string wallpaperSource: Qt.resolvedUrl("../../Assets/Tests/wallpaper.png") property string wallpaperSource: Wallpapers.currentWallpaper !== "" && !Settings.data.wallpaper.swww.enabled ? Wallpapers.currentWallpaper : ""
visible: wallpaperSource !== "" visible: wallpaperSource !== "" && !Settings.data.wallpaper.swww.enabled
color: "transparent" color: "transparent"
screen: modelData screen: modelData
WlrLayershell.layer: WlrLayer.Background WlrLayershell.layer: WlrLayer.Background

View file

@ -46,7 +46,13 @@ NLoader {
"label": "Wallpaper", "label": "Wallpaper",
"icon": "image", "icon": "image",
"source": "Tabs/Wallpaper.qml" "source": "Tabs/Wallpaper.qml"
}, { },
{
"label": "Wallpaper Selector",
"icon": "wallpaper_slideshow",
"source": "Tabs/WallpaperSelector.qml"
},
{
"label": "Misc", "label": "Misc",
"icon": "more_horiz", "icon": "more_horiz",
"source": "Tabs/Misc.qml" "source": "Tabs/Misc.qml"
@ -207,6 +213,7 @@ NLoader {
Tabs.Network {} Tabs.Network {}
Tabs.Display {} Tabs.Display {}
Tabs.Wallpaper {} Tabs.Wallpaper {}
Tabs.WallpaperSelector {}
Tabs.Misc {} Tabs.Misc {}
Tabs.About {} Tabs.About {}
} }

View file

@ -1,26 +1,57 @@
import QtQuick import QtQuick
import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
Item { ColumnLayout {
// Optional scaling prop to match other tabs id: root
property real scaling: 1
// Tab metadata spacing: 0
readonly property string tabIcon: "web_asset"
readonly property string tabLabel: "Bar" ScrollView {
readonly property int tabIndex: 1 id: scrollView
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
padding: 16
rightPadding: 12
clip: true
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
ScrollBar.vertical.policy: ScrollBar.AsNeeded
ColumnLayout { ColumnLayout {
anchors.fill: parent width: scrollView.availableWidth
spacing: Style.marginMedium * scaling spacing: 0
Item {
Layout.fillWidth: true
Layout.preferredHeight: 0
}
ColumnLayout {
spacing: 4
Layout.fillWidth: true
NText {
text: "Bar Settings"
font.pointSize: 18
font.weight: Style.fontWeightBold
color: Colors.textPrimary
Layout.bottomMargin: 8
}
// Elements section
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Layout.topMargin: 8
NText { NText {
text: "Elements" text: "Elements"
font.pointSize: 13
font.weight: Style.fontWeightBold font.weight: Style.fontWeightBold
color: Colors.accentSecondary color: Colors.textPrimary
} }
NToggle { NToggle {
@ -67,9 +98,8 @@ Item {
Settings.data.bar.showMedia = newValue Settings.data.bar.showMedia = newValue
} }
} }
}
Item { }
Layout.fillHeight: true
} }
} }
} }

View file

@ -1,50 +1,75 @@
import QtQuick import QtQuick
import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
Item { ColumnLayout {
id: generalPage id: root
// Public API spacing: 0
// Scaling factor provided by the parent settings window
property real scaling: 1 ScrollView {
// Tab metadata id: scrollView
readonly property string tabIcon: "tune"
readonly property string tabLabel: "General"
readonly property int tabIndex: 0
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
padding: 16
rightPadding: 12
clip: true
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
ScrollBar.vertical.policy: ScrollBar.AsNeeded
ColumnLayout { ColumnLayout {
anchors.fill: parent width: scrollView.availableWidth
anchors.margins: 0 spacing: 0
spacing: Style.marginMedium * scaling
Item {
Layout.fillWidth: true
Layout.preferredHeight: 0
}
ColumnLayout {
spacing: 4
Layout.fillWidth: true
NText {
text: "General Settings"
font.pointSize: 18
font.weight: Style.fontWeightBold
color: Colors.textPrimary
Layout.bottomMargin: 8
}
// Profile section // Profile section
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Layout.topMargin: 8
NText { NText {
text: "Profile" text: "Profile"
font.pointSize: 13
font.weight: Style.fontWeightBold font.weight: Style.fontWeightBold
color: Colors.accentSecondary color: Colors.textPrimary
} }
RowLayout { RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
spacing: Style.marginMedium * scaling spacing: 16
// Avatar preview // Avatar preview
NImageRounded { NImageRounded {
width: 64 * scaling width: 64
height: 64 * scaling height: 64
imagePath: Settings.data.general.avatarImage imagePath: Settings.data.general.avatarImage
fallbackIcon: "person" fallbackIcon: "person"
borderColor: Colors.accentPrimary borderColor: Colors.accentPrimary
borderWidth: Math.max(1, Style.borderMedium * scaling) borderWidth: Math.max(1, Style.borderMedium)
} }
ColumnLayout { ColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
spacing: 2 * scaling spacing: 4
NText { NText {
text: "Profile Image" text: "Profile Image"
color: Colors.textPrimary color: Colors.textPrimary
@ -53,7 +78,7 @@ Item {
NText { NText {
text: "Your profile picture displayed in various places throughout the shell" text: "Your profile picture displayed in various places throughout the shell"
color: Colors.textSecondary color: Colors.textSecondary
font.pointSize: Style.fontSizeSmall * scaling font.pointSize: 12
} }
NTextInput { NTextInput {
text: Settings.data.general.avatarImage text: Settings.data.general.avatarImage
@ -65,18 +90,25 @@ Item {
} }
} }
} }
}
}
NDivider { NDivider {
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: Style.marginSmall * scaling Layout.topMargin: 26
Layout.bottomMargin: Style.marginSmall * scaling Layout.bottomMargin: 18
} }
// UI section ColumnLayout {
spacing: 4
Layout.fillWidth: true
NText { NText {
text: "User Interface" text: "User Interface"
font.pointSize: 18
font.weight: Style.fontWeightBold font.weight: Style.fontWeightBold
color: Colors.accentSecondary color: Colors.textPrimary
Layout.bottomMargin: 8
} }
NToggle { NToggle {
@ -105,9 +137,7 @@ Item {
Settings.data.general.dimDesktop = v Settings.data.general.dimDesktop = v
} }
} }
}
Item {
Layout.fillHeight: true
} }
} }
} }

View file

@ -1,48 +1,69 @@
import QtQuick import QtQuick
import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
Item { ColumnLayout {
property real scaling: 1 id: root
readonly property string tabIcon: "more_horiz"
readonly property string tabLabel: "Misc" spacing: 0
readonly property int tabIndex: 7
ScrollView {
id: scrollView
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
padding: 16
rightPadding: 12
clip: true
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
ScrollBar.vertical.policy: ScrollBar.AsNeeded
ColumnLayout { ColumnLayout {
anchors.fill: parent width: scrollView.availableWidth
spacing: Style.marginMedium * scaling spacing: 0
NText { Item {
text: "Media" Layout.fillWidth: true
font.weight: Style.fontWeightBold Layout.preferredHeight: 0
color: Colors.accentSecondary
} }
ColumnLayout {
spacing: 4
Layout.fillWidth: true
NText { NText {
text: "Visualizer Type" text: "Miscellaneous Settings"
font.pointSize: 18
font.weight: Style.fontWeightBold
color: Colors.textPrimary color: Colors.textPrimary
font.weight: Style.fontWeightBold Layout.bottomMargin: 8
} }
// Audio Visualizer section
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Layout.topMargin: 8
NText { NText {
text: "Choose the style of the audio visualizer" text: "Audio Visualizer"
color: Colors.textSecondary font.pointSize: 13
font.weight: Style.fontWeightBold
color: Colors.textPrimary
} }
NComboBox { NComboBox {
id: visualizerTypeComboBox optionsKeys: ["radial", "bars", "wave"]
optionsKeys: ["radial", "fire", "diamond"] optionsLabels: ["Radial", "Bars", "Wave"]
optionsLabels: ["Radial", "Fire", "Diamond"]
currentKey: Settings.data.audioVisualizer.type currentKey: Settings.data.audioVisualizer.type
onSelected: function (key) { onSelected: function (key) {
Settings.data.audioVisualizer.type = key Settings.data.audioVisualizer.type = key
} }
} }
}
Item { }
Layout.fillHeight: true
} }
} }
} }

View file

@ -1,64 +1,80 @@
import QtQuick import QtQuick
import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import Quickshell import Quickshell
import Quickshell.Bluetooth import Quickshell.Bluetooth
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
Item { ColumnLayout {
property real scaling: 1 id: root
readonly property string tabIcon: "wifi"
readonly property string tabLabel: "Network" spacing: 0
readonly property int tabIndex: 4
ScrollView {
id: scrollView
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
padding: 16
rightPadding: 12
clip: true
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
ScrollBar.vertical.policy: ScrollBar.AsNeeded
ColumnLayout { ColumnLayout {
anchors.fill: parent width: scrollView.availableWidth
spacing: Style.marginMedium * scaling spacing: 0
Item {
Layout.fillWidth: true
Layout.preferredHeight: 0
}
ColumnLayout {
spacing: 4
Layout.fillWidth: true
NText { NText {
text: "WiFi" text: "Network Settings"
font.pointSize: 18
font.weight: Style.fontWeightBold font.weight: Style.fontWeightBold
color: Colors.accentSecondary color: Colors.textPrimary
Layout.bottomMargin: 8
}
// Network interfaces section
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Layout.topMargin: 8
NText {
text: "Network Interfaces"
font.pointSize: 13
font.weight: Style.fontWeightBold
color: Colors.textPrimary
} }
NToggle { NToggle {
label: "Enable WiFi" label: "WiFi Enabled"
description: "Turn WiFi radio on or off" description: "Enable WiFi connectivity"
value: Settings.data.network.wifiEnabled value: Settings.data.network.wifiEnabled
onToggled: function (newValue) { onToggled: function (newValue) {
Settings.data.network.wifiEnabled = newValue Settings.data.network.wifiEnabled = newValue
Quickshell.execDetached(["nmcli", "radio", "wifi", newValue ? "on" : "off"])
} }
} }
NDivider {
Layout.fillWidth: true
}
NText {
text: "Bluetooth"
font.weight: Style.fontWeightBold
color: Colors.accentSecondary
}
NToggle { NToggle {
label: "Enable Bluetooth" label: "Bluetooth Enabled"
description: "Turn Bluetooth radio on or off" description: "Enable Bluetooth connectivity"
value: Settings.data.network.bluetoothEnabled value: Settings.data.network.bluetoothEnabled
onToggled: function (newValue) { onToggled: function (newValue) {
Settings.data.network.bluetoothEnabled = newValue Settings.data.network.bluetoothEnabled = newValue
if (Bluetooth.defaultAdapter) {
Bluetooth.defaultAdapter.enabled = newValue
if (Bluetooth.defaultAdapter.enabled)
Bluetooth.defaultAdapter.discovering = true
} }
} }
} }
}
Item {
Layout.fillHeight: true
} }
} }
} }

View file

@ -1,36 +1,67 @@
import QtQuick import QtQuick
import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
Item { ColumnLayout {
property real scaling: 1 id: root
readonly property string tabIcon: "videocam"
readonly property string tabLabel: "Screen Recorder" spacing: 0
readonly property int tabIndex: 3
ScrollView {
id: scrollView
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
padding: 16
rightPadding: 12
clip: true
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
ScrollBar.vertical.policy: ScrollBar.AsNeeded
ColumnLayout { ColumnLayout {
anchors.fill: parent width: scrollView.availableWidth
spacing: Style.marginMedium * scaling spacing: 0
Item {
Layout.fillWidth: true
Layout.preferredHeight: 0
}
ColumnLayout {
spacing: 4
Layout.fillWidth: true
NText { NText {
text: "Screen Recording" text: "Screen Recording"
font.pointSize: 18
font.weight: Style.fontWeightBold font.weight: Style.fontWeightBold
color: Colors.accentSecondary color: Colors.textPrimary
Layout.bottomMargin: 8
} }
// Output Directory // Output Directory
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Layout.topMargin: 8
NText { NText {
text: "Output Directory" text: "Output Directory"
color: Colors.textPrimary font.pointSize: 13
font.weight: Style.fontWeightBold font.weight: Style.fontWeightBold
color: Colors.textPrimary
} }
NText { NText {
text: "Directory where screen recordings will be saved" text: "Directory where screen recordings will be saved"
font.pointSize: 12
color: Colors.textSecondary color: Colors.textSecondary
wrapMode: Text.WordWrap
Layout.fillWidth: true
} }
NTextInput { NTextInput {
text: Settings.data.screenRecorder.directory text: Settings.data.screenRecorder.directory
Layout.fillWidth: true Layout.fillWidth: true
@ -38,66 +69,94 @@ Item {
Settings.data.screenRecorder.directory = text Settings.data.screenRecorder.directory = text
} }
} }
}
NDivider {
Layout.fillWidth: true
Layout.topMargin: 26
Layout.bottomMargin: 18
}
// Video Settings
ColumnLayout {
spacing: 4
Layout.fillWidth: true
NText {
text: "Video Settings"
font.pointSize: 18
font.weight: Style.fontWeightBold
color: Colors.textPrimary
Layout.bottomMargin: 8
}
// Frame Rate // Frame Rate
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Layout.topMargin: 8
NText { NText {
text: "Frame Rate" text: "Frame Rate"
color: Colors.textPrimary font.pointSize: 13
font.weight: Style.fontWeightBold font.weight: Style.fontWeightBold
color: Colors.textPrimary
} }
NText { NText {
text: "Target frame rate for screen recordings (default: 60)" text: "Target frame rate for screen recordings (default: 60)"
font.pointSize: 12
color: Colors.textSecondary color: Colors.textSecondary
wrapMode: Text.WordWrap
Layout.fillWidth: true
} }
RowLayout { RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
NText { NText {
text: Settings.data.screenRecorder.frameRate + " FPS" text: Settings.data.screenRecorder.frameRate + " FPS"
font.pointSize: 13
color: Colors.textPrimary color: Colors.textPrimary
} }
Item { Item {
Layout.fillWidth: true Layout.fillWidth: true
} }
} }
NSlider { NSlider {
Layout.fillWidth: true Layout.fillWidth: true
from: 24 from: 24
to: 144 to: 144
stepSize: 1 stepSize: 1
value: Settings.data.screenRecorder.frameRate value: Settings.data.screenRecorder.frameRate
onPressedChanged: Settings.data.screenRecorder.frameRate = Math.round(value) onMoved: Settings.data.screenRecorder.frameRate = Math.round(value)
cutoutColor: Colors.surface cutoutColor: Colors.backgroundPrimary
}
// Audio Source
NText {
text: "Audio Source"
color: Colors.textPrimary
font.weight: Style.fontWeightBold
}
NText {
text: "Audio source to capture during recording"
color: Colors.textSecondary
}
NComboBox {
optionsKeys: ["default_output", "default_input", "both"]
optionsLabels: ["System Audio", "Microphone", "System Audio + Microphone"]
currentKey: Settings.data.screenRecorder.audioSource
onSelected: function (key) {
Settings.data.screenRecorder.audioSource = key
} }
} }
// Video Quality // Video Quality
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Layout.topMargin: 8
NText { NText {
text: "Video Quality" text: "Video Quality"
color: Colors.textPrimary font.pointSize: 13
font.weight: Style.fontWeightBold font.weight: Style.fontWeightBold
color: Colors.textPrimary
} }
NText { NText {
text: "Higher quality results in larger file sizes" text: "Higher quality results in larger file sizes"
font.pointSize: 12
color: Colors.textSecondary color: Colors.textSecondary
wrapMode: Text.WordWrap
Layout.fillWidth: true
} }
NComboBox { NComboBox {
optionsKeys: ["medium", "high", "very_high", "ultra"] optionsKeys: ["medium", "high", "very_high", "ultra"]
optionsLabels: ["Medium", "High", "Very High", "Ultra"] optionsLabels: ["Medium", "High", "Very High", "Ultra"]
@ -106,17 +165,29 @@ Item {
Settings.data.screenRecorder.quality = key Settings.data.screenRecorder.quality = key
} }
} }
}
// Video Codec // Video Codec
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Layout.topMargin: 8
NText { NText {
text: "Video Codec" text: "Video Codec"
color: Colors.textPrimary font.pointSize: 13
font.weight: Style.fontWeightBold font.weight: Style.fontWeightBold
color: Colors.textPrimary
} }
NText { NText {
text: "Different codecs offer different compression and compatibility" text: "Different codecs offer different compression and compatibility"
font.pointSize: 12
color: Colors.textSecondary color: Colors.textSecondary
wrapMode: Text.WordWrap
Layout.fillWidth: true
} }
NComboBox { NComboBox {
optionsKeys: ["h264", "hevc", "av1", "vp8", "vp9"] optionsKeys: ["h264", "hevc", "av1", "vp8", "vp9"]
optionsLabels: ["H264", "HEVC", "AV1", "VP8", "VP9"] optionsLabels: ["H264", "HEVC", "AV1", "VP8", "VP9"]
@ -125,36 +196,29 @@ Item {
Settings.data.screenRecorder.videoCodec = key Settings.data.screenRecorder.videoCodec = key
} }
} }
// Audio Codec
NText {
text: "Audio Codec"
color: Colors.textPrimary
font.weight: Style.fontWeightBold
}
NText {
text: "Opus is recommended for best performance and smallest audio size"
color: Colors.textSecondary
}
NComboBox {
optionsKeys: ["opus", "aac"]
optionsLabels: ["OPUS", "AAC"]
currentKey: Settings.data.screenRecorder.audioCodec
onSelected: function (key) {
Settings.data.screenRecorder.audioCodec = key
}
} }
// Color Range // Color Range
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Layout.topMargin: 8
NText { NText {
text: "Color Range" text: "Color Range"
color: Colors.textPrimary font.pointSize: 13
font.weight: Style.fontWeightBold font.weight: Style.fontWeightBold
color: Colors.textPrimary
} }
NText { NText {
text: "Limited is recommended for better compatibility" text: "Limited is recommended for better compatibility"
font.pointSize: 12
color: Colors.textSecondary color: Colors.textSecondary
wrapMode: Text.WordWrap
Layout.fillWidth: true
} }
NComboBox { NComboBox {
optionsKeys: ["limited", "full"] optionsKeys: ["limited", "full"]
optionsLabels: ["Limited", "Full"] optionsLabels: ["Limited", "Full"]
@ -163,7 +227,91 @@ Item {
Settings.data.screenRecorder.colorRange = key Settings.data.screenRecorder.colorRange = key
} }
} }
}
}
NDivider {
Layout.fillWidth: true
Layout.topMargin: 26
Layout.bottomMargin: 18
}
// Audio Settings
ColumnLayout {
spacing: 4
Layout.fillWidth: true
NText {
text: "Audio Settings"
font.pointSize: 18
font.weight: Style.fontWeightBold
color: Colors.textPrimary
Layout.bottomMargin: 8
}
// Audio Source
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Layout.topMargin: 8
NText {
text: "Audio Source"
font.pointSize: 13
font.weight: Style.fontWeightBold
color: Colors.textPrimary
}
NText {
text: "Audio source to capture during recording"
font.pointSize: 12
color: Colors.textSecondary
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
NComboBox {
optionsKeys: ["default_output", "default_input", "both"]
optionsLabels: ["System Audio", "Microphone", "System Audio + Microphone"]
currentKey: Settings.data.screenRecorder.audioSource
onSelected: function (key) {
Settings.data.screenRecorder.audioSource = key
}
}
}
// Audio Codec
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Layout.topMargin: 8
NText {
text: "Audio Codec"
font.pointSize: 13
font.weight: Style.fontWeightBold
color: Colors.textPrimary
}
NText {
text: "Opus is recommended for best performance and smallest audio size"
font.pointSize: 12
color: Colors.textSecondary
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
NComboBox {
optionsKeys: ["opus", "aac"]
optionsLabels: ["OPUS", "AAC"]
currentKey: Settings.data.screenRecorder.audioCodec
onSelected: function (key) {
Settings.data.screenRecorder.audioCodec = key
}
}
}
// Show Cursor
NToggle { NToggle {
label: "Show Cursor" label: "Show Cursor"
description: "Record mouse cursor in the video" description: "Record mouse cursor in the video"
@ -172,9 +320,8 @@ Item {
Settings.data.screenRecorder.showCursor = newValue Settings.data.screenRecorder.showCursor = newValue
} }
} }
}
Item { }
Layout.fillHeight: true
} }
} }
} }

View file

@ -1,29 +1,91 @@
import QtQuick import QtQuick
import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
Item { ColumnLayout {
property real scaling: 1 id: root
readonly property string tabIcon: "schedule"
readonly property string tabLabel: "Time & Weather" spacing: 0
readonly property int tabIndex: 2
ScrollView {
id: scrollView
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
padding: 16
rightPadding: 12
clip: true
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
ScrollBar.vertical.policy: ScrollBar.AsNeeded
ColumnLayout { ColumnLayout {
anchors.fill: parent width: scrollView.availableWidth
spacing: Style.marginMedium * scaling spacing: 0
Item {
Layout.fillWidth: true
Layout.preferredHeight: 0
}
ColumnLayout {
spacing: 4
Layout.fillWidth: true
NText { NText {
text: "Time" text: "Time & Weather Settings"
font.pointSize: 18
font.weight: Style.fontWeightBold font.weight: Style.fontWeightBold
color: Colors.accentSecondary color: Colors.textPrimary
Layout.bottomMargin: 8
}
// Location section
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Layout.topMargin: 8
NText {
text: "Location"
font.pointSize: 13
font.weight: Style.fontWeightBold
color: Colors.textPrimary
}
NTextInput {
text: Settings.data.location.name
placeholderText: "Enter city name"
Layout.fillWidth: true
onEditingFinished: function () {
Settings.data.location.name = text
}
}
}
NDivider {
Layout.fillWidth: true
Layout.topMargin: 26
Layout.bottomMargin: 18
}
// Time section
ColumnLayout {
spacing: 4
Layout.fillWidth: true
NText {
text: "Time Format"
font.pointSize: 18
font.weight: Style.fontWeightBold
color: Colors.textPrimary
Layout.bottomMargin: 8
} }
NToggle { NToggle {
label: "Use 12 Hour Clock" label: "Use 12-Hour Clock"
description: "Display time in 12-hour format (e.g., 2:30 PM) instead of 24-hour format" description: "Display time in 12-hour format (AM/PM) instead of 24-hour"
value: Settings.data.location.use12HourClock value: Settings.data.location.use12HourClock
onToggled: function (newValue) { onToggled: function (newValue) {
Settings.data.location.use12HourClock = newValue Settings.data.location.use12HourClock = newValue
@ -31,64 +93,44 @@ Item {
} }
NToggle { NToggle {
label: "US Style Date" label: "Reverse Day/Month"
description: "Display dates in MM/DD/YYYY format instead of DD/MM/YYYY" description: "Display date as DD/MM instead of MM/DD"
value: Settings.data.location.reverseDayMonth value: Settings.data.location.reverseDayMonth
onToggled: function (newValue) { onToggled: function (newValue) {
Settings.data.location.reverseDayMonth = newValue Settings.data.location.reverseDayMonth = newValue
} }
} }
}
NDivider { NDivider {
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 26
Layout.bottomMargin: 18
} }
// Weather section
ColumnLayout {
spacing: 4
Layout.fillWidth: true
NText { NText {
text: "Weather" text: "Weather"
font.pointSize: 18
font.weight: Style.fontWeightBold font.weight: Style.fontWeightBold
color: Colors.accentSecondary
}
NText {
text: "Location"
color: Colors.textPrimary color: Colors.textPrimary
font.weight: Style.fontWeightBold Layout.bottomMargin: 8
}
NText {
text: "Your city name for weather information"
color: Colors.textSecondary
font.pointSize: Style.fontSizeSmall * scaling
}
NTextInput {
text: Settings.data.location.name
Layout.fillWidth: true
onEditingFinished: function () {
Settings.data.location.name = text
Location.resetWeather()
}
} }
NText { NToggle {
text: "Temperature Unit" label: "Use Fahrenheit"
color: Colors.textPrimary description: "Display temperature in Fahrenheit instead of Celsius"
font.weight: Style.fontWeightBold value: Settings.data.location.useFahrenheit
} onToggled: function (newValue) {
NText { Settings.data.location.useFahrenheit = newValue
text: "Choose between Celsius and Fahrenheit" }
color: Colors.textSecondary }
font.pointSize: Style.fontSizeSmall * scaling
}
NComboBox {
optionsKeys: ["c", "f"]
optionsLabels: ["Celsius", "Fahrenheit"]
currentKey: Settings.data.location.useFahrenheit ? "f" : "c"
onSelected: function (key) {
Settings.data.location.useFahrenheit = (key === "f")
} }
} }
Item {
Layout.fillHeight: true
} }
} }
} }

View file

@ -1,37 +1,72 @@
import QtQuick import QtQuick
import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import qs.Services import qs.Services
import qs.Widgets import qs.Widgets
Item { ColumnLayout {
property real scaling: 1 id: root
readonly property string tabIcon: "image"
readonly property string tabLabel: "Wallpaper" spacing: 0
readonly property int tabIndex: 6
ScrollView {
id: scrollView
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
padding: 16
rightPadding: 12
clip: true
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
ScrollBar.vertical.policy: ScrollBar.AsNeeded
ColumnLayout { ColumnLayout {
anchors.fill: parent width: scrollView.availableWidth
spacing: Style.marginMedium * scaling spacing: 0
Item {
Layout.fillWidth: true
Layout.preferredHeight: 0
}
ColumnLayout {
spacing: 4
Layout.fillWidth: true
NText { NText {
text: "Wallpaper Settings" text: "Wallpaper Settings"
font.pointSize: 18
font.weight: Style.fontWeightBold font.weight: Style.fontWeightBold
color: Colors.accentSecondary color: Colors.textPrimary
Layout.bottomMargin: 8
} }
// Folder // Wallpaper Settings Category
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Layout.topMargin: 8
// Wallpaper Folder
ColumnLayout {
spacing: 8
Layout.fillWidth: true
NText { NText {
text: "Wallpaper Folder" text: "Wallpaper Folder"
font.pointSize: 13
font.weight: Style.fontWeightBold font.weight: Style.fontWeightBold
color: Colors.textPrimary
} }
NText { NText {
text: "Path to your wallpaper folder" text: "Path to your wallpaper folder"
font.pointSize: 12
color: Colors.textSecondary color: Colors.textSecondary
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
Layout.fillWidth: true
} }
NTextInput { NTextInput {
text: Settings.data.wallpaper.directory text: Settings.data.wallpaper.directory
Layout.fillWidth: true Layout.fillWidth: true
@ -39,18 +74,29 @@ Item {
Settings.data.wallpaper.directory = text Settings.data.wallpaper.directory = text
} }
} }
}
}
}
NDivider { NDivider {
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 26
Layout.bottomMargin: 18
} }
// ---------------------------- ColumnLayout {
spacing: 4
Layout.fillWidth: true
NText { NText {
text: "Automation" text: "Automation"
font.pointSize: 18
font.weight: Style.fontWeightBold font.weight: Style.fontWeightBold
color: Colors.accentSecondary color: Colors.textPrimary
Layout.bottomMargin: 8
} }
// Random Wallpaper
NToggle { NToggle {
label: "Random Wallpaper" label: "Random Wallpaper"
description: "Automatically select random wallpapers from the folder" description: "Automatically select random wallpapers from the folder"
@ -60,6 +106,7 @@ Item {
} }
} }
// Use Wallpaper Theme
NToggle { NToggle {
label: "Use Wallpaper Theme" label: "Use Wallpaper Theme"
description: "Automatically adjust theme colors based on wallpaper" description: "Automatically adjust theme colors based on wallpaper"
@ -69,45 +116,72 @@ Item {
} }
} }
// Wallpaper Interval
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Layout.topMargin: 8
NText { NText {
text: "Wallpaper Interval" text: "Wallpaper Interval"
color: Colors.textPrimary font.pointSize: 13
font.weight: Style.fontWeightBold font.weight: Style.fontWeightBold
color: Colors.textPrimary
} }
NText { NText {
text: "How often to change wallpapers automatically (in seconds)" text: "How often to change wallpapers automatically (in seconds)"
font.pointSize: 12
color: Colors.textSecondary color: Colors.textSecondary
wrapMode: Text.WordWrap
Layout.fillWidth: true
} }
RowLayout { RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
NText { NText {
text: Settings.data.wallpaper.randomInterval + " seconds" text: Settings.data.wallpaper.randomInterval + " seconds"
font.pointSize: 13
color: Colors.textPrimary color: Colors.textPrimary
} }
Item { Item {
Layout.fillWidth: true Layout.fillWidth: true
} }
} }
NSlider { NSlider {
Layout.fillWidth: true Layout.fillWidth: true
from: 10 from: 10
to: 900 to: 900
stepSize: 10 stepSize: 10
value: Settings.data.wallpaper.randomInterval value: Settings.data.wallpaper.randomInterval
onPressedChanged: Settings.data.wallpaper.randomInterval = Math.round(value) onMoved: Settings.data.wallpaper.randomInterval = Math.round(value)
cutoutColor: Colors.backgroundPrimary cutoutColor: Colors.backgroundPrimary
} }
}
}
NDivider { NDivider {
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 26
Layout.bottomMargin: 18
} }
ColumnLayout {
spacing: 4
Layout.fillWidth: true
NText { NText {
text: "SWWW" text: "SWWW"
font.pointSize: 18
font.weight: Style.fontWeightBold font.weight: Style.fontWeightBold
color: Colors.accentSecondary color: Colors.textPrimary
Layout.bottomMargin: 8
} }
// Use SWWW
NToggle { NToggle {
label: "Use SWWW" label: "Use SWWW"
description: "Use SWWW daemon for advanced wallpaper management" description: "Use SWWW daemon for advanced wallpaper management"
@ -117,20 +191,33 @@ Item {
} }
} }
// SWWW settings // SWWW Settings (only visible when useSWWW is enabled)
ColumnLayout { ColumnLayout {
spacing: Style.marginSmall * scaling spacing: 8
Layout.fillWidth: true
Layout.topMargin: 8
visible: Settings.data.wallpaper.swww.enabled visible: Settings.data.wallpaper.swww.enabled
// Resize Mode
ColumnLayout {
spacing: 8
Layout.fillWidth: true
NText { NText {
text: "Resize Mode" text: "Resize Mode"
font.pointSize: 13
font.weight: Style.fontWeightBold font.weight: Style.fontWeightBold
color: Colors.textPrimary
} }
NText { NText {
text: "How SWWW should resize wallpapers to fit the screen" text: "How SWWW should resize wallpapers to fit the screen"
font.pointSize: 12
color: Colors.textSecondary color: Colors.textSecondary
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
Layout.fillWidth: true
} }
NComboBox { NComboBox {
optionsKeys: ["no", "crop", "fit", "stretch"] optionsKeys: ["no", "crop", "fit", "stretch"]
optionsLabels: ["No", "Crop", "Fit", "Stretch"] optionsLabels: ["No", "Crop", "Fit", "Stretch"]
@ -139,16 +226,29 @@ Item {
Settings.data.wallpaper.swww.resizeMethod = key Settings.data.wallpaper.swww.resizeMethod = key
} }
} }
}
// Transition Type
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Layout.topMargin: 8
NText { NText {
text: "Transition Type" text: "Transition Type"
font.pointSize: 13
font.weight: Style.fontWeightBold font.weight: Style.fontWeightBold
color: Colors.textPrimary
} }
NText { NText {
text: "Animation type when switching between wallpapers" text: "Animation type when switching between wallpapers"
font.pointSize: 12
color: Colors.textSecondary color: Colors.textSecondary
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
Layout.fillWidth: true
} }
NComboBox { NComboBox {
optionsKeys: ["none", "simple", "fade", "left", "right", "top", "bottom", "wipe", "wave", "grow", "center", "any", "outer", "random"] optionsKeys: ["none", "simple", "fade", "left", "right", "top", "bottom", "wipe", "wave", "grow", "center", "any", "outer", "random"]
optionsLabels: ["None", "Simple", "Fade", "Left", "Right", "Top", "Bottom", "Wipe", "Wave", "Grow", "Center", "Any", "Outer", "Random"] optionsLabels: ["None", "Simple", "Fade", "Left", "Right", "Top", "Bottom", "Wipe", "Wave", "Grow", "Center", "Any", "Outer", "Random"]
@ -157,59 +257,101 @@ Item {
Settings.data.wallpaper.swww.transitionType = key Settings.data.wallpaper.swww.transitionType = key
} }
} }
}
// Transition FPS
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Layout.topMargin: 8
NText { NText {
text: "Transition FPS" text: "Transition FPS"
font.pointSize: 13
font.weight: Style.fontWeightBold font.weight: Style.fontWeightBold
}
RowLayout {
Layout.fillWidth: true
NText {
text: Settings.data.wallpaper.swww.transitionFps + " FPS"
color: Colors.textPrimary color: Colors.textPrimary
} }
NText {
text: "Frames per second for transition animations"
font.pointSize: 12
color: Colors.textSecondary
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
RowLayout {
Layout.fillWidth: true
NText {
text: Settings.data.wallpaper.swww.transitionFps + " FPS"
font.pointSize: 13
color: Colors.textPrimary
}
Item { Item {
Layout.fillWidth: true Layout.fillWidth: true
} }
} }
NSlider { NSlider {
Layout.fillWidth: true Layout.fillWidth: true
from: 30 from: 30
to: 500 to: 500
stepSize: 5 stepSize: 5
value: Settings.data.wallpaper.swww.transitionFps value: Settings.data.wallpaper.swww.transitionFps
onPressedChanged: Settings.data.wallpaper.swww.transitionFps = Math.round(value) onMoved: Settings.data.wallpaper.swww.transitionFps = Math.round(value)
cutoutColor: Colors.backgroundPrimary cutoutColor: Colors.backgroundPrimary
} }
}
// Transition Duration
ColumnLayout {
spacing: 8
Layout.fillWidth: true
Layout.topMargin: 8
NText { NText {
text: "Transition Duration" text: "Transition Duration"
color: Colors.textPrimary font.pointSize: 13
font.weight: Style.fontWeightBold font.weight: Style.fontWeightBold
color: Colors.textPrimary
} }
NText {
text: "Duration of transition animations in seconds"
font.pointSize: 12
color: Colors.textSecondary
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
RowLayout { RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
NText { NText {
text: Settings.data.wallpaper.swww.transitionDuration.toFixed(2) + " s" text: Settings.data.wallpaper.swww.transitionDuration.toFixed(3) + " seconds"
font.pointSize: 13
color: Colors.textPrimary color: Colors.textPrimary
} }
Item { Item {
Layout.fillWidth: true Layout.fillWidth: true
} }
} }
NSlider { NSlider {
Layout.fillWidth: true Layout.fillWidth: true
from: 0.25 from: 0.25
to: 10 to: 10
stepSize: 0.05 stepSize: 0.05
value: Settings.data.wallpaper.swww.transitionDuration value: Settings.data.wallpaper.swww.transitionDuration
onPressedChanged: Settings.data.wallpaper.swww.transitionDuration = value onMoved: Settings.data.wallpaper.swww.transitionDuration = value
cutoutColor: Colors.backgroundPrimary cutoutColor: Colors.backgroundPrimary
} }
} }
}
Item { }
Layout.fillHeight: true
} }
} }
} }

View file

@ -0,0 +1,270 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import Qt.labs.folderlistmodel
import qs.Services
import qs.Widgets
Item {
property real scaling: 1
readonly property string tabIcon: "photo_library"
readonly property string tabLabel: "Wallpaper Selector"
readonly property int tabIndex: 7
Layout.fillWidth: true
Layout.fillHeight: true
ColumnLayout {
anchors.fill: parent
spacing: Style.marginMedium * scaling
NText {
text: "Wallpaper Selector"
font.weight: Style.fontWeightBold
color: Colors.accentSecondary
}
NText {
text: "Select a wallpaper from your configured directory"
color: Colors.textSecondary
wrapMode: Text.WordWrap
}
// Current wallpaper display
NText {
text: "Current Wallpaper"
font.weight: Style.fontWeightBold
color: Colors.textPrimary
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 120 * scaling
radius: Style.radiusMedium * scaling
color: Colors.backgroundSecondary
border.color: Colors.outline
border.width: Math.max(1, Style.borderThin * scaling)
clip: true
Image {
id: currentWallpaperImage
anchors.fill: parent
anchors.margins: Style.marginSmall * scaling
source: Wallpapers.currentWallpaper
fillMode: Image.PreserveAspectCrop
asynchronous: true
cache: true
}
// Fallback if no image
Rectangle {
anchors.fill: parent
anchors.margins: Style.marginSmall * scaling
color: Colors.backgroundTertiary
radius: Style.radiusSmall * scaling
visible: currentWallpaperImage.status !== Image.Ready
ColumnLayout {
anchors.centerIn: parent
spacing: Style.marginSmall * scaling
NText {
text: "image"
font.family: "Material Symbols Outlined"
font.pointSize: Style.fontSizeLarge * scaling
color: Colors.textSecondary
Layout.alignment: Qt.AlignHCenter
}
NText {
text: "No wallpaper selected"
color: Colors.textSecondary
Layout.alignment: Qt.AlignHCenter
}
}
}
}
NDivider {
Layout.fillWidth: true
}
// Wallpaper grid
NText {
text: "Available Wallpapers"
font.weight: Style.fontWeightBold
color: Colors.textPrimary
}
NText {
text: "Click on a wallpaper to set it as your current wallpaper"
color: Colors.textSecondary
wrapMode: Text.WordWrap
}
NText {
text: Settings.data.wallpaper.swww.enabled ?
"Wallpapers will change with " + Settings.data.wallpaper.swww.transitionType + " transition" :
"Wallpapers will change instantly"
color: Colors.textSecondary
font.pointSize: Style.fontSizeSmall * scaling
visible: Settings.data.wallpaper.swww.enabled
}
// Refresh button and status
RowLayout {
Layout.fillWidth: true
spacing: Style.marginSmall * scaling
NIconButton {
icon: "refresh"
tooltipText: "Refresh wallpaper list"
onClicked: {
Wallpapers.loadWallpapers()
}
}
NText {
text: "Refresh"
color: Colors.textSecondary
}
}
// Wallpaper grid container
Item {
Layout.fillWidth: true
Layout.fillHeight: true
FolderListModel {
id: folderModel
folder: "file://" + (Settings.data.wallpaper.directory !== undefined ? Settings.data.wallpaper.directory : "")
nameFilters: ["*.jpg", "*.jpeg", "*.png", "*.gif", "*.pnm", "*.bmp"]
showDirs: false
sortField: FolderListModel.Name
}
GridView {
id: wallpaperGridView
anchors.fill: parent
clip: true
model: folderModel
// Fixed 5 items per row - more aggressive sizing
property int itemSize: Math.floor((width - leftMargin - rightMargin - (4 * Style.marginSmall * scaling)) / 5)
cellWidth: Math.floor((width - leftMargin - rightMargin) / 5)
cellHeight: Math.floor(itemSize * 0.67) + Style.marginSmall * scaling
leftMargin: Style.marginSmall * scaling
rightMargin: Style.marginSmall * scaling
topMargin: Style.marginSmall * scaling
bottomMargin: Style.marginSmall * scaling
delegate: Rectangle {
id: wallpaperItem
property string wallpaperPath: Settings.data.wallpaper.directory + "/" + fileName
property bool isSelected: wallpaperPath === Wallpapers.currentWallpaper
width: wallpaperGridView.itemSize
height: Math.floor(wallpaperGridView.itemSize * 0.67)
radius: Style.radiusMedium * scaling
color: isSelected ? Colors.accentPrimary : Colors.backgroundSecondary
border.color: isSelected ? Colors.accentSecondary : Colors.outline
border.width: Math.max(1, Style.borderThin * scaling)
clip: true
Image {
anchors.fill: parent
anchors.margins: Style.marginTiny * scaling
source: wallpaperPath
fillMode: Image.PreserveAspectCrop
asynchronous: true
cache: true
smooth: true
}
// Selection indicator
Rectangle {
anchors.top: parent.top
anchors.right: parent.right
anchors.margins: Style.marginTiny * scaling
width: 20 * scaling
height: 20 * scaling
radius: width / 2
color: Colors.accentPrimary
border.color: Colors.onAccent
border.width: Math.max(1, Style.borderThin * scaling)
visible: isSelected
NText {
anchors.centerIn: parent
text: "check"
font.family: "Material Symbols Outlined"
font.pointSize: Style.fontSizeSmall * scaling
color: Colors.onAccent
}
}
// Hover effect
Rectangle {
anchors.fill: parent
color: Colors.textPrimary
opacity: mouseArea.containsMouse ? 0.1 : 0
radius: parent.radius
Behavior on opacity {
NumberAnimation { duration: 150 }
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
acceptedButtons: Qt.LeftButton
hoverEnabled: true
onClicked: {
Wallpapers.changeWallpaper(wallpaperPath)
}
}
}
}
// Empty state
Rectangle {
anchors.fill: parent
color: Colors.backgroundSecondary
radius: Style.radiusMedium * scaling
border.color: Colors.outline
border.width: Math.max(1, Style.borderThin * scaling)
visible: folderModel.count === 0 && !Wallpapers.scanning
ColumnLayout {
anchors.centerIn: parent
spacing: Style.marginMedium * scaling
NText {
text: "folder_open"
font.family: "Material Symbols Outlined"
font.pointSize: Style.fontSizeLarge * scaling
color: Colors.textSecondary
Layout.alignment: Qt.AlignHCenter
}
NText {
text: "No wallpapers found"
color: Colors.textSecondary
font.weight: Style.fontWeightBold
Layout.alignment: Qt.AlignHCenter
}
NText {
text: "Make sure your wallpaper directory is configured and contains image files"
color: Colors.textSecondary
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignHCenter
Layout.preferredWidth: 300 * scaling
}
}
}
}
}
}

View file

@ -50,7 +50,14 @@ Singleton {
Component.onCompleted: function () { Component.onCompleted: function () {
reload() reload()
} }
onLoaded: function () {} onLoaded: function () {
Qt.callLater(function () {
if (adapter.wallpaper.current !== "") {
console.log("Settings: Initializing wallpaper to:", adapter.wallpaper.current)
Wallpapers.setCurrentWallpaper(adapter.wallpaper.current, true)
}
})
}
onLoadFailed: function (error) { onLoadFailed: function (error) {
if (error.toString().includes("No such file") || error === 2) if (error.toString().includes("No such file") || error === 2)
// File doesn't exist, create it with default values // File doesn't exist, create it with default values
@ -113,7 +120,7 @@ Singleton {
wallpaper: JsonObject { wallpaper: JsonObject {
property string directory: "/usr/share/wallpapers" property string directory: "/usr/share/wallpapers"
property string current: defaultWallpaper property string current: ""
property bool isRandom: false property bool isRandom: false
property int randomInterval: 300 property int randomInterval: 300
property bool generateTheme: false property bool generateTheme: false
@ -178,4 +185,11 @@ Singleton {
} }
} }
} }
Connections {
target: adapter.wallpaper
function onIsRandomChanged() { Wallpapers.toggleRandomWallpaper() }
function onRandomIntervalChanged() { Wallpapers.restartRandomWallpaperTimer() }
function onDirectoryChanged() { Wallpapers.loadWallpapers() }
}
} }

View file

@ -11,8 +11,13 @@ Singleton {
Item { Item {
Component.onCompleted: { Component.onCompleted: {
loadWallpapers() loadWallpapers()
// Only set initial wallpaper if it's not empty
if (currentWallpaper !== "") {
console.log("Wallpapers: Initializing with wallpaper:", currentWallpaper)
setCurrentWallpaper(currentWallpaper, true) setCurrentWallpaper(currentWallpaper, true)
toggleRandomWallpaper() }
// Don't start random wallpaper during initialization
// toggleRandomWallpaper()
} }
} }
@ -20,7 +25,7 @@ Singleton {
property string currentWallpaper: Settings.data.wallpaper.current property string currentWallpaper: Settings.data.wallpaper.current
property bool scanning: false property bool scanning: false
property string transitionType: Settings.data.wallpaper.swww.transitionType property string transitionType: Settings.data.wallpaper.swww.transitionType
property var randomChoices: ["fade", "left", "right", "top", "bottom", "wipe", "wave", "grow", "center", "any", "outer"] property var randomChoices: ["simple", "fade", "left", "right", "top", "bottom", "wipe", "wave", "grow", "center", "any", "outer"]
function loadWallpapers() { function loadWallpapers() {
scanning = true scanning = true
@ -29,10 +34,12 @@ Singleton {
} }
function changeWallpaper(path) { function changeWallpaper(path) {
setCurrentWallpaper(path) console.log("Wallpapers: changeWallpaper called with:", path)
setCurrentWallpaper(path, false)
} }
function setCurrentWallpaper(path, isInitial) { function setCurrentWallpaper(path, isInitial) {
console.log("Wallpapers: Setting wallpaper to:", path, "isInitial:", isInitial)
currentWallpaper = path currentWallpaper = path
if (!isInitial) { if (!isInitial) {
Settings.data.wallpaper.current = path Settings.data.wallpaper.current = path
@ -43,7 +50,11 @@ Singleton {
} else { } else {
transitionType = Settings.data.wallpaper.swww.transitionType transitionType = Settings.data.wallpaper.swww.transitionType
} }
console.log("SWWW: Changing wallpaper with transition type:", transitionType)
changeWallpaperProcess.running = true changeWallpaperProcess.running = true
} else {
// Fallback: update the settings directly for non-SWWW mode
console.log("Non-SWWW mode: Setting wallpaper directly")
} }
if (randomWallpaperTimer.running) { if (randomWallpaperTimer.running) {
@ -59,7 +70,7 @@ Singleton {
if (!randomPath) { if (!randomPath) {
return return
} }
setCurrentWallpaper(randomPath) setCurrentWallpaper(randomPath, false)
} }
function toggleRandomWallpaper() { function toggleRandomWallpaper() {
@ -84,6 +95,13 @@ Singleton {
} }
} }
function startSWWWDaemon() {
if (Settings.data.wallpaper.swww.enabled) {
console.log("SWWW: Attempting to start swww-daemon...")
startDaemonProcess.running = true
}
}
Timer { Timer {
id: randomWallpaperTimer id: randomWallpaperTimer
interval: Settings.data.wallpaper.randomInterval * 1000 interval: Settings.data.wallpaper.randomInterval * 1000
@ -120,6 +138,18 @@ Singleton {
), "--transition-type", transitionType, "--transition-duration", Settings.data.wallpaper.swww.transitionDuration.toString( ), "--transition-type", transitionType, "--transition-duration", Settings.data.wallpaper.swww.transitionDuration.toString(
), currentWallpaper] ), currentWallpaper]
running: false running: false
onStarted: {
console.log("SWWW: Process started with command:", command.join(" "))
}
onExited: function(exitCode, exitStatus) {
console.log("SWWW: Process finished with exit code:", exitCode, "status:", exitStatus)
if (exitCode !== 0) {
console.log("SWWW: Process failed. Make sure swww-daemon is running with: swww-daemon")
console.log("SWWW: You can start it with: swww-daemon --format xrgb")
}
}
} }
Process { Process {
@ -128,4 +158,23 @@ Singleton {
workingDirectory: Quickshell.shellDir workingDirectory: Quickshell.shellDir
running: false running: false
} }
Process {
id: startDaemonProcess
command: ["swww-daemon", "--format", "xrgb"]
running: false
onStarted: {
console.log("SWWW: Daemon start process initiated")
}
onExited: function(exitCode, exitStatus) {
console.log("SWWW: Daemon start process finished with exit code:", exitCode)
if (exitCode === 0) {
console.log("SWWW: Daemon started successfully")
} else {
console.log("SWWW: Failed to start daemon. It might already be running.")
}
}
}
} }