summaryrefslogtreecommitdiffstats
path: root/src/widgets/graphicsview
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/graphicsview')
-rw-r--r--src/widgets/graphicsview/qgraphicsitem.cpp49
-rw-r--r--src/widgets/graphicsview/qgraphicsscene.cpp21
-rw-r--r--src/widgets/graphicsview/qgraphicswidget_p.cpp104
3 files changed, 96 insertions, 78 deletions
diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp
index c30435e56a..cd379e1b05 100644
--- a/src/widgets/graphicsview/qgraphicsitem.cpp
+++ b/src/widgets/graphicsview/qgraphicsitem.cpp
@@ -1884,15 +1884,46 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags)
d_ptr->scene->d_func()->updateInputMethodSensitivityInViews();
}
+ if ((flags & ItemIsPanel) != (oldFlags & ItemIsPanel)) {
+ bool becomesPanel = (flags & ItemIsPanel);
+ if ((d_ptr->panelModality != NonModal) && d_ptr->scene) {
+ // update the panel's modal state
+ if (becomesPanel)
+ d_ptr->scene->d_func()->enterModal(this);
+ else
+ d_ptr->scene->d_func()->leaveModal(this);
+ }
+ if (d_ptr->isWidget && (becomesPanel || parentWidget())) {
+ QGraphicsWidget *w = static_cast<QGraphicsWidget *>(this);
+ QGraphicsWidget *focusFirst = w;
+ QGraphicsWidget *focusLast = w;
+ for (;;) {
+ QGraphicsWidget *test = focusLast->d_func()->focusNext;
+ if (!w->isAncestorOf(test) || test == w)
+ break;
+ focusLast = test;
+ }
- if ((d_ptr->panelModality != NonModal)
- && d_ptr->scene
- && (flags & ItemIsPanel) != (oldFlags & ItemIsPanel)) {
- // update the panel's modal state
- if (flags & ItemIsPanel)
- d_ptr->scene->d_func()->enterModal(this);
- else
- d_ptr->scene->d_func()->leaveModal(this);
+ if (becomesPanel) {
+ // unlink own widgets from focus chain
+ QGraphicsWidget *beforeMe = w->d_func()->focusPrev;
+ QGraphicsWidget *afterMe = focusLast->d_func()->focusNext;
+ beforeMe->d_func()->focusNext = afterMe;
+ afterMe->d_func()->focusPrev = beforeMe;
+ focusFirst->d_func()->focusPrev = focusLast;
+ focusLast->d_func()->focusNext = focusFirst;
+ if (!isAncestorOf(focusFirst->d_func()->focusNext))
+ focusFirst->d_func()->focusNext = w;
+ } else if (QGraphicsWidget *pw = parentWidget()) {
+ // link up own widgets to focus chain
+ QGraphicsWidget *beforeMe = pw;
+ QGraphicsWidget *afterMe = pw->d_func()->focusNext;
+ beforeMe->d_func()->focusNext = w;
+ afterMe->d_func()->focusPrev = focusLast;
+ w->d_func()->focusPrev = beforeMe;
+ focusLast->d_func()->focusNext = afterMe;
+ }
+ }
}
if (d_ptr->scene) {
@@ -2274,7 +2305,7 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly,
scene->d_func()->leaveModal(q_ptr);
}
if (hasFocus && scene) {
- // Hiding the closest non-panel ancestor of the focus item
+ // Hiding the focus item or the closest non-panel ancestor of the focus item
QGraphicsItem *focusItem = scene->focusItem();
bool clear = true;
if (isWidget && !focusItem->isPanel()) {
diff --git a/src/widgets/graphicsview/qgraphicsscene.cpp b/src/widgets/graphicsview/qgraphicsscene.cpp
index ee65fb8fa6..769b488f39 100644
--- a/src/widgets/graphicsview/qgraphicsscene.cpp
+++ b/src/widgets/graphicsview/qgraphicsscene.cpp
@@ -607,7 +607,7 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item)
q->removeItem(item->d_ptr->children.at(i));
}
- if (!item->d_ptr->inDestructor && item == tabFocusFirst) {
+ if (!item->d_ptr->inDestructor && !item->parentItem() && item->isWidget()) {
QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
widget->d_func()->fixFocusChainBeforeReparenting(0, oldScene, 0);
}
@@ -2528,14 +2528,13 @@ void QGraphicsScene::addItem(QGraphicsItem *item)
// No first tab focus widget - make this the first tab focus
// widget.
d->tabFocusFirst = widget;
- } else if (!widget->parentWidget()) {
+ } else if (!widget->parentWidget() && !widget->isPanel()) {
// Adding a widget that is not part of a tab focus chain.
- QGraphicsWidget *last = d->tabFocusFirst->d_func()->focusPrev;
- QGraphicsWidget *lastNew = widget->d_func()->focusPrev;
- last->d_func()->focusNext = widget;
- widget->d_func()->focusPrev = last;
- d->tabFocusFirst->d_func()->focusPrev = lastNew;
- lastNew->d_func()->focusNext = d->tabFocusFirst;
+ QGraphicsWidget *myNewPrev = d->tabFocusFirst->d_func()->focusPrev;
+ myNewPrev->d_func()->focusNext = widget;
+ widget->d_func()->focusPrev->d_func()->focusNext = d->tabFocusFirst;
+ d->tabFocusFirst->d_func()->focusPrev = widget->d_func()->focusPrev;
+ widget->d_func()->focusPrev = myNewPrev;
}
}
@@ -5330,7 +5329,7 @@ bool QGraphicsScene::focusNextPrevChild(bool next)
return true;
}
}
- if (!d->tabFocusFirst) {
+ if (!item && !d->tabFocusFirst) {
// No widgets...
return false;
}
@@ -5342,8 +5341,10 @@ bool QGraphicsScene::focusNextPrevChild(bool next)
} else {
QGraphicsWidget *test = static_cast<QGraphicsWidget *>(item);
widget = next ? test->d_func()->focusNext : test->d_func()->focusPrev;
- if ((next && widget == d->tabFocusFirst) || (!next && widget == d->tabFocusFirst->d_func()->focusPrev))
+ if (!widget->panel() && ((next && widget == d->tabFocusFirst) || (!next && widget == d->tabFocusFirst->d_func()->focusPrev))) {
+ // Tab out of the scene.
return false;
+ }
}
QGraphicsWidget *widgetThatHadFocus = widget;
diff --git a/src/widgets/graphicsview/qgraphicswidget_p.cpp b/src/widgets/graphicsview/qgraphicswidget_p.cpp
index 4ec215a720..dfebbb5036 100644
--- a/src/widgets/graphicsview/qgraphicswidget_p.cpp
+++ b/src/widgets/graphicsview/qgraphicswidget_p.cpp
@@ -764,73 +764,59 @@ bool QGraphicsWidgetPrivate::hasDecoration() const
void QGraphicsWidgetPrivate::fixFocusChainBeforeReparenting(QGraphicsWidget *newParent, QGraphicsScene *oldScene, QGraphicsScene *newScene)
{
Q_Q(QGraphicsWidget);
-
Q_ASSERT(focusNext && focusPrev);
- QGraphicsWidget *n = q; //last one in 'new' list
- QGraphicsWidget *o = 0; //last one in 'old' list
-
- QGraphicsWidget *w = focusNext;
-
- QGraphicsWidget *firstOld = 0;
- bool wasPreviousNew = true;
-
- while (w != q) {
- bool isCurrentNew = q->isAncestorOf(w);
- if (isCurrentNew) {
- if (!wasPreviousNew) {
- n->d_func()->focusNext = w;
- w->d_func()->focusPrev = n;
- }
- n = w;
- } else /*if (!isCurrentNew)*/ {
- if (wasPreviousNew) {
- if (o) {
- o->d_func()->focusNext = w;
- w->d_func()->focusPrev = o;
- } else {
- firstOld = w;
- }
- }
- o = w;
- }
- w = w->d_func()->focusNext;
- wasPreviousNew = isCurrentNew;
- }
-
- // repair the 'old' chain
- if (firstOld) {
- o->d_func()->focusNext = firstOld;
- firstOld->d_func()->focusPrev = o;
+ if (q_ptr->isPanel()) {
+ // panels are never a part of their parent's or ancestors' focus
+ // chains. so reparenting a panel is easy; there's nothing to
+ // do.
+ return;
}
- // update tabFocusFirst for oldScene if the item is going to be removed from oldScene
- if (newParent)
- newScene = newParent->scene();
-
- if (oldScene && newScene != oldScene)
- oldScene->d_func()->tabFocusFirst = (firstOld && firstOld->scene() == oldScene) ? firstOld : 0;
-
- QGraphicsItem *topLevelItem = newParent ? newParent->topLevelItem() : 0;
- QGraphicsWidget *topLevel = 0;
- if (topLevelItem && topLevelItem->isWidget())
- topLevel = static_cast<QGraphicsWidget *>(topLevelItem);
+ // we're not a panel, so find the first widget in the focus chain
+ // (this), and the last (this, or the last widget that is still
+ // a descendent of this). also find the widgets that currently /
+ // before reparenting point to this widgets' focus chain.
+ QGraphicsWidget *focusFirst = q;
+ QGraphicsWidget *focusBefore = focusPrev;
+ QGraphicsWidget *focusLast = focusFirst;
+ QGraphicsWidget *focusAfter = focusNext;
+ do {
+ if (!q->isAncestorOf(focusAfter))
+ break;
+ focusLast = focusAfter;
+ } while ((focusAfter = focusAfter->d_func()->focusNext));
- if (topLevel && newParent) {
- QGraphicsWidget *last = topLevel->d_func()->focusPrev;
- // link last with new chain
- last->d_func()->focusNext = q;
- focusPrev = last;
+ if (!parent && oldScene && oldScene != newScene && oldScene->d_func()->tabFocusFirst == q) {
+ // detach from old scene's top level focus chain.
+ oldScene->d_func()->tabFocusFirst = (focusAfter != q) ? focusAfter : 0;
+ }
- // link last in chain with
- topLevel->d_func()->focusPrev = n;
- n->d_func()->focusNext = topLevel;
+ // detach from current focus chain; skip this widget subtree.
+ focusBefore->d_func()->focusNext = focusAfter;
+ focusAfter->d_func()->focusPrev = focusBefore;
+
+ if (newParent) {
+ // attach to new parent's focus chain as the last element
+ // in its chain.
+ QGraphicsWidget *newFocusFirst = newParent;
+ QGraphicsWidget *newFocusLast = newFocusFirst;
+ QGraphicsWidget *newFocusAfter = newFocusFirst->d_func()->focusNext;
+ do {
+ if (!newParent->isAncestorOf(newFocusAfter))
+ break;
+ newFocusLast = newFocusAfter;
+ } while ((newFocusAfter = newFocusAfter->d_func()->focusNext));
+
+ newFocusLast->d_func()->focusNext = q;
+ focusLast->d_func()->focusNext = newFocusAfter;
+ newFocusAfter->d_func()->focusPrev = focusLast;
+ focusPrev = newFocusLast;
} else {
- // q is the start of the focus chain
- n->d_func()->focusNext = q;
- focusPrev = n;
+ // no new parent, so just link up our own prev->last widgets.
+ focusPrev = focusLast;
+ focusLast->d_func()->focusNext = q;
}
-
}
void QGraphicsWidgetPrivate::setLayout_helper(QGraphicsLayout *l)