summaryrefslogtreecommitdiffstats
path: root/src/gui/graphicsview/qgraphicsitem.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/graphicsview/qgraphicsitem.cpp')
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp97
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()).