aboutsummaryrefslogtreecommitdiffstats
path: root/appearance/Udt.qml
diff options
context:
space:
mode:
Diffstat (limited to 'appearance/Udt.qml')
-rw-r--r--appearance/Udt.qml152
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`);
- }
- }
-}