QSortFilterProxyModel OR connection



  • Hi everyone,

    I am currently trying to use the QSortFilterProxyModel on my tableview.
    I already wrote a new class to filter over several columns.
    The big Problem is, that I want to filter two columns with two regexpressions, but show them BOTH!
    e.g.:

    name occupation
    petra programmer
    carla analyst

    If I filter the "name" column for petra, and the "occupation" column for analyst, both should be shown.
    I currently have no means to achieve this, because each filter is built on the other... does anybody have suggestions?

    regards



  • Create a single filter that filters on multiple columns in one go. Libqxt provides one you can use, but it is not hard to create one for yourself either.



  • Thank you very much for your answer. I will look into the Libqxt library.
    Does it really provide the solution for my problem? As far as I understand it a single filter filtering over several columns is still an AND connection between the RegExpressions, or am I wrong?
    Thank you for your help.



  • Good one. I think you are right. Perhaps you can use it as the base of your own filter though, and make it an OR filter. Might be a nice patch for the Qxt one as well (optional, of course), as that really adds new functionality while the AND one can be achieved using a stack of standard QSortFilterProxyModels.



  • I solved the Problem.
    You can simply take the "myqsortfiltermodel" example and alter it to your needs.
    I will alter it in a way to make it dynamic... should I post it lateron?



  • Hi Mr. 010110102,
    can you please post your solution? I am also on the same path.

    Thanks



  • Will do, cant do it right now and I have to alter it a bit, but in atleast 1-2 days.



  • Well, i solved it myself. I had to override QSortFilterProxyModel's filterAcceptsRow() method.In this method all i have to do is loop through on desired columns that I wanted to filter and apply Regular-expression on them.If columns contains the filtered text then return True else return False.

    If this is wrong then please update it.

    python code:

    @def filterAcceptsRow(self,sourceRow,sourceParent):
    #say you have 5 columns
    for column in range(self.sourceModel().columnCount()):
    index=self.sourceModel().index(sourceRow,column,sourceParent)
    data=self.sourceModel().data(index,QtCore.Qt.ItemDataRole.DisplayRole)
    if column in [0,1,2]:#filter only the desired columns
    if self.filterRegExp().indexIn(data)==-1:
    return False
    return True
    @

    Thanks.



  • Well sounds about right...
    I Used the "Mysortfilterproxymodel" from the Qt Examples as my first goto... so just for completion some of it is still in here;

    Mysortfilterproxymodel.h:
    @
    #include <QDate>
    #include <QSortFilterProxyModel>

    //! [0]
    class MySortFilterProxyModel : public QSortFilterProxyModel
    {
    Q_OBJECT

    public:

    //Example for implementing it(no declarations) :
    //
    // myproxy=new MySortFilterProxyModel();
    // myproxy->setSourceModel(sourcemodel);
    // QRegExp regExp("NuMbeR1|Test3122|Dethklok");
    // myproxy->setFilterRegExp(regExp);
    // ui->view->setModel(myproxy);
    // this implementation will now filter the given rows (not dynamicly given)
    // after the regular [removed]NuMber1 OR Test3122 etc. etc.)

    MySortFilterProxyModel(QObject *parent = 0);

    //these are just included for purposes of completion,
    //they should be safe to remove.
    QDate filterMinimumDate() const { return minDate; }
    void setFilterMinimumDate(const QDate &date);

    QDate filterMaximumDate() const { return maxDate; }
    void setFilterMaximumDate(const QDate &date);
    //thill here not really nessecary

    protected:
    bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
    bool lessThan(const QModelIndex &left, const QModelIndex &right) const;

    private:
    bool dateInRange(const QDate &date) const;
    QDate minDate;
    QDate maxDate;
    };
    //! [0]

    #endif
    @

    Mysortfilterproxymodel.cpp:
    @

    #include <QtGui>

    #include "mysortfilterproxymodel.h"

    //! [0]
    MySortFilterProxyModel::MySortFilterProxyModel(QObject *parent)
    : QSortFilterProxyModel(parent)
    {
    }
    //! [0]

    //! [1]
    void MySortFilterProxyModel::setFilterMinimumDate(const QDate &date)
    {
    minDate = date;
    invalidateFilter();
    }
    //! [1]

    //! [2]
    void MySortFilterProxyModel::setFilterMaximumDate(const QDate &date)
    {
    maxDate = date;
    invalidateFilter();
    }
    //! [2]

    //! [3]
    bool MySortFilterProxyModel::filterAcceptsRow(int sourceRow,
    const QModelIndex &sourceParent) const
    {
    //Depending on how many rows have to be filtered...
    // 1. add new Indiezes
    // 2. select the concerned rows
    // 3.add them to your source model via return(just follow the example below)
    QModelIndex index0 = sourceModel()->index(sourceRow, 5, sourceParent);
    QModelIndex index1 = sourceModel()->index(sourceRow, 15, sourceParent);
    QModelIndex index2 = sourceModel()->index(sourceRow, 0, sourceParent);

    return (sourceModel()->data(index0).toString().contains(filterRegExp())
    || sourceModel()->data(index1).toString().contains(filterRegExp()))
    && dateInRange(sourceModel()->data(index2).toDate());
    }
    //! [3]

    //! [4] //! [5]
    bool MySortFilterProxyModel::lessThan(const QModelIndex &left,
    const QModelIndex &right) const
    {
    QVariant leftData = sourceModel()->data(left);
    QVariant rightData = sourceModel()->data(right);
    //! [4]

    //! [6]
    if (leftData.type() == QVariant::DateTime) {
    return leftData.toDateTime() < rightData.toDateTime();
    } else {
    QRegExp emailPattern = new QRegExp("([\w\.]@[\w\.]*)");

      QString leftString = leftData.toString();
      if(left.column() == 1 && emailPattern->indexIn(leftString) != -1)
         leftString = emailPattern->cap(1);
    
      QString rightString = rightData.toString();
      if(right.column() == 1 && emailPattern->indexIn(rightString) != -1)
         rightString = emailPattern->cap(1);
    
      return QString::localeAwareCompare(leftString, rightString) < 0;
    

    }
    }
    //! [5] //! [6]

    //! [7]
    bool MySortFilterProxyModel::dateInRange(const QDate &date) const
    {
    return (!minDate.isValid() || date > minDate)
    && (!maxDate.isValid() || date < maxDate);
    }
    //! [7]
    @

    Hope it helps.
    Sorry don't have too much time right now(obviously) but if there are other problems I will get to it as soon as possible.
    I wish you a very happy Christmas and all good things in 2012!


Log in to reply
 

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