feat: conversation grouping by default (Wino-style) + flatten single-mail threads

- MailListView: default group mode = GroupByThread (was None)
  - robustly applied at EmailTreeModel creation (avoids timing crash)
  - guard onGroupByChanged against null model
- EmailTreeModel.buildThreads: single-message 'threads' now shown as plain
  mail rows under root (no expander/nesting), matching Wino/Outlook behavior;
  only real 2+ message conversations render as collapsible thread groups
This commit is contained in:
2026-08-30 03:20:42 +02:00
parent 11e939b68f
commit 391055e6a1
2 changed files with 16 additions and 1 deletions
+6 -1
View File
@@ -149,6 +149,8 @@ void MailListView::setupUI()
); );
connect(m_groupByCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), connect(m_groupByCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &MailListView::onGroupByChanged); this, &MailListView::onGroupByChanged);
// Default to conversation grouping (Wino-style), index 2 = GroupByThread
m_groupByCombo->setCurrentIndex(2);
filterLayout->addWidget(m_groupByCombo); filterLayout->addWidget(m_groupByCombo);
layout->addWidget(filterBar); layout->addWidget(filterBar);
@@ -244,6 +246,8 @@ void MailListView::setupUI()
); );
m_treeModel = new EmailTreeModel(this); m_treeModel = new EmailTreeModel(this);
// Wino-style default: group inbox by conversation (thread)
m_treeModel->setGroupMode(EmailTreeModel::GroupByThread);
m_proxyModel = new QSortFilterProxyModel(this); m_proxyModel = new QSortFilterProxyModel(this);
m_proxyModel->setSourceModel(m_treeModel); m_proxyModel->setSourceModel(m_treeModel);
m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
@@ -528,6 +532,7 @@ void MailListView::onFilterChanged()
void MailListView::onGroupByChanged(int index) void MailListView::onGroupByChanged(int index)
{ {
if (!m_treeModel) return;
switch (index) { switch (index) {
case 0: // Sin agrupación case 0: // Sin agrupación
m_treeModel->setGroupMode(EmailTreeModel::NoGrouping); m_treeModel->setGroupMode(EmailTreeModel::NoGrouping);
@@ -542,7 +547,7 @@ void MailListView::onGroupByChanged(int index)
m_treeModel->setGroupMode(EmailTreeModel::GroupBySender); m_treeModel->setGroupMode(EmailTreeModel::GroupBySender);
break; break;
} }
m_treeView->expandAll(); if (m_treeView) m_treeView->expandAll();
} }
void MailListView::onDisplayModeChanged(int index) void MailListView::onDisplayModeChanged(int index)
+10
View File
@@ -465,6 +465,16 @@ void EmailTreeModel::buildThreads()
return dateA < dateB; // Oldest first return dateA < dateB; // Oldest first
}); });
if (sortedIndices.size() == 1) {
// A single-message "thread" isn't a real conversation — add it as a
// plain Mail row directly under root (no expander, no nesting).
TreeItem* mailItem = new TreeItem(TreeItem::Mail, m_rootItem);
mailItem->mailIndex = sortedIndices.first();
mailItem->row = m_rootItem->children.size();
m_rootItem->children.append(mailItem);
continue;
}
TreeItem* threadItem = new TreeItem(TreeItem::Thread, m_rootItem); TreeItem* threadItem = new TreeItem(TreeItem::Thread, m_rootItem);
threadItem->threadId = threadId; threadItem->threadId = threadId;
threadItem->groupIndex = threadIdx++; threadItem->groupIndex = threadIdx++;