From 6c44ab0f6edebce1e7190b94ac5b74c81812f482 Mon Sep 17 00:00:00 2001
From: Bill King <bill.king@nokia.com>
Date: Wed, 3 Mar 2010 10:01:47 +1000
Subject: Updating SQL binding docs to reflect reality.

Task-number: QTBUG-7218
Reviewed-by: Justin McPherson
---
 src/sql/kernel/qsqlquery.cpp  |  8 ++++++++
 src/sql/kernel/qsqlresult.cpp | 10 +++++++++-
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/src/sql/kernel/qsqlquery.cpp b/src/sql/kernel/qsqlquery.cpp
index 6c6436f..430cf1a 100644
--- a/src/sql/kernel/qsqlquery.cpp
+++ b/src/sql/kernel/qsqlquery.cpp
@@ -999,10 +999,18 @@ bool QSqlQuery::execBatch(BatchExecutionMode mode)
   must be included when specifying the placeholder name. If \a
   paramType is QSql::Out or QSql::InOut, the placeholder will be
   overwritten with data from the database after the exec() call.
+  In this case, sufficient space must be pre-allocated to store
+  the result into.
 
   To bind a NULL value, use a null QVariant; for example, use
   \c {QVariant(QVariant::String)} if you are binding a string.
 
+  Values cannot be bound to multiple locations in the query, eg:
+  \code
+  INSERT INTO testtable (id, name, samename) VALUES (:id, :name, :name)
+  \endcode
+  Binding to name will bind to the first :name, but not the second.
+
   \sa addBindValue(), prepare(), exec(), boundValue() boundValues()
 */
 void QSqlQuery::bindValue(const QString& placeholder, const QVariant& val,
diff --git a/src/sql/kernel/qsqlresult.cpp b/src/sql/kernel/qsqlresult.cpp
index 3d63f88..0c0c31c 100644
--- a/src/sql/kernel/qsqlresult.cpp
+++ b/src/sql/kernel/qsqlresult.cpp
@@ -707,7 +707,15 @@ void QSqlResult::bindValue(int index, const QVariant& val, QSql::ParamType param
     Binds the value \a val of parameter type \a paramType to the \a
     placeholder name in the current record (row).
 
-    Note that binding an undefined placeholder will result in undefined behavior.
+   Values cannot be bound to multiple locations in the query, eg:
+   \code
+   INSERT INTO testtable (id, name, samename) VALUES (:id, :name, :name)
+   \endcode
+   Binding to name will bind to the first :name, but not the second.
+
+    \note Binding an undefined placeholder will result in undefined behavior.
+
+    \sa QSqlQuery::bindValue()
 */
 void QSqlResult::bindValue(const QString& placeholder, const QVariant& val,
                            QSql::ParamType paramType)
-- 
cgit v0.12


From 971f19473a7e9c35f14140235c2be3b68006b5f2 Mon Sep 17 00:00:00 2001
From: Yoann Lopes <yoann.lopes@nokia.com>
Date: Wed, 3 Mar 2010 12:05:15 +0100
Subject: Properly fixes crash when destroying a QGraphicsItem.

The focus is now properly cleared when hiding or showing focus scopes or
when a child of a focus scope is destroyed.
No change of behavior in how focus scope works for QML.

Autotest included.

Task-number: QT-2649
Reviewed-by: Andreas Aardal Hanssen
---
 src/gui/graphicsview/qgraphicsitem.cpp         | 103 ++++++++++++++++---------
 src/gui/graphicsview/qgraphicsitem_p.h         |   3 +-
 tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp |  68 ++++++++++++++++
 3 files changed, 137 insertions(+), 37 deletions(-)

diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index 368af58..f3c90ca 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -641,10 +641,10 @@
     are children of a modal panel are not blocked.
 
     The values are:
-    
+
     \value NonModal The panel is not modal and does not block input to
     other panels. This is the default value for panels.
-    
+
     \value PanelModal The panel is modal to a single item hierarchy
     and blocks input to its parent pane, all grandparent panels, and
     all siblings of its parent and grandparent panels.
@@ -2181,6 +2181,7 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo
     }
 
     // Certain properties are dropped as an item becomes invisible.
+    bool hasFocus = q_ptr->hasFocus();
     if (!newVisible) {
         if (scene) {
             if (scene->d_func()->mouseGrabberItems.contains(q))
@@ -2190,7 +2191,7 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo
             if (q->isPanel() && panelModality != QGraphicsItem::NonModal)
                 scene->d_func()->leaveModal(q_ptr);
         }
-        if (q_ptr->hasFocus() && scene) {
+        if (hasFocus && scene) {
             // Hiding the closest non-panel ancestor of the focus item
             QGraphicsItem *focusItem = scene->focusItem();
             bool clear = true;
@@ -2203,7 +2204,7 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo
                 } while ((focusItem = focusItem->parentWidget()) && !focusItem->isPanel());
             }
             if (clear)
-                q_ptr->clearFocus();
+                clearFocusHelper(/* giveFocusToParent = */ false);
         }
         if (q_ptr->isSelected())
             q_ptr->setSelected(false);
@@ -2241,26 +2242,45 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo
     }
 
     // Enable subfocus
