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. Index for beginInsertRows() with QTreeView
Forum Update on Monday, May 27th 2025

Index for beginInsertRows() with QTreeView

Scheduled Pinned Locked Moved Solved General and Desktop
12 Posts 2 Posters 5.0k 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.
  • gde23G Offline
    gde23G Offline
    gde23
    wrote on last edited by
    #1

    Hello,

    i have a question on how to calculate the first and last index when inserting a row (new treeitem) in a treemodel
    documentation of beginInsertRows()

    My approach is as follows (the new item is appended after the existing items):

        QModelIndex index = tree_view->currentIndex();
        TreeItem* item = static_cast<ae_oe::TreeItem*>(index.internalPointer());
        int insert_pos = item->getNrChildren()+1;
        beginInsertRows(index, index.row()+insert_pos, index.row()+insert_pos);
        item.appendChild(childItem);
        endInsertRows();
    
        emit dataChanged();
    

    The dataChanged() signal calls the QWidget::update() of QTreeView.

    However when i insert a new child sometimes it does not update the view (collapsing the tree and expanding it again updates the view)

    What am i doing wrong?

    VRoninV 1 Reply Last reply
    0
    • gde23G gde23

      Hello,

      i have a question on how to calculate the first and last index when inserting a row (new treeitem) in a treemodel
      documentation of beginInsertRows()

      My approach is as follows (the new item is appended after the existing items):

          QModelIndex index = tree_view->currentIndex();
          TreeItem* item = static_cast<ae_oe::TreeItem*>(index.internalPointer());
          int insert_pos = item->getNrChildren()+1;
          beginInsertRows(index, index.row()+insert_pos, index.row()+insert_pos);
          item.appendChild(childItem);
          endInsertRows();
      
          emit dataChanged();
      

      The dataChanged() signal calls the QWidget::update() of QTreeView.

      However when i insert a new child sometimes it does not update the view (collapsing the tree and expanding it again updates the view)

      What am i doing wrong?

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

      First of all a design question: QModelIndex index = tree_view->currentIndex(); in the same method that calls beginInsertRows implies that the model knows (or even owns) the view. This goes against the design of model/view itself. The same model should be usable by different views


      int insert_pos = item->getNrChildren()+1;

      this depends on what getNrChildren actually does but, intuitively, if it returns the number of children of the index then it should just be const int insert_pos = item->getNrChildren();


      index.row()+insert_pos

      if index is the parent, what has its row to do with the new row?! its should just be beginInsertRows(index, insert_pos, insert_pos);


      The dataChanged() signal calls the QWidget::update() of QTreeView.

      No. Just no. Don't hack around the problems, if the view does not update correctly it just means your insert/remove/move implementation is wrong. Remove emit dataChanged();

      "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
      2
      • gde23G Offline
        gde23G Offline
        gde23
        wrote on last edited by
        #3

        @VRonin Thanks for the quick answer.


        The TreeModel knows the TreeView (there is only one view and one model) but you are right, i have to clean up where things belong here.


        getNrChildren() returns the children count of the item (not including the children's children)


        i have also tried with

        int insert_pos = item->getNrChildren();
        beginInsertRows(index, insert_pos, insert_pos);
        

        still the same behavior


        The emit dataChanged() was unneccesary, however removing it does not change anything.

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

          Try running the model test. download modeltest.h and modeltest.cpp. When you create the model add a line with something like new ModelTest(myModel ,myModel); and use the rest of your app as normal. it will assert if it detects something wrong

          "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
          2
          • gde23G Offline
            gde23G Offline
            gde23
            wrote on last edited by gde23
            #5

            Thanks for the hint with the model test.

            I've tested two versions of the code

            beginInsertRows(index, insert_pos, insert_pos);
            

            as well as some definitely wrong one

            beginInsertRows(index, 23, 42);
            

            The test itself seems to work since it detected an error somewhere else (when removing an item) however
            both version don't cause any errors detected by the test.

            edit:

            i've uncommented the output in ModelTest::rowsInserted() to get some details: This is what i get:

            For the first 3 insertations:

            rowsInserted start= 2 end= 2 oldsize= 2 parent= "TreeItem" current rowcount of parent= 13
            itemWasInserted: 2 QVariant(QString, "TreeItem")
            

            from then on:

            rowsInserted start= 5 end= 5 oldsize= 0 parent= "" current rowcount of parent= 0
            itemWasInserted: 5 QVariant(Invalid)
            

            until i collapse and expand the view. Then it works again for some items

            rowsInserted start= 2 end= 2 oldsize= 2 parent= "TreeItem" current rowcount of parent= 3
            itemWasInserted: 2 QVariant(QString, "TreeItem")
            rowsInserted start= 3 end= 3 oldsize= 3 parent= "TreeItem" current rowcount of parent= 4
            itemWasInserted: 3 QVariant(QString, "TreeItem")
            rowsInserted start= 4 end= 4 oldsize= 4 parent= "TreeItem" current rowcount of parent= 5
            itemWasInserted: 4 QVariant(QString, "TreeItem")
            rowsInserted start= 5 end= 5 oldsize= 0 parent= "" current rowcount of parent= 0
            itemWasInserted: 5 QVariant(Invalid)
            rowsInserted start= 6 end= 6 oldsize= 0 parent= "" current rowcount of parent= 0
            itemWasInserted: 6 QVariant(Invalid)
            rowsInserted start= 7 end= 7 oldsize= 0 parent= "" current rowcount of parent= 0
            itemWasInserted: 7 QVariant(Invalid)
            
            1 Reply Last reply
            0
            • VRoninV Offline
              VRoninV Offline
              VRonin
              wrote on last edited by VRonin
              #6

              What's childItem? how do you create it? What does TreeItem::appendChild() do? But most importantly, do you really need to waste your time in a custom model or could you just use QStandardItemModel instead?

              "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
              • gde23G Offline
                gde23G Offline
                gde23
                wrote on last edited by
                #7

                appendChild() just appends the item to the parent item

                void TreeItem::appendChild(TreeItem *item)
                {
                    m_child_items.push_back(item);
                }
                

                childItem is another TreeItem* it is crated in the method that is called to add a new TreeItem to the model.

                    TreeItem *childItem = new TreeItem(&item);
                    ...
                    ...
                    item.appendChild(childItem);
                

                My Model inherits from QAbstractItemModel. The reason i want to implement the insertion myself is as follows:

                • i have an eventFilter with a right-klick-menu that offers the possibility to insert several types of items to the model which all inherit from TreeItem
                • depending on the chosen action a signal is send to one of the "insert_item_slots" of the model
                • each of the slots then creates the demanded item and appends it to the parent
                VRoninV 1 Reply Last reply
                0
                • gde23G gde23

                  appendChild() just appends the item to the parent item

                  void TreeItem::appendChild(TreeItem *item)
                  {
                      m_child_items.push_back(item);
                  }
                  

                  childItem is another TreeItem* it is crated in the method that is called to add a new TreeItem to the model.

                      TreeItem *childItem = new TreeItem(&item);
                      ...
                      ...
                      item.appendChild(childItem);
                  

                  My Model inherits from QAbstractItemModel. The reason i want to implement the insertion myself is as follows:

                  • i have an eventFilter with a right-klick-menu that offers the possibility to insert several types of items to the model which all inherit from TreeItem
                  • depending on the chosen action a signal is send to one of the "insert_item_slots" of the model
                  • each of the slots then creates the demanded item and appends it to the parent
                  VRoninV Offline
                  VRoninV Offline
                  VRonin
                  wrote on last edited by
                  #8

                  @gde23 said in Index for beginInsertRows() with QTreeView:

                  (&item);
                  item.

                  This looks like item is on the stack. Is it the case?

                  i have an eventFilter with a right-klick-menu

                  Normally this is just achieved with setContextMenuPolicy(Qt::CustomContextMenu); and a slot connected to QWidget::customContextMenuRequested

                  "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
                  2
                  • gde23G Offline
                    gde23G Offline
                    gde23
                    wrote on last edited by
                    #9

                    Ok, i finally got it working.

                    The solution looks like this:

                    void TreeModel::addItem()
                    {
                        QModelIndex index = m_tree_view->currentIndex();
                        TreeItem* parent_item = static_cast<TreeItem*>(index.internalPointer());
                        if(parent_item == NULL)
                        {
                            return;
                        }
                        int c = parent_item->getChildCount();    
                        beginInsertRows(QModelIndex(), index.row()+c, index.row()+c);
                    
                        TreeItem* child_item = new TreeIrem(parent_item);
                        parent_item->appenChild(child_item);
                        endInsertRows();
                    }
                    

                    However I wonder why this is correct with the dummy QModelIndex() and not the real one?

                    @VRonin thanks a lot for the help

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

                      This can't be working. This tries to append rows on the root item without checking if index is root.
                      This, should work:

                      void TreeModel::addItem()
                      {
                          QModelIndex index = m_tree_view->currentIndex();
                          TreeItem* parent_item = static_cast<TreeItem*>(index.internalPointer());
                          if(!parent_item)
                              return;
                          const int c = parent_item->getChildCount();    
                          beginInsertRows(index.parent(), c, c);
                          TreeItem* child_item = new TreeIrem(parent_item);
                          parent_item->appenChild(child_item);
                          endInsertRows();
                      }
                      

                      "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
                      2
                      • gde23G Offline
                        gde23G Offline
                        gde23
                        wrote on last edited by
                        #11

                        I have tested both versions and i don't really get it either, but with the version I posted everything behaves like it should.
                        With the version you posted, after appending an item the tree (sometimes) collapses in some region.

                        1 Reply Last reply
                        0
                        • gde23G Offline
                          gde23G Offline
                          gde23
                          wrote on last edited by
                          #12

                          @VRonin Ok, so, finally your version was right. It didn't make a lot of sense that it worked with the one i posted.
                          The reason why it did was, that my method to get the current index was broken and leaded to some strange behavior.
                          Thanks again for the help.

                          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