aboutsummaryrefslogtreecommitdiffstats
path: root/src/carddelegate.h
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-10 08:37:22 +0200
committerDanilo M. <danix@danix.xyz>2026-08-10 08:37:22 +0200
commitecd363cd439442029229f45aa6db7d760cc41e1a (patch)
treeade7f1f1f545fdbcfe9f64976a9d4e2d31aa64ae /src/carddelegate.h
parentceaec34eb17d741536f91bad66876e94aad1c45d (diff)
downloadqtmaildir-ecd363cd439442029229f45aa6db7d760cc41e1a.tar.gz
qtmaildir-ecd363cd439442029229f45aa6db7d760cc41e1a.zip
feat(view): paint the whole card in one delegate
Replaces SubjectDelegate. The tag chips come home from the view: the strip was painted there only because a delegate cannot paint outside its column and the strip spanned all five, and with one column there is nothing to span. RowStyleDelegate is inherited rather than dropped. Its job survives the redesign: Qt resolves ForegroundRole into the palette's Text roles and prefers those over HighlightedText, so the read/unread dimming would win on a selected row and land as grey on the highlight. What it loses is the rest of its body, which aligned cells against a text band and centred two marker columns; both described a grid that no longer exists. A reply's Re: prefix is stripped here. Every reply repeating the thread's subject is the visual signature of a table of records, which is the thing item 53 is about. The account chip becomes a bar down the card's left edge, and the reply spines inherit its colour, so an expanded thread is bounded by one accent from its root to its last reply without a second line in the gutter. Neither uses the raw account colour: that colour is chosen to be a chip's fill with legible text on top, and the same value as a thin line has to be followable down an expansion without competing with the senders, so it is blended toward the palette's Base by the weight threadLineColour() already uses. A reply resolves its THREAD's colour by walking to the root, since AccountColourRole is empty on a message row and a neutral spine under an accented root would break the continuous edge. The build is red at this commit; the view and window still name the old delegate.
Diffstat (limited to 'src/carddelegate.h')
-rw-r--r--src/carddelegate.h68
1 files changed, 68 insertions, 0 deletions
diff --git a/src/carddelegate.h b/src/carddelegate.h
new file mode 100644
index 0000000..317c78a
--- /dev/null
+++ b/src/carddelegate.h
@@ -0,0 +1,68 @@
+/*
+ * qtmaildir - a Qt6 mail client for notmuch-indexed Maildirs
+ * Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include "tagchip.h"
+
+/// Paints a whole card: three lines, all of it, including the tag chips.
+///
+/// It replaces both SubjectDelegate and ThreadListView::paintEvent. The view
+/// used to paint the tag strip because a delegate cannot paint outside its
+/// column and the strip spanned all five; with one column there is nothing to
+/// span, so the strip comes home to the delegate and the view stops painting
+/// entirely. That removes the two failure modes CLAUDE.md records for the
+/// strip, a deleted row cut in half and every other row showing a bare stripe,
+/// both of which existed because the view had to re-honour alternating
+/// colours, the selection and BackgroundRole across cells it did not own.
+///
+/// Inherits RowStyleDelegate for its one job, which still matters: Qt resolves
+/// Qt::ForegroundRole into the palette's Text roles and then prefers those over
+/// HighlightedText, so the read/unread dimming would otherwise win on a
+/// selected row and land as grey on the highlight colour.
+class CardDelegate : public RowStyleDelegate
+{
+ Q_OBJECT
+public:
+ using RowStyleDelegate::RowStyleDelegate;
+
+ void paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const override;
+ QSize sizeHint(const QStyleOptionViewItem &option,
+ const QModelIndex &index) const override;
+
+ /// The expander's rect for a row, so the VIEW can hit-test a click without
+ /// duplicating the layout. The delegate draws it and the view owns the
+ /// click, because a delegate gets no click of its own without an editor.
+ static QRect expanderRectFor(const QStyleOptionViewItem &option,
+ const QModelIndex &index);
+
+ /// An account's colour as a thin LINE rather than as a chip's fill.
+ ///
+ /// Never use the raw account colour for the accent bar or the spine. That
+ /// colour is chosen to be a background with legible text drawn on top
+ /// (TagColors::textColourOn picks black or white against it). The same
+ /// colour as a few pixels of line on the pane's own background is a
+ /// different problem: it has to be followable down a long expansion
+ /// WITHOUT competing with the senders beside it, which is the constraint
+ /// threadLineColour() states and meets by blending 0.35 toward the
+ /// palette's text. This blends the account colour toward the palette's
+ /// Base by the same weight, keeping the hue that identifies the account
+ /// and dropping the saturation that would shout.
+ static QColor accentLineColour(const QColor &accountColour);
+};