diff options
Diffstat (limited to 'src/gui/graphicsview/qgraphicsscene.cpp')
-rw-r--r-- | src/gui/graphicsview/qgraphicsscene.cpp | 129 |
1 files changed, 77 insertions, 52 deletions
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index a819822..73dba7b 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -572,6 +572,10 @@ void QGraphicsScenePrivate::setFocusItemHelper(QGraphicsItem *item, Qt::FocusReason focusReason) { Q_Q(QGraphicsScene); + + while (item && item->d_ptr->focusScopeItem) + item = item->d_ptr->focusScopeItem; + if (item == focusItem) return; @@ -589,22 +593,18 @@ void QGraphicsScenePrivate::setFocusItemHelper(QGraphicsItem *item, return; } - // Auto-update focus proxy. The closest parent that detects - // focus proxies is updated as the proxy gains or loses focus. - if (item) { - QGraphicsItem *p = item->d_ptr->parent; - while (p) { - if (p->d_ptr->flags & QGraphicsItem::ItemAutoDetectsFocusProxy) { - p->setFocusProxy(item); - break; - } - p = p->d_ptr->parent; - } - } + QGraphicsItem *itemRootLevelFocusItem = + item?item->d_ptr->rootLevelFocusItem():0; if (focusItem) { QFocusEvent event(QEvent::FocusOut, focusReason); lastFocusItem = focusItem; + + QGraphicsItem *oldRootLevelFocusItem = + focusItem->d_ptr->rootLevelFocusItem(); + if (oldRootLevelFocusItem != itemRootLevelFocusItem) + oldRootLevelFocusItem->d_ptr->setItemFocusedInScope(false); + focusItem = 0; sendEvent(lastFocusItem, &event); @@ -622,6 +622,8 @@ void QGraphicsScenePrivate::setFocusItemHelper(QGraphicsItem *item, if (item) { focusItem = item; + itemRootLevelFocusItem->d_ptr->setItemFocusedInScope(true); + item->d_ptr->setItemFocusedInScope(true); QFocusEvent event(QEvent::FocusIn, focusReason); sendEvent(item, &event); } @@ -2240,11 +2242,19 @@ void QGraphicsScene::destroyItemGroup(QGraphicsItemGroup *group) void QGraphicsScene::addItem(QGraphicsItem *item) { Q_D(QGraphicsScene); + d->addItem(item); +} + +void QGraphicsScenePrivate::addItem(QGraphicsItem *item, + QGraphicsItem *focusScope) +{ + Q_Q(QGraphicsScene); + if (!item) { qWarning("QGraphicsScene::addItem: cannot add null item"); return; } - if (item->scene() == this) { + if (item->scene() == q) { qWarning("QGraphicsScene::addItem: item has already been added to this scene"); return; } @@ -2255,9 +2265,9 @@ void QGraphicsScene::addItem(QGraphicsItem *item) // Notify the item that its scene is changing, and allow the item to // react. const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange, - qVariantFromValue<QGraphicsScene *>(this))); + qVariantFromValue<QGraphicsScene *>(q))); QGraphicsScene *targetScene = qVariantValue<QGraphicsScene *>(newSceneVariant); - if (targetScene != this) { + if (targetScene != q) { if (targetScene && item->scene() != targetScene) targetScene->addItem(item); return; @@ -2266,7 +2276,7 @@ void QGraphicsScene::addItem(QGraphicsItem *item) // Detach this item from its parent if the parent's scene is different // from this scene. if (QGraphicsItem *itemParent = item->parentItem()) { - if (itemParent->scene() != this) + if (itemParent->scene() != q) item->setParentItem(0); } @@ -2274,98 +2284,113 @@ void QGraphicsScene::addItem(QGraphicsItem *item) item->d_func()->scene = targetScene; // Add the item in the index - d->index->addItem(item); + index->addItem(item); // Add to list of toplevels if this item is a toplevel. if (!item->d_ptr->parent) - d->registerTopLevelItem(item); + registerTopLevelItem(item); // Add to list of items that require an update. We cannot assume that the // item is fully constructed, so calling item->update() can lead to a pure // virtual function call to boundingRect(). - d->markDirty(item); - d->dirtyGrowingItemsBoundingRect = true; + markDirty(item); + dirtyGrowingItemsBoundingRect = true; // Disable selectionChanged() for individual items - ++d->selectionChanging; - int oldSelectedItemSize = d->selectedItems.size(); + ++selectionChanging; + int oldSelectedItemSize = selectedItems.size(); // Enable mouse tracking if the item accepts hover events or has a cursor set. - if (d->allItemsIgnoreHoverEvents && d->itemAcceptsHoverEvents_helper(item)) { - d->allItemsIgnoreHoverEvents = false; - d->enableMouseTrackingOnViews(); + if (allItemsIgnoreHoverEvents && itemAcceptsHoverEvents_helper(item)) { + allItemsIgnoreHoverEvents = false; + enableMouseTrackingOnViews(); } #ifndef QT_NO_CURSOR - if (d->allItemsUseDefaultCursor && item->hasCursor()) { - d->allItemsUseDefaultCursor = false; - if (d->allItemsIgnoreHoverEvents) // already enabled otherwise - d->enableMouseTrackingOnViews(); + if (allItemsUseDefaultCursor && item->hasCursor()) { + allItemsUseDefaultCursor = false; + if (allItemsIgnoreHoverEvents) // already enabled otherwise + enableMouseTrackingOnViews(); } #endif //QT_NO_CURSOR // Enable touch events if the item accepts touch events. - if (d->allItemsIgnoreTouchEvents && item->acceptTouchEvents()) { - d->allItemsIgnoreTouchEvents = false; - d->enableTouchEventsOnViews(); + if (allItemsIgnoreTouchEvents && item->acceptTouchEvents()) { + allItemsIgnoreTouchEvents = false; + enableTouchEventsOnViews(); } // Update selection lists if (item->isSelected()) - d->selectedItems << item; + selectedItems << item; if (item->isWidget() && item->isVisible() && static_cast<QGraphicsWidget *>(item)->windowType() == Qt::Popup) - d->addPopup(static_cast<QGraphicsWidget *>(item)); + addPopup(static_cast<QGraphicsWidget *>(item)); // Update creation order focus chain. Make sure to leave the widget's // internal tab order intact. if (item->isWidget()) { QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item); - if (!d->tabFocusFirst) { + if (!tabFocusFirst) { // No first tab focus widget - make this the first tab focus // widget. - d->tabFocusFirst = widget; + tabFocusFirst = widget; } else if (!widget->parentWidget()) { // Adding a widget that is not part of a tab focus chain. - QGraphicsWidget *last = d->tabFocusFirst->d_func()->focusPrev; + QGraphicsWidget *last = 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; + tabFocusFirst->d_func()->focusPrev = lastNew; + lastNew->d_func()->focusNext = tabFocusFirst; } } // Add all children recursively + QGraphicsItem *subFocusScope = + (item->d_ptr->flags & QGraphicsItem::ItemIsFocusScope)?item:focusScope; foreach (QGraphicsItem *child, item->children()) - addItem(child); + addItem(child, subFocusScope); // Resolve font and palette. - item->d_ptr->resolveFont(d->font.resolve()); - item->d_ptr->resolvePalette(d->palette.resolve()); + item->d_ptr->resolveFont(font.resolve()); + item->d_ptr->resolvePalette(palette.resolve()); if (!item->d_ptr->explicitlyHidden) { - if (d->unpolishedItems.isEmpty()) - QMetaObject::invokeMethod(this, "_q_polishItems", Qt::QueuedConnection); - d->unpolishedItems << item; + if (unpolishedItems.isEmpty()) + QMetaObject::invokeMethod(q, "_q_polishItems", Qt::QueuedConnection); + unpolishedItems << item; } // Reenable selectionChanged() for individual items - --d->selectionChanging; - if (!d->selectionChanging && d->selectedItems.size() != oldSelectedItemSize) - emit selectionChanged(); + --selectionChanging; + if (!selectionChanging && selectedItems.size() != oldSelectedItemSize) + emit q->selectionChanged(); // Deliver post-change notification item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant); // Auto-activate the first inactive window if the scene is active. - if (d->activationRefCount > 0 && !d->activeWindow && item->isWindow()) - setActiveWindow(static_cast<QGraphicsWidget *>(item)); + if (activationRefCount > 0 && !activeWindow && item->isWindow()) + q->setActiveWindow(static_cast<QGraphicsWidget *>(item)); // Ensure that newly added items that have subfocus set, gain // focus automatically if there isn't a focus item already. - if (!d->focusItem && item->focusItem()) + if (!focusItem && item->focusItem()) item->focusItem()->setFocus(); - d->updateInputMethodSensitivityInViews(); + // Ensure that focus scopes set themselves up at add time + if (item->d_ptr->itemIsFocusedInScope) { + if (focusScope && !focusScope->d_ptr->focusScopeItem) { + item->setFocus(); + } else if (!(focusScope && focusScope->d_ptr->focusScopeItem == item) && + !(focusItem && focusItem->d_ptr->rootLevelFocusItem() == item)) { + // We unset the focused in scope variable in this item if: + // It's not scope focused in the closest focus scope, and + // It's not the root-level item for the globally focused item + item->d_ptr->setItemFocusedInScope(false); + } + } + + updateInputMethodSensitivityInViews(); } /*! |