summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mainwindow.cpp43
-rw-r--r--src/mainwindow.h26
-rw-r--r--src/tagrulesdialog.cpp24
-rw-r--r--src/tagrulesdialog.h14
4 files changed, 107 insertions, 0 deletions
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index e8b4dda..e2df6de 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -1324,6 +1324,9 @@ void MainWindow::showTagRulesDialog()
// setFolders refills the rows that exist by then.
QMetaObject::invokeMethod(m_worker, "requestFolders", Qt::QueuedConnection);
+ connect(dialog, &TagRulesDialog::previewRequested,
+ this, &MainWindow::onRulePreviewRequested);
+
connect(dialog, &TagRulesDialog::countsRequested, this, [this, dialog]() {
QMetaObject::invokeMethod(
m_worker, "requestMessageCounts", Qt::QueuedConnection,
@@ -1570,6 +1573,46 @@ void MainWindow::onCountsReady(const QVector<int> &counts, quint64 generation)
m_messageView->showPlaceholder(placeholderHelpers());
}
+QString MainWindow::queryTextForTesting() const
+{
+ return m_queryEdit->text();
+}
+
+QString MainWindow::selectedAccountForTesting() const
+{
+ return m_accountBox->currentData().toString();
+}
+
+void MainWindow::selectAccountForTesting(const QString &key)
+{
+ const int index = m_accountBox->findData(key);
+ if (index >= 0)
+ m_accountBox->setCurrentIndex(index);
+}
+
+void MainWindow::onRulePreviewRequested(const QString &query)
+{
+ // Unscoped, deliberately. runQuery() wraps the bar's text in the selected
+ // account's scope, and a rule query usually names its own path already
+ // (path:"work/**" is what every account rule looks like), so previewing
+ // one with an account selected would scope it twice and match nothing.
+ // That reads as "this rule collects no mail", which is the opposite of
+ // what the preview is for.
+ m_accountBox->setCurrentIndex(0);
+
+ // Through the query bar, like onPlaceholderQueryRequested: the bar then
+ // shows what is on screen and the user can edit the rule's query there
+ // before deciding to change the rule itself.
+ m_queryEdit->setText(query);
+ runCurrentQuery();
+
+ // The dialog is a separate window and may be covering this one or sitting
+ // beside it. Raising makes the result visible either way, and the dialog
+ // stays open so the two can be compared.
+ raise();
+ activateWindow();
+}
+
void MainWindow::onPlaceholderQueryRequested(const QString &query)
{
// Through the query bar rather than straight to the worker, so the bar
diff --git a/src/mainwindow.h b/src/mainwindow.h
index adf63b0..18fbbb4 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -185,6 +185,27 @@ public:
/// The generation the next counts reply must carry to be accepted.
quint64 countsGenerationForTesting() const { return m_countsGeneration; }
+ /// The query bar's text, and the account the selector is scoped to
+ /// (empty for "All accounts"). Both are what a rule preview writes: the
+ /// bar so the user can see and edit what ran, and the selector because
+ /// runQuery() wraps the text in the selected account's scope, which would
+ /// double-scope a rule query that already names its own path.
+ QString queryTextForTesting() const;
+ QString selectedAccountForTesting() const;
+
+ /// Scopes the view to one account, as choosing it in the selector does.
+ /// A test for the rule preview needs this: with no account selected the
+ /// box already sits at "All accounts", so asserting that a preview leaves
+ /// it there passes whether or not the preview clears it.
+ void selectAccountForTesting(const QString &key);
+
+ /// Runs a rule preview without the dialog, which the offscreen platform
+ /// cannot click a button in.
+ void previewRuleQueryForTesting(const QString &query)
+ {
+ onRulePreviewRequested(query);
+ }
+
protected:
void closeEvent(QCloseEvent *event) override;
@@ -293,6 +314,11 @@ private slots:
/// Runs a query the user clicked on the placeholder pane.
void onPlaceholderQueryRequested(const QString &query);
+ /// Runs one tagging rule's query in the thread list, so the user can see
+ /// which mail it collects. The rules dialog stays open; the point is to
+ /// compare the rule against its results.
+ void onRulePreviewRequested(const QString &query);
+
/// Opens the auto-tagging rules editor, or raises the one already open.
void showTagRulesDialog();
diff --git a/src/tagrulesdialog.cpp b/src/tagrulesdialog.cpp
index 285043a..4fca971 100644
--- a/src/tagrulesdialog.cpp
+++ b/src/tagrulesdialog.cpp
@@ -234,6 +234,11 @@ TagRulesDialog::TagRulesDialog(QWidget *parent)
buttons->addWidget(copyButton);
buttons->addWidget(deleteButton);
buttons->addStretch();
+ m_previewButton = new QPushButton(tr("&Preview in list"), this);
+ m_previewButton->setToolTip(
+ tr("Run this rule's query in the main window, to see which mail it "
+ "collects. This does not tag anything."));
+ buttons->addWidget(m_previewButton);
buttons->addWidget(refreshButton);
layout->addLayout(buttons);
@@ -251,6 +256,8 @@ TagRulesDialog::TagRulesDialog(QWidget *parent)
this, &TagRulesDialog::onCopyRule);
connect(deleteButton, &QPushButton::clicked,
this, &TagRulesDialog::onDeleteRule);
+ connect(m_previewButton, &QPushButton::clicked,
+ this, &TagRulesDialog::previewForTest);
connect(refreshButton, &QPushButton::clicked,
this, &TagRulesDialog::countsRequested);
connect(box, &QDialogButtonBox::accepted,
@@ -369,6 +376,23 @@ int TagRulesDialog::heightDemandedBelowListForTest() const
return m_splitter->widget(1)->minimumSizeHint().height();
}
+void TagRulesDialog::previewForTest()
+{
+ // Flush any half-typed edit first, so previewing shows what the rule
+ // says NOW rather than what it said when the row was selected.
+ applyEditsToCurrentRule();
+
+ const int index = currentIndex();
+ if (index < 0 || index >= m_working.size())
+ return;
+
+ const QString query = m_working.at(index).query;
+ if (query.isEmpty())
+ return;
+
+ emit previewRequested(query);
+}
+
int TagRulesDialog::conditionAreaHeightForTest() const
{
// The CAP itself, not a qMin against the scroll area's own size hint: a
diff --git a/src/tagrulesdialog.h b/src/tagrulesdialog.h
index de35a55..e8979fe 100644
--- a/src/tagrulesdialog.h
+++ b/src/tagrulesdialog.h
@@ -109,6 +109,10 @@ public:
/// the width the user had dragged.
void reloadListForTest();
+ /// Presses Preview, which is otherwise reachable only through a click on
+ /// a button whose geometry the offscreen platform does not guarantee.
+ void previewForTest();
+
/// The height the condition-row editor asks for. This is what squeezed
/// the rule list: a stretch factor only shares out space ABOVE each
/// widget's minimum, so every row added here came out of the list.
@@ -133,6 +137,15 @@ signals:
/// Asks the owner to run countQueries() through the worker.
void countsRequested();
+ /// Asks the owner to run one rule's query in the main window, so the user
+ /// can see WHICH mail a rule collects rather than how much.
+ ///
+ /// The query goes out exactly as stored: no `tag:new`, and no wrapping
+ /// parentheses. The post-new hook adds both when it applies a rule, and a
+ /// preview that copied them would match nothing outside a sync window,
+ /// since `tag:new` is set only on mail that has just arrived.
+ void previewRequested(const QString &query);
+
public slots:
/// Corpus counts, positionally paired with countQueries().
void setCounts(const QVector<int> &counts);
@@ -241,6 +254,7 @@ private:
/// still squeezed, because a stretch factor only shares out space above
/// each widget's minimum and the form's grew with every condition row.
QSplitter *m_splitter = nullptr;
+ QPushButton *m_previewButton = nullptr;
QVBoxLayout *m_rowsLayout = nullptr;
QVBoxLayout *m_exclusionsLayout = nullptr;
QLabel *m_exclusionsHeader = nullptr;