Showing posts with label model/view. Show all posts
Showing posts with label model/view. Show all posts

Monday, 31 December 2012

Untouchable Views

So there I was, having a look at implementing QListView and realising that, as a control/widget, it didn't have any direct item interaction methods whatsoever!

Oh, bugger...

Fortunately, as noted in my last post, I've been creating a BlitzMax version of a type of a item model which subclasses QAbstractItemModel. And for QComboBox it is working really well. Changes to items on the combo eek down into the BlitzMax item objects. Whenever you change data in these item objects, they emit events that the rest of the model/view framework can handle appropriately. It's all rather cool and groovy!

Anyway, back to QListView. It doesn't do very much, on the face of it, apart from display a list. Any (and all) interaction with the items is done via the model and the "selection model". Changes to the model filter up to the view automagically, and stuff appears (or disappears) in the visual list before your very eyes.
As a framework, it appears to work very well indeed. Of course, if you are used to doing stuff directly with controls/widgets it is a bit of a leap to start playing with the model instead, and simply ignoring the view altogether!

As an example, if we want to change the text for an item in QComboBox, we simply call :

setItemText(index:Int, text:String)

and all the real work of processing that information and is handled by QComboBox.
On the otherhand, if we want to change the text for an item in QListView, we need to :

model.setData(index:QModelIndex, text:String)

where index is a reference to the location of the item in the model (row, column, parent item).
Notice that we need the model, and a way to map our row/index to the model's index reference.

Once we set/update the data, the view will update the text accordingly.

So, when we are working with Views, look, but don't touch!

:o)

Saturday, 29 December 2012

Not so QStandardItem...

So there I was trying to work out how I might integrate a model/view design into QtMax for handling all of the list/tree widgets, and I got to reading the QStandardItem/Model documentation.

"Hey, that sounds like just the thing I need!" I thought to myself, and hacked away at creating the wrapper code for QStandardItem and QStandardItemModel, using a custom QStandardItem object which handled user Object data on-the-fly.

Everything was looking shiny and new, so I decided I should test it out, and knocked together a quick QComboBox test app, which used my model and added a couple of items via the comboBox API.

Ta da! … oh, wait… nothing is actually happening!?

Further investigations revealed that QComboBox wasn't designed to expect a subclassed QStandardItem and went happily off to create base QStandardItems itself without using the "factory" that the documentation said I should implement (::clone()).

Which, as one would imagine, was somewhat of a let down after writing a whole bunch of code that I couldn't use ;-)

… time passes …

I pondered and pondered for a while, and went through a couple of mis-starts, but then came upon the idea that the best thing to do would be to code most of what I needed in BlitzMax, and interface that directly with the backend C++ classes, which would mostly act as a pass-through.

Okay, so the thought of implementing my own item/model for plugging into a QAbstractItemModel was a tad on the daunting side, considering that I wasn't only writing a couple of C++ classes, but a bunch of helper types, object transformations  and the main BlitzMax types to hold everything together.

I ended up keeping the names, QStandardItem and QStandardItemModel, and rewrote what I already had. I decided that all the item info needed to be kept in the Type, so I came up with a way to store everything in a TMap based on the "roles" that the model/view framework uses. I also built a custom children item holder which is based on an array, rather than a TList. I thought that it would be quicker doing lookups on an array index than trawling through a TList, and I am happy to take a hit on the resize of the array when it is required.

Because the underlying system passes data via QVariant, we need to do a lot of conversion between that and Objects. but it's simple casting so it shouldn't be too slow.

It took a whole day to get to a point where I was ready to try the QComboBox test app again, and after a couple of minor tweaks, I was very pleased with the results.
A simple call to :


combo.addItem("item 1", data)


iterates through the entire model framework, creating a new QStandardItem and populating it appropriately with all the role data, and even the user "data" object, which you can then retrieve by calling itemData(index) !

Of course, there's still much to do, like implementing cleanup and so forth, but with the basic engine running I feel much better about using this as a core for all of the Item-based widgets - lists and trees.

:o)