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

    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