Reputation: 141
I have a custom model (QAbstractListModel
) and a custom proxy model (QSortFilterProxyModel
) working as a filter.
In the view, when I update the model, I need to execute "emit dataChanged(...)
" in order to see this changes displayed.
But then, proxy model is automatically updated (filterAcceptsRow
is called) and the view applies the corresponding filtering options.
I need to disable this behavior, to be able to update the view and only apply filtering when clicking a button, and not automatically.
For example:
id (int)
and selected (bool)
With current behavior, this element disappears, since filter is applied when model changes. I want to display item with this change and apply filtering only when a button is clicked.
Upvotes: 2
Views: 1700
Reputation: 141
Setting dynamic sort filter has worked for me. It was false by default in older versions of QT but I realized that it's true for current version!
Upvotes: 1
Reputation: 5482
You could implement a public method in your custom proxy model which you use for enabling/disabling the filter. In my example code I'm using Q_INVOKABLE macro to make enableFilter()
callable from QML too. So you can enable the filter when a button is clicked by calling the method.
class ExampleFilterProxyModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
explicit ExampleFilterProxyModel(QObject *parent = nullptr) : QSortFilterProxyModel(parent) {}
Q_INVOKABLE void setFilter(const QString & pattern) {
QRegularExpression re(pattern, QRegularExpression::CaseInsensitiveOption);
if (re.isValid()) {
QSortFilterProxyModel::setFilterRegularExpression(pattern);
}
invalidateFilter();
}
Q_INVOKABLE void enableFilter(bool enabled) {
m_enabled = enabled;
invalidateFilter();
}
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override {
if (m_enabled) {
QModelIndex index = sourceModel()->index(sourceRow, filterKeyColumn(), sourceParent);
QString str = sourceModel()->data(index, filterRole()).toString();
return str.contains(filterRegularExpression());
}
return true;
}
private:
bool m_enabled = false;
};
When you instantiate the model if you don't explicitly call enableFilter with true the filterAcceptsRow()
method will return true for all rows.
myFilterProxyModel->setFilterRole(MyListModel::ExampleRole);
myFilterProxyModel->setFilter("^fullstringmatch$");
myFilterProxyModel->setSourceModel(myModel);
//myFilterProxyModel->enableFilter(true);
If you are using QML then you make the custom proxy model visible to the QML context e.g. by setting it as a context property (e.g. filterProxyModel) and enable the filter by calling
filterProxyModel.enableFilter(true)
Upvotes: 1