Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to implement simple internal drag&drop for reordering items in QListView using a custom model



  • I have a QList of custom structs and i'm using custom model class (subclass of QAbstractListModel) to display those structs in 1-dimensional QListView. I have overriden the methods rowCount, flags and data to construct a display string from the struct elements.

    Now i would like to enable internal drag&drop to be able to reorder the items in the list by dragging them and dropping them between some other items, but this task seems unbeliavably complicated. What exactly do i need to override and what parameters do i need to set? I tried a lot of things, i tried

    view->setDragEnabled( true );
    view->setAcceptDrops( true );
    view->setDragDropMode( QAbstractItemView::InternalMove );
    view->setDefaultDropAction( Qt::MoveAction );
    

    I tried

    Qt::DropActions supportedDropActions() const override {
        return Qt::MoveAction;
    }
    Qt::ItemFlags flags( const QModelIndex & index ) const override{
        return QAbstractItemModel::flags( index ) | Qt::ItemIsDragEnabled;
    }
    

    I tried implementing insertRows and removeRows, but it still doesn't work.

    I haven't found a single example of a code doing exactly that. The official documentation goes very deeply into how view/model pattern works and how to make drag&drops from external apps or from other widgets, but i don't want any of that. I only want simple internal drag&drop for manual reordering of the items in that one list view and nothing more.

    Can someone please help me? Or i'll get nuts from this.


  • Lifetime Qt Champion

    Hi
    When the build in drag & drop is not enough, then for the model you need to override
    mimeType()
    mimeData()
    dropMimeData()

    example.
    https://www.qtcentre.org/threads/51679-How-to-Drag-and-Drop-working-with-tableview

    ps. Qt Models and Views will drive you slightly nuts but really worth it :)



  • But this
    https://doc.qt.io/qt-5/model-view-programming.html#accepting-dropped-data
    says QAbstractListModel has default implementations of mimeType, mimeData, dropMimeData, that should do everything i need.


  • Lifetime Qt Champion

    @Youda008
    hi
    Yes, you are right, but last time i fiddled with view/custom model DD, it would only accept copy operations and that didn't not work so well with internal reordering. ;)
    I could be wrong though. Maybe we get lucky and @VRonin comes around and tell the painful truth :)



  • I got quite a good answer here https://stackoverflow.com/questions/56819085/qt-how-to-implement-simple-internal-dragdrop-for-reordering-items-in-qlistview
    Additionally i discovered few other important things about how it works, which i included in my own answer.
    Not gonna copy&paste here. TL,DR: default mimeData and dropMimeData work only if your underlying data structure only contains elements serialized inside data and deserialized in setData on EditRole. If there is something more in your structs than those display elements, you need your own mimeData and dropMimeData to move the whole content of your struct.


  • Lifetime Qt Champion


Log in to reply