diff options
| author | Danilo M. <danix@danix.xyz> | 2026-08-13 11:39:49 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-08-13 11:39:49 +0200 |
| commit | 2ad9b17d53e19418de089cc98820af0776c3bfba (patch) | |
| tree | dc3ce44242187d3b5205611b263e556b85968d63 /src | |
| parent | 4cb43886ceb18cc6078ab2e8ec28fa15a1c701f2 (diff) | |
| download | qtmaildir-2ad9b17d53e19418de089cc98820af0776c3bfba.tar.gz qtmaildir-2ad9b17d53e19418de089cc98820af0776c3bfba.zip | |
feat(rules): text mode, and leave untouched rules unwritten
Diffstat (limited to 'src')
| -rw-r--r-- | src/tagrulesdialog.cpp | 70 | ||||
| -rw-r--r-- | src/tagrulesdialog.h | 7 |
2 files changed, 76 insertions, 1 deletions
diff --git a/src/tagrulesdialog.cpp b/src/tagrulesdialog.cpp index 797cd92..1d31d07 100644 --- a/src/tagrulesdialog.cpp +++ b/src/tagrulesdialog.cpp @@ -162,6 +162,8 @@ TagRulesDialog::TagRulesDialog(QWidget *parent) connect(m_matchAll, &QRadioButton::toggled, this, &TagRulesDialog::syncQueryLine); + connect(m_textMode, &QCheckBox::toggled, + this, &TagRulesDialog::setTextMode); connect(m_addExclusion, &QPushButton::clicked, this, [this] { addRow(true); syncQueryLine(); @@ -326,6 +328,16 @@ void TagRulesDialog::onSelectionChanged() // rule and closing it cannot rewrite the file mailctl also reads. m_loadedQuery = RuleQuery::parse(rule.query); + // A rule the builder cannot show opens as text, and one it can show + // returns to the builder. Blocked, because letting setChecked run + // setTextMode() here would recompile and overwrite m_query mid-load. + { + const QSignalBlocker blockTextMode(m_textMode); + m_textMode->setChecked(!m_loadedQuery.parsed); + } + m_builder->setVisible(m_loadedQuery.parsed); + m_query->setReadOnly(m_loadedQuery.parsed); + if (m_loadedQuery.parsed) rebuildRows(m_loadedQuery); @@ -347,7 +359,16 @@ void TagRulesDialog::applyEditsToCurrentRule() rule.enabled = m_enabled->isChecked(); rule.add = splitTags(m_add->text()); rule.remove = splitTags(m_remove->text()); - rule.query = m_query->text().trimmed(); + if (m_textMode->isChecked()) { + rule.query = m_query->text().trimmed(); + } else { + const RuleQuery current = currentQueryFromRows(); + // Unchanged rows mean the stored string is left exactly as it was + // read. Recompiling an untouched rule would churn a file the + // companion tool also reads, showing a diff the user never made. + if (!(current == m_loadedQuery)) + rule.query = current.compile(); + } rule.note = m_note->toPlainText(); fillItem(m_list->topLevelItem(index), rule); @@ -431,6 +452,19 @@ QString TagRulesDialog::queryLineForTest() const return m_query->text(); } +bool TagRulesDialog::textModeForTest() const +{ + return m_textMode->isChecked(); +} + +void TagRulesDialog::setRowValueForTest(int index, const QString &value) +{ + if (index < 0 || index >= m_rows.size()) + return; + m_rows.at(index).value->setText(value); + syncQueryLine(); +} + void TagRulesDialog::selectRuleForTest(int index) { if (index >= 0 && index < m_list->topLevelItemCount()) @@ -587,6 +621,40 @@ RuleQuery TagRulesDialog::currentQueryFromRows() const return query; } +void TagRulesDialog::setTextMode(bool on) +{ + if (on) { + // Show what the rows currently mean, then hand the string over. + if (m_loadedQuery.parsed) + m_query->setText(currentQueryFromRows().compile()); + m_builder->setVisible(false); + m_query->setReadOnly(false); + return; + } + + // Going back needs the typed query to be representable. If it is not, the + // checkbox cannot clear: there are no rows that mean this query. + const RuleQuery parsed = RuleQuery::parse(m_query->text().trimmed()); + if (!parsed.parsed) { + const QSignalBlocker block(m_textMode); + m_textMode->setChecked(true); + QMessageBox::information( + this, tr("Cannot show as rows"), + tr("This query is more than the builder can show, so it stays " + "as text. It is still saved and applied normally.")); + return; + } + + const bool wasReloading = m_reloading; + m_reloading = true; + rebuildRows(parsed); + m_reloading = wasReloading; + + m_loadedQuery = parsed; + m_builder->setVisible(true); + m_query->setReadOnly(true); +} + void TagRulesDialog::rebuildRows(const RuleQuery &query) { while (!m_rows.isEmpty()) diff --git a/src/tagrulesdialog.h b/src/tagrulesdialog.h index 6676da9..9cee163 100644 --- a/src/tagrulesdialog.h +++ b/src/tagrulesdialog.h @@ -64,6 +64,11 @@ public: /// Selects the rule at `index` as a click on the list would. void selectRuleForTest(int index); + bool textModeForTest() const; + void setRowValueForTest(int index, const QString &value); + /// Runs the Save path without showing the dialog. + void saveForTest() { onSave(); } + signals: /// Asks the owner to run countQueries() through the worker. void countsRequested(); @@ -104,6 +109,8 @@ private: void updateExclusionsVisibility(); void syncQueryLine(); + void setTextMode(bool on); + void rebuildRows(const RuleQuery &query); void applyTermToRow(Row *row, const RuleTerm &term); RuleQuery currentQueryFromRows() const; |
