更改QSortFilterProxyModel行为以进行多列过滤 [英] Change QSortFilterProxyModel behaviour for multiple column filtering

查看:770
本文介绍了更改QSortFilterProxyModel行为以进行多列过滤的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们在QTableView上安装了QSortFilterProxyModel,并安装了两个(或多个)QLineEdit用于过滤视图(基于这些QLineEdit的文本)

We have a QSortFilterProxyModel installed on a QTableView and two (or more) QLineEdit for filtering the view (based on the text of these QLineEdits)

在我们看来,我们有一个插槽,可以告诉我们lineedits字符串和所需的当前列.像这样的东西:

In our view we have a slot that tells 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.

现在,我们为第2列输入年份(例如1985).到目前为止,过滤还可以,但是当我们切换到第一个lineedit并输入名称(例如john)时,基于年份的先前过滤将重置.

Now we enter a year for column 2 (for example 1985). Until now filtering is ok but when we switch to the first lineedit and enter a name (for example john) the previous filtering based on year will reset.

如何为自定义QSortFilterProxyModel更改此行为?

How could we change this behaviour for our custom QSortFilterProxyModel ?

(实际上,当我们更改过滤器键列时,filtermodel必须过滤现有视图而不重置它)

(Actually when we change the filter keycolumn the filtermodel must filter existing view not reset it)

基于@Mike的回答: 如果您使用QMap<int, QRegExp>与未知的列数进行交互,将对您有帮助

Based on @Mike's answer : If you interacting with unknown column count using QMap<int, QRegExp> will help you

推荐答案

您可以将QSortFilterProxyModel子类化,以使其采用两个单独的过滤器(一个用于名称,另一个用于年份),并将filterAcceptsRow覆盖为仅当两个过滤器都满足时才返回true.

You can subclass QSortFilterProxyModel, to make it take two separate filters (one for the name and the other for the year), and override filterAcceptsRow to return true only when both filters are satisfied.

Qt文档的自定义排序/过滤器模型示例显示了一个子类,除了用于搜索的主字符串过滤器外,该过滤器还可以对日期进行过滤.

The Qt documentation's Custom Sort/Filter Model Example shows a subclassed QSortFilterProxyModel that can take filters for dates in addition to the main string filter used for searching.

这是一个完整的示例,说明如何使子类为一个表应用两个单独的过滤器:

Here is a fully working example on how to make a subclassed QSortFilterProxyModel apply two separate filters for one table:

#include <QApplication>
#include <QtWidgets>

class NameYearFilterProxyModel : public QSortFilterProxyModel{
    Q_OBJECT
public:
    explicit NameYearFilterProxyModel(QObject* parent= nullptr):
        QSortFilterProxyModel(parent){
        //general parameters for the custom model
        nameRegExp.setCaseSensitivity(Qt::CaseInsensitive);
        yearRegExp.setCaseSensitivity(Qt::CaseInsensitive);
        yearRegExp.setPatternSyntax(QRegExp::RegExp);
        nameRegExp.setPatternSyntax(QRegExp::RegExp);
    }

    bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const  override{
        QModelIndex nameIndex= sourceModel()->index(sourceRow, 0, sourceParent);
        QModelIndex yearIndex= sourceModel()->index(sourceRow, 1, sourceParent);

        QString name= sourceModel()->data(nameIndex).toString();
        QString year= sourceModel()->data(yearIndex).toString();

        return (name.contains(nameRegExp) && year.contains(yearRegExp));
    }
public slots:
    void setNameFilter(const QString& regExp){
        nameRegExp.setPattern(regExp);
        invalidateFilter();
    }
    void setYearFilter(const QString& regExp){
        yearRegExp.setPattern(regExp);
        invalidateFilter();
    }
private:
    QRegExp nameRegExp;
    QRegExp yearRegExp;
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //set up GUI
    QWidget w;
    QVBoxLayout layout(&w);
    QHBoxLayout hLayout;
    QLineEdit lineEditName;
    QLineEdit lineEditYear;
    lineEditName.setPlaceholderText("name filter");
    lineEditYear.setPlaceholderText("year filter");
    lineEditYear.setValidator(new QRegExpValidator(QRegExp("[0-9]*")));
    lineEditYear.setMaxLength(4);
    hLayout.addWidget(&lineEditName);
    hLayout.addWidget(&lineEditYear);

    QTableView tableView;
    layout.addLayout(&hLayout);
    layout.addWidget(&tableView);

    //set up models
    QStandardItemModel sourceModel;
    NameYearFilterProxyModel filterModel;;
    filterModel.setSourceModel(&sourceModel);
    tableView.setModel(&filterModel);

    QObject::connect(&lineEditName, &QLineEdit::textChanged,
                     &filterModel, &NameYearFilterProxyModel::setNameFilter);
    QObject::connect(&lineEditYear, &QLineEdit::textChanged,
                     &filterModel, &NameYearFilterProxyModel::setYearFilter);

    //fill with dummy data
    QVector<QString> names{"Danny", "Christine", "Lars",
                           "Roberto", "Maria"};
    for(int i=0; i<100; i++){
        QList<QStandardItem*> row;
        row.append(new QStandardItem(names[i%names.size()]));
        row.append(new QStandardItem(QString::number((i%9)+1980)));
        sourceModel.appendRow(row);
    }
    w.show();
    return a.exec();
}

#include "main.moc"

这篇关于更改QSortFilterProxyModel行为以进行多列过滤的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