Files
2026-06-09 12:27:52 +02:00

131 lines
4.4 KiB
QML

pragma Singleton
import QtQuick
import Quickshell
import Quickshell.Io
QtObject {
id: root
readonly property string _configDir: (Quickshell.env("XDG_CONFIG_HOME") || (Quickshell.env("HOME") + "/.config")) + "/quick-visor"
readonly property string _themePath: _configDir + "/theme.jsonc"
property color background: "#101010"
property color foreground: "#e6e6e6"
property color idle: "#9a9a9a"
property color accent: "#7aa2f7"
property color warning: "#f7768e"
property color overlayStrong: "#26344d"
property color overlayWeak: "#202020"
property color border: "#3a3a3a"
property string fontFamily: Config.fontFamily
property int fontSize: Config.fontSize
property int padding: 8
property int spacing: 8
property int radius: 12
readonly property var _defaults: ({
background: "#101010",
foreground: "#e6e6e6",
idle: "#9a9a9a",
accent: "#7aa2f7",
warning: "#f7768e",
overlayStrong: "#26344d",
overlayWeak: "#202020",
border: "#3a3a3a",
fontFamily: "JetBrainsMono Nerd Font",
fontSize: 14,
padding: 8,
spacing: 8,
radius: 12
})
Component.onCompleted: {
_load();
_startWatcher();
}
function _load() {
loadProcess.command = ["cat", _themePath];
loadProcess.running = true;
}
function _startWatcher() {
watchProcess.command = [
"bash", "-c",
"while inotifywait -q -e close_write '" + _themePath + "' 2>/dev/null; do echo CHANGED; done"
];
watchProcess.running = true;
}
function _apply(json) {
if (typeof json.background === "string") background = json.background;
if (typeof json.foreground === "string") foreground = json.foreground;
if (typeof json.idle === "string") idle = json.idle;
if (typeof json.accent === "string") accent = json.accent;
if (typeof json.warning === "string") warning = json.warning;
if (typeof json.overlayStrong === "string") overlayStrong = json.overlayStrong;
if (typeof json.overlayWeak === "string") overlayWeak = json.overlayWeak;
if (typeof json.border === "string") border = json.border;
if (typeof json.fontFamily === "string" && json.fontFamily.length > 0) fontFamily = json.fontFamily;
if (typeof json.fontSize === "number" && json.fontSize > 0) fontSize = json.fontSize;
if (typeof json.padding === "number" && json.padding > 0) padding = json.padding;
if (typeof json.spacing === "number" && json.spacing > 0) spacing = json.spacing;
if (typeof json.radius === "number" && json.radius >= 0) radius = json.radius;
console.log("quick-visor: theme loaded from", _themePath);
}
function _writeDefaults() {
writeProcess.command = [
"bash", "-c",
"mkdir -p '" + _configDir + "' && cat > '" + _themePath + "'"
];
writeProcess.stdinEnabled = true;
writeProcess._content = "// Quick Visor theme file (JSONC)\n"
+ "// Auto-generated by ThemeEngine when applying shell-dev themes.\n"
+ JSON.stringify(_defaults, null, 2) + "\n";
writeProcess.running = true;
}
property Process watchProcess: Process {
running: false
stdout: SplitParser {
splitMarker: "\n"
onRead: line => {
if (line.indexOf("CHANGED") >= 0) root._load();
}
}
onExited: root._startWatcher()
}
property Process loadProcess: Process {
running: false
stdout: StdioCollector { id: loadStdout; waitForEnd: true }
onExited: exitCode => {
if (exitCode === 0 && loadStdout.text.length > 0) {
try {
const stripped = loadStdout.text
.replace(/\/\/.*$/gm, "")
.replace(/\/\*[\s\S]*?\*\//g, "");
root._apply(JSON.parse(stripped));
} catch (e) {
console.log("quick-visor: theme.jsonc parse error:", e);
}
} else {
root._writeDefaults();
}
}
}
property Process writeProcess: Process {
running: false
property string _content: ""
onStarted: {
writeProcess.write(writeProcess._content);
writeProcess.stdinEnabled = false;
}
}
}