Exemple #1
0
/**
 * is called after a reparent has taken place to fix up the focus chain(s)
 */
void QGraphicsWidgetPrivate::fixFocusChainBeforeReparenting(QGraphicsWidget *newParent, 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;

    if (focusChild) {
        // Ensure that the current focus child doesn't leave pointers around
        // before reparenting.
        focusChild->clearFocus();
    }

    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;
    }

    // update tabFocusFirst for oldScene if the item is going to be removed from oldScene
    if (newParent)
        newScene = newParent->scene();
    QGraphicsScene *oldScene = q->scene();
    if (oldScene && newScene != oldScene)
        oldScene->d_func()->tabFocusFirst = firstOld;

    QGraphicsItem *topLevelItem = newParent ? newParent->topLevelItem() : 0;
    QGraphicsWidget *topLevel = 0;
    if (topLevelItem && topLevelItem->isWidget())
        topLevel = static_cast<QGraphicsWidget *>(topLevelItem);

    if (topLevel && newParent) {
        QGraphicsWidget *last = topLevel->d_func()->focusPrev;
        // link last with new chain
        last->d_func()->focusNext = q;
        focusPrev = last;

        // link last in chain with
        topLevel->d_func()->focusPrev = n;
        n->d_func()->focusNext = topLevel;
    } else {
        // q is the start of the focus chain
        n->d_func()->focusNext = q;
        focusPrev = n;
    }

}