mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-27 17:06:32 +00:00
Move RDToolTip into separate file independent of tree view
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
/******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2026 Baldur Karlsson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include "RDToolTip.h"
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
#include <QMouseEvent>
|
||||
#include <QProxyStyle>
|
||||
#include <QStyleOptionFrame>
|
||||
#include <QStylePainter>
|
||||
|
||||
void ICustomToolTipDisplay::showTip(QWidget *widget, QString text, QModelIndex idx)
|
||||
{
|
||||
QPoint p = QCursor::pos();
|
||||
|
||||
// estimate, as this is not easily queryable
|
||||
const QPoint cursorSize(16, 16);
|
||||
const QRect screenAvailGeom = QApplication::desktop()->availableGeometry(p);
|
||||
|
||||
// start with the tooltip placed bottom-right of the cursor, as the default
|
||||
QRect tooltipRect;
|
||||
tooltipRect.setTopLeft(p + cursorSize);
|
||||
tooltipRect.setSize(configureTip(widget, text, idx));
|
||||
|
||||
// clip by the available geometry in x
|
||||
if(tooltipRect.right() > screenAvailGeom.right())
|
||||
tooltipRect.moveRight(screenAvailGeom.right());
|
||||
|
||||
// if we'd go out of bounds in y, place the tooltip above the cursor. Don't just clip like
|
||||
// in x, because that could place the tooltip over the cursor.
|
||||
if(tooltipRect.bottom() > screenAvailGeom.bottom())
|
||||
tooltipRect.moveBottom(p.y() - cursorSize.y());
|
||||
|
||||
showTipAtPos(tooltipRect.topLeft());
|
||||
}
|
||||
|
||||
RDToolTip::RDToolTip(QWidget *listener) : QLabel(NULL), mouseListener(listener)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
QSize RDToolTip::configureTip(QWidget *, QString text, QModelIndex)
|
||||
{
|
||||
setText(text);
|
||||
QSize ret = minimumSizeHint();
|
||||
resize(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void RDToolTip::showTipAtPos(QPoint pos)
|
||||
{
|
||||
move(pos);
|
||||
show();
|
||||
}
|
||||
|
||||
bool RDToolTip::forceTip(QWidget *widget, QModelIndex idx)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void RDToolTip::paintEvent(QPaintEvent *ev)
|
||||
{
|
||||
QStylePainter p(this);
|
||||
QStyleOptionFrame opt;
|
||||
opt.init(this);
|
||||
p.drawPrimitive(QStyle::PE_PanelTipLabel, opt);
|
||||
p.end();
|
||||
|
||||
QLabel::paintEvent(ev);
|
||||
}
|
||||
|
||||
void RDToolTip::mousePressEvent(QMouseEvent *e)
|
||||
{
|
||||
if(mouseListener)
|
||||
sendListenerEvent(e);
|
||||
}
|
||||
|
||||
void RDToolTip::sendListenerEvent(QMouseEvent *e)
|
||||
{
|
||||
QMouseEvent *duplicate =
|
||||
new QMouseEvent(e->type(), mouseListener->mapFromGlobal(e->globalPos()), e->windowPos(),
|
||||
e->globalPos(), e->button(), e->buttons(), e->modifiers(), e->source());
|
||||
QCoreApplication::postEvent(mouseListener, duplicate);
|
||||
}
|
||||
|
||||
void RDToolTip::mouseReleaseEvent(QMouseEvent *e)
|
||||
{
|
||||
if(mouseListener)
|
||||
sendListenerEvent(e);
|
||||
}
|
||||
|
||||
void RDToolTip::mouseDoubleClickEvent(QMouseEvent *e)
|
||||
{
|
||||
if(mouseListener)
|
||||
sendListenerEvent(e);
|
||||
}
|
||||
|
||||
void RDToolTip::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);
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2026 Baldur Karlsson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QLabel>
|
||||
#include <QModelIndex>
|
||||
|
||||
struct ICustomToolTipDisplay
|
||||
{
|
||||
public:
|
||||
virtual void hideTip() = 0;
|
||||
virtual QSize configureTip(QWidget *widget, QString text, QModelIndex idx = QModelIndex()) = 0;
|
||||
virtual void showTipAtPos(QPoint pos) = 0;
|
||||
virtual bool forceTip(QWidget *widget, QModelIndex idx) = 0;
|
||||
void showTip(QWidget *widget, QString text, QModelIndex idx = QModelIndex());
|
||||
};
|
||||
|
||||
class RDToolTip : public QLabel, public ICustomToolTipDisplay
|
||||
{
|
||||
private:
|
||||
Q_OBJECT
|
||||
|
||||
QWidget *mouseListener;
|
||||
|
||||
public:
|
||||
explicit RDToolTip(QWidget *listener = NULL);
|
||||
|
||||
void hideTip() { hide(); }
|
||||
QSize configureTip(QWidget *widget, QString text, QModelIndex idx = QModelIndex());
|
||||
void showTipAtPos(QPoint pos);
|
||||
bool forceTip(QWidget *widget, QModelIndex idx);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *);
|
||||
void mousePressEvent(QMouseEvent *);
|
||||
void mouseReleaseEvent(QMouseEvent *);
|
||||
void mouseDoubleClickEvent(QMouseEvent *);
|
||||
void resizeEvent(QResizeEvent *);
|
||||
|
||||
void sendListenerEvent(QMouseEvent *e);
|
||||
};
|
||||
@@ -26,16 +26,13 @@
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
#include <QContextMenuEvent>
|
||||
#include <QDesktopWidget>
|
||||
#include <QHeaderView>
|
||||
#include <QLabel>
|
||||
#include <QMenu>
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <QProxyStyle>
|
||||
#include <QScrollBar>
|
||||
#include <QStack>
|
||||
#include <QStylePainter>
|
||||
#include <QWheelEvent>
|
||||
#include "Code/QRDUtils.h"
|
||||
#include "Code/Resources.h"
|
||||
@@ -117,87 +114,6 @@ QSize RDTreeViewDelegate::sizeHint(const QStyleOptionViewItem &option, const QMo
|
||||
return ret;
|
||||
}
|
||||
|
||||
RDTipLabel::RDTipLabel(QWidget *listener) : QLabel(NULL), mouseListener(listener)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
QSize RDTipLabel::configureTip(QWidget *, QModelIndex, QString text)
|
||||
{
|
||||
setText(text);
|
||||
return minimumSizeHint();
|
||||
}
|
||||
|
||||
void RDTipLabel::showTip(QPoint pos)
|
||||
{
|
||||
move(pos);
|
||||
show();
|
||||
}
|
||||
|
||||
bool RDTipLabel::forceTip(QWidget *widget, QModelIndex idx)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
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::mousePressEvent(QMouseEvent *e)
|
||||
{
|
||||
if(mouseListener)
|
||||
sendListenerEvent(e);
|
||||
}
|
||||
|
||||
void RDTipLabel::sendListenerEvent(QMouseEvent *e)
|
||||
{
|
||||
QMouseEvent *duplicate =
|
||||
new QMouseEvent(e->type(), mouseListener->mapFromGlobal(e->globalPos()), e->windowPos(),
|
||||
e->globalPos(), e->button(), e->buttons(), e->modifiers(), e->source());
|
||||
QCoreApplication::postEvent(mouseListener, duplicate);
|
||||
}
|
||||
|
||||
void RDTipLabel::mouseReleaseEvent(QMouseEvent *e)
|
||||
{
|
||||
if(mouseListener)
|
||||
sendListenerEvent(e);
|
||||
}
|
||||
|
||||
void RDTipLabel::mouseDoubleClickEvent(QMouseEvent *e)
|
||||
{
|
||||
if(mouseListener)
|
||||
sendListenerEvent(e);
|
||||
}
|
||||
|
||||
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(parent)
|
||||
{
|
||||
setMouseTracking(true);
|
||||
@@ -205,7 +121,7 @@ RDTreeView::RDTreeView(QWidget *parent) : QTreeView(parent)
|
||||
m_delegate = new RDTreeViewDelegate(this);
|
||||
QTreeView::setItemDelegate(m_delegate);
|
||||
|
||||
m_TooltipLabel = new RDTipLabel(viewport());
|
||||
m_TooltipLabel = new RDToolTip(viewport());
|
||||
m_TooltipLabel->hide();
|
||||
m_CurrentTooltipElided = false;
|
||||
|
||||
@@ -258,27 +174,7 @@ void RDTreeView::mouseMoveEvent(QMouseEvent *e)
|
||||
// We don't use QToolTip since we have a custom tooltip for showing elided results, and we
|
||||
// use that for consistency. This also makes it easier to slot in a custom tooltip widget
|
||||
// externally.
|
||||
QPoint p = QCursor::pos();
|
||||
|
||||
// estimate, as this is not easily queryable
|
||||
const QPoint cursorSize(16, 16);
|
||||
const QRect screenAvailGeom = QApplication::desktop()->availableGeometry(p);
|
||||
|
||||
// start with the tooltip placed bottom-right of the cursor, as the default
|
||||
QRect tooltipRect;
|
||||
tooltipRect.setTopLeft(p + cursorSize);
|
||||
tooltipRect.setSize(m_Tooltip->configureTip(this, m_currentHoverIndex, tooltip));
|
||||
|
||||
// clip by the available geometry in x
|
||||
if(tooltipRect.right() > screenAvailGeom.right())
|
||||
tooltipRect.moveRight(screenAvailGeom.right());
|
||||
|
||||
// if we'd go out of bounds in y, place the tooltip above the cursor. Don't just clip like
|
||||
// in x, because that could place the tooltip over the cursor.
|
||||
if(tooltipRect.bottom() > screenAvailGeom.bottom())
|
||||
tooltipRect.moveBottom(p.y() - cursorSize.y());
|
||||
|
||||
m_Tooltip->showTip(tooltipRect.topLeft());
|
||||
m_Tooltip->showTip(this, tooltip, m_currentHoverIndex);
|
||||
m_CurrentTooltipElided = false;
|
||||
}
|
||||
}
|
||||
@@ -459,8 +355,8 @@ bool RDTreeView::viewportEvent(QEvent *event)
|
||||
// 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_Tooltip->configureTip(this, index, fullText);
|
||||
m_Tooltip->showTip(viewport()->mapToGlobal(option.rect.topLeft()));
|
||||
m_Tooltip->configureTip(this, fullText, index);
|
||||
m_Tooltip->showTipAtPos(viewport()->mapToGlobal(option.rect.topLeft()));
|
||||
m_CurrentTooltipElided = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QTreeView>
|
||||
#include "Code/QRDUtils.h"
|
||||
#include "RDToolTip.h"
|
||||
|
||||
class RDTreeView;
|
||||
|
||||
@@ -47,40 +48,6 @@ public:
|
||||
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
};
|
||||
|
||||
struct ITreeViewTipDisplay
|
||||
{
|
||||
public:
|
||||
virtual void hideTip() = 0;
|
||||
virtual QSize configureTip(QWidget *widget, QModelIndex idx, QString text) = 0;
|
||||
virtual void showTip(QPoint pos) = 0;
|
||||
virtual bool forceTip(QWidget *widget, QModelIndex idx) = 0;
|
||||
};
|
||||
|
||||
class RDTipLabel : public QLabel, public ITreeViewTipDisplay
|
||||
{
|
||||
private:
|
||||
Q_OBJECT
|
||||
|
||||
QWidget *mouseListener;
|
||||
|
||||
public:
|
||||
explicit RDTipLabel(QWidget *listener = NULL);
|
||||
|
||||
void hideTip() { hide(); }
|
||||
QSize configureTip(QWidget *widget, QModelIndex idx, QString text);
|
||||
void showTip(QPoint pos);
|
||||
bool forceTip(QWidget *widget, QModelIndex idx);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *);
|
||||
void mousePressEvent(QMouseEvent *);
|
||||
void mouseReleaseEvent(QMouseEvent *);
|
||||
void mouseDoubleClickEvent(QMouseEvent *);
|
||||
void resizeEvent(QResizeEvent *);
|
||||
|
||||
void sendListenerEvent(QMouseEvent *e);
|
||||
};
|
||||
|
||||
typedef std::function<uint(QModelIndex, uint)> ExpansionKeyGen;
|
||||
|
||||
class RDTreeView : public QTreeView
|
||||
@@ -116,7 +83,7 @@ public:
|
||||
void setItemDelegate(QAbstractItemDelegate *delegate);
|
||||
QAbstractItemDelegate *itemDelegate() const;
|
||||
|
||||
void setCustomTooltip(ITreeViewTipDisplay *tip)
|
||||
void setCustomTooltip(ICustomToolTipDisplay *tip)
|
||||
{
|
||||
m_Tooltip = tip;
|
||||
m_TooltipElidedItems = false;
|
||||
@@ -230,8 +197,8 @@ private:
|
||||
QAbstractItemDelegate *m_userDelegate = NULL;
|
||||
RDTreeViewDelegate *m_delegate;
|
||||
|
||||
RDTipLabel *m_TooltipLabel;
|
||||
ITreeViewTipDisplay *m_Tooltip;
|
||||
RDToolTip *m_TooltipLabel;
|
||||
ICustomToolTipDisplay *m_Tooltip;
|
||||
bool m_CurrentTooltipElided = false;
|
||||
|
||||
int m_VertMargin = 6;
|
||||
|
||||
Reference in New Issue
Block a user