diff options
author | Andreas Aardal Hanssen <andreas.aardal.hanssen@nokia.com> | 2009-08-31 12:06:47 (GMT) |
---|---|---|
committer | Andreas Aardal Hanssen <andreas.aardal.hanssen@nokia.com> | 2009-08-31 14:14:48 (GMT) |
commit | 62ca28a96d200fe55ed5bc2d0d1df327ab44c97e (patch) | |
tree | 0b88b18056f074f7dfb851f3a7fe0aa885955561 /src | |
parent | 940b0b9e51f234f251d332f729531d6e9c3cea84 (diff) | |
download | Qt-62ca28a96d200fe55ed5bc2d0d1df327ab44c97e.zip Qt-62ca28a96d200fe55ed5bc2d0d1df327ab44c97e.tar.gz Qt-62ca28a96d200fe55ed5bc2d0d1df327ab44c97e.tar.bz2 |
Fix activation behavior for panels, and add QGraphicsItem::setActive().
Allow delayed activation for more fine grained control over which panels
are activated or left inactive when the scene is created.
Autotests included.
Reviewed-by: Brad
Diffstat (limited to 'src')
-rw-r--r-- | src/gui/graphicsview/qgraphicsitem.cpp | 37 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsitem.h | 2 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsitem_p.h | 8 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsscene.cpp | 149 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsscene_p.h | 2 |
5 files changed, 137 insertions, 61 deletions
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 86c589d..31fd53a 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -2669,6 +2669,37 @@ bool QGraphicsItem::isActive() const } /*! + \since 4.6 + + If \a active is true, and the scene is active, this item's panel will be + activated. Otherwise, the panel is deactivated. + + If the item is not part of an active scene, \a active will decide what + happens to the panel when the scene becomes active or the item is added to + the scene. If true, the item's panel will be activated when the item is + either added to the scene or the scene is activated. Otherwise, the item + will stay inactive independent of the scene's activated state. + + \sa isPanel(), QGraphicsScene::setActivePanel(), QGraphicsScene::isActive() +*/ +void QGraphicsItem::setActive(bool active) +{ + d_ptr->explicitActivate = 1; + d_ptr->wantsActive = active; + if (d_ptr->scene) { + if (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); + } + } +} + +/*! Returns true if this item is active, and it or its \l{focusProxy()}{focus proxy} has keyboard input focus; otherwise, returns false. @@ -6099,8 +6130,10 @@ bool QGraphicsItem::sceneEvent(QEvent *event) if (d_ptr->scene) { for (int i = 0; i < d_ptr->children.size(); ++i) { QGraphicsItem *child = d_ptr->children.at(i); - if (!(child->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorHandlesChildEvents)) - d_ptr->scene->sendEvent(child, event); + if (child->isVisible() && !child->isPanel()) { + if (!(child->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorHandlesChildEvents)) + d_ptr->scene->sendEvent(child, event); + } } } break; diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index 04fe0cb..df25e6a 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -235,6 +235,8 @@ public: void setHandlesChildEvents(bool enabled); bool isActive() const; + void setActive(bool active); + bool hasFocus() const; void setFocus(Qt::FocusReason focusReason = Qt::OtherFocusReason); void clearFocus(); diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 2bc876c..1090620 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -171,6 +171,8 @@ public: notifyBoundingRectChanged(0), notifyInvalidated(0), mouseSetsFocus(1), + explicitActivate(0), + wantsActive(0), globalStackingOrder(-1), q_ptr(0) { @@ -461,7 +463,7 @@ public: quint32 needSortChildren : 1; quint32 allChildrenDirty : 1; - // New 32 bits + // Packed 32 bits quint32 fullUpdatePending : 1; quint32 flags : 16; quint32 dirtyChildrenBoundingRect : 1; @@ -480,6 +482,10 @@ public: quint32 notifyInvalidated : 1; quint32 mouseSetsFocus : 1; + // New 32 bits + quint32 explicitActivate : 1; + quint32 wantsActive : 1; + // Optional stacking order int globalStackingOrder; QGraphicsItem *q_ptr; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index ac30668..2ac1dca 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -291,6 +291,7 @@ QGraphicsScenePrivate::QGraphicsScenePrivate() activePanel(0), lastActivePanel(0), activationRefCount(0), + childExplicitActivation(0), lastMouseGrabberItem(0), lastMouseGrabberItemHasImplicitMouseGrab(false), dragDropItem(0), @@ -571,6 +572,66 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item) /*! \internal */ +void QGraphicsScenePrivate::setActivePanelHelper(QGraphicsItem *item, bool duringActivationEvent) +{ + Q_Q(QGraphicsScene); + if (item && item->scene() != q) { + qWarning("QGraphicsScene::setActivePanel: item %p must be part of this scene", + item); + return; + } + + // Find the item's panel. + QGraphicsItem *panel = item ? item->panel() : 0; + lastActivePanel = panel ? activePanel : 0; + if (panel == activePanel || (!q->isActive() && !duringActivationEvent)) + return; + + // Deactivate the last active panel. + if (activePanel) { + if (QGraphicsItem *fi = activePanel->focusItem()) { + // Remove focus from the current focus item. + if (fi == q->focusItem()) + q->setFocusItem(0, Qt::ActiveWindowFocusReason); + } + + QEvent event(QEvent::WindowDeactivate); + q->sendEvent(activePanel, &event); + } else if (panel && !duringActivationEvent) { + // Deactivate the scene if changing activation to a panel. + QEvent event(QEvent::WindowDeactivate); + foreach (QGraphicsItem *item, q->items()) { + if (item->isVisible() && !item->isPanel() && !item->parentItem()) + q->sendEvent(item, &event); + } + } + + // Update activate state. + activePanel = panel; + QEvent event(QEvent::ActivationChange); + QApplication::sendEvent(q, &event); + + // Activate + if (panel) { + QEvent event(QEvent::WindowActivate); + q->sendEvent(panel, &event); + + // Set focus on the panel's focus item. + if (QGraphicsItem *focusItem = panel->focusItem()) + focusItem->setFocus(Qt::ActiveWindowFocusReason); + } else if (q->isActive()) { + // Activate the scene + QEvent event(QEvent::WindowActivate); + foreach (QGraphicsItem *item, q->items()) { + if (item->isVisible() && !item->isPanel() && !item->parentItem()) + q->sendEvent(item, &event); + } + } +} + +/*! + \internal +*/ void QGraphicsScenePrivate::setFocusItemHelper(QGraphicsItem *item, Qt::FocusReason focusReason) { @@ -2351,9 +2412,29 @@ void QGraphicsScene::addItem(QGraphicsItem *item) // Deliver post-change notification item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant); - // Auto-activate the first inactive panel if the scene is active. - if (isActive() && !d->activePanel && item->isPanel()) - setActivePanel(item); + // Update explicit activation + bool autoActivate = true; + if (!d->childExplicitActivation && item->d_ptr->explicitActivate) + d->childExplicitActivation = item->d_ptr->wantsActive ? 1 : 2; + if (d->childExplicitActivation && item->isPanel()) { + if (d->childExplicitActivation == 1) + setActivePanel(item); + else + autoActivate = false; + d->childExplicitActivation = 0; + } else if (!item->d_ptr->parent) { + d->childExplicitActivation = 0; + } + + // Auto-activate this item's panel if nothing else has been activated + if (autoActivate) { + if (!d->lastActivePanel && !d->activePanel && item->isPanel()) { + if (isActive()) + setActivePanel(item); + else + d->lastActivePanel = item; + } + } // Ensure that newly added items that have subfocus set, gain // focus automatically if there isn't a focus item already. @@ -3129,11 +3210,11 @@ bool QGraphicsScene::event(QEvent *event) if (!d->activationRefCount++) { if (d->lastActivePanel) { // Activate the last panel. - setActivePanel(d->lastActivePanel); + d->setActivePanelHelper(d->lastActivePanel, true); } else if (d->tabFocusFirst && d->tabFocusFirst->isPanel()) { // Activate the panel of the first item in the tab focus // chain. - setActivePanel(d->tabFocusFirst); + d->setActivePanelHelper(d->tabFocusFirst, true); } else { // Activate all toplevel items. QEvent event(QEvent::WindowActivate); @@ -3150,7 +3231,7 @@ bool QGraphicsScene::event(QEvent *event) // Deactivate the active panel (but keep it so we can // reactivate it later). QGraphicsItem *lastActivePanel = d->activePanel; - setActivePanel(0); + d->setActivePanelHelper(0, true); d->lastActivePanel = lastActivePanel; } else { // Activate all toplevel items. @@ -5095,63 +5176,15 @@ QGraphicsItem *QGraphicsScene::activePanel() const can also pass 0 for \a item, in which case QGraphicsScene will deactivate any currently active panel. + If the scene is currently inactive, \a item remains inactive until the + scene becomes active (or, ir \a item is 0, no item will be activated). + \sa activePanel(), isActive(), QGraphicsItem::isActive() */ void QGraphicsScene::setActivePanel(QGraphicsItem *item) { Q_D(QGraphicsScene); - if (item && item->scene() != this) { - qWarning("QGraphicsScene::setActivePanel: item %p must be part of this scene", - item); - return; - } - - // Find the item's panel. - QGraphicsItem *panel = item ? item->panel() : 0; - d->lastActivePanel = panel ? d->activePanel : 0; - if (panel == d->activePanel) - return; - - // Deactivate the last active panel. - if (d->activePanel) { - if (QGraphicsItem *fi = d->activePanel->focusItem()) { - // Remove focus from the current focus item. - if (fi == focusItem()) - setFocusItem(0, Qt::ActiveWindowFocusReason); - } - - QEvent event(QEvent::WindowDeactivate); - sendEvent(d->activePanel, &event); - } else if (panel) { - // Deactivate the scene if changing activation to a panel. - QEvent event(QEvent::WindowDeactivate); - foreach (QGraphicsItem *item, items()) { - if (item->isVisible() && !item->isPanel() && !item->parentItem()) - sendEvent(item, &event); - } - } - - // Update activate state. - d->activePanel = panel; - QEvent event(QEvent::ActivationChange); - QApplication::sendEvent(this, &event); - - // Activate - if (panel) { - QEvent event(QEvent::WindowActivate); - sendEvent(panel, &event); - - // Set focus on the panel's focus item. - if (QGraphicsItem *focusItem = panel->focusItem()) - focusItem->setFocus(Qt::ActiveWindowFocusReason); - } else if (isActive()) { - // Activate the scene - QEvent event(QEvent::WindowActivate); - foreach (QGraphicsItem *item, items()) { - if (item->isVisible() && !item->isPanel() && !item->parentItem()) - sendEvent(item, &event); - } - } + d->setActivePanelHelper(item, false); } /*! diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index c1b78ff..1f66eb4 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -132,6 +132,8 @@ public: QGraphicsItem *activePanel; QGraphicsItem *lastActivePanel; int activationRefCount; + int childExplicitActivation; + void setActivePanelHelper(QGraphicsItem *item, bool duringActivationEvent); void setFocusItemHelper(QGraphicsItem *item, Qt::FocusReason focusReason); QList<QGraphicsWidget *> popupWidgets; |