From 46624cfb90986e1977a539d279516bd5ade3675f Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Mon, 31 Aug 2009 16:03:34 +0200 Subject: Add auto-activation on show/hide and setParentItem(). If you show a child panel of an active panel, the child will now be activated and the parent deactivated. Hiding the child panel will reactive the parent. If the parent is 0, no other panel is activated. Reparenting a panel onto an active panel will also activate the (new) child. Reparenting away does not affect activation in any way. This change also fixes QGraphicsWidget::isActiveWindow(), which returned true for all toplevel widgets (not in a panel/window). This is wrong; either the non-panel items are active, or a panel is active. The correct behavior is the same as calling QGraphicsItem::isActive(). Fixed the autotests (which wrongly tested that both a panel and a non-panel item were active at the same time). This change causes popups (QGraphics{Proxy,}Widget) to deactivate the parent widget. On the positive side this activates the popup, and ensures that the parent regains proper focus when the popup is closed. However it also means the parent widget is inactive while the popup is open, which (e.g.) causes editable combobox line edit cursors to stop blinking. This is to be fixed soon, but the fix is a bit big so we'll do that later. Autotests included. Reviewed-by: Brad --- src/gui/graphicsview/qgraphicsitem.cpp | 14 +++++ src/gui/graphicsview/qgraphicsproxywidget.cpp | 2 +- src/gui/graphicsview/qgraphicswidget.cpp | 6 +- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 64 ++++++++++++++++++++++ tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp | 6 +- 5 files changed, 83 insertions(+), 9 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 31fd53a..4f8755e 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1007,6 +1007,9 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) setEnabledHelper(parent->isEnabled(), /* explicit = */ false, /* update = */ !implicitUpdate); } + // Auto-activate if visible and the parent is active. + if (q->isVisible() && parent->isActive()) + q->setActive(true); } else { // Inherit ancestor flags from the new parent. updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-2)); @@ -1941,6 +1944,17 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo child->d_ptr->setVisibleHelper(newVisible, false, updateChildren); } + // Update activation + if (scene && q->isPanel()) { + if (newVisible) { + if (parent && parent->isActive()) + q->setActive(true); + } else { + if (q->isActive()) + scene->setActivePanel(parent); + } + } + // Enable subfocus if (newVisible && isWidget) { QGraphicsWidget *widget = static_cast(q_ptr); diff --git a/src/gui/graphicsview/qgraphicsproxywidget.cpp b/src/gui/graphicsview/qgraphicsproxywidget.cpp index 447fc50..c710c55 100644 --- a/src/gui/graphicsview/qgraphicsproxywidget.cpp +++ b/src/gui/graphicsview/qgraphicsproxywidget.cpp @@ -390,7 +390,7 @@ QWidget *QGraphicsProxyWidgetPrivate::findFocusChild(QWidget *child, bool next) if (child->isEnabled() && child->isVisibleTo(widget) && (child->focusPolicy() & Qt::TabFocus)) { - return child; + return child; } child = next ? child->d_func()->focus_next : child->d_func()->focus_prev; } while (child != oldChild && !(next && child == widget) && !(!next && child == widget->d_func()->focus_prev)); diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp index 9972223..afabf49 100644 --- a/src/gui/graphicsview/qgraphicswidget.cpp +++ b/src/gui/graphicsview/qgraphicswidget.cpp @@ -1665,11 +1665,7 @@ void QGraphicsWidget::setWindowFlags(Qt::WindowFlags wFlags) */ bool QGraphicsWidget::isActiveWindow() const { - Q_D(const QGraphicsWidget); - if (!d->scene) - return false; - const QGraphicsWidget *w = window(); - return (!w && d->scene->isActive()) || (w && d->scene->activeWindow() == w); + return isActive(); } /*! diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 517380e..2acb76d 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -291,6 +291,7 @@ private slots: void addPanelToActiveScene(); void activate(); void setActivePanelOnInactiveScene(); + void activationOnShowHide(); // task specific tests below me void task141694_textItemEnsureVisible(); @@ -8038,5 +8039,68 @@ void tst_QGraphicsItem::setActivePanelOnInactiveScene() QCOMPARE(sceneActivationChangeSpy.count(), 0); } +void tst_QGraphicsItem::activationOnShowHide() +{ + QGraphicsScene scene; + QEvent activate(QEvent::WindowActivate); + QApplication::sendEvent(&scene, &activate); + + QGraphicsRectItem *rootPanel = scene.addRect(QRectF()); + rootPanel->setFlag(QGraphicsItem::ItemIsPanel); + rootPanel->setActive(true); + + QGraphicsRectItem *subPanel = new QGraphicsRectItem; + subPanel->setFlag(QGraphicsItem::ItemIsPanel); + + // Reparenting onto an active panel auto-activates the child panel. + subPanel->setParentItem(rootPanel); + QVERIFY(subPanel->isActive()); + QVERIFY(!rootPanel->isActive()); + + // Hiding an active child panel will reactivate the parent panel. + subPanel->hide(); + QVERIFY(rootPanel->isActive()); + + // Showing a child panel will auto-activate it. + subPanel->show(); + QVERIFY(subPanel->isActive()); + QVERIFY(!rootPanel->isActive()); + + // Adding an unrelated panel doesn't affect activation. + QGraphicsRectItem *otherPanel = new QGraphicsRectItem; + otherPanel->setFlag(QGraphicsItem::ItemIsPanel); + scene.addItem(otherPanel); + QVERIFY(subPanel->isActive()); + + // Showing an unrelated panel doesn't affect activation. + otherPanel->hide(); + otherPanel->show(); + QVERIFY(subPanel->isActive()); + + // Add a non-panel item. + QGraphicsRectItem *otherItem = new QGraphicsRectItem; + scene.addItem(otherItem); + otherItem->setActive(true); + QVERIFY(otherItem->isActive()); + + // Reparent a panel onto an active non-panel item. + subPanel->setParentItem(otherItem); + QVERIFY(subPanel->isActive()); + + // Showing a child panel of a non-panel item will activate it. + subPanel->hide(); + QVERIFY(!subPanel->isActive()); + QVERIFY(otherItem->isActive()); + subPanel->show(); + QVERIFY(subPanel->isActive()); + + // Hiding a toplevel active panel will pass activation back + // to the non-panel items. + rootPanel->setActive(true); + rootPanel->hide(); + QVERIFY(!rootPanel->isActive()); + QVERIFY(otherItem->isActive()); +} + QTEST_MAIN(tst_QGraphicsItem) #include "tst_qgraphicsitem.moc" diff --git a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp index 663de22..65e6e56 100644 --- a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp +++ b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp @@ -352,12 +352,12 @@ void tst_QGraphicsWidget::activation() QEvent activateEvent(QEvent::WindowActivate); QApplication::sendEvent(&scene, &activateEvent); - QVERIFY(widget->isActiveWindow()); - QVERIFY(!window1->isActiveWindow()); + QVERIFY(!widget->isActiveWindow()); + QVERIFY(window1->isActiveWindow()); QVERIFY(!window2->isActiveWindow()); scene.setActiveWindow(window1); - QVERIFY(widget->isActiveWindow()); + QVERIFY(!widget->isActiveWindow()); QVERIFY(window1->isActiveWindow()); QVERIFY(!window2->isActiveWindow()); -- cgit v0.12