aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mainwindow.cpp49
1 files changed, 34 insertions, 15 deletions
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 19bf3c2..434f5d0 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -5382,8 +5382,9 @@ void MainWindow::applySelectors(const LaunchSelectors &requested)
// the thread when its row arrives and selects it. Item 91's
// double-click already reuses it; this is the third caller.
//
- // The empty message id is meaningful to it: land on the ROOT row,
- // which is the thread's first message.
+ // The empty message id is meaningful to it: land on the thread's own
+ // row, the dashboard for a conversation and the message for a thread
+ // of one.
recoverStaleThread(selectors.threadId, QString());
// After the query, which clears it: this is that query's own miss.
m_launchMiss = tr("No thread matched '%1'.").arg(selectors.threadId);
@@ -5492,10 +5493,16 @@ void MainWindow::onRowDoubleClicked(const QModelIndex &index)
messageId = node.messageId;
} else {
threadId = m_model->data(index, ThreadListModel::ThreadIdRole).toString();
- // The thread's first message, so the pane opens on it rather than on
- // nothing. Empty is fine and means the same thing to the recovery: land
- // on the root, which IS that message.
- messageId = m_model->data(index, ThreadListModel::MessageIdRole).toString();
+ // A CONVERSATION row asks for the conversation, so no message is
+ // named and the recovery lands on the row itself, on the dashboard. A
+ // named message is always a message row to the recovery, which would
+ // open the root's own row instead.
+ //
+ // A thread of one is its message: named, so the pane opens on it.
+ // Empty is fine there too and means the same thing to the recovery.
+ if (!m_model->isConversationRow(index))
+ messageId =
+ m_model->data(index, ThreadListModel::MessageIdRole).toString();
}
if (threadId.isEmpty())
@@ -5600,18 +5607,31 @@ void MainWindow::applyPendingRecovery()
// happen before any attempt to find one.
m_threadView->expand(thread);
- // The thread's first message IS the root card rather than a child row:
- // setThreadMessages drops depth 0 because the root stands for it, so
- // looking for it among the children finds nothing and the selection
- // would silently land nowhere.
+ // A named message is ALWAYS a message row, never the conversation.
+ // The user's rule for --message: "we target ALWAYS the message. If
+ // that message is part of a thread we show it inside the thread, but
+ // still the message. If I want the thread there's --thread." The
+ // stale notice and a double-click on a message row mean the same.
+ //
+ // So the thread row answers for a message only when it is NOT a
+ // conversation: a thread of one is its message and has no child to
+ // select. A conversation carries its first message as child 0 since
+ // item 177 (setThreadMessages keeps it), so the root is found among
+ // the children below like any reply. Matching the conversation row on
+ // its own message id, as this did, landed on the dashboard.
+ //
+ // An empty id is the request for the thread itself: --thread, a
+ // double-click on a conversation row, a stale dashboard.
//
// selectRowAt(), not setCurrentIndex(): a current index without a
// selection is what QTreeView sets by itself on focus, and
// onThreadSelected() deliberately ignores that, so pointing at the row
// renders nothing and leaves the pane blank.
if (m_recoverMessageId.isEmpty()
- || m_model->data(thread, ThreadListModel::MessageIdRole).toString()
- == m_recoverMessageId) {
+ || (!m_model->isConversationRow(thread)
+ && m_model->data(thread, ThreadListModel::MessageIdRole)
+ .toString()
+ == m_recoverMessageId)) {
selectRowAt(thread);
m_recoverThreadId.clear();
m_recoverMessageId.clear();
@@ -5627,9 +5647,8 @@ void MainWindow::applyPendingRecovery()
// (`src/threadlistmodel.cpp`), so the root check above cannot match yet
// and returning here would leave the user looking at a collapsed thread
// and a blank pane until the replies happen to arrive. Selecting the
- // thread renders its first message immediately, which is the right
- // answer outright when that is what they were reading, and is refined
- // to the correct reply on the next pass when it is not.
+ // thread puts something on screen immediately, and it is refined to
+ // the named message's own row, the root's included, on the next pass.
//
// The target is deliberately NOT cleared: this pass is provisional.
if (m_model->rowCount(thread) == 0) {