diff options
| author | Danilo M. <danix@danix.xyz> | 2026-10-21 10:11:12 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-10-21 10:11:12 +0200 |
| commit | cf63dfb7ffa306025ad2a196cb8991256aa091a8 (patch) | |
| tree | 7a35627871989508415a0a1e80030aae1a98da0b /desktop/modules/sbbuilder/Store.qml | |
| parent | 6e45e93e6e225015304716b934bea5dd1f3e1478 (diff) | |
| download | quickshell-cf63dfb7ffa306025ad2a196cb8991256aa091a8.tar.gz quickshell-cf63dfb7ffa306025ad2a196cb8991256aa091a8.zip | |
sbbuilder: the two config drafts
The desktop config is a watched local file; the VM one goes through the
helper's config-get and config-set over ssh, so the helper validates what
lands in root's file. Field text is typed after the key's default, the
same check sb-builder makes on load.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Diffstat (limited to 'desktop/modules/sbbuilder/Store.qml')
| -rw-r--r-- | desktop/modules/sbbuilder/Store.qml | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/desktop/modules/sbbuilder/Store.qml b/desktop/modules/sbbuilder/Store.qml new file mode 100644 index 0000000..b4a1ba1 --- /dev/null +++ b/desktop/modules/sbbuilder/Store.qml @@ -0,0 +1,79 @@ +// 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. + +import QtQuick +import "Toml.js" as T + +// One config.toml's draft, the store qtmaildir's Setting and BoolSetting +// edit. Fields hand it text; it writes the type of the key's default, the +// type sb-builder checks on load: a list is words split on spaces, a number +// is a number, a switch is true or false. +QtObject { + id: st + // The file as last read or written, the draft's start, and the draft. + property string text: "" + property string base: "" + property string draft: "" + readonly property bool dirty: st.draft !== st.base + // {section: {key: value}}, top-level keys under "". + property var defaults: ({}) + property var invalid: ({}) + readonly property bool valid: Object.keys(st.invalid).length === 0 + property string error: "" + // Assigned only when the set changes, as Qtm does: a Repeater bound to a + // fresh array per keystroke rebuilds the row being typed in. + property var manifests: [] + onDraftChanged: { + const k = T.entries(st.draft, "manifests").map(e => e.key); + if (JSON.stringify(k) !== JSON.stringify(st.manifests)) st.manifests = k; + } + + function fallback(section, key) { return (st.defaults[section] || {})[key]; } + function show(v) { return v === undefined ? undefined : Array.isArray(v) ? v.join(" ") : String(v); } + function placeholder(section, key) { return st.show(st.fallback(section, key)) ?? ""; } + + function get(section, key) { return st.show(T.get(st.draft, section, key)); } + // The effective value, typed: the file's, else the default. + function value(section, key) { return T.get(st.draft, section, key) ?? st.fallback(section, key); } + function entries(section) { return T.entries(st.draft, section); } + function put(section, key, v) { + try { st.draft = T.set(st.draft, section, key, v); } catch (e) { st.error = e.message; } + } + // A field's text; null or "" unsets. + function set(section, key, t) { + if (t === null || t === "") return st.put(section, key, null); + const d = st.fallback(section, key); + st.put(section, key, Array.isArray(d) ? t.split(/\s+/).filter(x => x !== "") + : typeof d === "number" ? Number(t) + : typeof d === "boolean" ? t === "true" : t); + } + function remove(section, key) { st.draft = T.remove(st.draft, section, key); } + + function markInvalid(id, bad) { + if (!!st.invalid[id] === bad) return; + const next = Object.assign({}, st.invalid); + if (bad) next[id] = true; else delete next[id]; + st.invalid = next; + } + + // The file as read: a clean draft follows it, a dirty one is kept and + // its save is refused. + function loaded(t) { + st.text = t; + if (!st.dirty) { st.base = t; st.draft = t; } + } + function discard() { + st.error = ""; + st.invalid = ({}); + st.base = st.text; + st.draft = st.text; + } +} |
