@@ -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
509516void 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
521536void 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
525575void 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
577616void 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
584624void 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+
608660bool 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
0 commit comments