From 846677caa14a4811704d5952fe9668ef5912a6b5 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sat, 10 May 2025 17:53:38 +0200 Subject: [PATCH] config loader --- .config/quickshell/services/ConfigLoader.qml | 106 +++++++++++++++++++ .config/quickshell/shell.qml | 1 + 2 files changed, 107 insertions(+) create mode 100644 .config/quickshell/services/ConfigLoader.qml diff --git a/.config/quickshell/services/ConfigLoader.qml b/.config/quickshell/services/ConfigLoader.qml new file mode 100644 index 000000000..749d3dc59 --- /dev/null +++ b/.config/quickshell/services/ConfigLoader.qml @@ -0,0 +1,106 @@ +pragma Singleton +pragma ComponentBehavior: Bound + +import "root:/modules/common" +import QtQuick +import Quickshell +import Quickshell.Io +import Quickshell.Hyprland +import Qt.labs.platform + +Singleton { + id: root + property string fileDir: `${StandardPaths.standardLocations(StandardPaths.ConfigLocation)[0]}/illogical-impulse` + property string fileName: "config.json" + property string filePath: `${root.fileDir}/${root.fileName}` + + function toPlainObject(qtObj) { + if (qtObj === null || typeof qtObj !== "object") return qtObj; + + // Handle arrays + if (Array.isArray(qtObj)) { + return qtObj.map(toPlainObject); + } + + const result = ({}); + for (let key in qtObj) { + if ( + typeof qtObj[key] !== "function" && + !key.startsWith("objectName") && + !key.startsWith("children") && + !key.startsWith("object") && + !key.startsWith("parent") && + !key.startsWith("metaObject") && + !key.startsWith("destroyed") && + !key.startsWith("reloadableId") + ) { + result[key] = toPlainObject(qtObj[key]); + } + } + return result; + } + + function loadConfig() { + configFileView.reload() + } + + function applyConfig(fileContent) { + const json = JSON.parse(fileContent); + + function applyToQtObject(qtObj, jsonObj) { + if (!qtObj || typeof jsonObj !== "object" || jsonObj === null) return; + + for (let key in jsonObj) { + if (!qtObj.hasOwnProperty(key)) continue; + + // Check if the property is a QtObject (not a value) + const value = qtObj[key]; + const jsonValue = jsonObj[key]; + + // If it's an object and not an array, recurse + if (value && typeof value === "object" && !Array.isArray(value)) { + applyToQtObject(value, jsonValue); + } else { + // Otherwise, assign the value + qtObj[key] = jsonValue; + } + } + } + + applyToQtObject(ConfigOptions, json); + } + + Timer { + id: delayedFileRead + interval: ConfigOptions.hacks.arbitraryRaceConditionDelay + repeat: false + running: false + onTriggered: { + root.applyConfig(configFileView.text()) + } + } + + FileView { + id: configFileView + path: root.filePath + watchChanges: true + onFileChanged: { + this.reload() + delayedFileRead.start() + } + onLoadedChanged: { + const fileContent = configFileView.text() + root.applyConfig(fileContent) + } + onLoadFailed: (error) => { + if(error == FileViewError.FileNotFound) { + console.log("[ConfigLoader] File not found, creating new file.") + // Apply ConfigOptions json to file + const plainConfig = toPlainObject(ConfigOptions) + configFileView.setText(JSON.stringify(plainConfig, null, 2)) + } else { + Hyprland.dispatch(`exec notify-send "Failed to load config file at ${root.filePath}"`) + } + } + } +} diff --git a/.config/quickshell/shell.qml b/.config/quickshell/shell.qml index b0e5250a0..7bc831b88 100644 --- a/.config/quickshell/shell.qml +++ b/.config/quickshell/shell.qml @@ -18,6 +18,7 @@ import "./services/" ShellRoot { Component.onCompleted: { MaterialThemeLoader.reapplyTheme() + ConfigLoader.loadConfig() } Bar {}