How to retrieve items indices from a treeView?
-
I don't know if the title is the most accurate one but here is the problem
As shown in the picture, I've built a TreeView list using QML (both delegate and treeview in QML) and a C++ Model.
The problem is I don't know how to access the items through their indeces.
For example if I were to retrieve the data of one item through its index I would only retrieve the parent item and not the child onefor example
(console.log(theModel.data(theModel.index(0,1),colView.role))
would show me "Vision Status"if I tried to change "theModel.index(0,1)" to "theModel.index(1,0)"
it won't retrieve anything and would return "undefined"I tried to console.log(styleData.index) but it would return me some gibberish that I can't make sense of
for example
if I pressed on "Camera connected" it would return
QModelIndex(0,0,0x5573e70,MyTreeModel(0x5591b60))and pressing on its parent (Vision Status) would return
QModelIndex(1,0,0x5573ce0,MyTreeModel(0x5591b60))this gibberish, the one written in hex, changes everytime I reload the program.
so does anyone have any leads to this problem?The codes if someone wants to check on them
main.qml
import QtQuick 2.0 import QtQuick.Controls 1.5 import QtQuick.Controls.Styles 1.4 import QtQuick.Window 2.2 import MyTreeModel 1.0 //from qmlRegister in C++ code Rectangle { id:root height: 300 width: 300 property string sourceRed : "images/RedOff.png" // property alias sourceRedAlias : root.sourceRed property string sourceGreen : "images/GreenOff.png" // property alias sourceGreenAlias : root.sourceGreen MyTreeModel { id: theModel } MyTreeDelegate { id: theDelegate } MyBranchDelegate { id: theBranchDelegate } TreeView { id: treeView height: root.height width: root.width selectionMode: SelectionMode.NoSelection //to hightlight selected items headerVisible: false //to hide the header anchors.fill: root //to fill rectangle highlightOnFocus: false model: theModel itemDelegate: theDelegate function expandTree() { //to expand the tree when initializing the program expand(theModel.index(0,0)); expand(theModel.index(1,0)); expand(theModel.index(2,0)); } Component.onCompleted: { expandTree(); } style: TreeViewStyle //for styling the tree { backgroundColor: "white" alternateBackgroundColor:"white" //branch delegates are used for delegating the arrow on the left branchDelegate: theBranchDelegate } TableViewColumn { id: colView role: "name_role" title: "Status" } } }
MyTreeDelegate.qml
import QtQuick 2.0 import QtQuick.Controls 1.4 Component //must wrap rectanlge inside a component QML type to be called from a different file { Rectangle { id:baseRec color: "transparent" // color: ( styleData.row % 2 == 1 ) ? "white" : "#60e6dd" height: 5 // border.color: "black" // border.width: 1 states: [ State { name: "GreenOn" PropertyChanges { target: green; source:"images/GreenOn.png"} PropertyChanges { target: red; source:"images/RedOff.png" } }, State { name: "RedOn" PropertyChanges { target: green; source:"images/GreenOff.png"} PropertyChanges { target: red; source:"images/RedOn.png" } }, State { name: "BothOff" PropertyChanges { target: green; source:"images/GreenOff.png"} PropertyChanges { target: red; source:"images/RedOff.png" } }, State { name: "None" PropertyChanges { target: green; source:""} PropertyChanges { target: red; source:"" } } ] MouseArea { anchors.fill: parent onClicked: { // baseRec.state="RedOn" //styleData.depth returns 0 for parents and 1 for children console.log("row: ",styleData.row) console.log("index: ",styleData.index) console.log(theModel.data(theModel.index(1,0),colView.role)); } } Text { anchors.verticalCenter: parent.verticalCenter text: ( styleData.value === undefined ) ? "" : styleData.value // The branches don't have a description_role so styleData.value will be undefined } //add two texts Image { id:red visible: !(styleData.depth === 0 || styleData.value==="Objects detected count"|| styleData.value==="Objects in pallet count") height: baseRec.height width: height source: root.sourceRed //"images/RedOff.png" anchors { verticalCenter:baseRec.verticalCenter right:baseRec.right } } Image { id:green visible: !(styleData.depth === 0 || styleData.value==="Objects detected count" || styleData.value==="Objects in pallet count") height: baseRec.height width: height source: root.sourceGreen //"images/GreenOff.png" anchors { verticalCenter:baseRec.verticalCenter right:red.left } } } }
MyTreeModel.cpp
#include "mytreemodel.h" #include <QDebug> MyTreeModel::MyTreeModel(QObject *parent) : QStandardItemModel(parent) { m_roleNameMapping[MyTreeModel_Role_Name] = "name_role"; addEntry("Listening","Communication Status"); addEntry("Connected","Communication Status"); addEntry("Camera connected","Vision Status"); addEntry("Started","Vision Status"); addEntry("Objects detected count","Vision Status"); addEntry("Conveyor running","Palletizing Status"); addEntry("Object picked up","Palletizing Status"); addEntry("Objects in pallet count","Palletizing Status"); } void MyTreeModel::addEntry(const QString &child, const QString &parent) { QStandardItem *childEntry = new QStandardItem(child); QStandardItem *entry= getBranch(parent); entry->appendRow(childEntry); } QStandardItem *MyTreeModel::getBranch(const QString &branchName) { QStandardItem *entry; auto entries = this->findItems(branchName); if(entries.count() > 0) { entry = entries.at(0); } else { entry = new QStandardItem(branchName); this->appendRow(entry); } return entry; } QHash<int, QByteArray> MyTreeModel::roleNames() const { return m_roleNameMapping; }
-
Be aware that TreeView is very limited and has many bugs.
Indexes are unsafe to use. You can find bugreports on qt bugreports.
You may want to support https://bugreports.qt.io/browse/QTBUG-56490?filter=-2 -
@Kofr I've read your question one year ago, referring to this one
That's why you are saying it has many bugs?
let me clarify why I needed to retrieve the index, I'm trying to access each item on its own so I can apply a specific delegate to it (i.e. the green icon next to Camera connected will turn on if a specific condition is met on the back-end, that's why I tried to address each item on its own.
So far the method VRonin provided worked well and gave me the data I expected, so I am hoping when I finish my code, manipulating the items through the back-end, the delegate will be applied correctly.
I will keep you posted if I encountered any problem, thanks for the heads up.
-
@VRonin
Thanks so much buddy, your method worked and I understood it, the problem with my method that I wasn't referring to a parent item so I can get its child.What I eventually want to achieve is to let the delegates react to some back-end code, so I want to apply delegates to only a specific item once the condition is met (e.g., if Camera is connected, the green off icon should be replaced with a green on one) and so on. By saying so, I think it makes sense now why I wanted to be able to reach each item through its index.
Please, let me follow it by another question,
is it better to address the items on the C++ side or do it on the QML side? -
@Haitham said in How to retrieve items indices from a treeView?:
What I eventually want to achieve is to let the delegates react to some back-end code, so I want to apply delegates to only a specific item once the condition is met (e.g., if Camera is connected, the green off icon should be replaced with a green on one) and so on. By saying so, I think it makes sense now why I wanted to be able to reach each item through its index.
Just save the state as a separate role in the item and let the delegate check that role before deciding what to do
-
@VRonin
Can you please provide an example or something to follow? Because I am still a newbie at both Qt and QML.
Sorry for bothering you with my many questions.Update:
as you can see in the code, I change the state of the delegate through the mouse area in the delegate (it's commented out in the code). I was using it to test the states, now I've noticed another thing; Whenever I collapse the parent Item and then expand it, the previous states are not saved....does this have to do anything with what you mentioned?