diff options
Diffstat (limited to 'src/widgets/graphicsview')
-rw-r--r-- | src/widgets/graphicsview/qgraphicsitem.cpp | 49 | ||||
-rw-r--r-- | src/widgets/graphicsview/qgraphicsscene.cpp | 21 | ||||
-rw-r--r-- | src/widgets/graphicsview/qgraphicswidget_p.cpp | 104 |
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) |