diff options
| author | Danilo M. <danix@danix.xyz> | 2026-08-24 12:15:09 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-08-24 12:15:09 +0200 |
| commit | 98ea0ee4691e60b430bd78eb615838da90bce244 (patch) | |
| tree | d64d9d02e25f5b04044ad982beefbce3600a1503 /tests/test_mainwindow.cpp | |
| parent | 02a795abe731da908928cd08a799ad79002ff421 (diff) | |
| download | qtmaildir-98ea0ee4691e60b430bd78eb615838da90bce244.tar.gz qtmaildir-98ea0ee4691e60b430bd78eb615838da90bce244.zip | |
feat: add a Drafts filter, and close the composer with Ctrl+W
Items 138 and 148.
The query row carried Unread, Inbox, Important, Sent and Trash, and no
Drafts, though the composer has been autosaving into each account's drafts
folder since compose shipped. Reaching them meant typing a query by hand.
Smaller than its size suggested: Account::draftsQuery() and
Config::allDraftsQuery() already existed for the placeholder pane's drafts
count, and builtinFilters() derives the row from kQueryGenerators, so the
work was the generator entry, two resolvedQuery branches, a label and an
icon.
It follows TRASH rather than Sent. Folder-matched like both, because `draft`
is a Maildir flag notmuch surfaces as a tag while the folder is what the
user means and what the composer actually writes into. But NOT flat: Sent is
flat so a thread cannot fold the user's own message back into the
conversation it answers, and a draft reply belongs with its conversation for
the same reason a trashed message does.
An account with no drafts folder shows no button, per item 103's rule. The
existing row test surfaced that by failing until its fixture configured one,
which is the rule working rather than a defect.
Ctrl+W closes the composer, which bound nothing at all: the only way out was
the title bar. The action is parented to the composer, so it is a
WindowShortcut dispatched to the active one only and the main window's
namespace is untouched, exactly like the formatting shortcuts. It calls
close() rather than doing anything of its own, since closeEvent() already
decides whether the draft is saved and a second route out that skipped it
would lose the message.
The Italian gains "Bozze"; lrelease reports 478 finished, 0 unfinished.
Diffstat (limited to 'tests/test_mainwindow.cpp')
| -rw-r--r-- | tests/test_mainwindow.cpp | 61 |
1 files changed, 60 insertions, 1 deletions
diff --git a/tests/test_mainwindow.cpp b/tests/test_mainwindow.cpp index 4c33302..3dbb227 100644 --- a/tests/test_mainwindow.cpp +++ b/tests/test_mainwindow.cpp @@ -276,6 +276,7 @@ private slots: void aStartupAccountAlsoScopesASavedStartupQuery(); void aGeneratedStartupQueryActuallyRuns(); void everyBuiltinFilterButtonCarriesAnIconAndItsText(); + void theDraftsButtonIsAbsentWithoutADraftsFolder(); void aQueryInTheMenuCanActuallyBeRun(); void theFourBuiltinFiltersAreOnTheRowInOrder(); void aFilterComposesWithTheSelectedAccount(); @@ -476,6 +477,7 @@ private slots: // MainWindow hands it, so a Config written to a temporary INI is the whole // fixture. void aComposerOpensClean(); + void ctrlWClosesTheComposer(); void theComposerSplitsItsToolbarByScope(); void ccAndBccHideBehindADisclosure(); void ccAndBccAreRevealedWhenTheyCarryAValue(); @@ -9572,6 +9574,32 @@ void TestMainWindow::aGeneratedStartupQueryActuallyRuns() QCOMPARE(queryEdit->text(), config.allSentQuery()); } +void TestMainWindow::theDraftsButtonIsAbsentWithoutADraftsFolder() +{ + // Item 138 follows item 103's rule: a folder filter with no folder to + // match is left out of the row rather than shown resolving to + // matchNothingQuery(). A button that can only ever report nothing is worse + // than no button, since it reads as "you have no drafts". + QTemporaryDir dir; + QVERIFY(dir.isValid()); + const QString path = writeSentConfig(dir, { + {QStringLiteral("work"), QStringLiteral("Sent")}, + }); + + Config config; + config.load(path); + MainWindow window(config); + + QVERIFY2(!window.findChild<QAbstractButton *>( + QStringLiteral("draftsButton")), + "a Drafts button appeared for an account with no drafts folder"); + + // The guard: Sent IS configured here, so a change that dropped every + // filter button would otherwise pass the assertion above. + QVERIFY2(window.findChild<QAbstractButton *>(QStringLiteral("sentButton")), + "the Sent button is missing, so this test proves nothing"); +} + void TestMainWindow::everyBuiltinFilterButtonCarriesAnIconAndItsText() { // The filters are part of the application now, so they carry icons like the @@ -9589,11 +9617,12 @@ void TestMainWindow::everyBuiltinFilterButtonCarriesAnIconAndItsText() }); // A trash key too, or the Trash filter finds nothing and is skipped from // the row entirely (item 103), leaving no trashButton for this loop to - // find. + // find. Drafts behaves the same way since item 138. { QSettings s(path, QSettings::IniFormat); s.beginGroup(QStringLiteral("account.work")); s.setValue(QStringLiteral("trash"), QStringLiteral("Trash")); + s.setValue(QStringLiteral("drafts"), QStringLiteral("Drafts")); s.endGroup(); } Config config; @@ -12420,6 +12449,36 @@ void TestMainWindow::removeAttachmentAppearsOnlyWithAttachments() "Remove attachment is not offered with a file attached"); } +void TestMainWindow::ctrlWClosesTheComposer() +{ + // Item 148. Ctrl+W closes a window in every application the user runs, and + // the composer bound nothing, so the only way out was the title bar. + // + // Scoped to the composer, not registered in KeyMap: Qt dispatches a + // WindowShortcut to the active window only, which is the same reason the + // formatting shortcuts are parented here rather than to the main window. + ComposeFixture fixture; + QVERIFY(fixture.build()); + ComposeContext context = newContext(); + + QPointer<ComposeWindow> window = + new ComposeWindow(context, fixture.config(), fixture.mailRoot()); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + auto *close = window->findChild<QAction *>(QStringLiteral("compose_close")); + QVERIFY2(close, "the composer has no close action"); + QVERIFY2(close->shortcut() == QKeySequence(QStringLiteral("Ctrl+W")), + qPrintable(QStringLiteral("the close action is bound to '%1', " + "not Ctrl+W") + .arg(close->shortcut().toString()))); + + close->trigger(); + + // WA_DeleteOnClose, so the window really goes rather than merely hiding. + QTRY_VERIFY_WITH_TIMEOUT(window.isNull(), 5000); +} + void TestMainWindow::aComposerOpensClean() { ComposeFixture fixture; |
