QTreeView not showing first child added to parent



  • I have a QTreeView on top of a custom module.
    I allow the user to add a child item for a selected item in the model.
    Every time a child item is added to its parent, I invoke the begin/end pairs of method as documented here: http://doc.qt.io/qt-5/qabstractitemmodel.html#beginInsertRows
    After that, I also work on the view to focus on the added item, in particular:

    • obtain a QPersistentModelIndex corresponding to the parent
    • insert the child row
    • view->expand() on the parent item (through persistent index) to show its children
    • view->update() on the parent item
    • select the lastly added child

    This works almost all the time, EXCEPT when I add the first child to a parent element with no children.
    The item is correctly added to the model, but the view doesn't show it.
    Forcing a full expand/update on the view shows the item, but it not a good solution as modify the collapse state of all the tree items.

    It there something else/different I should do?
    Thanks

    P.S. When adding the first child to a model item, beginInsertRows() is invoked using beginInsertRow (parentQIndex, 0, 0) - I believe this is the correct call to do



  • Difficult to reply with no code. Can you post what you are doing?



  • Here is an extract of the code which shows the issue I'm having when adding the first child to a parent element.
    Thank you

    // mView is a QTreeView
    // the model is a custom made model derived from QAbstractItemModel,
    // which adds the child elements correctly, see AddArrayEntry below
    
    // slot invoked when the  "add-child" button is pressed
    void AddChildSlot() 
    {
       // current selection from the view
       QModelIndex index = mView->selectionModel()->currentIndex();
       // helper class to implement the model
       PropertyTreeItem* item = static_cast<PropertyTreeItem*>(index.internalPointer());
    
       // selected element is the parent, add the new child at the end 
       if (/*parent item selected*/)
       {
          // save a persistent index corresponding to the array
          QPersistentModelIndex pmi(index);
    
          // see implementation below
          // the model adds the the item correctly
          mModel.AddArrayEntry(index);
    
          // does NOT work when adding the first child to the parent
          mView->expand(pmi);
          mView->update(pmi);
          // as a workaround I can use this, which messes up the view
          // mView->expandAll();
          // mView->update();
    
          // retrieve regular index from persistent one.
          QModelIndex normalIndex = pmi;
          // select added child
          mView->selectionModel()->setCurrentIndex(normalIndex.child(item->getNumChildren() - 1, 0), QItemSelectionModel::ClearAndSelect);
          mView->setFocus();
       }
    }
    
    
    void CustomModel::AddArrayEntry(const QModelIndex &index)
    {
       // grab internal pointer and prop
       PropertyTreeItem* item = static_cast<PropertyTreeItem*>(index.internalPointer());
    
       // get the internal array class
       <internal-array>* ap = item->AsArray();
    
       // compute index of the new row we're going to add
       int rowIndexToInsert = ap->Size();
    
       // notify row number about to change in the model
       beginInsertRows(index, rowIndexToInsert, rowIndexToInsert);
    
       // create a new element based on the prototype and the correspoding model tree item
       PropertyTreeItem* insertedItem = createTreeItem(/*params*/);
    
       // add the new item both on the internal array AND in the model wrapping it
       ap->Add(entry);
       item->addChild(insertedItem);
       
       // done inserting rows      
       endInsertRows();
    }
    


  • Hi, i read your problem description and your source code also , i hope that i can help you perfectly but i have something is ambiguous for me , and i need to understand them .

    • What do you mean by PropertyTreeItem class in your code , i think that a class dereaved from the abastractitemView or QStandarItem (did you mean the PropertyTreeItem * item the new item that you want to add ) ?
    • Just i wante to know how are you checked if the item is correctly added to the model (that my be wrong or is get the same result always ) ?

    I wante you to check befor this statement "PropertyTreeItem* item = static_cast<PropertyTreeItem*>(index.internalPointer());" if is doing the correct cast or no in the AddArrayEntry() method with debugging mode also rowIndexToInsert value when the item has no children .



  • Kind of guessing here but since you are not adding columns to the parent the view might just ignore the added rows. That would also explain why collapsing+expanding fixes it. try adding beginInsertColumns and endInsertColumns as well when the parent has no children



  • @VRonin said:

    Kind of guessing here but since you are not adding columns to the parent the view might just ignore the added rows. That would also explain why collapsing+expanding fixes it. try adding beginInsertColumns and endInsertColumns as well when the parent has no children

    Thanks @VRonin, I've tried your solution but still does not cover 100% of the cases.
    On the same line I've also tried mView->update() not only on the parent item, but also explicitly on all of its children: still working only sometimes, not always...

    @Maarouf-Med-Mahdi PropertyTreeItem is the internal used to build the model on, see: http://doc.qt.io/qt-5/qtwidgets-itemviews-simpletreemodel-example.html
    I'm sure the model is updated correctly because I've debugged it, and if I jump on another item and than relesect the one I've modified, the added child is shown correctly, which means that it's a problem of refreshing the view, not about the child item not added to the model.



  • @rickyviking
    There seem to be a few questions about this type of behaviour.

    From one of them (https://forum.qt.io/topic/18024/solved-qtreeview-child-indicator-is-not-updated-after-inserting-children):

    • Are you using any kind of sort behaviour (inc. proxy) on the model/view?

    • Are your columnCount()s returning the same number on every single index in the view (possibly including the parent)?



  • @rickyviking said in QTreeView not showing first child added to parent:

    I'm sure the model is updated correctly because I've debugged it

    When it comes to subclassing models you can never be sure, believe me.

    @JonB 's points are 100% worth exploring but I'd also recommend running the model test alongside your program to make sure everything is implemented correctly



  • Thanks @VRonin and @JonB for your suggestions.

    I finally found the cause of my issue: the model I shared in the code snippet above is based on 2 columns.
    Sometimes the method to add a new child row was invoked with an index referring to the right row, but to column 1 instead of 0, because the user might have selected that cell as last one.
    This probably doesn't play well with begin/endInsertRows().
    I have now checked that the column index for which I call begin/endInsertRows() is always 0, and after this change the view always updates correctly.

    I confirm the model behaves correctly, but the model test is a nice tool anyway.



  • @rickyviking said in QTreeView not showing first child added to parent:

    This probably doesn't play well with begin/endInsertRows().

    It does play well, however None of the views provided by Qt handle children of items in columns that are not the first one


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.