Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Changing headerData in QTreeView depending on selection



  • Hi,

    i have a QTreeView, that shows some model derived from QAbstractItemModel.
    now i want to show different headerData on the TreeView depending on which type of Item in the view is selected.
    How do i implement this?

    My problem is, that normally MyTreeModel does not know the TreeView and therefore I do not know where to get the selection information from.

    I have tried to get the inof directly from the view, which kind of works, however when using a QSortFilterProxyModel it will crash.

    QVariant MyTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
    {
        if(m_root_item != NULL){
            if (orientation == Qt::Horizontal && role == Qt::DisplayRole){
    
                // getting the current item from a pointer to the view stored in the model
                // this seems to be kind of a bad idea
                QModelIndex index = m_tree_view->currentIndex();
    
                if(!index.isValid()){
                    return QVariant();
                }
                
                Item* item_selected = static_cast<Item*>(index.internalPointer());
                if(item_selected != NULL){
                    std::string value;
                    value = item_selected->getHeader(section);
                    return QVariant(value.c_str());
                }
            }
        }
        return QVariant();
    }
    
    what is the right way to implement this?
    

  • Qt Champions 2019

    Why not listening on QTreeView::selectionChanged somewhere and adjust the header data the way you need it?



  • @Christian-Ehrlicher Thanks for the hint.

    The easiest way to implement this i can imagine atm is something as follows:

    • A slot in MyTreeView that is called when selection changes.
    • From there i call the TreeModel::data() for the current index and add a new role to get the headerData from the items.
    • Then i call setHeaderData for all the columns and store the data in the TreeModel.
    • This data is returned when headerData() is called.

    I guess this will work, however it sound not like the straight forward approach for such a common application?


  • Qt Champions 2019

    This is also the way I would solve it. But I don't see this as a common situation. I've no application in mind which changes the header based on the current (selected) index ...



  • If you have a working implementation of setHeaderData and headerData in your model you can just:

    QObject::connect(treeView->selectionModel(),&QItemSelectionModel::selectionChanged,treeView->model(),[=](const QItemSelection &selected, const QItemSelection &deselected)->void{
    const auto selectedIndexes = selected.indexes();
    const auto deselectedIndexes = deselected.indexes();
    for(auto&& idx : selectedIndexes){
    treeView->model()->setHeaderData(idx.column(),Qt::Horizontal,QStringLiteral("%1 Selected").arg(idx.column()));
    }
    for(auto&& idx : deselectedIndexes ){
    treeView->model()->setHeaderData(idx.column(),Qt::Horizontal,QString::number(idx.column()));
    }
    });
    

Log in to reply