Disable auto remove row in drag drop
-
Hi,
I made a drag and drop support for TreeView/ListView according to
http://doc.qt.io/qt-4.8/model-view-programming.html
I did not included the partinsertRows(beginRow, rows, QModelIndex()); foreach (const QString &text, newItems) { QModelIndex idx = index(beginRow, 0, QModelIndex()); setData(idx, text); beginRow++; }
because I did it manually in mainWindow. When I drag by Qt::CopyAction, I have no problem.
The problem is that when I move an item from ListView to TreeView by Qt::MoveAction, it seems it automatically removes a row in QListView.
It may make sence. But I would like to do it manually in mainWindow. How can I disable this removing row automatically function when I use Qt::MoveAction?And When I drag files by Qt::CopyAction, it shows "+" mouse cursor shape and by Qt::MoveAction, it shows "->" mouse cursor shape. How can I change these shape to other shapes?
-
@samdol Hi, friend, welcome.
Maybe you can try the
Qt::CopyAction
. Try again.Qt manual:
Qt::CopyAction Copy the data to the target.
Qt::MoveAction Move the data from the source to the target. -
Hi,
If you want to change the original behaviour then you have to re-implement the drag and drop feature to match what you want to do.
Out of curiosity, why do you want that modified behaviour ?
-
@samdol oh, maybe you should reimplement the
drag and drop event
. like following code.void ListWidget::dragEnterEvent(QDragEnterEvent *event) { if (event->mimeData()->hasFormat("image/list-item")) event->accept(); else event->ignore(); } void ListWidget::dragMoveEvent(QDragMoveEvent *event) { if (event->mimeData()->hasFormat("image/list-item")) { event->setDropAction(Qt::MoveAction); event->accept(); } else { event->ignore(); } } void ListWidget::dropEvent(QDropEvent *event) { QListWidgetItem *pItem = NULL; QListWidgetItem *pPosItem = NULL; if (event->mimeData()->hasFormat("image/list-item")) { if( NULL == m_pDragItem ) { event->ignore(); return; } pPosItem = itemAt( event->pos() ); if( NULL == pPosItem ) { event->ignore(); return; } pItem = m_pDragItem->clone(); insertItem(row(pPosItem), pItem); ///< insert item event->setDropAction(Qt::MoveAction); m_pDragItem = NULL; event->accept(); } } void ListWidget::startDrag(Qt::DropActions supportedActions) { Q_UNUSED( supportedActions ); QDrag *pDrag = NULL; QByteArray itemData; QMimeData *pMimeData = NULL; QListWidgetItem *pItem = currentItem(); if( NULL == pItem ){return;} if( NULL != m_pDragItem ){return;} if( count() <= 1 ){return;} clearSelection(); pMimeData = new QMimeData; pMimeData->setData("image/list-item", itemData); pDrag = new QDrag(this); pDrag->setMimeData(pMimeData); m_bDraging = true; m_pDragItem = pItem; if (pDrag->exec(Qt::MoveAction) == Qt::MoveAction) { /** after the drag and not to delete the item */ //delete takeItem(row(pItem)); ///< remove the item } }
-
@samdol oh, maybe you should reimplement the
drag and drop event
. like following code.void ListWidget::dragEnterEvent(QDragEnterEvent *event) { if (event->mimeData()->hasFormat("image/list-item")) event->accept(); else event->ignore(); } void ListWidget::dragMoveEvent(QDragMoveEvent *event) { if (event->mimeData()->hasFormat("image/list-item")) { event->setDropAction(Qt::MoveAction); event->accept(); } else { event->ignore(); } } void ListWidget::dropEvent(QDropEvent *event) { QListWidgetItem *pItem = NULL; QListWidgetItem *pPosItem = NULL; if (event->mimeData()->hasFormat("image/list-item")) { if( NULL == m_pDragItem ) { event->ignore(); return; } pPosItem = itemAt( event->pos() ); if( NULL == pPosItem ) { event->ignore(); return; } pItem = m_pDragItem->clone(); insertItem(row(pPosItem), pItem); ///< insert item event->setDropAction(Qt::MoveAction); m_pDragItem = NULL; event->accept(); } } void ListWidget::startDrag(Qt::DropActions supportedActions) { Q_UNUSED( supportedActions ); QDrag *pDrag = NULL; QByteArray itemData; QMimeData *pMimeData = NULL; QListWidgetItem *pItem = currentItem(); if( NULL == pItem ){return;} if( NULL != m_pDragItem ){return;} if( count() <= 1 ){return;} clearSelection(); pMimeData = new QMimeData; pMimeData->setData("image/list-item", itemData); pDrag = new QDrag(this); pDrag->setMimeData(pMimeData); m_bDraging = true; m_pDragItem = pItem; if (pDrag->exec(Qt::MoveAction) == Qt::MoveAction) { /** after the drag and not to delete the item */ //delete takeItem(row(pItem)); ///< remove the item } }
@joeQ
Thank you so much for supplying code. But When I put it in my IconView class which is subclassing of QListView, I got the following error messages. Did I put in the wrong place? QIconView uses a subclass of QSortFilterProxyModel. I am using Qt 5.6.2 windows binary.error: 'm_pDragItem' was not declared in this scope
if( NULL == m_pDragItem )
error: 'itemAt' was not declared in this scope
pPosItem = itemAt( event->pos() );
^
error: 'm_pDragItem' was not declared in this scope
pItem = m_pDragItem->clone();
^
^
error: 'row' was not declared in this scope
insertItem(row(pPosItem), pItem); ///< insert item
^
error: 'insertItem' was not declared in this scope
insertItem(row(pPosItem), pItem); ///< insert item
^
error: 'currentItem' was not declared in this scope
QListWidgetItem *pItem = currentItem();
^
error: 'm_pDragItem' was not declared in this scope
if( NULL != m_pDragItem ){return;}
^
error: 'count' was not declared in this scope
if( count() <= 1 ){return;}
^
error: 'm_bDraging' was not declared in this scope
m_bDraging = true;
^
error: 'm_pDragItem' was not declared in this scope
m_pDragItem = pItem;
^ -
@joeQ
Thank you so much for supplying code. But When I put it in my IconView class which is subclassing of QListView, I got the following error messages. Did I put in the wrong place? QIconView uses a subclass of QSortFilterProxyModel. I am using Qt 5.6.2 windows binary.error: 'm_pDragItem' was not declared in this scope
if( NULL == m_pDragItem )
error: 'itemAt' was not declared in this scope
pPosItem = itemAt( event->pos() );
^
error: 'm_pDragItem' was not declared in this scope
pItem = m_pDragItem->clone();
^
^
error: 'row' was not declared in this scope
insertItem(row(pPosItem), pItem); ///< insert item
^
error: 'insertItem' was not declared in this scope
insertItem(row(pPosItem), pItem); ///< insert item
^
error: 'currentItem' was not declared in this scope
QListWidgetItem *pItem = currentItem();
^
error: 'm_pDragItem' was not declared in this scope
if( NULL != m_pDragItem ){return;}
^
error: 'count' was not declared in this scope
if( count() <= 1 ){return;}
^
error: 'm_bDraging' was not declared in this scope
m_bDraging = true;
^
error: 'm_pDragItem' was not declared in this scope
m_pDragItem = pItem;
^@samdol Hi, friend. My code was copied from my Qt project. And if you want to use it. First you should understand it means. and then modify some code. In my code, It's OK in my project but it is not for you.
In
QListView
, has the drag and drop virtual function, you should like me to Re-implementation them. You should to understand the code frame but just to copy it.good luck for you!
-
@samdol Hi, friend. My code was copied from my Qt project. And if you want to use it. First you should understand it means. and then modify some code. In my code, It's OK in my project but it is not for you.
In
QListView
, has the drag and drop virtual function, you should like me to Re-implementation them. You should to understand the code frame but just to copy it.good luck for you!
-
@joeQ
Sorry, But when I click the link, it says
Not Found
You seem to have stumbled upon a page that does not exist. Return to the home page.
Is the link available? -
@samdol The link is http://doc.qt.io/qt-5/qlistview.html
I just search theQListView
class. You can searchQListView
in qt help. and You will find thedrag and drop virtual function
.Thank you about the link.
I followed
http://doc.qt.io/qt-5/model-view-programming.html
and drag/drop item by MoveAction. It runs
bool MyModel::dropMimeData(const QMimeData *data,
Qt::DropAction action, int row, int column, const QModelIndex &parent)
and drag/drop works fine, except the original item is removed by MoveAction.In order to prevent removing the original item, I reimplemeted the member functions of IconView class which is subclass of QListView. When I did the same drag/drop, it did not run bool MyModel::dropMimeData() function.
What should I change to make it run dropMimeData() function?
Here is my reimplemented member functions of IconView
,```
void startDrag(Qt::DropActions supportedActions)
{
qDebug()<<"startDrag()";
Q_UNUSED( supportedActions );QDrag *pDrag = new QDrag(this); QByteArray itemData; QMimeData *pMimeData = new QMimeData; pMimeData->setData("application/copy_cut_row.list", itemData); pDrag->setMimeData(pMimeData); Qt::DropAction dropAction = pDrag->exec(Qt::CopyAction | Qt::MoveAction); if (dropAction == Qt::MoveAction) { // after the drag and not to delete the item //delete takeItem(row(pItem)); ///< remove the item } } void dragEnterEvent(QDragEnterEvent *event) { qDebug()<<"dragEnterEvent()"; if (event->mimeData()->hasFormat("application/copy_cut_row.list")){ qDebug()<<"event->accept();"; event->acceptProposedAction(); // event->accept(); }else{ qDebug()<<"event->ignore();"; event->ignore(); } } void dropEvent(QDropEvent *event) { qDebug()<<"dropEvent()"; // event->acceptProposedAction(); // IconView *source= qobject_cast<IconView*>(event->source()); // if(source && source != this) if (event->mimeData()->hasFormat("application/copy_cut_row.list")){ qDebug()<<"hasFormat"; event->setDropAction(Qt::MoveAction); //To tell the source widget that it can now remove the original version of the dragged item. event->accept(); //event->acceptProposedAction(); } }
And I got the following result: I got the following result. startDrag() dragEnterEvent() event->accept(); dropEvent() hasFormat