PDA

View Full Version : Find Files QFileSystemModel



NIteLordz
7th September 2016, 17:28
I am displaying a QFileSystemModel in a QTreeView to display the directories, and then i have a QListView that displays the files of the selected directory.

I want to implement search functionality, so that if i am currently on the root directory, it will search the children directories, and display all matching files in the QListView.

I have tried, and currently still playing with QSortFilterModelProxy, but when it searches, it searches from the currently selected folder, back up to the ancestor list, instead of going into the children.

Any help or guidance would be much appreciated

anda_skoa
7th September 2016, 18:07
How do you populate the list view during non-search operation?

Do you have another proxy model between the file system model and are filtering on parent?
Or is that the same proxy model instance and you are changing the filter criteria when searching?
Or do you have a list model that is populated from a directory listing?

Cheers,
_

NIteLordz
7th September 2016, 18:48
Currently i have the following

QTreeView powered by DirectoryStructureModel (extended QFileSystemModel) and DirectoryStructureProxyModel (extended QSortFilterProxyModel)
QListView powered by FileListModel (extended QFileSystemModel) and FileListModelProxy (extended QSortFilterProxyModel).

When the QTreeView selection changes, the QListView updates the root path and the QListView displays the contents of the directory, based on the filter flags in FileListModelProxy.


So what i want to have is a line edit, that on textChanged signal, QListView displays all matches, from Root to full extents.


Ex.

Given the structure below, and Assets is currently selected, the list view is currently displaying Scenes and Textures folders. Entering "L" into the search edit, would clear the list view, and display only "Level_01.xml"

-Assets
--Scenes
---Level_01.xml
--Textures
---Player.png

anda_skoa
8th September 2016, 11:05
In your setup you will need to

- set the root path of the FileListModel to the very base root path
- in FileListModelProxy accept all rows that either match or which are directories and contain a match somewhere in their sub tree

Alternatively you could just have a special purpose list model for the second view.
That model would get a root path and the search string.
- If the search string is empty, it just lists the root path.
- If it is not empty, it uses a recursive QDirIterator starting at the top root path

More or less it could always use a QDirIterator, the presence of the search string would change the path to start with and the recursiveness.

Cheers,
_

NIteLordz
8th September 2016, 14:15
I have updated filterAcceptsRow for FileListViewModelProxy, and now when it hits a directory, it recursively dives in, and matches on filterText_, however, the display results are not what is expected.


bool FileListViewModelProxy::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const {
QFileSystemModel* fileSystemModel = qobject_cast<QFileSystemModel*>(sourceModel());

if (sourceParent == fileSystemModel->index(fileSystemModel->rootPath())) {
return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
}

QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
QFileInfo fileInfo = fileSystemModel->fileInfo(index);
QString fileName = fileInfo.fileName();

if (fileName.startsWith(filterText_))
return true;

if (fileInfo.isDir())
return searchDirectory(fileInfo);

return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
}


bool FileListViewModelProxy::searchDirectory(QFileInfo fileInfo) const {
QString filePath = fileInfo.filePath();
QDir dir(fileInfo.filePath());
QString dirName = fileInfo.fileName();

QFileInfoList fileList = dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
for (int i = 0; i < fileList.size(); i++) {
QFileInfo fileInfo = fileList[i];
QString fileName = fileInfo.fileName();

if (fileName.startsWith(filterText_))
return true;

if (fileInfo.isDir()) {
return searchDirectory(fileInfo);
}

}

return false;
}

anda_skoa
8th September 2016, 14:57
What do you get and what do you expect to see?

Cheers,
_

NIteLordz
8th September 2016, 15:08
I get Scenes and Textures folder displaying in the ListView, however, i expect/want Level_01.xml to be only displayed in the ListView.

I'm thinking i need to go the seperate model for search results and populate the list view with it when search is enabled.

anda_skoa
8th September 2016, 16:13
Hmm, does it work if your filter does not except the directories?

But yes, I would have always gone for a special purpose model, as suggested in #4
Cheers,
_

NIteLordz
8th September 2016, 21:49
I wound up implementing the custom model, and it works as i expected.

Thanks for the help!