Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. ListView with QSortFilterProxyModel displays empty lines resulting to the error "Unable to assign [undefined] to QString"
Forum Updated to NodeBB v4.3 + New Features

ListView with QSortFilterProxyModel displays empty lines resulting to the error "Unable to assign [undefined] to QString"

Scheduled Pinned Locked Moved Solved QML and Qt Quick
3 Posts 1 Posters 1.6k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • mbruelM Offline
    mbruelM Offline
    mbruel
    wrote on last edited by mbruel
    #1

    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)

    1 Reply Last reply
    0
    • mbruelM Offline
      mbruelM Offline
      mbruel
      wrote on last edited by
      #2

      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?

      1 Reply Last reply
      0
      • mbruelM Offline
        mbruelM Offline
        mbruel
        wrote on last edited by
        #3

        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.

        1 Reply Last reply
        0

        • Login

        • Login or register to search.
        • First post
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • Users
        • Groups
        • Search
        • Get Qt Extensions
        • Unsolved