diff options
| author | Danilo M. <danix@danix.xyz> | 2026-08-09 09:45:32 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-08-09 09:45:32 +0200 |
| commit | 2e66bb8b66df016164d44bf72a2d53b8c4a67dde (patch) | |
| tree | bf4c154d21b2d998aa64104a00a5430f12aef365 /src | |
| parent | aa8f50d7f3455a3c4e9ad147283bd85f1d752fc9 (diff) | |
| download | qtmaildir-2e66bb8b66df016164d44bf72a2d53b8c4a67dde.tar.gz qtmaildir-2e66bb8b66df016164d44bf72a2d53b8c4a67dde.zip | |
feat(ui): icons on every action, and rename Flag to Important
Items 56 and 57, done together because both touch the action registry.
56. The complaint was inconsistency, not absence: eight of twenty-four
actions had themed icons, so two adjacent entries in one menu disagreed
and the toolbar laid out an empty slot for the other sixteen. The
themeIcons table now covers them all. The fifteen names added were
probed against a live icon theme first rather than taken from the
freedesktop spec on faith, and the existing null-icon guard still lets a
theme that lacks one fall back to text.
The second half of the note asked that buttons honour the desktop's
"Icon only" setting. They could not: the hardcoded setToolButtonStyle
overrode it whatever the user had chosen. It now reads
SH_ToolButtonStyle. Dropping the call entirely was tried and rejected,
since a bare QToolBar defaults to ToolButtonIconOnly rather than to the
platform hint, which ignores the setting just as thoroughly the other
way. This is a visible change: on a desktop set to "Icon only" the
toolbar now shows icons without text.
57. "Important" over "Starred", the user's pick; the Message menu
already has "Mark &spam", so "Starred" would have needed an accelerator
from inside the word. Changed the action text, its status tip, the undo
description and the star column's tooltip, which still read "Flagged".
The tag stays `flagged`. It is wire format that neomutt, the user's
saved queries and ThreadSummary::isFlagged() all read, and following the
label through to the tag would rewrite the mail store and desynchronise
every other tool over the same Maildir. The action name stays `flag`
too, since that is the key users write in [keys].
Four tests. everyActionCarriesAnIcon names every action missing one and
guards against passing on an empty list; it reported all sixteen before
the change. theImportantActionStillWritesTheFlaggedTag asserts on the
tag the model actually received, and mutating it to `important` fails
that test plus two pre-existing held-edit tests.
Also adds the changelog entry for the cron-sync indicator fix, which the
commit that made it omitted.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/mainwindow.cpp | 50 | ||||
| -rw-r--r-- | src/threadlistmodel.cpp | 5 |
2 files changed, 50 insertions, 5 deletions
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 96e2a79..865c691 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -681,9 +681,17 @@ void MainWindow::registerActions() tagSelected({ QStringLiteral("spam") }, { QStringLiteral("inbox") }, tr("Mark spam")); }); - addAction(QStringLiteral("flag"), tr("&Flag"), - tr("Add the flagged tag"), [this]() { - tagSelected({ QStringLiteral("flagged") }, {}, tr("Flag")); + // Item 57. The LABEL is "Important"; the action name and the tag are both + // still `flag`/`flagged`, deliberately. The name is what a user writes in + // the config's [keys] section, and `flagged` is a notmuch tag that neomutt, + // the user's saved queries and ThreadSummary::isFlagged() all read. Only + // the wording the user sees changes. + // + // &I rather than &S: the Message menu already has "Mark &spam", so + // "Starred" would have needed an accelerator from inside the word. + addAction(QStringLiteral("flag"), tr("&Important"), + tr("Mark the selected threads as important"), [this]() { + tagSelected({ QStringLiteral("flagged") }, {}, tr("Mark important")); }); addAction(QStringLiteral("toggle_unread"), tr("Toggle &unread"), tr("Toggle the unread tag"), [this]() { @@ -899,6 +907,14 @@ void MainWindow::buildMenus() // Standard names from the icon theme, so the buttons match the rest of the // desktop rather than shipping bespoke art. A theme that lacks one leaves // that action with text alone, which still works. + // Item 56: every registered action, not a subset. Eight of these carried an + // icon and sixteen did not, which reads worse than none having one: two + // adjacent entries in the same menu disagreed, and the toolbar's + // TextBesideIcon style laid out an empty slot for each of the sixteen. + // + // Names are freedesktop ones, and were probed against a real icon theme + // rather than taken from the spec on faith. A name the running theme lacks + // still degrades to text through the null check below. const QHash<QString, QString> themeIcons = { { QStringLiteral("sync"), QStringLiteral("mail-receive") }, { QStringLiteral("archive"), QStringLiteral("mail-mark-read") }, @@ -908,6 +924,23 @@ void MainWindow::buildMenus() { QStringLiteral("flag"), QStringLiteral("mail-mark-important") }, { QStringLiteral("quit"), QStringLiteral("application-exit") }, { QStringLiteral("focus_query"), QStringLiteral("edit-find") }, + + { QStringLiteral("next_thread"), QStringLiteral("go-down") }, + { QStringLiteral("prev_thread"), QStringLiteral("go-up") }, + { QStringLiteral("open_thread"), QStringLiteral("document-open") }, + { QStringLiteral("toggle_unread"), QStringLiteral("mail-mark-unread") }, + { QStringLiteral("mark_all_read"), QStringLiteral("mail-mark-read") }, + { QStringLiteral("edit_tags"), QStringLiteral("tag") }, + { QStringLiteral("complete_query"), QStringLiteral("edit-find-replace") }, + { QStringLiteral("select_all"), QStringLiteral("edit-select-all") }, + { QStringLiteral("clear_pane"), QStringLiteral("edit-clear") }, + { QStringLiteral("clear_selection"), QStringLiteral("edit-clear-all") }, + { QStringLiteral("toggle_html"), QStringLiteral("text-html") }, + { QStringLiteral("load_remote"), QStringLiteral("image-loading") }, + { QStringLiteral("message_details"), QStringLiteral("dialog-information") }, + { QStringLiteral("zoom_in"), QStringLiteral("zoom-in") }, + { QStringLiteral("zoom_out"), QStringLiteral("zoom-out") }, + { QStringLiteral("zoom_reset"), QStringLiteral("zoom-original") }, }; for (auto it = themeIcons.cbegin(); it != themeIcons.cend(); ++it) { QAction *action = m_actions.value(it.key()); @@ -945,7 +978,16 @@ void MainWindow::buildMenus() // unreadable as no toolbar. auto *toolBar = addToolBar(tr("Main")); toolBar->setObjectName(QStringLiteral("main_toolbar")); - toolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + // Item 56, second half: the user asked that buttons honour the desktop's + // "Icon only" setting. They cannot while this asserts a style of its own. + // Qt exposes the desktop's preference as SH_ToolButtonStyle, and a + // hardcoded setToolButtonStyle() overrides it whatever the user chose. + // + // Read rather than dropped entirely: with no call at all a QToolBar + // defaults to Qt::ToolButtonIconOnly rather than to the platform's hint, + // which would ignore the setting just as thoroughly in the other direction. + toolBar->setToolButtonStyle(static_cast<Qt::ToolButtonStyle>( + style()->styleHint(QStyle::SH_ToolButtonStyle, nullptr, toolBar))); QAction *syncAction = m_actions.value(QStringLiteral("sync")); // Carried over from the QPushButton this replaced: with no command // configured the control is disabled, and the tooltip is the only thing diff --git a/src/threadlistmodel.cpp b/src/threadlistmodel.cpp index c675488..4bafca8 100644 --- a/src/threadlistmodel.cpp +++ b/src/threadlistmodel.cpp @@ -189,8 +189,11 @@ QVariant ThreadListModel::data(const QModelIndex &index, int role) const if (role == Qt::ToolTipRole && index.column() == AttachmentColumn) return thread.hasAttachment() ? tr("Has an attachment") : QVariant(); + // "Important", matching the action's own wording (item 57). The underlying + // tag is still `flagged` and isFlagged() still tests for it; only what the + // user reads changed. if (role == Qt::ToolTipRole && index.column() == FlagColumn) - return thread.isFlagged() ? tr("Flagged") : QVariant(); + return thread.isFlagged() ? tr("Important") : QVariant(); // Both marker columns: a glyph reads as a marker only when it sits in the // middle of its column rather than against the text beside it. |
