Solved Get geometry of a row in QTreeView
-
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.
-
Hi,
Can you provide a minimal compilable example that shows that behaviour ?
-
#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); }); }
-
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))); }
-
@VRonin That works though I had to change
editor->setGeometry(QRect(QPoint(top, left),QPoint(bottom, right)));
toeditor->setGeometry(QRect(QPoint(left, top),QPoint(right, bottom)));