QFileSystemModel and QSortFilterProxyModel - root index is not preserved
-
Mates,
I've encountered a strange issue - if I try to filter out something using
QSortFilterProxyModel::setFilterFixedString()
then root index set for the model is abandoned, and view shows whole path starting from drive letter. What might be the cause of such behavior?
Qt version: Qt 5.11.1
compiler: Mingw 5.3.0Code:
//Legend: //navigationModel -> class NavigationModel : public QFileSystemModel //filteringModel -> class FilteringModel : public QSortFilterProxyModel //ustaw główny model do wyboru paczki do zainstalowania QString root(qApp->applicationDirPath() + "/TreeInGUI"); navigationModel.setRootPath(root); //ustaw styl klasycznego windowsa dla drzewka nawigacyjnego aby pokazywało ładne prowadnice ui->treeView->setStyle(QStyleFactory::create("windows")); //filtry trybu admina navigationModel.setFilter(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::Files); navigationModel.setNameFilterDisables(true); //model nawigacyjny ma współpracować tylko z plikiem instaluj, oraz skrótami do paczek QStringList names{"instaluj", "*.lnk"}; navigationModel.setNameFilters(names); //filteringModel na razie nie działa do końca dobrze:/ filteringModel.setSourceModel(&navigationModel); filteringModel.setRecursiveFilteringEnabled(true); filteringModel.setFilterCaseSensitivity(Qt::CaseInsensitive); //ui->treeView->setModel(&navigationModel); //ui->treeView->setRootIndex(navigationModel.index(root)); ui->treeView->setModel(&filteringModel); ui->treeView->setRootIndex(filteringModel.mapFromSource(navigationModel.index(root))); //filteringModel.setFilterFixedString("Testy");
Below how it looks with set root and no active filter (last line from the code commented) - it's OK:
And this is the result is I uncomment last code line - true, the filtering is performed, however root index is not preserved which is not OK:
-
Hi,
That might be the case.
One thing you can do to get more answers: provide a minimal compilable example to reproduce that behaviour. While you are giving some code to reproduce it, people will have to rewrite it in order to build something functional that may or may not trigger the issue you have. If everybody has the same code, then it's going to be way easier to find out whether it's a Qt issue or something else.
-
@MasterBLB "minimal compilable example".
What you provided are some code snippets, nothing one can compile.
It is important to have a minimal example showing the issue, because the issue could be in other parts of the code than what you posted.
Also, if you only post code snippets you're actually asking others to create a minimal compilable example... -
Sorry but no it's not.
It's neither minimal nor compilable.
- It can't be just copied and pasted in a main.cpp to be built.
- There's no
main
function to launch the application - There's a designer based ui used that is not available
- You are using subclasses that are maybe doing something or not so we don't know whether it's in that part that something is going on.
Therefore, you are asking people to write and build themselves that minimal use case to find out whether they can reproduce your issue.
-
Well, I was sure Qt Champions are capable of:
- creaing a QTreeView instance
- creating a QFileSystemModel instance
- creating a QSortFilterProxyModel instance
- apply a simple filter for the filter model
well then, here is main:
int main(int argc, char *argv[]) { QApplication a(argc, argv); QTreeView treeView; QFileSystemModel navigationModel; navigationModel.setFilter(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::Files); navigationModel.setNameFilterDisables(true); QString root(/*set it somewhere into directory structure, say C:/Qt/some version*/); navigationModel.setRootPath(root); QSortFilterProxyModel filteringModel; filteringModel.setSourceModel(&navigationModel); filteringModel.setRecursiveFilteringEnabled(true); filteringModel.setFilterCaseSensitivity(Qt::CaseInsensitive); treeView.setModel(&filteringModel); treeView.setRootIndex(filteringModel.mapFromSource(navigationModel.index(root))); filteringModel.setFilterFixedString(/*put some folder name which appears deeper in the choosen root*/); treeView.show(); return a.exec(); }
-
@MasterBLB said in QFileSystemModel and QSortFilterProxyModel - root index is not preserved:
Well, I was sure Qt Champions are capable of
You're the one asking for help. It is not about whether Qt champions are capable of doing this or not, it's simply about to help others to help you. You're aware that your list means work for others, right? People in this forum are not paid workers who have to work for you, but just volunteers spending their own time to help others...
-
And that's why I've written the example within around 60s, as requested. I hope it fulfills expectations, but if needed feel free to ask about implementation details of models, though as mentioned there isn't anything related to manipulating root index.
-
Hi
I can confirm it get the same result on Qt5.12.3 and Qt5.9
so at least we can say its not a local bug of sorts.
#include <QApplication> #include <QFileSystemModel> #include <QSortFilterProxyModel> #include <QTreeView> int main(int argc, char *argv[]) { QApplication a(argc, argv); QTreeView treeView; QFileSystemModel navigationModel; navigationModel.setFilter(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::Files); navigationModel.setNameFilterDisables(true); QString root("C:/Qt/5.12.3/msvc2017_64"); navigationModel.setRootPath(root); QSortFilterProxyModel filteringModel; filteringModel.setSourceModel(&navigationModel); filteringModel.setRecursiveFilteringEnabled(true); filteringModel.setFilterCaseSensitivity(Qt::CaseInsensitive); treeView.setModel(&filteringModel); treeView.setRootIndex(filteringModel.mapFromSource(navigationModel.index(root))); filteringModel.setFilterFixedString("Lib"); treeView.show(); return a.exec(); }
-
As @mrjj I can reproduce that on macOS with a recent build of Qt.
You should check the bug report system to see if there's already something related. If not, then please consider opening a new report providing that minimal compilable example.
-
@MasterBLB
Hi
Well you just go there and login with the credentials you use here.
A good read is
https://wiki.qt.io/Reporting_Bugs -
Personally, I didn't. Since you found it, the honour is yours :)
-
Hi
nope, if i had made report, i would have linked url here :)
So please do. -
I don't think it's a bug.
setRootIndex
is a method of the view. The model has no way of knowing (and shouldn't know) what a view is using as root. The filter set on the proxy applies to the whole model. If the index used as root by a view gets filtered out it's only natural for a view to revert to usingQModelIndex()
as root.What you need is a proxy model that implements the
setRootIndex
functionality at the model level. This is on the list of nice-things-I-would-like-to-add-to-Qt-models and it's a fairly easy one to do but I need to find time for it :( -
In the way such behavior breaks SOLID substitute rule - I can't use descendant class QFileSystemModel like it was its base class QAbstractItemModel in QSortFilterProxyModel. While not a 100% bug it's definitely a serious design flaw, and worth to be reported. But where?