-    if (scene && newVisible) {
-        QGraphicsItem *p = parent;
-        bool done = false;
-        while (p) {
-            if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
-                QGraphicsItem *fsi = p->d_ptr->focusScopeItem;
-                if (q_ptr == fsi || q_ptr->isAncestorOf(fsi)) {
-                    done = true;
-                    while (fsi->d_ptr->focusScopeItem && fsi->d_ptr->focusScopeItem->isVisible())
-                        fsi = fsi->d_ptr->focusScopeItem;
-                    scene->setFocusItem(fsi);
+    if (scene) {
+        if (newVisible) {
+            // Item is shown
+            QGraphicsItem *p = parent;
+            bool done = false;
+            while (p) {
+                if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
+                    QGraphicsItem *fsi = p->d_ptr->focusScopeItem;
+                    if (q_ptr == fsi || q_ptr->isAncestorOf(fsi)) {
+                        done = true;
+                        while (fsi->d_ptr->focusScopeItem && fsi->d_ptr->focusScopeItem->isVisible())
+                            fsi = fsi->d_ptr->focusScopeItem;
+                        fsi->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ true,
+                                                   /* focusFromShow = */ true);
+                    }
+                    break;
                 }
-                break;
+                p = p->d_ptr->parent;
             }
-            p = p->d_ptr->parent;
-        }
-        if (!done) {
-            QGraphicsItem *fi = subFocusItem;
-            if (fi && fi != scene->focusItem()) {
-                scene->setFocusItem(fi);
+            if (!done) {
+                QGraphicsItem *fi = subFocusItem;
+                if (fi && fi != scene->focusItem()) {
+                    scene->setFocusItem(fi);
+                }
+            }
+        } else {
+            // Item is hidden
+            if (hasFocus) {
+                QGraphicsItem *p = parent;
+                while (p) {
+                    if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
+                        if (p->d_ptr->visible) {
+                            p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ true,
+                                                     /* focusFromShow = */ true);
+                        }
+                        break;
+                    }
+                    p = p->d_ptr->parent;
+                }
             }
         }
     }
@@ -3111,13 +3131,13 @@ bool QGraphicsItem::hasFocus() const
 */
 void QGraphicsItem::setFocus(Qt::FocusReason focusReason)
 {
-    d_ptr->setFocusHelper(focusReason, /* climb = */ true);
+    d_ptr->setFocusHelper(focusReason, /* climb = */ true, /* focusFromShow = */ false);
 }
 
 /*!
     \internal
 */
