Search code examples
qtlistviewqmlqtquick2qsqltablemodel

QML Remove Animation of ListView Item with a QSqlTableModel


I'm using a list view with a QSqlTableModel in the background. I use also a SwipeDelegate for the list view elements to provide a "delete button", as shown here:

Listview with SwipeDelegate Delete Button.

When the button is now pressed, the the item is deleted from the database using this code in the QSqlTableModel subclass:

void qsoModel::deleteQSO(int id) {
    removeRow(id);
    submitAll();
}

Side question: When I understood it correctly, removeRow is implicitly calling beginRemoveRows(...) and endRemoveRows()?

For the ListView I used a remove Transition:

    ListView {
        id: listView
        anchors.fill: parent
        model: qsoModel

        //...

        delegate: QSOItem {}

        remove: Transition {
               NumberAnimation { property: "opacity"; from: 1.0; to: 0; duration: 400 }
               NumberAnimation { property: "scale"; from: 1.0; to: 0.0; duration: 400 }
        }

However, If I press the delete button, the animation is not shown. the list element just disappears fastly. Any ideas why this is happening?

The complete source code can be found in this commit: https://github.com/myzinsky/cloudLogOffline/tree/b501d41a0f23d40139cfca9a6d4f724f4ab251b2


Solution

  • From looking at the code on github it looks like the model is executing the beginRemoveRows() and endRemoveRows() methods so I think this won't be the issue. And you say the records are removed from the database so I think the problem is more related to qml.

    So regarding the qml animations there are few things:

    First thing, if you want the opacity and scale animation parallel you will need to wrap them in a ParallelAnimation. Second thing is you will need to specify a transition for removeDisplaced otherwise the items that would be moved up in the list when you delete an item from the list are just being pushed to the new position covering the record that is executing the animation for removal. You should be able to see this if you assigned a transition to the removeDisplaced looking like this.

    removeDisplaced:Transition{
        NumberAnimation{
            property:"y" // Specifying "y" so the displaced records slowly proceed upwards
            duration:5000 // 5s should be enough to see what's actually happening
            easing.type: Easing.InOutQuad
        }
    }
    

    EDIT:

    The problem I mentioned in the original post wasn't the only problem. The problem is that the removeRow() function doesn't call beginRemoveRows() and endRemoveRows()! If you wrap those calls around the removeRow() call you will see animations happening. But you will still need to assign a transition to removeDisplaced to see everything happening.

    EDIT by Question Author

    The idea is to update the model after the animation from QML side:

    remove: Transition {
        SequentialAnimation {
            NumberAnimation {
                property: "opacity"
                from: 1.0
                to: 0
                duration: 400
            }
            ScriptAction {
                script: {
                    qsoModel.select()
                }
            }
        }
    }
    

    I just call select when the animation is done from the QML side