feat: Search Online (IMAP) + real Calendar/Contacts UI + iCloud auth wiring

Search Online:
- Synchronizer::searchOnline(folderId, query) virtual with default {}
- ImapSynchronizer: SELECT + UID SEARCH (Subject/From/To/TEXT) + fetch results
- MailService::searchOnline() + onlineSearchFinished/onlineSearchError signals
- MainMainWindow::onOnlineSearchRequested shows real server results

Calendar:
- Real QCalendarWidget view with per-day agenda from local mails
- New MailItemDao::findByDateRange(start, end)

Contacts:
- QTableWidget aggregating addresses from all local mails
- Regex email extraction + live search filter

iCloud/AccountService:
- Wire IcloudAuthenticator into AccountService::createAuthenticator
This commit is contained in:
2026-08-30 01:46:34 +02:00
parent d86df8ce51
commit 59692b5706
61 changed files with 1018 additions and 115 deletions
+19 -4
View File
@@ -326,9 +326,17 @@ void MailListView::setupUI()
connect(m_compactDelegate, &CompactMailDelegate::markUnreadRequested,
this, &MailListView::onCompactMarkUnreadRequested);
// Same proxy model for list view (single column)
m_listView->setModel(m_proxyModel);
m_listView->setModelColumn(0); // Use first column (subject)
// List view uses source model (EmailListModel) directly for proper roles
// NOT the proxy model that wraps EmailTreeModel
m_listView->setModel(m_sourceModel);
// For selection handling, we need a proxy to support single-column list view
m_listProxyModel = new QSortFilterProxyModel(this);
m_listProxyModel->setSourceModel(m_sourceModel);
m_listProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
m_listProxyModel->setFilterKeyColumn(-1); // Filter all columns
m_listView->setModel(m_listProxyModel);
m_listView->setModelColumn(0); // Use first column
connect(m_listView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &MailListView::onSelectionChanged);
@@ -362,6 +370,11 @@ void MailListView::setModel(EmailListModel *model)
connect(m_treeView->verticalScrollBar(), &QScrollBar::valueChanged, this, &MailListView::onTreeViewScrolled);
connect(m_listView->verticalScrollBar(), &QScrollBar::valueChanged, this, &MailListView::onListViewScrolled);
// Update list proxy model with new source model
if (m_listProxyModel) {
m_listProxyModel->setSourceModel(model);
}
// Initial population
refreshViews();
}
@@ -375,7 +388,9 @@ void MailListView::refreshViews()
m_treeModel->setEmails(emails);
m_treeView->expandAll();
// List view uses same proxy model, just refresh
// List view uses m_listProxyModel which wraps m_sourceModel directly
// Just refresh the view to reflect any data changes
m_listProxyModel->invalidate();
m_listView->update();
}