change QSortFilterProxyModel behaviour for multiple column filtering



  • Well let's say we have a QSortFilterProxyModel installed on a QTableView and two (or more) QLineEdit for filtering the view (based on the text of these QLineEdits)
    In our View we have slot that tell us the string of lineedits and the current column that we want
    Something like this :

    void onTextChange(int index, QString ntext) {
    	filter.setFilterKeyColumn(index);
    	filter.setFilterRegExp(QRegExp(ntext, Qt::CaseInsensitive));
    }
    

    On the first column we have names in the second we have year of birthday now we enter a year for column 2 (for example 1985) till now filtering is ok but when we switch to first lineedit and enter name (for example john) the previous filtering based on year will reset.
    How could we change this behaviour for our custom QSortFilterProxyModel ?
    (Actually when we change the filter keycolumn the filtermodel must filter existing view not reset it)



  • This is some old code I had. Looking at it there is a lot of room for optimisation but it does the job: http://pastebin.com/7yUnvW39

    use setDateRangeFilter and setRegExpFilter to set the filters you want



  • Most of the solutions I have seen regarding filtering of multiple columns involve subclassing QSortFilterProxyModel, which would likely have a very limited reusability. However, it is quite possible to chain proxy models that filter on different columns, resulting in the conditions being AND'ed.

    For example:

    QSqlTableModel *m = new QSqlTableModel(db); 
    // setup model
    
    QSortFilterProxyModel *nmFilter = new QSortFilterProxyModel(m);
    nmFilter->setSourceModel(m);
    nmFilter->setFilterKeyColumn(0);
    
    QSortFilterProxyModel *yrFilter = new QSortFilterProxyModel(m);
    yrFilter.setSourceModel(nmFilter);
    yrFilter.setFilterKeyColumn(1);
    
    QTableView *v = ui->tblPerson;
    v.setModel(yrFilter);
    
    // add slots to setFilterRegExp();
    

    Keep in mind the possible performance implications of chained proxies if you have very large models.


  • Moderators

    @IMAN4K

    1. subclass QSortFilterProxyModel
    2. get rid of the setFilterKeyColumn() calls
    3. Instead implement your custom setters of the filter-text for each column.
    4. In the setter call QSortFilterProxyModel::invalidate() everytime the filter-text changes
    5. reimplement QSortFilterProxyModel::filterAcceptsRow() and check if the Qt::DisplayData of the column matches your corresponding filter-text. Return true if it does, false otherwise


  • @raven-worx said in change QSortFilterProxyModel behaviour for multiple column filtering:

    1. reimplement QSortFilterProxyModel::filterAcceptsRow() and check if the Qt::DisplayData of the column matches your corresponding filter-text. Return true if it does, false otherwise

    QSortFilterProxyModel::filterRole() should be used instead of an arbitrary Qt::DisplayRole.
    Alternalively you can ditch it completely and do the same as you did for QSortFilterProxyModel::setFilterKeyColumn() that's what I did in the paste above

    @Glenn-Aycock said in change QSortFilterProxyModel behaviour for multiple column filtering:

    subclassing QSortFilterProxyModel, which would likely have a very limited reusability

    Subclassing QSortFilterProxyModel does not impact reusability at all. It does only if your implementation violates the D part of S.O.L.I.D. OOP principles





  • @IMAN4K said in change QSortFilterProxyModel behaviour for multiple column filtering:

    Answer from stackfverflow : http://stackoverflow.com/questions/39488901/change-qsortfilterproxymodel-behaviour-for-multiple-column-filtering

    This answer is the typical example that lead people to say

    subclassing QSortFilterProxyModel, which would likely have a very limited reusability

    It's bad. the proxy model implementation should not depend on the structure of the underlying data in sourceModel



  • This post is deleted!


  • This post is deleted!


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