[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