Important: Please read the Qt Code of Conduct -

QAbstractItemModel with QTreeview and accessing through indexing

  • Hi All Super brains.

    A question regarding QAbstractItemModel used in a QTreeview and its access from a button slot.

    I'm experimenting with the Example "/widgets/itemviews/editabletreemodel".

    My question is how do you Add only to the root a child, even if the selectionModel()->currentIndex() is pointing to a different branch (or child )

    void Dialog::on_btn_add_3branch_released()
        QModelIndex index = ui->tree_test->selectionModel()->currentIndex();
        QAbstractItemModel *model =  ui->tree_test->model();
    //Add only to current branch
    // if already 3nd branch add  to current branch as sibling node.
    //if 0=index (root?) Add parents till you reach 3nd branch then add  sibling node.

    In this use case The user can only ADD to 3 children deep, ( there are 3 buttons representing each depth. 1, 2 and 3)
    If the user selects a button for creating a child at the 3rd depth, it will create the needed branches till it reaches the correct depth then add the child.

    one attempt:

     //Create Scene node off root
            QModelIndex indexRoot = model->index(0, 0, QModelIndex());
            if (!model->insertRow(0, indexRoot ))   return; //try to create at root
            model->setData(indexRoot , QVariant( "[rootChild]"  ), Qt::EditRole);

    If the user "is" on the last 3rd depth as reported by "selectionModel()->currentIndex() " and the user presses to add depth 1 (or 0) the should be able to backup to the root child add add to that.

    its all related to the parent child relationship by I cant seem to quite master the detail

    any help appreciated.

  • Lifetime Qt Champion


    If you want to go back to the "root" index of a branch, you can follow back the trail using the QModelIndex::parent. When parent is invalid, you reached the top level item.

    Hope it helps

  • Thanks,
    So no easy way to get Root node without parent back trailing?,
    was hoping :
    QModelIndex indexRoot = model->index(0, 0, QModelIndex()); would give the root.

    throught im not sure why this is not in the QTreeview ui->tree_test->selectionModel()->rootIndex();

    or method of returning what tree depth you are in the tree from QTreeview ?

  • Lifetime Qt Champion

    Something's not clear, do you want the current root node of the model or the top level node of a branch ?

    For the current root index: myTreeView->rootIndex();

    You can change the root index used by the view to accommodate your needs. The model doesn't have that notion because its job is to manage data not what the view considers to be the root index.

  • thanks, both types interest me.
    I can get the model data from :
    QAbstractItemModel *model = ui->tree_test->model();

    The top level node of a branch is what im interesting in finding.
    (as seen from the QTreeView).

  • Lifetime Qt Champion

    What kind of model are you using ?

  • The model is closley based on the the Example "/widgets/itemviews/editabletreemodel".
    After testing this following code seems to work ( in adding to the root) by passing a blank QModelIndex().
    ie: if (!model->insertRow(0, QModelIndex())) return;

    only issue im still trying to resolve now is the backtrailing.
    If the TreeView currentIndex selection is several rows down (root children) AND several branches deep, I want to insert at the top level root another child (but after the currentIndex selections rootchild ). but finding all these index's required for navigating is a bit confusing.

    void Dialog::on_btn_add_topbranch_released()
        QModelIndex index = ui->tree_view->selectionModel()->currentIndex();
        tree_model *model =  ui->tree_view->model();
       QModelIndex indexRoot; ui->tree_shot->rootIndex(); //if set to rootNode
        QModelIndex child;
        if (model->columnCount(index) == 0) {
            if (!model->insertColumn(0, index))
    //chech if the index is valid from the view ,if not then its at the rootnode anyway
        if ( !index.isValid() )
            if (!model->insertRow(0, index))      
            child = model->index(0, 0, index); //Column index 0
            model->setData(child, QVariant( "[Top at root]"  ), Qt::EditRole);
    //otherwise force adding off root
        if (!model->insertRow(0, QModelIndex()))       return;
       // or could also use :
     //if (!model->insertRow(0, indexRoot))       return;
        child = model->index(0, 0, QModelIndex()); //Column index 0
        model->setData(child, QVariant( "[Top at root]"  ), Qt::EditRole);
    // but where to realy insert with knowledge of the selections top root child?

  • Lifetime Qt Champion

    Each index that is in a branch has a parent so basically you have to loop until the parent is null then you have the start index of your branch.

  • Cool, Thanks for all the insite: I have solved the problem with a little more testing.
    For the sake of completeness and for others Ive included my code:

    void DialogStructureXML::on_btn_add_toroot_released()
        QModelIndex currentIndex    = ui->tree->selectionModel()->currentIndex();
        QModelIndex rootIndex       = ui->tree->rootIndex();
        QModelIndex traceIndex      = currentIndex;
        QModelIndex child           = currentIndex;
        tree_model *model = (tree_model*) ui->tree->model();
        int rowCount = model->rowCount();
        int currentRow = 0;
        int prevRow = 0;
        //some string cleanup
        QString ItemText = ui->edit_textvaluefortree->text() ;
        //If its a valid index (ie: valid something in the GUI tree) trace back to the parent
        if ( traceIndex.isValid() ) {  
                while (  traceIndex.isValid() ) {
                    currentRow = traceIndex.row()+1;
                    traceIndex = model->parent(traceIndex);
        if (!model->insertRow(currentRow, rootIndex))       return;
        child = model->index(currentRow, 0, rootIndex); //Column index 0
        model->setData(child, QVariant( ItemText  ), Qt::EditRole);