aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/carddelegate.cpp16
-rw-r--r--src/mainwindow.cpp17
-rw-r--r--src/threadlistmodel.cpp123
-rw-r--r--src/threadlistmodel.h32
4 files changed, 23 insertions, 165 deletions
diff --git a/src/carddelegate.cpp b/src/carddelegate.cpp
index 2dd29a2..d0ee957 100644
--- a/src/carddelegate.cpp
+++ b/src/carddelegate.cpp
@@ -425,17 +425,11 @@ void CardDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
: ThreadListModel::PillColoursRole)
.toList();
- // A thread card draws its own tags at full size and the rest of the
- // conversation's smaller and muted (item 111). The count is where the two
- // tiers meet; a message row has no such split and reports its whole list.
- //
- // Shown rather than dropped, at the user's request: a card sits above a
- // conversation, so what its siblings carry is worth seeing, just not at
- // the same weight. Before the row has been opened everything is in the own
- // tier, so a chip SHRINKS when the split becomes known and none vanishes.
- const int ownCount =
- isMessage ? tags.size()
- : index.data(ThreadListModel::PillOwnCountRole).toInt();
+ // One tier since item 177: a conversation row draws the thread's own tags
+ // and a message row draws its message's, so nothing on a card belongs to
+ // anything but the row. The sibling tier this switched fonts at is Task
+ // 3's to remove.
+ const int ownCount = tags.size();
const QFont ownFont = CardLayout::smallFont(chrome.font);
const QFont siblingFont = CardLayout::siblingFont(chrome.font);
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 231a9a5..b64e20b 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -4058,21 +4058,8 @@ void MainWindow::onMessageLoaded(const QVector<MessageRef> &messages,
return;
// The worker's answer is the authority on what THIS message carries, and
- // it is the only place that truth arrives. Until it does, a thread row can
- // only offer ThreadSummary::tags, which is notmuch's union over the
- // conversation: a four-message thread whose third message is signed makes
- // the root card and the pane both claim `signed` for a message that is not
- // (item 110). Recording it here corrects the card and gives a
- // message-scoped write something to update, which is why marking a root
- // message read left the row bold before.
- //
- // A reply already has its own node from the thread tree, and
- // setRootMessageTags ignores anything that is not a root.
- for (const MessageRef &ref : messages)
- m_model->setRootMessageTags(ref.messageId, ref.tags);
-
- // The pane follows the same correction. setTags() at selection time can
- // only have used the union.
+ // the pane shows one message. setTags() at selection time can only have
+ // used the thread's union.
if (messages.size() == 1)
m_messageView->setTags(messages.first().tags);
diff --git a/src/threadlistmodel.cpp b/src/threadlistmodel.cpp
index 1bda728..4a75d47 100644
--- a/src/threadlistmodel.cpp
+++ b/src/threadlistmodel.cpp
@@ -503,24 +503,13 @@ QVariant ThreadListModel::data(const QModelIndex &index, int role) const
const ThreadNode &rowNode = m_threads.at(index.row());
- // A card stands for ONE message since item 108, so it must draw that
- // message's tags and not the thread's. `ThreadSummary::tags` is notmuch's
- // UNION over the conversation: a four-message thread whose third message
- // is signed reads as signed, and the card said so about a message that was
- // not (item 110).
- //
- // Only the tags are substituted. Everything else on the card, the subject,
- // the authors, the date and the reply count, describes the THREAD and is
- // correct as it stands; only the tags were ever the union that lied.
- //
- // `first.tags` is populated when the message is loaded, which is when the
- // user selects the row. Before that the union is the only answer available
- // and is what the card shows, which is why an unopened row can still
- // display a sibling's mark. Narrowing that further needs per-message state
- // in the query itself.
- ThreadSummary thread = rowNode.summary;
- if (!rowNode.first.messageId.isEmpty())
- thread.tags = rowNode.first.tags;
+ // The row IS the conversation since item 177, so `ThreadSummary::tags`,
+ // notmuch's UNION over it, is simply what the row means. Items 110 and 111
+ // substituted the displayed message's tags here and drew the rest in a
+ // muted second tier, to reconcile "this card shows one message" with "this
+ // row is a thread"; the first half of that is gone, so the whole apparatus
+ // is.
+ const ThreadSummary &thread = rowNode.summary;
if (role == ThreadIdRole)
return thread.threadId;
@@ -566,8 +555,7 @@ QVariant ThreadListModel::data(const QModelIndex &index, int role) const
if (role == MessageOwnColoursRole)
return QVariantList();
- if (role == PillTagsRole || role == PillColoursRole
- || role == PillOwnCountRole) {
+ if (role == PillTagsRole || role == PillColoursRole) {
// Everything the row already says another way is dropped: the account
// is the chip in the subject cell, flagged is the star column,
// attachment is the paperclip, unread is the row not being dimmed, and
@@ -601,28 +589,8 @@ QVariant ThreadListModel::data(const QModelIndex &index, int role) const
return pills;
};
- // `thread.tags` is the displayed message's own tags once the row has
- // been opened, and the thread's union before that (see the
- // substitution above). The union is always the full set, so the
- // difference is what belongs only to siblings.
- QStringList pills = pillsFrom(thread.tags);
- const int ownCount = pills.size();
-
- // The sibling tier, appended after the message's own. Shown rather
- // than dropped at the user's request: a card sits above a
- // conversation, so what the rest of it carries is worth seeing, just
- // not at the same weight. The delegate draws these smaller and muted.
- //
- // Empty until the row has been opened, because before that
- // `thread.tags` IS the union and the difference is nothing. That is
- // what makes a chip shrink rather than appear.
- for (const QString &tag : pillsFrom(rowNode.summary.tags)) {
- if (!pills.contains(tag))
- pills.append(tag);
- }
-
- if (role == PillOwnCountRole)
- return ownCount;
+ // One tier: the thread's own tags, which is what the row stands for.
+ const QStringList pills = pillsFrom(thread.tags);
if (role == PillTagsRole)
return pills;
@@ -799,22 +767,11 @@ QVariant ThreadListModel::data(const QModelIndex &index, int role) const
ThreadListModel::ThreadNode
ThreadListModel::nodeFor(const ThreadSummary &summary)
{
- ThreadNode node{ summary, {}, {}, false };
-
- // Only when the query actually supplied them. An empty list here would be
- // indistinguishable from "this message carries nothing", which would put
- // every chip in the sibling tier and mute the whole card.
- if (!summary.firstMessageId.isEmpty()
- && !summary.firstMessageTags.isEmpty()) {
- node.first.messageId = summary.firstMessageId;
- node.first.threadId = summary.threadId;
- node.first.tags = summary.firstMessageTags;
- // Carried alongside the tags, for the same reason messageById()
- // carries it onto a synthesised root: an unexpanded row has to know
- // which account it belongs to before Delete can name a folder.
- node.first.filePath = summary.firstMessagePath;
- }
- return node;
+ // No `first` node. A conversation row stands for the thread and draws the
+ // union; a one-message row's message arrives with its children like any
+ // other. Seeding it here is what made a row an ambiguous half-message
+ // (item 177).
+ return ThreadNode{ summary, {}, {}, false };
}
void ThreadListModel::appendBatch(const QVector<ThreadSummary> &batch)
@@ -926,26 +883,8 @@ void ThreadListModel::reconcile(const QVector<ThreadSummary> &threads)
|| m_threads.at(row).summary.authors != summary.authors
|| m_threads.at(row).summary.date != summary.date
|| m_threads.at(row).summary.totalCount != summary.totalCount
- || m_threads.at(row).summary.matchedCount != summary.matchedCount
- // The card's OWN message, which can move while the thread's union
- // does not: a root read elsewhere leaves the thread unread as long
- // as any reply is. Without this the card kept the tags it was
- // first given, and the sibling tier with them.
- || m_threads.at(row).summary.firstMessageTags
- != summary.firstMessageTags) {
+ || m_threads.at(row).summary.matchedCount != summary.matchedCount) {
m_threads[row].summary = summary;
-
- // The node too, since the card draws its tags from there. Only the
- // tags: the node's children and loaded flag are the expansion
- // state this whole method exists to preserve, and `first` carries
- // no children.
- if (!summary.firstMessageId.isEmpty()
- && !summary.firstMessageTags.isEmpty()) {
- m_threads[row].first.messageId = summary.firstMessageId;
- m_threads[row].first.threadId = summary.threadId;
- m_threads[row].first.tags = summary.firstMessageTags;
- }
-
emit dataChanged(index(row, 0), index(row, 0));
}
}
@@ -1064,36 +1003,6 @@ QString ThreadListModel::threadIdForMessage(const QString &messageId) const
return {};
}
-void ThreadListModel::setRootMessageTags(const QString &messageId,
- const QStringList &tags)
-{
- if (messageId.isEmpty())
- return;
-
- for (int row = 0; row < m_threads.size(); ++row) {
- ThreadNode &node = m_threads[row];
- if (node.summary.firstMessageId != messageId
- && node.first.messageId != messageId) {
- continue;
- }
-
- if (node.first.tags == tags && !node.first.messageId.isEmpty())
- return; // Nothing changed; do not churn the view.
-
- // Enough of a node for the card to draw from. The rest of the display
- // still comes from the summary, which is correct for it: the subject,
- // the authors and the date describe the thread, and only the TAGS were
- // ever the union that lied about this message.
- node.first.messageId = messageId;
- node.first.threadId = node.summary.threadId;
- node.first.tags = tags;
-
- const QModelIndex threadIndex = index(row, 0, QModelIndex());
- emit dataChanged(threadIndex, threadIndex);
- return;
- }
-}
-
MessageNode ThreadListModel::messageById(const QString &messageId) const
{
if (messageId.isEmpty())
diff --git a/src/threadlistmodel.h b/src/threadlistmodel.h
index d1baae1..5cd1392 100644
--- a/src/threadlistmodel.h
+++ b/src/threadlistmodel.h
@@ -74,21 +74,6 @@ public:
/// config itself would be a second source of truth.
PillColoursRole,
- /// How many of PillTagsRole's entries belong to the message the card
- /// DISPLAYS, the rest belonging only to its siblings.
- ///
- /// The card stands for one message but sits above a conversation, so
- /// it shows both: the message's own tags first at full size, then the
- /// thread's other tags smaller and muted. Without the split a card
- /// either claimed a sibling's tag as its own (item 110) or dropped it
- /// and looked like it had lost information.
- ///
- /// Equals the whole list until the row has been opened, since the
- /// per-message tags arrive with the message load and before that the
- /// union is the only answer there is. Chips therefore SHRINK when the
- /// split becomes known; none ever disappears.
- PillOwnCountRole,
-
/// True when the row is a MESSAGE row rather than a thread root.
/// Drives both the action scope and whether the view paints a tag
/// strip under the row.
@@ -341,23 +326,6 @@ public:
/// message the user could select is always findable here.
QString threadIdForMessage(const QString &messageId) const;
- /// Records the tags a MESSAGE really carries, as the worker reported them.
- ///
- /// Exists because `ThreadSummary::tags` is notmuch's UNION over the
- /// thread, which is right for a card standing for a conversation and wrong
- /// for one standing for a message. A four-message thread whose third
- /// message is signed makes the whole thread read as signed, so the root
- /// card and the message pane both claimed a tag the displayed message did
- /// not have.
- ///
- /// Only the ROOT needs this: reply rows already carry their own nodes from
- /// setThreadMessages. Calling it for anything else is a no-op.
- ///
- /// The thread's summary is deliberately NOT rewritten. It describes the
- /// conversation, and three unread siblings do not stop being unread
- /// because this message was read.
- void setRootMessageTags(const QString &messageId, const QStringList &tags);
-
/// A loaded message row's node, found by id rather than by position.
///
/// For callers that know WHICH message they mean and must not depend on it