Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Showing specific directories in QFileTreeView
Forum Updated to NodeBB v4.3 + New Features

Showing specific directories in QFileTreeView

Scheduled Pinned Locked Moved Solved General and Desktop
8 Posts 3 Posters 1.3k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    sogo
    wrote on last edited by
    #1

    Re: How to filter folder in treeview
    Hi,
    I was earlier reading this thread on filtering specific directories from QTreeView and one of the solution was to suclass QSortProxyModel's "filterAcceptsRow()" method. My situation is I'm showing on QTreeView my directory using QFileSystemModel which will contain only directories and no files as I'm checking for that. I was looking for a way to filter out certain directories with their name "csvs" and "logs" to not show up on QTreeView. For example here is what my structure looks like
    Capture1.PNG
    Now I looked at sub-classing filterAcceptsRow() method which takes in "int source_row, const QModelIndex &source_parent" as args. I would like to know the logic flow here as I was thinking how I would get the index and row# of that particular directory (csvs/logs) in my model. One way was to get through their filePath using "QModelIndex QFileSystemModel::index(const QString &path, int column = 0) const" but then I will have to detect first whether the "csvs" and "logs"directories are there during input. Just wanted to make sure if this is correct way to go for. Thanks
    @Chris-Kawa This is what you mean't when answering that post as that is an old post and I was wondering if there is any new modification for this feature

    JonBJ 1 Reply Last reply
    0
    • S sogo

      Re: How to filter folder in treeview
      Hi,
      I was earlier reading this thread on filtering specific directories from QTreeView and one of the solution was to suclass QSortProxyModel's "filterAcceptsRow()" method. My situation is I'm showing on QTreeView my directory using QFileSystemModel which will contain only directories and no files as I'm checking for that. I was looking for a way to filter out certain directories with their name "csvs" and "logs" to not show up on QTreeView. For example here is what my structure looks like
      Capture1.PNG
      Now I looked at sub-classing filterAcceptsRow() method which takes in "int source_row, const QModelIndex &source_parent" as args. I would like to know the logic flow here as I was thinking how I would get the index and row# of that particular directory (csvs/logs) in my model. One way was to get through their filePath using "QModelIndex QFileSystemModel::index(const QString &path, int column = 0) const" but then I will have to detect first whether the "csvs" and "logs"directories are there during input. Just wanted to make sure if this is correct way to go for. Thanks
      @Chris-Kawa This is what you mean't when answering that post as that is an old post and I was wondering if there is any new modification for this feature

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #2

      @sogo
      Not sure I understand what you are asking/suggesting here. You will not try to go from directory name to index, which I believe is what you are thinking. Rather, in filterAcceptsRow() you will go from index to directory name, and then return false if that matches one you want to hide.

      1 Reply Last reply
      0
      • S Offline
        S Offline
        sogo
        wrote on last edited by sogo
        #3

        So I tried from what I think I understand, Here is my code. I have TreeView class which has QTreeView widget and I have subclassed a QFileSystemModel class (FileSystem) to highlight the row bolds for row double clicked. This is what my TreeView.cpp looks like for this function. The openFile function is called from my MainWindow.cpp class which sends it the directory path I choose from QFileDialog:
        TreeView.cpp

        void TreeView::openFile(const QString& folderPath)
        
        {
        mySortFilterModel->setSourceModel(myModel);
        myModel->setFilter(QDir::NoDotAndDotDot | QDir::AllDirs);
        myModel->setRootPath(folderPath);
        QModelIndex index = myModel->index(folderPath);
        QDir path(folderPath);
        QString absPathLogs;
        QModelIndex indLogs;
        int rowLog;
        QString absPathCsvs;
        QModelIndex indCsvs;
        int rowCsvs;
        QStringList list = path.entryList(QDir::AllEntries | QDir::NoDotAndDotDot);
        if (list.contains("csvs"))
        {
            absPathCsvs = path.absoluteFilePath("csvs");
            indCsvs = myModel->index(absPathCsvs);
            rowCsvs = indCsvs.row();
            mySortFilterModel->catchIndex(indCsvs);
        }
        if (list.contains("logs"))
        {
            absPathLogs = path.absoluteFilePath("logs");
            indLogs = myModel->index(absPathLogs);
            rowLog = indLogs.row();
            mySortFilterModel->catchIndex(indLogs);
        }
        
        
        ui->treeView->setModel(mySortFilterModel);
        ui->treeView->setRootIndex(mySortFilterModel->mapFromSource(index));
        ui->treeView -> expand(index);
        }
        

        So the index is sent of the directory which is "csvs" or "logs" and to QSortFilterProxyModel subclass mySortFilterModel. which stores it using catchIndex function
        mySortFilterModel.cpp

        bool SortFilterModel::filterAcceptsRow(int sourceRow,
                    const QModelIndex &sourceParent) const
            {
            QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
            if (index.data() == _index.data()) { //Check if index.data() is equal to _index.data(). If equal, don't accept that row
                return false;
            }
            else{
                return QSortFilterProxyModel::filterAcceptsRow(sourceRow,sourceParent);
            }
            }
        void SortFilterModel::catchIndex (const QModelIndex& index)
        {
          _index = index; //Save index coming from TreeView class to QPersistentModelIndex variable
        }
        

        Right now this works but it only change model for one Directory, which ever is called last. In this case "logs" index is called last so it does not show logs directory in treeView. I'm not sure if this is correct way, I'm looking into it now but any suggestions will be helpful.

        @JonB you are right, this is what I'm doing currently

        JonBJ 1 Reply Last reply
        0
        • Chris KawaC Offline
          Chris KawaC Offline
          Chris Kawa
          Lifetime Qt Champion
          wrote on last edited by Chris Kawa
          #4

          @sogo You are doing the filtering on the wrong level. Get rid of the catchIndex method and all that logic on top level and do the filtering in filterAcceptRow with something like

          QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
          QString dir_name= index.data().toString();
          if ( /* dir_name.contains(...) or whatever your rules are */ )
             return false;
          
          1 Reply Last reply
          3
          • S sogo

            So I tried from what I think I understand, Here is my code. I have TreeView class which has QTreeView widget and I have subclassed a QFileSystemModel class (FileSystem) to highlight the row bolds for row double clicked. This is what my TreeView.cpp looks like for this function. The openFile function is called from my MainWindow.cpp class which sends it the directory path I choose from QFileDialog:
            TreeView.cpp

            void TreeView::openFile(const QString& folderPath)
            
            {
            mySortFilterModel->setSourceModel(myModel);
            myModel->setFilter(QDir::NoDotAndDotDot | QDir::AllDirs);
            myModel->setRootPath(folderPath);
            QModelIndex index = myModel->index(folderPath);
            QDir path(folderPath);
            QString absPathLogs;
            QModelIndex indLogs;
            int rowLog;
            QString absPathCsvs;
            QModelIndex indCsvs;
            int rowCsvs;
            QStringList list = path.entryList(QDir::AllEntries | QDir::NoDotAndDotDot);
            if (list.contains("csvs"))
            {
                absPathCsvs = path.absoluteFilePath("csvs");
                indCsvs = myModel->index(absPathCsvs);
                rowCsvs = indCsvs.row();
                mySortFilterModel->catchIndex(indCsvs);
            }
            if (list.contains("logs"))
            {
                absPathLogs = path.absoluteFilePath("logs");
                indLogs = myModel->index(absPathLogs);
                rowLog = indLogs.row();
                mySortFilterModel->catchIndex(indLogs);
            }
            
            
            ui->treeView->setModel(mySortFilterModel);
            ui->treeView->setRootIndex(mySortFilterModel->mapFromSource(index));
            ui->treeView -> expand(index);
            }
            

            So the index is sent of the directory which is "csvs" or "logs" and to QSortFilterProxyModel subclass mySortFilterModel. which stores it using catchIndex function
            mySortFilterModel.cpp

            bool SortFilterModel::filterAcceptsRow(int sourceRow,
                        const QModelIndex &sourceParent) const
                {
                QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
                if (index.data() == _index.data()) { //Check if index.data() is equal to _index.data(). If equal, don't accept that row
                    return false;
                }
                else{
                    return QSortFilterProxyModel::filterAcceptsRow(sourceRow,sourceParent);
                }
                }
            void SortFilterModel::catchIndex (const QModelIndex& index)
            {
              _index = index; //Save index coming from TreeView class to QPersistentModelIndex variable
            }
            

            Right now this works but it only change model for one Directory, which ever is called last. In this case "logs" index is called last so it does not show logs directory in treeView. I'm not sure if this is correct way, I'm looking into it now but any suggestions will be helpful.

            @JonB you are right, this is what I'm doing currently

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by JonB
            #5

            @sogo
            As per @Chris-Kawa's post. the whole idea of going from name to index is quite unnecessary and extremely slow. No need to entryList() to visit the files that are there. As per his, just inside filterAcceptRow() all you have to do is see the name of the file for index, and reject if not wanted. 4 lines of code, one lookup, small & quick :)

            1 Reply Last reply
            1
            • S Offline
              S Offline
              sogo
              wrote on last edited by sogo
              #6

              Hi @Chris-Kawa and @JonB , yea now it works perfectly fine. Got rid of catchIndex() and just checked for data contains in filterAcceptsRow function. I have one issue, I'm unable to get row count from my filtered model. It always returns 0. Here is my code snippet for checking row count in TreeView class:
              TreeView.cpp

              void TreeView::openFile(const QString& folderPath)
              
              {
              mySortFilterModel->setSourceModel(myModel);
              myModel->setFilter(QDir::NoDotAndDotDot | QDir::AllDirs);
              myModel->setRootPath(folderPath);
              QModelIndex index = myModel->index(folderPath);
              ui->treeView->setModel(mySortFilterModel);
              ui->treeView->setRootIndex(mySortFilterModel->mapFromSource(index));
              ui->treeView -> expand(index);
              int rows = myModel->rowCount(index);
              qDebug() << rows;
              }
              

              As per documentation, it says it will return 0 if
              Calls to rowCount() will return 0 until the model populates a directory.
              Shouldn't model would have populated the directory when I call it?

              Update: I see what it means by not completing the populating the directory. I have to use signal directoryLoaded() and slot to wait when the directory is completed loaded. It works now. I have to try few things and will close this thread.

              JonBJ 1 Reply Last reply
              0
              • S sogo

                Hi @Chris-Kawa and @JonB , yea now it works perfectly fine. Got rid of catchIndex() and just checked for data contains in filterAcceptsRow function. I have one issue, I'm unable to get row count from my filtered model. It always returns 0. Here is my code snippet for checking row count in TreeView class:
                TreeView.cpp

                void TreeView::openFile(const QString& folderPath)
                
                {
                mySortFilterModel->setSourceModel(myModel);
                myModel->setFilter(QDir::NoDotAndDotDot | QDir::AllDirs);
                myModel->setRootPath(folderPath);
                QModelIndex index = myModel->index(folderPath);
                ui->treeView->setModel(mySortFilterModel);
                ui->treeView->setRootIndex(mySortFilterModel->mapFromSource(index));
                ui->treeView -> expand(index);
                int rows = myModel->rowCount(index);
                qDebug() << rows;
                }
                

                As per documentation, it says it will return 0 if
                Calls to rowCount() will return 0 until the model populates a directory.
                Shouldn't model would have populated the directory when I call it?

                Update: I see what it means by not completing the populating the directory. I have to use signal directoryLoaded() and slot to wait when the directory is completed loaded. It works now. I have to try few things and will close this thread.

                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by
                #7

                @sogo said in Showing specific directories in QFileTreeView:

                Update: I see what it means by not completing the populating the directory. I have to use signal directoryLoaded() and slot to wait when the directory is completed loaded.

                Yes. In order to be "fast", in keeping with the way Qt tries to offer an asynchronous framework, QFileSystemModel does its directory reading population in the background, I believe, in its own thread. So the population is not complete until it sends you that directoryLoaded signal.

                1 Reply Last reply
                0
                • S Offline
                  S Offline
                  sogo
                  wrote on last edited by
                  #8

                  Closing this thread, thanks @JonB and @Chris-Kawa

                  1 Reply Last reply
                  0

                  • Login

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt Extensions
                  • Unsolved