feat: responsive compact mail view + folder unread badges
- CompactMailDelegate: card-based view for narrow panels (<420px) * Avatar with hash-based color, sender + date (relative format) * Subject line with attachment icon * Action buttons: flag, delete, category, more (context menu) * Unread highlight with light blue background + bold sender - MailListView: automatic switch between tree/table (wide) and list/cards (narrow) * QStackedWidget with QTreeView + QListView sharing same proxy model * resizeEvent threshold at 420px * Signals forwarded to MainMainWindow for actions - FolderTreeDelegate: custom paint for folder tree * Unread count badge (blue pill) right-aligned on folder nodes * Account nodes bold, folder nodes normal weight * Proper indentation per depth level - MailItemDao::countUnreadByFolderId() for real-time unread counts - MainMainWindow handlers for compact actions (flag, delete, category, more menu)
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
#include "services/rulesengine.h"
|
||||
#include "ui/rulesmanagerdialog.h"
|
||||
#include "ui/accountsetupdialog.h"
|
||||
#include "ui/delegates/FolderTreeDelegate.h"
|
||||
#include <optional>
|
||||
#include <QMessageBox>
|
||||
#include <QFileDialog>
|
||||
@@ -227,6 +228,7 @@ void MainMainWindow::setupMailPage()
|
||||
m_folderTree->setMaximumWidth(350);
|
||||
m_folderTree->setFrameShape(QFrame::NoFrame);
|
||||
m_folderTree->setExpandsOnDoubleClick(true);
|
||||
m_folderTree->setItemDelegate(new FolderTreeDelegate(this)); // Custom delegate with unread count badges
|
||||
leftSplitter->addWidget(m_folderTree);
|
||||
|
||||
// Category tree
|
||||
@@ -255,6 +257,10 @@ void MainMainWindow::setupMailPage()
|
||||
connect(m_mailListView, &MailListView::emailOpenRequested, this, [this](int mailId) {
|
||||
openMailInIndependentWindow(mailId);
|
||||
});
|
||||
connect(m_mailListView, &MailListView::flagRequested, this, &MainMainWindow::onFlagRequested);
|
||||
connect(m_mailListView, &MailListView::deleteRequested, this, &MainMainWindow::onDeleteRequested);
|
||||
connect(m_mailListView, &MailListView::categoryRequested, this, &MainMainWindow::onCategoryRequested);
|
||||
connect(m_mailListView, &MailListView::moreRequested, this, &MainMainWindow::onMoreRequested);
|
||||
m_folderSplitter->addWidget(m_mailListView);
|
||||
|
||||
// Viewer stack: placeholder, reader, compose
|
||||
@@ -466,6 +472,59 @@ void MainMainWindow::onReaderDeleteRequested(int mailId)
|
||||
statusBar()->showMessage(tr("Mensaje eliminado"), 3000);
|
||||
}
|
||||
|
||||
// MailListView action handlers (from compact delegate)
|
||||
void MainMainWindow::onFlagRequested(int mailId)
|
||||
{
|
||||
auto item = MailItemDao::findById(mailId);
|
||||
if (item.has_value()) {
|
||||
item->setFlagged(!item->isFlagged());
|
||||
MailItemDao::update(*item);
|
||||
m_emailModel->refresh();
|
||||
if (m_currentMailId == mailId) {
|
||||
m_emailViewer->setMailItem(&*item);
|
||||
}
|
||||
statusBar()->showMessage(tr(item->isFlagged() ? "Marcado para seguimiento" : "Seguimiento quitado"), 2000);
|
||||
}
|
||||
}
|
||||
|
||||
void MainMainWindow::onDeleteRequested(int mailId)
|
||||
{
|
||||
MailItemDao::remove(mailId);
|
||||
if (m_currentMailId == mailId) {
|
||||
m_currentMailId = -1;
|
||||
m_viewerStack->setCurrentIndex(0); // placeholder
|
||||
}
|
||||
m_emailModel->refresh();
|
||||
statusBar()->showMessage(tr("Mensaje eliminado"), 3000);
|
||||
}
|
||||
|
||||
void MainMainWindow::onCategoryRequested(int mailId)
|
||||
{
|
||||
// Show category context menu at cursor position
|
||||
// For now, just show status - could open a dialog
|
||||
statusBar()->showMessage(tr("Categoría para mensaje %1").arg(mailId), 2000);
|
||||
}
|
||||
|
||||
void MainMainWindow::onMoreRequested(int mailId, const QPoint &globalPos)
|
||||
{
|
||||
// Show context menu with more actions
|
||||
QMenu menu;
|
||||
menu.addAction("Responder", [this, mailId]() { onReaderReplyRequested(mailId); });
|
||||
menu.addAction("Reenviar", [this, mailId]() { onReaderForwardRequested(mailId); });
|
||||
menu.addAction("Mover a...", [this, mailId]() { /* TODO: move dialog */ });
|
||||
menu.addAction("Marcar como no leído", [this, mailId]() {
|
||||
auto item = MailItemDao::findById(mailId);
|
||||
if (item.has_value()) {
|
||||
item->setRead(false);
|
||||
MailItemDao::update(*item);
|
||||
m_emailModel->refresh();
|
||||
}
|
||||
});
|
||||
menu.addSeparator();
|
||||
menu.addAction("Eliminar", [this, mailId]() { onDeleteRequested(mailId); });
|
||||
menu.exec(globalPos);
|
||||
}
|
||||
|
||||
void MainMainWindow::onNewMessage()
|
||||
{ // Show compose view in the viewer stack
|
||||
m_embeddedComposeView->initializeComposition();
|
||||
|
||||
Reference in New Issue
Block a user