From 01ea9e9d7df04dc771430e4c378202b8ef37b8db Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Tue, 25 Aug 2026 09:54:10 +0200 Subject: feat(compose): report autosave state in a status bar Autosave worked and said nothing on success. The only feedback was m_banner, which is the failure channel and whose persistence is load-bearing for the quit path, so success got its own channel rather than sharing one. The fix is a funnel, not a label. m_dirty had seven writers, four of which clear it and only two of those are a save: the constructor clears it because seeding is not an edit, and the send handler clears it because the message is gone. A cue hung off saveDraftNow() would have been silently wrong in both. setDirty() is the only writer now, and it refreshes the status cue and setWindowModified() together so neither display can drift from the flag. The age line needs a tick of its own, since it moves with no edit to drive it. Five seconds against a label that reads in tens of them. Two defects found by probing rather than by reading. The %n plural rendered as "2 minute(s) ago" for every English user, because Qt picks a plural form only when a translation supplies the forms and there is no English .ts; it uses %1 and "min" now, which Italian substitutes identically. And the status mark was inside the translatable string, where a translator could drop it; it is concatenated outside tr(). Presentation reworked after the user looked at it. The first version reused item 151's yellow ribbon treatment, which reads as a misplaced widget on a bare status label rather than as a warning, and put both labels in the permanent widget area, which is the right-hand tray. They are ordinary status text on the left now. onlyTheSetterWritesTheDirtyFlag() asserts the funnel structurally, by reading composewindow.cpp: the first test for the send path called markClean() directly and a mutation restoring a direct assignment left the whole suite green. Four mutations now fail. The suite still cannot see the presentation, which is why that half needed a hand test. lrelease reports 487 finished, 0 unfinished. Closes item 160, and unblocks 161. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01UUQS6n3cmsFrsjCNmwNtf8 --- tests/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'tests/CMakeLists.txt') diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5938aeb..830e2b2 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -85,6 +85,12 @@ add_qtmaildir_test(translations) target_compile_definitions(test_translations PRIVATE TRANSLATIONS_DIR="${CMAKE_SOURCE_DIR}/translations") +# One test reads composewindow.cpp itself, to assert that m_dirty has a single +# writer. The property is structural, so no runtime probe can see it: a +# mutation restoring a direct assignment in the send path left the suite green. +target_compile_definitions(test_composewindow PRIVATE + SOURCE_DIR="${CMAKE_SOURCE_DIR}") + # The notmuch hooks (assets/hooks/), which are Python rather than C++ and are # therefore registered directly rather than through add_qtmaildir_test(). # -- cgit v1.2.3