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. QSortFilterProxyModel, QFileSystemModel and QTreeView browse USB
QtWS25 Last Chance

QSortFilterProxyModel, QFileSystemModel and QTreeView browse USB

Scheduled Pinned Locked Moved Solved General and Desktop
usb qt
8 Posts 2 Posters 1.1k Views
  • 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
    Sandra_Carney
    wrote on 8 May 2020, 18:48 last edited by
    #1

    Re: QTreeview filtering search

    All,
    We are on CentOS 7.6 and using Qt 5.12.0. We are using a QTreeView to browse local filesystems. The model is a QFileSystemModel. In the original code we were using the directoryLoaded and rootPathChanged signals in the QFileSystemModel. In the treeView, we were using setModel to aggregate the QFileSystemModel object(model) into the QTreeView object(tree).

    Now what happens is the user inserts a USB stick and informs our application of it's presence. The USB stick is auto-mounted by an external process and our application knows how to look for USB mounts. We can select from a list of USB sticks found and browse them.

    If the user pulls the USB stick out while it is being browsed, the root desktop is exposed. We don't want that.

    So after reading the Qt docs and posts in here, I got the idea to subclass the QSortFilterProxyModel class and reimplement filterAcceptsRow(). It is pretty simple. I just ask it to filter out anything that is not under the USB mount point. The filter works beautiful.

    Now we are currently using the QFileSystemModel::directoryLoaded() and QFileSystemModel::rootPathChanged() to signal a change.

    My question is do I need to reimplement those signals in my QSortFilterProxyModel subclass to run the directory through the filter and react accordingly? I am setting the sourceModel in my QSortFilterProxyModel object to the QFileSystemModel object so could access the signals through sourceModel()->directoryLoaded(). But that isn't what I should do, correct?

    The other piece is that were extracting a QModelIndexList by calling ui.tree->selectionModel()->selectedRows(). From reading the docs, I believe the selection model is the same as the source model unless we explicitly set the selection model. Is that correct? If that is the case, do I need to reimplement selectedRows() in my proxy class to filter the rows based on my filter?

    Regards,
    Sandra Carney

    1 Reply Last reply
    0
    • S Sandra_Carney
      8 May 2020, 21:42

      OK, I poked through the include files and found where selectedRows() is implemented. I plan to implement selectedRows() in my QSortFilterProxyModel subclass based on your suggestion of mapSelectionFromSource() right?

      J Offline
      J Offline
      JonB
      wrote on 8 May 2020, 22:01 last edited by
      #6

      @Sandra_Carney
      I'm tired, but I don't think there's anything for you to implement, These are methods for you to call. The selection model is not the same thing as the source model. It is a model for the selections the user has made. These are against the proxy model. QSortFilterProxyModel::mapSelectionToSource() maps from a proxy model selection through to the corresponding source model selection. Which resolves the crash you reported.

      1 Reply Last reply
      0
      • S Offline
        S Offline
        Sandra_Carney
        wrote on 8 May 2020, 20:28 last edited by
        #2

        I think I figured out how to hook the signals and slots up correctly. Now when I generate QModelIndexList(list) by calling ui.tree->selectionModel()->selectedRows() and try to access the list, my application crashes. I think I have to get the rows from the QSortFilterProxyModel object. That is where I am stuck.

        I also called QSortFilterProxyModel::rowCount() via my object. It always returns 0 which is surprising.

        J 1 Reply Last reply 8 May 2020, 20:55
        0
        • S Sandra_Carney
          8 May 2020, 20:28

          I think I figured out how to hook the signals and slots up correctly. Now when I generate QModelIndexList(list) by calling ui.tree->selectionModel()->selectedRows() and try to access the list, my application crashes. I think I have to get the rows from the QSortFilterProxyModel object. That is where I am stuck.

          I also called QSortFilterProxyModel::rowCount() via my object. It always returns 0 which is surprising.

          J Offline
          J Offline
          JonB
          wrote on 8 May 2020, 20:55 last edited by JonB 5 Aug 2020, 20:58
          #3

          @Sandra_Carney

          ui.tree->selectionModel()->selectedRows() and try to access the list, my application crashes
          I think I have to get the rows from the QSortFilterProxyModel object

          See https://doc.qt.io/qt-5/qsortfilterproxymodel.html#mapSelectionToSource (& https://doc.qt.io/qt-5/qsortfilterproxymodel.html#mapSelectionFromSource).

          I don't know why your QSortFilterProxyModel::rowCount() is 0.

          S 1 Reply Last reply 8 May 2020, 21:31
          0
          • J JonB
            8 May 2020, 20:55

            @Sandra_Carney

            ui.tree->selectionModel()->selectedRows() and try to access the list, my application crashes
            I think I have to get the rows from the QSortFilterProxyModel object

            See https://doc.qt.io/qt-5/qsortfilterproxymodel.html#mapSelectionToSource (& https://doc.qt.io/qt-5/qsortfilterproxymodel.html#mapSelectionFromSource).

            I don't know why your QSortFilterProxyModel::rowCount() is 0.

            S Offline
            S Offline
            Sandra_Carney
            wrote on 8 May 2020, 21:31 last edited by
            #4

            @JonB My first question is which class implements selectedRows()? I don't see it in QFileSystemModel() and besides the code is calling ui.tree->selectionModel()->selectedRows(). What is the selection model? Is it the same as the sourceModel() if it is not explictly set or is it some other default?

            1 Reply Last reply
            0
            • S Offline
              S Offline
              Sandra_Carney
              wrote on 8 May 2020, 21:42 last edited by
              #5

              OK, I poked through the include files and found where selectedRows() is implemented. I plan to implement selectedRows() in my QSortFilterProxyModel subclass based on your suggestion of mapSelectionFromSource() right?

              J 1 Reply Last reply 8 May 2020, 22:01
              0
              • S Sandra_Carney
                8 May 2020, 21:42

                OK, I poked through the include files and found where selectedRows() is implemented. I plan to implement selectedRows() in my QSortFilterProxyModel subclass based on your suggestion of mapSelectionFromSource() right?

                J Offline
                J Offline
                JonB
                wrote on 8 May 2020, 22:01 last edited by
                #6

                @Sandra_Carney
                I'm tired, but I don't think there's anything for you to implement, These are methods for you to call. The selection model is not the same thing as the source model. It is a model for the selections the user has made. These are against the proxy model. QSortFilterProxyModel::mapSelectionToSource() maps from a proxy model selection through to the corresponding source model selection. Which resolves the crash you reported.

                1 Reply Last reply
                0
                • S Offline
                  S Offline
                  Sandra_Carney
                  wrote on 8 May 2020, 23:28 last edited by
                  #7

                  @JonB Thankyou, very, very much. You gave me enough to figure it out. For folks' benefit:

                      MyProxy* pm= qobject_cast<MyProx*>(ui.tree->model());
                      QFileSystemModel* fm = (QFileSystemModel*)pm->sourceModel();
                      QItemSelectionModel *select = ui.tree->selectionModel();
                      QModelIndexList l = select->selectedRows();
                  
                      if( list.count() )
                      {
                          path = fm->filePath(pm->mapToSource(l[0]));
                          emit pathSelectionChanged(path);
                      }
                  
                  J 1 Reply Last reply 9 May 2020, 07:08
                  0
                  • S Sandra_Carney
                    8 May 2020, 23:28

                    @JonB Thankyou, very, very much. You gave me enough to figure it out. For folks' benefit:

                        MyProxy* pm= qobject_cast<MyProx*>(ui.tree->model());
                        QFileSystemModel* fm = (QFileSystemModel*)pm->sourceModel();
                        QItemSelectionModel *select = ui.tree->selectionModel();
                        QModelIndexList l = select->selectedRows();
                    
                        if( list.count() )
                        {
                            path = fm->filePath(pm->mapToSource(l[0]));
                            emit pathSelectionChanged(path);
                        }
                    
                    J Offline
                    J Offline
                    JonB
                    wrote on 9 May 2020, 07:08 last edited by JonB 5 Sept 2020, 07:18
                    #8

                    @Sandra_Carney

                        QItemSelectionModel *select = ui.tree->selectionModel();
                        QModelIndexList l = select->selectedRows();
                        ...
                            pm->mapToSource(l[...])
                    

                    This is fine. You are working through selectionModel()->selectedRows() calling QProxyModel::mapToSource() on an item to get from a proxy QModelIndex to the source QModelIndex.

                    I believe QSortFilterProxyModel::mapSelectionToSource() is just a convenience to save the two steps. E.g.

                    QItemSelectionModel *select = ui.tree->selectionModel();
                    QModelIndexList sourceIndexList = pm->mapSelectionToSource(select->selection())->indexes();
                    

                    Whether it's just a shortcut convenience or it's more efficient I don't know. The important thing either way is that you have to do this index mapping source model <--> proxy model indexes.

                    1 Reply Last reply
                    0

                    5/8

                    8 May 2020, 21:42

                    • Login

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