[PyQT] Model View Video Tutorial Series (Part 01)

One more thing I want to point out is; utilizing polymorphisim of our node classes which we wouldn’t be able to do inside the model class. Cause column 2 for Transform node is not Column 2 for Light node =} kinda have to decide at some point for complexity in code vs extendability. Where I went with the latter instead of cluttring the model class with if transform get x, if light get intensity, if camera get fov, if node get nothing etc :slight_smile: Now using the method you described would force me to do this, which is ALSO what I had before. Think of the size of our model would get… It would be very problematic when you wanted to add a new node type, new attribute to an existing node etc

Hope you understand the thoughts behind this, it was intentional :slight_smile:

O yeah, fully get why you did it for the tutorials.

It is definitely something that needs to happen in the design stage.

Both ways work, just depends on the use case(s).

Cheers!

Loving it so far. Thank you for putting these together sir.

Thanks for the kind words :slight_smile: Glad you like it!

Next part is in the workings right now!

I will cover dragging, dropping, mimetypes, using flag properties and also creating our own reusable flagwidget which allows “OR” ing flags, query their value or string representation for xml output etc.

Will go into selection models, and root items in tree views and how we can display SUBPARTS of our entire tree in several views: Example:

<!–ALL IN SAME HIERARCHY -->
<PhysicsEngine>

&lt;!--DISPLAY IN uiTreeApex --&gt;
&lt;Apex&gt; 
	&lt;Cloth name="cloth0" /&gt;
	&lt;Cloth name="cloth1" /&gt;
	&lt;Cloth name="cloth2" /&gt;
&lt;/Apex&gt;

&lt;!--DISPLAY IN uiTreePhysX --&gt;
&lt;PhysX&gt; 
	&lt;Concave name="concave0" /&gt;
	&lt;Concave name="concave1" /&gt;
	&lt;Concave name="concave2" /&gt;
&lt;/PhysX&gt;

</PhysicsEngine>

Might take 3-4 days for me to finish it :slight_smile:

yasin, not sure if you’ve seen this, may be helpful

http://www.commandprompt.com/community/pyqt/?page=pyqtbook

It’s a little bit old now…

Yeah I’ve seen it months ago =}

While he goes through PyQt, he doesn’t go through the model view framework that ships with Qt (Views, Models, Delegates, subclassing them etc), which is the goal of this series!

Though he does have a dedicated chapter about the Model-View-Controller pattern in general, which I don’t provide, since my main goal is talking about the Qt Model,View,Delegate framework that ships with Qt :slight_smile:

That link is a very useful source for anyone starting with PyQt and design patterns!

//Yaz

I am using QStandardItemModel, and appending 3 different objects subclassed from QStandardItem. So each row of the model has 3 columns and each column has different QStandardItem subclassed object.

I am using the QTreeView and set model. The problem is when i move the tree nodes around the rows are no longer my subclassed object, but QStandardItem. The way to fix this is to setItemPrototype on the model. But that only takes one class instance, i have three different instances i need to pass in.

Is there a way to do that?

If thats confusing just think of a QTreeView that is using the QStandardItemModel and each row is different class instance. How do you tell the model to clone the correct class instance when the tree nodes are moved around?

Thanks!

I watched the videos through the treeview series and I have my model working. I’m pulling in a list of rule names and displaying them under specific headers. Before converting to treeview and using the model, I had an action:

self.treeWidget_rulesList.itemClicked.connect(self.displayRule)

itemClicked is not available in the treeView, so how do I trigger my displayRule def when clicking an item in the treeView? Thanks,

Jason

For me it does not display the string. I had wrapped in QtCore.QVariant string, get it to work. Just curious why such a QVariant that?

Hi Yasin,
I’m really impressed by your tutorials !
Very very useful and so educational…
If only I could see your tutorials before, I would have saved a lot of time!

Just a question: will you post next tutorials soon ?

Thanks,
Steph

awsome ninja juice power!
More please.

Haha, I remember looking at these when you first posted them and when I was a complete Gui noob. They seemed so incredibly alien and I never thought I’d have any use for them.

For I was blind but now I see. :slight_smile: Awesome job dude, really looking forward to the drag and drop stuff!

1 Like

Thanks =}

We’ll see if I ever make anymore tutorials, I hope I can find the time and motivation to do them. While I’m at it I would probably revisit some of the earlier chapters and make them better and remove stuff I’m not entirely happy with :slight_smile:

Cheers!

Yeah, about that. Do you still agree with your previous self about keeping setData in the Node classes, instead of at the Model level? :slight_smile:

Well if you think about why I did that, it’s only and only because the dynamic behaviour of different “nodes” and node properties :slight_smile:

