From 85edfcbde9f1d2f77a05edb8d01361c76234f47c Mon Sep 17 00:00:00 2001
From: Andreas Aardal Hanssen <andreas.aardal.hanssen@nokia.com>
Date: Mon, 17 Aug 2009 15:41:51 +0200
Subject: Merge QGV delta from kinetic-declarativeui into master.

New flag: QGraphicsItem::ItemNegativeZStacksBehindParent, which makes
it easy to toggle stack-behind based on the value of Z alone.

Add interface initializations to QGV classes.

Add a simple internal focus policy to QGraphicsItem to allow derived
items to be focusable without allowing clickfocus.

Reviewed-by: Alexis
---
 src/gui/graphicsview/qgraphicsitem.cpp         | 15 +++++++++++++++
 src/gui/graphicsview/qgraphicsitem.h           |  8 +++++---
 src/gui/graphicsview/qgraphicsitem_p.h         | 10 ++++++----
 src/gui/graphicsview/qgraphicslayout.h         |  2 ++
 src/gui/graphicsview/qgraphicslayoutitem.h     |  2 ++
 src/gui/graphicsview/qgraphicsscene.cpp        |  7 ++++---
 src/gui/graphicsview/qgraphicsscene_p.h        |  1 +
 src/gui/graphicsview/qgraphicswidget.cpp       |  4 +++-
 src/gui/graphicsview/qgraphicswidget.h         |  1 +
 tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 26 ++++++++++++++++++++++++++
 10 files changed, 65 insertions(+), 11 deletions(-)

diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index 6d75db3..37d969b 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -328,6 +328,10 @@
     used for Asian languages.
     This flag was introduced in Qt 4.6.
 
+    \value ItemNegativeZStacksBehindParent The item automatically stacks behind
+    it's parent if it's z-value is negative. This flag enables setZValue() to
+    toggle ItemStacksBehindParent.
+
     \value ItemAutoDetectsFocusProxy The item will assign any child that
     gains input focus as its focus proxy. See also focusProxy().
     This flag was introduced in Qt 4.6.
@@ -1566,6 +1570,11 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags)
             d_ptr->scene->d_func()->updateInputMethodSensitivityInViews();
     }
 
+    if ((flags & ItemNegativeZStacksBehindParent) != (oldFlags & ItemNegativeZStacksBehindParent)) {
+        // Update stack-behind.
+        setFlag(ItemStacksBehindParent, d_ptr->z < qreal(0.0));
+    }
+
     if (d_ptr->scene) {
         d_ptr->scene->d_func()->markDirty(this, QRectF(),
                                           /*invalidateChildren=*/true,
@@ -3719,6 +3728,9 @@ void QGraphicsItem::setZValue(qreal z)
 
     itemChange(ItemZValueHasChanged, newZVariant);
 
+    if (d_ptr->flags & ItemNegativeZStacksBehindParent)
+        setFlag(QGraphicsItem::ItemStacksBehindParent, z < qreal(0.0));
+
     if (d_ptr->isObject)
         emit static_cast<QGraphicsObject *>(this)->zChanged();
 }
@@ -10103,6 +10115,9 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag)
     case QGraphicsItem::ItemAcceptsInputMethod:
         str = "ItemAcceptsInputMethod";
         break;
+    case QGraphicsItem::ItemNegativeZStacksBehindParent:
+        str = "ItemNegativeZStacksBehindParent";
+        break;
     case QGraphicsItem::ItemAutoDetectsFocusProxy:
         str = "ItemAutoDetectsFocusProxy";
         break;
diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h
index 3acf265..b5e6ed5 100644
--- a/src/gui/graphicsview/qgraphicsitem.h
+++ b/src/gui/graphicsview/qgraphicsitem.h
@@ -101,7 +101,8 @@ public:
         ItemHasNoContents = 0x400,
         ItemSendsGeometryChanges = 0x800,
         ItemAcceptsInputMethod = 0x1000,
-        ItemAutoDetectsFocusProxy = 0x2000
+        ItemAutoDetectsFocusProxy = 0x2000,
+        ItemNegativeZStacksBehindParent = 0x4000
         // NB! Don't forget to increase the d_ptr->flags bit field by 1 when adding a new flag.
     };
     Q_DECLARE_FLAGS(GraphicsItemFlags, GraphicsItemFlag)
@@ -452,6 +453,7 @@ private:
 };
 
 Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsItem::GraphicsItemFlags)
+Q_DECLARE_INTERFACE(QGraphicsItem, "com.trolltech.Qt.QGraphicsItem")
 
 inline void QGraphicsItem::setPos(qreal ax, qreal ay)
 { setPos(QPointF(ax, ay)); }
