Sign up for the KDAB Newsletter
Stay on top of the latest news, publications, events and more.
Go to Sign-up
When using Qt's model/view framework, filtering has always been very easy with QSortFilterProxyModel. To filter a list using text typed by the user in a line-edit, you have certainly been applying the standard recipe:
textChanged
signal to the proxy's setFilterFixedString
slot; done!But what if the model is a tree rather than a flat list?
Let's use the tree below as an example.
As you can see by looking at the highlighted row, there is a toplevel item "Form Editing Mode" containing the item "Layouts", which itself contains an item with the word "Vertical".
Now if we use the same code for filtering as for a flat model, we get a rather unpleasant surprise: typing "Vertical" shows... an empty view.
This is because the toplevel item "Form Editing Mode" doesn't match the filter and therefore it has been filtered out, with no consideration for its children.
This is logical from an implementation point of view (filterAcceptsRow()
returns false, the whole subtree is filtered out), but this isn't what we wanted to achieve.
We need the parents of matching items to be considered as matching the filter too. Until now this wasn't easily possible.
This is the reason why I implemented (with the help of my colleague Filipe Azevedo) a "recursive filtering" feature in QSortFilterProxyModel. It has just been merged into Qt's dev branch (commit), which means it will be in Qt 5.10. You will need to be a bit patient, but at some point you will be able to make filtering work for tree models by adding one simple line of code:
proxy->setRecursiveFilteringEnabled(true);
And here's the result:
Pretty neat, isn't it?
About KDAB
The KDAB Group is a globally recognized provider for software consulting, development and training, specializing in embedded devices and complex cross-platform desktop applications. In addition to being leading experts in Qt, C++ and 3D technologies for over two decades, KDAB provides deep expertise across the stack, including Linux, Rust and modern UI frameworks. With 100+ employees from 20 countries and offices in Sweden, Germany, USA, France and UK, we serve clients around the world.
Stay on top of the latest news, publications, events and more.
Go to Sign-up
Upgrade your applications from Qt 5 to Qt 6 with KDAB’s migration services. Get a free migration assessment and join a hands-on workshop to prepare your team for a successful transition!
Learn more
9 Comments
19 - Jul - 2017
Attila
This is very nice indeed, I'm just wondering how will this handle models where the tree is infinite levels deep? (For example because there is recursion in it.) Is there a depth limit that can be set?
19 - Jul - 2017
David Faure
Right now this would recursive infinitely (well, until the stack is filled, then it would crash), indeed. I wasn't aware that there was really a use case for an infinitely-deep tree due to a recursion, although now that you mention it, I can imagine a folder tree model with a symlink pointing up...
I'm not sure that a depth limit is the right solution though. What limit should the developer set in the example above ? If he sets 10, and a user is looking for a subfolder at depth 11 it won't be found, even though the model isn't infinitely deep. On the other hand detecting recursion is almost impossible since it doesn't appear that way at the model level.
This being said, if you have a use case for a depth limit setting, please create a JIRA entry on bugreports.qt.io (or feel free to contribute the feature, of course).
19 - Jul - 2017
Attila
I was just asking since we have such a model, and have experimented with using QSFPM, but it's not likely that it will be included in a release, so nothing critical yet from my part.
Anyways, I have created an Issue on JIRA: https://bugreports.qt.io/browse/QTBUG-62050 with a suggestion.
21 - Jul - 2017
Laurent Bauer
Great feature, Bravo. By the way, an infinite tree produced by a loop would no more be a tree. It is a cyclic graph. Such a structure imho doesn't fullfills the preconditions of treemodels. So, it isn't a requirement. However, a very big tree, optimized with canFetchMore, that is progressively filled when opened, could be a problem. Great job anyway, this was a long time expected feature. Laurent
24 - Jul - 2017
Attila
Looping was just an example, an infinite tree can be constructed easily without it. And AFAIK the tree model/view in Qt works just fine even in that case so far (using canFetchMore and such), this would be an exception.
3 - Aug - 2017
Andre Somers
Nice, I have found myself implementing this manually more than once. I do have an additional request though, and that may require an API change for this one:
Sometimes, you do not only want to show parents for a match (so the match is visible), you may (also) want to show children for a match. I guess a getter and setter taking an enum to set a recursive matching mode instead of a simple bool would be needed to do that API wise.
26 - May - 2020
David Faure
This has now been implemented as well, by Giulio from KDAB. It will be in Qt 6. https://codereview.qt-project.org/c/qt/qtbase/+/301180
27 - Mar - 2018
Simon
After about 5 days of hunting down a crash in the QSPFM, we've found that it's something to do with proxy->setRecursiveFiltering(true);
We raised a bug with a repeatable test case. https://bugreports.qt.io/browse/QTBUG-67281
26 - May - 2020
David Faure
This turned out to be a missing call to invalidateFilter().