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 Offline
    M Offline
    MNGL
    wrote on last edited by MNGL
    #1

    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 1 Reply Last reply
    0
    • 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 Offline
      JonBJ Offline
      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 Offline
            JonBJ Offline
            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 Offline
                JonBJ Offline
                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 Offline
                      JonBJ Offline
                      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 Offline
                          JonBJ Offline
                          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