@@ -504,9 +506,9 @@ class Q_GUI_EXPORT QGraphicsObject : public QObject, public QGraphicsItem
     Q_OBJECT
     Q_PROPERTY(QGraphicsObject * parent READ parentObject WRITE setParentItem NOTIFY parentChanged DESIGNABLE false)
     Q_PROPERTY(QString id READ objectName WRITE setObjectName)
-    Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged)
+    Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged FINAL)
     Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged)
-    Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged)
+    Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged FINAL)
     Q_PROPERTY(QPointF pos READ pos WRITE setPos)
     Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
     Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index c654d4f..43d690f 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -95,7 +95,7 @@ public:
     void purge();
 };
 
-class Q_AUTOTEST_EXPORT QGraphicsItemPrivate
+class Q_GUI_EXPORT QGraphicsItemPrivate
 {
     Q_DECLARE_PUBLIC(QGraphicsItem)
 public:
@@ -165,6 +165,7 @@ public:
         acceptedTouchBeginEvent(0),
         filtersDescendantEvents(0),
         sceneTransformTranslateOnly(0),
+        mouseSetsFocus(1),
         globalStackingOrder(-1),
         q_ptr(0)
     {
@@ -201,7 +202,7 @@ public:
     virtual QVariant inputMethodQueryHelper(Qt::InputMethodQuery query) const;
     static bool movableAncestorIsSelected(const QGraphicsItem *item);
 
-    void setPosHelper(const QPointF &pos);
+    virtual void setPosHelper(const QPointF &pos);
     void setTransformHelper(const QTransform &transform);
     void appendGraphicsTransform(QGraphicsTransform *t);
     void setVisibleHelper(bool newVisible, bool explicitly, bool update = true);
@@ -452,7 +453,7 @@ public:
 
     // New 32 bits
     quint32 fullUpdatePending : 1;
-    quint32 flags : 14;
+    quint32 flags : 15;
     quint32 dirtyChildrenBoundingRect : 1;
     quint32 paintedViewBoundingRectsNeedRepaint : 1;
     quint32 dirtySceneTransform : 1;
@@ -465,7 +466,8 @@ public:
     quint32 acceptedTouchBeginEvent : 1;
     quint32 filtersDescendantEvents : 1;
     quint32 sceneTransformTranslateOnly : 1;
-    quint32 unused : 5; // feel free to use
+    quint32 mouseSetsFocus : 1;
+    quint32 unused : 3; // feel free to use
 
     // Optional stacking order
     int globalStackingOrder;
diff --git a/src/gui/graphicsview/qgraphicslayout.h b/src/gui/graphicsview/qgraphicslayout.h
index d7e087b..1a21e53 100644
--- a/src/gui/graphicsview/qgraphicslayout.h
+++ b/src/gui/graphicsview/qgraphicslayout.h
@@ -85,6 +85,8 @@ private:
     friend class QGraphicsWidget;
 };
 
+Q_DECLARE_INTERFACE(QGraphicsLayout, "com.trolltech.Qt.QGraphicsLayout")
+
 #endif
 
 QT_END_NAMESPACE
diff --git a/src/gui/graphicsview/qgraphicslayoutitem.h b/src/gui/graphicsview/qgraphicslayoutitem.h
index 44c1c0f..f315404 100644
--- a/src/gui/graphicsview/qgraphicslayoutitem.h
+++ b/src/gui/graphicsview/qgraphicslayoutitem.h
@@ -121,6 +121,8 @@ private:
     friend class QGraphicsLayout;
 };
 
