diff options
| author | Danilo M. <danix@danix.xyz> | 2026-08-03 14:57:11 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-08-03 14:57:11 +0200 |
| commit | 1371a3901857a8d2ac4fcf235fb29e7caaf63cae (patch) | |
| tree | ef8c08db29a7ce6b4052e6533c4f66b8f5a258bf /src/threadlistmodel.cpp | |
| parent | 95d0d19a4c1323a4839c1544f3bc1c0323f85dd9 (diff) | |
| download | qtmaildir-1371a3901857a8d2ac4fcf235fb29e7caaf63cae.tar.gz qtmaildir-1371a3901857a8d2ac4fcf235fb29e7caaf63cae.zip | |
feat: show that a tag action landed
Selecting a thread and hitting Delete changed nothing on screen, so
there was no way to tell the action had stuck.
The tag was always applied: applyTagChange() emitted dataChanged across
the row, and the Tags column did update. But Subject was set to stretch
while Tags came after it, so Subject took all free width and pushed Tags
out of view. The feedback lived in the one column that could not be seen.
Columns are now Tags, Date, From, Subject, with Subject stretching last
so nothing can be pushed off the right edge. A thread tagged deleted or
spam fills its whole row, muted red or orange with white struck-through
text, through the background, foreground and font roles, so no cue
depends on one column remaining visible.
Strike-through accompanies the fill on purpose: it survives a theme that
overrides backgrounds and reads without colour. Bold for unread still
composes with it.
Archive adds no tag, so an archived row is left unstyled for now.
Diffstat (limited to 'src/threadlistmodel.cpp')
| -rw-r--r-- | src/threadlistmodel.cpp | 46 |
1 files changed, 43 insertions, 3 deletions
diff --git a/src/threadlistmodel.cpp b/src/threadlistmodel.cpp index c129be1..a083145 100644 --- a/src/threadlistmodel.cpp +++ b/src/threadlistmodel.cpp @@ -18,8 +18,24 @@ #include "threadlistmodel.h" +#include <QBrush> #include <QFont> +QColor ThreadListModel::deletedColour() +{ + // Desaturated crimson: legible under white text on a dark theme, and calm + // enough that deleting fifty threads does not repaint the list as a + // warning banner. + return QColor(0x8b, 0x2c, 0x2c); +} + +QColor ThreadListModel::spamColour() +{ + // Distinct hue rather than a lighter red, so spam and deleted are told + // apart by colour and not by shade. + return QColor(0xa8, 0x5c, 0x18); +} + ThreadListModel::ThreadListModel(QObject *parent) : QAbstractTableModel(parent) { @@ -67,10 +83,34 @@ QVariant ThreadListModel::data(const QModelIndex &index, int role) const } } - if (role == Qt::FontRole && thread.isUnread()) { + // A thread tagged deleted or spam is on its way out, and the user needs to + // see that the moment they act. Every one of these roles applies to the + // whole row: a cue on a single column disappears as soon as that column + // scrolls out of view, which is exactly how the tag change used to go + // unnoticed. + if (thread.isDoomed()) { + if (role == Qt::BackgroundRole) + return QBrush(thread.isDeleted() ? deletedColour() : spamColour()); + if (role == Qt::ForegroundRole) + return QBrush(QColor(Qt::white)); + } + + if (role == Qt::FontRole) { QFont font; - font.setBold(true); - return font; + bool styled = false; + if (thread.isUnread()) { + font.setBold(true); + styled = true; + } + // Struck through as well as filled, so the state survives a + // screenshot, a colourblind reader, and a theme that overrides the + // background. + if (thread.isDoomed()) { + font.setStrikeOut(true); + styled = true; + } + if (styled) + return font; } return {}; |
