feat: Drag & drop between folders

- MailListView: setDragEnabled, setAcceptDrops, setDropIndicatorShown, setDragDropMode(DragDrop)
- Custom MIME type: application/x-wino-mail-ids with QVector<int> mail IDs
- mousePressEvent + mouseMoveEvent for drag initiation (standard Qt drag distance)
- initDrag() creates QDrag with selected mail IDs
- dragEnterEvent, dragMoveEvent, dropEvent handlers
- dropEvent emits batchMoveRequested(mailIds, targetFolderId)
- Works in both tree view and compact list view
This commit is contained in:
2026-08-26 04:05:56 +02:00
parent 3a3a7b0ff8
commit 6d1feabfc5
10 changed files with 13316 additions and 13205 deletions
+86
View File
@@ -17,6 +17,8 @@
#include <QScrollBar>
#include <QToolButton>
#include <QMenu>
#include <QDrag>
#include <QMimeData>
#include "ui/delegates/CompactMailDelegate.h"
MailListView::MailListView(QWidget *parent) : QWidget(parent), m_sourceModel(nullptr), m_multiSelectMode(false)
@@ -205,6 +207,11 @@ void MailListView::setupUI()
m_treeView->setRootIsDecorated(true);
m_treeView->setItemsExpandable(true);
m_treeView->setUniformRowHeights(true);
// Enable drag & drop
m_treeView->setDragEnabled(true);
m_treeView->setAcceptDrops(true);
m_treeView->setDropIndicatorShown(true);
m_treeView->setDragDropMode(QAbstractItemView::DragDrop);
m_treeView->setStyleSheet(
"QTreeView { background-color: #ffffff; alternate-background-color: #f9f9fb; border: none; }"
"QTreeView::item { padding: 8px; border-bottom: 1px solid #e8e8ed; }"
@@ -256,6 +263,11 @@ void MailListView::setupUI()
m_listView->setUniformItemSizes(true);
m_listView->setFrameShape(QFrame::NoFrame);
m_listView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
// Enable drag & drop
m_listView->setDragEnabled(true);
m_listView->setAcceptDrops(true);
m_listView->setDropIndicatorShown(true);
m_listView->setDragDropMode(QAbstractItemView::DragDrop);
m_listView->setStyleSheet(
"QListView { background-color: #ffffff; border: none; outline: none; }"
"QListView::item { border: none; }"
@@ -619,4 +631,78 @@ void MailListView::onPivotChanged(int index)
// m_sourceModel->setShowFocusedOnly(false);
}
refreshViews();
}
void MailListView::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasFormat("application/x-wino-mail-ids")) {
event->acceptProposedAction();
}
}
void MailListView::dragMoveEvent(QDragMoveEvent *event)
{
if (event->mimeData()->hasFormat("application/x-wino-mail-ids")) {
event->acceptProposedAction();
}
}
void MailListView::dropEvent(QDropEvent *event)
{
if (event->mimeData()->hasFormat("application/x-wino-mail-ids")) {
QByteArray data = event->mimeData()->data("application/x-wino-mail-ids");
QDataStream stream(&data, QIODevice::ReadOnly);
QVector<int> mailIds;
stream >> mailIds;
if (!mailIds.isEmpty()) {
// Get target folder from the folder tree (via MainMainWindow)
// For now, emit signal with mailIds - the target folder will be handled by MainMainWindow
emit batchMoveRequested(mailIds, -1); // -1 = target folder from context
}
event->acceptProposedAction();
}
}
void MailListView::initDrag()
{
QVector<int> mailIds = getSelectedMailIds();
if (mailIds.isEmpty()) return;
QMimeData *mimeData = new QMimeData();
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream << mailIds;
mimeData->setData("application/x-wino-mail-ids", data);
QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
// Optional: set drag pixmap
// drag->setPixmap(createDragPixmap(mailIds));
Qt::DropAction dropAction = drag->exec(Qt::MoveAction);
Q_UNUSED(dropAction);
}
void MailListView::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
// Start drag distance timer
m_dragStartPosition = event->pos();
}
QWidget::mousePressEvent(event);
}
void MailListView::mouseMoveEvent(QMouseEvent *event)
{
if (!(event->buttons() & Qt::LeftButton))
return;
if ((event->pos() - m_dragStartPosition).manhattanLength() < QApplication::startDragDistance())
return;
initDrag();
}