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. QTreeView indent entire row
Forum Updated to NodeBB v4.3 + New Features

QTreeView indent entire row

Scheduled Pinned Locked Moved Unsolved General and Desktop
qtreeviewindentaion
4 Posts 3 Posters 4.5k Views 2 Watching
  • 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.
  • Joel BodenmannJ Offline
    Joel BodenmannJ Offline
    Joel Bodenmann
    wrote on last edited by Joel Bodenmann
    #1

    I am using a QTreeView with a custom QAbstractItemModel. My items can have children. If an item has one or more children, the tree view automatically indents the item of of the first column of the row.
    What is the correct way to make the view indent the entire row? I'd like that each item of that row (so each column so to speak) gets additional indentation relative to the parent item.

    Screenshot for reference:
    I'd like that the items of the columns Priority and Description are indented as well.

    Industrial process automation software: https://simulton.com
    Embedded Graphics & GUI library: https://ugfx.io

    1 Reply Last reply
    0
    • Chris KawaC Offline
      Chris KawaC Offline
      Chris Kawa
      Lifetime Qt Champion
      wrote on last edited by
      #2

      I don't think there's a built-in way to do that, but you can use a QStyledItemDelegate derived item delegate with paint method like this:

      void MyCustomDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override
      {
          //if it's column 0 just draw the original
          if (index.column() == 0)
          {
              QStyledItemDelegate::paint(painter, option, index);
              return;
          }
      
          //get the style to draw with
          QStyle* style = option.widget ? option.widget->style() : QApplication::style();
      
          //calculate tree level
          int level = 0;
          for(auto i = index; (i = i.parent()).isValid(); level++);
      
          //calculate indentation
          auto view = qobject_cast<const QTreeView*>(option.widget);
          int indent = level * (view ? view->indentation() : 20 ); //some arbitrary default value
      
          //create a styled option object
          QStyleOptionViewItem opt = option;
          QStyledItemDelegate::initStyleOption(&opt, index);
      
          //draw indented item
          opt.rect.adjust(indent, 0, 0, 0);
          style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, option.widget);
      
          //fill the gap space
          opt.rect = option.rect;
          opt.rect.setWidth(indent);
          opt.text.clear(); //remove text
          opt.viewItemPosition = QStyleOptionViewItem::Middle; //remove selection frame sides
          style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, option.widget);
      }
      
      Joel BodenmannJ 1 Reply Last reply
      5
      • Chris KawaC Chris Kawa

        I don't think there's a built-in way to do that, but you can use a QStyledItemDelegate derived item delegate with paint method like this:

        void MyCustomDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override
        {
            //if it's column 0 just draw the original
            if (index.column() == 0)
            {
                QStyledItemDelegate::paint(painter, option, index);
                return;
            }
        
            //get the style to draw with
            QStyle* style = option.widget ? option.widget->style() : QApplication::style();
        
            //calculate tree level
            int level = 0;
            for(auto i = index; (i = i.parent()).isValid(); level++);
        
            //calculate indentation
            auto view = qobject_cast<const QTreeView*>(option.widget);
            int indent = level * (view ? view->indentation() : 20 ); //some arbitrary default value
        
            //create a styled option object
            QStyleOptionViewItem opt = option;
            QStyledItemDelegate::initStyleOption(&opt, index);
        
            //draw indented item
            opt.rect.adjust(indent, 0, 0, 0);
            style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, option.widget);
        
            //fill the gap space
            opt.rect = option.rect;
            opt.rect.setWidth(indent);
            opt.text.clear(); //remove text
            opt.viewItemPosition = QStyleOptionViewItem::Middle; //remove selection frame sides
            style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, option.widget);
        }
        
        Joel BodenmannJ Offline
        Joel BodenmannJ Offline
        Joel Bodenmann
        wrote on last edited by Joel Bodenmann
        #3

        I'm not sure how to thank you for this. Your code works out of the box. Nothing left for me to do :D

        The only question I have is: Can I use this new IndentationDelegate together with my own custom delegates? I see that your code ultimately uses the default delegates. How can I make this work with my own delegates?

            _myTree->setItemDelegateForColumn(1, new PriorityComboboxDelegate(_todoItemsManager));
            _myTree->setItemDelegateForColumn(1, new IndentationItemDelegate);
        

        I know that this can't work that way. It's just to illustrate what I want to be doing. I'd like the IndentationDelegate to be able to use my own custom delegate and just add indentation like it currently works with the "built-in" delegates.

        Thank you very much, I appreciate it a lot!

        Industrial process automation software: https://simulton.com
        Embedded Graphics & GUI library: https://ugfx.io

        raven-worxR 1 Reply Last reply
        0
        • Joel BodenmannJ Joel Bodenmann

          I'm not sure how to thank you for this. Your code works out of the box. Nothing left for me to do :D

          The only question I have is: Can I use this new IndentationDelegate together with my own custom delegates? I see that your code ultimately uses the default delegates. How can I make this work with my own delegates?

              _myTree->setItemDelegateForColumn(1, new PriorityComboboxDelegate(_todoItemsManager));
              _myTree->setItemDelegateForColumn(1, new IndentationItemDelegate);
          

          I know that this can't work that way. It's just to illustrate what I want to be doing. I'd like the IndentationDelegate to be able to use my own custom delegate and just add indentation like it currently works with the "built-in" delegates.

          Thank you very much, I appreciate it a lot!

          raven-worxR Offline
          raven-worxR Offline
          raven-worx
          Moderators
          wrote on last edited by
          #4

          @Joel-Bodenmann said:

          How can I make this work with my own delegates?

          each index can max only have 1 delegate. Thus you need to merge the code into your own delegate.
          Since you also receive a QModelIndex in the most methods of the delegate you need to check the column there.

          --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
          If you have a question please use the forum so others can benefit from the solution in the future

          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