Add ForwardingDelegate for use in RD extended widgets.

* This item delegate will forward on either to a specified other
  delegate or to the base implementation. This allows chaining delegates
  (i.e. having one built-in to the widget, which forwards to a user-set
  delegate).
This commit is contained in:
baldurk
2017-11-14 11:41:23 +00:00
parent 0c1c171b4f
commit 79b51591c2
3 changed files with 158 additions and 25 deletions
+108
View File
@@ -32,6 +32,7 @@
#include <QProcess>
#include <QSemaphore>
#include <QSortFilterProxyModel>
#include <QStyledItemDelegate>
#include "Code/Interface/QRDInterface.h"
template <typename T>
@@ -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<int> 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
+34 -24
View File
@@ -31,33 +31,15 @@
#include <QToolTip>
#include <QWheelEvent>
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<QSize>())
{
ret = var.value<QSize>();
}
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();
+16 -1
View File
@@ -27,19 +27,28 @@
#include <QLabel>
#include <QStyledItemDelegate>
#include <QTreeView>
#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;