aboutsummaryrefslogtreecommitdiffstats
path: root/.gitignore
AgeCommit message (Collapse)AuthorFilesLines
4 daysfeat(hooks): own the notmuch hooks, and keep sent mail out of the inboxDanilo M.1-0/+3
The post-new hook and its rule store move here from the companion mailctl project, which is being retired. Nothing else was shared between the two, so this is a plain move: mailrules.py is stdlib-only and post-new imports only it. With that in hand, the hook learns the one thing it could not know before. notmuch's new.tags applies `inbox` to every file it indexes, and it cannot tell an arrival from the copy this application files into a sent folder after a send, so sent mail turned up in the inbox view and in any hand-typed tag:inbox search. Drafts arrived the same way, through the composer's autosave. 786 messages were affected on the developer's own index. qtmaildirconf.py reads the sent and drafts folders out of qtmaildir.conf, so adding an account fixes itself. Reading the application's own config is not the cross-repo coupling it would have been last week: this repo owns the hook now. Three properties are load-bearing: - it is NOT a relaxation of PROTECTED_REMOVALS, which is about a rule removing `inbox` from mail whose provenance the hook cannot judge. Here the provenance is the file's own path, and `inbox` was never true of it. - only `inbox`. maildir.synchronize_flags is true, so removing `unread` would rewrite Maildir filenames and reach the server on the next mbsync. - an empty folder list means NOTHING, never an empty query, which notmuch reads as "match everything". A system with no qtmaildir config must be left alone rather than have every new message stripped. Trash is deliberately not in the list: Delete leaves `inbox` on a trashed message so Restore can put it back where it came from. The three Python suites run under ctest rather than beside it as scripts someone remembers to run, since this code tags real mail unattended on every sync. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q2koFevoSxTLhfexJTZWQd
12 daysfeat(i18n): wire translations and ship an Italian one (item 22)Danilo M.1-0/+3
Nothing loaded a translation before this: no QTranslator, no .ts file and no build rule, so every string was English whatever the locale said. The language now comes from the environment, LANG=it_IT.UTF-8, and any other locale runs in English as before. The audit found that the tr() discipline was largely holding, and found eight strings that could never be translated into any language. kFields[] in tagrulesdialog.cpp declared the rule-builder field labels with QT_TR_NOOP inside an anonymous namespace, where lupdate reports "tr() cannot be called without context" and extracts nothing, while the use site calls TagRulesDialog::tr() on them at runtime. From, To, Cc, Subject, Tag, Folder, Attachment and Date: the whole vocabulary of the rule builder, absent from every translation file that could ever exist. The source compiles and reads correctly; only lupdate reveals it. Q_DECLARE_TR_FUNCTIONS is not the fix for that case, though it is the fix for a free function calling tr(). Measured against lupdate: a class carrying the macro beside the array still extracts 0 strings, because the context must be attached to the literal itself. QT_TRANSLATE_NOOP names it explicitly and matches the tr() that already reads them, so the use site needed no change. Twenty configuration and keybinding warnings were not translatable either. They are user-facing, reaching the status label and the "Configuration problems" dialog. Config already had the tr() macro; KeyMap needed it. Translating the filter labels then broke startup_query, found in hand testing: a filter's name is a translated label, so `startup_query = Inbox` matched nothing where the filter shows as "In arrivo". The application opened a different view and reported the user's own working config as invalid. Resolution matches the generator as well now, which is stored in queries.json and identical in every locale; the translated name still works. The regression test installs a real QTranslator rather than a stub, since the bug lives in the gap between the stored string and the displayed one, and it writes a queries.json because the warning it asserts on is guarded by a non-empty saved-query list: without one the branch never runs and the test passes against a broken check. main.cpp's --help and --version stay bare printf, as they run before QApplication exists and no translator could serve them. Verified per the backlog's own standard, that lupdate output is the evidence rather than reading: 355 strings extracted with zero context warnings, where before there were 327 with eight; lrelease reporting 355 finished and 0 unfinished; the built .qm loaded in a standalone probe printing "From -> Da" and both Italian plural forms; and the install rule placing it where main.cpp looks. test_translations guards it and was mutation checked, failing on an emptied translation and naming the defect when QT_TRANSLATE_NOOP is reverted. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04docs: add qtmaildir v1 design specDanilo M.1-0/+3
Qt6/notmuch mail client, GUI counterpart to neomutt. Read and organize only in v1; compose and send deferred to v2. Key decisions and their reasoning are recorded in the spec: C++/Qt6 over PySide6, QtWebEngine over QTextDocument for HTML mail, GMime for parsing, direct libnotmuch rather than shelling out to mailctl, and calling the existing sync script rather than reimplementing it so qtmaildir stays inside the flock guard shared with the hourly cron sync. Dependency availability verified on the development machine: Qt6 6.11.1 (WebEngine included in the monolithic package), libnotmuch 0.39, GMime 3.2.15. Notably notmuch installs no notmuch.pc, so CMake must locate it without pkg-config. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>