diff options
| author | Danilo M. <danix@danix.xyz> | 2026-08-13 19:06:41 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-08-13 19:06:41 +0200 |
| commit | 5e30d1805656895387ba83865d9635caf2e51618 (patch) | |
| tree | bd122169ac0918d45e76d24b8a18a0ec77d8fc66 /src/savequerydialog.h | |
| parent | f389db3aad498d46c95c2a95b4280ffb541043b2 (diff) | |
| download | qtmaildir-5e30d1805656895387ba83865d9635caf2e51618.tar.gz qtmaildir-5e30d1805656895387ba83865d9635caf2e51618.zip | |
feat(queries): store saved queries in queries.json
First half of item 23. The storage moves out of the [queries] INI section into
~/.config/qtmaildir/queries.json; the UI that writes it comes next.
The INI could not express order. QSettings reads a section through childKeys(),
which sorts alphabetically and never follows the file, so the saved-query
buttons could not be arranged and config.cpp carried a comment saying a
hand-rolled parser would be needed to change that. queries.json is an ordered
array and nothing sorts it on load. That also makes room for the two fields the
save dialog needs: pinned, which decides whether a query is a button or a menu
entry, and account, which scopes it.
account stores the account KEY, not the maildir path, so it does not duplicate
config that already lives in the account section and go stale when the user
edits it. Config::resolvedQuery() composes through Account::scopedQuery(), whose
parentheses are load-bearing: path:... and a or b binds as (path:... and a) or
b, so an unparenthesised disjunction escapes its scope and matches every
account. A key naming an account that no longer exists resolves to the bare
query rather than a scope built from an empty maildir, which would be path:"/**"
and match everything.
Migration reads [queries] once, when queries.json is absent, marks every entry
pinned so the query row does not empty on the first launch after an upgrade, and
leaves the INI section untouched. Stripping it would mean rewriting a
hand-edited file with QSettings, which drops comments and key order across the
whole file.
The format follows rules.json in shape only: a version and unknown fields
preserved at both levels, so a file written by a later build survives a save
from this one. None of its two-implementation machinery is here, because queries
have exactly one reader; the version constant says so where a future reader will
look. A file whose version this build does not know is refused AND blocks the
save, so a newer document is never overwritten with a lossy reading of itself.
Twelve tests, each checked against a mutation that puts the corresponding bug
back: sorting on load fails three of them, stripping the INI section after
migration fails the byte-identical assertion, concatenating the scope without
parentheses fails the disjunction test, and dropping unknown-field preservation
fails the round trip. The migration test compares the INI file's BYTES rather
than re-reading it through QSettings, which would have passed against a rewrite
that kept every value while dropping the comments.
startup_query still resolves by name, but its fallback now returns the first
entry in the user's own order rather than the alphabetically first one. That is
user-visible for a config whose startup_query matches nothing.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'src/savequerydialog.h')
0 files changed, 0 insertions, 0 deletions
