Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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
    alt text

    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.


Log in to reply