summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Aardal Hanssen <andrhans@cisco.com>2012-11-23 11:48:27 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2012-11-26 21:23:15 +0100
commitbfb569b6e70cc6a56566002d1cb278a0122189d1 (patch)
treec17330cd85296b0a512c2dd654712b99a78d4582
parent85cf6cd5f253694ad0e7d51fdd0fcfdfe65d8dc8 (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.cpp36
-rw-r--r--src/widgets/graphicsview/qgraphicsitem_p.h5
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp137
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()