在树视图中过滤模型项

Filter model items in tree view

我有一个模型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;

}

根据角色建模returns数据:

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

}

我使用父 class 的 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 在父 class 构造函数中设置:

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 注册为 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.sceneModelProxy.

替换了所有 parentClass.sceneModel 个实例

没有任何代理的原始树视图工作正常:

应用代理后,树视图为空:

我花了一些时间来调试 QSortFilterProxyModel 用法。有人可以给我提示吗?

尝试设置 m_sceneModelProxy->setDynamicSortFilter(true) 或在设置后调用 m_sceneModelProxy->invalidate() 一次。

在运行应用程序的时候查看Qt Creator日志,无意间注意到了这个日志:

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

我通过 a suggested approach 注册 QSortFilterProxyModel* 指针解决了上面的日志:

#include <QSortFilterProxyModel>

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

现在 QML TreeView 可以正确过滤掉不需要的项目 =)