ListView with QSortFilterProxyModel displays empty lines resulting to the error "Unable to assign [undefined] to QString"
-
Hi,
My app is using a ListView with its model coming from C++. Everything was ok using my custom QAbstractListModel following the doc.
I now wish to add a filtering feature and thus, I've switched the model to be a QSortFilterProxyModel whose source is my QAbstractListModel.
It is working but I've an issue I'd like to remove.Basically if my model doesn't fill the whole ListView, let's say only 7 rows where the view could display 10, then with a QSortFilterProxyModel, blank rows are displayed and selectable so I'm getting this error in the console:
qrc:/Playlist.qml:54:17: Unable to assign [undefined] to QString
Any idea what I should do to remove this behaviour?This is not happening when I'm using a QAbstractListModel. It's quite a bad user experience to be able to select blank rows. cf this snapshot
I've tried to do a Custom QSortFilterProxyModel as I'll need it anyway and try to trick the filter function to only accept valid rows but it doesn't seem to work. Here would be the code:
bool PlayListProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { ClementineRemote *remote = static_cast<PlayListModel *>(sourceModel())->remote(); if (sourceRow < remote->nbSongs()) return true; else return false; }
I suppose
sourceRow
is the index on the model.remote->nbSongs()
is returning the number of elements the model is exposing.Any idea what I could do?
Edit1: if I display the ListView.count, I'm getting 14 using the QSortFilterProxyModel, 7 as expected with a QAbstractListModel. if it is the double exactly there must be a reason no?
Edit2: no in fact it is random, if I use 8 elements in the model, I'm getting 11 rows in the view using the proxy (8 with the model)
-
wow really weird I found a way to make the BUG disappear by adding a debug which display the rowCount on the proxy model before I'm modifying the data (signalling the Model....)
I didn't understand yesterday how I managed to fix the issue.
Today by removing my debugs, the bug came back. By checking my commits, I managed to find up one debug line was needed to remove the bug...
Here is my code to populate my data and Model:void ClementineRemote::rcvPlaylistSongs(pb::remote::ResponsePlaylistSongs *songs) { // HACK to resolve ListView issue (displaying empty Rows after the number of elements) // cf https://forum.qt.io/topic/120302/listview-with-qsortfilterproxymodel-displays-empty-lines-resulting-to-the-error-unable-to-assign-undefined-to-qstring qint32 proxyRows = _playlistProxyModel->rowCount(); // qDebug() << "proxy row count before removal: " << proxyRows; emit preClearSongs(_songs.size() - 1); _songs.clear(); emit postSongRemoved(); emit preAddSongs(songs->songs_size() -1 ); _songs.reserve(songs->songs_size()); for (auto it = songs->songs().cbegin(), itEnd = songs->songs().cend(); it != itEnd; ++it) _songs.append(*it); emit postSongAppended(); }
So basically my model is connected on the
_song
list with those connections:void PlayListModel::setRemote(ClementineRemote *remote) { beginResetModel(); if (_remote) _remote->disconnect(this); _remote = remote; if (_remote) { connect(_remote, &ClementineRemote::preAddSongs, this, [=](int lastSongIdx) { beginInsertRows(QModelIndex(), 0, lastSongIdx); }); connect(_remote, &ClementineRemote::postSongAppended, this, [=]() { endInsertRows(); }); connect(_remote, &ClementineRemote::preClearSongs, this, [=](int lastSongIdx) { beginRemoveRows(QModelIndex(), 0, lastSongIdx); }); connect(_remote, &ClementineRemote::postSongRemoved, this, [=]() { endRemoveRows(); }); } endResetModel(); }
So any idea what I'm doing wrong or why do I need to call this
qint32 proxyRows = _playlistProxyModel->rowCount();
in order for the ListView to get the correct number of rows on the proxy once the Model is repopulated?
Is it a bug? -
The issue comes from the fact I'm updating the data from a
ConnectionWorker
Thread instead of the GUI one...
I've opened another thread more general to see how I could fix that.