Обновите sourceModel () без применения фильтрации к QSortFilterProxyModel - PullRequest
1 голос
/ 09 апреля 2020

У меня есть пользовательская модель (QAbstractListModel) и пользовательская модель прокси (QSortFilterProxyModel), работающая в качестве фильтра. В представлении, когда я обновляю модель, мне нужно выполнить «emit dataChanged(...)», чтобы увидеть эти изменения.

Но затем модель прокси обновляется автоматически (вызывается filterAcceptsRow), и представление применяет соответствующие параметры фильтрации.

Мне нужно отключить это поведение, чтобы иметь возможность обновлять представление и применять фильтрацию только при нажатии кнопки, а не автоматически.

Например:

  • Моя модель имеет два поля: id (int) и selected (bool)
  • В представлении я фильтрую только те элементы, которые выбраны (выбранный == true)
  • При применении этого фильтра я отменяю выбор одного элемента.

При текущем поведении этот элемент исчезает, так как фильтр применяется при изменении модели. Я хочу отобразить элемент с этим изменением и применить фильтрацию только при нажатии кнопки.

Ответы [ 2 ]

1 голос
/ 09 апреля 2020

Вы можете реализовать метод publi c в своей пользовательской модели прокси, который вы используете для включения / отключения фильтра. В моем примере кода я использую макрос Q_INVOKABLE , чтобы сделать также enableFilter() вызываемым из QML. Таким образом, вы можете включить фильтр при нажатии кнопки, вызвав метод.

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;
};

Когда вы создаете экземпляр модели, если явно не вызываете enableFilter со значением true, метод filterAcceptsRow() вернет значение true для всех строки.

myFilterProxyModel->setFilterRole(MyListModel::ExampleRole);
myFilterProxyModel->setFilter("^fullstringmatch$");
myFilterProxyModel->setSourceModel(myModel);
//myFilterProxyModel->enableFilter(true);

Если вы используете QML, то вы делаете пользовательскую модель прокси видимой для контекста QML, например, устанавливая ее как свойство контекста (например, filterProxyModel), и включаете фильтр, вызывая

filterProxyModel.enableFilter(true)
0 голосов
/ 10 апреля 2020

Настройка динамичности c Фильтр сортировки работал для меня. Это было ложно по умолчанию в старых версиях QT, но я понял, что это верно для текущей версии!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...