ListView : delay between onRowsRemoved and actual deletion of the delegate
-
Hi !
I am using a
ListView
that displays a model defined in C++ based on aQAbstractListModel
.Each delegate of the
ListView
contains a delete button to delete the item in the model on which the delegate is based.ListView { Connections { target: projects onRowsRemoved: { console.log('the row has been removed in the model') } } model: projects delegate: Item { // stuff Component.onDestruction: { console.log('component destroyed') } Button { text: 'Delete the ' + project.name + ' project' // each item in the projects model is accessible through 'project' onClicked: { projects.remove(project) // remove the current item from the model } } } }
In C++, the method
remove(Project *project);
is what is called by QML and looks like this :void ProjectsModel::remove(Project *project) { size_t index = getIndexInModel(project); // returns the index of project in the list beginRemoveRows(QModelIndex(), index, index); delete _projects.at(index); _projects.removeAt(index); endRemoveRows(); }
When I run my program and delete a row by clicking on the button, I get the following output :
qml: the row has been removed in the model qrc:xxx.qml: TypeError: Cannot read property 'name' of undefined qml: component destroyed
It seems that there is a delay between the row being removed in the model and the actual removal of the delegate that represent that row. This delay is long enough that it allows the bindings to be processed and the delegate to try to access the content of the item that has already been deleted.
Since the ViewList aknowledge that the row has been removed (as can be seen with the message logged when the
rowsRemoved
is received), but do not delete the delegate right away.Am I missing something ? I do not really understand why it is possible for a deleted row to still have its delegates bindings processed.
Any ideas on how to fix this problem ?
Thanks !
-
@ebatsin
my first guess would be garbage collection.
Also just to make sure: You haven't set theListView.delayRemove
attached proeprty right?Also where does
project
come from exactly? How is it instantiated?Any ideas on how to fix this problem ?
see the attached properties/signals of ListView element
For example, maybe the ListView.remove() signal is emitted earlier than Component.onCompleted.
-
ListView.delayRemoved
isfalse
My project list is simply a
QList<Project*> _projects;
To append to it I have the following method :
void ProjectsModel::append(Project* project) { int index = _projects.count(); beginInsertRows(QModelIndex(), index, index); _projects.insert(index, project); endInsertRows(); }
And to access
project
in QML, myProjectsModel
defines the roleproject
and returns it like this :QVariant ProjectsModel::data(QModelIndex const& index, int role = Qt::UserRole) const override { // boundary checks // I do not check the role since I defined only one user role & I always want to return the whole project. return QVariant::fromValue(_projects[index.row()]); }
I'll look into the order in which the signals are emitted