Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Solution: Rearranging QAbstractListModel by dragging and dropping in ListView
Forum Updated to NodeBB v4.3 + New Features

Solution: Rearranging QAbstractListModel by dragging and dropping in ListView

Scheduled Pinned Locked Moved QML and Qt Quick
1 Posts 1 Posters 63 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • N Offline
    N Offline
    nova_xo
    wrote 28 days ago last edited by nova_xo 5 Nov 2025, 11:08
    #1

    Following is a code snippet that allows for Rearranging QAbstractListModel by dragging and dropping it's ListView delegates. It is fully dynamic.

    I couldn't find any official documentation for this and what I did find was very obscure. I've been trying to get this in a project of mine for a week now and finally found a solution. All of the following code has been tested in Qt 6.9

    ListView {
            id: listview
            width: parent.width
            height: parent.height
            z: 5
            spacing: 10
    
            anchors {
                top: label_br.bottom
                topMargin: 10
                horizontalCenter: parent.horizontalCenter
            }
    
            displaced: Transition {
                NumberAnimation {
                    properties: "x,y"
                    easing.type: Easing.OutQuad
                }
            }
    
    
            model: DelegateModel {
                id: visualModel
                model: Model
    
                delegate: DropArea {
                    id: delegateRoot
                    required property var modelData
                    property int visualIndex: DelegateModel.itemsIndex
                    property int modelIndex
    
                    height: queue_item.fontsize * 2
                    width: listview.width * 0.95
                    anchors.horizontalCenter: parent?.horizontalCenter
    
                    onEntered: function (drag) {
                        var from = (drag.source as Queue_tile).visualIndex
                        var to = tile.visualIndex
                        visualModel.items.move(from, to)
                    }
    
                    onDropped: function (drag) {
                        var from = modelIndex
                        var to = (drag.source as Queue_tile).visualIndex
                        Model.move(from, to)
                    }
    
                    Queue_tile {
                        id: tile
                        height: queue_item.fontsize * 2
                        width: listview.width * 0.95
                        dragParent: listview
                        visualIndex: delegateRoot.visualIndex
                        onPressed: delegateRoot.modelIndex = visualIndex
                        color: "transparent"
                        
                        //Your content. make sure it doesnt already contain a mousearea as that will interfere with the tile wrapper
                        Queue_item {
                            id: queue_item
                            title: delegateRoot.modelData.title
                            anchors.centerIn: parent
                            width: listview.width * 0.95
                        }
                    }
                }
            }
        }
    

    Queue_tile.qml

    import QtQuick
    
    Rectangle {
        id: root
        required property Item dragParent
        signal pressed
        signal released
        signal clicked
    
        property int visualIndex: 0
    
        anchors {
            horizontalCenter: parent.horizontalCenter
            verticalCenter: parent.verticalCenter
        }
        radius: 3
    
        MouseArea {
            id: mouseArea
            anchors.fill: parent
            drag.target: root
            onClicked: root.clicked()
            onPressed: root.pressed()
            onReleased: {
                parent.Drag.drop()
                root.released()
            }
        }
    
        Drag.active: mouseArea.drag.active
        Drag.source: root
        Drag.hotSpot.x: root.width / 2
        Drag.hotSpot.y: root.height / 2
    
        states: [
            State {
                when: mouseArea.drag.active
                ParentChange {
                    target: root
                    parent: root.dragParent
                }
    
                AnchorChanges {
                    target: root
                    anchors.horizontalCenter: undefined
                    anchors.verticalCenter: undefined
                }
            }
        ]
    }
    
    

    Credits: It has been adapted from the gridview implementation from https://raymii.org/s/tutorials/Qml_Drag_and_Drop_example_including_reordering_the_Cpp_Model.html . It's an old solution and hadn't been tested in latest versions of Qt.

    1 Reply Last reply
    0
    • N nova_xo marked this topic as a regular topic 28 days ago

    1/1

    11 May 2025, 11:06

    • Login

    • Login or register to search.
    1 out of 1
    • First post
      1/1
      Last post
    0
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Get Qt Extensions
    • Unsolved