summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp10
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp24
-rw-r--r--src/gui/graphicsview/qgraphicsscene_p.h3
-rw-r--r--src/gui/graphicsview/qgraphicsview.cpp27
-rw-r--r--src/gui/graphicsview/qgraphicswidget.cpp5
-rw-r--r--tests/auto/qgraphicsview/tst_qgraphicsview.cpp101
6 files changed, 167 insertions, 3 deletions
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index 5c29e9c..b8ff5b4 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -1421,7 +1421,9 @@ void QGraphicsItem::setCursor(const QCursor &cursor)
d_ptr->setExtra(QGraphicsItemPrivate::ExtraCursor, qVariantValue<QCursor>(cursorVariant));
d_ptr->hasCursor = 1;
if (d_ptr->scene) {
+ d_ptr->scene->d_func()->allItemsUseDefaultCursor = false;
foreach (QGraphicsView *view, d_ptr->scene->views()) {
+ view->viewport()->setMouseTracking(true);
// Note: Some of this logic is duplicated in QGraphicsView's mouse events.
if (view->underMouse()) {
foreach (QGraphicsItem *itemUnderCursor, view->items(view->mapFromGlobal(QCursor::pos()))) {
@@ -2053,7 +2055,13 @@ bool QGraphicsItem::acceptsHoverEvents() const
*/
void QGraphicsItem::setAcceptHoverEvents(bool enabled)
{
+ if (d_ptr->acceptsHover == quint32(enabled))
+ return;
d_ptr->acceptsHover = quint32(enabled);
+ if (d_ptr->acceptsHover && d_ptr->scene && d_ptr->scene->d_func()->allItemsIgnoreHoverEvents) {
+ d_ptr->scene->d_func()->allItemsIgnoreHoverEvents = false;
+ d_ptr->scene->d_func()->enableMouseTrackingOnViews();
+ }
}
/*!
@@ -2063,7 +2071,7 @@ void QGraphicsItem::setAcceptHoverEvents(bool enabled)
*/
void QGraphicsItem::setAcceptsHoverEvents(bool enabled)
{
- d_ptr->acceptsHover = quint32(enabled);
+ setAcceptHoverEvents(enabled);
}
/*!
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 0439847..e885238 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -351,6 +351,8 @@ QGraphicsScenePrivate::QGraphicsScenePrivate()
dragDropItem(0),
enterWidget(0),
lastDropAction(Qt::IgnoreAction),
+ allItemsIgnoreHoverEvents(true),
+ allItemsUseDefaultCursor(true),
painterStateProtection(true),
sortCacheEnabled(false),
updatingSortCache(false),
@@ -1047,6 +1049,12 @@ void QGraphicsScenePrivate::clearKeyboardGrabber()
ungrabKeyboard(keyboardGrabberItems.first());
}
+void QGraphicsScenePrivate::enableMouseTrackingOnViews()
+{
+ foreach (QGraphicsView *view, views)
+ view->viewport()->setMouseTracking(true);
+}
+
/*!
Returns all items for the screen position in \a event.
*/
@@ -2763,6 +2771,8 @@ void QGraphicsScene::clear()
d->lastItemCount = 0;
d->bspTree.clear();
d->largestUntransformableItem = QRectF();
+ d->allItemsIgnoreHoverEvents = true;
+ d->allItemsUseDefaultCursor = true;
}
/*!
@@ -2927,6 +2937,17 @@ void QGraphicsScene::addItem(QGraphicsItem *item)
++d->selectionChanging;
int oldSelectedItemSize = d->selectedItems.size();
+ // Enable mouse tracking if the item accepts hover events or has a cursor set.
+ if (d->allItemsIgnoreHoverEvents && d->itemAcceptsHoverEvents_helper(item)) {
+ d->allItemsIgnoreHoverEvents = false;
+ d->enableMouseTrackingOnViews();
+ }
+ if (d->allItemsUseDefaultCursor && item->hasCursor()) {
+ d->allItemsUseDefaultCursor = false;
+ if (d->allItemsIgnoreHoverEvents) // already enabled otherwise
+ d->enableMouseTrackingOnViews();
+ }
+
// Update selection lists
if (item->isSelected())
d->selectedItems << item;
@@ -4219,6 +4240,9 @@ bool QGraphicsScenePrivate::itemAcceptsHoverEvents_helper(const QGraphicsItem *i
*/
bool QGraphicsScenePrivate::dispatchHoverEvent(QGraphicsSceneHoverEvent *hoverEvent)
{
+ if (allItemsIgnoreHoverEvents)
+ return false;
+
// Find the first item that accepts hover events, reusing earlier
// calculated data is possible.
if (cachedItemsUnderMouse.isEmpty()) {
diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h
index 8af8b28..9ace725 100644
--- a/src/gui/graphicsview/qgraphicsscene_p.h
+++ b/src/gui/graphicsview/qgraphicsscene_p.h
@@ -168,6 +168,9 @@ public:
Qt::DropAction lastDropAction;
QList<QGraphicsItem *> cachedItemsUnderMouse;
QList<QGraphicsItem *> hoverItems;
+ bool allItemsIgnoreHoverEvents;
+ bool allItemsUseDefaultCursor;
+ void enableMouseTrackingOnViews();
QMap<Qt::MouseButton, QPointF> mouseGrabberButtonDownPos;
QMap<Qt::MouseButton, QPointF> mouseGrabberButtonDownScenePos;
QMap<Qt::MouseButton, QPoint> mouseGrabberButtonDownScreenPos;
diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp
index b41dc66..797c895 100644
--- a/src/gui/graphicsview/qgraphicsview.cpp
+++ b/src/gui/graphicsview/qgraphicsview.cpp
@@ -587,6 +587,10 @@ void QGraphicsViewPrivate::mouseMoveEventHandler(QMouseEvent *event)
return;
if (!scene)
return;
+ if (scene->d_func()->allItemsIgnoreHoverEvents && scene->d_func()->allItemsUseDefaultCursor
+ && !event->buttons()) { // forward event to the scene if something is pressed.
+ return; // No need to process this event further.
+ }
QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
mouseEvent.setWidget(q->viewport());
@@ -614,6 +618,16 @@ void QGraphicsViewPrivate::mouseMoveEventHandler(QMouseEvent *event)
}
#ifndef QT_NO_CURSOR
+ // If all the items ignore hover events, we don't look-up any items
+ // in QGraphicsScenePrivate::dispatchHoverEvent, hence the
+ // cachedItemsUnderMouse list will be empty. We therefore do the look-up
+ // for cursor items here if not all items use the default cursor.
+ if (scene->d_func()->allItemsIgnoreHoverEvents && !scene->d_func()->allItemsUseDefaultCursor
+ && scene->d_func()->cachedItemsUnderMouse.isEmpty()) {
+ scene->d_func()->cachedItemsUnderMouse = scene->d_func()->itemsAtPosition(mouseEvent.screenPos(),
+ mouseEvent.scenePos(),
+ mouseEvent.widget());
+ }
// Find the topmost item under the mouse with a cursor.
foreach (QGraphicsItem *item, scene->d_func()->cachedItemsUnderMouse) {
if (item->hasCursor()) {
@@ -1688,6 +1702,12 @@ void QGraphicsView::setScene(QGraphicsScene *scene)
d->recalculateContentSize();
d->lastCenterPoint = sceneRect().center();
d->keepLastCenterPoint = true;
+ // We are only interested in mouse tracking if items accept
+ // hover events or use non-default cursors.
+ if (!d->scene->d_func()->allItemsIgnoreHoverEvents
+ || !d->scene->d_func()->allItemsUseDefaultCursor) {
+ d->viewport->setMouseTracking(true);
+ }
} else {
d->recalculateContentSize();
}
@@ -2799,7 +2819,12 @@ void QGraphicsView::setupViewport(QWidget *widget)
widget->setAutoFillBackground(true);
}
- widget->setMouseTracking(true);
+ // We are only interested in mouse tracking if items
+ // accept hover events or use non-default cursors.
+ if (d->scene && (!d->scene->d_func()->allItemsIgnoreHoverEvents
+ || !d->scene->d_func()->allItemsUseDefaultCursor)) {
+ widget->setMouseTracking(true);
+ }
widget->setAcceptDrops(acceptDrops());
}
diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp
index 7f02fb9..2e7d82a 100644
--- a/src/gui/graphicsview/qgraphicswidget.cpp
+++ b/src/gui/graphicsview/qgraphicswidget.cpp
@@ -1635,6 +1635,11 @@ void QGraphicsWidget::setWindowFlags(Qt::WindowFlags wFlags)
else
d->scene->d_func()->addPopup(this);
}
+
+ if (d->scene && d->scene->d_func()->allItemsIgnoreHoverEvents && d->hasDecoration()) {
+ d->scene->d_func()->allItemsIgnoreHoverEvents = false;
+ d->scene->d_func()->enableMouseTrackingOnViews();
+ }
}
/*!
diff --git a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp
index 412c6c5..6b3a9d4 100644
--- a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp
+++ b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp
@@ -191,6 +191,7 @@ private slots:
void scrollAfterResize_data();
void scrollAfterResize();
void centerOnDirtyItem();
+ void mouseTracking();
// task specific tests below me
void task172231_untransformableItems();
@@ -2515,7 +2516,8 @@ void tst_QGraphicsView::replayMouseMove()
// One mouse event should be translated into one scene event.
for (int i = 0; i < 3; ++i) {
- sendMouseMove(view.viewport(), view.viewport()->rect().center());
+ sendMouseMove(view.viewport(), view.viewport()->rect().center(),
+ Qt::LeftButton, Qt::MouseButtons(Qt::LeftButton));
QCOMPARE(viewSpy.count(), i + 1);
QCOMPARE(sceneSpy.count(), i + 1);
}
@@ -2705,6 +2707,7 @@ void tst_QGraphicsView::task186827_deleteReplayedItem()
MouseMoveCounter view;
view.setScene(&scene);
view.show();
+ view.viewport()->setMouseTracking(true);
#ifdef Q_WS_X11
qt_x11_wait_for_window_manager(&view);
#endif
@@ -3048,6 +3051,102 @@ void tst_QGraphicsView::centerOnDirtyItem()
QCOMPARE(before, after);
}
+void tst_QGraphicsView::mouseTracking()
+{
+ // Mouse tracking should only be automatically enabled if items either accept hover events
+ // or have a cursor set. We never disable mouse tracking if it is already enabled.
+
+ { // Make sure mouse tracking is disabled by default.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+ QVERIFY(!view.viewport()->hasMouseTracking());
+ }
+
+ { // Make sure we don't disable mouse tracking in setupViewport/setScene.
+ QGraphicsView view;
+ QWidget *viewport = new QWidget;
+ viewport->setMouseTracking(true);
+ view.setViewport(viewport);
+ QVERIFY(viewport->hasMouseTracking());
+
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ view.setScene(&scene);
+ QVERIFY(viewport->hasMouseTracking());
+ }
+
+ // Make sure we enable mouse tracking when having items that accept hover events.
+ {
+ // Adding an item to the scene after the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+ item->setAcceptHoverEvents(true);
+ scene.addItem(item);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+ {
+ // Adding an item to the scene before the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+ item->setAcceptHoverEvents(true);
+ scene.addItem(item);
+
+ QGraphicsView view(&scene);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+ {
+ // QGraphicsWidget implicitly accepts hover if it has window decoration.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ scene.addItem(widget);
+ QVERIFY(!view.viewport()->hasMouseTracking());
+ // Enable window decoraton.
+ widget->setWindowFlags(Qt::Window | Qt::WindowTitleHint);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+
+ // Make sure we enable mouse tracking when having items with a cursor set.
+ {
+ // Adding an item to the scene after the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+ item->setCursor(Qt::CrossCursor);
+ scene.addItem(item);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+ {
+ // Adding an item to the scene before the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+ item->setCursor(Qt::CrossCursor);
+ scene.addItem(item);
+
+ QGraphicsView view(&scene);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+
+ // Make sure we propagate mouse tracking to all views.
+ {
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view1(&scene);
+ QGraphicsView view2(&scene);
+ QGraphicsView view3(&scene);
+
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+ item->setCursor(Qt::CrossCursor);
+ scene.addItem(item);
+
+ QVERIFY(view1.viewport()->hasMouseTracking());
+ QVERIFY(view2.viewport()->hasMouseTracking());
+ QVERIFY(view3.viewport()->hasMouseTracking());
+ }
+}
+
QTEST_MAIN(tst_QGraphicsView)
#include "tst_qgraphicsview.moc"
#endif