+Q_DECLARE_INTERFACE(QGraphicsLayoutItem, "com.trolltech.Qt.QGraphicsLayoutItem")
+
 inline void QGraphicsLayoutItem::setMinimumSize(qreal aw, qreal ah)
 { setMinimumSize(QSizeF(aw, ah)); }
 inline void QGraphicsLayoutItem::setPreferredSize(qreal aw, qreal ah)
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 2178850..21ea72f 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -1079,7 +1079,7 @@ void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mou
     // Set focus on the topmost enabled item that can take focus.
     bool setFocus = false;
     foreach (QGraphicsItem *item, cachedItemsUnderMouse) {
-        if (item->isEnabled() && (item->flags() & QGraphicsItem::ItemIsFocusable)) {
+        if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) {
             if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) {
                 setFocus = true;
                 if (item != q->focusItem())
@@ -3802,7 +3802,8 @@ void QGraphicsScene::wheelEvent(QGraphicsSceneWheelEvent *wheelEvent)
 
     bool hasSetFocus = false;
     foreach (QGraphicsItem *item, wheelCandidates) {
-        if (!hasSetFocus && item->isEnabled() && (item->flags() & QGraphicsItem::ItemIsFocusable)) {
+        if (!hasSetFocus && item->isEnabled()
+            && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) {
             if (item->isWidget() && static_cast<QGraphicsWidget *>(item)->focusPolicy() == Qt::WheelFocus) {
                 hasSetFocus = true;
                 if (item != focusItem())
@@ -5298,7 +5299,7 @@ bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEve
     // Set focus on the topmost enabled item that can take focus.
     bool setFocus = false;
     foreach (QGraphicsItem *item, cachedItemsUnderMouse) {
-        if (item->isEnabled() && (item->flags() & QGraphicsItem::ItemIsFocusable)) {
+        if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) {
             if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) {
                 setFocus = true;
                 if (item != q->focusItem())
diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h
index 836522d..685f534 100644
--- a/src/gui/graphicsview/qgraphicsscene_p.h
+++ b/src/gui/graphicsview/qgraphicsscene_p.h
@@ -59,6 +59,7 @@
 
 #include "qgraphicssceneevent.h"
 #include "qgraphicsview.h"
+#include "qgraphicsview_p.h"
 #include "qgraphicsitem_p.h"
 
 #include <private/qobject_p.h>
diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp
index 64881b5..4b41f1f 100644
--- a/src/gui/graphicsview/qgraphicswidget.cpp
+++ b/src/gui/graphicsview/qgraphicswidget.cpp
@@ -258,7 +258,7 @@ QGraphicsWidget::~QGraphicsWidget()
 
     //we check if we have a layout previously
     if (d->layout) {
-        delete d->layout;
+        QGraphicsLayout *temp = d->layout;
         foreach (QGraphicsItem * item, childItems()) {
             // In case of a custom layout which doesn't remove and delete items, we ensure that
             // the parent layout item does not point to the deleted layout. This code is here to
@@ -269,6 +269,8 @@ QGraphicsWidget::~QGraphicsWidget()
                     widget->setParentLayoutItem(0);
             }
         }
+        d->layout = 0;
+        delete temp;
     }
 
     // Remove this graphics widget from widgetStyles
diff --git a/src/gui/graphicsview/qgraphicswidget.h b/src/gui/graphicsview/qgraphicswidget.h
index 62b353a..57015f9 100644
--- a/src/gui/graphicsview/qgraphicswidget.h
+++ b/src/gui/graphicsview/qgraphicswidget.h
@@ -69,6 +69,7 @@ class QGraphicsWidgetPrivate;
 class Q_GUI_EXPORT QGraphicsWidget : public QGraphicsObject, public QGraphicsLayoutItem
 {
     Q_OBJECT
+    Q_INTERFACES(QGraphicsItem QGraphicsLayoutItem)
     Q_PROPERTY(QPalette palette READ palette WRITE setPalette)
     Q_PROPERTY(QFont font READ font WRITE setFont)
     Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection RESET unsetLayoutDirection)
diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
index a623b50..10f0e42 100644
--- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
+++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
@@ -281,6 +281,7 @@ private slots:
     void subFocus();
     void reverseCreateAutoFocusProxy();
     void focusProxyDeletion();
+    void negativeZStacksBehindParent();
 
     // task specific tests below me
     void task141694_textItemEnsureVisible();
@@ -7558,5 +7559,30 @@ void tst_QGraphicsItem::focusProxyDeletion()
     delete scene; // don't crash
 }
 
+void tst_QGraphicsItem::negativeZStacksBehindParent()
+{
+    QGraphicsRectItem rect;
+    QCOMPARE(rect.zValue(), qreal(0.0));
+    QVERIFY(!(rect.flags() & QGraphicsItem::ItemNegativeZStacksBehindParent));
+    QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
+    rect.setZValue(-1);
+    QCOMPARE(rect.zValue(), qreal(-1.0));
+    QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
+    rect.setZValue(0);
+    rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent);
+    QVERIFY(rect.flags() & QGraphicsItem::ItemNegativeZStacksBehindParent);
+    QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
+    rect.setZValue(-1);
+    QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent);
+    rect.setZValue(0);
+    QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
+    rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, false);
+    rect.setZValue(-1);
+    rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, true);
+    QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent);
+    rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, false);
+    QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent);
+}
+
 QTEST_MAIN(tst_QGraphicsItem)
 #include "tst_qgraphicsitem.moc"
-- 
cgit v0.12