diff options
Diffstat (limited to 'appearance/Udt.qml')
| -rw-r--r-- | appearance/Udt.qml | 152 |
1 files changed, 0 insertions, 152 deletions
diff --git a/appearance/Udt.qml b/appearance/Udt.qml deleted file mode 100644 index cf97ba5..0000000 --- a/appearance/Udt.qml +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright (C) 2026 Danilo M. <danix@danix.xyz> -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License version 2 as -// published by the Free Software Foundation. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -pragma Singleton - -import Quickshell -import Quickshell.Io -import QtQuick - -// The unified-desktop-theme side: which schemes exist, what they look like, -// and switching between them. -Singleton { - id: root - - readonly property string home: Quickshell.env("HOME") - readonly property string repo: `${home}/Programming/GIT/unified-desktop-theme` - readonly property string selector: `${home}/.config/udt/roles.conf` - - property string current: "" - // name -> { bg, surface, text, accent, red, green, yellow } - property var swatches: ({}) - property list<string> names: [] - - property bool applying: false - signal applied(string scheme, bool ok, string message) - - // A scheme is two files: <name>.conf holds colours under the scheme's own - // names, roles-<name>.conf says what each colour is for. Resolving a role - // means looking its value up as a key in the first file. - function parseSwatch(rolesText, paletteText) { - // QML's JS engine has no String.matchAll, so this is an exec loop. - const colours = {}; - const re = /^(\w+)\s*=\s*(#[0-9a-fA-F]{6})/gm; - let m; - while ((m = re.exec(paletteText)) !== null) colours[m[1]] = m[2]; - - const role = key => { - const m = rolesText.match(new RegExp(`^${key}\\s*=\\s*(\\S+)`, "m")); - // A role can carry a /alpha or *shade suffix; the base colour is - // what a swatch shows. - return m ? colours[m[1].split(/[/*]/)[0]] ?? "" : ""; - }; - - return { - bg: role("bg"), surface: role("surface"), text: role("fg"), - accent: role("accent"), red: role("critical"), - green: role("success"), yellow: role("warning"), - }; - } - - // Which scheme is live. Watched, so switching it from an editor moves the - // panel's marker too. - FileView { - path: root.selector - watchChanges: true - onFileChanged: reload() - onLoaded: { - const m = text().match(/^\s*scheme\s*=\s*(\S+)/m); - if (m) root.current = m[1]; - } - } - - // The scheme list comes from the palette directory rather than the comment - // in roles.conf: adding a scheme is adding two files, and this then needs - // no edit at all. - // Rescanned whenever the panel opens: adding a scheme is adding two - // files, and a shell that has been running since before they appeared - // would otherwise keep showing the old list. - function refresh() { - listProc.running = false; - listProc.running = true; - } - - Process { - id: listProc - running: true - command: ["sh", "-c", - `ls ${root.repo}/palette/roles-*.conf 2>/dev/null | ` + - `sed 's|.*/roles-||; s|\\.conf$||' | sort`] - stdout: StdioCollector { - onStreamFinished: { - root.names = text.trim().split("\n").filter(s => s.length); - loadProc.next = 0; - loadProc.loadNext(); - } - } - } - - Process { - id: loadProc - property int next: 0 - property string scheme: "" - - function loadNext() { - if (next >= root.names.length) return; - scheme = root.names[next]; - next++; - // Both files at once, split on a marker: one process per scheme - // rather than two, and the pair is always consistent. - command = ["sh", "-c", - `cat ${root.repo}/palette/roles-${scheme}.conf; ` + - `echo '===SPLIT==='; cat ${root.repo}/palette/${scheme}.conf`]; - // Assigning true to an already-true `running` does nothing, and - // this Process is reused for every scheme in turn. - running = false; - running = true; - } - - stdout: StdioCollector { - onStreamFinished: { - const [rolesText, paletteText] = text.split("===SPLIT==="); - if (rolesText && paletteText) { - const next = Object.assign({}, root.swatches); - next[loadProc.scheme] = root.parseSwatch(rolesText, paletteText); - root.swatches = next; - } - loadProc.loadNext(); - } - } - } - - // Switching writes the scheme line and regenerates every config; - // install.sh also reloads what is running, and hands its whole output to - // the steps window's `install` tab itself. - function apply(scheme) { - if (applying || scheme === current) return; - applying = true; - applyProc.scheme = scheme; - applyProc.command = ["sh", "-c", - `sed -i 's|^scheme *=.*|scheme = ${scheme}|' ${JSON.stringify(root.selector)} && ` + - `${JSON.stringify(root.repo)}/install.sh >/dev/null 2>&1`]; - applyProc.running = true; - } - - Process { - id: applyProc - property string scheme: "" - onExited: code => { - root.applying = false; - root.applied(applyProc.scheme, code === 0, - code === 0 ? "" : `install.sh exited ${code}, its output is in the steps window`); - } - } -} |
