[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