summaryrefslogtreecommitdiffstats
path: root/src/gui/graphicsview/qgraphicsscene.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/graphicsview/qgraphicsscene.cpp')
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp242
1 files changed, 184 insertions, 58 deletions
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 6b6080b1d..a846cf680 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -484,6 +484,8 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item)
index->removeItem(item);
}
+ item->d_ptr->clearSubFocus();
+
if (!item->d_ptr->inDestructor && item == tabFocusFirst) {
QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
widget->d_func()->fixFocusChainBeforeReparenting(0, 0);
@@ -491,6 +493,13 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item)
item->d_func()->scene = 0;
+ // Unregister focus proxy.
+ QMultiHash<QGraphicsItem *, QGraphicsItem *>::iterator it = focusProxyReverseMap.find(item);
+ while (it != focusProxyReverseMap.end() && it.key() == item) {
+ it.value()->d_ptr->focusProxy = 0;
+ it = focusProxyReverseMap.erase(it);
+ }
+
// Remove from parent, or unregister from toplevels.
if (QGraphicsItem *parentItem = item->parentItem()) {
if (parentItem->scene()) {
@@ -559,6 +568,70 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item)
/*!
\internal
*/
+void QGraphicsScenePrivate::setFocusItemHelper(QGraphicsItem *item,
+ Qt::FocusReason focusReason)
+{
+ Q_Q(QGraphicsScene);
+ if (item == focusItem)
+ return;
+
+ // Clear focus if asked to set focus on something that can't
+ // accept input focus.
+ if (item && (!(item->flags() & QGraphicsItem::ItemIsFocusable)
+ || !item->isVisible() || !item->isEnabled())) {
+ item = 0;
+ }
+
+ // Set focus on the scene if an item requests focus.
+ if (item) {
+ q->setFocus(focusReason);
+ if (item == focusItem)
+ return;
+ }
+
+ // Auto-update focus proxy. The closest parent that detects
+ // focus proxies is updated as the proxy gains or loses focus.
+ if (item) {
+ QGraphicsItem *p = item->d_ptr->parent;
+ while (p) {
+ if (p->d_ptr->flags & QGraphicsItem::ItemAutoDetectsFocusProxy) {
+ p->setFocusProxy(item);
+ break;
+ }
+ p = p->d_ptr->parent;
+ }
+ }
+
+ if (focusItem) {
+ QFocusEvent event(QEvent::FocusOut, focusReason);
+ lastFocusItem = focusItem;
+ focusItem = 0;
+ sendEvent(lastFocusItem, &event);
+
+ if (lastFocusItem
+ && (lastFocusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod)) {
+ // Reset any visible preedit text
+ QInputMethodEvent imEvent;
+ sendEvent(lastFocusItem, &imEvent);
+
+ // Close any external input method panel
+ for (int i = 0; i < views.size(); ++i)
+ views.at(i)->inputContext()->reset();
+ }
+ }
+
+ if (item) {
+ focusItem = item;
+ QFocusEvent event(QEvent::FocusIn, focusReason);
+ sendEvent(item, &event);
+ }
+
+ updateInputMethodSensitivityInViews();
+}
+
+/*!
+ \internal
+*/
void QGraphicsScenePrivate::addPopup(QGraphicsWidget *widget)
{
Q_ASSERT(widget);
@@ -1587,10 +1660,16 @@ QList<QGraphicsItem *> QGraphicsScene::items(Qt::SortOrder order) const
}
/*!
+ \obsolete
+
Returns all visible items at position \a pos in the scene. The items are
listed in descending stacking order (i.e., the first item in the list is the
top-most item, and the last item is the bottom-most item).
+ This function is deprecated and returns incorrect results if the scene
+ contains items that ignore transformations. Use the overload that takes
+ a QTransform instead.
+
\sa itemAt()
*/
QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos) const
@@ -1600,9 +1679,8 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos) const
}
/*!
- \fn QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSelectionMode mode) const
-
\overload
+ \obsolete
Returns all visible items that, depending on \a mode, are either inside or
intersect with the specified \a rectangle.
@@ -1610,19 +1688,28 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos) const
The default value for \a mode is Qt::IntersectsItemShape; all items whose
exact shape intersects with or is contained by \a rectangle are returned.
+ This function is deprecated and returns incorrect results if the scene
+ contains items that ignore transformations. Use the overload that takes
+ a QTransform instead.
+
\sa itemAt()
*/
-QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode) const
+QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSelectionMode mode) const
{
Q_D(const QGraphicsScene);
- return d->index->items(rect, mode, Qt::AscendingOrder);
+ return d->index->items(rectangle, mode, Qt::AscendingOrder);
}
/*!
\fn QList<QGraphicsItem *> QGraphicsScene::items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode) const
+ \obsolete
\since 4.3
This convenience function is equivalent to calling items(QRectF(\a x, \a y, \a w, \a h), \a mode).
+
+ This function is deprecated and returns incorrect results if the scene
+ contains items that ignore transformations. Use the overload that takes
+ a QTransform instead.
*/
/*!
@@ -1641,6 +1728,7 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelecti
/*!
\overload
+ \obsolete
Returns all visible items that, depending on \a mode, are either inside or
intersect with the polygon \a polygon.
@@ -1648,6 +1736,10 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelecti
The default value for \a mode is Qt::IntersectsItemShape; all items whose
exact shape intersects with or is contained by \a polygon are returned.
+ This function is deprecated and returns incorrect results if the scene
+ contains items that ignore transformations. Use the overload that takes
+ a QTransform instead.
+
\sa itemAt()
*/
QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode) const
@@ -1658,6 +1750,7 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemS
/*!
\overload
+ \obsolete
Returns all visible items that, depending on \a path, are either inside or
intersect with the path \a path.
@@ -1665,6 +1758,10 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemS
The default value for \a mode is Qt::IntersectsItemShape; all items whose
exact shape intersects with or is contained by \a path are returned.
+ This function is deprecated and returns incorrect results if the scene
+ contains items that ignore transformations. Use the overload that takes
+ a QTransform instead.
+
\sa itemAt()
*/
QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const
@@ -1790,11 +1887,18 @@ QList<QGraphicsItem *> QGraphicsScene::collidingItems(const QGraphicsItem *item,
}
/*!
+ \overload
+ \obsolete
+
Returns the topmost visible item at the specified \a position, or 0 if
there are no items at this position.
\note The topmost item is the one with the highest Z-value.
+ This function is deprecated and returns incorrect results if the scene
+ contains items that ignore transformations. Use the overload that takes
+ a QTransform instead.
+
\sa items(), collidingItems(), QGraphicsItem::setZValue()
*/
QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position) const
@@ -1804,7 +1908,6 @@ QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position) const
}
/*!
- \overload
\since 4.6
Returns the topmost visible item at the specified \a position, or 0
@@ -1825,8 +1928,26 @@ QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position, const QTransform
}
/*!
+ \fn QGraphicsScene::itemAt(qreal x, qreal y, const QTransform &deviceTransform) const
+ \overload
+ \since 4.6
+
+ Returns the topmost item at the position specified by (\a x, \a
+ y), or 0 if there are no items at this position.
+
+ \a deviceTransform is the transformation that applies to the view, and needs to
+ be provided if the scene contains items that ignore transformations.
+
+ This convenience function is equivalent to calling \c
+ {itemAt(QPointF(x, y), deviceTransform)}.
+
+ \note The topmost item is the one with the highest Z-value.
+*/
+
+/*!
\fn QGraphicsScene::itemAt(qreal x, qreal y) const
\overload
+ \obsolete
Returns the topmost item at the position specified by (\a x, \a
y), or 0 if there are no items at this position.
@@ -1834,6 +1955,10 @@ QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position, const QTransform
This convenience function is equivalent to calling \c
{itemAt(QPointF(x, y))}.
+ This function is deprecated and returns incorrect results if the scene
+ contains items that ignore transformations. Use the overload that takes
+ a QTransform instead.
+
\note The topmost item is the one with the highest Z-value.
*/
@@ -1874,21 +1999,42 @@ QPainterPath QGraphicsScene::selectionArea() const
}
/*!
+ \since 4.6
+
Sets the selection area to \a path. All items within this area are
immediately selected, and all items outside are unselected. You can get
the list of all selected items by calling selectedItems().
+ \a deviceTransform is the transformation that applies to the view, and needs to
+ be provided if the scene contains items that ignore transformations.
+
For an item to be selected, it must be marked as \e selectable
(QGraphicsItem::ItemIsSelectable).
\sa clearSelection(), selectionArea()
*/
+void QGraphicsScene::setSelectionArea(const QPainterPath &path, const QTransform &deviceTransform)
+{
+ setSelectionArea(path, Qt::IntersectsItemShape, deviceTransform);
+}
+
+/*!
+ \obsolete
+ \overload
+
+ Sets the selection area to \a path.
+
+ This function is deprecated and leads to incorrect results if the scene
+ contains items that ignore transformations. Use the overload that takes
+ a QTransform instead.
+*/
void QGraphicsScene::setSelectionArea(const QPainterPath &path)
{
- setSelectionArea(path, Qt::IntersectsItemShape);
+ setSelectionArea(path, Qt::IntersectsItemShape, QTransform());
}
/*!
+ \obsolete
\overload
\since 4.3
@@ -2210,6 +2356,15 @@ void QGraphicsScene::addItem(QGraphicsItem *item)
// Deliver post-change notification
item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant);
+ // Auto-activate the first inactive window if the scene is active.
+ if (d->activationRefCount > 0 && !d->activeWindow && item->isWindow())
+ setActiveWindow(static_cast<QGraphicsWidget *>(item));
+
+ // Ensure that newly added items that have subfocus set, gain
+ // focus automatically if there isn't a focus item already.
+ if (!d->focusItem && item->focusItem())
+ item->focusItem()->setFocus();
+
d->updateInputMethodSensitivityInViews();
}
@@ -2524,49 +2679,10 @@ QGraphicsItem *QGraphicsScene::focusItem() const
void QGraphicsScene::setFocusItem(QGraphicsItem *item, Qt::FocusReason focusReason)
{
Q_D(QGraphicsScene);
- if (item == d->focusItem)
- return;
- if (item && (!(item->flags() & QGraphicsItem::ItemIsFocusable)
- || !item->isVisible() || !item->isEnabled())) {
- item = 0;
- }
-
- if (item) {
- setFocus(focusReason);
- if (item == d->focusItem)
- return;
- }
-
- if (d->focusItem) {
- QFocusEvent event(QEvent::FocusOut, focusReason);
- d->lastFocusItem = d->focusItem;
- d->focusItem = 0;
- d->sendEvent(d->lastFocusItem, &event);
-
- if (d->lastFocusItem
- && (d->lastFocusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod)) {
- // Reset any visible preedit text
- QInputMethodEvent imEvent;
- d->sendEvent(d->lastFocusItem, &imEvent);
-
- // Close any external input method panel
- for (int i = 0; i < d->views.size(); ++i)
- d->views.at(i)->inputContext()->reset();
- }
- }
-
- if (item) {
- if (item->isWidget()) {
- // Update focus child chain.
- static_cast<QGraphicsWidget *>(item)->d_func()->setFocusWidget();
- }
-
- d->focusItem = item;
- QFocusEvent event(QEvent::FocusIn, focusReason);
- d->sendEvent(item, &event);
- }
-
- d->updateInputMethodSensitivityInViews();
+ if (item)
+ item->setFocus(focusReason);
+ else
+ d->setFocusItemHelper(item, focusReason);
}
/*!
@@ -2621,13 +2737,17 @@ void QGraphicsScene::clearFocus()
/*!
\property QGraphicsScene::stickyFocus
- \brief whether or not clicking the scene will clear focus
+ \brief whether clicking into the scene background will clear focus
- If this property is false (the default), then clicking on the scene
- background or on an item that does not accept focus, will clear
- focus. Otherwise, focus will remain unchanged.
+ \since 4.6
+
+ In a QGraphicsScene with stickyFocus set to true, focus will remain
+ unchanged when the user clicks into the scene background or on an item
+ that does not accept focus. Otherwise, focus will be cleared.
- The focus change happens in response to a mouse press. You can reimplement
+ By default, this property is false.
+
+ Focus changes in response to a mouse press. You can reimplement
mousePressEvent() in a subclass of QGraphicsScene to toggle this property
based on where the user has clicked.
@@ -3360,7 +3480,7 @@ void QGraphicsScene::helpEvent(QGraphicsSceneHelpEvent *helpEvent)
text = toolTipItem->toolTip();
point = helpEvent->screenPos();
}
- QToolTip::showText(point, text);
+ QToolTip::showText(point, text, helpEvent->widget());
helpEvent->setAccepted(!text.isEmpty());
#endif
}
@@ -3459,8 +3579,7 @@ void QGraphicsScenePrivate::leaveScene()
{
Q_Q(QGraphicsScene);
#ifndef QT_NO_TOOLTIP
- // Remove any tooltips
- QToolTip::showText(QPoint(), QString());
+ QToolTip::hideText();
#endif
// Send HoverLeave events to all existing hover items, topmost first.
QGraphicsView *senderWidget = qobject_cast<QGraphicsView *>(q->sender());
@@ -3563,6 +3682,13 @@ void QGraphicsScene::keyReleaseEvent(QKeyEvent *keyEvent)
void QGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
Q_D(QGraphicsScene);
+ if (d->mouseGrabberItems.isEmpty()) {
+ // Dispatch hover events
+ QGraphicsSceneHoverEvent hover;
+ _q_hoverFromMouseEvent(&hover, mouseEvent);
+ d->dispatchHoverEvent(&hover);
+ }
+
d->mousePressEventHandler(mouseEvent);
}
@@ -4601,7 +4727,7 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool
background has been drawn, and before the foreground has been
drawn. All painting is done in \e scene coordinates. Before
drawing each item, the painter must be transformed using
- QGraphicsItem::sceneMatrix().
+ QGraphicsItem::sceneTransform().
The \a options parameter is the list of style option objects for
each item in \a items. The \a numItems parameter is the number of