问题
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