diff options
Diffstat (limited to 'src/gui/graphicsview/qgraphicsitem.cpp')
-rw-r--r-- | src/gui/graphicsview/qgraphicsitem.cpp | 97 |
1 files changed, 95 insertions, 2 deletions
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 3249bb1..c3934c7 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1479,6 +1479,7 @@ QList<QGraphicsItem *> QGraphicsItem::children() const */ QList<QGraphicsItem *> QGraphicsItem::childItems() const { + const_cast<QGraphicsItem *>(this)->d_ptr->ensureSortedChildren(); return d_ptr->children; } @@ -4048,6 +4049,82 @@ void QGraphicsItem::setZValue(qreal z) } /*! + \internal + + Ensures that the list of children is sorted by insertion order, and that + the siblingIndexes are packed (no gaps), and start at 0. + + ### This function is almost identical to + QGraphicsScenePrivate::ensureSequentialTopLevelSiblingIndexes(). +*/ +void QGraphicsItemPrivate::ensureSequentialSiblingIndex() +{ + if (!sequentialOrdering) { + qSort(children.begin(), children.end(), insertionOrder); + sequentialOrdering = 1; + needSortChildren = 1; + } + if (holesInSiblingIndex) { + holesInSiblingIndex = 0; + for (int i = 0; i < children.size(); ++i) + children[i]->d_ptr->siblingIndex = i; + } +} + +/*! + \since 4.6 + + Stacks this item before \a sibling, which must be a sibling item (i.e., the + two items must share the same parent item, or must both be toplevel items). + The \a sibling must have the same Z value as this item, otherwise calling + this function will have no effect. + + By default, all items are stacked by insertion order (i.e., the first item + you add is drawn before the next item you add). If two items' Z values are + different, then the item with the highest Z value is drawn on top. When the + Z values are the same, the insertion order will decide the stacking order. + + \sa setZValue(), ItemStacksBehindParent +*/ +void QGraphicsItem::stackBefore(const QGraphicsItem *sibling) +{ + if (sibling == this) + return; + if (!sibling || d_ptr->parent != sibling->parentItem()) { + qWarning("QGraphicsItem::stackUnder: cannot stack under %p, which must be a sibling", sibling); + return; + } + QList<QGraphicsItem *> *siblings = d_ptr->parent + ? &d_ptr->parent->d_ptr->children + : (d_ptr->scene ? &d_ptr->scene->d_func()->topLevelItems : 0); + if (!siblings) { + qWarning("QGraphicsItem::stackUnder: cannot stack under %p, which must be a sibling", sibling); + return; + } + + // First, make sure that the sibling indexes have no holes. This also + // marks the children list for sorting. + if (d_ptr->parent) + d_ptr->parent->d_ptr->ensureSequentialSiblingIndex(); + else + d_ptr->scene->d_func()->ensureSequentialTopLevelSiblingIndexes(); + + // Only move items with the same Z value, and that need moving. + int siblingIndex = sibling->d_ptr->siblingIndex; + int myIndex = d_ptr->siblingIndex; + if (myIndex >= siblingIndex && d_ptr->z == sibling->d_ptr->z) { + siblings->move(myIndex, siblingIndex); + // Fixup the insertion ordering. + for (int i = 0; i < siblings->size(); ++i) { + int &index = siblings->at(i)->d_ptr->siblingIndex; + if (i != siblingIndex && index >= siblingIndex && index <= myIndex) + ++index; + } + d_ptr->siblingIndex = siblingIndex; + } +} + +/*! Returns the bounding rect of this item's descendants (i.e., its children, their children, etc.) in local coordinates. The rectangle will contain all descendants after they have been mapped @@ -4753,20 +4830,36 @@ void QGraphicsItemPrivate::resolveDepth() /*! \internal + + ### This function is almost identical to + QGraphicsScenePrivate::registerTopLevelItem(). */ void QGraphicsItemPrivate::addChild(QGraphicsItem *child) { - needSortChildren = 1; + // Remove all holes from the sibling index list. Now the max index + // number is equal to the size of the children list. + ensureSequentialSiblingIndex(); + needSortChildren = 1; // ### maybe 0 child->d_ptr->siblingIndex = children.size(); children.append(child); } /*! \internal + + ### This function is almost identical to + QGraphicsScenePrivate::unregisterTopLevelItem(). */ void QGraphicsItemPrivate::removeChild(QGraphicsItem *child) { - children.removeOne(child); + // When removing elements in the middle of the children list, + // there will be a "gap" in the list of sibling indexes (0,1,3,4). + if (!holesInSiblingIndex) + holesInSiblingIndex = child->d_ptr->siblingIndex != children.size() - 1; + if (sequentialOrdering && !holesInSiblingIndex) + children.removeAt(child->d_ptr->siblingIndex); + else + children.removeOne(child); // NB! Do not use children.removeAt(child->d_ptr->siblingIndex) because // the child is not guaranteed to be at the index after the list is sorted. // (see ensureSortedChildren()). |