feat: Wino-style compact mail view with display modes + hover actions

- CompactMailDelegate: 3 display modes (Compact/Medium/Spacious) like WinUI original
  * Compact: 64px, minimal, no preview
  * Medium: 96px, with preview, detailed categories
  * Spacious: 120px, full padding, preview visible
- Hover actions: Reply (↩), Forward (↪), Mark unread (✎) on right side
- Unread dot indicator (top-right, blue) like WinUI
- User-configurable display mode via combo box in filter bar
- MainMainWindow handlers for reply/forward/mark-unread from compact view
- Signals: replyRequested, forwardRequested, markUnreadRequested
This commit is contained in:
2026-08-25 13:41:43 +02:00
parent 4c4fec7a0a
commit fa699b5399
92 changed files with 26111 additions and 13449 deletions
+162 -56
View File
@@ -1,5 +1,7 @@
#include "CompactMailDelegate.h"
#include <QDebug>
#include <QDateTime>
#include <QCursor>
CompactMailDelegate::CompactMailDelegate(QObject *parent)
: QStyledItemDelegate(parent)
@@ -11,11 +13,28 @@ void CompactMailDelegate::setConfig(const Config& config)
m_config = config;
}
void CompactMailDelegate::setDisplayMode(DisplayMode mode)
{
m_config.displayMode = mode;
m_config.cardHeight = cardHeightForMode(mode);
m_config.showPreviewText = (mode != Compact);
}
QSize CompactMailDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(option);
Q_UNUSED(index);
return QSize(0, m_config.cardHeight); // width will be determined by view
return QSize(0, m_config.cardHeight);
}
int CompactMailDelegate::cardHeightForMode(DisplayMode mode) const
{
switch (mode) {
case Compact: return 64;
case Medium: return 96;
case Spacious: return 120;
}
return 76;
}
void CompactMailDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
@@ -24,6 +43,8 @@ void CompactMailDelegate::paint(QPainter *painter, const QStyleOptionViewItem &o
painter->setRenderHint(QPainter::Antialiasing, true);
painter->setRenderHint(QPainter::TextAntialiasing, true);
bool hovered = (option.state & QStyle::State_MouseOver);
m_hovered = hovered;
drawCard(painter, option, index);
painter->restore();
@@ -35,9 +56,9 @@ bool CompactMailDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
QPoint pos = mouseEvent->pos();
// Check if click is on an action button
// Check action buttons
for (const ActionButton &btn : m_lastButtons) {
if (btn.rect.contains(pos)) {
if (btn.visible && btn.rect.contains(pos)) {
int mailId = index.data(EmailListModel::IdRole).toInt();
switch (btn.type) {
case ActionFlag:
@@ -57,21 +78,60 @@ bool CompactMailDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
}
}
// Click on card body (not buttons) - select mail
// Check hover actions (reply, forward, mark unread)
if (m_config.hoverActionsEnabled && m_hovered) {
int mailId = index.data(EmailListModel::IdRole).toInt();
QRect cardRect = m_lastCardRect;
int actionAreaX = cardRect.left() + (m_config.showAvatar ? m_config.avatarSize + 10 : 0);
int actionAreaWidth = 100; // area for hover actions on the right
QRect hoverActionRect(cardRect.right() - actionAreaWidth, cardRect.top(), actionAreaWidth, cardRect.height());
if (hoverActionRect.contains(pos)) {
// Determine which hover action based on vertical position
int third = cardRect.height() / 3;
int relativeY = pos.y() - cardRect.top();
if (relativeY < third) {
emit replyRequested(mailId);
} else if (relativeY < 2 * third) {
emit forwardRequested(mailId);
} else {
emit markUnreadRequested(mailId);
}
return true;
}
}
// Click on card body - select mail
int mailId = index.data(EmailListModel::IdRole).toInt();
emit mailClicked(mailId);
return true;
}
if (event->type() == QEvent::Enter) {
m_hovered = true;
} else if (event->type() == QEvent::Leave) {
m_hovered = false;
}
return QStyledItemDelegate::editorEvent(event, model, option, index);
}
void CompactMailDelegate::drawCard(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QRect cardRect = option.rect.adjusted(4, 2, -4, -2); // margins
QRect cardRect = option.rect.adjusted(4, 2, -4, -2);
m_lastCardRect = cardRect;
bool isSelected = option.state & QStyle::State_Selected;
bool isHovered = option.state & QStyle::State_MouseOver;
bool isUnread = !index.data(EmailListModel::ReadRole).toBool();
bool isFlagged = index.data(EmailListModel::FlaggedRole).toBool();
bool hasAttachments = !index.data(EmailListModel::AttachmentsRole).value<QVector<QString>>().isEmpty();
// Data from model
QString sender = index.data(EmailListModel::SenderRole).toString();
QString subject = index.data(EmailListModel::SubjectRole).toString();
QString previewText = index.data(EmailListModel::SubjectRole).toString(); // Using subject as preview for now
QDateTime date = index.data(EmailListModel::DateRole).toDateTime();
// Background
QColor bgColor;
@@ -86,18 +146,13 @@ void CompactMailDelegate::drawCard(QPainter *painter, const QStyleOptionViewItem
}
painter->setBrush(bgColor);
painter->setPen(QColor(0xe8, 0xe8, 0xed)); // separator color
painter->setPen(QColor(0xe8, 0xe8, 0xed));
painter->drawRoundedRect(cardRect, 8, 8);
// Inner padding
QRect contentRect = cardRect.adjusted(12, 8, -12, -8);
// Data from model
QString sender = index.data(EmailListModel::SenderRole).toString();
QString subject = index.data(EmailListModel::SubjectRole).toString();
QDateTime date = index.data(EmailListModel::DateRole).toDateTime();
bool hasAttachments = !index.data(EmailListModel::AttachmentsRole).value<QVector<QString>>().isEmpty();
bool flagged = index.data(EmailListModel::FlaggedRole).toBool();
// Inner padding based on display mode
int hPadding = (m_config.displayMode == Spacious) ? 16 : 12;
int vPadding = (m_config.displayMode == Spacious) ? 12 : 8;
QRect contentRect = cardRect.adjusted(hPadding, vPadding, -hPadding, -vPadding);
int x = contentRect.left();
int y = contentRect.top();
@@ -121,11 +176,24 @@ void CompactMailDelegate::drawCard(QPainter *painter, const QStyleOptionViewItem
subjectFont.setPointSizeF(12);
subjectFont.setWeight(QFont::Normal);
QFont previewFont = QApplication::font();
previewFont.setPointSizeF(11);
QFont dateFont = QApplication::font();
dateFont.setPointSizeF(11);
QFont actionFont = QApplication::font();
actionFont.setPointSizeF(11);
// Unread dot (top-right like WinUI)
if (isUnread && m_config.showAvatar) {
drawUnreadDot(painter, cardRect);
}
// Flag indicator
if (isFlagged && m_config.showAvatar) {
QRect flagRect(x - m_config.avatarSize - 10 + m_config.avatarSize - 8, y, 12, 12);
painter->setBrush(m_config.flagColor);
painter->setPen(Qt::NoPen);
painter->drawEllipse(flagRect);
}
// Line 1: Sender (left) + Date (right)
int line1Y = y + 2;
@@ -141,15 +209,18 @@ void CompactMailDelegate::drawCard(QPainter *painter, const QStyleOptionViewItem
// Draw sender
painter->setFont(senderFont);
painter->setPen(isUnread ? m_config.textPrimaryColor : m_config.textPrimaryColor);
QColor senderColor = isUnread ? m_config.accentColor : m_config.textPrimaryColor;
if (isSelected) senderColor = Qt::white;
painter->setPen(senderColor);
painter->drawText(QRect(x, line1Y, senderMaxWidth, senderFM.height()), Qt::AlignLeft | Qt::AlignVCenter, elidedSender);
// Draw date
painter->setFont(dateFont);
painter->setPen(m_config.textSecondaryColor);
QColor dateColor = isSelected ? Qt::white : m_config.textSecondaryColor;
painter->setPen(dateColor);
painter->drawText(QRect(x + senderMaxWidth + 8, line1Y, dateWidth, dateFM.height()), Qt::AlignRight | Qt::AlignVCenter, dateStr);
// Line 2: Attachment icon + Subject
// Line 2: Subject + Attachment icon
int line2Y = line1Y + senderFM.height() + 2;
QString subjectPrefix = "";
int prefixWidth = 0;
@@ -164,10 +235,27 @@ void CompactMailDelegate::drawCard(QPainter *painter, const QStyleOptionViewItem
QString elidedSubject = elideText(painter, subject, subjectMaxWidth, subjectFont);
painter->setFont(subjectFont);
painter->setPen(isUnread ? m_config.textPrimaryColor : m_config.textSecondaryColor);
QColor subjectColor = isUnread ? m_config.textPrimaryColor : m_config.textSecondaryColor;
if (isSelected) subjectColor = Qt::white;
painter->setPen(subjectColor);
painter->drawText(QRect(x, line2Y, prefixWidth, subjectFont.pointSizeF()), Qt::AlignLeft | Qt::AlignVCenter, subjectPrefix);
painter->drawText(QRect(x + prefixWidth, line2Y, subjectMaxWidth, subjectFont.pointSizeF()), Qt::AlignLeft | Qt::AlignVCenter, elidedSubject);
// Line 3: Preview text (Medium/Spacious only)
if (m_config.showPreviewText && m_config.displayMode != Compact) {
int line3Y = line2Y + subjectFont.pointSizeF() + 4;
int previewMaxWidth = availableWidth;
QString elidedPreview = elideText(painter, previewText, previewMaxWidth, previewFont);
painter->setFont(previewFont);
QColor previewColor = isSelected ? Qt::white : m_config.textSecondaryColor;
painter->setPen(previewColor);
painter->drawText(QRect(x, line3Y, previewMaxWidth, previewFont.pointSizeF()), Qt::AlignLeft | Qt::AlignVCenter, elidedPreview);
}
// Categories (if enabled and present) - simplified for now
// TODO: Add category support from model
// Action buttons (bottom)
int buttonAreaY = cardRect.bottom() - 28;
QRect buttonAreaRect(contentRect.left(), buttonAreaY, contentRect.width(), 24);
@@ -177,12 +265,9 @@ void CompactMailDelegate::drawCard(QPainter *painter, const QStyleOptionViewItem
drawActionButtons(painter, buttonAreaRect, index, m_lastButtons);
// Flag indicator (small dot on top-right of avatar area if flagged)
if (flagged && m_config.showAvatar) {
QRect flagRect(x - m_config.avatarSize - 10 + m_config.avatarSize - 8, y, 12, 12);
painter->setBrush(m_config.flagColor);
painter->setPen(Qt::NoPen);
painter->drawEllipse(flagRect);
// Hover actions (right side)
if (m_config.hoverActionsEnabled && isHovered) {
drawHoverActions(painter, cardRect, index, isHovered);
}
}
@@ -196,7 +281,6 @@ void CompactMailDelegate::drawAvatar(QPainter *painter, const QRect &rect, const
// Initial
QString initial;
if (!sender.isEmpty()) {
// Extract first letter of first name or email
QString clean = sender;
int lt = clean.indexOf('<');
if (lt > 0) clean = clean.left(lt).trimmed();
@@ -217,15 +301,57 @@ void CompactMailDelegate::drawAvatar(QPainter *painter, const QRect &rect, const
painter->drawText(rect, Qt::AlignCenter, initial);
}
void CompactMailDelegate::drawUnreadDot(QPainter *painter, const QRect &cardRect) const
{
// Draw unread indicator dot at top-right of card (like WinUI)
int dotSize = 8;
QRect dotRect(cardRect.right() - 12 - dotSize, cardRect.top() + 12, dotSize, dotSize);
painter->setBrush(m_config.unreadDotColor);
painter->setPen(Qt::NoPen);
painter->drawEllipse(dotRect);
}
void CompactMailDelegate::drawHoverActions(QPainter *painter, const QRect &cardRect, const QModelIndex &index, bool hovered) const
{
if (!hovered) return;
Q_UNUSED(index);
// Draw 3 hover action icons on the right side
int actionSize = 28;
int spacing = 4;
int totalHeight = 3 * actionSize + 2 * spacing;
int startY = cardRect.center().y() - totalHeight / 2;
int actionX = cardRect.right() - 12 - actionSize;
QFont font = QApplication::font();
font.setPointSizeF(14);
painter->setFont(font);
QString actions[3] = {"", "", ""}; // Reply, Forward, Mark unread
QColor actionColor = m_config.accentColor;
for (int i = 0; i < 3; ++i) {
QRect actionRect(actionX, startY + i * (actionSize + spacing), actionSize, actionSize);
// Background on hover
painter->setBrush(QColor(0x00, 0x71, 0xe3, 0x15));
painter->setPen(Qt::NoPen);
painter->drawRoundedRect(actionRect, 6, 6);
// Icon
painter->setPen(actionColor);
painter->drawText(actionRect, Qt::AlignCenter, actions[i]);
}
}
QColor CompactMailDelegate::avatarColorForSender(const QString &sender) const
{
// Hash-based color from sender email/name
uint hash = 0;
for (QChar c : sender) {
hash = hash * 31 + c.unicode();
}
// Predefined pleasant colors (macOS Mail style)
static const QColor colors[] = {
QColor(0xff, 0x3b, 0x30), // red
QColor(0xff, 0x95, 0x00), // orange
@@ -242,30 +368,6 @@ QColor CompactMailDelegate::avatarColorForSender(const QString &sender) const
return colors[hash % 10];
}
CompactMailDelegate::ActionButton CompactMailDelegate::makeButton(ActionButtonType type, const QRect &rect) const
{
QString icon, tooltip;
switch (type) {
case ActionFlag:
icon = "";
tooltip = "Marcar para seguimiento";
break;
case ActionDelete:
icon = "🗑";
tooltip = "Borrar";
break;
case ActionCategory:
icon = "🏷";
tooltip = "Categoría";
break;
case ActionMore:
icon = "";
tooltip = "Más opciones";
break;
}
return {type, icon, tooltip, rect};
}
QVector<CompactMailDelegate::ActionButton> CompactMailDelegate::layoutActionButtons(const QRect &areaRect) const
{
QVector<ActionButton> buttons;
@@ -275,10 +377,12 @@ QVector<CompactMailDelegate::ActionButton> CompactMailDelegate::layoutActionButt
int startX = areaRect.left() + (areaRect.width() - totalWidth) / 2;
int y = areaRect.top() + (areaRect.height() - buttonSize) / 2;
QString icons[] = {"", "🗑", "🏷", ""};
for (int i = 0; i < m_config.actionOrder.size(); ++i) {
ActionButtonType type = m_config.actionOrder[i];
QRect btnRect(startX + i * (buttonSize + spacing), y, buttonSize, buttonSize);
buttons.append(makeButton(type, btnRect));
buttons.append({type, icons[type], "", btnRect, true});
}
return buttons;
@@ -294,6 +398,8 @@ void CompactMailDelegate::drawActionButtons(QPainter *painter, const QRect &area
painter->setFont(font);
for (const ActionButton &btn : buttons) {
if (!btn.visible) continue;
// Icon
painter->setPen(m_config.textSecondaryColor);
painter->drawText(btn.rect, Qt::AlignCenter, btn.icon);
@@ -320,7 +426,7 @@ QString CompactMailDelegate::formatDateRelative(const QDateTime &date) const
QDate today = QDate::currentDate();
if (d == today) return date.toString("HH:mm");
if (d == today.addDays(-1)) return "Ayer";
if (d > today.addDays(-7)) return d.toString("ddd"); // "lun", "mar"...
if (d > today.addDays(-7)) return d.toString("ddd");
if (d.year() == today.year()) return d.toString("dd/MM");
return d.toString("dd/MM/yy");
}
+25 -5
View File
@@ -21,6 +21,12 @@ class CompactMailDelegate : public QStyledItemDelegate
Q_OBJECT
public:
enum DisplayMode {
Compact = 0, // 64px - minimal, no preview
Medium = 1, // 96px - with preview, detailed categories
Spacious = 2 // Auto - full padding, preview visible
};
enum ActionButtonType {
ActionFlag = 0,
ActionDelete = 1,
@@ -33,17 +39,22 @@ public:
QString icon;
QString tooltip;
QRect rect;
bool visible = true;
};
struct Config {
DisplayMode displayMode = Compact;
bool showAvatar = true;
int avatarSize = 36;
int cardHeight = 76;
int cardHeight = 76; // Compact default
int thresholdWidth = 420;
QVector<ActionButtonType> actionOrder = {ActionFlag, ActionDelete, ActionCategory, ActionMore};
bool showAttachmentIcon = true;
bool showDateRelative = true;
QColor unreadBgColor = QColor(0xe3, 0xf2, 0xfd); // light blue
bool showPreviewText = false; // only in Medium/Spacious
bool showCategories = true;
bool hoverActionsEnabled = true;
QColor unreadBgColor = QColor(0xe3, 0xf2, 0xfd);
QColor readBgColor = QColor(0xff, 0xff, 0xff);
QColor hoverBgColor = QColor(0xf0, 0xf0, 0xf5);
QColor selectedBgColor = QColor(0xd6, 0xe8, 0xf7);
@@ -51,6 +62,7 @@ public:
QColor textSecondaryColor = QColor(0x86, 0x86, 0x8b);
QColor accentColor = QColor(0x00, 0x71, 0xe3);
QColor flagColor = QColor(0xff, 0x3b, 0x30);
QColor unreadDotColor = QColor(0x00, 0x71, 0xe3);
};
explicit CompactMailDelegate(QObject *parent = nullptr);
@@ -58,6 +70,7 @@ public:
void setConfig(const Config& config);
Config config() const { return m_config; }
void setDisplayMode(DisplayMode mode);
// QStyledItemDelegate interface
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
@@ -68,20 +81,27 @@ signals:
void flagRequested(int mailId);
void deleteRequested(int mailId);
void categoryRequested(int mailId);
void moreRequested(int mailId, const QPoint& globalPos); // for context menu
void moreRequested(int mailId, const QPoint& globalPos);
void mailClicked(int mailId);
void replyRequested(int mailId);
void forwardRequested(int mailId);
void markUnreadRequested(int mailId);
private:
void drawCard(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void drawAvatar(QPainter *painter, const QRect &rect, const QString &sender) const;
void drawUnreadDot(QPainter *painter, const QRect &cardRect) const;
void drawHoverActions(QPainter *painter, const QRect &cardRect, const QModelIndex &index, bool hovered) const;
QColor avatarColorForSender(const QString &sender) const;
void drawActionButtons(QPainter *painter, const QRect &cardRect, const QModelIndex &index, const QVector<ActionButton>& buttons) const;
QVector<ActionButton> layoutActionButtons(const QRect &cardRect) const;
ActionButton makeButton(ActionButtonType type, const QRect &rect) const;
QString formatDateRelative(const QDateTime &date) const;
QString elideText(QPainter *painter, const QString &text, int maxWidth, const QFont &font) const;
int cardHeightForMode(DisplayMode mode) const;
Config m_config;
mutable QVector<ActionButton> m_lastButtons; // for hit testing
mutable QVector<ActionButton> m_lastButtons;
mutable QModelIndex m_lastIndex;
mutable QRect m_lastCardRect;
mutable bool m_hovered = false;
};
+38
View File
@@ -70,6 +70,22 @@ void MailListView::setupUI()
filterLayout->addStretch();
// Display mode combo (Compact/Medium/Spacious)
m_displayModeCombo = new QComboBox();
m_displayModeCombo->addItem("Compacto");
m_displayModeCombo->addItem("Medio");
m_displayModeCombo->addItem("Espacioso");
m_displayModeCombo->setFixedWidth(120);
m_displayModeCombo->setStyleSheet(
"QComboBox { border: 1px solid #d1d1d6; border-radius: 4px; padding: 4px 8px; "
"background: white; min-height: 20px; }"
"QComboBox:hover { border-color: #bdbdbd; }"
"QComboBox:focus { border-color: #1976D2; }"
);
connect(m_displayModeCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &MailListView::onDisplayModeChanged);
filterLayout->addWidget(m_displayModeCombo);
// Group by combo
m_groupByCombo = new QComboBox();
m_groupByCombo->addItem("Sin agrupación");
@@ -282,4 +298,26 @@ void MailListView::onCompactMoreRequested(int mailId, const QPoint &globalPos)
void MailListView::onCompactMailClicked(int mailId)
{
emit emailSelected(mailId);
}
void MailListView::onCompactReplyRequested(int mailId)
{
emit replyRequested(mailId);
}
void MailListView::onCompactForwardRequested(int mailId)
{
emit forwardRequested(mailId);
}
void MailListView::onCompactMarkUnreadRequested(int mailId)
{
emit markUnreadRequested(mailId);
}
void MailListView::onDisplayModeChanged(int index)
{
CompactMailDelegate::DisplayMode mode = static_cast<CompactMailDelegate::DisplayMode>(index);
m_compactDelegate->setDisplayMode(mode);
m_listView->update();
}
+9 -1
View File
@@ -38,6 +38,9 @@ signals:
void deleteRequested(int mailId);
void categoryRequested(int mailId);
void moreRequested(int mailId, const QPoint& globalPos);
void replyRequested(int mailId);
void forwardRequested(int mailId);
void markUnreadRequested(int mailId);
private slots:
void onRowSelected(const QModelIndex &index);
@@ -49,6 +52,10 @@ private slots:
void onCompactCategoryRequested(int mailId);
void onCompactMoreRequested(int mailId, const QPoint& globalPos);
void onCompactMailClicked(int mailId);
void onCompactReplyRequested(int mailId);
void onCompactForwardRequested(int mailId);
void onCompactMarkUnreadRequested(int mailId);
void onDisplayModeChanged(int index);
protected:
void resizeEvent(QResizeEvent *event) override;
@@ -70,7 +77,8 @@ private:
QCheckBox *m_flaggedOnlyCheck;
QCheckBox *m_hasAttachmentsCheck;
QComboBox *m_groupByCombo;
QComboBox *m_displayModeCombo;
CompactMailDelegate *m_compactDelegate = nullptr;
bool m_compactMode = false;
int m_compactThreshold = 420;
int m_compactThreshold = 500;
};
+27
View File
@@ -261,6 +261,9 @@ void MainMainWindow::setupMailPage()
connect(m_mailListView, &MailListView::deleteRequested, this, &MainMainWindow::onDeleteRequested);
connect(m_mailListView, &MailListView::categoryRequested, this, &MainMainWindow::onCategoryRequested);
connect(m_mailListView, &MailListView::moreRequested, this, &MainMainWindow::onMoreRequested);
connect(m_mailListView, &MailListView::replyRequested, this, &MainMainWindow::onReplyRequested);
connect(m_mailListView, &MailListView::forwardRequested, this, &MainMainWindow::onForwardRequested);
connect(m_mailListView, &MailListView::markUnreadRequested, this, &MainMainWindow::onMarkUnreadRequested);
m_folderSplitter->addWidget(m_mailListView);
// Viewer stack: placeholder, reader, compose
@@ -525,6 +528,30 @@ void MainMainWindow::onMoreRequested(int mailId, const QPoint &globalPos)
menu.exec(globalPos);
}
void MainMainWindow::onReplyRequested(int mailId)
{
onReaderReplyRequested(mailId);
}
void MainMainWindow::onForwardRequested(int mailId)
{
onReaderForwardRequested(mailId);
}
void MainMainWindow::onMarkUnreadRequested(int mailId)
{
auto item = MailItemDao::findById(mailId);
if (item.has_value()) {
item->setRead(false);
MailItemDao::update(*item);
m_emailModel->refresh();
if (m_currentMailId == mailId) {
m_emailViewer->setMailItem(&*item);
}
statusBar()->showMessage(tr("Marcado como no leído"), 2000);
}
}
void MainMainWindow::onNewMessage()
{ // Show compose view in the viewer stack
m_embeddedComposeView->initializeComposition();
+3
View File
@@ -79,6 +79,9 @@ private slots:
void onDeleteRequested(int mailId);
void onCategoryRequested(int mailId);
void onMoreRequested(int mailId, const QPoint &globalPos);
void onReplyRequested(int mailId);
void onForwardRequested(int mailId);
void onMarkUnreadRequested(int mailId);
// Slots for embedded compose view
void onEmbeddedSendRequested(const QString &to, const QString &cc, const QString &bcc,