From 9ed92310709095daa4236d96420d5bfb1126dbd3 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Mon, 29 Sep 2025 09:11:37 -0400 Subject: [PATCH 1/5] Init Sequence: removed a bunch of no longer necessary Settings.isLoaded --- Modules/Background/Background.qml | 37 ++++++++++---------------- Modules/Background/Overview.qml | 2 +- Modules/Bar/Bar.qml | 2 +- Modules/Bar/Extras/BarWidgetLoader.qml | 2 +- Modules/Dock/Dock.qml | 6 ++--- Modules/Notification/Notification.qml | 6 ++--- Modules/OSD/OSD.qml | 4 +-- Modules/Toast/ToastOverlay.qml | 2 +- Modules/Toast/ToastScreen.qml | 2 +- Services/ClipboardService.qml | 2 +- Services/MatugenService.qml | 7 +---- Services/WallpaperService.qml | 6 ++++- 12 files changed, 34 insertions(+), 44 deletions(-) diff --git a/Modules/Background/Background.qml b/Modules/Background/Background.qml index fefdcc6a..a83aed58 100644 --- a/Modules/Background/Background.qml +++ b/Modules/Background/Background.qml @@ -13,7 +13,7 @@ Variants { required property ShellScreen modelData - active: Settings.isLoaded && modelData && Settings.data.wallpaper.enabled + active: modelData && Settings.data.wallpaper.enabled sourceComponent: PanelWindow { id: root @@ -41,29 +41,10 @@ Variants { property string futureWallpaper: "" // Fillmode default is "crop" - property real fillMode: 1.0 + property real fillMode: WallpaperService.getFillModeUniform() property vector4d fillColor: Qt.vector4d(Settings.data.wallpaper.fillColor.r, Settings.data.wallpaper.fillColor.g, Settings.data.wallpaper.fillColor.b, 1.0) - // On startup, defer assigning wallpaper until the service cache is ready - function _startWallpaperOnceReady() { - if (!modelData) { - Qt.callLater(_startWallpaperOnceReady) - return - } - - var cacheReady = WallpaperService && WallpaperService.currentWallpapers && Object.keys(WallpaperService.currentWallpapers).length > 0 - if (!cacheReady) { - // Try again on the next tick until WallpaperService.init() populates cache - Qt.callLater(_startWallpaperOnceReady) - return - } - - fillMode = WallpaperService.getFillModeUniform() - var path = WallpaperService.getWallpaper(modelData.name) - setWallpaperImmediate(path) - } - - Component.onCompleted: _startWallpaperOnceReady() + Component.onCompleted: setWallpaperInitial() Connections { target: Settings.data.wallpaper @@ -254,6 +235,16 @@ Variants { }) } } + + function setWallpaperInitial() { + // On startup, defer assigning wallpaper until the service cache is ready, retries every tick + if (!WallpaperService || !WallpaperService.isInitialized) { + Qt.callLater(setWallpaperInitial) + return + } + + setWallpaperImmediate(WallpaperService.getWallpaper(modelData.name)) + } function setWallpaperImmediate(source) { transitionAnimation.stop() @@ -324,4 +315,4 @@ Variants { } } } -} +} \ No newline at end of file diff --git a/Modules/Background/Overview.qml b/Modules/Background/Overview.qml index 0828be9a..7aa67240 100644 --- a/Modules/Background/Overview.qml +++ b/Modules/Background/Overview.qml @@ -12,7 +12,7 @@ Variants { delegate: Loader { required property ShellScreen modelData - active: Settings.isLoaded && CompositorService.isNiri && modelData && Settings.data.wallpaper.enabled + active: CompositorService.isNiri && modelData && Settings.data.wallpaper.enabled property string wallpaper: "" diff --git a/Modules/Bar/Bar.qml b/Modules/Bar/Bar.qml index d6d4e356..f1140d8e 100644 --- a/Modules/Bar/Bar.qml +++ b/Modules/Bar/Bar.qml @@ -28,7 +28,7 @@ Variants { } } - active: Settings.isLoaded && BarService.isVisible && modelData && modelData.name ? (Settings.data.bar.monitors.includes(modelData.name) || (Settings.data.bar.monitors.length === 0)) : false + active: BarService.isVisible && modelData && modelData.name ? (Settings.data.bar.monitors.includes(modelData.name) || (Settings.data.bar.monitors.length === 0)) : false sourceComponent: PanelWindow { screen: modelData || null diff --git a/Modules/Bar/Extras/BarWidgetLoader.qml b/Modules/Bar/Extras/BarWidgetLoader.qml index 3aa5911f..358a42ef 100644 --- a/Modules/Bar/Extras/BarWidgetLoader.qml +++ b/Modules/Bar/Extras/BarWidgetLoader.qml @@ -29,7 +29,7 @@ Item { id: loader anchors.fill: parent - active: Settings.isLoaded && widgetId !== "" + active: widgetId !== "" sourceComponent: { if (!active) { return null diff --git a/Modules/Dock/Dock.qml b/Modules/Dock/Dock.qml index f6fab110..ca3e6ae7 100644 --- a/Modules/Dock/Dock.qml +++ b/Modules/Dock/Dock.qml @@ -55,7 +55,7 @@ Variants { // Initial update when component is ready Component.onCompleted: { - if (Settings.isLoaded && ToplevelManager) { + if (ToplevelManager) { updateDockApps() } } @@ -198,7 +198,7 @@ Variants { // PEEK WINDOW - Always visible when auto-hide is enabled Loader { - active: Settings.isLoaded && barIsReady && modelData && Settings.data.dock.monitors.includes(modelData.name) && autoHide + active: barIsReady && modelData && Settings.data.dock.monitors.includes(modelData.name) && autoHide sourceComponent: PanelWindow { id: peekWindow @@ -244,7 +244,7 @@ Variants { // DOCK WINDOW Loader { - active: Settings.isLoaded && barIsReady && modelData && Settings.data.dock.monitors.includes(modelData.name) && dockLoaded && ToplevelManager && (dockApps.length > 0) + active: barIsReady && modelData && Settings.data.dock.monitors.includes(modelData.name) && dockLoaded && ToplevelManager && (dockApps.length > 0) sourceComponent: PanelWindow { id: dockWindow diff --git a/Modules/Notification/Notification.qml b/Modules/Notification/Notification.qml index 3bb1383c..bb868bd6 100644 --- a/Modules/Notification/Notification.qml +++ b/Modules/Notification/Notification.qml @@ -22,7 +22,7 @@ Variants { property ListModel notificationModel: NotificationService.activeList // If no notification display activated in settings, then show them all - active: Settings.isLoaded && modelData && (Settings.data.notifications.monitors.includes(modelData.name) || (Settings.data.notifications.monitors.length === 0)) + active: modelData && (Settings.data.notifications.monitors.includes(modelData.name) || (Settings.data.notifications.monitors.length === 0)) Connections { target: ScalingService @@ -37,11 +37,11 @@ Variants { screen: modelData WlrLayershell.namespace: "noctalia-notifications" - WlrLayershell.layer: (Settings.isLoaded && Settings.data && Settings.data.notifications && Settings.data.notifications.alwaysOnTop) ? WlrLayer.Overlay : WlrLayer.Top + WlrLayershell.layer: (Settings.data.notifications && Settings.data.notifications.alwaysOnTop) ? WlrLayer.Overlay : WlrLayer.Top color: Color.transparent - readonly property string location: (Settings.isLoaded && Settings.data && Settings.data.notifications && Settings.data.notifications.location) ? Settings.data.notifications.location : "top_right" + readonly property string location: (Settings.data.notifications && Settings.data.notifications.location) ? Settings.data.notifications.location : "top_right" readonly property bool isTop: (location === "top") || (location.length >= 3 && location.substring(0, 3) === "top") readonly property bool isBottom: (location === "bottom") || (location.length >= 6 && location.substring(0, 6) === "bottom") readonly property bool isLeft: location.indexOf("_left") >= 0 diff --git a/Modules/OSD/OSD.qml b/Modules/OSD/OSD.qml index 07b028e5..e518cf89 100644 --- a/Modules/OSD/OSD.qml +++ b/Modules/OSD/OSD.qml @@ -22,7 +22,7 @@ Variants { property ListModel notificationModel: NotificationService.activeList // If no notification display activated in settings, then show them all - property bool canShowOnThisScreen: Settings.isLoaded && modelData && (Settings.data.osd.monitors.includes(modelData.name) || (Settings.data.osd.monitors.length === 0)) + property bool canShowOnThisScreen: modelData && (Settings.data.osd.monitors.includes(modelData.name) || (Settings.data.osd.monitors.length === 0)) // Loader is only active when actually showing something active: false @@ -104,7 +104,7 @@ Variants { id: panel screen: modelData - readonly property string location: (Settings.isLoaded && Settings.data && Settings.data.osd && Settings.data.osd.location) ? Settings.data.osd.location : "top_right" + readonly property string location: (Settings.data.osd && Settings.data.osd.location) ? Settings.data.osd.location : "top_right" readonly property bool isTop: (location === "top") || (location.length >= 3 && location.substring(0, 3) === "top") readonly property bool isBottom: (location === "bottom") || (location.length >= 6 && location.substring(0, 6) === "bottom") readonly property bool isLeft: (location.indexOf("_left") >= 0) || (location === "left") diff --git a/Modules/Toast/ToastOverlay.qml b/Modules/Toast/ToastOverlay.qml index 78cb670a..11cb5037 100644 --- a/Modules/Toast/ToastOverlay.qml +++ b/Modules/Toast/ToastOverlay.qml @@ -16,6 +16,6 @@ Variants { scaling: ScalingService.getScreenScale(modelData) // Only activate on enabled screens - active: Settings.isLoaded && modelData && (Settings.data.notifications.monitors.includes(modelData.name) || Settings.data.notifications.monitors.length === 0) + active: modelData && (Settings.data.notifications.monitors.includes(modelData.name) || Settings.data.notifications.monitors.length === 0) } } diff --git a/Modules/Toast/ToastScreen.qml b/Modules/Toast/ToastScreen.qml index 6a635aea..ca35c68c 100644 --- a/Modules/Toast/ToastScreen.qml +++ b/Modules/Toast/ToastScreen.qml @@ -128,7 +128,7 @@ Item { screen: root.screen - readonly property string location: (Settings.isLoaded && Settings.data && Settings.data.notifications && Settings.data.notifications.location) ? Settings.data.notifications.location : "top_right" + readonly property string location: (Settings.data.notifications && Settings.data.notifications.location) ? Settings.data.notifications.location : "top_right" readonly property bool isTop: (location === "top") || (location.length >= 3 && location.substring(0, 3) === "top") readonly property bool isBottom: (location === "bottom") || (location.length >= 6 && location.substring(0, 6) === "bottom") readonly property bool isLeft: location.indexOf("_left") >= 0 diff --git a/Services/ClipboardService.qml b/Services/ClipboardService.qml index 65287ea4..bb224a28 100644 --- a/Services/ClipboardService.qml +++ b/Services/ClipboardService.qml @@ -10,7 +10,7 @@ Singleton { id: root // Public API - property bool active: Settings.isLoaded && Settings.data.appLauncher.enableClipboardHistory && cliphistAvailable + property bool active: Settings.data.appLauncher.enableClipboardHistory && cliphistAvailable property bool loading: false property var items: [] // [{id, preview, mime, isImage}] diff --git a/Services/MatugenService.qml b/Services/MatugenService.qml index e3410d57..694bb1e7 100644 --- a/Services/MatugenService.qml +++ b/Services/MatugenService.qml @@ -10,7 +10,7 @@ import qs.Services Singleton { id: root - property string dynamicConfigPath: Settings.isLoaded ? Settings.cacheDir + "matugen.dynamic.toml" : "" + property string dynamicConfigPath: Settings.cacheDir + "matugen.dynamic.toml" // External state management Connections { @@ -47,11 +47,6 @@ Singleton { // Generate colors using current wallpaper and settings function generateFromWallpaper() { - if (!Settings.isLoaded) { - Logger.log("Matugen", "Settings not loaded yet, skipping wallpaper color generation") - return - } - Logger.log("Matugen", "Generating from wallpaper on screen:", Screen.name) var wp = WallpaperService.getWallpaper(Screen.name).replace(/'/g, "'\\''") if (wp === "") { diff --git a/Services/WallpaperService.qml b/Services/WallpaperService.qml index 37181a64..8b01f76c 100644 --- a/Services/WallpaperService.qml +++ b/Services/WallpaperService.qml @@ -26,6 +26,8 @@ Singleton { // Cache for current wallpapers - can be updated directly since we use signals for notifications property var currentWallpapers: ({}) + property bool isInitialized: false + // Signals for reactive UI updates signal wallpaperChanged(string screenName, string path) // Emitted when a wallpaper changes @@ -75,6 +77,8 @@ Singleton { function init() { Logger.log("Wallpaper", "Service started") + translateModels() + // Rebuild cache from persisted settings var monitors = Settings.data.wallpaper.monitors || [] currentWallpapers = ({}) @@ -86,7 +90,7 @@ Singleton { } } - translateModels() + isInitialized = true } // ------------------------------------------------- From 0d0b9a21f2e76dbbef4611176d721251ac504f84 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Mon, 29 Sep 2025 09:25:45 -0400 Subject: [PATCH 2/5] Wallpaper Selector: added a shortcut to the wallpaper settings in the top bar. --- Modules/Background/Background.qml | 8 ++------ Modules/Wallpaper/WallpaperPanel.qml | 12 ++++++++++++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/Modules/Background/Background.qml b/Modules/Background/Background.qml index a83aed58..3cd5661c 100644 --- a/Modules/Background/Background.qml +++ b/Modules/Background/Background.qml @@ -224,9 +224,7 @@ Variants { easing.type: Easing.InOutCubic onFinished: { // Swap images after transition completes - if (currentWallpaper.source !== "") { - currentWallpaper.source = "" - } + currentWallpaper.source = "" currentWallpaper.source = nextWallpaper.source nextWallpaper.source = "" transitionProgress = 0.0 @@ -249,9 +247,7 @@ Variants { function setWallpaperImmediate(source) { transitionAnimation.stop() transitionProgress = 0.0 - if (currentWallpaper.source !== "") { - currentWallpaper.source = "" - } + currentWallpaper.source = "" currentWallpaper.source = source nextWallpaper.source = "" } diff --git a/Modules/Wallpaper/WallpaperPanel.qml b/Modules/Wallpaper/WallpaperPanel.qml index 6266aa2b..4a8f8148 100644 --- a/Modules/Wallpaper/WallpaperPanel.qml +++ b/Modules/Wallpaper/WallpaperPanel.qml @@ -4,6 +4,7 @@ import QtQuick.Controls import Quickshell import Quickshell.Wayland import qs.Commons +import qs.Modules.Settings import qs.Services import qs.Widgets import "../../Helpers/FuzzySort.js" as FuzzySort @@ -63,6 +64,17 @@ NPanel { Layout.fillWidth: true } + NIconButton { + icon: "settings" + tooltipText: I18n.tr("settings.wallpaper.settings.section.label") + baseSize: Style.baseWidgetSize * 0.8 + onClicked: { + var settingsPanel = PanelService.getPanel("settingsPanel") + settingsPanel.requestedTab = SettingsPanel.Tab.Wallpaper + settingsPanel.open() + } + } + NIconButton { icon: "refresh" tooltipText: I18n.tr("tooltips.refresh-wallpaper-list") From 933ba5461214ef1bdd38d70f35b33d47bcdc671e Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Mon, 29 Sep 2025 09:58:48 -0400 Subject: [PATCH 3/5] Init Sequence: minor reordering --- shell.qml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/shell.qml b/shell.qml index 4a7afb58..c15468e1 100644 --- a/shell.qml +++ b/shell.qml @@ -82,12 +82,12 @@ ShellRoot { PanelService.lockScreen = lockScreen Logger.log("Shell", "---------------------------") + WallpaperService.init() + MatugenService.init() + ColorSchemeService.init() BarWidgetRegistry.init() LocationService.init() NightLightService.apply() - ColorSchemeService.init() - MatugenService.init() - WallpaperService.init() FontService.init() HooksService.init() BluetoothService.init() From 22794ea922ec4bb97a18948de3c7370963b0e9e8 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Mon, 29 Sep 2025 10:07:58 -0400 Subject: [PATCH 4/5] DateTime: proper locale usage. Fix #390 Replaced all Qt.formatDateTime() by Qt.locale().toString() --- Modules/Bar/Widgets/Clock.qml | 4 ++-- Modules/ControlCenter/Cards/WeatherCard.qml | 2 +- Modules/LockScreen/LockScreen.qml | 4 ++-- Modules/Settings/Bar/WidgetSettings/ClockSettings.qml | 4 ++-- Widgets/NDateTimeTokens.qml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Modules/Bar/Widgets/Clock.qml b/Modules/Bar/Widgets/Clock.qml index ae179ebe..14e1f4df 100644 --- a/Modules/Bar/Widgets/Clock.qml +++ b/Modules/Bar/Widgets/Clock.qml @@ -61,7 +61,7 @@ Rectangle { spacing: Settings.data.bar.showCapsule ? -4 * scaling : -2 * scaling Repeater { id: repeater - model: Qt.formatDateTime(now, formatHorizontal.trim()).split("\\n") + model: Qt.locale().toString(now, formatHorizontal.trim()).split("\\n") NText { visible: text !== "" text: modelData @@ -91,7 +91,7 @@ Rectangle { anchors.centerIn: parent spacing: -2 * scaling Repeater { - model: Qt.formatDateTime(now, formatVertical.trim()).split(" ") + model: Qt.locale().toString(now, formatVertical.trim()).split(" ") delegate: NText { visible: text !== "" text: modelData diff --git a/Modules/ControlCenter/Cards/WeatherCard.qml b/Modules/ControlCenter/Cards/WeatherCard.qml index 160c48cc..a5cf8f45 100644 --- a/Modules/ControlCenter/Cards/WeatherCard.qml +++ b/Modules/ControlCenter/Cards/WeatherCard.qml @@ -88,7 +88,7 @@ NBox { NText { text: { var weatherDate = new Date(LocationService.data.weather.daily.time[index].replace(/-/g, "/")) - return Qt.formatDateTime(weatherDate, "ddd") + return Qt.locale().toString(weatherDate, "ddd") } color: Color.mOnSurface Layout.alignment: Qt.AlignHCenter diff --git a/Modules/LockScreen/LockScreen.qml b/Modules/LockScreen/LockScreen.qml index be75508c..bdb5f4f4 100644 --- a/Modules/LockScreen/LockScreen.qml +++ b/Modules/LockScreen/LockScreen.qml @@ -27,12 +27,12 @@ Loader { } function formatTime() { - return Settings.data.location.use12hourFormat ? Qt.formatDateTime(new Date(), "h:mm A") : Qt.formatDateTime(new Date(), "HH:mm") + return Settings.data.location.use12hourFormat ? Qt.locale().toString(new Date(), "h:mm A") : Qt.locale().toString(new Date(), "HH:mm") } function formatDate() { // For full text date, day is always before month, so we use this format for everybody: Wednesday, September 17. - return Qt.formatDateTime(new Date(), "dddd, MMMM d") + return Qt.locale().toString(new Date(), "dddd, MMMM d") } function scheduleUnloadAfterUnlock() { diff --git a/Modules/Settings/Bar/WidgetSettings/ClockSettings.qml b/Modules/Settings/Bar/WidgetSettings/ClockSettings.qml index 6214590a..af48201a 100644 --- a/Modules/Settings/Bar/WidgetSettings/ClockSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/ClockSettings.qml @@ -182,7 +182,7 @@ ColumnLayout { // Horizontal Repeater { Layout.topMargin: Style.marginM * scaling - model: Qt.formatDateTime(now, valueFormatHorizontal.trim()).split("\\n") + model: Qt.locale().toString(now, valueFormatHorizontal.trim()).split("\\n") delegate: NText { visible: text !== "" text: modelData @@ -213,7 +213,7 @@ ColumnLayout { Repeater { Layout.topMargin: Style.marginM * scaling - model: Qt.formatDateTime(now, valueFormatVertical.trim()).split(" ") + model: Qt.locale().toString(now, valueFormatVertical.trim()).split(" ") delegate: NText { visible: text !== "" text: modelData diff --git a/Widgets/NDateTimeTokens.qml b/Widgets/NDateTimeTokens.qml index 523e74f0..eae75d7b 100644 --- a/Widgets/NDateTimeTokens.qml +++ b/Widgets/NDateTimeTokens.qml @@ -312,7 +312,7 @@ Rectangle { NText { anchors.centerIn: parent - text: Qt.formatDateTime(root.sampleDate, modelData.token) + text: Qt.locale().toString(root.sampleDate, modelData.token) color: tokenMouseArea.containsMouse ? Color.mOnPrimary : Color.mSurfaceVariant font.pointSize: Style.fontSizeS * scaling From 5cea61114bae4eb2c5c722b251cc1ea6d75a4345 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Mon, 29 Sep 2025 10:20:19 -0400 Subject: [PATCH 5/5] Scaling: fix scaling not properly applied on startup. --- Modules/Background/Background.qml | 4 ++-- Modules/Dock/Dock.qml | 8 -------- Services/ScalingService.qml | 20 +++++++------------- 3 files changed, 9 insertions(+), 23 deletions(-) diff --git a/Modules/Background/Background.qml b/Modules/Background/Background.qml index 3cd5661c..6a62ed9c 100644 --- a/Modules/Background/Background.qml +++ b/Modules/Background/Background.qml @@ -233,7 +233,7 @@ Variants { }) } } - + function setWallpaperInitial() { // On startup, defer assigning wallpaper until the service cache is ready, retries every tick if (!WallpaperService || !WallpaperService.isInitialized) { @@ -311,4 +311,4 @@ Variants { } } } -} \ No newline at end of file +} diff --git a/Modules/Dock/Dock.qml b/Modules/Dock/Dock.qml index ca3e6ae7..4d2158c0 100644 --- a/Modules/Dock/Dock.qml +++ b/Modules/Dock/Dock.qml @@ -60,14 +60,6 @@ Variants { } } - // Update when Settings are loaded - Connections { - target: Settings - function onSettingsLoaded() { - updateDockApps() - } - } - // Shared properties between peek and dock windows readonly property bool autoHide: Settings.data.dock.autoHide readonly property int hideDelay: 500 diff --git a/Services/ScalingService.qml b/Services/ScalingService.qml index 6b204f77..0b8ef479 100644 --- a/Services/ScalingService.qml +++ b/Services/ScalingService.qml @@ -15,19 +15,13 @@ Singleton { Component.onCompleted: { Logger.log("Scaling", "Service started") - } - - Connections { - target: Settings - function onSettingsLoaded() { - // Initialize cache from Settings once they are loaded on startup - var monitors = Settings.data.ui.monitorsScaling || [] - for (var i = 0; i < monitors.length; i++) { - if (monitors[i].name && monitors[i].scale !== undefined) { - currentScales[monitors[i].name] = monitors[i].scale - root.scaleChanged(monitors[i].name, monitors[i].scale) - Logger.log("Scaling", "Caching scaling for", monitors[i].name, ":", monitors[i].scale) - } + // Initialize cache from Settings once they are loaded on startup + var monitors = Settings.data.ui.monitorsScaling || [] + for (var i = 0; i < monitors.length; i++) { + if (monitors[i].name && monitors[i].scale !== undefined) { + currentScales[monitors[i].name] = monitors[i].scale + root.scaleChanged(monitors[i].name, monitors[i].scale) + Logger.log("Scaling", "Caching scaling for", monitors[i].name, ":", monitors[i].scale) } } }