0

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

Matthias
  • 135
  • 10
  • Don't you have to use `ParallelAnimation` to combine your animations? As I remember a `Transition` should contain only one animation item. – folibis May 31 '20 at 09:33
  • ```qml remove: Transition { ParallelAnimation { running: true NumberAnimation { property: "opacity"; from: 1.0; to: 0; duration: 400 } NumberAnimation { property: "scale"; from: 1.0; to: 0.0; duration: 400 } } } ``` does not help either :( – Matthias May 31 '20 at 11:09
  • From what I can see the delete animation is not triggered at all :( – Matthias May 31 '20 at 21:20

1 Answers1

1

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

Matthias
  • 135
  • 10
luv4bytes
  • 144
  • 7
  • I think we are almost there. However, I changed the code like this: ```void qsoModel::deleteQSO(int id) { beginRemoveRows(QModelIndex(), id, id); removeRow(id); submitAll(); endRemoveRows(); } ``` And now always two rows are removed from the view. But only one row is removed from the database. Its really strange. Any more tips? Thank you so much! – Matthias Jun 02 '20 at 21:32
  • Ah found the problem. It was related to submitAll. Which I now did avoid. The current code is here: https://github.com/myzinsky/cloudLogOffline/commits/638eb424656064756701c1a6986c9ddabc1b5a03 – Matthias Jun 02 '20 at 23:09
  • Glad I could help figuring it out :) – luv4bytes Jun 03 '20 at 09:47
  • Sorry for bothering you again. But it is still not working correctly. The animations are still fine. But when I delete something. It is not always deleted from the database. Sometime the row stays in the database table and the deleted row shows up again in the next application start. Could you have a look on what still goes wrong here: https://github.com/myzinsky/cloudLogOffline/tree/2db27a64f1ef0d0e7e3211ece09093a74e3b251e Thank you! – Matthias Jun 04 '20 at 21:35
  • So, the problems that I found are that the entry gets deleted from the database, but it doesn't get deleted from the model. This is expected behaviour which is stated in the documentation saying "Deletions are submitted immediately to the database. The model retains a blank row for successfully deleted row until refreshed with select()." -> https://doc.qt.io/qt-5/qsqltablemodel.html#removeRows. This is why if the ListView is opened again the model displays an empty row. – luv4bytes Jun 06 '20 at 14:59
  • Meaning you need to call "select()" after deletion. This is where another problem occurs. Calling "select()" will repopulate the model, doing a complete reset. So the animation that is assigned to the removal will not be displayed completely, because the reset happens immediately so there is no time for the animation. One solution for you would be to assign an animation to "populate". – luv4bytes Jun 06 '20 at 15:33
  • Exactly this is what I observed. When I use select() everything works, but the animations are then not showing up. But I don't understand how a populate animation could help here, because it animates how the list is build up and not how one thing removes? – Matthias Jun 06 '20 at 17:37
  • I think I found the solution: ```qml 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 :) – Matthias Jun 06 '20 at 17:41