Add more than text to TreeView delegates? (like an extra Icon, ...)
-
Hi,
I am trying to use a TreeView and have multiple things in the delegate. E.g. in some rows I would like to put an Icon. But from the example it seems there is only
styleData.value
available. I used to do that with different roles on a ListView but AFAICS they are used for the columns in the TreeView. Implementing a method likeQString getIcon(const QModelIndex &index);
which returns me the Icon is a workaround, but then I loose the property binding. So when I update my Model I would have to trigger the update of the display manually right?
Is there a better way to extra things like icons to the TreeView delegates?
Thanks, Heiko
-
Hi,
I am trying to use a TreeView and have multiple things in the delegate. E.g. in some rows I would like to put an Icon. But from the example it seems there is only
styleData.value
available. I used to do that with different roles on a ListView but AFAICS they are used for the columns in the TreeView. Implementing a method likeQString getIcon(const QModelIndex &index);
which returns me the Icon is a workaround, but then I loose the property binding. So when I update my Model I would have to trigger the update of the display manually right?
Is there a better way to extra things like icons to the TreeView delegates?
Thanks, Heiko
-
You need to do a combination of things:
- You'll need a custom model (trust me, I've tried to use built-in stuff and it's good for the basics only)
- Set custom roles (see roleNames())
Then your TableViewColumn will have a delegate with a role of (say) "compositeData" which you can then use for loading your image.
Something like:
TableViewColumn { role: "compositeData" delegate: Image{source: styleData.value.iconUrl} // Text{text: styleData.value.text} } ... QHash<int,QString> roleNames() const { QHash<int,QString> ret; ret[Qt::UserRole] = "compositeData" return ret; } QVariant data(...) { if(role == Qt::UserRole) return QVariantMap(...) }
-
First of all: Thanks for all the quick replies.
@p3c0: Hi, thanks for the welcome :) My question was more geared towards how to transport which icon should be drawn from the model (c++) to QML.
@cheezus: So if I understand correctly I should implement a
QAbstractItemModel
and use that to return aQVariantMap
in the data method. Is there any good example how to assemble the parent child stuff for the TreeView? At the moment I am using the QStandardItemModel since that is what I found in some example. I just searched and found this:http://doc.qt.io/qt-5/qtwidgets-itemviews-simpletreemodel-example.html
If I setup the model like there I should be able to use it with the TreeView in QML right?
-
First of all: Thanks for all the quick replies.
@p3c0: Hi, thanks for the welcome :) My question was more geared towards how to transport which icon should be drawn from the model (c++) to QML.
@cheezus: So if I understand correctly I should implement a
QAbstractItemModel
and use that to return aQVariantMap
in the data method. Is there any good example how to assemble the parent child stuff for the TreeView? At the moment I am using the QStandardItemModel since that is what I found in some example. I just searched and found this:http://doc.qt.io/qt-5/qtwidgets-itemviews-simpletreemodel-example.html
If I setup the model like there I should be able to use it with the TreeView in QML right?
@hvoigt Yep. I use the following:
#ifndef TREEMODEL_HPP #define TREEMODEL_HPP #include <QAbstractItemModel> #include <memory> #include <vector> template <typename T> class TreeModel : public QAbstractItemModel { public: explicit TreeModel(QObject * parent=0):QAbstractItemModel(parent){} void reset() { beginResetModel(); updateRootNodes(); endResetModel(); } protected: void updateRootNodes() { m_rootNodes = getRootNodes(); } struct Node; using NodeVec = std::vector<std::unique_ptr<Node>>; struct Node { Node(std::shared_ptr<T> const & value, Node*parent,int row): value(value), parent(parent), row(row){} std::shared_ptr<T> value; Node * parent = nullptr; int row = -1; NodeVec children; }; virtual NodeVec getRootNodes() = 0; private: std::vector<std::unique_ptr<Node>> m_rootNodes; protected: QModelIndex index(int row, int column, QModelIndex const & parent = QModelIndex()) const override; QModelIndex parent(QModelIndex const & index) const override; int rowCount(QModelIndex const & parent) const override; }; #include "TreeModel.ipp" #endif // TREEMODEL_HPP
// TreeModel.ipp template<typename T> QModelIndex TreeModel<T>::index(int row, int column, QModelIndex const & parent) const { if(!parent.isValid()) return createIndex(row,column,m_rootNodes[row].get()); else { auto parentNode = reinterpret_cast<Node*>(parent.internalPointer()); return createIndex(row,column,parentNode->children[row].get()); } } template<typename T> QModelIndex TreeModel<T>::parent(QModelIndex const & index) const { if(!index.isValid()) return QModelIndex(); auto node = reinterpret_cast<Node*>(index.internalPointer()); if(!node->parent) return QModelIndex(); else return createIndex(node->parent->row,0,node->parent); } template<typename T> int TreeModel<T>::rowCount(QModelIndex const & parent) const { if(!parent.isValid()) return m_rootNodes.size(); auto node = reinterpret_cast<Node*>(parent.internalPointer()); return node->children.size(); }
-
First of all: Thanks for all the quick replies.
@p3c0: Hi, thanks for the welcome :) My question was more geared towards how to transport which icon should be drawn from the model (c++) to QML.
@cheezus: So if I understand correctly I should implement a
QAbstractItemModel
and use that to return aQVariantMap
in the data method. Is there any good example how to assemble the parent child stuff for the TreeView? At the moment I am using the QStandardItemModel since that is what I found in some example. I just searched and found this:http://doc.qt.io/qt-5/qtwidgets-itemviews-simpletreemodel-example.html
If I setup the model like there I should be able to use it with the TreeView in QML right?
To return an image from
QAbstractItemModel
you can convert it to base64 and return aQString
and to decode it on QML side something like this should work:Image { source: "data:image/png;base64," + model.imagedata }
If I setup the model like there I should be able to use it with the TreeView in QML right?
Yes. Just make sure you re-implement
roleNames
.
https://forum.qt.io/topic/56497/request-treeview-c-model-to-qml-example
https://forum.qt.io/topic/56653/example-of-correctly-operating-c-model-with-qml-treeview/
https://forum.qt.io/topic/56099/solved-new-treeview-does-not-connect-to-c-model -
Got it. Its working for me now. Marked as solved.
@cheezus: The bit with returning the
QVariantMap()
from thedata(...)
method was what solved my question.@p3c0: Thanks for the links they helped to implement the
QAbstractItemModel
and avoid the seemingly common pitfalls as well. The bit with base64 encoding the icon is an interesting one. I am currently just using an Image Path from the resources. But that might come in handy sometime.Thanks a lot, this was awesome.
-
Since the question how to implement a
TreeView
with aQAbstractItemModel
seems to have been asked a few times I took the opportunity and adapted the "Simple Tree Model Example" to QML. You can find it on my GitHub: -
Since the question how to implement a
TreeView
with aQAbstractItemModel
seems to have been asked a few times I took the opportunity and adapted the "Simple Tree Model Example" to QML. You can find it on my GitHub: