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 Updated to NodeBB v4.3 + New Features

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 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