summaryrefslogtreecommitdiffstats
path: root/src/widgets/graphicsview/qgraphicsitem.cpp
diff options
context:
space:
mode:
authorAlexander Neundorf <alexander.neundorf@sharpreflections.com>2020-01-28 14:07:51 +0100
committerAlexander Neundorf <alexander.neundorf@sharpreflections.com>2020-02-03 11:40:52 +0100
commit71cf207b5473aa2d87d0e1133feca3c2991e135a (patch)
treecaa80381978c7c9c4eb181e323359b46be14941f /src/widgets/graphicsview/qgraphicsitem.cpp
parent07e5a05dcb91720a88122e4aba9d8ce6bfbd14ad (diff)
QGraphicsItem: optimize setCursor() for large number of graphic items
This patch optimizes setCursor() by invoking view->items(position) only if the current graphics item is under the mouse cursor. If it is not, setting the cursor for this item should not have any effect on the actually currently visible mouse cursor, so there should be no reason to call _q_setViewportCursor() at all in this case, so it is not necessary to query for all the items under the cursor position. In my use case this gives a significant performance improvement from slow behavior to almost immediately (Linux with X11). My scenario is that I have many rectangular graphic items next to each other in a graphics view, and there is the functionality to add one more graphics item (a "handle") to one of those rectangular graphics items, and then for this new "handle" a new graphics item will be added on each of the other existing rectangular graphics items. The ctor of the "handle" graphics item calls setCursor(Qt::OpenHandCursor). QGraphicsItem::setCursor() calls view->item(cursorPosition), and then updates the visible cursor according to the top most graphics item under the cursor. So assuming that there are e.g. 1000 rectangular graphics items next to each other, each showing e.g. 5 "handle" graphic items, adding one more "handle" graphics item will add one graphics item on each of the 1000 rectangular items, so 1000 times view->items(cursorPos) will be called, at the beginning with 6000 graphic items (1000 rectangles and 5000 handles) already in the scene, for the last one with 6999 items in the scene (999 "handles" have been already added), from which the ones under the cursor have to be found. This is basically O^2 complexity. With the patch it changes to linear regarding the number of rectangular graphics items. Change-Id: I9836fc710a8f11d01a94930ea64c6c946e0db282 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src/widgets/graphicsview/qgraphicsitem.cpp')
-rw-r--r--src/widgets/graphicsview/qgraphicsitem.cpp17
1 files changed, 11 insertions, 6 deletions
diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp
index a2120e53fe..38cab60fc2 100644
--- a/src/widgets/graphicsview/qgraphicsitem.cpp
+++ b/src/widgets/graphicsview/qgraphicsitem.cpp
@@ -2331,12 +2331,17 @@ void QGraphicsItem::setCursor(const QCursor &cursor)
view->viewport()->setMouseTracking(true);
// Note: Some of this logic is duplicated in QGraphicsView's mouse events.
if (view->underMouse()) {
- const auto itemsUnderCursor = view->items(view->mapFromGlobal(QCursor::pos()));
- for (QGraphicsItem *itemUnderCursor : itemsUnderCursor) {
- if (itemUnderCursor->hasCursor()) {
- QMetaObject::invokeMethod(view, "_q_setViewportCursor",
- Q_ARG(QCursor, itemUnderCursor->cursor()));
- break;
+ const QPoint viewPoint = view->mapFromGlobal(QCursor::pos());
+ const QPointF cursorPos = mapFromScene(view->mapToScene(viewPoint));
+ // the cursor can only change if the current item is under the mouse
+ if (boundingRect().contains(cursorPos)) {
+ const auto itemsUnderCursor = view->items(viewPoint);
+ for (QGraphicsItem *itemUnderCursor : itemsUnderCursor) {
+ if (itemUnderCursor->hasCursor()) {
+ QMetaObject::invokeMethod(view, "_q_setViewportCursor",
+ Q_ARG(QCursor, itemUnderCursor->cursor()));
+ break;
+ }
}
}
break;