diff options
| author | Danilo M. <danix@danix.xyz> | 2026-08-13 17:07:16 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-08-13 17:07:16 +0200 |
| commit | 4d84062e48ec35598b7c2ecdf8446939be6064c4 (patch) | |
| tree | ab280755094321666d29d50694c48722809d953c /src/rulequery.h | |
| parent | df6461fa9136f2110c8a24567a3e4a32432a9476 (diff) | |
| parent | b8de7ce746718c7193e40b0f70cd3e2178f4ed8a (diff) | |
| download | qtmaildir-4d84062e48ec35598b7c2ecdf8446939be6064c4.tar.gz qtmaildir-4d84062e48ec35598b7c2ecdf8446939be6064c4.zip | |
Merge branch 'rule-builder': a row builder for the tagging rules
Item 76 replaces the four free-text fields with a row builder: field and
operator dropdowns per condition, +/- to add and remove them, a match
all/any choice, and a separate "but not" block. The stored format does
not change, so mailctl needs no edit. The query string stays
authoritative and remains visible, and a rule the builder cannot
represent opens in a text mode every rule carries.
Along the way, items 75, 77 and 80, and a data-loss defect released in
0.16.0 (item 79): opening the dialog and pressing Save destroyed the
first rule with nothing edited. That one damaged a real rule in the
user's own file, which was repaired by hand.
Four defects in this work were found by hand rather than by the suite,
and each is recorded where it was missed: a lost note, a one-way text
mode toggle, a geometry save on a path neither button takes, and a rule
list squeezed to one row by a long rule. Two Qt traps and one about the
user's compositor went into CLAUDE.md.
Diffstat (limited to 'src/rulequery.h')
| -rw-r--r-- | src/rulequery.h | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/src/rulequery.h b/src/rulequery.h new file mode 100644 index 0000000..9d487d2 --- /dev/null +++ b/src/rulequery.h @@ -0,0 +1,65 @@ +/* + * qtmaildir - a Qt6 mail client for notmuch-indexed Maildirs + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +#include <QList> +#include <QString> + +/// One row in the builder: a field, an operator, and a value. +struct RuleTerm +{ + enum Field { From, To, Cc, Subject, Tag, Folder, Attachment, Date }; + + enum Op { + Contains, ContainsNot, ///< Unquoted term, optionally negated. + Is, IsNot, ///< Quoted phrase, optionally negated. + Has, HasNot, ///< attachment: only. + Before, After ///< date: only. "not before" is "after", so + ///< these carry no negated twin. + }; + + Field field = From; + Op op = Contains; + QString value; +}; + +bool operator==(const RuleTerm &a, const RuleTerm &b); + +/// A tagging rule's query, as rows. +/// +/// The STRING is the stored format, shared with mailctl and executed by the +/// notmuch post-new hook. This type is a view over it, never the store: a +/// query it cannot represent must still open, save and run unchanged. +struct RuleQuery +{ + enum Join { All, Any }; ///< and / or, over the positive terms only. + + Join join = All; + QList<RuleTerm> terms; ///< Positive section. + QList<RuleTerm> exclusions; ///< The "but not" block, joined `and not`. + + /// False when the query cannot be shown as rows. NOT an error and NOT a + /// claim that the query is invalid: the rule opens in text mode. + bool parsed = false; + + static RuleQuery parse(const QString &query); + QString compile() const; +}; + +bool operator==(const RuleQuery &a, const RuleQuery &b); |
