16 #include <QAbstractItemView>
18 #include <QApplication>
21 #include <QStyledItemDelegate>
22 #include <QToolButton>
26 class ItemViewOverlayWidget :
public QWidget {
28 ItemViewOverlayWidget(QAbstractItemView* view,
const QModelIndex& index);
30 static int heightForDelegate();
32 void setHover(
bool b);
35 void setHorizontalAlignment(Qt::Alignment a);
38 void enterEvent(QEvent* event)
override;
39 void leaveEvent(QEvent* event)
override;
40 void mouseDoubleClickEvent(QMouseEvent* event)
override;
44 QAbstractItemView* m_view;
46 Qt::Alignment m_horizontalAlignment;
49 class ItemViewOverlayDelegate :
public QStyledItemDelegate {
51 QSize sizeHint(
const QStyleOptionViewItem& option,
const QModelIndex& index)
const override
53 QSize s = QStyledItemDelegate::sizeHint(option, index);
54 if (index.parent().isValid()) {
55 const int h = ItemViewOverlayWidget::heightForDelegate();
56 s.setHeight(std::max(s.height(), h));
63 ItemViewOverlayWidget::ItemViewOverlayWidget(QAbstractItemView* view,
const QModelIndex& index)
68 , m_horizontalAlignment(Qt::AlignRight)
70 setMouseTracking(
true);
71 setFocusPolicy(Qt::NoFocus);
74 void ItemViewOverlayWidget::setHover(
bool b)
79 int ItemViewOverlayWidget::heightForDelegate()
82 const int size = QApplication::style()->pixelMetric(QStyle::PM_ToolBarIconSize);
83 btn.setIconSize(QSize(size, size));
84 return btn.sizeHint().height() + 6;
87 void ItemViewOverlayWidget::enterEvent(QEvent*)
92 void ItemViewOverlayWidget::leaveEvent(QEvent*)
97 void ItemViewOverlayWidget::mouseDoubleClickEvent(QMouseEvent* ev)
99 if (m_view->editTriggers().testFlag(QAbstractItemView::DoubleClicked)
100 && m_index.flags().testFlag(Qt::ItemIsEditable)) {
101 m_view->setIndexWidget(m_index,
nullptr);
102 m_view->edit(m_index);
110 void ItemViewOverlayWidget::create()
112 auto* h1 =
new QHBoxLayout;
114 h1->setContentsMargins(0, 3, 5, 3);
115 h1->setAlignment(m_horizontalAlignment | Qt::AlignTop);
118 for (
auto* a : actions()) {
119 auto* btn =
new QToolButton(
this);
120 btn->setDefaultAction(a);
121 Qt::ToolButtonStyle btnStyle = (Qt::ToolButtonStyle)a->data().toInt();
122 btn->setToolButtonStyle(btnStyle);
124 const int size = style()->pixelMetric(QStyle::PM_ToolBarIconSize);
125 btn->setIconSize(QSize(size, size));
127 if (a->menu() !=
nullptr)
128 btn->setPopupMode(QToolButton::InstantPopup);
137 void ItemViewOverlayWidget::hover(
bool h)
143 if (actions().size() != findChildren<QToolButton*>().size())
145 for (
auto* w : findChildren<QToolButton*>())
148 for (
auto* w : findChildren<QToolButton*>())
153 void ItemViewOverlayWidget::setHorizontalAlignment(Qt::Alignment a)
155 m_horizontalAlignment = a;
163 h->m_getActions = fnGetActions;
165 auto* d =
new ItemViewOverlayDelegate;
166 view->setItemDelegate(d);
167 view->installEventFilter(h);
173 Qt::QueuedConnection);
175 Qt::QueuedConnection);
177 Qt::QueuedConnection);
185 if (event->type() == QEvent::KeyPress) {
186 auto* keyEvent =
dynamic_cast<QKeyEvent*
>(event);
187 if (keyEvent->key() == Qt::Key_F2) {
188 QModelIndex ci =
m_view->currentIndex();
189 if (ci.isValid() && ci.flags().testFlag(Qt::ItemIsEditable))
190 m_view->setIndexWidget(ci,
nullptr);
193 return QObject::eventFilter(obj, event);
203 const auto hoverIfNecessary = [&](QModelIndex index) {
204 QPoint viewPortCoordinatesOfMouse =
m_view->mapFromGlobal(QCursor::pos());
205 if (
m_view->indexAt(viewPortCoordinatesOfMouse) == index)
206 if (
auto* w =
dynamic_cast<ItemViewOverlayWidget*
>(
m_view->indexWidget(index)))
210 if (
m_view->indexWidget(index) ==
nullptr)
212 hoverIfNecessary(index);
214 auto* m =
m_view->model();
215 for (
int childRow = 0; childRow < m->rowCount(index); childRow++)
222 if (
m_view->model() ==
nullptr)
224 auto* m =
m_view->model();
225 for (
int row = 0; row < m->rowCount(); row++)
231 const auto permanentActions =
m_getActions(index,
false);
234 if (permanentActions.isEmpty() && hoverActions.isEmpty())
237 auto* w =
new ItemViewOverlayWidget(
m_view, index);
239 const auto setAlignment = [&](
const QList<QAction*> actions) {
240 w->setHorizontalAlignment(Qt::AlignRight);
241 if (actions.first() ==
nullptr && actions.last() ==
nullptr)
242 w->setHorizontalAlignment(Qt::AlignCenter);
243 else if (actions.first() !=
nullptr && actions.last() ==
nullptr)
244 w->setHorizontalAlignment(Qt::AlignLeft);
247 if (!permanentActions.isEmpty()) {
248 setAlignment(permanentActions);
249 w->addActions(permanentActions);
251 }
else if (!hoverActions.isEmpty()) {
252 setAlignment(hoverActions);
253 w->addActions(hoverActions);
258 m_view->setIndexWidget(index, w);