diff options
author | Andreas Aardal Hanssen <andrhans@cisco.com> | 2012-11-23 11:48:27 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2012-11-26 21:23:15 +0100 |
commit | bfb569b6e70cc6a56566002d1cb278a0122189d1 (patch) | |
tree | c17330cd85296b0a512c2dd654712b99a78d4582 | |
parent | 85cf6cd5f253694ad0e7d51fdd0fcfdfe65d8dc8 (diff) |
Ensure subfocus is not reset to 0 when hiding a panel.
When hiding any widget that is not a panel, it is correct to clear
subfocus. In case clearFocus() has been called, the result is that
focusItem() / focusWidget() points to 0, which is correct. Upon
reactivation, nothing gains input focus. When changing focus, the
following setSubFocus() call will ensure subfocus points to the new
widget.
When hiding a panel, however, it's essential that subfocus within
that panel is not cleared, otherwise, when re-showing the panel,
nothing will have focus, whereas the expected behavior is that focus
is restored to the last item that had focus, i.e., the focusItem()
a.k.a. subfocus widget.
Task-number: QTBUG-22256
Change-Id: I84d849a505764e074e1369fef923cef1ad5c0b1e
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
-rw-r--r-- | src/widgets/graphicsview/qgraphicsitem.cpp | 36 | ||||
-rw-r--r-- | src/widgets/graphicsview/qgraphicsitem_p.h | 5 | ||||
-rw-r--r-- | tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp | 137 |
3 files changed, 118 insertions, 60 deletions
diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp index 95244b8534..70b44428f2 100644 --- a/src/widgets/graphicsview/qgraphicsitem.cpp +++ b/src/widgets/graphicsview/qgraphicsitem.cpp @@ -2216,7 +2216,8 @@ bool QGraphicsItem::isVisibleTo(const QGraphicsItem *parent) const Sets this item's visibility to \a newVisible. If \a explicitly is true, this item will be "explicitly" \a newVisible; otherwise, it.. will not be. */ -void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bool update) +void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, + bool update, bool hiddenByPanel) { Q_Q(QGraphicsItem); @@ -2277,7 +2278,7 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo } while ((focusItem = focusItem->parentWidget()) && !focusItem->isPanel()); } if (clear) - clearFocusHelper(/* giveFocusToParent = */ false); + clearFocusHelper(/* giveFocusToParent = */ false, hiddenByPanel); } if (q_ptr->isSelected()) q_ptr->setSelected(false); @@ -2301,7 +2302,7 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo && !(flags & QGraphicsItem::ItemHasNoContents)); foreach (QGraphicsItem *child, children) { if (!newVisible || !child->d_ptr->explicitlyHidden) - child->d_ptr->setVisibleHelper(newVisible, false, updateChildren); + child->d_ptr->setVisibleHelper(newVisible, false, updateChildren, hiddenByPanel); } // Update activation @@ -2399,7 +2400,10 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo */ void QGraphicsItem::setVisible(bool visible) { - d_ptr->setVisibleHelper(visible, /* explicit = */ true); + d_ptr->setVisibleHelper(visible, + /* explicit = */ true, + /* update = */ true, + /* hiddenByPanel = */ isPanel()); } /*! @@ -3159,10 +3163,16 @@ void QGraphicsItem::setActive(bool active) // Activate this item. d_ptr->scene->setActivePanel(this); } else { - // Deactivate this item, and reactivate the last active item - // (if any). - QGraphicsItem *lastActive = d_ptr->scene->d_func()->lastActivePanel; - d_ptr->scene->setActivePanel(lastActive != this ? lastActive : 0); + // Deactivate this item, and reactivate the parent panel, + // or the last active panel (if any). + QGraphicsItem *nextToActivate = 0; + if (d_ptr->parent) + nextToActivate = d_ptr->parent->panel(); + if (!nextToActivate) + nextToActivate = d_ptr->scene->d_func()->lastActivePanel; + if (nextToActivate == this || isAncestorOf(nextToActivate)) + nextToActivate = 0; + d_ptr->scene->setActivePanel(nextToActivate); } } } @@ -3256,7 +3266,7 @@ void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool clim // Update the child focus chain. QGraphicsItem *commonAncestor = 0; - if (scene && scene->focusItem()) { + if (scene && scene->focusItem() && scene->focusItem()->panel() == q_ptr->panel()) { commonAncestor = scene->focusItem()->commonAncestorItem(f); scene->focusItem()->d_ptr->clearSubFocus(scene->focusItem(), commonAncestor); } @@ -3286,13 +3296,14 @@ void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool clim */ void QGraphicsItem::clearFocus() { - d_ptr->clearFocusHelper(/* giveFocusToParent = */ true); + d_ptr->clearFocusHelper(/* giveFocusToParent = */ true, + /* hiddenByParentPanel = */ false); } /*! \internal */ -void QGraphicsItemPrivate::clearFocusHelper(bool giveFocusToParent) +void QGraphicsItemPrivate::clearFocusHelper(bool giveFocusToParent, bool hiddenByParentPanel) { if (giveFocusToParent) { // Pass focus to the closest parent focus scope @@ -3317,7 +3328,8 @@ void QGraphicsItemPrivate::clearFocusHelper(bool giveFocusToParent) if (q_ptr->hasFocus()) { // Invisible items with focus must explicitly clear subfocus. - clearSubFocus(q_ptr); + if (!hiddenByParentPanel) + clearSubFocus(q_ptr); // If this item has the scene's input focus, clear it. scene->setFocusItem(0); diff --git a/src/widgets/graphicsview/qgraphicsitem_p.h b/src/widgets/graphicsview/qgraphicsitem_p.h index 18a7376337..830afa938c 100644 --- a/src/widgets/graphicsview/qgraphicsitem_p.h +++ b/src/widgets/graphicsview/qgraphicsitem_p.h @@ -279,7 +279,8 @@ public: void setTransformHelper(const QTransform &transform); void prependGraphicsTransform(QGraphicsTransform *t); void appendGraphicsTransform(QGraphicsTransform *t); - void setVisibleHelper(bool newVisible, bool explicitly, bool update = true); + void setVisibleHelper(bool newVisible, bool explicitly, bool update = true, + bool hiddenByPanel = false); void setEnabledHelper(bool newEnabled, bool explicitly, bool update = true); bool discardUpdateRequest(bool ignoreVisibleBit = false, bool ignoreDirtyBit = false, bool ignoreOpacity = false) const; @@ -476,7 +477,7 @@ public: inline void markParentDirty(bool updateBoundingRect = false); void setFocusHelper(Qt::FocusReason focusReason, bool climb, bool focusFromHide); - void clearFocusHelper(bool giveFocusToParent); + void clearFocusHelper(bool giveFocusToParent, bool hiddenByParentPanel); void setSubFocus(QGraphicsItem *rootItem = 0, QGraphicsItem *stopItem = 0); void clearSubFocus(QGraphicsItem *rootItem = 0, QGraphicsItem *stopItem = 0); void resetFocusProxy(); diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp index 490d79b270..9a996cd0c6 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp @@ -424,7 +424,7 @@ private slots: void setGraphicsEffect(); void panel(); void addPanelToActiveScene(); - void panelWithFocusItem(); + void panelWithFocusItems(); void activate(); void setActivePanelOnInactiveScene(); void activationOnShowHide(); @@ -8721,52 +8721,97 @@ void tst_QGraphicsItem::panel() QVERIFY(!panel1->isActive()); } -void tst_QGraphicsItem::panelWithFocusItem() +void tst_QGraphicsItem::panelWithFocusItems() { - QGraphicsScene scene; - QEvent activate(QEvent::WindowActivate); - QApplication::sendEvent(&scene, &activate); - - QGraphicsRectItem *parentPanel = new QGraphicsRectItem; - QGraphicsRectItem *parentPanelFocusItem = new QGraphicsRectItem(parentPanel); - parentPanel->setFlag(QGraphicsItem::ItemIsPanel); - parentPanelFocusItem->setFlag(QGraphicsItem::ItemIsFocusable); - parentPanelFocusItem->setFocus(); - scene.addItem(parentPanel); - - QVERIFY(parentPanel->isActive()); - QVERIFY(parentPanelFocusItem->hasFocus()); - QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem); - QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem); - - QGraphicsRectItem *childPanel = new QGraphicsRectItem; - QGraphicsRectItem *childPanelFocusItem = new QGraphicsRectItem(childPanel); - childPanel->setFlag(QGraphicsItem::ItemIsPanel); - childPanelFocusItem->setFlag(QGraphicsItem::ItemIsFocusable); - childPanelFocusItem->setFocus(); - - QVERIFY(!childPanelFocusItem->hasFocus()); - QCOMPARE(childPanel->focusItem(), (QGraphicsItem *)childPanelFocusItem); - QCOMPARE(childPanelFocusItem->focusItem(), (QGraphicsItem *)childPanelFocusItem); - - childPanel->setParentItem(parentPanel); - - QVERIFY(!parentPanel->isActive()); - QVERIFY(!parentPanelFocusItem->hasFocus()); - QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem); - QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem); - - QVERIFY(childPanel->isActive()); - QVERIFY(childPanelFocusItem->hasFocus()); - QCOMPARE(childPanel->focusItem(), (QGraphicsItem *)childPanelFocusItem); - QCOMPARE(childPanelFocusItem->focusItem(), (QGraphicsItem *)childPanelFocusItem); - - childPanel->hide(); - - QVERIFY(parentPanel->isActive()); - QVERIFY(parentPanelFocusItem->hasFocus()); - QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem); - QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem); + for (int i = 0; i < 2; ++i) + { + QGraphicsScene scene; + QEvent activate(QEvent::WindowActivate); + QApplication::sendEvent(&scene, &activate); + + bool widget = (i == 1); + QGraphicsItem *parentPanel = widget ? (QGraphicsItem *)new QGraphicsWidget : (QGraphicsItem *)new QGraphicsRectItem; + QGraphicsItem *parentPanelFocusItem = widget ? (QGraphicsItem *)new QGraphicsWidget : (QGraphicsItem *)new QGraphicsRectItem; + QGraphicsItem *parentPanelFocusItemSibling = widget ? (QGraphicsItem *)new QGraphicsWidget : (QGraphicsItem *)new QGraphicsRectItem; + parentPanel->setFlag(QGraphicsItem::ItemIsPanel); + parentPanelFocusItem->setFlag(QGraphicsItem::ItemIsFocusable); + parentPanelFocusItemSibling->setFlag(QGraphicsItem::ItemIsFocusable); + if (widget) { + static_cast<QGraphicsWidget *>(parentPanelFocusItem)->setFocusPolicy(Qt::StrongFocus); + static_cast<QGraphicsWidget *>(parentPanelFocusItemSibling)->setFocusPolicy(Qt::StrongFocus); + } + parentPanelFocusItem->setParentItem(parentPanel); + parentPanelFocusItemSibling->setParentItem(parentPanel); + parentPanelFocusItem->setFocus(); + scene.addItem(parentPanel); + + QVERIFY(parentPanel->isActive()); + QVERIFY(parentPanelFocusItem->hasFocus()); + QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem); + QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem); + + QGraphicsItem *childPanel = widget ? (QGraphicsItem *)new QGraphicsWidget : (QGraphicsItem *)new QGraphicsRectItem; + QGraphicsItem *childPanelFocusItem = widget ? (QGraphicsItem *)new QGraphicsWidget : (QGraphicsItem *)new QGraphicsRectItem; + QGraphicsItem *grandChildPanelFocusItem = widget ? (QGraphicsItem *)new QGraphicsWidget : (QGraphicsItem *)new QGraphicsRectItem; + QGraphicsItem *grandChildPanelFocusItem2 = widget ? (QGraphicsItem *)new QGraphicsWidget : (QGraphicsItem *)new QGraphicsRectItem; + + childPanel->setFlag(QGraphicsItem::ItemIsPanel); + childPanelFocusItem->setFlag(QGraphicsItem::ItemIsFocusable); + grandChildPanelFocusItem->setFlag(QGraphicsItem::ItemIsFocusable); + grandChildPanelFocusItem2->setFlag(QGraphicsItem::ItemIsFocusable); + + if (widget) + { + static_cast<QGraphicsWidget *>(childPanelFocusItem)->setFocusPolicy(Qt::StrongFocus); + static_cast<QGraphicsWidget *>(grandChildPanelFocusItem)->setFocusPolicy(Qt::StrongFocus); + static_cast<QGraphicsWidget *>(grandChildPanelFocusItem2)->setFocusPolicy(Qt::StrongFocus); + } + grandChildPanelFocusItem->setParentItem(childPanelFocusItem); + grandChildPanelFocusItem2->setParentItem(childPanelFocusItem); + childPanelFocusItem->setParentItem(childPanel); + grandChildPanelFocusItem->setFocus(); + + QVERIFY(!grandChildPanelFocusItem->hasFocus()); + QCOMPARE(childPanel->focusItem(), (QGraphicsItem *)grandChildPanelFocusItem); + QCOMPARE(childPanelFocusItem->focusItem(), (QGraphicsItem *)grandChildPanelFocusItem); + QCOMPARE(grandChildPanelFocusItem->focusItem(), (QGraphicsItem *)grandChildPanelFocusItem); + + childPanel->setParentItem(parentPanel); + + QVERIFY(!parentPanel->isActive()); + QVERIFY(!parentPanelFocusItem->hasFocus()); + QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem); + QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem); + + QVERIFY(childPanel->isActive()); + QVERIFY(!childPanelFocusItem->hasFocus()); + QVERIFY(grandChildPanelFocusItem->hasFocus()); + QCOMPARE(childPanel->focusItem(), (QGraphicsItem *)grandChildPanelFocusItem); + QCOMPARE(childPanelFocusItem->focusItem(), (QGraphicsItem *)grandChildPanelFocusItem); + + childPanel->hide(); + QCOMPARE(childPanel->focusItem(), (QGraphicsItem *)grandChildPanelFocusItem); + QVERIFY(!childPanel->focusItem()->hasFocus()); + QVERIFY(parentPanel->isActive()); + QVERIFY(parentPanelFocusItem->hasFocus()); + QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem); + QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem); + QCOMPARE(grandChildPanelFocusItem->focusItem(), (QGraphicsItem *)grandChildPanelFocusItem); + + childPanel->show(); + QVERIFY(childPanel->isActive()); + QVERIFY(grandChildPanelFocusItem->hasFocus()); + QCOMPARE(childPanel->focusItem(), (QGraphicsItem *)grandChildPanelFocusItem); + QCOMPARE(childPanelFocusItem->focusItem(), (QGraphicsItem *)grandChildPanelFocusItem); + QCOMPARE(grandChildPanelFocusItem->focusItem(), (QGraphicsItem *)grandChildPanelFocusItem); + + childPanel->hide(); + + QVERIFY(parentPanel->isActive()); + QVERIFY(parentPanelFocusItem->hasFocus()); + QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem); + QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem); + } } void tst_QGraphicsItem::addPanelToActiveScene() |