feat: move-to-folder dialog, batch actions, reader source view, Focused/Other pivot
- MoveToFolderDialog: modal folder picker per account (excludes current) - Wire 'Mover a...' in reader ⋯ menu + batch move (emit -1 -> dialog) - Connect batch delete/mark-unread/flag handlers (were unconnected) - Reader: 'Ver codigo fuente' reads .eml via MimeStorageService::readEmlFile - Reader: 'Marcar como no leido' emits markUnreadRequested - Pivot Focused/Other: EmailListModel::setShowFocusedOnly heuristic (flagged/pinned/frequent senders), reset to Focused on inbox select
This commit is contained in:
+110
-1
@@ -8,6 +8,7 @@
|
||||
#include "services/rulesengine.h"
|
||||
#include "ui/rulesmanagerdialog.h"
|
||||
#include "ui/accountsetupdialog.h"
|
||||
#include "ui/movetofolderdialog.h"
|
||||
#include "ui/delegates/FolderTreeDelegate.h"
|
||||
#include "services/preferencesservice.h"
|
||||
#include "services/startupbehaviorservice.h"
|
||||
@@ -268,6 +269,10 @@ void MainMainWindow::setupMailPage()
|
||||
connect(m_mailListView, &MailListView::replyRequested, this, &MainMainWindow::onReplyRequested);
|
||||
connect(m_mailListView, &MailListView::forwardRequested, this, &MainMainWindow::onForwardRequested);
|
||||
connect(m_mailListView, &MailListView::markUnreadRequested, this, &MainMainWindow::onMarkUnreadRequested);
|
||||
connect(m_mailListView, &MailListView::batchMoveRequested, this, &MainMainWindow::onBatchMoveRequested);
|
||||
connect(m_mailListView, &MailListView::batchDeleteRequested, this, &MainMainWindow::onBatchDeleteRequested);
|
||||
connect(m_mailListView, &MailListView::batchMarkUnreadRequested, this, &MainMainWindow::onBatchMarkUnreadRequested);
|
||||
connect(m_mailListView, &MailListView::batchFlagRequested, this, &MainMainWindow::onBatchFlagRequested);
|
||||
m_folderSplitter->addWidget(m_mailListView);
|
||||
|
||||
// Viewer stack: placeholder, reader, compose
|
||||
@@ -299,6 +304,7 @@ void MainMainWindow::setupMailPage()
|
||||
connect(m_emailViewer, &ReaderView::replyRequested, this, &MainMainWindow::onReaderReplyRequested);
|
||||
connect(m_emailViewer, &ReaderView::forwardRequested, this, &MainMainWindow::onReaderForwardRequested);
|
||||
connect(m_emailViewer, &ReaderView::deleteRequested, this, &MainMainWindow::onReaderDeleteRequested);
|
||||
connect(m_emailViewer, &ReaderView::markUnreadRequested, this, &MainMainWindow::onMarkUnreadRequested);
|
||||
connect(m_emailViewer, &ReaderView::detachRequested, this, [this]() {
|
||||
if (m_currentMailId >= 0) {
|
||||
openMailInIndependentWindow(m_currentMailId);
|
||||
@@ -412,6 +418,8 @@ void MainMainWindow::onFolderSelected(const QModelIndex &index)
|
||||
m_mailService->fetchMails(QString::number(account->id()), QString::number(m_currentFolderId));
|
||||
// Tell MailListView the folder type for Focused/Other pivot
|
||||
m_mailListView->setFolderType(folder.type().toLower()); // "inbox", "sent", etc.
|
||||
// Reset pivot to Focused for inbox folders
|
||||
m_mailListView->resetPivot();
|
||||
delete account;
|
||||
}
|
||||
}
|
||||
@@ -525,6 +533,107 @@ void MainMainWindow::onDeleteRequested(int mailId)
|
||||
statusBar()->showMessage(tr("Mensaje eliminado"), 3000);
|
||||
}
|
||||
|
||||
void MainMainWindow::onMoveMailToFolderRequested(int mailId)
|
||||
{
|
||||
// Determine the account of the mail (via its current folder).
|
||||
std::optional<MailItem> optMail = MailItemDao::findById(mailId);
|
||||
if (!optMail) {
|
||||
statusBar()->showMessage(tr("Mensaje no encontrado"), 3000);
|
||||
return;
|
||||
}
|
||||
int currentFolderId = optMail->folderId();
|
||||
std::optional<Folder> optFolder = FolderDao::findById(currentFolderId);
|
||||
if (!optFolder) {
|
||||
statusBar()->showMessage(tr("Carpeta no encontrada"), 3000);
|
||||
return;
|
||||
}
|
||||
int accountId = optFolder->accountId();
|
||||
|
||||
QVector<Folder> folders = FolderDao::findByAccountId(accountId);
|
||||
MoveToFolderDialog dlg(folders, currentFolderId, this);
|
||||
if (dlg.exec() != QDialog::Accepted) return;
|
||||
int targetFolderId = dlg.selectedFolderId();
|
||||
if (targetFolderId < 0) return;
|
||||
|
||||
m_mailService->moveMail(QString::number(mailId), QString::number(targetFolderId));
|
||||
// MailService::moveMail emits mailMoved; here we also refresh locally.
|
||||
if (m_currentMailId == mailId) m_currentMailId = -1;
|
||||
m_emailModel->refresh();
|
||||
m_mailListView->treeView()->clearSelection();
|
||||
m_viewerStack->setCurrentIndex(0);
|
||||
statusBar()->showMessage(tr("Correo movido"), 3000);
|
||||
}
|
||||
|
||||
void MainMainWindow::onBatchMoveRequested(const QVector<int> &mailIds, int targetFolderId)
|
||||
{
|
||||
if (mailIds.isEmpty()) return;
|
||||
|
||||
// Resolve target folder. targetFolderId == -1 → ask the user via dialog.
|
||||
int resolvedTarget = targetFolderId;
|
||||
if (resolvedTarget < 0) {
|
||||
// Use the account of the first mail.
|
||||
std::optional<MailItem> optMail = MailItemDao::findById(mailIds.first());
|
||||
if (!optMail) return;
|
||||
std::optional<Folder> optFolder = FolderDao::findById(optMail->folderId());
|
||||
if (!optFolder) return;
|
||||
QVector<Folder> folders = FolderDao::findByAccountId(optFolder->accountId());
|
||||
MoveToFolderDialog dlg(folders, optMail->folderId(), this);
|
||||
if (dlg.exec() != QDialog::Accepted) return;
|
||||
resolvedTarget = dlg.selectedFolderId();
|
||||
if (resolvedTarget < 0) return;
|
||||
}
|
||||
|
||||
for (int mailId : mailIds) {
|
||||
m_mailService->moveMail(QString::number(mailId), QString::number(resolvedTarget));
|
||||
if (m_currentMailId == mailId) m_currentMailId = -1;
|
||||
}
|
||||
m_emailModel->refresh();
|
||||
m_mailListView->treeView()->clearSelection();
|
||||
m_viewerStack->setCurrentIndex(0);
|
||||
statusBar()->showMessage(tr("%1 correo(s) movidos").arg(mailIds.size()), 3000);
|
||||
}
|
||||
|
||||
void MainMainWindow::onBatchDeleteRequested(const QVector<int> &mailIds)
|
||||
{
|
||||
if (mailIds.isEmpty()) return;
|
||||
for (int mailId : mailIds) {
|
||||
MailItemDao::remove(mailId);
|
||||
if (m_currentMailId == mailId) m_currentMailId = -1;
|
||||
}
|
||||
m_emailModel->refresh();
|
||||
m_mailListView->treeView()->clearSelection();
|
||||
m_viewerStack->setCurrentIndex(0);
|
||||
statusBar()->showMessage(tr("%1 correo(s) eliminados").arg(mailIds.size()), 3000);
|
||||
}
|
||||
|
||||
void MainMainWindow::onBatchMarkUnreadRequested(const QVector<int> &mailIds)
|
||||
{
|
||||
if (mailIds.isEmpty()) return;
|
||||
for (int mailId : mailIds) {
|
||||
auto item = MailItemDao::findById(mailId);
|
||||
if (item.has_value()) {
|
||||
item->setRead(false);
|
||||
MailItemDao::update(*item);
|
||||
}
|
||||
}
|
||||
m_emailModel->refresh();
|
||||
statusBar()->showMessage(tr("%1 correo(s) marcados como no leídos").arg(mailIds.size()), 3000);
|
||||
}
|
||||
|
||||
void MainMainWindow::onBatchFlagRequested(const QVector<int> &mailIds, bool flagged)
|
||||
{
|
||||
if (mailIds.isEmpty()) return;
|
||||
for (int mailId : mailIds) {
|
||||
auto item = MailItemDao::findById(mailId);
|
||||
if (item.has_value()) {
|
||||
item->setFlagged(flagged);
|
||||
MailItemDao::update(*item);
|
||||
}
|
||||
}
|
||||
m_emailModel->refresh();
|
||||
statusBar()->showMessage(tr("%1 correo(s) actualizados").arg(mailIds.size()), 3000);
|
||||
}
|
||||
|
||||
void MainMainWindow::onCategoryRequested(int mailId)
|
||||
{
|
||||
// Show category context menu at cursor position
|
||||
@@ -538,7 +647,7 @@ void MainMainWindow::onMoreRequested(int mailId, const QPoint &globalPos)
|
||||
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("Mover a...", [this, mailId]() { onMoveMailToFolderRequested(mailId); });
|
||||
menu.addAction("Marcar como no leído", [this, mailId]() {
|
||||
auto item = MailItemDao::findById(mailId);
|
||||
if (item.has_value()) {
|
||||
|
||||
Reference in New Issue
Block a user