A light has properties a transform doesn’t, and a camera has stuff a light doesn’t, and they all have different amount of attributes with different types :slight_smile:
The model view framework is built for data layout of the same type and same layout across all objects, so setData in the nodes was done just because of this. I would take a completely different approach to the entire thing to be completely honest. I don’t like the model view framework for property type stuff since it can be so dynamic.

Sure there are ways around, you can wrap a QAbstractItemModel and a QItemDelegate in your own class and make sure it returns widgets depending on the data type and data count but it just makes everything so much more complex.

Because of that I didn’t want to bloat the model with different behaviour, the model view framework in Qt is good for data layouts that is same across all nodes, which wasn’t our case. Besides I would never watch a tutorial and take everything for granted, I’m usually doing my own research as well, and so should you!

Since everything is done on the fly during the tutorial I really didn’t sit and software design :slight_smile:

But I would probably have some sort of a
Property (holds tooltips, value, string value)
PropertyManager(creates properties, need to derive this for each data type, aka BoolManager)
PropertyFactory (creates the editable widgets, need to derive this for each data type aka CheckBoxFactory)
PropertyBrowser (the populated browser, so register a manager for a factory here, derive it GroupPropertyBrowser or TreePropertyBrowser etc)

and leave the model view framework for what it’s good for, displaying objects :slight_smile:

Be aware that the naming is not perfect and I just wrote it fast, I usually don’t name stuff “manager” because it tends to make it unclear what the class role is :slight_smile:

I didn’t mean to counter argue your way of working, it was more a question of if you later found that it’s definately the way to go, or the opposite.

This stuff diretly correlates to what I’m doing currently and I’m just trying to find a nice, future-proof, setup. :slight_smile:

No no I didn’t think you counter argued me, I just wanted to explain why I did it so you don’t get the idea that it’s the only way to go, because it’s not and there are better ways :slight_smile:
Also that I would not do property related stuff in the model view framework, since it’s better in displaying many objects with same data in lists, trees, tables etc :slight_smile:

Imo as soon as you introduce different objects and different amount of data with different data types the models usually get VERY bloated, you want a reusable and extendable generic system for property related stuff, that’s why I would not use model view framework in the future for this kind of stuff :slight_smile:

Model view framework is basicaly a kind of “adaptor pattern” and everytime you want to add something new your model would basicaly need to grow or would be a complex beast to work as a generic thing for property related stuff :slight_smile:

Model view framework solves a specific problem and is better in other areas. I would use the Model view framwork for displaying the objects in lists, tables and trees and a different system for handling and displaying the properties in a proeprty browser, so there are two different systems. Then just connect them with signal slot system.

This would be a far better way of handling it and be future proof since you can re-use the property system across projects, and was something I planned for the future tutorials :slight_smile:

Hehe, that just about goes over my head at this point. I’ll have to read it again in a few weeks to continue that discussion. :slight_smile:

An example :slight_smile:

SceneGraphNode <------> SceneGraphModel -----> SceneGraphView (derived from TreeView, can be TreeView as-well )

SceneGraphNode is your class that has your properties and is basicaly what your model uses to fill the SceneGraphView with displayable data. All SceneGraphView should do is show the hierarchy in a tree view with the name property or any other of your choice :slight_smile:
When you select something a PropertyBrowser should be populated with some widgets that you can use to edit properties right? What I did in the tutorials was to use QDataWidgetMapper to map indices from the model into certain widgets, I actually dont like this since it’s not generic and everytime we want something new we have to edit the model or the node itself and the mapping indices are a pain to handle and as pointed earlier doesn’t allow for reordering of properties.

So you would have a different system outside the model view framework that you have created called something like GroupPropertyBrowser that can show Property objects in editable widgets, and Property objects are created by AbstractPropertyManager that is associated with an AbstractPropertyFactory that creates the actual editors for the GroupPropertyBrowser to use. So BoolPropertyManager creates bool properties and it’s associated with either a CheckBoxPropertyFactory or RadioButtonPropertyFactory (derived from AbstractPropertyFactory) so you have the choice to display something differently if you want to :slight_smile:
You can add new data types by just deriving from AbstractPropertyFactory for the widget representation and AbstractPropertyManager for the data representation :slight_smile:

Then you bind the selection of the tree view to the property browser with the signal slot system and you can re-use the property system in other projects :slight_smile:
Basicaly don’t use the SceneGraphModel to return property related stuff, just return what you want to dislpay in your SceneGraphView and let a different system handle property editing features. Since that’s what the model view framework was built in Qt for, to display stuff in lists, tables, trees or extend to custom drawing.

Mm, it sounds exactly like what I’m after. I’ll mess around a bit and keep your advice in mind. Thanks Yasin.