Model for TreeView without parent() method.
-
Hello.
I have element class with parents() and children() methods. So each element can have some parents and some children.
Something like this:Class Element(){ public: QVector<Element *> parents(); QVector<Element *> children(); }
I need to get an element and display children tree for it and its children. So I can get children of element, but can't get a parent.
Is it possible to create model for QTreeView for this task (whithout creating additional data structures)? I checked a lot of examples but there parent() method is implemented. -
In QAbstractItemModel, the QModelIndex parent(const QModelIndex &index) const method is pure virtual, so yes you have to implement it.
But the question is, does the implementation of parent() have to be consistent with index()? I.e., for all values of row, col, idx: parent( index(row,col,idx) ) == idx.
I'm not sure, but I think it would be risking trouble if the model returns a different parent than the one that created it in the tree. So I think you do need an addition data structure to hold this information, forming a single-parent tree. You could create these node objects on demand, as they are needed in the implementation of index(). For example:
struct myNode { myNode( Element *e, myNode *p ) : element(e), parent(p), children( e->children().size() ) { } Element *element; myNode * parent; QVector<myNode*> children; }; QModelIndex myModel::index(int row, int column, const QModelIndex &index) const { auto *parentNode = static_cast<const myNode*>(index.internalPointer()); auto *myChild = parentNode->children[row]; if (myChild == nullptr) { myChild = new myNode( parentNode->element->children()[row], parentNode ); parentNode->children[row] = myChild; } return createIndex(row, column, myChild ); }
This myNode object is initialized with a vector of null pointers for the children, and they are only allocated when that child is needed by the TreeView. (the code is just to give you the gist, it probably has errors)
-
When the items don't have a parent - how is this supposed to be a tree then?
-
It can has some parent and some children. But we can get only list of parents, and can't detect parent, from which we moved to child level.
Is it possible to rely only on children to build a tree model? -
@Pavel-Romankov said in Model for TreeView without parent() method.:
Is it possible to rely only on children to build a tree model?
Since the view needs to know the parent of the children you have to figure it out. Don' see a problem when you have already a tree - simply add a pointer to the parent to every child.
-
I have another model (library), that provides elements. I can get pointer to element, whitch have methods parents() and children(). These methods return vectors of pointers to other elements.
I 'm trying not to create additional date structures at my side and operate only these pointers. But as I understand it is impossible? -
I have a lot of elements. For example, I have 100 elements with 100 children for each, and 100 children for each children.
If I decide to build tree before displaying it, I have to build tree with 1000000 elements in memory.
But user can expand only one branch.
In QTableView / QAbstractTableModel view requests data from model only for visible cells, and this is great. Because there is no need to process all 1000000 elements at once before displaying them.
I'm searching for way to display tree in similar way. -
@Pavel-Romankov said in Model for TreeView without parent() method.:
I'm searching for way to display tree in similar way.
You can create the items on demand here also - there is no difference between a QTreeView and QTableView here.
-
Can you give example with creating tree items on demand? In witch method I have to do this?
-
Where do you get your data from? How do you know how much children are under a parent?
I would reimplement QAIM::canFetchMore() / fetchMore() -
I have external library witch has method:
Element *getElement(QString elementName);
and each element has methods
QVector<Element *> parents(); QVector<Element *> children(); QString name(); QString data();
I need to build a tree for element and it would be great to create children nodes only after user expands a branch.
-
@Pavel-Romankov said in Model for TreeView without parent() method.:
I need to build a tree for element and it would be great to create children nodes only after user expands a branch.
But which nodes do you need to create at all - you've all in your Element class so use this in your model.
-
Is it necessarily to implement parent() method in my model?
But which nodes do you need to create at all - you've all in your Element class so use this in your model.
Could you explain a little more in detail? What methods I need to implement to provide data in right way?
-
In QAbstractItemModel, the QModelIndex parent(const QModelIndex &index) const method is pure virtual, so yes you have to implement it.
But the question is, does the implementation of parent() have to be consistent with index()? I.e., for all values of row, col, idx: parent( index(row,col,idx) ) == idx.
I'm not sure, but I think it would be risking trouble if the model returns a different parent than the one that created it in the tree. So I think you do need an addition data structure to hold this information, forming a single-parent tree. You could create these node objects on demand, as they are needed in the implementation of index(). For example:
struct myNode { myNode( Element *e, myNode *p ) : element(e), parent(p), children( e->children().size() ) { } Element *element; myNode * parent; QVector<myNode*> children; }; QModelIndex myModel::index(int row, int column, const QModelIndex &index) const { auto *parentNode = static_cast<const myNode*>(index.internalPointer()); auto *myChild = parentNode->children[row]; if (myChild == nullptr) { myChild = new myNode( parentNode->element->children()[row], parentNode ); parentNode->children[row] = myChild; } return createIndex(row, column, myChild ); }
This myNode object is initialized with a vector of null pointers for the children, and they are only allocated when that child is needed by the TreeView. (the code is just to give you the gist, it probably has errors)
-
@bee65, @Christian-Ehrlicher Thank you very much. It helped me a lot!