2
votes

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!

1

1 Answers

2
votes

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);
        endMoveRows();
    }
}

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.

Workaround:

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);
    beginResetModel();
    _objectList = newlist;
    endResetModel();
    return oldlist;
}