-void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool climb)
+void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool climb, bool focusFromShow)
 {
     // Disabled / unfocusable items cannot accept focus.
     if (!q_ptr->isEnabled() || !(flags & QGraphicsItem::ItemIsFocusable))
@@ -3137,7 +3157,7 @@ void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool clim
     while (p) {
         if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
             p->d_ptr->focusScopeItem = q_ptr;
-            if (!p->focusItem()) {
+            if (!p->focusItem() && !focusFromShow) {
                 // If you call setFocus on a child of a focus scope that
                 // doesn't currently have a focus item, then stop.
                 return;
@@ -3178,24 +3198,35 @@ void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool clim
 */
 void QGraphicsItem::clearFocus()
 {
-    // Pass focus to the closest parent focus scope.
-    if (!d_ptr->inDestructor) {
-        QGraphicsItem *p = d_ptr->parent;
-        while (p) {
-            if (p->flags() & ItemIsFocusScope) {
-                p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ false);
-                return;
+    d_ptr->clearFocusHelper(/* giveFocusToParent = */ true);
+}
+
+/*!
+    \internal
+*/
+void QGraphicsItemPrivate::clearFocusHelper(bool giveFocusToParent)
+{
+    if (giveFocusToParent) {
+        // Pass focus to the closest parent focus scope
+        if (!inDestructor) {
+            QGraphicsItem *p = parent;
+            while (p) {
+                if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
+                    p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ false,
+                                             /* focusFromShow = */ false);
+                    return;
+                }
+                p = p->d_ptr->parent;
             }
-            p = p->d_ptr->parent;
         }
     }
 
     // Invisible items with focus must explicitly clear subfocus.
-    d_ptr->clearSubFocus(this);
+    clearSubFocus(q_ptr);
 
-    if (hasFocus()) {
+    if (q_ptr->hasFocus()) {
         // If this item has the scene's input focus, clear it.
-        d_ptr->scene->setFocusItem(0);
+        scene->setFocusItem(0);
     }
 }
 
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index b3ca3b5..ea04e0b 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -414,7 +414,8 @@ public:
 
     inline void markParentDirty(bool updateBoundingRect = false);
 
-    void setFocusHelper(Qt::FocusReason focusReason, bool climb);
+    void setFocusHelper(Qt::FocusReason focusReason, bool climb, bool focusFromShow);
+    void clearFocusHelper(bool giveFocusToParent);
     void setSubFocus(QGraphicsItem *rootItem = 0);
     void clearSubFocus(QGraphicsItem *rootItem = 0);
     void resetFocusProxy();
diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
index 7c1b97e..4d9f23f 100644
--- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
+++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
@@ -438,6 +438,7 @@ private slots:
     void QTBUG_6738_missingUpdateWithSetParent();
     void QTBUG_7714_fullUpdateDiscardingOpacityUpdate2();
     void QT_2653_fullUpdateDiscardingOpacityUpdate();
+    void QT_2649_focusScope();
 
 private:
     QList<QGraphicsItem *> paintedItems;
@@ -10002,5 +10003,72 @@ void tst_QGraphicsItem::QTBUG_7714_fullUpdateDiscardingOpacityUpdate2()
     QTRY_COMPARE(view.repaints, 1);
 }
 
+void tst_QGraphicsItem::QT_2649_focusScope()
+{
+    QGraphicsScene *scene = new QGraphicsScene;
+
+    QGraphicsRectItem *subFocusItem = new QGraphicsRectItem;
+    subFocusItem->setFlags(QGraphicsItem::ItemIsFocusable);
+    subFocusItem->setFocus();
+    QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
+
+    QGraphicsRectItem *scope = new QGraphicsRectItem;
+    scope->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
+    scope->setFocus();
+    subFocusItem->setParentItem(scope);
+    QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
+    QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
+    QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
+    QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
+
+    QGraphicsRectItem *rootItem = new QGraphicsRectItem;
+    rootItem->setFlags(QGraphicsItem::ItemIsFocusable);
+    scope->setParentItem(rootItem);
+    QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)subFocusItem);
+    QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
+    QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
+    QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
+    QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
+    QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
+
+    scene->addItem(rootItem);
+
+    QEvent windowActivate(QEvent::WindowActivate);
+    qApp->sendEvent(scene, &windowActivate);
+    scene->setFocus();
+
+    QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)subFocusItem);
+    QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
+    QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
+    QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
+    QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
+    QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
+    QVERIFY(subFocusItem->hasFocus());
+
+    scope->hide();
+
+    QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)0);
+    QCOMPARE(scope->focusItem(), (QGraphicsItem *)0);
+    QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)0);
+    QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
+    QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
+    QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
+    QVERIFY(!subFocusItem->hasFocus());
+
+    scope->show();
+
+    QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)subFocusItem);
+    QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
+    QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
+    QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
+    QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
+    QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
+    QVERIFY(subFocusItem->hasFocus());
+
+    // This should not crash
+    scope->hide();
+    delete scene;
+}
+
 QTEST_MAIN(tst_QGraphicsItem)
 #include "tst_qgraphicsitem.moc"
-- 
cgit v0.12