diff --git a/qrenderdoc/Code/QRDUtils.h b/qrenderdoc/Code/QRDUtils.h index 27b183b64..938a616ef 100644 --- a/qrenderdoc/Code/QRDUtils.h +++ b/qrenderdoc/Code/QRDUtils.h @@ -32,6 +32,7 @@ #include #include #include +#include #include "Code/Interface/QRDInterface.h" template @@ -258,6 +259,113 @@ private: QDir::Filters m_requireMask, m_excludeMask; }; +// Simple QStyledItemDelegate child that will either forward to an external delegate (allowing +// chaining) or to the base implementation. Delegates can derive from this and specialise a couple +// of functions to still be able to chain +class ForwardingDelegate : public QStyledItemDelegate +{ + Q_OBJECT +public: + explicit ForwardingDelegate(QObject *parent = NULL) : QStyledItemDelegate(parent) {} + ~ForwardingDelegate() {} + void setForwardDelegate(QAbstractItemDelegate *real) { m_delegate = real; } + void paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const override + { + if(m_delegate) + return m_delegate->paint(painter, option, index); + + return QStyledItemDelegate::paint(painter, option, index); + } + + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override + { + if(m_delegate) + return m_delegate->sizeHint(option, index); + + return QStyledItemDelegate::sizeHint(option, index); + } + + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, + const QModelIndex &index) const override + { + if(m_delegate) + return m_delegate->createEditor(parent, option, index); + + return QStyledItemDelegate::createEditor(parent, option, index); + } + + void destroyEditor(QWidget *editor, const QModelIndex &index) const override + { + if(m_delegate) + return m_delegate->destroyEditor(editor, index); + + return QStyledItemDelegate::destroyEditor(editor, index); + } + + void setEditorData(QWidget *editor, const QModelIndex &index) const override + { + if(m_delegate) + return m_delegate->setEditorData(editor, index); + + return QStyledItemDelegate::setEditorData(editor, index); + } + + void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override + { + if(m_delegate) + return m_delegate->setModelData(editor, model, index); + + return QStyledItemDelegate::setModelData(editor, model, index); + } + + void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, + const QModelIndex &index) const override + { + if(m_delegate) + return m_delegate->updateEditorGeometry(editor, option, index); + + return QStyledItemDelegate::updateEditorGeometry(editor, option, index); + } + + bool eventFilter(QObject *watched, QEvent *event) override + { + if(m_delegate) + return m_delegate->eventFilter(watched, event); + + return QStyledItemDelegate::eventFilter(watched, event); + } + + bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, + const QModelIndex &index) override + { + if(m_delegate) + return m_delegate->editorEvent(event, model, option, index); + + return QStyledItemDelegate::editorEvent(event, model, option, index); + } + + bool helpEvent(QHelpEvent *event, QAbstractItemView *view, const QStyleOptionViewItem &option, + const QModelIndex &index) override + { + if(m_delegate) + return m_delegate->helpEvent(event, view, option, index); + + return QStyledItemDelegate::helpEvent(event, view, option, index); + } + + QVector paintingRoles() const override + { + if(m_delegate) + return m_delegate->paintingRoles(); + + return QStyledItemDelegate::paintingRoles(); + } + +private: + QAbstractItemDelegate *m_delegate = NULL; +}; + class QMenu; // helper for doing a manual blocking invoke of a dialog diff --git a/qrenderdoc/Widgets/Extended/RDTreeView.cpp b/qrenderdoc/Widgets/Extended/RDTreeView.cpp index dddeae2a6..93ba0cb82 100644 --- a/qrenderdoc/Widgets/Extended/RDTreeView.cpp +++ b/qrenderdoc/Widgets/Extended/RDTreeView.cpp @@ -31,33 +31,15 @@ #include #include -RDTreeViewDelegate::RDTreeViewDelegate(RDTreeView *view) : QStyledItemDelegate(view), m_View(view) +RDTreeViewDelegate::RDTreeViewDelegate(RDTreeView *view) : ForwardingDelegate(view), m_View(view) { } QSize RDTreeViewDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { - QSize ret; - - QVariant var = index.data(Qt::SizeHintRole); - if(var.canConvert()) - { - ret = var.value(); - } - else - { - QStyleOptionViewItem opt = option; - initStyleOption(&opt, index); - - if(m_View->ignoreIconSize()) - { - opt.icon = QIcon(); - opt.features &= ~QStyleOptionViewItem::HasDecoration; - opt.decorationSize = QSize(); - } - - ret = m_View->style()->sizeFromContents(QStyle::CT_ItemViewItem, &opt, QSize(), m_View); - } + m_suppressIcon = m_View->ignoreIconSize(); + QSize ret = ForwardingDelegate::sizeHint(option, index); + m_suppressIcon = false; // expand a pixel for the grid lines if(m_View->visibleGridLines()) @@ -73,6 +55,18 @@ QSize RDTreeViewDelegate::sizeHint(const QStyleOptionViewItem &option, const QMo return ret; } +void RDTreeViewDelegate::initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const +{ + QStyledItemDelegate::initStyleOption(option, index); + + if(m_suppressIcon) + { + option->icon = QIcon(); + option->features &= ~QStyleOptionViewItem::HasDecoration; + option->decorationSize = QSize(); + } +} + RDTipLabel::RDTipLabel() : QLabel(NULL) { int margin = style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth, NULL, this); @@ -115,7 +109,8 @@ RDTreeView::RDTreeView(QWidget *parent) : QTreeView(parent) { setMouseTracking(true); - setItemDelegate(new RDTreeViewDelegate(this)); + m_delegate = new RDTreeViewDelegate(this); + QTreeView::setItemDelegate(m_delegate); m_ElidedTooltip = new RDTipLabel(); m_ElidedTooltip->hide(); @@ -157,7 +152,11 @@ bool RDTreeView::viewportEvent(QEvent *event) QHelpEvent *he = (QHelpEvent *)event; QModelIndex index = indexAt(he->pos()); - QAbstractItemDelegate *delegate = itemDelegate(index); + QAbstractItemDelegate *delegate = m_userDelegate; + + if(!delegate) + delegate = QTreeView::itemDelegate(index); + if(delegate) { QStyleOptionViewItem option; @@ -190,6 +189,17 @@ bool RDTreeView::viewportEvent(QEvent *event) return QTreeView::viewportEvent(event); } +void RDTreeView::setItemDelegate(QAbstractItemDelegate *delegate) +{ + m_userDelegate = delegate; + m_delegate->setForwardDelegate(m_userDelegate); +} + +QAbstractItemDelegate *RDTreeView::itemDelegate() const +{ + return m_userDelegate; +} + void RDTreeView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) { m_currentHoverIndex = QModelIndex(); diff --git a/qrenderdoc/Widgets/Extended/RDTreeView.h b/qrenderdoc/Widgets/Extended/RDTreeView.h index 7adaf0236..72bf535e2 100644 --- a/qrenderdoc/Widgets/Extended/RDTreeView.h +++ b/qrenderdoc/Widgets/Extended/RDTreeView.h @@ -27,19 +27,28 @@ #include #include #include +#include "Code/QRDUtils.h" class RDTreeView; -class RDTreeViewDelegate : public QStyledItemDelegate +class RDTreeViewDelegate : public ForwardingDelegate { private: Q_OBJECT + // I hate the mutable keyword, but it's necessary to modify it inside sizeHint to access in + // initStyleOption. There's no other way to only remove the icon while in sizeHint, and not in + // other places that call initStyleOption. We don't want to try and manually init, since if + // there's a forwarded delegate it might do something different. + mutable bool m_suppressIcon = false; RDTreeView *m_View; public: RDTreeViewDelegate(RDTreeView *view); QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; + +protected: + void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const override; }; class RDTipLabel : public QLabel @@ -76,6 +85,9 @@ public: int verticalItemMargin() { return m_VertMargin; } void setIgnoreIconSize(bool ignore) { m_IgnoreIconSize = ignore; } bool ignoreIconSize() { return m_IgnoreIconSize; } + void setItemDelegate(QAbstractItemDelegate *delegate); + QAbstractItemDelegate *itemDelegate() const; + protected: void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) override; void mouseMoveEvent(QMouseEvent *e) override; @@ -96,6 +108,9 @@ private: bool m_VisibleGridLines = true; bool m_TooltipElidedItems = true; + QAbstractItemDelegate *m_userDelegate = NULL; + RDTreeViewDelegate *m_delegate; + RDTipLabel *m_ElidedTooltip; int m_VertMargin = 6;