PDA

View Full Version : Using a tree widget to display a list of model objects



xtal256
18th May 2011, 08:12
Once again i am at a point where i know what i want, but i have no idea how to get there. So i will just tell you what i want an hope you can help me in any way (even if it's just pointing me to some reading material).

My application, Window Detective (http://windowdetective.sourceforge.net/), monitors windows and logs messages sent to each window. I have a WindowMessage model object to represent each message and a UI which displays each of these messages. I use a tree widget to show each message in the list, where nodes of the tree are parameters of each message. e.g.


+- WM_SETCURSOR
| |
| +- wParam = 0x00020120
| |
| +- lParam = 0x02000001
|
+- WM_MOUSEMOVE
| |
| +- wParam = 0x00000000
| |
| +- lParam = 0x00001234
|
+ ...

Currently i am just creating and adding tree items when each message is recieved by my application. But now i want to do more advanced things to the UI such as filtering (hiding) certain messages or highlighting them. For that, i need to know stuff about the model object that each top-level tree item represents.
How do i design my model/view to achieve this? I suppose using the QTreeView instead of QTreeWidget would be better, but i am not quite sure how to use it. Despite learning the MVC pattern, i still do not fully understand it.

There are similar cases in my application where i do this sort of thing. For example, the tree that shows a hierarchy of all windows. In that cases, i created a subclass of QTreeWidgetItem which contained a pointer to my Window object. I am not sure if that was a good way to do it, but i cannot use that exact way here because i am not mapping tree items to model objects. Only top-level tree items represent the model object.

I am also thinking about custom rendering and how i could display each object as a list item but which can be expanded to show a tree view of it's parameters (which in the future will contain more than just wParam and lParam). I am just not sure whether i should be subclassing a list view or a tree view for this.

xtal256
19th May 2011, 06:08
Any ideas? Perhaps someone has a link to examples of how to do complex UI stuff like this in Qt. I have looked through the examples and demos that comes with Qt, but they are pretty simple.

xtal256
25th May 2011, 12:38
Ok, can anyone tell me when i should use Q*View over Q*Widget and what are the advantages/disadvantages?
What i have done so far with QTreeWidgets or QTableWidgets is to create the widget items and populate them with data from my model object/s. And i could continue to do so here, extending QTreeWidget and maybe QTreeWidgetItem to store a pointer to it's associated model and populating the UI with data from the model. But i get the impression that QTreeView gives more flexibility and power to do complex stuff like this.

jeanremi
25th May 2011, 12:56
The forum is not very quick in replying, is it? ;-)

Anyway, I asked a similar question on one of my threads and I was told by Squidge (expert member here) that the idea is to create a container widget which will contain your subclassed/derived widget, you can do custom drawing in your derived paint functions. That's my understanding for this kind of complex UI in Qt. Sorry if it misleads you ;)

I'm about to start my custom timeline control which will effectively be the container control and it will contain a custom qtreewidget, custom ruler, custom chart control (for tracks) and a custom moving thumb to achieve my goal.

There are no tutorial that shows me how to do this, so I'm heading myself into it from scratch (but yes some Qt examples will teach me how to code into the paint functions and stuff). When successful, I will probably post it as a tutorial.

Best of luck.

Jean

joyer83
25th May 2011, 13:21
Ok, can anyone tell me when i should use Q*View over Q*Widget and what are the advantages/disadvantages?
What i have done so far with QTreeWidgets or QTableWidgets is to create the widget items and populate them with data from my model object/s. And i could continue to do so here, extending QTreeWidget and maybe QTreeWidgetItem to store a pointer to it's associated model and populating the UI with data from the model. But i get the impression that QTreeView gives more flexibility and power to do complex stuff like this.

Use QTreeWidget when you have just some data that doesn't change. If the content can change then it is easier to use the View - Model system (in my opinion). Easiest way to start is to create a QTreeView and a QStandardItemModel and give the model to the view with QAbstractItemView::setModel(). When you modify the model the view will update itself automatically.
If you need to filter out items from the view, you can use QSortFilterProxyModel for that. The proxy is given to the QTreeView using the setModel() method above. The model which the proxy listens for is given with QAbstractProxyModel::setSourceModel().

xtal256
27th May 2011, 00:45
Thanks for the tips joyer83.

One thing i am still not sure about is what the "model" actually is. I have created classes to model the data in the system (OS windows in my case), but i get the feeling that the model objects used with views (QStandardItemModel) are something different. I will check out the documentation and examples and hope that clarifies things for me.

xtal256
29th May 2011, 05:05
Ok, i think i now understand the purpose of the "model". I was thinking that i needed to use my objects (Window, WindowMessage, etc) as the model for the QTreeView or QListView, where each item would have a model. But i now see that views have a model to represent the entire data structure. So i guess this means that i would subclass one of Qt's model classes to hold the list of messages. Is this right? Since i already store the messages in a list somewhere, how will this model object differ from the QList i already have?

If you don'tknow what i'm talking about, you can download the latest source code from here (http://sourceforge.net/projects/windowdetective/files/release-2.2.0/Window-Detective-2.2.0-src.zip/download) to see how i'm currently doing thinks.

joyer83
29th May 2011, 09:47
One thing you should notice first is that you wanted to represent the data as a tree while you data internally is stored as a list. While implementing something that can map between tree like structure and list like structure on-fly is not impossible, but it will not be easy either.

You have two choices, would you like to store WindowMessage's data into Qt's model or do you want to keep on using the QList?

For first choice, You could use QStandardItemModel, no need to subclass any model classes. Adding new messages would work something like this:

QStandardItem *messageItem = new QStandardItem( messageName );
QStandardItem *lparamItem = new QStandardItem( lParam );
QStandardItem *wparamItem = new QStandardItem( wParam );
model->invisibleRootItem()->appendRow( messageItem );
messageItem->appendRow( lparamItem );
messageItem->appendRow( wparamItem );

For second choice, you would subclass QAbstractItemModel and use it as an adapter which internally reads the QList and at same time provides an interface (QAbstractItemModel) which the QTreeView can access. In this choice you need to implement the list-tree mapping. You need to also remember to notify the model whenever the QList is being modified, otherwise the QTreeView will not update.

xtal256
30th May 2011, 01:28
Hmm, it looks like it will be hard to do no matter what way i choose.
I was also thinking instead of using a QTreeView, i could somehow use a custom QListView where each item would be rendered as a tree, but that is probably harder than anything you are describing.
I would also like to do custom drawing to make it look nice. For example, i want to be able to highlight items. So it would probably look nicer if the whole subtree of an item was coloured, perhaps with a gradient (like the selection look in Windows 7), rather than colouring each individual tree item.

Added after 22 minutes:
Basically what i want is a model/view which can show a list of objects where their member variables are shown as a tree under each item. So the list would show some text representing the object (in my case, the name of the window message), then that item can be expanded to show a hierarchy of that objects properties. Sort of like how Visual Studio shows objects in it's debugger.

Perhaps someone has done this already, maybe there is code out there somewhere that can do it. I have seen some pretty cool 3rd party Qt libraries (wysota's wwWidgets).
I don't expect (or want) something which can automatically show all properties/variables of an object, I would choose what gets displayed. I am mainly concerned with the UI side of it, such as how the data is displayed and the ability to sort and highlight. Perhaps it's too much to ask for.

xtal256
30th May 2011, 04:00
I discovered an article about a web history manager (http://labs.qt.nokia.com/2008/03/25/advanced-example-of-modelview/) that looks quite similar to something i want. It's part of the Qt demo/browser, so i will check out the code.