┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/kitemviews/kitemlistcontainer.cpp15
-rw-r--r--src/kitemviews/kitemlistcontainer.h1
-rw-r--r--src/kitemviews/kitemlistcontroller.cpp129
-rw-r--r--src/kitemviews/kitemlistcontroller.h2
-rw-r--r--src/kitemviews/kitemlistview.cpp4
5 files changed, 90 insertions, 61 deletions
diff --git a/src/kitemviews/kitemlistcontainer.cpp b/src/kitemviews/kitemlistcontainer.cpp
index f89a6c8ce..1cac8f7a6 100644
--- a/src/kitemviews/kitemlistcontainer.cpp
+++ b/src/kitemviews/kitemlistcontainer.cpp
@@ -138,6 +138,21 @@ void KItemListContainer::keyPressEvent(QKeyEvent *event)
}
}
+void KItemListContainer::contextMenuEvent(QContextMenuEvent *event)
+{
+ // Note copied from the keyPressEvent() method above because the same reasons probably also apply here.
+ // TODO: We should find a better way to handle the context menu events in the view.
+ // The reasons why we need this hack are:
+ // 1. Without reimplementing contextMenuEvent() here, the event would not reach the QGraphicsView.
+ // 2. By default, the KItemListView does not have the keyboard focus in the QGraphicsScene, so
+ // simply sending the event to the QGraphicsView which is the KItemListContainer's viewport
+ // does not work.
+ KItemListView *view = m_controller->view();
+ if (view) {
+ QApplication::sendEvent(view, event);
+ }
+}
+
void KItemListContainer::showEvent(QShowEvent *event)
{
QAbstractScrollArea::showEvent(event);
diff --git a/src/kitemviews/kitemlistcontainer.h b/src/kitemviews/kitemlistcontainer.h
index 40b075376..93016ab82 100644
--- a/src/kitemviews/kitemlistcontainer.h
+++ b/src/kitemviews/kitemlistcontainer.h
@@ -46,6 +46,7 @@ public:
protected:
void keyPressEvent(QKeyEvent *event) override;
+ void contextMenuEvent(QContextMenuEvent *event) override;
void showEvent(QShowEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
void scrollContentsBy(int dx, int dy) override;
diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp
index 5abf1830b..60f23c1db 100644
--- a/src/kitemviews/kitemlistcontroller.cpp
+++ b/src/kitemviews/kitemlistcontroller.cpp
@@ -425,28 +425,6 @@ bool KItemListController::keyPressEvent(QKeyEvent *event)
break;
}
- case Qt::Key_Menu: {
- // Emit the signal itemContextMenuRequested() in case if at least one
- // item is selected. Otherwise the signal viewContextMenuRequested() will be emitted.
- const KItemSet selectedItems = m_selectionManager->selectedItems();
- int index = -1;
- if (selectedItems.count() >= 2) {
- const int currentItemIndex = m_selectionManager->currentItem();
- index = selectedItems.contains(currentItemIndex) ? currentItemIndex : selectedItems.first();
- } else if (selectedItems.count() == 1) {
- index = selectedItems.first();
- }
-
- if (index >= 0) {
- const QRectF contextRect = m_view->itemContextRect(index);
- const QPointF pos(m_view->scene()->views().first()->mapToGlobal(contextRect.bottomRight().toPoint()));
- Q_EMIT itemContextMenuRequested(index, pos);
- } else {
- Q_EMIT viewContextMenuRequested(QCursor::pos());
- }
- break;
- }
-
case Qt::Key_Escape:
if (m_selectionMode) {
Q_EMIT selectionModeChangeRequested(false);
@@ -701,19 +679,7 @@ bool KItemListController::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event,
}
if (event->button() & Qt::RightButton) {
- m_selectionManager->clearSelection();
- if (index.has_value()) {
- m_selectionManager->setSelected(index.value());
- Q_EMIT itemContextMenuRequested(index.value(), event->screenPos());
- } else {
- const QRectF headerBounds = m_view->headerBoundaries();
- if (headerBounds.contains(event->pos())) {
- Q_EMIT headerContextMenuRequested(event->screenPos());
- } else {
- Q_EMIT viewContextMenuRequested(event->screenPos());
- }
- }
- return true;
+ return false;
}
bool emitItemActivated = !(m_view->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick) || m_singleClickActivationEnforced)
@@ -724,6 +690,59 @@ bool KItemListController::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event,
return false;
}
+bool KItemListController::contextMenuEvent(QContextMenuEvent *event)
+{
+ if (event->reason() == QContextMenuEvent::Keyboard) {
+ // Emit the signal itemContextMenuRequested() if at least one item is selected.
+ // Otherwise the signal viewContextMenuRequested() will be emitted.
+ const KItemSet selectedItems = m_selectionManager->selectedItems();
+ int index = -1;
+ if (selectedItems.count() >= 2) {
+ const int currentItemIndex = m_selectionManager->currentItem();
+ index = selectedItems.contains(currentItemIndex) ? currentItemIndex : selectedItems.first();
+ } else if (selectedItems.count() == 1) {
+ index = selectedItems.first();
+ }
+
+ if (index >= 0) {
+ const QRectF contextRect = m_view->itemContextRect(index);
+ const QPointF pos(m_view->scene()->views().first()->mapToGlobal(contextRect.bottomRight().toPoint()));
+ Q_EMIT itemContextMenuRequested(index, pos);
+ } else {
+ Q_EMIT viewContextMenuRequested(event->globalPos());
+ }
+ return true;
+ }
+
+ const auto pos = event->pos();
+ const auto globalPos = event->globalPos();
+
+ if (m_view->headerBoundaries().contains(pos)) {
+ Q_EMIT headerContextMenuRequested(globalPos);
+ return true;
+ }
+
+ const auto pressedItem = m_view->itemAt(pos);
+ // We only open a context menu for the pressed item if it is selected.
+ // That's because the same click might have de-selected the item or because the press was only in the row of the item but not on it.
+ if (pressedItem && m_selectionManager->selectedItems().contains(pressedItem.value())) {
+ // The selection rectangle for an item was clicked
+ Q_EMIT itemContextMenuRequested(m_pressedIndex.value(), globalPos);
+ return true;
+ }
+
+ // Remove any hover highlights so the context menu doesn't look like it applies to a row.
+ const auto widgets = m_view->visibleItemListWidgets();
+ for (KItemListWidget *widget : widgets) {
+ if (widget->isHovered()) {
+ widget->setHovered(false);
+ Q_EMIT itemUnhovered(widget->index());
+ }
+ }
+ Q_EMIT viewContextMenuRequested(globalPos);
+ return true;
+}
+
bool KItemListController::dragEnterEvent(QGraphicsSceneDragDropEvent *event, const QTransform &transform)
{
Q_UNUSED(event)
@@ -1208,6 +1227,8 @@ bool KItemListController::processEvent(QEvent *event, const QTransform &transfor
return mouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent *>(event), QTransform());
case QEvent::GraphicsSceneMouseDoubleClick:
return mouseDoubleClickEvent(static_cast<QGraphicsSceneMouseEvent *>(event), QTransform());
+ case QEvent::ContextMenu:
+ return contextMenuEvent(static_cast<QContextMenuEvent *>(event));
case QEvent::GraphicsSceneWheel:
return wheelEvent(static_cast<QGraphicsSceneWheelEvent *>(event), QTransform());
case QEvent::GraphicsSceneDragEnter:
@@ -1393,6 +1414,10 @@ KItemListWidget *KItemListController::widgetForPos(const QPointF &pos) const
{
Q_ASSERT(m_view);
+ if (m_view->headerBoundaries().contains(pos)) {
+ return nullptr;
+ }
+
const auto widgets = m_view->visibleItemListWidgets();
for (KItemListWidget *widget : widgets) {
const QPointF mappedPos = widget->mapFromItem(m_view, pos);
@@ -1408,6 +1433,10 @@ KItemListWidget *KItemListController::widgetForDropPos(const QPointF &pos) const
{
Q_ASSERT(m_view);
+ if (m_view->headerBoundaries().contains(pos)) {
+ return nullptr;
+ }
+
const auto widgets = m_view->visibleItemListWidgets();
for (KItemListWidget *widget : widgets) {
const QPointF mappedPos = widget->mapFromItem(m_view, pos);
@@ -1617,12 +1646,6 @@ bool KItemListController::onPress(const QPoint &screenPos, const QPointF &pos, c
}
if (rightClick) {
- // Do header hit check and short circuit before commencing any state changing effects
- if (m_view->headerBoundaries().contains(pos)) {
- Q_EMIT headerContextMenuRequested(screenPos);
- return true;
- }
-
// Stop rubber band from persisting after right-clicks
KItemListRubberBand *rubberBand = m_view->rubberBand();
if (rubberBand->isActive()) {
@@ -1634,7 +1657,6 @@ bool KItemListController::onPress(const QPoint &screenPos, const QPointF &pos, c
if (m_pressedIndex.has_value()) {
// The hover highlight area of an item is being pressed.
- m_selectionManager->setCurrentItem(m_pressedIndex.value());
const auto row = m_view->m_visibleItems.value(m_pressedIndex.value()); // anything outside of row.contains() will be the empty region of the row rect
const bool hitTargetIsRowEmptyRegion = !row->contains(row->mapFromItem(m_view, pos));
// again, when this method returns false, a rubberBand selection is created as the event is not consumed;
@@ -1642,18 +1664,13 @@ bool KItemListController::onPress(const QPoint &screenPos, const QPointF &pos, c
bool createRubberBand = (hitTargetIsRowEmptyRegion && m_selectionManager->selectedItems().isEmpty());
if (rightClick && hitTargetIsRowEmptyRegion) {
- // We have a right click outside the icon and text rect but within the hover highlight area
- // but it is unclear if this means that a selection rectangle for an item was clicked or the background of the view.
- if (m_selectionManager->selectedItems().contains(m_pressedIndex.value())) {
- // The selection rectangle for an item was clicked
- Q_EMIT itemContextMenuRequested(m_pressedIndex.value(), screenPos);
- } else {
- row->setHovered(false); // Removes the hover highlight so the context menu doesn't look like it applies to the row.
- Q_EMIT viewContextMenuRequested(screenPos);
- }
+ // We have a right click outside the icon and text rect but within the hover highlight area.
+ // We don't want items to get selected through this, so we return now.
return true;
}
+ m_selectionManager->setCurrentItem(m_pressedIndex.value());
+
switch (m_selectionBehavior) {
case NoSelection:
break;
@@ -1690,19 +1707,9 @@ bool KItemListController::onPress(const QPoint &screenPos, const QPointF &pos, c
break;
}
- if (rightClick) {
- Q_EMIT itemContextMenuRequested(m_pressedIndex.value(), screenPos);
- }
return !createRubberBand;
}
- if (rightClick) {
- // header right click handling would have been done before this so just normal context
- // menu here is fine
- Q_EMIT viewContextMenuRequested(screenPos);
- return true;
- }
-
return false;
}
diff --git a/src/kitemviews/kitemlistcontroller.h b/src/kitemviews/kitemlistcontroller.h
index 0576fc7fd..9c3a003d3 100644
--- a/src/kitemviews/kitemlistcontroller.h
+++ b/src/kitemviews/kitemlistcontroller.h
@@ -24,6 +24,7 @@ class KItemListKeyboardSearchManager;
class KItemListSelectionManager;
class KItemListView;
class KItemListWidget;
+class QContextMenuEvent;
class QGestureEvent;
class QGraphicsSceneHoverEvent;
class QGraphicsSceneDragDropEvent;
@@ -313,6 +314,7 @@ private:
bool mouseMoveEvent(QGraphicsSceneMouseEvent *event, const QTransform &transform);
bool mouseReleaseEvent(QGraphicsSceneMouseEvent *event, const QTransform &transform);
bool mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event, const QTransform &transform);
+ bool contextMenuEvent(QContextMenuEvent *event);
bool dragEnterEvent(QGraphicsSceneDragDropEvent *event, const QTransform &transform);
bool dragLeaveEvent(QGraphicsSceneDragDropEvent *event, const QTransform &transform);
bool dragMoveEvent(QGraphicsSceneDragDropEvent *event, const QTransform &transform);
diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp
index cf1483659..89376ab20 100644
--- a/src/kitemviews/kitemlistview.cpp
+++ b/src/kitemviews/kitemlistview.cpp
@@ -402,6 +402,10 @@ qreal KItemListView::verticalPageStep() const
std::optional<int> KItemListView::itemAt(const QPointF &pos) const
{
+ if (headerBoundaries().contains(pos)) {
+ return std::nullopt;
+ }
+
QHashIterator<int, KItemListWidget *> it(m_visibleItems);
while (it.hasNext()) {
it.next();