Qt World Summit: Submit your Presentation

QTreeView shows all the subfolders, but not the parent folder.

  • I'm trying to get QTreeView (using an underlying QFileSystemModel) to show a directory tree. If I set the RootPath to the parent directory, then I see all the children, but not the parent.

    I want to see parent folder and all it's subfolders.


    QString dir = QFileDialog::getExistingDirectory(this, tr("Open Directory"), "/home", QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
    viewtree=new QTreeView; 
    dir1=new QFileSystemModel(this); 
    dir1->setFilter(QDir::NoDotAndDotDot |QDir::AllDirs); 

    I want to show Parent folder along with it's subfolders in QTreeView.
    Any Suggestions?

  • I had the same problem and I resolved it using a QSortFilterProxyModel on the FileSystemModel, filtering just the folder that will be the root of the treeView.
    Anyway I used the same proxy model to do something else.

  • @giupigna @Lifetime-Qt-Champion @Moderators @Qt-Champions-2015

    I have a folder structure like this.


    I am trying to show a folder "test2" and all it's subfolders. I am a newbiew so don't know much about QSortFilterProxyModel. First of all if I select "test2" when prompt to select folder, my treeview only shows subfolders i.e. "First" and "Second". So I am using QDir::cdUp() function to set Desktop as my root folder. Now my treeview show all folders present inside "Desktop" including "test2". But, I want to show "test2" and all it's subfolders only.

    I have created my own proxy model to do so, but it's not working. Please help!



    class MyProxy : public QSortFilterProxyModel
        bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;


    #include "myproxy.h"
    bool MyProxy::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
        QModelIndex node= sourceModel()->index(source_row, 0, source_parent);
        QString foldername= sourceModel()->data(node, Qt::DisplayRole).toString();
        if(QString::compare(foldername ,"test2")==0)
              return true;
             return false;


    #include "myproxy.h"
      button=new QPushButton;
        dir=new QFileSystemModel;
        messagesTableWidget=new QTreeView;
        model=new MyProxy;    
    void MainWindow::work()
        QString folderpath = QFileDialog::getExistingDirectory(this, tr("Open Directory"),
                                                      | QFileDialog::DontResolveSymlinks);
    QDir* direct = new QDir(folderpath);
    dir->setFilter(QDir::NoDotAndDotDot |QDir::AllDirs);


  • Moderators

    try something like this:

    bool MyProxy::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
        QFileSystemModel* model = qobject_cast<QFileSystemModel*>( sourceModel );
        QModelIndex index = model->index(source_row, 0, source_parent);
        QModelIndex rootIndex = model->index( rootPath );   // create some getter/setter methods for the "rootPath" (QString)
        Q_ASSERT( rootIndex.isValid() );
        if( !rootIndex.isValid() )
             return false;
        return (index.isValid() && index == rootIndex) || this->isChildIndexOf(index, rootIndex);
    bool MyProxy::isChildIndexOf( const QModelIndex & child, const QModelIndex & parent )
         if( !child.isValid() )
             return false;
         QModelIndex idx = parent;
         do {
              if( child.parent() == idx )
                    return true;
              idx = idx.parent();
              if( child.parent() == idx )  // in case parent is already invalid we need to check here again
                    return true;
         while( idx.isValid() );
         return false;

    written straight from my head and thus untested.

  • I did it in the following way:

    bool PatternTreeFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
        QFileSystemModel *model = qobject_cast<QFileSystemModel*>(sourceModel());
        QDir pathDir(m_path); // path of the root folder
        QModelIndex idx = source_parent.child(source_row, 0);
        QDir sourceFilePath(model->filePath(idx) + QDir::separator() + "test2");
        QString sourceAbsFilePath = sourceFilePath.absolutePath();
        QString pathDirAbsFilePath = pathDir.absolutePath();
        if (sourceAbsFilePath.startsWith(pathDirAbsFilePath))
            if (model->isDir(idx))
                return true;
        return false;

    In my case I show only the folders in the treeView. Looking at the raven 's code it's better and more faster than mine, but I don't know if it works.

    Anyway my advise it: debug, debug, debug a lot how I did.

  • Thanks a lot. :) @raven-worx @giupigna. Problem solved.

  • I had issues making these solutions work for the QML TreeView. I ended up setting the root path of my QFileSystemModel to the directory I wanted to view. Then I set the rootIndex in the TreeView to the parent of the index for that directory. This is of course showed its siblings. Then I did the following to filter those siblings away. I also made this optional through a property as there are times when I want that behavior:

            bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
                FileSystemModel* tmodel = qobject_cast<FileSystemModel*>(parent());
                    QModelIndex index = tmodel->index(source_row, 0, source_parent);
                    QModelIndex rootIndex = tmodel->index(tmodel->rootPath());
                    if(!rootIndex.isValid() || !index.isValid())
                         return false;
                    return ((index == rootIndex) || !(tmodel->filtersiblings() && isSiblingOf(index, rootIndex)));
                return false;
            bool isSiblingOf(const QModelIndex& index, const QModelIndex& parent) const
                if(!index.isValid() || !parent.isValid())
                    return false;
                QModelIndex sibling;
                int row=0;
                    sibling = parent.sibling(row,0);
                    if(sibling == index)
                        return true;
                return false;

    I took more of a blacklist approach versus a whitelist approach.