From cf63dfb7ffa306025ad2a196cb8991256aa091a8 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Wed, 21 Oct 2026 10:11:12 +0200 Subject: 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 --- desktop/modules/sbbuilder/Store.qml | 79 +++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 desktop/modules/sbbuilder/Store.qml (limited to 'desktop/modules/sbbuilder/Store.qml') 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. +// +// 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; + } +} -- cgit v1.2.3