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. QFileSystemModel with filter QDir::Files shows not only files, but also opened subfolders
Forum Updated to NodeBB v4.3 + New Features

QFileSystemModel with filter QDir::Files shows not only files, but also opened subfolders

Scheduled Pinned Locked Moved Unsolved General and Desktop
12 Posts 5 Posters 4.8k Views 2 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.
  • M Offline
    M Offline
    Maxxii
    wrote on last edited by Maxxii
    #1

    Hello. I'm new with Qt and I'm following video tutorial about QFileSystemModel. So, I'm making file explorer with two views - one is displaying only folders (with treeView), the other one shows only files from the folder, selected in first view.
    Everything works fine, but if I choose folder with subfolder, click on subfolder, and then click on parent folder - it will show previously selected subfolder in the list, that is supposed to show files only. Not sure if it's bug or I did something wrong.
    BTW, I am on Mac, but somebody already asked about same problem in comments (without answer), not sure about his OS.
    Here is the code:
    Dialog.h

    class Dialog : public QDialog
    {
        Q_OBJECT
    
    public:
        explicit Dialog(QWidget *parent = 0);
        ~Dialog();
    
    private slots:
        void on_treeView_clicked(const QModelIndex &index);
    
    private:
        Ui::Dialog *ui;
        QFileSystemModel *dirmodel;
        QFileSystemModel *filemodel;
    };
    

    Dialog.cpp

    Dialog::Dialog(QWidget *parent) :
        QDialog(parent),
        ui(new Ui::Dialog)
    {
        ui->setupUi(this);
    
        QString sPath = "/users/Max/";
    
        dirmodel = new QFileSystemModel(this);
        dirmodel->setFilter(QDir::NoDotAndDotDot | QDir::AllDirs);
        dirmodel->setRootPath(sPath);
        ui->treeView->setModel(dirmodel);
        QModelIndex index = dirmodel->index(sPath, 0); 
        ui->treeView->setRootIndex(index);
    
        filemodel = new QFileSystemModel(this);
        filemodel->setFilter(QDir::NoDotAndDotDot | QDir::Files);
        filemodel->setRootPath(sPath);
        ui->listView->setModel(filemodel);
        index = filemodel->index(sPath, 0); 
        ui->listView->setRootIndex(index); 
    
    }
    
    Dialog::~Dialog()
    {
        delete ui;
    }
    
    void Dialog::on_treeView_clicked(const QModelIndex &index)
    {
        QString sPath = dirmodel->fileInfo(index).absoluteFilePath(); 
        ui->listView->setRootIndex(filemodel->setRootPath(sPath)); 
    
    }
    
    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi and welcome to devnet,

      What version of Qt are you using ?
      On what version of macOS ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • M Offline
        M Offline
        Maxxii
        wrote on last edited by Maxxii
        #3

        Hello. I'm using Mac OS 10.13.1 and version of Qt is 5.9.2
        I also just tested it on Windows 10 x64 (with Qt 5.9.2) and it has the same issue.

        alt text

        JonBJ 1 Reply Last reply
        0
        • M Maxxii

          Hello. I'm using Mac OS 10.13.1 and version of Qt is 5.9.2
          I also just tested it on Windows 10 x64 (with Qt 5.9.2) and it has the same issue.

          alt text

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

          @Maxxii

              QString sPath = dirmodel->fileInfo(index).absoluteFilePath(); 
              ui->listView->setRootIndex(filemodel->setRootPath(sPath));
          

          I don't actually see where http://doc.qt.io/qt-5/qfilesystemmodel.html#setRootPath states what the QModelIndex it returns is. Did you take this code from somewhere?**

          ** EDIT: Hmm, I see it at http://www.bogotobogo.com/Qt/Qt5_QTreeView_QFileSystemModel_ModelView_MVC.php. And someone said on your youtube that it has same problem. Perhaps an expert can say there is a problem in that code?

          1 Reply Last reply
          0
          • SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #5

            @Maxxii Can you also provide the .ui file for your example ?

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            1 Reply Last reply
            0
            • M Offline
              M Offline
              Maxxii
              wrote on last edited by
              #6

              Sure. But there is nothing more than 1 treeView and 1 listView.

              <?xml version="1.0" encoding="UTF-8"?>
              <ui version="4.0">
               <class>Dialog</class>
               <widget class="QDialog" name="Dialog">
                <property name="geometry">
                 <rect>
                  <x>0</x>
                  <y>0</y>
                  <width>597</width>
                  <height>303</height>
                 </rect>
                </property>
                <property name="windowTitle">
                 <string>Dialog</string>
                </property>
                <layout class="QHBoxLayout" name="horizontalLayout">
                 <item>
                  <widget class="QTreeView" name="treeView"/>
                 </item>
                 <item>
                  <widget class="QListView" name="listView"/>
                 </item>
                </layout>
               </widget>
               <layoutdefault spacing="6" margin="11"/>
               <resources/>
               <connections/>
              </ui>
              
              JonBJ 1 Reply Last reply
              0
              • SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on last edited by
                #7

                Even if simple, it avoids people trying to help you to have to rewrite it and guess what's in it and thus lose time to re-create a functional application.

                So there might be bug here with QFileSystemModel. I'd recommend taking a look at the bug report system to see if it's something known. If not please consider opening a new report providing the complete code sample.

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                M 1 Reply Last reply
                0
                • M Maxxii

                  Sure. But there is nothing more than 1 treeView and 1 listView.

                  <?xml version="1.0" encoding="UTF-8"?>
                  <ui version="4.0">
                   <class>Dialog</class>
                   <widget class="QDialog" name="Dialog">
                    <property name="geometry">
                     <rect>
                      <x>0</x>
                      <y>0</y>
                      <width>597</width>
                      <height>303</height>
                     </rect>
                    </property>
                    <property name="windowTitle">
                     <string>Dialog</string>
                    </property>
                    <layout class="QHBoxLayout" name="horizontalLayout">
                     <item>
                      <widget class="QTreeView" name="treeView"/>
                     </item>
                     <item>
                      <widget class="QListView" name="listView"/>
                     </item>
                    </layout>
                   </widget>
                   <layoutdefault spacing="6" margin="11"/>
                   <resources/>
                   <connections/>
                  </ui>
                  
                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by JonB
                  #8

                  @Maxxii
                  If this does indeed turn out to be a bug, as @SGaist suggests, and is something to do with changing the root path not quite respecting the filter and showing sub-driectories under some circumstances, to work around for now try something like refreshing or even recreating the filemodel in your on_treeView_clicked(), till it's fixed.

                  1 Reply Last reply
                  0
                  • SGaistS SGaist

                    Even if simple, it avoids people trying to help you to have to rewrite it and guess what's in it and thus lose time to re-create a functional application.

                    So there might be bug here with QFileSystemModel. I'd recommend taking a look at the bug report system to see if it's something known. If not please consider opening a new report providing the complete code sample.

                    M Offline
                    M Offline
                    Maxxii
                    wrote on last edited by Maxxii
                    #9

                    @SGaist
                    Ok. I thought I have to paste minimum amount code on forum, so thank you for clarification.
                    I wanted to report this as bug, but decided to post it here first, just to be sure it's not about my misunderstanding.

                    @JNBarchan
                    Ok, I will try this, thank you.

                    1 Reply Last reply
                    0
                    • VRoninV Offline
                      VRoninV Offline
                      VRonin
                      wrote on last edited by
                      #10

                      Don't use 2 separate models, use a single model and a few proxys operating on it to manipulate filtering and setting the roots.

                      Here is a working example:

                      CMakeLists.txt

                      cmake_minimum_required(VERSION 3.14)
                      
                      project(MyApp LANGUAGES CXX)
                      include(FetchContent)
                      FetchContent_Declare(QtModelUtilitiesFC
                          GIT_REPOSITORY https://github.com/VSRonin/QtModelUtilities.git
                          GIT_TAG master
                      )
                      FetchContent_MakeAvailable(QtModelUtilitiesFC)
                      find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
                      find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Gui Widgets REQUIRED)
                      
                      add_executable(MyApp
                        main.cpp
                      )
                      target_include_directories(MyApp PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
                      target_link_libraries(MyApp PUBLIC
                          Qt${QT_VERSION_MAJOR}::Core
                          Qt${QT_VERSION_MAJOR}::Gui
                          Qt${QT_VERSION_MAJOR}::Widgets
                          QtModelUtilities::QtModelUtilities
                      )
                      set_target_properties(MyApp PROPERTIES
                          AUTOMOC ON
                          AUTOUIC ON
                          AUTORCC ON
                          CXX_STANDARD 11
                          CXX_STANDARD_REQUIRED ON
                      )
                      

                      main.cpp

                      #include <QApplication>
                      #include <QSortFilterProxyModel>
                      #include <QListView>
                      #include <QTreeView>
                      #include <QDialog>
                      #include <QHBoxLayout>
                      #include <QFileSystemModel>
                      #include <RootIndexProxyModel>
                      
                      class FileDirFilterProxy : public QSortFilterProxyModel{
                      public:
                          explicit FileDirFilterProxy(bool filterDirs, QObject* parent=nullptr)
                              :QSortFilterProxyModel(parent)
                              ,m_filterDirs(filterDirs)
                          {}
                      protected:
                          bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override{
                              const QFileSystemModel* fileModel = qobject_cast<const QFileSystemModel*>(sourceModel());
                              const QAbstractProxyModel* proxy = qobject_cast<const QAbstractProxyModel*>(sourceModel());
                              while(!fileModel){
                                  if(!proxy)
                                      return QSortFilterProxyModel::filterAcceptsRow(source_row,source_parent);
                                  fileModel = qobject_cast<const QFileSystemModel*>(proxy->sourceModel());
                                  proxy = qobject_cast<const QAbstractProxyModel*>(proxy->sourceModel());
                              }
                              return m_filterDirs == fileModel->isDir(sourceModel()->index(source_row,0,source_parent));
                          }
                      private:
                          const bool m_filterDirs;
                      };
                      
                      class Dialog : public QDialog
                      {
                      public:
                          explicit Dialog(QWidget *parent = 0);
                          ~Dialog() = default;
                      
                      private slots:
                          void onTreeViewClicked(const QModelIndex &index);
                      
                      private:
                          QFileSystemModel *dirmodel;
                          FileDirFilterProxy* dirProxy;
                          FileDirFilterProxy* fileProxy;
                          RootIndexProxyModel* fileRootProxy;
                          QListView* listView;
                          QTreeView* treeView;
                      };
                      
                      Dialog::Dialog(QWidget *parent) :
                          QDialog(parent)
                      {
                          treeView = new QTreeView(this);
                          listView = new QListView(this);
                          auto dialogLay=new QHBoxLayout(this);
                          dialogLay->addWidget(treeView);
                          dialogLay->addWidget(listView);
                      
                          dirmodel = new QFileSystemModel(this);
                          dirmodel->setRootPath("C:/Temp");
                      
                          dirProxy = new FileDirFilterProxy(true,this);
                          dirProxy->setSourceModel(dirmodel);
                          treeView->setModel(dirProxy);
                      
                          fileRootProxy=new RootIndexProxyModel(this);
                          fileRootProxy->setSourceModel(dirmodel);
                          fileProxy = new FileDirFilterProxy(false,this);
                          fileProxy->setSourceModel(fileRootProxy);
                          listView->setModel(fileProxy);
                      
                          connect(treeView,&QTreeView::clicked,this,&Dialog::onTreeViewClicked);
                      }
                      
                      void Dialog::onTreeViewClicked(const QModelIndex &index)
                      {
                          fileRootProxy->setRootIndex(dirProxy->mapToSource(index));
                      }
                      
                      int main(int argc, char *argv[])
                      {
                          QApplication app(argc,argv);
                          Dialog wid;
                          wid.show();
                          return app.exec();
                      }
                      

                      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                      ~Napoleon Bonaparte

                      On a crusade to banish setIndexWidget() from the holy land of Qt

                      I 1 Reply Last reply
                      1
                      • VRoninV VRonin

                        Don't use 2 separate models, use a single model and a few proxys operating on it to manipulate filtering and setting the roots.

                        Here is a working example:

                        CMakeLists.txt

                        cmake_minimum_required(VERSION 3.14)
                        
                        project(MyApp LANGUAGES CXX)
                        include(FetchContent)
                        FetchContent_Declare(QtModelUtilitiesFC
                            GIT_REPOSITORY https://github.com/VSRonin/QtModelUtilities.git
                            GIT_TAG master
                        )
                        FetchContent_MakeAvailable(QtModelUtilitiesFC)
                        find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
                        find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Gui Widgets REQUIRED)
                        
                        add_executable(MyApp
                          main.cpp
                        )
                        target_include_directories(MyApp PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
                        target_link_libraries(MyApp PUBLIC
                            Qt${QT_VERSION_MAJOR}::Core
                            Qt${QT_VERSION_MAJOR}::Gui
                            Qt${QT_VERSION_MAJOR}::Widgets
                            QtModelUtilities::QtModelUtilities
                        )
                        set_target_properties(MyApp PROPERTIES
                            AUTOMOC ON
                            AUTOUIC ON
                            AUTORCC ON
                            CXX_STANDARD 11
                            CXX_STANDARD_REQUIRED ON
                        )
                        

                        main.cpp

                        #include <QApplication>
                        #include <QSortFilterProxyModel>
                        #include <QListView>
                        #include <QTreeView>
                        #include <QDialog>
                        #include <QHBoxLayout>
                        #include <QFileSystemModel>
                        #include <RootIndexProxyModel>
                        
                        class FileDirFilterProxy : public QSortFilterProxyModel{
                        public:
                            explicit FileDirFilterProxy(bool filterDirs, QObject* parent=nullptr)
                                :QSortFilterProxyModel(parent)
                                ,m_filterDirs(filterDirs)
                            {}
                        protected:
                            bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override{
                                const QFileSystemModel* fileModel = qobject_cast<const QFileSystemModel*>(sourceModel());
                                const QAbstractProxyModel* proxy = qobject_cast<const QAbstractProxyModel*>(sourceModel());
                                while(!fileModel){
                                    if(!proxy)
                                        return QSortFilterProxyModel::filterAcceptsRow(source_row,source_parent);
                                    fileModel = qobject_cast<const QFileSystemModel*>(proxy->sourceModel());
                                    proxy = qobject_cast<const QAbstractProxyModel*>(proxy->sourceModel());
                                }
                                return m_filterDirs == fileModel->isDir(sourceModel()->index(source_row,0,source_parent));
                            }
                        private:
                            const bool m_filterDirs;
                        };
                        
                        class Dialog : public QDialog
                        {
                        public:
                            explicit Dialog(QWidget *parent = 0);
                            ~Dialog() = default;
                        
                        private slots:
                            void onTreeViewClicked(const QModelIndex &index);
                        
                        private:
                            QFileSystemModel *dirmodel;
                            FileDirFilterProxy* dirProxy;
                            FileDirFilterProxy* fileProxy;
                            RootIndexProxyModel* fileRootProxy;
                            QListView* listView;
                            QTreeView* treeView;
                        };
                        
                        Dialog::Dialog(QWidget *parent) :
                            QDialog(parent)
                        {
                            treeView = new QTreeView(this);
                            listView = new QListView(this);
                            auto dialogLay=new QHBoxLayout(this);
                            dialogLay->addWidget(treeView);
                            dialogLay->addWidget(listView);
                        
                            dirmodel = new QFileSystemModel(this);
                            dirmodel->setRootPath("C:/Temp");
                        
                            dirProxy = new FileDirFilterProxy(true,this);
                            dirProxy->setSourceModel(dirmodel);
                            treeView->setModel(dirProxy);
                        
                            fileRootProxy=new RootIndexProxyModel(this);
                            fileRootProxy->setSourceModel(dirmodel);
                            fileProxy = new FileDirFilterProxy(false,this);
                            fileProxy->setSourceModel(fileRootProxy);
                            listView->setModel(fileProxy);
                        
                            connect(treeView,&QTreeView::clicked,this,&Dialog::onTreeViewClicked);
                        }
                        
                        void Dialog::onTreeViewClicked(const QModelIndex &index)
                        {
                            fileRootProxy->setRootIndex(dirProxy->mapToSource(index));
                        }
                        
                        int main(int argc, char *argv[])
                        {
                            QApplication app(argc,argv);
                            Dialog wid;
                            wid.show();
                            return app.exec();
                        }
                        
                        I Offline
                        I Offline
                        IknowQT
                        wrote on last edited by
                        #11

                        @VRonin

                        What is the content of RootIndexProxyModel?
                        Can you disclose the RootIndexProxyModel code?

                        VRoninV 1 Reply Last reply
                        0
                        • I IknowQT

                          @VRonin

                          What is the content of RootIndexProxyModel?
                          Can you disclose the RootIndexProxyModel code?

                          VRoninV Offline
                          VRoninV Offline
                          VRonin
                          wrote on last edited by
                          #12

                          @IknowQT Sure, as you can see from the CMakeLists.txt it's an open source library: https://github.com/VSRonin/QtModelUtilities
                          At the time of writing it's:

                          header

                          #ifndef ROOTINDEXPROXY_H
                          #define ROOTINDEXPROXY_H
                          #include <QIdentityProxyModel>
                          class RootIndexProxyModelPrivate;
                          class RootIndexProxyModel : public QIdentityProxyModel
                          {
                              Q_OBJECT
                              Q_PROPERTY(QModelIndex rootIndex READ rootIndex WRITE setRootIndex NOTIFY rootIndexChanged)
                              Q_DISABLE_COPY(RootIndexProxyModel)
                              Q_DECLARE_PRIVATE_D(m_dptr, RootIndexProxyModel)
                          public:
                              explicit RootIndexProxyModel(QObject *parent = Q_NULLPTR);
                              ~RootIndexProxyModel();
                              QModelIndex rootIndex() const;
                              void setRootIndex(const QModelIndex &root);
                              QModelIndex mapToSource(const QModelIndex &proxyIndex) const override;
                              QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override;
                              void setSourceModel(QAbstractItemModel *sourceModel) override;
                              QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
                              int rowCount(const QModelIndex &parent = QModelIndex()) const override;
                              int columnCount(const QModelIndex &parent = QModelIndex()) const override;
                              bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
                              bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
                              bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override;
                              bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override;
                              bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
                              bool hasChildren(const QModelIndex &parent) const override;
                              bool canFetchMore(const QModelIndex &parent) const override;
                              void fetchMore(const QModelIndex &parent) override;
                              bool moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count, const QModelIndex &destinationParent,
                                               int destinationChild) override;
                              bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) override;
                          Q_SIGNALS:
                              void rootIndexChanged();
                          
                          protected:
                              RootIndexProxyModel(RootIndexProxyModelPrivate &dptr, QObject *parent);
                              RootIndexProxyModelPrivate *m_dptr;
                          };
                          #endif // ROOTINDEXPROXY_H
                          

                          source

                          #include "rootindexproxymodel.h"
                          #include <functional>
                          #include <QSize>
                          class RootIndexProxyModelPrivate
                          {
                              Q_DECLARE_PUBLIC(RootIndexProxyModel)
                              Q_DISABLE_COPY(RootIndexProxyModelPrivate)
                              RootIndexProxyModelPrivate(RootIndexProxyModel *q);
                              QVector<QMetaObject::Connection> m_sourceConnections;
                              QPersistentModelIndex m_rootIndex;
                              RootIndexProxyModel *q_ptr;
                              bool m_rootRowDeleted;
                              bool m_rootColumnDeleted;
                              QList<QPersistentModelIndex> layoutChangePersistentIndexes;
                              QModelIndexList proxyIndexes;
                              bool isDescendant(QModelIndex childIdx, const QModelIndex &parentIdx) const;
                              void resetRootOnModelChange();
                              void checkRootRowRemoved(const QModelIndex &parent, int first, int last);
                              void checkRootColumnsRemoved(const QModelIndex &parent, int first, int last);
                              void onRowsAboutToBeInserted(const QModelIndex &parent, int first, int last);
                              void onRowsInserted(const QModelIndex &parent, int first, int last);
                              void onRowsAboutToBeRemoved(const QModelIndex &parent, int first, int last);
                              void onRowsRemoved(const QModelIndex &parent, int first, int last);
                              void onRowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest);
                              void onRowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest);
                              void onColumnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest);
                              void onColumnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest);
                              void onColumnsAboutToBeInserted(const QModelIndex &parent, int first, int last);
                              void onColumnsInserted(const QModelIndex &parent, int first, int last);
                              void onColumnsAboutToBeRemoved(const QModelIndex &parent, int first, int last);
                              void onColumnsRemoved(const QModelIndex &parent, int first, int last);
                              void onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles);
                              void onLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint);
                              void onLayoutChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint);
                          };
                          
                          RootIndexProxyModelPrivate::RootIndexProxyModelPrivate(RootIndexProxyModel *q)
                              : q_ptr(q)
                              , m_rootRowDeleted(false)
                              , m_rootColumnDeleted(false)
                          {
                              Q_ASSERT(q_ptr);
                              QObject::connect(q, &RootIndexProxyModel::sourceModelChanged, std::bind(&RootIndexProxyModelPrivate::resetRootOnModelChange, this));
                          }
                          
                          bool RootIndexProxyModelPrivate::isDescendant(QModelIndex childIdx, const QModelIndex &parentIdx) const
                          {
                              Q_ASSERT(childIdx.isValid());
                              if (!parentIdx.isValid())
                                  return true;
                              Q_ASSERT(childIdx.model() == parentIdx.model());
                              for (childIdx = childIdx.parent(); childIdx.isValid(); childIdx = childIdx.parent()) {
                                  if (childIdx == parentIdx)
                                      return true;
                              }
                              return false;
                          }
                          
                          void RootIndexProxyModelPrivate::resetRootOnModelChange()
                          {
                              m_rootIndex = QModelIndex();
                          }
                          
                          void RootIndexProxyModelPrivate::checkRootRowRemoved(const QModelIndex &parent, int first, int last)
                          {
                              Q_Q(RootIndexProxyModel);
                              Q_ASSERT(!parent.isValid() || parent.model() == q->sourceModel());
                              if (!m_rootIndex.isValid())
                                  return;
                              if (!isDescendant(m_rootIndex, parent))
                                  return;
                              if (m_rootIndex.row() >= first && m_rootIndex.row() <= last) {
                                  m_rootRowDeleted = true;
                                  q->setRootIndex(QModelIndex());
                              }
                          }
                          
                          void RootIndexProxyModelPrivate::checkRootColumnsRemoved(const QModelIndex &parent, int first, int last)
                          {
                              Q_Q(RootIndexProxyModel);
                              Q_ASSERT(!parent.isValid() || parent.model() == q->sourceModel());
                              if (!m_rootIndex.isValid())
                                  return;
                              if (!isDescendant(m_rootIndex, parent))
                                  return;
                              if (m_rootIndex.column() >= first && m_rootIndex.column() <= last) {
                                  m_rootColumnDeleted = true;
                                  q->setRootIndex(QModelIndex());
                              }
                          }
                          
                          void RootIndexProxyModelPrivate::onRowsAboutToBeInserted(const QModelIndex &parent, int first, int last)
                          {
                              Q_Q(RootIndexProxyModel);
                              Q_ASSERT(!parent.isValid() || parent.model() == q->sourceModel());
                              if (m_rootIndex.isValid()) {
                                  if (isDescendant(m_rootIndex, parent))
                                      return;
                              }
                              q->beginInsertRows(q->mapFromSource(parent), first, last);
                          }
                          
                          void RootIndexProxyModelPrivate::onRowsInserted(const QModelIndex &parent, int first, int last)
                          {
                              Q_UNUSED(first)
                              Q_UNUSED(last)
                              Q_Q(RootIndexProxyModel);
                              Q_ASSERT(!parent.isValid() || parent.model() == q->sourceModel());
                              if (m_rootIndex.isValid()) {
                                  if (isDescendant(m_rootIndex, parent))
                                      return;
                              }
                              q->endInsertRows();
                          }
                          
                          void RootIndexProxyModelPrivate::onRowsAboutToBeRemoved(const QModelIndex &parent, int first, int last)
                          {
                              Q_Q(RootIndexProxyModel);
                              Q_ASSERT(!parent.isValid() || parent.model() == q->sourceModel());
                              if (m_rootIndex.isValid()) {
                                  if (isDescendant(m_rootIndex, parent))
                                      return;
                              }
                              q->beginRemoveRows(q->mapFromSource(parent), first, last);
                          }
                          
                          void RootIndexProxyModelPrivate::onRowsRemoved(const QModelIndex &parent, int first, int last)
                          {
                              Q_UNUSED(first)
                              Q_UNUSED(last)
                              Q_Q(RootIndexProxyModel);
                              Q_ASSERT(!parent.isValid() || parent.model() == q->sourceModel());
                              if (m_rootIndex.isValid()) {
                                  if (isDescendant(m_rootIndex, parent))
                                      return;
                              }
                              if (m_rootRowDeleted)
                                  m_rootRowDeleted = false;
                              else
                                  q->endRemoveRows();
                          }
                          
                          void RootIndexProxyModelPrivate::onRowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent,
                                                                                int dest)
                          {
                              Q_Q(RootIndexProxyModel);
                              Q_ASSERT(!sourceParent.isValid() || sourceParent.model() == q->sourceModel());
                              Q_ASSERT(!destParent.isValid() || destParent.model() == q->sourceModel());
                              if (isDescendant(m_rootIndex, destParent) == isDescendant(m_rootIndex, sourceParent)) {
                                  if (isDescendant(m_rootIndex, destParent))
                                      return;
                                  q->beginMoveRows(q->mapFromSource(sourceParent), sourceStart, sourceEnd, q->mapFromSource(destParent), dest);
                              } else if (isDescendant(m_rootIndex, destParent))
                                  q->beginRemoveRows(q->mapFromSource(sourceParent), sourceStart, sourceEnd);
                              else
                                  q->beginInsertRows(q->mapFromSource(destParent), dest, dest + sourceEnd - sourceStart);
                          }
                          
                          void RootIndexProxyModelPrivate::onRowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent, int dest)
                          {
                              Q_UNUSED(sourceStart)
                              Q_UNUSED(sourceEnd)
                              Q_UNUSED(dest)
                              Q_Q(RootIndexProxyModel);
                              Q_ASSERT(!sourceParent.isValid() || sourceParent.model() == q->sourceModel());
                              Q_ASSERT(!destParent.isValid() || destParent.model() == q->sourceModel());
                              if (isDescendant(m_rootIndex, destParent) == isDescendant(m_rootIndex, sourceParent)) {
                                  if (isDescendant(m_rootIndex, destParent))
                                      return;
                                  q->endMoveRows();
                              } else if (isDescendant(m_rootIndex, destParent))
                                  q->endRemoveRows();
                              else
                                  q->endInsertRows();
                          }
                          
                          void RootIndexProxyModelPrivate::onColumnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destParent,
                                                                          int dest)
                          {
                              Q_UNUSED(sourceStart)
                              Q_UNUSED(sourceEnd)
                              Q_UNUSED(dest)
                              Q_Q(RootIndexProxyModel);
                              Q_ASSERT(!sourceParent.isValid() || sourceParent.model() == q->sourceModel());
                              Q_ASSERT(!destParent.isValid() || destParent.model() == q->sourceModel());
                              if (isDescendant(m_rootIndex, destParent) == isDescendant(m_rootIndex, sourceParent)) {
                                  if (isDescendant(m_rootIndex, destParent))
                                      return;
                                  q->endMoveColumns();
                              } else if (isDescendant(m_rootIndex, destParent))
                                  q->endRemoveColumns();
                              else
                                  q->endInsertColumns();
                          }
                          
                          void RootIndexProxyModelPrivate::onColumnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd,
                                                                                   const QModelIndex &destParent, int dest)
                          {
                              Q_Q(RootIndexProxyModel);
                              Q_ASSERT(!sourceParent.isValid() || sourceParent.model() == q->sourceModel());
                              Q_ASSERT(!destParent.isValid() || destParent.model() == q->sourceModel());
                              if (isDescendant(m_rootIndex, destParent) == isDescendant(m_rootIndex, sourceParent)) {
                                  if (isDescendant(m_rootIndex, destParent))
                                      return;
                                  q->beginMoveColumns(q->mapFromSource(sourceParent), sourceStart, sourceEnd, q->mapFromSource(destParent), dest);
                              } else if (isDescendant(m_rootIndex, destParent))
                                  q->beginRemoveColumns(q->mapFromSource(sourceParent), sourceStart, sourceEnd);
                              else
                                  q->beginInsertColumns(q->mapFromSource(destParent), dest, dest + sourceEnd - sourceStart);
                          }
                          
                          void RootIndexProxyModelPrivate::onColumnsAboutToBeInserted(const QModelIndex &parent, int first, int last)
                          {
                              Q_Q(RootIndexProxyModel);
                              Q_ASSERT(!parent.isValid() || parent.model() == q->sourceModel());
                              if (m_rootIndex.isValid()) {
                                  if (isDescendant(m_rootIndex, parent))
                                      return;
                              }
                              q->beginInsertColumns(q->mapFromSource(parent), first, last);
                          }
                          
                          void RootIndexProxyModelPrivate::onColumnsInserted(const QModelIndex &parent, int first, int last)
                          {
                              Q_UNUSED(first)
                              Q_UNUSED(last)
                              Q_Q(RootIndexProxyModel);
                              Q_ASSERT(!parent.isValid() || parent.model() == q->sourceModel());
                              if (m_rootIndex.isValid()) {
                                  if (isDescendant(m_rootIndex, parent))
                                      return;
                              }
                              q->endInsertColumns();
                          }
                          
                          void RootIndexProxyModelPrivate::onColumnsAboutToBeRemoved(const QModelIndex &parent, int first, int last)
                          {
                              Q_Q(RootIndexProxyModel);
                              Q_ASSERT(!parent.isValid() || parent.model() == q->sourceModel());
                              if (m_rootIndex.isValid()) {
                                  if (isDescendant(m_rootIndex, parent))
                                      return;
                              }
                              q->beginRemoveColumns(q->mapFromSource(parent), first, last);
                          }
                          
                          void RootIndexProxyModelPrivate::onColumnsRemoved(const QModelIndex &parent, int first, int last)
                          {
                              Q_UNUSED(first)
                              Q_UNUSED(last)
                              Q_Q(RootIndexProxyModel);
                              Q_ASSERT(!parent.isValid() || parent.model() == q->sourceModel());
                              if (m_rootIndex.isValid()) {
                                  if (isDescendant(m_rootIndex, parent))
                                      return;
                              }
                              if (m_rootColumnDeleted)
                                  m_rootColumnDeleted = false;
                              else
                                  q->endRemoveColumns();
                          }
                          
                          void RootIndexProxyModelPrivate::onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
                          {
                              Q_Q(RootIndexProxyModel);
                              Q_ASSERT(topLeft.isValid());
                              Q_ASSERT(bottomRight.isValid());
                              Q_ASSERT(topLeft.model() == q->sourceModel());
                              Q_ASSERT(bottomRight.model() == q->sourceModel());
                              Q_ASSERT(bottomRight.parent() == topLeft.parent());
                              if (m_rootIndex.isValid()) {
                                  if (isDescendant(m_rootIndex, topLeft.parent()))
                                      return;
                              }
                              q->dataChanged(q->mapFromSource(topLeft), q->mapFromSource(bottomRight), roles);
                          }
                          
                          void RootIndexProxyModelPrivate::onLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents,
                                                                                    QAbstractItemModel::LayoutChangeHint hint)
                          {
                              Q_Q(RootIndexProxyModel);
                              QList<QPersistentModelIndex> parents;
                              parents.reserve(sourceParents.size());
                              bool addedInvalidIndex = false;
                              for (const QPersistentModelIndex &parent : sourceParents) {
                                  if (!parent.isValid() || isDescendant(m_rootIndex, parent)) {
                                      if (!addedInvalidIndex) {
                                          addedInvalidIndex = true;
                                          parents << QPersistentModelIndex();
                                      }
                                      continue;
                                  }
                                  const QModelIndex mappedParent = q->mapFromSource(parent);
                                  Q_ASSERT(mappedParent.isValid());
                                  parents << mappedParent;
                              }
                              q->layoutAboutToBeChanged(parents, hint);
                              const auto proxyPersistentIndexes = q->persistentIndexList();
                              for (const QModelIndex &proxyPersistentIndex : proxyPersistentIndexes) {
                                  proxyIndexes << proxyPersistentIndex;
                                  Q_ASSERT(proxyPersistentIndex.isValid());
                                  const QPersistentModelIndex srcPersistentIndex = q->mapToSource(proxyPersistentIndex);
                                  Q_ASSERT(srcPersistentIndex.isValid());
                                  layoutChangePersistentIndexes << srcPersistentIndex;
                              }
                          }
                          
                          void RootIndexProxyModelPrivate::onLayoutChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint)
                          {
                              Q_Q(RootIndexProxyModel);
                              for (int i = 0; i < proxyIndexes.size(); ++i)
                                  q->changePersistentIndex(proxyIndexes.at(i), q->mapFromSource(layoutChangePersistentIndexes.at(i)));
                              layoutChangePersistentIndexes.clear();
                              proxyIndexes.clear();
                              QList<QPersistentModelIndex> parents;
                              parents.reserve(sourceParents.size());
                              bool addedInvalidIndex = false;
                              for (const QPersistentModelIndex &parent : sourceParents) {
                                  if (!parent.isValid() || isDescendant(m_rootIndex, parent)) {
                                      if (!addedInvalidIndex) {
                                          addedInvalidIndex = true;
                                          parents << QPersistentModelIndex();
                                      }
                                      continue;
                                  }
                                  const QModelIndex mappedParent = q->mapFromSource(parent);
                                  Q_ASSERT(mappedParent.isValid());
                                  parents << mappedParent;
                              }
                              q->layoutChanged(parents, hint);
                          }
                          
                          /*!
                          Constructs a new proxy model with the given \a parent.
                          */
                          RootIndexProxyModel::RootIndexProxyModel(QObject *parent)
                              : QIdentityProxyModel(parent)
                              , m_dptr(new RootIndexProxyModelPrivate(this))
                          { }
                          
                          /*!
                          \internal
                          */
                          RootIndexProxyModel::RootIndexProxyModel(RootIndexProxyModelPrivate &dptr, QObject *parent)
                              : QIdentityProxyModel(parent)
                              , m_dptr(&dptr)
                          { }
                          
                          /*!
                          Destructor
                          */
                          RootIndexProxyModel::~RootIndexProxyModel()
                          {
                              Q_D(RootIndexProxyModel);
                              for (auto discIter = d->m_sourceConnections.cbegin(); discIter != d->m_sourceConnections.cend(); ++discIter)
                                  QObject::disconnect(*discIter);
                              delete m_dptr;
                          }
                          
                          /*!
                          \property RootIndexProxyModel::rootIndex
                          \accessors %rootIndex(), setRootIndex()
                          \notifier rootIndexChanged()
                          \brief This property holds the root index of the model
                          \details The root index is an index of the source model used as root by all elements of the proxy model
                          */
                          
                          //! Getter for rootIndex property
                          QModelIndex RootIndexProxyModel::rootIndex() const
                          {
                              Q_D(const RootIndexProxyModel);
                              return d->m_rootIndex;
                          }
                          
                          //! Setter for rootIndex property
                          void RootIndexProxyModel::setRootIndex(const QModelIndex &root)
                          {
                              Q_ASSERT_X(!root.isValid() || root.model() == sourceModel(), "RootIndexProxyModel::setRootIndex",
                                         "The root index must be an index of the source model");
                              Q_D(RootIndexProxyModel);
                              if (d->m_rootIndex == root)
                                  return;
                              beginResetModel();
                              d->m_rootIndex = root;
                              endResetModel();
                              rootIndexChanged();
                          }
                          
                          /*!
                          \reimp
                          */
                          void RootIndexProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
                          {
                              Q_D(RootIndexProxyModel);
                              for (auto discIter = d->m_sourceConnections.cbegin(); discIter != d->m_sourceConnections.cend(); ++discIter)
                                  QObject::disconnect(*discIter);
                              d->m_sourceConnections.clear();
                              QIdentityProxyModel::setSourceModel(sourceModel);
                              if (sourceModel) {
                                  Q_ASSUME(disconnect(sourceModel, SIGNAL(rowsAboutToBeInserted(QModelIndex, int, int)), this,
                                                      SLOT(_q_sourceRowsAboutToBeInserted(QModelIndex, int, int))));
                                  Q_ASSUME(disconnect(sourceModel, SIGNAL(rowsInserted(QModelIndex, int, int)), this, SLOT(_q_sourceRowsInserted(QModelIndex, int, int))));
                                  Q_ASSUME(disconnect(sourceModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)), this,
                                                      SLOT(_q_sourceRowsAboutToBeRemoved(QModelIndex, int, int))));
                                  Q_ASSUME(disconnect(sourceModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, SLOT(_q_sourceRowsRemoved(QModelIndex, int, int))));
                                  Q_ASSUME(disconnect(sourceModel, SIGNAL(columnsAboutToBeInserted(QModelIndex, int, int)), this,
                                                      SLOT(_q_sourceColumnsAboutToBeInserted(QModelIndex, int, int))));
                                  Q_ASSUME(
                                          disconnect(sourceModel, SIGNAL(columnsInserted(QModelIndex, int, int)), this, SLOT(_q_sourceColumnsInserted(QModelIndex, int, int))));
                                  Q_ASSUME(disconnect(sourceModel, SIGNAL(columnsAboutToBeRemoved(QModelIndex, int, int)), this,
                                                      SLOT(_q_sourceColumnsAboutToBeRemoved(QModelIndex, int, int))));
                                  Q_ASSUME(disconnect(sourceModel, SIGNAL(columnsRemoved(QModelIndex, int, int)), this, SLOT(_q_sourceColumnsRemoved(QModelIndex, int, int))));
                                  Q_ASSUME(disconnect(sourceModel, SIGNAL(dataChanged(QModelIndex, QModelIndex, QVector<int>)), this,
                                                      SLOT(_q_sourceDataChanged(QModelIndex, QModelIndex, QVector<int>))));
                                  Q_ASSUME(disconnect(sourceModel, SIGNAL(columnsAboutToBeMoved(QModelIndex, int, int, QModelIndex, int)), this,
                                                      SLOT(_q_sourceColumnsAboutToBeMoved(QModelIndex, int, int, QModelIndex, int))));
                                  Q_ASSUME(disconnect(sourceModel, SIGNAL(columnsMoved(QModelIndex, int, int, QModelIndex, int)), this,
                                                      SLOT(_q_sourceColumnsMoved(QModelIndex, int, int, QModelIndex, int))));
                                  Q_ASSUME(disconnect(sourceModel, SIGNAL(rowsAboutToBeMoved(QModelIndex, int, int, QModelIndex, int)), this,
                                                      SLOT(_q_sourceRowsAboutToBeMoved(QModelIndex, int, int, QModelIndex, int))));
                                  Q_ASSUME(disconnect(sourceModel, SIGNAL(rowsMoved(QModelIndex, int, int, QModelIndex, int)), this,
                                                      SLOT(_q_sourceRowsMoved(QModelIndex, int, int, QModelIndex, int))));
                                  Q_ASSUME(disconnect(sourceModel, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>, QAbstractItemModel::LayoutChangeHint)), this,
                                                      SLOT(_q_sourceLayoutAboutToBeChanged(QList<QPersistentModelIndex>, QAbstractItemModel::LayoutChangeHint))));
                                  Q_ASSUME(disconnect(sourceModel, SIGNAL(layoutChanged(QList<QPersistentModelIndex>, QAbstractItemModel::LayoutChangeHint)), this,
                                                      SLOT(_q_sourceLayoutChanged(QList<QPersistentModelIndex>, QAbstractItemModel::LayoutChangeHint))));
                                  using namespace std::placeholders;
                                  d->m_sourceConnections
                                          << connect(sourceModel, &QAbstractItemModel::rowsAboutToBeRemoved,
                                                     std::bind(&RootIndexProxyModelPrivate::onRowsAboutToBeRemoved, d, _1, _2, _3))
                                          << connect(sourceModel, &QAbstractItemModel::columnsAboutToBeRemoved,
                                                     std::bind(&RootIndexProxyModelPrivate::onColumnsAboutToBeRemoved, d, _1, _2, _3))
                                          << connect(sourceModel, &QAbstractItemModel::rowsRemoved, std::bind(&RootIndexProxyModelPrivate::onRowsRemoved, d, _1, _2, _3))
                                          << connect(sourceModel, &QAbstractItemModel::columnsRemoved, std::bind(&RootIndexProxyModelPrivate::onColumnsRemoved, d, _1, _2, _3))
                                          << connect(sourceModel, &QAbstractItemModel::rowsAboutToBeInserted,
                                                     std::bind(&RootIndexProxyModelPrivate::onRowsAboutToBeInserted, d, _1, _2, _3))
                                          << connect(sourceModel, &QAbstractItemModel::columnsAboutToBeInserted,
                                                     std::bind(&RootIndexProxyModelPrivate::onColumnsAboutToBeInserted, d, _1, _2, _3))
                                          << connect(sourceModel, &QAbstractItemModel::rowsInserted, std::bind(&RootIndexProxyModelPrivate::onRowsInserted, d, _1, _2, _3))
                                          << connect(sourceModel, &QAbstractItemModel::columnsInserted,
                                                     std::bind(&RootIndexProxyModelPrivate::onColumnsInserted, d, _1, _2, _3))
                                          << connect(sourceModel, &QAbstractItemModel::dataChanged, std::bind(&RootIndexProxyModelPrivate::onDataChanged, d, _1, _2, _3))
                                          << connect(sourceModel, &QAbstractItemModel::rowsAboutToBeMoved,
                                                     std::bind(&RootIndexProxyModelPrivate::onRowsAboutToBeMoved, d, _1, _2, _3, _4, _5))
                                          << connect(sourceModel, &QAbstractItemModel::columnsAboutToBeMoved,
                                                     std::bind(&RootIndexProxyModelPrivate::onColumnsAboutToBeMoved, d, _1, _2, _3, _4, _5))
                                          << connect(sourceModel, &QAbstractItemModel::rowsMoved, std::bind(&RootIndexProxyModelPrivate::onRowsMoved, d, _1, _2, _3, _4, _5))
                                          << connect(sourceModel, &QAbstractItemModel::columnsMoved,
                                                     std::bind(&RootIndexProxyModelPrivate::onColumnsMoved, d, _1, _2, _3, _4, _5))
                                          << connect(sourceModel, &QAbstractItemModel::layoutAboutToBeChanged,
                                                     std::bind(&RootIndexProxyModelPrivate::onLayoutAboutToBeChanged, d, _1, _2))
                                          << connect(sourceModel, &QAbstractItemModel::layoutChanged, std::bind(&RootIndexProxyModelPrivate::onLayoutChanged, d, _1, _2))
                          
                                          << connect(sourceModel, &QAbstractItemModel::rowsAboutToBeRemoved,
                                                     std::bind(&RootIndexProxyModelPrivate::checkRootRowRemoved, d, _1, _2, _3))
                                          << connect(sourceModel, &QAbstractItemModel::columnsAboutToBeRemoved,
                                                     std::bind(&RootIndexProxyModelPrivate::checkRootColumnsRemoved, d, _1, _2, _3));
                              }
                          }
                          
                          /*!
                          \reimp
                          */
                          QModelIndex RootIndexProxyModel::mapToSource(const QModelIndex &proxyIndex) const
                          {
                              if (!sourceModel())
                                  return QModelIndex();
                              return QIdentityProxyModel::mapToSource(proxyIndex);
                          }
                          
                          /*!
                          \reimp
                          */
                          QModelIndex RootIndexProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
                          {
                              if (!sourceModel())
                                  return QModelIndex();
                              if (!sourceIndex.isValid())
                                  return QModelIndex();
                              Q_D(const RootIndexProxyModel);
                              if (d->m_rootIndex.isValid()) {
                                  if (!d->isDescendant(sourceIndex, d->m_rootIndex))
                                      return QModelIndex();
                              }
                              return QIdentityProxyModel::mapFromSource(sourceIndex);
                          }
                          
                          /*!
                          \reimp
                          */
                          QModelIndex RootIndexProxyModel::index(int row, int column, const QModelIndex &parent) const
                          {
                              Q_ASSERT(!parent.isValid() || parent.model() == this);
                              if (!sourceModel())
                                  return QModelIndex();
                              Q_D(const RootIndexProxyModel);
                              QModelIndex sourceParent;
                              if (parent.isValid())
                                  sourceParent = mapToSource(parent);
                              else
                                  sourceParent = d->m_rootIndex;
                              const QModelIndex sourceIndex = sourceModel()->index(row, column, sourceParent);
                              return mapFromSource(sourceIndex);
                          }
                          
                          /*!
                          \reimp
                          */
                          int RootIndexProxyModel::columnCount(const QModelIndex &parent) const
                          {
                              Q_ASSERT(!parent.isValid() || parent.model() == this);
                              if (!sourceModel())
                                  return 0;
                              Q_D(const RootIndexProxyModel);
                              QModelIndex sourceParent;
                              if (parent.isValid())
                                  sourceParent = mapToSource(parent);
                              else
                                  sourceParent = d->m_rootIndex;
                              return sourceModel()->columnCount(sourceParent);
                          }
                          
                          /*!
                          \reimp
                          */
                          int RootIndexProxyModel::rowCount(const QModelIndex &parent) const
                          {
                              Q_ASSERT(!parent.isValid() || parent.model() == this);
                              if (!sourceModel())
                                  return 0;
                              Q_D(const RootIndexProxyModel);
                              QModelIndex sourceParent;
                              if (parent.isValid())
                                  sourceParent = mapToSource(parent);
                              else
                                  sourceParent = d->m_rootIndex;
                              return sourceModel()->rowCount(sourceParent);
                          }
                          
                          /*!
                          \reimp
                          */
                          bool RootIndexProxyModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
                          {
                              Q_ASSERT(!parent.isValid() || parent.model() == this);
                              if (!sourceModel())
                                  return 0;
                              Q_D(const RootIndexProxyModel);
                              QModelIndex sourceParent;
                              if (parent.isValid())
                                  sourceParent = mapToSource(parent);
                              else
                                  sourceParent = d->m_rootIndex;
                              return sourceModel()->dropMimeData(data, action, row, column, sourceParent);
                          }
                          
                          /*!
                          \reimp
                          */
                          bool RootIndexProxyModel::insertColumns(int column, int count, const QModelIndex &parent)
                          {
                              Q_ASSERT(!parent.isValid() || parent.model() == this);
                              if (!sourceModel())
                                  return 0;
                              Q_D(RootIndexProxyModel);
                              QModelIndex sourceParent;
                              if (parent.isValid())
                                  sourceParent = mapToSource(parent);
                              else
                                  sourceParent = d->m_rootIndex;
                              return sourceModel()->insertColumns(column, count, sourceParent);
                          }
                          /*!
                          \reimp
                          */
                          bool RootIndexProxyModel::insertRows(int row, int count, const QModelIndex &parent)
                          {
                              Q_ASSERT(!parent.isValid() || parent.model() == this);
                              if (!sourceModel())
                                  return 0;
                              Q_D(RootIndexProxyModel);
                              QModelIndex sourceParent;
                              if (parent.isValid())
                                  sourceParent = mapToSource(parent);
                              else
                                  sourceParent = d->m_rootIndex;
                              return sourceModel()->insertRows(row, count, sourceParent);
                          }
                          
                          /*!
                          \reimp
                          */
                          bool RootIndexProxyModel::removeColumns(int column, int count, const QModelIndex &parent)
                          {
                              Q_ASSERT(!parent.isValid() || parent.model() == this);
                              if (!sourceModel())
                                  return false;
                              Q_D(RootIndexProxyModel);
                              QModelIndex sourceParent;
                              if (parent.isValid())
                                  sourceParent = mapToSource(parent);
                              else
                                  sourceParent = d->m_rootIndex;
                              return sourceModel()->removeColumns(column, count, sourceParent);
                          }
                          
                          /*!
                          \reimp
                          */
                          bool RootIndexProxyModel::removeRows(int row, int count, const QModelIndex &parent)
                          {
                              Q_ASSERT(!parent.isValid() || parent.model() == this);
                              if (!sourceModel())
                                  return false;
                              Q_D(RootIndexProxyModel);
                              QModelIndex sourceParent;
                              if (parent.isValid())
                                  sourceParent = mapToSource(parent);
                              else
                                  sourceParent = d->m_rootIndex;
                              return sourceModel()->removeRows(row, count, sourceParent);
                          }
                          
                          /*!
                          \reimp
                          */
                          bool RootIndexProxyModel::hasChildren(const QModelIndex &parent) const
                          {
                              Q_ASSERT(!parent.isValid() || parent.model() == this);
                              if (!sourceModel())
                                  return false;
                              Q_D(const RootIndexProxyModel);
                              QModelIndex sourceParent;
                              if (parent.isValid())
                                  sourceParent = mapToSource(parent);
                              else
                                  sourceParent = d->m_rootIndex;
                              return sourceModel()->hasChildren(sourceParent);
                          }
                          
                          /*!
                          \reimp
                          */
                          bool RootIndexProxyModel::canFetchMore(const QModelIndex &parent) const
                          {
                              Q_ASSERT(!parent.isValid() || parent.model() == this);
                              if (!sourceModel())
                                  return false;
                              Q_D(const RootIndexProxyModel);
                              QModelIndex sourceParent;
                              if (parent.isValid())
                                  sourceParent = mapToSource(parent);
                              else
                                  sourceParent = d->m_rootIndex;
                              return sourceModel()->canFetchMore(sourceParent);
                          }
                          
                          /*!
                          \reimp
                          */
                          void RootIndexProxyModel::fetchMore(const QModelIndex &parent)
                          {
                              Q_ASSERT(!parent.isValid() || parent.model() == this);
                              if (!sourceModel())
                                  return;
                              Q_D(RootIndexProxyModel);
                              QModelIndex sourceParent;
                              if (parent.isValid())
                                  sourceParent = mapToSource(parent);
                              else
                                  sourceParent = d->m_rootIndex;
                              sourceModel()->fetchMore(sourceParent);
                          }
                          
                          /*!
                          \reimp
                          */
                          bool RootIndexProxyModel::moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count, const QModelIndex &destinationParent,
                                                                int destinationChild)
                          {
                              Q_ASSERT(!sourceParent.isValid() || sourceParent.model() == this);
                              Q_ASSERT(!destinationParent.isValid() || destinationParent.model() == this);
                              if (!sourceModel())
                                  return false;
                              Q_D(RootIndexProxyModel);
                              QModelIndex srcParent;
                              if (sourceParent.isValid())
                                  srcParent = mapToSource(sourceParent);
                              else
                                  srcParent = d->m_rootIndex;
                              QModelIndex destParent;
                              if (destinationParent.isValid())
                                  destParent = mapToSource(destinationParent);
                              else
                                  destParent = d->m_rootIndex;
                              return sourceModel()->moveColumns(srcParent, sourceColumn, count, destParent, destinationChild);
                          }
                          
                          /*!
                          \reimp
                          */
                          bool RootIndexProxyModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent,
                                                             int destinationChild)
                          {
                              Q_ASSERT(!sourceParent.isValid() || sourceParent.model() == this);
                              Q_ASSERT(!destinationParent.isValid() || destinationParent.model() == this);
                              if (!sourceModel())
                                  return false;
                              Q_D(RootIndexProxyModel);
                              QModelIndex srcParent;
                              if (sourceParent.isValid())
                                  srcParent = mapToSource(sourceParent);
                              else
                                  srcParent = d->m_rootIndex;
                              QModelIndex destParent;
                              if (destinationParent.isValid())
                                  destParent = mapToSource(destinationParent);
                              else
                                  destParent = d->m_rootIndex;
                              return sourceModel()->moveColumns(srcParent, sourceRow, count, destParent, destinationChild);
                          }
                          
                          /*!
                          \class RootIndexProxyModel
                          \brief This proxy model will display only the portion of a tree model with the common ancestor \a rootIndex
                          The functionality is similar to QAbstractItemView::setRootIndex but on the model side
                          */
                          

                          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                          ~Napoleon Bonaparte

                          On a crusade to banish setIndexWidget() from the holy land of Qt

                          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