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

Andreas Ntaflos daff at pseudoterminal.org
Thu May 7 05:01:39 CEST 2009


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?

Any and all help is appreciated!

Thanks in advance, 

Andreas

[1] http://doc.trolltech.com/4.5/itemviews-simpletreemodel.html
[2] C++ Gui Programming with Qt 4, ch. 10, pp. 238 (the "RegExpModel")
-- 
Andreas Ntaflos 
Vienna, Austria 

GPG Fingerprint: 6234 2E8E 5C81 C6CB E5EC  7E65 397C E2A8 090C A9B4



More information about the Qt-interest-old mailing list