[SOLVED] QML: Dynamic view re-ordering in original model


Implemented QML Dynamic View Ordering by Dragging View Items using this Qt tutorial: QML Dynamic View Ordering Tutorial. Original underlying model is QAbstractListModel descendant in our case. Model stores data in a QList<QObject*> objectList; field type. Works fine, however item ordering changed in proxy DelegateModel only.

How to change items order automatically in original underlying model as well for other C++ and QML consumers where order matters? Or I could we otherway access some resulted (sorted) List Model model from C++ somehow?

Thanks for any help!


In the QML Dynamic View Ordering Tutorial 3 example I’ve replaced visualModel.items.move() call with my ObjectListModel::move() method like this:

ObjectListModel : public QAbstractListModel:

void ObjectListModel::move(int from, int to)
    if(0 <= from && from < count() && 0 <= to && to < count() && from != to) {
        if(from == to - 1) // Allow item moving to the bottom
            to = from++;

        beginMoveRows(QModelIndex(), from, from, QModelIndex(), to);
        objectList.move(from, to);

Delegate component:

DropArea {
    anchors { fill: parent; }

    onEntered: {
        let from = drag.source.DelegateModel.itemsIndex
        let to = mouseArea.DelegateModel.itemsIndex
        objectListModel.move(from, to)

And above works perfectly for the ListView and ObjectListModel itself – I have checked: items (and therefore objects) are moved correctly, indexes are correct, C++ consumers works just fine and take new order into account correctly, etc.

However another consumer like MapItemView fails to use the model after beginMoveRows/endMoveRows calls: moved item disappeared on the map and other manipulations with an item crashes the app.

 Map {
     MapItemView {
         model: objectListModel

         delegate: SomeItemIndicator {

Reported QTBUG-81076 bug, which is confirmed.


Found workaround for now: created 2nd duplicate model which content will be replaced completely on every change in the 1st model on every add/delete/moving(reordering). Above works since beginResetModel/endResetModel works correctly for MapItemView. So MapItemView now utilizes only the 2nd model. So on every 1st model change this method is called for the 2nd model:

QObjectList ObjectListModel::swapObjectList(const QObjectList& newlist)
    QObjectList oldlist(_objectList);
    _objectList = newlist;
    return oldlist;

Answered By – Aleksey Kontsevich

Answer Checked By – David Goodson (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *