PDA

View Full Version : QFileSystemModel with QTreeView Questions



MJ9797
8th June 2016, 16:48
I'm new to Qt and I'm trying a to create file system tree showing folders only, but I'm failing miserably. I've got three questions I was hoping for some help with:

1) How do you check if a directory has been loaded by the model? There's the directoryLoaded() signal, which tells you when a directory has finished loading, but I can't find a function to check at a random point if a directory has been loaded. One option would be to check if the rowCount() is 0, but a rowCount() of 0 could also mean the directory has no subfolders so you wouldn't be sure if it was loaded or not. The only other option is to save a list of loaded directories, but that would be very inefficient. Is there a better option?

2) How do you get the list of children of the root node? For other nodes I use:

QModelIndexList children;
int numChildRows = fileSystem->rowCount(modelIndex);
for (int i = 0 ; i < numChildRows ; ++i)
fileSystem->fetchMore(modelIndex.child(i, 0));
This won't work for the root note because the root modelIndex is invalid, so I'm not sure how to iterate through the root's children.

3) The third problem is that the QTreeView shows expansion marks next to folders that have no subfolders and I only want it to have expansion marks next to folders that can be expanded. One solution is to subclass QFileSystemModel and override hasChildren() so that it only returns true if the folder has subfolders. This works, but makes it incredibly slow to expand a branch with a lot of folders in (as much as 15 seconds) so that's not viable. Another solution I've seen suggested is to call fetchMore() more on all subfolders in the expanded directory, but when I tried this the QTreeView doesn't update to remove the expansion marks. Here's my code:

Constructor:

fileSystem = new QFileSystemModel(parent);
fileSystem->setReadOnly(false);
fileSystem->setRootPath(m_pqfsmFolderSystem->myComputer().toString());
fileSystem->setFilter(QDir::Dirs | QDir::NoDotAndDotDot);

directoryTree = new QTreeView(parent);
directoryTree->setModel(fileSystem);
directoryTree->setEditTriggers(QTreeView::NoEditTriggers);
directoryTree->hideColumn(1);
directoryTree->hideColumn(2);
directoryTree->hideColumn(3);
directoryTree->header()->hide();

connect(directoryTree, SIGNAL(expanded(const QModelIndex &)), this, SLOT(nodeExpanded(const QModelIndex &)));
connect(fileSystem, SIGNAL(directoryLoaded(const QString &)), this, SLOT(directoryLoaded(const QString &)));

Relevant functions

void FileTree::nodeExpanded(const QModelIndex & modelIndex)
{
// Need to find out how to check if directory is already loaded
//if (directory loaded)
// fetchChildren(modelIndex);
//else
directoriesToFetch.push_back(krqmiModelIndex);
}

void FileTree::directoryLoaded(const QString & path)
{
if (directoriesToFetch.empty())
return;

QVector<QModelIndex>::iterator directoryIndex;
for (directoryIndex = directoriesToFetch.begin() ; directoryIndex != directoriesToFetch.end() ; ++directoryIndex)
{
if (path == fileSystem->filePath(*directoryIndex))
{
fetchChildren(*directoryIndex);
directoriesToFetch.erase(directoryIndex);
break;
}
}
}

void FileTree::fetchChildren(const QModelIndex & modelIndex)
{
int numChildren = fileSystem->rowCount(modelIndex);
for (int i = 0 ; i < numChildren ; ++i)
fileSystem->fetchMore(krqmiModelIndex.child(i, 0));
}

I've debugged through and fetchMore() is being called for all the sub-folders, but the QTreeView isn't being updated to remove the expansion symbols for directories with no subfolders. Is there something else I need to do?

Sorry for all the questions. I can't seem to get anything to work. I think I'm just stupid :)

anda_skoa
8th June 2016, 19:17
2) How do you get the list of children of the root node? For other nodes I use:

To get indexes of children of any node you just pass the index of that node as the third argument to the model's index() method


const int numChildren = model->rowCount(index);
for (int i = 0; i < numChildren; ++i) {
const QModelIndex child = model->index(i, 0, index);
}


Cheers,
_