summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorAndreas Aardal Hanssen <andreas.aardal.hanssen@nokia.com>2009-08-31 12:06:47 (GMT)
committerAndreas Aardal Hanssen <andreas.aardal.hanssen@nokia.com>2009-08-31 14:14:48 (GMT)
commit62ca28a96d200fe55ed5bc2d0d1df327ab44c97e (patch)
tree0b88b18056f074f7dfb851f3a7fe0aa885955561 /src/gui
parent940b0b9e51f234f251d332f729531d6e9c3cea84 (diff)
downloadQt-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/gui')
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp37
-rw-r--r--src/gui/graphicsview/qgraphicsitem.h2
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h8
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp149
-rw-r--r--src/gui/graphicsview/qgraphicsscene_p.h2
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;