summaryrefslogtreecommitdiffstats
path: root/src/threadlistview.h
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-08 10:35:06 +0200
committerDanilo M. <danix@danix.xyz>2026-08-10 08:23:23 +0200
commit5487d581069333a64e0e0480f53f06a7b64e486d (patch)
tree5471690779c57324cd40fec1a7369c846a9b8f34 /src/threadlistview.h
parentc80c060a593fb802f7149223d0d2f8495bc1f443 (diff)
downloadqtmaildir-5487d581069333a64e0e0480f53f06a7b64e486d.tar.gz
qtmaildir-5487d581069333a64e0e0480f53f06a7b64e486d.zip
refactor(view): make ThreadListView a QTreeView for message rows
The strip survived the port because every geometry call it needs exists on both classes. What did not survive is anything keyed on a row NUMBER: a tree numbers rows per parent, so row 0 exists once per expanded thread and the old flat 0..N walk would paint the first thread's strip over every one of them. The walk now goes by index, and the alternating colour follows visual position rather than index.row() for the same reason. QTableView::isRowSelected(int) has no QTreeView equivalent; isSelected on the index replaces it. MainWindow loses verticalHeader and selectRow, so row height comes from uniformRowHeights and three helpers replace the row arithmetic. next_thread and prev_thread now resolve the containing thread first: in a tree current.row() + 1 is the next SIBLING, which under an expanded thread is the next reply, not the next thread. Two test defects found by mutation and worth recording, since both produced a green suite over a broken assertion: The indent test asserted on column 0. A QTreeView indents only the column holding the expander, verified against Qt 6.11: with setTreePosition(4), column 0 reports the same left edge for a thread and its reply while column 4 reports 420 against 440. It was failing against a correctly indented tree. The strip test passed with the view's skip deleted, because the real model already returns no pills for a child row, so the view's guard was never the thing under test. It now runs against a stub model that hands pills to every row, which leaves the view's skip as the only thing that can keep replies clean. That rewrite then failed for a third reason: without the delegates MainWindow installs, rows take the default height, the band is measured against SubjectDelegate::rowHeightFor and overflows into the row below, and the thread's own strip paints across the reply. Reads exactly like a missing skip and is not one.
Diffstat (limited to 'src/threadlistview.h')
-rw-r--r--src/threadlistview.h18
1 files changed, 15 insertions, 3 deletions
diff --git a/src/threadlistview.h b/src/threadlistview.h
index 0b4eafc..520d610 100644
--- a/src/threadlistview.h
+++ b/src/threadlistview.h
@@ -18,7 +18,7 @@
#pragma once
-#include <QTableView>
+#include <QTreeView>
/// The thread list, with a row-wide strip of tag chips under each row's cells.
///
@@ -36,11 +36,23 @@
/// The cells confine themselves to the upper band so the lower one is free;
/// SubjectDelegate::kRowPadding and rowHeightFor() are the shared measurements
/// that keep the two halves agreeing.
-class ThreadListView : public QTableView
+///
+/// A QTreeView rather than a QTableView since item 20: a thread's replies are
+/// child rows, and a table can neither indent nor expand. The strip survived
+/// the port because every geometry call it needs (visualRect,
+/// columnViewportPosition, indexAt, indexBelow) exists on both. What did NOT
+/// survive is anything keyed on a row NUMBER: a tree numbers rows per parent,
+/// so row 0 exists once per expanded thread and a flat 0..N walk paints the
+/// first thread's strip over every one of them. The walk below goes by index.
+///
+/// The strip is painted for THREAD rows only. It carries the thread's tags, so
+/// one under each reply would stripe the list and repeat identical tags down
+/// the whole expansion.
+class ThreadListView : public QTreeView
{
Q_OBJECT
public:
- using QTableView::QTableView;
+ using QTreeView::QTreeView;
protected:
void paintEvent(QPaintEvent *event) override;