Subclass of QSortFilterProxyModel to filter selected columns



  • Hi Everyone.

    I would like to create a subclass of QSortFilterProxyModel , which will filter selected columns. For example columns 1,4 and 6. Can someone help me?

    I already implement subclass, and now i want to change filterAcceptsRow function properly. Is this good idea?

    The reason why i want to do this is that my program using hiding columns in my qtableview. For example: column 3 and 4 is hidden. When filtering my proxy model columns 3 and 4 are also filtered ,what is incorrect for me.


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Shouldn't you rather reimplement filterAcceptColumn ?



  • I found functions:

    void QSortFilterProxyModel::setFilterKeyColumn(int column)
    {
    Q_D(QSortFilterProxyModel);
    d->filter_column = column;
    d->filter_changed();
    }

    AND

    bool QSortFilterProxyModel::filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const
    {
    Q_UNUSED(source_column);
    Q_UNUSED(source_parent);
    return true;
    }

    But I have no idea how to start reimplementing. Could you give me some advice?



  • I'm not exactly following what you want to do, but I found this thread useful when I wanted to filter based on multiple columns.



  • I used this code, but this sublclass is usefull for filtering columns with different filter on each of them.



  • Solution to this problem is very important for me. Can someone help me? Please


  • Lifetime Qt Champion

    The example shown in the filtering part of QFilterProxyModel's documentation shows how to filter only the columns 0, 1 and 2. You should be able to make your model from there.



  • I have a subclass of QHeaderView where I'm hiding columns. Also I implement in QHeaderView signal which sends to my QSortFilterProxyModel hidden columns (as bool, true if not hidden). Slot in QSortFilterProxyModel received that signal .I have about 10 different tables, each of them with different number of columns.

    SLOT in QSortFilterProxyModel:

        void SortFilterProxyModel::receiveHiddenColumns(bool* ichecked_columns)
        {
            checked_columns=ichecked_columns;
            for(int i=0;i<7;i++){
            qDebug()<<"R"<<ichecked_columns[i];
            }
        }
    

    This part of code works and filter only 0 and 1 column:

     bool SortFilterProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent) const
        {
            QModelIndex index0 = sourceModel()->index(sourceRow, 0, sourceParent);
            QModelIndex index1 = sourceModel()->index(sourceRow, 1, sourceParent);
    
    
            return  (sourceModel()->data(index0).toString().contains(filterRegExp())
                   || sourceModel()->data(index1).toString().contains(filterRegExp()));
     // HOW TO RETURN ONLY NOT HIDDEN COLUMNS????
        }
    

    I have no idea how to return in filterAcceptsRow() the appropriate columns depending on the received hidden.


  • Lifetime Qt Champion

    One solution would be to add a setter to your SortFilterProxyModel that takes a QList<int> that contains the hidden columns, and in filterAccpetsRow, use that list to check what you should do.



  • I have a different question. I declared bool * checked_columns=NULL in header file.

    #ifndef SORTFILTERPROXYMODEL_H
    #define SORTFILTERPROXYMODEL_H
    
    #include <QSortFilterProxyModel>
    #include <QDate>
    
    namespace CerSimpleDynamics
    {
    namespace Models
    {
        class SortFilterProxyModel : public QSortFilterProxyModel
        {
            Q_OBJECT
        public:
            explicit SortFilterProxyModel(int columns_maximum, QObject *parent = 0);
            int columns_max;
            bool * checked_columns=NULL;
    
       public slots:
            void receiveHiddenColumns(bool* ichecked_columns);
    
       protected:
            bool filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent) const;
    
        private:
        };
    }
    

    }

    #endif // SORTFILTERPROXYMODEL_H
    

    Then i received signal in my SLOT receiveHiddenColumns(). Data is received becouse i see it on the debug screen.

    #include "sortfilterproxymodel.h"
    #include <qdebug.h>
    
    namespace CerSimpleDynamics
    {
    namespace Models
    {
        SortFilterProxyModel::SortFilterProxyModel(int columns_maximum,QObject *parent) : QSortFilterProxyModel(parent)
        {
            columns_max=columns_maximum;
        }
    
        void SortFilterProxyModel::receiveHiddenColumns(bool* ichecked_columns)
        {
            checked_columns=ichecked_columns;
            qDebug()<<"RHC-adres checked_columns"<<checked_columns;
            qDebug()<<"RHC-adres ichecked_columns"<<ichecked_columns;
            for(int i=0;i<columns_max;i++)
            {
                qDebug()<<"RHC"<<checked_columns[i];
            }
        }
    
    
        bool SortFilterProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent) const
        {
            qDebug()<<"RFAR-adres checked_columns"<<checked_columns<<endl;
    
            QModelIndex index0 = sourceModel()->index(sourceRow, 0, sourceParent);
            QModelIndex index1 = sourceModel()->index(sourceRow, 1, sourceParent);
            QModelIndex index2 = sourceModel()->index(sourceRow, 2, sourceParent);
            bool tab[3];
            tab[0]=sourceModel()->data(index0).toString().contains(filterRegExp());
            tab[1]=sourceModel()->data(index1).toString().contains(filterRegExp());
            tab[2]=sourceModel()->data(index2).toString().contains(filterRegExp());
            bool all;
            for (int i=0;i<3;i++)
            {
               all = all || tab[i];
            }
    
            return all;
        }
    
    }
    

    }

      #include "moc_sortfilterproxymodel.cpp"
    

    I wolud like to display my pointer variable (checked_columns) in fuction filterAccpeptsRow() but the pointer shows NULL adress as during declaration in header file. Why initialization in SLOT doesn't work?


  • Lifetime Qt Champion

    What makes you think it doesn't work ? Is it called somewhere ?

    And why are you using an array of boolean ?



  • I solved this problem, but I have another one now. I received hidden columns as array of boolean.

        bool SortFilterProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent) const
        {
                bool all=false;
                bool tab[23];
                std::fill(tab, tab + columns_max, false);
                QModelIndex hidden_columns[23];
                int j=0;
    
                for(int i=0;i<sourceModel()->columnCount();i++)
                    {
                    if(checked_columns[i]==true)
                         {
                 hidden_columns[j] = sourceModel()->index(sourceRow, i, sourceParent);                                                                                                                                                              tab[j]=sourceModel()->data(hidden_columns[j]).toString().contains(filterRegExp());
                         all = all || tab[j];
                         j++ ;
                         }
                    }
            return all;
        }
    

    It work's but function FilterAcceptsRow() is called as many times as rows in proxy model. I tried to perform a calculation in function only when checking the first row, but it doesnt work.

    Do you know some solution to skip calculation in every call of function?


  • Lifetime Qt Champion

    Do you mean do your calculation only on row 0 ?

    And again: why not just use a QList/QVector<int> to store the hidden columns ?



  • 1.Do you mean that hidden column is 1 and unhidden column is 0?
    2.What's the difference in implementation between using array of boolean and qlist/qvector?

    1. Could you tell me advantege of your solution?

  • Lifetime Qt Champion

    I don't understand your question 1.

    1. With a QList of hidden column, you don't need to know the size of the array in your model and you don't need to loop through the complete array to know which columns are hidden or not. You just need to do something like
    if (!hiddenColumnList.contains(index.column())) { 
    //  do some stuff if column is not hidden
    }
    

Log in to reply
 

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