diff options
| author | Danilo M. <danix@danix.xyz> | 2026-08-13 16:44:16 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-08-13 16:44:16 +0200 |
| commit | 1ab12862fd47bf3816f7fad7b8a96eceb8f84272 (patch) | |
| tree | a170aaca6adde67b931b3899ffaadb6e788c12c8 /tests/test_tagrules.cpp | |
| parent | 1dd39414fd6139f2934554fc90b1c5721603d14b (diff) | |
| download | qtmaildir-1ab12862fd47bf3816f7fad7b8a96eceb8f84272.tar.gz qtmaildir-1ab12862fd47bf3816f7fad7b8a96eceb8f84272.zip | |
fix(rules): a long rule no longer squeezes the rule list away
Item 80. A rule with eight From conditions left the list showing about
one and a half rows.
The list was added with stretch 1 and the form below it with none, which
looks decisive and is not: a stretch factor only distributes space above
each widget's minimum, and the form's minimum grew with every condition
row, so each row came straight out of the list. The builder asked for
120px with one row and 414px with eight.
A QSplitter now divides the list from the editor, so the balance is the
user's and is saved beside the column widths, and the condition rows sit
in a QScrollArea capped at 190px so the editor cannot grow without bound
however the splitter is set. The scroll area is what text mode hides;
hiding the builder inside it would leave an empty frame.
Three measures were tried in the test before one told the bug and the
fix apart, and two passed against broken code: the dialog's
minimumSizeHint does not track form rows and read 580 either way, and a
qMin against the scroll area's own hint read small whether or not the
cap was set, since an uncapped maximumHeight is QWIDGETSIZE_MAX. What
survives mutation is the editor pane's minimum inside the splitter, plus
the cap read directly, and both are asserted. A row's size hint is
invalid until the event loop runs, so the test calls processEvents after
selecting a rule or it measures the same height twice.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'tests/test_tagrules.cpp')
| -rw-r--r-- | tests/test_tagrules.cpp | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/tests/test_tagrules.cpp b/tests/test_tagrules.cpp index 8ca7671..268c41f 100644 --- a/tests/test_tagrules.cpp +++ b/tests/test_tagrules.cpp @@ -54,6 +54,7 @@ private slots: void theWindowSizeAndColumnWidthsSurviveAReopen(); void theWindowSizeIsSavedOnEveryWayOutOfTheDialog(); void aReloadDoesNotDiscardARestoredColumnWidth(); + void manyConditionRowsDoNotSqueezeTheRuleList(); private: QString writeRules(const QString &json); @@ -321,6 +322,11 @@ void TestTagRules::switchingRulesDoesNotLeakRowsBetweenThem() // And back, to prove the first rule was not overwritten by loading the // second. dialog.selectRuleForTest(0); + // The row widgets are created during the select and their size hints are + // not valid until the layout has run, which needs the event loop: without + // this the builder reports the same height for one row and for eight, and + // the test passes against the bug. + QCoreApplication::processEvents(); QCOMPARE(dialog.rowCountForTest(), 1); QCOMPARE(dialog.queryLineForTest(), QStringLiteral("from:one.example.org")); } @@ -795,5 +801,71 @@ void TestTagRules::aReloadDoesNotDiscardARestoredColumnWidth() qputenv("XDG_STATE_HOME", previousState); } +void TestTagRules::manyConditionRowsDoNotSqueezeTheRuleList() +{ + // A rule with eight senders left the rule list showing about one and a + // half rows: the list had stretch 1, but a stretch factor only shares out + // space ABOVE each widget's minimum, and the form below it has no ceiling, + // so every condition row added to the minimum the list had to give up. + // + // Measured as the height the layout demands below the list. A rule with + // many rows must not demand materially more than a rule with one; what it + // needs beyond that belongs in the builder's own scroll area. + QTemporaryDir configHome; + QVERIFY(configHome.isValid()); + qputenv("XDG_CONFIG_HOME", configHome.path().toUtf8()); + QVERIFY(QDir().mkpath(configHome.filePath(QStringLiteral("mailrules")))); + + QFile out(configHome.filePath(QStringLiteral("mailrules/rules.json"))); + QVERIFY(out.open(QIODevice::WriteOnly)); + out.write(R"({ + "version": 1, + "rules": [ + {"id": "one", "query": "from:a.example.org", + "add": ["x"], "stage": 50, "enabled": true}, + {"id": "many", "query": + "from:a.example.org or from:b.example.org or from:c.example.org or from:d.example.org or from:e.example.org or from:f.example.org or from:g.example.org or from:h.example.org", + "add": ["y"], "stage": 50, "enabled": true} + ] + })"); + out.close(); + + TagRulesDialog dialog; + dialog.show(); + + dialog.selectRuleForTest(0); + // The row widgets are created during the select and their size hints are + // not valid until the layout has run, which needs the event loop: without + // this the builder reports the same height for one row and for eight, and + // the test passes against the bug. + QCoreApplication::processEvents(); + QCOMPARE(dialog.rowCountForTest(), 1); + const int withOneRow = dialog.heightDemandedBelowListForTest(); + + dialog.selectRuleForTest(1); + QCoreApplication::processEvents(); + // Guard: the fixture must actually produce the many-row case, or this + // test passes by measuring the same rule twice. + QCOMPARE(dialog.rowCountForTest(), 8); + const int withEightRows = dialog.heightDemandedBelowListForTest(); + + // Seven extra rows at roughly 30px each would be over 200px of growth. + // A small increase is fine (the scroll area still has a minimum), a + // proportional one is the bug. + QVERIFY2(withEightRows - withOneRow < 100, + qPrintable(QStringLiteral("one row demands %1, eight demand %2") + .arg(withOneRow).arg(withEightRows))); + + // And the rows are CAPPED, not merely allowed to grow inside a scroll + // area that has no ceiling. Asserted separately because removing the cap + // leaves the assertion above green: the editor's minimum stays flat + // either way, so only the visible height of the row area distinguishes + // them. Without a cap a thirty-sender rule fills the window again, this + // time scrolling instead of squeezing. + QVERIFY2(dialog.conditionAreaHeightForTest() <= 200, + qPrintable(QStringLiteral("condition area is %1px tall") + .arg(dialog.conditionAreaHeightForTest()))); +} + QTEST_MAIN(TestTagRules) #include "test_tagrules.moc" |
