[Qt-interest] Filtering only certain child rows of a tree model but include their parents when displaying (QSortFilterProxyModel)

Girish Ramakrishnan girish at forwardbias.in
Thu May 7 09:34:33 CEST 2009


Andreas Ntaflos wrote:
> Hi list, 
> 
> I apologise for this lengthy post but I tried to be as clear as possible 
> with my problem description so that a kind, knowledgeable soul will be 
> willing to help me :)
> 
> I am trying to apply a filter to a custom tree model (based closely on 
> [1] and [2]) with two columns. The second column is the filter key 
> column. I only want to filter certain child items (that are not parents 
> themselves, i.e. leaves), but still display their parents.
> 
> The first column holds the collapsible items that make up the tree and 
> the second column holds the data that I'd like to filter 
> (setFilterKeyColumn), but, as mentioned, only for those rows of the 
> source model that are not parents. See the following figure (best 
> viewed with a fixed-width font):
> 
> Figure 1: Tree model unfiltered
> column 0             column 1
> -----------------------------
> ParentItem1          <empty>
>  - SubItem11         <empty>
>   - ChildItem111     data111
>   - ChildItem112     data112
>   - ChildItem113     data113
>  - SubItem12         <empty>
>   - ChildItem121     data121
>   - ChildItem122     data122
>  - SubItem13         <empty>
>   - ChildItem131     data131
>   - ChildItem132     data132
> ParentItem2          <empty>
>  - SubItem21         <empty>
>   - ChildItem211     data211
>   - ChildItem212     data212
>  - SubItem22         <empty>
>   - ChildItem221     data221
>   - ChildItem222     data222
> 
> You see the model only returns a valid QVariant when a ChildItem is 
> encountered. For both a ParentItem or a SubItem an empty QVariant is 
> returned (return QVariant();).
> 
> Now I'd like to apply a filter based on a regular expression on column 
> 1. Currently I use a standard QSortFilterProxyModel for this. The data 
> in column 1 is formatted reliably so a regexp can be applied easily. 
> Let's say the Regexp for column 1 is set to "data111|data112" (via 
> setFilterRegExp). What I'd like the proxy model to return is 
> illustrated in the following figure:
> 
> Figure 2: Model as it should be filtered by regexp "data111|data112"
> column 0             column 1
> -----------------------------
> ParentItem1          <empty>
>  - SubItem11         <empty>
>   - ChildItem111     data111
>   - ChildItem112     data112
> 
> But, as you can probably imagine, the filter/regexp doesn't match any of 
> the rows that are <empty> in column 1, thus filtering away all parent 
> items of the ChildItems I'd like to filter. The end result is a 
> completely empty proxy model/tree view.
> 
> I have solved this for now by replacing <empty> with some special string 
> ("####" for example) and including that string in the filter 
> regexp: "data111|data112|####". It is, however, not a very elegant 
> solution because this way all ParentItems and SubItems remain visible 
> in the filtered model, just their non-matching children are not:
> 
> Figure 3: Model is it is filtered by "data111|data112|####"
> column 0             column 1
> -----------------------------
> ParentItem1          ####
>  - SubItem11         ####
>   - ChildItem111     data111
>   - ChildItem112     data112
>  - SubItem12         ####
>  - SubItem13         ####
> ParentItem2          ####
>  - SubItem21         ####
>  - SubItem22         ####
>  - SubItem23         ####
> 
> Clearly it is undesirable to display all those items that have no 
> ChildItems under them. It clutters up the view and makes navigating the 
> filtered result harder.
> 
> What do I have to do to make my filter model behave like illustrated in 
> figure 2, i.e. filter only those rows that contain a ChildItem but 
> still display their parents and grandparents? Is there even a way?
> 

I don't think it is possible to achieve what you want using
QSortFilterProxyModel. It just doesn't support introspecting whether the
item has any matching children when filtering the parent.

You will have to write your own QAbstractProxyModel or
QAbstractItemModel to achieve what you want.

Girish



More information about the Qt-interest-old mailing list