Skip to content

Commit a1e7ff2

Browse files
committed
App: add drag and drop in favorite
1 parent b563fcc commit a1e7ff2

4 files changed

Lines changed: 172 additions & 51 deletions

File tree

App/Client/Favorite/FavoriteModel.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,47 @@ bool CFavoriteModel::UpdateFavorite(
270270
return true;
271271
}
272272

273+
bool CFavoriteModel::Move(QModelIndex index, QModelIndex parentIndex)
274+
{
275+
if(!index.isValid()) return false;
276+
tree* ip = GetTree(index);
277+
if(!ip) return false;
278+
tree* ipParent = GetTree(parentIndex);
279+
if(!ipParent || ipParent->item.isFavorite()) return false;
280+
int nParentId = ipParent->item.id;
281+
auto& item = ip->item;
282+
bool bRet = false;
283+
if(item.isFavorite())
284+
bRet = m_pDatabase->Move(item.id, nParentId);
285+
else
286+
bRet = m_pDatabase->MoveNode(item.id, nParentId);
287+
if(!bRet) return false;
288+
bRet = MoveTree(ip->item, ipParent->item.id);
289+
return bRet;
290+
}
291+
292+
// TODO: not test!!!
293+
bool CFavoriteModel::Copy(QModelIndex index, QModelIndex parentIndex)
294+
{
295+
bool bRet = true;
296+
if(!index.isValid()) return false;
297+
tree* ip = GetTree(index);
298+
if(!ip) return false;
299+
tree* ipParent = GetTree(parentIndex);
300+
if(!ipParent || ipParent->item.isFavorite()) return false;
301+
int nParentId = ipParent->item.id;
302+
auto& item = ip->item;
303+
if(item.isFavorite())
304+
bRet = AddFavorite(item.szFile, item.szName, item.GetIcon(),
305+
item.szDescription, nParentId);
306+
else {
307+
bRet = m_pDatabase->AddNode(item.szName, nParentId);
308+
if(!bRet) return false;
309+
bRet = AddTree(item, nParentId);
310+
}
311+
return bRet;
312+
}
313+
273314
CFavoriteDatabase::Item CFavoriteModel::GetFavorite(const QString &szFile)
274315
{
275316
CFavoriteDatabase::Item item;

App/Client/Favorite/FavoriteModel.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ class CFavoriteModel : public QAbstractItemModel
2626
CFavoriteDatabase::Item GetFavorite(const QString& szFile);
2727
void Refresh();
2828

29+
bool Move(QModelIndex index, QModelIndex parentIndex);
30+
bool Copy(QModelIndex index, QModelIndex parentIndex);
2931
enum RoleType {
3032
RoleFile = Qt::UserRole,
3133
RoleNodeType,

App/Client/Favorite/FavoriteView.cpp

Lines changed: 126 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,14 @@ void CFavoriteView::setupTreeView(QLayout *layout)
185185
return;
186186
layout->addWidget(m_pTreeView);
187187

188+
//m_pTreeView->installEventFilter(this);
189+
m_pTreeView->viewport()->installEventFilter(this);
188190
m_pTreeView->setAcceptDrops(true);
191+
m_pTreeView->setDragEnabled(true);
192+
m_pTreeView->setDragDropMode(QTreeView::InternalMove);
193+
m_pTreeView->setDefaultDropAction(Qt::MoveAction);
194+
m_pTreeView->setDropIndicatorShown(true);
195+
189196
m_pTreeView->setUniformRowHeights(true);
190197
m_pTreeView->setHeaderHidden(true);
191198

@@ -508,77 +515,110 @@ void CFavoriteView::slotExport()
508515

509516
void CFavoriteView::dragEnterEvent(QDragEnterEvent *event)
510517
{
511-
qDebug(log) << "dragEnterEvent";
518+
qDebug(log) << Q_FUNC_INFO;
512519
const CFavoriteMimeData* pData =
513520
qobject_cast<const CFavoriteMimeData*>(event->mimeData());
514521
if (pData)
515522
{
516523
qDebug(log) << "dragEnterEvent acceptProposedAction";
517524
event->acceptProposedAction();
518-
}
525+
/*
526+
// 设置拖拽时的光标
527+
if (event->proposedAction() == Qt::MoveAction) {
528+
setCursor(Qt::DragMoveCursor);
529+
} else {
530+
setCursor(Qt::DragCopyCursor);
531+
}//*/
532+
} else
533+
event->ignore();
519534
}
520535

521536
void CFavoriteView::dragMoveEvent(QDragMoveEvent *event)
522537
{
538+
qDebug(log) << Q_FUNC_INFO;
539+
const CFavoriteMimeData* pData =
540+
qobject_cast<const CFavoriteMimeData*>(event->mimeData());
541+
if (!pData)
542+
{
543+
event->ignore();
544+
return;
545+
}
546+
547+
// 获取鼠标位置下的索引
548+
QModelIndex index = m_pTreeView->indexAt(event->pos());
549+
550+
// 检查是否可以放置
551+
if (index.isValid()) {
552+
// 这里可以添加验证逻辑,比如不能将文件夹拖到自身
553+
event->acceptProposedAction();
554+
555+
// 更新拖拽指示器位置
556+
m_pTreeView->updateDropIndicator(event->pos());
557+
558+
// 自动展开文件夹(如果悬停足够长时间)
559+
if (!isExpanded(index) && m_DragHoverIndex != index) {
560+
m_DragHoverIndex = index;
561+
QTimer::singleShot(500, [this, index]() {
562+
if (m_Dragging && m_DragHoverIndex == index) {
563+
expand(index);
564+
}
565+
});
566+
}
567+
} else {
568+
// 允许拖拽到空白区域(根节点)
569+
event->acceptProposedAction();
570+
}
571+
572+
m_pTreeView->viewport()->update(); // 触发重绘以显示指示器
523573
}
524574

525575
void CFavoriteView::dropEvent(QDropEvent *event)
526576
{
527-
qDebug(log) << "dropEvent";
577+
qDebug(log) << Q_FUNC_INFO << "drop action:" << event->dropAction();
578+
528579
const CFavoriteMimeData *pData = qobject_cast<const CFavoriteMimeData*>(event->mimeData());
529-
if(!pData) return;
530-
/*
531-
QStandardItemModel* pModel = dynamic_cast<QStandardItemModel*>(model());
532-
if(!pModel) return;
580+
if(!pData || pData->m_Items.isEmpty() || !m_pTreeView || !m_pModel) {
581+
event->ignore();
582+
return;
583+
}
584+
585+
bool bRet = false;
533586
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
534-
auto index = indexAt(event->position().toPoint());
587+
auto idxParent = m_pTreeView->indexAt(event->position().toPoint());
535588
#else
536-
auto index = indexAt(event->pos());
589+
auto idxParent = m_pTreeView->indexAt(event->pos());
537590
#endif
538-
if(index.isValid())
591+
592+
CFavoriteDatabase::Item item
593+
= m_pModel->data(idxParent, CFavoriteModel::RoleItem)
594+
.value<CFavoriteDatabase::Item>();
595+
if(0 < item.id && item.isFolder())
539596
{
540-
auto item = pModel->itemFromIndex(index);
541-
if(item->data().isNull())
542-
{
543-
foreach(auto i, pData->m_Items)
544-
{
545-
qDebug(log) << "dropEvent:" << item->text();
546-
547-
auto newItem = NewItem(i);
548-
item->appendRow(newItem);
549-
if(event->dropAction() == Qt::MoveAction)
550-
pModel->removeRow(i.row(), i.parent());
551-
}
552-
} else
553-
qWarning(log) << "Don't group node. the data:" << item->data();
554-
}else{
555597
foreach(auto i, pData->m_Items)
556598
{
557-
pModel->appendRow(NewItem(i));
558-
if(event->dropAction() == Qt::MoveAction)
559-
pModel->removeRow(i.row(), i.parent());
599+
if (event->dropAction() == Qt::MoveAction)
600+
bRet = m_pModel->Move(i, idxParent);
601+
else if (event->dropAction() == Qt::CopyAction)
602+
bRet = m_pModel->Copy(i, idxParent);
603+
if(!bRet) break;
560604
}
605+
} else {
606+
qWarning(log) << "Don't group node. the id:" << item.id
607+
<< " Folder:" << item.isFolder();
561608
}
562-
//*/
563-
event->accept();
564-
}
565-
/*
566-
QStandardItem* CFavoriteView::NewItem(const QModelIndex &index)
567-
{
568-
QStandardItemModel* pModel = dynamic_cast<QStandardItemModel*>(model());
569-
if(!pModel) return nullptr;
570-
auto item = pModel->itemFromIndex(index);
571-
if(!item) return nullptr;
572-
auto ri = new QStandardItem(item->text());
573-
ri->setData(item->data());
574-
return ri;
609+
610+
if(bRet)
611+
event->accept();
612+
else
613+
event->ignore();
575614
}
576615

577616
void CFavoriteView::mousePressEvent(QMouseEvent *event)
578617
{
618+
qDebug(log) << "mousePressEvent";
579619
if (event->button() == Qt::LeftButton)
580620
m_DragStartPosition = event->pos();
581-
QTreeView::mousePressEvent(event);
621+
QWidget::mousePressEvent(event);
582622
}
583623

584624
void CFavoriteView::mouseMoveEvent(QMouseEvent *event)
@@ -591,22 +631,61 @@ void CFavoriteView::mouseMoveEvent(QMouseEvent *event)
591631
< QApplication::startDragDistance())
592632
break;
593633
qDebug(log) << "mouseMoveEvent drag";
634+
// 获取选中的索引
635+
QModelIndexList indexes = m_pTreeView->selectionModel()->selectedIndexes();
636+
if (indexes.isEmpty()) {
637+
break;
638+
}
594639
QDrag *drag = new QDrag(this);
595640
CFavoriteMimeData *pData = new CFavoriteMimeData();
596-
pData->m_Items = this->selectionModel()->selectedIndexes();
641+
pData->m_Items = indexes;
597642
drag->setMimeData(pData);
598-
599643
Qt::DropAction dropAction = Qt::MoveAction;
600-
if(event->modifiers() & Qt::ControlModifier)
644+
/*
645+
if(event->modifiers() & Qt::ControlModifier) {
601646
dropAction = Qt::CopyAction;
647+
// 设置拖拽时的光标
648+
// QIcon icon = QIcon::fromTheme("edit-copy");
649+
// QSize size(16, 16);
650+
// if(!icon.availableSizes().isEmpty())
651+
// size = icon.availableSizes().at(0);
652+
// drag->setDragCursor(icon.pixmap(size), Qt::MoveAction);
653+
}//*/
602654
drag->exec(dropAction);
603655
} while (false);
604656

