Фильтровать элементы модели в виде дерева - PullRequest
1 голос
/ 03 марта 2020

У меня есть класс модели:

class ItemModel : public QAbstractItemModel
{
    Q_OBJECT
public:
    enum ItemRoles {
        ItemRole = Qt::UserRole + 1,
        NameRole,
        IdRole,
        FilterRole // To be used in filtering
    };

    QVariant data(const QModelIndex &index, int role) const;

}

Модель возвращает данные в соответствии с ролями:

QVariant ItemModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    Item *item = itemFromIndex(index);

    switch (role) {
    case ItemRole:
        return QVariant::fromValue(item);
    case NameRole:
        return QVariant::fromValue(item->entity()->objectName());
    case IdRole:
        return QVariant::fromValue(item->entity()->id().id());
    case FilterRole:
    {
        switch (item->itemTask()) {
        case Item::ItemTask::ToBeFiltered:
            return QVariant::fromValue(QString("yes"));
        default:
            return QVariant::fromValue(QString("no"));
        }
    }
    default:
        return QVariant();
    }

}

Я использовал член QSortFilterProxyModel для родительского класса для фильтрации моей модели:

class ParentClass : public QObject
{
    Q_OBJECT
    Q_PROPERTY(ItemModel             * sceneModel      READ sceneModel      CONSTANT)
    Q_PROPERTY(QSortFilterProxyModel * sceneModelProxy READ sceneModelProxy CONSTANT)

private:
    ItemModel             *m_sceneModel;
    QSortFilterProxyModel *m_sceneModelProxy;

}

QSortFilterProxyModel устанавливается в конструкторе родительского класса:

ParentClass::ParentClass(QObject *parent)
    : QObject(parent)
    , m_sceneModel(new ItemModel(this))
    , m_sceneModelProxy(new QSortFilterProxyModel())
{
    // Proxy to filter out unwanted items from tree-view of model
    // Looks into a specific role for each item,
    // if data value returned for that role passes the regexp, then include item in proxy model
    m_sceneModelProxy->setFilterRole(ItemModel::ItemRoles::FilterRole);
    m_sceneModelProxy->setFilterRegExp("^no$");
    m_sceneModelProxy->setSourceModel(m_sceneModel);
}

Родительский класс зарегистрирован как тип QML и используется в QML:

ParentClass {
    id: parentClass
}

Теперь в QML, я использую тип TreeView, чтобы показать модель:

TreeView {
    model: parentClass.sceneModel
    selection: ItemSelectionModel {
        model: parentClass.sceneModel
    }
    style: TreeViewStyle { // ... }
    itemDelegate: FocusScope { // ... }
    TableViewColumn { role: "name" }
}

* * * * * * * * * * * * * * * * * * * * * * * * * * TreeView * * * * * * * * * parentClass.sceneModel. Я заменил все parentClass.sceneModel экземпляры на parentClass.sceneModelProxy.

. Исходный вид дерева без прокси работает нормально:

No proxy

После При использовании прокси, дерево не отображается:

With proxy

Я потратил некоторое время на отладку использования QSortFilterProxyModel. Кто-нибудь может дать мне подсказку?

Ответы [ 2 ]

0 голосов
/ 26 марта 2020

Просматривая журналы Qt Creator при запуске приложения, я случайно заметил этот журнал:

QMetaProperty :: read: Невозможно обработать незарегистрированный тип данных 'QSortFilterProxyModel *' для свойства 'ParentClass_QML_193 :: sceneModelProxy'

Я разрешил вышеуказанный журнал с помощью предложенного подхода регистрации указателя QSortFilterProxyModel*:

#include <QSortFilterProxyModel>

qRegisterMetaType<QSortFilterProxyModel*>("QSortFilterProxyModel*");

Теперь QML TreeView правильно отфильтровывает ненужные элементы =)

0 голосов
/ 03 марта 2020

Попробуйте либо установить m_sceneModelProxy->setDynamicSortFilter(true), либо вызвать m_sceneModelProxy->invalidate() один раз после настройки.

...