[Qt-interest] Question about Models, Roles and data

Andre Somers andre at familiesomers.nl
Wed Aug 26 17:18:06 CEST 2009


Murphy, Sean M. wrote:
>> Did you see the QTreeView::hideColumn() method? It allows you to hide
>> the columns in the views where you don't want them. Alternatively, you
>> could create a simple proxy model that hides the columns for you.
>>     
>
> No, and I was actually looking for it!  I must have skimmed too fast, I
> think I was looking for a set number of columns method, not a method
> that hides individual ones.  Thanks for pointing that out!
>
> I think the proxy model might be the right solution for the
> description-only tree view that we want.  I think my model naturally
> might want around 5 columns for the file object, about 10 columns for
> the foo objects and around 20 columns for the bar objects, but for that
> tree view, I'd only want to show the first column of each of the 3
> classes.  So rather than hide 19 columns, it seems like it might be
> easier to have a separate model that only builds up one column for that
> one view?
>   
Fair enough, hiding 19 columns (although that is of course a simple 
two-liner) is not all that elegant. Still, it's less code than building 
a proxy model.

For that proxy model, there are two alternative approaches:
1) Build a new QAbstractItemModel or QSortFilterProxyModel based model 
that reimplements all the needed methods and forwards them on another 
QAbstractItemModel based model that you set. This is the standard and 
most flexible way. It is a little bit of coding though, but not excessive.
2) Simply subclass your model implementation and re-implement 
columnCount() to return 1 everywhere. Less code, but you can not, for 
instance, keep only a single instance of your model alive for the 
different views you need.

I would go for option 1. It is more reusable, and not that hard to 
implement. It has the advantage that you could keep only a single 
instance of your data model in memory.
>> It is no problem for your table views if the foos and bars have a
>> different number of columns. See QAbstractItemModel::columnCount(). Do
>> you see the parent argument in that method? You can determine by the
>> parent model index what kind of object you are dealing with, and return the correct number of columns for your item.
>>     
>
> Ok, this one I'm not understanding what you mean.  I think you're
> describing a method that I can still get by just using one model; that I
> would not need to use a proxy?  
Correct, in principle.
The idea is to create one model that has the basic information. Most of 
what you want can be done directly with that data model, but for some 
things  you need to build a proxy model that re-arranges your data a 
bit. So, you end up with three models:
1) your actual data model. It contains all the data, all the columns you 
need in a tree.
2) the simple "only first column" proxy model (optional, as you can 
limit the display on the views too)
3) a proxy model to only show your bar objects.
> If my one model naturally has different
> numbers of columns, and I have several views I want to use with that one
> model: one a tree view where I only show the first column of all
> objects, and other table views where I show all columns of only one type
> of object (so a 10 column table that shows only foo's or a 20 column
> table that shows only the bar's for example), I don't quite see how I
> set a table view to use my model, but only get foo's (or only bar's) to
> pop out of it.
>   
For the foo objects, this is easy. A QTableView only displays one level 
of items at a time, and can start that display at any root node. In this 
case, your root node would be your file object. Your foo objects will 
appear as rows, with the data you need in the 10 columns).
> The bar only table that I want especially confuses me.  If this is the
> file data structure (spaces delimit columns):
>
> fileDescription fileData1 fileData2 ... fileData4
>   foo1_Description foo1_Data1 ... foo1_Data9
>     bar1_1_Description bar1_1_Data1 ... bar1_1_Data19
>     bar1_2_Description bar1_2_Data1 ... bar1_2_Data19
>   foo2_Description foo2_Data1 ... foo2_Data9
>     bar2_1_Description bar2_1_Data1 ... bar2_1_Data19
>   foo3_Description foo3_Data1 ... foo3_Data9
>     bar3_1_Description bar3_1_Data1 ... bar3_1_Data19
>
> I'd want my bar only table to show all 4 bar objects that are in the
> file, regardless of which foo's they belong too.  So I should end up
> with a 20 column table that looks like:
>     bar1_1_Description bar1_1_Data1 ... bar1_1_Data19
>     bar1_2_Description bar1_2_Data1 ... bar1_2_Data19
>     bar2_1_Description bar2_1_Data1 ... bar2_1_Data19
>     bar3_1_Description bar3_1_Data1 ... bar3_1_Data19
>   
The idea is clear. As Arnold said (and I realize now that he is right), 
you can use a proxy model to do this. Your proxy model will basically 
need to implement a two way mapping between your original tree leaf 
nodes and a linear list. I would start with subclassing 
QAbstractProxyModel. The trick is to come up with a smart mapping 
between indexes that make sense for a list, and indexes that make sense 
for a tree. There are many possible ways to do this, and the best or 
easiest way will partly depend on the specifics of your data model such 
as size and if it will change the number of rows (often). If you have a 
relatively stable data model, building up a list with incremential leaf 
node counts for each parent node (in your example above: [2,3,4]) could 
be a first step for making such a two way mapping.

André





More information about the Qt-interest-old mailing list