diff options
| author | Danilo M. <danix@danix.xyz> | 2026-08-03 17:17:25 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-08-03 17:17:25 +0200 |
| commit | e45f68b04b5ee2400a7885d5f5b054a889061df5 (patch) | |
| tree | bcf0a90e65dd2a85665b83694fdf4a39bf97c565 /src/threadlistmodel.cpp | |
| parent | 7f505624b1f385a89c9ff32e15f4d4e68595e5b8 (diff) | |
| download | qtmaildir-e45f68b04b5ee2400a7885d5f5b054a889061df5.tar.gz qtmaildir-e45f68b04b5ee2400a7885d5f5b054a889061df5.zip | |
feat: show a paperclip for threads with attachments
An attachment was only discoverable by opening the thread. A narrow
leftmost column now marks the threads that carry one.
No new worker query is involved: notmuch applies the "attachment" tag
while indexing, so ThreadSummary already holds what this needs. The
marker is a glyph rather than an icon resource, which ships no new asset
and inherits the row font, so it strikes through with a doomed thread
like every other cell. It falls back to "*" where the system font cannot
draw U+1F4CE, since an unrenderable codepoint reads as breakage rather
than as a marker.
Two silent Qt behaviours had to be handled, both found by probe:
QHeaderView::restoreState() returns true for a blob saved against fewer
columns and applies the old widths shifted one place right. Adding a
column in front would therefore have mangled every existing saved
layout with no error to detect it by. The column count is now stored
beside the blob and a mismatch discards it, so the widths reset once on
upgrade instead of landing on the wrong columns.
QHeaderView's default minimumSectionSize is 58px on this platform, and
setColumnWidth() clamps to it without reporting the smaller value back,
so the column could not be narrow at all until it was lowered.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'src/threadlistmodel.cpp')
| -rw-r--r-- | src/threadlistmodel.cpp | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/src/threadlistmodel.cpp b/src/threadlistmodel.cpp index 2f2882e..2289e6c 100644 --- a/src/threadlistmodel.cpp +++ b/src/threadlistmodel.cpp @@ -20,6 +20,27 @@ #include <QBrush> #include <QFont> +#include <QFontDatabase> +#include <QFontMetrics> + +QString ThreadListModel::attachmentGlyph() +{ + // U+1F4CE PAPERCLIP, with a fallback for a system whose default font + // cannot draw it: an unrenderable codepoint shows as a tofu box, which + // reads as "something is broken" rather than "this has an attachment". + // Computed once; the font does not change under a running application. + static const QString glyph = [] { + const char32_t paperclip = 0x1F4CE; + const QString preferred = QString::fromUcs4(&paperclip, 1); + const QFontMetrics metrics{QFontDatabase::systemFont( + QFontDatabase::GeneralFont)}; + // "*" as the fallback: ASCII, present in every practical font, and + // unambiguous in a column that shows nothing else. + return metrics.inFontUcs4(paperclip) ? preferred + : QStringLiteral("*"); + }(); + return glyph; +} QColor ThreadListModel::deletedColour() { @@ -85,8 +106,19 @@ QVariant ThreadListModel::data(const QModelIndex &index, int role) const return {}; } + if (role == Qt::ToolTipRole && index.column() == AttachmentColumn) + return thread.hasAttachment() ? tr("Has an attachment") : QVariant(); + + if (role == Qt::TextAlignmentRole && index.column() == AttachmentColumn) + return QVariant::fromValue(Qt::AlignCenter); + if (role == Qt::DisplayRole) { switch (index.column()) { + case AttachmentColumn: + // A glyph rather than an icon resource: no new asset to ship, and + // it inherits the row's font, so it strikes through with a doomed + // thread like every other cell. + return thread.hasAttachment() ? attachmentGlyph() : QString(); case DateColumn: return thread.date.toString(QStringLiteral("yyyy-MM-dd hh:mm")); case AuthorsColumn: @@ -141,6 +173,9 @@ QVariant ThreadListModel::headerData(int section, Qt::Orientation orientation, return {}; switch (section) { + // No label: any text would set a minimum width far wider than the icon, + // which defeats the point of a narrow column. + case AttachmentColumn: return QString(); case DateColumn: return QStringLiteral("Date"); case AuthorsColumn: return QStringLiteral("From"); case SubjectColumn: return QStringLiteral("Subject"); |
