QML + TreeView + Sorting/Filtering Challenges
-
Dear all,
I am struggling with the integration of my C++ model and QML.The model is hierarchical and reflects a virtual file system (VFS). The view is a tree view and shall display the data of the model, whereas the entries in shall be sortable and filterable.
After reading a lot of stuff and examples I assume that the only solution to do this is based on the following mix:
Subclass QSortFilterProxyModel in order to implement sorting and filtering logic
As the QSortFilterProxyModel needs a reference to QAbstractItemModel as its input source model, I cannot use a simple QList to store the children of an element. I also can not use a QQmlListProperty (which works great to expose my hierarchical model to QML). Hence I have to implement the child list by subclassing QAbstractListModel and expose it to QML through a respective Q_PROPERTY statement
My problem is now: when trying to access this property, QML cannot find it (i.e. undefined). I of course called qmlRegisterType for my subclass of QAbstractListModel and my FileItem class. So this is not the problem (I can access all other properties of the FileItem).
What is going wrong?
Here's the header file of my FileItem class
@class FileItem : public Models::ListItem
{
Q_OBJECT
Q_PROPERTY(int id READ GetId NOTIFY IdChanged)
Q_PROPERTY(QString title READ GetTitle NOTIFY TitleChanged)
Q_PROPERTY(Models::ListModel* elements READ GetElements NOTIFY ElementsChanged)public:
FileItem(FileItem *parent = 0);
FileItem(int id, QString title, FileItem *parent = 0);
~FileItem();// ListItem interface
enum Roles
{
ROLE_ID = Qt::UserRole + 1,
ROLE_TITLE,
};// Inherited methods / members
QVariant data(int role) const;
bool setData(int role, const QVariant &value);
QHash<int, QByteArray> roleNames() const;// Self-defined methods / members
int GetId() const;
QString GetTitle() const;
Models::ListModel* GetElements();signals:
void IdChanged(int);
void TitleChanged(QString);
void ElementsChanged();private:
int m_id;
QString m_title;
Models::ListModel *m_children;};@
The Models::ListModel and Models::ListItem classes are taken from https://github.com/lemirep/simple_qml_list_model_example
In QML I try to access the model through a simple ListView with a Repeater that takes care of the child records (called "elements" here).
@Component {
id: treeViewRecursiveDelegate
Item {
id: wrapper
width: treeListView.width
height: childrenRect.height
Column {// Rendering stuff here...
Repeater {
model: elements
delegate: treeViewRecursiveDelegate
}
}
}
}Item {
anchors.fill: parent
ListView {
id: treeListView
anchors.fill: parent
model: treeViewListModel
delegate: treeViewRecursiveDelegate
}
}@However, as said, I get a "qrc:/qml/Files.qml:386: ReferenceError: elements is not defined". There seems to be a problem with the way how the entries in the list are exposed. For instance, if I set the context property "treeViewListModel" to a single FileItem object by calling
@QQmlContext *ctxt = engine.rootContext();
ctxt->setContextProperty("treeViewListModel", QVariant::fromValue(root));@where root is the single object with a list of children, the property "elements" exists and everything works. But for the children of the root object the property "elements" does not existing anymore (all other properties do exist).
I debugged the code a little bit further to see the difference between the two cases. In the first case, the model is an instance of QQmlDMObjectData, in the second case the model of an object is an instance of QQmlDMAbstractItemModelData. How can that be?
I spent the past few days on this issue but I fail to find a solution. Does anyone know this problem and hopefully a solution to it?
Thanks in advance
Jens
PS: I also tried the "hack" that is mentioned in several threads and blog articles to expose the raw list as a QObject* through an invokable method, i.e. by offering
@Q_INVOKABLE QObject* elementsRaw();@
on FileItem and then call that method from QML, but no success.