From a292838f4330d670ed90571909e22b23b0319737 Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 9 Jun 2017 18:41:21 +0100 Subject: [PATCH] Add a custom tooltip to display elided data in RDTreeViews --- qrenderdoc/Widgets/Extended/RDTreeView.cpp | 97 ++++++++++++++++++++++ qrenderdoc/Widgets/Extended/RDTreeView.h | 24 ++++++ 2 files changed, 121 insertions(+) diff --git a/qrenderdoc/Widgets/Extended/RDTreeView.cpp b/qrenderdoc/Widgets/Extended/RDTreeView.cpp index 267863a90..994e452a4 100644 --- a/qrenderdoc/Widgets/Extended/RDTreeView.cpp +++ b/qrenderdoc/Widgets/Extended/RDTreeView.cpp @@ -23,9 +23,12 @@ ******************************************************************************/ #include "RDTreeView.h" +#include #include #include #include +#include +#include RDTreeViewDelegate::RDTreeViewDelegate(RDTreeView *view) : QStyledItemDelegate(view), m_View(view) { @@ -49,21 +52,115 @@ QSize RDTreeViewDelegate::sizeHint(const QStyleOptionViewItem &option, const QMo return ret; } +RDTipLabel::RDTipLabel() : QLabel(NULL) +{ + int margin = style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth, NULL, this); + int opacity = style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, NULL, this); + + setWindowFlags(Qt::ToolTip); + setAttribute(Qt::WA_TransparentForMouseEvents); + setForegroundRole(QPalette::ToolTipText); + setBackgroundRole(QPalette::ToolTipBase); + setMargin(margin + 1); + setFrameStyle(QFrame::NoFrame); + setAlignment(Qt::AlignLeft); + setIndent(1); + setWindowOpacity(opacity / 255.0); +} + +void RDTipLabel::paintEvent(QPaintEvent *ev) +{ + QStylePainter p(this); + QStyleOptionFrame opt; + opt.init(this); + p.drawPrimitive(QStyle::PE_PanelTipLabel, opt); + p.end(); + + QLabel::paintEvent(ev); +} + +void RDTipLabel::resizeEvent(QResizeEvent *e) +{ + QStyleHintReturnMask frameMask; + QStyleOption option; + option.init(this); + if(style()->styleHint(QStyle::SH_ToolTip_Mask, &option, this, &frameMask)) + setMask(frameMask.region); + + QLabel::resizeEvent(e); +} + RDTreeView::RDTreeView(QWidget *parent) : QTreeView(NULL) { setMouseTracking(true); setItemDelegate(new RDTreeViewDelegate(this)); + + m_ElidedTooltip = new RDTipLabel(); + m_ElidedTooltip->hide(); +} + +RDTreeView::~RDTreeView() +{ + delete m_ElidedTooltip; } void RDTreeView::mouseMoveEvent(QMouseEvent *e) { + if(m_ElidedTooltip->isVisible() && !m_ElidedTooltip->geometry().contains(QCursor::pos())) + m_ElidedTooltip->hide(); + m_currentHoverIndex = indexAt(e->pos()); + QTreeView::mouseMoveEvent(e); } void RDTreeView::leaveEvent(QEvent *e) { + if(m_ElidedTooltip->isVisible() && !m_ElidedTooltip->geometry().contains(QCursor::pos())) + m_ElidedTooltip->hide(); + m_currentHoverIndex = QModelIndex(); + QTreeView::leaveEvent(e); +} + +bool RDTreeView::viewportEvent(QEvent *event) +{ + if(m_TooltipElidedItems && event->type() == QEvent::ToolTip) + { + QHelpEvent *he = (QHelpEvent *)event; + QModelIndex index = indexAt(he->pos()); + + QAbstractItemDelegate *delegate = itemDelegate(index); + if(delegate) + { + QStyleOptionViewItem option; + option.initFrom(this); + option.rect = visualRect(index); + + // delegates get first dibs at processing the event + bool ret = delegate->helpEvent(he, this, option, index); + + if(ret) + return true; + + QSize desiredSize = delegate->sizeHint(option, index); + + if(desiredSize.width() > option.rect.width()) + { + const QString fullText = index.data(Qt::DisplayRole).toString(); + if(!fullText.isEmpty()) + { + // need to use a custom label tooltip since the QToolTip freaks out as we're placing it + // underneath the cursor instead of next to it (so that the tooltip lines up over the row) + m_ElidedTooltip->move(viewport()->mapToGlobal(option.rect.topLeft())); + m_ElidedTooltip->setText(fullText); + m_ElidedTooltip->show(); + } + } + } + } + + return QTreeView::viewportEvent(event); } void RDTreeView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) diff --git a/qrenderdoc/Widgets/Extended/RDTreeView.h b/qrenderdoc/Widgets/Extended/RDTreeView.h index 3ad48dbc7..3b0e63606 100644 --- a/qrenderdoc/Widgets/Extended/RDTreeView.h +++ b/qrenderdoc/Widgets/Extended/RDTreeView.h @@ -24,6 +24,7 @@ #pragma once +#include #include #include @@ -41,22 +42,42 @@ public: QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; }; +class RDTipLabel : public QLabel +{ +private: + Q_OBJECT + + int m_TooltipMargin = 0; + +public: + explicit RDTipLabel(); + + int tipMargin() { return m_TooltipMargin; } +protected: + void paintEvent(QPaintEvent *); + void resizeEvent(QResizeEvent *); +}; + class RDTreeView : public QTreeView { Q_OBJECT public: explicit RDTreeView(QWidget *parent = 0); + virtual ~RDTreeView(); void showBranches() { m_VisibleBranches = true; } void hideBranches() { m_VisibleBranches = false; } void showGridLines() { m_VisibleGridLines = true; } void hideGridLines() { m_VisibleGridLines = false; } + void setTooltipElidedItems(bool tool) { m_TooltipElidedItems = tool; } + bool tooltipElidedItems() { return m_TooltipElidedItems; } void setItemVerticalMargin(int vertical) { m_VertMargin = vertical; } int verticalItemMargin() { return m_VertMargin; } protected: void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) override; void mouseMoveEvent(QMouseEvent *e) override; void leaveEvent(QEvent *e) override; + bool viewportEvent(QEvent *event) override; void drawRow(QPainter *painter, const QStyleOptionViewItem &options, const QModelIndex &index) const override; @@ -69,6 +90,9 @@ protected: private: bool m_VisibleBranches = true; bool m_VisibleGridLines = true; + bool m_TooltipElidedItems = true; + + RDTipLabel *m_ElidedTooltip; int m_VertMargin = 6;