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