Wallpaper rework
- removed swww to the code is easier to maintain - basic multi monitor wallpaper support
This commit is contained in:
parent
3cc8c8fb03
commit
e79c163dd9
12 changed files with 330 additions and 552 deletions
|
|
@ -94,10 +94,10 @@ Singleton {
|
|||
// And not on every reload
|
||||
if (!isLoaded) {
|
||||
Logger.log("Settings", "JSON completed loading")
|
||||
if (adapter.wallpaper.current !== "") {
|
||||
Logger.log("Settings", "Set current wallpaper", adapter.wallpaper.current)
|
||||
WallpaperService.setCurrentWallpaper(adapter.wallpaper.current, true)
|
||||
}
|
||||
// if (adapter.wallpaper.current !== "") {
|
||||
// Logger.log("Settings", "Set current wallpaper", adapter.wallpaper.current)
|
||||
// WallpaperService.setCurrentWallpaper(adapter.wallpaper.current, true)
|
||||
// }
|
||||
|
||||
// Validate monitor configurations, only once
|
||||
// if none of the configured monitors exist, clear the lists
|
||||
|
|
@ -171,22 +171,13 @@ Singleton {
|
|||
// wallpaper
|
||||
property JsonObject wallpaper: JsonObject {
|
||||
property string directory: "/usr/share/wallpapers"
|
||||
property string current: ""
|
||||
property bool isRandom: false
|
||||
property int randomInterval: 300
|
||||
property JsonObject swww
|
||||
|
||||
onDirectoryChanged: WallpaperService.listWallpapers()
|
||||
onIsRandomChanged: WallpaperService.toggleRandomWallpaper()
|
||||
onRandomIntervalChanged: WallpaperService.restartRandomWallpaperTimer()
|
||||
|
||||
swww: JsonObject {
|
||||
property bool enabled: false
|
||||
property string resizeMethod: "crop"
|
||||
property int transitionFps: 60
|
||||
property string transitionType: "random"
|
||||
property real transitionDuration: 1.1
|
||||
}
|
||||
property bool enableMultiMonitorDirectories: false
|
||||
property bool setWallpaperOnAllMonitors: true
|
||||
property bool randomEnabled: false
|
||||
property int randomIntervalSec: 300 // 5 min
|
||||
property int transitionDuration: 1500 // 1500 ms
|
||||
property string transitionType: "fade"
|
||||
property list<var> monitors: []
|
||||
}
|
||||
|
||||
// applauncher
|
||||
|
|
@ -234,19 +225,10 @@ Singleton {
|
|||
property string fontDefault: "Roboto" // Default font for all text
|
||||
property string fontFixed: "DejaVu Sans Mono" // Fixed width font for terminal
|
||||
property string fontBillboard: "Inter" // Large bold font for clocks and prominent displays
|
||||
|
||||
// Legacy compatibility
|
||||
property string fontFamily: fontDefault // Keep for backward compatibility
|
||||
|
||||
// Idle inhibitor state
|
||||
property list<var> monitorsScaling: []
|
||||
property bool idleInhibitorEnabled: false
|
||||
}
|
||||
|
||||
// Scaling (not stored inside JsonObject, or it crashes)
|
||||
property var monitorsScaling: {
|
||||
|
||||
}
|
||||
|
||||
// brightness
|
||||
property JsonObject brightness: JsonObject {
|
||||
property int brightnessStep: 5
|
||||
|
|
|
|||
|
|
@ -5,26 +5,16 @@ import qs.Commons
|
|||
import qs.Services
|
||||
|
||||
Loader {
|
||||
active: !Settings.data.wallpaper.swww.enabled
|
||||
active: true
|
||||
|
||||
sourceComponent: Variants {
|
||||
model: Quickshell.screens
|
||||
|
||||
delegate: PanelWindow {
|
||||
required property ShellScreen modelData
|
||||
property string wallpaperSource: WallpaperService.currentWallpaper !== ""
|
||||
&& !Settings.data.wallpaper.swww.enabled ? WallpaperService.currentWallpaper : ""
|
||||
property string wallpaperSource: WallpaperService.getWallpaper(modelData.name)
|
||||
|
||||
visible: wallpaperSource !== "" && !Settings.data.wallpaper.swww.enabled
|
||||
|
||||
// Force update when SWWW setting changes
|
||||
onVisibleChanged: {
|
||||
if (visible) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
visible: wallpaperSource !== ""
|
||||
color: Color.transparent
|
||||
screen: modelData
|
||||
WlrLayershell.layer: WlrLayer.Background
|
||||
|
|
|
|||
|
|
@ -20,10 +20,9 @@ Loader {
|
|||
|
||||
delegate: PanelWindow {
|
||||
required property ShellScreen modelData
|
||||
property string wallpaperSource: WallpaperService.currentWallpaper !== ""
|
||||
&& !Settings.data.wallpaper.swww.enabled ? WallpaperService.currentWallpaper : ""
|
||||
property string wallpaperSource: WallpaperService.getWallpaper(modelData.name)
|
||||
|
||||
visible: wallpaperSource !== "" && !Settings.data.wallpaper.swww.enabled
|
||||
visible: wallpaperSource !== ""
|
||||
color: Color.transparent
|
||||
screen: modelData
|
||||
WlrLayershell.layer: WlrLayer.Background
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ ColumnLayout {
|
|||
}
|
||||
|
||||
NText {
|
||||
text: `${Math.round(ScalingService.scaleByName(modelData.name) * 100)}%`
|
||||
text: `${Math.round(ScalingService.getMonitorScale(modelData.name) * 100)}%`
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.minimumWidth: 50 * scaling
|
||||
horizontalAlignment: Text.AlignRight
|
||||
|
|
@ -204,12 +204,8 @@ ColumnLayout {
|
|||
from: 0.7
|
||||
to: 1.8
|
||||
stepSize: 0.01
|
||||
value: ScalingService.scaleByName(modelData.name)
|
||||
onPressedChanged: {
|
||||
var data = Settings.data.monitorsScaling || {}
|
||||
data[modelData.name] = value
|
||||
Settings.data.monitorsScaling = data
|
||||
}
|
||||
value: ScalingService.getMonitorScale(modelData.name)
|
||||
onPressedChanged: ScalingService.setMonitorScale(modelData.name, value)
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumWidth: 150 * scaling
|
||||
}
|
||||
|
|
@ -217,11 +213,7 @@ ColumnLayout {
|
|||
NIconButton {
|
||||
icon: "refresh"
|
||||
tooltipText: "Reset Scaling"
|
||||
onClicked: {
|
||||
var data = Settings.data.monitorsScaling || {}
|
||||
data[modelData.name] = 1.0
|
||||
Settings.data.monitorsScaling = data
|
||||
}
|
||||
onClicked: ScalingService.setMonitorScale(modelData.name, 1.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ ColumnLayout {
|
|||
id: currentWallpaperImage
|
||||
anchors.fill: parent
|
||||
anchors.margins: Style.marginXS * scaling
|
||||
imagePath: WallpaperService.currentWallpaper
|
||||
imagePath: WallpaperService.getWallpaper(screen.name)
|
||||
fallbackIcon: "image"
|
||||
imageRadius: Style.radiusM * scaling
|
||||
}
|
||||
|
|
@ -62,14 +62,6 @@ ColumnLayout {
|
|||
wrapMode: Text.WordWrap
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
NText {
|
||||
text: Settings.data.wallpaper.swww.enabled ? "Wallpapers will change with " + Settings.data.wallpaper.swww.transitionType
|
||||
+ " transition." : "Wallpapers will change instantly."
|
||||
color: Color.mOnSurface
|
||||
font.pointSize: Style.fontSizeXS * scaling
|
||||
visible: Settings.data.wallpaper.swww.enabled
|
||||
}
|
||||
}
|
||||
|
||||
NIconButton {
|
||||
|
|
@ -78,10 +70,17 @@ ColumnLayout {
|
|||
onClicked: {
|
||||
WallpaperService.listWallpapers()
|
||||
}
|
||||
Layout.alignment: Qt.AlignTop | Qt.AlignRight
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
||||
}
|
||||
}
|
||||
|
||||
NToggle {
|
||||
label: "Assign selection to all monitors"
|
||||
description: "Set selected wallpaper on all monitors at once."
|
||||
checked: Settings.data.wallpaper.setWallpaperOnAllMonitors
|
||||
onToggled: checked => Settings.data.wallpaper.setWallpaperOnAllMonitors = checked
|
||||
}
|
||||
|
||||
// Wallpaper grid container
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
|
|
@ -179,7 +178,11 @@ ColumnLayout {
|
|||
acceptedButtons: Qt.LeftButton
|
||||
hoverEnabled: true
|
||||
onClicked: {
|
||||
WallpaperService.changeWallpaper(wallpaperPath)
|
||||
if (Settings.data.wallpaper.setWallpaperOnAllMonitors) {
|
||||
WallpaperService.changeWallpaper(undefined, wallpaperPath)
|
||||
} else {
|
||||
WallpaperService.changeWallpaper(screen.name, wallpaperPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import qs.Commons
|
||||
import qs.Services
|
||||
|
|
@ -9,36 +10,59 @@ import qs.Widgets
|
|||
ColumnLayout {
|
||||
id: root
|
||||
|
||||
// Process to check if swww is installed
|
||||
Process {
|
||||
id: swwwCheck
|
||||
command: ["which", "swww"]
|
||||
running: false
|
||||
ColumnLayout {
|
||||
spacing: Style.marginL * scaling
|
||||
Layout.fillWidth: true
|
||||
NTextInput {
|
||||
label: "Wallpaper Directory"
|
||||
description: "Path to your wallpaper directory."
|
||||
text: Settings.data.wallpaper.directory
|
||||
onEditingFinished: {
|
||||
Settings.data.wallpaper.directory = text
|
||||
}
|
||||
Layout.maximumWidth: 420 * scaling
|
||||
}
|
||||
|
||||
onExited: function (exitCode) {
|
||||
if (exitCode === 0) {
|
||||
// SWWW exists, enable it
|
||||
Settings.data.wallpaper.swww.enabled = true
|
||||
WallpaperService.startSWWWDaemon()
|
||||
ToastService.showNotice("Swww", "Enabled")
|
||||
} else {
|
||||
// SWWW not found
|
||||
ToastService.showWarning("Swww", "Not installed")
|
||||
// Monitor-specific directories
|
||||
NToggle {
|
||||
label: "Monitor-specific directories"
|
||||
description: "Enable multi-monitor wallpaper directory management."
|
||||
checked: Settings.data.wallpaper.enableMultiMonitorDirectories
|
||||
onToggled: checked => Settings.data.wallpaper.enableMultiMonitorDirectories = checked
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
visible: Settings.data.wallpaper.enableMultiMonitorDirectories
|
||||
spacing: Style.marginL * scaling
|
||||
Repeater {
|
||||
model: Quickshell.screens || []
|
||||
delegate: Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumWidth: 550 * scaling
|
||||
radius: Style.radiusM * scaling
|
||||
color: Color.mSurface
|
||||
border.color: Color.mOutline
|
||||
border.width: Math.max(1, Style.borderS * scaling)
|
||||
implicitHeight: contentCol.implicitHeight + Style.marginXL * 2 * scaling
|
||||
|
||||
ColumnLayout {
|
||||
id: contentCol
|
||||
anchors.fill: parent
|
||||
anchors.margins: Style.marginL * scaling
|
||||
spacing: Style.marginXXS * scaling
|
||||
|
||||
NTextInput {
|
||||
label: (modelData.name || "Unknown")
|
||||
description: `Path to your wallpaper directory for "${(modelData.name || "Unknown")}" monitor`
|
||||
text: WallpaperService.getMonitorWallpaperDirectory(modelData.name)
|
||||
labelColor: Color.mSecondary
|
||||
onEditingFinished: WallpaperService.setMonitorWallpaperDirectory(modelData.name, text)
|
||||
Layout.maximumWidth: 420 * scaling
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stdout: StdioCollector {}
|
||||
stderr: StdioCollector {}
|
||||
}
|
||||
|
||||
NTextInput {
|
||||
label: "Wallpaper Directory"
|
||||
description: "Path to your wallpaper directory."
|
||||
text: Settings.data.wallpaper.directory
|
||||
onEditingFinished: {
|
||||
Settings.data.wallpaper.directory = text
|
||||
}
|
||||
Layout.maximumWidth: 420 * scaling
|
||||
}
|
||||
|
||||
NDivider {
|
||||
|
|
@ -62,10 +86,42 @@ ColumnLayout {
|
|||
NToggle {
|
||||
label: "Random Wallpaper"
|
||||
description: "Automatically select random wallpapers from the folder."
|
||||
checked: Settings.data.wallpaper.isRandom
|
||||
onToggled: checked => {
|
||||
Settings.data.wallpaper.isRandom = checked
|
||||
}
|
||||
checked: Settings.data.wallpaper.randomEnabled
|
||||
onToggled: checked => Settings.data.wallpaper.randomEnabled = checked
|
||||
}
|
||||
|
||||
// Transition Type
|
||||
NComboBox {
|
||||
label: "Transition Type"
|
||||
description: "Animation type when switching between wallpapers."
|
||||
model: WallpaperService.transitionsModel
|
||||
currentKey: Settings.data.wallpaper.transitionType
|
||||
onSelected: key => Settings.data.wallpaper.transitionType = key
|
||||
}
|
||||
|
||||
// Transition Duration
|
||||
ColumnLayout {
|
||||
NLabel {
|
||||
label: "Transition Duration"
|
||||
description: "Duration of transition animations in seconds."
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
spacing: Style.marginL * scaling
|
||||
NSlider {
|
||||
Layout.fillWidth: true
|
||||
from: 100
|
||||
to: 10000
|
||||
stepSize: 100
|
||||
value: Settings.data.wallpaper.transitionDuration
|
||||
onMoved: Settings.data.wallpaper.transitionDuration = value
|
||||
cutoutColor: Color.mSurface
|
||||
}
|
||||
NText {
|
||||
text: (Settings.data.wallpaper.transitionDuration / 1000).toFixed(2) + "s"
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Interval (slider + H:M inputs)
|
||||
|
|
@ -79,25 +135,37 @@ ColumnLayout {
|
|||
|
||||
NText {
|
||||
// Show friendly H:MM format from current settings
|
||||
text: Time.formatVagueHumanReadableDuration(Settings.data.wallpaper.randomInterval)
|
||||
text: Time.formatVagueHumanReadableDuration(Settings.data.wallpaper.randomIntervalSec)
|
||||
Layout.alignment: Qt.AlignBottom | Qt.AlignRight
|
||||
}
|
||||
}
|
||||
|
||||
// Preset chips
|
||||
// Preset chips using Repeater
|
||||
RowLayout {
|
||||
id: presetRow
|
||||
spacing: Style.marginS * scaling
|
||||
|
||||
// Preset seconds list
|
||||
property var presets: [15 * 60, 30 * 60, 45 * 60, 60 * 60, 90 * 60, 120 * 60]
|
||||
// Factorized presets data
|
||||
property var intervalPresets: [
|
||||
5 * 60,
|
||||
10 * 60,
|
||||
15 * 60,
|
||||
30 * 60,
|
||||
45 * 60,
|
||||
60 * 60,
|
||||
90 * 60,
|
||||
120 * 60,
|
||||
]
|
||||
|
||||
// Whether current interval equals one of the presets
|
||||
property bool isCurrentPreset: presets.indexOf(Settings.data.wallpaper.randomInterval) !== -1
|
||||
property bool isCurrentPreset: {
|
||||
return intervalPresets.some(seconds => seconds === Settings.data.wallpaper.randomIntervalSec)
|
||||
}
|
||||
// Allow user to force open the custom input; otherwise it's auto-open when not a preset
|
||||
property bool customForcedVisible: false
|
||||
|
||||
function setIntervalSeconds(sec) {
|
||||
Settings.data.wallpaper.randomInterval = sec
|
||||
Settings.data.wallpaper.randomIntervalSec = sec
|
||||
WallpaperService.restartRandomWallpaperTimer()
|
||||
// Hide custom when selecting a preset
|
||||
customForcedVisible = false
|
||||
|
|
@ -105,168 +173,25 @@ ColumnLayout {
|
|||
|
||||
// Helper to color selected chip
|
||||
function isSelected(sec) {
|
||||
return Settings.data.wallpaper.randomInterval === sec
|
||||
return Settings.data.wallpaper.randomIntervalSec === sec
|
||||
}
|
||||
|
||||
// 15m
|
||||
Rectangle {
|
||||
radius: height * 0.5
|
||||
color: presetRow.isSelected(15 * 60) ? Color.mPrimary : Color.mSurfaceVariant
|
||||
implicitHeight: Math.max(Style.baseWidgetSize * 0.55 * scaling, 24 * scaling)
|
||||
implicitWidth: label15.implicitWidth + Style.marginM * 1.5 * scaling
|
||||
border.width: 1
|
||||
border.color: presetRow.isSelected(15 * 60) ? Color.transparent : Color.mOutline
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: presetRow.setIntervalSeconds(15 * 60)
|
||||
}
|
||||
NText {
|
||||
id: label15
|
||||
anchors.centerIn: parent
|
||||
text: "15m"
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
color: presetRow.isSelected(15 * 60) ? Color.mOnPrimary : Color.mOnSurface
|
||||
}
|
||||
}
|
||||
|
||||
// 30m
|
||||
Rectangle {
|
||||
radius: height * 0.5
|
||||
color: presetRow.isSelected(30 * 60) ? Color.mPrimary : Color.mSurfaceVariant
|
||||
implicitHeight: Math.max(Style.baseWidgetSize * 0.55 * scaling, 24 * scaling)
|
||||
implicitWidth: label30.implicitWidth + Style.marginM * 1.5 * scaling
|
||||
border.width: 1
|
||||
border.color: presetRow.isSelected(30 * 60) ? Color.transparent : Color.mOutline
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: presetRow.setIntervalSeconds(30 * 60)
|
||||
}
|
||||
NText {
|
||||
id: label30
|
||||
anchors.centerIn: parent
|
||||
text: "30m"
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
color: presetRow.isSelected(30 * 60) ? Color.mOnPrimary : Color.mOnSurface
|
||||
}
|
||||
}
|
||||
|
||||
// 45m
|
||||
Rectangle {
|
||||
radius: height * 0.5
|
||||
color: presetRow.isSelected(45 * 60) ? Color.mPrimary : Color.mSurfaceVariant
|
||||
implicitHeight: Math.max(Style.baseWidgetSize * 0.55 * scaling, 24 * scaling)
|
||||
implicitWidth: label45.implicitWidth + Style.marginM * 1.5 * scaling
|
||||
border.width: 1
|
||||
border.color: presetRow.isSelected(45 * 60) ? Color.transparent : Color.mOutline
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: presetRow.setIntervalSeconds(45 * 60)
|
||||
}
|
||||
NText {
|
||||
id: label45
|
||||
anchors.centerIn: parent
|
||||
text: "45m"
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
color: presetRow.isSelected(45 * 60) ? Color.mOnPrimary : Color.mOnSurface
|
||||
}
|
||||
}
|
||||
|
||||
// 1h
|
||||
Rectangle {
|
||||
radius: height * 0.5
|
||||
color: presetRow.isSelected(60 * 60) ? Color.mPrimary : Color.mSurfaceVariant
|
||||
implicitHeight: Math.max(Style.baseWidgetSize * 0.55 * scaling, 24 * scaling)
|
||||
implicitWidth: label1h.implicitWidth + Style.marginM * 1.5 * scaling
|
||||
border.width: 1
|
||||
border.color: presetRow.isSelected(60 * 60) ? Color.transparent : Color.mOutline
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: presetRow.setIntervalSeconds(60 * 60)
|
||||
}
|
||||
NText {
|
||||
id: label1h
|
||||
anchors.centerIn: parent
|
||||
text: "1h"
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
color: presetRow.isSelected(60 * 60) ? Color.mOnPrimary : Color.mOnSurface
|
||||
}
|
||||
}
|
||||
|
||||
// 1h 30m
|
||||
Rectangle {
|
||||
radius: height * 0.5
|
||||
color: presetRow.isSelected(90 * 60) ? Color.mPrimary : Color.mSurfaceVariant
|
||||
implicitHeight: Math.max(Style.baseWidgetSize * 0.55 * scaling, 24 * scaling)
|
||||
implicitWidth: label90.implicitWidth + Style.marginM * 1.5 * scaling
|
||||
border.width: 1
|
||||
border.color: presetRow.isSelected(90 * 60) ? Color.transparent : Color.mOutline
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: presetRow.setIntervalSeconds(90 * 60)
|
||||
}
|
||||
NText {
|
||||
id: label90
|
||||
anchors.centerIn: parent
|
||||
text: "1h 30m"
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
color: presetRow.isSelected(90 * 60) ? Color.mOnPrimary : Color.mOnSurface
|
||||
}
|
||||
}
|
||||
|
||||
// 2h
|
||||
Rectangle {
|
||||
radius: height * 0.5
|
||||
color: presetRow.isSelected(120 * 60) ? Color.mPrimary : Color.mSurfaceVariant
|
||||
implicitHeight: Math.max(Style.baseWidgetSize * 0.55 * scaling, 24 * scaling)
|
||||
implicitWidth: label2h.implicitWidth + Style.marginM * 1.5 * scaling
|
||||
border.width: 1
|
||||
border.color: presetRow.isSelected(120 * 60) ? Color.transparent : Color.mOutline
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: presetRow.setIntervalSeconds(120 * 60)
|
||||
}
|
||||
NText {
|
||||
id: label2h
|
||||
anchors.centerIn: parent
|
||||
text: "2h"
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
color: presetRow.isSelected(120 * 60) ? Color.mOnPrimary : Color.mOnSurface
|
||||
// Repeater for preset chips
|
||||
Repeater {
|
||||
model: presetRow.intervalPresets
|
||||
delegate: IntervalPresetChip {
|
||||
seconds: modelData
|
||||
label: Time.formatVagueHumanReadableDuration(modelData)
|
||||
selected: presetRow.isSelected(modelData)
|
||||
onClicked: presetRow.setIntervalSeconds(modelData)
|
||||
}
|
||||
}
|
||||
|
||||
// Custom… opens inline input
|
||||
Rectangle {
|
||||
radius: height * 0.5
|
||||
color: customRow.visible ? Color.mPrimary : Color.mSurfaceVariant
|
||||
implicitHeight: Math.max(Style.baseWidgetSize * 0.55 * scaling, 24 * scaling)
|
||||
implicitWidth: labelCustom.implicitWidth + Style.marginM * 1.5 * scaling
|
||||
border.width: 1
|
||||
border.color: customRow.visible ? Color.transparent : Color.mOutline
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: presetRow.customForcedVisible = !presetRow.customForcedVisible
|
||||
}
|
||||
NText {
|
||||
id: labelCustom
|
||||
anchors.centerIn: parent
|
||||
text: customRow.visible ? "Custom" : "Custom…"
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
font.weight: Style.fontWeightMedium
|
||||
color: customRow.visible ? Color.mOnPrimary : Color.mOnSurface
|
||||
}
|
||||
IntervalPresetChip {
|
||||
label: customRow.visible ? "Custom" : "Custom…"
|
||||
selected: customRow.visible
|
||||
onClicked: presetRow.customForcedVisible = !presetRow.customForcedVisible
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -282,12 +207,11 @@ ColumnLayout {
|
|||
description: "Enter time as HH:MM (e.g., 01:30)."
|
||||
inputMaxWidth: 100 * scaling
|
||||
text: {
|
||||
const s = Settings.data.wallpaper.randomInterval
|
||||
const s = Settings.data.wallpaper.randomIntervalSec
|
||||
const h = Math.floor(s / 3600)
|
||||
const m = Math.floor((s % 3600) / 60)
|
||||
return h + ":" + (m < 10 ? ("0" + m) : m)
|
||||
}
|
||||
|
||||
onEditingFinished: {
|
||||
const m = text.trim().match(/^(\d{1,2}):(\d{2})$/)
|
||||
if (m) {
|
||||
|
|
@ -297,7 +221,7 @@ ColumnLayout {
|
|||
return
|
||||
h = Math.max(0, Math.min(24, h))
|
||||
min = Math.max(0, Math.min(59, min))
|
||||
Settings.data.wallpaper.randomInterval = (h * 3600) + (min * 60)
|
||||
Settings.data.wallpaper.randomIntervalSec = (h * 3600) + (min * 60)
|
||||
WallpaperService.restartRandomWallpaperTimer()
|
||||
// Keep custom visible after manual entry
|
||||
presetRow.customForcedVisible = true
|
||||
|
|
@ -308,193 +232,32 @@ ColumnLayout {
|
|||
}
|
||||
}
|
||||
|
||||
NDivider {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.marginXL * scaling
|
||||
Layout.bottomMargin: Style.marginXL * scaling
|
||||
}
|
||||
// Reusable component for interval preset chips
|
||||
component IntervalPresetChip: Rectangle {
|
||||
property int seconds: 0
|
||||
property string label: ""
|
||||
property bool selected: false
|
||||
signal clicked()
|
||||
|
||||
// -------------------------------
|
||||
// Swww
|
||||
ColumnLayout {
|
||||
spacing: Style.marginL * scaling
|
||||
Layout.fillWidth: true
|
||||
radius: height * 0.5
|
||||
color: selected ? Color.mPrimary : Color.mSurfaceVariant
|
||||
implicitHeight: Math.max(Style.baseWidgetSize * 0.55 * scaling, 24 * scaling)
|
||||
implicitWidth: chipLabel.implicitWidth + Style.marginM * 1.5 * scaling
|
||||
border.width: 1
|
||||
border.color: selected ? Color.transparent : Color.mOutline
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: parent.clicked()
|
||||
}
|
||||
|
||||
NText {
|
||||
text: "Swww"
|
||||
font.pointSize: Style.fontSizeXXL * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
color: Color.mSecondary
|
||||
}
|
||||
|
||||
// Use SWWW
|
||||
NToggle {
|
||||
label: "Use Swww"
|
||||
description: "Use Swww daemon for advanced wallpaper management."
|
||||
checked: Settings.data.wallpaper.swww.enabled
|
||||
onToggled: checked => {
|
||||
if (checked) {
|
||||
// Check if swww is installed
|
||||
swwwCheck.running = true
|
||||
} else {
|
||||
Settings.data.wallpaper.swww.enabled = false
|
||||
ToastService.showNotice("Swww", "Disabled")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SWWW Settings (only visible when useSWWW is enabled)
|
||||
ColumnLayout {
|
||||
spacing: Style.marginS * scaling
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.marginS * scaling
|
||||
visible: Settings.data.wallpaper.swww.enabled
|
||||
|
||||
// Resize Mode
|
||||
NComboBox {
|
||||
label: "Resize Mode"
|
||||
description: "How Swww should resize wallpapers to fit the screen."
|
||||
model: ListModel {
|
||||
ListElement {
|
||||
key: "no"
|
||||
name: "No"
|
||||
}
|
||||
ListElement {
|
||||
key: "crop"
|
||||
name: "Crop"
|
||||
}
|
||||
ListElement {
|
||||
key: "fit"
|
||||
name: "Fit"
|
||||
}
|
||||
ListElement {
|
||||
key: "stretch"
|
||||
name: "Stretch"
|
||||
}
|
||||
}
|
||||
currentKey: Settings.data.wallpaper.swww.resizeMethod
|
||||
onSelected: key => {
|
||||
Settings.data.wallpaper.swww.resizeMethod = key
|
||||
}
|
||||
}
|
||||
|
||||
// Transition Type
|
||||
NComboBox {
|
||||
label: "Transition Type"
|
||||
description: "Animation type when switching between wallpapers."
|
||||
model: ListModel {
|
||||
ListElement {
|
||||
key: "none"
|
||||
name: "None"
|
||||
}
|
||||
ListElement {
|
||||
key: "simple"
|
||||
name: "Simple"
|
||||
}
|
||||
ListElement {
|
||||
key: "fade"
|
||||
name: "Fade"
|
||||
}
|
||||
ListElement {
|
||||
key: "left"
|
||||
name: "Left"
|
||||
}
|
||||
ListElement {
|
||||
key: "right"
|
||||
name: "Right"
|
||||
}
|
||||
ListElement {
|
||||
key: "top"
|
||||
name: "Top"
|
||||
}
|
||||
ListElement {
|
||||
key: "bottom"
|
||||
name: "Bottom"
|
||||
}
|
||||
ListElement {
|
||||
key: "wipe"
|
||||
name: "Wipe"
|
||||
}
|
||||
ListElement {
|
||||
key: "wave"
|
||||
name: "Wave"
|
||||
}
|
||||
ListElement {
|
||||
key: "grow"
|
||||
name: "Grow"
|
||||
}
|
||||
ListElement {
|
||||
key: "center"
|
||||
name: "Center"
|
||||
}
|
||||
ListElement {
|
||||
key: "any"
|
||||
name: "Any"
|
||||
}
|
||||
ListElement {
|
||||
key: "outer"
|
||||
name: "Outer"
|
||||
}
|
||||
ListElement {
|
||||
key: "random"
|
||||
name: "Random"
|
||||
}
|
||||
}
|
||||
currentKey: Settings.data.wallpaper.swww.transitionType
|
||||
onSelected: key => {
|
||||
Settings.data.wallpaper.swww.transitionType = key
|
||||
}
|
||||
}
|
||||
|
||||
// Transition FPS
|
||||
ColumnLayout {
|
||||
NLabel {
|
||||
label: "Transition FPS"
|
||||
description: "Frames per second for transition animations."
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
spacing: Style.marginL * scaling
|
||||
NSlider {
|
||||
Layout.fillWidth: true
|
||||
from: 30
|
||||
to: 500
|
||||
stepSize: 5
|
||||
value: Settings.data.wallpaper.swww.transitionFps
|
||||
onMoved: Settings.data.wallpaper.swww.transitionFps = Math.round(value)
|
||||
cutoutColor: Color.mSurface
|
||||
}
|
||||
NText {
|
||||
text: Settings.data.wallpaper.swww.transitionFps + " FPS"
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Transition Duration
|
||||
ColumnLayout {
|
||||
NLabel {
|
||||
label: "Transition Duration"
|
||||
description: "Duration of transition animations in seconds."
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
spacing: Style.marginL * scaling
|
||||
NSlider {
|
||||
Layout.fillWidth: true
|
||||
from: 0.25
|
||||
to: 10
|
||||
stepSize: 0.05
|
||||
value: Settings.data.wallpaper.swww.transitionDuration
|
||||
onMoved: Settings.data.wallpaper.swww.transitionDuration = value
|
||||
cutoutColor: Color.mSurface
|
||||
}
|
||||
NText {
|
||||
text: Settings.data.wallpaper.swww.transitionDuration.toFixed(2) + "s"
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
||||
}
|
||||
}
|
||||
}
|
||||
id: chipLabel
|
||||
anchors.centerIn: parent
|
||||
text: parent.label
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
color: parent.selected ? Color.mOnPrimary : Color.mOnSurface
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -503,4 +266,4 @@ ColumnLayout {
|
|||
Layout.topMargin: Style.marginXL * scaling
|
||||
Layout.bottomMargin: Style.marginXL * scaling
|
||||
}
|
||||
}
|
||||
}
|
||||
14
README.md
14
README.md
|
|
@ -75,7 +75,6 @@ Features a modern modular architecture with a status bar, notification system, c
|
|||
### Optional
|
||||
|
||||
- `cliphist` - For clipboard history support
|
||||
- `swww` - Wallpaper animations and effects
|
||||
- `matugen` - Material You color scheme generation
|
||||
- `cava` - Audio visualizer component
|
||||
- `wlsunset` - To be able to use NightLight
|
||||
|
|
@ -270,14 +269,6 @@ The launcher supports special commands for enhanced functionality:
|
|||
|
||||
## Advanced Configuration
|
||||
|
||||
### Niri Configuration
|
||||
|
||||
Add this to your `layout` section for proper swww integration:
|
||||
|
||||
```
|
||||
background-color "transparent"
|
||||
```
|
||||
|
||||
### Recommended Compositor Settings
|
||||
|
||||
For Niri:
|
||||
|
|
@ -288,11 +279,6 @@ window-rule {
|
|||
clip-to-geometry true
|
||||
}
|
||||
|
||||
layer-rule {
|
||||
match namespace="^swww-daemon$"
|
||||
place-within-backdrop true
|
||||
}
|
||||
|
||||
layer-rule {
|
||||
match namespace="^quickshell-wallpaper$"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ Singleton {
|
|||
function scale(aScreen) {
|
||||
try {
|
||||
if (aScreen !== undefined && aScreen.name !== undefined) {
|
||||
return scaleByName(aScreen.name)
|
||||
return getMonitorScale(aScreen.name)
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
|
|
@ -20,21 +20,46 @@ Singleton {
|
|||
return 1.0
|
||||
}
|
||||
|
||||
function scaleByName(aScreenName) {
|
||||
// -------------------------------------------
|
||||
function getMonitorScale(aScreenName) {
|
||||
try {
|
||||
if (Settings.data.monitorsScaling !== undefined) {
|
||||
if (Settings.data.monitorsScaling[aScreenName] !== undefined) {
|
||||
return Settings.data.monitorsScaling[aScreenName]
|
||||
var monitors = Settings.data.ui.monitorsScaling
|
||||
if (monitors !== undefined) {
|
||||
for (var i = 0; i < monitors.length; i++) {
|
||||
if (monitors[i].name !== undefined && monitors[i].name === aScreenName) {
|
||||
return monitors[i].scale
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
//Logger.warn(e)
|
||||
}
|
||||
|
||||
return 1.0
|
||||
}
|
||||
|
||||
// -------------------------------------------
|
||||
function setMonitorScale(aScreenName, scale) {
|
||||
try {
|
||||
var monitors = Settings.data.ui.monitorsScaling
|
||||
if (monitors !== undefined) {
|
||||
for (var i = 0; i < monitors.length; i++) {
|
||||
if (monitors[i].name !== undefined && monitors[i].name === aScreenName) {
|
||||
monitors[i].scale = scale
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
monitors.push({
|
||||
"name": aScreenName,
|
||||
"scale": scale
|
||||
})
|
||||
} catch (e) {
|
||||
|
||||
//Logger.warn(e)
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------
|
||||
// Dynamic scaling based on resolution
|
||||
|
||||
|
|
|
|||
|
|
@ -10,66 +10,138 @@ Singleton {
|
|||
id: root
|
||||
|
||||
Component.onCompleted: {
|
||||
Logger.log("Wallpapers", "Service started")
|
||||
Logger.log("Wallpaper", "Service started")
|
||||
listWallpapers()
|
||||
|
||||
// Wallpaper is set when the settings are loaded.
|
||||
// Don't start random wallpaper during initialization
|
||||
}
|
||||
|
||||
readonly property ListModel transitionsModel: ListModel {
|
||||
ListElement {
|
||||
key: "none"
|
||||
name: "None"
|
||||
}
|
||||
ListElement {
|
||||
key: "fade"
|
||||
name: "Fade"
|
||||
}
|
||||
}
|
||||
|
||||
property var wallpaperList: []
|
||||
property string currentWallpaper: Settings.data.wallpaper.current
|
||||
property bool scanning: false
|
||||
|
||||
// SWWW
|
||||
property string transitionType: Settings.data.wallpaper.swww.transitionType
|
||||
property var randomChoices: ["simple", "fade", "left", "right", "top", "bottom", "wipe", "wave", "grow", "center", "any", "outer"]
|
||||
Connections {
|
||||
target: Settings.data.wallpaper
|
||||
onDirectoryChanged: WallpaperService.listWallpapers()
|
||||
onRandomEnabledChanged: WallpaperService.toggleRandomWallpaper()
|
||||
onRandomIntervalChanged: WallpaperService.restartRandomWallpaperTimer()
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
function geMonitorDefinition(screenName) {
|
||||
var monitors = Settings.data.wallpaper.monitors
|
||||
if (monitors !== undefined) {
|
||||
for (var i = 0; i < monitors.length; i++) {
|
||||
if (monitors[i].name !== undefined && monitors[i].name === screenName) {
|
||||
return monitors[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
function getMonitorWallpaperDirectory(screenName) {
|
||||
var monitor = geMonitorDefinition(screenName)
|
||||
if (monitor !== undefined) {
|
||||
return monitor.directory
|
||||
}
|
||||
return Settings.data.wallpaper.directory
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
function setMonitorWallpaperDirectory(screenName, directory) {
|
||||
var monitor = geMonitorDefinition(screenName)
|
||||
if (monitor !== undefined) {
|
||||
monitor.directory = directory
|
||||
return
|
||||
}
|
||||
|
||||
Settings.data.wallpaper.monitors.push({
|
||||
"name": screenName,
|
||||
"directory": directory,
|
||||
"wallpaper": ""
|
||||
})
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
function listWallpapers() {
|
||||
Logger.log("Wallpapers", "Listing wallpapers")
|
||||
Logger.log("Wallpaper", "Listing wallpapers")
|
||||
scanning = true
|
||||
wallpaperList = []
|
||||
// Set the folder directly to avoid model reset issues
|
||||
folderModel.folder = "file://" + (Settings.data.wallpaper.directory !== undefined ? Settings.data.wallpaper.directory : "")
|
||||
}
|
||||
|
||||
function changeWallpaper(path) {
|
||||
Logger.log("Wallpapers", "Changing to:", path)
|
||||
setCurrentWallpaper(path, false)
|
||||
// -------------------------------------------------------------------
|
||||
function getWallpaper(screenName) {
|
||||
// Logger.log("Wallpaper", "getWallpaper on", screenName)
|
||||
var monitor = geMonitorDefinition(screenName)
|
||||
if (monitor !== undefined) {
|
||||
return monitor["wallpaper"]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
function setCurrentWallpaper(path, isInitial) {
|
||||
// Only regenerate colors if the wallpaper actually changed
|
||||
var wallpaperChanged = currentWallpaper !== path
|
||||
|
||||
currentWallpaper = path
|
||||
if (!isInitial) {
|
||||
Settings.data.wallpaper.current = path
|
||||
}
|
||||
if (Settings.data.wallpaper.swww.enabled) {
|
||||
if (Settings.data.wallpaper.swww.transitionType === "random") {
|
||||
transitionType = randomChoices[Math.floor(Math.random() * randomChoices.length)]
|
||||
} else {
|
||||
transitionType = Settings.data.wallpaper.swww.transitionType
|
||||
}
|
||||
|
||||
changeWallpaperProcess.running = true
|
||||
// -------------------------------------------------------------------
|
||||
function changeWallpaper(screenName, path) {
|
||||
if (screenName !== undefined) {
|
||||
setCurrentWallpaper(screenName, path, false)
|
||||
} else {
|
||||
for (var i = 0; i < Quickshell.screens.length; i++) {
|
||||
setCurrentWallpaper(Quickshell.screens[i].name, path, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: update the settings directly for non-SWWW mode
|
||||
//Logger.log("Wallpapers", "Not using Swww, setting wallpaper directly")
|
||||
// -------------------------------------------------------------------
|
||||
function setCurrentWallpaper(screenName, path, isInitial) {
|
||||
if (screenName === undefined) {
|
||||
Logger.warn("Wallpaper", "setCurrentWallpaper", "no screen specified")
|
||||
return
|
||||
}
|
||||
|
||||
Logger.log("Wallpaper", "setCurrentWallpaper on", screenName, ": ", path)
|
||||
|
||||
var monitor = geMonitorDefinition(screenName)
|
||||
if (monitor !== undefined) {
|
||||
monitor["wallpaper"] = path
|
||||
} else {
|
||||
Settings.data.wallpaper.monitors.push({
|
||||
"name": screenName,
|
||||
"directory": Settings.data.wallpaper.directory,
|
||||
"wallpaper": path
|
||||
})
|
||||
}
|
||||
|
||||
// // Only regenerate colors if the wallpaper actually changed
|
||||
// var wallpaperChanged = currentWallpaper !== path
|
||||
|
||||
// currentWallpaper = path
|
||||
// if (!isInitial) {
|
||||
// Settings.data.wallpaper.current = path
|
||||
// }
|
||||
if (randomWallpaperTimer.running) {
|
||||
randomWallpaperTimer.restart()
|
||||
}
|
||||
|
||||
// Only notify ColorScheme service if the wallpaper actually changed
|
||||
if (wallpaperChanged) {
|
||||
ColorSchemeService.changedWallpaper()
|
||||
}
|
||||
// if (wallpaperChanged) {
|
||||
// ColorSchemeService.changedWallpaper()
|
||||
// }
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
function setRandomWallpaper() {
|
||||
var randomIndex = Math.floor(Math.random() * wallpaperList.length)
|
||||
var randomPath = wallpaperList[randomIndex]
|
||||
|
|
@ -79,6 +151,7 @@ Singleton {
|
|||
setCurrentWallpaper(randomPath, false)
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
function toggleRandomWallpaper() {
|
||||
if (Settings.data.wallpaper.isRandom && !randomWallpaperTimer.running) {
|
||||
randomWallpaperTimer.start()
|
||||
|
|
@ -88,6 +161,7 @@ Singleton {
|
|||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
function restartRandomWallpaperTimer() {
|
||||
if (Settings.data.wallpaper.isRandom) {
|
||||
randomWallpaperTimer.stop()
|
||||
|
|
@ -95,16 +169,12 @@ Singleton {
|
|||
}
|
||||
}
|
||||
|
||||
function startSWWWDaemon() {
|
||||
if (Settings.data.wallpaper.swww.enabled) {
|
||||
Logger.log("Swww", "Requesting swww-daemon")
|
||||
startDaemonProcess.running = true
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// -------------------------------------------------------------------
|
||||
// -------------------------------------------------------------------
|
||||
Timer {
|
||||
id: randomWallpaperTimer
|
||||
interval: Settings.data.wallpaper.randomInterval * 1000
|
||||
interval: Settings.data.wallpaper.randomIntervalSec * 1000
|
||||
running: false
|
||||
repeat: true
|
||||
onTriggered: setRandomWallpaper()
|
||||
|
|
@ -113,7 +183,6 @@ Singleton {
|
|||
|
||||
FolderListModel {
|
||||
id: folderModel
|
||||
// Swww supports many images format but Quickshell only support a subset of those.
|
||||
nameFilters: ["*.jpg", "*.jpeg", "*.png", "*.gif", "*.pnm", "*.bmp"]
|
||||
showDirs: false
|
||||
sortField: FolderListModel.Name
|
||||
|
|
@ -127,46 +196,7 @@ Singleton {
|
|||
}
|
||||
wallpaperList = files
|
||||
scanning = false
|
||||
Logger.log("Wallpapers", "List refreshed, count:", wallpaperList.length)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: changeWallpaperProcess
|
||||
command: ["swww", "img", "--resize", Settings.data.wallpaper.swww.resizeMethod, "--transition-fps", Settings.data.wallpaper.swww.transitionFps.toString(
|
||||
), "--transition-type", transitionType, "--transition-duration", Settings.data.wallpaper.swww.transitionDuration.toString(
|
||||
), currentWallpaper]
|
||||
running: false
|
||||
|
||||
onStarted: {
|
||||
|
||||
}
|
||||
|
||||
onExited: function (exitCode, exitStatus) {
|
||||
Logger.log("Swww", "Process finished with exit code:", exitCode, "status:", exitStatus)
|
||||
if (exitCode !== 0) {
|
||||
Logger.log("Swww", "Process failed. Make sure swww-daemon is running with: swww-daemon")
|
||||
Logger.log("Swww", "You can start it with: swww-daemon --format xrgb")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: startDaemonProcess
|
||||
command: ["swww-daemon", "--format", "xrgb"]
|
||||
running: false
|
||||
|
||||
onStarted: {
|
||||
Logger.log("Swww", "Daemon start process initiated")
|
||||
}
|
||||
|
||||
onExited: function (exitCode, exitStatus) {
|
||||
Logger.log("Swww", "Daemon start process finished with exit code:", exitCode)
|
||||
if (exitCode === 0) {
|
||||
Logger.log("Swww", "Daemon started successfully")
|
||||
} else {
|
||||
Logger.log("Swww", "Failed to start daemon, may already be running")
|
||||
Logger.log("Wallpaper", "List refreshed, count:", wallpaperList.length)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,12 @@ import QtQuick.Layouts
|
|||
import qs.Commons
|
||||
|
||||
ColumnLayout {
|
||||
id: root
|
||||
|
||||
property string label: ""
|
||||
property string description: ""
|
||||
property color labelColor: Color.mOnSurface
|
||||
property color descriptionColor: Color.mOnSurfaceVariant
|
||||
|
||||
spacing: Style.marginXXS * scaling
|
||||
Layout.fillWidth: true
|
||||
|
|
@ -13,14 +17,14 @@ ColumnLayout {
|
|||
text: label
|
||||
font.pointSize: Style.fontSizeL * scaling
|
||||
font.weight: Style.fontWeightBold
|
||||
color: Color.mOnSurface
|
||||
color: labelColor
|
||||
visible: label !== ""
|
||||
}
|
||||
|
||||
NText {
|
||||
text: description
|
||||
font.pointSize: Style.fontSizeS * scaling
|
||||
color: Color.mOnSurfaceVariant
|
||||
color: descriptionColor
|
||||
wrapMode: Text.WordWrap
|
||||
visible: description !== ""
|
||||
Layout.fillWidth: true
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ ColumnLayout {
|
|||
property bool readOnly: false
|
||||
property bool enabled: true
|
||||
property int inputMaxWidth: 420 * scaling
|
||||
property color labelColor: Color.mOnSurface
|
||||
property color descriptionColor: Color.mOnSurfaceVariant
|
||||
|
||||
property alias text: input.text
|
||||
property alias placeholderText: input.placeholderText
|
||||
|
|
@ -25,6 +27,8 @@ ColumnLayout {
|
|||
NLabel {
|
||||
label: root.label
|
||||
description: root.description
|
||||
labelColor: root.labelColor
|
||||
descriptionColor: root.descriptionColor
|
||||
visible: root.label !== "" || root.description !== ""
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ Item {
|
|||
}
|
||||
}
|
||||
}
|
||||
Logger.log("NWidgetLoader", "Loaded", widgetName, "on screen", item.screen.name)
|
||||
//Logger.log("NWidgetLoader", "Loaded", widgetName, "on screen", item.screen.name)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue