17

I'm writing an application in Qt (with C++) and I need to represent an object structure in a tree view. One of the ways to do this is to create a model for this, but I'm still quite confused after reading the Qt documentation about the subject.

The "structure" I have is pretty simple - there's a Project object that holds Task objects in a std::vector container. These tasks can also hold child tasks.

I've already written methods to read & write these projects to/from XML files using Qt's XML classes.

Is there any more documentation or "recommended reading" for creating models from scratch? How do you recommend I start implementing this?

Veeti
  • 5,270
  • 3
  • 31
  • 37
  • For `QTreeView` newbies, the main challenge is with understanding `index()` and `parent()`. I have written an article about this a while ago: http://www.hardcoded.net/articles/using_qtreeview_with_qabstractitemmodel.htm The example code is in Python, but the principles stay the same. – Virgil Dupras Dec 31 '09 at 16:04

2 Answers2

19

As an alternative to what was said by Virgil in a comment to the question, you could use QStandardItemModel class for your model and just build your tree using this class. Below is an example:

QStandardItemModel* model = new QStandardItemModel();

QStandardItem* item0 = new QStandardItem(QIcon("test.png"), "1 first item");
QStandardItem* item1 = new QStandardItem(QIcon("test.png"), "2 second item");
QStandardItem* item3 = new QStandardItem(QIcon("test.png"), "3 third item");
QStandardItem* item4 = new QStandardItem("4 forth item");

model->appendRow(item0);
item0->appendRow(item3);
item0->appendRow(item4);
model->appendRow(item1);

ui->treeView->setModel(model);

When the UI (view) is destroyed, delete model. Documentation:

Lekensteyn
  • 64,486
  • 22
  • 159
  • 192
serge_gubenko
  • 20,186
  • 2
  • 61
  • 64
  • who takes the ownership of the QStandardItemModel (model) and the created QStandardItems ? i.e. when the ui->treeView is destroyed, should i delete the model and the items manually? – AAEM Nov 06 '18 at 23:11
  • 1
    @AAEM It is not clear from the QStandardItem[Model] documentation, but it appears that appendRow takes ownership of the items (trying to append the second item twice fails). Like all other `setModel` invocations, the view does not take ownership of the model (to facilitate sharing). You have to delete the model at the end. (Verified with valgrind and Qt 5.11.2) – Lekensteyn Dec 05 '18 at 18:16
  • That's great for simple cases. But let's assume you can't build your model in one go (let's say you add the first item to `invisibleRootItem` and some rows (child nodes) to it. Then you do something else (like parsing the data needed further down the tree). Then you'd like to continue. You have to retrieve the already added nodes. How would you do that? You have 2 methods: `findItems()` and `item()`. The former is not designed for this purpose and I found it unreliable and the latter accepts `row` and `column`. How is it enough to locate a node in a tree? Of course no answer in the docs. – z33k Oct 04 '19 at 09:51
  • Greetings from the future! 10 years later and this answer just saved me hours, if not days worth of work. Thank you! – insaner Jan 02 '20 at 12:11
6

The basic trick to get this working is really to get the model to data structure mapping right. Something that might seem hard, but needn't be.

First, using the QAbstractItemModel::createIndex to build model indexes, you can refer to your own data structure through the pointer or uint32 that you can add to the index, depending on which instance of createIndex that you choose to use.

Second, having the structure clear in mind (as you seem to have), it is quite easy to write the parent and index functions. The key here is to understand that the model root is an unintialized QModelIndex instance. I.e. QModelIndex::isValid() == false indicates root.

Third, if you go multi-column, remember that only the first column has children.

Fourth, to check that you do things the expected way, do use the ModelTest class. It monitors and checks your model, so that you follow the conventions that the Qt model view classes expect.

Lekensteyn
  • 64,486
  • 22
  • 159
  • 192
e8johan
  • 2,899
  • 17
  • 20