605-
QTreeView::mouseMoveEvent(event);
657+
QWidget::mouseMoveEvent(event);
606658
}
607-
//*/
659+
608660
bool CFavoriteView::eventFilter(QObject *watched, QEvent *event)
609661
{
662+
// 处理 treeview 的事件
663+
if (watched == m_pTreeView->viewport()) { // 处理 viewport 的事件
664+
qDebug(log) << Q_FUNC_INFO << "Viewport event:" << event->type();
665+
666+
switch (event->type()) {
667+
case QEvent::DragEnter:
668+
dragEnterEvent(static_cast<QDragEnterEvent*>(event));
669+
return true;
670+
case QEvent::DragMove:
671+
dragMoveEvent(static_cast<QDragMoveEvent*>(event));
672+
return true;
673+
case QEvent::Drop:
674+
dropEvent(static_cast<QDropEvent*>(event));
675+
return true;
676+
case QEvent::MouseButtonPress:
677+
mousePressEvent(static_cast<QMouseEvent*>(event));
678+
// 不返回true,让 viewport 也处理
679+
break;
680+
case QEvent::MouseMove:
681+
mouseMoveEvent(static_cast<QMouseEvent*>(event));
682+
// 不返回true,让 viewport 也处理
683+
break;
684+
default:
685+
break;
686+
}
687+
}
688+
610689
return QWidget::eventFilter(watched, event);
611690
}
612691

App/Client/Favorite/FavoriteView.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,21 +35,20 @@ public Q_SLOTS:
3535
const QString& szName = QString(),
3636
const QString& szDescription = QString(),
3737
const QIcon& icon = QIcon());
38-
virtual bool eventFilter(QObject *watched, QEvent *event) override;
3938

4039
Q_SIGNALS:
4140
void sigStart(const QString &szFile, bool bOpenSettings);
4241
void sigFavorite();
4342

44-
// QWidget interface
4543
protected:
44+
virtual bool eventFilter(QObject *watched, QEvent *event) override;
4645
virtual void dragEnterEvent(QDragEnterEvent *event) override;
4746
virtual void dragMoveEvent(QDragMoveEvent *event) override;
4847
virtual void dropEvent(QDropEvent *event) override;
49-
/*
48+
5049
virtual void mousePressEvent(QMouseEvent *event) override;
5150
virtual void mouseMoveEvent(QMouseEvent *event) override;
52-
*/
51+
5352
private slots:
5453
void slotFavrtieClicked(const QModelIndex &index);
5554
void slotFavortiedoubleClicked(const QModelIndex &index);

0 commit comments

Comments
 (0)