更改QSortFilterProxyModel行为以进行多列过滤 [英] Change QSortFilterProxyModel behaviour for multiple column filtering
问题描述
我们在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 QLineEdit
s)
在我们看来,我们有一个插槽,可以告诉我们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屋!