summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorninerider <qt-info@nokia.com>2009-09-25 08:20:57 (GMT)
committerninerider <qt-info@nokia.com>2009-09-25 08:20:57 (GMT)
commit4c35ea3b6e39cbbaffb3e5187cba247da368b638 (patch)
tree6e3551b8001817fa214444eeb423da2dcd77f061
parentb7070e227b587485b7dec3d1c8a89f23b67540d3 (diff)
parent45bf804ce2feec74bd7787a64d72184da9458254 (diff)
downloadQt-4c35ea3b6e39cbbaffb3e5187cba247da368b638.zip
Qt-4c35ea3b6e39cbbaffb3e5187cba247da368b638.tar.gz
Qt-4c35ea3b6e39cbbaffb3e5187cba247da368b638.tar.bz2
Merge branch '4.6' of scm.dev.nokia.troll.no:qt/qt into 4.6
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp97
-rw-r--r--src/gui/graphicsview/qgraphicsitem.h1
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h26
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp41
-rw-r--r--src/gui/graphicsview/qgraphicsscene_p.h5
-rw-r--r--src/gui/kernel/qapplication_mac.mm82
-rw-r--r--src/gui/kernel/qcocoaview_mac.mm35
-rw-r--r--tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp79
8 files changed, 331 insertions, 35 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()).
diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h
index 089d6fe..99d2e12 100644
--- a/src/gui/graphicsview/qgraphicsitem.h
+++ b/src/gui/graphicsview/qgraphicsitem.h
@@ -302,6 +302,7 @@ public:
// Stacking order
qreal zValue() const;
void setZValue(qreal z);
+ void stackBefore(const QGraphicsItem *sibling);
// Hit test
virtual QRectF boundingRect() const = 0;
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index fd2ff34..3feccdc 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -153,7 +153,7 @@ public:
dirtyClipPath(1),
emptyClipPath(0),
inSetPosHelper(0),
- needSortChildren(1),
+ needSortChildren(1), // ### can be 0 by default?
allChildrenDirty(0),
fullUpdatePending(0),
flags(0),
@@ -174,6 +174,8 @@ public:
mouseSetsFocus(1),
explicitActivate(0),
wantsActive(0),
+ holesInSiblingIndex(0),
+ sequentialOrdering(1),
globalStackingOrder(-1),
q_ptr(0)
{
@@ -421,6 +423,8 @@ public:
inline QTransform transformToParent() const;
inline void ensureSortedChildren();
+ static inline bool insertionOrder(QGraphicsItem *a, QGraphicsItem *b);
+ void ensureSequentialSiblingIndex();
QPainterPath cachedClipPath;
QRectF childrenBoundingRect;
@@ -493,6 +497,8 @@ public:
// New 32 bits
quint32 explicitActivate : 1;
quint32 wantsActive : 1;
+ quint32 holesInSiblingIndex : 1;
+ quint32 sequentialOrdering : 1;
// Optional stacking order
int globalStackingOrder;
@@ -646,14 +652,32 @@ inline QTransform QGraphicsItemPrivate::transformToParent() const
return matrix;
}
+/*!
+ \internal
+*/
inline void QGraphicsItemPrivate::ensureSortedChildren()
{
if (needSortChildren) {
qSort(children.begin(), children.end(), qt_notclosestLeaf);
needSortChildren = 0;
+ sequentialOrdering = 1;
+ for (int i = 0; i < children.size(); ++i) {
+ if (children[i]->d_ptr->siblingIndex != i) {
+ sequentialOrdering = 0;
+ break;
+ }
+ }
}
}
+/*!
+ \internal
+*/
+inline bool QGraphicsItemPrivate::insertionOrder(QGraphicsItem *a, QGraphicsItem *b)
+{
+ return a->d_ptr->siblingIndex < b->d_ptr->siblingIndex;
+}
+
QT_END_NAMESPACE
#endif // QT_NO_GRAPHICSVIEW
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 0655ecc..4b74b67 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -283,6 +283,8 @@ QGraphicsScenePrivate::QGraphicsScenePrivate()
processDirtyItemsEmitted(false),
selectionChanging(0),
needSortTopLevelItems(true),
+ holesInTopLevelSiblingIndex(false),
+ topLevelSequentialOrdering(true),
stickyFocus(false),
hasFocus(false),
focusItem(0),
@@ -379,24 +381,36 @@ void QGraphicsScenePrivate::_q_emitUpdated()
/*!
\internal
+
+ ### This function is almost identical to QGraphicsItemPrivate::addChild().
*/
void QGraphicsScenePrivate::registerTopLevelItem(QGraphicsItem *item)
{
- needSortTopLevelItems = true;
+ item->d_ptr->ensureSequentialSiblingIndex();
+ needSortTopLevelItems = true; // ### maybe false
item->d_ptr->siblingIndex = topLevelItems.size();
topLevelItems.append(item);
}
/*!
\internal
+
+ ### This function is almost identical to QGraphicsItemPrivate::removeChild().
*/
void QGraphicsScenePrivate::unregisterTopLevelItem(QGraphicsItem *item)
{
- topLevelItems.removeOne(item);
+ if (!holesInTopLevelSiblingIndex)
+ holesInTopLevelSiblingIndex = item->d_ptr->siblingIndex != topLevelItems.size() - 1;
+ if (topLevelSequentialOrdering && !holesInTopLevelSiblingIndex)
+ topLevelItems.removeAt(item->d_ptr->siblingIndex);
+ else
+ topLevelItems.removeOne(item);
// NB! Do not use topLevelItems.removeAt(item->d_ptr->siblingIndex) because
// the item is not guaranteed to be at the index after the list is sorted
// (see ensureSortedTopLevelItems()).
item->d_ptr->siblingIndex = -1;
+ if (topLevelSequentialOrdering)
+ topLevelSequentialOrdering = !holesInTopLevelSiblingIndex;
}
/*!
@@ -1239,6 +1253,29 @@ void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mou
/*!
\internal
+ Ensures that the list of toplevels is sorted by insertion order, and that
+ the siblingIndexes are packed (no gaps), and start at 0.
+
+ ### This function is almost identical to
+ QGraphicsItemPrivate::ensureSequentialSiblingIndex().
+*/
+void QGraphicsScenePrivate::ensureSequentialTopLevelSiblingIndexes()
+{
+ if (!topLevelSequentialOrdering) {
+ qSort(topLevelItems.begin(), topLevelItems.end(), QGraphicsItemPrivate::insertionOrder);
+ topLevelSequentialOrdering = true;
+ needSortTopLevelItems = 1;
+ }
+ if (holesInTopLevelSiblingIndex) {
+ holesInTopLevelSiblingIndex = 0;
+ for (int i = 0; i < topLevelItems.size(); ++i)
+ topLevelItems[i]->d_ptr->siblingIndex = i;
+ }
+}
+
+/*!
+ \internal
+
Set the font and propagate the changes if the font is different from the
current font.
*/
diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h
index 3b03624..46917ce 100644
--- a/src/gui/graphicsview/qgraphicsscene_p.h
+++ b/src/gui/graphicsview/qgraphicsscene_p.h
@@ -111,6 +111,9 @@ public:
QList<QGraphicsItem *> unpolishedItems;
QList<QGraphicsItem *> topLevelItems;
bool needSortTopLevelItems;
+ bool holesInTopLevelSiblingIndex;
+ bool topLevelSequentialOrdering;
+
QMap<QGraphicsItem *, QPointF> movingItemsInitialPositions;
void registerTopLevelItem(QGraphicsItem *item);
void unregisterTopLevelItem(QGraphicsItem *item);
@@ -255,6 +258,8 @@ public:
}
}
+ void ensureSequentialTopLevelSiblingIndexes();
+
QStyle *style;
QFont font;
void setFont_helper(const QFont &font);
diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm
index 7e8d96f..a656c7f 100644
--- a/src/gui/kernel/qapplication_mac.mm
+++ b/src/gui/kernel/qapplication_mac.mm
@@ -972,6 +972,7 @@ static EventTypeSpec app_events[] = {
{ kEventClassWindow, kEventWindowActivated },
{ kEventClassWindow, kEventWindowDeactivated },
+ { kEventClassMouse, kEventMouseScroll },
{ kEventClassMouse, kEventMouseWheelMoved },
{ kEventClassMouse, kEventMouseDown },
{ kEventClassMouse, kEventMouseUp },
@@ -1639,6 +1640,7 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event
case kEventMouseDown: edesc = "MouseButtonPress"; break;
case kEventMouseUp: edesc = "MouseButtonRelease"; break;
case kEventMouseDragged: case kEventMouseMoved: edesc = "MouseMove"; break;
+ case kEventMouseScroll: edesc = "MouseWheelScroll"; break;
case kEventMouseWheelMoved: edesc = "MouseWheelMove"; break;
}
if(ekind == kEventMouseDown || ekind == kEventMouseUp)
@@ -1659,12 +1661,43 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event
sizeof(mac_buttons), 0, &mac_buttons);
buttons = qt_mac_get_buttons(mac_buttons);
}
- int wheel_delta=0;
- if(ekind == kEventMouseWheelMoved) {
- int mdelt = 0;
- GetEventParameter(event, kEventParamMouseWheelDelta, typeSInt32, 0,
+
+ int wheel_deltaX = 0;
+ int wheel_deltaY = 0;
+ static EventRef compatibilityEvent = 0;
+
+ if (ekind == kEventMouseScroll) {
+ // kEventMouseScroll is the new way of dealing with mouse wheel
+ // events (kEventMouseWheelMoved was the old). kEventMouseScroll results
+ // in much smoother scrolling when using Mighty Mouse or TrackPad. For
+ // compatibility with older applications, carbon will also send us
+ // kEventMouseWheelMoved events if we dont eat this event
+ // (actually two events; one for horizontal and one for vertical).
+ // As a results of this, and to make sure we dont't receive duplicate events,
+ // we try to detect when this happend by checking the 'compatibilityEvent'.
+ SInt32 mdelt = 0;
+ GetEventParameter(event, kEventParamMouseWheelSmoothHorizontalDelta, typeSInt32, 0,
+ sizeof(mdelt), 0, &mdelt);
+ wheel_deltaX = mdelt;
+ GetEventParameter(event, kEventParamMouseWheelSmoothVerticalDelta, typeSInt32, 0,
sizeof(mdelt), 0, &mdelt);
- wheel_delta = mdelt * 120;
+ wheel_deltaY = mdelt;
+ GetEventParameter(event, kEventParamEventRef, typeEventRef, 0,
+ sizeof(compatibilityEvent), 0, &compatibilityEvent);
+ } else if (ekind == kEventMouseWheelMoved) {
+ if (event != compatibilityEvent) {
+ compatibilityEvent = 0;
+ int mdelt = 0;
+ GetEventParameter(event, kEventParamMouseWheelDelta, typeSInt32, 0,
+ sizeof(mdelt), 0, &mdelt);
+ EventMouseWheelAxis axis;
+ GetEventParameter(event, kEventParamMouseWheelAxis, typeMouseWheelAxis, 0,
+ sizeof(axis), 0, &axis);
+ if (axis == kEventMouseWheelAxisX)
+ wheel_deltaX = mdelt * 120;
+ else
+ wheel_deltaY = mdelt * 120;
+ }
}
Qt::MouseButton button = Qt::NoButton;
@@ -2054,20 +2087,29 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event
qt_mac_dblclick.last_button = button;
qt_mac_dblclick.last_time = GetEventTime(event);
}
- if(wheel_delta) {
- EventMouseWheelAxis axis;
- GetEventParameter(event, kEventParamMouseWheelAxis, typeMouseWheelAxis, 0,
- sizeof(axis), 0, &axis);
- QWheelEvent qwe(plocal, p, wheel_delta, buttons, modifiers,
- axis == kEventMouseWheelAxisX ? Qt::Horizontal : Qt::Vertical);
- QApplication::sendSpontaneousEvent(widget, &qwe);
- if(!qwe.isAccepted() && QApplicationPrivate::focus_widget && QApplicationPrivate::focus_widget != widget) {
- QWheelEvent qwe2(QApplicationPrivate::focus_widget->mapFromGlobal(p), p,
- wheel_delta, buttons, modifiers,
- axis == kEventMouseWheelAxisX ? Qt::Horizontal : Qt::Vertical);
- QApplication::sendSpontaneousEvent(QApplicationPrivate::focus_widget, &qwe2);
- if(!qwe2.isAccepted())
- handled_event = false;
+
+ if (wheel_deltaX || wheel_deltaY) {
+ if (wheel_deltaX) {
+ QWheelEvent qwe(plocal, p, wheel_deltaX, buttons, modifiers, Qt::Horizontal);
+ QApplication::sendSpontaneousEvent(widget, &qwe);
+ if (!qwe.isAccepted() && QApplicationPrivate::focus_widget && QApplicationPrivate::focus_widget != widget) {
+ QWheelEvent qwe2(QApplicationPrivate::focus_widget->mapFromGlobal(p), p,
+ wheel_deltaX, buttons, modifiers, Qt::Horizontal);
+ QApplication::sendSpontaneousEvent(QApplicationPrivate::focus_widget, &qwe2);
+ if (!qwe2.isAccepted())
+ handled_event = false;
+ }
+ }
+ if (wheel_deltaY) {
+ QWheelEvent qwe(plocal, p, wheel_deltaY, buttons, modifiers, Qt::Vertical);
+ QApplication::sendSpontaneousEvent(widget, &qwe);
+ if (!qwe.isAccepted() && QApplicationPrivate::focus_widget && QApplicationPrivate::focus_widget != widget) {
+ QWheelEvent qwe2(QApplicationPrivate::focus_widget->mapFromGlobal(p), p,
+ wheel_deltaY, buttons, modifiers, Qt::Vertical);
+ QApplication::sendSpontaneousEvent(QApplicationPrivate::focus_widget, &qwe2);
+ if (!qwe2.isAccepted())
+ handled_event = false;
+ }
}
} else {
#ifdef QMAC_SPEAK_TO_ME
@@ -2130,7 +2172,7 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event
plocal.x(), plocal.y(), event_desc, (QWidget*)widget,
widget ? widget->objectName().toLocal8Bit().constData() : "*Unknown*",
widget ? widget->metaObject()->className() : "*Unknown*",
- button, (int)buttons, (int)modifiers, wheel_delta);
+ button, (int)buttons, (int)modifiers, wheel_deltaX);
#endif
} else {
handled_event = false;
diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm
index 7693ca7..4ebf8a9 100644
--- a/src/gui/kernel/qcocoaview_mac.mm
+++ b/src/gui/kernel/qcocoaview_mac.mm
@@ -63,6 +63,11 @@
#include <qdebug.h>
+@interface NSEvent (DeviceDelta)
+ - (float)deviceDeltaX;
+ - (float)deviceDeltaY;
+ - (float)deviceDeltaZ;
+@end
QT_BEGIN_NAMESPACE
@@ -776,17 +781,27 @@ extern "C" {
Qt::MouseButton buttons = cocoaButton2QtButton([theEvent buttonNumber]);
bool wheelOK = false;
Qt::KeyboardModifiers keyMods = qt_cocoaModifiers2QtModifiers([theEvent modifierFlags]);
-
QWidget *widgetToGetMouse = qwidget;
-
- // Mouse wheel deltas seem to tick in at increments of 0.1. Qt widgets
- // expect the delta to be a multiple of 120.
- const int ScrollFactor = 10 * 120;
- // The qMax(...) factor reduces the
- // acceleration for large wheel deltas.
- int deltaX = [theEvent deltaX] * ScrollFactor * qMax(0.6, 1.1 - qAbs([theEvent deltaX]));
- int deltaY = [theEvent deltaY] * ScrollFactor * qMax(0.6, 1.1 - qAbs([theEvent deltaY]));
- int deltaZ = [theEvent deltaZ] * ScrollFactor * qMax(0.6, 1.1 - qAbs([theEvent deltaZ]));
+ int deltaX = 0;
+ int deltaY = 0;
+ int deltaZ = 0;
+
+ const EventRef carbonEvent = (EventRef)[theEvent eventRef];
+ const UInt32 carbonEventKind = carbonEvent ? ::GetEventKind(carbonEvent) : 0;
+ if (carbonEventKind == kEventMouseScroll) {
+ // The mouse device containts pixel scroll
+ // wheel support (Mighty Mouse, Trackpad)
+ deltaX = (int)[theEvent deviceDeltaX] * 120;
+ deltaY = (int)[theEvent deviceDeltaY] * 120;
+ deltaZ = (int)[theEvent deviceDeltaZ] * 120;
+ } else { // carbonEventKind == kEventMouseWheelMoved
+ // Mouse wheel deltas seem to tick in at increments of 0.1.
+ // Qt widgets expect the delta to be a multiple of 120.
+ const int scrollFactor = 10 * 120;
+ deltaX = [theEvent deltaX] * scrollFactor * qMax(0.6, 1.1 - qAbs([theEvent deltaX]));
+ deltaY = [theEvent deltaY] * scrollFactor * qMax(0.6, 1.1 - qAbs([theEvent deltaY]));
+ deltaZ = [theEvent deltaZ] * scrollFactor * qMax(0.6, 1.1 - qAbs([theEvent deltaZ]));
+ }
if (deltaX != 0) {
QWheelEvent qwe(qlocal, qglobal, deltaX, buttons, keyMods, Qt::Horizontal);
diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
index b0e4b9d..956faa1 100644
--- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
+++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
@@ -296,6 +296,7 @@ private slots:
void moveWhileDeleting();
void ensureDirtySceneTransform();
void focusScope();
+ void stackBefore();
// task specific tests below me
void task141694_textItemEnsureVisible();
@@ -8384,5 +8385,83 @@ void tst_QGraphicsItem::focusScope()
QCOMPARE(scopeB->focusItem(), (QGraphicsItem *)scopeB);
}
+void tst_QGraphicsItem::stackBefore()
+{
+ QGraphicsRectItem parent;
+ QGraphicsRectItem *child1 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
+ QGraphicsRectItem *child2 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
+ QGraphicsRectItem *child3 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
+ QGraphicsRectItem *child4 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
+ child1->setData(0, "child1");
+ child2->setData(0, "child2");
+ child3->setData(0, "child3");
+ child4->setData(0, "child4");
+
+ // Remove and append
+ child2->setParentItem(0);
+ child2->setParentItem(&parent);
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child3 << child4 << child2));
+
+ // Move child2 before child1
+ child2->stackBefore(child1);
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
+ child2->stackBefore(child2);
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
+ child1->setZValue(1);
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
+ child1->stackBefore(child2); // no effect
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
+ child1->setZValue(0);
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
+ child4->stackBefore(child1);
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child4 << child1 << child3));
+ child4->setZValue(1);
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
+ child3->stackBefore(child1);
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child3 << child1 << child4));
+ child4->setZValue(0);
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child4 << child3 << child1));
+
+ // Make them all toplevels
+ child1->setParentItem(0);
+ child2->setParentItem(0);
+ child3->setParentItem(0);
+ child4->setParentItem(0);
+
+ QGraphicsScene scene;
+ scene.addItem(child1);
+ scene.addItem(child2);
+ scene.addItem(child3);
+ scene.addItem(child4);
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder),
+ (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
+
+ // Remove and append
+ scene.removeItem(child2);
+ scene.addItem(child2);
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child1 << child3 << child4 << child2));
+
+ // Move child2 before child1
+ child2->stackBefore(child1);
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
+ child2->stackBefore(child2);
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
+ child1->setZValue(1);
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
+ child1->stackBefore(child2); // no effect
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
+ child1->setZValue(0);
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
+ child4->stackBefore(child1);
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child4 << child1 << child3));
+ child4->setZValue(1);
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
+ child3->stackBefore(child1);
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child3 << child1 << child4));
+ child4->setZValue(0);
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child4 << child3 << child1));
+}
+
QTEST_MAIN(tst_QGraphicsItem)
#include "tst_qgraphicsitem.moc"