// 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. pragma Singleton import Quickshell import Quickshell.Io import QtQuick import "Ini.js" as I // qtmaildir.conf, shared by the four Mail settings pages. qtmaildir reads // it at startup and never writes it, so editing it under a running // qtmaildir is safe and applies on its next launch. Singleton { id: root readonly property string path: (Quickshell.env("XDG_CONFIG_HOME") || Quickshell.env("HOME") + "/.config") + "/qtmaildir/qtmaildir.conf" property string text: "" property string error: "" // Whether qtmaildir runs now, so a page can say a change waits for a // restart. Rechecked on every refresh(). property bool running: false // Keys of the [account.] sections, in file order. readonly property var accounts: I.sections(root.text).filter(s => s.startsWith("account.")).map(s => s.slice(8)) function get(section, key) { return I.get(root.text, section, key); } function entries(section) { return I.entries(root.text, section); } // val null unsets: the line is commented out where it stands. function set(section, key, val) { root.write(I.set(root.text, section, key, val)); } function remove(section, key) { root.write(I.remove(root.text, section, key)); } function addAccount(key, pairs) { root.write(I.addSection(root.text, "account." + key, pairs)); } function removeAccount(key) { root.write(I.removeSection(root.text, "account." + key)); } // Never empty, since a header always remains, so FileView.setText is safe // here (AGENTS.md: it writes nothing for empty text on an unloaded path). function write(t) { if (t === root.text) return; root.error = ""; root.text = t; fv.setText(t); } function refresh() { fv.reload(); pg.running = false; pg.running = true; } FileView { id: fv path: root.path atomicWrites: true watchChanges: true printErrors: false // Its own writes come back here too; reparsing the same text is a no-op. onFileChanged: reload() onLoaded: root.text = text() onLoadFailed: root.text = "" onSaveFailed: err => root.error = "Cannot write " + root.path + ": " + FileViewError.toString(err) } Process { id: pg command: ["pgrep", "-x", "qtmaildir"] onExited: code => root.running = code === 0 } }