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. How to sort item names in treeview alphabetically ignorent of the case?
Forum Updated to NodeBB v4.3 + New Features

How to sort item names in treeview alphabetically ignorent of the case?

Scheduled Pinned Locked Moved Unsolved General and Desktop
15 Posts 3 Posters 1.3k 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.
  • M MNGL

    Hi, Guys

    Below is my treeview code, and I want sort to sort the directory keys alphabetically whatever whether they start with a capital letter or not, for example, the "auto-update" should be listed right after the "Audio", how to implement this? Thanks.

    RegistryTreeView::RegistryTreeView(Registry &inRegistry, QWidget *inParent)
    {
        mModel = new RegistryItemModel;
        mModel->setRegistry(&inRegistry);
    
        mTreeView = new QTreeView;
        mTreeView->setContextMenuPolicy(Qt::DefaultContextMenu);
        mTreeView->setModel(mModel);
        mTreeView->setItemDelegate(new RegistryItemDelegate(mModel));
        mTreeView->installEventFilter(new AutoSelectEventFilter(this));
        
        mainLayout->addWidget(mTreeView);
        
    }
    

    editor1.jpg editor2.jpg image url)

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

    @MNGL
    You must either interpose a QSortFilterProxyModel between your model and the QTreeView so that you can use setSortCaseSensitivity(Qt::CaseInsensitive) (e.g. https://stackoverflow.com/questions/50693571/how-to-sort-qtableview-ignoring-case) or you could override the virtual QAbstractItemModel::sort() to implement your own case-insensitive sorting. If you do the latter be careful to maintain the correct tree structure, i.e. sorting only on siblings of each node separately.

    1 Reply Last reply
    4
    • M Offline
      M Offline
      MNGL
      wrote on last edited by MNGL
      #3

      Thanks, @JonB

      I tried the option 1, it worked, but it did not work with code in BOLD:
      Is there any way to make the setItemDelegate to work with QSortFilterProxyModel object?

      RegistryTreeView::RegistryTreeView(Registry &inRegistry, QWidget *inParent)
      {
          mModel = new RegistryItemModel;
          mModel->setRegistry(&inRegistry);
      
          QSortFilterProxyModel *ProxyModel = new QSortFilterProxyModel(this);
          ProxyModel->setSourceModel(mModel);
          ProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
          ProxyModel->sort(0, Qt::AscendingOrder);
      
          mTreeView = new QTreeView;
          mTreeView->setContextMenuPolicy(Qt::DefaultContextMenu);
          mTreeView->setModel(ProxyModel);
          **mTreeView->setItemDelegate(new RegistryItemDelegate(mModel));** //this line will cause abend.
          mTreeView->installEventFilter(new AutoSelectEventFilter(this));
          
          mainLayout->addWidget(mTreeView);
          
      }
      
      class RegistryItemDelegate : public QStyledItemDelegate
      {
          Q_OBJECT;
      
      public:
      
          RegistryItemDelegate(RegistryItemModel *inModel, QObject *inParent=NULL);
          //RegistryItemDelegate(QSortFilterProxyModel *inModel, QObject *inParent=NULL);
          virtual ~RegistryItemDelegate();
      
      protected:
          virtual void initStyleOption(QStyleOptionViewItem *inOption, const QModelIndex &inIndex) const;
      
      
      private:
          RegistryItemModel *mModel;
      	
          QColor mModifiedColor;
          QIcon mFolderIcon;
      };
      
      B JonBJ 2 Replies Last reply
      0
      • M MNGL

        Thanks, @JonB

        I tried the option 1, it worked, but it did not work with code in BOLD:
        Is there any way to make the setItemDelegate to work with QSortFilterProxyModel object?

        RegistryTreeView::RegistryTreeView(Registry &inRegistry, QWidget *inParent)
        {
            mModel = new RegistryItemModel;
            mModel->setRegistry(&inRegistry);
        
            QSortFilterProxyModel *ProxyModel = new QSortFilterProxyModel(this);
            ProxyModel->setSourceModel(mModel);
            ProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
            ProxyModel->sort(0, Qt::AscendingOrder);
        
            mTreeView = new QTreeView;
            mTreeView->setContextMenuPolicy(Qt::DefaultContextMenu);
            mTreeView->setModel(ProxyModel);
            **mTreeView->setItemDelegate(new RegistryItemDelegate(mModel));** //this line will cause abend.
            mTreeView->installEventFilter(new AutoSelectEventFilter(this));
            
            mainLayout->addWidget(mTreeView);
            
        }
        
        class RegistryItemDelegate : public QStyledItemDelegate
        {
            Q_OBJECT;
        
        public:
        
            RegistryItemDelegate(RegistryItemModel *inModel, QObject *inParent=NULL);
            //RegistryItemDelegate(QSortFilterProxyModel *inModel, QObject *inParent=NULL);
            virtual ~RegistryItemDelegate();
        
        protected:
            virtual void initStyleOption(QStyleOptionViewItem *inOption, const QModelIndex &inIndex) const;
        
        
        private:
            RegistryItemModel *mModel;
        	
            QColor mModifiedColor;
            QIcon mFolderIcon;
        };
        
        B Offline
        B Offline
        Bonnie
        wrote on last edited by Bonnie
        #4

        @MNGL What's your RegistryItemModel's base class?
        If it is subclassed from QStandardItemModel, I'd just add one custom role for sorting, something like

        const int sort_role = Qt::UserRole + 1;
        
        RegistryItemModel() {
            ...
            setSortRole(sort_role);
            ...
        }
        

        And save toLower() of the original text in every item's sort_role data

        1 Reply Last reply
        0
        • M MNGL

          Thanks, @JonB

          I tried the option 1, it worked, but it did not work with code in BOLD:
          Is there any way to make the setItemDelegate to work with QSortFilterProxyModel object?

          RegistryTreeView::RegistryTreeView(Registry &inRegistry, QWidget *inParent)
          {
              mModel = new RegistryItemModel;
              mModel->setRegistry(&inRegistry);
          
              QSortFilterProxyModel *ProxyModel = new QSortFilterProxyModel(this);
              ProxyModel->setSourceModel(mModel);
              ProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
              ProxyModel->sort(0, Qt::AscendingOrder);
          
              mTreeView = new QTreeView;
              mTreeView->setContextMenuPolicy(Qt::DefaultContextMenu);
              mTreeView->setModel(ProxyModel);
              **mTreeView->setItemDelegate(new RegistryItemDelegate(mModel));** //this line will cause abend.
              mTreeView->installEventFilter(new AutoSelectEventFilter(this));
              
              mainLayout->addWidget(mTreeView);
              
          }
          
          class RegistryItemDelegate : public QStyledItemDelegate
          {
              Q_OBJECT;
          
          public:
          
              RegistryItemDelegate(RegistryItemModel *inModel, QObject *inParent=NULL);
              //RegistryItemDelegate(QSortFilterProxyModel *inModel, QObject *inParent=NULL);
              virtual ~RegistryItemDelegate();
          
          protected:
              virtual void initStyleOption(QStyleOptionViewItem *inOption, const QModelIndex &inIndex) const;
          
          
          private:
              RegistryItemModel *mModel;
          	
              QColor mModifiedColor;
              QIcon mFolderIcon;
          };
          
          JonBJ Online
          JonBJ Online
          JonB
          wrote on last edited by
          #5

          @MNGL said in How to sort item names in treeview alphabetically ignorent of the case?:

          **mTreeView->setItemDelegate(new RegistryItemDelegate(mModel));** //this line will cause abend.

          I don't know what abend means. Find out whether there is a problem with the new RegistryItemDelegate(mModel) or with the mTreeView->setItemDelegate().

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

            class RegistryItemModel : public QAbstractItemModel
            {
            Q_OBJECT;

            public:
            RegistryItemModel(QWidget *parent=NULL);
            virtual ~RegistryItemModel();
            ......
            }

            if I don't comment out following line, the program will crash before the Main Window is launched.

            mTreeView->setItemDelegate(new RegistryItemDelegate(mModel));
            
            JonBJ 1 Reply Last reply
            0
            • M MNGL

              class RegistryItemModel : public QAbstractItemModel
              {
              Q_OBJECT;

              public:
              RegistryItemModel(QWidget *parent=NULL);
              virtual ~RegistryItemModel();
              ......
              }

              if I don't comment out following line, the program will crash before the Main Window is launched.

              mTreeView->setItemDelegate(new RegistryItemDelegate(mModel));
              
              JonBJ Online
              JonBJ Online
              JonB
              wrote on last edited by JonB
              #7

              @MNGL
              Yes, you said that earlier. Already suggested what you should do next. Also you can see the cause of "crashes" from the debugger.

              1 Reply Last reply
              0
              • M Offline
                M Offline
                MNGL
                wrote on last edited by
                #8

                Thanks, @JonB JonB
                QAbstractItemModel does not have a function called setSortRole.

                Here is the crash screenshot:

                abend.JPG abend2.JPG

                JonBJ 1 Reply Last reply
                0
                • M Offline
                  M Offline
                  MNGL
                  wrote on last edited by
                  #9

                  Does anyone have the code example on how to override the virtual QAbstractItemModel::sort() to implement case-insensitive sorting?

                  1 Reply Last reply
                  0
                  • M MNGL

                    Thanks, @JonB JonB
                    QAbstractItemModel does not have a function called setSortRole.

                    Here is the crash screenshot:

                    abend.JPG abend2.JPG

                    JonBJ Online
                    JonBJ Online
                    JonB
                    wrote on last edited by JonB
                    #10

                    @MNGL said in How to sort item names in treeview alphabetically ignorent of the case?:

                    Thanks, @JonB JonB
                    QAbstractItemModel does not have a function called setSortRole.

                    It was @Bonnie who suggested that, if you had been using QStandardItemModel.

                    Here is the crash screenshot:

                    I'm not sure of the reason. It comes in your RegistryItemDelegate::initStyleOption() override, whose code so far you have steadfastly refused to show. When you create it you pass it mModel (I don't know why, I don't think you should be doing this), which is your source model. But the treeview is attached to the QSortFilterProxyModel model. At a guess, the QModelIndex &inIndex being passed is an index into the proxy model, but you are using it to index into the source model??

                    M 1 Reply Last reply
                    0
                    • JonBJ JonB

                      @MNGL said in How to sort item names in treeview alphabetically ignorent of the case?:

                      Thanks, @JonB JonB
                      QAbstractItemModel does not have a function called setSortRole.

                      It was @Bonnie who suggested that, if you had been using QStandardItemModel.

                      Here is the crash screenshot:

                      I'm not sure of the reason. It comes in your RegistryItemDelegate::initStyleOption() override, whose code so far you have steadfastly refused to show. When you create it you pass it mModel (I don't know why, I don't think you should be doing this), which is your source model. But the treeview is attached to the QSortFilterProxyModel model. At a guess, the QModelIndex &inIndex being passed is an index into the proxy model, but you are using it to index into the source model??

                      M Offline
                      M Offline
                      MNGL
                      wrote on last edited by MNGL
                      #11

                      @JonB

                      class RegistryItemDelegate : public QStyledItemDelegate
                      {
                          Q_OBJECT;
                      
                      public:
                      
                        //RegistryItemDelegate(RegistryItemModel *inModel, QObject *inParent=NULL);
                          RegistryItemDelegate(QSortFilterProxyModel *mModel, QObject *inParent=NULL);
                          virtual ~RegistryItemDelegate();
                      
                      protected:
                          virtual void initStyleOption(QStyleOptionViewItem *inOption, const QModelIndex &inIndex) const;
                      
                      
                      private:
                        //RegistryItemModel *mModel;
                          QSortFilterProxyModel *mModel;
                          QColor mModifiedColor;
                          QIcon mFolderIcon;
                      };
                      
                      void RegistryItemDelegate::initStyleOption(QStyleOptionViewItem *inOption, const QModelIndex &inIndex) const
                      {
                          QStyledItemDelegate::initStyleOption(inOption, inIndex);
                      
                          const Node *node = mModel->node(inIndex); //error C2039: 'node' : is not a member of 'QSortFilterProxyModel'
                          if(node == NULL)
                              return;
                      
                          if(!node->isDefault())
                              inOption->palette.setColor(QPalette::Text, mModifiedColor);
                      
                          if(node->nodeType() == eRegDir && inOption->version == 4)
                          { 
                              ((QStyleOptionViewItemV4*)inOption)->features |= QStyleOptionViewItemV2::HasDecoration;
                              ((QStyleOptionViewItemV4*)inOption)->icon = mFolderIcon;
                          }
                      }
                      

                      if I change the type of mModel from RegistryItemModel to QSortFilterProxyModel, I got following error:

                      error C2039: 'node' : is not a member of 'QSortFilterProxyModel'

                      JonBJ 1 Reply Last reply
                      0
                      • M MNGL

                        @JonB

                        class RegistryItemDelegate : public QStyledItemDelegate
                        {
                            Q_OBJECT;
                        
                        public:
                        
                          //RegistryItemDelegate(RegistryItemModel *inModel, QObject *inParent=NULL);
                            RegistryItemDelegate(QSortFilterProxyModel *mModel, QObject *inParent=NULL);
                            virtual ~RegistryItemDelegate();
                        
                        protected:
                            virtual void initStyleOption(QStyleOptionViewItem *inOption, const QModelIndex &inIndex) const;
                        
                        
                        private:
                          //RegistryItemModel *mModel;
                            QSortFilterProxyModel *mModel;
                            QColor mModifiedColor;
                            QIcon mFolderIcon;
                        };
                        
                        void RegistryItemDelegate::initStyleOption(QStyleOptionViewItem *inOption, const QModelIndex &inIndex) const
                        {
                            QStyledItemDelegate::initStyleOption(inOption, inIndex);
                        
                            const Node *node = mModel->node(inIndex); //error C2039: 'node' : is not a member of 'QSortFilterProxyModel'
                            if(node == NULL)
                                return;
                        
                            if(!node->isDefault())
                                inOption->palette.setColor(QPalette::Text, mModifiedColor);
                        
                            if(node->nodeType() == eRegDir && inOption->version == 4)
                            { 
                                ((QStyleOptionViewItemV4*)inOption)->features |= QStyleOptionViewItemV2::HasDecoration;
                                ((QStyleOptionViewItemV4*)inOption)->icon = mFolderIcon;
                            }
                        }
                        

                        if I change the type of mModel from RegistryItemModel to QSortFilterProxyModel, I got following error:

                        error C2039: 'node' : is not a member of 'QSortFilterProxyModel'

                        JonBJ Online
                        JonBJ Online
                        JonB
                        wrote on last edited by JonB
                        #12

                        @MNGL
                        OK. But I still don't know why you pass a mModel parameter to your delegate. I would be getting the model from the QModelIndex &inIndex() passed to initStyleOption().

                        If your screenshot shows it is crashing on the node->isDefault() line, what is a Node, how does mModel->node(inIndex) work, what is Node::isDefault()? Have you compiled for Debug with no code optimizations? Just in case the line is misleading, Q_ASSERT(mModel). Otherwise it looks like node is 0/nullptr for the exception at 0x00000000, though you test for that, so presumably it can't be....

                        BTW, you have not said, but are you still using Qt4 (it looks like you are), not Qt5/6??

                        M 2 Replies Last reply
                        0
                        • JonBJ JonB

                          @MNGL
                          OK. But I still don't know why you pass a mModel parameter to your delegate. I would be getting the model from the QModelIndex &inIndex() passed to initStyleOption().

                          If your screenshot shows it is crashing on the node->isDefault() line, what is a Node, how does mModel->node(inIndex) work, what is Node::isDefault()? Have you compiled for Debug with no code optimizations? Just in case the line is misleading, Q_ASSERT(mModel). Otherwise it looks like node is 0/nullptr for the exception at 0x00000000, though you test for that, so presumably it can't be....

                          BTW, you have not said, but are you still using Qt4 (it looks like you are), not Qt5/6??

                          M Offline
                          M Offline
                          MNGL
                          wrote on last edited by
                          #13
                          This post is deleted!
                          1 Reply Last reply
                          0
                          • JonBJ JonB

                            @MNGL
                            OK. But I still don't know why you pass a mModel parameter to your delegate. I would be getting the model from the QModelIndex &inIndex() passed to initStyleOption().

                            If your screenshot shows it is crashing on the node->isDefault() line, what is a Node, how does mModel->node(inIndex) work, what is Node::isDefault()? Have you compiled for Debug with no code optimizations? Just in case the line is misleading, Q_ASSERT(mModel). Otherwise it looks like node is 0/nullptr for the exception at 0x00000000, though you test for that, so presumably it can't be....

                            BTW, you have not said, but are you still using Qt4 (it looks like you are), not Qt5/6??

                            M Offline
                            M Offline
                            MNGL
                            wrote on last edited by
                            #14

                            @JonB strikethrough text

                            it's obviously that object of QSortFilterProxyModel cannot replace the mModel of RegistryItemModel.
                            I'm using Qt 4.8.7, and what about override the QAbstractItemModel::sort() to implement your own case-insensitive sorting, where can find a code example?

                            1 Reply Last reply
                            0
                            • M Offline
                              M Offline
                              MNGL
                              wrote on last edited by MNGL
                              #15

                              Here is the code change that fixed the crash:

                              void RegistryItemDelegate::initStyleOption(QStyleOptionViewItem *inOption, const QModelIndex &inIndex) const
                              {
                                  QStyledItemDelegate::initStyleOption(inOption, inIndex);
                              
                                  //const Node *node = mModel->node(inIndex);
                                  const Node* node = nullptr;  //code change start
                              
                                  QModelIndex sourceIndex = inIndex;
                                  auto proxyModel = dynamic_cast<const QAbstractProxyModel*>(sourceIndex.model());
                                  //We map the index back to its source as many times as needed.
                                  //We expect to do it once for now but that may change in the future.
                                  while (proxyModel) {
                                        sourceIndex = proxyModel->mapToSource(sourceIndex);
                                        proxyModel = dynamic_cast<const QAbstractProxyModel*>(sourceIndex.model());
                                  }
                                 
                                  auto regModel = dynamic_cast<const RegistryItemModel*>(sourceIndex.model()) ;
                                  if (regModel)
                                  node = regModel->node(sourceIndex);  //code change end
                              	
                                  if(node == NULL)
                                      return;
                              
                                  if(!node->isDefault())
                                      inOption->palette.setColor(QPalette::Text, mModifiedColor);
                              
                                  if(node->nodeType() == eRegDir && inOption->version == 4)
                                  { 
                                      ((QStyleOptionViewItemV4*)inOption)->features |= QStyleOptionViewItemV2::HasDecoration;
                                      ((QStyleOptionViewItemV4*)inOption)->icon = mFolderIcon;
                                  }
                              }
                              
                              1 Reply Last reply
                              1

                              • Login

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