Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Solved Get geometry of a row in QTreeView

    General and Desktop
    3
    5
    559
    Loading More Posts
    • 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.
    • L
      Lurkki last edited by

      I want to be able to make an editor in my custom delegate span all columns on demand. I'm trying to do it with a subclassed QStyledItemDelegate and QTreeView as follows:

          // Subclassed QTreeView
          QRect rowGeometry(const QModelIndex &index) {
              int indent = (index.column() + 1) * indentation();
              int firstSection = header()->logicalIndex(0);
              int lastSection = header()->logicalIndex(header()->count() - 1);
              int left = header()->sectionViewportPosition(firstSection);
              int right = header()->sectionViewportPosition(lastSection) + header()->sectionSize(lastSection);
      
              left += indent;
      
              QPoint rowTopLeft(rect().topLeft().x() + indent, rect().topLeft().y() + rowHeight(index) * (index.row() + 1);
              QRect rec(rect().topLeft(), QSize(right - left, rowHeight(index)));
              return rec;
          }
      
          // Subclassed QStyledItemDelegate
          void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const {
              editor->setGeometry(m_subclassedTreeView->rowGeometry(index));
          }
      

      The result is that the editor doesn't follow the indentation, and is always on row 0. I'm also open to accomplishing this some other way.

      1 Reply Last reply Reply Quote 1
      • SGaist
        SGaist Lifetime Qt Champion last edited by

        Hi,

        Can you provide a minimal compilable example that shows that behaviour ?

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply Reply Quote 0
        • L
          Lurkki last edited by

          #include <QTreeView>
          #include <QHeaderView>
          #include <QStyledItemDelegate>
          #include <QStandardItemModel>
          #include <QVBoxLayout>
          
          class ExpandableTreeView : public QTreeView {
          public:
              ExpandableTreeView(QWidget *parent = nullptr) : QTreeView(parent) {
              }
              void setExpandableIndex(const QModelIndex &index) {m_expandableIndex = index;}
              QRect rowGeometry(const QModelIndex &index) {
                  int indent = (index.column() + 1) * indentation();
                  int firstSection = header()->logicalIndex(0);
                  int lastSection = header()->logicalIndex(header()->count() - 1);
                  int left = header()->sectionViewportPosition(firstSection);
                  int right = header()->sectionViewportPosition(lastSection) + header()->sectionSize(lastSection);
          
                  left += indent;
          
                  QPoint rowTopLeft(rect().topLeft().x() + indent, rect().topLeft().y() + rowHeight(index));
                  QRect rec(rect().topLeft(), QSize(right - left, rowHeight(index)));
                  return rec;
              }
          private:
              QModelIndex m_expandableIndex;
          };
          
          class ExpandableDelegate : public QStyledItemDelegate {
          public:
              ExpandableDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {}
              QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const {
                  return QStyledItemDelegate::sizeHint(option, index);
              }
              void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const {
                  QRect geo = m_eview->rowGeometry(index);
                  editor->setGeometry(geo);
              }
              void setExpandableIndex(const QModelIndex &index) {m_expandableIndex = index;}
              void setExpandableTreeView(ExpandableTreeView *view) {m_eview = view;}
          private:
              QModelIndex m_expandableIndex;
              ExpandableTreeView *m_eview;
          };
          
          MainWindow::MainWindow(QWidget *parent)
              : QMainWindow(parent)
          {
              auto central = new QWidget;
          
              auto lo = new QVBoxLayout;
          
              auto model = new QStandardItemModel;
          
              auto root = model->invisibleRootItem();
          
              auto view = new ExpandableTreeView;
          
              QList <QStandardItem*> rowItems;
              for (int i = 0; i < 3; i++) {
                  auto item = new QStandardItem;
                  item->setText(QString::number(i));
                  rowItems.append(item);
          
                  auto i2 = new QStandardItem;
                  i2->setText(QString::number(i + 1));
                  rowItems.append(i2);
          
          
                  root->appendRow(rowItems);
                  rowItems.clear();
              }
              auto delegate = new ExpandableDelegate;
              delegate->setExpandableTreeView(view);
          
              view->setItemDelegate(delegate);
              view->setModel(model);
          
              lo->addWidget(view);
          
              central->setLayout(lo);
          
              setCentralWidget(central);
          
              connect(view, &ExpandableTreeView::activated, [=](const QModelIndex &index) {
                  delegate->setExpandableIndex(index);
              });
          }
          
          1 Reply Last reply Reply Quote 0
          • VRonin
            VRonin last edited by VRonin

            I think this could be easily solved by just using visualRect() in the delegate:

            void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &, const QModelIndex &index) const {
                const int maxCol = index.model()->columnCount(index.parent());
                QRect tempRect = m_subclassedTreeView->visualRect(index.model()->index(index.row(),0,index.parent()));
                int top = tempRect.top();
                int left = tempRect.left();
                int bottom = tempRect.bottom();
                int right= tempRect.right();
                for(int i = 1;i<maxCol ;++i){
                    tempRect =m_subclassedTreeView->visualRect(index.model()->index(index.row(),i,index.parent()));
                    if(tempRect.top()<top)
                        top = tempRect.top();
                    if(Q_UNLIKELY(tempRect.left()<left))
                        left= tempRect.left();
                    if(tempRect.bottom()>bottom)
                        bottom = tempRect.bottom();
                    if(Q_LIKELY(tempRect.right()>right))
                        right= tempRect.right();
                }
                editor->setGeometry(QRect(QPoint(top,left),QPoint(bottom,right)));
            }
            

            "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

            L 1 Reply Last reply Reply Quote 2
            • L
              Lurkki @VRonin last edited by

              @VRonin That works though I had to change editor->setGeometry(QRect(QPoint(top, left),QPoint(bottom, right))); to editor->setGeometry(QRect(QPoint(left, top),QPoint(right, bottom)));

              1 Reply Last reply Reply Quote 2
              • First post
                Last post