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 part

    insertRows(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.



  • @joeQ
    Thanks, but I need both actions.


  • Lifetime Qt Champion

    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
        }
    
    }
    


  • @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!



  • @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 the QListView class. You can search QListView in qt help. and You will find the drag and drop virtual function.



  • @joeQ

    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

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.