How to filter QListView that contains with QSortFilterProxyModel?



  • Hello all.

    I have list of my own data type in class subclassed from QAbstreactListModel, I set this source to QSortFilterProxyModel on order to filter it. but I display the items in list view with delegate's paint method.
    how can I filter this data? each of my object contains an pixmap, and QStrings(name, last name,etc.) and I paint this data on list view next to each other in each row.
    i tried this.
    @
    proxy = new QSortFilterProxyModel;
    proxy->setSourceModel(model);
    listView->setModel(proxy);
    listView->setItemDelegate(delegate);

    searchLine = new QLineEdit;
    connect(searchLine,SIGNAL(textChanged(QString)),this,SLOT(onNewFilterText(QString)));

    void onNewFilterTExt(QString filter)
    {
    proxy->setDynamicSortFilter(true);
    proxy->setFilterFixedString(filter);
    }
    @

    but when I type even 1 character, the view gets empty. what is wrong and how can I fix it?
    thank you!


  • Moderators

    the posted code of yours should work.
    The default implementation of QSortFilterProxyModel filters all columns (using the DisplayRole) of your source model.

    The only thing that comes to my mind is that you type in lower-case text but the data is upper-case? By default QSortFilterProxyModel is case-sensitive (see QSortFilterProxyModel::setFilterCaseSensitivity())



  • I'm doing this.
    @
    void MainWindow::onNewFilterText(QString filter)
    {
    QList<Connection> searchDataList;
    foreach (Connection conn, model->getData())
    {
    if(conn.getName().contains(filter,Qt::CaseInsensitive)
    ||conn.getProductName().contains(filter,Qt::CaseInsensitive)||
    conn.getOS().contains(filter,Qt::CaseInsensitive)||
    conn.getOS().contains(filter,Qt::CaseInsensitive)||
    conn.getProtocol().contains(filter,Qt::CaseInsensitive))
    {
    searchDataList.append(conn);
    }
    }
    }
    @
    but how to set this list to the proxy?



  • I set it case insensitive but no result.


  • Moderators

    [quote author="tokafr" date="1421828913"]I'm doing this.
    @
    void MainWindow::onNewFilterText(QString filter)
    {
    QList<Connection> searchDataList;
    foreach (Connection conn, model->getData())
    {
    if(conn.getName().contains(filter,Qt::CaseInsensitive)
    ||conn.getProductName().contains(filter,Qt::CaseInsensitive)||
    conn.getOS().contains(filter,Qt::CaseInsensitive)||
    conn.getOS().contains(filter,Qt::CaseInsensitive)||
    conn.getProtocol().contains(filter,Qt::CaseInsensitive))
    {
    searchDataList.append(conn);
    }
    }
    }
    @
    but how to set this list to the proxy?[/quote]

    this is the wrong approach. QSortFitlerProxyModel already provides all you need.

    Please post the data() method of your source model.



  • @
    QVariant Model::data(const QModelIndex &index, int role) const
    {

    QVariant data;
    if(!index.isValid())
    {
    return QVariant();
    }

    if(index.row() < 0 || index.row() >= dataList.size())
    {
    return QVariant();
    }

    if(role == Qt::DecorationRole || role == Qt::DisplayRole)
    {

     data.setValue(dataList.at(index.row()));
    return data;
    

    }

    return QVariant();
    }
    @



  • I declared my data type as metatype with
    @
    Q_DECLARE_METATYPE(Connection)
    @


  • Moderators

    @
    if(role == Qt::DecorationRole || role == Qt::DisplayRole)
    {
    data.setValue(dataList.at(index.row()));
    return data;
    }
    @
    whats the type of the items contained in "dataList"? I guess they are not of type QString. Thats the reason why it doesn't work because it tried to find your entered text inside an empty string.

    You need to return a string representation for Qt::DisplayRole, because QSortFilterProxyModel uses this role by default for filtering.

    Or you introduce a new item role and tell QSortFilterProxyModel to do the filtering on this role:

    @
    QVariant Model::data(const QModelIndex &index, int role) const
    {

      QVariant data;
      if(!index.isValid())
      {
        return QVariant();
      }
     
      if(index.row() < 0 || index.row() >= dataList.size())
      {
        return QVariant();
      }
     
      if(role == Qt::DecorationRole || role == Qt::DisplayRole)
      {
     
         data.setValue(dataList.at(index.row()));
        return data;
      }
      else if( role == Qt::UserRole )
           return dataList.at(index.row())->toString(); //<--- adapt this to return QString
     
      return QVariant();
    }
    

    @

    and then this on your proxy model:
    @
    proxy->setFilterRole( Qt::UserRole );
    @



  • that's it thank you!



  • I had already told you that in one of your other topics, by the way.

    Please stop opening topics on the same problem over and over again.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.