[Qt-interest] ModelView - how to use proxies to filter this data?
Stephen Kelly
steveire at gmail.com
Mon Nov 30 13:55:02 CET 2009
Daniel Price wrote:
> I need to use modelView in an advanced way.
>
> I have data like this (contrived example):
>
> People{}
> ---person1{first name, last name,address1,address2,phone, email}
> ---person2{first name, last name,address1,address2,phone, email}
> ---person3{first name, last name,address1,address2,phone, email}
> Companies{}
> ---company1{name, address1, address2,phone,website}
> ------product1{name,type,price}
> ------product2{name,type,price}
> ---company2{name, address1, address2,phone,website}
> ------product1{name,type,price}
> ------product2{name,type,price}
>
> The data is hierarchical but sub-categories of data have different columns
> and different data for each column. In the above example, 'person' records
> have 6 columns, but 'product' records have 3. The actual data I'm dealing
> with is a lot more complex.
>
> Now an QAbstractItemModel-derived class can be used as an adaptor for this
> but the data cannot (practically) by displayed within a QTreeView. So my
> idea is to use QAbstractItemProxy-derived classes to wrap the model. The
> primary single-column TreeView will display the following as headers:
>
> People
> ---person1
> ---person2
> ---person3
> Companies
> ---Company1
> ---Company2
>
> When a Person or Company row is selected, a secondary TableView with
> display the data, stored as child indexes of that item in the original
> model.
Have a closer look at the models/proxies used in Akonadi. The
EntityTreeModel is the invisible "core" model, the
EntityMimeTypeFilterProxyModel creates something like your overview proxy
model above, and the KSelectionProxyModel uses the selection from that to
give a listing related to what you have selected. The result of that is
usually then further processed by another EntityMimeTypeFilterProxyModel,
but depending on your real data, you might not need to do something similar.
http://api.kde.org/4.x-api/kdepimlibs-
apidocs/akonadi/html/classAkonadi_1_1EntityTreeModel.html
http://api.kde.org/4.x-api/kdepimlibs-
apidocs/akonadi/html/classAkonadi_1_1EntityMimeTypeFilterModel.html
http://api.kde.org/4.x-api/kdelibs-
apidocs/kdeui/html/classKSelectionProxyModel.html
There is a bit of hackery between those classes to make different headers
appear in the different views (see the use of EntityTreeModel::HeaderGroup).
If you come up with a better way to do that than I did, let me know.
You can see how they are used together in akonadiconsole:
http://websvn.kde.org/trunk/KDE/kdepim/akonadi/akonadiconsole/browserwidget.cpp?view=markup
(AkonadiBrowserModel is-a EntityTreeModel)
and KAddressBook (including ASCII art :) )
http://websvn.kde.org/trunk/KDE/kdepim/kaddressbook/mainwidget.cpp?view=markup
It's not exactly the same as what you want to do, but it's good for ideas of
how to do this kind of stuff.
>
> So I would need four models - the original (invisible) model with all the
> data, an Overview proxy model for the primary tree, a Person proxy model,
> and Company proxy model.
That could work. You might not have to do the headerData hackery if Person
and Company are different QSFPM subclasses. The akonadi equivalent is the
EntityMimeTypeFilterModel which handles both.
>
> I'm having trouble implementing this due to the lack of
> examples/information available. Here is what I have discovered:
>
> 1) It looks like QAbstractProxyModel-derived classes must propagate
> all signals emitted by the source model or it will do nothing (the
> examples I've seen work only on static data created before the model is
> hooked up so it does not matter).
Yes.
>
> 2) From studying the QSortFilterProxyModel implementation, it seems
> that proxies cannot share indexes from the source model - they must create
> their own.
Yes.
>
> I just need to be able to pick out the data from the primary model for
> each view. Does anyone have examples on how to proceed? No-one seems to
> have done this publically outside of Nokia so information is rare!
I couldn't find anything either at the start, and it has taken a long time
to get this far.
>
> I can think of discrete ways of doing the same thing without proxies but
> having everything in a primary model has certain advantages (simplified
> undo for example).
And not-broken selection, caching possibilities etc.
For more advanced model-view stuff see my blog, particularly:
http://steveire.wordpress.com/2009/10/01/akonadi-its-all-sausage/
http://steveire.wordpress.com/2009/10/06/cache-invalidation-in-akonadi-
models/
http://steveire.wordpress.com/2009/06/23/testing-non-trivial-generic-proxy-
models/
Note that KSelectionProxyModel is covered by the LGPL, so you must be aware
of your licencing obligations if you want to use it. Also, it is currently
broken in a subtle way and I have a large patch pending to fix it.
Final tip: Never use the internalPointer or internalId of a QModelIndex in
the source model when implementing a proxy model.
All the best,
Steve.
>
>
> Daniel Price
> Software Engineer
> FXhome Limited
>
>
> ________________________________
> This email is confidential. It may also be privileged or otherwise
> protected by work product immunity or other legal rules. If you are not
> the intended recipient please notify the sender. Please delete the message
> from all places in your computer where it is stored. You should not copy
> the email or use it for any purpose or disclose its contents to any other
> person.To do so may be unlawful. Email is an informal means of
> communicating and may be subject to data corruption accidentally or
> deliberately. For this reason it is inappropriate to rely on advice
> contained in an email without obtaining written confirmation of it first.
>
> FXhome Limited is a limited company registered in England and Wales.
> Registered number: 04172812. Registered office: The Henderson Business
> Centre, Ivy Road, Norwich, Norfolk, NR5 8BF, U.K.
More information about the Qt-interest-old
mailing list