diff --git a/core/cmd/dms/commands_common.go b/core/cmd/dms/commands_common.go index 15769f8c..b479814e 100644 --- a/core/cmd/dms/commands_common.go +++ b/core/cmd/dms/commands_common.go @@ -26,6 +26,17 @@ var runCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { daemon, _ := cmd.Flags().GetBool("daemon") session, _ := cmd.Flags().GetBool("session") + if v, _ := cmd.Flags().GetString("log-level"); v != "" { + if err := os.Setenv("DMS_LOG_LEVEL", v); err != nil { + log.Fatalf("Failed to set DMS_LOG_LEVEL: %v", err) + } + } + if v, _ := cmd.Flags().GetString("log-file"); v != "" { + if err := os.Setenv("DMS_LOG_FILE", v); err != nil { + log.Fatalf("Failed to set DMS_LOG_FILE: %v", err) + } + } + log.ApplyEnvOverrides() if daemon { runShellDaemon(session) } else { diff --git a/core/cmd/dms/main.go b/core/cmd/dms/main.go index c8181481..45b9a1e2 100644 --- a/core/cmd/dms/main.go +++ b/core/cmd/dms/main.go @@ -15,6 +15,8 @@ func init() { runCmd.Flags().BoolP("daemon", "d", false, "Run in daemon mode") runCmd.Flags().Bool("daemon-child", false, "Internal flag for daemon child process") runCmd.Flags().Bool("session", false, "Session managed (like as a systemd unit)") + runCmd.Flags().String("log-level", "", "Log level: debug, info, warn, error, fatal (overrides DMS_LOG_LEVEL)") + runCmd.Flags().String("log-file", "", "Append logs to this file in addition to stderr (overrides DMS_LOG_FILE)") runCmd.Flags().MarkHidden("daemon-child") greeterCmd.AddCommand(greeterInstallCmd, greeterSyncCmd, greeterEnableCmd, greeterStatusCmd, greeterUninstallCmd) diff --git a/core/cmd/dms/main_distro.go b/core/cmd/dms/main_distro.go index 2b544ff7..3f679052 100644 --- a/core/cmd/dms/main_distro.go +++ b/core/cmd/dms/main_distro.go @@ -15,6 +15,8 @@ func init() { runCmd.Flags().BoolP("daemon", "d", false, "Run in daemon mode") runCmd.Flags().Bool("daemon-child", false, "Internal flag for daemon child process") runCmd.Flags().Bool("session", false, "Session managed (like as a systemd unit)") + runCmd.Flags().String("log-level", "", "Log level: debug, info, warn, error, fatal (overrides DMS_LOG_LEVEL)") + runCmd.Flags().String("log-file", "", "Append logs to this file in addition to stderr (overrides DMS_LOG_FILE)") runCmd.Flags().MarkHidden("daemon-child") greeterCmd.AddCommand(greeterInstallCmd, greeterSyncCmd, greeterEnableCmd, greeterStatusCmd, greeterUninstallCmd) diff --git a/core/cmd/dms/shell.go b/core/cmd/dms/shell.go index 7ce20039..b481d7b3 100644 --- a/core/cmd/dms/shell.go +++ b/core/cmd/dms/shell.go @@ -80,6 +80,16 @@ func getRuntimeDir() string { return os.TempDir() } +func appendLogEnv(env []string) []string { + if v := os.Getenv("DMS_LOG_LEVEL"); v != "" { + env = append(env, "DMS_LOG_LEVEL="+v) + } + if v := os.Getenv("DMS_LOG_FILE"); v != "" { + env = append(env, "DMS_LOG_FILE="+v) + } + return env +} + func hasSystemdRun() bool { _, err := exec.LookPath("systemd-run") return err == nil @@ -216,6 +226,8 @@ func runShellInteractive(session bool) { cmd.Env = append(cmd.Env, "QT_QPA_PLATFORM=wayland;xcb") } + cmd.Env = appendLogEnv(cmd.Env) + cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr @@ -459,6 +471,8 @@ func runShellDaemon(session bool) { cmd.Env = append(cmd.Env, "QT_QPA_PLATFORM=wayland;xcb") } + cmd.Env = appendLogEnv(cmd.Env) + devNull, err := os.OpenFile("/dev/null", os.O_RDWR, 0) if err != nil { log.Fatalf("Error opening /dev/null: %v", err) diff --git a/core/go.mod b/core/go.mod index 41d1efd4..fc270bf0 100644 --- a/core/go.mod +++ b/core/go.mod @@ -66,12 +66,12 @@ require ( github.com/go-git/go-git/v6 v6.0.0-alpha.2 github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/lucasb-eyer/go-colorful v1.4.0 - github.com/mattn/go-isatty v0.0.22 // indirect + github.com/mattn/go-isatty v0.0.22 github.com/mattn/go-localereader v0.0.1 // indirect github.com/mattn/go-runewidth v0.0.23 // indirect github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect github.com/muesli/cancelreader v0.2.2 // indirect - github.com/muesli/termenv v0.16.0 // indirect + github.com/muesli/termenv v0.16.0 github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/spf13/afero v1.15.0 diff --git a/core/internal/log/log.go b/core/internal/log/log.go index 6b3ede3c..c52ed623 100644 --- a/core/internal/log/log.go +++ b/core/internal/log/log.go @@ -1,12 +1,16 @@ package log import ( + "io" "os" + "regexp" "strings" "sync" "github.com/charmbracelet/lipgloss" cblog "github.com/charmbracelet/log" + "github.com/mattn/go-isatty" + "github.com/muesli/termenv" ) // Logger embeds the Charm Logger and adds Printf/Fatalf @@ -21,8 +25,26 @@ func (l *Logger) Fatalf(format string, v ...any) { l.Logger.Fatalf(format, v...) var ( logger *Logger initLogger sync.Once + + logMu sync.Mutex + logFile *os.File + logStderr io.Writer = os.Stderr + + ansiRe = regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]`) ) +// ansiStripWriter strips ANSI escape sequences before forwarding to w. Used +// for the file sink so colored stderr stays colored while the file stays plain. +type ansiStripWriter struct{ w io.Writer } + +func (a *ansiStripWriter) Write(p []byte) (int, error) { + stripped := ansiRe.ReplaceAll(p, nil) + if _, err := a.w.Write(stripped); err != nil { + return 0, err + } + return len(p), nil +} + func parseLogLevel(level string) cblog.Level { switch strings.ToLower(level) { case "debug": @@ -86,7 +108,7 @@ func GetLogger() *Logger { SetString(" DEBUG"). Foreground(lipgloss.Color("4")) - base := cblog.New(os.Stderr) + base := cblog.New(logStderr) base.SetStyles(styles) base.SetReportTimestamp(false) @@ -98,10 +120,85 @@ func GetLogger() *Logger { base.SetPrefix(" go") logger = &Logger{base} + + if path := os.Getenv("DMS_LOG_FILE"); path != "" { + _ = SetLogFile(path) + } }) return logger } +// SetLevel updates the active log level. Accepts the same strings as +// DMS_LOG_LEVEL. Unknown values default to info. +func SetLevel(level string) { + GetLogger().SetLevel(parseLogLevel(level)) +} + +// SetLogFile makes the logger append to path in addition to stderr. Passing an +// empty string detaches the file sink. Atomic per-line writes (≤PIPE_BUF) on +// O_APPEND keep concurrent Go and QML writers from corrupting each other. +// +// Color handling: charmbracelet/log auto-detects color support from its +// io.Writer, and io.MultiWriter doesn't pass that through, so we force the ANSI +// profile when stderr is a TTY and route the file through ansiStripWriter so +// the file stays plain while stderr keeps its colors. +func SetLogFile(path string) error { + logMu.Lock() + defer logMu.Unlock() + + if logFile != nil { + logFile.Close() + logFile = nil + } + + l := GetLogger() + if path == "" { + l.SetOutput(logStderr) + applyColorProfile(l, logStderr) + return nil + } + + f, err := os.OpenFile(path, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0o644) + if err != nil { + return err + } + logFile = f + out := io.MultiWriter(logStderr, &ansiStripWriter{w: f}) + l.SetOutput(out) + applyColorProfile(l, logStderr) + return nil +} + +// applyColorProfile forces the renderer's color profile to match what stderr +// would produce on its own, undoing the auto-downgrade triggered by wrapping +// stderr in a non-TTY writer (e.g. io.MultiWriter). +func applyColorProfile(l *Logger, stderr io.Writer) { + f, ok := stderr.(*os.File) + if !ok { + l.SetColorProfile(termenv.Ascii) + return + } + if isatty.IsTerminal(f.Fd()) { + l.SetColorProfile(termenv.ANSI) + return + } + l.SetColorProfile(termenv.Ascii) +} + +// ApplyEnvOverrides re-reads DMS_LOG_LEVEL and DMS_LOG_FILE and reconfigures +// the singleton. Safe to call after CLI flags have rewritten the environment. +func ApplyEnvOverrides() { + GetLogger() + if level := os.Getenv("DMS_LOG_LEVEL"); level != "" { + SetLevel(level) + } + if path := os.Getenv("DMS_LOG_FILE"); path != "" { + if err := SetLogFile(path); err != nil { + Warnf("Failed to open log file %q: %v", path, err) + } + } +} + // * Convenience wrappers func Debug(msg any, keyvals ...any) { GetLogger().Debug(msg, keyvals...) } diff --git a/quickshell/Common/CacheData.qml b/quickshell/Common/CacheData.qml index 6de7a8bd..70ef250a 100644 --- a/quickshell/Common/CacheData.qml +++ b/quickshell/Common/CacheData.qml @@ -5,9 +5,11 @@ import QtCore import QtQuick import Quickshell import Quickshell.Io +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("CacheData") readonly property int cacheConfigVersion: 1 @@ -131,7 +133,7 @@ Singleton { } } } catch (e) { - console.warn("CacheData: Failed to parse cache:", e.message); + log.warn("Failed to parse cache:", e.message); } finally { _loading = false; } @@ -149,7 +151,7 @@ Singleton { } function migrateFromUndefinedToV1(cache) { - console.info("CacheData: Migrating configuration from undefined to version 1"); + log.info("Migrating configuration from undefined to version 1"); } function cleanupUnusedKeys() { @@ -164,7 +166,7 @@ Singleton { for (const key in cache) { if (!validKeys.includes(key)) { - console.log("CacheData: Removing unused key:", key); + log.debug("Removing unused key:", key); delete cache[key]; needsSave = true; } @@ -174,7 +176,7 @@ Singleton { cacheFile.setText(JSON.stringify(cache, null, 2)); } } catch (e) { - console.warn("CacheData: Failed to cleanup unused keys:", e.message); + log.warn("Failed to cleanup unused keys:", e.message); } } @@ -184,7 +186,7 @@ Singleton { if (content && content.trim()) return JSON.parse(content); } catch (e) { - console.warn("CacheData: Failed to parse launcher cache:", e.message); + log.warn("Failed to parse launcher cache:", e.message); } return null; } @@ -220,7 +222,7 @@ Singleton { } onLoadFailed: error => { if (!isGreeterMode) { - console.info("CacheData: No cache file found, starting fresh"); + log.info("No cache file found, starting fresh"); } } } diff --git a/quickshell/Common/I18n.qml b/quickshell/Common/I18n.qml index aae0009b..079b3746 100644 --- a/quickshell/Common/I18n.qml +++ b/quickshell/Common/I18n.qml @@ -5,9 +5,11 @@ import QtQuick import Qt.labs.folderlistmodel import Quickshell import Quickshell.Io +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("I18n") property string _resolvedLocale: "en" @@ -54,15 +56,15 @@ Singleton { try { root.translations = JSON.parse(text()); root.translationsLoaded = true; - console.info(`I18n: Loaded translations for '${root._resolvedLocale}' (${Object.keys(root.translations).length} contexts)`); + log.info(`I18n: Loaded translations for '${root._resolvedLocale}' (${Object.keys(root.translations).length} contexts)`); } catch (e) { - console.warn(`I18n: Error parsing '${root._resolvedLocale}':`, e, "- falling back to English"); + log.warn(`I18n: Error parsing '${root._resolvedLocale}':`, e, "- falling back to English"); root._fallbackToEnglish(); } } onLoadFailed: error => { - console.warn(`I18n: Failed to load '${root._resolvedLocale}' (${error}), ` + "falling back to English"); + log.warn(`I18n: Failed to load '${root._resolvedLocale}' (${error}), ` + "falling back to English"); root._fallbackToEnglish(); } } @@ -105,14 +107,14 @@ Singleton { _selectedPath = fileUrl; translationsLoaded = false; translations = ({}); - console.info(`I18n: Using locale '${localeTag}' from ${fileUrl}`); + log.info(`I18n: Using locale '${localeTag}' from ${fileUrl}`); } function _fallbackToEnglish() { _selectedPath = ""; translationsLoaded = false; translations = ({}); - console.warn("I18n: Falling back to built-in English strings"); + log.warn("Falling back to built-in English strings"); } function tr(term, context) { diff --git a/quickshell/Common/Proc.qml b/quickshell/Common/Proc.qml index 813f9380..e84239ff 100644 --- a/quickshell/Common/Proc.qml +++ b/quickshell/Common/Proc.qml @@ -3,9 +3,11 @@ pragma ComponentBehavior: Bound import QtQuick import Quickshell +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("Proc") readonly property int noTimeout: -1 property int defaultDebounceMs: 50 @@ -112,7 +114,7 @@ Singleton { const safeExitCode = exitCodeValue !== null && exitCodeValue !== undefined ? exitCodeValue : -1; entry.callback(safeOutput, safeExitCode); } catch (e) { - console.warn("runCommand callback error for command:", entry.command, "Error:", e); + log.warn("runCommand callback error for command:", entry.command, "Error:", e); } } try { diff --git a/quickshell/Common/SessionData.qml b/quickshell/Common/SessionData.qml index ea5be6a1..2fbedca9 100644 --- a/quickshell/Common/SessionData.qml +++ b/quickshell/Common/SessionData.qml @@ -12,6 +12,7 @@ import "settings/SessionStore.js" as Store Singleton { id: root + readonly property var log: Log.scoped("SessionData") readonly property int sessionConfigVersion: 3 @@ -257,7 +258,7 @@ Singleton { } catch (e) { _parseError = true; const msg = e.message; - console.error("SessionData: Failed to parse session.json - file will not be overwritten."); + log.error("Failed to parse session.json - file will not be overwritten."); Qt.callLater(() => ToastService.showError(I18n.tr("Failed to parse session.json"), msg)); } } @@ -337,7 +338,7 @@ Singleton { } catch (e) { _parseError = true; const msg = e.message; - console.error("SessionData: Failed to parse session.json - file will not be overwritten."); + log.error("Failed to parse session.json - file will not be overwritten."); Qt.callLater(() => ToastService.showError(I18n.tr("Failed to parse session.json"), msg)); } } @@ -552,7 +553,7 @@ Singleton { } if (!screen) { - console.warn("SessionData: Screen not found"); + log.warn("Screen not found"); return; } @@ -649,7 +650,7 @@ Singleton { } if (!screen) { - console.warn("SessionData: Screen not found"); + log.warn("Screen not found"); return; } @@ -680,7 +681,7 @@ Singleton { } if (!screen) { - console.warn("SessionData: Screen not found"); + log.warn("Screen not found"); return; } @@ -711,7 +712,7 @@ Singleton { } if (!screen) { - console.warn("SessionData: Screen not found"); + log.warn("Screen not found"); return; } @@ -742,7 +743,7 @@ Singleton { } if (!screen) { - console.warn("SessionData: Screen not found"); + log.warn("Screen not found"); return; } diff --git a/quickshell/Common/SettingsData.qml b/quickshell/Common/SettingsData.qml index 247a9949..9c8b6ffb 100644 --- a/quickshell/Common/SettingsData.qml +++ b/quickshell/Common/SettingsData.qml @@ -13,6 +13,7 @@ import "settings/SettingsStore.js" as Store Singleton { id: root + readonly property var log: Log.scoped("SettingsData") readonly property int settingsConfigVersion: 5 @@ -1294,7 +1295,7 @@ Singleton { } catch (e) { _parseError = true; const msg = e.message; - console.error("SettingsData: Failed to parse settings.json - file will not be overwritten. Error:", msg); + log.error("Failed to parse settings.json - file will not be overwritten. Error:", msg); Qt.callLater(() => ToastService.showError(I18n.tr("Failed to parse settings.json"), msg)); applyStoredTheme(); } finally { @@ -1315,12 +1316,12 @@ Singleton { if (_isReadOnly) { _hasUnsavedChanges = _checkForUnsavedChanges(); if (!wasReadOnly) - console.info("SettingsData: settings.json is now read-only"); + log.info("settings.json is now read-only"); } else { _loadedSettingsSnapshot = JSON.stringify(Store.toJson(root)); _hasUnsavedChanges = false; if (wasReadOnly) - console.info("SettingsData: settings.json is now writable"); + log.info("settings.json is now writable"); if (_pendingMigration) settingsFile.setText(JSON.stringify(_pendingMigration, null, 2)); } @@ -1374,7 +1375,7 @@ Singleton { } catch (e) { const msg = e.message || String(e); if (!_isMissingPluginSettingsError(e)) - console.warn("SettingsData: Failed to load plugin_settings.json. Error:", msg); + log.warn("Failed to load plugin_settings.json. Error:", msg); _resetPluginSettings(); } } @@ -1391,7 +1392,7 @@ Singleton { } catch (e) { _pluginParseError = true; const msg = e.message; - console.error("SettingsData: Failed to parse plugin_settings.json - file will not be overwritten. Error:", msg); + log.error("Failed to parse plugin_settings.json - file will not be overwritten. Error:", msg); Qt.callLater(() => ToastService.showError(I18n.tr("Failed to parse plugin_settings.json"), msg)); pluginSettings = {}; } finally { @@ -2794,7 +2795,7 @@ Singleton { } catch (e) { _parseError = true; const msg = e.message; - console.error("SettingsData: Failed to reload settings.json - file will not be overwritten. Error:", msg); + log.error("Failed to reload settings.json - file will not be overwritten. Error:", msg); Qt.callLater(() => ToastService.showError(I18n.tr("Failed to parse settings.json"), msg)); } finally { _loading = false; @@ -2829,7 +2830,7 @@ Singleton { if (!isGreeterMode) { const msg = String(error || ""); if (!_isMissingPluginSettingsError(error)) - console.warn("SettingsData: Failed to load plugin_settings.json. Error:", msg); + log.warn("Failed to load plugin_settings.json. Error:", msg); _resetPluginSettings(); } } diff --git a/quickshell/Common/Theme.qml b/quickshell/Common/Theme.qml index e6b1e5c7..7a692a8f 100644 --- a/quickshell/Common/Theme.qml +++ b/quickshell/Common/Theme.qml @@ -12,6 +12,7 @@ import "StockThemes.js" as StockThemes Singleton { id: root + readonly property var log: Log.scoped("Theme") readonly property string stateDir: Paths.strip(StandardPaths.writableLocation(StandardPaths.GenericCacheLocation).toString()) + "/DankMaterialShell" readonly property bool envDisableMatugen: Quickshell.env("DMS_DISABLE_MATUGEN") === "1" || Quickshell.env("DMS_DISABLE_MATUGEN") === "true" @@ -148,7 +149,7 @@ Singleton { } if (colorsFileLoadFailed && currentTheme === dynamic && rawWallpaperPath) { - console.info("Theme: Matugen now available, regenerating colors for dynamic theme"); + log.info("Matugen now available, regenerating colors for dynamic theme"); const isLight = (typeof SessionData !== "undefined" && SessionData.isLightMode); const iconTheme = (typeof SettingsData !== "undefined" && SettingsData.iconTheme) ? SettingsData.iconTheme : "System Default"; const selectedMatugenType = (typeof SettingsData !== "undefined" && SettingsData.matugenScheme) ? SettingsData.matugenScheme : "scheme-tonal-spot"; @@ -376,7 +377,7 @@ Singleton { "use": true }, response => { if (!response.error) { - console.info("Theme automation: IP location enabled after connection"); + log.info("Theme automation: IP location enabled after connection"); } }); } else if (SessionData.latitude !== 0.0 && SessionData.longitude !== 0.0) { @@ -389,13 +390,13 @@ Singleton { "longitude": SessionData.longitude }, locationResponse => { if (locationResponse?.error) { - console.warn("Theme automation: Failed to set location", locationResponse.error); + log.warn("Theme automation: Failed to set location", locationResponse.error); } }); } }); } else { - console.warn("Theme automation: No location configured"); + log.warn("Theme automation: No location configured"); } } } @@ -1525,12 +1526,12 @@ Singleton { function setDesiredTheme(kind, value, isLight, iconTheme, matugenType, stockColors) { if (!matugenAvailable) { - console.warn("Theme: matugen not available or disabled - cannot set system theme"); + log.warn("matugen not available or disabled - cannot set system theme"); return; } if (workerRunning) { - console.info("Theme: Worker already running, queueing request"); + log.info("Worker already running, queueing request"); pendingThemeRequest = { kind, value, @@ -1542,7 +1543,7 @@ Singleton { return; } - console.info("Theme: Setting desired theme -", kind, "mode:", isLight ? "light" : "dark", stockColors ? "(stock colors)" : "(dynamic)"); + log.info("Setting desired theme -", kind, "mode:", isLight ? "light" : "dark", stockColors ? "(stock colors)" : "(dynamic)"); if (typeof NiriService !== "undefined" && CompositorService.isNiri) { NiriService.suppressNextToast(); @@ -1557,7 +1558,7 @@ Singleton { "runUserTemplates": (typeof SettingsData !== "undefined") ? SettingsData.runUserMatugenTemplates : true }; - console.log("Theme: Starting matugen worker"); + log.debug("Starting matugen worker"); workerRunning = true; const args = ["dms", "matugen", "queue", "--state-dir", stateDir, "--shell-dir", shellDir, "--config-dir", configDir, "--kind", desired.kind, "--value", desired.value, "--mode", desired.mode, "--icon-theme", desired.iconTheme, "--matugen-type", desired.matugenType,]; @@ -1715,7 +1716,7 @@ Singleton { } if (!darkTheme || !darkTheme.primary) { - console.warn("Theme data not available for:", currentTheme); + log.warn("Theme data not available for:", currentTheme); return; } @@ -1953,10 +1954,10 @@ Singleton { id: systemThemeGenerator running: false stdout: SplitParser { - onRead: data => console.info("Theme worker:", data) + onRead: data => log.info("Theme worker:", data) } stderr: SplitParser { - onRead: data => console.warn("Theme worker:", data) + onRead: data => log.warn("Theme worker:", data) } onExited: exitCode => { @@ -1965,18 +1966,18 @@ Singleton { switch (exitCode) { case 0: - console.info("Theme: Matugen worker completed successfully"); + log.info("Matugen worker completed successfully"); root.matugenCompleted(currentMode, "success"); break; case 2: - console.log("Theme: Matugen worker completed with code 2 (no changes needed)"); + log.debug("Matugen worker completed with code 2 (no changes needed)"); root.matugenCompleted(currentMode, "no-changes"); break; default: if (typeof ToastService !== "undefined") { ToastService.showError("Theme worker failed (" + exitCode + ")"); } - console.warn("Theme: Matugen worker failed with exit code:", exitCode); + log.warn("Matugen worker failed with exit code:", exitCode); root.matugenCompleted(currentMode, "error"); } @@ -1985,7 +1986,7 @@ Singleton { const req = pendingThemeRequest; pendingThemeRequest = null; - console.info("Theme: Processing queued theme request"); + log.info("Processing queued theme request"); setDesiredTheme(req.kind, req.value, req.isLight, req.iconTheme, req.matugenType, req.stockColors); } } @@ -2039,7 +2040,7 @@ Singleton { } } } catch (e) { - console.error("Theme: Failed to parse dynamic colors:", e); + log.error("Failed to parse dynamic colors:", e); if (typeof ToastService !== "undefined") { ToastService.wallpaperErrorStatus = "error"; ToastService.showError("Dynamic colors parse error: " + e.message); @@ -2059,11 +2060,11 @@ Singleton { onLoadFailed: function (error) { if (currentTheme === dynamic) { - console.warn("Theme: Dynamic colors file load failed, marking for regeneration"); + log.warn("Dynamic colors file load failed, marking for regeneration"); colorsFileLoadFailed = true; const isGreeterMode = (typeof SessionData !== "undefined" && SessionData.isGreeterMode); if (!isGreeterMode && matugenAvailable && rawWallpaperPath) { - console.log("Theme: Matugen available, triggering immediate regeneration"); + log.debug("Matugen available, triggering immediate regeneration"); generateSystemThemesFromCurrentTheme(); } } @@ -2187,7 +2188,7 @@ Singleton { "endMinute": endMinute }, response => { if (response && response.error) { - console.error("Theme automation: Failed to sync time schedule:", response.error); + log.error("Theme automation: Failed to sync time schedule:", response.error); } }); @@ -2280,9 +2281,9 @@ Singleton { if (root.themeModeAutomationActive) { if (SessionData.nightModeUseIPLocation) { - console.warn("Theme automation: Waiting for IP location from backend"); + log.warn("Theme automation: Waiting for IP location from backend"); } else { - console.warn("Theme automation: Location mode requires coordinates"); + log.warn("Theme automation: Location mode requires coordinates"); } } } @@ -2364,7 +2365,7 @@ Singleton { "use": true }, response => { if (response?.error) { - console.warn("Theme automation: Failed to enable IP location", response.error); + log.warn("Theme automation: Failed to enable IP location", response.error); } }); return true; @@ -2378,7 +2379,7 @@ Singleton { "longitude": SessionData.longitude }, locResp => { if (locResp?.error) { - console.warn("Theme automation: Failed to set location", locResp.error); + log.warn("Theme automation: Failed to set location", locResp.error); } }); } diff --git a/quickshell/DMSShell.qml b/quickshell/DMSShell.qml index c0cbf84a..9052fbc0 100644 --- a/quickshell/DMSShell.qml +++ b/quickshell/DMSShell.qml @@ -27,6 +27,7 @@ import qs.Services Item { id: root + readonly property var log: Log.scoped("DMSShell") property bool osdSurfacesLoaded: true property int pendingOsdResumeReloads: 0 @@ -54,7 +55,7 @@ Item { item.popoutService = PopoutService; } item.pluginId = pluginId; - console.info("Daemon plugin loaded:", pluginId); + log.info("Daemon plugin loaded:", pluginId); } } } @@ -93,7 +94,7 @@ Item { } onFadeCancelled: { - console.log("Fade to lock cancelled by user on screen:", fadeWindowLoader.modelData.name); + log.debug("Fade to lock cancelled by user on screen:", fadeWindowLoader.modelData.name); } } @@ -133,7 +134,7 @@ Item { } onFadeCancelled: { - console.log("Fade to DPMS cancelled by user on screen:", fadeDpmsWindowLoader.modelData.name); + log.debug("Fade to DPMS cancelled by user on screen:", fadeDpmsWindowLoader.modelData.name); } } @@ -773,7 +774,7 @@ Item { cmd += " " + escapedPath; } - console.log("FilePicker: Launching", cmd); + log.debug("FilePicker: Launching", cmd); Quickshell.execDetached({ command: ["sh", "-c", cmd] @@ -805,10 +806,10 @@ Item { } function onAppPickerRequested(data) { - console.log("DMSShell: App picker requested with data:", JSON.stringify(data)); + log.debug("App picker requested with data:", JSON.stringify(data)); if (!data || !data.target) { - console.warn("DMSShell: Invalid app picker request data"); + log.warn("Invalid app picker request data"); return; } diff --git a/quickshell/DMSShellIPC.qml b/quickshell/DMSShellIPC.qml index c0258a98..37ed3810 100644 --- a/quickshell/DMSShellIPC.qml +++ b/quickshell/DMSShellIPC.qml @@ -9,6 +9,7 @@ import qs.Modules.Settings.DisplayConfig Item { id: root + readonly property var log: Log.scoped("DMSShellIPC") required property var powerMenuModalLoader required property var processListModalLoader @@ -861,7 +862,7 @@ Item { function set(key: string, value: string): string { if (!(key in SettingsData)) { - console.warn("Cannot set property, not found:", key); + log.warn("Cannot set property, not found:", key); return "SETTINGS_INVALID_KEY"; } @@ -894,12 +895,12 @@ Item { throw "Unsupported type"; } - console.warn("Setting:", key, value); + log.warn("Setting:", key, value); SettingsData[key] = value; SettingsData.saveSettings(); return "SETTINGS_SET_SUCCESS"; } catch (e) { - console.warn("Failed to set property:", key, "error:", e); + log.warn("Failed to set property:", key, "error:", e); return "SETTINGS_SET_FAILURE"; } } diff --git a/quickshell/Modals/AppPickerModal.qml b/quickshell/Modals/AppPickerModal.qml index 21881119..ba66acc0 100644 --- a/quickshell/Modals/AppPickerModal.qml +++ b/quickshell/Modals/AppPickerModal.qml @@ -1,5 +1,4 @@ import QtQuick -import Quickshell import qs.Common import qs.Modals.Common import qs.Widgets @@ -7,6 +6,7 @@ import qs.Services DankModal { id: root + readonly property var log: Log.scoped("AppPickerModal") property string title: I18n.tr("Select Application") property string targetData: "" @@ -30,52 +30,52 @@ DankModal { onBackgroundClicked: close() onDialogClosed: { - searchQuery = "" - selectedIndex = 0 - keyboardNavigationActive = false + searchQuery = ""; + selectedIndex = 0; + keyboardNavigationActive = false; } onOpened: { - searchQuery = "" - updateApplicationList() - selectedIndex = 0 + searchQuery = ""; + updateApplicationList(); + selectedIndex = 0; Qt.callLater(() => { if (contentLoader.item && contentLoader.item.searchField) { - contentLoader.item.searchField.text = "" - contentLoader.item.searchField.forceActiveFocus() + contentLoader.item.searchField.text = ""; + contentLoader.item.searchField.forceActiveFocus(); } - }) + }); } function updateApplicationList() { - applicationsModel.clear() - const apps = AppSearchService.applications - const usageHistory = usageHistoryKey && SettingsData[usageHistoryKey] ? SettingsData[usageHistoryKey] : {} - let filteredApps = [] + applicationsModel.clear(); + const apps = AppSearchService.applications; + const usageHistory = usageHistoryKey && SettingsData[usageHistoryKey] ? SettingsData[usageHistoryKey] : {}; + let filteredApps = []; for (const app of apps) { - if (!app || !app.categories) continue - - let matchesCategory = categoryFilter.length === 0 + if (!app || !app.categories) + continue; + let matchesCategory = categoryFilter.length === 0; if (categoryFilter.length > 0) { try { for (const cat of app.categories) { if (categoryFilter.includes(cat)) { - matchesCategory = true - break + matchesCategory = true; + break; } } } catch (e) { - console.warn("AppPicker: Error iterating categories for", app.name, ":", e) - continue + log.warn("AppPicker: Error iterating categories for", app.name, ":", e); + continue; } } if (matchesCategory) { - const name = app.name || "" - const lowerName = name.toLowerCase() - const lowerQuery = searchQuery.toLowerCase() + const name = app.name || ""; + const lowerName = name.toLowerCase(); + const lowerQuery = searchQuery.toLowerCase(); if (searchQuery === "" || lowerName.includes(lowerQuery)) { filteredApps.push({ @@ -84,21 +84,21 @@ DankModal { exec: app.exec || app.execString || "", startupClass: app.startupWMClass || "", appData: app - }) + }); } } } filteredApps.sort((a, b) => { - const aId = a.appData.id || a.appData.execString || a.appData.exec || "" - const bId = b.appData.id || b.appData.execString || b.appData.exec || "" - const aUsage = usageHistory[aId] ? usageHistory[aId].count : 0 - const bUsage = usageHistory[bId] ? usageHistory[bId].count : 0 + const aId = a.appData.id || a.appData.execString || a.appData.exec || ""; + const bId = b.appData.id || b.appData.execString || b.appData.exec || ""; + const aUsage = usageHistory[aId] ? usageHistory[aId].count : 0; + const bUsage = usageHistory[bId] ? usageHistory[bId].count : 0; if (aUsage !== bUsage) { - return bUsage - aUsage + return bUsage - aUsage; } - return (a.name || "").localeCompare(b.name || "") - }) + return (a.name || "").localeCompare(b.name || ""); + }); filteredApps.forEach(app => { applicationsModel.append({ @@ -107,10 +107,10 @@ DankModal { exec: app.exec, startupClass: app.startupClass, appId: app.appData.id || app.appData.execString || app.appData.exec || "" - }) - }) + }); + }); - console.log("AppPicker: Found " + filteredApps.length + " applications") + log.debug("AppPicker: Found " + filteredApps.length + " applications"); } onSearchQueryChanged: updateApplicationList() @@ -129,56 +129,57 @@ DankModal { focus: true Keys.onEscapePressed: event => { - root.close() - event.accepted = true + root.close(); + event.accepted = true; } Keys.onPressed: event => { - if (applicationsModel.count === 0) return + if (applicationsModel.count === 0) + return; // Toggle view mode with Tab key if (event.key === Qt.Key_Tab) { - root.viewMode = root.viewMode === "grid" ? "list" : "grid" - event.accepted = true - return + root.viewMode = root.viewMode === "grid" ? "list" : "grid"; + event.accepted = true; + return; } if (root.viewMode === "grid") { if (event.key === Qt.Key_Left) { - root.keyboardNavigationActive = true - root.selectedIndex = Math.max(0, root.selectedIndex - 1) - event.accepted = true + root.keyboardNavigationActive = true; + root.selectedIndex = Math.max(0, root.selectedIndex - 1); + event.accepted = true; } else if (event.key === Qt.Key_Right) { - root.keyboardNavigationActive = true - root.selectedIndex = Math.min(applicationsModel.count - 1, root.selectedIndex + 1) - event.accepted = true + root.keyboardNavigationActive = true; + root.selectedIndex = Math.min(applicationsModel.count - 1, root.selectedIndex + 1); + event.accepted = true; } else if (event.key === Qt.Key_Up) { - root.keyboardNavigationActive = true - root.selectedIndex = Math.max(0, root.selectedIndex - root.gridColumns) - event.accepted = true + root.keyboardNavigationActive = true; + root.selectedIndex = Math.max(0, root.selectedIndex - root.gridColumns); + event.accepted = true; } else if (event.key === Qt.Key_Down) { - root.keyboardNavigationActive = true - root.selectedIndex = Math.min(applicationsModel.count - 1, root.selectedIndex + root.gridColumns) - event.accepted = true + root.keyboardNavigationActive = true; + root.selectedIndex = Math.min(applicationsModel.count - 1, root.selectedIndex + root.gridColumns); + event.accepted = true; } } else { if (event.key === Qt.Key_Up) { - root.keyboardNavigationActive = true - root.selectedIndex = Math.max(0, root.selectedIndex - 1) - event.accepted = true + root.keyboardNavigationActive = true; + root.selectedIndex = Math.max(0, root.selectedIndex - 1); + event.accepted = true; } else if (event.key === Qt.Key_Down) { - root.keyboardNavigationActive = true - root.selectedIndex = Math.min(applicationsModel.count - 1, root.selectedIndex + 1) - event.accepted = true + root.keyboardNavigationActive = true; + root.selectedIndex = Math.min(applicationsModel.count - 1, root.selectedIndex + 1); + event.accepted = true; } } if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) { if (root.selectedIndex >= 0 && root.selectedIndex < applicationsModel.count) { - const app = applicationsModel.get(root.selectedIndex) - launchApplication(app) + const app = applicationsModel.get(root.selectedIndex); + launchApplication(app); } - event.accepted = true + event.accepted = true; } } @@ -217,7 +218,7 @@ DankModal { iconColor: root.viewMode === "list" ? Theme.primary : Theme.surfaceText backgroundColor: root.viewMode === "list" ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" onClicked: { - root.viewMode = "list" + root.viewMode = "list"; } } @@ -229,7 +230,7 @@ DankModal { iconColor: root.viewMode === "grid" ? Theme.primary : Theme.surfaceText backgroundColor: root.viewMode === "grid" ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent" onClicked: { - root.viewMode = "grid" + root.viewMode = "grid"; } } } @@ -257,42 +258,42 @@ DankModal { keyForwardTargets: [appContent] onTextEdited: { - root.searchQuery = text + root.searchQuery = text; } Keys.onPressed: function (event) { if (event.key === Qt.Key_Escape) { - root.close() - event.accepted = true - return + root.close(); + event.accepted = true; + return; } - const isEnterKey = [Qt.Key_Return, Qt.Key_Enter].includes(event.key) - const hasText = text.length > 0 + const isEnterKey = [Qt.Key_Return, Qt.Key_Enter].includes(event.key); + const hasText = text.length > 0; if (isEnterKey && hasText) { if (root.keyboardNavigationActive && applicationsModel.count > 0) { - const app = applicationsModel.get(root.selectedIndex) - launchApplication(app) + const app = applicationsModel.get(root.selectedIndex); + launchApplication(app); } else if (applicationsModel.count > 0) { - const app = applicationsModel.get(0) - launchApplication(app) + const app = applicationsModel.get(0); + launchApplication(app); } - event.accepted = true - return + event.accepted = true; + return; } - const navigationKeys = [Qt.Key_Down, Qt.Key_Up, Qt.Key_Left, Qt.Key_Right, Qt.Key_Tab, Qt.Key_Backtab] - const isNavigationKey = navigationKeys.includes(event.key) - const isEmptyEnter = isEnterKey && !hasText + const navigationKeys = [Qt.Key_Down, Qt.Key_Up, Qt.Key_Left, Qt.Key_Right, Qt.Key_Tab, Qt.Key_Backtab]; + const isNavigationKey = navigationKeys.includes(event.key); + const isEmptyEnter = isEnterKey && !hasText; - event.accepted = !(isNavigationKey || isEmptyEnter) + event.accepted = !(isNavigationKey || isEmptyEnter); } Connections { function onShouldBeVisibleChanged() { if (!root.shouldBeVisible) { - searchField.focus = false + searchField.focus = false; } } @@ -303,12 +304,12 @@ DankModal { Rectangle { width: parent.width height: { - let usedHeight = 40 + Theme.spacingS - usedHeight += 52 + Theme.spacingS + let usedHeight = 40 + Theme.spacingS; + usedHeight += 52 + Theme.spacingS; if (root.showTargetData) { - usedHeight += 36 + Theme.spacingS + usedHeight += 36 + Theme.spacingS; } - return parent.height - usedHeight + return parent.height - usedHeight; } radius: Theme.cornerRadius color: "transparent" @@ -320,14 +321,14 @@ DankModal { property int itemSpacing: Theme.spacingS function ensureVisible(index) { - if (index < 0 || index >= count) return - - const itemY = index * (itemHeight + itemSpacing) - const itemBottom = itemY + itemHeight + if (index < 0 || index >= count) + return; + const itemY = index * (itemHeight + itemSpacing); + const itemBottom = itemY + itemHeight; if (itemY < contentY) { - contentY = itemY + contentY = itemY; } else if (itemBottom > contentY + height) { - contentY = itemBottom - height + contentY = itemBottom - height; } } @@ -343,9 +344,9 @@ DankModal { spacing: itemSpacing onCurrentIndexChanged: { - root.selectedIndex = currentIndex + root.selectedIndex = currentIndex; if (root.keyboardNavigationActive) { - ensureVisible(currentIndex) + ensureVisible(currentIndex); } } @@ -360,11 +361,11 @@ DankModal { hoverUpdatesSelection: true onItemClicked: (idx, modelData) => { - launchApplication(modelData) + launchApplication(modelData); } onKeyboardNavigationReset: { - root.keyboardNavigationActive = false + root.keyboardNavigationActive = false; } } } @@ -373,14 +374,14 @@ DankModal { id: appGrid function ensureVisible(index) { - if (index < 0 || index >= count) return - - const itemY = Math.floor(index / root.gridColumns) * cellHeight - const itemBottom = itemY + cellHeight + if (index < 0 || index >= count) + return; + const itemY = Math.floor(index / root.gridColumns) * cellHeight; + const itemBottom = itemY + cellHeight; if (itemY < contentY) { - contentY = itemY + contentY = itemY; } else if (itemBottom > contentY + height) { - contentY = itemBottom - height + contentY = itemBottom - height; } } @@ -397,9 +398,9 @@ DankModal { currentIndex: root.selectedIndex onCurrentIndexChanged: { - root.selectedIndex = currentIndex + root.selectedIndex = currentIndex; if (root.keyboardNavigationActive) { - ensureVisible(currentIndex) + ensureVisible(currentIndex); } } @@ -413,11 +414,11 @@ DankModal { hoverUpdatesSelection: true onItemClicked: (idx, modelData) => { - launchApplication(modelData) + launchApplication(modelData); } onKeyboardNavigationReset: { - root.keyboardNavigationActive = false + root.keyboardNavigationActive = false; } } } @@ -449,22 +450,22 @@ DankModal { } function launchApplication(app) { - if (!app) return - - root.applicationSelected(app, root.targetData) + if (!app) + return; + root.applicationSelected(app, root.targetData); if (usageHistoryKey && app.appId) { - const usageHistory = SettingsData[usageHistoryKey] || {} - const currentCount = usageHistory[app.appId] ? usageHistory[app.appId].count : 0 + const usageHistory = SettingsData[usageHistoryKey] || {}; + const currentCount = usageHistory[app.appId] ? usageHistory[app.appId].count : 0; usageHistory[app.appId] = { count: currentCount + 1, lastUsed: Date.now(), name: app.name - } - SettingsData.set(usageHistoryKey, usageHistory) + }; + SettingsData.set(usageHistoryKey, usageHistory); } - root.close() + root.close(); } } } diff --git a/quickshell/Modals/BluetoothPairingModal.qml b/quickshell/Modals/BluetoothPairingModal.qml index cd3c9b7e..21b0b411 100644 --- a/quickshell/Modals/BluetoothPairingModal.qml +++ b/quickshell/Modals/BluetoothPairingModal.qml @@ -7,6 +7,7 @@ import qs.Widgets DankModal { id: root + readonly property var log: Log.scoped("BluetoothPairingModal") layerNamespace: "dms:bluetooth-pairing" @@ -24,7 +25,7 @@ DankModal { property string passkeyInput: "" function show(pairingData) { - console.log("BluetoothPairingModal.show() called:", JSON.stringify(pairingData)); + log.debug("BluetoothPairingModal.show() called:", JSON.stringify(pairingData)); token = pairingData.token || ""; deviceName = pairingData.deviceName || ""; deviceAddress = pairingData.deviceAddr || ""; @@ -33,7 +34,7 @@ DankModal { pinInput = ""; passkeyInput = ""; - console.log("BluetoothPairingModal: Calling open()"); + log.debug("Calling open()"); open(); Qt.callLater(() => { if (contentLoader.item) { diff --git a/quickshell/Modals/BrowserPickerModal.qml b/quickshell/Modals/BrowserPickerModal.qml index e4afcb84..eee3bd42 100644 --- a/quickshell/Modals/BrowserPickerModal.qml +++ b/quickshell/Modals/BrowserPickerModal.qml @@ -2,9 +2,11 @@ import QtQuick import Quickshell import qs.Common import qs.Modals +import qs.Services AppPickerModal { id: root + readonly property var log: Log.scoped("BrowserPickerModal") property string url: "" @@ -17,35 +19,44 @@ AppPickerModal { showTargetData: true function shellEscape(str) { - return "'" + str.replace(/'/g, "'\\''") + "'" + return "'" + str.replace(/'/g, "'\\''") + "'"; } onApplicationSelected: (app, url) => { - if (!app) return + if (!app) + return; + let cmd = app.exec || ""; + const escapedUrl = shellEscape(url); - let cmd = app.exec || "" - const escapedUrl = shellEscape(url) - - let hasField = false - if (cmd.includes("%u")) { cmd = cmd.replace("%u", escapedUrl); hasField = true } - else if (cmd.includes("%U")) { cmd = cmd.replace("%U", escapedUrl); hasField = true } - else if (cmd.includes("%f")) { cmd = cmd.replace("%f", escapedUrl); hasField = true } - else if (cmd.includes("%F")) { cmd = cmd.replace("%F", escapedUrl); hasField = true } - - cmd = cmd.replace(/%[ikc]/g, "") - - if (!hasField) { - cmd += " " + escapedUrl + let hasField = false; + if (cmd.includes("%u")) { + cmd = cmd.replace("%u", escapedUrl); + hasField = true; + } else if (cmd.includes("%U")) { + cmd = cmd.replace("%U", escapedUrl); + hasField = true; + } else if (cmd.includes("%f")) { + cmd = cmd.replace("%f", escapedUrl); + hasField = true; + } else if (cmd.includes("%F")) { + cmd = cmd.replace("%F", escapedUrl); + hasField = true; } - console.log("BrowserPicker: Launching", cmd) + cmd = cmd.replace(/%[ikc]/g, ""); + + if (!hasField) { + cmd += " " + escapedUrl; + } + + log.debug("BrowserPicker: Launching", cmd); Quickshell.execDetached({ command: ["sh", "-c", cmd] - }) + }); } onViewModeChanged: { - SettingsData.set("browserPickerViewMode", viewMode) + SettingsData.set("browserPickerViewMode", viewMode); } } diff --git a/quickshell/Modals/Clipboard/ClipboardThumbnail.qml b/quickshell/Modals/Clipboard/ClipboardThumbnail.qml index 26a92109..10cf2ed3 100644 --- a/quickshell/Modals/Clipboard/ClipboardThumbnail.qml +++ b/quickshell/Modals/Clipboard/ClipboardThumbnail.qml @@ -6,6 +6,7 @@ import qs.Widgets Item { id: thumbnail + readonly property var log: Log.scoped("ClipboardThumbnail") required property var entry required property string entryType @@ -52,7 +53,7 @@ Item { modal.activeImageLoads--; } if (response.error) { - console.warn("ClipboardThumbnail: Failed to load image:", entry.id); + log.warn("Failed to load image:", entry.id); return; } const data = response.result?.data; diff --git a/quickshell/Modals/Common/DankModal.qml b/quickshell/Modals/Common/DankModal.qml index b0651c83..373243c7 100644 --- a/quickshell/Modals/Common/DankModal.qml +++ b/quickshell/Modals/Common/DankModal.qml @@ -7,6 +7,7 @@ import qs.Widgets Item { id: root + readonly property var log: Log.scoped("DankModal") property string layerNamespace: "dms:modal" property alias content: contentLoader.sourceComponent @@ -246,10 +247,10 @@ Item { return WlrLayershell.Overlay; switch (Quickshell.env("DMS_MODAL_LAYER")) { case "bottom": - console.error("DankModal: 'bottom' layer is not valid for modals. Defaulting to 'top' layer."); + log.error("'bottom' layer is not valid for modals. Defaulting to 'top' layer."); return WlrLayershell.Top; case "background": - console.error("DankModal: 'background' layer is not valid for modals. Defaulting to 'top' layer."); + log.error("'background' layer is not valid for modals. Defaulting to 'top' layer."); return WlrLayershell.Top; case "overlay": return WlrLayershell.Overlay; diff --git a/quickshell/Modals/DankColorPickerModal.qml b/quickshell/Modals/DankColorPickerModal.qml index 8a33878b..dacc8351 100644 --- a/quickshell/Modals/DankColorPickerModal.qml +++ b/quickshell/Modals/DankColorPickerModal.qml @@ -9,6 +9,7 @@ import qs.Widgets DankModal { id: root + readonly property var log: Log.scoped("DankColorPickerModal") layerNamespace: "dms:color-picker" @@ -50,17 +51,17 @@ DankModal { function toggle() { if (shouldBeVisible) { - hide(); + hide(); } else { - show(); + show(); } } function toggleInstant() { if (shouldBeVisible) { - hideInstant(); + hideInstant(); } else { - show(); + show(); } } @@ -111,7 +112,7 @@ DankModal { hideInstant(); Proc.runCommand("dms-color-pick", ["dms", "color", "pick", "--json"], (output, exitCode) => { if (exitCode !== 0) { - console.warn("dms color pick exited with code:", exitCode); + log.warn("dms color pick exited with code:", exitCode); root.show(); return; } @@ -120,11 +121,11 @@ DankModal { if (result.hex) { applyPickedColor(result.hex); } else { - console.warn("Failed to parse dms color pick output: missing hex"); + log.warn("Failed to parse dms color pick output: missing hex"); root.show(); } } catch (e) { - console.warn("Failed to parse dms color pick JSON:", e); + log.warn("Failed to parse dms color pick JSON:", e); root.show(); } }, 0, Proc.noTimeout); @@ -142,39 +143,39 @@ DankModal { onBackgroundClicked: hide() IpcHandler { - function open(): string { - root.show(); - return "COLOR_PICKER_MODAL_OPEN_SUCCESS"; - } + function open(): string { + root.show(); + return "COLOR_PICKER_MODAL_OPEN_SUCCESS"; + } - function openColor(color: string): string { - root.selectedColor = Qt.color(color); - root.currentColor = Qt.color(color); - root.updateFromColor(Qt.color(color)); - return open(); - } + function openColor(color: string): string { + root.selectedColor = Qt.color(color); + root.currentColor = Qt.color(color); + root.updateFromColor(Qt.color(color)); + return open(); + } - function close(): string { - root.hide(); - return "COLOR_PICKER_MODAL_CLOSE_SUCCESS"; - } + function close(): string { + root.hide(); + return "COLOR_PICKER_MODAL_CLOSE_SUCCESS"; + } - function closeInstant(): string { - root.hideInstant(); - return "COLOR_PICKER_MODAL_CLOSE_INSTANT_SUCCESS"; - } + function closeInstant(): string { + root.hideInstant(); + return "COLOR_PICKER_MODAL_CLOSE_INSTANT_SUCCESS"; + } - function toggle(): string { - root.toggle(); - return "COLOR_PICKER_MODAL_TOGGLE_SUCCESS"; - } + function toggle(): string { + root.toggle(); + return "COLOR_PICKER_MODAL_TOGGLE_SUCCESS"; + } - function toggleInstant(): string { - root.toggleInstant(); - return "COLOR_PICKER_MODAL_TOGGLE_INSTANT_SUCCESS"; - } + function toggleInstant(): string { + root.toggleInstant(); + return "COLOR_PICKER_MODAL_TOGGLE_INSTANT_SUCCESS"; + } - target: "color-picker" + target: "color-picker" } content: Component { diff --git a/quickshell/Modals/DankLauncherV2/DankLauncherV2Modal.qml b/quickshell/Modals/DankLauncherV2/DankLauncherV2Modal.qml index 3bb032c1..c3855a7c 100644 --- a/quickshell/Modals/DankLauncherV2/DankLauncherV2Modal.qml +++ b/quickshell/Modals/DankLauncherV2/DankLauncherV2Modal.qml @@ -8,6 +8,7 @@ import qs.Widgets Item { id: root + readonly property var log: Log.scoped("DankLauncherV2Modal") visible: false @@ -323,10 +324,10 @@ Item { WlrLayershell.layer: { switch (Quickshell.env("DMS_MODAL_LAYER")) { case "bottom": - console.error("DankModal: 'bottom' layer is not valid for modals. Defaulting to 'top' layer."); + log.error("DankModal: 'bottom' layer is not valid for modals. Defaulting to 'top' layer."); return WlrLayershell.Top; case "background": - console.error("DankModal: 'background' layer is not valid for modals. Defaulting to 'top' layer."); + log.error("DankModal: 'background' layer is not valid for modals. Defaulting to 'top' layer."); return WlrLayershell.Top; case "overlay": return WlrLayershell.Overlay; diff --git a/quickshell/Modals/Greeter/GreeterDoctorPage.qml b/quickshell/Modals/Greeter/GreeterDoctorPage.qml index 288cd581..5d9b904e 100644 --- a/quickshell/Modals/Greeter/GreeterDoctorPage.qml +++ b/quickshell/Modals/Greeter/GreeterDoctorPage.qml @@ -1,10 +1,12 @@ import QtQuick import Quickshell.Io import qs.Common +import qs.Services import qs.Widgets Item { id: root + readonly property var log: Log.scoped("GreeterDoctorPage") property bool isRunning: false property bool hasRun: false @@ -228,9 +230,7 @@ Item { text: { if (root.errorCount === 0) return I18n.tr("All checks passed", "greeter doctor page success"); - return root.errorCount === 1 - ? I18n.tr("%1 issue found", "greeter doctor page error count").arg(root.errorCount) - : I18n.tr("%1 issues found", "greeter doctor page error count").arg(root.errorCount); + return root.errorCount === 1 ? I18n.tr("%1 issue found", "greeter doctor page error count").arg(root.errorCount) : I18n.tr("%1 issues found", "greeter doctor page error count").arg(root.errorCount); } font.pixelSize: Theme.fontSizeMedium color: root.errorCount > 0 ? Theme.error : Theme.surfaceVariantText @@ -412,7 +412,7 @@ Item { else root.selectedFilter = "ok"; } catch (e) { - console.error("GreeterDoctorPage: Failed to parse doctor output:", e); + log.error("Failed to parse doctor output:", e); } } } diff --git a/quickshell/Modals/Greeter/GreeterModal.qml b/quickshell/Modals/Greeter/GreeterModal.qml index 973dab2b..49581fab 100644 --- a/quickshell/Modals/Greeter/GreeterModal.qml +++ b/quickshell/Modals/Greeter/GreeterModal.qml @@ -7,6 +7,7 @@ import qs.Widgets FloatingWindow { id: root + readonly property var log: Log.scoped("GreeterModal") property bool disablePopupTransparency: true property int currentPage: 0 @@ -105,7 +106,7 @@ FloatingWindow { root.cheatsheetData = JSON.parse(trimmed); root.cheatsheetLoaded = true; } catch (e) { - console.warn("Greeter: Failed to parse cheatsheet:", e); + log.warn("Greeter: Failed to parse cheatsheet:", e); } } } diff --git a/quickshell/Modals/ProcessListModal.qml b/quickshell/Modals/ProcessListModal.qml index 8cfc7057..dc872033 100644 --- a/quickshell/Modals/ProcessListModal.qml +++ b/quickshell/Modals/ProcessListModal.qml @@ -9,6 +9,7 @@ import qs.Widgets FloatingWindow { id: processListModal + readonly property var log: Log.scoped("ProcessListModal") property bool disablePopupTransparency: true property int currentTab: 0 @@ -22,7 +23,7 @@ FloatingWindow { function show() { if (!DgopService.dgopAvailable) { - console.warn("ProcessListModal: dgop is not available"); + log.warn("dgop is not available"); return; } visible = true; @@ -36,7 +37,7 @@ FloatingWindow { function toggle() { if (!DgopService.dgopAvailable) { - console.warn("ProcessListModal: dgop is not available"); + log.warn("dgop is not available"); return; } visible = !visible; @@ -44,7 +45,7 @@ FloatingWindow { function focusOrToggle() { if (!DgopService.dgopAvailable) { - console.warn("ProcessListModal: dgop is not available"); + log.warn("dgop is not available"); return; } if (visible) { diff --git a/quickshell/Modals/WorkspaceRenameModal.qml b/quickshell/Modals/WorkspaceRenameModal.qml index 6519ac37..2158f794 100644 --- a/quickshell/Modals/WorkspaceRenameModal.qml +++ b/quickshell/Modals/WorkspaceRenameModal.qml @@ -7,6 +7,7 @@ import qs.Widgets FloatingWindow { id: root + readonly property var log: Log.scoped("WorkspaceRenameModal") property bool disablePopupTransparency: true readonly property int inputFieldHeight: Theme.fontSizeMedium + Theme.spacingL * 2 @@ -39,7 +40,7 @@ FloatingWindow { } else if (CompositorService.isHyprland) { HyprlandService.renameWorkspace(name); } else { - console.warn("WorkspaceRenameModal: rename not supported for this compositor"); + log.warn("rename not supported for this compositor"); } } diff --git a/quickshell/Modules/ControlCenter/Components/DragDropGrid.qml b/quickshell/Modules/ControlCenter/Components/DragDropGrid.qml index 047f6010..65ebf041 100644 --- a/quickshell/Modules/ControlCenter/Components/DragDropGrid.qml +++ b/quickshell/Modules/ControlCenter/Components/DragDropGrid.qml @@ -7,6 +7,7 @@ import "../utils/layout.js" as LayoutUtils Column { id: root + readonly property var log: Log.scoped("DragDropGrid") property bool editMode: false property string expandedSection: "" @@ -988,7 +989,7 @@ Column { return true; } } catch (e) { - console.warn("DragDropGrid: stale plugin component for", pluginId, "- reloading"); + log.warn("stale plugin component for", pluginId, "- reloading"); PluginService.reloadPlugin(pluginId); } return false; diff --git a/quickshell/Modules/ControlCenter/Models/WidgetModel.qml b/quickshell/Modules/ControlCenter/Models/WidgetModel.qml index ac616aec..b71df737 100644 --- a/quickshell/Modules/ControlCenter/Models/WidgetModel.qml +++ b/quickshell/Modules/ControlCenter/Models/WidgetModel.qml @@ -6,6 +6,7 @@ import "../utils/widgets.js" as WidgetUtils QtObject { id: root + readonly property var log: Log.scoped("WidgetModel") property var vpnBuiltinInstance: null property var cupsBuiltinInstance: null @@ -26,7 +27,7 @@ QtObject { const widgets = SettingsData.controlCenterWidgets || []; const hasVpnWidget = widgets.some(w => w.id === "builtin_vpn"); if (!hasVpnWidget && vpnLoader.active) { - console.log("VpnWidget: No VPN widget in control center, deactivating loader"); + log.debug("VpnWidget: No VPN widget in control center, deactivating loader"); vpnLoader.active = false; } } @@ -55,7 +56,7 @@ QtObject { const widgets = SettingsData.controlCenterWidgets || []; const hasCupsWidget = widgets.some(w => w.id === "builtin_cups"); if (!hasCupsWidget && cupsLoader.active) { - console.log("CupsWidget: No CUPS widget in control center, deactivating loader"); + log.debug("CupsWidget: No CUPS widget in control center, deactivating loader"); cupsLoader.active = false; } } diff --git a/quickshell/Modules/ControlCenter/Widgets/ColorPickerPill.qml b/quickshell/Modules/ControlCenter/Widgets/ColorPickerPill.qml index a95410bb..77d98190 100644 --- a/quickshell/Modules/ControlCenter/Widgets/ColorPickerPill.qml +++ b/quickshell/Modules/ControlCenter/Widgets/ColorPickerPill.qml @@ -1,9 +1,11 @@ import QtQuick import qs.Common import qs.Modules.ControlCenter.Widgets +import qs.Services CompoundPill { id: root + readonly property var log: Log.scoped("ColorPickerPill") property var colorPickerModal: null @@ -14,14 +16,14 @@ CompoundPill { secondaryText: I18n.tr("Choose a color") onToggled: { - console.log("ColorPickerPill toggled, modal:", colorPickerModal); + log.debug("ColorPickerPill toggled, modal:", colorPickerModal); if (colorPickerModal) { colorPickerModal.show(); } } onExpandClicked: { - console.log("ColorPickerPill expandClicked, modal:", colorPickerModal); + log.debug("ColorPickerPill expandClicked, modal:", colorPickerModal); if (colorPickerModal) { colorPickerModal.show(); } diff --git a/quickshell/Modules/DankBar/DankBarWindow.qml b/quickshell/Modules/DankBar/DankBarWindow.qml index d8b0216c..71e2c27a 100644 --- a/quickshell/Modules/DankBar/DankBarWindow.qml +++ b/quickshell/Modules/DankBar/DankBarWindow.qml @@ -7,6 +7,7 @@ import qs.Services PanelWindow { id: barWindow + readonly property var log: Log.scoped("DankBarWindow") required property var rootWindow required property var barConfig @@ -164,7 +165,7 @@ PanelWindow { barWindow.BackgroundEffect.blurRegion = region; barWindow.blurRegion = region; } catch (e) { - console.warn("BarBlur: Failed to create blur region:", e); + log.warn("BarBlur: Failed to create blur region:", e); } } @@ -534,11 +535,11 @@ PanelWindow { Connections { target: PluginService function onPluginLoaded(pluginId) { - console.info("DankBar: Plugin loaded:", pluginId); + log.info("DankBar: Plugin loaded:", pluginId); SettingsData.widgetDataChanged(); } function onPluginUnloaded(pluginId) { - console.info("DankBar: Plugin unloaded:", pluginId); + log.info("DankBar: Plugin unloaded:", pluginId); SettingsData.widgetDataChanged(); } } diff --git a/quickshell/Modules/DankBar/Widgets/AppsDock.qml b/quickshell/Modules/DankBar/Widgets/AppsDock.qml index 294102dd..a8df08ba 100644 --- a/quickshell/Modules/DankBar/Widgets/AppsDock.qml +++ b/quickshell/Modules/DankBar/Widgets/AppsDock.qml @@ -9,6 +9,7 @@ import qs.Widgets BasePill { id: root + readonly property var log: Log.scoped("AppsDock") enableBackgroundHover: false enableCursor: false @@ -550,9 +551,9 @@ BasePill { showBadge: root.showOverflowBadge z: 10 onClicked: { - console.log("Overflow button clicked! Current state:", root.overflowExpanded); + log.debug("Overflow button clicked! Current state:", root.overflowExpanded); root.overflowExpanded = !root.overflowExpanded; - console.log("New state:", root.overflowExpanded); + log.debug("New state:", root.overflowExpanded); } } diff --git a/quickshell/Modules/DankBar/Widgets/Battery.qml b/quickshell/Modules/DankBar/Widgets/Battery.qml index 51d4b546..9f3fa468 100644 --- a/quickshell/Modules/DankBar/Widgets/Battery.qml +++ b/quickshell/Modules/DankBar/Widgets/Battery.qml @@ -7,6 +7,7 @@ import qs.Widgets BasePill { id: battery + readonly property var log: Log.scoped("Battery") property bool batteryPopupVisible: false property var popoutTarget: null @@ -130,13 +131,13 @@ BasePill { // Check if this is a touchpad if (delta !== 120 && delta !== -120) { touchpadAccumulator += delta; - console.info("Acc: "+touchpadAccumulator); + log.info("Acc: " + touchpadAccumulator); if (Math.abs(touchpadAccumulator) < 500) return; delta = touchpadAccumulator; touchpadAccumulator = 0; } - console.info("Trigger! Delta: "+delta) + log.info("Trigger! Delta: " + delta); // This is after the other delta checks so it only shows on valid Y scroll if (typeof PowerProfiles === "undefined") { @@ -149,11 +150,14 @@ BasePill { var index = profiles.findIndex(profile => PowerProfiles.profile === profile); // Step once based on mouse wheel direction - if (delta > 0) index += 1; - else index -= 1; + if (delta > 0) + index += 1; + else + index -= 1; // Already at end of list, can't go further - if (index < 0 || index >= profiles.length) return; + if (index < 0 || index >= profiles.length) + return; // Set new profile PowerProfiles.profile = profiles[index]; diff --git a/quickshell/Modules/DankDash/Overview/CalendarOverviewCard.qml b/quickshell/Modules/DankDash/Overview/CalendarOverviewCard.qml index d7fc1fa8..5d2407c1 100644 --- a/quickshell/Modules/DankDash/Overview/CalendarOverviewCard.qml +++ b/quickshell/Modules/DankDash/Overview/CalendarOverviewCard.qml @@ -6,6 +6,7 @@ import qs.Widgets Rectangle { id: root + readonly property var log: Log.scoped("CalendarOverviewCard") implicitWidth: SettingsData.showWeekNumber ? 736 : 700 @@ -521,7 +522,7 @@ Rectangle { onClicked: { if (modelData.url && modelData.url !== "") { if (Qt.openUrlExternally(modelData.url) === false) { - console.warn("Failed to open URL: " + modelData.url); + log.warn("Failed to open URL: " + modelData.url); } else { root.closeDash(); } diff --git a/quickshell/Modules/DankDash/WeatherTab.qml b/quickshell/Modules/DankDash/WeatherTab.qml index 69408b6f..c699fcf8 100644 --- a/quickshell/Modules/DankDash/WeatherTab.qml +++ b/quickshell/Modules/DankDash/WeatherTab.qml @@ -7,6 +7,7 @@ import qs.Widgets Item { id: root + readonly property var log: Log.scoped("WeatherTab") LayoutMirroring.enabled: I18n.isRtl LayoutMirroring.childrenInherit: true @@ -45,7 +46,7 @@ Item { hourlyList.currentIndex = Math.max(0, Math.min((WeatherService.weather.hourlyForecast?.length ?? 1) - 1, WeatherService.calendarHourDifference((new Date()), date) + (new Date()).getHours())); } } catch (e) { - console.warn("Weather Date Sync Error:", e); + log.warn("Weather Date Sync Error:", e); } syncing = false; diff --git a/quickshell/Modules/Greetd/GreetdMemory.qml b/quickshell/Modules/Greetd/GreetdMemory.qml index da949d30..b78e04d3 100644 --- a/quickshell/Modules/Greetd/GreetdMemory.qml +++ b/quickshell/Modules/Greetd/GreetdMemory.qml @@ -5,9 +5,11 @@ import QtQuick import Quickshell import Quickshell.Io import "GreetdEnv.js" as GreetdEnv +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("GreetdMemory") readonly property string greetCfgDir: Quickshell.env("DMS_GREET_CFG_DIR") || "/var/cache/dms-greeter" readonly property string sessionConfigPath: greetCfgDir + "/session.json" @@ -42,7 +44,7 @@ Singleton { nightModeEnabled = config.nightModeEnabled !== undefined ? config.nightModeEnabled : false; } } catch (e) { - console.warn("Failed to parse greeter session config:", e); + log.warn("Failed to parse greeter session config:", e); } } @@ -56,7 +58,7 @@ Singleton { if (!rememberLastSession || !rememberLastUser) saveMemory(); } catch (e) { - console.warn("Failed to parse greetd memory:", e); + log.warn("Failed to parse greetd memory:", e); } } @@ -122,7 +124,7 @@ Singleton { parseSessionConfig(sessionConfigFileView.text()); } onLoadFailed: error => { - console.warn("Could not load greeter session config from", root.sessionConfigPath, "error:", error); + log.warn("Could not load greeter session config from", root.sessionConfigPath, "error:", error); } } } diff --git a/quickshell/Modules/Greetd/GreetdSettings.qml b/quickshell/Modules/Greetd/GreetdSettings.qml index e1f670ca..ea240cf2 100644 --- a/quickshell/Modules/Greetd/GreetdSettings.qml +++ b/quickshell/Modules/Greetd/GreetdSettings.qml @@ -5,10 +5,12 @@ import QtQuick import Quickshell import Quickshell.Io import qs.Common +import qs.Services import "GreetdEnv.js" as GreetdEnv Singleton { id: root + readonly property var log: Log.scoped("GreetdSettings") readonly property string configPath: { const greetCfgDir = Quickshell.env("DMS_GREET_CFG_DIR") || "/var/cache/dms-greeter"; @@ -81,8 +83,7 @@ Singleton { currentThemeName = settings.currentThemeName !== undefined ? settings.currentThemeName : "purple"; customThemeFile = settings.customThemeFile !== undefined ? settings.customThemeFile : ""; - registryThemeVariants = settings.registryThemeVariants !== undefined ? - settings.registryThemeVariants : ({}); + registryThemeVariants = settings.registryThemeVariants !== undefined ? settings.registryThemeVariants : ({}); matugenScheme = settings.matugenScheme !== undefined ? settings.matugenScheme : "scheme-tonal-spot"; use24HourClock = settings.use24HourClock !== undefined ? settings.use24HourClock : true; showSeconds = settings.showSeconds !== undefined ? settings.showSeconds : false; @@ -142,7 +143,7 @@ Singleton { Theme.applyGreeterTheme(currentThemeName); } } catch (e) { - console.warn("Failed to parse greetd settings:", e); + log.warn("Failed to parse greetd settings:", e); } finally { settingsLoaded = true; } @@ -192,7 +193,7 @@ Singleton { parseSettings(settingsFile.text()); } onLoadFailed: error => { - console.warn("Failed to load greetd settings:", error); + log.warn("Failed to load greetd settings:", error); root.parseSettings(""); } } diff --git a/quickshell/Modules/Lock/KeyboardController.qml b/quickshell/Modules/Lock/KeyboardController.qml index 09d77a54..d2d07c6a 100644 --- a/quickshell/Modules/Lock/KeyboardController.qml +++ b/quickshell/Modules/Lock/KeyboardController.qml @@ -1,9 +1,11 @@ pragma ComponentBehavior: Bound import QtQuick +import qs.Services Item { id: keyboard_controller + readonly property var log: Log.scoped("KeyboardController") // reference on the TextInput property Item target @@ -14,21 +16,20 @@ Item { function show() { if (!isKeyboardActive && keyboard === null) { - keyboard = keyboardComponent.createObject( - keyboard_controller.rootObject) - keyboard.target = keyboard_controller.target - keyboard.dismissed.connect(hide) - isKeyboardActive = true + keyboard = keyboardComponent.createObject(keyboard_controller.rootObject); + keyboard.target = keyboard_controller.target; + keyboard.dismissed.connect(hide); + isKeyboardActive = true; } else - console.log("The keyboard is already shown") + log.debug("The keyboard is already shown"); } function hide() { if (isKeyboardActive && keyboard !== null) { - keyboard.destroy() - isKeyboardActive = false + keyboard.destroy(); + isKeyboardActive = false; } else - console.log("The keyboard is already hidden") + log.debug("The keyboard is already hidden"); } // private diff --git a/quickshell/Modules/Lock/LockScreenContent.qml b/quickshell/Modules/Lock/LockScreenContent.qml index 761f5f11..1a5bb5d7 100644 --- a/quickshell/Modules/Lock/LockScreenContent.qml +++ b/quickshell/Modules/Lock/LockScreenContent.qml @@ -14,6 +14,7 @@ import qs.Widgets Item { id: root + readonly property var log: Log.scoped("LockScreenContent") function encodeFileUrl(path) { if (!path) @@ -95,9 +96,9 @@ Item { if (SessionService.loginctlAvailable && DMSService.apiVersion >= 2) { DMSService.sendRequest("loginctl.lockerReady", null, resp => { if (resp?.error) - console.warn("lockerReady failed:", resp.error); + log.warn("lockerReady failed:", resp.error); else - console.log("lockerReady sent (afterAnimating/afterRendering)"); + log.debug("lockerReady sent (afterAnimating/afterRendering)"); }); } } @@ -803,7 +804,7 @@ Item { } if (pam.passwd.active) { - console.log("PAM is active, ignoring input"); + log.debug("PAM is active, ignoring input"); event.accepted = true; return; } @@ -1622,7 +1623,7 @@ Item { buttonSize: 40 onClicked: { if (demoMode) { - console.log("Demo: Power Menu"); + log.debug("Demo: Power Menu"); } else { powerMenu.show(); } diff --git a/quickshell/Modules/Lock/LockScreenDemo.qml b/quickshell/Modules/Lock/LockScreenDemo.qml index e13eac9e..502eef1d 100644 --- a/quickshell/Modules/Lock/LockScreenDemo.qml +++ b/quickshell/Modules/Lock/LockScreenDemo.qml @@ -3,9 +3,11 @@ pragma ComponentBehavior: Bound import QtQuick import Quickshell import Quickshell.Wayland +import qs.Services PanelWindow { id: root + readonly property var log: Log.scoped("LockScreenDemo") property bool demoActive: false @@ -25,12 +27,12 @@ PanelWindow { color: "transparent" function showDemo(): void { - console.log("Showing lock screen demo"); + log.debug("Showing lock screen demo"); demoActive = true; } function hideDemo(): void { - console.log("Hiding lock screen demo"); + log.debug("Hiding lock screen demo"); demoActive = false; } diff --git a/quickshell/Modules/Lock/VideoScreensaver.qml b/quickshell/Modules/Lock/VideoScreensaver.qml index 129f507b..a04fe545 100644 --- a/quickshell/Modules/Lock/VideoScreensaver.qml +++ b/quickshell/Modules/Lock/VideoScreensaver.qml @@ -7,6 +7,7 @@ import qs.Services Item { id: root + readonly property var log: Log.scoped("VideoScreensaver") required property string screenName property bool active: false @@ -53,7 +54,7 @@ Item { onExited: exitCode => { if (exitCode !== 0 || !videoPicker.result) { - console.warn("VideoScreensaver: no video found in folder"); + log.warn("no video found in folder"); ToastService.showError(I18n.tr("Video Screensaver"), I18n.tr("No video found in folder")); root.dismiss(); } @@ -98,14 +99,14 @@ Item { `, background, "VideoScreensaver.VideoPlayer"); videoPlayer.errorOccurred.connect((error, errorString) => { - console.warn("VideoScreensaver: playback error:", errorString); + log.warn("playback error:", errorString); ToastService.showError(I18n.tr("Video Screensaver"), I18n.tr("Playback error: ") + errorString); root.dismiss(); }); return true; } catch (e) { - console.warn("VideoScreensaver: Failed to create video player:", e); + log.warn("Failed to create video player:", e); return false; } } diff --git a/quickshell/Modules/Plugins/PluginSettings.qml b/quickshell/Modules/Plugins/PluginSettings.qml index 2ba5d05f..2b096fc0 100644 --- a/quickshell/Modules/Plugins/PluginSettings.qml +++ b/quickshell/Modules/Plugins/PluginSettings.qml @@ -1,10 +1,12 @@ import QtQuick import Quickshell import qs.Common +import qs.Services import qs.Widgets Item { id: root + readonly property var log: Log.scoped("PluginSettings") required property string pluginId property var pluginService: null @@ -131,7 +133,7 @@ Item { return; } if (!hasPermission) { - console.warn("PluginSettings: Plugin", pluginId, "does not have settings_write permission"); + log.warn("Plugin", pluginId, "does not have settings_write permission"); return; } if (pluginService.savePluginData) { diff --git a/quickshell/Modules/Settings/DisplayConfig/DisplayConfigState.qml b/quickshell/Modules/Settings/DisplayConfig/DisplayConfigState.qml index b6e253ba..b1c600fc 100644 --- a/quickshell/Modules/Settings/DisplayConfig/DisplayConfigState.qml +++ b/quickshell/Modules/Settings/DisplayConfig/DisplayConfigState.qml @@ -9,6 +9,7 @@ import qs.Services Singleton { id: root + readonly property var log: Log.scoped("DisplayConfigState") readonly property bool hasOutputBackend: WlrOutputService.wlrOutputAvailable readonly property var wlrOutputs: WlrOutputService.outputs @@ -106,7 +107,7 @@ Singleton { function findMatchingProfile() { const profiles = validatedProfiles; - console.log("[Profile Match] Current outputs:", JSON.stringify(currentOutputSet)); + log.debug("[Profile Match] Current outputs:", JSON.stringify(currentOutputSet)); let bestMatch = ""; let bestScore = -1; @@ -116,25 +117,25 @@ Singleton { const profile = profiles[profileId]; const profileSet = new Set(profile.outputSet); - console.log("[Profile Match] Checking", profile.name, "outputSet:", JSON.stringify(profile.outputSet)); + log.debug("[Profile Match] Checking", profile.name, "outputSet:", JSON.stringify(profile.outputSet)); let allCurrentPresent = true; for (const output of currentOutputSet) { if (!profileSet.has(output)) { - console.log("[Profile Match] - Missing output:", output); + log.debug("[Profile Match] - Missing output:", output); allCurrentPresent = false; break; } } if (!allCurrentPresent) { - console.log("[Profile Match] - SKIP: not all current outputs present"); + log.debug("[Profile Match] - SKIP: not all current outputs present"); continue; } const disconnectedCount = profile.outputSet.length - currentOutputSet.length; const score = currentOutputSet.length * 100 - disconnectedCount; const updatedAt = profile.updatedAt || profile.createdAt || 0; - console.log("[Profile Match] - MATCH score:", score, "(disconnected:", disconnectedCount, "updatedAt:", updatedAt + ")"); + log.debug("[Profile Match] - MATCH score:", score, "(disconnected:", disconnectedCount, "updatedAt:", updatedAt + ")"); if (score > bestScore || (score === bestScore && updatedAt > bestUpdatedAt)) { bestScore = score; @@ -142,7 +143,7 @@ Singleton { bestUpdatedAt = updatedAt; } } - console.log("[Profile Match] Best match:", bestMatch, "score:", bestScore); + log.debug("[Profile Match] Best match:", bestMatch, "score:", bestScore); return bestMatch; } diff --git a/quickshell/Modules/Settings/WidgetsTabSection.qml b/quickshell/Modules/Settings/WidgetsTabSection.qml index 5363f371..e02245e4 100644 --- a/quickshell/Modules/Settings/WidgetsTabSection.qml +++ b/quickshell/Modules/Settings/WidgetsTabSection.qml @@ -6,6 +6,7 @@ import qs.Services Column { id: root + readonly property var log: Log.scoped("WidgetsTabSection") property var items: [] property var allWidgets: [] @@ -1726,11 +1727,11 @@ Column { closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside onOpened: { - console.log("Privacy context menu opened"); + log.debug("Privacy context menu opened"); } onClosed: { - console.log("Privacy Center context menu closed"); + log.debug("Privacy Center context menu closed"); } background: Rectangle { diff --git a/quickshell/Modules/WallpaperBackground.qml b/quickshell/Modules/WallpaperBackground.qml index 8430b01f..15763ed4 100644 --- a/quickshell/Modules/WallpaperBackground.qml +++ b/quickshell/Modules/WallpaperBackground.qml @@ -7,6 +7,7 @@ import qs.Widgets import qs.Services Variants { + readonly property var log: Log.scoped("WallpaperBackground") model: { if (SessionData.isGreeterMode) { return Quickshell.screens; @@ -103,7 +104,7 @@ Variants { function _recheckScreenScale() { const newScale = CompositorService.getScreenScale(modelData); if (newScale !== root.screenScale) { - console.info("WallpaperBackground: screen scale corrected for", modelData.name + ":", root.screenScale, "->", newScale); + log.info("screen scale corrected for", modelData.name + ":", root.screenScale, "->", newScale); root.screenScale = newScale; } } diff --git a/quickshell/Modules/WorkspaceOverlays/OverviewWidget.qml b/quickshell/Modules/WorkspaceOverlays/OverviewWidget.qml index 03d39fb7..08afcd90 100644 --- a/quickshell/Modules/WorkspaceOverlays/OverviewWidget.qml +++ b/quickshell/Modules/WorkspaceOverlays/OverviewWidget.qml @@ -8,6 +8,7 @@ import qs.Widgets Item { id: root + readonly property var log: Log.scoped("OverviewWidget") required property var panelWindow required property bool overviewOpen readonly property HyprlandMonitor monitor: Hyprland.monitorFor(panelWindow.screen) @@ -276,7 +277,7 @@ Item { } return result; } catch (e) { - console.error("OverviewWidget filter error:", e); + log.error("OverviewWidget filter error:", e); return []; } } diff --git a/quickshell/Services/AppSearchService.qml b/quickshell/Services/AppSearchService.qml index 1c8413f9..b6f840ff 100644 --- a/quickshell/Services/AppSearchService.qml +++ b/quickshell/Services/AppSearchService.qml @@ -4,9 +4,11 @@ pragma ComponentBehavior: Bound import QtQuick import Quickshell import qs.Common +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("AppSearchService") property var applications: [] property var _cachedCategories: null @@ -811,7 +813,7 @@ Singleton { }); isPersistent = false; } catch (e) { - console.warn("AppSearchService: Error creating temporary plugin instance", pluginId, ":", e); + log.warn("Error creating temporary plugin instance", pluginId, ":", e); return []; } } @@ -831,7 +833,7 @@ Singleton { instance.destroy(); } } catch (e) { - console.warn("AppSearchService: Error getting items from plugin", pluginId, ":", e); + log.warn("Error getting items from plugin", pluginId, ":", e); if (!isPersistent) instance.destroy(); } @@ -857,7 +859,7 @@ Singleton { }); isPersistent = false; } catch (e) { - console.warn("AppSearchService: Error creating temporary plugin instance for execution", pluginId, ":", e); + log.warn("Error creating temporary plugin instance for execution", pluginId, ":", e); return false; } } @@ -877,7 +879,7 @@ Singleton { instance.destroy(); } } catch (e) { - console.warn("AppSearchService: Error executing item from plugin", pluginId, ":", e); + log.warn("Error executing item from plugin", pluginId, ":", e); if (!isPersistent) instance.destroy(); } @@ -949,7 +951,7 @@ Singleton { try { return instance.getCategories() || []; } catch (e) { - console.warn("AppSearchService: Error getting categories from plugin", pluginId, ":", e); + log.warn("Error getting categories from plugin", pluginId, ":", e); return []; } } @@ -968,7 +970,7 @@ Singleton { try { instance.setCategory(categoryId); } catch (e) { - console.warn("AppSearchService: Error setting category on plugin", pluginId, ":", e); + log.warn("Error setting category on plugin", pluginId, ":", e); } } diff --git a/quickshell/Services/AudioService.qml b/quickshell/Services/AudioService.qml index 31a17448..b86408a4 100644 --- a/quickshell/Services/AudioService.qml +++ b/quickshell/Services/AudioService.qml @@ -11,6 +11,7 @@ import qs.Services Singleton { id: root + readonly property var log: Log.scoped("AudioService") readonly property PwNode sink: Pipewire.defaultAudioSink readonly property PwNode source: Pipewire.defaultAudioSource @@ -143,7 +144,7 @@ Singleton { function setDeviceAlias(nodeName, customAlias) { if (!nodeName) { - console.error("AudioService: Cannot set alias - nodeName is empty"); + log.error("Cannot set alias - nodeName is empty"); return false; } @@ -189,8 +190,8 @@ EOFCONFIG Proc.runCommand("writeWireplumberConfig", ["sh", "-c", shellCmd], (output, exitCode) => { if (exitCode !== 0) { - console.error("AudioService: Failed to write WirePlumber config. Exit code:", exitCode); - console.error("AudioService: Error output:", output); + log.error("Failed to write WirePlumber config. Exit code:", exitCode); + log.error("Error output:", output); ToastService.showError(I18n.tr("Failed to save audio config"), output || ""); return; } @@ -305,7 +306,7 @@ EOFCONFIG ToastService.showInfo(I18n.tr("Audio system restarted"), I18n.tr("Device names updated")); wireplumberReloadCompleted(true); } else { - console.error("AudioService: Failed to restart WirePlumber:", output); + log.error("Failed to restart WirePlumber:", output); ToastService.showError(I18n.tr("Failed to restart audio system"), output); wireplumberReloadCompleted(false); } @@ -317,7 +318,7 @@ EOFCONFIG Proc.runCommand("readWireplumberConfig", ["cat", configPath], (output, exitCode) => { if (exitCode !== 0) { - console.log("AudioService: No existing WirePlumber config found"); + log.debug("No existing WirePlumber config found"); return; } @@ -340,7 +341,7 @@ EOFCONFIG if (Object.keys(aliases).length > 0) { deviceAliases = aliases; - console.log("AudioService: Loaded", Object.keys(aliases).length, "device aliases"); + log.debug("Loaded", Object.keys(aliases).length, "device aliases"); } }, 0); } @@ -394,13 +395,13 @@ EOFCONFIG Proc.runCommand("getCurrentSoundTheme", ["sh", "-c", "gsettings get org.gnome.desktop.sound theme-name 2>/dev/null | sed \"s/'//g\""], (output, exitCode) => { if (exitCode === 0 && output.trim()) { currentSoundTheme = output.trim(); - console.log("AudioService: Current system sound theme:", currentSoundTheme); + log.debug("Current system sound theme:", currentSoundTheme); if (SettingsData.useSystemSoundTheme) { discoverSoundFiles(currentSoundTheme); } } else { currentSoundTheme = ""; - console.log("AudioService: No system sound theme found"); + log.debug("No system sound theme found"); } }, 0); } @@ -510,22 +511,22 @@ EOFCONFIG const themeLower = currentSoundTheme.toLowerCase(); if (SettingsData.useSystemSoundTheme && specialConditions[themeLower]?.includes(soundEvent)) { const bundledPath = Qt.resolvedUrl(soundMap[soundEvent] || "../assets/sounds/freedesktop/message.wav"); - console.log("AudioService: Using bundled sound (special condition) for", soundEvent, ":", bundledPath); + log.debug("Using bundled sound (special condition) for", soundEvent, ":", bundledPath); return bundledPath; } if (SettingsData.useSystemSoundTheme && soundFilePaths[soundEvent]) { - console.log("AudioService: Using system sound for", soundEvent, ":", soundFilePaths[soundEvent]); + log.debug("Using system sound for", soundEvent, ":", soundFilePaths[soundEvent]); return soundFilePaths[soundEvent]; } const bundledPath = Qt.resolvedUrl(soundMap[soundEvent] || "../assets/sounds/freedesktop/message.wav"); - console.log("AudioService: Using bundled sound for", soundEvent, ":", bundledPath); + log.debug("Using bundled sound for", soundEvent, ":", bundledPath); return bundledPath; } function reloadSounds() { - console.log("AudioService: Reloading sounds, useSystemSoundTheme:", SettingsData.useSystemSoundTheme, "currentSoundTheme:", currentSoundTheme); + log.debug("Reloading sounds, useSystemSoundTheme:", SettingsData.useSystemSoundTheme, "currentSoundTheme:", currentSoundTheme); if (SettingsData.useSystemSoundTheme && currentSoundTheme) { discoverSoundFiles(currentSoundTheme); } else { @@ -549,7 +550,7 @@ EOFCONFIG MediaDevices { id: devices Component.onCompleted: { - console.log("AudioService: MediaDevices initialized, default output:", defaultAudioOutput?.description) + log.debug("MediaDevices initialized, default output:", defaultAudioOutput?.description) } } `, root, "AudioService.MediaDevices"); @@ -560,7 +561,7 @@ EOFCONFIG Connections { target: root.mediaDevices function onDefaultAudioOutputChanged() { - console.log("AudioService: Default audio output changed, recreating sound players") + log.debug("Default audio output changed, recreating sound players") root.destroySoundPlayers() root.createSoundPlayers() } @@ -568,7 +569,7 @@ EOFCONFIG `, root, "AudioService.MediaDevicesConnections"); } } catch (e) { - console.log("AudioService: MediaDevices not available, using default audio output"); + log.debug("MediaDevices not available, using default audio output"); mediaDevices = null; } } @@ -682,7 +683,7 @@ EOFCONFIG } `, root, "AudioService.LoginSound"); } catch (e) { - console.warn("AudioService: Error creating sound players:", e); + log.warn("Error creating sound players:", e); } } diff --git a/quickshell/Services/BluetoothService.qml b/quickshell/Services/BluetoothService.qml index 4de300ea..a8caa8b1 100644 --- a/quickshell/Services/BluetoothService.qml +++ b/quickshell/Services/BluetoothService.qml @@ -1,5 +1,4 @@ pragma Singleton - pragma ComponentBehavior: Bound import QtQuick @@ -19,206 +18,217 @@ Singleton { readonly property bool enhancedPairingAvailable: DMSService.dmsAvailable && DMSService.apiVersion >= 9 && DMSService.capabilities.includes("bluetooth") readonly property bool connected: { if (!adapter || !adapter.devices) { - return false + return false; } - let isConnected = false - adapter.devices.values.forEach(dev => { if (dev.connected) isConnected = true }) - return isConnected + let isConnected = false; + adapter.devices.values.forEach(dev => { + if (dev.connected) + isConnected = true; + }); + return isConnected; } readonly property var pairedDevices: { if (!adapter || !adapter.devices) { - return [] + return []; } return adapter.devices.values.filter(dev => { - return dev && (dev.paired || dev.trusted) - }) + return dev && (dev.paired || dev.trusted); + }); } readonly property var allDevicesWithBattery: { if (!adapter || !adapter.devices) { - return [] + return []; } return adapter.devices.values.filter(dev => { - return dev && dev.batteryAvailable && dev.battery > 0 - }) + return dev && dev.batteryAvailable && dev.battery > 0; + }); } function sortDevices(devices) { return devices.sort((a, b) => { - const aName = a.name || a.deviceName || "" - const bName = b.name || b.deviceName || "" - const aAddr = a.address || "" - const bAddr = b.address || "" + const aName = a.name || a.deviceName || ""; + const bName = b.name || b.deviceName || ""; + const aAddr = a.address || ""; + const bAddr = b.address || ""; - const aHasRealName = aName.includes(" ") && aName.length > 3 - const bHasRealName = bName.includes(" ") && bName.length > 3 + const aHasRealName = aName.includes(" ") && aName.length > 3; + const bHasRealName = bName.includes(" ") && bName.length > 3; - if (aHasRealName && !bHasRealName) return -1 - if (!aHasRealName && bHasRealName) return 1 + if (aHasRealName && !bHasRealName) + return -1; + if (!aHasRealName && bHasRealName) + return 1; - if (aHasRealName && bHasRealName) { - return aName.localeCompare(bName) - } + if (aHasRealName && bHasRealName) { + return aName.localeCompare(bName); + } - return aAddr.localeCompare(bAddr) - }) + return aAddr.localeCompare(bAddr); + }); } function getDeviceIcon(device) { if (!device) { - return "bluetooth" + return "bluetooth"; } - const name = (device.name || device.deviceName || "").toLowerCase() - const icon = (device.icon || "").toLowerCase() + const name = (device.name || device.deviceName || "").toLowerCase(); + const icon = (device.icon || "").toLowerCase(); - const audioKeywords = ["headset", "audio", "headphone", "airpod", "arctis"] + const audioKeywords = ["headset", "audio", "headphone", "airpod", "arctis"]; if (audioKeywords.some(keyword => icon.includes(keyword) || name.includes(keyword))) { - return "headset" + return "headset"; } if (icon.includes("mouse") || name.includes("mouse")) { - return "mouse" + return "mouse"; } if (icon.includes("keyboard") || name.includes("keyboard")) { - return "keyboard" + return "keyboard"; } - const phoneKeywords = ["phone", "iphone", "android", "samsung"] + const phoneKeywords = ["phone", "iphone", "android", "samsung"]; if (phoneKeywords.some(keyword => icon.includes(keyword) || name.includes(keyword))) { - return "smartphone" + return "smartphone"; } if (icon.includes("watch") || name.includes("watch")) { - return "watch" + return "watch"; } if (icon.includes("speaker") || name.includes("speaker")) { - return "speaker" + return "speaker"; } if (icon.includes("display") || name.includes("tv")) { - return "tv" + return "tv"; } - return "bluetooth" + return "bluetooth"; } function canConnect(device) { if (!device) { - return false + return false; } - return !device.paired && !device.pairing && !device.blocked + return !device.paired && !device.pairing && !device.blocked; } function getSignalStrength(device) { if (!device || device.signalStrength === undefined || device.signalStrength <= 0) { - return "Unknown" + return "Unknown"; } - const signal = device.signalStrength + const signal = device.signalStrength; if (signal >= 80) { - return "Excellent" + return "Excellent"; } if (signal >= 60) { - return "Good" + return "Good"; } if (signal >= 40) { - return "Fair" + return "Fair"; } if (signal >= 20) { - return "Poor" + return "Poor"; } - return "Very Poor" + return "Very Poor"; } function getSignalIcon(device) { if (!device || device.signalStrength === undefined || device.signalStrength <= 0) { - return "signal_cellular_null" + return "signal_cellular_null"; } - const signal = device.signalStrength + const signal = device.signalStrength; if (signal >= 80) { - return "signal_cellular_4_bar" + return "signal_cellular_4_bar"; } if (signal >= 60) { - return "signal_cellular_3_bar" + return "signal_cellular_3_bar"; } if (signal >= 40) { - return "signal_cellular_2_bar" + return "signal_cellular_2_bar"; } if (signal >= 20) { - return "signal_cellular_1_bar" + return "signal_cellular_1_bar"; } - return "signal_cellular_0_bar" + return "signal_cellular_0_bar"; } function isDeviceBusy(device) { if (!device) { - return false + return false; } - return device.pairing || device.state === BluetoothDeviceState.Disconnecting || device.state === BluetoothDeviceState.Connecting + return device.pairing || device.state === BluetoothDeviceState.Disconnecting || device.state === BluetoothDeviceState.Connecting; } function connectDeviceWithTrust(device) { if (!device) { - return + return; } - device.trusted = true - device.connect() + device.trusted = true; + device.connect(); } function pairDevice(device, callback) { if (!device) { - if (callback) callback({error: "Invalid device"}) - return + if (callback) + callback({ + error: "Invalid device" + }); + return; } // The DMS backend actually implements a bluez agent, so we can pair anything if (enhancedPairingAvailable) { - const devicePath = getDevicePath(device) - DMSService.bluetoothPair(devicePath, callback) - return + const devicePath = getDevicePath(device); + DMSService.bluetoothPair(devicePath, callback); + return; } // Quickshell does not implement a bluez agent, so we can try to pair but only with devices that don't require a passcode - device.trusted = true - device.connect() - if (callback) callback({success: true}) + device.trusted = true; + device.connect(); + if (callback) + callback({ + success: true + }); } function getCardName(device) { if (!device) { - return "" + return ""; } - return `bluez_card.${device.address.replace(/:/g, "_")}` + return `bluez_card.${device.address.replace(/:/g, "_")}`; } function getDevicePath(device) { if (!device || !device.address) { - return "" + return ""; } - const adapterPath = adapter ? "/org/bluez/hci0" : "/org/bluez/hci0" - return `${adapterPath}/dev_${device.address.replace(/:/g, "_")}` + const adapterPath = adapter ? "/org/bluez/hci0" : "/org/bluez/hci0"; + return `${adapterPath}/dev_${device.address.replace(/:/g, "_")}`; } function isAudioDevice(device) { if (!device) { - return false + return false; } - const icon = getDeviceIcon(device) - return icon === "headset" || icon === "speaker" + const icon = getDeviceIcon(device); + return icon === "headset" || icon === "speaker"; } function getCodecInfo(codecName) { - const codec = codecName.replace(/-/g, "_").toUpperCase() + const codec = codecName.replace(/-/g, "_").toUpperCase(); const codecMap = { "LDAC": { @@ -261,77 +271,77 @@ Singleton { "description": "Basic speech codec • Legacy compatibility", "qualityColor": "#9E9E9E" } - } + }; return codecMap[codec] || { "name": codecName, "description": "Unknown codec", "qualityColor": "#9E9E9E" - } + }; } property var deviceCodecs: ({}) function updateDeviceCodec(deviceAddress, codec) { - deviceCodecs[deviceAddress] = codec - deviceCodecsChanged() + deviceCodecs[deviceAddress] = codec; + deviceCodecsChanged(); } function refreshDeviceCodec(device) { if (!device || !device.connected || !isAudioDevice(device)) { - return + return; } - const cardName = getCardName(device) - codecQueryProcess.cardName = cardName - codecQueryProcess.deviceAddress = device.address - codecQueryProcess.availableCodecs = [] - codecQueryProcess.parsingTargetCard = false - codecQueryProcess.detectedCodec = "" - codecQueryProcess.running = true + const cardName = getCardName(device); + codecQueryProcess.cardName = cardName; + codecQueryProcess.deviceAddress = device.address; + codecQueryProcess.availableCodecs = []; + codecQueryProcess.parsingTargetCard = false; + codecQueryProcess.detectedCodec = ""; + codecQueryProcess.running = true; } function getCurrentCodec(device, callback) { if (!device || !device.connected || !isAudioDevice(device)) { - callback("") - return + callback(""); + return; } - const cardName = getCardName(device) - codecQueryProcess.cardName = cardName - codecQueryProcess.callback = callback - codecQueryProcess.availableCodecs = [] - codecQueryProcess.parsingTargetCard = false - codecQueryProcess.detectedCodec = "" - codecQueryProcess.running = true + const cardName = getCardName(device); + codecQueryProcess.cardName = cardName; + codecQueryProcess.callback = callback; + codecQueryProcess.availableCodecs = []; + codecQueryProcess.parsingTargetCard = false; + codecQueryProcess.detectedCodec = ""; + codecQueryProcess.running = true; } function getAvailableCodecs(device, callback) { if (!device || !device.connected || !isAudioDevice(device)) { - callback([], "") - return + callback([], ""); + return; } - const cardName = getCardName(device) - codecFullQueryProcess.cardName = cardName - codecFullQueryProcess.callback = callback - codecFullQueryProcess.availableCodecs = [] - codecFullQueryProcess.parsingTargetCard = false - codecFullQueryProcess.detectedCodec = "" - codecFullQueryProcess.running = true + const cardName = getCardName(device); + codecFullQueryProcess.cardName = cardName; + codecFullQueryProcess.callback = callback; + codecFullQueryProcess.availableCodecs = []; + codecFullQueryProcess.parsingTargetCard = false; + codecFullQueryProcess.detectedCodec = ""; + codecFullQueryProcess.running = true; } function switchCodec(device, profileName, callback) { if (!device || !isAudioDevice(device)) { - callback(false, "Invalid device") - return + callback(false, "Invalid device"); + return; } - const cardName = getCardName(device) - codecSwitchProcess.cardName = cardName - codecSwitchProcess.profile = profileName - codecSwitchProcess.callback = callback - codecSwitchProcess.running = true + const cardName = getCardName(device); + codecSwitchProcess.cardName = cardName; + codecSwitchProcess.profile = profileName; + codecSwitchProcess.callback = callback; + codecSwitchProcess.running = true; } Process { @@ -349,67 +359,67 @@ Singleton { onExited: (exitCode, exitStatus) => { if (exitCode === 0 && detectedCodec) { if (deviceAddress) { - root.updateDeviceCodec(deviceAddress, detectedCodec) + root.updateDeviceCodec(deviceAddress, detectedCodec); } if (callback) { - callback(detectedCodec) + callback(detectedCodec); } } else if (callback) { - callback("") + callback(""); } - parsingTargetCard = false - detectedCodec = "" - availableCodecs = [] - deviceAddress = "" - callback = null + parsingTargetCard = false; + detectedCodec = ""; + availableCodecs = []; + deviceAddress = ""; + callback = null; } stdout: SplitParser { splitMarker: "\n" onRead: data => { - let line = data.trim() + let line = data.trim(); if (line.includes(`Name: ${codecQueryProcess.cardName}`)) { - codecQueryProcess.parsingTargetCard = true - return + codecQueryProcess.parsingTargetCard = true; + return; } if (codecQueryProcess.parsingTargetCard && line.startsWith("Name: ") && !line.includes(codecQueryProcess.cardName)) { - codecQueryProcess.parsingTargetCard = false - return + codecQueryProcess.parsingTargetCard = false; + return; } if (codecQueryProcess.parsingTargetCard) { if (line.startsWith("Active Profile:")) { - let profile = line.split(": ")[1] || "" + let profile = line.split(": ")[1] || ""; let activeCodec = codecQueryProcess.availableCodecs.find(c => { - return c.profile === profile - }) + return c.profile === profile; + }); if (activeCodec) { - codecQueryProcess.detectedCodec = activeCodec.name + codecQueryProcess.detectedCodec = activeCodec.name; } - return + return; } if (line.includes("codec") && line.includes("available: yes")) { - let parts = line.split(": ") + let parts = line.split(": "); if (parts.length >= 2) { - let profile = parts[0].trim() - let description = parts[1] - let codecMatch = description.match(/codec ([^\)\s]+)/i) - let codecName = codecMatch ? codecMatch[1].toUpperCase() : "UNKNOWN" - let codecInfo = root.getCodecInfo(codecName) + let profile = parts[0].trim(); + let description = parts[1]; + let codecMatch = description.match(/codec ([^\)\s]+)/i); + let codecName = codecMatch ? codecMatch[1].toUpperCase() : "UNKNOWN"; + let codecInfo = root.getCodecInfo(codecName); if (codecInfo && !codecQueryProcess.availableCodecs.some(c => { - return c.profile === profile - })) { - let newCodecs = codecQueryProcess.availableCodecs.slice() + return c.profile === profile; + })) { + let newCodecs = codecQueryProcess.availableCodecs.slice(); newCodecs.push({ - "name": codecInfo.name, - "profile": profile, - "description": codecInfo.description, - "qualityColor": codecInfo.qualityColor - }) - codecQueryProcess.availableCodecs = newCodecs + "name": codecInfo.name, + "profile": profile, + "description": codecInfo.description, + "qualityColor": codecInfo.qualityColor + }); + codecQueryProcess.availableCodecs = newCodecs; } } } @@ -431,59 +441,59 @@ Singleton { onExited: function (exitCode, exitStatus) { if (callback) { - callback(exitCode === 0 ? availableCodecs : [], exitCode === 0 ? detectedCodec : "") + callback(exitCode === 0 ? availableCodecs : [], exitCode === 0 ? detectedCodec : ""); } - parsingTargetCard = false - detectedCodec = "" - availableCodecs = [] - callback = null + parsingTargetCard = false; + detectedCodec = ""; + availableCodecs = []; + callback = null; } stdout: SplitParser { splitMarker: "\n" onRead: data => { - let line = data.trim() + let line = data.trim(); if (line.includes(`Name: ${codecFullQueryProcess.cardName}`)) { - codecFullQueryProcess.parsingTargetCard = true - return + codecFullQueryProcess.parsingTargetCard = true; + return; } if (codecFullQueryProcess.parsingTargetCard && line.startsWith("Name: ") && !line.includes(codecFullQueryProcess.cardName)) { - codecFullQueryProcess.parsingTargetCard = false - return + codecFullQueryProcess.parsingTargetCard = false; + return; } if (codecFullQueryProcess.parsingTargetCard) { if (line.startsWith("Active Profile:")) { - let profile = line.split(": ")[1] || "" + let profile = line.split(": ")[1] || ""; let activeCodec = codecFullQueryProcess.availableCodecs.find(c => { - return c.profile === profile - }) + return c.profile === profile; + }); if (activeCodec) { - codecFullQueryProcess.detectedCodec = activeCodec.name + codecFullQueryProcess.detectedCodec = activeCodec.name; } - return + return; } if (line.includes("codec") && line.includes("available: yes")) { - let parts = line.split(": ") + let parts = line.split(": "); if (parts.length >= 2) { - let profile = parts[0].trim() - let description = parts[1] - let codecMatch = description.match(/codec ([^\)\s]+)/i) - let codecName = codecMatch ? codecMatch[1].toUpperCase() : "UNKNOWN" - let codecInfo = root.getCodecInfo(codecName) + let profile = parts[0].trim(); + let description = parts[1]; + let codecMatch = description.match(/codec ([^\)\s]+)/i); + let codecName = codecMatch ? codecMatch[1].toUpperCase() : "UNKNOWN"; + let codecInfo = root.getCodecInfo(codecName); if (codecInfo && !codecFullQueryProcess.availableCodecs.some(c => { - return c.profile === profile - })) { - let newCodecs = codecFullQueryProcess.availableCodecs.slice() + return c.profile === profile; + })) { + let newCodecs = codecFullQueryProcess.availableCodecs.slice(); newCodecs.push({ - "name": codecInfo.name, - "profile": profile, - "description": codecInfo.description, - "qualityColor": codecInfo.qualityColor - }) - codecFullQueryProcess.availableCodecs = newCodecs + "name": codecInfo.name, + "profile": profile, + "description": codecInfo.description, + "qualityColor": codecInfo.qualityColor + }); + codecFullQueryProcess.availableCodecs = newCodecs; } } } @@ -503,21 +513,21 @@ Singleton { onExited: function (exitCode, exitStatus) { if (callback) { - callback(exitCode === 0, exitCode === 0 ? "Codec switched successfully" : "Failed to switch codec") + callback(exitCode === 0, exitCode === 0 ? "Codec switched successfully" : "Failed to switch codec"); } // If successful, refresh the codec for this device if (exitCode === 0) { if (root.adapter && root.adapter.devices) { root.adapter.devices.values.forEach(device => { - if (device && root.getCardName(device) === cardName) { - Qt.callLater(() => root.refreshDeviceCodec(device)) - } - }) + if (device && root.getCardName(device) === cardName) { + Qt.callLater(() => root.refreshDeviceCodec(device)); + } + }); } } - callback = null + callback = null; } } } diff --git a/quickshell/Services/BlurService.qml b/quickshell/Services/BlurService.qml index 0ccb5df6..1b511bb6 100644 --- a/quickshell/Services/BlurService.qml +++ b/quickshell/Services/BlurService.qml @@ -6,9 +6,11 @@ import Quickshell import Quickshell.Io import Quickshell.Wayland // ! Import is needed despite what qmlls says import qs.Common +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("BlurService") property bool quickshellSupported: false property bool compositorSupported: false @@ -52,7 +54,7 @@ Singleton { targetWindow.BackgroundEffect.blurRegion = region; return region; } catch (e) { - console.warn("BlurService: Failed to create blur region:", e); + log.warn("Failed to create blur region:", e); return null; } } @@ -84,15 +86,15 @@ Singleton { onStreamFinished: { root.compositorSupported = text.trim() === "supported"; if (root.compositorSupported) - console.info("BlurService: Compositor supports ext-background-effect-v1"); + log.info("Compositor supports ext-background-effect-v1"); else - console.info("BlurService: Compositor does not support ext-background-effect-v1"); + log.info("Compositor does not support ext-background-effect-v1"); } } onExited: exitCode => { if (exitCode !== 0) - console.warn("BlurService: blur probe failed with code:", exitCode); + log.warn("blur probe failed with code:", exitCode); } } @@ -104,10 +106,10 @@ Singleton { `, root, "BlurAvailabilityTest"); test.destroy(); quickshellSupported = true; - console.info("BlurService: Quickshell blur support available"); + log.info("Quickshell blur support available"); blurProbe.running = true; } catch (e) { - console.info("BlurService: BackgroundEffect not available - blur disabled. Requires a newer version of Quickshell."); + log.info("BackgroundEffect not available - blur disabled. Requires a newer version of Quickshell."); } } } diff --git a/quickshell/Services/CalendarService.qml b/quickshell/Services/CalendarService.qml index 1146f7b7..280eccbb 100644 --- a/quickshell/Services/CalendarService.qml +++ b/quickshell/Services/CalendarService.qml @@ -19,68 +19,69 @@ Singleton { function checkKhalAvailability() { if (!khalCheckProcess.running) - khalCheckProcess.running = true + khalCheckProcess.running = true; } function detectKhalDateFormat() { if (!khalFormatProcess.running) - khalFormatProcess.running = true + khalFormatProcess.running = true; } function parseKhalDateFormat(formatExample) { - let qtFormat = formatExample.replace("12", "MM").replace("21", "dd").replace("2013", "yyyy") - return { format: qtFormat, parser: null } + let qtFormat = formatExample.replace("12", "MM").replace("21", "dd").replace("2013", "yyyy"); + return { + format: qtFormat, + parser: null + }; } - function loadCurrentMonth() { if (!root.khalAvailable) - return - - let today = new Date() - let firstDay = new Date(today.getFullYear(), today.getMonth(), 1) - let lastDay = new Date(today.getFullYear(), today.getMonth() + 1, 0) + return; + let today = new Date(); + let firstDay = new Date(today.getFullYear(), today.getMonth(), 1); + let lastDay = new Date(today.getFullYear(), today.getMonth() + 1, 0); // Add padding - let startDate = new Date(firstDay) - startDate.setDate(startDate.getDate() - firstDay.getDay() - 7) - let endDate = new Date(lastDay) - endDate.setDate(endDate.getDate() + (6 - lastDay.getDay()) + 7) - loadEvents(startDate, endDate) + let startDate = new Date(firstDay); + startDate.setDate(startDate.getDate() - firstDay.getDay() - 7); + let endDate = new Date(lastDay); + endDate.setDate(endDate.getDate() + (6 - lastDay.getDay()) + 7); + loadEvents(startDate, endDate); } function loadEvents(startDate, endDate) { if (!root.khalAvailable) { - return + return; } if (eventsProcess.running) { - return + return; } // Store last requested date range for refresh timer - root.lastStartDate = startDate - root.lastEndDate = endDate - root.isLoading = true + root.lastStartDate = startDate; + root.lastEndDate = endDate; + root.isLoading = true; // Format dates for khal using detected format - let startDateStr = Qt.formatDate(startDate, root.khalDateFormat) - let endDateStr = Qt.formatDate(endDate, root.khalDateFormat) - eventsProcess.requestStartDate = startDate - eventsProcess.requestEndDate = endDate - eventsProcess.command = ["khal", "list", "--json", "title", "--json", "description", "--json", "start-date", "--json", "start-time", "--json", "end-date", "--json", "end-time", "--json", "all-day", "--json", "location", "--json", "url", startDateStr, endDateStr] - eventsProcess.running = true + let startDateStr = Qt.formatDate(startDate, root.khalDateFormat); + let endDateStr = Qt.formatDate(endDate, root.khalDateFormat); + eventsProcess.requestStartDate = startDate; + eventsProcess.requestEndDate = endDate; + eventsProcess.command = ["khal", "list", "--json", "title", "--json", "description", "--json", "start-date", "--json", "start-time", "--json", "end-date", "--json", "end-time", "--json", "all-day", "--json", "location", "--json", "url", startDateStr, endDateStr]; + eventsProcess.running = true; } function getEventsForDate(date) { - let dateKey = Qt.formatDate(date, "yyyy-MM-dd") - return root.eventsByDate[dateKey] || [] + let dateKey = Qt.formatDate(date, "yyyy-MM-dd"); + return root.eventsByDate[dateKey] || []; } function hasEventsForDate(date) { - let events = getEventsForDate(date) - return events.length > 0 + let events = getEventsForDate(date); + return events.length > 0; } // Initialize on component completion Component.onCompleted: { - detectKhalDateFormat() + detectKhalDateFormat(); } // Process for detecting khal date format @@ -91,22 +92,22 @@ Singleton { running: false onExited: exitCode => { if (exitCode !== 0) { - checkKhalAvailability() + checkKhalAvailability(); } } stdout: StdioCollector { onStreamFinished: { - let lines = text.split('\n') + let lines = text.split('\n'); for (let line of lines) { if (line.startsWith('dateformat:')) { - let formatExample = line.substring(line.indexOf(':') + 1).trim() - let formatInfo = parseKhalDateFormat(formatExample) - root.khalDateFormat = formatInfo.format - break + let formatExample = line.substring(line.indexOf(':') + 1).trim(); + let formatInfo = parseKhalDateFormat(formatExample); + root.khalDateFormat = formatInfo.format; + break; } } - checkKhalAvailability() + checkKhalAvailability(); } } } @@ -118,9 +119,9 @@ Singleton { command: ["khal", "list", "today"] running: false onExited: exitCode => { - root.khalAvailable = (exitCode === 0) + root.khalAvailable = (exitCode === 0); if (exitCode === 0) { - loadCurrentMonth() + loadCurrentMonth(); } } } @@ -135,100 +136,96 @@ Singleton { running: false onExited: exitCode => { - root.isLoading = false + root.isLoading = false; if (exitCode !== 0) { - root.lastError = "Failed to load events (exit code: " + exitCode + ")" - return + root.lastError = "Failed to load events (exit code: " + exitCode + ")"; + return; } try { - let newEventsByDate = {} - let lines = eventsProcess.rawOutput.split('\n') + let newEventsByDate = {}; + let lines = eventsProcess.rawOutput.split('\n'); for (let line of lines) { - line = line.trim() + line = line.trim(); if (!line || line === "[]") - continue + continue; // Parse JSON line - let dayEvents = JSON.parse(line) + let dayEvents = JSON.parse(line); // Process each event in this day's array for (let event of dayEvents) { if (!event.title) - continue + continue; // Parse start and end dates using detected format - let startDate, endDate + let startDate, endDate; if (event['start-date']) { - startDate = Date.fromLocaleString(I18n.locale(), event['start-date'], root.khalDateFormat) + startDate = Date.fromLocaleString(I18n.locale(), event['start-date'], root.khalDateFormat); } else { - startDate = new Date() + startDate = new Date(); } if (event['end-date']) { - endDate = Date.fromLocaleString(I18n.locale(), event['end-date'], root.khalDateFormat) + endDate = Date.fromLocaleString(I18n.locale(), event['end-date'], root.khalDateFormat); } else { - endDate = new Date(startDate) + endDate = new Date(startDate); } // Create start/end times - let startTime = new Date(startDate) - let endTime = new Date(endDate) - if (event['start-time'] - && event['all-day'] !== "True") { + let startTime = new Date(startDate); + let endTime = new Date(endDate); + if (event['start-time'] && event['all-day'] !== "True") { // Parse time if available and not all-day - let timeStr = event['start-time'] + let timeStr = event['start-time']; if (timeStr) { // Match time with optional seconds and AM/PM - let timeParts = timeStr.match(/(\d+):(\d+)(?::\d+)?\s*(AM|PM)?/i) + let timeParts = timeStr.match(/(\d+):(\d+)(?::\d+)?\s*(AM|PM)?/i); if (timeParts) { - let hours = parseInt(timeParts[1]) - let minutes = parseInt(timeParts[2]) + let hours = parseInt(timeParts[1]); + let minutes = parseInt(timeParts[2]); // Handle AM/PM conversion if present if (timeParts[3]) { - let period = timeParts[3].toUpperCase() + let period = timeParts[3].toUpperCase(); if (period === 'PM' && hours !== 12) { - hours += 12 + hours += 12; } else if (period === 'AM' && hours === 12) { - hours = 0 + hours = 0; } } - startTime.setHours(hours, minutes) + startTime.setHours(hours, minutes); if (event['end-time']) { - let endTimeParts = event['end-time'].match( - /(\d+):(\d+)(?::\d+)?\s*(AM|PM)?/i) + let endTimeParts = event['end-time'].match(/(\d+):(\d+)(?::\d+)?\s*(AM|PM)?/i); if (endTimeParts) { - let endHours = parseInt(endTimeParts[1]) - let endMinutes = parseInt(endTimeParts[2]) + let endHours = parseInt(endTimeParts[1]); + let endMinutes = parseInt(endTimeParts[2]); // Handle AM/PM conversion if present if (endTimeParts[3]) { - let endPeriod = endTimeParts[3].toUpperCase() + let endPeriod = endTimeParts[3].toUpperCase(); if (endPeriod === 'PM' && endHours !== 12) { - endHours += 12 + endHours += 12; } else if (endPeriod === 'AM' && endHours === 12) { - endHours = 0 + endHours = 0; } } - endTime.setHours(endHours, endMinutes) + endTime.setHours(endHours, endMinutes); } } else { // Default to 1 hour duration on same day - endTime = new Date(startTime) - endTime.setHours( - startTime.getHours() + 1) + endTime = new Date(startTime); + endTime.setHours(startTime.getHours() + 1); } } } } // Create unique ID for this event (to track multi-day events) - let eventId = event.title + "_" + event['start-date'] - + "_" + (event['start-time'] || 'allday') + let eventId = event.title + "_" + event['start-date'] + "_" + (event['start-time'] || 'allday'); // Create event object template - let extractedUrl = "" + let extractedUrl = ""; if (!event.url && event.description) { - let urlMatch = event.description.match(/https?:\/\/[^\s]+/) + let urlMatch = event.description.match(/https?:\/\/[^\s]+/); if (urlMatch) { - extractedUrl = urlMatch[0] + extractedUrl = urlMatch[0]; } } let eventTemplate = { @@ -242,75 +239,71 @@ Singleton { "calendar": "", "color": "", "allDay": event['all-day'] === "True", - "isMultiDay": startDate.toDateString( - ) !== endDate.toDateString() - } + "isMultiDay": startDate.toDateString() !== endDate.toDateString() + }; // Add event to each day it spans - let currentDate = new Date(startDate) + let currentDate = new Date(startDate); while (currentDate <= endDate) { - let dateKey = Qt.formatDate(currentDate, - "yyyy-MM-dd") + let dateKey = Qt.formatDate(currentDate, "yyyy-MM-dd"); if (!newEventsByDate[dateKey]) - newEventsByDate[dateKey] = [] + newEventsByDate[dateKey] = []; // Check if this exact event is already added to this date (prevent duplicates) - let existingEvent = newEventsByDate[dateKey].find( - e => { - return e.id === eventId - }) + let existingEvent = newEventsByDate[dateKey].find(e => { + return e.id === eventId; + }); if (existingEvent) { // Move to next day without adding duplicate - currentDate.setDate(currentDate.getDate() + 1) - continue + currentDate.setDate(currentDate.getDate() + 1); + continue; } // Create a copy of the event for this date - let dayEvent = Object.assign({}, eventTemplate) + let dayEvent = Object.assign({}, eventTemplate); // For multi-day events, adjust the display time for this specific day if (currentDate.getTime() === startDate.getTime()) { // First day - use original start time - dayEvent.start = new Date(startTime) + dayEvent.start = new Date(startTime); } else { // Subsequent days - start at beginning of day for all-day events - dayEvent.start = new Date(currentDate) + dayEvent.start = new Date(currentDate); if (!dayEvent.allDay) - dayEvent.start.setHours(0, 0, 0, 0) + dayEvent.start.setHours(0, 0, 0, 0); } if (currentDate.getTime() === endDate.getTime()) { // Last day - use original end time - dayEvent.end = new Date(endTime) + dayEvent.end = new Date(endTime); } else { // Earlier days - end at end of day for all-day events - dayEvent.end = new Date(currentDate) + dayEvent.end = new Date(currentDate); if (!dayEvent.allDay) - dayEvent.end.setHours(23, 59, 59, 999) + dayEvent.end.setHours(23, 59, 59, 999); } - newEventsByDate[dateKey].push(dayEvent) + newEventsByDate[dateKey].push(dayEvent); // Move to next day - currentDate.setDate(currentDate.getDate() + 1) + currentDate.setDate(currentDate.getDate() + 1); } } } // Sort events by start time within each date for (let dateKey in newEventsByDate) { newEventsByDate[dateKey].sort((a, b) => { - return a.start.getTime( - ) - b.start.getTime() - }) + return a.start.getTime() - b.start.getTime(); + }); } - root.eventsByDate = newEventsByDate - root.lastError = "" + root.eventsByDate = newEventsByDate; + root.lastError = ""; } catch (error) { - root.lastError = "Failed to parse events JSON: " + error.toString() - root.eventsByDate = {} + root.lastError = "Failed to parse events JSON: " + error.toString(); + root.eventsByDate = {}; } // Reset for next run - eventsProcess.rawOutput = "" + eventsProcess.rawOutput = ""; } stdout: SplitParser { splitMarker: "\n" onRead: data => { - eventsProcess.rawOutput += data + "\n" + eventsProcess.rawOutput += data + "\n"; } } } diff --git a/quickshell/Services/ChangelogService.qml b/quickshell/Services/ChangelogService.qml index 562a513a..f3cb9e35 100644 --- a/quickshell/Services/ChangelogService.qml +++ b/quickshell/Services/ChangelogService.qml @@ -6,9 +6,11 @@ import QtQuick import Quickshell import Quickshell.Io import qs.Common +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("ChangelogService") readonly property string currentVersion: "1.4" readonly property bool changelogEnabled: false @@ -101,7 +103,7 @@ Singleton { onExited: exitCode => { if (exitCode !== 0) { - console.warn("ChangelogService: Failed to create changelog marker"); + log.warn("Failed to create changelog marker"); } } } diff --git a/quickshell/Services/ClipboardService.qml b/quickshell/Services/ClipboardService.qml index 4c092551..e49a44c6 100644 --- a/quickshell/Services/ClipboardService.qml +++ b/quickshell/Services/ClipboardService.qml @@ -5,9 +5,11 @@ import QtQuick import Quickshell import Quickshell.Io import qs.Common +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("ClipboardService") readonly property int longTextThreshold: 200 @@ -78,7 +80,7 @@ Singleton { } DMSService.sendRequest("clipboard.getHistory", null, function (response) { if (response.error) { - console.warn("ClipboardService: Failed to get history:", response.error); + log.warn("Failed to get history:", response.error); return; } internalEntries = response.result || []; @@ -144,7 +146,7 @@ Singleton { "id": entry.id }, function (response) { if (response.error) { - console.warn("ClipboardService: Failed to delete entry:", response.error); + log.warn("Failed to delete entry:", response.error); return; } internalEntries = internalEntries.filter(e => e.id !== entry.id); @@ -169,7 +171,7 @@ Singleton { "id": entry.id }, function (response) { if (response.error) { - console.warn("ClipboardService: Failed to delete entry:", response.error); + log.warn("Failed to delete entry:", response.error); return; } internalEntries = internalEntries.filter(e => e.id !== entry.id); @@ -223,7 +225,7 @@ Singleton { const savedCount = pinnedCount; DMSService.sendRequest("clipboard.clearHistory", null, function (response) { if (response.error) { - console.warn("ClipboardService: Failed to clear history:", response.error); + log.warn("Failed to clear history:", response.error); return; } refresh(); diff --git a/quickshell/Services/CompositorService.qml b/quickshell/Services/CompositorService.qml index adcc4985..541148d0 100644 --- a/quickshell/Services/CompositorService.qml +++ b/quickshell/Services/CompositorService.qml @@ -7,9 +7,11 @@ import Quickshell.I3 import Quickshell.Wayland import Quickshell.Hyprland import qs.Common +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("CompositorService") property bool isHyprland: false property bool isNiri: false @@ -52,7 +54,7 @@ Singleton { randrScales = scales; } } catch (e) { - console.warn("CompositorService: failed to parse randr data:", e); + log.warn("failed to parse randr data:", e); } } randrReady = true; @@ -379,9 +381,7 @@ Singleton { const focusedWin = NiriService.windows.find(nw => nw.is_focused); if (!focusedWin) return []; - const screenWsIds = new Set( - NiriService.allWorkspaces.filter(ws => ws.output === screenName).map(ws => ws.id) - ); + const screenWsIds = new Set(NiriService.allWorkspaces.filter(ws => ws.output === screenName).map(ws => ws.id)); return screenWsIds.has(focusedWin.workspace_id) ? toplevels : []; } return NiriService.filterCurrentDisplay(toplevels, screenName); @@ -454,7 +454,7 @@ Singleton { } } } catch (e) { - console.warn("CompositorService: workspace snapshot failed:", e); + log.warn("workspace snapshot failed:", e); } if (currentWorkspaceId === null) @@ -498,7 +498,7 @@ Singleton { isMiracle = false; isLabwc = false; compositor = "hyprland"; - console.info("CompositorService: Detected Hyprland"); + log.info("Detected Hyprland"); return; } @@ -513,7 +513,7 @@ Singleton { isMiracle = false; isLabwc = false; compositor = "niri"; - console.info("CompositorService: Detected Niri with socket:", niriSocket); + log.info("Detected Niri with socket:", niriSocket); NiriService.generateNiriBlurrule(); } }, 0); @@ -531,7 +531,7 @@ Singleton { isMiracle = false; isLabwc = false; compositor = "sway"; - console.info("CompositorService: Detected Sway with socket:", swaySocket); + log.info("Detected Sway with socket:", swaySocket); } }, 0); return; @@ -548,7 +548,7 @@ Singleton { isMiracle = true; isLabwc = false; compositor = "miracle"; - console.info("CompositorService: Detected Miracle WM with socket:", miracleSocket); + log.info("Detected Miracle WM with socket:", miracleSocket); } }, 0); return; @@ -565,7 +565,7 @@ Singleton { isMiracle = false; isLabwc = false; compositor = "scroll"; - console.info("CompositorService: Detected Scroll with socket:", scrollSocket); + log.info("Detected Scroll with socket:", scrollSocket); } }, 0); return; @@ -580,7 +580,7 @@ Singleton { isMiracle = false; isLabwc = true; compositor = "labwc"; - console.info("CompositorService: Detected LabWC with PID:", labwcPid); + log.info("Detected LabWC with PID:", labwcPid); return; } @@ -595,7 +595,7 @@ Singleton { isMiracle = false; isLabwc = false; compositor = "unknown"; - console.warn("CompositorService: No compositor detected"); + log.warn("No compositor detected"); } } @@ -618,7 +618,7 @@ Singleton { isMiracle = false; isLabwc = false; compositor = "dwl"; - console.info("CompositorService: Detected DWL via DMS capability"); + log.info("Detected DWL via DMS capability"); } } @@ -638,7 +638,7 @@ Singleton { if (isLabwc) { Quickshell.execDetached(["dms", "dpms", "off"]); } - console.warn("CompositorService: Cannot power off monitors, unknown compositor"); + log.warn("Cannot power off monitors, unknown compositor"); } function powerOnMonitors() { @@ -657,12 +657,12 @@ Singleton { if (isLabwc) { Quickshell.execDetached(["dms", "dpms", "on"]); } - console.warn("CompositorService: Cannot power on monitors, unknown compositor"); + log.warn("Cannot power on monitors, unknown compositor"); } function _dwlPowerOffMonitors() { if (!Quickshell.screens || Quickshell.screens.length === 0) { - console.warn("CompositorService: No screens available for DWL power off"); + log.warn("No screens available for DWL power off"); return; } @@ -676,7 +676,7 @@ Singleton { function _dwlPowerOnMonitors() { if (!Quickshell.screens || Quickshell.screens.length === 0) { - console.warn("CompositorService: No screens available for DWL power on"); + log.warn("No screens available for DWL power on"); return; } diff --git a/quickshell/Services/CupsService.qml b/quickshell/Services/CupsService.qml index a88655d2..57d77441 100644 --- a/quickshell/Services/CupsService.qml +++ b/quickshell/Services/CupsService.qml @@ -4,9 +4,11 @@ pragma ComponentBehavior: Bound import QtQuick import Quickshell import qs.Common +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("CupsService") property int refCount: 0 @@ -205,7 +207,7 @@ Singleton { enabled: DMSService.isConnected function onCupsStateUpdate(data) { - console.log("CupsService: Subscription update received"); + log.debug("Subscription update received"); getState(); } diff --git a/quickshell/Services/DMSNetworkService.qml b/quickshell/Services/DMSNetworkService.qml index e234cf47..471480db 100644 --- a/quickshell/Services/DMSNetworkService.qml +++ b/quickshell/Services/DMSNetworkService.qml @@ -4,9 +4,11 @@ pragma ComponentBehavior: Bound import QtQuick import Quickshell import qs.Common +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("DMSNetworkService") property bool networkAvailable: false property string backend: "" @@ -141,7 +143,7 @@ Singleton { function onNetworkStateUpdate(data) { const networksCount = data.wifiNetworks?.length ?? "null"; - console.log("DMSNetworkService: Subscription update received, networks:", networksCount); + log.debug("Subscription update received, networks:", networksCount); updateState(data); } } @@ -301,7 +303,7 @@ Singleton { const timeout = 30000; if (busyDuration > timeout) { - console.warn("DMSNetworkService: VPN operation timed out after", timeout, "ms"); + log.warn("VPN operation timed out after", timeout, "ms"); vpnIsBusy = false; pendingVpnUuid = ""; vpnBusyStartTime = 0; @@ -331,7 +333,7 @@ Singleton { if (pendingConnectionSSID) { if (wifiConnected && currentWifiSSID === pendingConnectionSSID && wifiIP) { const elapsed = Date.now() - pendingConnectionStartTime; - console.info("DMSNetworkService: Successfully connected to", pendingConnectionSSID, "in", elapsed, "ms"); + log.info("Successfully connected to", pendingConnectionSSID, "in", elapsed, "ms"); ToastService.showInfo(`Connected to ${pendingConnectionSSID}`); if (userPreference === "wifi" || userPreference === "auto") { @@ -402,7 +404,7 @@ Singleton { DMSService.sendRequest("network.wifi.scan", params, response => { isScanning = false; if (response.error) { - console.warn("DMSNetworkService: WiFi scan failed:", response.error); + log.warn("WiFi scan failed:", response.error); } else { Qt.callLater(() => getState()); } @@ -485,10 +487,10 @@ Singleton { } function submitCredentials(token, secrets, save) { - console.log("submitCredentials: networkAvailable=" + networkAvailable + " apiVersion=" + DMSService.apiVersion); + log.debug("submitCredentials: networkAvailable=" + networkAvailable + " apiVersion=" + DMSService.apiVersion); if (!networkAvailable || DMSService.apiVersion < 7) { - console.warn("submitCredentials: Aborting - networkAvailable=" + networkAvailable + " apiVersion=" + DMSService.apiVersion); + log.warn("submitCredentials: Aborting - networkAvailable=" + networkAvailable + " apiVersion=" + DMSService.apiVersion); return; } @@ -502,7 +504,7 @@ Singleton { DMSService.sendRequest("network.credentials.submit", params, response => { if (response.error) { - console.warn("DMSNetworkService: Failed to submit credentials:", response.error); + log.warn("Failed to submit credentials:", response.error); } }); } @@ -520,7 +522,7 @@ Singleton { DMSService.sendRequest("network.credentials.cancel", params, response => { if (response.error) { - console.warn("DMSNetworkService: Failed to cancel credentials:", response.error); + log.warn("Failed to cancel credentials:", response.error); } }); } @@ -533,7 +535,7 @@ Singleton { ssid: ssid }, response => { if (response.error) { - console.warn("Failed to forget network:", response.error); + log.warn("Failed to forget network:", response.error); } else { ToastService.showInfo(I18n.tr("Forgot network %1").arg(ssid)); @@ -565,7 +567,7 @@ Singleton { wifiToggling = false; if (response.error) { - console.warn("Failed to toggle WiFi:", response.error); + log.warn("Failed to toggle WiFi:", response.error); } else if (response.result) { wifiEnabled = response.result.enabled; ToastService.showInfo(wifiEnabled ? I18n.tr("WiFi enabled") : I18n.tr("WiFi disabled")); @@ -600,7 +602,7 @@ Singleton { targetPreference = ""; if (response.error) { - console.warn("Failed to set network preference:", response.error); + log.warn("Failed to set network preference:", response.error); } }); } diff --git a/quickshell/Services/DMSService.qml b/quickshell/Services/DMSService.qml index 62236b2d..7c54a396 100644 --- a/quickshell/Services/DMSService.qml +++ b/quickshell/Services/DMSService.qml @@ -5,9 +5,11 @@ import QtQuick import Quickshell import Quickshell.Io import qs.Common +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("DMSService") property bool dmsAvailable: false property var capabilities: [] @@ -198,14 +200,14 @@ Singleton { try { response = JSON.parse(line); } catch (e) { - console.warn("DMSService: Failed to parse request response:", line.substring(0, 100)); + log.warn("Failed to parse request response:", line.substring(0, 100)); return; } const isClipboard = clipboardRequestIds[response.id]; if (isClipboard) delete clipboardRequestIds[response.id]; else - console.log("DMSService: Request socket <<", line); + log.debug("Request socket <<", line); handleResponse(response); } } @@ -232,11 +234,11 @@ Singleton { try { response = JSON.parse(line); } catch (e) { - console.warn("DMSService: Failed to parse subscription event:", line.substring(0, 100)); + log.warn("Failed to parse subscription event:", line.substring(0, 100)); return; } if (!line.includes("clipboard")) - console.log("DMSService: Subscribe socket <<", line); + log.debug("Subscribe socket <<", line); handleSubscriptionEvent(response); } } @@ -251,9 +253,9 @@ Singleton { request.params = { "services": activeSubscriptions }; - console.log("DMSService: Subscribing to services:", JSON.stringify(activeSubscriptions)); + log.debug("Subscribing to services:", JSON.stringify(activeSubscriptions)); } else { - console.log("DMSService: Subscribing to all services"); + log.debug("Subscribing to all services"); } subscribeSocket.send(request); @@ -291,7 +293,7 @@ Singleton { } else { const filtered = activeSubscriptions.filter(s => s !== service); if (filtered.length === 0) { - console.warn("DMSService: Cannot remove last subscription"); + log.warn("Cannot remove last subscription"); return; } subscribe(filtered); @@ -316,7 +318,7 @@ Singleton { if (response.error) { if (response.error.includes("unknown method") && response.error.includes("subscribe")) { if (!shownOutdatedError) { - console.error("DMSService: Server does not support subscribe method"); + log.error("Server does not support subscribe method"); ToastService.showError(I18n.tr("DMS out of date"), I18n.tr("To update, run the following command:"), updateCommand); shownOutdatedError = true; } @@ -336,7 +338,7 @@ Singleton { cliVersion = data.cliVersion || ""; capabilities = data.capabilities || []; - console.info("DMSService: Connected (API v" + apiVersion + ", CLI " + cliVersion + ") -", JSON.stringify(capabilities)); + log.info("Connected (API v" + apiVersion + ", CLI " + cliVersion + ") -", JSON.stringify(capabilities)); if (apiVersion < expectedApiVersion) { ToastService.showError("DMS server is outdated (API v" + apiVersion + ", expected v" + expectedApiVersion + ")"); @@ -401,7 +403,7 @@ Singleton { function sendRequest(method, params, callback) { if (!isConnected) { - console.warn("DMSService.sendRequest: Not connected, method:", method); + log.warn("DMSService.sendRequest: Not connected, method:", method); if (callback) { callback({ "error": "not connected to DMS socket" @@ -427,7 +429,7 @@ Singleton { if (method.startsWith("clipboard")) { clipboardRequestIds[id] = true; } else { - console.log("DMSService.sendRequest: Sending request id=" + id + " method=" + method); + log.debug("DMSService.sendRequest: Sending request id=" + id + " method=" + method); } requestSocket.send(request); } diff --git a/quickshell/Services/DesktopService.qml b/quickshell/Services/DesktopService.qml index c9913e92..c0117218 100644 --- a/quickshell/Services/DesktopService.qml +++ b/quickshell/Services/DesktopService.qml @@ -1,10 +1,8 @@ pragma Singleton - pragma ComponentBehavior: Bound import QtQuick import Quickshell -import Quickshell.Io Singleton { id: root @@ -18,75 +16,75 @@ Singleton { if (_cache[moddedAppId] !== undefined) return _cache[moddedAppId]; - const result = (function() { - // 1. Try heuristic lookup (standard) - const entry = DesktopEntries.heuristicLookup(moddedAppId); - let icon = Quickshell.iconPath(entry?.icon, true); - if (icon && icon !== "") - return icon; - - // 2. Try the appId itself as an icon name - icon = Quickshell.iconPath(moddedAppId, true); - if (icon && icon !== "") - return icon; - - // 3. Try variations of the appId (lowercase, last part) - const appIds = [moddedAppId.toLowerCase()]; - const lastPart = moddedAppId.split('.').pop(); - if (lastPart && lastPart !== moddedAppId) { - appIds.push(lastPart); - appIds.push(lastPart.toLowerCase()); - } - - for (const id of appIds) { - icon = Quickshell.iconPath(id, true); - if (icon && icon !== "") - return icon; - } - - // 4. Deep search in all desktop entries (if the above fail) - // This is slow-ish but only happens once for failed icons - const strippedId = moddedAppId.replace(/-bin$/, "").toLowerCase(); - const allEntries = DesktopEntries.applications.values; - for (let i = 0; i < allEntries.length; i++) { - const e = allEntries[i]; - const eId = (e.id || "").toLowerCase(); - const eName = (e.name || "").toLowerCase(); - const eExec = (e.execString || "").toLowerCase(); - - if (eId.includes(strippedId) || eName.includes(strippedId) || eExec.includes(strippedId)) { - icon = Quickshell.iconPath(e.icon, true); - if (icon && icon !== "") - return icon; - } - } - - // 5. Nix/Guix specific store check (as a last resort) - for (const appId of appIds) { - let execPath = entry?.execString?.replace(/\/bin.*/, ""); - if (!execPath) - continue; - - if (execPath.startsWith("/nix/store/") || execPath.startsWith("/gnu/store/")) { - const basePath = execPath; - const sizes = ["256x256", "128x128", "64x64", "48x48", "32x32", "24x24", "16x16"]; - - let iconPath = `${basePath}/share/icons/hicolor/scalable/apps/${appId}.svg`; - icon = Quickshell.iconPath(iconPath, true); + const result = (function () { + // 1. Try heuristic lookup (standard) + const entry = DesktopEntries.heuristicLookup(moddedAppId); + let icon = Quickshell.iconPath(entry?.icon, true); if (icon && icon !== "") return icon; - for (const size of sizes) { - iconPath = `${basePath}/share/icons/hicolor/${size}/apps/${appId}.png`; - icon = Quickshell.iconPath(iconPath, true); + // 2. Try the appId itself as an icon name + icon = Quickshell.iconPath(moddedAppId, true); + if (icon && icon !== "") + return icon; + + // 3. Try variations of the appId (lowercase, last part) + const appIds = [moddedAppId.toLowerCase()]; + const lastPart = moddedAppId.split('.').pop(); + if (lastPart && lastPart !== moddedAppId) { + appIds.push(lastPart); + appIds.push(lastPart.toLowerCase()); + } + + for (const id of appIds) { + icon = Quickshell.iconPath(id, true); if (icon && icon !== "") return icon; } - } - } - return ""; - })(); + // 4. Deep search in all desktop entries (if the above fail) + // This is slow-ish but only happens once for failed icons + const strippedId = moddedAppId.replace(/-bin$/, "").toLowerCase(); + const allEntries = DesktopEntries.applications.values; + for (let i = 0; i < allEntries.length; i++) { + const e = allEntries[i]; + const eId = (e.id || "").toLowerCase(); + const eName = (e.name || "").toLowerCase(); + const eExec = (e.execString || "").toLowerCase(); + + if (eId.includes(strippedId) || eName.includes(strippedId) || eExec.includes(strippedId)) { + icon = Quickshell.iconPath(e.icon, true); + if (icon && icon !== "") + return icon; + } + } + + // 5. Nix/Guix specific store check (as a last resort) + for (const appId of appIds) { + let execPath = entry?.execString?.replace(/\/bin.*/, ""); + if (!execPath) + continue; + + if (execPath.startsWith("/nix/store/") || execPath.startsWith("/gnu/store/")) { + const basePath = execPath; + const sizes = ["256x256", "128x128", "64x64", "48x48", "32x32", "24x24", "16x16"]; + + let iconPath = `${basePath}/share/icons/hicolor/scalable/apps/${appId}.svg`; + icon = Quickshell.iconPath(iconPath, true); + if (icon && icon !== "") + return icon; + + for (const size of sizes) { + iconPath = `${basePath}/share/icons/hicolor/${size}/apps/${appId}.png`; + icon = Quickshell.iconPath(iconPath, true); + if (icon && icon !== "") + return icon; + } + } + } + + return ""; + })(); _cache[moddedAppId] = result; return result; diff --git a/quickshell/Services/DgopService.qml b/quickshell/Services/DgopService.qml index e63c5c57..0d00f806 100644 --- a/quickshell/Services/DgopService.qml +++ b/quickshell/Services/DgopService.qml @@ -5,9 +5,11 @@ import QtQuick import Quickshell import Quickshell.Io import qs.Common +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("DgopService") property int refCount: 0 property int updateInterval: refCount > 0 ? 3000 : 30000 @@ -643,7 +645,7 @@ Singleton { onStarted: dgopProcessPid = processId ?? 0 onExited: exitCode => { if (exitCode !== 0) { - console.warn("Dgop process failed with exit code:", exitCode); + log.warn("Dgop process failed with exit code:", exitCode); isUpdating = false; } } @@ -654,8 +656,8 @@ Singleton { const data = JSON.parse(text.trim()); parseData(data); } catch (e) { - console.warn("Failed to parse dgop JSON:", e); - console.warn("Raw text was:", text.substring(0, 200)); + log.warn("Failed to parse dgop JSON:", e); + log.warn("Raw text was:", text.substring(0, 200)); isUpdating = false; } } @@ -669,7 +671,7 @@ Singleton { running: false onExited: exitCode => { if (exitCode !== 0) { - console.warn("GPU init process failed with exit code:", exitCode); + log.warn("GPU init process failed with exit code:", exitCode); } } stdout: StdioCollector { @@ -679,7 +681,7 @@ Singleton { const data = JSON.parse(text.trim()); parseData(data); } catch (e) { - console.warn("Failed to parse GPU init JSON:", e); + log.warn("Failed to parse GPU init JSON:", e); } } } @@ -692,7 +694,7 @@ Singleton { running: false onExited: exitCode => { if (exitCode !== 0) { - console.warn("System init process failed with exit code:", exitCode); + log.warn("System init process failed with exit code:", exitCode); } } stdout: StdioCollector { @@ -702,7 +704,7 @@ Singleton { const data = JSON.parse(text.trim()); parseData(data); } catch (e) { - console.warn("Failed to parse system init JSON:", e); + log.warn("Failed to parse system init JSON:", e); } } } @@ -727,7 +729,7 @@ Singleton { } } } else { - console.warn("dgop is not installed or not in PATH"); + log.warn("dgop is not installed or not in PATH"); } } } @@ -738,7 +740,7 @@ Singleton { running: false onExited: exitCode => { if (exitCode !== 0) { - console.warn("Failed to read /etc/os-release"); + log.warn("Failed to read /etc/os-release"); } } stdout: StdioCollector { @@ -761,9 +763,9 @@ Singleton { // Prefer PRETTY_NAME, fallback to NAME const distroName = prettyName || name || "Linux"; distribution = distroName; - console.info("Detected distribution:", distroName); + log.info("Detected distribution:", distroName); } catch (e) { - console.warn("Failed to parse /etc/os-release:", e); + log.warn("Failed to parse /etc/os-release:", e); distribution = "Linux"; } } diff --git a/quickshell/Services/DisplayService.qml b/quickshell/Services/DisplayService.qml index 7666a586..9c462e51 100644 --- a/quickshell/Services/DisplayService.qml +++ b/quickshell/Services/DisplayService.qml @@ -5,9 +5,11 @@ import QtQuick import Quickshell import Quickshell.Io import qs.Common +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("DisplayService") property bool brightnessAvailable: devices.length > 0 property var devices: [] @@ -247,7 +249,7 @@ Singleton { function setBrightness(percentage, device, suppressOsd) { const actualDevice = device === "" ? getDefaultDevice() : (device || currentDevice || getDefaultDevice()); if (!actualDevice) { - console.warn("DisplayService: No device selected for brightness change"); + log.warn("No device selected for brightness change"); return; } @@ -273,14 +275,14 @@ Singleton { } if (maxValue <= 0) { - console.warn("DisplayService: Invalid max value for device", actualDevice, "- skipping brightness change"); + log.warn("Invalid max value for device", actualDevice, "- skipping brightness change"); return; } const clampedValue = Math.max(minValue, Math.min(maxValue, percentage)); if (!DMSService.isConnected) { - console.warn("DisplayService: Not connected to DMS"); + log.warn("Not connected to DMS"); return; } @@ -319,7 +321,7 @@ Singleton { DMSService.sendRequest("brightness.setBrightness", params, response => { if (response.error) { - console.error("DisplayService: Failed to set brightness:", response.error); + log.error("Failed to set brightness:", response.error); ToastService.showError(I18n.tr("Failed to set brightness"), response.error, "", "brightness"); } else { ToastService.dismissCategory("brightness"); @@ -453,7 +455,7 @@ Singleton { "enabled": true }, response => { if (response.error) { - console.error("DisplayService: Failed to enable gamma control:", response.error); + log.error("Failed to enable gamma control:", response.error); ToastService.showError(I18n.tr("Failed to enable night mode"), response.error, "", "night-mode"); nightModeEnabled = false; SessionData.setNightModeEnabled(false); @@ -481,7 +483,7 @@ Singleton { "enabled": false }, response => { if (response.error) { - console.error("DisplayService: Failed to disable gamma control:", response.error); + log.error("Failed to disable gamma control:", response.error); ToastService.showError(I18n.tr("Failed to disable night mode"), response.error, "", "night-mode"); } else { ToastService.dismissCategory("night-mode"); @@ -505,7 +507,7 @@ Singleton { "sunset": null }, response => { if (response.error) { - console.error("DisplayService: Failed to clear manual times:", response.error); + log.error("Failed to clear manual times:", response.error); return; } @@ -513,7 +515,7 @@ Singleton { "use": false }, response => { if (response.error) { - console.error("DisplayService: Failed to disable IP location:", response.error); + log.error("Failed to disable IP location:", response.error); return; } @@ -522,7 +524,7 @@ Singleton { "high": temperature }, response => { if (response.error) { - console.error("DisplayService: Failed to set temperature:", response.error); + log.error("Failed to set temperature:", response.error); ToastService.showError(I18n.tr("Failed to set night mode temperature"), response.error, "", "night-mode"); } else { ToastService.dismissCategory("night-mode"); @@ -564,7 +566,7 @@ Singleton { "use": false }, response => { if (response.error) { - console.error("DisplayService: Failed to disable IP location:", response.error); + log.error("Failed to disable IP location:", response.error); return; } @@ -573,7 +575,7 @@ Singleton { "high": highTemp }, response => { if (response.error) { - console.error("DisplayService: Failed to set temperature:", response.error); + log.error("Failed to set temperature:", response.error); ToastService.showError(I18n.tr("Failed to set night mode temperature"), response.error, "", "night-mode"); return; } @@ -583,7 +585,7 @@ Singleton { "sunset": sunset }, response => { if (response.error) { - console.error("DisplayService: Failed to set manual times:", response.error); + log.error("Failed to set manual times:", response.error); ToastService.showError(I18n.tr("Failed to set night mode schedule"), response.error, "", "night-mode"); } else { ToastService.dismissCategory("night-mode"); @@ -602,7 +604,7 @@ Singleton { "sunset": null }, response => { if (response.error) { - console.error("DisplayService: Failed to clear manual times:", response.error); + log.error("Failed to clear manual times:", response.error); return; } @@ -611,7 +613,7 @@ Singleton { "high": highTemp }, response => { if (response.error) { - console.error("DisplayService: Failed to set temperature:", response.error); + log.error("Failed to set temperature:", response.error); ToastService.showError(I18n.tr("Failed to set night mode temperature"), response.error, "", "night-mode"); return; } @@ -621,7 +623,7 @@ Singleton { "use": true }, response => { if (response.error) { - console.error("DisplayService: Failed to enable IP location:", response.error); + log.error("Failed to enable IP location:", response.error); ToastService.showError(I18n.tr("Failed to enable IP location"), response.error, "", "night-mode"); } else { ToastService.dismissCategory("night-mode"); @@ -632,7 +634,7 @@ Singleton { "use": false }, response => { if (response.error) { - console.error("DisplayService: Failed to disable IP location:", response.error); + log.error("Failed to disable IP location:", response.error); return; } @@ -641,7 +643,7 @@ Singleton { "longitude": SessionData.longitude }, response => { if (response.error) { - console.error("DisplayService: Failed to set location:", response.error); + log.error("Failed to set location:", response.error); ToastService.showError(I18n.tr("Failed to set night mode location"), response.error, "", "night-mode"); } else { ToastService.dismissCategory("night-mode"); @@ -649,7 +651,7 @@ Singleton { }); }); } else { - console.warn("DisplayService: Location mode selected but no coordinates set and IP location disabled"); + log.warn("Location mode selected but no coordinates set and IP location disabled"); } }); }); @@ -703,7 +705,7 @@ Singleton { if (response.error) { gammaControlAvailable = false; automationAvailable = false; - console.error("DisplayService: Gamma control not available:", response.error); + log.error("Gamma control not available:", response.error); } else { gammaControlAvailable = true; automationAvailable = true; @@ -713,7 +715,7 @@ Singleton { "enabled": true }, enableResponse => { if (enableResponse.error) { - console.error("DisplayService: Failed to enable gamma control on startup:", enableResponse.error); + log.error("Failed to enable gamma control on startup:", enableResponse.error); return; } @@ -772,7 +774,7 @@ Singleton { DMSService.sendRequest("brightness.rescan", null, response => { if (response.error) { - console.error("DisplayService: Failed to rescan brightness devices:", response.error); + log.error("Failed to rescan brightness devices:", response.error); } }); } diff --git a/quickshell/Services/DwlService.qml b/quickshell/Services/DwlService.qml index 564e5619..b2483dcc 100644 --- a/quickshell/Services/DwlService.qml +++ b/quickshell/Services/DwlService.qml @@ -6,9 +6,11 @@ import QtQuick import Quickshell import Quickshell.Io import qs.Common +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("DwlService") readonly property string configDir: Paths.strip(StandardPaths.writableLocation(StandardPaths.ConfigLocation)) readonly property string mangoDmsDir: configDir + "/mango/dms" @@ -91,7 +93,7 @@ Singleton { const hasDwl = DMSService.capabilities.includes("dwl"); if (hasDwl && !dwlAvailable) { dwlAvailable = true; - console.info("DwlService: DWL capability detected"); + log.info("DWL capability detected"); requestState(); refreshOutputScales(); } else if (!hasDwl) { @@ -130,7 +132,7 @@ Singleton { "toggleTagset": toggleTagset }, response => { if (response.error) { - console.warn("DwlService: setTags error:", response.error); + log.warn("setTags error:", response.error); } }); } @@ -146,7 +148,7 @@ Singleton { "xorTags": xorTags }, response => { if (response.error) { - console.warn("DwlService: setClientTags error:", response.error); + log.warn("setClientTags error:", response.error); } }); } @@ -161,7 +163,7 @@ Singleton { "index": index }, response => { if (response.error) { - console.warn("DwlService: setLayout error:", response.error); + log.warn("setLayout error:", response.error); } }); } @@ -205,7 +207,7 @@ Singleton { function toggleTag(outputName, tagIndex) { const output = getOutputState(outputName); if (!output || !output.tags) { - console.log("toggleTag: no output or tags for", outputName); + log.debug("toggleTag: no output or tags for", outputName); return; } @@ -219,13 +221,13 @@ Singleton { const clickedMask = 1 << tagIndex; const newMask = currentMask ^ clickedMask; - console.log("toggleTag:", outputName, "tag:", tagIndex, "currentMask:", currentMask.toString(2), "clickedMask:", clickedMask.toString(2), "newMask:", newMask.toString(2)); + log.debug("toggleTag:", outputName, "tag:", tagIndex, "currentMask:", currentMask.toString(2), "clickedMask:", clickedMask.toString(2), "newMask:", newMask.toString(2)); if (newMask === 0) { - console.log("toggleTag: newMask is 0, switching to tag", tagIndex); + log.debug("toggleTag: newMask is 0, switching to tag", tagIndex); setTags(outputName, 1 << tagIndex, 0); } else { - console.log("toggleTag: setting combined mask", newMask); + log.debug("toggleTag: setting combined mask", newMask); setTags(outputName, newMask, 0); } } @@ -256,14 +258,14 @@ Singleton { } outputScales = newScales; } catch (e) { - console.warn("DwlService: Failed to parse mmsg output:", e); + log.warn("Failed to parse mmsg output:", e); } } } onExited: exitCode => { if (exitCode !== 0) { - console.warn("DwlService: mmsg failed with exit code:", exitCode); + log.warn("mmsg failed with exit code:", exitCode); } } } @@ -333,10 +335,10 @@ Singleton { Proc.runCommand("mango-write-outputs", ["sh", "-c", `mkdir -p "${mangoDmsDir}" && cat > "${outputsPath}" << 'EOF'\n${content}EOF`], (output, exitCode) => { if (exitCode !== 0) { - console.warn("DwlService: Failed to write outputs config:", output); + log.warn("Failed to write outputs config:", output); return; } - console.info("DwlService: Generated outputs config at", outputsPath); + log.info("Generated outputs config at", outputsPath); if (CompositorService.isDwl) reloadConfig(); }); @@ -345,7 +347,7 @@ Singleton { function reloadConfig() { Proc.runCommand("mango-reload", ["mmsg", "-d", "reload_config"], (output, exitCode) => { if (exitCode !== 0) - console.warn("DwlService: mmsg reload_config failed:", output); + log.warn("mmsg reload_config failed:", output); }); } @@ -372,10 +374,10 @@ borderpx=${borderSize} Proc.runCommand("mango-write-layout", ["sh", "-c", `mkdir -p "${mangoDmsDir}" && cat > "${layoutPath}" << 'EOF'\n${content}EOF`], (output, exitCode) => { if (exitCode !== 0) { - console.warn("DwlService: Failed to write layout config:", output); + log.warn("Failed to write layout config:", output); return; } - console.info("DwlService: Generated layout config at", layoutPath); + log.info("Generated layout config at", layoutPath); reloadConfig(); }); } @@ -407,13 +409,13 @@ borderpx=${borderSize} if (!CompositorService.isDwl) return; - console.log("DwlService: Generating cursor config..."); + log.debug("Generating cursor config..."); const settings = typeof SettingsData !== "undefined" ? SettingsData.cursorSettings : null; if (!settings) { Proc.runCommand("mango-write-cursor", ["sh", "-c", `mkdir -p "${mangoDmsDir}" && : > "${cursorPath}"`], (output, exitCode) => { if (exitCode !== 0) - console.warn("DwlService: Failed to write cursor config:", output); + log.warn("Failed to write cursor config:", output); }); return; } @@ -426,7 +428,7 @@ borderpx=${borderSize} if (isDefaultConfig) { Proc.runCommand("mango-write-cursor", ["sh", "-c", `mkdir -p "${mangoDmsDir}" && : > "${cursorPath}"`], (output, exitCode) => { if (exitCode !== 0) - console.warn("DwlService: Failed to write cursor config:", output); + log.warn("Failed to write cursor config:", output); }); return; } @@ -444,10 +446,10 @@ cursor_size=${size}`; Proc.runCommand("mango-write-cursor", ["sh", "-c", `mkdir -p "${mangoDmsDir}" && cat > "${cursorPath}" << 'EOF'\n${content}EOF`], (output, exitCode) => { if (exitCode !== 0) { - console.warn("DwlService: Failed to write cursor config:", output); + log.warn("Failed to write cursor config:", output); return; } - console.info("DwlService: Generated cursor config at", cursorPath); + log.info("Generated cursor config at", cursorPath); reloadConfig(); }); } diff --git a/quickshell/Services/ExtWorkspaceService.qml b/quickshell/Services/ExtWorkspaceService.qml index 48a8f9a1..5b4fc654 100644 --- a/quickshell/Services/ExtWorkspaceService.qml +++ b/quickshell/Services/ExtWorkspaceService.qml @@ -3,9 +3,11 @@ pragma ComponentBehavior: Bound import QtQuick import Quickshell +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("ExtWorkspaceService") property bool extWorkspaceAvailable: false property var groups: [] @@ -49,13 +51,13 @@ Singleton { if (typeof CompositorService !== "undefined") { const useExtWorkspace = DMSService.forceExtWorkspace || (!CompositorService.isNiri && !CompositorService.isHyprland && !CompositorService.isDwl && !CompositorService.isSway && !CompositorService.isScroll && !CompositorService.isMiracle); if (!useExtWorkspace) { - console.info("ExtWorkspaceService: ext-workspace available but compositor has native support"); + log.info("ext-workspace available but compositor has native support"); extWorkspaceAvailable = false; return; } } extWorkspaceAvailable = true; - console.info("ExtWorkspaceService: ext-workspace capability detected"); + log.info("ext-workspace capability detected"); DMSService.addSubscription("extworkspace"); requestState(); } else if (!hasExtWorkspace) { @@ -78,9 +80,9 @@ Singleton { function handleStateUpdate(state) { groups = state.groups || []; if (groups.length === 0) { - console.warn("ExtWorkspaceService: Received empty workspace groups from backend"); + log.warn("Received empty workspace groups from backend"); } else { - console.log("ExtWorkspaceService: Updated with", groups.length, "workspace groups"); + log.debug("Updated with", groups.length, "workspace groups"); } stateChanged(); } @@ -95,7 +97,7 @@ Singleton { "groupID": groupID }, response => { if (response.error) { - console.warn("ExtWorkspaceService: activateWorkspace error:", response.error); + log.warn("activateWorkspace error:", response.error); } }); } @@ -110,7 +112,7 @@ Singleton { "groupID": groupID }, response => { if (response.error) { - console.warn("ExtWorkspaceService: deactivateWorkspace error:", response.error); + log.warn("deactivateWorkspace error:", response.error); } }); } @@ -125,7 +127,7 @@ Singleton { "groupID": groupID }, response => { if (response.error) { - console.warn("ExtWorkspaceService: removeWorkspace error:", response.error); + log.warn("removeWorkspace error:", response.error); } }); } @@ -140,7 +142,7 @@ Singleton { "name": name }, response => { if (response.error) { - console.warn("ExtWorkspaceService: createWorkspace error:", response.error); + log.warn("createWorkspace error:", response.error); } }); } @@ -272,6 +274,6 @@ Singleton { return; } } - console.warn("ExtWorkspaceService: workspace not found:", workspaceName); + log.warn("workspace not found:", workspaceName); } } diff --git a/quickshell/Services/FirstLaunchService.qml b/quickshell/Services/FirstLaunchService.qml index 8b7acd36..f3aaa866 100644 --- a/quickshell/Services/FirstLaunchService.qml +++ b/quickshell/Services/FirstLaunchService.qml @@ -6,9 +6,11 @@ import QtQuick import Quickshell import Quickshell.Io import qs.Common +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("FirstLaunchService") readonly property string configDir: Paths.strip(StandardPaths.writableLocation(StandardPaths.ConfigLocation)) + "/DankMaterialShell" readonly property string settingsPath: configDir + "/settings.json" @@ -77,10 +79,10 @@ Singleton { if (result === "first") { root.isFirstLaunch = true; - console.info("FirstLaunchService: First launch detected, greeter will be shown"); + log.info("First launch detected, greeter will be shown"); } else if (result === "existing_user") { root.isFirstLaunch = false; - console.info("FirstLaunchService: Existing user detected, silently creating marker"); + log.info("Existing user detected, silently creating marker"); touchMarkerProcess.running = true; } else { root.isFirstLaunch = false; @@ -102,9 +104,9 @@ Singleton { onExited: exitCode => { if (exitCode === 0) { - console.info("FirstLaunchService: First launch marker created"); + log.info("First launch marker created"); } else { - console.warn("FirstLaunchService: Failed to create first launch marker"); + log.warn("Failed to create first launch marker"); } } } diff --git a/quickshell/Services/HyprlandService.qml b/quickshell/Services/HyprlandService.qml index 20096ef6..d0db4c23 100644 --- a/quickshell/Services/HyprlandService.qml +++ b/quickshell/Services/HyprlandService.qml @@ -6,9 +6,11 @@ import QtQuick import Quickshell import Quickshell.Hyprland import qs.Common +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("HyprlandService") readonly property string configDir: Paths.strip(StandardPaths.writableLocation(StandardPaths.ConfigLocation)) readonly property string hyprDmsDir: configDir + "/hypr/dms" @@ -29,7 +31,7 @@ Singleton { function ensureWindowrulesConfig() { Proc.runCommand("hypr-ensure-windowrules", ["sh", "-c", `mkdir -p "${hyprDmsDir}" && [ ! -f "${windowrulesPath}" ] && touch "${windowrulesPath}" || true`], (output, exitCode) => { if (exitCode !== 0) - console.warn("HyprlandService: Failed to ensure windowrules.conf:", output); + log.warn("Failed to ensure windowrules.conf:", output); }); } @@ -159,10 +161,10 @@ Singleton { Proc.runCommand("hypr-write-outputs", ["sh", "-c", `mkdir -p "${hyprDmsDir}" && cat > "${outputsPath}" << 'EOF'\n${content}EOF`], (output, exitCode) => { if (exitCode !== 0) { - console.warn("HyprlandService: Failed to write outputs config:", output); + log.warn("Failed to write outputs config:", output); return; } - console.info("HyprlandService: Generated outputs config at", outputsPath); + log.info("Generated outputs config at", outputsPath); if (CompositorService.isHyprland) reloadConfig(); }); @@ -171,7 +173,7 @@ Singleton { function reloadConfig() { Proc.runCommand("hyprctl-reload", ["hyprctl", "reload"], (output, exitCode) => { if (exitCode !== 0) - console.warn("HyprlandService: hyprctl reload failed:", output); + log.warn("hyprctl reload failed:", output); }); } @@ -202,10 +204,10 @@ decoration { Proc.runCommand("hypr-write-layout", ["sh", "-c", `mkdir -p "${hyprDmsDir}" && cat > "${layoutPath}" << 'EOF'\n${content}EOF`], (output, exitCode) => { if (exitCode !== 0) { - console.warn("HyprlandService: Failed to write layout config:", output); + log.warn("Failed to write layout config:", output); return; } - console.info("HyprlandService: Generated layout config at", layoutPath); + log.info("Generated layout config at", layoutPath); reloadConfig(); }); } @@ -264,7 +266,7 @@ decoration { if (!settings) { Proc.runCommand("hypr-write-cursor", ["sh", "-c", `mkdir -p "${hyprDmsDir}" && : > "${cursorPath}"`], (output, exitCode) => { if (exitCode !== 0) - console.warn("HyprlandService: Failed to write cursor config:", output); + log.warn("Failed to write cursor config:", output); }); return; } @@ -282,7 +284,7 @@ decoration { if (!hasTheme && !hasNonDefaultSize && !hasCursorSettings) { Proc.runCommand("hypr-write-cursor", ["sh", "-c", `mkdir -p "${hyprDmsDir}" && : > "${cursorPath}"`], (output, exitCode) => { if (exitCode !== 0) - console.warn("HyprlandService: Failed to write cursor config:", output); + log.warn("Failed to write cursor config:", output); }); return; } @@ -313,7 +315,7 @@ decoration { Proc.runCommand("hypr-write-cursor", ["sh", "-c", `mkdir -p "${hyprDmsDir}" && cat > "${cursorPath}" << 'EOF'\n${content}EOF`], (output, exitCode) => { if (exitCode !== 0) { - console.warn("HyprlandService: Failed to write cursor config:", output); + log.warn("Failed to write cursor config:", output); return; } if (hasTheme) @@ -331,7 +333,7 @@ decoration { const fullName = wsId + " " + newName; Proc.runCommand("hyprland-rename-ws", ["hyprctl", "dispatch", "renameworkspace", String(wsId), fullName], (output, exitCode) => { if (exitCode !== 0) { - console.warn("HyprlandService: Failed to rename workspace:", output); + log.warn("Failed to rename workspace:", output); } }); } diff --git a/quickshell/Services/IdleService.qml b/quickshell/Services/IdleService.qml index f0645096..00283942 100644 --- a/quickshell/Services/IdleService.qml +++ b/quickshell/Services/IdleService.qml @@ -5,9 +5,11 @@ import QtQuick import Quickshell import Quickshell.Wayland import qs.Common +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("IdleService") readonly property bool idleMonitorAvailable: { try { @@ -82,7 +84,7 @@ Singleton { function createIdleMonitors() { if (!idleMonitorAvailable) { - console.info("IdleService: IdleMonitor not available, skipping creation"); + log.info("IdleMonitor not available, skipping creation"); return; } @@ -157,7 +159,7 @@ Singleton { } }); } catch (e) { - console.warn("IdleService: Error creating IdleMonitors:", e); + log.warn("Error creating IdleMonitors:", e); } } @@ -181,11 +183,11 @@ Singleton { onExternalInhibitActiveChanged: { if (externalInhibitActive) { const apps = DMSService.screensaverInhibitors.map(i => i.appName).join(", "); - console.info("IdleService: External idle inhibit active from:", apps || "unknown"); + log.info("External idle inhibit active from:", apps || "unknown"); SessionService.idleInhibited = true; SessionService.inhibitReason = "External app: " + (apps || "unknown"); } else { - console.info("IdleService: External idle inhibit released"); + log.info("External idle inhibit released"); SessionService.idleInhibited = false; SessionService.inhibitReason = "Keep system awake"; } @@ -193,9 +195,9 @@ Singleton { Component.onCompleted: { if (!idleMonitorAvailable) { - console.warn("IdleService: IdleMonitor not available - power management disabled. This requires a newer version of Quickshell."); + log.warn("IdleMonitor not available - power management disabled. This requires a newer version of Quickshell."); } else { - console.info("IdleService: Initialized with idle monitoring support"); + log.info("Initialized with idle monitoring support"); createIdleMonitors(); } diff --git a/quickshell/Services/KeybindsService.qml b/quickshell/Services/KeybindsService.qml index 470831b2..6d58893e 100644 --- a/quickshell/Services/KeybindsService.qml +++ b/quickshell/Services/KeybindsService.qml @@ -8,14 +8,16 @@ import Quickshell.Io import Quickshell.Wayland // ! Even though qmlls says this is unused, it is wrong import qs.Common +import qs.Services import "../Common/KeybindActions.js" as Actions Singleton { id: root + readonly property var log: Log.scoped("KeybindsService") Component.onCompleted: { if (!shortcutInhibitorAvailable) { - console.warn("[KeybindsService] ShortcutInhibitor is not available in this environment, keybinds editor disabled."); + log.warn("ShortcutInhibitor is not available in this environment, keybinds editor disabled."); } } @@ -150,7 +152,7 @@ Singleton { try { root.cheatsheet = JSON.parse(text); } catch (e) { - console.error("[KeybindsService] Failed to parse cheatsheet:", e); + log.error("Failed to parse cheatsheet:", e); root.cheatsheet = {}; } root.cheatsheetLoading = false; @@ -161,7 +163,7 @@ Singleton { onExited: exitCode => { if (exitCode === 0) return; - console.warn("[KeybindsService] Cheatsheet load failed with code:", exitCode); + log.warn("Cheatsheet load failed with code:", exitCode); root.cheatsheetLoading = false; } } @@ -176,7 +178,7 @@ Singleton { root._rawData = JSON.parse(text); root._processData(); } catch (e) { - console.error("[KeybindsService] Failed to parse binds:", e); + log.error("Failed to parse binds:", e); } root.loading = false; } @@ -184,7 +186,7 @@ Singleton { onExited: exitCode => { if (exitCode !== 0) { - console.warn("[KeybindsService] Load process failed with code:", exitCode); + log.warn("Load process failed with code:", exitCode); root.loading = false; } } @@ -206,7 +208,7 @@ Singleton { onExited: exitCode => { root.saving = false; if (exitCode !== 0) { - console.error("[KeybindsService] Save failed with code:", exitCode); + log.error("Save failed with code:", exitCode); root.bindSaveCompleted(false); return; } @@ -231,7 +233,7 @@ Singleton { onExited: exitCode => { if (exitCode !== 0) { - console.error("[KeybindsService] Remove failed with code:", exitCode); + log.error("Remove failed with code:", exitCode); return; } root.lastError = ""; @@ -255,7 +257,7 @@ Singleton { onExited: exitCode => { root.fixing = false; if (exitCode !== 0) { - console.error("[KeybindsService] Fix failed with code:", exitCode); + log.error("Fix failed with code:", exitCode); return; } root.lastError = ""; diff --git a/quickshell/Services/LegacyNetworkService.qml b/quickshell/Services/LegacyNetworkService.qml index 97d87458..f4cca39f 100644 --- a/quickshell/Services/LegacyNetworkService.qml +++ b/quickshell/Services/LegacyNetworkService.qml @@ -1,14 +1,15 @@ pragma Singleton - pragma ComponentBehavior: Bound import QtQuick import Quickshell import Quickshell.Io import qs.Common +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("LegacyNetworkService") property bool isActive: false property string networkStatus: "disconnected" @@ -33,20 +34,18 @@ Singleton { property int wifiSignalStrength: 0 property var wifiNetworks: [] property var savedConnections: [] - property var ssidToConnectionName: { - - } + property var ssidToConnectionName: {} property var wifiSignalIcon: { if (!wifiConnected || networkStatus !== "wifi") { - return "wifi_off" + return "wifi_off"; } if (wifiSignalStrength >= 50) { - return "wifi" + return "wifi"; } if (wifiSignalStrength >= 25) { - return "wifi_2_bar" + return "wifi_2_bar"; } - return "wifi_1_bar" + return "wifi_1_bar"; } property string userPreference: "auto" // "auto", "wifi", "ethernet" @@ -80,49 +79,48 @@ Singleton { signal connectionChanged function splitNmcliFields(line) { - const parts = [] - let cur = "" - let escape = false + const parts = []; + let cur = ""; + let escape = false; for (var i = 0; i < line.length; i++) { - const ch = line[i] + const ch = line[i]; if (escape) { - cur += ch - escape = false + cur += ch; + escape = false; } else if (ch === '\\') { - escape = true + escape = true; } else if (ch === ':') { - parts.push(cur) - cur = "" + parts.push(cur); + cur = ""; } else { - cur += ch + cur += ch; } } - parts.push(cur) - return parts + parts.push(cur); + return parts; } Component.onCompleted: { - root.userPreference = SettingsData.networkPreference + root.userPreference = SettingsData.networkPreference; } function activate() { if (!isActive) { - isActive = true - console.info("LegacyNetworkService: Activating...") - doRefreshNetworkState() + isActive = true; + log.info("Activating..."); + doRefreshNetworkState(); } } - function doRefreshNetworkState() { - updatePrimaryConnection() - updateDeviceStates() - updateActiveConnections() - updateWifiState() + updatePrimaryConnection(); + updateDeviceStates(); + updateActiveConnections(); + updateWifiState(); } function updatePrimaryConnection() { - primaryConnectionQuery.running = true + primaryConnectionQuery.running = true; } Process { @@ -132,13 +130,13 @@ Singleton { stdout: StdioCollector { onStreamFinished: { - const match = text.match(/objectpath '([^']+)'/) + const match = text.match(/objectpath '([^']+)'/); if (match && match[1] !== '/') { - root.primaryConnection = match[1] - getPrimaryConnectionType.running = true + root.primaryConnection = match[1]; + getPrimaryConnectionType.running = true; } else { - root.primaryConnection = "" - root.networkStatus = "disconnected" + root.primaryConnection = ""; + root.networkStatus = "disconnected"; } } } @@ -152,18 +150,18 @@ Singleton { stdout: StdioCollector { onStreamFinished: { if (text.includes("802-3-ethernet")) { - root.networkStatus = "ethernet" + root.networkStatus = "ethernet"; } else if (text.includes("802-11-wireless")) { - root.networkStatus = "wifi" + root.networkStatus = "wifi"; } - root.connectionChanged() + root.connectionChanged(); } } } function updateDeviceStates() { - getEthernetDevice.running = true - getWifiDevice.running = true + getEthernetDevice.running = true; + getWifiDevice.running = true; } Process { @@ -173,26 +171,26 @@ Singleton { stdout: StdioCollector { onStreamFinished: { - const lines = text.trim().split('\n') - let ethernetInterface = "" + const lines = text.trim().split('\n'); + let ethernetInterface = ""; for (const line of lines) { - const splitParts = line.split(':') - const device = splitParts[0] - const type = splitParts.length > 1 ? splitParts[1] : "" + const splitParts = line.split(':'); + const device = splitParts[0]; + const type = splitParts.length > 1 ? splitParts[1] : ""; if (type === "ethernet") { - ethernetInterface = device - break + ethernetInterface = device; + break; } } if (ethernetInterface) { - root.ethernetInterface = ethernetInterface - getEthernetDevicePath.command = lowPriorityCmd.concat(["gdbus", "call", "--system", "--dest", "org.freedesktop.NetworkManager", "--object-path", "/org/freedesktop/NetworkManager", "--method", "org.freedesktop.NetworkManager.GetDeviceByIpIface", ethernetInterface]) - getEthernetDevicePath.running = true + root.ethernetInterface = ethernetInterface; + getEthernetDevicePath.command = lowPriorityCmd.concat(["gdbus", "call", "--system", "--dest", "org.freedesktop.NetworkManager", "--object-path", "/org/freedesktop/NetworkManager", "--method", "org.freedesktop.NetworkManager.GetDeviceByIpIface", ethernetInterface]); + getEthernetDevicePath.running = true; } else { - root.ethernetInterface = "" - root.ethernetConnected = false + root.ethernetInterface = ""; + root.ethernetConnected = false; } } } @@ -204,21 +202,21 @@ Singleton { stdout: StdioCollector { onStreamFinished: { - const match = text.match(/objectpath '([^']+)'/) + const match = text.match(/objectpath '([^']+)'/); if (match && match[1] !== '/') { - checkEthernetState.command = lowPriorityCmd.concat(["gdbus", "call", "--system", "--dest", "org.freedesktop.NetworkManager", "--object-path", match[1], "--method", "org.freedesktop.DBus.Properties.Get", "org.freedesktop.NetworkManager.Device", "State"]) - checkEthernetState.running = true + checkEthernetState.command = lowPriorityCmd.concat(["gdbus", "call", "--system", "--dest", "org.freedesktop.NetworkManager", "--object-path", match[1], "--method", "org.freedesktop.DBus.Properties.Get", "org.freedesktop.NetworkManager.Device", "State"]); + checkEthernetState.running = true; } else { - root.ethernetInterface = "" - root.ethernetConnected = false + root.ethernetInterface = ""; + root.ethernetConnected = false; } } } onExited: exitCode => { if (exitCode !== 0) { - root.ethernetInterface = "" - root.ethernetConnected = false + root.ethernetInterface = ""; + root.ethernetConnected = false; } } } @@ -229,12 +227,12 @@ Singleton { stdout: StdioCollector { onStreamFinished: { - const isConnected = text.includes("uint32 100") - root.ethernetConnected = isConnected + const isConnected = text.includes("uint32 100"); + root.ethernetConnected = isConnected; if (isConnected) { - getEthernetIP.running = true + getEthernetIP.running = true; } else { - root.ethernetIP = "" + root.ethernetIP = ""; } } } @@ -247,9 +245,9 @@ Singleton { stdout: StdioCollector { onStreamFinished: { - const match = text.match(/inet (\d+\.\d+\.\d+\.\d+)/) + const match = text.match(/inet (\d+\.\d+\.\d+\.\d+)/); if (match) { - root.ethernetIP = match[1] + root.ethernetIP = match[1]; } } } @@ -262,26 +260,26 @@ Singleton { stdout: StdioCollector { onStreamFinished: { - const lines = text.trim().split('\n') - let wifiInterface = "" + const lines = text.trim().split('\n'); + let wifiInterface = ""; for (const line of lines) { - const splitParts = line.split(':') - const device = splitParts[0] - const type = splitParts.length > 1 ? splitParts[1] : "" + const splitParts = line.split(':'); + const device = splitParts[0]; + const type = splitParts.length > 1 ? splitParts[1] : ""; if (type === "wifi") { - wifiInterface = device - break + wifiInterface = device; + break; } } if (wifiInterface) { - root.wifiInterface = wifiInterface - getWifiDevicePath.command = lowPriorityCmd.concat(["gdbus", "call", "--system", "--dest", "org.freedesktop.NetworkManager", "--object-path", "/org/freedesktop/NetworkManager", "--method", "org.freedesktop.NetworkManager.GetDeviceByIpIface", wifiInterface]) - getWifiDevicePath.running = true + root.wifiInterface = wifiInterface; + getWifiDevicePath.command = lowPriorityCmd.concat(["gdbus", "call", "--system", "--dest", "org.freedesktop.NetworkManager", "--object-path", "/org/freedesktop/NetworkManager", "--method", "org.freedesktop.NetworkManager.GetDeviceByIpIface", wifiInterface]); + getWifiDevicePath.running = true; } else { - root.wifiInterface = "" - root.wifiConnected = false + root.wifiInterface = ""; + root.wifiConnected = false; } } } @@ -293,24 +291,24 @@ Singleton { stdout: StdioCollector { onStreamFinished: { - const match = text.match(/objectpath '([^']+)'/) + const match = text.match(/objectpath '([^']+)'/); if (match && match[1] !== '/') { - root.wifiDevicePath = match[1] - checkWifiState.command = lowPriorityCmd.concat(["gdbus", "call", "--system", "--dest", "org.freedesktop.NetworkManager", "--object-path", match[1], "--method", "org.freedesktop.DBus.Properties.Get", "org.freedesktop.NetworkManager.Device", "State"]) - checkWifiState.running = true + root.wifiDevicePath = match[1]; + checkWifiState.command = lowPriorityCmd.concat(["gdbus", "call", "--system", "--dest", "org.freedesktop.NetworkManager", "--object-path", match[1], "--method", "org.freedesktop.DBus.Properties.Get", "org.freedesktop.NetworkManager.Device", "State"]); + checkWifiState.running = true; } else { - root.wifiInterface = "" - root.wifiConnected = false - root.wifiDevicePath = "" - root.activeAccessPointPath = "" + root.wifiInterface = ""; + root.wifiConnected = false; + root.wifiDevicePath = ""; + root.activeAccessPointPath = ""; } } } onExited: exitCode => { if (exitCode !== 0) { - root.wifiInterface = "" - root.wifiConnected = false + root.wifiInterface = ""; + root.wifiConnected = false; } } } @@ -321,24 +319,24 @@ Singleton { stdout: StdioCollector { onStreamFinished: { - root.wifiConnected = text.includes("uint32 100") + root.wifiConnected = text.includes("uint32 100"); if (root.wifiConnected) { - getWifiIP.running = true - getCurrentWifiInfo.running = true - getActiveAccessPoint.running = true + getWifiIP.running = true; + getCurrentWifiInfo.running = true; + getActiveAccessPoint.running = true; if (root.currentWifiSSID === "") { if (root.wifiConnectionUuid) { - resolveWifiSSID.running = true + resolveWifiSSID.running = true; } if (root.wifiInterface) { - resolveWifiSSIDFromDevice.running = true + resolveWifiSSIDFromDevice.running = true; } } } else { - root.wifiIP = "" - root.currentWifiSSID = "" - root.wifiSignalStrength = 0 - root.activeAccessPointPath = "" + root.wifiIP = ""; + root.currentWifiSSID = ""; + root.wifiSignalStrength = 0; + root.activeAccessPointPath = ""; } } } @@ -351,9 +349,9 @@ Singleton { stdout: StdioCollector { onStreamFinished: { - const match = text.match(/inet (\d+\.\d+\.\d+\.\d+)/) + const match = text.match(/inet (\d+\.\d+\.\d+\.\d+)/); if (match) { - root.wifiIP = match[1] + root.wifiIP = match[1]; } } } @@ -366,11 +364,11 @@ Singleton { stdout: StdioCollector { onStreamFinished: { - const match = text.match(/objectpath '([^']+)'/) + const match = text.match(/objectpath '([^']+)'/); if (match && match[1] !== '/') { - root.activeAccessPointPath = match[1] + root.activeAccessPointPath = match[1]; } else { - root.activeAccessPointPath = "" + root.activeAccessPointPath = ""; } } } @@ -385,23 +383,23 @@ Singleton { splitMarker: "\n" onRead: line => { if (line.startsWith("yes:")) { - const rest = line.substring(4) - const parts = root.splitNmcliFields(rest) + const rest = line.substring(4); + const parts = root.splitNmcliFields(rest); if (parts.length >= 2) { - const signal = parseInt(parts[0]) - console.log("Current WiFi signal strength:", signal) - root.wifiSignalStrength = isNaN(signal) ? 0 : signal - root.currentWifiSSID = parts[1] - console.log("Current WiFi SSID:", root.currentWifiSSID) + const signal = parseInt(parts[0]); + log.debug("Current WiFi signal strength:", signal); + root.wifiSignalStrength = isNaN(signal) ? 0 : signal; + root.currentWifiSSID = parts[1]; + log.debug("Current WiFi SSID:", root.currentWifiSSID); } - return + return; } } } } function updateActiveConnections() { - getActiveConnections.running = true + getActiveConnections.running = true; } Process { @@ -411,18 +409,18 @@ Singleton { stdout: StdioCollector { onStreamFinished: { - const lines = text.trim().split('\n') + const lines = text.trim().split('\n'); for (const line of lines) { - const parts = line.split(':') + const parts = line.split(':'); if (parts.length >= 4) { - const uuid = parts[0] - const type = parts[1] - const device = parts[2] - const state = parts[3] + const uuid = parts[0]; + const type = parts[1]; + const device = parts[2]; + const state = parts[3]; if (type === "802-3-ethernet" && state === "activated") { - root.ethernetConnectionUuid = uuid + root.ethernetConnectionUuid = uuid; } else if (type === "802-11-wireless" && state === "activated") { - root.wifiConnectionUuid = uuid + root.wifiConnectionUuid = uuid; } } } @@ -438,9 +436,9 @@ Singleton { stdout: StdioCollector { onStreamFinished: { - const ssid = text.trim() + const ssid = text.trim(); if (ssid) { - root.currentWifiSSID = ssid + root.currentWifiSSID = ssid; } } } @@ -455,9 +453,9 @@ Singleton { stdout: StdioCollector { onStreamFinished: { if (!root.currentWifiSSID) { - const name = text.trim() + const name = text.trim(); if (name) { - root.currentWifiSSID = name + root.currentWifiSSID = name; } } } @@ -465,7 +463,7 @@ Singleton { } function updateWifiState() { - checkWifiEnabled.running = true + checkWifiEnabled.running = true; } Process { @@ -475,19 +473,19 @@ Singleton { stdout: StdioCollector { onStreamFinished: { - root.wifiEnabled = text.includes("true") - root.wifiAvailable = true // Always available if we can check it + root.wifiEnabled = text.includes("true"); + root.wifiAvailable = true; // Always available if we can check it } } } function scanWifi() { if (root.isScanning || !root.wifiEnabled) { - return + return; } - root.isScanning = true - requestWifiScan.running = true + root.isScanning = true; + requestWifiScan.running = true; } Process { @@ -497,22 +495,22 @@ Singleton { onExited: exitCode => { if (exitCode === 0) { - scanWifiNetworks() + scanWifiNetworks(); } else { - console.warn("WiFi scan request failed") - root.isScanning = false + log.warn("WiFi scan request failed"); + root.isScanning = false; } } } function scanWifiNetworks() { if (!root.wifiInterface) { - root.isScanning = false - return + root.isScanning = false; + return; } - getWifiNetworks.running = true - getSavedConnections.running = true + getWifiNetworks.running = true; + getSavedConnections.running = true; } Process { @@ -522,34 +520,34 @@ Singleton { stdout: StdioCollector { onStreamFinished: { - const networks = [] - const lines = text.trim().split('\n') - const seen = new Set() + const networks = []; + const lines = text.trim().split('\n'); + const seen = new Set(); for (const line of lines) { - const parts = root.splitNmcliFields(line) + const parts = root.splitNmcliFields(line); if (parts.length >= 4 && parts[0]) { - const ssid = parts[0] + const ssid = parts[0]; if (!seen.has(ssid)) { - seen.add(ssid) - const signal = parseInt(parts[1]) || 0 + seen.add(ssid); + const signal = parseInt(parts[1]) || 0; networks.push({ - "ssid": ssid, - "signal": signal, - "secured": parts[2] !== "", - "bssid": parts[3], - "connected": ssid === root.currentWifiSSID, - "saved": false - }) + "ssid": ssid, + "signal": signal, + "secured": parts[2] !== "", + "bssid": parts[3], + "connected": ssid === root.currentWifiSSID, + "saved": false + }); } } } - networks.sort((a, b) => b.signal - a.signal) - root.wifiNetworks = networks - root.isScanning = false - root.networksUpdated() + networks.sort((a, b) => b.signal - a.signal); + root.wifiNetworks = networks; + root.isScanning = false; + root.networksUpdated(); } } } @@ -561,57 +559,57 @@ Singleton { stdout: StdioCollector { onStreamFinished: { - const saved = [] - const mapping = {} - const lines = text.trim().split('\n') + const saved = []; + const mapping = {}; + const lines = text.trim().split('\n'); for (const line of lines) { - const parts = line.trim().split(':') + const parts = line.trim().split(':'); if (parts.length >= 2) { - const ssid = parts[0] - const connectionName = parts[1] + const ssid = parts[0]; + const connectionName = parts[1]; if (ssid && ssid.length > 0 && connectionName && connectionName.length > 0) { saved.push({ - "ssid": ssid, - "saved": true - }) - mapping[ssid] = connectionName + "ssid": ssid, + "saved": true + }); + mapping[ssid] = connectionName; } } } - root.savedConnections = saved - root.savedWifiNetworks = saved - root.ssidToConnectionName = mapping + root.savedConnections = saved; + root.savedWifiNetworks = saved; + root.ssidToConnectionName = mapping; - const updated = [...root.wifiNetworks] + const updated = [...root.wifiNetworks]; for (const network of updated) { - network.saved = saved.some(s => s.ssid === network.ssid) + network.saved = saved.some(s => s.ssid === network.ssid); } - root.wifiNetworks = updated + root.wifiNetworks = updated; } } } function connectToWifi(ssid, password = "", username = "") { if (root.isConnecting) { - return + return; } - root.isConnecting = true - root.connectingSSID = ssid - root.connectionError = "" - root.connectionStatus = "connecting" + root.isConnecting = true; + root.connectingSSID = ssid; + root.connectionError = ""; + root.connectionStatus = "connecting"; if (!password && root.ssidToConnectionName[ssid]) { - const connectionName = root.ssidToConnectionName[ssid] - wifiConnector.command = lowPriorityCmd.concat(["nmcli", "connection", "up", connectionName]) + const connectionName = root.ssidToConnectionName[ssid]; + wifiConnector.command = lowPriorityCmd.concat(["nmcli", "connection", "up", connectionName]); } else if (password) { - wifiConnector.command = lowPriorityCmd.concat(["nmcli", "dev", "wifi", "connect", ssid, "password", password]) + wifiConnector.command = lowPriorityCmd.concat(["nmcli", "dev", "wifi", "connect", ssid, "password", password]); } else { - wifiConnector.command = lowPriorityCmd.concat(["nmcli", "dev", "wifi", "connect", ssid]) + wifiConnector.command = lowPriorityCmd.concat(["nmcli", "dev", "wifi", "connect", ssid]); } - wifiConnector.running = true + wifiConnector.running = true; } Process { @@ -623,13 +621,13 @@ Singleton { stdout: StdioCollector { onStreamFinished: { if (text.includes("successfully")) { - wifiConnector.connectionSucceeded = true - ToastService.showInfo(`Connected to ${root.connectingSSID}`) - root.connectionError = "" - root.connectionStatus = "connected" + wifiConnector.connectionSucceeded = true; + ToastService.showInfo(`Connected to ${root.connectingSSID}`); + root.connectionError = ""; + root.connectionStatus = "connected"; if (root.userPreference === "wifi" || root.userPreference === "auto") { - setConnectionPriority("wifi") + setConnectionPriority("wifi"); } } } @@ -637,14 +635,14 @@ Singleton { stderr: StdioCollector { onStreamFinished: { - root.connectionError = text - root.lastConnectionError = text + root.connectionError = text; + root.lastConnectionError = text; if (!wifiConnector.connectionSucceeded && text.trim() !== "") { if (text.includes("password") || text.includes("authentication")) { - root.connectionStatus = "invalid_password" - root.passwordDialogShouldReopen = true + root.connectionStatus = "invalid_password"; + root.passwordDialogShouldReopen = true; } else { - root.connectionStatus = "failed" + root.connectionStatus = "failed"; } } } @@ -653,34 +651,34 @@ Singleton { onExited: exitCode => { if (exitCode === 0 || wifiConnector.connectionSucceeded) { if (!wifiConnector.connectionSucceeded) { - ToastService.showInfo(`Connected to ${root.connectingSSID}`) - root.connectionStatus = "connected" + ToastService.showInfo(`Connected to ${root.connectingSSID}`); + root.connectionStatus = "connected"; } } else { if (root.connectionStatus === "") { - root.connectionStatus = "failed" + root.connectionStatus = "failed"; } if (root.connectionStatus === "invalid_password") { - ToastService.showError(`Invalid password for ${root.connectingSSID}`) + ToastService.showError(`Invalid password for ${root.connectingSSID}`); } else { - ToastService.showError(`Failed to connect to ${root.connectingSSID}`) + ToastService.showError(`Failed to connect to ${root.connectingSSID}`); } } - wifiConnector.connectionSucceeded = false - root.isConnecting = false - root.connectingSSID = "" - doRefreshNetworkState() + wifiConnector.connectionSucceeded = false; + root.isConnecting = false; + root.connectingSSID = ""; + doRefreshNetworkState(); } } function disconnectWifi() { if (!root.wifiInterface) { - return + return; } - wifiDisconnector.command = lowPriorityCmd.concat(["nmcli", "dev", "disconnect", root.wifiInterface]) - wifiDisconnector.running = true + wifiDisconnector.command = lowPriorityCmd.concat(["nmcli", "dev", "disconnect", root.wifiInterface]); + wifiDisconnector.running = true; } Process { @@ -689,19 +687,19 @@ Singleton { onExited: exitCode => { if (exitCode === 0) { - ToastService.showInfo("Disconnected from WiFi") - root.currentWifiSSID = "" - root.connectionStatus = "" + ToastService.showInfo("Disconnected from WiFi"); + root.currentWifiSSID = ""; + root.connectionStatus = ""; } - doRefreshNetworkState() + doRefreshNetworkState(); } } function forgetWifiNetwork(ssid) { - root.forgetSSID = ssid - const connectionName = root.ssidToConnectionName[ssid] || ssid - networkForgetter.command = lowPriorityCmd.concat(["nmcli", "connection", "delete", connectionName]) - networkForgetter.running = true + root.forgetSSID = ssid; + const connectionName = root.ssidToConnectionName[ssid] || ssid; + networkForgetter.command = lowPriorityCmd.concat(["nmcli", "connection", "delete", connectionName]); + networkForgetter.running = true; } Process { @@ -710,39 +708,39 @@ Singleton { onExited: exitCode => { if (exitCode === 0) { - ToastService.showInfo(`Forgot network ${root.forgetSSID}`) + ToastService.showInfo(`Forgot network ${root.forgetSSID}`); - root.savedConnections = root.savedConnections.filter(s => s.ssid !== root.forgetSSID) - root.savedWifiNetworks = root.savedWifiNetworks.filter(s => s.ssid !== root.forgetSSID) + root.savedConnections = root.savedConnections.filter(s => s.ssid !== root.forgetSSID); + root.savedWifiNetworks = root.savedWifiNetworks.filter(s => s.ssid !== root.forgetSSID); - const updated = [...root.wifiNetworks] + const updated = [...root.wifiNetworks]; for (const network of updated) { if (network.ssid === root.forgetSSID) { - network.saved = false + network.saved = false; if (network.connected) { - network.connected = false - root.currentWifiSSID = "" + network.connected = false; + root.currentWifiSSID = ""; } } } - root.wifiNetworks = updated - root.networksUpdated() - doRefreshNetworkState() + root.wifiNetworks = updated; + root.networksUpdated(); + doRefreshNetworkState(); } - root.forgetSSID = "" + root.forgetSSID = ""; } } function toggleWifiRadio() { if (root.wifiToggling) { - return + return; } - root.wifiToggling = true - const targetState = root.wifiEnabled ? "off" : "on" - wifiRadioToggler.targetState = targetState - wifiRadioToggler.command = lowPriorityCmd.concat(["nmcli", "radio", "wifi", targetState]) - wifiRadioToggler.running = true + root.wifiToggling = true; + const targetState = root.wifiEnabled ? "off" : "on"; + wifiRadioToggler.targetState = targetState; + wifiRadioToggler.command = lowPriorityCmd.concat(["nmcli", "radio", "wifi", targetState]); + wifiRadioToggler.running = true; } Process { @@ -752,34 +750,34 @@ Singleton { property string targetState: "" onExited: exitCode => { - root.wifiToggling = false + root.wifiToggling = false; if (exitCode === 0) { - ToastService.showInfo(targetState === "on" ? "WiFi enabled" : "WiFi disabled") + ToastService.showInfo(targetState === "on" ? "WiFi enabled" : "WiFi disabled"); } - doRefreshNetworkState() + doRefreshNetworkState(); } } function setNetworkPreference(preference) { - root.userPreference = preference - root.changingPreference = true - root.targetPreference = preference - SettingsData.set("networkPreference", preference) + root.userPreference = preference; + root.changingPreference = true; + root.targetPreference = preference; + SettingsData.set("networkPreference", preference); if (preference === "wifi") { - setConnectionPriority("wifi") + setConnectionPriority("wifi"); } else if (preference === "ethernet") { - setConnectionPriority("ethernet") + setConnectionPriority("ethernet"); } } function setConnectionPriority(type) { if (type === "wifi") { - setRouteMetrics.command = lowPriorityCmd.concat(["bash", "-c", "nmcli -t -f NAME,TYPE connection show | grep 802-11-wireless | cut -d: -f1 | " + "xargs -I {} bash -c 'nmcli connection modify \"{}\" ipv4.route-metric 50 ipv6.route-metric 50'; " + "nmcli -t -f NAME,TYPE connection show | grep 802-3-ethernet | cut -d: -f1 | " + "xargs -I {} bash -c 'nmcli connection modify \"{}\" ipv4.route-metric 100 ipv6.route-metric 100'"]) + setRouteMetrics.command = lowPriorityCmd.concat(["bash", "-c", "nmcli -t -f NAME,TYPE connection show | grep 802-11-wireless | cut -d: -f1 | " + "xargs -I {} bash -c 'nmcli connection modify \"{}\" ipv4.route-metric 50 ipv6.route-metric 50'; " + "nmcli -t -f NAME,TYPE connection show | grep 802-3-ethernet | cut -d: -f1 | " + "xargs -I {} bash -c 'nmcli connection modify \"{}\" ipv4.route-metric 100 ipv6.route-metric 100'"]); } else if (type === "ethernet") { - setRouteMetrics.command = lowPriorityCmd.concat(["bash", "-c", "nmcli -t -f NAME,TYPE connection show | grep 802-3-ethernet | cut -d: -f1 | " + "xargs -I {} bash -c 'nmcli connection modify \"{}\" ipv4.route-metric 50 ipv6.route-metric 50'; " + "nmcli -t -f NAME,TYPE connection show | grep 802-11-wireless | cut -d: -f1 | " + "xargs -I {} bash -c 'nmcli connection modify \"{}\" ipv4.route-metric 100 ipv6.route-metric 100'"]) + setRouteMetrics.command = lowPriorityCmd.concat(["bash", "-c", "nmcli -t -f NAME,TYPE connection show | grep 802-3-ethernet | cut -d: -f1 | " + "xargs -I {} bash -c 'nmcli connection modify \"{}\" ipv4.route-metric 50 ipv6.route-metric 50'; " + "nmcli -t -f NAME,TYPE connection show | grep 802-11-wireless | cut -d: -f1 | " + "xargs -I {} bash -c 'nmcli connection modify \"{}\" ipv4.route-metric 100 ipv6.route-metric 100'"]); } - setRouteMetrics.running = true + setRouteMetrics.running = true; } Process { @@ -787,9 +785,9 @@ Singleton { running: false onExited: exitCode => { - console.log("Set route metrics process exited with code:", exitCode) + log.debug("Set route metrics process exited with code:", exitCode); if (exitCode === 0) { - restartConnections.running = true + restartConnections.running = true; } } } @@ -800,18 +798,17 @@ Singleton { running: false onExited: { - root.changingPreference = false - root.targetPreference = "" - doRefreshNetworkState() + root.changingPreference = false; + root.targetPreference = ""; + doRefreshNetworkState(); } } - function fetchNetworkInfo(ssid) { - root.networkInfoSSID = ssid - root.networkInfoLoading = true - root.networkInfoDetails = "Loading network information..." - wifiInfoFetcher.running = true + root.networkInfoSSID = ssid; + root.networkInfoLoading = true; + root.networkInfoDetails = "Loading network information..."; + wifiInfoFetcher.running = true; } Process { @@ -821,102 +818,102 @@ Singleton { stdout: StdioCollector { onStreamFinished: { - let details = "" + let details = ""; if (text.trim()) { - const lines = text.trim().split('\n') - const bands = [] + const lines = text.trim().split('\n'); + const bands = []; for (const line of lines) { - const parts = line.split(':') + const parts = line.split(':'); if (parts.length >= 11 && parts[0] === root.networkInfoSSID) { - const signal = parts[1] || "0" - const security = parts[2] || "Open" - const freq = parts[3] || "Unknown" - const rate = parts[4] || "Unknown" - const channel = parts[6] || "Unknown" - const isActive = parts[9] === "yes" - let colonCount = 0 - let bssidStart = -1 + const signal = parts[1] || "0"; + const security = parts[2] || "Open"; + const freq = parts[3] || "Unknown"; + const rate = parts[4] || "Unknown"; + const channel = parts[6] || "Unknown"; + const isActive = parts[9] === "yes"; + let colonCount = 0; + let bssidStart = -1; for (var i = 0; i < line.length; i++) { if (line[i] === ':') { - colonCount++ + colonCount++; if (colonCount === 10) { - bssidStart = i + 1 - break + bssidStart = i + 1; + break; } } } - const bssid = bssidStart >= 0 ? line.substring(bssidStart).replace(/\\:/g, ":") : "" + const bssid = bssidStart >= 0 ? line.substring(bssidStart).replace(/\\:/g, ":") : ""; - let band = "Unknown" - const freqNum = parseInt(freq) + let band = "Unknown"; + const freqNum = parseInt(freq); if (freqNum >= 2400 && freqNum <= 2500) { - band = "2.4 GHz" + band = "2.4 GHz"; } else if (freqNum >= 5000 && freqNum <= 6000) { - band = "5 GHz" + band = "5 GHz"; } else if (freqNum >= 6000) { - band = "6 GHz" + band = "6 GHz"; } bands.push({ - "band": band, - "freq": freq, - "channel": channel, - "signal": signal, - "rate": rate, - "security": security, - "isActive": isActive, - "bssid": bssid - }) + "band": band, + "freq": freq, + "channel": channel, + "signal": signal, + "rate": rate, + "security": security, + "isActive": isActive, + "bssid": bssid + }); } } if (bands.length > 0) { bands.sort((a, b) => { - if (a.isActive && !b.isActive) { - return -1 - } - if (!a.isActive && b.isActive) { - return 1 - } - return parseInt(b.signal) - parseInt(a.signal) - }) + if (a.isActive && !b.isActive) { + return -1; + } + if (!a.isActive && b.isActive) { + return 1; + } + return parseInt(b.signal) - parseInt(a.signal); + }); for (var i = 0; i < bands.length; i++) { - const b = bands[i] + const b = bands[i]; if (b.isActive) { - details += "● " + b.band + " (Connected) - " + b.signal + "%\\n" + details += "● " + b.band + " (Connected) - " + b.signal + "%\\n"; } else { - details += " " + b.band + " - " + b.signal + "%\\n" + details += " " + b.band + " - " + b.signal + "%\\n"; } - details += " Channel " + b.channel + " (" + b.freq + " MHz) • " + b.rate + " Mbit/s\\n" - details += " " + b.bssid + details += " Channel " + b.channel + " (" + b.freq + " MHz) • " + b.rate + " Mbit/s\\n"; + details += " " + b.bssid; if (i < bands.length - 1) { - details += "\\n\\n" + details += "\\n\\n"; } } } } if (details === "") { - details = "Network information not found or network not available." + details = "Network information not found or network not available."; } - root.networkInfoDetails = details - root.networkInfoLoading = false + root.networkInfoDetails = details; + root.networkInfoLoading = false; } } onExited: exitCode => { - root.networkInfoLoading = false + root.networkInfoLoading = false; if (exitCode !== 0) { - root.networkInfoDetails = "Failed to fetch network information" + root.networkInfoDetails = "Failed to fetch network information"; } } } function enableWifiDevice() { - wifiDeviceEnabler.running = true + wifiDeviceEnabler.running = true; } Process { @@ -926,25 +923,25 @@ Singleton { onExited: exitCode => { if (exitCode === 0) { - ToastService.showInfo("WiFi enabled") + ToastService.showInfo("WiFi enabled"); } else { - ToastService.showError("Failed to enable WiFi") + ToastService.showError("Failed to enable WiFi"); } - doRefreshNetworkState() + doRefreshNetworkState(); } } function connectToWifiAndSetPreference(ssid, password) { - connectToWifi(ssid, password) - setNetworkPreference("wifi") + connectToWifi(ssid, password); + setNetworkPreference("wifi"); } function toggleNetworkConnection(type) { if (type === "ethernet") { if (root.networkStatus === "ethernet") { - ethernetDisconnector.running = true + ethernetDisconnector.running = true; } else { - ethernetConnector.running = true + ethernetConnector.running = true; } } } @@ -955,7 +952,7 @@ Singleton { running: false onExited: function (exitCode) { - doRefreshNetworkState() + doRefreshNetworkState(); } } @@ -965,14 +962,14 @@ Singleton { running: false onExited: function (exitCode) { - doRefreshNetworkState() + doRefreshNetworkState(); } } function getNetworkInfo(ssid) { - const network = root.wifiNetworks.find(n => n.ssid === ssid) + const network = root.wifiNetworks.find(n => n.ssid === ssid); if (!network) { - return null + return null; } return { @@ -982,6 +979,6 @@ Singleton { "saved": network.saved, "connected": network.connected, "bssid": network.bssid - } + }; } } diff --git a/quickshell/Services/LocationService.qml b/quickshell/Services/LocationService.qml index 0fde5870..cba8bec3 100644 --- a/quickshell/Services/LocationService.qml +++ b/quickshell/Services/LocationService.qml @@ -3,8 +3,6 @@ pragma ComponentBehavior: Bound import QtQuick import Quickshell -import Quickshell.Io -import qs.Common Singleton { id: root diff --git a/quickshell/Services/Log.qml b/quickshell/Services/Log.qml new file mode 100644 index 00000000..7a2fcba4 --- /dev/null +++ b/quickshell/Services/Log.qml @@ -0,0 +1,226 @@ +pragma Singleton +pragma ComponentBehavior: Bound + +import QtQuick +import Quickshell +import Quickshell.Io + +Singleton { + id: root + + enum Level { + Debug, + Info, + Warn, + Error, + Fatal + } + + readonly property int level: _parseLevel(Quickshell.env("DMS_LOG_LEVEL")) + readonly property string levelName: _levelName(level) + + readonly property string _logFilePath: Quickshell.env("DMS_LOG_FILE") || "" + readonly property bool _useColor: !Quickshell.env("NO_COLOR") && Quickshell.env("DMS_LOG_NO_COLOR") !== "1" + + function scoped(module) { + return { + debug: function () { + root._emit(Log.Level.Debug, module, arguments); + }, + info: function () { + root._emit(Log.Level.Info, module, arguments); + }, + warn: function () { + root._emit(Log.Level.Warn, module, arguments); + }, + error: function () { + root._emit(Log.Level.Error, module, arguments); + }, + fatal: function () { + root._emit(Log.Level.Fatal, module, arguments); + } + }; + } + + function debug() { + _emit(Log.Level.Debug, "", arguments); + } + function info() { + _emit(Log.Level.Info, "", arguments); + } + function warn() { + _emit(Log.Level.Warn, "", arguments); + } + function error() { + _emit(Log.Level.Error, "", arguments); + } + function fatal() { + _emit(Log.Level.Fatal, "", arguments); + } + + function callStack() { + const trace = _captureStack(0).split("\n").map(l => l.trim()).filter(l => l.length > 0); + _emit(Log.Level.Info, "Debug", ["--------------------------"]); + _emit(Log.Level.Info, "Debug", ["Current call stack"]); + for (const line of trace) + _emit(Log.Level.Info, "Debug", ["- " + line]); + _emit(Log.Level.Info, "Debug", ["--------------------------"]); + } + + function _parseLevel(name) { + switch ((name || "").toLowerCase()) { + case "debug": + return Log.Level.Debug; + case "warn": + case "warning": + return Log.Level.Warn; + case "error": + return Log.Level.Error; + case "fatal": + return Log.Level.Fatal; + default: + return Log.Level.Info; + } + } + + function _levelName(lvl) { + switch (lvl) { + case Log.Level.Debug: + return "debug"; + case Log.Level.Info: + return "info"; + case Log.Level.Warn: + return "warn"; + case Log.Level.Error: + return "error"; + case Log.Level.Fatal: + return "fatal"; + } + return "info"; + } + + function _levelTag(lvl, color) { + let tag, ansi; + switch (lvl) { + case Log.Level.Fatal: + tag = " FATAL"; + ansi = "\x1b[31m"; + break; + case Log.Level.Error: + tag = " ERROR"; + ansi = "\x1b[91m"; + break; + case Log.Level.Warn: + tag = " WARN"; + ansi = "\x1b[33m"; + break; + case Log.Level.Info: + tag = " INFO"; + ansi = "\x1b[32m"; + break; + case Log.Level.Debug: + tag = " DEBUG"; + ansi = "\x1b[34m"; + break; + default: + return " INFO"; + } + if (!color) + return tag; + return ansi + tag + "\x1b[0m"; + } + + function _stringify(v) { + if (v === null) + return "null"; + if (v === undefined) + return "undefined"; + if (typeof v === "string") + return v; + if (v instanceof Error) + return v.toString(); + try { + return JSON.stringify(v); + } catch (e) { + return String(v); + } + } + + function _captureStack(skip) { + try { + throw new Error(); + } catch (e) { + const lines = (e.stack || "").split("\n"); + return lines.slice(1 + (skip || 0)).join("\n"); + } + } + + function _callerLocation() { + const stack = _captureStack(2); + const lines = stack.split("\n"); + for (const line of lines) { + const m = line.match(/([^/@\s]+\.qml):(\d+)/); + if (!m) + continue; + if (m[1] === "Log.qml") + continue; + return { + file: m[1], + line: m[2] + }; + } + return null; + } + + function _emit(lvl, module, args) { + if (lvl < root.level) + return; + + const argList = Array.from(args); + const loc = _callerLocation(); + const msg = argList.map(_stringify).join(" "); + + let tag; + if (module && loc && loc.file === module + ".qml") + tag = "[" + module + ":" + loc.line + "] "; + else if (module && loc) + tag = "[" + module + "] (" + loc.file + ":" + loc.line + ") "; + else if (module) + tag = "[" + module + "] "; + else if (loc) + tag = "(" + loc.file + ":" + loc.line + ") "; + else + tag = ""; + + const body = tag + msg; + + switch (lvl) { + case Log.Level.Debug: + console.debug(body); + break; + case Log.Level.Info: + console.info(body); + break; + case Log.Level.Warn: + console.warn(body); + break; + case Log.Level.Error: + case Log.Level.Fatal: + console.error(body); + break; + } + + if (root._logFilePath && fileTee.running) + fileTee.write(_levelTag(lvl, false) + " qml: " + body + "\n"); + + if (lvl === Log.Level.Fatal) + Qt.callLater(() => Qt.exit(1)); + } + + Process { + id: fileTee + command: ["sh", "-c", "exec tee -a \"$0\" >/dev/null", root._logFilePath] + stdinEnabled: true + running: root._logFilePath.length > 0 + } +} diff --git a/quickshell/Services/MultimediaService.qml b/quickshell/Services/MultimediaService.qml index f570c72a..1f4f0372 100644 --- a/quickshell/Services/MultimediaService.qml +++ b/quickshell/Services/MultimediaService.qml @@ -6,6 +6,7 @@ import Quickshell Singleton { id: root + readonly property var log: Log.scoped("MultimediaService") property bool available: false @@ -14,6 +15,7 @@ Singleton { const testObj = Qt.createQmlObject(` import QtQuick import QtMultimedia +import qs.Services Item {} `, root, "MultimediaService.TestComponent"); if (testObj) { @@ -29,7 +31,7 @@ Singleton { Component.onCompleted: { if (!detectAvailability()) { - console.warn("MultimediaService: QtMultimedia not available"); + log.warn("QtMultimedia not available"); } } } diff --git a/quickshell/Services/MuxService.qml b/quickshell/Services/MuxService.qml index 59737f94..04347cea 100644 --- a/quickshell/Services/MuxService.qml +++ b/quickshell/Services/MuxService.qml @@ -5,9 +5,11 @@ import QtQuick import Quickshell import Quickshell.Io import qs.Common +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("MuxService") property var sessions: [] property bool loading: false @@ -20,46 +22,50 @@ Singleton { readonly property string displayName: muxType === "zellij" ? "Zellij" : "Tmux" readonly property var terminalFlags: ({ - "ghostty": ["-e"], - "kitty": ["-e"], - "alacritty": ["-e"], - "foot": [], - "wezterm": ["start", "--"], - "gnome-terminal": ["--"], - "xterm": ["-e"], - "konsole": ["-e"], - "st": ["-e"], - "terminator": ["-e"], - "xfce4-terminal": ["-e"] - }) + "ghostty": ["-e"], + "kitty": ["-e"], + "alacritty": ["-e"], + "foot": [], + "wezterm": ["start", "--"], + "gnome-terminal": ["--"], + "xterm": ["-e"], + "konsole": ["-e"], + "st": ["-e"], + "terminator": ["-e"], + "xfce4-terminal": ["-e"] + }) function getTerminalFlag(terminal) { - return terminalFlags[terminal] ?? ["-e"] + return terminalFlags[terminal] ?? ["-e"]; } readonly property string terminal: SessionData.resolveTerminal() || "ghostty" function _terminalPrefix() { - return [terminal].concat(getTerminalFlag(terminal)) + return [terminal].concat(getTerminalFlag(terminal)); } Process { id: tmuxCheckProcess command: ["which", "tmux"] running: false - onExited: (code) => { root.tmuxAvailable = (code === 0) } + onExited: code => { + root.tmuxAvailable = (code === 0); + } } Process { id: zellijCheckProcess command: ["which", "zellij"] running: false - onExited: (code) => { root.zellijAvailable = (code === 0) } + onExited: code => { + root.zellijAvailable = (code === 0); + } } function checkAvailability() { - tmuxCheckProcess.running = true - zellijCheckProcess.running = true + tmuxCheckProcess.running = true; + zellijCheckProcess.running = true; } Component.onCompleted: checkAvailability() @@ -72,141 +78,139 @@ Singleton { onStreamFinished: { try { if (root.muxType === "zellij") - root._parseZellijSessions(text) + root._parseZellijSessions(text); else - root._parseTmuxSessions(text) + root._parseTmuxSessions(text); } catch (e) { - console.error("[MuxService] Error parsing sessions:", e) - root.sessions = [] + log.error("Error parsing sessions:", e); + root.sessions = []; } - root.loading = false + root.loading = false; } } stderr: SplitParser { - onRead: (line) => { + onRead: line => { if (line.trim()) - console.error("[MuxService] stderr:", line) + log.error("stderr:", line); } } - onExited: (code) => { + onExited: code => { if (code !== 0 && code !== 1) { - console.warn("[MuxService] Process exited with code:", code) - root.sessions = [] + log.warn("Process exited with code:", code); + root.sessions = []; } - root.loading = false + root.loading = false; } } function refreshSessions() { if (!root.currentMuxAvailable) { - root.sessions = [] - return + root.sessions = []; + return; } - root.loading = true + root.loading = true; if (listProcess.running) - listProcess.running = false + listProcess.running = false; if (root.muxType === "zellij") - listProcess.command = ["zellij", "list-sessions", "--no-formatting"] + listProcess.command = ["zellij", "list-sessions", "--no-formatting"]; else - listProcess.command = ["tmux", "list-sessions", "-F", "#{session_name}|#{session_windows}|#{session_attached}"] + listProcess.command = ["tmux", "list-sessions", "-F", "#{session_name}|#{session_windows}|#{session_attached}"]; Qt.callLater(function () { - listProcess.running = true - }) + listProcess.running = true; + }); } function _isSessionExcluded(name) { - var filter = SettingsData.muxSessionFilter.trim() + var filter = SettingsData.muxSessionFilter.trim(); if (filter.length === 0) - return false - var parts = filter.split(",") + return false; + var parts = filter.split(","); for (var i = 0; i < parts.length; i++) { - var pattern = parts[i].trim() + var pattern = parts[i].trim(); if (pattern.length === 0) - continue + continue; if (pattern.startsWith("/") && pattern.endsWith("/") && pattern.length > 2) { try { - var re = new RegExp(pattern.slice(1, -1)) + var re = new RegExp(pattern.slice(1, -1)); if (re.test(name)) - return true + return true; } catch (e) {} } else { if (name.toLowerCase() === pattern.toLowerCase()) - return true + return true; } } - return false + return false; } function _parseTmuxSessions(output) { - var sessionList = [] - var lines = output.trim().split('\n') + var sessionList = []; + var lines = output.trim().split('\n'); for (var i = 0; i < lines.length; i++) { - var line = lines[i].trim() + var line = lines[i].trim(); if (line.length === 0) - continue - - var parts = line.split('|') + continue; + var parts = line.split('|'); if (parts.length >= 3 && !_isSessionExcluded(parts[0])) { sessionList.push({ name: parts[0], windows: parts[1], attached: parts[2] === "1" - }) + }); } } - root.sessions = sessionList + root.sessions = sessionList; } function _parseZellijSessions(output) { - var sessionList = [] - var lines = output.trim().split('\n') + var sessionList = []; + var lines = output.trim().split('\n'); for (var i = 0; i < lines.length; i++) { - var line = lines[i].trim() + var line = lines[i].trim(); if (line.length === 0) - continue - - var exited = line.includes("(EXITED") - var bracketIdx = line.indexOf(" [") - var name = (bracketIdx > 0 ? line.substring(0, bracketIdx) : line).trim() + continue; + var exited = line.includes("(EXITED"); + var bracketIdx = line.indexOf(" ["); + var name = (bracketIdx > 0 ? line.substring(0, bracketIdx) : line).trim(); if (!_isSessionExcluded(name)) { sessionList.push({ name: name, windows: "N/A", attached: !exited - }) + }); } } - root.sessions = sessionList + root.sessions = sessionList; } function attachToSession(name) { if (SettingsData.muxUseCustomCommand && SettingsData.muxCustomCommand) { - Quickshell.execDetached([Paths.expandTilde(SettingsData.muxCustomCommand), name]) + Quickshell.execDetached([Paths.expandTilde(SettingsData.muxCustomCommand), name]); } else if (root.muxType === "zellij") { - Quickshell.execDetached(_terminalPrefix().concat(["zellij", "attach", name])) + Quickshell.execDetached(_terminalPrefix().concat(["zellij", "attach", name])); } else { - Quickshell.execDetached(_terminalPrefix().concat(["tmux", "attach", "-t", name])) + Quickshell.execDetached(_terminalPrefix().concat(["tmux", "attach", "-t", name])); } } function createSession(name) { if (SettingsData.muxUseCustomCommand && SettingsData.muxCustomCommand) { - Quickshell.execDetached([Paths.expandTilde(SettingsData.muxCustomCommand), name]) + Quickshell.execDetached([Paths.expandTilde(SettingsData.muxCustomCommand), name]); } else if (root.muxType === "zellij") { - Quickshell.execDetached(_terminalPrefix().concat(["zellij", "-s", name])) + Quickshell.execDetached(_terminalPrefix().concat(["zellij", "-s", name])); } else { - Quickshell.execDetached(_terminalPrefix().concat(["tmux", "new-session", "-s", name])) + Quickshell.execDetached(_terminalPrefix().concat(["tmux", "new-session", "-s", name])); } } @@ -214,17 +218,17 @@ Singleton { function renameSession(oldName, newName) { if (root.muxType === "zellij") - return - Quickshell.execDetached(["tmux", "rename-session", "-t", oldName, newName]) - Qt.callLater(refreshSessions) + return; + Quickshell.execDetached(["tmux", "rename-session", "-t", oldName, newName]); + Qt.callLater(refreshSessions); } function killSession(name) { if (root.muxType === "zellij") { - Quickshell.execDetached(["zellij", "kill-session", name]) + Quickshell.execDetached(["zellij", "kill-session", name]); } else { - Quickshell.execDetached(["tmux", "kill-session", "-t", name]) + Quickshell.execDetached(["tmux", "kill-session", "-t", name]); } - Qt.callLater(refreshSessions) + Qt.callLater(refreshSessions); } } diff --git a/quickshell/Services/NetworkService.qml b/quickshell/Services/NetworkService.qml index 38383d28..7b988dcc 100644 --- a/quickshell/Services/NetworkService.qml +++ b/quickshell/Services/NetworkService.qml @@ -3,9 +3,11 @@ pragma ComponentBehavior: Bound import QtQuick import Quickshell +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("NetworkService") property bool networkAvailable: activeService !== null property string backend: activeService?.backend ?? "" @@ -97,12 +99,12 @@ Singleton { readonly property string socketPath: Quickshell.env("DMS_SOCKET") Component.onCompleted: { - console.info("NetworkService: Initializing..."); + log.info("Initializing..."); if (!socketPath || socketPath.length === 0) { - console.info("NetworkService: DMS_SOCKET not set, using LegacyNetworkService"); + log.info("DMS_SOCKET not set, using LegacyNetworkService"); useLegacyService(); } else { - console.log("NetworkService: DMS_SOCKET found, waiting for capabilities..."); + log.debug("DMS_SOCKET found, waiting for capabilities..."); } } @@ -111,13 +113,13 @@ Singleton { function onNetworkAvailableChanged() { if (!activeService && DMSNetworkService.networkAvailable) { - console.info("NetworkService: Network capability detected, using DMSNetworkService"); + log.info("Network capability detected, using DMSNetworkService"); activeService = DMSNetworkService; usingLegacy = false; - console.info("NetworkService: Switched to DMSNetworkService, networkAvailable:", networkAvailable); + log.info("Switched to DMSNetworkService, networkAvailable:", networkAvailable); connectSignals(); } else if (!activeService && !DMSNetworkService.networkAvailable && socketPath && socketPath.length > 0) { - console.info("NetworkService: Network capability not available in DMS, using LegacyNetworkService"); + log.info("Network capability not available in DMS, using LegacyNetworkService"); useLegacyService(); } } @@ -126,7 +128,7 @@ Singleton { function useLegacyService() { activeService = LegacyNetworkService; usingLegacy = true; - console.info("NetworkService: Switched to LegacyNetworkService, networkAvailable:", networkAvailable); + log.info("Switched to LegacyNetworkService, networkAvailable:", networkAvailable); if (LegacyNetworkService.activate) { LegacyNetworkService.activate(); } diff --git a/quickshell/Services/NiriService.qml b/quickshell/Services/NiriService.qml index 49748eb9..1963be0d 100644 --- a/quickshell/Services/NiriService.qml +++ b/quickshell/Services/NiriService.qml @@ -6,9 +6,11 @@ import QtQuick import Quickshell import Quickshell.Io import qs.Common +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("NiriService") readonly property string socketPath: Quickshell.env("NIRI_SOCKET") @@ -118,10 +120,10 @@ Singleton { onExited: exitCode => { if (exitCode === 0) { - console.info("NiriService: Generated layout config at", configPath); + log.info("Generated layout config at", configPath); return; } - console.warn("NiriService: Failed to write layout config, exit code:", exitCode); + log.warn("Failed to write layout config, exit code:", exitCode); } } @@ -132,10 +134,10 @@ Singleton { onExited: exitCode => { if (exitCode === 0) { - console.info("NiriService: Generated alttab config at", alttabPath); + log.info("Generated alttab config at", alttabPath); return; } - console.warn("NiriService: Failed to write alttab config, exit code:", exitCode); + log.warn("Failed to write alttab config, exit code:", exitCode); } } @@ -145,10 +147,10 @@ Singleton { onExited: exitCode => { if (exitCode === 0) { - console.info("NiriService: Generated wpblur config at", blurrulePath); + log.info("Generated wpblur config at", blurrulePath); return; } - console.warn("NiriService: Failed to write wpblur config, exit code:", exitCode); + log.warn("Failed to write wpblur config, exit code:", exitCode); } } @@ -159,10 +161,10 @@ Singleton { onExited: exitCode => { if (exitCode === 0) { - console.info("NiriService: Generated cursor config at", cursorPath); + log.info("Generated cursor config at", cursorPath); return; } - console.warn("NiriService: Failed to write cursor config, exit code:", exitCode); + log.warn("Failed to write cursor config, exit code:", exitCode); } } @@ -184,7 +186,7 @@ Singleton { const event = JSON.parse(line); handleNiriEvent(event); } catch (e) { - console.warn("NiriService: Failed to parse event:", line, e); + log.warn("Failed to parse event:", line, e); } } } @@ -201,19 +203,19 @@ Singleton { return; Proc.runCommand("niri-fetch-outputs", ["niri", "msg", "-j", "outputs"], (output, exitCode) => { if (exitCode !== 0) { - console.warn("NiriService: Failed to fetch outputs, exit code:", exitCode); + log.warn("Failed to fetch outputs, exit code:", exitCode); return; } try { const outputsData = JSON.parse(output); outputs = outputsData; - console.info("NiriService: Loaded", Object.keys(outputsData).length, "outputs"); + log.info("Loaded", Object.keys(outputsData).length, "outputs"); updateDisplayScales(); if (windows.length > 0) { windows = sortWindowsByLayout(windows); } } catch (e) { - console.warn("NiriService: Failed to parse outputs:", e); + log.warn("Failed to parse outputs:", e); } }); } @@ -1076,7 +1078,7 @@ Singleton { } function doGenerateNiriLayoutConfig() { - console.log("NiriService: Generating layout config..."); + log.debug("Generating layout config..."); const defaultRadius = typeof SettingsData !== "undefined" ? SettingsData.cornerRadius : 12; const defaultGaps = typeof SettingsData !== "undefined" ? Math.max(4, (SettingsData.barConfigs[0]?.spacing ?? 4)) : 4; @@ -1136,7 +1138,7 @@ Singleton { const path = niriDmsDir + "/" + name + ".kdl"; Proc.runCommand("niri-ensure-" + name, ["sh", "-c", `mkdir -p "${niriDmsDir}" && [ ! -f "${path}" ] && touch "${path}" || true`], (output, exitCode) => { if (exitCode !== 0) - console.warn("NiriService: Failed to ensure " + name + ".kdl, exit code:", exitCode); + log.warn("Failed to ensure " + name + ".kdl, exit code:", exitCode); }); } @@ -1144,7 +1146,7 @@ Singleton { } function generateNiriBlurrule() { - console.log("NiriService: Generating wpblur config..."); + log.debug("Generating wpblur config..."); const configDir = Paths.strip(StandardPaths.writableLocation(StandardPaths.ConfigLocation)); const niriDmsDir = configDir + "/niri/dms"; @@ -1160,7 +1162,7 @@ Singleton { if (!CompositorService.isNiri) return; - console.log("NiriService: Generating cursor config..."); + log.debug("Generating cursor config..."); const configDir = Paths.strip(StandardPaths.writableLocation(StandardPaths.ConfigLocation)); const niriDmsDir = configDir + "/niri/dms"; @@ -1275,12 +1277,12 @@ Singleton { const fullCommand = commands.join(" && "); Proc.runCommand("niri-output-config", ["sh", "-c", fullCommand], (output, exitCode) => { if (exitCode !== 0) { - console.warn("NiriService: Failed to apply output config:", output); + log.warn("Failed to apply output config:", output); if (callback) callback(false, output); return; } - console.info("NiriService: Applied output config for", outputName); + log.info("Applied output config for", outputName); fetchOutputs(); if (callback) callback(true, "Success"); @@ -1369,10 +1371,10 @@ Singleton { Proc.runCommand("niri-write-outputs", ["sh", "-c", `mkdir -p "${niriDmsDir}" && cat > "${outputsPath}" << 'EOF'\n${kdlContent}EOF`], (output, exitCode) => { if (exitCode !== 0) { - console.warn("NiriService: Failed to write outputs config:", output); + log.warn("Failed to write outputs config:", output); return; } - console.info("NiriService: Generated outputs config at", outputsPath); + log.info("Generated outputs config at", outputsPath); }); } diff --git a/quickshell/Services/NotepadStorageService.qml b/quickshell/Services/NotepadStorageService.qml index 3a6257a4..fc14699e 100644 --- a/quickshell/Services/NotepadStorageService.qml +++ b/quickshell/Services/NotepadStorageService.qml @@ -6,9 +6,11 @@ import QtCore import Quickshell import Quickshell.Io import qs.Common +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("NotepadStorageService") property int refCount: 0 @@ -39,7 +41,7 @@ Singleton { root.metadataLoaded = true root.validateTabs() } catch(e) { - console.warn("Failed to parse notepad metadata:", e) + log.warn("Failed to parse notepad metadata:", e) root.createDefaultTab() } } @@ -148,7 +150,7 @@ Singleton { callback: callback }) } else { - console.warn("Tab file does not exist:", fullPath) + log.warn("Tab file does not exist:", fullPath) callback("") } } @@ -389,7 +391,7 @@ Singleton { } onSaveFailed: { - console.error("Failed to save tab content") + log.error("Failed to save tab content") if (creationCallback) { creationCallback() } diff --git a/quickshell/Services/NotificationService.qml b/quickshell/Services/NotificationService.qml index 0615b580..1b6d85c4 100644 --- a/quickshell/Services/NotificationService.qml +++ b/quickshell/Services/NotificationService.qml @@ -6,10 +6,12 @@ import Quickshell import Quickshell.Io import Quickshell.Services.Notifications import qs.Common +import qs.Services import "../Common/markdown2html.js" as Markdown2Html Singleton { id: root + readonly property var log: Log.scoped("NotificationService") readonly property list notifications: [] readonly property list allWrappers: [] @@ -153,7 +155,7 @@ Singleton { historyAdapter.notifications = historyList; historyFileView.writeAdapter(); } catch (e) { - console.warn("NotificationService: save history failed:", e); + log.warn("save history failed:", e); } } @@ -203,7 +205,7 @@ Singleton { if ((maxAgeMs > 0 && loaded.length !== (historyAdapter.notifications || []).length) || needsRewrite) saveHistory(); } catch (e) { - console.warn("NotificationService: load history failed:", e); + log.warn("load history failed:", e); historyLoaded = true; } } @@ -403,7 +405,7 @@ Singleton { try { return new RegExp(pattern, "i").test(value); } catch (e) { - console.warn("NotificationService: invalid notification rule regex:", pattern); + log.warn("invalid notification rule regex:", pattern); return false; } } diff --git a/quickshell/Services/PluginService.qml b/quickshell/Services/PluginService.qml index 1a58d98a..1f9efa0e 100644 --- a/quickshell/Services/PluginService.qml +++ b/quickshell/Services/PluginService.qml @@ -10,6 +10,7 @@ import qs.Services Singleton { id: root + readonly property var log: Log.scoped("PluginService") property var availablePlugins: ({}) property var loadedPlugins: ({}) @@ -167,13 +168,13 @@ Singleton { const manifest = JSON.parse(raw) root._onManifestParsed(absPath, manifest, "${sourceTag}", ${mtimeEpochMs}) } catch (e) { - console.error("PluginService: bad manifest", absPath, e.message) + log.error("bad manifest", absPath, e.message) knownManifests[absPath] = { mtime: ${mtimeEpochMs}, source: "${sourceTag}", bad: true } } fv.destroy() } onLoadFailed: (err) => { - console.warn("PluginService: manifest load failed", absPath, err) + log.warn("manifest load failed", absPath, err) fv.destroy() } } @@ -186,7 +187,7 @@ Singleton { function _onManifestParsed(absPath, manifest, sourceTag, mtimeEpochMs) { if (!manifest || !manifest.id || !manifest.name || !manifest.component) { - console.error("PluginService: invalid manifest fields:", absPath); + log.error("invalid manifest fields:", absPath); knownManifests[absPath] = { mtime: mtimeEpochMs, source: sourceTag, @@ -269,7 +270,7 @@ Singleton { function loadPlugin(pluginId, bustCache) { const plugin = availablePlugins[pluginId]; if (!plugin) { - console.error("PluginService: Plugin not found:", pluginId); + log.error("Plugin not found:", pluginId); pluginLoadFailed(pluginId, "Plugin not found"); return false; } @@ -296,7 +297,7 @@ Singleton { url += "?t=" + Date.now(); const comp = Qt.createComponent(url, Component.PreferSynchronous); if (comp.status === Component.Error) { - console.error("PluginService: component error", pluginId, comp.errorString()); + log.error("component error", pluginId, comp.errorString()); pluginLoadFailed(pluginId, comp.errorString()); return false; } @@ -310,7 +311,7 @@ Singleton { "pluginService": root }); if (!instance) { - console.error("PluginService: failed to instantiate plugin:", pluginId, comp.errorString()); + log.error("failed to instantiate plugin:", pluginId, comp.errorString()); pluginLoadFailed(pluginId, comp.errorString()); return false; } @@ -339,7 +340,7 @@ Singleton { pluginLoaded(pluginId); return true; } catch (e) { - console.error("PluginService: Error loading plugin:", pluginId, e.message); + log.error("Error loading plugin:", pluginId, e.message); pluginLoadFailed(pluginId, e.message); return false; } @@ -348,7 +349,7 @@ Singleton { function unloadPlugin(pluginId) { const plugin = loadedPlugins[pluginId]; if (!plugin) { - console.warn("PluginService: Plugin not loaded:", pluginId); + log.warn("Plugin not loaded:", pluginId); return false; } @@ -392,7 +393,7 @@ Singleton { pluginUnloaded(pluginId); return true; } catch (error) { - console.error("PluginService: Error unloading plugin:", pluginId, "Error:", error.message); + log.error("Error unloading plugin:", pluginId, "Error:", error.message); return false; } } @@ -705,7 +706,7 @@ Singleton { fv.setText(content); }); } catch (e) { - console.warn("PluginService: Failed to write state for", pluginId, e.message); + log.warn("Failed to write state for", pluginId, e.message); } } @@ -753,14 +754,14 @@ Singleton { process.command = ["mkdir", "-p", pluginDirectory]; process.exited.connect(function (exitCode) { if (exitCode !== 0) { - console.error("PluginService: Failed to create plugin directory, exit code:", exitCode); + log.error("Failed to create plugin directory, exit code:", exitCode); } process.destroy(); }); process.running = true; return true; } else { - console.error("PluginService: Failed to create mkdir process"); + log.error("Failed to create mkdir process"); return false; } } diff --git a/quickshell/Services/PolkitService.qml b/quickshell/Services/PolkitService.qml index 5238d042..0762596a 100644 --- a/quickshell/Services/PolkitService.qml +++ b/quickshell/Services/PolkitService.qml @@ -6,6 +6,7 @@ import Quickshell Singleton { id: root + readonly property var log: Log.scoped("PolkitService") readonly property bool disablePolkitIntegration: Quickshell.env("DMS_DISABLE_POLKIT") === "1" @@ -17,6 +18,7 @@ Singleton { const qmlString = ` import QtQuick import Quickshell.Services.Polkit +import qs.Services PolkitAgent { } @@ -24,10 +26,10 @@ Singleton { agent = Qt.createQmlObject(qmlString, root, "PolkitService.Agent") polkitAvailable = true - console.info("PolkitService: Initialized successfully") + log.info("Initialized successfully") } catch (e) { polkitAvailable = false - console.warn("PolkitService: Polkit not available - authentication prompts disabled. This requires a newer version of Quickshell.") + log.warn("Polkit not available - authentication prompts disabled. This requires a newer version of Quickshell.") } } diff --git a/quickshell/Services/PortalService.qml b/quickshell/Services/PortalService.qml index 73c0a9f9..d3c16666 100644 --- a/quickshell/Services/PortalService.qml +++ b/quickshell/Services/PortalService.qml @@ -5,9 +5,11 @@ import QtQuick import Quickshell import Quickshell.Io import qs.Common +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("PortalService") property bool accountsServiceAvailable: false property string systemProfileImage: "" @@ -127,7 +129,7 @@ Singleton { "iconTheme": themeName }, response => { if (response.error) { - console.warn("PortalService: Failed to set icon theme:", response.error); + log.warn("Failed to set icon theme:", response.error); } }); } @@ -139,7 +141,7 @@ Singleton { "path": imagePath || "" }, response => { if (response.error) { - console.warn("PortalService: Failed to set icon file:", response.error); + log.warn("Failed to set icon file:", response.error); const errorMsg = response.error.toString(); let userMessage = I18n.tr("Failed to set profile image"); @@ -169,7 +171,7 @@ Singleton { if (socketPath && socketPath.length > 0) { checkDMSCapabilities(); } else { - console.info("PortalService: DMS_SOCKET not set"); + log.info("DMS_SOCKET not set"); } colorSchemeDetector.running = true; } @@ -207,7 +209,7 @@ Singleton { checkAccountsService(); checkSettingsPortal(); } else { - console.info("PortalService: freedesktop capability not available in DMS"); + log.info("freedesktop capability not available in DMS"); } } diff --git a/quickshell/Services/SessionService.qml b/quickshell/Services/SessionService.qml index 6b008f5a..74473499 100644 --- a/quickshell/Services/SessionService.qml +++ b/quickshell/Services/SessionService.qml @@ -8,9 +8,11 @@ import Quickshell.Hyprland import Quickshell.I3 import Quickshell.Wayland import qs.Common +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("SessionService") property bool hasUwsm: false property bool isElogind: false @@ -64,15 +66,15 @@ Singleton { detectHibernateProcess.running = true; detectPrimeRunProcess.running = true; detectWtypeProcess.running = true; - console.info("SessionService: Native inhibitor available:", nativeInhibitorAvailable); + log.info("Native inhibitor available:", nativeInhibitorAvailable); if (!SettingsData.loginctlLockIntegration) { - console.log("SessionService: loginctl lock integration disabled by user"); + log.debug("loginctl lock integration disabled by user"); return; } if (socketPath && socketPath.length > 0) { checkDMSCapabilities(); } else { - console.log("SessionService: DMS_SOCKET not set"); + log.debug("DMS_SOCKET not set"); } } } @@ -93,7 +95,7 @@ Singleton { command: ["sh", "-c", "ps -eo comm= | grep -E '^(elogind|elogind-daemon)$'"] onExited: function (exitCode) { - console.log("SessionService: Elogind detection exited with code", exitCode); + log.debug("Elogind detection exited with code", exitCode); isElogind = (exitCode === 0); } } @@ -396,7 +398,7 @@ Singleton { if (idleInhibited) { return; } - console.log("SessionService: Enabling idle inhibit (native:", nativeInhibitorAvailable, ")"); + log.debug("Enabling idle inhibit (native:", nativeInhibitorAvailable, ")"); idleInhibited = true; inhibitorChanged(); } @@ -405,7 +407,7 @@ Singleton { if (!idleInhibited) { return; } - console.log("SessionService: Disabling idle inhibit (native:", nativeInhibitorAvailable, ")"); + log.debug("Disabling idle inhibit (native:", nativeInhibitorAvailable, ")"); idleInhibited = false; inhibitorChanged(); } @@ -441,19 +443,19 @@ Singleton { return ["true"]; } - console.log("SessionService: Starting systemd/elogind inhibit process"); + log.debug("Starting systemd/elogind inhibit process"); return [isElogind ? "elogind-inhibit" : "systemd-inhibit", "--what=idle", "--who=quickshell", `--why=${inhibitReason}`, "--mode=block", "sleep", "infinity"]; } running: idleInhibited && !nativeInhibitorAvailable onRunningChanged: { - console.log("SessionService: Inhibit process running:", running, "(native:", nativeInhibitorAvailable, ")"); + log.debug("Inhibit process running:", running, "(native:", nativeInhibitorAvailable, ")"); } onExited: function (exitCode) { if (idleInhibited && exitCode !== 0 && !nativeInhibitorAvailable) { - console.warn("SessionService: Inhibitor process crashed with exit code:", exitCode); + log.warn("Inhibitor process crashed with exit code:", exitCode); idleInhibited = false; ToastService.showWarning("Idle inhibitor failed"); } @@ -545,7 +547,7 @@ Singleton { } } else { loginctlAvailable = false; - console.log("SessionService: loginctl capability not available in DMS"); + log.debug("loginctl capability not available in DMS"); } if (DMSService.capabilities.includes("dbus")) { @@ -574,7 +576,7 @@ Singleton { prepareForSleepSubscriptionPending = false; if (response.error) { - console.warn("SessionService: Failed to subscribe to PrepareForSleep:", response.error); + log.warn("Failed to subscribe to PrepareForSleep:", response.error); return; } @@ -621,9 +623,9 @@ Singleton { enabled: SettingsData.lockBeforeSuspend }, response => { if (response.error) { - console.warn("SessionService: Failed to sync lock before suspend:", response.error); + log.warn("Failed to sync lock before suspend:", response.error); } else { - console.log("SessionService: Synced lock before suspend:", SettingsData.lockBeforeSuspend); + log.debug("Synced lock before suspend:", SettingsData.lockBeforeSuspend); } }); } @@ -637,9 +639,9 @@ Singleton { enabled: SettingsData.loginctlLockIntegration && SettingsData.lockBeforeSuspend }, response => { if (response.error) { - console.warn("SessionService: Failed to sync sleep inhibitor:", response.error); + log.warn("Failed to sync sleep inhibitor:", response.error); } else { - console.log("SessionService: Synced sleep inhibitor:", SettingsData.loginctlLockIntegration); + log.debug("Synced sleep inhibitor:", SettingsData.loginctlLockIntegration); } }); } diff --git a/quickshell/Services/SettingsSearchService.qml b/quickshell/Services/SettingsSearchService.qml index 97e5d116..00af5287 100644 --- a/quickshell/Services/SettingsSearchService.qml +++ b/quickshell/Services/SettingsSearchService.qml @@ -5,9 +5,11 @@ import QtQuick import Quickshell import Quickshell.Io import qs.Common +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("SettingsSearchService") property string query: "" property var results: [] @@ -41,12 +43,12 @@ Singleton { root.indexLoaded = true; root._rebuildTranslationCache(); } catch (e) { - console.warn("SettingsSearchService: Failed to parse index:", e); + log.warn("Failed to parse index:", e); root.settingsIndex = []; root._translatedCache = []; } } - onLoadFailed: error => console.warn("SettingsSearchService: Failed to load index:", error) + onLoadFailed: error => log.warn("Failed to load index:", error) } function registerCard(settingKey, item, flickable) { diff --git a/quickshell/Services/VPNService.qml b/quickshell/Services/VPNService.qml index effc54ea..b8483d50 100644 --- a/quickshell/Services/VPNService.qml +++ b/quickshell/Services/VPNService.qml @@ -4,9 +4,11 @@ pragma ComponentBehavior: Bound import QtQuick import Quickshell import qs.Common +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("VPNService") readonly property bool available: DMSNetworkService.vpnAvailable @@ -48,7 +50,7 @@ Singleton { DMSService.sendRequest("network.vpn.plugins", null, response => { pluginsLoading = false; if (response.error) { - console.warn("VPNService: Failed to fetch plugins:", response.error); + log.warn("Failed to fetch plugins:", response.error); return; } if (!response.result) diff --git a/quickshell/Services/WlrOutputService.qml b/quickshell/Services/WlrOutputService.qml index 655a4854..5e09328e 100644 --- a/quickshell/Services/WlrOutputService.qml +++ b/quickshell/Services/WlrOutputService.qml @@ -3,9 +3,11 @@ pragma ComponentBehavior: Bound import QtQuick import Quickshell +import qs.Services Singleton { id: root + readonly property var log: Log.scoped("WlrOutputService") property bool wlrOutputAvailable: false property var outputs: [] @@ -53,7 +55,7 @@ Singleton { const hasWlrOutput = DMSService.capabilities.includes("wlroutput"); if (hasWlrOutput && !wlrOutputAvailable) { wlrOutputAvailable = true; - console.info("WlrOutputService: wlr-output-management capability detected"); + log.info("wlr-output-management capability detected"); requestState(); return; } @@ -81,11 +83,11 @@ Singleton { serial = state.serial || 0; if (outputs.length === 0) { - console.warn("WlrOutputService: Received empty outputs list"); + log.warn("Received empty outputs list"); } else { - console.log("WlrOutputService: Updated with", outputs.length, "outputs, serial:", serial); + log.debug("Updated with", outputs.length, "outputs, serial:", serial); outputs.forEach((output, index) => { - console.log("WlrOutputService: Output", index, "-", output.name, "enabled:", output.enabled, "mode:", output.currentMode ? output.currentMode.width + "x" + output.currentMode.height + "@" + (output.currentMode.refresh / 1000) + "Hz" : "none"); + log.debug("Output", index, "-", output.name, "enabled:", output.enabled, "mode:", output.currentMode ? output.currentMode.width + "x" + output.currentMode.height + "@" + (output.currentMode.refresh / 1000) + "Hz" : "none"); }); } stateChanged(); @@ -112,9 +114,9 @@ Singleton { return; } - console.log("WlrOutputService: Applying configuration for", heads.length, "outputs"); + log.debug("Applying configuration for", heads.length, "outputs"); heads.forEach((head, index) => { - console.log("WlrOutputService: Head", index, "- name:", head.name, "enabled:", head.enabled, "modeId:", head.modeId, "customMode:", JSON.stringify(head.customMode), "position:", JSON.stringify(head.position), "scale:", head.scale, "transform:", head.transform, "adaptiveSync:", head.adaptiveSync); + log.debug("Head", index, "- name:", head.name, "enabled:", head.enabled, "modeId:", head.modeId, "customMode:", JSON.stringify(head.customMode), "position:", JSON.stringify(head.position), "scale:", head.scale, "transform:", head.transform, "adaptiveSync:", head.adaptiveSync); }); DMSService.sendRequest("wlroutput.applyConfiguration", { @@ -124,9 +126,9 @@ Singleton { const message = response.error || response.result?.message || ""; if (response.error) { - console.warn("WlrOutputService: applyConfiguration error:", response.error); + log.warn("applyConfiguration error:", response.error); } else { - console.log("WlrOutputService: Configuration applied successfully"); + log.debug("Configuration applied successfully"); } configurationApplied(success, message); @@ -144,7 +146,7 @@ Singleton { return; } - console.log("WlrOutputService: Testing configuration for", heads.length, "outputs"); + log.debug("Testing configuration for", heads.length, "outputs"); DMSService.sendRequest("wlroutput.testConfiguration", { "heads": heads @@ -153,9 +155,9 @@ Singleton { const message = response.error || response.result?.message || ""; if (response.error) { - console.warn("WlrOutputService: testConfiguration error:", response.error); + log.warn("testConfiguration error:", response.error); } else { - console.log("WlrOutputService: Configuration test passed"); + log.debug("Configuration test passed"); } if (callback) { @@ -167,7 +169,7 @@ Singleton { function setOutputEnabled(outputName, enabled, callback) { const output = getOutput(outputName); if (!output) { - console.warn("WlrOutputService: Output not found:", outputName); + log.warn("Output not found:", outputName); if (callback) { callback(false, "Output not found"); } diff --git a/quickshell/Widgets/DankOSD.qml b/quickshell/Widgets/DankOSD.qml index f2a454b5..ad5625b8 100644 --- a/quickshell/Widgets/DankOSD.qml +++ b/quickshell/Widgets/DankOSD.qml @@ -6,6 +6,7 @@ import qs.Services PanelWindow { id: root + readonly property var log: Log.scoped("DankOSD") property string blurNamespace: "dms:osd" WlrLayershell.namespace: blurNamespace @@ -94,10 +95,10 @@ PanelWindow { WlrLayershell.layer: { switch (Quickshell.env("DMS_OSD_LAYER")) { case "bottom": - console.warn("DankOSD: 'bottom' layer is not valid for OSDs. Defaulting to 'overlay' layer."); + log.warn("'bottom' layer is not valid for OSDs. Defaulting to 'overlay' layer."); return WlrLayershell.Overlay; case "background": - console.warn("DankOSD: 'background' layer is not valid for OSDs. Defaulting to 'overlay' layer."); + log.warn("'background' layer is not valid for OSDs. Defaulting to 'overlay' layer."); return WlrLayershell.Overlay; case "top": return WlrLayershell.Top; diff --git a/quickshell/Widgets/DankPopout.qml b/quickshell/Widgets/DankPopout.qml index 197af681..a82a27b3 100644 --- a/quickshell/Widgets/DankPopout.qml +++ b/quickshell/Widgets/DankPopout.qml @@ -6,6 +6,7 @@ import qs.Services Item { id: root + readonly property var log: Log.scoped("DankPopout") property string layerNamespace: "dms:popout" property alias content: contentLoader.sourceComponent @@ -414,10 +415,10 @@ Item { WlrLayershell.layer: { switch (Quickshell.env("DMS_POPOUT_LAYER")) { case "bottom": - console.warn("DankPopout: 'bottom' layer is not valid for popouts. Defaulting to 'top' layer."); + log.warn("'bottom' layer is not valid for popouts. Defaulting to 'top' layer."); return WlrLayershell.Top; case "background": - console.warn("DankPopout: 'background' layer is not valid for popouts. Defaulting to 'top' layer."); + log.warn("'background' layer is not valid for popouts. Defaulting to 'top' layer."); return WlrLayershell.Top; case "overlay": return WlrLayershell.Overlay; diff --git a/quickshell/Widgets/KeybindItem.qml b/quickshell/Widgets/KeybindItem.qml index a68cc4a1..6f33db5e 100644 --- a/quickshell/Widgets/KeybindItem.qml +++ b/quickshell/Widgets/KeybindItem.qml @@ -11,6 +11,7 @@ import "../Common/KeybindActions.js" as Actions Item { id: root + readonly property var log: Log.scoped("KeybindItem") LayoutMirroring.enabled: I18n.isRtl LayoutMirroring.childrenInherit: true @@ -716,7 +717,7 @@ Item { const key = KeyUtils.xkbKeyFromQtKey(qtKey); if (!key) { - console.warn("[KeybindItem] Unknown key:", event.key, "mods:", event.modifiers); + log.warn("Unknown key:", event.key, "mods:", event.modifiers); return; } diff --git a/quickshell/Widgets/PluginGlobalVar.qml b/quickshell/Widgets/PluginGlobalVar.qml index 6a95a976..e46ddf62 100644 --- a/quickshell/Widgets/PluginGlobalVar.qml +++ b/quickshell/Widgets/PluginGlobalVar.qml @@ -3,24 +3,25 @@ import qs.Services Item { id: root + readonly property var log: Log.scoped("PluginGlobalVar") required property string varName property var defaultValue: undefined readonly property var value: { - const pid = parent?.pluginId ?? "" + const pid = parent?.pluginId ?? ""; if (!pid || !PluginService.globalVars[pid]) { - return defaultValue + return defaultValue; } - return PluginService.globalVars[pid][varName] ?? defaultValue + return PluginService.globalVars[pid][varName] ?? defaultValue; } function set(newValue) { - const pid = parent?.pluginId ?? "" + const pid = parent?.pluginId ?? ""; if (pid) { - PluginService.setGlobalVar(pid, varName, newValue) + PluginService.setGlobalVar(pid, varName, newValue); } else { - console.warn("PluginGlobalVar: Cannot set", varName, "- no pluginId from parent") + log.warn("Cannot set", varName, "- no pluginId from parent"); } }