Filter model items in tree view

浪子不回头ぞ 提交于 2020-04-16 05:49:43

问题


I have a model class:

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;

}

Model returns data according to roles:

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

}

I have used a QSortFilterProxyModel member for parent class to filter my model:

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 is set up at parent class constructor:

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

Parent class is registered as a QML type and is used on QML:

ParentClass {
    id: parentClass
}

Now on QML, I'm using TreeView type to show the model:

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

There is quite some logic inside TreeView which depends on parentClass.sceneModel. I replaced all parentClass.sceneModel instances with parentClass.sceneModelProxy.

The original tree view without any proxy works fine:

After applying proxy, tree view is empty:

I have spent some time to debug the QSortFilterProxyModel usage. Can anybody give me a hint?


回答1:


Try either setting m_sceneModelProxy->setDynamicSortFilter(true) or call m_sceneModelProxy->invalidate() once after setup.




回答2:


Looking at Qt Creator logs while running the application, I accidentally noticed this log:

QMetaProperty::read: Unable to handle unregistered datatype 'QSortFilterProxyModel*' for property 'ParentClass_QML_193::sceneModelProxy'

I resolved the above log by a suggested approach of registering QSortFilterProxyModel* pointer:

#include <QSortFilterProxyModel>

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

Now QML TreeView filters out unwanted items correctly =)



来源:https://stackoverflow.com/questions/60507762/filter-model-items-in-tree-view

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!