From 33a0ebfc5c9b18850d4d09900fe9dea8abfd1fd2 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Wed, 4 Mar 2009 16:35:08 +0100 Subject: Fixes: Initial work on an API to allow a custom/indexing on the QGraphicsScene --- src/gui/graphicsview/graphicsview.pri | 2 + src/gui/graphicsview/qgraphicsscene.cpp | 51 +++++++++++++++-- src/gui/graphicsview/qgraphicsscene.h | 4 ++ src/gui/graphicsview/qgraphicsscene_p.h | 3 + src/gui/graphicsview/qgraphicssceneindex.cpp | 61 ++++++++++++++++++++ src/gui/graphicsview/qgraphicssceneindex.h | 83 ++++++++++++++++++++++++++++ 6 files changed, 198 insertions(+), 6 deletions(-) create mode 100644 src/gui/graphicsview/qgraphicssceneindex.cpp create mode 100644 src/gui/graphicsview/qgraphicssceneindex.h diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri index 02d9bb1..f0bdddc 100644 --- a/src/gui/graphicsview/graphicsview.pri +++ b/src/gui/graphicsview/graphicsview.pri @@ -7,6 +7,7 @@ HEADERS += \ graphicsview/qgraphicsscene.h \ graphicsview/qgraphicsscene_p.h \ graphicsview/qgraphicsscene_bsp_p.h \ + graphicsview/qgraphicssceneindex.h \ graphicsview/qgraphicssceneevent.h \ graphicsview/qgraphicsview_p.h \ graphicsview/qgraphicsview.h @@ -16,6 +17,7 @@ SOURCES += \ graphicsview/qgraphicsitemanimation.cpp \ graphicsview/qgraphicsscene.cpp \ graphicsview/qgraphicsscene_bsp.cpp \ + graphicsview/qgraphicssceneindex.cpp \ graphicsview/qgraphicssceneevent.cpp \ graphicsview/qgraphicsview.cpp diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index e885238..e74ae3a 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -219,6 +219,7 @@ static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; #include "qgraphicsview_p.h" #include "qgraphicswidget.h" #include "qgraphicswidget_p.h" +#include "qgraphicssceneindex.h" #include #include @@ -330,6 +331,7 @@ QGraphicsScenePrivate::QGraphicsScenePrivate() indexMethod(QGraphicsScene::BspTreeIndex), bspTreeDepth(0), lastItemCount(0), + customIndex(0), hasSceneRect(false), updateAll(false), calledEmitUpdated(false), @@ -381,12 +383,18 @@ QList QGraphicsScenePrivate::estimateItemsInRect(const QRectF & const_cast(this)->purgeRemovedItems(); const_cast(this)->_q_updateSortCache(); - if (indexMethod == QGraphicsScene::BspTreeIndex) { + if (indexMethod != QGraphicsScene::NoIndex) { // ### Only do this once in a while. QGraphicsScenePrivate *that = const_cast(this); - // Get items from BSP tree - QList items = that->bspTree.items(rect); + QList items; + if (indexMethod == QGraphicsScene::BspTreeIndex) { + // Get items from BSP tree + items = that->bspTree.items(rect); + } else { + //ask to the custom indexing + items = that->customIndex->items(rect); + } // Fill in with any unindexed items for (int i = 0; i < unindexedItems.size(); ++i) { @@ -444,6 +452,12 @@ void QGraphicsScenePrivate::addToIndex(QGraphicsItem *item) // size. startIndexTimer(); } + } else if (indexMethod == QGraphicsScene::CustomIndex) { + if (item->d_func()->index != -1) { + customIndex->insertItem(item, item->sceneBoundingRect()); + foreach (QGraphicsItem *child, item->children()) + child->addToIndex(); + } } } @@ -452,10 +466,13 @@ void QGraphicsScenePrivate::addToIndex(QGraphicsItem *item) */ void QGraphicsScenePrivate::removeFromIndex(QGraphicsItem *item) { - if (indexMethod == QGraphicsScene::BspTreeIndex) { + if (indexMethod != QGraphicsScene::NoIndex) { int index = item->d_func()->index; if (index != -1) { - bspTree.removeItem(item, item->sceneBoundingRect()); + if (indexMethod == QGraphicsScene::CustomIndex) + customIndex->removeItem(item, item->sceneBoundingRect()); + else + bspTree.removeItem(item, item->sceneBoundingRect()); freeItemIndexes << index; indexedItems[index] = 0; item->d_func()->index = -1; @@ -464,7 +481,6 @@ void QGraphicsScenePrivate::removeFromIndex(QGraphicsItem *item) foreach (QGraphicsItem *child, item->children()) child->removeFromIndex(); } - startIndexTimer(); } } @@ -564,6 +580,8 @@ void QGraphicsScenePrivate::_q_updateIndex() continue; if (indexMethod == QGraphicsScene::BspTreeIndex) bspTree.insertItem(item, rect); + if (indexMethod == QGraphicsScene::CustomIndex) + customIndex->insertItem(item,rect); // If the item ignores view transformations, update our // largest-item-counter to ensure that the view can accurately @@ -2359,10 +2377,31 @@ QGraphicsScene::ItemIndexMethod QGraphicsScene::itemIndexMethod() const void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) { Q_D(QGraphicsScene); + if (method == CustomIndex) { + qWarning("QGraphicsScene: Invalid index type %d", CustomIndex); + return; + } d->resetIndex(); d->indexMethod = method; } +void QGraphicsScene::setSceneIndex(QGraphicsSceneIndex *index) +{ + Q_D(QGraphicsScene); + if (!index) { + qWarning("QGraphicsScene::setSceneIndex: Attempt to insert a null indexer"); + } else { + d->indexMethod = CustomIndex; + d->customIndex = index; + } +} + +QGraphicsSceneIndex* QGraphicsScene::sceneIndex() +{ + Q_D(QGraphicsScene); + return d->customIndex; +} + /*! \property QGraphicsScene::bspTreeDepth \brief the depth of QGraphicsScene's BSP index tree diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h index 9802f87..7e1e040 100644 --- a/src/gui/graphicsview/qgraphicsscene.h +++ b/src/gui/graphicsview/qgraphicsscene.h @@ -83,6 +83,7 @@ class QGraphicsSimpleTextItem; class QGraphicsTextItem; class QGraphicsView; class QGraphicsWidget; +class QGraphicsSceneIndex; class QHelpEvent; class QInputMethodEvent; class QKeyEvent; @@ -113,6 +114,7 @@ class Q_GUI_EXPORT QGraphicsScene : public QObject public: enum ItemIndexMethod { BspTreeIndex, + CustomIndex, NoIndex = -1 }; @@ -142,6 +144,8 @@ public: ItemIndexMethod itemIndexMethod() const; void setItemIndexMethod(ItemIndexMethod method); + void setSceneIndex(QGraphicsSceneIndex *index); + QGraphicsSceneIndex* sceneIndex(); bool isSortCacheEnabled() const; void setSortCacheEnabled(bool enabled); diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 9ace725..fe36fbd 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -58,6 +58,7 @@ #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW #include "qgraphicsscene_bsp_p.h" +#include "qgraphicssceneindex.h" #include "qgraphicsitem_p.h" #include @@ -95,6 +96,8 @@ public: void _q_updateIndex(); int lastItemCount; + QGraphicsSceneIndex *customIndex; + QRectF sceneRect; bool hasSceneRect; QRectF growingItemsBoundingRect; diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp new file mode 100644 index 0000000..00c63a3 --- /dev/null +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgraphicssceneindex.h" + +#ifndef QT_NO_GRAPHICSVIEW + +QT_BEGIN_NAMESPACE + +QGraphicsSceneIndex::QGraphicsSceneIndex() +{ +} + +QGraphicsSceneIndex::~QGraphicsSceneIndex() +{ + +} + +QT_END_NAMESPACE + +//#include "moc_qgraphicssceneindex.cpp" + +#endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h new file mode 100644 index 0000000..2b1cc6e --- /dev/null +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSCENEINDEX_H +#define QGRAPHICSSCENEINDEX_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW + +class QGraphicsItem; +class QRectF; +class QPointF; +template class QList; +template class QSet; + +class Q_GUI_EXPORT QGraphicsSceneIndex +{ +public: + QGraphicsSceneIndex(); + virtual ~QGraphicsSceneIndex(); + + virtual void clear() = 0; + + virtual void insertItem(QGraphicsItem *item, const QRectF &rect) = 0; + virtual void removeItem(QGraphicsItem *item, const QRectF &rect) = 0; + virtual void removeItems(const QSet &items) = 0; + + virtual QList items(const QRectF &rect) = 0; + virtual QList items(const QPointF &pos) = 0; +}; + +#endif // QT_NO_GRAPHICSVIEW + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGRAPHICSSCENEINDEX_H -- cgit v0.12 From 030554d7527663bd389b681f2e2c7e8262517013 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Thu, 5 Mar 2009 12:22:42 +0100 Subject: Fixes: Adapt a bit the public API --- src/gui/graphicsview/qgraphicssceneindex.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index 2b1cc6e..8e8c3ea 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -64,14 +64,13 @@ public: QGraphicsSceneIndex(); virtual ~QGraphicsSceneIndex(); + virtual void initialize(const QRectF &rect) = 0; virtual void clear() = 0; virtual void insertItem(QGraphicsItem *item, const QRectF &rect) = 0; virtual void removeItem(QGraphicsItem *item, const QRectF &rect) = 0; - virtual void removeItems(const QSet &items) = 0; virtual QList items(const QRectF &rect) = 0; - virtual QList items(const QPointF &pos) = 0; }; #endif // QT_NO_GRAPHICSVIEW -- cgit v0.12 From a7f4886b896751ed52db474514a2c4244ed6fc14 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Tue, 7 Apr 2009 20:02:09 +0200 Subject: Fixes: Some modifications after a talk with Ariya --- src/gui/graphicsview/qgraphicsscene.cpp | 7 ++++--- src/gui/graphicsview/qgraphicsscene.h | 2 +- src/gui/graphicsview/qgraphicssceneindex.cpp | 6 ++++++ src/gui/graphicsview/qgraphicssceneindex.h | 11 +++++++++-- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index e74ae3a..fc9590f 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -491,7 +491,7 @@ void QGraphicsScenePrivate::removeFromIndex(QGraphicsItem *item) void QGraphicsScenePrivate::resetIndex() { purgeRemovedItems(); - if (indexMethod == QGraphicsScene::BspTreeIndex) { + if (indexMethod != QGraphicsScene::NoIndex) { for (int i = 0; i < indexedItems.size(); ++i) { if (QGraphicsItem *item = indexedItems.at(i)) { item->d_ptr->index = -1; @@ -2393,12 +2393,13 @@ void QGraphicsScene::setSceneIndex(QGraphicsSceneIndex *index) } else { d->indexMethod = CustomIndex; d->customIndex = index; + index->mscene = this; } } -QGraphicsSceneIndex* QGraphicsScene::sceneIndex() +QGraphicsSceneIndex* QGraphicsScene::sceneIndex() const { - Q_D(QGraphicsScene); + Q_D(const QGraphicsScene); return d->customIndex; } diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h index 7e1e040..bb3cea7 100644 --- a/src/gui/graphicsview/qgraphicsscene.h +++ b/src/gui/graphicsview/qgraphicsscene.h @@ -145,7 +145,7 @@ public: ItemIndexMethod itemIndexMethod() const; void setItemIndexMethod(ItemIndexMethod method); void setSceneIndex(QGraphicsSceneIndex *index); - QGraphicsSceneIndex* sceneIndex(); + QGraphicsSceneIndex* sceneIndex() const; bool isSortCacheEnabled() const; void setSortCacheEnabled(bool enabled); diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 00c63a3..7868388 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qgraphicssceneindex.h" +#include "qgraphicsscene.h" #ifndef QT_NO_GRAPHICSVIEW @@ -54,6 +55,11 @@ QGraphicsSceneIndex::~QGraphicsSceneIndex() } +QGraphicsScene* QGraphicsSceneIndex::scene() +{ + return mscene; +} + QT_END_NAMESPACE //#include "moc_qgraphicssceneindex.cpp" diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index 8e8c3ea..a56634d 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -53,10 +53,10 @@ QT_MODULE(Gui) #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW class QGraphicsItem; +class QGraphicsScene; class QRectF; class QPointF; template class QList; -template class QSet; class Q_GUI_EXPORT QGraphicsSceneIndex { @@ -64,13 +64,20 @@ public: QGraphicsSceneIndex(); virtual ~QGraphicsSceneIndex(); - virtual void initialize(const QRectF &rect) = 0; + virtual void setRect(const QRectF &rect) = 0; + virtual QRectF rect() const = 0; virtual void clear() = 0; virtual void insertItem(QGraphicsItem *item, const QRectF &rect) = 0; + virtual void insertItems(QList items, const QRectF &rect) = 0; virtual void removeItem(QGraphicsItem *item, const QRectF &rect) = 0; + virtual void removeItems(QList items, const QRectF &rect) = 0; virtual QList items(const QRectF &rect) = 0; + + QGraphicsScene* scene(); + + QGraphicsScene* mscene; }; #endif // QT_NO_GRAPHICSVIEW -- cgit v0.12 From 9e5293822b849ed37742054cf1f4c0bb1b1e7156 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Tue, 7 Apr 2009 20:05:20 +0200 Subject: Fixes: Some API adjusments --- src/gui/graphicsview/qgraphicsscene.cpp | 6 +++--- src/gui/graphicsview/qgraphicssceneindex.h | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index fc9590f..a41f931 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -454,7 +454,7 @@ void QGraphicsScenePrivate::addToIndex(QGraphicsItem *item) } } else if (indexMethod == QGraphicsScene::CustomIndex) { if (item->d_func()->index != -1) { - customIndex->insertItem(item, item->sceneBoundingRect()); + customIndex->insertItem(item); foreach (QGraphicsItem *child, item->children()) child->addToIndex(); } @@ -470,7 +470,7 @@ void QGraphicsScenePrivate::removeFromIndex(QGraphicsItem *item) int index = item->d_func()->index; if (index != -1) { if (indexMethod == QGraphicsScene::CustomIndex) - customIndex->removeItem(item, item->sceneBoundingRect()); + customIndex->removeItem(item); else bspTree.removeItem(item, item->sceneBoundingRect()); freeItemIndexes << index; @@ -581,7 +581,7 @@ void QGraphicsScenePrivate::_q_updateIndex() if (indexMethod == QGraphicsScene::BspTreeIndex) bspTree.insertItem(item, rect); if (indexMethod == QGraphicsScene::CustomIndex) - customIndex->insertItem(item,rect); + customIndex->insertItem(item); // If the item ignores view transformations, update our // largest-item-counter to ensure that the view can accurately diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index a56634d..5e825ba 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -68,10 +68,10 @@ public: virtual QRectF rect() const = 0; virtual void clear() = 0; - virtual void insertItem(QGraphicsItem *item, const QRectF &rect) = 0; - virtual void insertItems(QList items, const QRectF &rect) = 0; - virtual void removeItem(QGraphicsItem *item, const QRectF &rect) = 0; - virtual void removeItems(QList items, const QRectF &rect) = 0; + virtual void insertItem(QGraphicsItem *item) = 0; + virtual void insertItems(QList items) = 0; + virtual void removeItem(QGraphicsItem *item) = 0; + virtual void removeItems(QList items) = 0; virtual QList items(const QRectF &rect) = 0; -- cgit v0.12 From e2e30d5c0ca99a47cc142465436d5e0a3f616b82 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Tue, 7 Apr 2009 20:06:38 +0200 Subject: Fixes: Make the bsp tree inherits from the new API --- src/gui/graphicsview/qgraphicsscene.cpp | 6 +++--- src/gui/graphicsview/qgraphicsscene_bsp.cpp | 31 ++++++++++++++++++++++------- src/gui/graphicsview/qgraphicsscene_bsp_p.h | 16 ++++++++++----- src/gui/graphicsview/qgraphicsscene_p.h | 2 +- src/gui/graphicsview/qgraphicssceneindex.h | 4 ++-- 5 files changed, 41 insertions(+), 18 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index a41f931..8660853 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -443,7 +443,7 @@ void QGraphicsScenePrivate::addToIndex(QGraphicsItem *item) { if (indexMethod == QGraphicsScene::BspTreeIndex) { if (item->d_func()->index != -1) { - bspTree.insertItem(item, item->sceneBoundingRect()); + bspTree.insertItem(item); foreach (QGraphicsItem *child, item->children()) child->addToIndex(); } else { @@ -472,7 +472,7 @@ void QGraphicsScenePrivate::removeFromIndex(QGraphicsItem *item) if (indexMethod == QGraphicsScene::CustomIndex) customIndex->removeItem(item); else - bspTree.removeItem(item, item->sceneBoundingRect()); + bspTree.removeItem(item); freeItemIndexes << index; indexedItems[index] = 0; item->d_func()->index = -1; @@ -579,7 +579,7 @@ void QGraphicsScenePrivate::_q_updateIndex() if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) continue; if (indexMethod == QGraphicsScene::BspTreeIndex) - bspTree.insertItem(item, rect); + bspTree.insertItem(item); if (indexMethod == QGraphicsScene::CustomIndex) customIndex->insertItem(item); diff --git a/src/gui/graphicsview/qgraphicsscene_bsp.cpp b/src/gui/graphicsview/qgraphicsscene_bsp.cpp index f8fa450..c295cb3 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp.cpp +++ b/src/gui/graphicsview/qgraphicsscene_bsp.cpp @@ -100,7 +100,7 @@ QGraphicsSceneBspTree::~QGraphicsSceneBspTree() void QGraphicsSceneBspTree::initialize(const QRectF &rect, int depth) { - this->rect = rect; + sceneRect = rect; leafCnt = 0; nodes.resize((1 << (depth + 1)) - 1); nodes.fill(Node()); @@ -117,19 +117,36 @@ void QGraphicsSceneBspTree::clear() leaves.clear(); } -void QGraphicsSceneBspTree::insertItem(QGraphicsItem *item, const QRectF &rect) +QRectF QGraphicsSceneBspTree::rect() const +{ + return sceneRect; +} + +void QGraphicsSceneBspTree::setRect(const QRectF &rect) +{ + sceneRect = rect; +} + +void QGraphicsSceneBspTree::insertItem(QGraphicsItem *item) { insertVisitor->item = item; - climbTree(insertVisitor, rect); + climbTree(insertVisitor, item->sceneBoundingRect()); +} + +void QGraphicsSceneBspTree::insertItems(const QList &items) +{ + foreach(QGraphicsItem *item, items) { + insertItem(item); + } } -void QGraphicsSceneBspTree::removeItem(QGraphicsItem *item, const QRectF &rect) +void QGraphicsSceneBspTree::removeItem(QGraphicsItem *item) { removeVisitor->item = item; - climbTree(removeVisitor, rect); + climbTree(removeVisitor, item->sceneBoundingRect()); } -void QGraphicsSceneBspTree::removeItems(const QSet &items) +void QGraphicsSceneBspTree::removeItems(const QList &items) { for (int i = 0; i < leaves.size(); ++i) { QList newItemList; @@ -302,7 +319,7 @@ void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, con QRectF QGraphicsSceneBspTree::rectForIndex(int index) const { if (index <= 0) - return rect; + return sceneRect; int parentIdx = parentIndex(index); QRectF rect = rectForIndex(parentIdx); diff --git a/src/gui/graphicsview/qgraphicsscene_bsp_p.h b/src/gui/graphicsview/qgraphicsscene_bsp_p.h index e6ceb78..4114b3b 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp_p.h +++ b/src/gui/graphicsview/qgraphicsscene_bsp_p.h @@ -60,6 +60,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -69,7 +70,7 @@ class QGraphicsSceneInsertItemBspTreeVisitor; class QGraphicsSceneRemoveItemBspTreeVisitor; class QGraphicsSceneFindItemBspTreeVisitor; -class QGraphicsSceneBspTree +class QGraphicsSceneBspTree : public QGraphicsSceneIndex { public: struct Node @@ -87,10 +88,13 @@ public: void initialize(const QRectF &rect, int depth); void clear(); + QRectF rect() const; + void setRect(const QRectF &rect); - void insertItem(QGraphicsItem *item, const QRectF &rect); - void removeItem(QGraphicsItem *item, const QRectF &rect); - void removeItems(const QSet &items); + void insertItem(QGraphicsItem *item); + void insertItems(const QList &items); + void removeItem(QGraphicsItem *item); + void removeItems(const QList &items); QList items(const QRectF &rect); QList items(const QPointF &pos); @@ -116,7 +120,7 @@ private: QVector nodes; QVector > leaves; int leafCnt; - QRectF rect; + QRectF sceneRect; QGraphicsSceneInsertItemBspTreeVisitor *insertVisitor; QGraphicsSceneRemoveItemBspTreeVisitor *removeVisitor; @@ -130,6 +134,8 @@ public: virtual void visit(QList *items) = 0; }; +Q_DECLARE_TYPEINFO(QGraphicsSceneBspTree::Node, Q_PRIMITIVE_TYPE); + QT_END_NAMESPACE #endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index fe36fbd..aacbc40 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -132,7 +132,7 @@ public: bool purgePending; void _q_removeItemLater(QGraphicsItem *item); - QSet removedItems; + QList removedItems; void purgeRemovedItems(); QBrush backgroundBrush; diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index 5e825ba..bda6f5e 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -69,9 +69,9 @@ public: virtual void clear() = 0; virtual void insertItem(QGraphicsItem *item) = 0; - virtual void insertItems(QList items) = 0; + virtual void insertItems(const QList &items) = 0; virtual void removeItem(QGraphicsItem *item) = 0; - virtual void removeItems(QList items) = 0; + virtual void removeItems(const QList &items) = 0; virtual QList items(const QRectF &rect) = 0; -- cgit v0.12 From 45c70c9834316f39a939b87450099560fd286a6e Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Tue, 7 Apr 2009 20:11:32 +0200 Subject: Fixes: Default implementation for QGraphicsSceneIndex::removeItems and QGraphicsSceneIndex::insertItems --- src/gui/graphicsview/qgraphicsscene_bsp.cpp | 7 ------- src/gui/graphicsview/qgraphicsscene_bsp_p.h | 1 - src/gui/graphicsview/qgraphicssceneindex.cpp | 13 +++++++++++++ src/gui/graphicsview/qgraphicssceneindex.h | 5 +++-- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene_bsp.cpp b/src/gui/graphicsview/qgraphicsscene_bsp.cpp index c295cb3..bf95893 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp.cpp +++ b/src/gui/graphicsview/qgraphicsscene_bsp.cpp @@ -133,13 +133,6 @@ void QGraphicsSceneBspTree::insertItem(QGraphicsItem *item) climbTree(insertVisitor, item->sceneBoundingRect()); } -void QGraphicsSceneBspTree::insertItems(const QList &items) -{ - foreach(QGraphicsItem *item, items) { - insertItem(item); - } -} - void QGraphicsSceneBspTree::removeItem(QGraphicsItem *item) { removeVisitor->item = item; diff --git a/src/gui/graphicsview/qgraphicsscene_bsp_p.h b/src/gui/graphicsview/qgraphicsscene_bsp_p.h index 4114b3b..a35148c 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp_p.h +++ b/src/gui/graphicsview/qgraphicsscene_bsp_p.h @@ -92,7 +92,6 @@ public: void setRect(const QRectF &rect); void insertItem(QGraphicsItem *item); - void insertItems(const QList &items); void removeItem(QGraphicsItem *item); void removeItems(const QList &items); diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 7868388..d8c28ed 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -60,6 +60,19 @@ QGraphicsScene* QGraphicsSceneIndex::scene() return mscene; } +void QGraphicsSceneIndex::insertItems(const QList &items) +{ + foreach (QGraphicsItem *item, items) + insertItem(item); +} + +void QGraphicsSceneIndex::removeItems(const QList &items) +{ + foreach (QGraphicsItem *item, items) + removeItem(item); +} + + QT_END_NAMESPACE //#include "moc_qgraphicssceneindex.cpp" diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index bda6f5e..df398ae 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -69,9 +69,10 @@ public: virtual void clear() = 0; virtual void insertItem(QGraphicsItem *item) = 0; - virtual void insertItems(const QList &items) = 0; virtual void removeItem(QGraphicsItem *item) = 0; - virtual void removeItems(const QList &items) = 0; + + virtual void insertItems(const QList &items); + virtual void removeItems(const QList &items); virtual QList items(const QRectF &rect) = 0; -- cgit v0.12 From 600beb2a2ed1c3df581230c526f1e64b78112477 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Thu, 12 Mar 2009 16:08:24 +0100 Subject: Fixes: Mark the BSP tree class so we can autotest it. --- src/gui/graphicsview/qgraphicsscene_bsp_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsscene_bsp_p.h b/src/gui/graphicsview/qgraphicsscene_bsp_p.h index a35148c..ebcb402 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp_p.h +++ b/src/gui/graphicsview/qgraphicsscene_bsp_p.h @@ -70,7 +70,7 @@ class QGraphicsSceneInsertItemBspTreeVisitor; class QGraphicsSceneRemoveItemBspTreeVisitor; class QGraphicsSceneFindItemBspTreeVisitor; -class QGraphicsSceneBspTree : public QGraphicsSceneIndex +class Q_AUTOTEST_EXPORT QGraphicsSceneBspTree : public QGraphicsSceneIndex { public: struct Node -- cgit v0.12 From d5ab1562ea7b8ce8e94e8db9ea2a7fcab17f657f Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Thu, 12 Mar 2009 15:51:19 +0100 Subject: Fixes: Add a simple test for the scene index. Details: This is just the beginning. More complex tests follow. --- tests/auto/auto.pro | 1 + .../qgraphicssceneindex/qgraphicssceneindex.pro | 3 + .../tst_qgraphicssceneindex.cpp | 74 ++++++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 tests/auto/qgraphicssceneindex/qgraphicssceneindex.pro create mode 100644 tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 443ee7e..9bde383 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -140,6 +140,7 @@ SUBDIRS += bic \ qgraphicsitem \ qgraphicsitemanimation \ qgraphicsscene \ + qgraphicssceneindex \ qgraphicsview \ qgridlayout \ qgroupbox \ diff --git a/tests/auto/qgraphicssceneindex/qgraphicssceneindex.pro b/tests/auto/qgraphicssceneindex/qgraphicssceneindex.pro new file mode 100644 index 0000000..740a23e --- /dev/null +++ b/tests/auto/qgraphicssceneindex/qgraphicssceneindex.pro @@ -0,0 +1,3 @@ +load(qttest_p4) +SOURCES += tst_qgraphicssceneindex.cpp + diff --git a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp new file mode 100644 index 0000000..209e4be --- /dev/null +++ b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include +#include +#include + +#include + +//TESTED_CLASS= +//TESTED_FILES= + +class tst_QGraphicsSceneIndex : public QObject +{ + Q_OBJECT +public slots: + void initTestCase(); + +private slots: + void sceneRect(); +}; + +void tst_QGraphicsSceneIndex::initTestCase() +{ +} + +void tst_QGraphicsSceneIndex::sceneRect() +{ + QGraphicsSceneIndex *index = new QGraphicsSceneBspTree; + index->setRect(QRectF(0, 0, 2000, 2000)); + QCOMPARE(index->rect(), QRectF(0, 0, 2000, 2000)); +} + +QTEST_MAIN(tst_QGraphicsSceneIndex) +#include "tst_qgraphicssceneindex.moc" -- cgit v0.12 From 14785a965fc475d220ca8592c6ee4a44a0be25f6 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Mon, 16 Mar 2009 13:54:20 +0100 Subject: Fixes: Parametrize the test with potentially different indexing method. --- .../tst_qgraphicssceneindex.cpp | 28 +++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp index 209e4be..f2a2bf1 100644 --- a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -44,7 +44,6 @@ #include #include -#include //TESTED_CLASS= //TESTED_FILES= @@ -56,13 +55,40 @@ public slots: void initTestCase(); private slots: + void sceneRect_data(); void sceneRect(); + +private: + void common_data(); + QGraphicsSceneIndex *createIndex(const QString &name); }; void tst_QGraphicsSceneIndex::initTestCase() { } +void tst_QGraphicsSceneIndex::common_data() +{ + QTest::addColumn("indexMethod"); + + QTest::newRow("BSP") << QString("bsp"); +} + +QGraphicsSceneIndex *tst_QGraphicsSceneIndex::createIndex(const QString &indexMethod) +{ + QGraphicsSceneIndex *index = 0; + + if (indexMethod == "bsp") + index = new QGraphicsSceneBspTree; + + return index; +} + +void tst_QGraphicsSceneIndex::sceneRect_data() +{ + common_data(); +} + void tst_QGraphicsSceneIndex::sceneRect() { QGraphicsSceneIndex *index = new QGraphicsSceneBspTree; -- cgit v0.12 From 7b21055e3966ed8620586decaca4c30f9bf0823a Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Mon, 16 Mar 2009 13:57:05 +0100 Subject: Fixes: Autotest for changing the index method of a scene. --- .../qgraphicssceneindex/tst_qgraphicssceneindex.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp index f2a2bf1..9372823 100644 --- a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -41,6 +41,7 @@ #include +#include #include #include @@ -57,6 +58,8 @@ public slots: private slots: void sceneRect_data(); void sceneRect(); + void customIndex_data(); + void customIndex(); private: void common_data(); @@ -96,5 +99,23 @@ void tst_QGraphicsSceneIndex::sceneRect() QCOMPARE(index->rect(), QRectF(0, 0, 2000, 2000)); } +void tst_QGraphicsSceneIndex::customIndex_data() +{ + common_data(); +} + +void tst_QGraphicsSceneIndex::customIndex() +{ + QFETCH(QString, indexMethod); + QGraphicsSceneIndex *index = createIndex(indexMethod); + + QGraphicsScene scene; + scene.setSceneIndex(index); + + scene.addRect(0, 0, 30, 40); + QCOMPARE(scene.items(QRectF(0, 0, 10, 10)).count(), 1); +} + + QTEST_MAIN(tst_QGraphicsSceneIndex) #include "tst_qgraphicssceneindex.moc" -- cgit v0.12 From 7185361703e2837e4258b18350da791c84f7ef62 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Mon, 16 Mar 2009 13:58:02 +0100 Subject: Fixes: Autotest for inserting non-overlapped items in the scene index. --- .../tst_qgraphicssceneindex.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp index 9372823..cfe3ef0 100644 --- a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -60,6 +60,8 @@ private slots: void sceneRect(); void customIndex_data(); void customIndex(); + void scatteredItems_data(); + void scatteredItems(); private: void common_data(); @@ -116,6 +118,26 @@ void tst_QGraphicsSceneIndex::customIndex() QCOMPARE(scene.items(QRectF(0, 0, 10, 10)).count(), 1); } +void tst_QGraphicsSceneIndex::scatteredItems_data() +{ + common_data(); +} + +void tst_QGraphicsSceneIndex::scatteredItems() +{ + QFETCH(QString, indexMethod); + QGraphicsSceneIndex *index = createIndex(indexMethod); + + QGraphicsScene scene; + scene.setSceneIndex(index); + + for (int i = 0; i < 10; ++i) + scene.addRect(i*50, i*50, 40, 35); + + QCOMPARE(scene.items(QRectF(0, 0, 10, 10)).count(), 1); + QCOMPARE(scene.items(QRectF(0, 0, 1000, 1000)).count(), 10); + QCOMPARE(scene.items(QRectF(-100, -1000, 0, 0)).count(), 0); +} QTEST_MAIN(tst_QGraphicsSceneIndex) #include "tst_qgraphicssceneindex.moc" -- cgit v0.12 From 2a1ced292424501d3bf453f337f8ce9c8c17bda9 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Mon, 16 Mar 2009 15:07:06 +0100 Subject: Fixes: Initialize the BSP tree if it has not been initialized before. Details: The BSP tree internal to QGraphicsScene does need this as the scene does call initialize() at proper time. This fix is needed only for using the BSP tree as custom indexing and/or for autotest. --- src/gui/graphicsview/qgraphicsscene_bsp.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene_bsp.cpp b/src/gui/graphicsview/qgraphicsscene_bsp.cpp index bf95893..b73cba2 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp.cpp +++ b/src/gui/graphicsview/qgraphicsscene_bsp.cpp @@ -247,8 +247,10 @@ void QGraphicsSceneBspTree::initialize(const QRectF &rect, int depth, int index) void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QPointF &pos, int index) { - if (nodes.isEmpty()) - return; + if (nodes.isEmpty()) { + // should never happen for bsp tree internal to QGraphicsScene + initialize(sceneRect, 0); + } const Node &node = nodes.at(index); int childIndex = firstChildIndex(index); @@ -277,8 +279,10 @@ void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, con void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index) { - if (nodes.isEmpty()) - return; + if (nodes.isEmpty()) { + // should never happen for bsp tree internal to QGraphicsScene + initialize(sceneRect, 0); + } const Node &node = nodes.at(index); int childIndex = firstChildIndex(index); -- cgit v0.12 From e30e12306c9cc834eada3ce07b32761748fa423a Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Mon, 16 Mar 2009 15:34:07 +0100 Subject: Fixes: Make some BSP tree functions as 'private'. --- src/gui/graphicsview/qgraphicsscene_bsp_p.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene_bsp_p.h b/src/gui/graphicsview/qgraphicsscene_bsp_p.h index ebcb402..a8c54f0 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp_p.h +++ b/src/gui/graphicsview/qgraphicsscene_bsp_p.h @@ -96,9 +96,13 @@ public: void removeItems(const QList &items); QList items(const QRectF &rect); - QList items(const QPointF &pos); + int leafCount() const; +private: + + QList items(const QPointF &pos); + inline int firstChildIndex(int index) const { return index * 2 + 1; } @@ -107,7 +111,6 @@ public: QString debug(int index) const; -private: void initialize(const QRectF &rect, int depth, int index); void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QPointF &pos, int index = 0); void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index = 0); -- cgit v0.12 From 79257690c8fe8802e75a642138a2b466a0f54e65 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Thu, 12 Mar 2009 15:43:19 +0100 Subject: Fixes: Added linear scene index class. Not used yet. --- src/gui/graphicsview/graphicsview.pri | 1 + src/gui/graphicsview/qgraphicsscene_linear_p.h | 110 +++++++++++++++++++++ .../tst_qgraphicssceneindex.cpp | 5 + 3 files changed, 116 insertions(+) create mode 100644 src/gui/graphicsview/qgraphicsscene_linear_p.h diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri index f0bdddc..bc4d9dd 100644 --- a/src/gui/graphicsview/graphicsview.pri +++ b/src/gui/graphicsview/graphicsview.pri @@ -7,6 +7,7 @@ HEADERS += \ graphicsview/qgraphicsscene.h \ graphicsview/qgraphicsscene_p.h \ graphicsview/qgraphicsscene_bsp_p.h \ + graphicsview/qgraphicsscene_linear_p.h \ graphicsview/qgraphicssceneindex.h \ graphicsview/qgraphicssceneevent.h \ graphicsview/qgraphicsview_p.h \ diff --git a/src/gui/graphicsview/qgraphicsscene_linear_p.h b/src/gui/graphicsview/qgraphicsscene_linear_p.h new file mode 100644 index 0000000..1ef1902 --- /dev/null +++ b/src/gui/graphicsview/qgraphicsscene_linear_p.h @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSCENELINEARINDEX_P_H +#define QGRAPHICSSCENELINEARINDEX_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex +{ +private: + QRectF m_sceneRect; + QList m_items; + +public: + QGraphicsSceneLinearIndex(): QGraphicsSceneIndex() { + } + + virtual void setRect(const QRectF &rect) { + m_sceneRect = rect; + } + + virtual QRectF rect() const { + return m_sceneRect; + } + + virtual void clear() { + m_items.clear(); + } + + virtual void insertItem(QGraphicsItem *item) { + m_items << item; + } + + virtual void removeItem(QGraphicsItem *item) { + m_items.removeAll(item); + } + + virtual QList items(const QRectF &rect) { + QList result; + foreach (QGraphicsItem *item, m_items) + if (item->sceneBoundingRect().intersects(rect)) + result << item; + return result; + } +}; + +QT_END_NAMESPACE + +#endif // QT_NO_GRAPHICSVIEW + +#endif // QGRAPHICSSCENELINEARINDEX_P_H diff --git a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp index cfe3ef0..d199351 100644 --- a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -44,6 +44,7 @@ #include #include #include +#include //TESTED_CLASS= @@ -77,6 +78,7 @@ void tst_QGraphicsSceneIndex::common_data() QTest::addColumn("indexMethod"); QTest::newRow("BSP") << QString("bsp"); + QTest::newRow("Linear") << QString("linear"); } QGraphicsSceneIndex *tst_QGraphicsSceneIndex::createIndex(const QString &indexMethod) @@ -86,6 +88,9 @@ QGraphicsSceneIndex *tst_QGraphicsSceneIndex::createIndex(const QString &indexMe if (indexMethod == "bsp") index = new QGraphicsSceneBspTree; + if (indexMethod == "linear") + index = new QGraphicsSceneLinearIndex; + return index; } -- cgit v0.12 From ff2f96de0c71f53cc71902e8119c84aed9967226 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Tue, 17 Mar 2009 12:06:44 +0100 Subject: Fixes: New updateItem(s) function with default implementation (of removing and inserting) --- src/gui/graphicsview/qgraphicssceneindex.cpp | 11 +++++++++++ src/gui/graphicsview/qgraphicssceneindex.h | 2 ++ 2 files changed, 13 insertions(+) diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index d8c28ed..cb84f6b 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -60,6 +60,12 @@ QGraphicsScene* QGraphicsSceneIndex::scene() return mscene; } +void QGraphicsSceneIndex::updateItem(QGraphicsItem *item) +{ + removeItem(item); + insertItem(item); +} + void QGraphicsSceneIndex::insertItems(const QList &items) { foreach (QGraphicsItem *item, items) @@ -72,6 +78,11 @@ void QGraphicsSceneIndex::removeItems(const QList &items) removeItem(item); } +void QGraphicsSceneIndex::updateItems(const QList &items) +{ + foreach (QGraphicsItem *item, items) + updateItem(item); +} QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index df398ae..6246753 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -70,9 +70,11 @@ public: virtual void insertItem(QGraphicsItem *item) = 0; virtual void removeItem(QGraphicsItem *item) = 0; + virtual void updateItem(QGraphicsItem *item); virtual void insertItems(const QList &items); virtual void removeItems(const QList &items); + virtual void updateItems(const QList &items); virtual QList items(const QRectF &rect) = 0; -- cgit v0.12 From 6df288191c5b6de8c6d1f00fd931401dc9f0c342 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Tue, 17 Mar 2009 13:50:05 +0100 Subject: Fixes: Add API documentation for QGraphicsSceneIndex --- src/gui/graphicsview/qgraphicssceneindex.cpp | 80 ++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index cb84f6b..99d1b3b 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -46,38 +46,118 @@ QT_BEGIN_NAMESPACE +/*! + Constructs an abstract scene index. +*/ QGraphicsSceneIndex::QGraphicsSceneIndex() { } +/*! + Destroys the scene index. +*/ QGraphicsSceneIndex::~QGraphicsSceneIndex() { } +/*! + \fn virtual void setRect(const QRectF &rect) = 0 + + This pure virtual function is called when the scene changes its bounding + rectangle. + + \sa rect(), QGraphicsScene::setSceneRect +*/ + +/*! + \fn virtual QRectF rect() const = 0 + + This pure virtual function returns the bounding rectangle of this + scene index. It could be as large as or larger than the scene + bounding rectangle, depending on the implementation of the + scene index. + + \sa setRect(), QGraphicsScene::sceneRect +*/ + +/*! + \fn virtual void clear() = 0 + + This pure virtual function removes all items in the scene index. +*/ + +/*! + \fn virtual void insertItem(QGraphicsItem *item) = 0 + + This pure virtual function inserts an item to the scene index. + + \sa removeItem(), updateItem(), insertItems() +*/ + +/*! + \fn virtual void removeItem(QGraphicsItem *item) = 0 + + This pure virtual function removes an item to the scene index. + + \sa insertItem(), updateItem(), removeItems() +*/ + +/*! + Returns the scene of this scene index. +*/ QGraphicsScene* QGraphicsSceneIndex::scene() { return mscene; } +/*! + Updates an item when its geometry has changed. + + The default implemention will remove the item from the index + and then insert it again. + + \sa insertItem(), removeItem(), updateItems() +*/ void QGraphicsSceneIndex::updateItem(QGraphicsItem *item) { removeItem(item); insertItem(item); } +/*! + Inserts a list of items to the index. + + The default implemention will insert the items one by one. + + \sa insertItem(), removeItems(), updateItems() +*/ void QGraphicsSceneIndex::insertItems(const QList &items) { foreach (QGraphicsItem *item, items) insertItem(item); } +/*! + Removes a list of items from the index. + + The default implemention will remove the items one by one. + + \sa removeItem(), removeItems(), updateItems() +*/ void QGraphicsSceneIndex::removeItems(const QList &items) { foreach (QGraphicsItem *item, items) removeItem(item); } +/*! + Update a list of items which have changed the geometry. + + The default implemention will update the items one by one. + + \sa updateItem(), insertItems(), removeItems() +*/ void QGraphicsSceneIndex::updateItems(const QList &items) { foreach (QGraphicsItem *item, items) -- cgit v0.12 From 8e13ebc41ccbf4d1ec6ba552f8865007db5af875 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Tue, 17 Mar 2009 14:56:04 +0100 Subject: Fixes: Add autotest for overlapped rectangles --- .../tst_qgraphicssceneindex.cpp | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp index d199351..f03404e 100644 --- a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -63,6 +63,8 @@ private slots: void customIndex(); void scatteredItems_data(); void scatteredItems(); + void overlappedItems_data(); + void overlappedItems(); private: void common_data(); @@ -144,5 +146,32 @@ void tst_QGraphicsSceneIndex::scatteredItems() QCOMPARE(scene.items(QRectF(-100, -1000, 0, 0)).count(), 0); } +void tst_QGraphicsSceneIndex::overlappedItems_data() +{ + common_data(); +} + +void tst_QGraphicsSceneIndex::overlappedItems() +{ + QFETCH(QString, indexMethod); + QGraphicsSceneIndex *index = createIndex(indexMethod); + + QGraphicsScene scene; + scene.setSceneIndex(index); + + for (int i = 0; i < 10; ++i) + for (int j = 0; j < 10; ++j) + scene.addRect(i*50, j*50, 200, 200); + + QCOMPARE(scene.items(QRectF(0, 0, 1000, 1000)).count(), 100); + QCOMPARE(scene.items(QRectF(-100, -1000, 0, 0)).count(), 0); + QCOMPARE(scene.items(QRectF(0, 0, 200, 200)).count(), 16); + QCOMPARE(scene.items(QRectF(0, 0, 100, 100)).count(), 4); + QCOMPARE(scene.items(QRectF(0, 0, 1, 100)).count(), 2); + QCOMPARE(scene.items(QRectF(0, 0, 1, 1000)).count(), 10); +} + + + QTEST_MAIN(tst_QGraphicsSceneIndex) #include "tst_qgraphicssceneindex.moc" -- cgit v0.12 From 72f34ea254d2ad93e11f740bf2ed2523f1975ee9 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Tue, 17 Mar 2009 15:04:52 +0100 Subject: Fixes: Add autotest for moving rectangle between items. --- .../tst_qgraphicssceneindex.cpp | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp index f03404e..9a01cb8 100644 --- a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -65,6 +65,8 @@ private slots: void scatteredItems(); void overlappedItems_data(); void overlappedItems(); + void movingItems_data(); + void movingItems(); private: void common_data(); @@ -171,6 +173,33 @@ void tst_QGraphicsSceneIndex::overlappedItems() QCOMPARE(scene.items(QRectF(0, 0, 1, 1000)).count(), 10); } +void tst_QGraphicsSceneIndex::movingItems_data() +{ + common_data(); +} + +void tst_QGraphicsSceneIndex::movingItems() +{ + QFETCH(QString, indexMethod); + QGraphicsSceneIndex *index = createIndex(indexMethod); + + QGraphicsScene scene; + scene.setSceneIndex(index); + + for (int i = 0; i < 10; ++i) + scene.addRect(i*50, i*50, 40, 35); + + QGraphicsRectItem *box = scene.addRect(0, 0, 10, 10); + QCOMPARE(scene.items(QRectF(0, 0, 5, 5)).count(), 2); + + box->setPos(10, 10); + QCOMPARE(scene.items(QRectF(0, 0, 1, 1)).count(), 1); + + box->setPos(-5, -5); + QCOMPARE(scene.items(QRectF(0, 0, 1, 1)).count(), 2); + + QCOMPARE(scene.items(QRectF(0, 0, 1000, 1000)).count(), 11); +} QTEST_MAIN(tst_QGraphicsSceneIndex) -- cgit v0.12 From 22a3772006c34e51f446eb3ab1cfaf5e40cab583 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Tue, 17 Mar 2009 15:07:53 +0100 Subject: Fixes: Remove from the custom index too (this will change anyway) --- src/gui/graphicsview/qgraphicsscene.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 8660853..77711ad 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -822,8 +822,13 @@ void QGraphicsScenePrivate::purgeRemovedItems() return; // Remove stale items from the BSP tree. - if (indexMethod != QGraphicsScene::NoIndex) - bspTree.removeItems(removedItems); + if (indexMethod != QGraphicsScene::NoIndex) { + if (indexMethod == QGraphicsScene::BspTreeIndex) { + bspTree.removeItems(removedItems); + } else { + customIndex->removeItems(removedItems); + } + } // Purge this list. removedItems.clear(); -- cgit v0.12 From 133bded765f224bce31d8abff87cc74a63569715 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Tue, 17 Mar 2009 17:26:26 +0100 Subject: Fixes: The bsp and customs index share the same pointer --- src/gui/graphicsview/qgraphicsscene.cpp | 66 ++++++++++++++++++--------------- src/gui/graphicsview/qgraphicsscene_p.h | 6 ++- 2 files changed, 41 insertions(+), 31 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 77711ad..4070f11 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -331,7 +331,7 @@ QGraphicsScenePrivate::QGraphicsScenePrivate() indexMethod(QGraphicsScene::BspTreeIndex), bspTreeDepth(0), lastItemCount(0), - customIndex(0), + index(new QGraphicsSceneBspTree()), hasSceneRect(false), updateAll(false), calledEmitUpdated(false), @@ -361,7 +361,11 @@ QGraphicsScenePrivate::QGraphicsScenePrivate() style(0) { } - +QGraphicsScenePrivate::~QGraphicsScenePrivate() +{ + if (index) + delete index; +} /*! \internal */ @@ -388,13 +392,8 @@ QList QGraphicsScenePrivate::estimateItemsInRect(const QRectF & QGraphicsScenePrivate *that = const_cast(this); QList items; - if (indexMethod == QGraphicsScene::BspTreeIndex) { - // Get items from BSP tree - items = that->bspTree.items(rect); - } else { - //ask to the custom indexing - items = that->customIndex->items(rect); - } + // Get items from index + items = that->index->items(rect); // Fill in with any unindexed items for (int i = 0; i < unindexedItems.size(); ++i) { @@ -443,7 +442,7 @@ void QGraphicsScenePrivate::addToIndex(QGraphicsItem *item) { if (indexMethod == QGraphicsScene::BspTreeIndex) { if (item->d_func()->index != -1) { - bspTree.insertItem(item); + index->insertItem(item); foreach (QGraphicsItem *child, item->children()) child->addToIndex(); } else { @@ -454,7 +453,7 @@ void QGraphicsScenePrivate::addToIndex(QGraphicsItem *item) } } else if (indexMethod == QGraphicsScene::CustomIndex) { if (item->d_func()->index != -1) { - customIndex->insertItem(item); + index->insertItem(item); foreach (QGraphicsItem *child, item->children()) child->addToIndex(); } @@ -469,10 +468,7 @@ void QGraphicsScenePrivate::removeFromIndex(QGraphicsItem *item) if (indexMethod != QGraphicsScene::NoIndex) { int index = item->d_func()->index; if (index != -1) { - if (indexMethod == QGraphicsScene::CustomIndex) - customIndex->removeItem(item); - else - bspTree.removeItem(item); + this->index->removeItem(item); freeItemIndexes << index; indexedItems[index] = 0; item->d_func()->index = -1; @@ -551,7 +547,9 @@ void QGraphicsScenePrivate::_q_updateIndex() int oldDepth = intmaxlog(lastItemCount); depth = intmaxlog(indexedItems.size()); static const int slack = 100; - if (bspTree.leafCount() == 0 || (oldDepth != depth && qAbs(lastItemCount - indexedItems.size()) > slack)) { + //### do something better + QGraphicsSceneBspTree *bsp = static_cast(index); + if (bsp->leafCount() == 0 || (oldDepth != depth && qAbs(lastItemCount - indexedItems.size()) > slack)) { // ### Crude algorithm. regenerateIndex = true; } @@ -560,7 +558,9 @@ void QGraphicsScenePrivate::_q_updateIndex() // Regenerate the tree. if (regenerateIndex) { regenerateIndex = false; - bspTree.initialize(q->sceneRect(), depth); + //### do something better + QGraphicsSceneBspTree *bsp = static_cast(index); + bsp->initialize(q->sceneRect(), depth); unindexedItems = indexedItems; lastItemCount = indexedItems.size(); q->update(); @@ -578,10 +578,9 @@ void QGraphicsScenePrivate::_q_updateIndex() QRectF rect = item->sceneBoundingRect(); if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) continue; - if (indexMethod == QGraphicsScene::BspTreeIndex) - bspTree.insertItem(item); - if (indexMethod == QGraphicsScene::CustomIndex) - customIndex->insertItem(item); + + if (indexMethod != QGraphicsScene::NoIndex) + index->insertItem(item); // If the item ignores view transformations, update our // largest-item-counter to ensure that the view can accurately @@ -823,11 +822,7 @@ void QGraphicsScenePrivate::purgeRemovedItems() // Remove stale items from the BSP tree. if (indexMethod != QGraphicsScene::NoIndex) { - if (indexMethod == QGraphicsScene::BspTreeIndex) { - bspTree.removeItems(removedItems); - } else { - customIndex->removeItems(removedItems); - } + index->removeItems(removedItems); } // Purge this list. @@ -2386,8 +2381,18 @@ void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) qWarning("QGraphicsScene: Invalid index type %d", CustomIndex); return; } + if (d->indexMethod == method) { + return; + } d->resetIndex(); + if (d->indexMethod != NoIndex) { + delete d->index; + } d->indexMethod = method; + if (method == BspTreeIndex) { + d->index = new QGraphicsSceneBspTree(); + } + } void QGraphicsScene::setSceneIndex(QGraphicsSceneIndex *index) @@ -2396,8 +2401,11 @@ void QGraphicsScene::setSceneIndex(QGraphicsSceneIndex *index) if (!index) { qWarning("QGraphicsScene::setSceneIndex: Attempt to insert a null indexer"); } else { + if (d->indexMethod == BspTreeIndex) { + delete d->index; + } d->indexMethod = CustomIndex; - d->customIndex = index; + d->index = index; index->mscene = this; } } @@ -2405,7 +2413,7 @@ void QGraphicsScene::setSceneIndex(QGraphicsSceneIndex *index) QGraphicsSceneIndex* QGraphicsScene::sceneIndex() const { Q_D(const QGraphicsScene); - return d->customIndex; + return d->index; } /*! @@ -2814,7 +2822,7 @@ void QGraphicsScene::clear() d->indexedItems.clear(); d->freeItemIndexes.clear(); d->lastItemCount = 0; - d->bspTree.clear(); + d->index->clear(); d->largestUntransformableItem = QRectF(); d->allItemsIgnoreHoverEvents = true; d->allItemsUseDefaultCursor = true; diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index aacbc40..b06db38 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -58,6 +58,7 @@ #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW #include "qgraphicsscene_bsp_p.h" +#include "qgraphicsscene_linear_p.h" #include "qgraphicssceneindex.h" #include "qgraphicsitem_p.h" @@ -80,6 +81,7 @@ class QGraphicsScenePrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QGraphicsScene) public: QGraphicsScenePrivate(); + ~QGraphicsScenePrivate(); void init(); quint32 changedSignalMask; @@ -92,11 +94,11 @@ public: void removeFromIndex(QGraphicsItem *item); void resetIndex(); - QGraphicsSceneBspTree bspTree; void _q_updateIndex(); int lastItemCount; - QGraphicsSceneIndex *customIndex; + QGraphicsSceneIndex *index; + QGraphicsSceneLinearIndex *linearIndex; QRectF sceneRect; bool hasSceneRect; -- cgit v0.12 From 5cf43cf62221e3241e33ea25efc7014c07e4d7ad Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Tue, 7 Apr 2009 20:20:53 +0200 Subject: Fixes: Add new virtual QGraphicsSceneIndex::items(QPointF) --- src/gui/graphicsview/qgraphicsscene_bsp_p.h | 3 +-- src/gui/graphicsview/qgraphicsscene_linear_p.h | 8 ++++++++ src/gui/graphicsview/qgraphicssceneindex.h | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene_bsp_p.h b/src/gui/graphicsview/qgraphicsscene_bsp_p.h index a8c54f0..ed207ea 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp_p.h +++ b/src/gui/graphicsview/qgraphicsscene_bsp_p.h @@ -95,14 +95,13 @@ public: void removeItem(QGraphicsItem *item); void removeItems(const QList &items); + QList items(const QPointF &point); QList items(const QRectF &rect); int leafCount() const; private: - QList items(const QPointF &pos); - inline int firstChildIndex(int index) const { return index * 2 + 1; } diff --git a/src/gui/graphicsview/qgraphicsscene_linear_p.h b/src/gui/graphicsview/qgraphicsscene_linear_p.h index 1ef1902..1981b17 100644 --- a/src/gui/graphicsview/qgraphicsscene_linear_p.h +++ b/src/gui/graphicsview/qgraphicsscene_linear_p.h @@ -94,6 +94,14 @@ public: m_items.removeAll(item); } + virtual QList items(const QPointF &point) { + QList result; + foreach (QGraphicsItem *item, m_items) + if (item->sceneBoundingRect().contains(point)) + result << item; + return result; + } + virtual QList items(const QRectF &rect) { QList result; foreach (QGraphicsItem *item, m_items) diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index 6246753..f78672f 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -76,6 +76,7 @@ public: virtual void removeItems(const QList &items); virtual void updateItems(const QList &items); + virtual QList items(const QPointF &point) = 0; virtual QList items(const QRectF &rect) = 0; QGraphicsScene* scene(); -- cgit v0.12 From 875d5f41b1a796d91a4a8edac6c23a7965395470 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Wed, 18 Mar 2009 15:36:41 +0100 Subject: Fixes: Autotest the scene index using the new items(QPointF) function. --- tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp index 9a01cb8..955f2d3 100644 --- a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -143,6 +143,10 @@ void tst_QGraphicsSceneIndex::scatteredItems() for (int i = 0; i < 10; ++i) scene.addRect(i*50, i*50, 40, 35); + QCOMPARE(scene.items(QPointF(5, 5)).count(), 1); + QCOMPARE(scene.items(QPointF(55, 55)).count(), 1); + QCOMPARE(scene.items(QPointF(-100, -100)).count(), 0); + QCOMPARE(scene.items(QRectF(0, 0, 10, 10)).count(), 1); QCOMPARE(scene.items(QRectF(0, 0, 1000, 1000)).count(), 10); QCOMPARE(scene.items(QRectF(-100, -1000, 0, 0)).count(), 0); @@ -165,6 +169,11 @@ void tst_QGraphicsSceneIndex::overlappedItems() for (int j = 0; j < 10; ++j) scene.addRect(i*50, j*50, 200, 200); + QCOMPARE(scene.items(QPointF(5, 5)).count(), 1); + QCOMPARE(scene.items(QPointF(55, 55)).count(), 4); + QCOMPARE(scene.items(QPointF(105, 105)).count(), 9); + QCOMPARE(scene.items(QPointF(-100, -100)).count(), 0); + QCOMPARE(scene.items(QRectF(0, 0, 1000, 1000)).count(), 100); QCOMPARE(scene.items(QRectF(-100, -1000, 0, 0)).count(), 0); QCOMPARE(scene.items(QRectF(0, 0, 200, 200)).count(), 16); @@ -190,12 +199,17 @@ void tst_QGraphicsSceneIndex::movingItems() scene.addRect(i*50, i*50, 40, 35); QGraphicsRectItem *box = scene.addRect(0, 0, 10, 10); + QCOMPARE(scene.items(QPointF(5, 5)).count(), 2); + QCOMPARE(scene.items(QPointF(-1, -1)).count(), 0); QCOMPARE(scene.items(QRectF(0, 0, 5, 5)).count(), 2); box->setPos(10, 10); + QCOMPARE(scene.items(QPointF(9, 9)).count(), 1); + QCOMPARE(scene.items(QPointF(15, 15)).count(), 2); QCOMPARE(scene.items(QRectF(0, 0, 1, 1)).count(), 1); box->setPos(-5, -5); + QCOMPARE(scene.items(QPointF(-1, -1)).count(), 1); QCOMPARE(scene.items(QRectF(0, 0, 1, 1)).count(), 2); QCOMPARE(scene.items(QRectF(0, 0, 1000, 1000)).count(), 11); -- cgit v0.12 From 76b8d22cee1d0a12de30f2c9d49ead5625b5122f Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Wed, 18 Mar 2009 16:33:03 +0100 Subject: Fixes: QGraphicsSceneIndex now inherits from QObject --- src/gui/graphicsview/qgraphicsscene_bsp.cpp | 4 ++-- src/gui/graphicsview/qgraphicsscene_bsp_p.h | 4 +++- src/gui/graphicsview/qgraphicsscene_linear_p.h | 4 +++- src/gui/graphicsview/qgraphicssceneindex.cpp | 4 ++-- src/gui/graphicsview/qgraphicssceneindex.h | 7 +++++-- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene_bsp.cpp b/src/gui/graphicsview/qgraphicsscene_bsp.cpp index b73cba2..29c54bb 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp.cpp +++ b/src/gui/graphicsview/qgraphicsscene_bsp.cpp @@ -83,8 +83,8 @@ public: } }; -QGraphicsSceneBspTree::QGraphicsSceneBspTree() - : leafCnt(0) +QGraphicsSceneBspTree::QGraphicsSceneBspTree(QObject *parent) + : QGraphicsSceneIndex(parent), leafCnt(0) { insertVisitor = new QGraphicsSceneInsertItemBspTreeVisitor; removeVisitor = new QGraphicsSceneRemoveItemBspTreeVisitor; diff --git a/src/gui/graphicsview/qgraphicsscene_bsp_p.h b/src/gui/graphicsview/qgraphicsscene_bsp_p.h index ed207ea..8b7d753 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp_p.h +++ b/src/gui/graphicsview/qgraphicsscene_bsp_p.h @@ -72,6 +72,8 @@ class QGraphicsSceneFindItemBspTreeVisitor; class Q_AUTOTEST_EXPORT QGraphicsSceneBspTree : public QGraphicsSceneIndex { + Q_OBJECT + public: struct Node { @@ -83,7 +85,7 @@ public: Type type; }; - QGraphicsSceneBspTree(); + QGraphicsSceneBspTree(QObject *parent = 0); ~QGraphicsSceneBspTree(); void initialize(const QRectF &rect, int depth); diff --git a/src/gui/graphicsview/qgraphicsscene_linear_p.h b/src/gui/graphicsview/qgraphicsscene_linear_p.h index 1981b17..4871b2c 100644 --- a/src/gui/graphicsview/qgraphicsscene_linear_p.h +++ b/src/gui/graphicsview/qgraphicsscene_linear_p.h @@ -66,12 +66,14 @@ QT_BEGIN_NAMESPACE class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex { + Q_OBJECT + private: QRectF m_sceneRect; QList m_items; public: - QGraphicsSceneLinearIndex(): QGraphicsSceneIndex() { + QGraphicsSceneLinearIndex(QObject *parent = 0): QGraphicsSceneIndex(parent) { } virtual void setRect(const QRectF &rect) { diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 99d1b3b..904e0af 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE /*! Constructs an abstract scene index. */ -QGraphicsSceneIndex::QGraphicsSceneIndex() +QGraphicsSceneIndex::QGraphicsSceneIndex(QObject *parent): QObject(parent) { } @@ -166,6 +166,6 @@ void QGraphicsSceneIndex::updateItems(const QList &items) QT_END_NAMESPACE -//#include "moc_qgraphicssceneindex.cpp" +#include "moc_qgraphicssceneindex.cpp" #endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index f78672f..d3b6c9f 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -43,6 +43,7 @@ #define QGRAPHICSSCENEINDEX_H #include +#include QT_BEGIN_HEADER @@ -58,10 +59,12 @@ class QRectF; class QPointF; template class QList; -class Q_GUI_EXPORT QGraphicsSceneIndex +class Q_GUI_EXPORT QGraphicsSceneIndex: public QObject { + Q_OBJECT + public: - QGraphicsSceneIndex(); + QGraphicsSceneIndex(QObject *parent = 0); virtual ~QGraphicsSceneIndex(); virtual void setRect(const QRectF &rect) = 0; -- cgit v0.12 From dfd72ab3c8e519f2c08b9a85e1309f8e06a5dd45 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Wed, 18 Mar 2009 19:49:55 +0100 Subject: Fixes: 'delete' always works even with null pointer. --- src/gui/graphicsview/qgraphicsscene.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 4070f11..dd67067 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -363,8 +363,7 @@ QGraphicsScenePrivate::QGraphicsScenePrivate() } QGraphicsScenePrivate::~QGraphicsScenePrivate() { - if (index) - delete index; + delete index; } /*! \internal -- cgit v0.12 From 31bba59443638a2f97f330a9b64ded261b060701 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Wed, 18 Mar 2009 20:16:55 +0100 Subject: Fixes: Own our internal scene index so we do not need to explicitly delete it. --- src/gui/graphicsview/qgraphicsscene.cpp | 7 +++---- src/gui/graphicsview/qgraphicsscene_p.h | 1 - 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index dd67067..d4fcbd0 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -361,10 +361,7 @@ QGraphicsScenePrivate::QGraphicsScenePrivate() style(0) { } -QGraphicsScenePrivate::~QGraphicsScenePrivate() -{ - delete index; -} + /*! \internal */ @@ -372,6 +369,8 @@ void QGraphicsScenePrivate::init() { Q_Q(QGraphicsScene); + index->setParent(q); + // Keep this index so we can check for connected slots later on. changedSignalMask = (1 << q->metaObject()->indexOfSignal("changed(QList)")); qApp->d_func()->scene_list.append(q); diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index b06db38..7e311ee 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -81,7 +81,6 @@ class QGraphicsScenePrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QGraphicsScene) public: QGraphicsScenePrivate(); - ~QGraphicsScenePrivate(); void init(); quint32 changedSignalMask; -- cgit v0.12 From 980e01d69a29e2710a954e2bcd47d78039c76dbd Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Wed, 18 Mar 2009 20:21:36 +0100 Subject: Fixes: Recreate the BSP tree properly. --- src/gui/graphicsview/qgraphicsscene.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index d4fcbd0..4b40d3b 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -2383,14 +2383,12 @@ void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) return; } d->resetIndex(); - if (d->indexMethod != NoIndex) { + if (method == BspTreeIndex) { delete d->index; + d->index = new QGraphicsSceneBspTree(this); + // ### FIXME: transfer the items } d->indexMethod = method; - if (method == BspTreeIndex) { - d->index = new QGraphicsSceneBspTree(); - } - } void QGraphicsScene::setSceneIndex(QGraphicsSceneIndex *index) -- cgit v0.12 From f4c03e0eec3b39145471f25d0a1cdcdba604790c Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Wed, 18 Mar 2009 20:41:27 +0100 Subject: Fixes: Recreate the index properly when switching the index method. --- src/gui/graphicsview/qgraphicsscene.cpp | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 4b40d3b..f8f8e98 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -2372,6 +2372,17 @@ QGraphicsScene::ItemIndexMethod QGraphicsScene::itemIndexMethod() const Q_D(const QGraphicsScene); return d->indexMethod; } + +// Possibilities +// NoIndex -> CustomIndex : warning +// BspTreeIndex -> CustomIndex : warning +// CustomIndex -> CustomIndex : warning +// NoIndex -> BspTreeIndex : create an empty BSP if necessary +// BspTreeIndex -> BspTreeIndex : nothing +// CustomIndex -> BspTreeIndex : create BSP and transfer items +// NoIndex -> NoIndex : nothing +// BspTreeIndex -> NoIndex : nothing +// CustomIndex -> NoIndex : create BSP tree but do not populate void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) { Q_D(QGraphicsScene); @@ -2383,11 +2394,25 @@ void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) return; } d->resetIndex(); - if (method == BspTreeIndex) { - delete d->index; + + if (d->indexMethod == NoIndex && method == BspTreeIndex) { + QGraphicsSceneBspTree *tree = qobject_cast(d->index); + if (!tree) { + delete d->index; + d->index = new QGraphicsSceneBspTree(this); + } + } + + if (d->indexMethod == CustomIndex && method == BspTreeIndex) { + QGraphicsSceneIndex *oldIndex = d->index; d->index = new QGraphicsSceneBspTree(this); - // ### FIXME: transfer the items + d->index->insertItems(oldIndex->items(oldIndex->rect())); } + + if (d->indexMethod == CustomIndex && method == NoIndex) { + d->index = new QGraphicsSceneBspTree(this); + } + d->indexMethod = method; } -- cgit v0.12 From ce77e1d327653c2c0724d6d4a45564c25d98eda8 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Thu, 19 Mar 2009 11:26:24 +0100 Subject: Fixes: Move the bsp depth variable to the BSP tree class. --- src/gui/graphicsview/qgraphicsscene.cpp | 16 ++++++++++++---- src/gui/graphicsview/qgraphicsscene_bsp.cpp | 2 +- src/gui/graphicsview/qgraphicsscene_bsp_p.h | 2 ++ 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index f8f8e98..6aab9df 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -329,7 +329,6 @@ static void _q_hoverFromMouseEvent(QGraphicsSceneHoverEvent *hover, const QGraph QGraphicsScenePrivate::QGraphicsScenePrivate() : changedSignalMask(0), indexMethod(QGraphicsScene::BspTreeIndex), - bspTreeDepth(0), lastItemCount(0), index(new QGraphicsSceneBspTree()), hasSceneRect(false), @@ -540,7 +539,9 @@ void QGraphicsScenePrivate::_q_updateIndex() // Determine whether we should regenerate the BSP tree. if (indexMethod == QGraphicsScene::BspTreeIndex) { - int depth = bspTreeDepth; + QGraphicsSceneBspTree *bspTree = qobject_cast(index); + Q_ASSERT(bspTree); + int depth = bspTree->depth; if (depth == 0) { int oldDepth = intmaxlog(lastItemCount); depth = intmaxlog(indexedItems.size()); @@ -2472,7 +2473,8 @@ QGraphicsSceneIndex* QGraphicsScene::sceneIndex() const int QGraphicsScene::bspTreeDepth() const { Q_D(const QGraphicsScene); - return d->bspTreeDepth; + QGraphicsSceneBspTree *bspTree = qobject_cast(d->index); + return bspTree ? bspTree->depth : 0; } void QGraphicsScene::setBspTreeDepth(int depth) { @@ -2485,7 +2487,13 @@ void QGraphicsScene::setBspTreeDepth(int depth) return; } - d->bspTreeDepth = depth; + QGraphicsSceneBspTree *bspTree = qobject_cast(d->index); + if (!bspTree) { + qWarning("QGraphicsScene::setBspTreeDepth: can not apply if indexing method is not BSP"); + return; + } + + bspTree->depth = depth; d->resetIndex(); } diff --git a/src/gui/graphicsview/qgraphicsscene_bsp.cpp b/src/gui/graphicsview/qgraphicsscene_bsp.cpp index 29c54bb..a81b14d 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp.cpp +++ b/src/gui/graphicsview/qgraphicsscene_bsp.cpp @@ -84,7 +84,7 @@ public: }; QGraphicsSceneBspTree::QGraphicsSceneBspTree(QObject *parent) - : QGraphicsSceneIndex(parent), leafCnt(0) + : QGraphicsSceneIndex(parent), depth(0), leafCnt(0) { insertVisitor = new QGraphicsSceneInsertItemBspTreeVisitor; removeVisitor = new QGraphicsSceneRemoveItemBspTreeVisitor; diff --git a/src/gui/graphicsview/qgraphicsscene_bsp_p.h b/src/gui/graphicsview/qgraphicsscene_bsp_p.h index 8b7d753..69d9eee 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp_p.h +++ b/src/gui/graphicsview/qgraphicsscene_bsp_p.h @@ -102,6 +102,8 @@ public: int leafCount() const; + int depth; + private: inline int firstChildIndex(int index) const -- cgit v0.12 From a779817905ae66de9333fbe3896b0ff1c3990581 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Thu, 19 Mar 2009 14:23:41 +0100 Subject: Fixes: First step to remove the indexing logic inside the scene. This commit basically remove the list of unindexingItems and use the linear index instead. Details: We now must be able to get rid of the timer which is the BSP role. --- src/gui/graphicsview/qgraphicsscene.cpp | 117 ++++++++++++------------- src/gui/graphicsview/qgraphicsscene_linear_p.h | 4 + src/gui/graphicsview/qgraphicsscene_p.h | 1 - 3 files changed, 60 insertions(+), 62 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 6aab9df..b559835 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -331,6 +331,7 @@ QGraphicsScenePrivate::QGraphicsScenePrivate() indexMethod(QGraphicsScene::BspTreeIndex), lastItemCount(0), index(new QGraphicsSceneBspTree()), + linearIndex(new QGraphicsSceneLinearIndex()), hasSceneRect(false), updateAll(false), calledEmitUpdated(false), @@ -369,6 +370,7 @@ void QGraphicsScenePrivate::init() Q_Q(QGraphicsScene); index->setParent(q); + linearIndex->setParent(q); // Keep this index so we can check for connected slots later on. changedSignalMask = (1 << q->metaObject()->indexOfSignal("changed(QList)")); @@ -392,16 +394,13 @@ QList QGraphicsScenePrivate::estimateItemsInRect(const QRectF & // Get items from index items = that->index->items(rect); + //### Why there are items indexed and not at some point? + // Fill in with any unindexed items - for (int i = 0; i < unindexedItems.size(); ++i) { - if (QGraphicsItem *item = unindexedItems.at(i)) { - if (!item->d_ptr->itemDiscovered && item->d_ptr->visible && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { - QRectF boundingRect = item->sceneBoundingRect(); - if (QRectF_intersects(boundingRect, rect)) { - item->d_ptr->itemDiscovered = 1; - items << item; - } - } + foreach (QGraphicsItem *item, linearIndex->items(rect)) { + if (!item->d_ptr->itemDiscovered && item->d_ptr->visible && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { + item->d_ptr->itemDiscovered = 1; + items << item; } } @@ -412,14 +411,15 @@ QList QGraphicsScenePrivate::estimateItemsInRect(const QRectF & } QList itemsInRect; - for (int i = 0; i < unindexedItems.size(); ++i) { - if (QGraphicsItem *item = unindexedItems.at(i)) { - if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) - continue; - if (item->d_ptr->visible && item->effectiveOpacity() > qreal(0.0)) - itemsInRect << item; - } + foreach (QGraphicsItem *item, linearIndex->items(rect)) { + if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) + continue; + if (item->d_ptr->visible && item->effectiveOpacity() > qreal(0.0)) + itemsInRect << item; } + + //### Why there are items indexed and not at some point? + for (int i = 0; i < indexedItems.size(); ++i) { if (QGraphicsItem *item = indexedItems.at(i)) { if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) @@ -469,7 +469,7 @@ void QGraphicsScenePrivate::removeFromIndex(QGraphicsItem *item) freeItemIndexes << index; indexedItems[index] = 0; item->d_func()->index = -1; - unindexedItems << item; + linearIndex->insertItem(item); foreach (QGraphicsItem *child, item->children()) child->removeFromIndex(); @@ -488,7 +488,7 @@ void QGraphicsScenePrivate::resetIndex() for (int i = 0; i < indexedItems.size(); ++i) { if (QGraphicsItem *item = indexedItems.at(i)) { item->d_ptr->index = -1; - unindexedItems << item; + linearIndex->insertItem(item); } } indexedItems.clear(); @@ -519,17 +519,15 @@ void QGraphicsScenePrivate::_q_updateIndex() // Add unindexedItems to indexedItems QRectF unindexedItemsBoundingRect; - for (int i = 0; i < unindexedItems.size(); ++i) { - if (QGraphicsItem *item = unindexedItems.at(i)) { - unindexedItemsBoundingRect |= item->sceneBoundingRect(); - if (!freeItemIndexes.isEmpty()) { - int freeIndex = freeItemIndexes.takeFirst(); - item->d_func()->index = freeIndex; - indexedItems[freeIndex] = item; - } else { - item->d_func()->index = indexedItems.size(); - indexedItems << item; - } + foreach (QGraphicsItem *item, linearIndex->indexedItems()) { + unindexedItemsBoundingRect |= item->sceneBoundingRect(); + if (!freeItemIndexes.isEmpty()) { + int freeIndex = freeItemIndexes.takeFirst(); + item->d_func()->index = freeIndex; + indexedItems[freeIndex] = item; + } else { + item->d_func()->index = indexedItems.size(); + indexedItems << item; } } @@ -560,7 +558,8 @@ void QGraphicsScenePrivate::_q_updateIndex() //### do something better QGraphicsSceneBspTree *bsp = static_cast(index); bsp->initialize(q->sceneRect(), depth); - unindexedItems = indexedItems; + foreach (QGraphicsItem *item, indexedItems) + linearIndex->insertItem(item); lastItemCount = indexedItems.size(); q->update(); @@ -572,30 +571,28 @@ void QGraphicsScenePrivate::_q_updateIndex() } // Insert all unindexed items into the tree. - for (int i = 0; i < unindexedItems.size(); ++i) { - if (QGraphicsItem *item = unindexedItems.at(i)) { - QRectF rect = item->sceneBoundingRect(); - if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) - continue; + foreach (QGraphicsItem *item, linearIndex->indexedItems()) { + QRectF rect = item->sceneBoundingRect(); + if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) + continue; - if (indexMethod != QGraphicsScene::NoIndex) - index->insertItem(item); - - // If the item ignores view transformations, update our - // largest-item-counter to ensure that the view can accurately - // discover untransformable items when drawing. - if (item->d_ptr->itemIsUntransformable()) { - QGraphicsItem *topmostUntransformable = item; - while (topmostUntransformable && (topmostUntransformable->d_ptr->ancestorFlags - & QGraphicsItemPrivate::AncestorIgnoresTransformations)) { - topmostUntransformable = topmostUntransformable->parentItem(); - } - // ### Verify that this is the correct largest untransformable rectangle. - largestUntransformableItem |= item->mapToItem(topmostUntransformable, item->boundingRect()).boundingRect(); + if (indexMethod != QGraphicsScene::NoIndex) + index->insertItem(item); + + // If the item ignores view transformations, update our + // largest-item-counter to ensure that the view can accurately + // discover untransformable items when drawing. + if (item->d_ptr->itemIsUntransformable()) { + QGraphicsItem *topmostUntransformable = item; + while (topmostUntransformable && (topmostUntransformable->d_ptr->ancestorFlags + & QGraphicsItemPrivate::AncestorIgnoresTransformations)) { + topmostUntransformable = topmostUntransformable->parentItem(); } + // ### Verify that this is the correct largest untransformable rectangle. + largestUntransformableItem |= item->mapToItem(topmostUntransformable, item->boundingRect()).boundingRect(); } } - unindexedItems.clear(); + linearIndex->clear(); // Notify scene rect changes. if (!hasSceneRect && growingItemsBoundingRect != oldGrowingItemsBoundingRect) @@ -756,7 +753,7 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item) } else { // Recently added items are purged immediately. unindexedItems() never // contains stale items. - unindexedItems.removeAll(item); + linearIndex->removeItem(item); q->update(); } @@ -1982,8 +1979,7 @@ void QGraphicsScenePrivate::_q_updateSortCache() if (item && item->parentItem() == 0) topLevels << item; } - for (int i = 0; i < unindexedItems.size(); ++i) { - QGraphicsItem *item = unindexedItems.at(i); + foreach (QGraphicsItem *item, linearIndex->indexedItems()) { if (item->parentItem() == 0) topLevels << item; } @@ -2552,15 +2548,15 @@ QList QGraphicsScene::items() const // If freeItemIndexes is empty, we know there are no holes in indexedItems and // unindexedItems. if (d->freeItemIndexes.isEmpty()) { - if (d->unindexedItems.isEmpty()) + if (d->linearIndex->indexedItems().isEmpty()) return d->indexedItems; - return d->indexedItems + d->unindexedItems; + return d->indexedItems + d->linearIndex->indexedItems(); } // Rebuild the list of items to avoid holes. ### We could also just // compress the item lists at this point. QList itemList; - foreach (QGraphicsItem *item, d->indexedItems + d->unindexedItems) { + foreach (QGraphicsItem *item, d->indexedItems + d->linearIndex->indexedItems()) { if (item) itemList << item; } @@ -2841,12 +2837,11 @@ void QGraphicsScene::clear() } } QList unindexedParents; - for (int i = 0; i < d->unindexedItems.size(); ++i) { - QGraphicsItem *item = d->unindexedItems.at(i); + foreach (QGraphicsItem *item, d->linearIndex->indexedItems()) { if (!item->parentItem()) unindexedParents << item; } - d->unindexedItems.clear(); + d->linearIndex->clear(); qDeleteAll(unindexedParents); d->indexedItems.clear(); d->freeItemIndexes.clear(); @@ -2994,7 +2989,7 @@ void QGraphicsScene::addItem(QGraphicsItem *item) // Indexing requires sceneBoundingRect(), but because \a item might // not be completely constructed at this point, we need to store it in // a temporary list and schedule an indexing for later. - d->unindexedItems << item; + d->linearIndex->insertItem(item); item->d_func()->index = -1; d->startIndexTimer(); @@ -3382,7 +3377,7 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) d->freeItemIndexes << index; d->indexedItems[index] = 0; } else { - d->unindexedItems.removeAll(item); + d->linearIndex->removeItem(item); } // Remove from scene transform cache diff --git a/src/gui/graphicsview/qgraphicsscene_linear_p.h b/src/gui/graphicsview/qgraphicsscene_linear_p.h index 4871b2c..41e03e4 100644 --- a/src/gui/graphicsview/qgraphicsscene_linear_p.h +++ b/src/gui/graphicsview/qgraphicsscene_linear_p.h @@ -111,6 +111,10 @@ public: result << item; return result; } + + QList indexedItems() { + return m_items; + } }; QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 7e311ee..65c1a69 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -112,7 +112,6 @@ public: QPainterPath selectionArea; int selectionChanging; QSet selectedItems; - QList unindexedItems; QList indexedItems; QList dirtyItems; QList pendingUpdateItems; -- cgit v0.12 From 226baa99f53eeeff2489148c9187c19f5bc86f0e Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Tue, 7 Apr 2009 20:42:53 +0200 Subject: Remove the indexing (BSP) logic from the scene We basically add a new index that implement the old BSP logic but in a separate class instead of living into the QGraphicsScene. It will be much more easier to add a new index method or for people to use their own Conflicts: src/gui/graphicsview/qgraphicsitem.cpp src/gui/graphicsview/qgraphicssceneindex.h --- src/gui/graphicsview/graphicsview.pri | 4 +- src/gui/graphicsview/qgraphicsitem.cpp | 10 +- src/gui/graphicsview/qgraphicsitem.h | 1 + src/gui/graphicsview/qgraphicsscene.cpp | 390 ++---------------- src/gui/graphicsview/qgraphicsscene.h | 2 +- src/gui/graphicsview/qgraphicsscene_bsp.cpp | 40 +- src/gui/graphicsview/qgraphicsscene_bsp_p.h | 27 +- src/gui/graphicsview/qgraphicsscene_linear_p.h | 124 ------ src/gui/graphicsview/qgraphicsscene_p.h | 20 +- .../graphicsview/qgraphicsscenebsptreeindex_p.cpp | 437 +++++++++++++++++++++ .../graphicsview/qgraphicsscenebsptreeindex_p.h | 118 ++++++ src/gui/graphicsview/qgraphicssceneindex.cpp | 14 +- src/gui/graphicsview/qgraphicssceneindex.h | 15 +- src/gui/graphicsview/qgraphicsscenelinearindex_p.h | 126 ++++++ .../tst_qgraphicssceneindex.cpp | 15 +- 15 files changed, 769 insertions(+), 574 deletions(-) delete mode 100644 src/gui/graphicsview/qgraphicsscene_linear_p.h create mode 100644 src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp create mode 100644 src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h create mode 100644 src/gui/graphicsview/qgraphicsscenelinearindex_p.h diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri index bc4d9dd..9097497 100644 --- a/src/gui/graphicsview/graphicsview.pri +++ b/src/gui/graphicsview/graphicsview.pri @@ -6,8 +6,9 @@ HEADERS += \ graphicsview/qgraphicsitemanimation.h \ graphicsview/qgraphicsscene.h \ graphicsview/qgraphicsscene_p.h \ + graphicsview/qgraphicsscenebsptreeindex_p.h \ graphicsview/qgraphicsscene_bsp_p.h \ - graphicsview/qgraphicsscene_linear_p.h \ + graphicsview/qgraphicsscenelinearindex_p.h \ graphicsview/qgraphicssceneindex.h \ graphicsview/qgraphicssceneevent.h \ graphicsview/qgraphicsview_p.h \ @@ -18,6 +19,7 @@ SOURCES += \ graphicsview/qgraphicsitemanimation.cpp \ graphicsview/qgraphicsscene.cpp \ graphicsview/qgraphicsscene_bsp.cpp \ + graphicsview/qgraphicsscenebsptreeindex_p.cpp \ graphicsview/qgraphicssceneindex.cpp \ graphicsview/qgraphicssceneevent.cpp \ graphicsview/qgraphicsview.cpp diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index b8ff5b4..4574334 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -5789,7 +5789,7 @@ void QGraphicsItem::addToIndex() return; } if (d_ptr->scene) - d_ptr->scene->d_func()->addToIndex(this); + d_ptr->scene->d_func()->index->insertItem(this); d_ptr->updateHelper(); } @@ -5802,13 +5802,9 @@ void QGraphicsItem::addToIndex() */ void QGraphicsItem::removeFromIndex() { - if (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { - // ### remove from child index only if applicable - return; - } d_ptr->updateHelper(); if (d_ptr->scene) - d_ptr->scene->d_func()->removeFromIndex(this); + d_ptr->scene->d_func()->index->removeItem(this,false); } /*! @@ -5831,7 +5827,7 @@ void QGraphicsItem::prepareGeometryChange() d_ptr->updateHelper(QRectF(), false, /*maybeDirtyClipPath=*/!d_ptr->inSetPosHelper); QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func(); - scenePrivate->removeFromIndex(this); + scenePrivate->index->updateItem(this); if (d_ptr->inSetPosHelper) return; diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index b98882d..1b41232 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -398,6 +398,7 @@ private: friend class QGraphicsWidget; friend class QGraphicsWidgetPrivate; friend class QGraphicsProxyWidgetPrivate; + friend class QGraphicsSceneBspTreeIndex; friend class ::tst_QGraphicsItem; friend bool qt_closestLeaf(const QGraphicsItem *, const QGraphicsItem *); friend bool qt_closestItemFirst(const QGraphicsItem *, const QGraphicsItem *); diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index b559835..8140f79 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -39,8 +39,6 @@ ** ****************************************************************************/ -static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; - /*! \class QGraphicsScene \brief The QGraphicsScene class provides a surface for managing a large @@ -329,18 +327,14 @@ static void _q_hoverFromMouseEvent(QGraphicsSceneHoverEvent *hover, const QGraph QGraphicsScenePrivate::QGraphicsScenePrivate() : changedSignalMask(0), indexMethod(QGraphicsScene::BspTreeIndex), + bspTreeDepth(0), lastItemCount(0), - index(new QGraphicsSceneBspTree()), - linearIndex(new QGraphicsSceneLinearIndex()), + index(0), hasSceneRect(false), updateAll(false), calledEmitUpdated(false), selectionChanging(0), dirtyItemResetPending(false), - regenerateIndex(true), - purgePending(false), - indexTimerId(0), - restartIndexTimer(false), stickyFocus(false), hasFocus(false), focusItem(0), @@ -369,8 +363,7 @@ void QGraphicsScenePrivate::init() { Q_Q(QGraphicsScene); - index->setParent(q); - linearIndex->setParent(q); + index = new QGraphicsSceneBspTreeIndex(q); // Keep this index so we can check for connected slots later on. changedSignalMask = (1 << q->metaObject()->indexOfSignal("changed(QList)")); @@ -383,220 +376,14 @@ void QGraphicsScenePrivate::init() */ QList QGraphicsScenePrivate::estimateItemsInRect(const QRectF &rect) const { - const_cast(this)->purgeRemovedItems(); const_cast(this)->_q_updateSortCache(); - if (indexMethod != QGraphicsScene::NoIndex) { - // ### Only do this once in a while. - QGraphicsScenePrivate *that = const_cast(this); - - QList items; - // Get items from index - items = that->index->items(rect); - - //### Why there are items indexed and not at some point? - - // Fill in with any unindexed items - foreach (QGraphicsItem *item, linearIndex->items(rect)) { - if (!item->d_ptr->itemDiscovered && item->d_ptr->visible && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { - item->d_ptr->itemDiscovered = 1; - items << item; - } - } - - // Reset the discovered state of all discovered items - for (int i = 0; i < items.size(); ++i) - items.at(i)->d_func()->itemDiscovered = 0; - return items; - } - - QList itemsInRect; - foreach (QGraphicsItem *item, linearIndex->items(rect)) { - if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) - continue; - if (item->d_ptr->visible && item->effectiveOpacity() > qreal(0.0)) - itemsInRect << item; - } + // ### Only do this once in a while. + QGraphicsScenePrivate *that = const_cast(this); - //### Why there are items indexed and not at some point? - - for (int i = 0; i < indexedItems.size(); ++i) { - if (QGraphicsItem *item = indexedItems.at(i)) { - if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) - continue; - if (item->d_ptr->visible && item->effectiveOpacity() > qreal(0.0)) - itemsInRect << item; - } - } + // Get items from index + return that->index->items(rect); - return itemsInRect; -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::addToIndex(QGraphicsItem *item) -{ - if (indexMethod == QGraphicsScene::BspTreeIndex) { - if (item->d_func()->index != -1) { - index->insertItem(item); - foreach (QGraphicsItem *child, item->children()) - child->addToIndex(); - } else { - // The BSP tree is regenerated if the number of items grows to a - // certain threshold, or if the bounding rect of the graph doubles in - // size. - startIndexTimer(); - } - } else if (indexMethod == QGraphicsScene::CustomIndex) { - if (item->d_func()->index != -1) { - index->insertItem(item); - foreach (QGraphicsItem *child, item->children()) - child->addToIndex(); - } - } -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::removeFromIndex(QGraphicsItem *item) -{ - if (indexMethod != QGraphicsScene::NoIndex) { - int index = item->d_func()->index; - if (index != -1) { - this->index->removeItem(item); - freeItemIndexes << index; - indexedItems[index] = 0; - item->d_func()->index = -1; - linearIndex->insertItem(item); - - foreach (QGraphicsItem *child, item->children()) - child->removeFromIndex(); - } - startIndexTimer(); - } -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::resetIndex() -{ - purgeRemovedItems(); - if (indexMethod != QGraphicsScene::NoIndex) { - for (int i = 0; i < indexedItems.size(); ++i) { - if (QGraphicsItem *item = indexedItems.at(i)) { - item->d_ptr->index = -1; - linearIndex->insertItem(item); - } - } - indexedItems.clear(); - freeItemIndexes.clear(); - regenerateIndex = true; - startIndexTimer(); - } -} - -static inline int intmaxlog(int n) -{ - return (n > 0 ? qMax(qCeil(qLn(qreal(n)) / qLn(qreal(2))), 5) : 0); -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::_q_updateIndex() -{ - if (!indexTimerId) - return; - - Q_Q(QGraphicsScene); - q->killTimer(indexTimerId); - indexTimerId = 0; - - purgeRemovedItems(); - - // Add unindexedItems to indexedItems - QRectF unindexedItemsBoundingRect; - foreach (QGraphicsItem *item, linearIndex->indexedItems()) { - unindexedItemsBoundingRect |= item->sceneBoundingRect(); - if (!freeItemIndexes.isEmpty()) { - int freeIndex = freeItemIndexes.takeFirst(); - item->d_func()->index = freeIndex; - indexedItems[freeIndex] = item; - } else { - item->d_func()->index = indexedItems.size(); - indexedItems << item; - } - } - - // Update growing scene rect. - QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect; - growingItemsBoundingRect |= unindexedItemsBoundingRect; - - // Determine whether we should regenerate the BSP tree. - if (indexMethod == QGraphicsScene::BspTreeIndex) { - QGraphicsSceneBspTree *bspTree = qobject_cast(index); - Q_ASSERT(bspTree); - int depth = bspTree->depth; - if (depth == 0) { - int oldDepth = intmaxlog(lastItemCount); - depth = intmaxlog(indexedItems.size()); - static const int slack = 100; - //### do something better - QGraphicsSceneBspTree *bsp = static_cast(index); - if (bsp->leafCount() == 0 || (oldDepth != depth && qAbs(lastItemCount - indexedItems.size()) > slack)) { - // ### Crude algorithm. - regenerateIndex = true; - } - } - - // Regenerate the tree. - if (regenerateIndex) { - regenerateIndex = false; - //### do something better - QGraphicsSceneBspTree *bsp = static_cast(index); - bsp->initialize(q->sceneRect(), depth); - foreach (QGraphicsItem *item, indexedItems) - linearIndex->insertItem(item); - lastItemCount = indexedItems.size(); - q->update(); - - // Take this opportunity to reset our largest-item counter for - // untransformable items. When the items are inserted into the BSP - // tree, we'll get an accurate calculation. - largestUntransformableItem = QRectF(); - } - } - - // Insert all unindexed items into the tree. - foreach (QGraphicsItem *item, linearIndex->indexedItems()) { - QRectF rect = item->sceneBoundingRect(); - if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) - continue; - - if (indexMethod != QGraphicsScene::NoIndex) - index->insertItem(item); - - // If the item ignores view transformations, update our - // largest-item-counter to ensure that the view can accurately - // discover untransformable items when drawing. - if (item->d_ptr->itemIsUntransformable()) { - QGraphicsItem *topmostUntransformable = item; - while (topmostUntransformable && (topmostUntransformable->d_ptr->ancestorFlags - & QGraphicsItemPrivate::AncestorIgnoresTransformations)) { - topmostUntransformable = topmostUntransformable->parentItem(); - } - // ### Verify that this is the correct largest untransformable rectangle. - largestUntransformableItem |= item->mapToItem(topmostUntransformable, item->boundingRect()).boundingRect(); - } - } - linearIndex->clear(); - - // Notify scene rect changes. - if (!hasSceneRect && growingItemsBoundingRect != oldGrowingItemsBoundingRect) - emit q->sceneRectChanged(growingItemsBoundingRect); } /*! @@ -740,22 +527,8 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item) // chain. item->clearFocus(); - int index = item->d_func()->index; - if (index != -1) { - // Important: The index is useless until purgeRemovedItems() is - // called. - indexedItems[index] = (QGraphicsItem *)0; - if (!purgePending) { - purgePending = true; - q->update(); - } - removedItems << item; - } else { - // Recently added items are purged immediately. unindexedItems() never - // contains stale items. - linearIndex->removeItem(item); - q->update(); - } + //We ask for a removing in the index + this->index->removeItem(item, true); // Reset the mouse grabber and focus item data. if (item == focusItem) @@ -806,51 +579,6 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item) /*! \internal - - Removes stale pointers from all data structures. -*/ -void QGraphicsScenePrivate::purgeRemovedItems() -{ - Q_Q(QGraphicsScene); - - if (!purgePending && removedItems.isEmpty()) - return; - - // Remove stale items from the BSP tree. - if (indexMethod != QGraphicsScene::NoIndex) { - index->removeItems(removedItems); - } - - // Purge this list. - removedItems.clear(); - freeItemIndexes.clear(); - for (int i = 0; i < indexedItems.size(); ++i) { - if (!indexedItems.at(i)) - freeItemIndexes << i; - } - purgePending = false; - - // No locality info for the items; update the whole scene. - q->update(); -} - -/*! - \internal - - Starts or restarts the timer used for reindexing unindexed items. -*/ -void QGraphicsScenePrivate::startIndexTimer() -{ - Q_Q(QGraphicsScene); - if (indexTimerId) { - restartIndexTimer = true; - } else { - indexTimerId = q->startTimer(QGRAPHICSSCENE_INDEXTIMER_TIMEOUT); - } -} - -/*! - \internal */ void QGraphicsScenePrivate::addPopup(QGraphicsWidget *widget) { @@ -1964,7 +1692,7 @@ void QGraphicsScenePrivate::climbTree(QGraphicsItem *item, int *stackingOrder) void QGraphicsScenePrivate::_q_updateSortCache() { - _q_updateIndex(); + index->updateIndex(); if (!sortCacheEnabled || !updatingSortCache) return; @@ -1974,15 +1702,11 @@ void QGraphicsScenePrivate::_q_updateSortCache() QList topLevels; - for (int i = 0; i < indexedItems.size(); ++i) { - QGraphicsItem *item = indexedItems.at(i); + for (int i = 0; i < index->indexedItems().count(); ++i) { + QGraphicsItem *item = index->indexedItems().at(i); if (item && item->parentItem() == 0) topLevels << item; } - foreach (QGraphicsItem *item, linearIndex->indexedItems()) { - if (item->parentItem() == 0) - topLevels << item; - } qSort(topLevels.begin(), topLevels.end(), qt_closestLeaf); for (int i = 0; i < topLevels.size(); ++i) @@ -2139,8 +1863,8 @@ QGraphicsScene::QGraphicsScene(QObject *parent) QGraphicsScene::QGraphicsScene(const QRectF &sceneRect, QObject *parent) : QObject(*new QGraphicsScenePrivate, parent) { - setSceneRect(sceneRect); d_func()->init(); + setSceneRect(sceneRect); } /*! @@ -2154,8 +1878,8 @@ QGraphicsScene::QGraphicsScene(const QRectF &sceneRect, QObject *parent) QGraphicsScene::QGraphicsScene(qreal x, qreal y, qreal width, qreal height, QObject *parent) : QObject(*new QGraphicsScenePrivate, parent) { - setSceneRect(x, y, width, height); d_func()->init(); + setSceneRect(x, y, width, height); } /*! @@ -2192,8 +1916,8 @@ QGraphicsScene::~QGraphicsScene() QRectF QGraphicsScene::sceneRect() const { Q_D(const QGraphicsScene); - const_cast(d)->_q_updateIndex(); - return d->hasSceneRect ? d->sceneRect : d->growingItemsBoundingRect; + d->index->updateIndex(); + return d->hasSceneRect ? d->index->rect() : d->growingItemsBoundingRect; } void QGraphicsScene::setSceneRect(const QRectF &rect) { @@ -2201,7 +1925,7 @@ void QGraphicsScene::setSceneRect(const QRectF &rect) if (rect != d->sceneRect) { d->hasSceneRect = !rect.isNull(); d->sceneRect = rect; - d->resetIndex(); + d->index->setRect(rect); emit sceneRectChanged(rect); } } @@ -2390,24 +2114,23 @@ void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) if (d->indexMethod == method) { return; } - d->resetIndex(); if (d->indexMethod == NoIndex && method == BspTreeIndex) { - QGraphicsSceneBspTree *tree = qobject_cast(d->index); + QGraphicsSceneBspTreeIndex *tree = qobject_cast(d->index); if (!tree) { delete d->index; - d->index = new QGraphicsSceneBspTree(this); + d->index = new QGraphicsSceneBspTreeIndex(this); } } if (d->indexMethod == CustomIndex && method == BspTreeIndex) { QGraphicsSceneIndex *oldIndex = d->index; - d->index = new QGraphicsSceneBspTree(this); + d->index = new QGraphicsSceneBspTreeIndex(this); d->index->insertItems(oldIndex->items(oldIndex->rect())); } if (d->indexMethod == CustomIndex && method == NoIndex) { - d->index = new QGraphicsSceneBspTree(this); + d->index = new QGraphicsSceneLinearIndex(this); } d->indexMethod = method; @@ -2424,7 +2147,6 @@ void QGraphicsScene::setSceneIndex(QGraphicsSceneIndex *index) } d->indexMethod = CustomIndex; d->index = index; - index->mscene = this; } } @@ -2469,8 +2191,8 @@ QGraphicsSceneIndex* QGraphicsScene::sceneIndex() const int QGraphicsScene::bspTreeDepth() const { Q_D(const QGraphicsScene); - QGraphicsSceneBspTree *bspTree = qobject_cast(d->index); - return bspTree ? bspTree->depth : 0; + QGraphicsSceneBspTreeIndex *bspTree = qobject_cast(d->index); + return bspTree ? bspTree->bspDepth() : 0; } void QGraphicsScene::setBspTreeDepth(int depth) { @@ -2483,14 +2205,13 @@ void QGraphicsScene::setBspTreeDepth(int depth) return; } - QGraphicsSceneBspTree *bspTree = qobject_cast(d->index); + QGraphicsSceneBspTreeIndex *bspTree = qobject_cast(d->index); if (!bspTree) { qWarning("QGraphicsScene::setBspTreeDepth: can not apply if indexing method is not BSP"); return; } - bspTree->depth = depth; - d->resetIndex(); + bspTree->setBspDepth(depth); } /*! @@ -2543,24 +2264,7 @@ QRectF QGraphicsScene::itemsBoundingRect() const QList QGraphicsScene::items() const { Q_D(const QGraphicsScene); - const_cast(d)->purgeRemovedItems(); - - // If freeItemIndexes is empty, we know there are no holes in indexedItems and - // unindexedItems. - if (d->freeItemIndexes.isEmpty()) { - if (d->linearIndex->indexedItems().isEmpty()) - return d->indexedItems; - return d->indexedItems + d->linearIndex->indexedItems(); - } - - // Rebuild the list of items to avoid holes. ### We could also just - // compress the item lists at this point. - QList itemList; - foreach (QGraphicsItem *item, d->indexedItems + d->linearIndex->indexedItems()) { - if (item) - itemList << item; - } - return itemList; + return d->index->indexedItems(); } /*! @@ -2830,21 +2534,12 @@ void QGraphicsScene::clear() { Q_D(QGraphicsScene); // Recursive descent delete - for (int i = 0; i < d->indexedItems.size(); ++i) { - if (QGraphicsItem *item = d->indexedItems.at(i)) { + for (int i = 0; i < d->index->indexedItems().size(); ++i) { + if (QGraphicsItem *item = d->index->indexedItems().at(i)) { if (!item->parentItem()) delete item; } } - QList unindexedParents; - foreach (QGraphicsItem *item, d->linearIndex->indexedItems()) { - if (!item->parentItem()) - unindexedParents << item; - } - d->linearIndex->clear(); - qDeleteAll(unindexedParents); - d->indexedItems.clear(); - d->freeItemIndexes.clear(); d->lastItemCount = 0; d->index->clear(); d->largestUntransformableItem = QRectF(); @@ -2968,10 +2663,6 @@ void QGraphicsScene::addItem(QGraphicsItem *item) return; } - // Prevent reusing a recently deleted pointer: purge all removed items - // from our lists. - d->purgeRemovedItems(); - // Invalidate any sort caching; arrival of a new item means we need to // resort. d->invalidateSortCache(); @@ -2989,9 +2680,7 @@ void QGraphicsScene::addItem(QGraphicsItem *item) // Indexing requires sceneBoundingRect(), but because \a item might // not be completely constructed at this point, we need to store it in // a temporary list and schedule an indexing for later. - d->linearIndex->insertItem(item); - item->d_func()->index = -1; - d->startIndexTimer(); + d->index->insertItem(item); // Add to list of toplevels if this item is a toplevel. if (!item->d_ptr->parent) @@ -3351,7 +3040,7 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) // Note: This will access item's sceneBoundingRect(), which (as this is // C++) is why we cannot call removeItem() from QGraphicsItem's // destructor. - d->removeFromIndex(item); + d->index->removeItem(item, false); if (item == d->tabFocusFirst) { QGraphicsWidget *widget = static_cast(item); @@ -3371,15 +3060,6 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) d->unregisterTopLevelItem(item); } - // Remove from our item lists. - int index = item->d_func()->index; - if (index != -1) { - d->freeItemIndexes << index; - d->indexedItems[index] = 0; - } else { - d->linearIndex->removeItem(item); - } - // Remove from scene transform cache int transformIndex = item->d_func()->sceneTransformIndex; if (transformIndex != -1) { @@ -3998,16 +3678,6 @@ bool QGraphicsScene::event(QEvent *event) // geometries that do not have an explicit style set. update(); break; - case QEvent::Timer: - if (d->indexTimerId && static_cast(event)->timerId() == d->indexTimerId) { - if (d->restartIndexTimer) { - d->restartIndexTimer = false; - } else { - // this call will kill the timer - d->_q_updateIndex(); - } - } - // Fallthrough intended - support timers in subclasses. default: return QObject::event(event); } diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h index bb3cea7..6476b8c 100644 --- a/src/gui/graphicsview/qgraphicsscene.h +++ b/src/gui/graphicsview/qgraphicsscene.h @@ -279,7 +279,6 @@ private: Q_DECLARE_PRIVATE(QGraphicsScene) Q_DISABLE_COPY(QGraphicsScene) - Q_PRIVATE_SLOT(d_func(), void _q_updateIndex()) Q_PRIVATE_SLOT(d_func(), void _q_emitUpdated()) Q_PRIVATE_SLOT(d_func(), void _q_removeItemLater(QGraphicsItem *item)) Q_PRIVATE_SLOT(d_func(), void _q_updateLater()) @@ -292,6 +291,7 @@ private: friend class QGraphicsViewPrivate; friend class QGraphicsWidget; friend class QGraphicsWidgetPrivate; + friend class QGraphicsSceneBspTreeIndex; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsScene::SceneLayers) diff --git a/src/gui/graphicsview/qgraphicsscene_bsp.cpp b/src/gui/graphicsview/qgraphicsscene_bsp.cpp index a81b14d..f8fa450 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp.cpp +++ b/src/gui/graphicsview/qgraphicsscene_bsp.cpp @@ -83,8 +83,8 @@ public: } }; -QGraphicsSceneBspTree::QGraphicsSceneBspTree(QObject *parent) - : QGraphicsSceneIndex(parent), depth(0), leafCnt(0) +QGraphicsSceneBspTree::QGraphicsSceneBspTree() + : leafCnt(0) { insertVisitor = new QGraphicsSceneInsertItemBspTreeVisitor; removeVisitor = new QGraphicsSceneRemoveItemBspTreeVisitor; @@ -100,7 +100,7 @@ QGraphicsSceneBspTree::~QGraphicsSceneBspTree() void QGraphicsSceneBspTree::initialize(const QRectF &rect, int depth) { - sceneRect = rect; + this->rect = rect; leafCnt = 0; nodes.resize((1 << (depth + 1)) - 1); nodes.fill(Node()); @@ -117,29 +117,19 @@ void QGraphicsSceneBspTree::clear() leaves.clear(); } -QRectF QGraphicsSceneBspTree::rect() const -{ - return sceneRect; -} - -void QGraphicsSceneBspTree::setRect(const QRectF &rect) -{ - sceneRect = rect; -} - -void QGraphicsSceneBspTree::insertItem(QGraphicsItem *item) +void QGraphicsSceneBspTree::insertItem(QGraphicsItem *item, const QRectF &rect) { insertVisitor->item = item; - climbTree(insertVisitor, item->sceneBoundingRect()); + climbTree(insertVisitor, rect); } -void QGraphicsSceneBspTree::removeItem(QGraphicsItem *item) +void QGraphicsSceneBspTree::removeItem(QGraphicsItem *item, const QRectF &rect) { removeVisitor->item = item; - climbTree(removeVisitor, item->sceneBoundingRect()); + climbTree(removeVisitor, rect); } -void QGraphicsSceneBspTree::removeItems(const QList &items) +void QGraphicsSceneBspTree::removeItems(const QSet &items) { for (int i = 0; i < leaves.size(); ++i) { QList newItemList; @@ -247,10 +237,8 @@ void QGraphicsSceneBspTree::initialize(const QRectF &rect, int depth, int index) void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QPointF &pos, int index) { - if (nodes.isEmpty()) { - // should never happen for bsp tree internal to QGraphicsScene - initialize(sceneRect, 0); - } + if (nodes.isEmpty()) + return; const Node &node = nodes.at(index); int childIndex = firstChildIndex(index); @@ -279,10 +267,8 @@ void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, con void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index) { - if (nodes.isEmpty()) { - // should never happen for bsp tree internal to QGraphicsScene - initialize(sceneRect, 0); - } + if (nodes.isEmpty()) + return; const Node &node = nodes.at(index); int childIndex = firstChildIndex(index); @@ -316,7 +302,7 @@ void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, con QRectF QGraphicsSceneBspTree::rectForIndex(int index) const { if (index <= 0) - return sceneRect; + return rect; int parentIdx = parentIndex(index); QRectF rect = rectForIndex(parentIdx); diff --git a/src/gui/graphicsview/qgraphicsscene_bsp_p.h b/src/gui/graphicsview/qgraphicsscene_bsp_p.h index 69d9eee..e6ceb78 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp_p.h +++ b/src/gui/graphicsview/qgraphicsscene_bsp_p.h @@ -60,7 +60,6 @@ #include #include #include -#include QT_BEGIN_NAMESPACE @@ -70,10 +69,8 @@ class QGraphicsSceneInsertItemBspTreeVisitor; class QGraphicsSceneRemoveItemBspTreeVisitor; class QGraphicsSceneFindItemBspTreeVisitor; -class Q_AUTOTEST_EXPORT QGraphicsSceneBspTree : public QGraphicsSceneIndex +class QGraphicsSceneBspTree { - Q_OBJECT - public: struct Node { @@ -85,27 +82,20 @@ public: Type type; }; - QGraphicsSceneBspTree(QObject *parent = 0); + QGraphicsSceneBspTree(); ~QGraphicsSceneBspTree(); void initialize(const QRectF &rect, int depth); void clear(); - QRectF rect() const; - void setRect(const QRectF &rect); - void insertItem(QGraphicsItem *item); - void removeItem(QGraphicsItem *item); - void removeItems(const QList &items); + void insertItem(QGraphicsItem *item, const QRectF &rect); + void removeItem(QGraphicsItem *item, const QRectF &rect); + void removeItems(const QSet &items); - QList items(const QPointF &point); QList items(const QRectF &rect); - + QList items(const QPointF &pos); int leafCount() const; - int depth; - -private: - inline int firstChildIndex(int index) const { return index * 2 + 1; } @@ -114,6 +104,7 @@ private: QString debug(int index) const; +private: void initialize(const QRectF &rect, int depth, int index); void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QPointF &pos, int index = 0); void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index = 0); @@ -125,7 +116,7 @@ private: QVector nodes; QVector > leaves; int leafCnt; - QRectF sceneRect; + QRectF rect; QGraphicsSceneInsertItemBspTreeVisitor *insertVisitor; QGraphicsSceneRemoveItemBspTreeVisitor *removeVisitor; @@ -139,8 +130,6 @@ public: virtual void visit(QList *items) = 0; }; -Q_DECLARE_TYPEINFO(QGraphicsSceneBspTree::Node, Q_PRIMITIVE_TYPE); - QT_END_NAMESPACE #endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicsscene_linear_p.h b/src/gui/graphicsview/qgraphicsscene_linear_p.h deleted file mode 100644 index 41e03e4..0000000 --- a/src/gui/graphicsview/qgraphicsscene_linear_p.h +++ /dev/null @@ -1,124 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSSCENELINEARINDEX_P_H -#define QGRAPHICSSCENELINEARINDEX_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex -{ - Q_OBJECT - -private: - QRectF m_sceneRect; - QList m_items; - -public: - QGraphicsSceneLinearIndex(QObject *parent = 0): QGraphicsSceneIndex(parent) { - } - - virtual void setRect(const QRectF &rect) { - m_sceneRect = rect; - } - - virtual QRectF rect() const { - return m_sceneRect; - } - - virtual void clear() { - m_items.clear(); - } - - virtual void insertItem(QGraphicsItem *item) { - m_items << item; - } - - virtual void removeItem(QGraphicsItem *item) { - m_items.removeAll(item); - } - - virtual QList items(const QPointF &point) { - QList result; - foreach (QGraphicsItem *item, m_items) - if (item->sceneBoundingRect().contains(point)) - result << item; - return result; - } - - virtual QList items(const QRectF &rect) { - QList result; - foreach (QGraphicsItem *item, m_items) - if (item->sceneBoundingRect().intersects(rect)) - result << item; - return result; - } - - QList indexedItems() { - return m_items; - } -}; - -QT_END_NAMESPACE - -#endif // QT_NO_GRAPHICSVIEW - -#endif // QGRAPHICSSCENELINEARINDEX_P_H diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 65c1a69..2c0d464 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -57,8 +57,8 @@ #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW -#include "qgraphicsscene_bsp_p.h" -#include "qgraphicsscene_linear_p.h" +#include "qgraphicsscenebsptreeindex_p.h" +#include "qgraphicsscenelinearindex_p.h" #include "qgraphicssceneindex.h" #include "qgraphicsitem_p.h" @@ -89,15 +89,10 @@ public: int bspTreeDepth; QList estimateItemsInRect(const QRectF &rect) const; - void addToIndex(QGraphicsItem *item); - void removeFromIndex(QGraphicsItem *item); - void resetIndex(); - void _q_updateIndex(); int lastItemCount; QGraphicsSceneIndex *index; - QGraphicsSceneLinearIndex *linearIndex; QRectF sceneRect; bool hasSceneRect; @@ -112,7 +107,6 @@ public: QPainterPath selectionArea; int selectionChanging; QSet selectedItems; - QList indexedItems; QList dirtyItems; QList pendingUpdateItems; QList unpolishedItems; @@ -127,21 +121,11 @@ public: void resetDirtyItemsLater(); bool dirtyItemResetPending; - QList freeItemIndexes; - bool regenerateIndex; - - bool purgePending; void _q_removeItemLater(QGraphicsItem *item); - QList removedItems; - void purgeRemovedItems(); QBrush backgroundBrush; QBrush foregroundBrush; - int indexTimerId; - bool restartIndexTimer; - void startIndexTimer(); - bool stickyFocus; bool hasFocus; QGraphicsItem *focusItem; diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp new file mode 100644 index 0000000..ebc167a --- /dev/null +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp @@ -0,0 +1,437 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; + +#include "qgraphicsscenebsptreeindex_p.h" +#include "qgraphicsitem_p.h" +#include "qgraphicsscene_p.h" + +#include + +#include + +QGraphicsSceneBspTreeIndex::QGraphicsSceneBspTreeIndex(QGraphicsScene *scene) + : QGraphicsSceneIndex(scene), + bspTreeDepth(0), + indexTimerId(0), + restartIndexTimer(false), + regenerateIndex(true), + lastItemCount(0), + purgePending(false) +{ + +} + +void QGraphicsSceneBspTreeIndex::setRect(const QRectF &rect) +{ + m_sceneRect = rect; + resetIndex(); +} + +QRectF QGraphicsSceneBspTreeIndex::rect() const +{ + const_cast(this)->updateIndex(); + return m_sceneRect; +} + +void QGraphicsSceneBspTreeIndex::clear() +{ + bsp.clear(); + lastItemCount = 0; + freeItemIndexes.clear(); + m_indexedItems.clear(); + unindexedItems.clear(); +} + +void QGraphicsSceneBspTreeIndex::insertItem(QGraphicsItem *item) +{ + // Prevent reusing a recently deleted pointer: purge all removed items + // from our lists. + purgeRemovedItems(); + + // Indexing requires sceneBoundingRect(), but because \a item might + // not be completely constructed at this point, we need to store it in + // a temporary list and schedule an indexing for later. + unindexedItems << item; + item->d_func()->index = -1; + startIndexTimer(); +} + +/*! + \internal +*/ +void QGraphicsSceneBspTreeIndex::addToIndex(QGraphicsItem *item) +{ + if (item->d_func()->index != -1) { + bsp.insertItem(item, item->sceneBoundingRect()); + foreach (QGraphicsItem *child, item->children()) + child->addToIndex(); + } else { + // The BSP tree is regenerated if the number of items grows to a + // certain threshold, or if the bounding rect of the graph doubles in + // size. + startIndexTimer(); + } +} + +void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item, bool itemIsAboutToDie) +{ + if (!itemIsAboutToDie) { + // Note: This will access item's sceneBoundingRect(), which (as this is + // C++) is why we cannot call removeItem() from QGraphicsItem's + // destructor. + removeFromIndex(item); + + // Remove from our item lists. + int index = item->d_func()->index; + if (index != -1) { + freeItemIndexes << index; + m_indexedItems[index] = 0; + } else { + unindexedItems.removeAll(item); + } + + } else { + int index = item->d_func()->index; + if (index != -1) { + // Important: The index is useless until purgeRemovedItems() is + // called. + m_indexedItems[index] = (QGraphicsItem *)0; + if (!purgePending) { + purgePending = true; + scene()->update(); + } + removedItems << item; + } else { + // Recently added items are purged immediately. unindexedItems() never + // contains stale items. + unindexedItems.removeAll(item); + scene()->update(); + } + } +} +/*! + \internal +*/ +void QGraphicsSceneBspTreeIndex::removeFromIndex(QGraphicsItem *item) +{ + if (item->d_func()->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { + // ### remove from child index only if applicable + return; + } + int index = item->d_func()->index; + if (index != -1) { + bsp.removeItem(item, item->sceneBoundingRect()); + freeItemIndexes << index; + m_indexedItems[index] = 0; + item->d_func()->index = -1; + unindexedItems << item; + + //prepareGeometryChange will call updateItem + foreach (QGraphicsItem *child, item->children()) + child->prepareGeometryChange(); + } + startIndexTimer(); +} + +void QGraphicsSceneBspTreeIndex::updateItem(QGraphicsItem *item) +{ + // Note: This will access item's sceneBoundingRect(), which (as this is + // C++) is why we cannot call removeItem() from QGraphicsItem's + // destructor. + removeFromIndex(item); +} + +QList QGraphicsSceneBspTreeIndex::items(const QPointF &point) +{ + purgeRemovedItems(); + QList rectItems = bsp.items(QRectF(point, QSizeF(1, 1))); + // Fill in with any unindexed items + for (int i = 0; i < unindexedItems.size(); ++i) { + if (QGraphicsItem *item = unindexedItems.at(i)) { + if (!item->d_ptr->itemDiscovered && item->d_ptr->visible && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { + QRectF boundingRect = item->sceneBoundingRect(); + if (boundingRect.intersects(QRectF(point, QSizeF(1, 1)))) { + item->d_ptr->itemDiscovered = 1; + rectItems << item; + } + } + } + } + + // Reset the discovered state of all discovered items + for (int i = 0; i < rectItems.size(); ++i) + rectItems.at(i)->d_func()->itemDiscovered = 0; + + return rectItems; +} + +QList QGraphicsSceneBspTreeIndex::items(const QRectF &rect) +{ + purgeRemovedItems(); + QList rectItems = bsp.items(rect); + // Fill in with any unindexed items + for (int i = 0; i < unindexedItems.size(); ++i) { + if (QGraphicsItem *item = unindexedItems.at(i)) { + if (!item->d_ptr->itemDiscovered && item->d_ptr->visible && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { + QRectF boundingRect = item->sceneBoundingRect(); + if (boundingRect.intersects(rect)) { + item->d_ptr->itemDiscovered = 1; + rectItems << item; + } + } + } + } + + // Reset the discovered state of all discovered items + for (int i = 0; i < rectItems.size(); ++i) + rectItems.at(i)->d_func()->itemDiscovered = 0; + + return rectItems; +} + +QList QGraphicsSceneBspTreeIndex::indexedItems() +{ + purgeRemovedItems(); + // If freeItemIndexes is empty, we know there are no holes in indexedItems and + // unindexedItems. + if (freeItemIndexes.isEmpty()) { + if (unindexedItems.isEmpty()) + return m_indexedItems; + return m_indexedItems + unindexedItems; + } + + // Rebuild the list of items to avoid holes. ### We could also just + // compress the item lists at this point. + QList itemList; + foreach (QGraphicsItem *item, m_indexedItems + unindexedItems) { + if (item) + itemList << item; + } + return itemList; +} + +void QGraphicsSceneBspTreeIndex::updateIndex() +{ + _q_updateIndex(); +} + +int QGraphicsSceneBspTreeIndex::bspDepth() +{ + return bspTreeDepth; +} + +void QGraphicsSceneBspTreeIndex::setBspDepth(int depth) +{ + bspTreeDepth = depth; + resetIndex(); +} + +bool QGraphicsSceneBspTreeIndex::event(QEvent *event) +{ + switch (event->type()) { + case QEvent::Timer: + if (indexTimerId && static_cast(event)->timerId() == indexTimerId) { + if (restartIndexTimer) { + restartIndexTimer = false; + } else { + // this call will kill the timer + _q_updateIndex(); + } + } + // Fallthrough intended - support timers in subclasses. + default: + return QObject::event(event); + } + return true; +} + +static inline int intmaxlog(int n) +{ + return (n > 0 ? qMax(qCeil(qLn(qreal(n)) / qLn(qreal(2))), 5) : 0); +} + +/*! + \internal +*/ +void QGraphicsSceneBspTreeIndex::_q_updateIndex() +{ + if (!indexTimerId) + return; + + killTimer(indexTimerId); + indexTimerId = 0; + + purgeRemovedItems(); + + // Add unindexedItems to indexedItems + QRectF unindexedItemsBoundingRect; + for (int i = 0; i < unindexedItems.size(); ++i) { + if (QGraphicsItem *item = unindexedItems.at(i)) { + unindexedItemsBoundingRect |= item->sceneBoundingRect(); + if (!freeItemIndexes.isEmpty()) { + int freeIndex = freeItemIndexes.takeFirst(); + item->d_func()->index = freeIndex; + m_indexedItems[freeIndex] = item; + } else { + item->d_func()->index = m_indexedItems.size(); + m_indexedItems << item; + } + } + } + + // Update growing scene rect. + QRectF oldGrowingItemsBoundingRect = scene()->d_func()->growingItemsBoundingRect; + scene()->d_func()->growingItemsBoundingRect |= unindexedItemsBoundingRect; + + // Determine whether we should regenerate the BSP tree. + if (bspTreeDepth == 0) { + int oldDepth = intmaxlog(lastItemCount); + bspTreeDepth = intmaxlog(m_indexedItems.size()); + static const int slack = 100; + if (bsp.leafCount() == 0 || (oldDepth != bspTreeDepth && qAbs(lastItemCount - m_indexedItems.size()) > slack)) { + // ### Crude algorithm. + regenerateIndex = true; + } + } + + // Regenerate the tree. + if (regenerateIndex) { + regenerateIndex = false; + bsp.initialize(scene()->sceneRect(), bspTreeDepth); + unindexedItems = m_indexedItems; + lastItemCount = m_indexedItems.size(); + scene()->update(); + + // Take this opportunity to reset our largest-item counter for + // untransformable items. When the items are inserted into the BSP + // tree, we'll get an accurate calculation. + scene()->d_func()->largestUntransformableItem = QRectF(); + } + + // Insert all unindexed items into the tree. + for (int i = 0; i < unindexedItems.size(); ++i) { + if (QGraphicsItem *item = unindexedItems.at(i)) { + QRectF rect = item->sceneBoundingRect(); + if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) + continue; + + bsp.insertItem(item,rect); + + // If the item ignores view transformations, update our + // largest-item-counter to ensure that the view can accurately + // discover untransformable items when drawing. + if (item->d_ptr->itemIsUntransformable()) { + QGraphicsItem *topmostUntransformable = item; + while (topmostUntransformable && (topmostUntransformable->d_ptr->ancestorFlags + & QGraphicsItemPrivate::AncestorIgnoresTransformations)) { + topmostUntransformable = topmostUntransformable->parentItem(); + } + // ### Verify that this is the correct largest untransformable rectangle. + scene()->d_func()->largestUntransformableItem |= item->mapToItem(topmostUntransformable, item->boundingRect()).boundingRect(); + } + } + } + unindexedItems.clear(); + + // Notify scene rect changes. + if (!scene()->d_func()->hasSceneRect && scene()->d_func()->growingItemsBoundingRect != oldGrowingItemsBoundingRect) + emit scene()->sceneRectChanged(scene()->d_func()->growingItemsBoundingRect); +} + + +/*! + \internal + + Removes stale pointers from all data structures. +*/ +void QGraphicsSceneBspTreeIndex::purgeRemovedItems() +{ + if (!purgePending && removedItems.isEmpty()) + return; + + // Remove stale items from the BSP tree. + bsp.removeItems(removedItems.toSet()); + // Purge this list. + removedItems.clear(); + freeItemIndexes.clear(); + for (int i = 0; i < m_indexedItems.size(); ++i) { + if (!m_indexedItems.at(i)) + freeItemIndexes << i; + } + purgePending = false; + + // No locality info for the items; update the whole scene. + scene()->update(); +} + +/*! + \internal + + Starts or restarts the timer used for reindexing unindexed items. +*/ +void QGraphicsSceneBspTreeIndex::startIndexTimer() +{ + if (indexTimerId) { + restartIndexTimer = true; + } else { + indexTimerId = startTimer(QGRAPHICSSCENE_INDEXTIMER_TIMEOUT); + } +} + +/*! + \internal +*/ +void QGraphicsSceneBspTreeIndex::resetIndex() +{ + purgeRemovedItems(); + for (int i = 0; i < m_indexedItems.size(); ++i) { + if (QGraphicsItem *item = m_indexedItems.at(i)) { + item->d_ptr->index = -1; + unindexedItems << item; + } + } + m_indexedItems.clear(); + freeItemIndexes.clear(); + regenerateIndex = true; + startIndexTimer(); +} diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h new file mode 100644 index 0000000..74af910 --- /dev/null +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#ifndef QGRAPHICSBSPTREEINDEX_H +#define QGRAPHICSBSPTREEINDEX_H + +#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW + +QT_BEGIN_NAMESPACE + +#include +#include +#include +#include +#include + +#include "qgraphicsscene_bsp_p.h" + +class Q_AUTOTEST_EXPORT QGraphicsSceneBspTreeIndex : public QGraphicsSceneIndex +{ + Q_OBJECT +public: + QGraphicsSceneBspTreeIndex(QGraphicsScene *scene = 0); + + void setRect(const QRectF &rect); + virtual QRectF rect() const; + + void clear(); + + void insertItem(QGraphicsItem *item); + void removeItem(QGraphicsItem *item, bool itemIsAboutToDie); + void updateItem(QGraphicsItem *item); + + QList items(const QPointF &point); + QList items(const QRectF &rect); + + QList indexedItems(); + + void updateIndex(); + + int bspDepth(); + void setBspDepth(int depth); + +protected: + bool event(QEvent *event); + +public slots : + void _q_updateIndex(); + +private : + QGraphicsSceneBspTree bsp; + QRectF m_sceneRect; + int bspTreeDepth; + int indexTimerId; + bool restartIndexTimer; + bool regenerateIndex; + int lastItemCount; + + QList m_indexedItems; + QList unindexedItems; + QList freeItemIndexes; + + bool purgePending; + QList removedItems; + void purgeRemovedItems(); + + void startIndexTimer(); + void resetIndex(); + + void addToIndex(QGraphicsItem *item); + void removeFromIndex(QGraphicsItem *item); +}; + +QT_END_NAMESPACE + +#endif // QT_NO_GRAPHICSVIEW + +#endif // QGRAPHICSBSPTREEINDEX_H diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 904e0af..7360bed 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE /*! Constructs an abstract scene index. */ -QGraphicsSceneIndex::QGraphicsSceneIndex(QObject *parent): QObject(parent) +QGraphicsSceneIndex::QGraphicsSceneIndex(QGraphicsScene *scene): QObject(scene), m_scene(scene) { } @@ -108,7 +108,7 @@ QGraphicsSceneIndex::~QGraphicsSceneIndex() */ QGraphicsScene* QGraphicsSceneIndex::scene() { - return mscene; + return m_scene; } /*! @@ -121,7 +121,7 @@ QGraphicsScene* QGraphicsSceneIndex::scene() */ void QGraphicsSceneIndex::updateItem(QGraphicsItem *item) { - removeItem(item); + removeItem(item,false); insertItem(item); } @@ -145,10 +145,10 @@ void QGraphicsSceneIndex::insertItems(const QList &items) \sa removeItem(), removeItems(), updateItems() */ -void QGraphicsSceneIndex::removeItems(const QList &items) +void QGraphicsSceneIndex::removeItems(const QList &items, bool itemsAreAboutToDie) { foreach (QGraphicsItem *item, items) - removeItem(item); + removeItem(item,itemsAreAboutToDie); } /*! @@ -164,6 +164,10 @@ void QGraphicsSceneIndex::updateItems(const QList &items) updateItem(item); } +void QGraphicsSceneIndex::updateIndex() +{ +} + QT_END_NAMESPACE #include "moc_qgraphicssceneindex.cpp" diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index d3b6c9f..3b034d4 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -64,27 +64,32 @@ class Q_GUI_EXPORT QGraphicsSceneIndex: public QObject Q_OBJECT public: - QGraphicsSceneIndex(QObject *parent = 0); + QGraphicsSceneIndex(QGraphicsScene *scene = 0); virtual ~QGraphicsSceneIndex(); + QGraphicsScene* scene(); + virtual void setRect(const QRectF &rect) = 0; virtual QRectF rect() const = 0; virtual void clear() = 0; virtual void insertItem(QGraphicsItem *item) = 0; - virtual void removeItem(QGraphicsItem *item) = 0; + virtual void removeItem(QGraphicsItem *items, bool itemIsAboutToDie) = 0; virtual void updateItem(QGraphicsItem *item); virtual void insertItems(const QList &items); - virtual void removeItems(const QList &items); + virtual void removeItems(const QList &items, bool itemsAreAboutToDie); virtual void updateItems(const QList &items); virtual QList items(const QPointF &point) = 0; virtual QList items(const QRectF &rect) = 0; - QGraphicsScene* scene(); + virtual QList indexedItems() = 0; + + virtual void updateIndex(); - QGraphicsScene* mscene; +private: + QGraphicsScene *m_scene; }; #endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h new file mode 100644 index 0000000..30948d9 --- /dev/null +++ b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSCENELINEARINDEX_P_H +#define QGRAPHICSSCENELINEARINDEX_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex +{ + Q_OBJECT + +private: + QRectF m_sceneRect; + QList m_items; + +public: + QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0): QGraphicsSceneIndex(scene) + { + } + + virtual void setRect(const QRectF &rect) { + m_sceneRect = rect; + } + + virtual QRectF rect() const { + return m_sceneRect; + } + + virtual void clear() { + m_items.clear(); + } + + virtual void insertItem(QGraphicsItem *item) { + m_items << item; + } + + virtual void removeItem(QGraphicsItem *item, bool itemIsAboutToDie) { + Q_UNUSED(itemIsAboutToDie); + m_items.removeAll(item); + } + + virtual QList items(const QPointF &point) { + QList result; + foreach (QGraphicsItem *item, m_items) + if (item->sceneBoundingRect().contains(point)) + result << item; + return result; + } + + virtual QList items(const QRectF &rect) { + QList result; + foreach (QGraphicsItem *item, m_items) + if (item->sceneBoundingRect().intersects(rect)) + result << item; + return result; + } + + QList indexedItems() { + return m_items; + } +}; + +QT_END_NAMESPACE + +#endif // QT_NO_GRAPHICSVIEW + +#endif // QGRAPHICSSCENELINEARINDEX_P_H diff --git a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp index 955f2d3..3dca152 100644 --- a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -43,8 +43,8 @@ #include #include #include -#include -#include +#include +#include //TESTED_CLASS= @@ -88,12 +88,12 @@ void tst_QGraphicsSceneIndex::common_data() QGraphicsSceneIndex *tst_QGraphicsSceneIndex::createIndex(const QString &indexMethod) { QGraphicsSceneIndex *index = 0; - + QGraphicsScene *scene = new QGraphicsScene(); if (indexMethod == "bsp") - index = new QGraphicsSceneBspTree; + index = new QGraphicsSceneBspTreeIndex(scene); if (indexMethod == "linear") - index = new QGraphicsSceneLinearIndex; + index = new QGraphicsSceneLinearIndex(scene); return index; } @@ -104,8 +104,9 @@ void tst_QGraphicsSceneIndex::sceneRect_data() } void tst_QGraphicsSceneIndex::sceneRect() -{ - QGraphicsSceneIndex *index = new QGraphicsSceneBspTree; +{ + QGraphicsScene *scene = new QGraphicsScene(); + QGraphicsSceneIndex *index = new QGraphicsSceneBspTreeIndex(scene); index->setRect(QRectF(0, 0, 2000, 2000)); QCOMPARE(index->rect(), QRectF(0, 0, 2000, 2000)); } -- cgit v0.12 From 7d39e871e679be8afc10c7109a5cc396ead886f7 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Tue, 5 May 2009 17:56:43 +0200 Subject: Fix deletion of indexed items, and fix comments. It was not a good idea to delete all items in the middle of the loop when clearing the scene since we change the content of indexedItems by deleting one of them. We need to store first all top level items in a temporary list and then delete them in one shot (that will delete their children as well). --- src/gui/graphicsview/qgraphicsscene.cpp | 9 +++++---- tests/auto/qgraphicslayout/tst_qgraphicslayout.cpp | 1 - 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index e9fad68..f2e5f57 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -2549,13 +2549,16 @@ void QGraphicsScene::clearSelection() void QGraphicsScene::clear() { Q_D(QGraphicsScene); + QList items; // Recursive descent delete for (int i = 0; i < d->index->indexedItems().size(); ++i) { if (QGraphicsItem *item = d->index->indexedItems().at(i)) { if (!item->parentItem()) - delete item; + items << item; } } + //We delete all top level items + qDeleteAll(items); d->lastItemCount = 0; d->index->clear(); d->largestUntransformableItem = QRectF(); @@ -2693,9 +2696,7 @@ void QGraphicsScene::addItem(QGraphicsItem *item) // Add the item to this scene item->d_func()->scene = targetScene; - // Indexing requires sceneBoundingRect(), but because \a item might - // not be completely constructed at this point, we need to store it in - // a temporary list and schedule an indexing for later. + // Add the item in the index d->index->insertItem(item); // Add to list of toplevels if this item is a toplevel. diff --git a/tests/auto/qgraphicslayout/tst_qgraphicslayout.cpp b/tests/auto/qgraphicslayout/tst_qgraphicslayout.cpp index f2a6bfd..617790c 100644 --- a/tests/auto/qgraphicslayout/tst_qgraphicslayout.cpp +++ b/tests/auto/qgraphicslayout/tst_qgraphicslayout.cpp @@ -687,7 +687,6 @@ void tst_QGraphicsLayout::ownership() delete top; //don't crash after that. } - } QTEST_MAIN(tst_QGraphicsLayout) -- cgit v0.12 From 560ca373e4879f335a0ceeb3f8a769cc0e4297fe Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Wed, 6 May 2009 10:16:51 +0200 Subject: Make const when it needs to be. --- src/gui/graphicsview/qgraphicssceneindex.cpp | 4 ++-- src/gui/graphicsview/qgraphicssceneindex.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 7360bed..86a2fbb 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -104,9 +104,9 @@ QGraphicsSceneIndex::~QGraphicsSceneIndex() */ /*! - Returns the scene of this scene index. + Returns the scene of this index. */ -QGraphicsScene* QGraphicsSceneIndex::scene() +QGraphicsScene* QGraphicsSceneIndex::scene() const { return m_scene; } diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index 3b034d4..a782323 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -67,7 +67,7 @@ public: QGraphicsSceneIndex(QGraphicsScene *scene = 0); virtual ~QGraphicsSceneIndex(); - QGraphicsScene* scene(); + QGraphicsScene* scene() const; virtual void setRect(const QRectF &rect) = 0; virtual QRectF rect() const = 0; -- cgit v0.12 From 9281f4c219cec2e6a1e24b43e1edd0feb0fcfce5 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Fri, 29 May 2009 14:45:35 +0200 Subject: First bunch of changes after an very first API review This basically move some logic from the scene to the index base class. Lot of work need to be done in order to benefits from the device transform. The sorting needs to be move in the BSP tree. --- src/gui/graphicsview/graphicsview.pri | 1 + src/gui/graphicsview/qgraphicsitem.cpp | 17 +- src/gui/graphicsview/qgraphicsitem.h | 4 + src/gui/graphicsview/qgraphicsscene.cpp | 618 +++------------------ src/gui/graphicsview/qgraphicsscene.h | 9 + src/gui/graphicsview/qgraphicsscene_bsp.cpp | 12 +- src/gui/graphicsview/qgraphicsscene_bsp_p.h | 8 +- src/gui/graphicsview/qgraphicsscene_p.h | 88 ++- .../graphicsview/qgraphicsscenebsptreeindex_p.cpp | 120 ++-- .../graphicsview/qgraphicsscenebsptreeindex_p.h | 18 +- src/gui/graphicsview/qgraphicssceneindex.cpp | 558 +++++++++++++++++-- src/gui/graphicsview/qgraphicssceneindex.h | 50 +- src/gui/graphicsview/qgraphicssceneindex_p.h | 96 ++++ src/gui/graphicsview/qgraphicsscenelinearindex_p.h | 17 +- src/gui/graphicsview/qgraphicsview.cpp | 21 +- 15 files changed, 857 insertions(+), 780 deletions(-) create mode 100644 src/gui/graphicsview/qgraphicssceneindex_p.h diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri index 9097497..cc57892 100644 --- a/src/gui/graphicsview/graphicsview.pri +++ b/src/gui/graphicsview/graphicsview.pri @@ -10,6 +10,7 @@ HEADERS += \ graphicsview/qgraphicsscene_bsp_p.h \ graphicsview/qgraphicsscenelinearindex_p.h \ graphicsview/qgraphicssceneindex.h \ + graphicsview/qgraphicssceneindex_p.h \ graphicsview/qgraphicssceneevent.h \ graphicsview/qgraphicsview_p.h \ graphicsview/qgraphicsview.h diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index c1d44d3..fc5895c 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -567,17 +567,6 @@ QT_BEGIN_NAMESPACE -// QRectF::intersects() returns false always if either the source or target -// rectangle's width or height are 0. This works around that problem. -static inline void _q_adjustRect(QRectF *rect) -{ - Q_ASSERT(rect); - if (!rect->width()) - rect->adjust(-0.00001, 0, 0.00001, 0); - if (!rect->height()) - rect->adjust(0, -0.00001, 0, 0.00001); -} - static inline void _q_adjustRect(QRect *rect) { Q_ASSERT(rect); @@ -6357,7 +6346,7 @@ void QGraphicsItem::addToIndex() return; } if (d_ptr->scene) - d_ptr->scene->d_func()->index->insertItem(this); + d_ptr->scene->d_func()->index->addItem(this); d_ptr->updateHelper(); } @@ -6372,7 +6361,7 @@ void QGraphicsItem::removeFromIndex() { d_ptr->updateHelper(); if (d_ptr->scene) - d_ptr->scene->d_func()->index->removeItem(this,false); + d_ptr->scene->d_func()->index->removeItem(this); } /*! @@ -6393,7 +6382,7 @@ void QGraphicsItem::prepareGeometryChange() if (d_ptr->scene) { d_ptr->updateHelper(QRectF(), false, /*maybeDirtyClipPath=*/!d_ptr->inSetPosHelper); QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func(); - scenePrivate->index->updateItem(this); + scenePrivate->index->prepareBoundingRectChange(this); } if (d_ptr->inSetPosHelper) diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index cb86020..e244c13 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -409,6 +409,8 @@ protected: virtual void setExtension(Extension extension, const QVariant &variant); virtual QVariant extension(const QVariant &variant) const; + bool operator<(const QGraphicsItem *other) const; + protected: QGraphicsItem(QGraphicsItemPrivate &dd, QGraphicsItem *parent, QGraphicsScene *scene); @@ -430,6 +432,8 @@ private: friend class QGraphicsWidget; friend class QGraphicsWidgetPrivate; friend class QGraphicsProxyWidgetPrivate; + friend class QGraphicsSceneIndex; + friend class QGraphicsSceneIndexPrivate; friend class QGraphicsSceneBspTreeIndex; friend class ::tst_QGraphicsItem; friend bool qt_closestLeaf(const QGraphicsItem *, const QGraphicsItem *); diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 51c8294..9b6d40b 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -249,65 +249,6 @@ QT_BEGIN_NAMESPACE -static inline bool QRectF_intersects(const QRectF &s, const QRectF &r) -{ - qreal xp = s.left(); - qreal yp = s.top(); - qreal w = s.width(); - qreal h = s.height(); - qreal l1 = xp; - qreal r1 = xp; - if (w < 0) - l1 += w; - else - r1 += w; - - qreal l2 = r.left(); - qreal r2 = r.left(); - if (w < 0) - l2 += r.width(); - else - r2 += r.width(); - - if (l1 >= r2 || l2 >= r1) - return false; - - qreal t1 = yp; - qreal b1 = yp; - if (h < 0) - t1 += h; - else - b1 += h; - - qreal t2 = r.top(); - qreal b2 = r.top(); - if (r.height() < 0) - t2 += r.height(); - else - b2 += r.height(); - - return !(t1 >= b2 || t2 >= b1); -} - -// QRectF::intersects() returns false always if either the source or target -// rectangle's width or height are 0. This works around that problem. -static inline void _q_adjustRect(QRectF *rect) -{ - Q_ASSERT(rect); - if (!rect->width()) - rect->adjust(-0.00001, 0, 0.00001, 0); - if (!rect->height()) - rect->adjust(0, -0.00001, 0, 0.00001); -} - -static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item) -{ - Q_ASSERT(item); - QRectF boundingRect(item->boundingRect()); - _q_adjustRect(&boundingRect); - return boundingRect; -} - static void _q_hoverFromMouseEvent(QGraphicsSceneHoverEvent *hover, const QGraphicsSceneMouseEvent *mouseEvent) { hover->setWidget(mouseEvent->widget()); @@ -374,21 +315,6 @@ void QGraphicsScenePrivate::init() /*! \internal */ -QList QGraphicsScenePrivate::estimateItemsInRect(const QRectF &rect) const -{ - const_cast(this)->_q_updateSortCache(); - - // ### Only do this once in a while. - QGraphicsScenePrivate *that = const_cast(this); - - // Get items from index - return that->index->items(rect); - -} - -/*! - \internal -*/ void QGraphicsScenePrivate::_q_emitUpdated() { Q_Q(QGraphicsScene); @@ -528,7 +454,7 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item) item->clearFocus(); //We ask for a removing in the index - this->index->removeItem(item, true); + this->index->deleteItem(item); // Reset the mouse grabber and focus item data. if (item == focusItem) @@ -1145,444 +1071,6 @@ QGraphicsWidget *QGraphicsScenePrivate::windowForItem(const QGraphicsItem *item) return 0; } - -QList QGraphicsScenePrivate::items_helper(const QPointF &pos) const -{ - QList items; - - // The index returns a rough estimate of what items are inside the rect. - // Refine it by iterating through all returned items. - QRectF adjustedRect = QRectF(pos, QSize(1,1)); - foreach (QGraphicsItem *item, estimateItemsInRect(adjustedRect)) { - // Find the item's scene transform in a clever way. - QTransform x = item->sceneTransform(); - bool keep = false; - - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - // Rect intersects/contains item's shape - if (QRectF_intersects(adjustedRect, x.mapRect(br))) { - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) { - if (item->contains(xinv.map(pos))) { - items << item; - keep = true; - } - } - } - - if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) { - // Recurse into children that clip children. - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) - childItems_helper(&items, item, xinv.map(pos)); - } - } - - sortItems(&items, Qt::AscendingOrder, sortCacheEnabled); - return items; -} - -QList QGraphicsScenePrivate::items_helper(const QRectF &rect, - Qt::ItemSelectionMode mode, - Qt::SortOrder order) const -{ - QList items; - - QPainterPath path; - - // The index returns a rough estimate of what items are inside the rect. - // Refine it by iterating through all returned items. - QRectF adjustedRect(rect); - _q_adjustRect(&adjustedRect); - foreach (QGraphicsItem *item, estimateItemsInRect(adjustedRect)) { - // Find the item's scene transform in a clever way. - QTransform x = item->sceneTransform(); - bool keep = false; - - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - if (mode >= Qt::ContainsItemBoundingRect) { - // Rect intersects/contains item's bounding rect - QRectF mbr = x.mapRect(br); - if ((mode == Qt::IntersectsItemBoundingRect && QRectF_intersects(rect, mbr)) - || (mode == Qt::ContainsItemBoundingRect && rect != mbr && rect.contains(mbr))) { - items << item; - keep = true; - } - } else { - // Rect intersects/contains item's shape - if (QRectF_intersects(adjustedRect, x.mapRect(br))) { - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) { - if (path.isEmpty()) - path.addRect(rect); - if (itemCollidesWithPath(item, xinv.map(path), mode)) { - items << item; - keep = true; - } - } - } - } - - if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) { - // Recurse into children that clip children. - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) { - if (x.type() <= QTransform::TxScale) { - // Rect - childItems_helper(&items, item, xinv.mapRect(rect), mode); - } else { - // Polygon - childItems_helper(&items, item, xinv.map(rect), mode); - } - } - } - } - - if (order != Qt::SortOrder(-1)) - sortItems(&items, order, sortCacheEnabled); - return items; -} - -QList QGraphicsScenePrivate::items_helper(const QPolygonF &polygon, - Qt::ItemSelectionMode mode, - Qt::SortOrder order) const -{ - QList items; - - QRectF polyRect(polygon.boundingRect()); - _q_adjustRect(&polyRect); - QPainterPath path; - - // The index returns a rough estimate of what items are inside the rect. - // Refine it by iterating through all returned items. - foreach (QGraphicsItem *item, estimateItemsInRect(polyRect)) { - // Find the item's scene transform in a clever way. - QTransform x = item->sceneTransform(); - bool keep = false; - - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - if (mode >= Qt::ContainsItemBoundingRect) { - // Polygon contains/intersects item's bounding rect - if (path == QPainterPath()) - path.addPolygon(polygon); - if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(x.mapRect(br))) - || (mode == Qt::ContainsItemBoundingRect && path.contains(x.mapRect(br)))) { - items << item; - keep = true; - } - } else { - // Polygon contains/intersects item's shape - if (QRectF_intersects(polyRect, x.mapRect(br))) { - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) { - if (path == QPainterPath()) - path.addPolygon(polygon); - if (itemCollidesWithPath(item, xinv.map(path), mode)) { - items << item; - keep = true; - } - } - } - } - - if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) { - // Recurse into children that clip children. - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) - childItems_helper(&items, item, xinv.map(polygon), mode); - } - } - - if (order != Qt::SortOrder(-1)) - sortItems(&items, order, sortCacheEnabled); - return items; -} - -QList QGraphicsScenePrivate::items_helper(const QPainterPath &path, - Qt::ItemSelectionMode mode, - Qt::SortOrder order) const -{ - QList items; - QRectF pathRect(path.controlPointRect()); - _q_adjustRect(&pathRect); - - // The index returns a rough estimate of what items are inside the rect. - // Refine it by iterating through all returned items. - foreach (QGraphicsItem *item, estimateItemsInRect(pathRect)) { - // Find the item's scene transform in a clever way. - QTransform x = item->sceneTransform(); - bool keep = false; - - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - if (mode >= Qt::ContainsItemBoundingRect) { - // Path contains/intersects item's bounding rect - if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(x.mapRect(br))) - || (mode == Qt::ContainsItemBoundingRect && path.contains(x.mapRect(br)))) { - items << item; - keep = true; - } - } else { - // Path contains/intersects item's shape - if (QRectF_intersects(pathRect, x.mapRect(br))) { - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) { - if (itemCollidesWithPath(item, xinv.map(path), mode)) { - items << item; - keep = true; - } - } - } - } - - if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) { - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) - childItems_helper(&items, item, xinv.map(path), mode); - } - } - - if (order != Qt::SortOrder(-1)) - sortItems(&items, order, sortCacheEnabled); - return items; -} - -void QGraphicsScenePrivate::childItems_helper(QList *items, - const QGraphicsItem *parent, - const QPointF &pos) const -{ - bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); - if (parentClip && parent->d_ptr->isClippedAway()) - return; - // ### is this needed? - if (parentClip && !parent->boundingRect().contains(pos)) - return; - - QList &children = parent->d_ptr->children; - for (int i = 0; i < children.size(); ++i) { - QGraphicsItem *item = children.at(i); - if (item->d_ptr->hasTransform && !item->transform().isInvertible()) - continue; - - // Skip invisible items and all their children. - if (item->d_ptr->isInvisible()) - continue; - - bool keep = false; - if (!item->d_ptr->isClippedAway()) { - if (item->contains(item->mapFromParent(pos))) { - items->append(item); - keep = true; - } - } - - if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) - // Recurse into children. - childItems_helper(items, item, item->mapFromParent(pos)); - } -} - - -void QGraphicsScenePrivate::childItems_helper(QList *items, - const QGraphicsItem *parent, - const QRectF &rect, - Qt::ItemSelectionMode mode) const -{ - bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); - if (parentClip && parent->d_ptr->isClippedAway()) - return; - QRectF adjustedRect(rect); - _q_adjustRect(&adjustedRect); - QRectF r = !parentClip ? adjustedRect : adjustedRect.intersected(adjustedItemBoundingRect(parent)); - if (r.isEmpty()) - return; - - QPainterPath path; - QList &children = parent->d_ptr->children; - for (int i = 0; i < children.size(); ++i) { - QGraphicsItem *item = children.at(i); - if (item->d_ptr->hasTransform && !item->transform().isInvertible()) - continue; - - // Skip invisible items and all their children. - if (item->d_ptr->isInvisible()) - continue; - - bool keep = false; - if (!item->d_ptr->isClippedAway()) { - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - QRectF mbr = item->mapRectToParent(br); - if (mode >= Qt::ContainsItemBoundingRect) { - // Rect intersects/contains item's bounding rect - if ((mode == Qt::IntersectsItemBoundingRect && QRectF_intersects(rect, mbr)) - || (mode == Qt::ContainsItemBoundingRect && rect != mbr && rect.contains(br))) { - items->append(item); - keep = true; - } - } else { - // Rect intersects/contains item's shape - if (QRectF_intersects(rect, mbr)) { - if (path == QPainterPath()) - path.addRect(rect); - if (itemCollidesWithPath(item, item->mapFromParent(path), mode)) { - items->append(item); - keep = true; - } - } - } - } - - if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) { - // Recurse into children. - if (!item->d_ptr->hasTransform || item->transform().type() <= QTransform::TxScale) { - // Rect - childItems_helper(items, item, item->mapRectFromParent(rect), mode); - } else { - // Polygon - childItems_helper(items, item, item->mapFromParent(rect), mode); - } - } - } -} - - -void QGraphicsScenePrivate::childItems_helper(QList *items, - const QGraphicsItem *parent, - const QPolygonF &polygon, - Qt::ItemSelectionMode mode) const -{ - bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); - if (parentClip && parent->d_ptr->isClippedAway()) - return; - QRectF polyRect(polygon.boundingRect()); - _q_adjustRect(&polyRect); - QRectF r = !parentClip ? polyRect : polyRect.intersected(adjustedItemBoundingRect(parent)); - if (r.isEmpty()) - return; - - QPainterPath path; - QList &children = parent->d_ptr->children; - for (int i = 0; i < children.size(); ++i) { - QGraphicsItem *item = children.at(i); - if (item->d_ptr->hasTransform && !item->transform().isInvertible()) - continue; - - // Skip invisible items. - if (item->d_ptr->isInvisible()) - continue; - - bool keep = false; - if (!item->d_ptr->isClippedAway()) { - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - if (mode >= Qt::ContainsItemBoundingRect) { - // Polygon contains/intersects item's bounding rect - if (path == QPainterPath()) - path.addPolygon(polygon); - if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br))) - || (mode == Qt::ContainsItemBoundingRect && path.contains(item->mapRectToParent(br)))) { - items->append(item); - keep = true; - } - } else { - // Polygon contains/intersects item's shape - if (QRectF_intersects(polyRect, item->mapRectToParent(br))) { - if (path == QPainterPath()) - path.addPolygon(polygon); - if (itemCollidesWithPath(item, item->mapFromParent(path), mode)) { - items->append(item); - keep = true; - } - } - } - } - - if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) { - // Recurse into children that clip children. - childItems_helper(items, item, item->mapFromParent(polygon), mode); - } - } -} - -void QGraphicsScenePrivate::childItems_helper(QList *items, - const QGraphicsItem *parent, - const QPainterPath &path, - Qt::ItemSelectionMode mode) const -{ - bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); - if (parentClip && parent->d_ptr->isClippedAway()) - return; - QRectF pathRect(path.boundingRect()); - _q_adjustRect(&pathRect); - QRectF r = !parentClip ? pathRect : pathRect.intersected(adjustedItemBoundingRect(parent)); - if (r.isEmpty()) - return; - - QList &children = parent->d_ptr->children; - for (int i = 0; i < children.size(); ++i) { - QGraphicsItem *item = children.at(i); - if (item->d_ptr->hasTransform && !item->transform().isInvertible()) - continue; - - // Skip invisible items. - if (item->d_ptr->isInvisible()) - continue; - - bool keep = false; - if (!item->d_ptr->isClippedAway()) { - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - if (mode >= Qt::ContainsItemBoundingRect) { - // Polygon contains/intersects item's bounding rect - if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br))) - || (mode == Qt::ContainsItemBoundingRect && path.contains(item->mapRectToParent(br)))) { - items->append(item); - keep = true; - } - } else { - // Path contains/intersects item's shape - if (QRectF_intersects(pathRect, item->mapRectToParent(br))) { - if (itemCollidesWithPath(item, item->mapFromParent(path), mode)) { - items->append(item); - keep = true; - } - } - } - } - - if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) { - // Recurse into children that clip children. - childItems_helper(items, item, item->mapFromParent(path), mode); - } - } -} - void QGraphicsScenePrivate::invalidateSortCache() { Q_Q(QGraphicsScene); @@ -1709,7 +1197,8 @@ void QGraphicsScenePrivate::climbTree(QGraphicsItem *item, int *stackingOrder) void QGraphicsScenePrivate::_q_updateSortCache() { - index->updateIndex(); + //### FIXME + //index->updateIndex(); if (!sortCacheEnabled || !updatingSortCache) return; @@ -1719,8 +1208,8 @@ void QGraphicsScenePrivate::_q_updateSortCache() QList topLevels; - for (int i = 0; i < index->indexedItems().count(); ++i) { - QGraphicsItem *item = index->indexedItems().at(i); + for (int i = 0; i < index->items().count(); ++i) { + QGraphicsItem *item = index->items().at(i); if (item && item->parentItem() == 0) topLevels << item; } @@ -1933,8 +1422,7 @@ QGraphicsScene::~QGraphicsScene() QRectF QGraphicsScene::sceneRect() const { Q_D(const QGraphicsScene); - d->index->updateIndex(); - return d->hasSceneRect ? d->index->rect() : d->growingItemsBoundingRect; + return d->hasSceneRect ? d->sceneRect : d->growingItemsBoundingRect; } void QGraphicsScene::setSceneRect(const QRectF &rect) { @@ -1942,7 +1430,7 @@ void QGraphicsScene::setSceneRect(const QRectF &rect) if (rect != d->sceneRect) { d->hasSceneRect = !rect.isNull(); d->sceneRect = rect; - d->index->setRect(rect); + d->index->sceneRectChanged(rect); emit sceneRectChanged(rect); } } @@ -2106,9 +1594,11 @@ void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) } if (d->indexMethod == CustomIndex && method == BspTreeIndex) { + //We re-add in the new index all items from the old index QGraphicsSceneIndex *oldIndex = d->index; d->index = new QGraphicsSceneBspTreeIndex(this); - d->index->insertItems(oldIndex->items(oldIndex->rect())); + for (int i = 0 ; i < oldIndex->items().size() ; ++ i) + d->index->addItem(oldIndex->items().at(i)); } if (d->indexMethod == CustomIndex && method == NoIndex) { @@ -2246,7 +1736,7 @@ QRectF QGraphicsScene::itemsBoundingRect() const QList QGraphicsScene::items() const { Q_D(const QGraphicsScene); - return d->index->indexedItems(); + return d->index->items(); } /*! @@ -2259,7 +1749,7 @@ QList QGraphicsScene::items() const QList QGraphicsScene::items(const QPointF &pos) const { Q_D(const QGraphicsScene); - return d->items_helper(pos); + return d->index->items(pos, Qt::IntersectsItemShape, Qt::AscendingOrder); } @@ -2279,7 +1769,7 @@ QList QGraphicsScene::items(const QPointF &pos) const QList QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode) const { Q_D(const QGraphicsScene); - return d->items_helper(rect, mode, Qt::AscendingOrder); + return d->index->items(rect, mode, Qt::AscendingOrder); } /*! @@ -2303,7 +1793,7 @@ QList QGraphicsScene::items(const QRectF &rect, Qt::ItemSelecti QList QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode) const { Q_D(const QGraphicsScene); - return d->items_helper(polygon, mode, Qt::AscendingOrder); + return d->index->items(polygon, mode, Qt::AscendingOrder); } /*! @@ -2320,7 +1810,74 @@ QList QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemS QList QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const { Q_D(const QGraphicsScene); - return d->items_helper(path, mode, Qt::AscendingOrder); + return d->index->items(path, mode, Qt::AscendingOrder); +} + +/*! + Returns all visible items at position \a pos in the scene. + + The default value for \a mode is Qt::IntersectsItemShape; all items whose + exact shape intersects with or is contained by \a path are returned. + + \sa itemAt() +*/ +QList QGraphicsScene::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +{ + Q_D(const QGraphicsScene); + return d->index->items(pos, mode, order, deviceTransform); +} + +/*! + \fn QList QGraphicsScene::items(const QRectF &rectangle, Qt::SortOrder order, const QTransform &deviceTransform) const + + \overload + + Returns all visible items that, depending on \a mode, are either inside or + intersect with the specified \a rectangle. + + The default value for \a mode is Qt::IntersectsItemShape; all items whose + exact shape intersects with or is contained by \a rectangle are returned. + + \sa itemAt() +*/ +QList QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +{ + Q_D(const QGraphicsScene); + return d->index->items(rect, mode, order, deviceTransform); +} + +/*! + \overload + + Returns all visible items that, depending on \a mode, are either inside or + intersect with the polygon \a polygon. + + The default value for \a mode is Qt::IntersectsItemShape; all items whose + exact shape intersects with or is contained by \a polygon are returned. + + \sa itemAt() +*/ +QList QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +{ + Q_D(const QGraphicsScene); + return d->index->items(polygon, mode, order, deviceTransform); +} + +/*! + \overload + + Returns all visible items that, depending on \a path, are either inside or + intersect with the path \a path. + + The default value for \a mode is Qt::IntersectsItemShape; all items whose + exact shape intersects with or is contained by \a path are returned. + + \sa itemAt() +*/ +QList QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +{ + Q_D(const QGraphicsScene); + return d->index->items(path, mode, order, deviceTransform); } /*! @@ -2344,10 +1901,11 @@ QList QGraphicsScene::collidingItems(const QGraphicsItem *item, } QList tmp; - foreach (QGraphicsItem *itemInVicinity, d->estimateItemsInRect(item->sceneBoundingRect())) { + foreach (QGraphicsItem *itemInVicinity, d->index->estimateItems(item->sceneBoundingRect(), Qt::AscendingOrder, QTransform())) { if (item != itemInVicinity && item->collidesWithItem(itemInVicinity, mode)) tmp << itemInVicinity; } + //### remove me d->sortItems(&tmp, Qt::AscendingOrder, d->sortCacheEnabled); return tmp; } @@ -2517,8 +2075,8 @@ void QGraphicsScene::clear() Q_D(QGraphicsScene); QList items; // Recursive descent delete - for (int i = 0; i < d->index->indexedItems().size(); ++i) { - if (QGraphicsItem *item = d->index->indexedItems().at(i)) { + for (int i = 0; i < d->index->items().size(); ++i) { + if (QGraphicsItem *item = d->index->items().at(i)) { if (!item->parentItem()) items << item; } @@ -2663,7 +2221,7 @@ void QGraphicsScene::addItem(QGraphicsItem *item) item->d_func()->scene = targetScene; // Add the item in the index - d->index->insertItem(item); + d->index->addItem(item); // Add to list of toplevels if this item is a toplevel. if (!item->d_ptr->parent) @@ -3023,7 +2581,7 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) // Note: This will access item's sceneBoundingRect(), which (as this is // C++) is why we cannot call removeItem() from QGraphicsItem's // destructor. - d->index->removeItem(item, false); + d->index->deleteItem(item); if (item == d->tabFocusFirst) { QGraphicsWidget *widget = static_cast(item); diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h index 6476b8c..5d70087 100644 --- a/src/gui/graphicsview/qgraphicsscene.h +++ b/src/gui/graphicsview/qgraphicsscene.h @@ -156,10 +156,17 @@ public: QRectF itemsBoundingRect() const; QList items() const; + + QList items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + QList items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + QList items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + QList items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + QList items(const QPointF &pos) const; QList items(const QRectF &rect, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; QList items(const QPolygonF &polygon, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; QList items(const QPainterPath &path, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; + QList collidingItems(const QGraphicsItem *item, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; QGraphicsItem *itemAt(const QPointF &pos) const; @@ -291,6 +298,8 @@ private: friend class QGraphicsViewPrivate; friend class QGraphicsWidget; friend class QGraphicsWidgetPrivate; + friend class QGraphicsSceneIndex; + friend class QGraphicsSceneIndexPrivate; friend class QGraphicsSceneBspTreeIndex; }; diff --git a/src/gui/graphicsview/qgraphicsscene_bsp.cpp b/src/gui/graphicsview/qgraphicsscene_bsp.cpp index f8fa450..5c1820f 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp.cpp +++ b/src/gui/graphicsview/qgraphicsscene_bsp.cpp @@ -143,7 +143,7 @@ void QGraphicsSceneBspTree::removeItems(const QSet &items) } } -QList QGraphicsSceneBspTree::items(const QRectF &rect) +QList QGraphicsSceneBspTree::items(const QRectF &rect) const { QList tmp; findVisitor->foundItems = &tmp; @@ -151,7 +151,7 @@ QList QGraphicsSceneBspTree::items(const QRectF &rect) return tmp; } -QList QGraphicsSceneBspTree::items(const QPointF &pos) +QList QGraphicsSceneBspTree::items(const QPointF &pos) const { QList tmp; findVisitor->foundItems = &tmp; @@ -235,7 +235,7 @@ void QGraphicsSceneBspTree::initialize(const QRectF &rect, int depth, int index) } } -void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QPointF &pos, int index) +void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QPointF &pos, int index) const { if (nodes.isEmpty()) return; @@ -245,7 +245,7 @@ void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, con switch (node.type) { case Node::Leaf: { - visitor->visit(&leaves[node.leafIndex]); + visitor->visit(const_cast*>(&leaves[node.leafIndex])); break; } case Node::Vertical: @@ -265,7 +265,7 @@ void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, con } } -void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index) +void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index) const { if (nodes.isEmpty()) return; @@ -275,7 +275,7 @@ void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, con switch (node.type) { case Node::Leaf: { - visitor->visit(&leaves[node.leafIndex]); + visitor->visit(const_cast*>(&leaves[node.leafIndex])); break; } case Node::Vertical: diff --git a/src/gui/graphicsview/qgraphicsscene_bsp_p.h b/src/gui/graphicsview/qgraphicsscene_bsp_p.h index e6ceb78..a13d862 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp_p.h +++ b/src/gui/graphicsview/qgraphicsscene_bsp_p.h @@ -92,8 +92,8 @@ public: void removeItem(QGraphicsItem *item, const QRectF &rect); void removeItems(const QSet &items); - QList items(const QRectF &rect); - QList items(const QPointF &pos); + QList items(const QRectF &rect) const; + QList items(const QPointF &pos) const; int leafCount() const; inline int firstChildIndex(int index) const @@ -106,8 +106,8 @@ public: private: void initialize(const QRectF &rect, int depth, int index); - void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QPointF &pos, int index = 0); - void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index = 0); + void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QPointF &pos, int index = 0) const; + void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index = 0) const; void findItems(QList *foundItems, const QRectF &rect, int index); void findItems(QList *foundItems, const QPointF &pos, int index); diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 2c0d464..a035159 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -88,8 +88,6 @@ public: QGraphicsScene::ItemIndexMethod indexMethod; int bspTreeDepth; - QList estimateItemsInRect(const QRectF &rect) const; - int lastItemCount; QGraphicsSceneIndex *index; @@ -189,33 +187,6 @@ public: void sendMouseEvent(QGraphicsSceneMouseEvent *mouseEvent); void mousePressEventHandler(QGraphicsSceneMouseEvent *mouseEvent); QGraphicsWidget *windowForItem(const QGraphicsItem *item) const; - - QList items_helper(const QPointF &pos) const; - QList items_helper(const QRectF &rect, - Qt::ItemSelectionMode mode, - Qt::SortOrder order) const; - QList items_helper(const QPolygonF &rect, - Qt::ItemSelectionMode mode, - Qt::SortOrder order) const; - QList items_helper(const QPainterPath &rect, - Qt::ItemSelectionMode mode, - Qt::SortOrder order) const; - void childItems_helper(QList *items, - const QGraphicsItem *parent, - const QPointF &pos) const; - void childItems_helper(QList *items, - const QGraphicsItem *parent, - const QRectF &rect, - Qt::ItemSelectionMode mode) const; - void childItems_helper(QList *items, - const QGraphicsItem *parent, - const QPolygonF &polygon, - Qt::ItemSelectionMode mode) const; - void childItems_helper(QList *items, - const QGraphicsItem *parent, - const QPainterPath &path, - Qt::ItemSelectionMode mode) const; - bool sortCacheEnabled; bool updatingSortCache; void invalidateSortCache(); @@ -255,6 +226,65 @@ public: mutable QVector freeSceneTransformSlots; }; +static inline bool QRectF_intersects(const QRectF &s, const QRectF &r) +{ + qreal xp = s.left(); + qreal yp = s.top(); + qreal w = s.width(); + qreal h = s.height(); + qreal l1 = xp; + qreal r1 = xp; + if (w < 0) + l1 += w; + else + r1 += w; + + qreal l2 = r.left(); + qreal r2 = r.left(); + if (w < 0) + l2 += r.width(); + else + r2 += r.width(); + + if (l1 >= r2 || l2 >= r1) + return false; + + qreal t1 = yp; + qreal b1 = yp; + if (h < 0) + t1 += h; + else + b1 += h; + + qreal t2 = r.top(); + qreal b2 = r.top(); + if (r.height() < 0) + t2 += r.height(); + else + b2 += r.height(); + + return !(t1 >= b2 || t2 >= b1); +} + +// QRectF::intersects() returns false always if either the source or target +// rectangle's width or height are 0. This works around that problem. +static inline void _q_adjustRect(QRectF *rect) +{ + Q_ASSERT(rect); + if (!rect->width()) + rect->adjust(-0.00001, 0, 0.00001, 0); + if (!rect->height()) + rect->adjust(0, -0.00001, 0, 0.00001); +} + +static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item) +{ + Q_ASSERT(item); + QRectF boundingRect(item->boundingRect()); + _q_adjustRect(&boundingRect); + return boundingRect; +} + QT_END_NAMESPACE #endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp index ebc167a..1f2b81d 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp @@ -61,18 +61,6 @@ QGraphicsSceneBspTreeIndex::QGraphicsSceneBspTreeIndex(QGraphicsScene *scene) } -void QGraphicsSceneBspTreeIndex::setRect(const QRectF &rect) -{ - m_sceneRect = rect; - resetIndex(); -} - -QRectF QGraphicsSceneBspTreeIndex::rect() const -{ - const_cast(this)->updateIndex(); - return m_sceneRect; -} - void QGraphicsSceneBspTreeIndex::clear() { bsp.clear(); @@ -82,7 +70,7 @@ void QGraphicsSceneBspTreeIndex::clear() unindexedItems.clear(); } -void QGraphicsSceneBspTreeIndex::insertItem(QGraphicsItem *item) +void QGraphicsSceneBspTreeIndex::addItem(QGraphicsItem *item) { // Prevent reusing a recently deleted pointer: purge all removed items // from our lists. @@ -113,42 +101,43 @@ void QGraphicsSceneBspTreeIndex::addToIndex(QGraphicsItem *item) } } -void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item, bool itemIsAboutToDie) +void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item) { - if (!itemIsAboutToDie) { - // Note: This will access item's sceneBoundingRect(), which (as this is - // C++) is why we cannot call removeItem() from QGraphicsItem's - // destructor. - removeFromIndex(item); - - // Remove from our item lists. - int index = item->d_func()->index; - if (index != -1) { - freeItemIndexes << index; - m_indexedItems[index] = 0; - } else { - unindexedItems.removeAll(item); - } + // Note: This will access item's sceneBoundingRect(), which (as this is + // C++) is why we cannot call removeItem() from QGraphicsItem's + // destructor. + removeFromIndex(item); + // Remove from our item lists. + int index = item->d_func()->index; + if (index != -1) { + freeItemIndexes << index; + m_indexedItems[index] = 0; } else { - int index = item->d_func()->index; - if (index != -1) { - // Important: The index is useless until purgeRemovedItems() is - // called. - m_indexedItems[index] = (QGraphicsItem *)0; - if (!purgePending) { - purgePending = true; - scene()->update(); - } - removedItems << item; - } else { - // Recently added items are purged immediately. unindexedItems() never - // contains stale items. - unindexedItems.removeAll(item); + unindexedItems.removeAll(item); + } +} + +void QGraphicsSceneBspTreeIndex::deleteItem(QGraphicsItem *item) +{ + int index = item->d_func()->index; + if (index != -1) { + // Important: The index is useless until purgeRemovedItems() is + // called. + m_indexedItems[index] = (QGraphicsItem *)0; + if (!purgePending) { + purgePending = true; scene()->update(); } + removedItems << item; + } else { + // Recently added items are purged immediately. unindexedItems() never + // contains stale items. + unindexedItems.removeAll(item); + scene()->update(); } } + /*! \internal */ @@ -173,41 +162,17 @@ void QGraphicsSceneBspTreeIndex::removeFromIndex(QGraphicsItem *item) startIndexTimer(); } -void QGraphicsSceneBspTreeIndex::updateItem(QGraphicsItem *item) +void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem *item) { // Note: This will access item's sceneBoundingRect(), which (as this is // C++) is why we cannot call removeItem() from QGraphicsItem's // destructor. - removeFromIndex(item); -} - -QList QGraphicsSceneBspTreeIndex::items(const QPointF &point) -{ - purgeRemovedItems(); - QList rectItems = bsp.items(QRectF(point, QSizeF(1, 1))); - // Fill in with any unindexed items - for (int i = 0; i < unindexedItems.size(); ++i) { - if (QGraphicsItem *item = unindexedItems.at(i)) { - if (!item->d_ptr->itemDiscovered && item->d_ptr->visible && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { - QRectF boundingRect = item->sceneBoundingRect(); - if (boundingRect.intersects(QRectF(point, QSizeF(1, 1)))) { - item->d_ptr->itemDiscovered = 1; - rectItems << item; - } - } - } - } - - // Reset the discovered state of all discovered items - for (int i = 0; i < rectItems.size(); ++i) - rectItems.at(i)->d_func()->itemDiscovered = 0; - - return rectItems; + removeFromIndex(const_cast(item)); } -QList QGraphicsSceneBspTreeIndex::items(const QRectF &rect) +QList QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const { - purgeRemovedItems(); + const_cast(this)->purgeRemovedItems(); QList rectItems = bsp.items(rect); // Fill in with any unindexed items for (int i = 0; i < unindexedItems.size(); ++i) { @@ -229,9 +194,9 @@ QList QGraphicsSceneBspTreeIndex::items(const QRectF &rect) return rectItems; } -QList QGraphicsSceneBspTreeIndex::indexedItems() +QList QGraphicsSceneBspTreeIndex::items() const { - purgeRemovedItems(); + const_cast(this)->purgeRemovedItems(); // If freeItemIndexes is empty, we know there are no holes in indexedItems and // unindexedItems. if (freeItemIndexes.isEmpty()) { @@ -250,11 +215,6 @@ QList QGraphicsSceneBspTreeIndex::indexedItems() return itemList; } -void QGraphicsSceneBspTreeIndex::updateIndex() -{ - _q_updateIndex(); -} - int QGraphicsSceneBspTreeIndex::bspDepth() { return bspTreeDepth; @@ -266,6 +226,12 @@ void QGraphicsSceneBspTreeIndex::setBspDepth(int depth) resetIndex(); } +void QGraphicsSceneBspTreeIndex::sceneRectChanged(const QRectF &rect) +{ + m_sceneRect = rect; + resetIndex(); +} + bool QGraphicsSceneBspTreeIndex::event(QEvent *event) { switch (event->type()) { diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index 74af910..63cd0e1 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -62,27 +62,23 @@ class Q_AUTOTEST_EXPORT QGraphicsSceneBspTreeIndex : public QGraphicsSceneIndex public: QGraphicsSceneBspTreeIndex(QGraphicsScene *scene = 0); - void setRect(const QRectF &rect); - virtual QRectF rect() const; - void clear(); - void insertItem(QGraphicsItem *item); - void removeItem(QGraphicsItem *item, bool itemIsAboutToDie); - void updateItem(QGraphicsItem *item); - - QList items(const QPointF &point); - QList items(const QRectF &rect); + void addItem(QGraphicsItem *item); + void removeItem(QGraphicsItem *item); + void deleteItem(QGraphicsItem *item); + void prepareBoundingRectChange(const QGraphicsItem *item); - QList indexedItems(); + QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const; - void updateIndex(); + QList items() const; int bspDepth(); void setBspDepth(int depth); protected: bool event(QEvent *event); + void sceneRectChanged(const QRectF &rect); public slots : void _q_updateIndex(); diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 86a2fbb..870a62a 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -40,16 +40,244 @@ ****************************************************************************/ #include "qgraphicssceneindex.h" +#include "qgraphicssceneindex_p.h" #include "qgraphicsscene.h" +#include "qgraphicsitem_p.h" +#include "qgraphicsscene_p.h" #ifndef QT_NO_GRAPHICSVIEW QT_BEGIN_NAMESPACE /*! + Constructs a private scene index. +*/ +QGraphicsSceneIndexPrivate::QGraphicsSceneIndexPrivate(QGraphicsScene *scene) : scene(scene) +{ +} + +void QGraphicsSceneIndexPrivate::childItems_helper(QList *items, + const QGraphicsItem *parent, + const QPointF &pos) const +{ + bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); + if (parentClip && parent->d_ptr->isClippedAway()) + return; + // ### is this needed? + if (parentClip && !parent->boundingRect().contains(pos)) + return; + + QList &children = parent->d_ptr->children; + for (int i = 0; i < children.size(); ++i) { + QGraphicsItem *item = children.at(i); + if (item->d_ptr->hasTransform && !item->transform().isInvertible()) + continue; + + // Skip invisible items and all their children. + if (item->d_ptr->isInvisible()) + continue; + + bool keep = false; + if (!item->d_ptr->isClippedAway()) { + if (item->contains(item->mapFromParent(pos))) { + items->append(item); + keep = true; + } + } + + if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) + // Recurse into children. + childItems_helper(items, item, item->mapFromParent(pos)); + } +} + + +void QGraphicsSceneIndexPrivate::childItems_helper(QList *items, + const QGraphicsItem *parent, + const QRectF &rect, + Qt::ItemSelectionMode mode) const +{ + bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); + if (parentClip && parent->d_ptr->isClippedAway()) + return; + QRectF adjustedRect(rect); + _q_adjustRect(&adjustedRect); + QRectF r = !parentClip ? adjustedRect : adjustedRect.intersected(adjustedItemBoundingRect(parent)); + if (r.isEmpty()) + return; + + QPainterPath path; + QList &children = parent->d_ptr->children; + for (int i = 0; i < children.size(); ++i) { + QGraphicsItem *item = children.at(i); + if (item->d_ptr->hasTransform && !item->transform().isInvertible()) + continue; + + // Skip invisible items and all their children. + if (item->d_ptr->isInvisible()) + continue; + + bool keep = false; + if (!item->d_ptr->isClippedAway()) { + // ### _q_adjustedRect is only needed because QRectF::intersects, + // QRectF::contains and QTransform::map() and friends don't work with + // flat rectangles. + const QRectF br(adjustedItemBoundingRect(item)); + QRectF mbr = item->mapRectToParent(br); + if (mode >= Qt::ContainsItemBoundingRect) { + // Rect intersects/contains item's bounding rect + if ((mode == Qt::IntersectsItemBoundingRect && QRectF_intersects(rect, mbr)) + || (mode == Qt::ContainsItemBoundingRect && rect != mbr && rect.contains(br))) { + items->append(item); + keep = true; + } + } else { + // Rect intersects/contains item's shape + if (QRectF_intersects(rect, mbr)) { + if (path == QPainterPath()) + path.addRect(rect); + if (scene->d_func()->itemCollidesWithPath(item, item->mapFromParent(path), mode)) { + items->append(item); + keep = true; + } + } + } + } + + if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) { + // Recurse into children. + if (!item->d_ptr->hasTransform || item->transform().type() <= QTransform::TxScale) { + // Rect + childItems_helper(items, item, item->mapRectFromParent(rect), mode); + } else { + // Polygon + childItems_helper(items, item, item->mapFromParent(rect), mode); + } + } + } +} + + +void QGraphicsSceneIndexPrivate::childItems_helper(QList *items, + const QGraphicsItem *parent, + const QPolygonF &polygon, + Qt::ItemSelectionMode mode) const +{ + bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); + if (parentClip && parent->d_ptr->isClippedAway()) + return; + QRectF polyRect(polygon.boundingRect()); + _q_adjustRect(&polyRect); + QRectF r = !parentClip ? polyRect : polyRect.intersected(adjustedItemBoundingRect(parent)); + if (r.isEmpty()) + return; + + QPainterPath path; + QList &children = parent->d_ptr->children; + for (int i = 0; i < children.size(); ++i) { + QGraphicsItem *item = children.at(i); + if (item->d_ptr->hasTransform && !item->transform().isInvertible()) + continue; + + // Skip invisible items. + if (item->d_ptr->isInvisible()) + continue; + + bool keep = false; + if (!item->d_ptr->isClippedAway()) { + // ### _q_adjustedRect is only needed because QRectF::intersects, + // QRectF::contains and QTransform::map() and friends don't work with + // flat rectangles. + const QRectF br(adjustedItemBoundingRect(item)); + if (mode >= Qt::ContainsItemBoundingRect) { + // Polygon contains/intersects item's bounding rect + if (path == QPainterPath()) + path.addPolygon(polygon); + if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br))) + || (mode == Qt::ContainsItemBoundingRect && path.contains(item->mapRectToParent(br)))) { + items->append(item); + keep = true; + } + } else { + // Polygon contains/intersects item's shape + if (QRectF_intersects(polyRect, item->mapRectToParent(br))) { + if (path == QPainterPath()) + path.addPolygon(polygon); + if (scene->d_func()->itemCollidesWithPath(item, item->mapFromParent(path), mode)) { + items->append(item); + keep = true; + } + } + } + } + + if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) { + // Recurse into children that clip children. + childItems_helper(items, item, item->mapFromParent(polygon), mode); + } + } +} + +void QGraphicsSceneIndexPrivate::childItems_helper(QList *items, + const QGraphicsItem *parent, + const QPainterPath &path, + Qt::ItemSelectionMode mode) const +{ + bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); + if (parentClip && parent->d_ptr->isClippedAway()) + return; + QRectF pathRect(path.boundingRect()); + _q_adjustRect(&pathRect); + QRectF r = !parentClip ? pathRect : pathRect.intersected(adjustedItemBoundingRect(parent)); + if (r.isEmpty()) + return; + + QList &children = parent->d_ptr->children; + for (int i = 0; i < children.size(); ++i) { + QGraphicsItem *item = children.at(i); + if (item->d_ptr->hasTransform && !item->transform().isInvertible()) + continue; + + // Skip invisible items. + if (item->d_ptr->isInvisible()) + continue; + + bool keep = false; + if (!item->d_ptr->isClippedAway()) { + // ### _q_adjustedRect is only needed because QRectF::intersects, + // QRectF::contains and QTransform::map() and friends don't work with + // flat rectangles. + const QRectF br(adjustedItemBoundingRect(item)); + if (mode >= Qt::ContainsItemBoundingRect) { + // Polygon contains/intersects item's bounding rect + if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br))) + || (mode == Qt::ContainsItemBoundingRect && path.contains(item->mapRectToParent(br)))) { + items->append(item); + keep = true; + } + } else { + // Path contains/intersects item's shape + if (QRectF_intersects(pathRect, item->mapRectToParent(br))) { + if (scene->d_func()->itemCollidesWithPath(item, item->mapFromParent(path), mode)) { + items->append(item); + keep = true; + } + } + } + } + + if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) { + // Recurse into children that clip children. + childItems_helper(items, item, item->mapFromParent(path), mode); + } + } +} + +/*! Constructs an abstract scene index. */ -QGraphicsSceneIndex::QGraphicsSceneIndex(QGraphicsScene *scene): QObject(scene), m_scene(scene) +QGraphicsSceneIndex::QGraphicsSceneIndex(QGraphicsScene *scene) +: QObject(*new QGraphicsSceneIndexPrivate(scene)) { } @@ -62,109 +290,325 @@ QGraphicsSceneIndex::~QGraphicsSceneIndex() } /*! - \fn virtual void setRect(const QRectF &rect) = 0 - - This pure virtual function is called when the scene changes its bounding - rectangle. - - \sa rect(), QGraphicsScene::setSceneRect + Returns the scene of this index. */ - +QGraphicsScene* QGraphicsSceneIndex::scene() const +{ + Q_D(const QGraphicsSceneIndex); + return d->scene; +} /*! - \fn virtual QRectF rect() const = 0 + \fn QList items() const = 0 - This pure virtual function returns the bounding rectangle of this - scene index. It could be as large as or larger than the scene - bounding rectangle, depending on the implementation of the - scene index. + This pure virtual function return the list of items that are actually in the index. - \sa setRect(), QGraphicsScene::sceneRect */ -/*! - \fn virtual void clear() = 0 +QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +{ + Q_D(const QGraphicsSceneIndex); + QList items; + + // The index returns a rough estimate of what items are inside the rect. + // Refine it by iterating through all returned items. + QRectF adjustedRect = QRectF(pos, QSize(1,1)); + foreach (QGraphicsItem *item, estimateItems(adjustedRect, order, deviceTransform)) { + // Find the item's scene transform in a clever way. + QTransform x = item->sceneTransform(); + bool keep = false; + + // ### _q_adjustedRect is only needed because QRectF::intersects, + // QRectF::contains and QTransform::map() and friends don't work with + // flat rectangles. + const QRectF br(adjustedItemBoundingRect(item)); + // Rect intersects/contains item's shape + if (QRectF_intersects(adjustedRect, x.mapRect(br))) { + bool ok; + QTransform xinv = x.inverted(&ok); + if (ok) { + if (item->contains(xinv.map(pos))) { + items << item; + keep = true; + } + } + } + + if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) { + // Recurse into children that clip children. + bool ok; + QTransform xinv = x.inverted(&ok); + if (ok) + d->childItems_helper(&items, item, xinv.map(pos)); + } + } + + d->scene->d_func()->sortItems(&items, Qt::AscendingOrder, d->scene->d_func()->sortCacheEnabled); + return items; +} - This pure virtual function removes all items in the scene index. -*/ +QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +{ + Q_D(const QGraphicsSceneIndex); + QList items; + + QPainterPath path; + + // The index returns a rough estimate of what items are inside the rect. + // Refine it by iterating through all returned items. + QRectF adjustedRect(rect); + _q_adjustRect(&adjustedRect); + foreach (QGraphicsItem *item, estimateItems(adjustedRect, order, deviceTransform)) { + // Find the item's scene transform in a clever way. + QTransform x = item->sceneTransform(); + bool keep = false; + + // ### _q_adjustedRect is only needed because QRectF::intersects, + // QRectF::contains and QTransform::map() and friends don't work with + // flat rectangles. + const QRectF br(adjustedItemBoundingRect(item)); + if (mode >= Qt::ContainsItemBoundingRect) { + // Rect intersects/contains item's bounding rect + QRectF mbr = x.mapRect(br); + if ((mode == Qt::IntersectsItemBoundingRect && QRectF_intersects(rect, mbr)) + || (mode == Qt::ContainsItemBoundingRect && rect != mbr && rect.contains(mbr))) { + items << item; + keep = true; + } + } else { + // Rect intersects/contains item's shape + if (QRectF_intersects(adjustedRect, x.mapRect(br))) { + bool ok; + QTransform xinv = x.inverted(&ok); + if (ok) { + if (path.isEmpty()) + path.addRect(rect); + if (d->scene->d_func()->itemCollidesWithPath(item, xinv.map(path), mode)) { + items << item; + keep = true; + } + } + } + } + + if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) { + // Recurse into children that clip children. + bool ok; + QTransform xinv = x.inverted(&ok); + if (ok) { + if (x.type() <= QTransform::TxScale) { + // Rect + d->childItems_helper(&items, item, xinv.mapRect(rect), mode); + } else { + // Polygon + d->childItems_helper(&items, item, xinv.map(rect), mode); + } + } + } + } + + if (order != Qt::SortOrder(-1)) + d->scene->d_func()->sortItems(&items, order, d->scene->d_func()->sortCacheEnabled); + return items; +} -/*! - \fn virtual void insertItem(QGraphicsItem *item) = 0 +QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +{ + Q_D(const QGraphicsSceneIndex); + QList items; + + QRectF polyRect(polygon.boundingRect()); + _q_adjustRect(&polyRect); + QPainterPath path; + + // The index returns a rough estimate of what items are inside the rect. + // Refine it by iterating through all returned items. + foreach (QGraphicsItem *item, estimateItems(polyRect, order, deviceTransform)) { + // Find the item's scene transform in a clever way. + QTransform x = item->sceneTransform(); + bool keep = false; + + // ### _q_adjustedRect is only needed because QRectF::intersects, + // QRectF::contains and QTransform::map() and friends don't work with + // flat rectangles. + const QRectF br(adjustedItemBoundingRect(item)); + if (mode >= Qt::ContainsItemBoundingRect) { + // Polygon contains/intersects item's bounding rect + if (path == QPainterPath()) + path.addPolygon(polygon); + if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(x.mapRect(br))) + || (mode == Qt::ContainsItemBoundingRect && path.contains(x.mapRect(br)))) { + items << item; + keep = true; + } + } else { + // Polygon contains/intersects item's shape + if (QRectF_intersects(polyRect, x.mapRect(br))) { + bool ok; + QTransform xinv = x.inverted(&ok); + if (ok) { + if (path == QPainterPath()) + path.addPolygon(polygon); + if (d->scene->d_func()->itemCollidesWithPath(item, xinv.map(path), mode)) { + items << item; + keep = true; + } + } + } + } + + if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) { + // Recurse into children that clip children. + bool ok; + QTransform xinv = x.inverted(&ok); + if (ok) + d->childItems_helper(&items, item, xinv.map(polygon), mode); + } + } + + if (order != Qt::SortOrder(-1)) + d->scene->d_func()->sortItems(&items, order, d->scene->d_func()->sortCacheEnabled); + return items; +} +QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +{ + Q_D(const QGraphicsSceneIndex); + QList items; + QRectF pathRect(path.controlPointRect()); + _q_adjustRect(&pathRect); + + // The index returns a rough estimate of what items are inside the rect. + // Refine it by iterating through all returned items. + foreach (QGraphicsItem *item, estimateItems(pathRect, order, deviceTransform)) { + // Find the item's scene transform in a clever way. + QTransform x = item->sceneTransform(); + bool keep = false; + + // ### _q_adjustedRect is only needed because QRectF::intersects, + // QRectF::contains and QTransform::map() and friends don't work with + // flat rectangles. + const QRectF br(adjustedItemBoundingRect(item)); + if (mode >= Qt::ContainsItemBoundingRect) { + // Path contains/intersects item's bounding rect + if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(x.mapRect(br))) + || (mode == Qt::ContainsItemBoundingRect && path.contains(x.mapRect(br)))) { + items << item; + keep = true; + } + } else { + // Path contains/intersects item's shape + if (QRectF_intersects(pathRect, x.mapRect(br))) { + bool ok; + QTransform xinv = x.inverted(&ok); + if (ok) { + if (d->scene->d_func()->itemCollidesWithPath(item, xinv.map(path), mode)) { + items << item; + keep = true; + } + } + } + } + + if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) { + bool ok; + QTransform xinv = x.inverted(&ok); + if (ok) + d->childItems_helper(&items, item, xinv.map(path), mode); + } + } + + if (order != Qt::SortOrder(-1)) + d->scene->d_func()->sortItems(&items, order, d->scene->d_func()->sortCacheEnabled); + return items; +} - This pure virtual function inserts an item to the scene index. +/*! + This pure virtual function return an estimation of items at position \a pos. - \sa removeItem(), updateItem(), insertItems() */ +QList QGraphicsSceneIndex::estimateItems(const QPointF &point, Qt::SortOrder order, const QTransform &deviceTransform) const +{ + return estimateItems(QRectF(point, QSize(1,1)), order, deviceTransform); +} /*! - \fn virtual void removeItem(QGraphicsItem *item) = 0 + \fn virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const = 0 - This pure virtual function removes an item to the scene index. + This pure virtual function return an estimation of items in the \a rect. - \sa insertItem(), updateItem(), removeItems() */ + /*! - Returns the scene of this index. + This virtual function removes all items in the scene index. */ -QGraphicsScene* QGraphicsSceneIndex::scene() const +void QGraphicsSceneIndex::clear() { - return m_scene; + for (int i = 0 ; i < items().size(); ++i) + removeItem(items().at(i)); } /*! - Updates an item when its geometry has changed. + \fn virtual void addItem(QGraphicsItem *item) = 0 - The default implemention will remove the item from the index - and then insert it again. + This pure virtual function inserts an item to the scene index. - \sa insertItem(), removeItem(), updateItems() + \sa removeItem(), deleteItem() */ -void QGraphicsSceneIndex::updateItem(QGraphicsItem *item) -{ - removeItem(item,false); - insertItem(item); -} /*! - Inserts a list of items to the index. + \fn virtual void removeItem(QGraphicsItem *item) = 0 - The default implemention will insert the items one by one. + This pure virtual function removes an item to the scene index. - \sa insertItem(), removeItems(), updateItems() + \sa addItem(), deleteItem() */ -void QGraphicsSceneIndex::insertItems(const QList &items) + +/*! + This method is called when an item has been deleted. + The default implementation call removeItem. Be carefull, + if your implementation of removeItem use pure virtual method + of QGraphicsItem like boundingRect(), then you should reimplement + this method. + + \sa addItem(), removeItem() +*/ +void QGraphicsSceneIndex::deleteItem(QGraphicsItem *item) { - foreach (QGraphicsItem *item, items) - insertItem(item); + removeItem(item); } /*! - Removes a list of items from the index. + This virtual function is called by QGraphicsItem to notify the index + that some part of the item's state changes. By reimplementing this + function, your can react to a change, and in some cases, (depending on \a + change,) adjustments in the index can be made. - The default implemention will remove the items one by one. + \a change is the parameter of the item that is changing. \a value is the + value that changed; the type of the value depends on \a change. - \sa removeItem(), removeItems(), updateItems() + The default implementation does nothing. + + \sa GraphicsItemChange */ -void QGraphicsSceneIndex::removeItems(const QList &items, bool itemsAreAboutToDie) +void QGraphicsSceneIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const QVariant &value) { - foreach (QGraphicsItem *item, items) - removeItem(item,itemsAreAboutToDie); } /*! - Update a list of items which have changed the geometry. - - The default implemention will update the items one by one. + Notify the index for a geometry change of an item. - \sa updateItem(), insertItems(), removeItems() + \sa QGraphicsItem::prepareGeometryChange */ -void QGraphicsSceneIndex::updateItems(const QList &items) +void QGraphicsSceneIndex::prepareBoundingRectChange(const QGraphicsItem *item) { - foreach (QGraphicsItem *item, items) - updateItem(item); } -void QGraphicsSceneIndex::updateIndex() +/*! + This virtual function is called when the scene changes its bounding + rectangle. + \sa QGraphicsScene::sceneRect +*/ +void QGraphicsSceneIndex::sceneRectChanged(const QRectF &rect) { } diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index a782323..da3096e 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -44,6 +44,8 @@ #include #include +#include +#include QT_BEGIN_HEADER @@ -53,7 +55,7 @@ QT_MODULE(Gui) #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW -class QGraphicsItem; +class QGraphicsSceneIndexPrivate; class QGraphicsScene; class QRectF; class QPointF; @@ -67,29 +69,31 @@ public: QGraphicsSceneIndex(QGraphicsScene *scene = 0); virtual ~QGraphicsSceneIndex(); - QGraphicsScene* scene() const; - - virtual void setRect(const QRectF &rect) = 0; - virtual QRectF rect() const = 0; - virtual void clear() = 0; - - virtual void insertItem(QGraphicsItem *item) = 0; - virtual void removeItem(QGraphicsItem *items, bool itemIsAboutToDie) = 0; - virtual void updateItem(QGraphicsItem *item); - - virtual void insertItems(const QList &items); - virtual void removeItems(const QList &items, bool itemsAreAboutToDie); - virtual void updateItems(const QList &items); - - virtual QList items(const QPointF &point) = 0; - virtual QList items(const QRectF &rect) = 0; - - virtual QList indexedItems() = 0; - - virtual void updateIndex(); - + QGraphicsScene *scene() const; + + virtual QList items() const = 0; + virtual QList items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + virtual QList items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + virtual QList items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + virtual QList items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + virtual QList estimateItems(const QPointF &point, Qt::SortOrder order, const QTransform &deviceTransform) const; + virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const = 0; + +protected: + virtual void clear(); + virtual void addItem(QGraphicsItem *item) = 0; + virtual void removeItem(QGraphicsItem *item) = 0; + virtual void deleteItem(QGraphicsItem *item); + + virtual void itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const QVariant &value); + virtual void prepareBoundingRectChange(const QGraphicsItem *item); + virtual void sceneRectChanged(const QRectF &rect); + + friend class QGraphicsScene; + friend class QGraphicsScenePrivate; + friend class QGraphicsItem; private: - QGraphicsScene *m_scene; + Q_DECLARE_PRIVATE(QGraphicsSceneIndex) }; #endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h new file mode 100644 index 0000000..f2cdca3 --- /dev/null +++ b/src/gui/graphicsview/qgraphicssceneindex_p.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSCENEINDEX_P_H +#define QGRAPHICSSCENEINDEX_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + +#include "qgraphicssceneindex.h" + +#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW + +#include + +QT_BEGIN_NAMESPACE + +class QGraphicsScene; + +class QGraphicsSceneIndexPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsSceneIndex) +public: + QGraphicsSceneIndexPrivate(QGraphicsScene *scene); + + + void childItems_helper(QList *items, + const QGraphicsItem *parent, + const QPointF &pos) const; + void childItems_helper(QList *items, + const QGraphicsItem *parent, + const QRectF &rect, + Qt::ItemSelectionMode mode) const; + void childItems_helper(QList *items, + const QGraphicsItem *parent, + const QPolygonF &polygon, + Qt::ItemSelectionMode mode) const; + void childItems_helper(QList *items, + const QGraphicsItem *parent, + const QPainterPath &path, + Qt::ItemSelectionMode mode) const; + + QGraphicsScene *scene; +}; + +QT_END_NAMESPACE + +#endif // QGRAPHICSSCENEINDEX_P_H + +#endif diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h index 30948d9..dc45a17 100644 --- a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h @@ -89,24 +89,15 @@ public: m_items.clear(); } - virtual void insertItem(QGraphicsItem *item) { + virtual void addItem(QGraphicsItem *item) { m_items << item; } - virtual void removeItem(QGraphicsItem *item, bool itemIsAboutToDie) { - Q_UNUSED(itemIsAboutToDie); + virtual void removeItem(QGraphicsItem *item) { m_items.removeAll(item); } - virtual QList items(const QPointF &point) { - QList result; - foreach (QGraphicsItem *item, m_items) - if (item->sceneBoundingRect().contains(point)) - result << item; - return result; - } - - virtual QList items(const QRectF &rect) { + virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const { QList result; foreach (QGraphicsItem *item, m_items) if (item->sceneBoundingRect().intersects(rect)) @@ -114,7 +105,7 @@ public: return result; } - QList indexedItems() { + QList items() const { return m_items; } }; diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 10b837a..91f97a1 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -791,19 +791,6 @@ QRegion QGraphicsViewPrivate::mapToViewRegion(const QGraphicsItem *item, const Q return item->boundingRegion(itv) & itv.mapRect(rect).toAlignedRect(); } -// QRectF::intersects() returns false always if either the source or target -// rectangle's width or height are 0. This works around that problem. -static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item) -{ - Q_ASSERT(item); - QRectF boundingRect(item->boundingRect()); - if (!boundingRect.width()) - boundingRect.adjust(-0.00001, 0, 0.00001, 0); - if (!boundingRect.height()) - boundingRect.adjust(0, -0.00001, 0, 0.00001); - return boundingRect; -} - /*! \internal */ @@ -1094,7 +1081,7 @@ QList QGraphicsViewPrivate::findItems(const QRegion &exposedReg bool simpleRectLookup = (scene->d_func()->largestUntransformableItem.isNull() && exposedRegion.numRects() == 1 && matrix.type() <= QTransform::TxScale); if (simpleRectLookup) { - return scene->d_func()->items_helper(exposedRegionSceneBounds, + return scene->d_func()->index->items(exposedRegionSceneBounds, Qt::IntersectsItemBoundingRect, Qt::DescendingOrder); } @@ -1109,7 +1096,7 @@ QList QGraphicsViewPrivate::findItems(const QRegion &exposedReg const QPainterPath exposedPath(qt_regionToPath(adjustedRegion)); if (scene->d_func()->largestUntransformableItem.isNull()) { const QPainterPath exposedScenePath(q->mapToScene(exposedPath)); - return scene->d_func()->items_helper(exposedScenePath, + return scene->d_func()->index->items(exposedScenePath, Qt::IntersectsItemBoundingRect, Qt::DescendingOrder); } @@ -2143,7 +2130,7 @@ QList QGraphicsViewPrivate::itemsInArea(const QPainterPath &pat // First build a (potentially large) list of all items in the vicinity // that might be untransformable. - QList allCandidates = scene->d_func()->estimateItemsInRect(adjustedRect); + QList allCandidates = scene->d_func()->index->estimateItems(adjustedRect, order, q->transform()); // Then find the minimal list of items that are inside \a path, and // convert it to a set. @@ -2154,6 +2141,8 @@ QList QGraphicsViewPrivate::itemsInArea(const QPainterPath &pat QList result; + //### this will disapear + // Run through all candidates and keep all items that are in candSet, or // are untransformable and collide with \a path. ### We can improve this // algorithm. -- cgit v0.12 From 32155ed07a6f8b8c831db6ba219395b4825fa9fd Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Fri, 29 May 2009 15:15:58 +0200 Subject: Fix a wrong parenting. --- src/gui/graphicsview/qgraphicssceneindex.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 870a62a..36da295 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -277,7 +277,7 @@ void QGraphicsSceneIndexPrivate::childItems_helper(QList *items Constructs an abstract scene index. */ QGraphicsSceneIndex::QGraphicsSceneIndex(QGraphicsScene *scene) -: QObject(*new QGraphicsSceneIndexPrivate(scene)) +: QObject(*new QGraphicsSceneIndexPrivate(scene), scene) { } -- cgit v0.12 From 53187fabdbfb8a513e735fdd034e1a9fbbccc9cd Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Fri, 29 May 2009 17:18:38 +0200 Subject: Add an API to know the indexed rect of the index. Usefull for the POV of the scene and let the BSP update its internal structure before the next event loop reentrancy. --- src/gui/graphicsview/qgraphicsscene.cpp | 2 +- src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp | 7 +++++++ src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h | 1 + src/gui/graphicsview/qgraphicssceneindex.cpp | 10 ++++++++++ src/gui/graphicsview/qgraphicssceneindex.h | 2 ++ 5 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 9b6d40b..479a548 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1422,7 +1422,7 @@ QGraphicsScene::~QGraphicsScene() QRectF QGraphicsScene::sceneRect() const { Q_D(const QGraphicsScene); - return d->hasSceneRect ? d->sceneRect : d->growingItemsBoundingRect; + return d->index->indexedRect(); } void QGraphicsScene::setSceneRect(const QRectF &rect) { diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp index 1f2b81d..8a26447 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp @@ -61,6 +61,13 @@ QGraphicsSceneBspTreeIndex::QGraphicsSceneBspTreeIndex(QGraphicsScene *scene) } + +QRectF QGraphicsSceneBspTreeIndex::indexedRect() +{ + _q_updateIndex(); + return scene()->d_func()->hasSceneRect ? scene()->d_func()->sceneRect : scene()->d_func()->growingItemsBoundingRect; +} + void QGraphicsSceneBspTreeIndex::clear() { bsp.clear(); diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index 63cd0e1..7a6ea0b 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -61,6 +61,7 @@ class Q_AUTOTEST_EXPORT QGraphicsSceneBspTreeIndex : public QGraphicsSceneIndex Q_OBJECT public: QGraphicsSceneBspTreeIndex(QGraphicsScene *scene = 0); + QRectF indexedRect(); void clear(); diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 36da295..fe3a68a 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -297,6 +297,16 @@ QGraphicsScene* QGraphicsSceneIndex::scene() const Q_D(const QGraphicsSceneIndex); return d->scene; } + +/*! + Returns the indexed area for the index +*/ +QRectF QGraphicsSceneIndex::indexedRect() +{ + Q_D(const QGraphicsSceneIndex); + return d->scene->d_func()->sceneRect; +} + /*! \fn QList items() const = 0 diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index da3096e..11d9aae 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -71,6 +71,8 @@ public: QGraphicsScene *scene() const; + virtual QRectF indexedRect(); + virtual QList items() const = 0; virtual QList items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; virtual QList items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; -- cgit v0.12 From 427c4d6b0a8b3004c86facd382de33c171c0458b Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Tue, 2 Jun 2009 17:45:27 +0200 Subject: Fix all auto-tests regressions. --- src/gui/graphicsview/qgraphicsscene.cpp | 15 +++++++++------ src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp | 11 ++++++----- src/gui/graphicsview/qgraphicssceneindex.cpp | 2 +- tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp | 3 +++ .../auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp | 4 ++-- 5 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 479a548..0172a23 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -453,7 +453,9 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item) // chain. item->clearFocus(); - //We ask for a removing in the index + // Note: This will access item's sceneBoundingRect(), which (as this is + // C++) is why we cannot call removeItem() from QGraphicsItem's + // destructor. this->index->deleteItem(item); // Reset the mouse grabber and focus item data. @@ -1198,7 +1200,10 @@ void QGraphicsScenePrivate::climbTree(QGraphicsItem *item, int *stackingOrder) void QGraphicsScenePrivate::_q_updateSortCache() { //### FIXME - //index->updateIndex(); + QGraphicsSceneBspTreeIndex *tree = qobject_cast(index); + if (tree) { + tree->_q_updateIndex(); + } if (!sortCacheEnabled || !updatingSortCache) return; @@ -2578,10 +2583,8 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) // Clear its background item->update(); - // Note: This will access item's sceneBoundingRect(), which (as this is - // C++) is why we cannot call removeItem() from QGraphicsItem's - // destructor. - d->index->deleteItem(item); + // Remove it from the index properly + d->index->removeItem(item); if (item == d->tabFocusFirst) { QGraphicsWidget *widget = static_cast(item); diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp index 8a26447..f8f1f56 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp @@ -61,11 +61,10 @@ QGraphicsSceneBspTreeIndex::QGraphicsSceneBspTreeIndex(QGraphicsScene *scene) } - QRectF QGraphicsSceneBspTreeIndex::indexedRect() { _q_updateIndex(); - return scene()->d_func()->hasSceneRect ? scene()->d_func()->sceneRect : scene()->d_func()->growingItemsBoundingRect; + return scene()->d_func()->hasSceneRect ? scene()->d_func()->sceneRect : scene()->d_func()->growingItemsBoundingRect; } void QGraphicsSceneBspTreeIndex::clear() @@ -162,7 +161,7 @@ void QGraphicsSceneBspTreeIndex::removeFromIndex(QGraphicsItem *item) item->d_func()->index = -1; unindexedItems << item; - //prepareGeometryChange will call updateItem + //prepareGeometryChange will call prepareBoundingRectChange foreach (QGraphicsItem *child, item->children()) child->prepareGeometryChange(); } @@ -180,13 +179,15 @@ void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem * QList QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const { const_cast(this)->purgeRemovedItems(); + scene()->d_func()->_q_updateSortCache(); + QList rectItems = bsp.items(rect); // Fill in with any unindexed items for (int i = 0; i < unindexedItems.size(); ++i) { if (QGraphicsItem *item = unindexedItems.at(i)) { if (!item->d_ptr->itemDiscovered && item->d_ptr->visible && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { QRectF boundingRect = item->sceneBoundingRect(); - if (boundingRect.intersects(rect)) { + if (QRectF_intersects(boundingRect, rect)) { item->d_ptr->itemDiscovered = 1; rectItems << item; } @@ -328,7 +329,7 @@ void QGraphicsSceneBspTreeIndex::_q_updateIndex() if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) continue; - bsp.insertItem(item,rect); + bsp.insertItem(item, rect); // If the item ignores view transformations, update our // largest-item-counter to ensure that the view can accurately diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index fe3a68a..d0d6081 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -352,7 +352,7 @@ QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSe } } - d->scene->d_func()->sortItems(&items, Qt::AscendingOrder, d->scene->d_func()->sortCacheEnabled); + d->scene->d_func()->sortItems(&items, order, d->scene->d_func()->sortCacheEnabled); return items; } diff --git a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp index 0c5ebf6..eb117ab 100644 --- a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp @@ -395,6 +395,9 @@ void tst_QGraphicsScene::items() QGraphicsLineItem *l2 = scene.addLine(0, -5, 0, 5); QVERIFY(!l1->sceneBoundingRect().intersects(l2->sceneBoundingRect())); QVERIFY(!l2->sceneBoundingRect().intersects(l1->sceneBoundingRect())); + QList items; + items<setRect(QRectF(0, 0, 2000, 2000)); - QCOMPARE(index->rect(), QRectF(0, 0, 2000, 2000)); + scene->setSceneRect(QRectF(0, 0, 2000, 2000)); + QCOMPARE(index->indexedRect(), QRectF(0, 0, 2000, 2000)); } void tst_QGraphicsSceneIndex::customIndex_data() -- cgit v0.12 From ffd6bc0351c96c8a3828bd7376f2b6bda317cd71 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Wed, 3 Jun 2009 18:23:20 +0200 Subject: Remove the sorting cache from the QGraphicsScene and move it to the BSP. Now the QGraphicsScene has no idea how works the index. So we can improve it separatly, add new ones and benchmarks existing ones. --- src/gui/graphicsview/graphicsview.pri | 1 + src/gui/graphicsview/qgraphicsitem.cpp | 22 +- src/gui/graphicsview/qgraphicsitem.h | 1 + src/gui/graphicsview/qgraphicsscene.cpp | 200 +------ src/gui/graphicsview/qgraphicsscene.h | 2 +- src/gui/graphicsview/qgraphicsscene_p.h | 19 - .../graphicsview/qgraphicsscenebsptreeindex_p.cpp | 614 ++++++++++++++------- .../graphicsview/qgraphicsscenebsptreeindex_p.h | 51 +- .../graphicsview/qgraphicsscenebsptreeindex_p_p.h | 140 +++++ src/gui/graphicsview/qgraphicssceneindex.cpp | 28 +- src/gui/graphicsview/qgraphicssceneindex.h | 9 +- src/gui/graphicsview/qgraphicssceneindex_p.h | 3 +- src/gui/graphicsview/qgraphicsscenelinearindex_p.h | 2 +- src/gui/graphicsview/qgraphicsview.cpp | 11 +- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 5 + tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp | 5 +- tests/auto/qgraphicsview/tst_qgraphicsview.cpp | 8 +- 17 files changed, 642 insertions(+), 479 deletions(-) create mode 100644 src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri index cc57892..a4a79e8 100644 --- a/src/gui/graphicsview/graphicsview.pri +++ b/src/gui/graphicsview/graphicsview.pri @@ -7,6 +7,7 @@ HEADERS += \ graphicsview/qgraphicsscene.h \ graphicsview/qgraphicsscene_p.h \ graphicsview/qgraphicsscenebsptreeindex_p.h \ + graphicsview/qgraphicsscenebsptreeindex_p_p.h \ graphicsview/qgraphicsscene_bsp_p.h \ graphicsview/qgraphicsscenelinearindex_p.h \ graphicsview/qgraphicssceneindex.h \ diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index fc5895c..ee32724 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -537,6 +537,7 @@ #include "qgraphicsview.h" #include "qgraphicswidget.h" #include "qgraphicsproxywidget.h" +#include "qgraphicsscenebsptreeindex_p_p.h" #include #include #include @@ -888,12 +889,6 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool de } } - if (scene) { - // Invalidate any sort caching; arrival of a new item means we need to - // resort. - scene->d_func()->invalidateSortCache(); - } - // Resolve opacity. updateEffectiveOpacity(); @@ -905,6 +900,11 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool de // Deliver post-change notification q->itemChange(QGraphicsItem::ItemParentHasChanged, newParentVariant); + + if (scene) { + // Deliver the change to the index + scene->d_func()->index->itemChanged(q, QGraphicsItem::ItemParentHasChanged, newParentVariant); + } } /*! @@ -3528,11 +3528,9 @@ void QGraphicsItem::setZValue(qreal z) d_ptr->z = newZ; d_ptr->fullUpdateHelper(); - if (d_ptr->scene) { - // Invalidate any sort caching; arrival of a new item means we need to - // resort. - d_ptr->scene->d_func()->invalidateSortCache(); - } + //Z Value has changed, we have to notify the index. + if (d_ptr->scene) + d_ptr->scene->d_func()->index->itemChanged(this, ItemZValueChange, z); itemChange(ItemZValueHasChanged, newZVariant); } @@ -3991,7 +3989,7 @@ bool QGraphicsItem::isObscuredBy(const QGraphicsItem *item) const { if (!item) return false; - return QGraphicsScenePrivate::closestItemFirst_withoutCache(item, this) + return QGraphicsSceneBspTreeIndexPrivate::closestItemFirst_withoutCache(item, this) && qt_QGraphicsItem_isObscured(this, item, boundingRect()); } diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index e244c13..7874033 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -435,6 +435,7 @@ private: friend class QGraphicsSceneIndex; friend class QGraphicsSceneIndexPrivate; friend class QGraphicsSceneBspTreeIndex; + friend class QGraphicsSceneBspTreeIndexPrivate; friend class ::tst_QGraphicsItem; friend bool qt_closestLeaf(const QGraphicsItem *, const QGraphicsItem *); friend bool qt_closestItemFirst(const QGraphicsItem *, const QGraphicsItem *); diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 0172a23..4734e74 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -218,6 +218,7 @@ #include "qgraphicswidget.h" #include "qgraphicswidget_p.h" #include "qgraphicssceneindex.h" +#include "qgraphicsscenebsptreeindex_p_p.h" #include #include @@ -291,8 +292,6 @@ QGraphicsScenePrivate::QGraphicsScenePrivate() allItemsIgnoreHoverEvents(true), allItemsUseDefaultCursor(true), painterStateProtection(true), - sortCacheEnabled(false), - updatingSortCache(false), style(0) { } @@ -1073,175 +1072,6 @@ QGraphicsWidget *QGraphicsScenePrivate::windowForItem(const QGraphicsItem *item) return 0; } -void QGraphicsScenePrivate::invalidateSortCache() -{ - Q_Q(QGraphicsScene); - if (!sortCacheEnabled || updatingSortCache) - return; - - updatingSortCache = true; - QMetaObject::invokeMethod(q, "_q_updateSortCache", Qt::QueuedConnection); -} - -/*! - \internal - - Should not be exported, but we can't change that now. - ### Qt 5: Remove symbol / make static -*/ -inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) -{ - // Return true if sibling item1 is on top of item2. - const QGraphicsItemPrivate *d1 = item1->d_ptr; - const QGraphicsItemPrivate *d2 = item2->d_ptr; - bool f1 = d1->flags & QGraphicsItem::ItemStacksBehindParent; - bool f2 = d2->flags & QGraphicsItem::ItemStacksBehindParent; - if (f1 != f2) return f2; - qreal z1 = d1->z; - qreal z2 = d2->z; - return z1 != z2 ? z1 > z2 : d1->siblingIndex > d2->siblingIndex; -} - -/*! - \internal - - Should not be exported, but we can't change that now. -*/ -inline bool qt_closestItemFirst(const QGraphicsItem *item1, const QGraphicsItem *item2) -{ - return QGraphicsScenePrivate::closestItemFirst_withoutCache(item1, item2); -} - -/*! - Returns true if \a item1 is on top of \a item2. - - \internal -*/ -bool QGraphicsScenePrivate::closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2) -{ - // Siblings? Just check their z-values. - const QGraphicsItemPrivate *d1 = item1->d_ptr; - const QGraphicsItemPrivate *d2 = item2->d_ptr; - if (d1->parent == d2->parent) - return qt_closestLeaf(item1, item2); - - // Find common ancestor, and each item's ancestor closest to the common - // ancestor. - int item1Depth = d1->depth; - int item2Depth = d2->depth; - const QGraphicsItem *p = item1; - const QGraphicsItem *t1 = item1; - while (item1Depth > item2Depth && (p = p->d_ptr->parent)) { - if (p == item2) { - // item2 is one of item1's ancestors; item1 is on top - return !(t1->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); - } - t1 = p; - --item1Depth; - } - p = item2; - const QGraphicsItem *t2 = item2; - while (item2Depth > item1Depth && (p = p->d_ptr->parent)) { - if (p == item1) { - // item1 is one of item2's ancestors; item1 is not on top - return (t2->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); - } - t2 = p; - --item2Depth; - } - - // item1Ancestor is now at the same level as item2Ancestor, but not the same. - const QGraphicsItem *a1 = t1; - const QGraphicsItem *a2 = t2; - while (a1) { - const QGraphicsItem *p1 = a1; - const QGraphicsItem *p2 = a2; - a1 = a1->parentItem(); - a2 = a2->parentItem(); - if (a1 && a1 == a2) - return qt_closestLeaf(p1, p2); - } - - // No common ancestor? Then just compare the items' toplevels directly. - return qt_closestLeaf(t1->topLevelItem(), t2->topLevelItem()); -} - -/*! - Returns true if \a item2 is on top of \a item1. - - \internal -*/ -bool QGraphicsScenePrivate::closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2) -{ - return closestItemFirst_withoutCache(item2, item1); -} - -void QGraphicsScenePrivate::climbTree(QGraphicsItem *item, int *stackingOrder) -{ - if (!item->d_ptr->children.isEmpty()) { - QList childList = item->d_ptr->children; - qSort(childList.begin(), childList.end(), qt_closestLeaf); - for (int i = 0; i < childList.size(); ++i) { - QGraphicsItem *item = childList.at(i); - if (!(item->flags() & QGraphicsItem::ItemStacksBehindParent)) - climbTree(childList.at(i), stackingOrder); - } - item->d_ptr->globalStackingOrder = (*stackingOrder)++; - for (int i = 0; i < childList.size(); ++i) { - QGraphicsItem *item = childList.at(i); - if (item->flags() & QGraphicsItem::ItemStacksBehindParent) - climbTree(childList.at(i), stackingOrder); - } - } else { - item->d_ptr->globalStackingOrder = (*stackingOrder)++; - } -} - -void QGraphicsScenePrivate::_q_updateSortCache() -{ - //### FIXME - QGraphicsSceneBspTreeIndex *tree = qobject_cast(index); - if (tree) { - tree->_q_updateIndex(); - } - - if (!sortCacheEnabled || !updatingSortCache) - return; - - updatingSortCache = false; - int stackingOrder = 0; - - QList topLevels; - - for (int i = 0; i < index->items().count(); ++i) { - QGraphicsItem *item = index->items().at(i); - if (item && item->parentItem() == 0) - topLevels << item; - } - - qSort(topLevels.begin(), topLevels.end(), qt_closestLeaf); - for (int i = 0; i < topLevels.size(); ++i) - climbTree(topLevels.at(i), &stackingOrder); -} - -void QGraphicsScenePrivate::sortItems(QList *itemList, Qt::SortOrder order, - bool sortCacheEnabled) -{ - if (sortCacheEnabled) { - if (order == Qt::AscendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemFirst_withCache); - } else if (order == Qt::DescendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemLast_withCache); - } - } else { - if (order == Qt::AscendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemFirst_withoutCache); - } else if (order == Qt::DescendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemLast_withoutCache); - } - } -} - /*! \internal @@ -1707,15 +1537,25 @@ void QGraphicsScene::setBspTreeDepth(int depth) bool QGraphicsScene::isSortCacheEnabled() const { Q_D(const QGraphicsScene); - return d->sortCacheEnabled; + QGraphicsSceneBspTreeIndex *bspTree = qobject_cast(d->index); + if (!bspTree) { + qWarning("QGraphicsScene::isSortCacheEnabled: can not apply if indexing method is not BSP"); + return false; + } + return bspTree->d_func()->sortCacheEnabled; } void QGraphicsScene::setSortCacheEnabled(bool enabled) { Q_D(QGraphicsScene); - if (enabled == d->sortCacheEnabled) + QGraphicsSceneBspTreeIndex *bspTree = qobject_cast(d->index); + if (!bspTree) { + qWarning("QGraphicsScene::isSortCacheEnabled: can not apply if indexing method is not BSP"); return; - if ((d->sortCacheEnabled = enabled)) - d->invalidateSortCache(); + } + if (enabled == bspTree->d_func()->sortCacheEnabled) + return; + if ((bspTree->d_func()->sortCacheEnabled = enabled)) + bspTree->d_func()->invalidateSortCache(); } /*! @@ -1910,8 +1750,6 @@ QList QGraphicsScene::collidingItems(const QGraphicsItem *item, if (item != itemInVicinity && item->collidesWithItem(itemInVicinity, mode)) tmp << itemInVicinity; } - //### remove me - d->sortItems(&tmp, Qt::AscendingOrder, d->sortCacheEnabled); return tmp; } @@ -2211,10 +2049,6 @@ void QGraphicsScene::addItem(QGraphicsItem *item) return; } - // Invalidate any sort caching; arrival of a new item means we need to - // resort. - d->invalidateSortCache(); - // Detach this item from its parent if the parent's scene is different // from this scene. if (QGraphicsItem *itemParent = item->parentItem()) { @@ -2232,10 +2066,6 @@ void QGraphicsScene::addItem(QGraphicsItem *item) if (!item->d_ptr->parent) d->registerTopLevelItem(item); - // Update the scene's sort cache settings. - item->d_ptr->globalStackingOrder = -1; - d->invalidateSortCache(); - // Add to list of items that require an update. We cannot assume that the // item is fully constructed, so calling item->update() can lead to a pure // virtual function call to boundingRect(). diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h index 5d70087..702813c 100644 --- a/src/gui/graphicsview/qgraphicsscene.h +++ b/src/gui/graphicsview/qgraphicsscene.h @@ -290,7 +290,6 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_removeItemLater(QGraphicsItem *item)) Q_PRIVATE_SLOT(d_func(), void _q_updateLater()) Q_PRIVATE_SLOT(d_func(), void _q_polishItems()) - Q_PRIVATE_SLOT(d_func(), void _q_updateSortCache()) Q_PRIVATE_SLOT(d_func(), void _q_resetDirtyItems()) friend class QGraphicsItem; friend class QGraphicsItemPrivate; @@ -301,6 +300,7 @@ private: friend class QGraphicsSceneIndex; friend class QGraphicsSceneIndexPrivate; friend class QGraphicsSceneBspTreeIndex; + friend class QGraphicsSceneBspTreeIndexPrivate; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsScene::SceneLayers) diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index a035159..d2a5cdb 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -187,25 +187,6 @@ public: void sendMouseEvent(QGraphicsSceneMouseEvent *mouseEvent); void mousePressEventHandler(QGraphicsSceneMouseEvent *mouseEvent); QGraphicsWidget *windowForItem(const QGraphicsItem *item) const; - bool sortCacheEnabled; - bool updatingSortCache; - void invalidateSortCache(); - static void climbTree(QGraphicsItem *item, int *stackingOrder); - void _q_updateSortCache(); - - static bool closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2); - static bool closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2); - - static inline bool closestItemFirst_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2) - { - return item1->d_ptr->globalStackingOrder < item2->d_ptr->globalStackingOrder; - } - static inline bool closestItemLast_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2) - { - return item1->d_ptr->globalStackingOrder >= item2->d_ptr->globalStackingOrder; - } - - static void sortItems(QList *itemList, Qt::SortOrder order, bool cached); void drawItemHelper(QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget, diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp index f8f1f56..19aa9d5 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp @@ -39,9 +39,15 @@ ** ****************************************************************************/ + static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; #include "qgraphicsscenebsptreeindex_p.h" + +#ifndef QT_NO_GRAPHICSVIEW + +#include "qgraphicsscenebsptreeindex_p_p.h" +#include "qgraphicssceneindex_p.h" #include "qgraphicsitem_p.h" #include "qgraphicsscene_p.h" @@ -49,51 +55,365 @@ static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; #include -QGraphicsSceneBspTreeIndex::QGraphicsSceneBspTreeIndex(QGraphicsScene *scene) - : QGraphicsSceneIndex(scene), +QT_BEGIN_NAMESPACE + +static inline int intmaxlog(int n) +{ + return (n > 0 ? qMax(qCeil(qLn(qreal(n)) / qLn(qreal(2))), 5) : 0); +} + +/*! + Constructs a private scene index. +*/ +QGraphicsSceneBspTreeIndexPrivate::QGraphicsSceneBspTreeIndexPrivate(QGraphicsScene *scene) + : scene(scene), bspTreeDepth(0), indexTimerId(0), restartIndexTimer(false), regenerateIndex(true), lastItemCount(0), - purgePending(false) + purgePending(false), + sortCacheEnabled(false), + updatingSortCache(false) +{ +} + + +/*! + \internal +*/ +void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() { + Q_Q(QGraphicsSceneBspTreeIndex); + if (!indexTimerId) + return; + QGraphicsScenePrivate * scenePrivate = q->scene()->d_func(); + q->killTimer(indexTimerId); + indexTimerId = 0; + + purgeRemovedItems(); + + // Add unindexedItems to indexedItems + QRectF unindexedItemsBoundingRect; + for (int i = 0; i < unindexedItems.size(); ++i) { + if (QGraphicsItem *item = unindexedItems.at(i)) { + unindexedItemsBoundingRect |= item->sceneBoundingRect(); + if (!freeItemIndexes.isEmpty()) { + int freeIndex = freeItemIndexes.takeFirst(); + item->d_func()->index = freeIndex; + indexedItems[freeIndex] = item; + } else { + item->d_func()->index = indexedItems.size(); + indexedItems << item; + } + } + } + + // Update growing scene rect. + QRectF oldGrowingItemsBoundingRect = scenePrivate->growingItemsBoundingRect; + scenePrivate->growingItemsBoundingRect |= unindexedItemsBoundingRect; + + // Determine whether we should regenerate the BSP tree. + if (bspTreeDepth == 0) { + int oldDepth = intmaxlog(lastItemCount); + bspTreeDepth = intmaxlog(indexedItems.size()); + static const int slack = 100; + if (bsp.leafCount() == 0 || (oldDepth != bspTreeDepth && qAbs(lastItemCount - indexedItems.size()) > slack)) { + // ### Crude algorithm. + regenerateIndex = true; + } + } + + // Regenerate the tree. + if (regenerateIndex) { + regenerateIndex = false; + bsp.initialize(q->scene()->sceneRect(), bspTreeDepth); + unindexedItems = indexedItems; + lastItemCount = indexedItems.size(); + q->scene()->update(); + + // Take this opportunity to reset our largest-item counter for + // untransformable items. When the items are inserted into the BSP + // tree, we'll get an accurate calculation. + scenePrivate->largestUntransformableItem = QRectF(); + } + + // Insert all unindexed items into the tree. + for (int i = 0; i < unindexedItems.size(); ++i) { + if (QGraphicsItem *item = unindexedItems.at(i)) { + QRectF rect = item->sceneBoundingRect(); + if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) + continue; + + bsp.insertItem(item, rect); + + // If the item ignores view transformations, update our + // largest-item-counter to ensure that the view can accurately + // discover untransformable items when drawing. + if (item->d_ptr->itemIsUntransformable()) { + QGraphicsItem *topmostUntransformable = item; + while (topmostUntransformable && (topmostUntransformable->d_ptr->ancestorFlags + & QGraphicsItemPrivate::AncestorIgnoresTransformations)) { + topmostUntransformable = topmostUntransformable->parentItem(); + } + // ### Verify that this is the correct largest untransformable rectangle. + scenePrivate->largestUntransformableItem |= item->mapToItem(topmostUntransformable, item->boundingRect()).boundingRect(); + } + } + } + unindexedItems.clear(); + + // Notify scene rect changes. + if (!scenePrivate->hasSceneRect && scenePrivate->growingItemsBoundingRect != oldGrowingItemsBoundingRect) + emit q->scene()->sceneRectChanged(scenePrivate->growingItemsBoundingRect); } -QRectF QGraphicsSceneBspTreeIndex::indexedRect() + +/*! + \internal + + Removes stale pointers from all data structures. +*/ +void QGraphicsSceneBspTreeIndexPrivate::purgeRemovedItems() +{ + Q_Q(QGraphicsSceneBspTreeIndex); + if (!purgePending && removedItems.isEmpty()) + return; + + // Remove stale items from the BSP tree. + bsp.removeItems(removedItems.toSet()); + // Purge this list. + removedItems.clear(); + freeItemIndexes.clear(); + for (int i = 0; i < indexedItems.size(); ++i) { + if (!indexedItems.at(i)) + freeItemIndexes << i; + } + purgePending = false; + + // No locality info for the items; update the whole scene. + q->scene()->update(); +} + +/*! + \internal + + Starts or restarts the timer used for reindexing unindexed items. +*/ +void QGraphicsSceneBspTreeIndexPrivate::startIndexTimer() +{ + Q_Q(QGraphicsSceneBspTreeIndex); + if (indexTimerId) { + restartIndexTimer = true; + } else { + indexTimerId = q->startTimer(QGRAPHICSSCENE_INDEXTIMER_TIMEOUT); + } +} + +/*! + \internal +*/ +void QGraphicsSceneBspTreeIndexPrivate::resetIndex() +{ + purgeRemovedItems(); + for (int i = 0; i < indexedItems.size(); ++i) { + if (QGraphicsItem *item = indexedItems.at(i)) { + item->d_ptr->index = -1; + unindexedItems << item; + } + } + indexedItems.clear(); + freeItemIndexes.clear(); + regenerateIndex = true; + startIndexTimer(); +} + +void QGraphicsSceneBspTreeIndexPrivate::climbTree(QGraphicsItem *item, int *stackingOrder) { + if (!item->d_ptr->children.isEmpty()) { + QList childList = item->d_ptr->children; + qSort(childList.begin(), childList.end(), qt_closestLeaf); + for (int i = 0; i < childList.size(); ++i) { + QGraphicsItem *item = childList.at(i); + if (!(item->flags() & QGraphicsItem::ItemStacksBehindParent)) + climbTree(childList.at(i), stackingOrder); + } + item->d_ptr->globalStackingOrder = (*stackingOrder)++; + for (int i = 0; i < childList.size(); ++i) { + QGraphicsItem *item = childList.at(i); + if (item->flags() & QGraphicsItem::ItemStacksBehindParent) + climbTree(childList.at(i), stackingOrder); + } + } else { + item->d_ptr->globalStackingOrder = (*stackingOrder)++; + } +} + +void QGraphicsSceneBspTreeIndexPrivate::_q_updateSortCache() +{ + Q_Q(QGraphicsSceneBspTreeIndex); _q_updateIndex(); + + if (!sortCacheEnabled || !updatingSortCache) + return; + + updatingSortCache = false; + int stackingOrder = 0; + + QList topLevels; + + for (int i = 0; i < q->items().count(); ++i) { + QGraphicsItem *item = q->items().at(i); + if (item && item->parentItem() == 0) + topLevels << item; + } + + qSort(topLevels.begin(), topLevels.end(), qt_closestLeaf); + for (int i = 0; i < topLevels.size(); ++i) + climbTree(topLevels.at(i), &stackingOrder); +} + +void QGraphicsSceneBspTreeIndexPrivate::invalidateSortCache() +{ + Q_Q(QGraphicsSceneBspTreeIndex); + if (!sortCacheEnabled || updatingSortCache) + return; + + updatingSortCache = true; + QMetaObject::invokeMethod(q, "_q_updateSortCache", Qt::QueuedConnection); +} + +/*! + Returns true if \a item1 is on top of \a item2. + + \internal +*/ +bool QGraphicsSceneBspTreeIndexPrivate::closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2) +{ + // Siblings? Just check their z-values. + const QGraphicsItemPrivate *d1 = item1->d_ptr; + const QGraphicsItemPrivate *d2 = item2->d_ptr; + if (d1->parent == d2->parent) + return qt_closestLeaf(item1, item2); + + // Find common ancestor, and each item's ancestor closest to the common + // ancestor. + int item1Depth = d1->depth; + int item2Depth = d2->depth; + const QGraphicsItem *p = item1; + const QGraphicsItem *t1 = item1; + while (item1Depth > item2Depth && (p = p->d_ptr->parent)) { + if (p == item2) { + // item2 is one of item1's ancestors; item1 is on top + return !(t1->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); + } + t1 = p; + --item1Depth; + } + p = item2; + const QGraphicsItem *t2 = item2; + while (item2Depth > item1Depth && (p = p->d_ptr->parent)) { + if (p == item1) { + // item1 is one of item2's ancestors; item1 is not on top + return (t2->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); + } + t2 = p; + --item2Depth; + } + + // item1Ancestor is now at the same level as item2Ancestor, but not the same. + const QGraphicsItem *a1 = t1; + const QGraphicsItem *a2 = t2; + while (a1) { + const QGraphicsItem *p1 = a1; + const QGraphicsItem *p2 = a2; + a1 = a1->parentItem(); + a2 = a2->parentItem(); + if (a1 && a1 == a2) + return qt_closestLeaf(p1, p2); + } + + // No common ancestor? Then just compare the items' toplevels directly. + return qt_closestLeaf(t1->topLevelItem(), t2->topLevelItem()); +} + +/*! + Returns true if \a item2 is on top of \a item1. + + \internal +*/ +bool QGraphicsSceneBspTreeIndexPrivate::closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2) +{ + return closestItemFirst_withoutCache(item2, item1); +} + +void QGraphicsSceneBspTreeIndexPrivate::sortItems(QList *itemList, Qt::SortOrder order, + bool sortCacheEnabled) +{ + if (sortCacheEnabled) { + if (order == Qt::AscendingOrder) { + qSort(itemList->begin(), itemList->end(), closestItemFirst_withCache); + } else if (order == Qt::DescendingOrder) { + qSort(itemList->begin(), itemList->end(), closestItemLast_withCache); + } + } else { + if (order == Qt::AscendingOrder) { + qSort(itemList->begin(), itemList->end(), closestItemFirst_withoutCache); + } else if (order == Qt::DescendingOrder) { + qSort(itemList->begin(), itemList->end(), closestItemLast_withoutCache); + } + } +} + +QGraphicsSceneBspTreeIndex::QGraphicsSceneBspTreeIndex(QGraphicsScene *scene) + : QGraphicsSceneIndex(*new QGraphicsSceneBspTreeIndexPrivate(scene), scene) +{ + +} + +QRectF QGraphicsSceneBspTreeIndex::indexedRect() const +{ + Q_D(const QGraphicsSceneBspTreeIndex); + const_cast(d)->_q_updateIndex(); return scene()->d_func()->hasSceneRect ? scene()->d_func()->sceneRect : scene()->d_func()->growingItemsBoundingRect; } void QGraphicsSceneBspTreeIndex::clear() { - bsp.clear(); - lastItemCount = 0; - freeItemIndexes.clear(); - m_indexedItems.clear(); - unindexedItems.clear(); + Q_D(QGraphicsSceneBspTreeIndex); + d->bsp.clear(); + d->lastItemCount = 0; + d->freeItemIndexes.clear(); + d->indexedItems.clear(); + d->unindexedItems.clear(); } void QGraphicsSceneBspTreeIndex::addItem(QGraphicsItem *item) { + Q_D(QGraphicsSceneBspTreeIndex); // Prevent reusing a recently deleted pointer: purge all removed items // from our lists. - purgeRemovedItems(); + d->purgeRemovedItems(); + + // Invalidate any sort caching; arrival of a new item means we need to + // resort. + // Update the scene's sort cache settings. + item->d_ptr->globalStackingOrder = -1; + d->invalidateSortCache(); // Indexing requires sceneBoundingRect(), but because \a item might // not be completely constructed at this point, we need to store it in // a temporary list and schedule an indexing for later. - unindexedItems << item; + d->unindexedItems << item; item->d_func()->index = -1; - startIndexTimer(); + d->startIndexTimer(); } /*! \internal */ -void QGraphicsSceneBspTreeIndex::addToIndex(QGraphicsItem *item) +void QGraphicsSceneBspTreeIndexPrivate::addToIndex(QGraphicsItem *item) { if (item->d_func()->index != -1) { bsp.insertItem(item, item->sceneBoundingRect()); @@ -109,37 +429,47 @@ void QGraphicsSceneBspTreeIndex::addToIndex(QGraphicsItem *item) void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item) { + Q_D(QGraphicsSceneBspTreeIndex); // Note: This will access item's sceneBoundingRect(), which (as this is // C++) is why we cannot call removeItem() from QGraphicsItem's // destructor. - removeFromIndex(item); + d->removeFromIndex(item); + + // Invalidate any sort caching; arrival of a new item means we need to + // resort. + d->invalidateSortCache(); // Remove from our item lists. int index = item->d_func()->index; if (index != -1) { - freeItemIndexes << index; - m_indexedItems[index] = 0; + d->freeItemIndexes << index; + d->indexedItems[index] = 0; } else { - unindexedItems.removeAll(item); + d->unindexedItems.removeAll(item); } } void QGraphicsSceneBspTreeIndex::deleteItem(QGraphicsItem *item) { + Q_D(QGraphicsSceneBspTreeIndex); + // Invalidate any sort caching; arrival of a new item means we need to + // resort. + d->invalidateSortCache(); + int index = item->d_func()->index; if (index != -1) { // Important: The index is useless until purgeRemovedItems() is // called. - m_indexedItems[index] = (QGraphicsItem *)0; - if (!purgePending) { - purgePending = true; + d->indexedItems[index] = (QGraphicsItem *)0; + if (!d->purgePending) { + d->purgePending = true; scene()->update(); } - removedItems << item; + d->removedItems << item; } else { // Recently added items are purged immediately. unindexedItems() never // contains stale items. - unindexedItems.removeAll(item); + d->unindexedItems.removeAll(item); scene()->update(); } } @@ -147,7 +477,7 @@ void QGraphicsSceneBspTreeIndex::deleteItem(QGraphicsItem *item) /*! \internal */ -void QGraphicsSceneBspTreeIndex::removeFromIndex(QGraphicsItem *item) +void QGraphicsSceneBspTreeIndexPrivate::removeFromIndex(QGraphicsItem *item) { if (item->d_func()->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { // ### remove from child index only if applicable @@ -157,7 +487,7 @@ void QGraphicsSceneBspTreeIndex::removeFromIndex(QGraphicsItem *item) if (index != -1) { bsp.removeItem(item, item->sceneBoundingRect()); freeItemIndexes << index; - m_indexedItems[index] = 0; + indexedItems[index] = 0; item->d_func()->index = -1; unindexedItems << item; @@ -170,21 +500,23 @@ void QGraphicsSceneBspTreeIndex::removeFromIndex(QGraphicsItem *item) void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem *item) { + Q_D(QGraphicsSceneBspTreeIndex); // Note: This will access item's sceneBoundingRect(), which (as this is // C++) is why we cannot call removeItem() from QGraphicsItem's // destructor. - removeFromIndex(const_cast(item)); + d->removeFromIndex(const_cast(item)); } QList QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const { - const_cast(this)->purgeRemovedItems(); - scene()->d_func()->_q_updateSortCache(); + Q_D(const QGraphicsSceneBspTreeIndex); + const_cast(d)->purgeRemovedItems(); + const_cast(d)->_q_updateSortCache(); - QList rectItems = bsp.items(rect); + QList rectItems = d->bsp.items(rect); // Fill in with any unindexed items - for (int i = 0; i < unindexedItems.size(); ++i) { - if (QGraphicsItem *item = unindexedItems.at(i)) { + for (int i = 0; i < d->unindexedItems.size(); ++i) { + if (QGraphicsItem *item = d->unindexedItems.at(i)) { if (!item->d_ptr->itemDiscovered && item->d_ptr->visible && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { QRectF boundingRect = item->sceneBoundingRect(); if (QRectF_intersects(boundingRect, rect)) { @@ -199,57 +531,83 @@ QList QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &r for (int i = 0; i < rectItems.size(); ++i) rectItems.at(i)->d_func()->itemDiscovered = 0; + d->sortItems(&rectItems, order, d->sortCacheEnabled); + return rectItems; } -QList QGraphicsSceneBspTreeIndex::items() const +QList QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order) const { - const_cast(this)->purgeRemovedItems(); + Q_D(const QGraphicsSceneBspTreeIndex); + const_cast(d)->purgeRemovedItems(); + QList itemList; // If freeItemIndexes is empty, we know there are no holes in indexedItems and // unindexedItems. - if (freeItemIndexes.isEmpty()) { - if (unindexedItems.isEmpty()) - return m_indexedItems; - return m_indexedItems + unindexedItems; - } - - // Rebuild the list of items to avoid holes. ### We could also just - // compress the item lists at this point. - QList itemList; - foreach (QGraphicsItem *item, m_indexedItems + unindexedItems) { - if (item) - itemList << item; + if (d->freeItemIndexes.isEmpty()) { + if (d->unindexedItems.isEmpty()) { + itemList = d->indexedItems; + } else { + itemList = d->indexedItems + d->unindexedItems; + } + } else { + // Rebuild the list of items to avoid holes. ### We could also just + // compress the item lists at this point. + foreach (QGraphicsItem *item, d->indexedItems + d->unindexedItems) { + if (item) + itemList << item; + } } + //We sort descending order + d->sortItems(&itemList, order, d->sortCacheEnabled); return itemList; } int QGraphicsSceneBspTreeIndex::bspDepth() { - return bspTreeDepth; + Q_D(const QGraphicsSceneBspTreeIndex); + return d->bspTreeDepth; } void QGraphicsSceneBspTreeIndex::setBspDepth(int depth) { - bspTreeDepth = depth; - resetIndex(); + Q_D(QGraphicsSceneBspTreeIndex); + d->bspTreeDepth = depth; + d->resetIndex(); } void QGraphicsSceneBspTreeIndex::sceneRectChanged(const QRectF &rect) { - m_sceneRect = rect; - resetIndex(); + Q_D(QGraphicsSceneBspTreeIndex); + d->sceneRect = rect; + d->resetIndex(); +} + +void QGraphicsSceneBspTreeIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value) +{ + Q_D(QGraphicsSceneBspTreeIndex); + switch (change) { + case QGraphicsItem::ItemZValueChange: + case QGraphicsItem::ItemParentChange: { + d->invalidateSortCache(); + break; + } + default: + break; + } + return QGraphicsSceneIndex::itemChanged(item, change, value); } bool QGraphicsSceneBspTreeIndex::event(QEvent *event) { + Q_D(QGraphicsSceneBspTreeIndex); switch (event->type()) { case QEvent::Timer: - if (indexTimerId && static_cast(event)->timerId() == indexTimerId) { - if (restartIndexTimer) { - restartIndexTimer = false; + if (d->indexTimerId && static_cast(event)->timerId() == d->indexTimerId) { + if (d->restartIndexTimer) { + d->restartIndexTimer = false; } else { // this call will kill the timer - _q_updateIndex(); + d->_q_updateIndex(); } } // Fallthrough intended - support timers in subclasses. @@ -259,153 +617,9 @@ bool QGraphicsSceneBspTreeIndex::event(QEvent *event) return true; } -static inline int intmaxlog(int n) -{ - return (n > 0 ? qMax(qCeil(qLn(qreal(n)) / qLn(qreal(2))), 5) : 0); -} +QT_END_NAMESPACE -/*! - \internal -*/ -void QGraphicsSceneBspTreeIndex::_q_updateIndex() -{ - if (!indexTimerId) - return; +#include "moc_qgraphicsscenebsptreeindex_p.cpp" - killTimer(indexTimerId); - indexTimerId = 0; +#endif // QT_NO_GRAPHICSVIEW - purgeRemovedItems(); - - // Add unindexedItems to indexedItems - QRectF unindexedItemsBoundingRect; - for (int i = 0; i < unindexedItems.size(); ++i) { - if (QGraphicsItem *item = unindexedItems.at(i)) { - unindexedItemsBoundingRect |= item->sceneBoundingRect(); - if (!freeItemIndexes.isEmpty()) { - int freeIndex = freeItemIndexes.takeFirst(); - item->d_func()->index = freeIndex; - m_indexedItems[freeIndex] = item; - } else { - item->d_func()->index = m_indexedItems.size(); - m_indexedItems << item; - } - } - } - - // Update growing scene rect. - QRectF oldGrowingItemsBoundingRect = scene()->d_func()->growingItemsBoundingRect; - scene()->d_func()->growingItemsBoundingRect |= unindexedItemsBoundingRect; - - // Determine whether we should regenerate the BSP tree. - if (bspTreeDepth == 0) { - int oldDepth = intmaxlog(lastItemCount); - bspTreeDepth = intmaxlog(m_indexedItems.size()); - static const int slack = 100; - if (bsp.leafCount() == 0 || (oldDepth != bspTreeDepth && qAbs(lastItemCount - m_indexedItems.size()) > slack)) { - // ### Crude algorithm. - regenerateIndex = true; - } - } - - // Regenerate the tree. - if (regenerateIndex) { - regenerateIndex = false; - bsp.initialize(scene()->sceneRect(), bspTreeDepth); - unindexedItems = m_indexedItems; - lastItemCount = m_indexedItems.size(); - scene()->update(); - - // Take this opportunity to reset our largest-item counter for - // untransformable items. When the items are inserted into the BSP - // tree, we'll get an accurate calculation. - scene()->d_func()->largestUntransformableItem = QRectF(); - } - - // Insert all unindexed items into the tree. - for (int i = 0; i < unindexedItems.size(); ++i) { - if (QGraphicsItem *item = unindexedItems.at(i)) { - QRectF rect = item->sceneBoundingRect(); - if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) - continue; - - bsp.insertItem(item, rect); - - // If the item ignores view transformations, update our - // largest-item-counter to ensure that the view can accurately - // discover untransformable items when drawing. - if (item->d_ptr->itemIsUntransformable()) { - QGraphicsItem *topmostUntransformable = item; - while (topmostUntransformable && (topmostUntransformable->d_ptr->ancestorFlags - & QGraphicsItemPrivate::AncestorIgnoresTransformations)) { - topmostUntransformable = topmostUntransformable->parentItem(); - } - // ### Verify that this is the correct largest untransformable rectangle. - scene()->d_func()->largestUntransformableItem |= item->mapToItem(topmostUntransformable, item->boundingRect()).boundingRect(); - } - } - } - unindexedItems.clear(); - - // Notify scene rect changes. - if (!scene()->d_func()->hasSceneRect && scene()->d_func()->growingItemsBoundingRect != oldGrowingItemsBoundingRect) - emit scene()->sceneRectChanged(scene()->d_func()->growingItemsBoundingRect); -} - - -/*! - \internal - - Removes stale pointers from all data structures. -*/ -void QGraphicsSceneBspTreeIndex::purgeRemovedItems() -{ - if (!purgePending && removedItems.isEmpty()) - return; - - // Remove stale items from the BSP tree. - bsp.removeItems(removedItems.toSet()); - // Purge this list. - removedItems.clear(); - freeItemIndexes.clear(); - for (int i = 0; i < m_indexedItems.size(); ++i) { - if (!m_indexedItems.at(i)) - freeItemIndexes << i; - } - purgePending = false; - - // No locality info for the items; update the whole scene. - scene()->update(); -} - -/*! - \internal - - Starts or restarts the timer used for reindexing unindexed items. -*/ -void QGraphicsSceneBspTreeIndex::startIndexTimer() -{ - if (indexTimerId) { - restartIndexTimer = true; - } else { - indexTimerId = startTimer(QGRAPHICSSCENE_INDEXTIMER_TIMEOUT); - } -} - -/*! - \internal -*/ -void QGraphicsSceneBspTreeIndex::resetIndex() -{ - purgeRemovedItems(); - for (int i = 0; i < m_indexedItems.size(); ++i) { - if (QGraphicsItem *item = m_indexedItems.at(i)) { - item->d_ptr->index = -1; - unindexedItems << item; - } - } - m_indexedItems.clear(); - freeItemIndexes.clear(); - regenerateIndex = true; - startIndexTimer(); -} diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index 7a6ea0b..b1ea977 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -56,56 +56,41 @@ QT_BEGIN_NAMESPACE #include "qgraphicsscene_bsp_p.h" +class QGraphicsSceneBspTreeIndexPrivate; class Q_AUTOTEST_EXPORT QGraphicsSceneBspTreeIndex : public QGraphicsSceneIndex { Q_OBJECT public: QGraphicsSceneBspTreeIndex(QGraphicsScene *scene = 0); - QRectF indexedRect(); - - void clear(); - - void addItem(QGraphicsItem *item); - void removeItem(QGraphicsItem *item); - void deleteItem(QGraphicsItem *item); - void prepareBoundingRectChange(const QGraphicsItem *item); + QRectF indexedRect() const; QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const; - QList items() const; + QList items(Qt::SortOrder order = Qt::AscendingOrder) const; int bspDepth(); void setBspDepth(int depth); protected: bool event(QEvent *event); - void sceneRectChanged(const QRectF &rect); + void clear(); + + void addItem(QGraphicsItem *item); + void removeItem(QGraphicsItem *item); + void deleteItem(QGraphicsItem *item); + void prepareBoundingRectChange(const QGraphicsItem *item); -public slots : - void _q_updateIndex(); + void sceneRectChanged(const QRectF &rect); + void itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value); private : - QGraphicsSceneBspTree bsp; - QRectF m_sceneRect; - int bspTreeDepth; - int indexTimerId; - bool restartIndexTimer; - bool regenerateIndex; - int lastItemCount; - - QList m_indexedItems; - QList unindexedItems; - QList freeItemIndexes; - - bool purgePending; - QList removedItems; - void purgeRemovedItems(); - - void startIndexTimer(); - void resetIndex(); - - void addToIndex(QGraphicsItem *item); - void removeFromIndex(QGraphicsItem *item); + Q_DECLARE_PRIVATE(QGraphicsSceneBspTreeIndex) + Q_DISABLE_COPY(QGraphicsSceneBspTreeIndex) + Q_PRIVATE_SLOT(d_func(), void _q_updateSortCache()) + Q_PRIVATE_SLOT(d_func(), void _q_updateIndex()) + + friend class QGraphicsScene; + friend class QGraphicsScenePrivate; }; QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h new file mode 100644 index 0000000..2df5fbc --- /dev/null +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSCENEBSPTREEINDEX_P_P_H +#define QGRAPHICSSCENEBSPTREEINDEX_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + +#include "qgraphicsscenebsptreeindex_p.h" + +#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW + +#include +#include + +QT_BEGIN_NAMESPACE + +class QGraphicsScene; + +class QGraphicsSceneBspTreeIndexPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsSceneBspTreeIndex) +public: + QGraphicsSceneBspTreeIndexPrivate(QGraphicsScene *scene); + + QGraphicsScene *scene; + QGraphicsSceneBspTree bsp; + QRectF sceneRect; + int bspTreeDepth; + int indexTimerId; + bool restartIndexTimer; + bool regenerateIndex; + int lastItemCount; + + QList indexedItems; + QList unindexedItems; + QList freeItemIndexes; + + bool purgePending; + QList removedItems; + void purgeRemovedItems(); + + void _q_updateIndex(); + void startIndexTimer(); + void resetIndex(); + + void addToIndex(QGraphicsItem *item); + void removeFromIndex(QGraphicsItem *item); + + void _q_updateSortCache(); + bool sortCacheEnabled; + bool updatingSortCache; + void invalidateSortCache(); + + static void climbTree(QGraphicsItem *item, int *stackingOrder); + static bool closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2); + static bool closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2); + + static inline bool closestItemFirst_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2) + { + return item1->d_ptr->globalStackingOrder < item2->d_ptr->globalStackingOrder; + } + static inline bool closestItemLast_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2) + { + return item1->d_ptr->globalStackingOrder >= item2->d_ptr->globalStackingOrder; + } + + static void sortItems(QList *itemList, Qt::SortOrder order, bool cached); +}; + + +/*! + \internal +*/ +inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) +{ + // Return true if sibling item1 is on top of item2. + const QGraphicsItemPrivate *d1 = item1->d_ptr; + const QGraphicsItemPrivate *d2 = item2->d_ptr; + bool f1 = d1->flags & QGraphicsItem::ItemStacksBehindParent; + bool f2 = d2->flags & QGraphicsItem::ItemStacksBehindParent; + if (f1 != f2) return f2; + qreal z1 = d1->z; + qreal z2 = d2->z; + return z1 != z2 ? z1 > z2 : d1->siblingIndex > d2->siblingIndex; +} + +QT_END_NAMESPACE + +#endif // QGRAPHICSSCENEBSPTREEINDEX_P_P_H + +#endif + diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index d0d6081..eeee74e 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -41,6 +41,7 @@ #include "qgraphicssceneindex.h" #include "qgraphicssceneindex_p.h" +#include "qgraphicsscenebsptreeindex_p_p.h" #include "qgraphicsscene.h" #include "qgraphicsitem_p.h" #include "qgraphicsscene_p.h" @@ -282,6 +283,14 @@ QGraphicsSceneIndex::QGraphicsSceneIndex(QGraphicsScene *scene) } /*! + \internal +*/ +QGraphicsSceneIndex::QGraphicsSceneIndex(QObjectPrivate &dd, QGraphicsScene *scene) + : QObject(dd, scene) +{ +} + +/*! Destroys the scene index. */ QGraphicsSceneIndex::~QGraphicsSceneIndex() @@ -301,7 +310,7 @@ QGraphicsScene* QGraphicsSceneIndex::scene() const /*! Returns the indexed area for the index */ -QRectF QGraphicsSceneIndex::indexedRect() +QRectF QGraphicsSceneIndex::indexedRect() const { Q_D(const QGraphicsSceneIndex); return d->scene->d_func()->sceneRect; @@ -351,8 +360,9 @@ QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSe d->childItems_helper(&items, item, xinv.map(pos)); } } - - d->scene->d_func()->sortItems(&items, order, d->scene->d_func()->sortCacheEnabled); + //### Needed but it should be handle differently + if (order != Qt::SortOrder(-1)) + QGraphicsSceneBspTreeIndexPrivate::sortItems(&items, order, false); return items; } @@ -415,9 +425,9 @@ QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSe } } } - + //### Needed but it should be handle differently if (order != Qt::SortOrder(-1)) - d->scene->d_func()->sortItems(&items, order, d->scene->d_func()->sortCacheEnabled); + QGraphicsSceneBspTreeIndexPrivate::sortItems(&items, order, false); return items; } @@ -474,9 +484,9 @@ QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt:: d->childItems_helper(&items, item, xinv.map(polygon), mode); } } - + //### Needed but it should be handle differently if (order != Qt::SortOrder(-1)) - d->scene->d_func()->sortItems(&items, order, d->scene->d_func()->sortCacheEnabled); + QGraphicsSceneBspTreeIndexPrivate::sortItems(&items, order, false); return items; } QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const @@ -525,9 +535,9 @@ QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt:: d->childItems_helper(&items, item, xinv.map(path), mode); } } - + //### Needed but it should be handle differently if (order != Qt::SortOrder(-1)) - d->scene->d_func()->sortItems(&items, order, d->scene->d_func()->sortCacheEnabled); + QGraphicsSceneBspTreeIndexPrivate::sortItems(&items, order, false); return items; } diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index 11d9aae..084a623 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -71,9 +71,9 @@ public: QGraphicsScene *scene() const; - virtual QRectF indexedRect(); + virtual QRectF indexedRect() const; - virtual QList items() const = 0; + virtual QList items(Qt::SortOrder order = Qt::AscendingOrder) const = 0; virtual QList items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; virtual QList items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; virtual QList items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; @@ -91,10 +91,15 @@ protected: virtual void prepareBoundingRectChange(const QGraphicsItem *item); virtual void sceneRectChanged(const QRectF &rect); + QGraphicsSceneIndex(QObjectPrivate &dd, QGraphicsScene *scene); + friend class QGraphicsScene; friend class QGraphicsScenePrivate; friend class QGraphicsItem; + friend class QGraphicsItemPrivate; + friend class QGraphicsSceneBspTreeIndex; private: + Q_DISABLE_COPY(QGraphicsSceneIndex) Q_DECLARE_PRIVATE(QGraphicsSceneIndex) }; diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h index f2cdca3..2014693 100644 --- a/src/gui/graphicsview/qgraphicssceneindex_p.h +++ b/src/gui/graphicsview/qgraphicssceneindex_p.h @@ -58,6 +58,7 @@ #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW #include +#include QT_BEGIN_NAMESPACE @@ -86,7 +87,7 @@ public: const QPainterPath &path, Qt::ItemSelectionMode mode) const; - QGraphicsScene *scene; + QGraphicsScene *scene; }; QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h index dc45a17..3057b4a 100644 --- a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h @@ -105,7 +105,7 @@ public: return result; } - QList items() const { + QList items(Qt::SortOrder order = Qt::AscendingOrder) const { return m_items; } }; diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 91f97a1..e8330a9 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -1056,7 +1056,7 @@ QList QGraphicsViewPrivate::findItems(const QRegion &exposedReg *allItems = true; // All items are guaranteed within the exposed region, don't bother using the index. - QList itemList(scene->items()); + QList itemList(scene->d_func()->index->items(Qt::DescendingOrder)); int i = 0; while (i < itemList.size()) { const QGraphicsItem *item = itemList.at(i); @@ -1069,9 +1069,6 @@ QList QGraphicsViewPrivate::findItems(const QRegion &exposedReg else ++i; } - - // Sort the items. - QGraphicsScenePrivate::sortItems(&itemList, Qt::DescendingOrder, scene->d_func()->sortCacheEnabled); return itemList; } @@ -2134,7 +2131,7 @@ QList QGraphicsViewPrivate::itemsInArea(const QPainterPath &pat // Then find the minimal list of items that are inside \a path, and // convert it to a set. - QList regularCandidates = scene->items(q->mapToScene(path), mode); + QList regularCandidates = scene->items(q->mapToScene(path), mode, order, q->transform()); QSet candSet = QSet::fromList(regularCandidates); QTransform viewMatrix = q->viewportTransform(); @@ -2161,10 +2158,6 @@ QList QGraphicsViewPrivate::itemsInArea(const QPainterPath &pat } ++it; } - - // ### Insertion sort would be faster. - if (order != Qt::SortOrder(-1)) - QGraphicsScenePrivate::sortItems(&result, order, scene->d_func()->sortCacheEnabled); return result; } diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 8afdeb4..c83134f 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -4685,6 +4685,11 @@ void tst_QGraphicsItem::itemClipsChildrenToShape() scene.render(&painter); painter.end(); + QGraphicsView view(&scene); + view.show(); + + QTest::qWait(5000); + QCOMPARE(image.pixel(16, 16), QColor(255, 0, 0).rgba()); QCOMPARE(image.pixel(32, 32), QColor(0, 0, 255).rgba()); QCOMPARE(image.pixel(50, 50), QColor(0, 255, 0).rgba()); diff --git a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp index eb117ab..dd997c7 100644 --- a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp @@ -379,8 +379,7 @@ void tst_QGraphicsScene::items() for (int x = minX; x < maxX; x += 100) items << scene.addRect(QRectF(0, 0, 10, 10)); } - - QCOMPARE(scene.items(), items); + QCOMPARE(scene.items().size(), items.size()); scene.itemAt(0, 0); // trigger indexing scene.removeItem(items.at(5)); @@ -397,7 +396,7 @@ void tst_QGraphicsScene::items() QVERIFY(!l2->sceneBoundingRect().intersects(l1->sceneBoundingRect())); QList items; items<rect().center()); - QTest::qWait(100); + QTest::qWait(250); for (int size = 200; size <= 400; size += 25) { view.resize(size, size); @@ -2122,7 +2122,7 @@ void tst_QGraphicsView::resizeAnchor() QVERIFY(qAbs(newCenter.x() - center.x()) < slack); QVERIFY(qAbs(newCenter.y() - center.y()) < slack); } - QTest::qWait(100); + QTest::qWait(250); } } } @@ -2925,7 +2925,7 @@ void tst_QGraphicsView::task245469_itemsAtPointWithClip() QTest::qWait(100); QList itemsAtCenter = view.items(view.viewport()->rect().center()); - QCOMPARE(itemsAtCenter, (QList() << child << parent)); + QCOMPARE(itemsAtCenter, (QList() << parent << child)); QPolygonF p = view.mapToScene(QRect(view.viewport()->rect().center(), QSize(1, 1))); QList itemsAtCenter2 = scene.items(p); -- cgit v0.12 From cea8678e5fca8b33bbd5da057282888bc260a5c9 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Thu, 4 Jun 2009 16:46:36 +0200 Subject: Fix doc and auto-test regression. --- src/gui/graphicsview/qgraphicsscene.cpp | 2 +- tests/auto/qgraphicsview/tst_qgraphicsview.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 4734e74..d811ade 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1586,7 +1586,7 @@ QList QGraphicsScene::items() const /*! Returns all visible items at position \a pos in the scene. The items are - listed in descending Z order (i.e., the first item in the list is the + listed in descending stacking order (i.e., the first item in the list is the top-most item, and the last item is the bottom-most item). \sa itemAt() diff --git a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp index 447de34..696a42d 100644 --- a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp @@ -2925,7 +2925,7 @@ void tst_QGraphicsView::task245469_itemsAtPointWithClip() QTest::qWait(100); QList itemsAtCenter = view.items(view.viewport()->rect().center()); - QCOMPARE(itemsAtCenter, (QList() << parent << child)); + QCOMPARE(itemsAtCenter, (QList() << child << parent)); QPolygonF p = view.mapToScene(QRect(view.viewport()->rect().center(), QSize(1, 1))); QList itemsAtCenter2 = scene.items(p); -- cgit v0.12 From 3d9d7d10c2c6a4aed4650572bc9f3c8bd5b899b5 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Thu, 11 Jun 2009 17:05:32 +0200 Subject: Kill one items_helper + one childItem helper and use the new recursive approach. --- src/gui/graphicsview/qgraphicsscene.cpp | 5 +- src/gui/graphicsview/qgraphicssceneindex.cpp | 232 ++++++++++++--------------- src/gui/graphicsview/qgraphicssceneindex_p.h | 7 +- 3 files changed, 110 insertions(+), 134 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 33232af..0a1cd2b 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1734,10 +1734,7 @@ QList QGraphicsScene::items(const QPointF &pos) const QList QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode) const { Q_D(const QGraphicsScene); - QList itemList; - //###d->index->items(rect, mode, Qt::AscendingOrder); - d->recursive_items_helper(0, rect, &itemList, QTransform(), QTransform(), mode, Qt::AscendingOrder); - return itemList; + return d->index->items(rect, mode, Qt::AscendingOrder); } /*! diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 6895911..954cef3 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -57,57 +57,121 @@ QGraphicsSceneIndexPrivate::QGraphicsSceneIndexPrivate(QGraphicsScene *scene) : { } -void QGraphicsSceneIndexPrivate::childItems_helper(QList *items, - const QGraphicsItem *parent, - const QPointF &pos) const +void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRectF rect, + QList *items, + const QTransform &parentTransform, + const QTransform &viewTransform, + Qt::ItemSelectionMode mode, Qt::SortOrder order, + qreal parentOpacity) const { - bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); - if (parentClip && parent->d_ptr->isClippedAway()) - return; - // ### is this needed? - if (parentClip && !parent->boundingRect().contains(pos)) - return; + // Calculate opacity. + qreal opacity; + if (item) { + if (!item->d_ptr->visible) + return; + QGraphicsItem *p = item->d_ptr->parent; + bool itemIgnoresParentOpacity = item->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity; + bool parentDoesntPropagateOpacity = (p && (p->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)); + if (!itemIgnoresParentOpacity && !parentDoesntPropagateOpacity) { + opacity = parentOpacity * item->opacity(); + } else { + opacity = item->d_ptr->opacity; + } + if (opacity == 0.0 && !(item->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) + return; + } else { + opacity = parentOpacity; + } - QList &children = parent->d_ptr->children; - for (int i = 0; i < children.size(); ++i) { - QGraphicsItem *item = children.at(i); - if (item->d_ptr->transformData && !item->d_ptr->transformData->computedFullTransform().isInvertible()) - continue; + // Calculate the full transform for this item. + QTransform transform = parentTransform; + bool keep = false; + if (item) { + item->d_ptr->combineTransformFromParent(&transform, &viewTransform); + + // ### This does not take the clip into account. + QRectF brect = item->boundingRect(); + _q_adjustRect(&brect); + + keep = true; + if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) + keep = rect.contains(transform.mapRect(brect)) && rect != brect; + else + keep = rect.intersects(transform.mapRect(brect)); + + if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { + QPainterPath rectPath; + rectPath.addRect(rect); + keep = scene->d_func()->itemCollidesWithPath(item, transform.inverted().map(rectPath), mode); + } + } - // Skip invisible items and all their children. - if (item->d_ptr->isInvisible()) - continue; + bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)); + bool dontProcessItem = !item || !keep; + bool dontProcessChildren = item && dontProcessItem && childClip; + + // Find and sort children. + QList &children = item ? item->d_ptr->children : const_cast(scene->d_func())->topLevelItems; + if (!dontProcessChildren) { + if (item && item->d_ptr->needSortChildren) { + item->d_ptr->needSortChildren = 0; + qStableSort(children.begin(), children.end(), qt_notclosestLeaf); + } else if (!item && scene->d_func()->needSortTopLevelItems) { + const_cast(scene->d_func())->needSortTopLevelItems = false; + qStableSort(children.begin(), children.end(), qt_notclosestLeaf); + } + } - bool keep = false; - if (!item->d_ptr->isClippedAway()) { - if (item->contains(item->mapFromParent(pos))) { - items->append(item); - keep = true; - } + childClip &= !dontProcessChildren & !children.isEmpty(); + + // Clip. + if (childClip) + rect &= transform.map(item->shape()).controlPointRect(); + + // Process children behind + int i = 0; + if (!dontProcessChildren) { + for (i = 0; i < children.size(); ++i) { + QGraphicsItem *child = children.at(i); + if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent)) + break; + recursive_items_helper(child, rect, items, transform, viewTransform, + mode, order, opacity); } + } - if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) - // Recurse into children. - childItems_helper(items, item, item->mapFromParent(pos)); + // Process item + if (!dontProcessItem) + items->append(item); + + // Process children in front + if (!dontProcessChildren) { + for (; i < children.size(); ++i) + recursive_items_helper(children.at(i), rect, items, transform, viewTransform, + mode, order, opacity); } -} + if (!item && order == Qt::AscendingOrder) { + int n = items->size(); + for (int i = 0; i < n / 2; ++i) { + QGraphicsItem *tmp = (*items)[n - i - 1]; + (*items)[n - i - 1] = (*items)[i]; + (*items)[i] = tmp; + } + } +} void QGraphicsSceneIndexPrivate::childItems_helper(QList *items, const QGraphicsItem *parent, - const QRectF &rect, - Qt::ItemSelectionMode mode) const + const QPointF &pos) const { bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); if (parentClip && parent->d_ptr->isClippedAway()) return; - QRectF adjustedRect(rect); - _q_adjustRect(&adjustedRect); - QRectF r = !parentClip ? adjustedRect : adjustedRect.intersected(adjustedItemBoundingRect(parent)); - if (r.isEmpty()) + // ### is this needed? + if (parentClip && !parent->boundingRect().contains(pos)) return; - QPainterPath path; QList &children = parent->d_ptr->children; for (int i = 0; i < children.size(); ++i) { QGraphicsItem *item = children.at(i); @@ -120,45 +184,18 @@ void QGraphicsSceneIndexPrivate::childItems_helper(QList *items bool keep = false; if (!item->d_ptr->isClippedAway()) { - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - QRectF mbr = item->mapRectToParent(br); - if (mode >= Qt::ContainsItemBoundingRect) { - // Rect intersects/contains item's bounding rect - if ((mode == Qt::IntersectsItemBoundingRect && QRectF_intersects(rect, mbr)) - || (mode == Qt::ContainsItemBoundingRect && rect != mbr && rect.contains(br))) { - items->append(item); - keep = true; - } - } else { - // Rect intersects/contains item's shape - if (QRectF_intersects(rect, mbr)) { - if (path == QPainterPath()) - path.addRect(rect); - if (scene->d_func()->itemCollidesWithPath(item, item->mapFromParent(path), mode)) { - items->append(item); - keep = true; - } - } + if (item->contains(item->mapFromParent(pos))) { + items->append(item); + keep = true; } } - if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) { + if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) // Recurse into children. - if (!item->d_ptr->transformData || item->d_ptr->transformData->computedFullTransform().type() <= QTransform::TxScale) { - // Rect - childItems_helper(items, item, item->mapRectFromParent(rect), mode); - } else { - // Polygon - childItems_helper(items, item, item->mapFromParent(rect), mode); - } - } + childItems_helper(items, item, item->mapFromParent(pos)); } } - void QGraphicsSceneIndexPrivate::childItems_helper(QList *items, const QGraphicsItem *parent, const QPolygonF &polygon, @@ -369,66 +406,9 @@ QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSe QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); - QList items; - - QPainterPath path; - - // The index returns a rough estimate of what items are inside the rect. - // Refine it by iterating through all returned items. - QRectF adjustedRect(rect); - _q_adjustRect(&adjustedRect); - foreach (QGraphicsItem *item, estimateItems(adjustedRect, order, deviceTransform)) { - // Find the item's scene transform in a clever way. - QTransform x = item->sceneTransform(); - bool keep = false; - - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - if (mode >= Qt::ContainsItemBoundingRect) { - // Rect intersects/contains item's bounding rect - QRectF mbr = x.mapRect(br); - if ((mode == Qt::IntersectsItemBoundingRect && QRectF_intersects(rect, mbr)) - || (mode == Qt::ContainsItemBoundingRect && rect != mbr && rect.contains(mbr))) { - items << item; - keep = true; - } - } else { - // Rect intersects/contains item's shape - if (QRectF_intersects(adjustedRect, x.mapRect(br))) { - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) { - if (path.isEmpty()) - path.addRect(rect); - if (d->scene->d_func()->itemCollidesWithPath(item, xinv.map(path), mode)) { - items << item; - keep = true; - } - } - } - } - - if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) { - // Recurse into children that clip children. - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) { - if (x.type() <= QTransform::TxScale) { - // Rect - d->childItems_helper(&items, item, xinv.mapRect(rect), mode); - } else { - // Polygon - d->childItems_helper(&items, item, xinv.map(rect), mode); - } - } - } - } - //### Needed but it should be handle differently - if (order != Qt::SortOrder(-1)) - QGraphicsSceneBspTreeIndexPrivate::sortItems(&items, order, false); - return items; + QList itemList; + d->recursive_items_helper(0, rect, &itemList, QTransform(), deviceTransform, mode, order); + return itemList; } QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h index 2014693..3a2cb27 100644 --- a/src/gui/graphicsview/qgraphicssceneindex_p.h +++ b/src/gui/graphicsview/qgraphicssceneindex_p.h @@ -70,16 +70,15 @@ class QGraphicsSceneIndexPrivate : public QObjectPrivate public: QGraphicsSceneIndexPrivate(QGraphicsScene *scene); + void recursive_items_helper(QGraphicsItem *item, QRectF rect, QList *items, + const QTransform &parentTransform, const QTransform &viewTransform, + Qt::ItemSelectionMode mode, Qt::SortOrder order, qreal parentOpacity = 1.0) const; void childItems_helper(QList *items, const QGraphicsItem *parent, const QPointF &pos) const; void childItems_helper(QList *items, const QGraphicsItem *parent, - const QRectF &rect, - Qt::ItemSelectionMode mode) const; - void childItems_helper(QList *items, - const QGraphicsItem *parent, const QPolygonF &polygon, Qt::ItemSelectionMode mode) const; void childItems_helper(QList *items, -- cgit v0.12 From da70cf2876cee57299dbeebb86c4c3881e3df721 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Mon, 15 Jun 2009 20:50:26 +0200 Subject: Kill items_helper and child_items_helper for ever. We have now on function recusrsive_item_helper that doing the job. To resolve different use cases we use concept of interceptors for QRectF, QPointF QPolygonF and QPainterPath. --- src/gui/graphicsview/qgraphicsscene.cpp | 5 + src/gui/graphicsview/qgraphicsscene_p.h | 2 + .../graphicsview/qgraphicsscenebsptreeindex_p.cpp | 3 +- .../graphicsview/qgraphicsscenebsptreeindex_p_p.h | 5 +- src/gui/graphicsview/qgraphicssceneindex.cpp | 408 ++++++--------------- src/gui/graphicsview/qgraphicssceneindex_p.h | 36 +- 6 files changed, 140 insertions(+), 319 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 0a1cd2b..eb06186 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -312,6 +312,11 @@ void QGraphicsScenePrivate::init() q->update(); } +QGraphicsScenePrivate *QGraphicsScenePrivate::get(QGraphicsScene *q) +{ + return q->d_func(); +} + void QGraphicsScenePrivate::_q_emitUpdated() { Q_Q(QGraphicsScene); diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index afdba7e..c63e121 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -85,6 +85,8 @@ public: QGraphicsScenePrivate(); void init(); + static QGraphicsScenePrivate *get(QGraphicsScene *q); + quint32 changedSignalMask; QGraphicsScene::ItemIndexMethod indexMethod; diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp index 97d0500..acadcbd 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp @@ -64,7 +64,7 @@ static inline int intmaxlog(int n) Constructs a private scene index. */ QGraphicsSceneBspTreeIndexPrivate::QGraphicsSceneBspTreeIndexPrivate(QGraphicsScene *scene) - : scene(scene), + : QGraphicsSceneIndexPrivate(scene), bspTreeDepth(0), indexTimerId(0), restartIndexTimer(false), @@ -175,7 +175,6 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() */ void QGraphicsSceneBspTreeIndexPrivate::purgeRemovedItems() { - Q_Q(QGraphicsSceneBspTreeIndex); if (!purgePending && removedItems.isEmpty()) return; diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h index 098b278..30f6e26 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h @@ -57,7 +57,7 @@ #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW -#include +#include #include QT_BEGIN_NAMESPACE @@ -66,13 +66,12 @@ static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; class QGraphicsScene; -class QGraphicsSceneBspTreeIndexPrivate : public QObjectPrivate +class QGraphicsSceneBspTreeIndexPrivate : public QGraphicsSceneIndexPrivate { Q_DECLARE_PUBLIC(QGraphicsSceneBspTreeIndex) public: QGraphicsSceneBspTreeIndexPrivate(QGraphicsScene *scene); - QGraphicsScene *scene; QGraphicsSceneBspTree bsp; QRectF sceneRect; int bspTreeDepth; diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 954cef3..8d18806 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -50,14 +50,88 @@ QT_BEGIN_NAMESPACE +class QGraphicsSceneIndexRectIntersector : public QGraphicsSceneIndexIntersector +{ +public: + QGraphicsSceneIndexRectIntersector(QGraphicsScene *scene) : QGraphicsSceneIndexIntersector(scene) {} + bool intersect(const QRectF &brect) const + { + bool keep = true; + if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) + keep = rect.contains(transform.mapRect(brect)) && rect != brect; + else + keep = rect.intersects(transform.mapRect(brect)); + + if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { + QPainterPath rectPath; + rectPath.addRect(rect); + keep = QGraphicsScenePrivate::get(scene)->itemCollidesWithPath(item, transform.inverted().map(rectPath), mode); + } + return keep; + } +}; + +class QGraphicsSceneIndexPointIntersector : public QGraphicsSceneIndexIntersector +{ +public: + QGraphicsSceneIndexPointIntersector(QGraphicsScene *scene) : QGraphicsSceneIndexIntersector(scene) {} + bool intersect(const QRectF &brect) const + { + bool keep = false; + if (rect.intersects(transform.mapRect(brect))) + if (item->contains(transform.inverted().map(pos))) + keep = true; + if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { + QPainterPath rectPath; + rectPath.addRect(rect); + keep = QGraphicsScenePrivate::get(scene)->itemCollidesWithPath(item, transform.inverted().map(rectPath), mode); + } + return keep; + } + QPointF pos; +}; + +class QGraphicsSceneIndexPathIntersector : public QGraphicsSceneIndexIntersector +{ +public: + QGraphicsSceneIndexPathIntersector(QGraphicsScene *scene) : QGraphicsSceneIndexIntersector(scene) {} + bool intersect(const QRectF &brect) const + { + bool keep = true; + if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) + keep = rect.contains(transform.mapRect(brect)) && rect != brect; + else + keep = rect.intersects(transform.mapRect(brect)); + + if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { + keep = QGraphicsScenePrivate::get(scene)->itemCollidesWithPath(item, transform.inverted().map(path), mode); + } + return keep; + } + QPainterPath path; +}; + /*! Constructs a private scene index. */ QGraphicsSceneIndexPrivate::QGraphicsSceneIndexPrivate(QGraphicsScene *scene) : scene(scene) { + pointIntersector = new QGraphicsSceneIndexPointIntersector(scene); + rectIntersector = new QGraphicsSceneIndexRectIntersector(scene); + pathIntersector = new QGraphicsSceneIndexPathIntersector(scene); +} + +/*! + Destructor of private scene index. +*/ +QGraphicsSceneIndexPrivate::~QGraphicsSceneIndexPrivate() +{ + delete pointIntersector; + delete rectIntersector; + delete pathIntersector; } -void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRectF rect, +void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QGraphicsSceneIndexIntersector *intersector, QList *items, const QTransform &parentTransform, const QTransform &viewTransform, @@ -93,17 +167,10 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe QRectF brect = item->boundingRect(); _q_adjustRect(&brect); - keep = true; - if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) - keep = rect.contains(transform.mapRect(brect)) && rect != brect; - else - keep = rect.intersects(transform.mapRect(brect)); - - if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { - QPainterPath rectPath; - rectPath.addRect(rect); - keep = scene->d_func()->itemCollidesWithPath(item, transform.inverted().map(rectPath), mode); - } + //We fill the intersector with needed informations + intersector->transform = transform; + intersector->item = item; + keep = intersector->intersect(brect); } bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)); @@ -126,7 +193,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe // Clip. if (childClip) - rect &= transform.map(item->shape()).controlPointRect(); + intersector->rect &= transform.map(item->shape()).controlPointRect(); // Process children behind int i = 0; @@ -135,7 +202,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe QGraphicsItem *child = children.at(i); if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent)) break; - recursive_items_helper(child, rect, items, transform, viewTransform, + recursive_items_helper(child, intersector, items, transform, viewTransform, mode, order, opacity); } } @@ -147,7 +214,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe // Process children in front if (!dontProcessChildren) { for (; i < children.size(); ++i) - recursive_items_helper(children.at(i), rect, items, transform, viewTransform, + recursive_items_helper(children.at(i), intersector, items, transform, viewTransform, mode, order, opacity); } @@ -161,156 +228,6 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe } } -void QGraphicsSceneIndexPrivate::childItems_helper(QList *items, - const QGraphicsItem *parent, - const QPointF &pos) const -{ - bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); - if (parentClip && parent->d_ptr->isClippedAway()) - return; - // ### is this needed? - if (parentClip && !parent->boundingRect().contains(pos)) - return; - - QList &children = parent->d_ptr->children; - for (int i = 0; i < children.size(); ++i) { - QGraphicsItem *item = children.at(i); - if (item->d_ptr->transformData && !item->d_ptr->transformData->computedFullTransform().isInvertible()) - continue; - - // Skip invisible items and all their children. - if (item->d_ptr->isInvisible()) - continue; - - bool keep = false; - if (!item->d_ptr->isClippedAway()) { - if (item->contains(item->mapFromParent(pos))) { - items->append(item); - keep = true; - } - } - - if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) - // Recurse into children. - childItems_helper(items, item, item->mapFromParent(pos)); - } -} - -void QGraphicsSceneIndexPrivate::childItems_helper(QList *items, - const QGraphicsItem *parent, - const QPolygonF &polygon, - Qt::ItemSelectionMode mode) const -{ - bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); - if (parentClip && parent->d_ptr->isClippedAway()) - return; - QRectF polyRect(polygon.boundingRect()); - _q_adjustRect(&polyRect); - QRectF r = !parentClip ? polyRect : polyRect.intersected(adjustedItemBoundingRect(parent)); - if (r.isEmpty()) - return; - - QPainterPath path; - QList &children = parent->d_ptr->children; - for (int i = 0; i < children.size(); ++i) { - QGraphicsItem *item = children.at(i); - if (item->d_ptr->transformData && !item->d_ptr->transformData->computedFullTransform().isInvertible()) - continue; - - // Skip invisible items. - if (item->d_ptr->isInvisible()) - continue; - - bool keep = false; - if (!item->d_ptr->isClippedAway()) { - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - if (mode >= Qt::ContainsItemBoundingRect) { - // Polygon contains/intersects item's bounding rect - if (path == QPainterPath()) - path.addPolygon(polygon); - if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br))) - || (mode == Qt::ContainsItemBoundingRect && path.contains(item->mapRectToParent(br)))) { - items->append(item); - keep = true; - } - } else { - // Polygon contains/intersects item's shape - if (QRectF_intersects(polyRect, item->mapRectToParent(br))) { - if (path == QPainterPath()) - path.addPolygon(polygon); - if (scene->d_func()->itemCollidesWithPath(item, item->mapFromParent(path), mode)) { - items->append(item); - keep = true; - } - } - } - } - - if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) { - // Recurse into children that clip children. - childItems_helper(items, item, item->mapFromParent(polygon), mode); - } - } -} - -void QGraphicsSceneIndexPrivate::childItems_helper(QList *items, - const QGraphicsItem *parent, - const QPainterPath &path, - Qt::ItemSelectionMode mode) const -{ - bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); - if (parentClip && parent->d_ptr->isClippedAway()) - return; - QRectF pathRect(path.boundingRect()); - _q_adjustRect(&pathRect); - QRectF r = !parentClip ? pathRect : pathRect.intersected(adjustedItemBoundingRect(parent)); - if (r.isEmpty()) - return; - - QList &children = parent->d_ptr->children; - for (int i = 0; i < children.size(); ++i) { - QGraphicsItem *item = children.at(i); - if (item->d_ptr->transformData && !item->d_ptr->transformData->computedFullTransform().isInvertible()) - continue; - - // Skip invisible items. - if (item->d_ptr->isInvisible()) - continue; - - bool keep = false; - if (!item->d_ptr->isClippedAway()) { - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - if (mode >= Qt::ContainsItemBoundingRect) { - // Polygon contains/intersects item's bounding rect - if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br))) - || (mode == Qt::ContainsItemBoundingRect && path.contains(item->mapRectToParent(br)))) { - items->append(item); - keep = true; - } - } else { - // Path contains/intersects item's shape - if (QRectF_intersects(pathRect, item->mapRectToParent(br))) { - if (scene->d_func()->itemCollidesWithPath(item, item->mapFromParent(path), mode)) { - items->append(item); - keep = true; - } - } - } - } - - if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) { - // Recurse into children that clip children. - childItems_helper(items, item, item->mapFromParent(path), mode); - } - } -} - /*! Constructs an abstract scene index. */ @@ -363,162 +280,50 @@ QRectF QGraphicsSceneIndex::indexedRect() const QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); - QList items; - - // The index returns a rough estimate of what items are inside the rect. - // Refine it by iterating through all returned items. - QRectF adjustedRect = QRectF(pos, QSize(1,1)); - foreach (QGraphicsItem *item, estimateItems(adjustedRect, order, deviceTransform)) { - // Find the item's scene transform in a clever way. - QTransform x = item->sceneTransform(); - bool keep = false; - - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - // Rect intersects/contains item's shape - if (QRectF_intersects(adjustedRect, x.mapRect(br))) { - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) { - if (item->contains(xinv.map(pos))) { - items << item; - keep = true; - } - } - } - - if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) { - // Recurse into children that clip children. - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) - d->childItems_helper(&items, item, xinv.map(pos)); - } - } - //### Needed but it should be handle differently - if (order != Qt::SortOrder(-1)) - QGraphicsSceneBspTreeIndexPrivate::sortItems(&items, order, false); - return items; + QList itemList; + d->pointIntersector->mode = mode; + d->pointIntersector->rect = QRectF(pos, QSize(1,1)); + d->pointIntersector->pos = pos; + d->recursive_items_helper(0, d->pointIntersector, &itemList, QTransform(), deviceTransform, mode, order); + return itemList; } QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); QList itemList; - d->recursive_items_helper(0, rect, &itemList, QTransform(), deviceTransform, mode, order); + d->rectIntersector->mode = mode; + d->rectIntersector->rect = rect; + d->recursive_items_helper(0, d->rectIntersector, &itemList, QTransform(), deviceTransform, mode, order); return itemList; } QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); - QList items; - + QList itemList; QRectF polyRect(polygon.boundingRect()); _q_adjustRect(&polyRect); + d->pathIntersector->mode = mode; + d->pathIntersector->rect = polyRect; QPainterPath path; - - // The index returns a rough estimate of what items are inside the rect. - // Refine it by iterating through all returned items. - foreach (QGraphicsItem *item, estimateItems(polyRect, order, deviceTransform)) { - // Find the item's scene transform in a clever way. - QTransform x = item->sceneTransform(); - bool keep = false; - - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - if (mode >= Qt::ContainsItemBoundingRect) { - // Polygon contains/intersects item's bounding rect - if (path == QPainterPath()) - path.addPolygon(polygon); - if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(x.mapRect(br))) - || (mode == Qt::ContainsItemBoundingRect && path.contains(x.mapRect(br)))) { - items << item; - keep = true; - } - } else { - // Polygon contains/intersects item's shape - if (QRectF_intersects(polyRect, x.mapRect(br))) { - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) { - if (path == QPainterPath()) - path.addPolygon(polygon); - if (d->scene->d_func()->itemCollidesWithPath(item, xinv.map(path), mode)) { - items << item; - keep = true; - } - } - } - } - - if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) { - // Recurse into children that clip children. - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) - d->childItems_helper(&items, item, xinv.map(polygon), mode); - } - } - //### Needed but it should be handle differently - if (order != Qt::SortOrder(-1)) - QGraphicsSceneBspTreeIndexPrivate::sortItems(&items, order, false); - return items; + path.addPolygon(polygon); + d->pathIntersector->path = path; + d->recursive_items_helper(0, d->pathIntersector, &itemList, QTransform(), deviceTransform, mode, order); + return itemList; } + QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); - QList items; + QList itemList; QRectF pathRect(path.controlPointRect()); _q_adjustRect(&pathRect); - - // The index returns a rough estimate of what items are inside the rect. - // Refine it by iterating through all returned items. - foreach (QGraphicsItem *item, estimateItems(pathRect, order, deviceTransform)) { - // Find the item's scene transform in a clever way. - QTransform x = item->sceneTransform(); - bool keep = false; - - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - if (mode >= Qt::ContainsItemBoundingRect) { - // Path contains/intersects item's bounding rect - if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(x.mapRect(br))) - || (mode == Qt::ContainsItemBoundingRect && path.contains(x.mapRect(br)))) { - items << item; - keep = true; - } - } else { - // Path contains/intersects item's shape - if (QRectF_intersects(pathRect, x.mapRect(br))) { - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) { - if (d->scene->d_func()->itemCollidesWithPath(item, xinv.map(path), mode)) { - items << item; - keep = true; - } - } - } - } - - if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) { - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) - d->childItems_helper(&items, item, xinv.map(path), mode); - } - } - //### Needed but it should be handle differently - if (order != Qt::SortOrder(-1)) - QGraphicsSceneBspTreeIndexPrivate::sortItems(&items, order, false); - return items; + d->pathIntersector->mode = mode; + d->pathIntersector->rect = pathRect; + d->pathIntersector->path = path; + d->recursive_items_helper(0, d->pathIntersector, &itemList, QTransform(), deviceTransform, mode, order); + return itemList; } /*! @@ -592,6 +397,8 @@ void QGraphicsSceneIndex::deleteItem(QGraphicsItem *item) */ void QGraphicsSceneIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const QVariant &value) { + //Q_UNUSED(item); + //Q_UNUSED(value); } /*! @@ -601,6 +408,7 @@ void QGraphicsSceneIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem:: */ void QGraphicsSceneIndex::prepareBoundingRectChange(const QGraphicsItem *item) { + //Q_UNUSED(item); } /*! diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h index 3a2cb27..d0d181b 100644 --- a/src/gui/graphicsview/qgraphicssceneindex_p.h +++ b/src/gui/graphicsview/qgraphicssceneindex_p.h @@ -63,30 +63,38 @@ QT_BEGIN_NAMESPACE class QGraphicsScene; +class QGraphicsSceneIndexIntersector; +class QGraphicsSceneIndexRectIntersector; +class QGraphicsSceneIndexPointIntersector; +class QGraphicsSceneIndexPathIntersector; class QGraphicsSceneIndexPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QGraphicsSceneIndex) public: QGraphicsSceneIndexPrivate(QGraphicsScene *scene); + ~QGraphicsSceneIndexPrivate(); - void recursive_items_helper(QGraphicsItem *item, QRectF rect, QList *items, + void recursive_items_helper(QGraphicsItem *item, QGraphicsSceneIndexIntersector *intersector, QList *items, const QTransform &parentTransform, const QTransform &viewTransform, Qt::ItemSelectionMode mode, Qt::SortOrder order, qreal parentOpacity = 1.0) const; - - void childItems_helper(QList *items, - const QGraphicsItem *parent, - const QPointF &pos) const; - void childItems_helper(QList *items, - const QGraphicsItem *parent, - const QPolygonF &polygon, - Qt::ItemSelectionMode mode) const; - void childItems_helper(QList *items, - const QGraphicsItem *parent, - const QPainterPath &path, - Qt::ItemSelectionMode mode) const; - QGraphicsScene *scene; + QGraphicsSceneIndexPointIntersector *pointIntersector; + QGraphicsSceneIndexRectIntersector *rectIntersector; + QGraphicsSceneIndexPathIntersector *pathIntersector; +}; + +class QGraphicsSceneIndexIntersector +{ +public: + QGraphicsSceneIndexIntersector(QGraphicsScene *scene) : scene(scene) { } + virtual ~QGraphicsSceneIndexIntersector() { } + virtual bool intersect(const QRectF &rect) const = 0; + Qt::ItemSelectionMode mode; + QGraphicsItem *item; + QGraphicsScene *scene; + QRectF rect; + QTransform transform; }; QT_END_NAMESPACE -- cgit v0.12 From 3dce31e5eb0fac43d445fb9664f1b68f4cd4c11f Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Tue, 16 Jun 2009 10:26:34 +0200 Subject: Warnings -- --- src/gui/graphicsview/qgraphicssceneindex.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 8d18806..3c4efe7 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -395,10 +395,11 @@ void QGraphicsSceneIndex::deleteItem(QGraphicsItem *item) \sa GraphicsItemChange */ -void QGraphicsSceneIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const QVariant &value) +void QGraphicsSceneIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value) { - //Q_UNUSED(item); - //Q_UNUSED(value); + Q_UNUSED(item); + Q_UNUSED(change); + Q_UNUSED(value); } /*! @@ -408,7 +409,7 @@ void QGraphicsSceneIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem:: */ void QGraphicsSceneIndex::prepareBoundingRectChange(const QGraphicsItem *item) { - //Q_UNUSED(item); + Q_UNUSED(item); } /*! @@ -418,6 +419,7 @@ void QGraphicsSceneIndex::prepareBoundingRectChange(const QGraphicsItem *item) */ void QGraphicsSceneIndex::sceneRectChanged(const QRectF &rect) { + Q_UNUSED(rect); } QT_END_NAMESPACE -- cgit v0.12 From 2ceb72068fbb9157a058a1788863b68a12d25646 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Tue, 16 Jun 2009 11:41:35 +0200 Subject: Fix all documentation warnings. --- src/gui/graphicsview/qgraphicsitem.h | 2 - src/gui/graphicsview/qgraphicsscene.cpp | 50 +++++++++---- src/gui/graphicsview/qgraphicssceneindex.cpp | 106 ++++++++++++++++++++++----- 3 files changed, 125 insertions(+), 33 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index 6194249..56a4a3b 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -418,8 +418,6 @@ protected: virtual void setExtension(Extension extension, const QVariant &variant); virtual QVariant extension(const QVariant &variant) const; - bool operator<(const QGraphicsItem *other) const; - protected: QGraphicsItem(QGraphicsItemPrivate &dd, QGraphicsItem *parent, QGraphicsScene *scene); diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 6e08a76..0729a9d 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -201,6 +201,8 @@ however, is done in constant time. This approach is ideal for dynamic scenes, where many items are added, moved or removed continuously. + \omitvalue CustomIndex + \sa setItemIndexMethod(), bspTreeDepth */ @@ -312,6 +314,9 @@ void QGraphicsScenePrivate::init() q->update(); } +/*! + \internal +*/ QGraphicsScenePrivate *QGraphicsScenePrivate::get(QGraphicsScene *q) { return q->d_func(); @@ -454,11 +459,11 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item) markDirty(item, QRectF(), false, false, false, false, /*removingItemFromScene=*/true); if (item->d_ptr->inDestructor) { - // Can potentially call item->boundingRect() (virtual function), that's why - // we only can call this function if the item is not in its destructor. + // The item is actually in its destructor, we call the special method in the index. index->deleteItem(item); } else { - // Remove it from the index properly + // Can potentially call item->boundingRect() (virtual function), that's why + // we only can call this function if the item is not in its destructor. index->removeItem(item); } @@ -1569,6 +1574,13 @@ void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) d->indexMethod = method; } +/*! + \brief the item indexing method. + This method allow to apply an indexing algorithm \a index to the scene, to speed up + item discovery functions like items() and itemAt(). + + \sa sceneIndex(), QGraphicsSceneIndex +*/ void QGraphicsScene::setSceneIndex(QGraphicsSceneIndex *index) { Q_D(QGraphicsScene); @@ -1583,6 +1595,11 @@ void QGraphicsScene::setSceneIndex(QGraphicsSceneIndex *index) } } +/*! + This method return the current indexing algorithm of the scene. + + \sa setSceneIndex(), QGraphicsSceneIndex +*/ QGraphicsSceneIndex* QGraphicsScene::sceneIndex() const { Q_D(const QGraphicsScene); @@ -1784,10 +1801,13 @@ QList QGraphicsScene::items(const QPainterPath &path, Qt::ItemS } /*! - Returns all visible items at position \a pos in the scene. + Returns all visible items that, depending on \a mode, are at the specified \a pos + and return a list sorted using \a order. The default value for \a mode is Qt::IntersectsItemShape; all items whose - exact shape intersects with or is contained by \a path are returned. + exact shape intersects with \a pos are returned. + + \a deviceTransform is the transformation apply to the view. \sa itemAt() */ @@ -1798,15 +1818,15 @@ QList QGraphicsScene::items(const QPointF &pos, Qt::ItemSelecti } /*! - \fn QList QGraphicsScene::items(const QRectF &rectangle, Qt::SortOrder order, const QTransform &deviceTransform) const - \overload Returns all visible items that, depending on \a mode, are either inside or - intersect with the specified \a rectangle. + intersect with the specified \a rect and return a list sorted using \a order. The default value for \a mode is Qt::IntersectsItemShape; all items whose - exact shape intersects with or is contained by \a rectangle are returned. + exact shape intersects with or is contained by \a rect are returned. + + \a deviceTransform is the transformation apply to the view. \sa itemAt() */ @@ -1820,11 +1840,13 @@ QList QGraphicsScene::items(const QRectF &rect, Qt::ItemSelecti \overload Returns all visible items that, depending on \a mode, are either inside or - intersect with the polygon \a polygon. + intersect with the specified \a polygon and return a list sorted using \a order. The default value for \a mode is Qt::IntersectsItemShape; all items whose exact shape intersects with or is contained by \a polygon are returned. + \a deviceTransform is the transformation apply to the view. + \sa itemAt() */ QList QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const @@ -1834,14 +1856,16 @@ QList QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemS } /*! - \overload + \overload - Returns all visible items that, depending on \a path, are either inside or - intersect with the path \a path. + Returns all visible items that, depending on \a mode, are either inside or + intersect with the specified \a path and return a list sorted using \a order. The default value for \a mode is Qt::IntersectsItemShape; all items whose exact shape intersects with or is contained by \a path are returned. + \a deviceTransform is the transformation apply to the view. + \sa itemAt() */ QList QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 3c4efe7..b713452 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -38,6 +38,22 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +/*! + \class QGraphicsSceneIndex + \brief The QGraphicsSceneIndex class provides a base class to implement + a custom indexing algorithm for discovering items in QGraphicsScene. + \since 4.6 + \ingroup multimedia + \ingroup graphicsview-api + \mainclass + + The QGraphicsSceneIndex class provides a base class to implement + a custom indexing algorithm for discovering items in QGraphicsScene. You + need to subclass it and reimplement addItem, removeItem, estimateItems + and items in order to have an functional indexing. + + \sa QGraphicsScene, QGraphicsView +*/ #include "qgraphicssceneindex.h" #include "qgraphicssceneindex_p.h" @@ -229,7 +245,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QGr } /*! - Constructs an abstract scene index. + Constructs an abstract scene index for a given \a scene. */ QGraphicsSceneIndex::QGraphicsSceneIndex(QGraphicsScene *scene) : QObject(*new QGraphicsSceneIndexPrivate(scene), scene) @@ -271,12 +287,17 @@ QRectF QGraphicsSceneIndex::indexedRect() const } /*! - \fn QList items() const = 0 + \fn QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const - This pure virtual function return the list of items that are actually in the index. + Returns all visible items that, depending on \a mode, are at the specified \a pos + and return a list sorted using \a order. -*/ + The default value for \a mode is Qt::IntersectsItemShape; all items whose + exact shape intersects with \a pos are returned. + + \a deviceTransform is the transformation apply to the view. +*/ QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); @@ -288,6 +309,20 @@ QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSe return itemList; } +/*! + \fn QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const + + \overload + + Returns all visible items that, depending on \a mode, are either inside or + intersect with the specified \a rect and return a list sorted using \a order. + + The default value for \a mode is Qt::IntersectsItemShape; all items whose + exact shape intersects with or is contained by \a rect are returned. + + \a deviceTransform is the transformation apply to the view. + +*/ QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); @@ -298,6 +333,20 @@ QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSe return itemList; } +/*! + \fn QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const + + \overload + + Returns all visible items that, depending on \a mode, are either inside or + intersect with the specified \a polygon and return a list sorted using \a order. + + The default value for \a mode is Qt::IntersectsItemShape; all items whose + exact shape intersects with or is contained by \a polygon are returned. + + \a deviceTransform is the transformation apply to the view. + +*/ QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); @@ -313,6 +362,20 @@ QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt:: return itemList; } +/*! + \fn QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const + + \overload + + Returns all visible items that, depending on \a mode, are either inside or + intersect with the specified \a path and return a list sorted using \a order. + + The default value for \a mode is Qt::IntersectsItemShape; all items whose + exact shape intersects with or is contained by \a path are returned. + + \a deviceTransform is the transformation apply to the view. + +*/ QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); @@ -327,8 +390,9 @@ QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt:: } /*! - This pure virtual function return an estimation of items at position \a pos. - + This virtual function return an estimation of items at position \a point. + This method return a list sorted using \a order. + \a deviceTransform is the transformation apply to the view. */ QList QGraphicsSceneIndex::estimateItems(const QPointF &point, Qt::SortOrder order, const QTransform &deviceTransform) const { @@ -336,12 +400,18 @@ QList QGraphicsSceneIndex::estimateItems(const QPointF &point, } /*! - \fn virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const = 0 + \fn virtual QList QGraphicsSceneIndex::estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const = 0 This pure virtual function return an estimation of items in the \a rect. + This method return a list sorted using \a order. + \a deviceTransform is the transformation apply to the view. */ +/*! + \fn virtual QList QGraphicsSceneIndex::items(Qt::SortOrder order = Qt::AscendingOrder) const = 0; + This pure virtual function all items in the index and sort them using \a order. +*/ /*! This virtual function removes all items in the scene index. @@ -353,23 +423,23 @@ void QGraphicsSceneIndex::clear() } /*! - \fn virtual void addItem(QGraphicsItem *item) = 0 + \fn virtual void QGraphicsSceneIndex::addItem(QGraphicsItem *item) = 0 - This pure virtual function inserts an item to the scene index. + This pure virtual function inserts an \a item to the scene index. \sa removeItem(), deleteItem() */ /*! - \fn virtual void removeItem(QGraphicsItem *item) = 0 + \fn virtual void QGraphicsSceneIndex::removeItem(QGraphicsItem *item) = 0 - This pure virtual function removes an item to the scene index. + This pure virtual function removes an \a item to the scene index. \sa addItem(), deleteItem() */ /*! - This method is called when an item has been deleted. + This method is called when an \a item has been deleted. The default implementation call removeItem. Be carefull, if your implementation of removeItem use pure virtual method of QGraphicsItem like boundingRect(), then you should reimplement @@ -384,7 +454,7 @@ void QGraphicsSceneIndex::deleteItem(QGraphicsItem *item) /*! This virtual function is called by QGraphicsItem to notify the index - that some part of the item's state changes. By reimplementing this + that some part of the \a item 's state changes. By reimplementing this function, your can react to a change, and in some cases, (depending on \a change,) adjustments in the index can be made. @@ -393,7 +463,7 @@ void QGraphicsSceneIndex::deleteItem(QGraphicsItem *item) The default implementation does nothing. - \sa GraphicsItemChange + \sa QGraphicsItem::GraphicsItemChange */ void QGraphicsSceneIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value) { @@ -403,9 +473,9 @@ void QGraphicsSceneIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem:: } /*! - Notify the index for a geometry change of an item. + Notify the index for a geometry change of an \a item. - \sa QGraphicsItem::prepareGeometryChange + \sa QGraphicsItem::prepareGeometryChange() */ void QGraphicsSceneIndex::prepareBoundingRectChange(const QGraphicsItem *item) { @@ -414,8 +484,8 @@ void QGraphicsSceneIndex::prepareBoundingRectChange(const QGraphicsItem *item) /*! This virtual function is called when the scene changes its bounding - rectangle. - \sa QGraphicsScene::sceneRect + rectangle. \a rect is the new value of the scene rectangle. + \sa QGraphicsScene::sceneRect() */ void QGraphicsSceneIndex::sceneRectChanged(const QRectF &rect) { -- cgit v0.12 From 0fa15d71015adfd8895ef41a082fb9479bf4bb3d Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Tue, 16 Jun 2009 13:45:36 +0200 Subject: Remove old legacy and fix documentation. --- src/gui/graphicsview/graphicsview.pri | 1 + src/gui/graphicsview/qgraphicsscene.cpp | 12 +- src/gui/graphicsview/qgraphicsscene_p.h | 4 +- .../graphicsview/qgraphicsscenebsptreeindex_p.cpp | 145 ++++++++++++++++++++- .../graphicsview/qgraphicsscenebsptreeindex_p.h | 5 +- src/gui/graphicsview/qgraphicssceneindex.cpp | 27 ++++ src/gui/graphicsview/qgraphicsscenelinearindex_p.h | 37 +++--- 7 files changed, 198 insertions(+), 33 deletions(-) diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri index 9dc4112..a4d142a 100644 --- a/src/gui/graphicsview/graphicsview.pri +++ b/src/gui/graphicsview/graphicsview.pri @@ -18,6 +18,7 @@ SOURCES += graphicsview/qgraphicsitem.cpp \ graphicsview/qgraphicsscene.cpp \ graphicsview/qgraphicsscene_bsp.cpp \ graphicsview/qgraphicsscenebsptreeindex_p.cpp \ + graphicsview/qgraphicsscenelinearindex.cpp \ graphicsview/qgraphicssceneindex.cpp \ graphicsview/qgraphicssceneevent.cpp \ graphicsview/qgraphicsview.cpp diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 0729a9d..328ab4c 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -271,9 +271,8 @@ static void _q_hoverFromMouseEvent(QGraphicsSceneHoverEvent *hover, const QGraph QGraphicsScenePrivate::QGraphicsScenePrivate() : changedSignalMask(0), indexMethod(QGraphicsScene::BspTreeIndex), - bspTreeDepth(0), - lastItemCount(0), index(0), + lastItemCount(0), hasSceneRect(false), updateAll(false), calledEmitUpdated(false), @@ -1642,14 +1641,11 @@ int QGraphicsScene::bspTreeDepth() const { Q_D(const QGraphicsScene); QGraphicsSceneBspTreeIndex *bspTree = qobject_cast(d->index); - return bspTree ? bspTree->bspDepth() : 0; + return bspTree ? bspTree->bspTreeDepth() : 0; } void QGraphicsScene::setBspTreeDepth(int depth) { Q_D(QGraphicsScene); - if (d->bspTreeDepth == depth) - return; - if (depth < 0) { qWarning("QGraphicsScene::setBspTreeDepth: invalid depth %d ignored; must be >= 0", depth); return; @@ -1660,8 +1656,10 @@ void QGraphicsScene::setBspTreeDepth(int depth) qWarning("QGraphicsScene::setBspTreeDepth: can not apply if indexing method is not BSP"); return; } + if (bspTree->bspTreeDepth() == depth) + return; - bspTree->setBspDepth(depth); + bspTree->setBspTreeDepth(depth); } /*! diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index c63e121..db401ef 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -90,12 +90,10 @@ public: quint32 changedSignalMask; QGraphicsScene::ItemIndexMethod indexMethod; - int bspTreeDepth; + QGraphicsSceneIndex *index; int lastItemCount; - QGraphicsSceneIndex *index; - QRectF sceneRect; bool hasSceneRect; QRectF growingItemsBoundingRect; diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp index acadcbd..b19248a 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp @@ -39,6 +39,40 @@ ** ****************************************************************************/ +/*! + \class QGraphicsSceneBspTreeIndex + \brief The QGraphicsSceneBspTreeIndex class provides an implementation of + a BSP indexing algorithm for discovering items in QGraphicsScene. + \since 4.6 + \ingroup multimedia + \ingroup graphicsview-api + \mainclass + + QGraphicsSceneBspTreeIndex index use a BSP(Binary Space Partitioning) + implementation to discover items quickly. This implementation is + very efficient for static scene. It has a depth that you can set. + The depth directly affects performance and memory usage; the latter + growing exponentially with the depth of the tree. With an optimal tree + depth, the index can instantly determine the locality of items, even + for scenes with thousands or millions of items. This also greatly improves + rendering performance. + + By default, the value is 0, in which case Qt will guess a reasonable + default depth based on the size, location and number of items in the + scene. If these parameters change frequently, however, you may experience + slowdowns as the index retunes the depth internally. You can avoid + potential slowdowns by fixating the tree depth through setting this + property. + + The depth of the tree and the size of the scene rectangle decide the + granularity of the scene's partitioning. The size of each scene segment is + determined by the following algorithm: + + The BSP tree has an optimal size when each segment contains between 0 and + 10 items. + + \sa QGraphicsScene, QGraphicsView, QGraphicsSceneIndex +*/ #include "qgraphicsscenebsptreeindex_p.h" @@ -61,7 +95,7 @@ static inline int intmaxlog(int n) } /*! - Constructs a private scene index. + Constructs a private scene bsp index. */ QGraphicsSceneBspTreeIndexPrivate::QGraphicsSceneBspTreeIndexPrivate(QGraphicsScene *scene) : QGraphicsSceneIndexPrivate(scene), @@ -78,6 +112,11 @@ QGraphicsSceneBspTreeIndexPrivate::QGraphicsSceneBspTreeIndexPrivate(QGraphicsSc /*! + This method will update the BSP index by removing the items from the temporary + unindexed list and add them in the indexedItems list. This will also + update the growingItemsBoundingRect if needed. This will update the BSP + implementation as well. + \internal */ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() @@ -223,6 +262,9 @@ void QGraphicsSceneBspTreeIndexPrivate::resetIndex() startIndexTimer(); } +/*! + \internal +*/ void QGraphicsSceneBspTreeIndexPrivate::climbTree(QGraphicsItem *item, int *stackingOrder) { if (!item->d_ptr->children.isEmpty()) { @@ -244,6 +286,9 @@ void QGraphicsSceneBspTreeIndexPrivate::climbTree(QGraphicsItem *item, int *stac } } +/*! + \internal +*/ void QGraphicsSceneBspTreeIndexPrivate::_q_updateSortCache() { Q_Q(QGraphicsSceneBspTreeIndex); @@ -268,6 +313,9 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateSortCache() climbTree(topLevels.at(i), &stackingOrder); } +/*! + \internal +*/ void QGraphicsSceneBspTreeIndexPrivate::invalidateSortCache() { Q_Q(QGraphicsSceneBspTreeIndex); @@ -342,6 +390,11 @@ bool QGraphicsSceneBspTreeIndexPrivate::closestItemLast_withoutCache(const QGrap return closestItemFirst_withoutCache(item2, item1); } +/*! + Sort a list of \a itemList in a specific \a order and use the cache if requested. + + \internal +*/ void QGraphicsSceneBspTreeIndexPrivate::sortItems(QList *itemList, Qt::SortOrder order, bool sortCacheEnabled) { @@ -360,12 +413,19 @@ void QGraphicsSceneBspTreeIndexPrivate::sortItems(QList *itemLi } } +/*! + Constructs a BSP scene index for the given \a scene. +*/ QGraphicsSceneBspTreeIndex::QGraphicsSceneBspTreeIndex(QGraphicsScene *scene) : QGraphicsSceneIndex(*new QGraphicsSceneBspTreeIndexPrivate(scene), scene) { } +/*! + \reimp + Return the rect indexed by the BSP index. +*/ QRectF QGraphicsSceneBspTreeIndex::indexedRect() const { Q_D(const QGraphicsSceneBspTreeIndex); @@ -373,6 +433,10 @@ QRectF QGraphicsSceneBspTreeIndex::indexedRect() const return scene()->d_func()->hasSceneRect ? scene()->d_func()->sceneRect : scene()->d_func()->growingItemsBoundingRect; } +/*! + \reimp + Clear the all the BSP index. +*/ void QGraphicsSceneBspTreeIndex::clear() { Q_D(QGraphicsSceneBspTreeIndex); @@ -383,6 +447,9 @@ void QGraphicsSceneBspTreeIndex::clear() d->unindexedItems.clear(); } +/*! + Add the \a item into the BSP index. +*/ void QGraphicsSceneBspTreeIndex::addItem(QGraphicsItem *item) { Q_D(QGraphicsSceneBspTreeIndex); @@ -405,6 +472,7 @@ void QGraphicsSceneBspTreeIndex::addItem(QGraphicsItem *item) } /*! + This really add the item in the BSP. \internal */ void QGraphicsSceneBspTreeIndexPrivate::addToIndex(QGraphicsItem *item) @@ -421,6 +489,9 @@ void QGraphicsSceneBspTreeIndexPrivate::addToIndex(QGraphicsItem *item) } } +/*! + Remove the \a item from the BSP index. +*/ void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item) { Q_D(QGraphicsSceneBspTreeIndex); @@ -443,6 +514,10 @@ void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item) } } +/*! + \reimp + Delete the \a item from the BSP index (without accessing its boundingRect). +*/ void QGraphicsSceneBspTreeIndex::deleteItem(QGraphicsItem *item) { Q_D(QGraphicsSceneBspTreeIndex); @@ -469,6 +544,7 @@ void QGraphicsSceneBspTreeIndex::deleteItem(QGraphicsItem *item) } /*! + Really remove the item from the BSP \internal */ void QGraphicsSceneBspTreeIndexPrivate::removeFromIndex(QGraphicsItem *item) @@ -492,6 +568,10 @@ void QGraphicsSceneBspTreeIndexPrivate::removeFromIndex(QGraphicsItem *item) startIndexTimer(); } +/*! + \reimp + Update the BSP when the \a item 's bounding rect has changed. +*/ void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem *item) { Q_D(QGraphicsSceneBspTreeIndex); @@ -501,6 +581,13 @@ void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem * d->removeFromIndex(const_cast(item)); } +/*! + Returns an estimation visible items that are either inside or + intersect with the specified \a rect and return a list sorted using \a order. + + \a deviceTransform is the transformation apply to the view. + +*/ QList QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneBspTreeIndex); @@ -530,6 +617,12 @@ QList QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &r return rectItems; } + +/*! + \fn QList QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order = Qt::AscendingOrder) const; + + Return all items in the BSP index and sort them using \a order. +*/ QList QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order) const { Q_D(const QGraphicsSceneBspTreeIndex); @@ -558,19 +651,52 @@ QList QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order) co return itemList; } -int QGraphicsSceneBspTreeIndex::bspDepth() +/*! + \property QGraphicsSceneBspTreeIndex::bspTreeDepth + \brief the depth of the BSP index tree + \since 4.6 + + This value determines the depth of BSP tree. The depth + directly affects performance and memory usage; the latter + growing exponentially with the depth of the tree. With an optimal tree + depth, the index can instantly determine the locality of items, even + for scenes with thousands or millions of items. This also greatly improves + rendering performance. + + By default, the value is 0, in which case Qt will guess a reasonable + default depth based on the size, location and number of items in the + scene. If these parameters change frequently, however, you may experience + slowdowns as the index retunes the depth internally. You can avoid + potential slowdowns by fixating the tree depth through setting this + property. + + The depth of the tree and the size of the scene rectangle decide the + granularity of the scene's partitioning. The size of each scene segment is + determined by the following algorithm: + + The BSP tree has an optimal size when each segment contains between 0 and + 10 items. + +*/ +int QGraphicsSceneBspTreeIndex::bspTreeDepth() { Q_D(const QGraphicsSceneBspTreeIndex); return d->bspTreeDepth; } -void QGraphicsSceneBspTreeIndex::setBspDepth(int depth) +void QGraphicsSceneBspTreeIndex::setBspTreeDepth(int depth) { Q_D(QGraphicsSceneBspTreeIndex); d->bspTreeDepth = depth; d->resetIndex(); } +/*! + \reimp + + This method react to the \a rect change of the scene and + reset the BSP tree index. +*/ void QGraphicsSceneBspTreeIndex::sceneRectChanged(const QRectF &rect) { Q_D(QGraphicsSceneBspTreeIndex); @@ -578,6 +704,13 @@ void QGraphicsSceneBspTreeIndex::sceneRectChanged(const QRectF &rect) d->resetIndex(); } +/*! + \reimp + + This method react to the \a change of the \a item and use the \a value to + update the BSP tree if necessary. + +*/ void QGraphicsSceneBspTreeIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value) { Q_D(QGraphicsSceneBspTreeIndex); @@ -592,7 +725,13 @@ void QGraphicsSceneBspTreeIndex::itemChanged(const QGraphicsItem *item, QGraphic } return QGraphicsSceneIndex::itemChanged(item, change, value); } +/*! + \reimp + Used to catch the timer event. + + \internal +*/ bool QGraphicsSceneBspTreeIndex::event(QEvent *event) { Q_D(QGraphicsSceneBspTreeIndex); diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index b1ea977..40b8f0b 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -60,6 +60,7 @@ class QGraphicsSceneBspTreeIndexPrivate; class Q_AUTOTEST_EXPORT QGraphicsSceneBspTreeIndex : public QGraphicsSceneIndex { Q_OBJECT + Q_PROPERTY(int bspTreeDepth READ bspTreeDepth WRITE setBspTreeDepth) public: QGraphicsSceneBspTreeIndex(QGraphicsScene *scene = 0); QRectF indexedRect() const; @@ -68,8 +69,8 @@ public: QList items(Qt::SortOrder order = Qt::AscendingOrder) const; - int bspDepth(); - void setBspDepth(int depth); + int bspTreeDepth(); + void setBspTreeDepth(int depth); protected: bool event(QEvent *event); diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index b713452..05ec28b 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -147,6 +147,9 @@ QGraphicsSceneIndexPrivate::~QGraphicsSceneIndexPrivate() delete pathIntersector; } +/*! + \internal +*/ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QGraphicsSceneIndexIntersector *intersector, QList *items, const QTransform &parentTransform, @@ -297,6 +300,12 @@ QRectF QGraphicsSceneIndex::indexedRect() const \a deviceTransform is the transformation apply to the view. + This method use the estimation of the index (estimateItems) and refine + the list to get an exact result. If you want to implement your own + refinement algorithm you can reimplement this method. + + \sa estimateItems() + */ QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { @@ -322,6 +331,12 @@ QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSe \a deviceTransform is the transformation apply to the view. + This method use the estimation of the index (estimateItems) and refine + the list to get an exact result. If you want to implement your own + refinement algorithm you can reimplement this method. + + \sa estimateItems() + */ QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { @@ -346,6 +361,12 @@ QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSe \a deviceTransform is the transformation apply to the view. + This method use the estimation of the index (estimateItems) and refine + the list to get an exact result. If you want to implement your own + refinement algorithm you can reimplement this method. + + \sa estimateItems() + */ QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { @@ -375,6 +396,12 @@ QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt:: \a deviceTransform is the transformation apply to the view. + This method use the estimation of the index (estimateItems) and refine + the list to get an exact result. If you want to implement your own + refinement algorithm you can reimplement this method. + + \sa estimateItems() + */ QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h index 3057b4a..d21475c 100644 --- a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h @@ -68,23 +68,32 @@ class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex { Q_OBJECT -private: - QRectF m_sceneRect; - QList m_items; - public: QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0): QGraphicsSceneIndex(scene) { } - virtual void setRect(const QRectF &rect) { - m_sceneRect = rect; + QList items(Qt::SortOrder order = Qt::AscendingOrder) const { + Q_UNUSED(order); + return m_items; + } + + virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const { + Q_UNUSED(rect); + Q_UNUSED(order); + Q_UNUSED(deviceTransform); + return m_items; } - virtual QRectF rect() const { + virtual QRectF indexedRect() const { return m_sceneRect; } +protected : + void sceneRectChanged(const QRectF &rect) { + m_sceneRect = rect; + } + virtual void clear() { m_items.clear(); } @@ -97,17 +106,9 @@ public: m_items.removeAll(item); } - virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const { - QList result; - foreach (QGraphicsItem *item, m_items) - if (item->sceneBoundingRect().intersects(rect)) - result << item; - return result; - } - - QList items(Qt::SortOrder order = Qt::AscendingOrder) const { - return m_items; - } +private: + QRectF m_sceneRect; + QList m_items; }; QT_END_NAMESPACE -- cgit v0.12 From 8dee7b0c5be293f4b8ebafcae6baa052ca92f1d0 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Tue, 16 Jun 2009 13:46:43 +0200 Subject: Add missing file. --- src/gui/graphicsview/qgraphicsscenelinearindex.cpp | 70 ++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/gui/graphicsview/qgraphicsscenelinearindex.cpp diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex.cpp b/src/gui/graphicsview/qgraphicsscenelinearindex.cpp new file mode 100644 index 0000000..1c898bc --- /dev/null +++ b/src/gui/graphicsview/qgraphicsscenelinearindex.cpp @@ -0,0 +1,70 @@ +#include "qgraphicsscenelinearindex_p.h" + +/*! + \class QGraphicsSceneLinearIndex + \brief The QGraphicsSceneLinearIndex class provides an implementation of + a linear indexing algorithm for discovering items in QGraphicsScene. + \since 4.6 + \ingroup multimedia + \ingroup graphicsview-api + \mainclass + + QGraphicsSceneLinearIndex index is default linear implementation to discover items. + It basically store all items in a list and return them to the scene. + + \sa QGraphicsScene, QGraphicsView, QGraphicsSceneIndex, QGraphicsSceneBspTreeIndex +*/ + +/*! + \fn QGraphicsSceneLinearIndex::QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0): + + Construct a linear index for the given \a scene. +*/ + +/*! + \fn QList QGraphicsSceneLinearIndex::items(Qt::SortOrder order = Qt::AscendingOrder) const; + + Return all items in the index and sort them using \a order. +*/ + + +/*! + \fn virtual QList QGraphicsSceneLinearIndex::estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const; + + Returns an estimation visible items that are either inside or + intersect with the specified \a rect and return a list sorted using \a order. + + \a deviceTransform is the transformation apply to the view. + +*/ + +/*! + \fn QRectF QGraphicsSceneLinearIndex::indexedRect() const; + \reimp + Return the rect indexed by the the index. +*/ + +/*! + \fn void QGraphicsSceneLinearIndex::sceneRectChanged(const QRectF &rect); + \reimp + This method react to the \a rect change of the scene. +*/ + +/*! + \fn void QGraphicsSceneLinearIndex::clear(); + \reimp + Clear the all the BSP index. +*/ + +/*! + \fn virtual void QGraphicsSceneLinearIndex::addItem(QGraphicsItem *item); + + Add the \a item into the index. +*/ + +/*! + \fn virtual void QGraphicsSceneLinearIndex::removeItem(QGraphicsItem *item); + + Add the \a item from the index. +*/ + -- cgit v0.12 From d72727cb7530da54b59c51effa97263512e9238c Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Wed, 17 Jun 2009 11:25:36 +0200 Subject: Fix broken auto-test for the index. Since now items() doesn't use the index then the growingboundingrect is not updated if you call right after a delete. It's because the timer is not yet fired (even the processEvent) so you call add, move, remove which will trigger only one update index so the growingboundingrect will never change. --- tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp index 4d786c7..17d290b 100644 --- a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp @@ -2726,8 +2726,8 @@ void tst_QGraphicsScene::update() qRegisterMetaType >("QList"); QSignalSpy spy(&scene, SIGNAL(changed(QList))); - // When deleted, the item will lazy-remove itself - delete rect; + // We update the scene. + scene.update(); // This function forces a purge, which will post an update signal scene.itemAt(0, 0); -- cgit v0.12 From 8a0e002ccc762ef3edbc3c9ad91b4d6017cb91bb Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Wed, 17 Jun 2009 14:15:14 +0200 Subject: Make eveything internal for now but ready to see the light. --- src/gui/graphicsview/graphicsview.pri | 6 +- src/gui/graphicsview/qgraphicsitem.cpp | 2 +- src/gui/graphicsview/qgraphicsscene.cpp | 7 +- src/gui/graphicsview/qgraphicsscene_p.h | 1 - .../graphicsview/qgraphicsscenebsptreeindex.cpp | 761 +++++++++++++++++++++ src/gui/graphicsview/qgraphicsscenebsptreeindex.h | 119 ++++ .../graphicsview/qgraphicsscenebsptreeindex_p.cpp | 760 -------------------- .../graphicsview/qgraphicsscenebsptreeindex_p.h | 137 ++-- .../graphicsview/qgraphicsscenebsptreeindex_p_p.h | 150 ---- src/gui/graphicsview/qgraphicssceneindex.cpp | 2 +- src/gui/graphicsview/qgraphicssceneindex.h | 13 +- src/gui/graphicsview/qgraphicsscenelinearindex.cpp | 3 +- src/gui/graphicsview/qgraphicsscenelinearindex.h | 124 ++++ src/gui/graphicsview/qgraphicsscenelinearindex_p.h | 118 ---- 14 files changed, 1122 insertions(+), 1081 deletions(-) create mode 100644 src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp create mode 100644 src/gui/graphicsview/qgraphicsscenebsptreeindex.h delete mode 100644 src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp delete mode 100644 src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h create mode 100644 src/gui/graphicsview/qgraphicsscenelinearindex.h delete mode 100644 src/gui/graphicsview/qgraphicsscenelinearindex_p.h diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri index a4d142a..5ac1c54 100644 --- a/src/gui/graphicsview/graphicsview.pri +++ b/src/gui/graphicsview/graphicsview.pri @@ -5,11 +5,11 @@ HEADERS += graphicsview/qgraphicsitem.h \ graphicsview/qgraphicsscene.h \ graphicsview/qgraphicsscene_p.h \ graphicsview/qgraphicsscene_bsp_p.h \ - graphicsview/qgraphicsscenelinearindex_p.h \ + graphicsview/qgraphicsscenelinearindex.h \ graphicsview/qgraphicssceneindex.h \ graphicsview/qgraphicssceneindex_p.h \ + graphicsview/qgraphicsscenebsptreeindex.h \ graphicsview/qgraphicsscenebsptreeindex_p.h \ - graphicsview/qgraphicsscenebsptreeindex_p_p.h \ graphicsview/qgraphicssceneevent.h \ graphicsview/qgraphicsview_p.h \ graphicsview/qgraphicsview.h @@ -17,7 +17,7 @@ SOURCES += graphicsview/qgraphicsitem.cpp \ graphicsview/qgraphicsitemanimation.cpp \ graphicsview/qgraphicsscene.cpp \ graphicsview/qgraphicsscene_bsp.cpp \ - graphicsview/qgraphicsscenebsptreeindex_p.cpp \ + graphicsview/qgraphicsscenebsptreeindex.cpp \ graphicsview/qgraphicsscenelinearindex.cpp \ graphicsview/qgraphicssceneindex.cpp \ graphicsview/qgraphicssceneevent.cpp \ diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 39ad447..593d7be 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -554,7 +554,7 @@ #include "qgraphicsview.h" #include "qgraphicswidget.h" #include "qgraphicsproxywidget.h" -#include "qgraphicsscenebsptreeindex_p_p.h" +#include "qgraphicsscenebsptreeindex_p.h" #include #include #include diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 5a3028c..a33cb3e 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -220,7 +220,8 @@ #include "qgraphicswidget.h" #include "qgraphicswidget_p.h" #include "qgraphicssceneindex.h" -#include "qgraphicsscenebsptreeindex_p_p.h" +#include "qgraphicsscenebsptreeindex.h" +#include "qgraphicsscenelinearindex.h" #include #include @@ -1574,6 +1575,8 @@ void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) } /*! + \internal + \brief the item indexing method. This method allow to apply an indexing algorithm \a index to the scene, to speed up item discovery functions like items() and itemAt(). @@ -1595,6 +1598,8 @@ void QGraphicsScene::setSceneIndex(QGraphicsSceneIndex *index) } /*! + \internal + This method return the current indexing algorithm of the scene. \sa setSceneIndex(), QGraphicsSceneIndex diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 72ae158..563e016 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -58,7 +58,6 @@ #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW #include "qgraphicsscenebsptreeindex_p.h" -#include "qgraphicsscenelinearindex_p.h" #include "qgraphicssceneindex.h" #include "qgraphicsview.h" #include "qgraphicsitem_p.h" diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp new file mode 100644 index 0000000..76fd218 --- /dev/null +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -0,0 +1,761 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \class QGraphicsSceneBspTreeIndex + \brief The QGraphicsSceneBspTreeIndex class provides an implementation of + a BSP indexing algorithm for discovering items in QGraphicsScene. + \since 4.6 + \ingroup multimedia + \ingroup graphicsview-api + \mainclass + \internal + + QGraphicsSceneBspTreeIndex index use a BSP(Binary Space Partitioning) + implementation to discover items quickly. This implementation is + very efficient for static scene. It has a depth that you can set. + The depth directly affects performance and memory usage; the latter + growing exponentially with the depth of the tree. With an optimal tree + depth, the index can instantly determine the locality of items, even + for scenes with thousands or millions of items. This also greatly improves + rendering performance. + + By default, the value is 0, in which case Qt will guess a reasonable + default depth based on the size, location and number of items in the + scene. If these parameters change frequently, however, you may experience + slowdowns as the index retunes the depth internally. You can avoid + potential slowdowns by fixating the tree depth through setting this + property. + + The depth of the tree and the size of the scene rectangle decide the + granularity of the scene's partitioning. The size of each scene segment is + determined by the following algorithm: + + The BSP tree has an optimal size when each segment contains between 0 and + 10 items. + + \sa QGraphicsScene, QGraphicsView, QGraphicsSceneIndex +*/ + +#include "qgraphicsscenebsptreeindex.h" + +#ifndef QT_NO_GRAPHICSVIEW + +#include "qgraphicsscenebsptreeindex_p.h" +#include "qgraphicssceneindex_p.h" +#include "qgraphicsitem_p.h" +#include "qgraphicsscene_p.h" + +#include + +#include + +QT_BEGIN_NAMESPACE + +static inline int intmaxlog(int n) +{ + return (n > 0 ? qMax(qCeil(qLn(qreal(n)) / qLn(qreal(2))), 5) : 0); +} + +/*! + Constructs a private scene bsp index. +*/ +QGraphicsSceneBspTreeIndexPrivate::QGraphicsSceneBspTreeIndexPrivate(QGraphicsScene *scene) + : QGraphicsSceneIndexPrivate(scene), + bspTreeDepth(0), + indexTimerId(0), + restartIndexTimer(false), + regenerateIndex(true), + lastItemCount(0), + purgePending(false), + sortCacheEnabled(false), + updatingSortCache(false) +{ +} + + +/*! + This method will update the BSP index by removing the items from the temporary + unindexed list and add them in the indexedItems list. This will also + update the growingItemsBoundingRect if needed. This will update the BSP + implementation as well. + + \internal +*/ +void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() +{ + Q_Q(QGraphicsSceneBspTreeIndex); + if (!indexTimerId) + return; + + QGraphicsScenePrivate * scenePrivate = q->scene()->d_func(); + q->killTimer(indexTimerId); + indexTimerId = 0; + + purgeRemovedItems(); + + // Add unindexedItems to indexedItems + QRectF unindexedItemsBoundingRect; + for (int i = 0; i < unindexedItems.size(); ++i) { + if (QGraphicsItem *item = unindexedItems.at(i)) { + unindexedItemsBoundingRect |= item->sceneBoundingRect(); + if (!freeItemIndexes.isEmpty()) { + int freeIndex = freeItemIndexes.takeFirst(); + item->d_func()->index = freeIndex; + indexedItems[freeIndex] = item; + } else { + item->d_func()->index = indexedItems.size(); + indexedItems << item; + } + } + } + + // Update growing scene rect. + QRectF oldGrowingItemsBoundingRect = scenePrivate->growingItemsBoundingRect; + scenePrivate->growingItemsBoundingRect |= unindexedItemsBoundingRect; + + // Determine whether we should regenerate the BSP tree. + if (bspTreeDepth == 0) { + int oldDepth = intmaxlog(lastItemCount); + bspTreeDepth = intmaxlog(indexedItems.size()); + static const int slack = 100; + if (bsp.leafCount() == 0 || (oldDepth != bspTreeDepth && qAbs(lastItemCount - indexedItems.size()) > slack)) { + // ### Crude algorithm. + regenerateIndex = true; + } + } + + // Regenerate the tree. + if (regenerateIndex) { + regenerateIndex = false; + bsp.initialize(q->scene()->sceneRect(), bspTreeDepth); + unindexedItems = indexedItems; + lastItemCount = indexedItems.size(); + q->scene()->update(); + + // Take this opportunity to reset our largest-item counter for + // untransformable items. When the items are inserted into the BSP + // tree, we'll get an accurate calculation. + scenePrivate->largestUntransformableItem = QRectF(); + } + + // Insert all unindexed items into the tree. + for (int i = 0; i < unindexedItems.size(); ++i) { + if (QGraphicsItem *item = unindexedItems.at(i)) { + QRectF rect = item->sceneBoundingRect(); + if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) + continue; + + bsp.insertItem(item, rect); + + // If the item ignores view transformations, update our + // largest-item-counter to ensure that the view can accurately + // discover untransformable items when drawing. + if (item->d_ptr->itemIsUntransformable()) { + QGraphicsItem *topmostUntransformable = item; + while (topmostUntransformable && (topmostUntransformable->d_ptr->ancestorFlags + & QGraphicsItemPrivate::AncestorIgnoresTransformations)) { + topmostUntransformable = topmostUntransformable->parentItem(); + } + // ### Verify that this is the correct largest untransformable rectangle. + scenePrivate->largestUntransformableItem |= item->mapToItem(topmostUntransformable, item->boundingRect()).boundingRect(); + } + } + } + unindexedItems.clear(); + + // Notify scene rect changes. + if (!scenePrivate->hasSceneRect && scenePrivate->growingItemsBoundingRect != oldGrowingItemsBoundingRect) + emit q->scene()->sceneRectChanged(scenePrivate->growingItemsBoundingRect); +} + + +/*! + \internal + + Removes stale pointers from all data structures. +*/ +void QGraphicsSceneBspTreeIndexPrivate::purgeRemovedItems() +{ + if (!purgePending && removedItems.isEmpty()) + return; + + // Remove stale items from the BSP tree. + bsp.removeItems(removedItems); + // Purge this list. + removedItems.clear(); + freeItemIndexes.clear(); + for (int i = 0; i < indexedItems.size(); ++i) { + if (!indexedItems.at(i)) + freeItemIndexes << i; + } + purgePending = false; +} + +/*! + \internal + + Starts or restarts the timer used for reindexing unindexed items. +*/ +void QGraphicsSceneBspTreeIndexPrivate::startIndexTimer(int interval) +{ + Q_Q(QGraphicsSceneBspTreeIndex); + if (indexTimerId) { + restartIndexTimer = true; + } else { + indexTimerId = q->startTimer(interval); + } +} + +/*! + \internal +*/ +void QGraphicsSceneBspTreeIndexPrivate::resetIndex() +{ + purgeRemovedItems(); + for (int i = 0; i < indexedItems.size(); ++i) { + if (QGraphicsItem *item = indexedItems.at(i)) { + item->d_ptr->index = -1; + unindexedItems << item; + } + } + indexedItems.clear(); + freeItemIndexes.clear(); + regenerateIndex = true; + startIndexTimer(); +} + +/*! + \internal +*/ +void QGraphicsSceneBspTreeIndexPrivate::climbTree(QGraphicsItem *item, int *stackingOrder) +{ + if (!item->d_ptr->children.isEmpty()) { + QList childList = item->d_ptr->children; + qSort(childList.begin(), childList.end(), qt_closestLeaf); + for (int i = 0; i < childList.size(); ++i) { + QGraphicsItem *item = childList.at(i); + if (!(item->flags() & QGraphicsItem::ItemStacksBehindParent)) + climbTree(childList.at(i), stackingOrder); + } + item->d_ptr->globalStackingOrder = (*stackingOrder)++; + for (int i = 0; i < childList.size(); ++i) { + QGraphicsItem *item = childList.at(i); + if (item->flags() & QGraphicsItem::ItemStacksBehindParent) + climbTree(childList.at(i), stackingOrder); + } + } else { + item->d_ptr->globalStackingOrder = (*stackingOrder)++; + } +} + +/*! + \internal +*/ +void QGraphicsSceneBspTreeIndexPrivate::_q_updateSortCache() +{ + Q_Q(QGraphicsSceneBspTreeIndex); + _q_updateIndex(); + + if (!sortCacheEnabled || !updatingSortCache) + return; + + updatingSortCache = false; + int stackingOrder = 0; + + QList topLevels; + + for (int i = 0; i < q->items().count(); ++i) { + QGraphicsItem *item = q->items().at(i); + if (item && item->parentItem() == 0) + topLevels << item; + } + + qSort(topLevels.begin(), topLevels.end(), qt_closestLeaf); + for (int i = 0; i < topLevels.size(); ++i) + climbTree(topLevels.at(i), &stackingOrder); +} + +/*! + \internal +*/ +void QGraphicsSceneBspTreeIndexPrivate::invalidateSortCache() +{ + Q_Q(QGraphicsSceneBspTreeIndex); + if (!sortCacheEnabled || updatingSortCache) + return; + + updatingSortCache = true; + QMetaObject::invokeMethod(q, "_q_updateSortCache", Qt::QueuedConnection); +} + +/*! + Returns true if \a item1 is on top of \a item2. + + \internal +*/ +bool QGraphicsSceneBspTreeIndexPrivate::closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2) +{ + // Siblings? Just check their z-values. + const QGraphicsItemPrivate *d1 = item1->d_ptr; + const QGraphicsItemPrivate *d2 = item2->d_ptr; + if (d1->parent == d2->parent) + return qt_closestLeaf(item1, item2); + + // Find common ancestor, and each item's ancestor closest to the common + // ancestor. + int item1Depth = d1->depth; + int item2Depth = d2->depth; + const QGraphicsItem *p = item1; + const QGraphicsItem *t1 = item1; + while (item1Depth > item2Depth && (p = p->d_ptr->parent)) { + if (p == item2) { + // item2 is one of item1's ancestors; item1 is on top + return !(t1->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); + } + t1 = p; + --item1Depth; + } + p = item2; + const QGraphicsItem *t2 = item2; + while (item2Depth > item1Depth && (p = p->d_ptr->parent)) { + if (p == item1) { + // item1 is one of item2's ancestors; item1 is not on top + return (t2->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); + } + t2 = p; + --item2Depth; + } + + // item1Ancestor is now at the same level as item2Ancestor, but not the same. + const QGraphicsItem *a1 = t1; + const QGraphicsItem *a2 = t2; + while (a1) { + const QGraphicsItem *p1 = a1; + const QGraphicsItem *p2 = a2; + a1 = a1->parentItem(); + a2 = a2->parentItem(); + if (a1 && a1 == a2) + return qt_closestLeaf(p1, p2); + } + + // No common ancestor? Then just compare the items' toplevels directly. + return qt_closestLeaf(t1->topLevelItem(), t2->topLevelItem()); +} + +/*! + Returns true if \a item2 is on top of \a item1. + + \internal +*/ +bool QGraphicsSceneBspTreeIndexPrivate::closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2) +{ + return closestItemFirst_withoutCache(item2, item1); +} + +/*! + Sort a list of \a itemList in a specific \a order and use the cache if requested. + + \internal +*/ +void QGraphicsSceneBspTreeIndexPrivate::sortItems(QList *itemList, Qt::SortOrder order, + bool sortCacheEnabled) +{ + if (sortCacheEnabled) { + if (order == Qt::AscendingOrder) { + qSort(itemList->begin(), itemList->end(), closestItemFirst_withCache); + } else if (order == Qt::DescendingOrder) { + qSort(itemList->begin(), itemList->end(), closestItemLast_withCache); + } + } else { + if (order == Qt::AscendingOrder) { + qSort(itemList->begin(), itemList->end(), closestItemFirst_withoutCache); + } else if (order == Qt::DescendingOrder) { + qSort(itemList->begin(), itemList->end(), closestItemLast_withoutCache); + } + } +} + +/*! + Constructs a BSP scene index for the given \a scene. +*/ +QGraphicsSceneBspTreeIndex::QGraphicsSceneBspTreeIndex(QGraphicsScene *scene) + : QGraphicsSceneIndex(*new QGraphicsSceneBspTreeIndexPrivate(scene), scene) +{ + +} + +/*! + \reimp + Return the rect indexed by the BSP index. +*/ +QRectF QGraphicsSceneBspTreeIndex::indexedRect() const +{ + Q_D(const QGraphicsSceneBspTreeIndex); + const_cast(d)->_q_updateIndex(); + return scene()->d_func()->hasSceneRect ? scene()->d_func()->sceneRect : scene()->d_func()->growingItemsBoundingRect; +} + +/*! + \reimp + Clear the all the BSP index. +*/ +void QGraphicsSceneBspTreeIndex::clear() +{ + Q_D(QGraphicsSceneBspTreeIndex); + d->bsp.clear(); + d->lastItemCount = 0; + d->freeItemIndexes.clear(); + d->indexedItems.clear(); + d->unindexedItems.clear(); +} + +/*! + Add the \a item into the BSP index. +*/ +void QGraphicsSceneBspTreeIndex::addItem(QGraphicsItem *item) +{ + Q_D(QGraphicsSceneBspTreeIndex); + // Prevent reusing a recently deleted pointer: purge all removed items + // from our lists. + d->purgeRemovedItems(); + + // Invalidate any sort caching; arrival of a new item means we need to + // resort. + // Update the scene's sort cache settings. + item->d_ptr->globalStackingOrder = -1; + d->invalidateSortCache(); + + // Indexing requires sceneBoundingRect(), but because \a item might + // not be completely constructed at this point, we need to store it in + // a temporary list and schedule an indexing for later. + d->unindexedItems << item; + item->d_func()->index = -1; + d->startIndexTimer(0); +} + +/*! + This really add the item in the BSP. + \internal +*/ +void QGraphicsSceneBspTreeIndexPrivate::addToIndex(QGraphicsItem *item) +{ + if (item->d_func()->index != -1) { + bsp.insertItem(item, item->sceneBoundingRect()); + foreach (QGraphicsItem *child, item->children()) + child->addToIndex(); + } else { + // The BSP tree is regenerated if the number of items grows to a + // certain threshold, or if the bounding rect of the graph doubles in + // size. + startIndexTimer(); + } +} + +/*! + Remove the \a item from the BSP index. +*/ +void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item) +{ + Q_D(QGraphicsSceneBspTreeIndex); + // Note: This will access item's sceneBoundingRect(), which (as this is + // C++) is why we cannot call removeItem() from QGraphicsItem's + // destructor. + d->removeFromIndex(item); + + // Invalidate any sort caching; arrival of a new item means we need to + // resort. + d->invalidateSortCache(); + + // Remove from our item lists. + int index = item->d_func()->index; + if (index != -1) { + d->freeItemIndexes << index; + d->indexedItems[index] = 0; + } else { + d->unindexedItems.removeAll(item); + } +} + +/*! + \reimp + Delete the \a item from the BSP index (without accessing its boundingRect). +*/ +void QGraphicsSceneBspTreeIndex::deleteItem(QGraphicsItem *item) +{ + Q_D(QGraphicsSceneBspTreeIndex); + // Invalidate any sort caching; arrival of a new item means we need to + // resort. + d->invalidateSortCache(); + + int index = item->d_func()->index; + if (index != -1) { + // Important: The index is useless until purgeRemovedItems() is + // called. + d->indexedItems[index] = (QGraphicsItem *)0; + if (!d->purgePending) { + d->purgePending = true; + scene()->update(); + } + d->removedItems << item; + } else { + // Recently added items are purged immediately. unindexedItems() never + // contains stale items. + d->unindexedItems.removeAll(item); + scene()->update(); + } +} + +/*! + Really remove the item from the BSP + \internal +*/ +void QGraphicsSceneBspTreeIndexPrivate::removeFromIndex(QGraphicsItem *item) +{ + if (item->d_func()->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { + // ### remove from child index only if applicable + return; + } + int index = item->d_func()->index; + if (index != -1) { + bsp.removeItem(item, item->sceneBoundingRect()); + freeItemIndexes << index; + indexedItems[index] = 0; + item->d_func()->index = -1; + unindexedItems << item; + + //prepareGeometryChange will call prepareBoundingRectChange + foreach (QGraphicsItem *child, item->children()) + child->prepareGeometryChange(); + } + startIndexTimer(); +} + +/*! + \reimp + Update the BSP when the \a item 's bounding rect has changed. +*/ +void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem *item) +{ + Q_D(QGraphicsSceneBspTreeIndex); + // Note: This will access item's sceneBoundingRect(), which (as this is + // C++) is why we cannot call removeItem() from QGraphicsItem's + // destructor. + d->removeFromIndex(const_cast(item)); +} + +/*! + Returns an estimation visible items that are either inside or + intersect with the specified \a rect and return a list sorted using \a order. + + \a deviceTransform is the transformation apply to the view. + +*/ +QList QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const +{ + Q_D(const QGraphicsSceneBspTreeIndex); + const_cast(d)->purgeRemovedItems(); + const_cast(d)->_q_updateSortCache(); + + QList rectItems = d->bsp.items(rect); + // Fill in with any unindexed items + for (int i = 0; i < d->unindexedItems.size(); ++i) { + if (QGraphicsItem *item = d->unindexedItems.at(i)) { + if (!item->d_ptr->itemDiscovered && item->d_ptr->visible && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { + QRectF boundingRect = item->sceneBoundingRect(); + if (QRectF_intersects(boundingRect, rect)) { + item->d_ptr->itemDiscovered = 1; + rectItems << item; + } + } + } + } + + // Reset the discovered state of all discovered items + for (int i = 0; i < rectItems.size(); ++i) + rectItems.at(i)->d_func()->itemDiscovered = 0; + + d->sortItems(&rectItems, order, d->sortCacheEnabled); + + return rectItems; +} + + +/*! + \fn QList QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order = Qt::AscendingOrder) const; + + Return all items in the BSP index and sort them using \a order. +*/ +QList QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order) const +{ + Q_D(const QGraphicsSceneBspTreeIndex); + const_cast(d)->purgeRemovedItems(); + QList itemList; + // If freeItemIndexes is empty, we know there are no holes in indexedItems and + // unindexedItems. + if (d->freeItemIndexes.isEmpty()) { + if (d->unindexedItems.isEmpty()) { + itemList = d->indexedItems; + } else { + itemList = d->indexedItems + d->unindexedItems; + } + } else { + // Rebuild the list of items to avoid holes. ### We could also just + // compress the item lists at this point. + foreach (QGraphicsItem *item, d->indexedItems + d->unindexedItems) { + if (item) + itemList << item; + } + } + if (order != -1) { + //We sort descending order + d->sortItems(&itemList, order, d->sortCacheEnabled); + } + return itemList; +} + +/*! + \property QGraphicsSceneBspTreeIndex::bspTreeDepth + \brief the depth of the BSP index tree + \since 4.6 + + This value determines the depth of BSP tree. The depth + directly affects performance and memory usage; the latter + growing exponentially with the depth of the tree. With an optimal tree + depth, the index can instantly determine the locality of items, even + for scenes with thousands or millions of items. This also greatly improves + rendering performance. + + By default, the value is 0, in which case Qt will guess a reasonable + default depth based on the size, location and number of items in the + scene. If these parameters change frequently, however, you may experience + slowdowns as the index retunes the depth internally. You can avoid + potential slowdowns by fixating the tree depth through setting this + property. + + The depth of the tree and the size of the scene rectangle decide the + granularity of the scene's partitioning. The size of each scene segment is + determined by the following algorithm: + + The BSP tree has an optimal size when each segment contains between 0 and + 10 items. + +*/ +int QGraphicsSceneBspTreeIndex::bspTreeDepth() +{ + Q_D(const QGraphicsSceneBspTreeIndex); + return d->bspTreeDepth; +} + +void QGraphicsSceneBspTreeIndex::setBspTreeDepth(int depth) +{ + Q_D(QGraphicsSceneBspTreeIndex); + d->bspTreeDepth = depth; + d->resetIndex(); +} + +/*! + \reimp + + This method react to the \a rect change of the scene and + reset the BSP tree index. +*/ +void QGraphicsSceneBspTreeIndex::sceneRectChanged(const QRectF &rect) +{ + Q_D(QGraphicsSceneBspTreeIndex); + d->sceneRect = rect; + d->resetIndex(); +} + +/*! + \reimp + + This method react to the \a change of the \a item and use the \a value to + update the BSP tree if necessary. + +*/ +void QGraphicsSceneBspTreeIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value) +{ + Q_D(QGraphicsSceneBspTreeIndex); + switch (change) { + case QGraphicsItem::ItemZValueChange: + case QGraphicsItem::ItemParentChange: { + d->invalidateSortCache(); + break; + } + default: + break; + } + return QGraphicsSceneIndex::itemChanged(item, change, value); +} +/*! + \reimp + + Used to catch the timer event. + + \internal +*/ +bool QGraphicsSceneBspTreeIndex::event(QEvent *event) +{ + Q_D(QGraphicsSceneBspTreeIndex); + switch (event->type()) { + case QEvent::Timer: + if (d->indexTimerId && static_cast(event)->timerId() == d->indexTimerId) { + if (d->restartIndexTimer) { + d->restartIndexTimer = false; + } else { + // this call will kill the timer + d->_q_updateIndex(); + } + } + // Fallthrough intended - support timers in subclasses. + default: + return QObject::event(event); + } + return true; +} + +QT_END_NAMESPACE + +#include "moc_qgraphicsscenebsptreeindex.cpp" + +#endif // QT_NO_GRAPHICSVIEW + diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex.h new file mode 100644 index 0000000..0444a30 --- /dev/null +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.h @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + +#ifndef QGRAPHICSBSPTREEINDEX_H +#define QGRAPHICSBSPTREEINDEX_H + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW + +#include +#include +#include +#include +#include + +#include "qgraphicsscene_bsp_p.h" + +class QGraphicsSceneBspTreeIndexPrivate; + +class Q_AUTOTEST_EXPORT QGraphicsSceneBspTreeIndex : public QGraphicsSceneIndex +{ + Q_OBJECT + Q_PROPERTY(int bspTreeDepth READ bspTreeDepth WRITE setBspTreeDepth) +public: + QGraphicsSceneBspTreeIndex(QGraphicsScene *scene = 0); + QRectF indexedRect() const; + + QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const; + + QList items(Qt::SortOrder order = Qt::AscendingOrder) const; + + int bspTreeDepth(); + void setBspTreeDepth(int depth); + +protected: + bool event(QEvent *event); + void clear(); + + void addItem(QGraphicsItem *item); + void removeItem(QGraphicsItem *item); + void deleteItem(QGraphicsItem *item); + void prepareBoundingRectChange(const QGraphicsItem *item); + + void sceneRectChanged(const QRectF &rect); + void itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value); + +private : + Q_DECLARE_PRIVATE(QGraphicsSceneBspTreeIndex) + Q_DISABLE_COPY(QGraphicsSceneBspTreeIndex) + Q_PRIVATE_SLOT(d_func(), void _q_updateSortCache()) + Q_PRIVATE_SLOT(d_func(), void _q_updateIndex()) + + friend class QGraphicsScene; + friend class QGraphicsScenePrivate; +}; + +#endif // QT_NO_GRAPHICSVIEW + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGRAPHICSBSPTREEINDEX_H diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp deleted file mode 100644 index b19248a..0000000 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp +++ /dev/null @@ -1,760 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \class QGraphicsSceneBspTreeIndex - \brief The QGraphicsSceneBspTreeIndex class provides an implementation of - a BSP indexing algorithm for discovering items in QGraphicsScene. - \since 4.6 - \ingroup multimedia - \ingroup graphicsview-api - \mainclass - - QGraphicsSceneBspTreeIndex index use a BSP(Binary Space Partitioning) - implementation to discover items quickly. This implementation is - very efficient for static scene. It has a depth that you can set. - The depth directly affects performance and memory usage; the latter - growing exponentially with the depth of the tree. With an optimal tree - depth, the index can instantly determine the locality of items, even - for scenes with thousands or millions of items. This also greatly improves - rendering performance. - - By default, the value is 0, in which case Qt will guess a reasonable - default depth based on the size, location and number of items in the - scene. If these parameters change frequently, however, you may experience - slowdowns as the index retunes the depth internally. You can avoid - potential slowdowns by fixating the tree depth through setting this - property. - - The depth of the tree and the size of the scene rectangle decide the - granularity of the scene's partitioning. The size of each scene segment is - determined by the following algorithm: - - The BSP tree has an optimal size when each segment contains between 0 and - 10 items. - - \sa QGraphicsScene, QGraphicsView, QGraphicsSceneIndex -*/ - -#include "qgraphicsscenebsptreeindex_p.h" - -#ifndef QT_NO_GRAPHICSVIEW - -#include "qgraphicsscenebsptreeindex_p_p.h" -#include "qgraphicssceneindex_p.h" -#include "qgraphicsitem_p.h" -#include "qgraphicsscene_p.h" - -#include - -#include - -QT_BEGIN_NAMESPACE - -static inline int intmaxlog(int n) -{ - return (n > 0 ? qMax(qCeil(qLn(qreal(n)) / qLn(qreal(2))), 5) : 0); -} - -/*! - Constructs a private scene bsp index. -*/ -QGraphicsSceneBspTreeIndexPrivate::QGraphicsSceneBspTreeIndexPrivate(QGraphicsScene *scene) - : QGraphicsSceneIndexPrivate(scene), - bspTreeDepth(0), - indexTimerId(0), - restartIndexTimer(false), - regenerateIndex(true), - lastItemCount(0), - purgePending(false), - sortCacheEnabled(false), - updatingSortCache(false) -{ -} - - -/*! - This method will update the BSP index by removing the items from the temporary - unindexed list and add them in the indexedItems list. This will also - update the growingItemsBoundingRect if needed. This will update the BSP - implementation as well. - - \internal -*/ -void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() -{ - Q_Q(QGraphicsSceneBspTreeIndex); - if (!indexTimerId) - return; - - QGraphicsScenePrivate * scenePrivate = q->scene()->d_func(); - q->killTimer(indexTimerId); - indexTimerId = 0; - - purgeRemovedItems(); - - // Add unindexedItems to indexedItems - QRectF unindexedItemsBoundingRect; - for (int i = 0; i < unindexedItems.size(); ++i) { - if (QGraphicsItem *item = unindexedItems.at(i)) { - unindexedItemsBoundingRect |= item->sceneBoundingRect(); - if (!freeItemIndexes.isEmpty()) { - int freeIndex = freeItemIndexes.takeFirst(); - item->d_func()->index = freeIndex; - indexedItems[freeIndex] = item; - } else { - item->d_func()->index = indexedItems.size(); - indexedItems << item; - } - } - } - - // Update growing scene rect. - QRectF oldGrowingItemsBoundingRect = scenePrivate->growingItemsBoundingRect; - scenePrivate->growingItemsBoundingRect |= unindexedItemsBoundingRect; - - // Determine whether we should regenerate the BSP tree. - if (bspTreeDepth == 0) { - int oldDepth = intmaxlog(lastItemCount); - bspTreeDepth = intmaxlog(indexedItems.size()); - static const int slack = 100; - if (bsp.leafCount() == 0 || (oldDepth != bspTreeDepth && qAbs(lastItemCount - indexedItems.size()) > slack)) { - // ### Crude algorithm. - regenerateIndex = true; - } - } - - // Regenerate the tree. - if (regenerateIndex) { - regenerateIndex = false; - bsp.initialize(q->scene()->sceneRect(), bspTreeDepth); - unindexedItems = indexedItems; - lastItemCount = indexedItems.size(); - q->scene()->update(); - - // Take this opportunity to reset our largest-item counter for - // untransformable items. When the items are inserted into the BSP - // tree, we'll get an accurate calculation. - scenePrivate->largestUntransformableItem = QRectF(); - } - - // Insert all unindexed items into the tree. - for (int i = 0; i < unindexedItems.size(); ++i) { - if (QGraphicsItem *item = unindexedItems.at(i)) { - QRectF rect = item->sceneBoundingRect(); - if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) - continue; - - bsp.insertItem(item, rect); - - // If the item ignores view transformations, update our - // largest-item-counter to ensure that the view can accurately - // discover untransformable items when drawing. - if (item->d_ptr->itemIsUntransformable()) { - QGraphicsItem *topmostUntransformable = item; - while (topmostUntransformable && (topmostUntransformable->d_ptr->ancestorFlags - & QGraphicsItemPrivate::AncestorIgnoresTransformations)) { - topmostUntransformable = topmostUntransformable->parentItem(); - } - // ### Verify that this is the correct largest untransformable rectangle. - scenePrivate->largestUntransformableItem |= item->mapToItem(topmostUntransformable, item->boundingRect()).boundingRect(); - } - } - } - unindexedItems.clear(); - - // Notify scene rect changes. - if (!scenePrivate->hasSceneRect && scenePrivate->growingItemsBoundingRect != oldGrowingItemsBoundingRect) - emit q->scene()->sceneRectChanged(scenePrivate->growingItemsBoundingRect); -} - - -/*! - \internal - - Removes stale pointers from all data structures. -*/ -void QGraphicsSceneBspTreeIndexPrivate::purgeRemovedItems() -{ - if (!purgePending && removedItems.isEmpty()) - return; - - // Remove stale items from the BSP tree. - bsp.removeItems(removedItems); - // Purge this list. - removedItems.clear(); - freeItemIndexes.clear(); - for (int i = 0; i < indexedItems.size(); ++i) { - if (!indexedItems.at(i)) - freeItemIndexes << i; - } - purgePending = false; -} - -/*! - \internal - - Starts or restarts the timer used for reindexing unindexed items. -*/ -void QGraphicsSceneBspTreeIndexPrivate::startIndexTimer(int interval) -{ - Q_Q(QGraphicsSceneBspTreeIndex); - if (indexTimerId) { - restartIndexTimer = true; - } else { - indexTimerId = q->startTimer(interval); - } -} - -/*! - \internal -*/ -void QGraphicsSceneBspTreeIndexPrivate::resetIndex() -{ - purgeRemovedItems(); - for (int i = 0; i < indexedItems.size(); ++i) { - if (QGraphicsItem *item = indexedItems.at(i)) { - item->d_ptr->index = -1; - unindexedItems << item; - } - } - indexedItems.clear(); - freeItemIndexes.clear(); - regenerateIndex = true; - startIndexTimer(); -} - -/*! - \internal -*/ -void QGraphicsSceneBspTreeIndexPrivate::climbTree(QGraphicsItem *item, int *stackingOrder) -{ - if (!item->d_ptr->children.isEmpty()) { - QList childList = item->d_ptr->children; - qSort(childList.begin(), childList.end(), qt_closestLeaf); - for (int i = 0; i < childList.size(); ++i) { - QGraphicsItem *item = childList.at(i); - if (!(item->flags() & QGraphicsItem::ItemStacksBehindParent)) - climbTree(childList.at(i), stackingOrder); - } - item->d_ptr->globalStackingOrder = (*stackingOrder)++; - for (int i = 0; i < childList.size(); ++i) { - QGraphicsItem *item = childList.at(i); - if (item->flags() & QGraphicsItem::ItemStacksBehindParent) - climbTree(childList.at(i), stackingOrder); - } - } else { - item->d_ptr->globalStackingOrder = (*stackingOrder)++; - } -} - -/*! - \internal -*/ -void QGraphicsSceneBspTreeIndexPrivate::_q_updateSortCache() -{ - Q_Q(QGraphicsSceneBspTreeIndex); - _q_updateIndex(); - - if (!sortCacheEnabled || !updatingSortCache) - return; - - updatingSortCache = false; - int stackingOrder = 0; - - QList topLevels; - - for (int i = 0; i < q->items().count(); ++i) { - QGraphicsItem *item = q->items().at(i); - if (item && item->parentItem() == 0) - topLevels << item; - } - - qSort(topLevels.begin(), topLevels.end(), qt_closestLeaf); - for (int i = 0; i < topLevels.size(); ++i) - climbTree(topLevels.at(i), &stackingOrder); -} - -/*! - \internal -*/ -void QGraphicsSceneBspTreeIndexPrivate::invalidateSortCache() -{ - Q_Q(QGraphicsSceneBspTreeIndex); - if (!sortCacheEnabled || updatingSortCache) - return; - - updatingSortCache = true; - QMetaObject::invokeMethod(q, "_q_updateSortCache", Qt::QueuedConnection); -} - -/*! - Returns true if \a item1 is on top of \a item2. - - \internal -*/ -bool QGraphicsSceneBspTreeIndexPrivate::closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2) -{ - // Siblings? Just check their z-values. - const QGraphicsItemPrivate *d1 = item1->d_ptr; - const QGraphicsItemPrivate *d2 = item2->d_ptr; - if (d1->parent == d2->parent) - return qt_closestLeaf(item1, item2); - - // Find common ancestor, and each item's ancestor closest to the common - // ancestor. - int item1Depth = d1->depth; - int item2Depth = d2->depth; - const QGraphicsItem *p = item1; - const QGraphicsItem *t1 = item1; - while (item1Depth > item2Depth && (p = p->d_ptr->parent)) { - if (p == item2) { - // item2 is one of item1's ancestors; item1 is on top - return !(t1->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); - } - t1 = p; - --item1Depth; - } - p = item2; - const QGraphicsItem *t2 = item2; - while (item2Depth > item1Depth && (p = p->d_ptr->parent)) { - if (p == item1) { - // item1 is one of item2's ancestors; item1 is not on top - return (t2->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); - } - t2 = p; - --item2Depth; - } - - // item1Ancestor is now at the same level as item2Ancestor, but not the same. - const QGraphicsItem *a1 = t1; - const QGraphicsItem *a2 = t2; - while (a1) { - const QGraphicsItem *p1 = a1; - const QGraphicsItem *p2 = a2; - a1 = a1->parentItem(); - a2 = a2->parentItem(); - if (a1 && a1 == a2) - return qt_closestLeaf(p1, p2); - } - - // No common ancestor? Then just compare the items' toplevels directly. - return qt_closestLeaf(t1->topLevelItem(), t2->topLevelItem()); -} - -/*! - Returns true if \a item2 is on top of \a item1. - - \internal -*/ -bool QGraphicsSceneBspTreeIndexPrivate::closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2) -{ - return closestItemFirst_withoutCache(item2, item1); -} - -/*! - Sort a list of \a itemList in a specific \a order and use the cache if requested. - - \internal -*/ -void QGraphicsSceneBspTreeIndexPrivate::sortItems(QList *itemList, Qt::SortOrder order, - bool sortCacheEnabled) -{ - if (sortCacheEnabled) { - if (order == Qt::AscendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemFirst_withCache); - } else if (order == Qt::DescendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemLast_withCache); - } - } else { - if (order == Qt::AscendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemFirst_withoutCache); - } else if (order == Qt::DescendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemLast_withoutCache); - } - } -} - -/*! - Constructs a BSP scene index for the given \a scene. -*/ -QGraphicsSceneBspTreeIndex::QGraphicsSceneBspTreeIndex(QGraphicsScene *scene) - : QGraphicsSceneIndex(*new QGraphicsSceneBspTreeIndexPrivate(scene), scene) -{ - -} - -/*! - \reimp - Return the rect indexed by the BSP index. -*/ -QRectF QGraphicsSceneBspTreeIndex::indexedRect() const -{ - Q_D(const QGraphicsSceneBspTreeIndex); - const_cast(d)->_q_updateIndex(); - return scene()->d_func()->hasSceneRect ? scene()->d_func()->sceneRect : scene()->d_func()->growingItemsBoundingRect; -} - -/*! - \reimp - Clear the all the BSP index. -*/ -void QGraphicsSceneBspTreeIndex::clear() -{ - Q_D(QGraphicsSceneBspTreeIndex); - d->bsp.clear(); - d->lastItemCount = 0; - d->freeItemIndexes.clear(); - d->indexedItems.clear(); - d->unindexedItems.clear(); -} - -/*! - Add the \a item into the BSP index. -*/ -void QGraphicsSceneBspTreeIndex::addItem(QGraphicsItem *item) -{ - Q_D(QGraphicsSceneBspTreeIndex); - // Prevent reusing a recently deleted pointer: purge all removed items - // from our lists. - d->purgeRemovedItems(); - - // Invalidate any sort caching; arrival of a new item means we need to - // resort. - // Update the scene's sort cache settings. - item->d_ptr->globalStackingOrder = -1; - d->invalidateSortCache(); - - // Indexing requires sceneBoundingRect(), but because \a item might - // not be completely constructed at this point, we need to store it in - // a temporary list and schedule an indexing for later. - d->unindexedItems << item; - item->d_func()->index = -1; - d->startIndexTimer(0); -} - -/*! - This really add the item in the BSP. - \internal -*/ -void QGraphicsSceneBspTreeIndexPrivate::addToIndex(QGraphicsItem *item) -{ - if (item->d_func()->index != -1) { - bsp.insertItem(item, item->sceneBoundingRect()); - foreach (QGraphicsItem *child, item->children()) - child->addToIndex(); - } else { - // The BSP tree is regenerated if the number of items grows to a - // certain threshold, or if the bounding rect of the graph doubles in - // size. - startIndexTimer(); - } -} - -/*! - Remove the \a item from the BSP index. -*/ -void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item) -{ - Q_D(QGraphicsSceneBspTreeIndex); - // Note: This will access item's sceneBoundingRect(), which (as this is - // C++) is why we cannot call removeItem() from QGraphicsItem's - // destructor. - d->removeFromIndex(item); - - // Invalidate any sort caching; arrival of a new item means we need to - // resort. - d->invalidateSortCache(); - - // Remove from our item lists. - int index = item->d_func()->index; - if (index != -1) { - d->freeItemIndexes << index; - d->indexedItems[index] = 0; - } else { - d->unindexedItems.removeAll(item); - } -} - -/*! - \reimp - Delete the \a item from the BSP index (without accessing its boundingRect). -*/ -void QGraphicsSceneBspTreeIndex::deleteItem(QGraphicsItem *item) -{ - Q_D(QGraphicsSceneBspTreeIndex); - // Invalidate any sort caching; arrival of a new item means we need to - // resort. - d->invalidateSortCache(); - - int index = item->d_func()->index; - if (index != -1) { - // Important: The index is useless until purgeRemovedItems() is - // called. - d->indexedItems[index] = (QGraphicsItem *)0; - if (!d->purgePending) { - d->purgePending = true; - scene()->update(); - } - d->removedItems << item; - } else { - // Recently added items are purged immediately. unindexedItems() never - // contains stale items. - d->unindexedItems.removeAll(item); - scene()->update(); - } -} - -/*! - Really remove the item from the BSP - \internal -*/ -void QGraphicsSceneBspTreeIndexPrivate::removeFromIndex(QGraphicsItem *item) -{ - if (item->d_func()->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { - // ### remove from child index only if applicable - return; - } - int index = item->d_func()->index; - if (index != -1) { - bsp.removeItem(item, item->sceneBoundingRect()); - freeItemIndexes << index; - indexedItems[index] = 0; - item->d_func()->index = -1; - unindexedItems << item; - - //prepareGeometryChange will call prepareBoundingRectChange - foreach (QGraphicsItem *child, item->children()) - child->prepareGeometryChange(); - } - startIndexTimer(); -} - -/*! - \reimp - Update the BSP when the \a item 's bounding rect has changed. -*/ -void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem *item) -{ - Q_D(QGraphicsSceneBspTreeIndex); - // Note: This will access item's sceneBoundingRect(), which (as this is - // C++) is why we cannot call removeItem() from QGraphicsItem's - // destructor. - d->removeFromIndex(const_cast(item)); -} - -/*! - Returns an estimation visible items that are either inside or - intersect with the specified \a rect and return a list sorted using \a order. - - \a deviceTransform is the transformation apply to the view. - -*/ -QList QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const -{ - Q_D(const QGraphicsSceneBspTreeIndex); - const_cast(d)->purgeRemovedItems(); - const_cast(d)->_q_updateSortCache(); - - QList rectItems = d->bsp.items(rect); - // Fill in with any unindexed items - for (int i = 0; i < d->unindexedItems.size(); ++i) { - if (QGraphicsItem *item = d->unindexedItems.at(i)) { - if (!item->d_ptr->itemDiscovered && item->d_ptr->visible && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { - QRectF boundingRect = item->sceneBoundingRect(); - if (QRectF_intersects(boundingRect, rect)) { - item->d_ptr->itemDiscovered = 1; - rectItems << item; - } - } - } - } - - // Reset the discovered state of all discovered items - for (int i = 0; i < rectItems.size(); ++i) - rectItems.at(i)->d_func()->itemDiscovered = 0; - - d->sortItems(&rectItems, order, d->sortCacheEnabled); - - return rectItems; -} - - -/*! - \fn QList QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order = Qt::AscendingOrder) const; - - Return all items in the BSP index and sort them using \a order. -*/ -QList QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order) const -{ - Q_D(const QGraphicsSceneBspTreeIndex); - const_cast(d)->purgeRemovedItems(); - QList itemList; - // If freeItemIndexes is empty, we know there are no holes in indexedItems and - // unindexedItems. - if (d->freeItemIndexes.isEmpty()) { - if (d->unindexedItems.isEmpty()) { - itemList = d->indexedItems; - } else { - itemList = d->indexedItems + d->unindexedItems; - } - } else { - // Rebuild the list of items to avoid holes. ### We could also just - // compress the item lists at this point. - foreach (QGraphicsItem *item, d->indexedItems + d->unindexedItems) { - if (item) - itemList << item; - } - } - if (order != -1) { - //We sort descending order - d->sortItems(&itemList, order, d->sortCacheEnabled); - } - return itemList; -} - -/*! - \property QGraphicsSceneBspTreeIndex::bspTreeDepth - \brief the depth of the BSP index tree - \since 4.6 - - This value determines the depth of BSP tree. The depth - directly affects performance and memory usage; the latter - growing exponentially with the depth of the tree. With an optimal tree - depth, the index can instantly determine the locality of items, even - for scenes with thousands or millions of items. This also greatly improves - rendering performance. - - By default, the value is 0, in which case Qt will guess a reasonable - default depth based on the size, location and number of items in the - scene. If these parameters change frequently, however, you may experience - slowdowns as the index retunes the depth internally. You can avoid - potential slowdowns by fixating the tree depth through setting this - property. - - The depth of the tree and the size of the scene rectangle decide the - granularity of the scene's partitioning. The size of each scene segment is - determined by the following algorithm: - - The BSP tree has an optimal size when each segment contains between 0 and - 10 items. - -*/ -int QGraphicsSceneBspTreeIndex::bspTreeDepth() -{ - Q_D(const QGraphicsSceneBspTreeIndex); - return d->bspTreeDepth; -} - -void QGraphicsSceneBspTreeIndex::setBspTreeDepth(int depth) -{ - Q_D(QGraphicsSceneBspTreeIndex); - d->bspTreeDepth = depth; - d->resetIndex(); -} - -/*! - \reimp - - This method react to the \a rect change of the scene and - reset the BSP tree index. -*/ -void QGraphicsSceneBspTreeIndex::sceneRectChanged(const QRectF &rect) -{ - Q_D(QGraphicsSceneBspTreeIndex); - d->sceneRect = rect; - d->resetIndex(); -} - -/*! - \reimp - - This method react to the \a change of the \a item and use the \a value to - update the BSP tree if necessary. - -*/ -void QGraphicsSceneBspTreeIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value) -{ - Q_D(QGraphicsSceneBspTreeIndex); - switch (change) { - case QGraphicsItem::ItemZValueChange: - case QGraphicsItem::ItemParentChange: { - d->invalidateSortCache(); - break; - } - default: - break; - } - return QGraphicsSceneIndex::itemChanged(item, change, value); -} -/*! - \reimp - - Used to catch the timer event. - - \internal -*/ -bool QGraphicsSceneBspTreeIndex::event(QEvent *event) -{ - Q_D(QGraphicsSceneBspTreeIndex); - switch (event->type()) { - case QEvent::Timer: - if (d->indexTimerId && static_cast(event)->timerId() == d->indexTimerId) { - if (d->restartIndexTimer) { - d->restartIndexTimer = false; - } else { - // this call will kill the timer - d->_q_updateIndex(); - } - } - // Fallthrough intended - support timers in subclasses. - default: - return QObject::event(event); - } - return true; -} - -QT_END_NAMESPACE - -#include "moc_qgraphicsscenebsptreeindex_p.cpp" - -#endif // QT_NO_GRAPHICSVIEW - diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index 40b8f0b..6bafbc8 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -39,63 +39,112 @@ ** ****************************************************************************/ -#include - -#ifndef QGRAPHICSBSPTREEINDEX_H -#define QGRAPHICSBSPTREEINDEX_H +#ifndef QGRAPHICSSCENEBSPTREEINDEX_P_H +#define QGRAPHICSSCENEBSPTREEINDEX_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + +#include "qgraphicsscenebsptreeindex.h" #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW +#include +#include + QT_BEGIN_NAMESPACE -#include -#include -#include -#include -#include +static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; -#include "qgraphicsscene_bsp_p.h" +class QGraphicsScene; -class QGraphicsSceneBspTreeIndexPrivate; -class Q_AUTOTEST_EXPORT QGraphicsSceneBspTreeIndex : public QGraphicsSceneIndex +class QGraphicsSceneBspTreeIndexPrivate : public QGraphicsSceneIndexPrivate { - Q_OBJECT - Q_PROPERTY(int bspTreeDepth READ bspTreeDepth WRITE setBspTreeDepth) + Q_DECLARE_PUBLIC(QGraphicsSceneBspTreeIndex) public: - QGraphicsSceneBspTreeIndex(QGraphicsScene *scene = 0); - QRectF indexedRect() const; - - QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const; - - QList items(Qt::SortOrder order = Qt::AscendingOrder) const; - - int bspTreeDepth(); - void setBspTreeDepth(int depth); - -protected: - bool event(QEvent *event); - void clear(); - - void addItem(QGraphicsItem *item); - void removeItem(QGraphicsItem *item); - void deleteItem(QGraphicsItem *item); - void prepareBoundingRectChange(const QGraphicsItem *item); + QGraphicsSceneBspTreeIndexPrivate(QGraphicsScene *scene); + + QGraphicsSceneBspTree bsp; + QRectF sceneRect; + int bspTreeDepth; + int indexTimerId; + bool restartIndexTimer; + bool regenerateIndex; + int lastItemCount; + + QList indexedItems; + QList unindexedItems; + QList freeItemIndexes; + + bool purgePending; + QSet removedItems; + void purgeRemovedItems(); + + void _q_updateIndex(); + void startIndexTimer(int interval = QGRAPHICSSCENE_INDEXTIMER_TIMEOUT); + void resetIndex(); + + void addToIndex(QGraphicsItem *item); + void removeFromIndex(QGraphicsItem *item); + + void _q_updateSortCache(); + bool sortCacheEnabled; + bool updatingSortCache; + void invalidateSortCache(); + + static void climbTree(QGraphicsItem *item, int *stackingOrder); + static bool closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2); + static bool closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2); + + static inline bool closestItemFirst_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2) + { + return item1->d_ptr->globalStackingOrder < item2->d_ptr->globalStackingOrder; + } + static inline bool closestItemLast_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2) + { + return item1->d_ptr->globalStackingOrder >= item2->d_ptr->globalStackingOrder; + } + + static void sortItems(QList *itemList, Qt::SortOrder order, bool cached); +}; - void sceneRectChanged(const QRectF &rect); - void itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value); -private : - Q_DECLARE_PRIVATE(QGraphicsSceneBspTreeIndex) - Q_DISABLE_COPY(QGraphicsSceneBspTreeIndex) - Q_PRIVATE_SLOT(d_func(), void _q_updateSortCache()) - Q_PRIVATE_SLOT(d_func(), void _q_updateIndex()) +/*! + \internal +*/ +inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) +{ + // Return true if sibling item1 is on top of item2. + const QGraphicsItemPrivate *d1 = item1->d_ptr; + const QGraphicsItemPrivate *d2 = item2->d_ptr; + bool f1 = d1->flags & QGraphicsItem::ItemStacksBehindParent; + bool f2 = d2->flags & QGraphicsItem::ItemStacksBehindParent; + if (f1 != f2) return f2; + qreal z1 = d1->z; + qreal z2 = d2->z; + return z1 > z2; +} + +/*! + \internal +*/ +static inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) +{ + return qt_closestLeaf(item2, item1); +} - friend class QGraphicsScene; - friend class QGraphicsScenePrivate; -}; QT_END_NAMESPACE -#endif // QT_NO_GRAPHICSVIEW +#endif // QGRAPHICSSCENEBSPTREEINDEX_P_H + +#endif -#endif // QGRAPHICSBSPTREEINDEX_H diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h deleted file mode 100644 index 30f6e26..0000000 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h +++ /dev/null @@ -1,150 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSSCENEBSPTREEINDEX_P_P_H -#define QGRAPHICSSCENEBSPTREEINDEX_P_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header -// file may change from version to version without notice, or even be removed. -// -// We mean it. -// - -#include "qgraphicsscenebsptreeindex_p.h" - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -#include -#include - -QT_BEGIN_NAMESPACE - -static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; - -class QGraphicsScene; - -class QGraphicsSceneBspTreeIndexPrivate : public QGraphicsSceneIndexPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsSceneBspTreeIndex) -public: - QGraphicsSceneBspTreeIndexPrivate(QGraphicsScene *scene); - - QGraphicsSceneBspTree bsp; - QRectF sceneRect; - int bspTreeDepth; - int indexTimerId; - bool restartIndexTimer; - bool regenerateIndex; - int lastItemCount; - - QList indexedItems; - QList unindexedItems; - QList freeItemIndexes; - - bool purgePending; - QSet removedItems; - void purgeRemovedItems(); - - void _q_updateIndex(); - void startIndexTimer(int interval = QGRAPHICSSCENE_INDEXTIMER_TIMEOUT); - void resetIndex(); - - void addToIndex(QGraphicsItem *item); - void removeFromIndex(QGraphicsItem *item); - - void _q_updateSortCache(); - bool sortCacheEnabled; - bool updatingSortCache; - void invalidateSortCache(); - - static void climbTree(QGraphicsItem *item, int *stackingOrder); - static bool closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2); - static bool closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2); - - static inline bool closestItemFirst_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2) - { - return item1->d_ptr->globalStackingOrder < item2->d_ptr->globalStackingOrder; - } - static inline bool closestItemLast_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2) - { - return item1->d_ptr->globalStackingOrder >= item2->d_ptr->globalStackingOrder; - } - - static void sortItems(QList *itemList, Qt::SortOrder order, bool cached); -}; - - -/*! - \internal -*/ -inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) -{ - // Return true if sibling item1 is on top of item2. - const QGraphicsItemPrivate *d1 = item1->d_ptr; - const QGraphicsItemPrivate *d2 = item2->d_ptr; - bool f1 = d1->flags & QGraphicsItem::ItemStacksBehindParent; - bool f2 = d2->flags & QGraphicsItem::ItemStacksBehindParent; - if (f1 != f2) return f2; - qreal z1 = d1->z; - qreal z2 = d2->z; - return z1 > z2; -} - -/*! - \internal -*/ -static inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) -{ - return qt_closestLeaf(item2, item1); -} - - -QT_END_NAMESPACE - -#endif // QGRAPHICSSCENEBSPTREEINDEX_P_P_H - -#endif - diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 05ec28b..966d8fe 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -46,6 +46,7 @@ \ingroup multimedia \ingroup graphicsview-api \mainclass + \internal The QGraphicsSceneIndex class provides a base class to implement a custom indexing algorithm for discovering items in QGraphicsScene. You @@ -57,7 +58,6 @@ #include "qgraphicssceneindex.h" #include "qgraphicssceneindex_p.h" -#include "qgraphicsscenebsptreeindex_p_p.h" #include "qgraphicsscene.h" #include "qgraphicsitem_p.h" #include "qgraphicsscene_p.h" diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index 084a623..c0e415c 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -42,6 +42,17 @@ #ifndef QGRAPHICSSCENEINDEX_H #define QGRAPHICSSCENEINDEX_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + #include #include #include @@ -61,7 +72,7 @@ class QRectF; class QPointF; template class QList; -class Q_GUI_EXPORT QGraphicsSceneIndex: public QObject +class Q_AUTOTEST_EXPORT QGraphicsSceneIndex: public QObject { Q_OBJECT diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex.cpp b/src/gui/graphicsview/qgraphicsscenelinearindex.cpp index 1c898bc..5504493 100644 --- a/src/gui/graphicsview/qgraphicsscenelinearindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenelinearindex.cpp @@ -1,4 +1,4 @@ -#include "qgraphicsscenelinearindex_p.h" +#include "qgraphicsscenelinearindex.h" /*! \class QGraphicsSceneLinearIndex @@ -8,6 +8,7 @@ \ingroup multimedia \ingroup graphicsview-api \mainclass + \internal QGraphicsSceneLinearIndex index is default linear implementation to discover items. It basically store all items in a list and return them to the scene. diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex.h b/src/gui/graphicsview/qgraphicsscenelinearindex.h new file mode 100644 index 0000000..b793d98 --- /dev/null +++ b/src/gui/graphicsview/qgraphicsscenelinearindex.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSCENELINEARINDEX_H +#define QGRAPHICSSCENELINEARINDEX_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW + +#include +#include +#include +#include + +class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex +{ + Q_OBJECT + +public: + QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0): QGraphicsSceneIndex(scene) + { + } + + QList items(Qt::SortOrder order = Qt::AscendingOrder) const { + Q_UNUSED(order); + return m_items; + } + + virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const { + Q_UNUSED(rect); + Q_UNUSED(order); + Q_UNUSED(deviceTransform); + return m_items; + } + + virtual QRectF indexedRect() const { + return m_sceneRect; + } + +protected : + void sceneRectChanged(const QRectF &rect) { + m_sceneRect = rect; + } + + virtual void clear() { + m_items.clear(); + } + + virtual void addItem(QGraphicsItem *item) { + m_items << item; + } + + virtual void removeItem(QGraphicsItem *item) { + m_items.removeAll(item); + } + +private: + QRectF m_sceneRect; + QList m_items; +}; + +#endif // QT_NO_GRAPHICSVIEW + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGRAPHICSSCENELINEARINDEX_H diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h deleted file mode 100644 index d21475c..0000000 --- a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h +++ /dev/null @@ -1,118 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSSCENELINEARINDEX_P_H -#define QGRAPHICSSCENELINEARINDEX_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex -{ - Q_OBJECT - -public: - QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0): QGraphicsSceneIndex(scene) - { - } - - QList items(Qt::SortOrder order = Qt::AscendingOrder) const { - Q_UNUSED(order); - return m_items; - } - - virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const { - Q_UNUSED(rect); - Q_UNUSED(order); - Q_UNUSED(deviceTransform); - return m_items; - } - - virtual QRectF indexedRect() const { - return m_sceneRect; - } - -protected : - void sceneRectChanged(const QRectF &rect) { - m_sceneRect = rect; - } - - virtual void clear() { - m_items.clear(); - } - - virtual void addItem(QGraphicsItem *item) { - m_items << item; - } - - virtual void removeItem(QGraphicsItem *item) { - m_items.removeAll(item); - } - -private: - QRectF m_sceneRect; - QList m_items; -}; - -QT_END_NAMESPACE - -#endif // QT_NO_GRAPHICSVIEW - -#endif // QGRAPHICSSCENELINEARINDEX_P_H -- cgit v0.12 From 5d682567d1acb79b2fa55ae8f005c5dcdc9aacb7 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Wed, 17 Jun 2009 14:27:46 +0200 Subject: API / code review for QGraphicsSceneIndex (internal API). A few minor modifications only, marked some things as ### obsolete, removed the public get/set for the index (it's internal anyway). --- src/gui/graphicsview/qgraphicsitem.h | 48 ++++++------ src/gui/graphicsview/qgraphicsscene.cpp | 90 ++++------------------ src/gui/graphicsview/qgraphicsscene.h | 11 +-- src/gui/graphicsview/qgraphicsscene_p.h | 40 ---------- .../graphicsview/qgraphicsscenebsptreeindex.cpp | 6 +- .../graphicsview/qgraphicsscenebsptreeindex_p.h | 40 ++++++++++ 6 files changed, 86 insertions(+), 149 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index ec16d26..12dcad2 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -141,7 +141,7 @@ public: QGraphicsItem(QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); @@ -208,8 +208,8 @@ public: Qt::MouseButtons acceptedMouseButtons() const; void setAcceptedMouseButtons(Qt::MouseButtons buttons); - bool acceptsHoverEvents() const; // obsolete - void setAcceptsHoverEvents(bool enabled); // obsolete + bool acceptsHoverEvents() const; // ### obsolete + void setAcceptsHoverEvents(bool enabled); // ### obsolete bool acceptHoverEvents() const; void setAcceptHoverEvents(bool enabled); @@ -534,7 +534,7 @@ class Q_GUI_EXPORT QAbstractGraphicsShapeItem : public QGraphicsItem public: QAbstractGraphicsShapeItem(QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); @@ -564,13 +564,13 @@ class Q_GUI_EXPORT QGraphicsPathItem : public QAbstractGraphicsShapeItem public: QGraphicsPathItem(QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); QGraphicsPathItem(const QPainterPath &path, QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); @@ -607,19 +607,19 @@ class Q_GUI_EXPORT QGraphicsRectItem : public QAbstractGraphicsShapeItem public: QGraphicsRectItem(QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); QGraphicsRectItem(const QRectF &rect, QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); QGraphicsRectItem(qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); @@ -660,19 +660,19 @@ class Q_GUI_EXPORT QGraphicsEllipseItem : public QAbstractGraphicsShapeItem public: QGraphicsEllipseItem(QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); QGraphicsEllipseItem(const QRectF &rect, QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); QGraphicsEllipseItem(qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); @@ -719,14 +719,14 @@ class Q_GUI_EXPORT QGraphicsPolygonItem : public QAbstractGraphicsShapeItem public: QGraphicsPolygonItem(QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); QGraphicsPolygonItem(const QPolygonF &polygon, QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); @@ -766,19 +766,19 @@ class Q_GUI_EXPORT QGraphicsLineItem : public QGraphicsItem public: QGraphicsLineItem(QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); QGraphicsLineItem(const QLineF &line, QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); QGraphicsLineItem(qreal x1, qreal y1, qreal x2, qreal y2, QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); @@ -826,13 +826,13 @@ public: QGraphicsPixmapItem(QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); QGraphicsPixmapItem(const QPixmap &pixmap, QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); @@ -888,13 +888,13 @@ class Q_GUI_EXPORT QGraphicsTextItem : public QGraphicsObject public: QGraphicsTextItem(QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); QGraphicsTextItem(const QString &text, QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); @@ -989,13 +989,13 @@ class Q_GUI_EXPORT QGraphicsSimpleTextItem : public QAbstractGraphicsShapeItem public: QGraphicsSimpleTextItem(QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); QGraphicsSimpleTextItem(const QString &text, QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); @@ -1035,7 +1035,7 @@ class Q_GUI_EXPORT QGraphicsItemGroup : public QGraphicsItem public: QGraphicsItemGroup(QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index a33cb3e..dacfc87 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -201,8 +201,6 @@ however, is done in constant time. This approach is ideal for dynamic scenes, where many items are added, moved or removed continuously. - \omitvalue CustomIndex - \sa setItemIndexMethod(), bspTreeDepth */ @@ -1529,85 +1527,19 @@ QGraphicsScene::ItemIndexMethod QGraphicsScene::itemIndexMethod() const Q_D(const QGraphicsScene); return d->indexMethod; } - -// Possibilities -// NoIndex -> CustomIndex : warning -// BspTreeIndex -> CustomIndex : warning -// CustomIndex -> CustomIndex : warning -// NoIndex -> BspTreeIndex : create an empty BSP if necessary -// BspTreeIndex -> BspTreeIndex : nothing -// CustomIndex -> BspTreeIndex : create BSP and transfer items -// NoIndex -> NoIndex : nothing -// BspTreeIndex -> NoIndex : nothing -// CustomIndex -> NoIndex : create BSP tree but do not populate void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) { Q_D(QGraphicsScene); - if (method == CustomIndex) { - qWarning("QGraphicsScene: Invalid index type %d", CustomIndex); + if (d->indexMethod == method) return; - } - if (d->indexMethod == method) { - return; - } - if (d->indexMethod == NoIndex && method == BspTreeIndex) { - QGraphicsSceneBspTreeIndex *tree = qobject_cast(d->index); - if (!tree) { - delete d->index; - d->index = new QGraphicsSceneBspTreeIndex(this); - } - } + d->indexMethod = method; - if (d->indexMethod == CustomIndex && method == BspTreeIndex) { - //We re-add in the new index all items from the old index - QGraphicsSceneIndex *oldIndex = d->index; + delete d->index; + if (method == BspTreeIndex) d->index = new QGraphicsSceneBspTreeIndex(this); - for (int i = 0 ; i < oldIndex->items().size() ; ++ i) - d->index->addItem(oldIndex->items().at(i)); - } - - if (d->indexMethod == CustomIndex && method == NoIndex) { + else d->index = new QGraphicsSceneLinearIndex(this); - } - - d->indexMethod = method; -} - -/*! - \internal - - \brief the item indexing method. - This method allow to apply an indexing algorithm \a index to the scene, to speed up - item discovery functions like items() and itemAt(). - - \sa sceneIndex(), QGraphicsSceneIndex -*/ -void QGraphicsScene::setSceneIndex(QGraphicsSceneIndex *index) -{ - Q_D(QGraphicsScene); - if (!index) { - qWarning("QGraphicsScene::setSceneIndex: Attempt to insert a null indexer"); - } else { - if (d->indexMethod == BspTreeIndex) { - delete d->index; - } - d->indexMethod = CustomIndex; - d->index = index; - } -} - -/*! - \internal - - This method return the current indexing algorithm of the scene. - - \sa setSceneIndex(), QGraphicsSceneIndex -*/ -QGraphicsSceneIndex* QGraphicsScene::sceneIndex() const -{ - Q_D(const QGraphicsScene); - return d->index; } /*! @@ -1814,7 +1746,8 @@ QList QGraphicsScene::items(const QPainterPath &path, Qt::ItemS \sa itemAt() */ -QList QGraphicsScene::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +QList QGraphicsScene::items(const QPointF &pos, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsScene); return d->index->items(pos, mode, order, deviceTransform); @@ -1833,7 +1766,8 @@ QList QGraphicsScene::items(const QPointF &pos, Qt::ItemSelecti \sa itemAt() */ -QList QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +QList QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsScene); return d->index->items(rect, mode, order, deviceTransform); @@ -1852,7 +1786,8 @@ QList QGraphicsScene::items(const QRectF &rect, Qt::ItemSelecti \sa itemAt() */ -QList QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +QList QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsScene); return d->index->items(polygon, mode, order, deviceTransform); @@ -1871,7 +1806,8 @@ QList QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemS \sa itemAt() */ -QList QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +QList QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsScene); return d->index->items(path, mode, order, deviceTransform); diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h index 36374c8..b922be5 100644 --- a/src/gui/graphicsview/qgraphicsscene.h +++ b/src/gui/graphicsview/qgraphicsscene.h @@ -114,7 +114,6 @@ class Q_GUI_EXPORT QGraphicsScene : public QObject public: enum ItemIndexMethod { BspTreeIndex, - CustomIndex, NoIndex = -1 }; @@ -144,8 +143,6 @@ public: ItemIndexMethod itemIndexMethod() const; void setItemIndexMethod(ItemIndexMethod method); - void setSceneIndex(QGraphicsSceneIndex *index); - QGraphicsSceneIndex* sceneIndex() const; bool isSortCacheEnabled() const; void setSortCacheEnabled(bool enabled); @@ -162,10 +159,10 @@ public: QList items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; QList items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; - QList items(const QPointF &pos) const; - QList items(const QRectF &rect, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; - QList items(const QPolygonF &polygon, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; - QList items(const QPainterPath &path, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; + QList items(const QPointF &pos) const; // ### obsolete + QList items(const QRectF &rect, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; // ### obsolete + QList items(const QPolygonF &polygon, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; // ### obsolete + QList items(const QPainterPath &path, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; // ### obsolete QList collidingItems(const QGraphicsItem *item, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; QGraphicsItem *itemAt(const QPointF &pos) const; diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 563e016..8e05c00 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -229,46 +229,6 @@ public: QStyleOptionGraphicsItem styleOptionTmp; }; -static inline bool QRectF_intersects(const QRectF &s, const QRectF &r) -{ - qreal xp = s.left(); - qreal yp = s.top(); - qreal w = s.width(); - qreal h = s.height(); - qreal l1 = xp; - qreal r1 = xp; - if (w < 0) - l1 += w; - else - r1 += w; - - qreal l2 = r.left(); - qreal r2 = r.left(); - if (w < 0) - l2 += r.width(); - else - r2 += r.width(); - - if (l1 >= r2 || l2 >= r1) - return false; - - qreal t1 = yp; - qreal b1 = yp; - if (h < 0) - t1 += h; - else - b1 += h; - - qreal t2 = r.top(); - qreal b2 = r.top(); - if (r.height() < 0) - t2 += r.height(); - else - b2 += r.height(); - - return !(t1 >= b2 || t2 >= b1); -} - // QRectF::intersects() returns false always if either the source or target // rectangle's width or height are 0. This works around that problem. static inline void _q_adjustRect(QRectF *rect) diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 76fd218..969d3c5 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -589,12 +589,16 @@ void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem * \a deviceTransform is the transformation apply to the view. */ -QList QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const +QList QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &rect, Qt::SortOrder order, + const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneBspTreeIndex); const_cast(d)->purgeRemovedItems(); const_cast(d)->_q_updateSortCache(); + // ### Handle items that ignore transformations + Q_UNUSED(deviceTransform); + QList rectItems = d->bsp.items(rect); // Fill in with any unindexed items for (int i = 0; i < d->unindexedItems.size(); ++i) { diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index 6bafbc8..b6f782d 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -142,6 +142,46 @@ static inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphics } +static inline bool QRectF_intersects(const QRectF &s, const QRectF &r) +{ + qreal xp = s.left(); + qreal yp = s.top(); + qreal w = s.width(); + qreal h = s.height(); + qreal l1 = xp; + qreal r1 = xp; + if (w < 0) + l1 += w; + else + r1 += w; + + qreal l2 = r.left(); + qreal r2 = r.left(); + if (w < 0) + l2 += r.width(); + else + r2 += r.width(); + + if (l1 >= r2 || l2 >= r1) + return false; + + qreal t1 = yp; + qreal b1 = yp; + if (h < 0) + t1 += h; + else + b1 += h; + + qreal t2 = r.top(); + qreal b2 = r.top(); + if (r.height() < 0) + t2 += r.height(); + else + b2 += r.height(); + + return !(t1 >= b2 || t2 >= b1); +} + QT_END_NAMESPACE #endif // QGRAPHICSSCENEBSPTREEINDEX_P_H -- cgit v0.12 From 625dadcc9b88dccebf607b84089ab960740b94f2 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Wed, 17 Jun 2009 14:36:55 +0200 Subject: Don't lose all the items when we switch item index method. Readd the items to the new index. Reviewed-by: Alexis --- src/gui/graphicsview/qgraphicsscene.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index dacfc87..36af30d 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1535,11 +1535,14 @@ void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) d->indexMethod = method; + QList oldItems = d->index->items(); delete d->index; if (method == BspTreeIndex) d->index = new QGraphicsSceneBspTreeIndex(this); else d->index = new QGraphicsSceneLinearIndex(this); + for (int i = 0; i < oldItems.size(); ++i) + d->index->addItem(oldItems.at(i)); } /*! -- cgit v0.12 From ac8bf5ec1f99d0e00e3ffefe53306c0d511376bf Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Wed, 17 Jun 2009 14:46:54 +0200 Subject: More cleanups during code review. Reviewed-by: Alexis --- src/gui/graphicsview/qgraphicsscene.cpp | 104 --------------------------- src/gui/graphicsview/qgraphicsscene_p.h | 4 -- src/gui/graphicsview/qgraphicssceneindex.cpp | 54 +++++++++----- src/gui/graphicsview/qgraphicssceneindex.h | 18 +++-- 4 files changed, 47 insertions(+), 133 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 36af30d..380ac20 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1097,110 +1097,6 @@ QGraphicsWidget *QGraphicsScenePrivate::windowForItem(const QGraphicsItem *item) return 0; } -void QGraphicsScenePrivate::recursive_items_helper(QGraphicsItem *item, QRectF rect, - QList *items, - const QTransform &parentTransform, - const QTransform &viewTransform, - Qt::ItemSelectionMode mode, Qt::SortOrder order, - qreal parentOpacity) const -{ - // Calculate opacity. - qreal opacity; - if (item) { - if (!item->d_ptr->visible) - return; - QGraphicsItem *p = item->d_ptr->parent; - bool itemIgnoresParentOpacity = item->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity; - bool parentDoesntPropagateOpacity = (p && (p->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)); - if (!itemIgnoresParentOpacity && !parentDoesntPropagateOpacity) { - opacity = parentOpacity * item->opacity(); - } else { - opacity = item->d_ptr->opacity; - } - if (opacity == 0.0 && !(item->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) - return; - } else { - opacity = parentOpacity; - } - - // Calculate the full transform for this item. - QTransform transform = parentTransform; - bool keep = false; - if (item) { - item->d_ptr->combineTransformFromParent(&transform, &viewTransform); - - // ### This does not take the clip into account. - QRectF brect = item->boundingRect(); - _q_adjustRect(&brect); - - keep = true; - if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) - keep = rect.contains(transform.mapRect(brect)) && rect != brect; - else - keep = rect.intersects(transform.mapRect(brect)); - - if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { - QPainterPath rectPath; - rectPath.addRect(rect); - keep = itemCollidesWithPath(item, transform.inverted().map(rectPath), mode); - } - } - - bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)); - bool dontProcessItem = !item || !keep; - bool dontProcessChildren = item && dontProcessItem && childClip; - - // Find and sort children. - QList &children = item ? item->d_ptr->children : const_cast(this)->topLevelItems; - if (!dontProcessChildren) { - if (item && item->d_ptr->needSortChildren) { - item->d_ptr->needSortChildren = 0; - qStableSort(children.begin(), children.end(), qt_notclosestLeaf); - } else if (!item && needSortTopLevelItems) { - const_cast(this)->needSortTopLevelItems = false; - qStableSort(children.begin(), children.end(), qt_notclosestLeaf); - } - } - - childClip &= !dontProcessChildren & !children.isEmpty(); - - // Clip. - if (childClip) - rect &= transform.map(item->shape()).controlPointRect(); - - // Process children behind - int i = 0; - if (!dontProcessChildren) { - for (i = 0; i < children.size(); ++i) { - QGraphicsItem *child = children.at(i); - if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent)) - break; - recursive_items_helper(child, rect, items, transform, viewTransform, - mode, order, opacity); - } - } - - // Process item - if (!dontProcessItem) - items->append(item); - - // Process children in front - if (!dontProcessChildren) { - for (; i < children.size(); ++i) - recursive_items_helper(children.at(i), rect, items, transform, viewTransform, - mode, order, opacity); - } - - if (!item && order == Qt::AscendingOrder) { - int n = items->size(); - for (int i = 0; i < n / 2; ++i) { - QGraphicsItem *tmp = (*items)[n - i - 1]; - (*items)[n - i - 1] = (*items)[i]; - (*items)[i] = tmp; - } - } -} - /*! \internal diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 8e05c00..538ff3f 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -188,10 +188,6 @@ public: void mousePressEventHandler(QGraphicsSceneMouseEvent *mouseEvent); QGraphicsWidget *windowForItem(const QGraphicsItem *item) const; - void recursive_items_helper(QGraphicsItem *item, QRectF rect, QList *items, - const QTransform &parentTransform, const QTransform &viewTransform, - Qt::ItemSelectionMode mode, Qt::SortOrder order, qreal parentOpacity = 1.0) const; - void drawItemHelper(QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget, bool painterStateProtection); diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 966d8fe..4ca1c02 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -119,9 +119,8 @@ public: else keep = rect.intersects(transform.mapRect(brect)); - if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { + if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) keep = QGraphicsScenePrivate::get(scene)->itemCollidesWithPath(item, transform.inverted().map(path), mode); - } return keep; } QPainterPath path; @@ -290,24 +289,27 @@ QRectF QGraphicsSceneIndex::indexedRect() const } /*! - \fn QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const + \fn QList QGraphicsSceneIndex::items(const QPointF &pos, + Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform + &deviceTransform) const - Returns all visible items that, depending on \a mode, are at the specified \a pos - and return a list sorted using \a order. + Returns all visible items that, depending on \a mode, are at the specified + \a pos and return a list sorted using \a order. The default value for \a mode is Qt::IntersectsItemShape; all items whose exact shape intersects with \a pos are returned. \a deviceTransform is the transformation apply to the view. - This method use the estimation of the index (estimateItems) and refine - the list to get an exact result. If you want to implement your own - refinement algorithm you can reimplement this method. + This method use the estimation of the index (estimateItems) and refine the + list to get an exact result. If you want to implement your own refinement + algorithm you can reimplement this method. \sa estimateItems() */ -QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); QList itemList; @@ -319,7 +321,9 @@ QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSe } /*! - \fn QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const + \fn QList QGraphicsSceneIndex::items(const QRectF &rect, + Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform + &deviceTransform) const \overload @@ -338,7 +342,8 @@ QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSe \sa estimateItems() */ -QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); QList itemList; @@ -349,7 +354,9 @@ QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSe } /*! - \fn QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const + \fn QList QGraphicsSceneIndex::items(const QPolygonF + &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const + QTransform &deviceTransform) const \overload @@ -368,7 +375,8 @@ QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSe \sa estimateItems() */ -QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); QList itemList; @@ -384,7 +392,9 @@ QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt:: } /*! - \fn QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const + \fn QList QGraphicsSceneIndex::items(const QPainterPath + &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform + &deviceTransform) const \overload @@ -403,7 +413,8 @@ QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt:: \sa estimateItems() */ -QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); QList itemList; @@ -421,13 +432,16 @@ QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt:: This method return a list sorted using \a order. \a deviceTransform is the transformation apply to the view. */ -QList QGraphicsSceneIndex::estimateItems(const QPointF &point, Qt::SortOrder order, const QTransform &deviceTransform) const +QList QGraphicsSceneIndex::estimateItems(const QPointF &point, Qt::SortOrder order, + const QTransform &deviceTransform) const { return estimateItems(QRectF(point, QSize(1,1)), order, deviceTransform); } /*! - \fn virtual QList QGraphicsSceneIndex::estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const = 0 + \fn virtual QList + QGraphicsSceneIndex::estimateItems(const QRectF &rect, Qt::SortOrder + order, const QTransform &deviceTransform) const = 0 This pure virtual function return an estimation of items in the \a rect. This method return a list sorted using \a order. @@ -436,8 +450,10 @@ QList QGraphicsSceneIndex::estimateItems(const QPointF &point, */ /*! - \fn virtual QList QGraphicsSceneIndex::items(Qt::SortOrder order = Qt::AscendingOrder) const = 0; - This pure virtual function all items in the index and sort them using \a order. + \fn virtual QList + QGraphicsSceneIndex::items(Qt::SortOrder order = Qt::AscendingOrder) const + = 0; This pure virtual function all items in the index and sort them using + \a order. */ /*! diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index c0e415c..ddce9d4 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -85,12 +85,18 @@ public: virtual QRectF indexedRect() const; virtual QList items(Qt::SortOrder order = Qt::AscendingOrder) const = 0; - virtual QList items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; - virtual QList items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; - virtual QList items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; - virtual QList items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; - virtual QList estimateItems(const QPointF &point, Qt::SortOrder order, const QTransform &deviceTransform) const; - virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const = 0; + virtual QList items(const QPointF &pos, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + virtual QList items(const QRectF &rect, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + virtual QList items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + virtual QList items(const QPainterPath &path, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + virtual QList estimateItems(const QPointF &point, + Qt::SortOrder order, const QTransform &deviceTransform) const; + virtual QList estimateItems(const QRectF &rect, + Qt::SortOrder order, const QTransform &deviceTransform) const = 0; protected: virtual void clear(); -- cgit v0.12 From 0d839e3655d985920aff81882bd444605d97c21c Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Thu, 18 Jun 2009 14:28:29 +0200 Subject: Changes after first round of code reviewing. This change removes all code that handles ItemIgnoresTransformations from QGraphicsView, and changes the APIs of the scene index intersectors. Reviewed-by: Alexis --- src/gui/graphicsview/qgraphicsitem.cpp | 33 ++-- src/gui/graphicsview/qgraphicsitem_p.h | 9 + src/gui/graphicsview/qgraphicsscene.cpp | 141 ++++++-------- src/gui/graphicsview/qgraphicsscene.h | 17 +- src/gui/graphicsview/qgraphicsscene_p.h | 4 +- .../graphicsview/qgraphicsscenebsptreeindex.cpp | 96 +++++---- src/gui/graphicsview/qgraphicsscenebsptreeindex.h | 2 +- .../graphicsview/qgraphicsscenebsptreeindex_p.h | 5 +- src/gui/graphicsview/qgraphicssceneindex.cpp | 216 ++++++++++++++------- src/gui/graphicsview/qgraphicssceneindex.h | 2 +- src/gui/graphicsview/qgraphicssceneindex_p.h | 19 +- src/gui/graphicsview/qgraphicsview.cpp | 161 ++++----------- src/gui/graphicsview/qgraphicsview_p.h | 7 +- 13 files changed, 368 insertions(+), 344 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 593d7be..75683d8 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -857,6 +857,11 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) if (newParent == parent) return; + if (scene) { + // Deliver the change to the index + scene->d_func()->index->itemChange(q, QGraphicsItem::ItemParentChange, newParentVariant); + } + if (QGraphicsWidget *w = isWidget ? static_cast(q) : q->parentWidget()) { // Update the child focus chain; when reparenting a widget that has a // focus child, ensure that that focus child clears its focus child @@ -951,11 +956,6 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) // Deliver post-change notification q->itemChange(QGraphicsItem::ItemParentHasChanged, newParentVariant); - if (scene) { - // Deliver the change to the index - scene->d_func()->index->itemChanged(q, QGraphicsItem::ItemParentHasChanged, newParentVariant); - } - if (isObject) emit static_cast(q)->parentChanged(); } @@ -1426,6 +1426,8 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) flags = GraphicsItemFlags(itemChange(ItemFlagsChange, quint32(flags)).toUInt()); if (quint32(d_ptr->flags) == quint32(flags)) return; + if (d_ptr->scene) + d_ptr->scene->d_func()->index->itemChange(this, ItemFlagsChange, quint32(flags)); // Flags that alter the geometry of the item (or its children). const quint32 geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations); @@ -3577,17 +3579,20 @@ void QGraphicsItem::setZValue(qreal z) qreal newZ = qreal(newZVariant.toDouble()); if (newZ == d_ptr->z) return; + + if (d_ptr->scene) { + // Z Value has changed, we have to notify the index. + d_ptr->scene->d_func()->index->itemChange(this, ItemZValueChange, newZVariant); + } + d_ptr->z = newZ; if (d_ptr->parent) d_ptr->parent->d_ptr->needSortChildren = 1; else if (d_ptr->scene) d_ptr->scene->d_func()->needSortTopLevelItems = 1; - if (d_ptr->scene) { + if (d_ptr->scene) d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true); - //Z Value has changed, we have to notify the index. - d_ptr->scene->d_func()->index->itemChanged(this, ItemZValueChange, z); - } itemChange(ItemZValueHasChanged, newZVariant); @@ -9655,17 +9660,11 @@ QDebug operator<<(QDebug debug, QGraphicsItem *item) return debug; } - QStringList flags; - if (item->isVisible()) flags << QLatin1String("isVisible"); - if (item->isEnabled()) flags << QLatin1String("isEnabled"); - if (item->isSelected()) flags << QLatin1String("isSelected"); - if (item->hasFocus()) flags << QLatin1String("HasFocus"); - debug << "QGraphicsItem(this =" << ((void*)item) << ", parent =" << ((void*)item->parentItem()) << ", pos =" << item->pos() - << ", z =" << item->zValue() << ", flags = {" - << flags.join(QLatin1String("|")) << " })"; + << ", z =" << item->zValue() << ", flags = " + << item->flags() << ")"; return debug; } diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 9c1ee4f..1c95a62 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -158,6 +158,15 @@ public: inline virtual ~QGraphicsItemPrivate() { } + static const QGraphicsItemPrivate *get(const QGraphicsItem *item) + { + return item->d_ptr; + } + static QGraphicsItemPrivate *get(QGraphicsItem *item) + { + return item->d_ptr; + } + void updateAncestorFlag(QGraphicsItem::GraphicsItemFlag childFlag, AncestorFlag flag = NoFlag, bool enabled = false, bool root = true); void setIsMemberOfGroup(bool enabled); diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 380ac20..55f0f20 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -774,41 +774,8 @@ QList QGraphicsScenePrivate::itemsAtPosition(const QPoint &scre { Q_Q(const QGraphicsScene); QGraphicsView *view = widget ? qobject_cast(widget->parentWidget()) : 0; - QList items; - if (view) - items = view->items(view->viewport()->mapFromGlobal(screenPos)); - else - items = q->items(scenePos); - return items; -} - -/*! - \internal - - Checks if item collides with the path and mode, but also checks that if it - doesn't collide, maybe its frame rect will. -*/ -bool QGraphicsScenePrivate::itemCollidesWithPath(QGraphicsItem *item, - const QPainterPath &path, - Qt::ItemSelectionMode mode) -{ - if (item->collidesWithPath(path, mode)) - return true; - if (item->isWidget()) { - // Check if this is a window, and if its frame rect collides. - QGraphicsWidget *widget = static_cast(item); - if (widget->isWindow()) { - QRectF frameRect = widget->windowFrameRect(); - QPainterPath framePath; - framePath.addRect(frameRect); - bool intersects = path.intersects(frameRect); - if (mode == Qt::IntersectsItemShape || mode == Qt::IntersectsItemBoundingRect) - return intersects || path.contains(frameRect.topLeft()) - || framePath.contains(path.elementAt(0)); - return !intersects && path.contains(frameRect.topLeft()); - } - } - return false; + return q->items(scenePos, Qt::IntersectsItemShape, Qt::AscendingOrder, + view ? view->viewportTransform() : QTransform()); } /*! @@ -820,7 +787,7 @@ void QGraphicsScenePrivate::storeMouseButtonsForMouseGrabber(QGraphicsSceneMouse if (event->buttons() & i) { mouseGrabberButtonDownPos.insert(Qt::MouseButton(i), mouseGrabberItems.last()->d_ptr->genericMapFromScene(event->scenePos(), - event->widget())); + event->widget())); mouseGrabberButtonDownScenePos.insert(Qt::MouseButton(i), event->scenePos()); mouseGrabberButtonDownScreenPos.insert(Qt::MouseButton(i), event->screenPos()); } @@ -1282,6 +1249,8 @@ QGraphicsScene::~QGraphicsScene() QRectF QGraphicsScene::sceneRect() const { Q_D(const QGraphicsScene); + /// ### Remove? The growing items bounding rect might be managed + // by the scene. return d->index->indexedRect(); } void QGraphicsScene::setSceneRect(const QRectF &rect) @@ -1332,6 +1301,8 @@ void QGraphicsScene::setSceneRect(const QRectF &rect) void QGraphicsScene::render(QPainter *painter, const QRectF &target, const QRectF &source, Qt::AspectRatioMode aspectRatioMode) { + // ### Switch to using the recursive rendering algorithm instead. + // Default source rect = scene rect QRectF sourceRect = source; if (sourceRect.isNull()) @@ -1431,14 +1402,16 @@ void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) d->indexMethod = method; - QList oldItems = d->index->items(); + QList oldItems = d->index->items(Qt::AscendingOrder); delete d->index; if (method == BspTreeIndex) d->index = new QGraphicsSceneBspTreeIndex(this); else d->index = new QGraphicsSceneLinearIndex(this); - for (int i = 0; i < oldItems.size(); ++i) + for (int i = oldItems.size() - 1; i >= 0; --i) d->index->addItem(oldItems.at(i)); + + d->index->sceneRectChanged(d->sceneRect); } /*! @@ -1476,7 +1449,7 @@ void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) int QGraphicsScene::bspTreeDepth() const { Q_D(const QGraphicsScene); - QGraphicsSceneBspTreeIndex *bspTree = qobject_cast(d->index); + QGraphicsSceneBspTreeIndex *bspTree = qobject_cast(d->index); return bspTree ? bspTree->bspTreeDepth() : 0; } void QGraphicsScene::setBspTreeDepth(int depth) @@ -1487,14 +1460,11 @@ void QGraphicsScene::setBspTreeDepth(int depth) return; } - QGraphicsSceneBspTreeIndex *bspTree = qobject_cast(d->index); + QGraphicsSceneBspTreeIndex *bspTree = qobject_cast(d->index); if (!bspTree) { qWarning("QGraphicsScene::setBspTreeDepth: can not apply if indexing method is not BSP"); return; } - if (bspTree->bspTreeDepth() == depth) - return; - bspTree->setBspTreeDepth(depth); } @@ -1502,37 +1472,21 @@ void QGraphicsScene::setBspTreeDepth(int depth) \property QGraphicsScene::sortCacheEnabled \brief whether sort caching is enabled \since 4.5 + \obsolete - When enabled, this property adds a cache that speeds up sorting and - transformations for scenes with deep hierarchies (i.e., items with many - levels of descendents), at the cost of using more memory (approx. 100 more - bytes of memory per item). - - Items that are not part of a deep hierarchy suffer no penalty from this - cache. + Since Qt 4.6, this property has no effect. */ bool QGraphicsScene::isSortCacheEnabled() const { Q_D(const QGraphicsScene); - QGraphicsSceneBspTreeIndex *bspTree = qobject_cast(d->index); - if (!bspTree) { - qWarning("QGraphicsScene::isSortCacheEnabled: can not apply if indexing method is not BSP"); - return false; - } - return bspTree->d_func()->sortCacheEnabled; + return d->sortCacheEnabled; } void QGraphicsScene::setSortCacheEnabled(bool enabled) { Q_D(QGraphicsScene); - QGraphicsSceneBspTreeIndex *bspTree = qobject_cast(d->index); - if (!bspTree) { - qWarning("QGraphicsScene::isSortCacheEnabled: can not apply if indexing method is not BSP"); + if (d->sortCacheEnabled == enabled) return; - } - if (enabled == bspTree->d_func()->sortCacheEnabled) - return; - if ((bspTree->d_func()->sortCacheEnabled = enabled)) - bspTree->d_func()->invalidateSortCache(); + d->sortCacheEnabled = enabled; } /*! @@ -1544,6 +1498,7 @@ void QGraphicsScene::setSortCacheEnabled(bool enabled) */ QRectF QGraphicsScene::itemsBoundingRect() const { + // Does not take untransformable items into account. QRectF boundingRect; foreach (QGraphicsItem *item, items()) boundingRect |= item->sceneBoundingRect(); @@ -1558,7 +1513,19 @@ QRectF QGraphicsScene::itemsBoundingRect() const QList QGraphicsScene::items() const { Q_D(const QGraphicsScene); - return d->index->items(); + return d->index->items(Qt::AscendingOrder); +} + +/*! + Returns an ordered list of all items on the scene. \a order decides the + sorting. + + \sa addItem(), removeItem() +*/ +QList QGraphicsScene::items(Qt::SortOrder order) const +{ + Q_D(const QGraphicsScene); + return d->index->items(order); } /*! @@ -1732,6 +1699,7 @@ QList QGraphicsScene::collidingItems(const QGraphicsItem *item, return QList(); } + // Does not support ItemIgnoresTransformations. QList tmp; foreach (QGraphicsItem *itemInVicinity, d->index->estimateItems(item->sceneBoundingRect(), Qt::AscendingOrder, QTransform())) { if (item != itemInVicinity && item->collidesWithItem(itemInVicinity, mode)) @@ -1756,6 +1724,13 @@ QGraphicsItem *QGraphicsScene::itemAt(const QPointF &pos) const return itemsAtPoint.isEmpty() ? 0 : itemsAtPoint.first(); } +QGraphicsItem *QGraphicsScene::itemAt(const QPointF &pos, const QTransform &deviceTransform) const +{ + QList itemsAtPoint = items(pos, Qt::IntersectsItemShape, + Qt::AscendingOrder, deviceTransform); + return itemsAtPoint.isEmpty() ? 0 : itemsAtPoint.first(); +} + /*! \fn QGraphicsScene::itemAt(qreal x, qreal y) const \overload @@ -1831,6 +1806,21 @@ void QGraphicsScene::setSelectionArea(const QPainterPath &path) */ void QGraphicsScene::setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode) { + setSelectionArea(path, Qt::IntersectsItemShape, QTransform()); +} + +/*! + \overload + \since 4.3 + + Sets the selection area to \a path using \a mode to determine if items are + included in the selection area. + + \sa clearSelection(), selectionArea() +*/ +void QGraphicsScene::setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode, + const QTransform &deviceTransform) +{ Q_D(QGraphicsScene); // Note: with boolean path operations, we can improve performance here @@ -1846,7 +1836,7 @@ void QGraphicsScene::setSelectionArea(const QPainterPath &path, Qt::ItemSelectio bool changed = false; // Set all items in path to selected. - foreach (QGraphicsItem *item, items(path, mode)) { + foreach (QGraphicsItem *item, items(path, mode, Qt::AscendingOrder, deviceTransform)) { if (item->flags() & QGraphicsItem::ItemIsSelectable) { if (!item->isSelected()) changed = true; @@ -1904,7 +1894,10 @@ void QGraphicsScene::clear() { Q_D(QGraphicsScene); QList items = d->index->items(); +#if 1 QList toDelete; + // ### As the item list is already in ascending order, + // the items should be deleted in topological order. // Recursive descent delete for (int i = 0; i < items.size(); ++i) { if (QGraphicsItem *item = items.at(i)) { @@ -1912,11 +1905,13 @@ void QGraphicsScene::clear() toDelete << item; } } - //We delete all top level items + // We delete all top level items qDeleteAll(toDelete); +#else + qDeleteAll(items); +#endif d->lastItemCount = 0; d->index->clear(); - d->largestUntransformableItem = QRectF(); d->allItemsIgnoreHoverEvents = true; d->allItemsUseDefaultCursor = true; } @@ -4129,16 +4124,6 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * children = &this->topLevelItems; } else { QRectF sceneRect = viewTransform.inverted().mapRect(QRectF(exposedRegion->boundingRect().adjusted(-1, -1, 1, 1))); - if (!largestUntransformableItem.isEmpty()) { - // ### Nuke this when we move the indexing code into a separate - // class. All the largestUntransformableItem code should then go - // away, and the estimate function should return untransformable - // items as well. - QRectF untr = largestUntransformableItem; - QRectF ltri = viewTransform.inverted().mapRect(untr); - ltri.adjust(-untr.width(), -untr.height(), untr.width(), untr.height()); - sceneRect.adjust(-ltri.width(), -ltri.height(), ltri.width(), ltri.height()); - } tmp = index->estimateItems(sceneRect, Qt::DescendingOrder, viewTransform); QList tli; diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h index b922be5..421adbd 100644 --- a/src/gui/graphicsview/qgraphicsscene.h +++ b/src/gui/graphicsview/qgraphicsscene.h @@ -153,6 +153,7 @@ public: QRectF itemsBoundingRect() const; QList items() const; + QList items(Qt::SortOrder order) const; // ### Qt 5: unify QList items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; QList items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; @@ -165,17 +166,25 @@ public: QList items(const QPainterPath &path, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; // ### obsolete QList collidingItems(const QGraphicsItem *item, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; - QGraphicsItem *itemAt(const QPointF &pos) const; + + QGraphicsItem *itemAt(const QPointF &pos) const; // ### obsolete + QGraphicsItem *itemAt(const QPointF &pos, const QTransform &deviceTransform) const; inline QList items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const - { return items(QRectF(x, y, w, h), mode); } - inline QGraphicsItem *itemAt(qreal x, qreal y) const + { return items(QRectF(x, y, w, h), mode); } // ### obsolete + inline QList items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode, Qt::SortOrder order, + const QTransform &deviceTransform = QTransform()) const + { return items(QRectF(x, y, w, h), mode, order, deviceTransform); } + inline QGraphicsItem *itemAt(qreal x, qreal y) const // ### obsolete { return itemAt(QPointF(x, y)); } + inline QGraphicsItem *itemAt(qreal x, qreal y, const QTransform &deviceTransform) const + { return itemAt(QPointF(x, y), deviceTransform); } QList selectedItems() const; QPainterPath selectionArea() const; void setSelectionArea(const QPainterPath &path); - void setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode); + void setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode); + void setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode, const QTransform &deviceTransform); QGraphicsItemGroup *createItemGroup(const QList &items); void destroyItemGroup(QGraphicsItemGroup *group); diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 538ff3f..a081e04 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -96,7 +96,6 @@ public: QRectF sceneRect; bool hasSceneRect; QRectF growingItemsBoundingRect; - QRectF largestUntransformableItem; void _q_emitUpdated(); QList updatedRects; @@ -162,7 +161,6 @@ public: QList itemsAtPosition(const QPoint &screenPos, const QPointF &scenePos, QWidget *widget) const; - static bool itemCollidesWithPath(QGraphicsItem *item, const QPainterPath &path, Qt::ItemSelectionMode mode); void storeMouseButtonsForMouseGrabber(QGraphicsSceneMouseEvent *event); QList views; @@ -188,6 +186,8 @@ public: void mousePressEventHandler(QGraphicsSceneMouseEvent *mouseEvent); QGraphicsWidget *windowForItem(const QGraphicsItem *item) const; + bool sortCacheEnabled; // for compatibility + void drawItemHelper(QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget, bool painterStateProtection); diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 969d3c5..40cafa6 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -170,11 +170,6 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() unindexedItems = indexedItems; lastItemCount = indexedItems.size(); q->scene()->update(); - - // Take this opportunity to reset our largest-item counter for - // untransformable items. When the items are inserted into the BSP - // tree, we'll get an accurate calculation. - scenePrivate->largestUntransformableItem = QRectF(); } // Insert all unindexed items into the tree. @@ -185,19 +180,6 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() continue; bsp.insertItem(item, rect); - - // If the item ignores view transformations, update our - // largest-item-counter to ensure that the view can accurately - // discover untransformable items when drawing. - if (item->d_ptr->itemIsUntransformable()) { - QGraphicsItem *topmostUntransformable = item; - while (topmostUntransformable && (topmostUntransformable->d_ptr->ancestorFlags - & QGraphicsItemPrivate::AncestorIgnoresTransformations)) { - topmostUntransformable = topmostUntransformable->parentItem(); - } - // ### Verify that this is the correct largest untransformable rectangle. - scenePrivate->largestUntransformableItem |= item->mapToItem(topmostUntransformable, item->boundingRect()).boundingRect(); - } } } unindexedItems.clear(); @@ -467,17 +449,23 @@ void QGraphicsSceneBspTreeIndex::addItem(QGraphicsItem *item) // Indexing requires sceneBoundingRect(), but because \a item might // not be completely constructed at this point, we need to store it in // a temporary list and schedule an indexing for later. - d->unindexedItems << item; - item->d_func()->index = -1; - d->startIndexTimer(0); + item->d_ptr->index = -1; + if (item->d_ptr->itemIsUntransformable()) { + d->untransformableItems << item; + } else { + d->unindexedItems << item; + d->startIndexTimer(0); + } } /*! This really add the item in the BSP. \internal */ -void QGraphicsSceneBspTreeIndexPrivate::addToIndex(QGraphicsItem *item) +void QGraphicsSceneBspTreeIndexPrivate::addToBspTree(QGraphicsItem *item) { + if (item->d_ptr->itemIsUntransformable()) + return; if (item->d_func()->index != -1) { bsp.insertItem(item, item->sceneBoundingRect()); foreach (QGraphicsItem *child, item->children()) @@ -496,10 +484,11 @@ void QGraphicsSceneBspTreeIndexPrivate::addToIndex(QGraphicsItem *item) void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item) { Q_D(QGraphicsSceneBspTreeIndex); + // Note: This will access item's sceneBoundingRect(), which (as this is // C++) is why we cannot call removeItem() from QGraphicsItem's // destructor. - d->removeFromIndex(item); + d->removeFromBspTree(item); // Invalidate any sort caching; arrival of a new item means we need to // resort. @@ -511,7 +500,10 @@ void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item) d->freeItemIndexes << index; d->indexedItems[index] = 0; } else { - d->unindexedItems.removeAll(item); + if (item->d_ptr->itemIsUntransformable()) + d->untransformableItems.removeOne(item); + else + d->unindexedItems.removeOne(item); } } @@ -539,7 +531,10 @@ void QGraphicsSceneBspTreeIndex::deleteItem(QGraphicsItem *item) } else { // Recently added items are purged immediately. unindexedItems() never // contains stale items. - d->unindexedItems.removeAll(item); + if (item->d_ptr->itemIsUntransformable()) + d->untransformableItems.removeOne(item); + else + d->unindexedItems.removeOne(item); scene()->update(); } } @@ -548,8 +543,11 @@ void QGraphicsSceneBspTreeIndex::deleteItem(QGraphicsItem *item) Really remove the item from the BSP \internal */ -void QGraphicsSceneBspTreeIndexPrivate::removeFromIndex(QGraphicsItem *item) +void QGraphicsSceneBspTreeIndexPrivate::removeFromBspTree(QGraphicsItem *item) { + if (item->d_ptr->itemIsUntransformable()) + return; + if (item->d_func()->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { // ### remove from child index only if applicable return; @@ -579,7 +577,7 @@ void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem * // Note: This will access item's sceneBoundingRect(), which (as this is // C++) is why we cannot call removeItem() from QGraphicsItem's // destructor. - d->removeFromIndex(const_cast(item)); + d->removeFromBspTree(const_cast(item)); } /*! @@ -633,7 +631,8 @@ QList QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order) co Q_D(const QGraphicsSceneBspTreeIndex); const_cast(d)->purgeRemovedItems(); QList itemList; - // If freeItemIndexes is empty, we know there are no holes in indexedItems and + + // If freeItemIndexes is empty, we know there are no holes in indexedItems and // unindexedItems. if (d->freeItemIndexes.isEmpty()) { if (d->unindexedItems.isEmpty()) { @@ -649,6 +648,7 @@ QList QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order) co itemList << item; } } + itemList += d->untransformableItems; if (order != -1) { //We sort descending order d->sortItems(&itemList, order, d->sortCacheEnabled); @@ -692,6 +692,8 @@ int QGraphicsSceneBspTreeIndex::bspTreeDepth() void QGraphicsSceneBspTreeIndex::setBspTreeDepth(int depth) { Q_D(QGraphicsSceneBspTreeIndex); + if (d->bspTreeDepth == depth) + return; d->bspTreeDepth = depth; d->resetIndex(); } @@ -716,19 +718,41 @@ void QGraphicsSceneBspTreeIndex::sceneRectChanged(const QRectF &rect) update the BSP tree if necessary. */ -void QGraphicsSceneBspTreeIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value) +void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value) { Q_D(QGraphicsSceneBspTreeIndex); switch (change) { - case QGraphicsItem::ItemZValueChange: - case QGraphicsItem::ItemParentChange: { - d->invalidateSortCache(); - break; + case QGraphicsItem::ItemFlagsChange: { + // Handle ItemIgnoresTransformations + bool ignoredTransform = item->flags() & QGraphicsItem::ItemIgnoresTransformations; + bool willIgnoreTransform = value.toUInt() & QGraphicsItem::ItemIgnoresTransformations; + if (ignoredTransform != willIgnoreTransform) { + QGraphicsItem *thatItem = const_cast(item); + removeItem(thatItem); + addItem(thatItem); } - default: - break; + break; + } + case QGraphicsItem::ItemZValueChange: + d->invalidateSortCache(); + break; + case QGraphicsItem::ItemParentChange: { + d->invalidateSortCache(); + // Handle ItemIgnoresTransformations + QGraphicsItem *newParent = qVariantValue(value); + bool ignoredTransform = item->d_ptr->itemIsUntransformable(); + bool willIgnoreTransform = (item->flags() & QGraphicsItem::ItemIgnoresTransformations) || (newParent && newParent->d_ptr->itemIsUntransformable()); + if (ignoredTransform != willIgnoreTransform) { + QGraphicsItem *thatItem = const_cast(item); + removeItem(thatItem); + addItem(thatItem); + } + break; + } + default: + break; } - return QGraphicsSceneIndex::itemChanged(item, change, value); + return QGraphicsSceneIndex::itemChange(item, change, value); } /*! \reimp diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex.h index 0444a30..504ea8b 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.h @@ -98,7 +98,7 @@ protected: void prepareBoundingRectChange(const QGraphicsItem *item); void sceneRectChanged(const QRectF &rect); - void itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value); + void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value); private : Q_DECLARE_PRIVATE(QGraphicsSceneBspTreeIndex) diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index b6f782d..ed12fac 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -82,6 +82,7 @@ public: QList indexedItems; QList unindexedItems; + QList untransformableItems; QList freeItemIndexes; bool purgePending; @@ -92,8 +93,8 @@ public: void startIndexTimer(int interval = QGRAPHICSSCENE_INDEXTIMER_TIMEOUT); void resetIndex(); - void addToIndex(QGraphicsItem *item); - void removeFromIndex(QGraphicsItem *item); + void addToBspTree(QGraphicsItem *item); + void removeFromBspTree(QGraphicsItem *item); void _q_updateSortCache(); bool sortCacheEnabled; diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 4ca1c02..eb3abc1 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -61,6 +61,7 @@ #include "qgraphicsscene.h" #include "qgraphicsitem_p.h" #include "qgraphicsscene_p.h" +#include "qgraphicswidget.h" #ifndef QT_NO_GRAPHICSVIEW @@ -69,61 +70,118 @@ QT_BEGIN_NAMESPACE class QGraphicsSceneIndexRectIntersector : public QGraphicsSceneIndexIntersector { public: - QGraphicsSceneIndexRectIntersector(QGraphicsScene *scene) : QGraphicsSceneIndexIntersector(scene) {} - bool intersect(const QRectF &brect) const + bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode, + const QTransform &transform, const QTransform &deviceTransform) const { + QRectF brect = item->boundingRect(); + _q_adjustRect(&brect); + + // ### Add test for this (without making things slower?) + Q_UNUSED(exposeRect); + bool keep = true; - if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) - keep = rect.contains(transform.mapRect(brect)) && rect != brect; - else - keep = rect.intersects(transform.mapRect(brect)); - - if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { - QPainterPath rectPath; - rectPath.addRect(rect); - keep = QGraphicsScenePrivate::get(scene)->itemCollidesWithPath(item, transform.inverted().map(rectPath), mode); + if (QGraphicsItemPrivate::get(item)->itemIsUntransformable()) { + // Untransformable items; map the scene rect to item coordinates. + QRectF itemRect = (deviceTransform * transform.inverted()).mapRect(sceneRect); + if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) + keep = itemRect.contains(brect) && itemRect != brect; + else + keep = itemRect.intersects(brect); + if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { + QPainterPath itemPath; + itemPath.addRect(itemRect); + keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, itemPath, mode); + } + } else { + if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) + keep = sceneRect.contains(transform.mapRect(brect)) && sceneRect != brect; + else + keep = sceneRect.intersects(transform.mapRect(brect)); + if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { + QPainterPath rectPath; + rectPath.addRect(sceneRect); + keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, transform.inverted().map(rectPath), mode); + } } return keep; } + + QRectF sceneRect; }; class QGraphicsSceneIndexPointIntersector : public QGraphicsSceneIndexIntersector { public: - QGraphicsSceneIndexPointIntersector(QGraphicsScene *scene) : QGraphicsSceneIndexIntersector(scene) {} - bool intersect(const QRectF &brect) const + bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode, + const QTransform &transform, const QTransform &deviceTransform) const { + QRectF brect = item->boundingRect(); + _q_adjustRect(&brect); + + // ### Add test for this (without making things slower?) + Q_UNUSED(exposeRect); + bool keep = false; - if (rect.intersects(transform.mapRect(brect))) - if (item->contains(transform.inverted().map(pos))) - keep = true; - if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { - QPainterPath rectPath; - rectPath.addRect(rect); - keep = QGraphicsScenePrivate::get(scene)->itemCollidesWithPath(item, transform.inverted().map(rectPath), mode); + if (QGraphicsItemPrivate::get(item)->itemIsUntransformable()) { + // Untransformable items; map the scene point to item coordinates. + QPointF itemPoint = (deviceTransform * transform.inverted()).map(scenePoint); + keep = brect.contains(itemPoint); + if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { + QPainterPath pointPath; + pointPath.addRect(QRectF(itemPoint, QSizeF(1, 1))); + keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, pointPath, mode); + } + } else { + QRectF sceneBrect = transform.mapRect(brect); + keep = sceneBrect.contains(scenePoint); + if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { + QPainterPath pointPath; + pointPath.addRect(QRectF(transform.inverted().map(scenePoint), QSizeF(1, 1))); + keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, pointPath, mode); + } } return keep; } - QPointF pos; + + QPointF scenePoint; }; class QGraphicsSceneIndexPathIntersector : public QGraphicsSceneIndexIntersector { public: - QGraphicsSceneIndexPathIntersector(QGraphicsScene *scene) : QGraphicsSceneIndexIntersector(scene) {} - bool intersect(const QRectF &brect) const + bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode, + const QTransform &transform, const QTransform &deviceTransform) const { - bool keep = true; - if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) - keep = rect.contains(transform.mapRect(brect)) && rect != brect; - else - keep = rect.intersects(transform.mapRect(brect)); + QRectF brect = item->boundingRect(); + _q_adjustRect(&brect); + + // ### Add test for this (without making things slower?) + Q_UNUSED(exposeRect); - if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) - keep = QGraphicsScenePrivate::get(scene)->itemCollidesWithPath(item, transform.inverted().map(path), mode); + bool keep = true; + if (QGraphicsItemPrivate::get(item)->itemIsUntransformable()) { + // Untransformable items; map the scene rect to item coordinates. + QPainterPath itemPath = (deviceTransform * transform.inverted()).map(scenePath); + if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) + keep = itemPath.contains(brect); + else + keep = itemPath.intersects(brect); + if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) + keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, itemPath, mode); + } else { + if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) + keep = scenePath.contains(transform.mapRect(brect)); + else + keep = scenePath.intersects(transform.mapRect(brect)); + if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { + QPainterPath itemPath = transform.inverted().map(scenePath); + keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, itemPath, mode); + } + } return keep; } - QPainterPath path; + + QPainterPath scenePath; }; /*! @@ -131,9 +189,9 @@ public: */ QGraphicsSceneIndexPrivate::QGraphicsSceneIndexPrivate(QGraphicsScene *scene) : scene(scene) { - pointIntersector = new QGraphicsSceneIndexPointIntersector(scene); - rectIntersector = new QGraphicsSceneIndexRectIntersector(scene); - pathIntersector = new QGraphicsSceneIndexPathIntersector(scene); + pointIntersector = new QGraphicsSceneIndexPointIntersector; + rectIntersector = new QGraphicsSceneIndexRectIntersector; + pathIntersector = new QGraphicsSceneIndexPathIntersector; } /*! @@ -148,19 +206,50 @@ QGraphicsSceneIndexPrivate::~QGraphicsSceneIndexPrivate() /*! \internal + + Checks if item collides with the path and mode, but also checks that if it + doesn't collide, maybe its frame rect will. +*/ +bool QGraphicsSceneIndexPrivate::itemCollidesWithPath(const QGraphicsItem *item, + const QPainterPath &path, + Qt::ItemSelectionMode mode) +{ + if (item->collidesWithPath(path, mode)) + return true; + if (item->isWidget()) { + // Check if this is a window, and if its frame rect collides. + const QGraphicsWidget *widget = static_cast(item); + if (widget->isWindow()) { + QRectF frameRect = widget->windowFrameRect(); + QPainterPath framePath; + framePath.addRect(frameRect); + bool intersects = path.intersects(frameRect); + if (mode == Qt::IntersectsItemShape || mode == Qt::IntersectsItemBoundingRect) + return intersects || path.contains(frameRect.topLeft()) + || framePath.contains(path.elementAt(0)); + return !intersects && path.contains(frameRect.topLeft()); + } + } + return false; +} + +/*! + \internal */ -void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QGraphicsSceneIndexIntersector *intersector, - QList *items, - const QTransform &parentTransform, - const QTransform &viewTransform, - Qt::ItemSelectionMode mode, Qt::SortOrder order, - qreal parentOpacity) const +void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRectF exposeRect, + QGraphicsSceneIndexIntersector *intersector, + QList *items, + const QTransform &parentTransform, + const QTransform &viewTransform, + Qt::ItemSelectionMode mode, Qt::SortOrder order, + qreal parentOpacity) const { // Calculate opacity. qreal opacity; if (item) { if (!item->d_ptr->visible) return; + QGraphicsItem *p = item->d_ptr->parent; bool itemIgnoresParentOpacity = item->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity; bool parentDoesntPropagateOpacity = (p && (p->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)); @@ -186,9 +275,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QGr _q_adjustRect(&brect); //We fill the intersector with needed informations - intersector->transform = transform; - intersector->item = item; - keep = intersector->intersect(brect); + keep = intersector->intersect(item, exposeRect, mode, transform, viewTransform); } bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)); @@ -211,7 +298,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QGr // Clip. if (childClip) - intersector->rect &= transform.map(item->shape()).controlPointRect(); + exposeRect &= transform.map(item->shape()).controlPointRect(); // Process children behind int i = 0; @@ -220,7 +307,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QGr QGraphicsItem *child = children.at(i); if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent)) break; - recursive_items_helper(child, intersector, items, transform, viewTransform, + recursive_items_helper(child, exposeRect, intersector, items, transform, viewTransform, mode, order, opacity); } } @@ -232,7 +319,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QGr // Process children in front if (!dontProcessChildren) { for (; i < children.size(); ++i) - recursive_items_helper(children.at(i), intersector, items, transform, viewTransform, + recursive_items_helper(children.at(i), exposeRect, intersector, items, transform, viewTransform, mode, order, opacity); } @@ -311,12 +398,12 @@ QRectF QGraphicsSceneIndex::indexedRect() const QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { + Q_D(const QGraphicsSceneIndex); QList itemList; - d->pointIntersector->mode = mode; - d->pointIntersector->rect = QRectF(pos, QSize(1,1)); - d->pointIntersector->pos = pos; - d->recursive_items_helper(0, d->pointIntersector, &itemList, QTransform(), deviceTransform, mode, order); + d->pointIntersector->scenePoint = pos; + d->recursive_items_helper(0, QRectF(pos, QSizeF(1, 1)), d->pointIntersector, &itemList, + QTransform(), deviceTransform, mode, order); return itemList; } @@ -346,10 +433,11 @@ QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSe Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); + QRectF exposeRect = rect; + _q_adjustRect(&exposeRect); QList itemList; - d->rectIntersector->mode = mode; - d->rectIntersector->rect = rect; - d->recursive_items_helper(0, d->rectIntersector, &itemList, QTransform(), deviceTransform, mode, order); + d->rectIntersector->sceneRect = rect; + d->recursive_items_helper(0, exposeRect, d->rectIntersector, &itemList, QTransform(), deviceTransform, mode, order); return itemList; } @@ -380,14 +468,12 @@ QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt:: { Q_D(const QGraphicsSceneIndex); QList itemList; - QRectF polyRect(polygon.boundingRect()); - _q_adjustRect(&polyRect); - d->pathIntersector->mode = mode; - d->pathIntersector->rect = polyRect; + QRectF exposeRect = polygon.boundingRect(); + _q_adjustRect(&exposeRect); QPainterPath path; path.addPolygon(polygon); - d->pathIntersector->path = path; - d->recursive_items_helper(0, d->pathIntersector, &itemList, QTransform(), deviceTransform, mode, order); + d->pathIntersector->scenePath = path; + d->recursive_items_helper(0, exposeRect, d->pathIntersector, &itemList, QTransform(), deviceTransform, mode, order); return itemList; } @@ -418,12 +504,10 @@ QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt:: { Q_D(const QGraphicsSceneIndex); QList itemList; - QRectF pathRect(path.controlPointRect()); - _q_adjustRect(&pathRect); - d->pathIntersector->mode = mode; - d->pathIntersector->rect = pathRect; - d->pathIntersector->path = path; - d->recursive_items_helper(0, d->pathIntersector, &itemList, QTransform(), deviceTransform, mode, order); + QRectF exposeRect = path.controlPointRect(); + _q_adjustRect(&exposeRect); + d->pathIntersector->scenePath = path; + d->recursive_items_helper(0, exposeRect, d->pathIntersector, &itemList, QTransform(), deviceTransform, mode, order); return itemList; } @@ -508,7 +592,7 @@ void QGraphicsSceneIndex::deleteItem(QGraphicsItem *item) \sa QGraphicsItem::GraphicsItemChange */ -void QGraphicsSceneIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value) +void QGraphicsSceneIndex::itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value) { Q_UNUSED(item); Q_UNUSED(change); diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index ddce9d4..25ece04 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -104,7 +104,7 @@ protected: virtual void removeItem(QGraphicsItem *item) = 0; virtual void deleteItem(QGraphicsItem *item); - virtual void itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const QVariant &value); + virtual void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const QVariant &value); virtual void prepareBoundingRectChange(const QGraphicsItem *item); virtual void sceneRectChanged(const QRectF &rect); diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h index d0d181b..576ee98 100644 --- a/src/gui/graphicsview/qgraphicssceneindex_p.h +++ b/src/gui/graphicsview/qgraphicssceneindex_p.h @@ -75,9 +75,12 @@ public: QGraphicsSceneIndexPrivate(QGraphicsScene *scene); ~QGraphicsSceneIndexPrivate(); - void recursive_items_helper(QGraphicsItem *item, QGraphicsSceneIndexIntersector *intersector, QList *items, - const QTransform &parentTransform, const QTransform &viewTransform, - Qt::ItemSelectionMode mode, Qt::SortOrder order, qreal parentOpacity = 1.0) const; + static bool itemCollidesWithPath(const QGraphicsItem *item, const QPainterPath &path, Qt::ItemSelectionMode mode); + + void recursive_items_helper(QGraphicsItem *item, QRectF exposeRect, + QGraphicsSceneIndexIntersector *intersector, QList *items, + const QTransform &parentTransform, const QTransform &viewTransform, + Qt::ItemSelectionMode mode, Qt::SortOrder order, qreal parentOpacity = 1.0) const; QGraphicsScene *scene; QGraphicsSceneIndexPointIntersector *pointIntersector; QGraphicsSceneIndexRectIntersector *rectIntersector; @@ -87,14 +90,10 @@ public: class QGraphicsSceneIndexIntersector { public: - QGraphicsSceneIndexIntersector(QGraphicsScene *scene) : scene(scene) { } + QGraphicsSceneIndexIntersector() { } virtual ~QGraphicsSceneIndexIntersector() { } - virtual bool intersect(const QRectF &rect) const = 0; - Qt::ItemSelectionMode mode; - QGraphicsItem *item; - QGraphicsScene *scene; - QRectF rect; - QTransform transform; + virtual bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode, + const QTransform &transform, const QTransform &deviceTransform) const = 0; }; QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 8c40878..a1e6d9c 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -914,44 +914,32 @@ extern QPainterPath qt_regionToPath(const QRegion ®ion); is at risk of painting 1 pixel outside the bounding rect. Therefore we must search for items with an adjustment of (-1, -1, 1, 1). */ -QList QGraphicsViewPrivate::findItems(const QRegion &exposedRegion, bool *allItems) const +QList QGraphicsViewPrivate::findItems(const QRegion &exposedRegion, bool *allItems, + const QTransform &viewTransform) const { Q_Q(const QGraphicsView); // Step 1) If all items are contained within the expose region, then - // return a list of all visible items. + // return a list of all visible items. ### the scene's growing bounding + // rect does not take into account untransformable items. const QRectF exposedRegionSceneBounds = q->mapToScene(exposedRegion.boundingRect().adjusted(-1, -1, 1, 1)) .boundingRect(); if (exposedRegionSceneBounds.contains(scene->d_func()->growingItemsBoundingRect)) { Q_ASSERT(allItems); *allItems = true; - // All items are guaranteed within the exposed region, don't bother using the index. - QList itemList(scene->d_func()->index->items(Qt::DescendingOrder)); - int i = 0; - while (i < itemList.size()) { - const QGraphicsItem *item = itemList.at(i); - // But we only want to include items that are visible - // The following check is basically the same as item->d_ptr->isInvisible(), except - // that we don't check whether the item clips children to shape or propagates its - // opacity (we loop through all items, so those checks are wrong in this context). - if (!item->isVisible() || item->d_ptr->isClippedAway() || item->d_ptr->isFullyTransparent()) - itemList.removeAt(i); - else - ++i; - } - return itemList; + // All items are guaranteed within the exposed region. + return scene->items(Qt::DescendingOrder); } // Step 2) If the expose region is a simple rect and the view is only // translated or scaled, search for items using // QGraphicsScene::items(QRectF). - bool simpleRectLookup = (scene->d_func()->largestUntransformableItem.isNull() - && exposedRegion.numRects() == 1 && matrix.type() <= QTransform::TxScale); + bool simpleRectLookup = exposedRegion.numRects() == 1 && matrix.type() <= QTransform::TxScale; if (simpleRectLookup) { - return scene->d_func()->index->items(exposedRegionSceneBounds, - Qt::IntersectsItemBoundingRect, - Qt::DescendingOrder); + return scene->items(exposedRegionSceneBounds, + Qt::IntersectsItemBoundingRect, + Qt::DescendingOrder, viewTransform); } // If the region is complex or the view has a complex transform, adjust @@ -961,16 +949,9 @@ QList QGraphicsViewPrivate::findItems(const QRegion &exposedReg foreach (const QRect &r, exposedRegion.rects()) adjustedRegion += r.adjusted(-1, -1, 1, 1); - const QPainterPath exposedPath(qt_regionToPath(adjustedRegion)); - if (scene->d_func()->largestUntransformableItem.isNull()) { - const QPainterPath exposedScenePath(q->mapToScene(exposedPath)); - return scene->d_func()->index->items(exposedScenePath, - Qt::IntersectsItemBoundingRect, - Qt::DescendingOrder); - } - - // NB! Path must be in viewport coordinates. - return itemsInArea(exposedPath, Qt::IntersectsItemBoundingRect, Qt::DescendingOrder); + const QPainterPath exposedScenePath(q->mapToScene(qt_regionToPath(adjustedRegion))); + return scene->items(exposedScenePath, Qt::IntersectsItemBoundingRect, + Qt::DescendingOrder, viewTransform); } /*! @@ -1875,6 +1856,8 @@ void QGraphicsView::fitInView(const QGraphicsItem *item, Qt::AspectRatioMode asp void QGraphicsView::render(QPainter *painter, const QRectF &target, const QRect &source, Qt::AspectRatioMode aspectRatioMode) { + // ### Switch to using the recursive rendering algorithm instead. + Q_D(QGraphicsView); if (!d->scene || !(painter && painter->isActive())) return; @@ -1972,67 +1955,6 @@ QList QGraphicsView::items() const } /*! - Returns all items in the area \a path, which is in viewport coordinates, - also taking untransformable items into consideration. This function is - considerably slower than just checking the scene directly. There is - certainly room for improvement. -*/ -QList QGraphicsViewPrivate::itemsInArea(const QPainterPath &path, - Qt::ItemSelectionMode mode, - Qt::SortOrder order) const -{ - Q_Q(const QGraphicsView); - - // Determine the size of the largest untransformable subtree of children - // mapped to scene coordinates. - QRectF untr = scene->d_func()->largestUntransformableItem; - QRectF ltri = matrix.inverted().mapRect(untr); - ltri.adjust(-untr.width(), -untr.height(), untr.width(), untr.height()); - - QRectF rect = path.controlPointRect(); - - // Find all possible items in the relevant area. - // ### Improve this algorithm; it might be searching a too large area. - QRectF adjustedRect = q->mapToScene(rect.adjusted(-1, -1, 1, 1).toRect()).boundingRect(); - adjustedRect.adjust(-ltri.width(), -ltri.height(), ltri.width(), ltri.height()); - - // First build a (potentially large) list of all items in the vicinity - // that might be untransformable. - QList allCandidates = scene->d_func()->index->estimateItems(adjustedRect, order, q->transform()); - - // Then find the minimal list of items that are inside \a path, and - // convert it to a set. - QList regularCandidates = scene->items(q->mapToScene(path), mode, order, q->transform()); - QSet candSet = QSet::fromList(regularCandidates); - - QTransform viewMatrix = q->viewportTransform(); - - QList result; - - //### this will disapear - - // Run through all candidates and keep all items that are in candSet, or - // are untransformable and collide with \a path. ### We can improve this - // algorithm. - QList::Iterator it = allCandidates.begin(); - while (it != allCandidates.end()) { - QGraphicsItem *item = *it; - if (item->d_ptr->itemIsUntransformable()) { - // Check if this untransformable item collides with the - // original selection rect. - QTransform itemTransform = item->deviceTransform(viewMatrix); - if (QGraphicsScenePrivate::itemCollidesWithPath(item, itemTransform.inverted().map(path), mode)) - result << item; - } else { - if (candSet.contains(item)) - result << item; - } - ++it; - } - return result; -} - -/*! Returns a list of all the items at the position \a pos in the view. The items are listed in descending Z order (i.e., the first item in the list is the top-most item, and the last item is the bottom-most item). \a pos @@ -2051,17 +1973,22 @@ QList QGraphicsView::items(const QPoint &pos) const Q_D(const QGraphicsView); if (!d->scene) return QList(); - if (d->scene->d_func()->largestUntransformableItem.isNull()) { - if ((d->identityMatrix || d->matrix.type() <= QTransform::TxScale)) { - QTransform xinv = viewportTransform().inverted(); - return d->scene->items(xinv.mapRect(QRectF(pos.x(), pos.y(), 1, 1))); - } - return d->scene->items(mapToScene(pos.x(), pos.y(), 1, 1)); + // ### Unify these two, and use the items(QPointF) version in + // QGraphicsScene instead. The scene items function could use the viewport + // transform to map the point to a rect/polygon. + if ((d->identityMatrix || d->matrix.type() <= QTransform::TxScale)) { + // Use the rect version + QTransform xinv = viewportTransform().inverted(); + return d->scene->items(xinv.mapRect(QRectF(pos.x(), pos.y(), 1, 1)), + Qt::IntersectsItemShape, + Qt::AscendingOrder, + viewportTransform()); } - - QPainterPath path; - path.addRect(QRectF(pos.x(), pos.y(), 1, 1)); - return d->itemsInArea(path); + // Use the polygon version + return d->scene->items(mapToScene(pos.x(), pos.y(), 1, 1), + Qt::IntersectsItemShape, + Qt::AscendingOrder, + viewportTransform()); } /*! @@ -2088,12 +2015,7 @@ QList QGraphicsView::items(const QRect &rect, Qt::ItemSelection Q_D(const QGraphicsView); if (!d->scene) return QList(); - if (d->scene->d_func()->largestUntransformableItem.isNull()) - return d->scene->items(mapToScene(rect), mode); - - QPainterPath path; - path.addRect(rect); - return d->itemsInArea(path); + return d->scene->items(mapToScene(rect), mode, Qt::AscendingOrder, viewportTransform()); } /*! @@ -2121,13 +2043,7 @@ QList QGraphicsView::items(const QPolygon &polygon, Qt::ItemSel Q_D(const QGraphicsView); if (!d->scene) return QList(); - if (d->scene->d_func()->largestUntransformableItem.isNull()) - return d->scene->items(mapToScene(polygon), mode); - - QPainterPath path; - path.addPolygon(polygon); - path.closeSubpath(); - return d->itemsInArea(path); + return d->scene->items(mapToScene(polygon), mode, Qt::AscendingOrder, viewportTransform()); } /*! @@ -2147,9 +2063,7 @@ QList QGraphicsView::items(const QPainterPath &path, Qt::ItemSe Q_D(const QGraphicsView); if (!d->scene) return QList(); - if (d->scene->d_func()->largestUntransformableItem.isNull()) - return d->scene->items(mapToScene(path), mode); - return d->itemsInArea(path); + return d->scene->items(mapToScene(path), mode, Qt::AscendingOrder, viewportTransform()); } /*! @@ -2168,7 +2082,9 @@ QGraphicsItem *QGraphicsView::itemAt(const QPoint &pos) const Q_D(const QGraphicsView); if (!d->scene) return 0; - QList itemsAtPos = items(pos); + // ### Use QGraphicsScene::itemAt() instead. + QList itemsAtPos = d->scene->items(pos, Qt::IntersectsItemShape, Qt::AscendingOrder, + viewportTransform()); return itemsAtPos.isEmpty() ? 0 : itemsAtPos.first(); } @@ -3073,7 +2989,8 @@ void QGraphicsView::mouseMoveEvent(QMouseEvent *event) selectionArea.addPolygon(mapToScene(d->rubberBandRect)); selectionArea.closeSubpath(); if (d->scene) - d->scene->setSelectionArea(selectionArea, d->rubberBandSelectionMode); + d->scene->setSelectionArea(selectionArea, d->rubberBandSelectionMode, + viewportTransform()); return; } } else @@ -3280,7 +3197,7 @@ void QGraphicsView::paintEvent(QPaintEvent *event) } else { // Find all exposed items bool allItems = false; - QList itemList = d->findItems(d->exposedRegion, &allItems); + QList itemList = d->findItems(d->exposedRegion, &allItems, viewTransform); if (!itemList.isEmpty()) { // Generate the style options. diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h index fac7bf9..760f54e 100644 --- a/src/gui/graphicsview/qgraphicsview_p.h +++ b/src/gui/graphicsview/qgraphicsview_p.h @@ -84,10 +84,6 @@ public: qint64 horizontalScroll() const; qint64 verticalScroll() const; - QList itemsInArea(const QPainterPath &path, - Qt::ItemSelectionMode mode = Qt::IntersectsItemShape, - Qt::SortOrder = Qt::AscendingOrder) const; - QPointF mousePressItemPoint; QPointF mousePressScenePoint; QPoint mousePressViewPoint; @@ -176,7 +172,8 @@ public: bool updateSceneSlotReimplementedChecked; QRegion exposedRegion; - QList findItems(const QRegion &exposedRegion, bool *allItems) const; + QList findItems(const QRegion &exposedRegion, bool *allItems, + const QTransform &viewTransform) const; }; QT_END_NAMESPACE -- cgit v0.12 From b8ca90d6ca745915455f044f967a345bab7a910e Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Thu, 18 Jun 2009 14:49:24 +0200 Subject: Move QGraphicsSceneIndex into private headers (=> _p.h). We'd like to keep this API private for now. Reviewed-by: Alexis --- src/gui/graphicsview/graphicsview.pri | 57 +++++---- src/gui/graphicsview/qgraphicsscene.cpp | 5 +- src/gui/graphicsview/qgraphicsscene_p.h | 2 +- .../graphicsview/qgraphicsscenebsptreeindex.cpp | 4 +- src/gui/graphicsview/qgraphicsscenebsptreeindex.h | 2 +- src/gui/graphicsview/qgraphicssceneindex.cpp | 5 +- src/gui/graphicsview/qgraphicssceneindex.h | 129 --------------------- src/gui/graphicsview/qgraphicssceneindex_p.h | 79 +++++++++++-- src/gui/graphicsview/qgraphicsscenelinearindex.h | 2 +- 9 files changed, 106 insertions(+), 179 deletions(-) delete mode 100644 src/gui/graphicsview/qgraphicssceneindex.h diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri index 5ac1c54..2d8f37e 100644 --- a/src/gui/graphicsview/graphicsview.pri +++ b/src/gui/graphicsview/graphicsview.pri @@ -1,46 +1,43 @@ # Qt graphicsview module -HEADERS += graphicsview/qgraphicsitem.h \ +HEADERS += graphicsview/qgraphicsgridlayout.h \ + graphicsview/qgraphicsitem.h \ graphicsview/qgraphicsitem_p.h \ graphicsview/qgraphicsitemanimation.h \ + graphicsview/qgraphicslayout.h \ + graphicsview/qgraphicslayout_p.h \ + graphicsview/qgraphicslayoutitem.h \ + graphicsview/qgraphicslayoutitem_p.h \ + graphicsview/qgraphicslinearlayout.h \ + graphicsview/qgraphicsproxywidget.h \ graphicsview/qgraphicsscene.h \ - graphicsview/qgraphicsscene_p.h \ graphicsview/qgraphicsscene_bsp_p.h \ - graphicsview/qgraphicsscenelinearindex.h \ - graphicsview/qgraphicssceneindex.h \ - graphicsview/qgraphicssceneindex_p.h \ + graphicsview/qgraphicsscene_p.h \ graphicsview/qgraphicsscenebsptreeindex.h \ graphicsview/qgraphicsscenebsptreeindex_p.h \ graphicsview/qgraphicssceneevent.h \ + graphicsview/qgraphicssceneindex_p.h \ + graphicsview/qgraphicsscenelinearindex.h \ + graphicsview/qgraphicsview.h \ graphicsview/qgraphicsview_p.h \ - graphicsview/qgraphicsview.h -SOURCES += graphicsview/qgraphicsitem.cpp \ - graphicsview/qgraphicsitemanimation.cpp \ - graphicsview/qgraphicsscene.cpp \ - graphicsview/qgraphicsscene_bsp.cpp \ - graphicsview/qgraphicsscenebsptreeindex.cpp \ - graphicsview/qgraphicsscenelinearindex.cpp \ - graphicsview/qgraphicssceneindex.cpp \ - graphicsview/qgraphicssceneevent.cpp \ - graphicsview/qgraphicsview.cpp - - -# Widgets on the canvas -HEADERS += graphicsview/qgraphicslayout.h \ - graphicsview/qgraphicslayout_p.h \ - graphicsview/qgraphicslayoutitem.h \ - graphicsview/qgraphicslayoutitem_p.h \ - graphicsview/qgraphicslinearlayout.h \ graphicsview/qgraphicswidget.h \ graphicsview/qgraphicswidget_p.h \ - graphicsview/qgridlayoutengine_p.h \ - graphicsview/qgraphicsproxywidget.h \ - graphicsview/qgraphicsgridlayout.h -SOURCES += graphicsview/qgraphicslayout.cpp \ + graphicsview/qgridlayoutengine_p.h + +SOURCES += graphicsview/qgraphicsgridlayout.cpp \ + graphicsview/qgraphicsitem.cpp \ + graphicsview/qgraphicsitemanimation.cpp \ + graphicsview/qgraphicslayout.cpp \ graphicsview/qgraphicslayout_p.cpp \ graphicsview/qgraphicslayoutitem.cpp \ graphicsview/qgraphicslinearlayout.cpp \ + graphicsview/qgraphicsproxywidget.cpp \ + graphicsview/qgraphicsscene.cpp \ + graphicsview/qgraphicsscene_bsp.cpp \ + graphicsview/qgraphicsscenebsptreeindex.cpp \ + graphicsview/qgraphicssceneevent.cpp \ + graphicsview/qgraphicssceneindex.cpp \ + graphicsview/qgraphicsscenelinearindex.cpp \ + graphicsview/qgraphicsview.cpp \ graphicsview/qgraphicswidget.cpp \ graphicsview/qgraphicswidget_p.cpp \ - graphicsview/qgridlayoutengine.cpp \ - graphicsview/qgraphicsproxywidget.cpp \ - graphicsview/qgraphicsgridlayout.cpp + graphicsview/qgridlayoutengine.cpp diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 55f0f20..9d224b1 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -217,7 +217,6 @@ #include "qgraphicsview_p.h" #include "qgraphicswidget.h" #include "qgraphicswidget_p.h" -#include "qgraphicssceneindex.h" #include "qgraphicsscenebsptreeindex.h" #include "qgraphicsscenelinearindex.h" @@ -244,6 +243,7 @@ #include #include #include +#include #include #ifdef Q_WS_X11 #include @@ -772,6 +772,7 @@ QList QGraphicsScenePrivate::itemsAtPosition(const QPoint &scre const QPointF &scenePos, QWidget *widget) const { + Q_UNUSED(screenPos); Q_Q(const QGraphicsScene); QGraphicsView *view = widget ? qobject_cast(widget->parentWidget()) : 0; return q->items(scenePos, Qt::IntersectsItemShape, Qt::AscendingOrder, @@ -1806,7 +1807,7 @@ void QGraphicsScene::setSelectionArea(const QPainterPath &path) */ void QGraphicsScene::setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode) { - setSelectionArea(path, Qt::IntersectsItemShape, QTransform()); + setSelectionArea(path, mode, QTransform()); } /*! diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index a081e04..fd25283 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -58,7 +58,6 @@ #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW #include "qgraphicsscenebsptreeindex_p.h" -#include "qgraphicssceneindex.h" #include "qgraphicsview.h" #include "qgraphicsitem_p.h" @@ -74,6 +73,7 @@ QT_BEGIN_NAMESPACE +class QGraphicsSceneIndex; class QGraphicsView; class QGraphicsWidget; diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 40cafa6..54bf09b 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -80,12 +80,12 @@ #ifndef QT_NO_GRAPHICSVIEW #include "qgraphicsscenebsptreeindex_p.h" -#include "qgraphicssceneindex_p.h" #include "qgraphicsitem_p.h" #include "qgraphicsscene_p.h" -#include +#include +#include #include QT_BEGIN_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex.h index 504ea8b..f3c77d3 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.h @@ -67,7 +67,7 @@ QT_MODULE(Gui) #include #include #include -#include +#include #include "qgraphicsscene_bsp_p.h" diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index eb3abc1..8d7581f 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -56,12 +56,11 @@ \sa QGraphicsScene, QGraphicsView */ -#include "qgraphicssceneindex.h" -#include "qgraphicssceneindex_p.h" #include "qgraphicsscene.h" #include "qgraphicsitem_p.h" #include "qgraphicsscene_p.h" #include "qgraphicswidget.h" +#include #ifndef QT_NO_GRAPHICSVIEW @@ -621,6 +620,6 @@ void QGraphicsSceneIndex::sceneRectChanged(const QRectF &rect) QT_END_NAMESPACE -#include "moc_qgraphicssceneindex.cpp" +#include "moc_qgraphicssceneindex_p.cpp" #endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h deleted file mode 100644 index 25ece04..0000000 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ /dev/null @@ -1,129 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSSCENEINDEX_H -#define QGRAPHICSSCENEINDEX_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header -// file may change from version to version without notice, or even be removed. -// -// We mean it. -// - -#include -#include -#include -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -class QGraphicsSceneIndexPrivate; -class QGraphicsScene; -class QRectF; -class QPointF; -template class QList; - -class Q_AUTOTEST_EXPORT QGraphicsSceneIndex: public QObject -{ - Q_OBJECT - -public: - QGraphicsSceneIndex(QGraphicsScene *scene = 0); - virtual ~QGraphicsSceneIndex(); - - QGraphicsScene *scene() const; - - virtual QRectF indexedRect() const; - - virtual QList items(Qt::SortOrder order = Qt::AscendingOrder) const = 0; - virtual QList items(const QPointF &pos, Qt::ItemSelectionMode mode, - Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; - virtual QList items(const QRectF &rect, Qt::ItemSelectionMode mode, - Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; - virtual QList items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, - Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; - virtual QList items(const QPainterPath &path, Qt::ItemSelectionMode mode, - Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; - virtual QList estimateItems(const QPointF &point, - Qt::SortOrder order, const QTransform &deviceTransform) const; - virtual QList estimateItems(const QRectF &rect, - Qt::SortOrder order, const QTransform &deviceTransform) const = 0; - -protected: - virtual void clear(); - virtual void addItem(QGraphicsItem *item) = 0; - virtual void removeItem(QGraphicsItem *item) = 0; - virtual void deleteItem(QGraphicsItem *item); - - virtual void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const QVariant &value); - virtual void prepareBoundingRectChange(const QGraphicsItem *item); - virtual void sceneRectChanged(const QRectF &rect); - - QGraphicsSceneIndex(QObjectPrivate &dd, QGraphicsScene *scene); - - friend class QGraphicsScene; - friend class QGraphicsScenePrivate; - friend class QGraphicsItem; - friend class QGraphicsItemPrivate; - friend class QGraphicsSceneBspTreeIndex; -private: - Q_DISABLE_COPY(QGraphicsSceneIndex) - Q_DECLARE_PRIVATE(QGraphicsSceneIndex) -}; - -#endif // QT_NO_GRAPHICSVIEW - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QGRAPHICSSCENEINDEX_H diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h index 576ee98..85a1140 100644 --- a/src/gui/graphicsview/qgraphicssceneindex_p.h +++ b/src/gui/graphicsview/qgraphicssceneindex_p.h @@ -39,8 +39,8 @@ ** ****************************************************************************/ -#ifndef QGRAPHICSSCENEINDEX_P_H -#define QGRAPHICSSCENEINDEX_P_H +#ifndef QGRAPHICSSCENEINDEX_H +#define QGRAPHICSSCENEINDEX_H // // W A R N I N G @@ -53,20 +53,77 @@ // We mean it. // -#include "qgraphicssceneindex.h" - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - +#include +#include +#include +#include #include -#include + +QT_BEGIN_HEADER QT_BEGIN_NAMESPACE +QT_MODULE(Gui) + +#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW + class QGraphicsScene; class QGraphicsSceneIndexIntersector; -class QGraphicsSceneIndexRectIntersector; class QGraphicsSceneIndexPointIntersector; +class QGraphicsSceneIndexRectIntersector; class QGraphicsSceneIndexPathIntersector; +class QGraphicsSceneIndexPrivate; +class QPointF; +class QRectF; +template class QList; + +class Q_AUTOTEST_EXPORT QGraphicsSceneIndex : public QObject +{ + Q_OBJECT + +public: + QGraphicsSceneIndex(QGraphicsScene *scene = 0); + virtual ~QGraphicsSceneIndex(); + + QGraphicsScene *scene() const; + + virtual QRectF indexedRect() const; + + virtual QList items(Qt::SortOrder order = Qt::AscendingOrder) const = 0; + virtual QList items(const QPointF &pos, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + virtual QList items(const QRectF &rect, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + virtual QList items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + virtual QList items(const QPainterPath &path, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + virtual QList estimateItems(const QPointF &point, + Qt::SortOrder order, const QTransform &deviceTransform) const; + virtual QList estimateItems(const QRectF &rect, + Qt::SortOrder order, const QTransform &deviceTransform) const = 0; + +protected: + virtual void clear(); + virtual void addItem(QGraphicsItem *item) = 0; + virtual void removeItem(QGraphicsItem *item) = 0; + virtual void deleteItem(QGraphicsItem *item); + + virtual void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const QVariant &value); + virtual void prepareBoundingRectChange(const QGraphicsItem *item); + virtual void sceneRectChanged(const QRectF &rect); + + QGraphicsSceneIndex(QObjectPrivate &dd, QGraphicsScene *scene); + + friend class QGraphicsScene; + friend class QGraphicsScenePrivate; + friend class QGraphicsItem; + friend class QGraphicsItemPrivate; + friend class QGraphicsSceneBspTreeIndex; +private: + Q_DISABLE_COPY(QGraphicsSceneIndex) + Q_DECLARE_PRIVATE(QGraphicsSceneIndex) +}; class QGraphicsSceneIndexPrivate : public QObjectPrivate { @@ -96,8 +153,10 @@ public: const QTransform &transform, const QTransform &deviceTransform) const = 0; }; +#endif // QT_NO_GRAPHICSVIEW + QT_END_NAMESPACE -#endif // QGRAPHICSSCENEINDEX_P_H +QT_END_HEADER -#endif +#endif // QGRAPHICSSCENEINDEX_H diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex.h b/src/gui/graphicsview/qgraphicsscenelinearindex.h index b793d98..a5327ef 100644 --- a/src/gui/graphicsview/qgraphicsscenelinearindex.h +++ b/src/gui/graphicsview/qgraphicsscenelinearindex.h @@ -65,8 +65,8 @@ QT_MODULE(Gui) #include #include -#include #include +#include class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex { -- cgit v0.12 From d49fd874258c055b54b122a0c1f6f10ee20f11ea Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Thu, 18 Jun 2009 14:52:47 +0200 Subject: Move QGraphicsSceneLinearIndex into private headers (=> _p.h). We want to keep this as private API for now. Reviewed-by: Alexis --- src/gui/graphicsview/graphicsview.pri | 2 +- src/gui/graphicsview/qgraphicsscene.cpp | 2 +- src/gui/graphicsview/qgraphicsscenelinearindex.cpp | 4 +- src/gui/graphicsview/qgraphicsscenelinearindex.h | 124 --------------------- src/gui/graphicsview/qgraphicsscenelinearindex_p.h | 124 +++++++++++++++++++++ 5 files changed, 128 insertions(+), 128 deletions(-) delete mode 100644 src/gui/graphicsview/qgraphicsscenelinearindex.h create mode 100644 src/gui/graphicsview/qgraphicsscenelinearindex_p.h diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri index 2d8f37e..5981ce5 100644 --- a/src/gui/graphicsview/graphicsview.pri +++ b/src/gui/graphicsview/graphicsview.pri @@ -16,7 +16,7 @@ HEADERS += graphicsview/qgraphicsgridlayout.h \ graphicsview/qgraphicsscenebsptreeindex_p.h \ graphicsview/qgraphicssceneevent.h \ graphicsview/qgraphicssceneindex_p.h \ - graphicsview/qgraphicsscenelinearindex.h \ + graphicsview/qgraphicsscenelinearindex_p.h \ graphicsview/qgraphicsview.h \ graphicsview/qgraphicsview_p.h \ graphicsview/qgraphicswidget.h \ diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 9d224b1..e004917 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -218,7 +218,7 @@ #include "qgraphicswidget.h" #include "qgraphicswidget_p.h" #include "qgraphicsscenebsptreeindex.h" -#include "qgraphicsscenelinearindex.h" +#include #include #include diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex.cpp b/src/gui/graphicsview/qgraphicsscenelinearindex.cpp index 5504493..694062b 100644 --- a/src/gui/graphicsview/qgraphicsscenelinearindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenelinearindex.cpp @@ -1,5 +1,3 @@ -#include "qgraphicsscenelinearindex.h" - /*! \class QGraphicsSceneLinearIndex \brief The QGraphicsSceneLinearIndex class provides an implementation of @@ -16,6 +14,8 @@ \sa QGraphicsScene, QGraphicsView, QGraphicsSceneIndex, QGraphicsSceneBspTreeIndex */ +#include + /*! \fn QGraphicsSceneLinearIndex::QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0): diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex.h b/src/gui/graphicsview/qgraphicsscenelinearindex.h deleted file mode 100644 index a5327ef..0000000 --- a/src/gui/graphicsview/qgraphicsscenelinearindex.h +++ /dev/null @@ -1,124 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSSCENELINEARINDEX_H -#define QGRAPHICSSCENELINEARINDEX_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -#include -#include -#include -#include - -class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex -{ - Q_OBJECT - -public: - QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0): QGraphicsSceneIndex(scene) - { - } - - QList items(Qt::SortOrder order = Qt::AscendingOrder) const { - Q_UNUSED(order); - return m_items; - } - - virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const { - Q_UNUSED(rect); - Q_UNUSED(order); - Q_UNUSED(deviceTransform); - return m_items; - } - - virtual QRectF indexedRect() const { - return m_sceneRect; - } - -protected : - void sceneRectChanged(const QRectF &rect) { - m_sceneRect = rect; - } - - virtual void clear() { - m_items.clear(); - } - - virtual void addItem(QGraphicsItem *item) { - m_items << item; - } - - virtual void removeItem(QGraphicsItem *item) { - m_items.removeAll(item); - } - -private: - QRectF m_sceneRect; - QList m_items; -}; - -#endif // QT_NO_GRAPHICSVIEW - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QGRAPHICSSCENELINEARINDEX_H diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h new file mode 100644 index 0000000..a5327ef --- /dev/null +++ b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSCENELINEARINDEX_H +#define QGRAPHICSSCENELINEARINDEX_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW + +#include +#include +#include +#include + +class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex +{ + Q_OBJECT + +public: + QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0): QGraphicsSceneIndex(scene) + { + } + + QList items(Qt::SortOrder order = Qt::AscendingOrder) const { + Q_UNUSED(order); + return m_items; + } + + virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const { + Q_UNUSED(rect); + Q_UNUSED(order); + Q_UNUSED(deviceTransform); + return m_items; + } + + virtual QRectF indexedRect() const { + return m_sceneRect; + } + +protected : + void sceneRectChanged(const QRectF &rect) { + m_sceneRect = rect; + } + + virtual void clear() { + m_items.clear(); + } + + virtual void addItem(QGraphicsItem *item) { + m_items << item; + } + + virtual void removeItem(QGraphicsItem *item) { + m_items.removeAll(item); + } + +private: + QRectF m_sceneRect; + QList m_items; +}; + +#endif // QT_NO_GRAPHICSVIEW + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGRAPHICSSCENELINEARINDEX_H -- cgit v0.12 From 734cc7dd63147f80cd4794351b9124f8d6eb88fe Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Thu, 18 Jun 2009 14:56:59 +0200 Subject: Move QGraphicsSceneBspTreeIndex into private headers (=> _p.h). We'll keep this as private API for now. Reviewed-by: Alexis --- src/gui/graphicsview/graphicsview.pri | 1 - src/gui/graphicsview/qgraphicsscene.cpp | 2 +- .../graphicsview/qgraphicsscenebsptreeindex.cpp | 10 +- src/gui/graphicsview/qgraphicsscenebsptreeindex.h | 119 --------------------- .../graphicsview/qgraphicsscenebsptreeindex_p.h | 66 ++++++++++-- 5 files changed, 61 insertions(+), 137 deletions(-) delete mode 100644 src/gui/graphicsview/qgraphicsscenebsptreeindex.h diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri index 5981ce5..0c0747e 100644 --- a/src/gui/graphicsview/graphicsview.pri +++ b/src/gui/graphicsview/graphicsview.pri @@ -12,7 +12,6 @@ HEADERS += graphicsview/qgraphicsgridlayout.h \ graphicsview/qgraphicsscene.h \ graphicsview/qgraphicsscene_bsp_p.h \ graphicsview/qgraphicsscene_p.h \ - graphicsview/qgraphicsscenebsptreeindex.h \ graphicsview/qgraphicsscenebsptreeindex_p.h \ graphicsview/qgraphicssceneevent.h \ graphicsview/qgraphicssceneindex_p.h \ diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index e004917..28dd3be 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -217,7 +217,7 @@ #include "qgraphicsview_p.h" #include "qgraphicswidget.h" #include "qgraphicswidget_p.h" -#include "qgraphicsscenebsptreeindex.h" +#include #include #include diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 54bf09b..27b5514 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -75,14 +75,10 @@ \sa QGraphicsScene, QGraphicsView, QGraphicsSceneIndex */ -#include "qgraphicsscenebsptreeindex.h" - #ifndef QT_NO_GRAPHICSVIEW -#include "qgraphicsscenebsptreeindex_p.h" -#include "qgraphicsitem_p.h" -#include "qgraphicsscene_p.h" - +#include +#include #include #include @@ -783,7 +779,7 @@ bool QGraphicsSceneBspTreeIndex::event(QEvent *event) QT_END_NAMESPACE -#include "moc_qgraphicsscenebsptreeindex.cpp" +#include "moc_qgraphicsscenebsptreeindex_p.cpp" #endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex.h deleted file mode 100644 index f3c77d3..0000000 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.h +++ /dev/null @@ -1,119 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header -// file may change from version to version without notice, or even be removed. -// -// We mean it. -// - -#ifndef QGRAPHICSBSPTREEINDEX_H -#define QGRAPHICSBSPTREEINDEX_H - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -#include -#include -#include -#include -#include - -#include "qgraphicsscene_bsp_p.h" - -class QGraphicsSceneBspTreeIndexPrivate; - -class Q_AUTOTEST_EXPORT QGraphicsSceneBspTreeIndex : public QGraphicsSceneIndex -{ - Q_OBJECT - Q_PROPERTY(int bspTreeDepth READ bspTreeDepth WRITE setBspTreeDepth) -public: - QGraphicsSceneBspTreeIndex(QGraphicsScene *scene = 0); - QRectF indexedRect() const; - - QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const; - - QList items(Qt::SortOrder order = Qt::AscendingOrder) const; - - int bspTreeDepth(); - void setBspTreeDepth(int depth); - -protected: - bool event(QEvent *event); - void clear(); - - void addItem(QGraphicsItem *item); - void removeItem(QGraphicsItem *item); - void deleteItem(QGraphicsItem *item); - void prepareBoundingRectChange(const QGraphicsItem *item); - - void sceneRectChanged(const QRectF &rect); - void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value); - -private : - Q_DECLARE_PRIVATE(QGraphicsSceneBspTreeIndex) - Q_DISABLE_COPY(QGraphicsSceneBspTreeIndex) - Q_PRIVATE_SLOT(d_func(), void _q_updateSortCache()) - Q_PRIVATE_SLOT(d_func(), void _q_updateIndex()) - - friend class QGraphicsScene; - friend class QGraphicsScenePrivate; -}; - -#endif // QT_NO_GRAPHICSVIEW - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QGRAPHICSBSPTREEINDEX_H diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index ed12fac..1e4234e 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -39,8 +39,7 @@ ** ****************************************************************************/ -#ifndef QGRAPHICSSCENEBSPTREEINDEX_P_H -#define QGRAPHICSSCENEBSPTREEINDEX_P_H +#include // // W A R N I N G @@ -53,18 +52,66 @@ // We mean it. // -#include "qgraphicsscenebsptreeindex.h" +#ifndef QGRAPHICSBSPTREEINDEX_H +#define QGRAPHICSBSPTREEINDEX_H + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW -#include +#include +#include +#include +#include #include - -QT_BEGIN_NAMESPACE +#include +#include static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; class QGraphicsScene; +class QGraphicsSceneBspTreeIndexPrivate; + +class Q_AUTOTEST_EXPORT QGraphicsSceneBspTreeIndex : public QGraphicsSceneIndex +{ + Q_OBJECT + Q_PROPERTY(int bspTreeDepth READ bspTreeDepth WRITE setBspTreeDepth) +public: + QGraphicsSceneBspTreeIndex(QGraphicsScene *scene = 0); + QRectF indexedRect() const; + + QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const; + + QList items(Qt::SortOrder order = Qt::AscendingOrder) const; + + int bspTreeDepth(); + void setBspTreeDepth(int depth); + +protected: + bool event(QEvent *event); + void clear(); + + void addItem(QGraphicsItem *item); + void removeItem(QGraphicsItem *item); + void deleteItem(QGraphicsItem *item); + void prepareBoundingRectChange(const QGraphicsItem *item); + + void sceneRectChanged(const QRectF &rect); + void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value); + +private : + Q_DECLARE_PRIVATE(QGraphicsSceneBspTreeIndex) + Q_DISABLE_COPY(QGraphicsSceneBspTreeIndex) + Q_PRIVATE_SLOT(d_func(), void _q_updateSortCache()) + Q_PRIVATE_SLOT(d_func(), void _q_updateIndex()) + + friend class QGraphicsScene; + friend class QGraphicsScenePrivate; +}; class QGraphicsSceneBspTreeIndexPrivate : public QGraphicsSceneIndexPrivate { @@ -183,9 +230,10 @@ static inline bool QRectF_intersects(const QRectF &s, const QRectF &r) return !(t1 >= b2 || t2 >= b1); } -QT_END_NAMESPACE +#endif // QT_NO_GRAPHICSVIEW -#endif // QGRAPHICSSCENEBSPTREEINDEX_P_H +QT_END_NAMESPACE -#endif +QT_END_HEADER +#endif // QGRAPHICSBSPTREEINDEX_H -- cgit v0.12 From 378b5b603bd269b631bbe108268a683adde11828 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Thu, 18 Jun 2009 15:02:05 +0200 Subject: Make the autotests compile again. Reviewed-by: Alexis --- .../tst_qgraphicssceneindex.cpp | 23 +++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp index 6b352ab..d10f86d 100644 --- a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -42,11 +42,10 @@ #include #include -#include #include +#include #include - //TESTED_CLASS= //TESTED_FILES= @@ -118,6 +117,7 @@ void tst_QGraphicsSceneIndex::customIndex_data() void tst_QGraphicsSceneIndex::customIndex() { +#if 0 QFETCH(QString, indexMethod); QGraphicsSceneIndex *index = createIndex(indexMethod); @@ -126,6 +126,7 @@ void tst_QGraphicsSceneIndex::customIndex() scene.addRect(0, 0, 30, 40); QCOMPARE(scene.items(QRectF(0, 0, 10, 10)).count(), 1); +#endif } void tst_QGraphicsSceneIndex::scatteredItems_data() @@ -136,10 +137,14 @@ void tst_QGraphicsSceneIndex::scatteredItems_data() void tst_QGraphicsSceneIndex::scatteredItems() { QFETCH(QString, indexMethod); - QGraphicsSceneIndex *index = createIndex(indexMethod); QGraphicsScene scene; +#if 1 + scene.setItemIndexMethod(indexMethod == "linear" ? QGraphicsScene::NoIndex : QGraphicsScene::BspTreeIndex); +#else + QGraphicsSceneIndex *index = createIndex(indexMethod); scene.setSceneIndex(index); +#endif for (int i = 0; i < 10; ++i) scene.addRect(i*50, i*50, 40, 35); @@ -161,10 +166,14 @@ void tst_QGraphicsSceneIndex::overlappedItems_data() void tst_QGraphicsSceneIndex::overlappedItems() { QFETCH(QString, indexMethod); - QGraphicsSceneIndex *index = createIndex(indexMethod); QGraphicsScene scene; +#if 1 + scene.setItemIndexMethod(indexMethod == "linear" ? QGraphicsScene::NoIndex : QGraphicsScene::BspTreeIndex); +#else + QGraphicsSceneIndex *index = createIndex(indexMethod); scene.setSceneIndex(index); +#endif for (int i = 0; i < 10; ++i) for (int j = 0; j < 10; ++j) @@ -191,10 +200,14 @@ void tst_QGraphicsSceneIndex::movingItems_data() void tst_QGraphicsSceneIndex::movingItems() { QFETCH(QString, indexMethod); - QGraphicsSceneIndex *index = createIndex(indexMethod); QGraphicsScene scene; +#if 1 + scene.setItemIndexMethod(indexMethod == "linear" ? QGraphicsScene::NoIndex : QGraphicsScene::BspTreeIndex); +#else + QGraphicsSceneIndex *index = createIndex(indexMethod); scene.setSceneIndex(index); +#endif for (int i = 0; i < 10; ++i) scene.addRect(i*50, i*50, 40, 35); -- cgit v0.12 From a18e5288324aa13da014ee52daffbfc589c87be3 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Thu, 18 Jun 2009 17:29:42 +0200 Subject: Fix crash with untransformable items. Be sure that item goes in the correct list if it set its flags to untransformable. Reviewed-by: andreas --- .../graphicsview/qgraphicsscenebsptreeindex.cpp | 43 +++++++++++++++------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 27b5514..72636b8 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -548,14 +548,9 @@ void QGraphicsSceneBspTreeIndexPrivate::removeFromBspTree(QGraphicsItem *item) // ### remove from child index only if applicable return; } - int index = item->d_func()->index; - if (index != -1) { - bsp.removeItem(item, item->sceneBoundingRect()); - freeItemIndexes << index; - indexedItems[index] = 0; - item->d_func()->index = -1; - unindexedItems << item; + if (item->d_func()->index != -1) { + bsp.removeItem(item, item->sceneBoundingRect()); //prepareGeometryChange will call prepareBoundingRectChange foreach (QGraphicsItem *child, item->children()) child->prepareGeometryChange(); @@ -570,10 +565,20 @@ void QGraphicsSceneBspTreeIndexPrivate::removeFromBspTree(QGraphicsItem *item) void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem *item) { Q_D(QGraphicsSceneBspTreeIndex); - // Note: This will access item's sceneBoundingRect(), which (as this is - // C++) is why we cannot call removeItem() from QGraphicsItem's - // destructor. - d->removeFromBspTree(const_cast(item)); + if (!item->d_ptr->itemIsUntransformable()) { + // Note: This will access item's sceneBoundingRect(), which (as this is + // C++) is why we cannot call removeItem() from QGraphicsItem's + // destructor. + QGraphicsItem *thatItem = const_cast(item); + d->removeFromBspTree(thatItem); + int index = item->d_func()->index; + if (index != -1) { + d->freeItemIndexes << index; + d->indexedItems[index] = 0; + thatItem->d_func()->index = -1; + d->unindexedItems << thatItem; + } + } } /*! @@ -725,7 +730,13 @@ void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphics if (ignoredTransform != willIgnoreTransform) { QGraphicsItem *thatItem = const_cast(item); removeItem(thatItem); - addItem(thatItem); + thatItem->d_ptr->index = -1; + if (willIgnoreTransform) { + d->untransformableItems << thatItem; + } else { + d->unindexedItems << thatItem; + d->startIndexTimer(0); + } } break; } @@ -741,7 +752,13 @@ void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphics if (ignoredTransform != willIgnoreTransform) { QGraphicsItem *thatItem = const_cast(item); removeItem(thatItem); - addItem(thatItem); + thatItem->d_ptr->index = -1; + if (willIgnoreTransform) { + d->untransformableItems << thatItem; + } else { + d->unindexedItems << thatItem; + d->startIndexTimer(0); + } } break; } -- cgit v0.12 From 8befd7589456c6fd193676daeba8f0779d88776e Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Mon, 22 Jun 2009 11:32:51 +0200 Subject: Remove unused code / delay in this autotest. --- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 1ca6c98..981efeb 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -4710,11 +4710,6 @@ void tst_QGraphicsItem::itemClipsChildrenToShape() scene.render(&painter); painter.end(); - QGraphicsView view(&scene); - view.show(); - - QTest::qWait(5000); - QCOMPARE(image.pixel(16, 16), QColor(255, 0, 0).rgba()); QCOMPARE(image.pixel(32, 32), QColor(0, 0, 255).rgba()); QCOMPARE(image.pixel(50, 50), QColor(0, 255, 0).rgba()); -- cgit v0.12 From 375c4f53e9702aa3273154c0879e3b6dbd2723d6 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Mon, 22 Jun 2009 11:38:17 +0200 Subject: QGraphicsSceneLinearIndex: touch-ups. --- src/gui/graphicsview/qgraphicsscenelinearindex_p.h | 39 +++++++++------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h index a5327ef..88e0e6a 100644 --- a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h @@ -73,42 +73,35 @@ class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex Q_OBJECT public: - QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0): QGraphicsSceneIndex(scene) - { - } + QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0) : QGraphicsSceneIndex(scene) + { } - QList items(Qt::SortOrder order = Qt::AscendingOrder) const { - Q_UNUSED(order); - return m_items; - } + QList items(Qt::SortOrder order = Qt::AscendingOrder) const + { Q_UNUSED(order); return m_items; } - virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const { + virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const + { Q_UNUSED(rect); Q_UNUSED(order); Q_UNUSED(deviceTransform); return m_items; } - virtual QRectF indexedRect() const { - return m_sceneRect; - } + virtual QRectF indexedRect() const + { return m_sceneRect; } protected : - void sceneRectChanged(const QRectF &rect) { - m_sceneRect = rect; - } + void sceneRectChanged(const QRectF &rect) + { m_sceneRect = rect; } - virtual void clear() { - m_items.clear(); - } + virtual void clear() + { m_items.clear(); } - virtual void addItem(QGraphicsItem *item) { - m_items << item; - } + virtual void addItem(QGraphicsItem *item) + { m_items << item; } - virtual void removeItem(QGraphicsItem *item) { - m_items.removeAll(item); - } + virtual void removeItem(QGraphicsItem *item) + { m_items.removeOne(item); } private: QRectF m_sceneRect; -- cgit v0.12 From be79229e9c454764d63262f46f686b3e1721ee2c Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Tue, 23 Jun 2009 12:35:31 +0200 Subject: More work on getting autotests to pass. --- src/gui/graphicsview/qgraphicsscene.cpp | 33 ++++++++++++++------ src/gui/graphicsview/qgraphicsscene_p.h | 1 + .../graphicsview/qgraphicsscenebsptreeindex.cpp | 36 +++++----------------- .../graphicsview/qgraphicsscenebsptreeindex_p.h | 3 +- src/gui/graphicsview/qgraphicssceneindex.cpp | 23 +++----------- src/gui/graphicsview/qgraphicssceneindex_p.h | 4 +-- src/gui/graphicsview/qgraphicsscenelinearindex_p.h | 7 ----- src/gui/graphicsview/qgraphicsview.cpp | 16 +++++----- tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp | 28 ++++++++++++++--- tests/auto/qgraphicsview/tst_qgraphicsview.cpp | 1 + 10 files changed, 71 insertions(+), 81 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 2f7ae04..6f92629 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -273,6 +273,7 @@ QGraphicsScenePrivate::QGraphicsScenePrivate() index(0), lastItemCount(0), hasSceneRect(false), + dirtyGrowingItemsBoundingRect(true), updateAll(false), calledEmitUpdated(false), processDirtyItemsEmitted(false), @@ -378,8 +379,9 @@ void QGraphicsScenePrivate::unregisterTopLevelItem(QGraphicsItem *item) */ void QGraphicsScenePrivate::_q_updateLater() { + QRectF null; foreach (QGraphicsItem *item, pendingUpdateItems) - item->update(); + markDirty(item, null); pendingUpdateItems.clear(); } @@ -409,8 +411,11 @@ void QGraphicsScenePrivate::_q_processDirtyItems() const bool wasPendingSceneUpdate = calledEmitUpdated; const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect; processDirtyItemsRecursive(0); - if (!hasSceneRect && oldGrowingItemsBoundingRect != growingItemsBoundingRect) + dirtyGrowingItemsBoundingRect = false; + if (oldGrowingItemsBoundingRect != growingItemsBoundingRect) { + index->sceneRectChanged(); emit q_func()->sceneRectChanged(growingItemsBoundingRect); + } if (wasPendingSceneUpdate) return; @@ -1250,9 +1255,18 @@ QGraphicsScene::~QGraphicsScene() QRectF QGraphicsScene::sceneRect() const { Q_D(const QGraphicsScene); - /// ### Remove? The growing items bounding rect might be managed - // by the scene. - return d->index->indexedRect(); + if (!d->hasSceneRect && d->dirtyGrowingItemsBoundingRect) { + // Lazily update the growing items bounding rect + QGraphicsScenePrivate *thatd = const_cast(d); + QRectF oldGrowingBoundingRect = thatd->growingItemsBoundingRect; + thatd->growingItemsBoundingRect |= itemsBoundingRect(); + thatd->dirtyGrowingItemsBoundingRect = false; + if (oldGrowingBoundingRect != thatd->growingItemsBoundingRect) { + thatd->index->sceneRectChanged(); + emit const_cast(this)->sceneRectChanged(thatd->growingItemsBoundingRect); + } + } + return d->hasSceneRect ? d->sceneRect : d->growingItemsBoundingRect; } void QGraphicsScene::setSceneRect(const QRectF &rect) { @@ -1260,8 +1274,8 @@ void QGraphicsScene::setSceneRect(const QRectF &rect) if (rect != d->sceneRect) { d->hasSceneRect = !rect.isNull(); d->sceneRect = rect; - d->index->sceneRectChanged(rect); - emit sceneRectChanged(rect); + d->index->sceneRectChanged(); + emit sceneRectChanged(d->hasSceneRect ? rect : d->growingItemsBoundingRect); } } @@ -1411,8 +1425,6 @@ void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) d->index = new QGraphicsSceneLinearIndex(this); for (int i = oldItems.size() - 1; i >= 0; --i) d->index->addItem(oldItems.at(i)); - - d->index->sceneRectChanged(d->sceneRect); } /*! @@ -2057,6 +2069,8 @@ void QGraphicsScene::addItem(QGraphicsItem *item) if (d->pendingUpdateItems.isEmpty()) QMetaObject::invokeMethod(this, "_q_updateLater", Qt::QueuedConnection); d->pendingUpdateItems << item; + } else { + d->dirtyGrowingItemsBoundingRect = true; } // Disable selectionChanged() for individual items @@ -4235,6 +4249,7 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b bool removingItemFromScene) { Q_ASSERT(item); + dirtyGrowingItemsBoundingRect = true; if (updateAll) return; diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index ea65707..8c4b2d2 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -95,6 +95,7 @@ public: QRectF sceneRect; bool hasSceneRect; + bool dirtyGrowingItemsBoundingRect; QRectF growingItemsBoundingRect; void _q_emitUpdated(); diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 72636b8..aeee982 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -122,7 +122,6 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() if (!indexTimerId) return; - QGraphicsScenePrivate * scenePrivate = q->scene()->d_func(); q->killTimer(indexTimerId); indexTimerId = 0; @@ -144,10 +143,6 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() } } - // Update growing scene rect. - QRectF oldGrowingItemsBoundingRect = scenePrivate->growingItemsBoundingRect; - scenePrivate->growingItemsBoundingRect |= unindexedItemsBoundingRect; - // Determine whether we should regenerate the BSP tree. if (bspTreeDepth == 0) { int oldDepth = intmaxlog(lastItemCount); @@ -165,7 +160,6 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() bsp.initialize(q->scene()->sceneRect(), bspTreeDepth); unindexedItems = indexedItems; lastItemCount = indexedItems.size(); - q->scene()->update(); } // Insert all unindexed items into the tree. @@ -179,10 +173,6 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() } } unindexedItems.clear(); - - // Notify scene rect changes. - if (!scenePrivate->hasSceneRect && scenePrivate->growingItemsBoundingRect != oldGrowingItemsBoundingRect) - emit q->scene()->sceneRectChanged(scenePrivate->growingItemsBoundingRect); } @@ -248,7 +238,7 @@ void QGraphicsSceneBspTreeIndexPrivate::climbTree(QGraphicsItem *item, int *stac { if (!item->d_ptr->children.isEmpty()) { QList childList = item->d_ptr->children; - qSort(childList.begin(), childList.end(), qt_closestLeaf); + qStableSort(childList.begin(), childList.end(), qt_closestLeaf); for (int i = 0; i < childList.size(); ++i) { QGraphicsItem *item = childList.at(i); if (!(item->flags() & QGraphicsItem::ItemStacksBehindParent)) @@ -287,7 +277,7 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateSortCache() topLevels << item; } - qSort(topLevels.begin(), topLevels.end(), qt_closestLeaf); + qStableSort(topLevels.begin(), topLevels.end(), qt_closestLeaf); for (int i = 0; i < topLevels.size(); ++i) climbTree(topLevels.at(i), &stackingOrder); } @@ -379,15 +369,15 @@ void QGraphicsSceneBspTreeIndexPrivate::sortItems(QList *itemLi { if (sortCacheEnabled) { if (order == Qt::AscendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemFirst_withCache); + qStableSort(itemList->begin(), itemList->end(), closestItemFirst_withCache); } else if (order == Qt::DescendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemLast_withCache); + qStableSort(itemList->begin(), itemList->end(), closestItemLast_withCache); } } else { if (order == Qt::AscendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemFirst_withoutCache); + qStableSort(itemList->begin(), itemList->end(), closestItemFirst_withoutCache); } else if (order == Qt::DescendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemLast_withoutCache); + qStableSort(itemList->begin(), itemList->end(), closestItemLast_withoutCache); } } } @@ -403,17 +393,6 @@ QGraphicsSceneBspTreeIndex::QGraphicsSceneBspTreeIndex(QGraphicsScene *scene) /*! \reimp - Return the rect indexed by the BSP index. -*/ -QRectF QGraphicsSceneBspTreeIndex::indexedRect() const -{ - Q_D(const QGraphicsSceneBspTreeIndex); - const_cast(d)->_q_updateIndex(); - return scene()->d_func()->hasSceneRect ? scene()->d_func()->sceneRect : scene()->d_func()->growingItemsBoundingRect; -} - -/*! - \reimp Clear the all the BSP index. */ void QGraphicsSceneBspTreeIndex::clear() @@ -705,10 +684,9 @@ void QGraphicsSceneBspTreeIndex::setBspTreeDepth(int depth) This method react to the \a rect change of the scene and reset the BSP tree index. */ -void QGraphicsSceneBspTreeIndex::sceneRectChanged(const QRectF &rect) +void QGraphicsSceneBspTreeIndex::sceneRectChanged() { Q_D(QGraphicsSceneBspTreeIndex); - d->sceneRect = rect; d->resetIndex(); } diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index 1e4234e..715b22f 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -82,7 +82,6 @@ class Q_AUTOTEST_EXPORT QGraphicsSceneBspTreeIndex : public QGraphicsSceneIndex Q_PROPERTY(int bspTreeDepth READ bspTreeDepth WRITE setBspTreeDepth) public: QGraphicsSceneBspTreeIndex(QGraphicsScene *scene = 0); - QRectF indexedRect() const; QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const; @@ -100,7 +99,7 @@ protected: void deleteItem(QGraphicsItem *item); void prepareBoundingRectChange(const QGraphicsItem *item); - void sceneRectChanged(const QRectF &rect); + void sceneRectChanged(); void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value); private : diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 8d7581f..4eaed2b 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -56,6 +56,7 @@ \sa QGraphicsScene, QGraphicsView */ +#include "qdebug.h" #include "qgraphicsscene.h" #include "qgraphicsitem_p.h" #include "qgraphicsscene_p.h" @@ -131,14 +132,10 @@ public: keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, pointPath, mode); } } else { - QRectF sceneBrect = transform.mapRect(brect); - keep = sceneBrect.contains(scenePoint); - if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { - QPainterPath pointPath; - pointPath.addRect(QRectF(transform.inverted().map(scenePoint), QSizeF(1, 1))); - keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, pointPath, mode); - } + QRectF sceneBoundingRect = transform.mapRect(brect); + keep = sceneBoundingRect.intersects(QRectF(scenePoint, QSizeF(1, 1))) && item->contains(transform.inverted().map(scenePoint)); } + return keep; } @@ -366,15 +363,6 @@ QGraphicsScene* QGraphicsSceneIndex::scene() const } /*! - Returns the indexed area for the index -*/ -QRectF QGraphicsSceneIndex::indexedRect() const -{ - Q_D(const QGraphicsSceneIndex); - return d->scene->d_func()->sceneRect; -} - -/*! \fn QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const @@ -613,9 +601,8 @@ void QGraphicsSceneIndex::prepareBoundingRectChange(const QGraphicsItem *item) rectangle. \a rect is the new value of the scene rectangle. \sa QGraphicsScene::sceneRect() */ -void QGraphicsSceneIndex::sceneRectChanged(const QRectF &rect) +void QGraphicsSceneIndex::sceneRectChanged() { - Q_UNUSED(rect); } QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h index 85a1140..60e9032 100644 --- a/src/gui/graphicsview/qgraphicssceneindex_p.h +++ b/src/gui/graphicsview/qgraphicssceneindex_p.h @@ -87,8 +87,6 @@ public: QGraphicsScene *scene() const; - virtual QRectF indexedRect() const; - virtual QList items(Qt::SortOrder order = Qt::AscendingOrder) const = 0; virtual QList items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; @@ -111,7 +109,7 @@ protected: virtual void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const QVariant &value); virtual void prepareBoundingRectChange(const QGraphicsItem *item); - virtual void sceneRectChanged(const QRectF &rect); + virtual void sceneRectChanged(); QGraphicsSceneIndex(QObjectPrivate &dd, QGraphicsScene *scene); diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h index 88e0e6a..9463487 100644 --- a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h @@ -87,13 +87,7 @@ public: return m_items; } - virtual QRectF indexedRect() const - { return m_sceneRect; } - protected : - void sceneRectChanged(const QRectF &rect) - { m_sceneRect = rect; } - virtual void clear() { m_items.clear(); } @@ -104,7 +98,6 @@ protected : { m_items.removeOne(item); } private: - QRectF m_sceneRect; QList m_items; }; diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index ec1746a..640f85b 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -802,13 +802,15 @@ void QGraphicsViewPrivate::processPendingUpdates() return; } + if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing) + dirtyBoundingRect.adjust(-1, -1, 1, 1); + else + dirtyBoundingRect.adjust(-2, -2, 2, 2); + if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) { - if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing) - viewport->update(dirtyBoundingRect.adjusted(-1, -1, 1, 1)); - else - viewport->update(dirtyBoundingRect.adjusted(-2, -2, 2, 2)); + viewport->update((dirtyRegion + dirtyBoundingRect).boundingRect()); } else { - viewport->update(dirtyRegion); // Already adjusted in updateRect/Region. + viewport->update(dirtyRegion + dirtyBoundingRect); // Already adjusted in updateRect/Region. } dirtyBoundingRect = QRect(); @@ -2087,9 +2089,7 @@ QGraphicsItem *QGraphicsView::itemAt(const QPoint &pos) const Q_D(const QGraphicsView); if (!d->scene) return 0; - // ### Use QGraphicsScene::itemAt() instead. - QList itemsAtPos = d->scene->items(pos, Qt::IntersectsItemShape, Qt::AscendingOrder, - viewportTransform()); + QList itemsAtPos = items(pos); return itemsAtPos.isEmpty() ? 0 : itemsAtPos.first(); } diff --git a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp index 1d03ef1..1a7a076 100644 --- a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp @@ -271,28 +271,46 @@ void tst_QGraphicsScene::construction() void tst_QGraphicsScene::sceneRect() { QGraphicsScene scene; + QSignalSpy sceneRectChanged(&scene, SIGNAL(sceneRectChanged(QRectF))); QCOMPARE(scene.sceneRect(), QRectF()); + QCOMPARE(sceneRectChanged.count(), 0); QGraphicsItem *item = scene.addRect(QRectF(0, 0, 10, 10)); - qApp->processEvents(); item->setPos(-5, -5); - qApp->processEvents(); + QCOMPARE(sceneRectChanged.count(), 0); QCOMPARE(scene.itemAt(0, 0), item); QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0); + QCOMPARE(sceneRectChanged.count(), 0); + QCOMPARE(scene.sceneRect(), QRectF(-5, -5, 10, 10)); + QCOMPARE(sceneRectChanged.count(), 1); + QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect()); + + item->setPos(0, 0); QCOMPARE(scene.sceneRect(), QRectF(-5, -5, 15, 15)); + QCOMPARE(sceneRectChanged.count(), 2); + QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect()); scene.setSceneRect(-100, -100, 10, 10); + QCOMPARE(sceneRectChanged.count(), 3); + QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect()); QCOMPARE(scene.itemAt(0, 0), item); QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0); QCOMPARE(scene.sceneRect(), QRectF(-100, -100, 10, 10)); + item->setPos(10, 10); + QCOMPARE(scene.sceneRect(), QRectF(-100, -100, 10, 10)); + QCOMPARE(sceneRectChanged.count(), 3); + QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect()); scene.setSceneRect(QRectF()); - QCOMPARE(scene.itemAt(0, 0), item); - QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0); - QCOMPARE(scene.sceneRect(), QRectF(-5, -5, 15, 15)); + QCOMPARE(scene.itemAt(10, 10), item); + QCOMPARE(scene.itemAt(20, 20), (QGraphicsItem *)0); + QCOMPARE(sceneRectChanged.count(), 4); + QCOMPARE(scene.sceneRect(), QRectF(-5, -5, 25, 25)); + QCOMPARE(sceneRectChanged.count(), 5); + QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect()); } void tst_QGraphicsScene::itemIndexMethod() diff --git a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp index c8c032a..02e4046 100644 --- a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp @@ -371,6 +371,7 @@ void tst_QGraphicsView::interactive() QCOMPARE(item->events.size(), 0); QPoint itemPoint = view.mapFromScene(item->scenePos()); + QVERIFY(view.itemAt(itemPoint)); for (int i = 0; i < 100; ++i) { -- cgit v0.12 From d39a62720ba67a0fa6e4e37519d22f14c7b7404e Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Tue, 23 Jun 2009 14:35:30 +0200 Subject: Ensure that the BSP index returns all untransformable items. --- src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index aeee982..464fe8e 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -595,6 +595,8 @@ QList QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &r for (int i = 0; i < rectItems.size(); ++i) rectItems.at(i)->d_func()->itemDiscovered = 0; + rectItems += d->untransformableItems; + d->sortItems(&rectItems, order, d->sortCacheEnabled); return rectItems; -- cgit v0.12 From b0f391ae8f2efc272be852f951403fa8e4a8f561 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Tue, 23 Jun 2009 16:57:32 +0200 Subject: Fix tst_QGraphicsItem::collidesWith_item autotest. Avoid unwanted recursion by keeping the sceneRect variable locally. The recursion happens if the call to sceneRect() lazily emits the sceneRectChanged() signal. --- src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 464fe8e..8861c7b 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -157,7 +157,7 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() // Regenerate the tree. if (regenerateIndex) { regenerateIndex = false; - bsp.initialize(q->scene()->sceneRect(), bspTreeDepth); + bsp.initialize(sceneRect, bspTreeDepth); unindexedItems = indexedItems; lastItemCount = indexedItems.size(); } @@ -689,6 +689,7 @@ void QGraphicsSceneBspTreeIndex::setBspTreeDepth(int depth) void QGraphicsSceneBspTreeIndex::sceneRectChanged() { Q_D(QGraphicsSceneBspTreeIndex); + d->sceneRect = d->scene->sceneRect(); d->resetIndex(); } -- cgit v0.12 From 4fb0f9d8d5275c21b3d16be1170b5e7d2ed77f8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 25 Jun 2009 14:36:03 +0200 Subject: Partially revert be79229e The change in processPendingUpdates was completely wrong and broke several auto-tests. --- src/gui/graphicsview/qgraphicsview.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 94547a5..e4decf9 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -802,15 +802,13 @@ void QGraphicsViewPrivate::processPendingUpdates() return; } - if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing) - dirtyBoundingRect.adjust(-1, -1, 1, 1); - else - dirtyBoundingRect.adjust(-2, -2, 2, 2); - if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) { - viewport->update((dirtyRegion + dirtyBoundingRect).boundingRect()); + if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing) + viewport->update(dirtyBoundingRect.adjusted(-1, -1, 1, 1)); + else + viewport->update(dirtyBoundingRect.adjusted(-2, -2, 2, 2)); } else { - viewport->update(dirtyRegion + dirtyBoundingRect); // Already adjusted in updateRect/Region. + viewport->update(dirtyRegion); // Already adjusted in updateRect/Region. } dirtyBoundingRect = QRect(); -- cgit v0.12 From fe64e44b0dab0152101b4ec17a49305912415016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 25 Jun 2009 14:42:16 +0200 Subject: Stabilize tst_QGraphicsView::moveItemWhileScrolling. --- tests/auto/qgraphicsview/tst_qgraphicsview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp index 02e4046..65e066f 100644 --- a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp @@ -3093,7 +3093,7 @@ void tst_QGraphicsView::moveItemWhileScrolling() #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&view); #endif - QTest::qWait(100); + QTest::qWait(200); view.lastPaintedRegion = QRegion(); view.horizontalScrollBar()->setValue(view.horizontalScrollBar()->value() + 10); -- cgit v0.12 From 9dc1fc2d30205bb0bad12df4d3cb061f55f4f3f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 25 Jun 2009 16:42:10 +0200 Subject: Compile tst_QGrahicsSceneIndex after be79229e --- .../auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp index d10f86d..ac21e20 100644 --- a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -56,8 +56,6 @@ public slots: void initTestCase(); private slots: - void sceneRect_data(); - void sceneRect(); void customIndex_data(); void customIndex(); void scatteredItems_data(); @@ -97,19 +95,6 @@ QGraphicsSceneIndex *tst_QGraphicsSceneIndex::createIndex(const QString &indexMe return index; } -void tst_QGraphicsSceneIndex::sceneRect_data() -{ - common_data(); -} - -void tst_QGraphicsSceneIndex::sceneRect() -{ - QGraphicsScene *scene = new QGraphicsScene(); - QGraphicsSceneIndex *index = new QGraphicsSceneBspTreeIndex(scene); - scene->setSceneRect(QRectF(0, 0, 2000, 2000)); - QCOMPARE(index->indexedRect(), QRectF(0, 0, 2000, 2000)); -} - void tst_QGraphicsSceneIndex::customIndex_data() { common_data(); -- cgit v0.12 From eab949e2ec8f820a54826c1a837c8c8de07814ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 25 Jun 2009 11:31:04 +0200 Subject: Re-factor parts of the QGraphicsSceneBspTreeIndex. This patch adds better support for untransformable items and removes some redundant code. --- src/gui/graphicsview/qgraphicsscene.cpp | 22 +- .../graphicsview/qgraphicsscenebsptreeindex.cpp | 282 +++++++++------------ .../graphicsview/qgraphicsscenebsptreeindex_p.h | 6 +- 3 files changed, 133 insertions(+), 177 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 06a251e..6efede2 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1954,25 +1954,13 @@ void QGraphicsScene::clearSelection() void QGraphicsScene::clear() { Q_D(QGraphicsScene); - QList items = d->index->items(); -#if 1 - QList toDelete; - // ### As the item list is already in ascending order, - // the items should be deleted in topological order. - // Recursive descent delete - for (int i = 0; i < items.size(); ++i) { - if (QGraphicsItem *item = items.at(i)) { - if (!item->parentItem()) - toDelete << item; - } - } - // We delete all top level items - qDeleteAll(toDelete); -#else + // NB! We have to clear the index before deleting items; otherwise the + // index might try to access dangling item pointers. + d->index->clear(); + const QList items = d->topLevelItems; qDeleteAll(items); -#endif + Q_ASSERT(d->topLevelItems.isEmpty()); d->lastItemCount = 0; - d->index->clear(); d->allItemsIgnoreHoverEvents = true; d->allItemsUseDefaultCursor = true; } diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 8861c7b..f6994f9 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -128,10 +128,9 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() purgeRemovedItems(); // Add unindexedItems to indexedItems - QRectF unindexedItemsBoundingRect; for (int i = 0; i < unindexedItems.size(); ++i) { if (QGraphicsItem *item = unindexedItems.at(i)) { - unindexedItemsBoundingRect |= item->sceneBoundingRect(); + item->d_ptr->itemDiscovered = 0; if (!freeItemIndexes.isEmpty()) { int freeIndex = freeItemIndexes.takeFirst(); item->d_func()->index = freeIndex; @@ -165,11 +164,14 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() // Insert all unindexed items into the tree. for (int i = 0; i < unindexedItems.size(); ++i) { if (QGraphicsItem *item = unindexedItems.at(i)) { - QRectF rect = item->sceneBoundingRect(); + if (item->d_ptr->itemIsUntransformable()) { + untransformableItems << item; + continue; + } if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) continue; - bsp.insertItem(item, rect); + bsp.insertItem(item, item->sceneBoundingRect()); } } unindexedItems.clear(); @@ -222,11 +224,13 @@ void QGraphicsSceneBspTreeIndexPrivate::resetIndex() for (int i = 0; i < indexedItems.size(); ++i) { if (QGraphicsItem *item = indexedItems.at(i)) { item->d_ptr->index = -1; + item->d_ptr->itemDiscovered = 0; unindexedItems << item; } } indexedItems.clear(); freeItemIndexes.clear(); + untransformableItems.clear(); regenerateIndex = true; startIndexTimer(); } @@ -270,10 +274,10 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateSortCache() int stackingOrder = 0; QList topLevels; - - for (int i = 0; i < q->items().count(); ++i) { - QGraphicsItem *item = q->items().at(i); - if (item && item->parentItem() == 0) + const QList items = q->items(); + for (int i = 0; i < items.size(); ++i) { + QGraphicsItem *item = items.at(i); + if (item && !item->d_ptr->parent) topLevels << item; } @@ -295,6 +299,79 @@ void QGraphicsSceneBspTreeIndexPrivate::invalidateSortCache() QMetaObject::invokeMethod(q, "_q_updateSortCache", Qt::QueuedConnection); } +void QGraphicsSceneBspTreeIndexPrivate::addItem(QGraphicsItem *item, bool recursive) +{ + if (!item) + return; + + // Prevent reusing a recently deleted pointer: purge all removed item from our lists. + purgeRemovedItems(); + + // Invalidate any sort caching; arrival of a new item means we need to resort. + // Update the scene's sort cache settings. + item->d_ptr->globalStackingOrder = -1; + invalidateSortCache(); + + // Indexing requires sceneBoundingRect(), but because \a item might + // not be completely constructed at this point, we need to store it in + // a temporary list and schedule an indexing for later. + if (item->d_ptr->index == -1) { + Q_ASSERT(!unindexedItems.contains(item)); + unindexedItems << item; + startIndexTimer(0); + } else { + Q_ASSERT(indexedItems.contains(item)); + qWarning("QGraphicsSceneBspTreeIndex::addItem: item has already been added to this BSP"); + } + + if (recursive) { + for (int i = 0; i < item->d_ptr->children.size(); ++i) + addItem(item->d_ptr->children.at(i), recursive); + } +} + +void QGraphicsSceneBspTreeIndexPrivate::removeItem(QGraphicsItem *item, bool recursive, + bool moveToUnindexedItems) +{ + if (!item) + return; + + if (item->d_ptr->index != -1) { + Q_ASSERT(item->d_ptr->index < indexedItems.size()); + Q_ASSERT(indexedItems.at(item->d_ptr->index) == item); + freeItemIndexes << item->d_ptr->index; + indexedItems[item->d_ptr->index] = 0; + item->d_ptr->index = -1; + item->d_ptr->itemDiscovered = 0; + + if (item->d_ptr->itemIsUntransformable()) { + untransformableItems.removeOne(item); + } else if (item->d_ptr->inDestructor) { + // Avoid virtual function calls from the destructor. + purgePending = true; + removedItems << item; + } else if (!item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { + bsp.removeItem(item, item->sceneBoundingRect()); + } + } else { + unindexedItems.removeOne(item); + } + invalidateSortCache(); // ### Only do this when removing from BSP? + + Q_ASSERT(item->d_ptr->index == -1); + Q_ASSERT(!indexedItems.contains(item)); + Q_ASSERT(!unindexedItems.contains(item)); + Q_ASSERT(!untransformableItems.contains(item)); + + if (moveToUnindexedItems) + addItem(item); + + if (recursive) { + for (int i = 0; i < item->d_ptr->children.size(); ++i) + removeItem(item->d_ptr->children.at(i), recursive, moveToUnindexedItems); + } +} + /*! Returns true if \a item1 is on top of \a item2. @@ -401,8 +478,16 @@ void QGraphicsSceneBspTreeIndex::clear() d->bsp.clear(); d->lastItemCount = 0; d->freeItemIndexes.clear(); + for (int i = 0; i < d->indexedItems.size(); ++i) { + // Ensure item bits are reset properly. + if (QGraphicsItem *item = d->indexedItems.at(i)) { + item->d_ptr->index = -1; + item->d_ptr->itemDiscovered = 0; + } + } d->indexedItems.clear(); d->unindexedItems.clear(); + d->untransformableItems.clear(); } /*! @@ -411,46 +496,7 @@ void QGraphicsSceneBspTreeIndex::clear() void QGraphicsSceneBspTreeIndex::addItem(QGraphicsItem *item) { Q_D(QGraphicsSceneBspTreeIndex); - // Prevent reusing a recently deleted pointer: purge all removed items - // from our lists. - d->purgeRemovedItems(); - - // Invalidate any sort caching; arrival of a new item means we need to - // resort. - // Update the scene's sort cache settings. - item->d_ptr->globalStackingOrder = -1; - d->invalidateSortCache(); - - // Indexing requires sceneBoundingRect(), but because \a item might - // not be completely constructed at this point, we need to store it in - // a temporary list and schedule an indexing for later. - item->d_ptr->index = -1; - if (item->d_ptr->itemIsUntransformable()) { - d->untransformableItems << item; - } else { - d->unindexedItems << item; - d->startIndexTimer(0); - } -} - -/*! - This really add the item in the BSP. - \internal -*/ -void QGraphicsSceneBspTreeIndexPrivate::addToBspTree(QGraphicsItem *item) -{ - if (item->d_ptr->itemIsUntransformable()) - return; - if (item->d_func()->index != -1) { - bsp.insertItem(item, item->sceneBoundingRect()); - foreach (QGraphicsItem *child, item->children()) - child->addToIndex(); - } else { - // The BSP tree is regenerated if the number of items grows to a - // certain threshold, or if the bounding rect of the graph doubles in - // size. - startIndexTimer(); - } + d->addItem(item); } /*! @@ -459,105 +505,28 @@ void QGraphicsSceneBspTreeIndexPrivate::addToBspTree(QGraphicsItem *item) void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item) { Q_D(QGraphicsSceneBspTreeIndex); - - // Note: This will access item's sceneBoundingRect(), which (as this is - // C++) is why we cannot call removeItem() from QGraphicsItem's - // destructor. - d->removeFromBspTree(item); - - // Invalidate any sort caching; arrival of a new item means we need to - // resort. - d->invalidateSortCache(); - - // Remove from our item lists. - int index = item->d_func()->index; - if (index != -1) { - d->freeItemIndexes << index; - d->indexedItems[index] = 0; - } else { - if (item->d_ptr->itemIsUntransformable()) - d->untransformableItems.removeOne(item); - else - d->unindexedItems.removeOne(item); - } + d->removeItem(item); } /*! \reimp - Delete the \a item from the BSP index (without accessing its boundingRect). -*/ -void QGraphicsSceneBspTreeIndex::deleteItem(QGraphicsItem *item) -{ - Q_D(QGraphicsSceneBspTreeIndex); - // Invalidate any sort caching; arrival of a new item means we need to - // resort. - d->invalidateSortCache(); - - int index = item->d_func()->index; - if (index != -1) { - // Important: The index is useless until purgeRemovedItems() is - // called. - d->indexedItems[index] = (QGraphicsItem *)0; - if (!d->purgePending) { - d->purgePending = true; - scene()->update(); - } - d->removedItems << item; - } else { - // Recently added items are purged immediately. unindexedItems() never - // contains stale items. - if (item->d_ptr->itemIsUntransformable()) - d->untransformableItems.removeOne(item); - else - d->unindexedItems.removeOne(item); - scene()->update(); - } -} - -/*! - Really remove the item from the BSP - \internal + Update the BSP when the \a item 's bounding rect has changed. */ -void QGraphicsSceneBspTreeIndexPrivate::removeFromBspTree(QGraphicsItem *item) +void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem *item) { - if (item->d_ptr->itemIsUntransformable()) + if (!item) return; - if (item->d_func()->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { - // ### remove from child index only if applicable - return; + if (item->d_ptr->index == -1 || item->d_ptr->itemIsUntransformable() + || item->d_func()->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { + return; // Item is not in BSP tree; nothing to do. } - if (item->d_func()->index != -1) { - bsp.removeItem(item, item->sceneBoundingRect()); - //prepareGeometryChange will call prepareBoundingRectChange - foreach (QGraphicsItem *child, item->children()) - child->prepareGeometryChange(); - } - startIndexTimer(); -} - -/*! - \reimp - Update the BSP when the \a item 's bounding rect has changed. -*/ -void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem *item) -{ Q_D(QGraphicsSceneBspTreeIndex); - if (!item->d_ptr->itemIsUntransformable()) { - // Note: This will access item's sceneBoundingRect(), which (as this is - // C++) is why we cannot call removeItem() from QGraphicsItem's - // destructor. - QGraphicsItem *thatItem = const_cast(item); - d->removeFromBspTree(thatItem); - int index = item->d_func()->index; - if (index != -1) { - d->freeItemIndexes << index; - d->indexedItems[index] = 0; - thatItem->d_func()->index = -1; - d->unindexedItems << thatItem; - } - } + QGraphicsItem *thatItem = const_cast(item); + d->removeItem(thatItem, /*recursive=*/false, /*moveToUnindexedItems=*/true); + for (int i = 0; i < item->d_ptr->children.size(); ++i) // ### Do we really need this? + prepareBoundingRectChange(item->d_ptr->children.at(i)); } /*! @@ -706,18 +675,17 @@ void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphics switch (change) { case QGraphicsItem::ItemFlagsChange: { // Handle ItemIgnoresTransformations - bool ignoredTransform = item->flags() & QGraphicsItem::ItemIgnoresTransformations; + bool ignoredTransform = item->d_ptr->flags & QGraphicsItem::ItemIgnoresTransformations; bool willIgnoreTransform = value.toUInt() & QGraphicsItem::ItemIgnoresTransformations; - if (ignoredTransform != willIgnoreTransform) { + bool clipsChildren = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape; + bool willClipChildren = value.toUInt() & QGraphicsItem::ItemClipsChildrenToShape; + if ((ignoredTransform != willIgnoreTransform) || (clipsChildren != willClipChildren)) { QGraphicsItem *thatItem = const_cast(item); - removeItem(thatItem); - thatItem->d_ptr->index = -1; - if (willIgnoreTransform) { - d->untransformableItems << thatItem; - } else { - d->unindexedItems << thatItem; - d->startIndexTimer(0); - } + // Remove item and its descendants from the index and append + // them to the list of unindexed items. Then, when the index + // is updated, they will be put into the bsp-tree or the list + // of untransformable items. + d->removeItem(thatItem, /*recursive=*/true, /*moveToUnidexedItems=*/true); } break; } @@ -729,17 +697,19 @@ void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphics // Handle ItemIgnoresTransformations QGraphicsItem *newParent = qVariantValue(value); bool ignoredTransform = item->d_ptr->itemIsUntransformable(); - bool willIgnoreTransform = (item->flags() & QGraphicsItem::ItemIgnoresTransformations) || (newParent && newParent->d_ptr->itemIsUntransformable()); - if (ignoredTransform != willIgnoreTransform) { + bool willIgnoreTransform = (item->d_ptr->flags & QGraphicsItem::ItemIgnoresTransformations) + || (newParent && newParent->d_ptr->itemIsUntransformable()); + bool ancestorClippedChildren = item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren; + bool ancestorWillClipChildren = newParent + && ((newParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) + || (newParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)); + if ((ignoredTransform != willIgnoreTransform) || (ancestorClippedChildren != ancestorWillClipChildren)) { QGraphicsItem *thatItem = const_cast(item); - removeItem(thatItem); - thatItem->d_ptr->index = -1; - if (willIgnoreTransform) { - d->untransformableItems << thatItem; - } else { - d->unindexedItems << thatItem; - d->startIndexTimer(0); - } + // Remove item and its descendants from the index and append + // them to the list of unindexed items. Then, when the index + // is updated, they will be put into the bsp-tree or the list + // of untransformable items. + d->removeItem(thatItem, /*recursive=*/true, /*moveToUnidexedItems=*/true); } break; } diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index 715b22f..f2f958f 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -96,7 +96,6 @@ protected: void addItem(QGraphicsItem *item); void removeItem(QGraphicsItem *item); - void deleteItem(QGraphicsItem *item); void prepareBoundingRectChange(const QGraphicsItem *item); void sceneRectChanged(); @@ -139,13 +138,12 @@ public: void startIndexTimer(int interval = QGRAPHICSSCENE_INDEXTIMER_TIMEOUT); void resetIndex(); - void addToBspTree(QGraphicsItem *item); - void removeFromBspTree(QGraphicsItem *item); - void _q_updateSortCache(); bool sortCacheEnabled; bool updatingSortCache; void invalidateSortCache(); + void addItem(QGraphicsItem *item, bool recursive = false); + void removeItem(QGraphicsItem *item, bool recursive = false, bool moveToUnindexedItems = false); static void climbTree(QGraphicsItem *item, int *stackingOrder); static bool closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2); -- cgit v0.12 From 7541247a025bf112716a752bc4d114303f2a77f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 26 Jun 2009 15:54:04 +0200 Subject: Proper handling of scene rect in QGraphicsScene(Index). Reviewed-by: Andreas --- src/gui/graphicsview/qgraphicsitem.cpp | 1 + src/gui/graphicsview/qgraphicsitem_p.h | 2 +- src/gui/graphicsview/qgraphicsscene.cpp | 65 +++++++++------------- src/gui/graphicsview/qgraphicsscene.h | 1 - src/gui/graphicsview/qgraphicsscene_p.h | 1 - .../graphicsview/qgraphicsscenebsptreeindex.cpp | 4 +- .../graphicsview/qgraphicsscenebsptreeindex_p.h | 4 +- src/gui/graphicsview/qgraphicssceneindex.cpp | 25 ++++++--- src/gui/graphicsview/qgraphicssceneindex_p.h | 4 +- src/gui/graphicsview/qgraphicsscenelinearindex.cpp | 6 -- 10 files changed, 52 insertions(+), 61 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 7393f00..e9d1076 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -6322,6 +6322,7 @@ void QGraphicsItem::removeFromIndex() void QGraphicsItem::prepareGeometryChange() { if (d_ptr->scene) { + d_ptr->scene->d_func()->dirtyGrowingItemsBoundingRect = true; d_ptr->geometryChanged = 1; d_ptr->paintedViewBoundingRectsNeedRepaint = 1; diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 1dfb140..243582a 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -148,7 +148,7 @@ public: dirtyChildrenBoundingRect(1), paintedViewBoundingRectsNeedRepaint(0), dirtySceneTransform(1), - geometryChanged(0), + geometryChanged(1), inDestructor(0), isObject(0), ignoreVisible(0), diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 6efede2..de6f5c4 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -326,6 +326,16 @@ void QGraphicsScenePrivate::_q_emitUpdated() Q_Q(QGraphicsScene); calledEmitUpdated = false; + if (dirtyGrowingItemsBoundingRect) { + if (!hasSceneRect) { + const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect; + growingItemsBoundingRect |= q->itemsBoundingRect(); + if (oldGrowingItemsBoundingRect != growingItemsBoundingRect) + emit q->sceneRectChanged(growingItemsBoundingRect); + } + dirtyGrowingItemsBoundingRect = false; + } + // Ensure all views are connected if anything is connected. This disables // the optimization that items send updates directly to the views, but it // needs to happen in order to keep compatibility with the behavior from @@ -373,20 +383,6 @@ void QGraphicsScenePrivate::unregisterTopLevelItem(QGraphicsItem *item) /*! \internal - - Updates all items in the pending update list. At this point, the list is - unlikely to contain partially constructed items. -*/ -void QGraphicsScenePrivate::_q_updateLater() -{ - QRectF null; - foreach (QGraphicsItem *item, pendingUpdateItems) - markDirty(item, null); - pendingUpdateItems.clear(); -} - -/*! - \internal */ void QGraphicsScenePrivate::_q_polishItems() { @@ -412,10 +408,8 @@ void QGraphicsScenePrivate::_q_processDirtyItems() const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect; processDirtyItemsRecursive(0); dirtyGrowingItemsBoundingRect = false; - if (oldGrowingItemsBoundingRect != growingItemsBoundingRect) { - index->sceneRectChanged(); + if (!hasSceneRect && oldGrowingItemsBoundingRect != growingItemsBoundingRect) emit q_func()->sceneRectChanged(growingItemsBoundingRect); - } if (wasPendingSceneUpdate) return; @@ -507,7 +501,6 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item) hoverItems.removeAll(item); cachedItemsUnderMouse.removeAll(item); unpolishedItems.removeAll(item); - pendingUpdateItems.removeAll(item); resetDirtyItem(item); //We remove all references of item from the sceneEventFilter arrays @@ -1303,18 +1296,19 @@ QGraphicsScene::~QGraphicsScene() QRectF QGraphicsScene::sceneRect() const { Q_D(const QGraphicsScene); - if (!d->hasSceneRect && d->dirtyGrowingItemsBoundingRect) { + if (d->hasSceneRect) + return d->sceneRect; + + if (d->dirtyGrowingItemsBoundingRect) { // Lazily update the growing items bounding rect QGraphicsScenePrivate *thatd = const_cast(d); QRectF oldGrowingBoundingRect = thatd->growingItemsBoundingRect; thatd->growingItemsBoundingRect |= itemsBoundingRect(); thatd->dirtyGrowingItemsBoundingRect = false; - if (oldGrowingBoundingRect != thatd->growingItemsBoundingRect) { - thatd->index->sceneRectChanged(); + if (oldGrowingBoundingRect != thatd->growingItemsBoundingRect) emit const_cast(this)->sceneRectChanged(thatd->growingItemsBoundingRect); - } } - return d->hasSceneRect ? d->sceneRect : d->growingItemsBoundingRect; + return d->growingItemsBoundingRect; } void QGraphicsScene::setSceneRect(const QRectF &rect) { @@ -1322,7 +1316,6 @@ void QGraphicsScene::setSceneRect(const QRectF &rect) if (rect != d->sceneRect) { d->hasSceneRect = !rect.isNull(); d->sceneRect = rect; - d->index->sceneRectChanged(); emit sceneRectChanged(d->hasSceneRect ? rect : d->growingItemsBoundingRect); } } @@ -2101,13 +2094,8 @@ void QGraphicsScene::addItem(QGraphicsItem *item) // Add to list of items that require an update. We cannot assume that the // item is fully constructed, so calling item->update() can lead to a pure // virtual function call to boundingRect(). - if (!d->updateAll) { - if (d->pendingUpdateItems.isEmpty()) - QMetaObject::invokeMethod(this, "_q_updateLater", Qt::QueuedConnection); - d->pendingUpdateItems << item; - } else { - d->dirtyGrowingItemsBoundingRect = true; - } + d->markDirty(item); + d->dirtyGrowingItemsBoundingRect = true; // Disable selectionChanged() for individual items ++d->selectionChanging; @@ -4245,7 +4233,6 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b bool removingItemFromScene) { Q_ASSERT(item); - dirtyGrowingItemsBoundingRect = true; if (updateAll) return; @@ -4351,6 +4338,13 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool item->d_ptr->dirty = 0; item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0; } + + if (item->d_ptr->geometryChanged) { + // Update growingItemsBoundingRect. + if (!hasSceneRect && !itemIsHidden) + growingItemsBoundingRect |= item->d_ptr->sceneTransform.mapRect(item->boundingRect()); + item->d_ptr->geometryChanged = 0; + } } // Process item. @@ -4359,13 +4353,6 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool const bool untransformableItem = item->d_ptr->itemIsUntransformable(); const QRectF itemBoundingRect = adjustedItemBoundingRect(item); - if (item->d_ptr->geometryChanged) { - // Update growingItemsBoundingRect. - if (!hasSceneRect) - growingItemsBoundingRect |= item->d_ptr->sceneTransform.mapRect(itemBoundingRect); - item->d_ptr->geometryChanged = 0; - } - if (useCompatUpdate && !untransformableItem && qFuzzyIsNull(item->boundingRegionGranularity())) { // This block of code is kept for compatibility. Since 4.5, by default // QGraphicsView does not connect the signal and we use the below diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h index 421adbd..560671a 100644 --- a/src/gui/graphicsview/qgraphicsscene.h +++ b/src/gui/graphicsview/qgraphicsscene.h @@ -291,7 +291,6 @@ private: Q_DECLARE_PRIVATE(QGraphicsScene) Q_DISABLE_COPY(QGraphicsScene) Q_PRIVATE_SLOT(d_func(), void _q_emitUpdated()) - Q_PRIVATE_SLOT(d_func(), void _q_updateLater()) Q_PRIVATE_SLOT(d_func(), void _q_polishItems()) Q_PRIVATE_SLOT(d_func(), void _q_processDirtyItems()) friend class QGraphicsItem; diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 36a7e63..f286a8d 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -107,7 +107,6 @@ public: QPainterPath selectionArea; int selectionChanging; QSet selectedItems; - QList pendingUpdateItems; QList unpolishedItems; QList topLevelItems; bool needSortTopLevelItems; diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index f6994f9..3efc742 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -655,10 +655,10 @@ void QGraphicsSceneBspTreeIndex::setBspTreeDepth(int depth) This method react to the \a rect change of the scene and reset the BSP tree index. */ -void QGraphicsSceneBspTreeIndex::sceneRectChanged() +void QGraphicsSceneBspTreeIndex::updateSceneRect(const QRectF &rect) { Q_D(QGraphicsSceneBspTreeIndex); - d->sceneRect = d->scene->sceneRect(); + d->sceneRect = rect; d->resetIndex(); } diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index f2f958f..850cc3f 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -90,6 +90,9 @@ public: int bspTreeDepth(); void setBspTreeDepth(int depth); +protected Q_SLOTS: + void updateSceneRect(const QRectF &rect); + protected: bool event(QEvent *event); void clear(); @@ -98,7 +101,6 @@ protected: void removeItem(QGraphicsItem *item); void prepareBoundingRectChange(const QGraphicsItem *item); - void sceneRectChanged(); void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value); private : diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 4eaed2b..88fb6b0 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -335,6 +335,10 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe QGraphicsSceneIndex::QGraphicsSceneIndex(QGraphicsScene *scene) : QObject(*new QGraphicsSceneIndexPrivate(scene), scene) { + if (scene) { + connect(scene, SIGNAL(sceneRectChanged(const QRectF&)), + this, SLOT(updateSceneRect(const QRectF&))); + } } /*! @@ -527,6 +531,18 @@ QList QGraphicsSceneIndex::estimateItems(const QPointF &point, \a order. */ + +/*! + Notifies the index that the scene's scene rect has changed. \a rect + is thew new scene rect. + + \sa QGraphicsScene::sceneRect() +*/ +void QGraphicsSceneIndex::updateSceneRect(const QRectF &rect) +{ + Q_UNUSED(rect); +} + /*! This virtual function removes all items in the scene index. */ @@ -596,15 +612,6 @@ void QGraphicsSceneIndex::prepareBoundingRectChange(const QGraphicsItem *item) Q_UNUSED(item); } -/*! - This virtual function is called when the scene changes its bounding - rectangle. \a rect is the new value of the scene rectangle. - \sa QGraphicsScene::sceneRect() -*/ -void QGraphicsSceneIndex::sceneRectChanged() -{ -} - QT_END_NAMESPACE #include "moc_qgraphicssceneindex_p.cpp" diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h index 60e9032..dc6a740 100644 --- a/src/gui/graphicsview/qgraphicssceneindex_p.h +++ b/src/gui/graphicsview/qgraphicssceneindex_p.h @@ -101,6 +101,9 @@ public: virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const = 0; +protected Q_SLOTS: + virtual void updateSceneRect(const QRectF &rect); + protected: virtual void clear(); virtual void addItem(QGraphicsItem *item) = 0; @@ -109,7 +112,6 @@ protected: virtual void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const QVariant &value); virtual void prepareBoundingRectChange(const QGraphicsItem *item); - virtual void sceneRectChanged(); QGraphicsSceneIndex(QObjectPrivate &dd, QGraphicsScene *scene); diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex.cpp b/src/gui/graphicsview/qgraphicsscenelinearindex.cpp index 694062b..bc401f2 100644 --- a/src/gui/graphicsview/qgraphicsscenelinearindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenelinearindex.cpp @@ -46,12 +46,6 @@ */ /*! - \fn void QGraphicsSceneLinearIndex::sceneRectChanged(const QRectF &rect); - \reimp - This method react to the \a rect change of the scene. -*/ - -/*! \fn void QGraphicsSceneLinearIndex::clear(); \reimp Clear the all the BSP index. -- cgit v0.12 From eff4c4b4172d1a95b1b5806622b4e7fe43c2b006 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 26 Jun 2009 16:32:27 +0200 Subject: Fix broken point item lookup in Graphics View. Done with Andreas. --- src/gui/graphicsview/qgraphicsscene.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index de6f5c4..7c46598 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -770,11 +770,22 @@ QList QGraphicsScenePrivate::itemsAtPosition(const QPoint &scre const QPointF &scenePos, QWidget *widget) const { - Q_UNUSED(screenPos); Q_Q(const QGraphicsScene); QGraphicsView *view = widget ? qobject_cast(widget->parentWidget()) : 0; - return q->items(scenePos, Qt::IntersectsItemShape, Qt::AscendingOrder, - view ? view->viewportTransform() : QTransform()); + if (!view) + return q->items(scenePos, Qt::IntersectsItemShape, Qt::AscendingOrder, QTransform()); + + const QRectF pointRect(QPointF(widget->mapFromGlobal(screenPos)), QSizeF(1, 1)); + if (!view->isTransformed()) + return q->items(pointRect, Qt::IntersectsItemShape, Qt::AscendingOrder); + + const QTransform viewTransform = view->viewportTransform(); + if (viewTransform.type() <= QTransform::TxScale) { + return q->items(viewTransform.inverted().mapRect(pointRect), Qt::IntersectsItemShape, + Qt::AscendingOrder, viewTransform); + } + return q->items(viewTransform.inverted().map(pointRect), Qt::IntersectsItemShape, + Qt::AscendingOrder, viewTransform); } /*! -- cgit v0.12 From 7fe4f8ff71cf09bbabbd3438ef637fe408a11c33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Mon, 29 Jun 2009 15:33:30 +0200 Subject: Graphics View: BSP tree cleanup. Ensure the BSP resets the QGraphicsItemPrivate::itemDiscovered bit before returning the list of discovered items. --- src/gui/graphicsview/qgraphicsitem.h | 1 + src/gui/graphicsview/qgraphicsscene.cpp | 7 +++++-- src/gui/graphicsview/qgraphicsscene_bsp.cpp | 11 ++++++++--- src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp | 21 ++++++++------------- 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index 12dcad2..48fb5c3 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -434,6 +434,7 @@ private: friend class QGraphicsScene; friend class QGraphicsScenePrivate; friend class QGraphicsSceneFindItemBspTreeVisitor; + friend class QGraphicsSceneBspTree; friend class QGraphicsView; friend class QGraphicsViewPrivate; friend class QGraphicsWidget; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 7c46598..f1e56c1 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1097,8 +1097,11 @@ QList QGraphicsScenePrivate::topLevelItemsInStackingOrder(const QList tmp = index->estimateItems(sceneRect, Qt::SortOrder(-1), viewTransform ? *viewTransform : QTransform()); - for (int i = 0; i < tmp.size(); ++i) - tmp.at(i)->topLevelItem()->d_ptr->itemDiscovered = 1; + for (int i = 0; i < tmp.size(); ++i) { + QGraphicsItem *item = tmp.at(i); + if (!item->d_ptr->parent) + item->d_ptr->itemDiscovered = 1; + } // Sort if the toplevel list is unsorted. if (needSortTopLevelItems) { diff --git a/src/gui/graphicsview/qgraphicsscene_bsp.cpp b/src/gui/graphicsview/qgraphicsscene_bsp.cpp index eaeec54..5858eab 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp.cpp +++ b/src/gui/graphicsview/qgraphicsscene_bsp.cpp @@ -148,6 +148,9 @@ QList QGraphicsSceneBspTree::items(const QRectF &rect) const QList tmp; findVisitor->foundItems = &tmp; climbTree(findVisitor, rect); + // Reset discovery bits. + for (int i = 0; i < tmp.size(); ++i) + tmp.at(i)->d_ptr->itemDiscovered = 0; return tmp; } @@ -156,6 +159,9 @@ QList QGraphicsSceneBspTree::items(const QPointF &pos) const QList tmp; findVisitor->foundItems = &tmp; climbTree(findVisitor, pos); + // Reset discovery bits. + for (int i = 0; i < tmp.size(); ++i) + tmp.at(i)->d_ptr->itemDiscovered = 0; return tmp; } @@ -241,7 +247,7 @@ void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, con return; const Node &node = nodes.at(index); - int childIndex = firstChildIndex(index); + const int childIndex = firstChildIndex(index); switch (node.type) { case Node::Leaf: { @@ -271,7 +277,7 @@ void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, con return; const Node &node = nodes.at(index); - int childIndex = firstChildIndex(index); + const int childIndex = firstChildIndex(index); switch (node.type) { case Node::Leaf: { @@ -288,7 +294,6 @@ void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, con } break; case Node::Horizontal: - int childIndex = firstChildIndex(index); if (rect.top() < node.offset) { climbTree(visitor, rect, childIndex); if (rect.bottom() >= node.offset) diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 3efc742..44a0082 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -130,7 +130,7 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() // Add unindexedItems to indexedItems for (int i = 0; i < unindexedItems.size(); ++i) { if (QGraphicsItem *item = unindexedItems.at(i)) { - item->d_ptr->itemDiscovered = 0; + Q_ASSERT(!item->d_ptr->itemDiscovered); if (!freeItemIndexes.isEmpty()) { int freeIndex = freeItemIndexes.takeFirst(); item->d_func()->index = freeIndex; @@ -224,7 +224,7 @@ void QGraphicsSceneBspTreeIndexPrivate::resetIndex() for (int i = 0; i < indexedItems.size(); ++i) { if (QGraphicsItem *item = indexedItems.at(i)) { item->d_ptr->index = -1; - item->d_ptr->itemDiscovered = 0; + Q_ASSERT(!item->d_ptr->itemDiscovered); unindexedItems << item; } } @@ -339,10 +339,10 @@ void QGraphicsSceneBspTreeIndexPrivate::removeItem(QGraphicsItem *item, bool rec if (item->d_ptr->index != -1) { Q_ASSERT(item->d_ptr->index < indexedItems.size()); Q_ASSERT(indexedItems.at(item->d_ptr->index) == item); + Q_ASSERT(!item->d_ptr->itemDiscovered); freeItemIndexes << item->d_ptr->index; indexedItems[item->d_ptr->index] = 0; item->d_ptr->index = -1; - item->d_ptr->itemDiscovered = 0; if (item->d_ptr->itemIsUntransformable()) { untransformableItems.removeOne(item); @@ -481,8 +481,8 @@ void QGraphicsSceneBspTreeIndex::clear() for (int i = 0; i < d->indexedItems.size(); ++i) { // Ensure item bits are reset properly. if (QGraphicsItem *item = d->indexedItems.at(i)) { + Q_ASSERT(!item->d_ptr->itemDiscovered); item->d_ptr->index = -1; - item->d_ptr->itemDiscovered = 0; } } d->indexedItems.clear(); @@ -547,25 +547,20 @@ QList QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &r Q_UNUSED(deviceTransform); QList rectItems = d->bsp.items(rect); + // Fill in with any unindexed items for (int i = 0; i < d->unindexedItems.size(); ++i) { if (QGraphicsItem *item = d->unindexedItems.at(i)) { - if (!item->d_ptr->itemDiscovered && item->d_ptr->visible && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { + if (item->d_ptr->visible + && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { QRectF boundingRect = item->sceneBoundingRect(); - if (QRectF_intersects(boundingRect, rect)) { - item->d_ptr->itemDiscovered = 1; + if (QRectF_intersects(boundingRect, rect)) rectItems << item; - } } } } - // Reset the discovered state of all discovered items - for (int i = 0; i < rectItems.size(); ++i) - rectItems.at(i)->d_func()->itemDiscovered = 0; - rectItems += d->untransformableItems; - d->sortItems(&rectItems, order, d->sortCacheEnabled); return rectItems; -- cgit v0.12 From 4dcb46a3796fbd9baf1ba6dcddcc9944e69e3153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Mon, 29 Jun 2009 15:44:11 +0200 Subject: Add lacking parenthesis around bitwise AND operator. This caused a crash in the diagramscene example because "!bits & something" does not have the same meaning as "!(bits & something)", hence item was never removed from the BSP resulting in a stale item pointer. --- src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 44a0082..413c8de 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -350,7 +350,7 @@ void QGraphicsSceneBspTreeIndexPrivate::removeItem(QGraphicsItem *item, bool rec // Avoid virtual function calls from the destructor. purgePending = true; removedItems << item; - } else if (!item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { + } else if (!(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { bsp.removeItem(item, item->sceneBoundingRect()); } } else { @@ -518,7 +518,7 @@ void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem * return; if (item->d_ptr->index == -1 || item->d_ptr->itemIsUntransformable() - || item->d_func()->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { + || (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { return; // Item is not in BSP tree; nothing to do. } -- cgit v0.12 From 6ee3fb750377eeedf161d96fef02c5fa336810e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 30 Jun 2009 13:00:32 +0200 Subject: More re-factoring of QGraphicsSceneIndex. Mostly re-factoring of QGraphicsSceneIndexPrivate::recursive_items_helper so it can re-use code from the scene (topLevelItemsInStackingOrder). That also means we'll use the bsp tree in case of NoIndex instead of always looping through the top-levels. This function is now almost identical to QGraphicsScenePrivate::drawSubtreeRecursive, so it might be worth looking into how we can abstract it even more and have one common recursive function. --- src/gui/graphicsview/qgraphicsscene.cpp | 20 +--- src/gui/graphicsview/qgraphicsscene_p.h | 11 +- .../graphicsview/qgraphicsscenebsptreeindex_p.h | 12 +-- src/gui/graphicsview/qgraphicssceneindex.cpp | 115 ++++++++------------- src/gui/graphicsview/qgraphicssceneindex_p.h | 34 ++++-- 5 files changed, 89 insertions(+), 103 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index f1e56c1..faacf4d 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -217,8 +217,9 @@ #include "qgraphicsview_p.h" #include "qgraphicswidget.h" #include "qgraphicswidget_p.h" -#include -#include +#include "qgraphicssceneindex_p.h" +#include "qgraphicsscenebsptreeindex_p.h" +#include "qgraphicsscenelinearindex_p.h" #include #include @@ -243,7 +244,6 @@ #include #include #include -#include #include #ifdef Q_WS_X11 #include @@ -1075,9 +1075,9 @@ QGraphicsWidget *QGraphicsScenePrivate::windowForItem(const QGraphicsItem *item) } QList QGraphicsScenePrivate::topLevelItemsInStackingOrder(const QTransform *const viewTransform, - QRegion *exposedRegion) + const QRectF &sceneRect) { - if (indexMethod == QGraphicsScene::NoIndex || !exposedRegion) { + if (indexMethod == QGraphicsScene::NoIndex || sceneRect.isNull()) { if (needSortTopLevelItems) { needSortTopLevelItems = false; qStableSort(topLevelItems.begin(), topLevelItems.end(), qt_notclosestLeaf); @@ -1085,16 +1085,6 @@ QList QGraphicsScenePrivate::topLevelItemsInStackingOrder(const return topLevelItems; } - const QRectF exposedRect = exposedRegion->boundingRect().adjusted(-1, -1, 1, 1); - QRectF sceneRect; - QTransform invertedViewTransform(Qt::Uninitialized); - if (!viewTransform) { - sceneRect = exposedRect; - } else { - invertedViewTransform = viewTransform->inverted(); - sceneRect = invertedViewTransform.mapRect(exposedRect); - } - QList tmp = index->estimateItems(sceneRect, Qt::SortOrder(-1), viewTransform ? *viewTransform : QTransform()); for (int i = 0; i < tmp.size(); ++i) { diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index f286a8d..b3d7535 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -57,7 +57,6 @@ #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW -#include "qgraphicsscenebsptreeindex_p.h" #include "qgraphicsview.h" #include "qgraphicsitem_p.h" @@ -187,7 +186,7 @@ public: QGraphicsWidget *windowForItem(const QGraphicsItem *item) const; bool sortCacheEnabled; // for compatibility - QList topLevelItemsInStackingOrder(const QTransform *const, QRegion *); + QList topLevelItemsInStackingOrder(const QTransform *const, const QRectF&); void drawItemHelper(QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget, @@ -196,7 +195,13 @@ public: inline void drawItems(QPainter *painter, const QTransform *const viewTransform, QRegion *exposedRegion, QWidget *widget) { - const QList tli = topLevelItemsInStackingOrder(viewTransform, exposedRegion); + QRectF exposedSceneRect; + if (exposedRegion && indexMethod != QGraphicsScene::NoIndex) { + exposedSceneRect = exposedRegion->boundingRect().adjusted(-1, -1, 1, 1); + if (viewTransform) + exposedSceneRect = viewTransform->inverted().mapRect(exposedSceneRect); + } + const QList tli = topLevelItemsInStackingOrder(viewTransform, exposedSceneRect); for (int i = 0; i < tli.size(); ++i) drawSubtreeRecursive(tli.at(i), painter, viewTransform, exposedRegion, widget); return; diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index 850cc3f..90cc8c3 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -39,8 +39,6 @@ ** ****************************************************************************/ -#include - // // W A R N I N G // ------------- @@ -63,13 +61,13 @@ QT_MODULE(Gui) #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW +#include "qgraphicssceneindex_p.h" +#include "qgraphicsitem_p.h" +#include "qgraphicsscene_bsp_p.h" + +#include #include #include -#include -#include -#include -#include -#include static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 88fb6b0..a42dc54 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -61,7 +61,8 @@ #include "qgraphicsitem_p.h" #include "qgraphicsscene_p.h" #include "qgraphicswidget.h" -#include +#include "qgraphicssceneindex_p.h" +#include "qgraphicsscenebsptreeindex_p.h" #ifndef QT_NO_GRAPHICSVIEW @@ -240,91 +241,64 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe Qt::ItemSelectionMode mode, Qt::SortOrder order, qreal parentOpacity) const { - // Calculate opacity. - qreal opacity; - if (item) { - if (!item->d_ptr->visible) - return; + Q_ASSERT(item); + if (!item->d_ptr->visible) + return; - QGraphicsItem *p = item->d_ptr->parent; - bool itemIgnoresParentOpacity = item->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity; - bool parentDoesntPropagateOpacity = (p && (p->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)); - if (!itemIgnoresParentOpacity && !parentDoesntPropagateOpacity) { - opacity = parentOpacity * item->opacity(); - } else { - opacity = item->d_ptr->opacity; - } - if (opacity == 0.0 && !(item->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) - return; - } else { - opacity = parentOpacity; - } + const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity); + const bool itemIsFullyTransparent = (opacity < 0.0001); + const bool itemHasChildren = !item->d_ptr->children.isEmpty(); + if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) + return; // Calculate the full transform for this item. - QTransform transform = parentTransform; - bool keep = false; - if (item) { - item->d_ptr->combineTransformFromParent(&transform, &viewTransform); - - // ### This does not take the clip into account. - QRectF brect = item->boundingRect(); - _q_adjustRect(&brect); - - //We fill the intersector with needed informations - keep = intersector->intersect(item, exposeRect, mode, transform, viewTransform); - } - - bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)); - bool dontProcessItem = !item || !keep; - bool dontProcessChildren = item && dontProcessItem && childClip; + QTransform transform(parentTransform); + item->d_ptr->combineTransformFromParent(&transform, &viewTransform); + + const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape); + bool processItem = !itemIsFullyTransparent; + if (processItem) { + processItem = intersector->intersect(item, exposeRect, mode, transform, viewTransform); + if (!processItem && (!itemHasChildren || itemClipsChildrenToShape)) + return; + } // else we know for sure this item has children we must process. - // Find and sort children. - QList &children = item ? item->d_ptr->children : const_cast(scene->d_func())->topLevelItems; - if (!dontProcessChildren) { - if (item && item->d_ptr->needSortChildren) { + int i = 0; + if (itemHasChildren) { + // Sort children. + if (item->d_ptr->needSortChildren) { item->d_ptr->needSortChildren = 0; - qStableSort(children.begin(), children.end(), qt_notclosestLeaf); - } else if (!item && scene->d_func()->needSortTopLevelItems) { - const_cast(scene->d_func())->needSortTopLevelItems = false; - qStableSort(children.begin(), children.end(), qt_notclosestLeaf); + qStableSort(item->d_ptr->children.begin(), item->d_ptr->children.end(), qt_notclosestLeaf); } - } - - childClip &= !dontProcessChildren & !children.isEmpty(); - // Clip. - if (childClip) - exposeRect &= transform.map(item->shape()).controlPointRect(); + // Clip to shape. + if (itemClipsChildrenToShape) + exposeRect &= transform.map(item->shape()).controlPointRect(); - // Process children behind - int i = 0; - if (!dontProcessChildren) { - for (i = 0; i < children.size(); ++i) { - QGraphicsItem *child = children.at(i); + // Process children behind + for (i = 0; i < item->d_ptr->children.size(); ++i) { + QGraphicsItem *child = item->d_ptr->children.at(i); if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent)) break; + if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)) + continue; recursive_items_helper(child, exposeRect, intersector, items, transform, viewTransform, mode, order, opacity); } } // Process item - if (!dontProcessItem) + if (processItem) items->append(item); // Process children in front - if (!dontProcessChildren) { - for (; i < children.size(); ++i) - recursive_items_helper(children.at(i), exposeRect, intersector, items, transform, viewTransform, + if (itemHasChildren) { + for (; i < item->d_ptr->children.size(); ++i) { + QGraphicsItem *child = item->d_ptr->children.at(i); + if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)) + continue; + recursive_items_helper(child, exposeRect, intersector, items, transform, viewTransform, mode, order, opacity); - } - - if (!item && order == Qt::AscendingOrder) { - int n = items->size(); - for (int i = 0; i < n / 2; ++i) { - QGraphicsItem *tmp = (*items)[n - i - 1]; - (*items)[n - i - 1] = (*items)[i]; - (*items)[i] = tmp; } } } @@ -393,8 +367,7 @@ QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSe Q_D(const QGraphicsSceneIndex); QList itemList; d->pointIntersector->scenePoint = pos; - d->recursive_items_helper(0, QRectF(pos, QSizeF(1, 1)), d->pointIntersector, &itemList, - QTransform(), deviceTransform, mode, order); + d->items_helper(QRectF(pos, QSizeF(1, 1)), d->pointIntersector, &itemList, deviceTransform, mode, order); return itemList; } @@ -428,7 +401,7 @@ QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSe _q_adjustRect(&exposeRect); QList itemList; d->rectIntersector->sceneRect = rect; - d->recursive_items_helper(0, exposeRect, d->rectIntersector, &itemList, QTransform(), deviceTransform, mode, order); + d->items_helper(exposeRect, d->rectIntersector, &itemList, deviceTransform, mode, order); return itemList; } @@ -464,7 +437,7 @@ QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt:: QPainterPath path; path.addPolygon(polygon); d->pathIntersector->scenePath = path; - d->recursive_items_helper(0, exposeRect, d->pathIntersector, &itemList, QTransform(), deviceTransform, mode, order); + d->items_helper(exposeRect, d->pathIntersector, &itemList, deviceTransform, mode, order); return itemList; } @@ -498,7 +471,7 @@ QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt:: QRectF exposeRect = path.controlPointRect(); _q_adjustRect(&exposeRect); d->pathIntersector->scenePath = path; - d->recursive_items_helper(0, exposeRect, d->pathIntersector, &itemList, QTransform(), deviceTransform, mode, order); + d->items_helper(exposeRect, d->pathIntersector, &itemList, deviceTransform, mode, order); return itemList; } diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h index dc6a740..122d7ae 100644 --- a/src/gui/graphicsview/qgraphicssceneindex_p.h +++ b/src/gui/graphicsview/qgraphicssceneindex_p.h @@ -53,11 +53,13 @@ // We mean it. // +#include "qgraphicsscene_p.h" +#include "qgraphicsscene.h" +#include + #include #include #include -#include -#include QT_BEGIN_HEADER @@ -67,7 +69,6 @@ QT_MODULE(Gui) #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW -class QGraphicsScene; class QGraphicsSceneIndexIntersector; class QGraphicsSceneIndexPointIntersector; class QGraphicsSceneIndexRectIntersector; @@ -138,12 +139,31 @@ public: QGraphicsSceneIndexIntersector *intersector, QList *items, const QTransform &parentTransform, const QTransform &viewTransform, Qt::ItemSelectionMode mode, Qt::SortOrder order, qreal parentOpacity = 1.0) const; - QGraphicsScene *scene; - QGraphicsSceneIndexPointIntersector *pointIntersector; - QGraphicsSceneIndexRectIntersector *rectIntersector; - QGraphicsSceneIndexPathIntersector *pathIntersector; + inline void items_helper(const QRectF &rect, QGraphicsSceneIndexIntersector *intersector, + QList *items, const QTransform &viewTransform, + Qt::ItemSelectionMode mode, Qt::SortOrder order) const; + + QGraphicsScene *scene; + QGraphicsSceneIndexPointIntersector *pointIntersector; + QGraphicsSceneIndexRectIntersector *rectIntersector; + QGraphicsSceneIndexPathIntersector *pathIntersector; }; +inline void QGraphicsSceneIndexPrivate::items_helper(const QRectF &rect, QGraphicsSceneIndexIntersector *intersector, + QList *items, const QTransform &viewTransform, + Qt::ItemSelectionMode mode, Qt::SortOrder order) const +{ + const QList tli = scene->d_func()->topLevelItemsInStackingOrder(&viewTransform, rect); + const QTransform identity; + for (int i = 0; i < tli.size(); ++i) + recursive_items_helper(tli.at(i), rect, intersector, items, identity, viewTransform, mode, order); + if (order == Qt::AscendingOrder) { + const int n = items->size(); + for (int i = 0; i < n / 2; ++i) + items->swap(i, n - i - 1); + } +} + class QGraphicsSceneIndexIntersector { public: -- cgit v0.12 From 99bea47fd9b868fb22f175943c11ecb05b51f07c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 30 Jun 2009 15:54:19 +0200 Subject: Fix broken tst_QGraphicsView::embeddedViews. This test has been broken after 32f32ee3e752a6cc03505ddaa48d2849eaedc2a6, but the test continued to pass because another bug, which is fixed by 6ee3fb750377eeedf161d96fef02c5fa336810e9. The transform should be exactly the same in both cases. --- tests/auto/qgraphicsview/tst_qgraphicsview.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp index 65e066f..6db8f27 100644 --- a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp @@ -2989,14 +2989,7 @@ void tst_QGraphicsView::embeddedViews() v2->QWidget::render(&actual); QTransform b = item->transform; -#ifdef Q_WS_MAC - // We don't use shared painter on the Mac, so the - // transform should be exactly the same. QVERIFY(a == b); -#else - QVERIFY(a != b); -#endif - delete v1; } -- cgit v0.12 From 3a00930fe167e6db5588d9e93d429486f9591bd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 30 Jun 2009 16:15:28 +0200 Subject: More BSP tree index cleanup. Ensure the index of indexed items are reset to -1. Makes tst_QGraphicsScene::itemIndexMethod happy. (this test passed before we actually started using the BSP from the items() functions, see 6ee3fb750377eeedf161d96fef02c5fa336810e9) --- src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp | 12 ++++++++++++ src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h | 1 + 2 files changed, 13 insertions(+) diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 413c8de..ff9a3da 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -468,6 +468,18 @@ QGraphicsSceneBspTreeIndex::QGraphicsSceneBspTreeIndex(QGraphicsScene *scene) } +QGraphicsSceneBspTreeIndex::~QGraphicsSceneBspTreeIndex() +{ + Q_D(QGraphicsSceneBspTreeIndex); + for (int i = 0; i < d->indexedItems.size(); ++i) { + // Ensure item bits are reset properly. + if (QGraphicsItem *item = d->indexedItems.at(i)) { + Q_ASSERT(!item->d_ptr->itemDiscovered); + item->d_ptr->index = -1; + } + } +} + /*! \reimp Clear the all the BSP index. diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index 90cc8c3..7b431e6 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -80,6 +80,7 @@ class Q_AUTOTEST_EXPORT QGraphicsSceneBspTreeIndex : public QGraphicsSceneIndex Q_PROPERTY(int bspTreeDepth READ bspTreeDepth WRITE setBspTreeDepth) public: QGraphicsSceneBspTreeIndex(QGraphicsScene *scene = 0); + ~QGraphicsSceneBspTreeIndex(); QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const; -- cgit v0.12 From 53ef0b0f8b1227cff6ce4c9e2a91a6fbc7e7ee3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 30 Jun 2009 16:19:25 +0200 Subject: Make QGraphicsSceneIndex::clear() less nasty. --- src/gui/graphicsview/qgraphicssceneindex.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index a42dc54..2f2f05e 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -521,8 +521,9 @@ void QGraphicsSceneIndex::updateSceneRect(const QRectF &rect) */ void QGraphicsSceneIndex::clear() { - for (int i = 0 ; i < items().size(); ++i) - removeItem(items().at(i)); + const QList allItems = items(); + for (int i = 0 ; i < allItems.size(); ++i) + removeItem(allItems.at(i)); } /*! -- cgit v0.12 From a1d5b33bd33ecf1d809346a39d2386cafaf50cef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 30 Jun 2009 18:41:18 +0200 Subject: Partially revert 7fe4f8ff71cf09bbabbd3438ef637fe408a11c33 We have to ensure that the item's top-level is marked as discovered. This broke the dragandroprobot example after we started using the BSP from QGraphicsSceneIndex::items()* (see 6ee3fb750377eeedf161d96fef02c5fa336810e9) --- src/gui/graphicsview/qgraphicsscene.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index faacf4d..ed1d2f3 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1087,11 +1087,8 @@ QList QGraphicsScenePrivate::topLevelItemsInStackingOrder(const QList tmp = index->estimateItems(sceneRect, Qt::SortOrder(-1), viewTransform ? *viewTransform : QTransform()); - for (int i = 0; i < tmp.size(); ++i) { - QGraphicsItem *item = tmp.at(i); - if (!item->d_ptr->parent) - item->d_ptr->itemDiscovered = 1; - } + for (int i = 0; i < tmp.size(); ++i) + tmp.at(i)->topLevelItem()->d_ptr->itemDiscovered = 1; // Sort if the toplevel list is unsorted. if (needSortTopLevelItems) { -- cgit v0.12 From 145e17f6cc405dd935451f0151b1a8a451c78f71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 1 Jul 2009 14:01:54 +0200 Subject: Compiler warning. --- src/gui/graphicsview/qgraphicsscene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 9de6598..8fdf651 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -297,8 +297,8 @@ QGraphicsScenePrivate::QGraphicsScenePrivate() allItemsIgnoreHoverEvents(true), allItemsUseDefaultCursor(true), painterStateProtection(true), - style(0), sortCacheEnabled(false), + style(0), allItemsIgnoreTouchEvents(true) { } -- cgit v0.12 From f4a95e6d6e4c046ac4857cbd54f9488d3b67ce5a Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Wed, 1 Jul 2009 17:09:17 +0200 Subject: Fix a regression with extended style option items. We basically passed an unitialized transform to construct the styleoptions for items that use the useExtendedStyleOption flag. We had an auto-test to cover that but for some reason view.show() was removed by me so the auto-test did nothing. oops. Reviewed-by:bnilsen --- src/gui/graphicsview/qgraphicsscene.cpp | 8 ++++---- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 8fdf651..8a032f4 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4312,7 +4312,8 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (drawItem) { Q_ASSERT(!itemIsFullyTransparent); Q_ASSERT(itemHasContents); - item->d_ptr->initStyleOption(&styleOptionTmp, transform, exposedRegion + ENSURE_TRANSFORM_PTR + item->d_ptr->initStyleOption(&styleOptionTmp, *transformPtr, exposedRegion ? *exposedRegion : QRegion(), exposedRegion == 0); const bool itemClipsToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsToShape; @@ -4320,10 +4321,9 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (savePainter) painter->save(); - if (!itemHasChildren || !itemClipsChildrenToShape) { - ENSURE_TRANSFORM_PTR + if (!itemHasChildren || !itemClipsChildrenToShape) painter->setWorldTransform(*transformPtr); - } + if (itemClipsToShape) painter->setClipPath(item->shape(), Qt::IntersectClip); painter->setOpacity(opacity); diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 7552f18..3f7a50b 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -6837,9 +6837,11 @@ public: //Doesn't use the extended style option so the exposed rect is the boundingRect if (!(flags() & QGraphicsItem::ItemUsesExtendedStyleOption)) { QCOMPARE(option->exposedRect, boundingRect()); + QCOMPARE(option->matrix, QMatrix()); } else { QVERIFY(option->exposedRect != QRect()); QVERIFY(option->exposedRect != boundingRect()); + QCOMPARE(option->matrix, sceneTransform().toAffine()); } } QGraphicsRectItem::paint(painter, option, widget); @@ -6861,6 +6863,8 @@ void tst_QGraphicsItem::itemUsesExtendedStyleOption() scene.addItem(rect); rect->setPos(200, 200); QGraphicsView view(&scene); + rect->startTrack = false; + view.show(); QTest::qWait(500); rect->startTrack = true; rect->update(10, 10, 10, 10); -- cgit v0.12 From 2b9294a2b47c4a193ef83be60a07a3e61b8531b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 1 Jul 2009 17:30:46 +0200 Subject: Fixes broken BSP lookup in QGraphicsSceneBspTreeIndex. The chip demo was unbelievable slow, so I investigated and found out the bsp always returned almost all items in the tree (40 000 in this particular case). It did so because the tree was initialized with an empty sceneRect. The sceneRect was empty due to a lacking signal-slot connection, resulting in QGraphicsSceneBspTreeIndex::updateSceneRect never being invoked. Auto-test included. --- src/gui/graphicsview/qgraphicssceneindex.cpp | 17 ++++++++++++----- src/gui/graphicsview/qgraphicssceneindex_p.h | 3 ++- .../qgraphicssceneindex/tst_qgraphicssceneindex.cpp | 13 +++++++++++++ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 2f2f05e..b317e8e 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -303,24 +303,31 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe } } +void QGraphicsSceneIndexPrivate::init() +{ + if (!scene) + return; + + QObject::connect(scene, SIGNAL(sceneRectChanged(const QRectF&)), + q_func(), SLOT(updateSceneRect(const QRectF&))); +} + /*! Constructs an abstract scene index for a given \a scene. */ QGraphicsSceneIndex::QGraphicsSceneIndex(QGraphicsScene *scene) : QObject(*new QGraphicsSceneIndexPrivate(scene), scene) { - if (scene) { - connect(scene, SIGNAL(sceneRectChanged(const QRectF&)), - this, SLOT(updateSceneRect(const QRectF&))); - } + d_func()->init(); } /*! \internal */ -QGraphicsSceneIndex::QGraphicsSceneIndex(QObjectPrivate &dd, QGraphicsScene *scene) +QGraphicsSceneIndex::QGraphicsSceneIndex(QGraphicsSceneIndexPrivate &dd, QGraphicsScene *scene) : QObject(dd, scene) { + d_func()->init(); } /*! diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h index 122d7ae..aabfa79 100644 --- a/src/gui/graphicsview/qgraphicssceneindex_p.h +++ b/src/gui/graphicsview/qgraphicssceneindex_p.h @@ -114,7 +114,7 @@ protected: virtual void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const QVariant &value); virtual void prepareBoundingRectChange(const QGraphicsItem *item); - QGraphicsSceneIndex(QObjectPrivate &dd, QGraphicsScene *scene); + QGraphicsSceneIndex(QGraphicsSceneIndexPrivate &dd, QGraphicsScene *scene); friend class QGraphicsScene; friend class QGraphicsScenePrivate; @@ -133,6 +133,7 @@ public: QGraphicsSceneIndexPrivate(QGraphicsScene *scene); ~QGraphicsSceneIndexPrivate(); + void init(); static bool itemCollidesWithPath(const QGraphicsItem *item, const QPainterPath &path, Qt::ItemSelectionMode mode); void recursive_items_helper(QGraphicsItem *item, QRectF exposeRect, diff --git a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp index ac21e20..9d0675d 100644 --- a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -64,6 +64,7 @@ private slots: void overlappedItems(); void movingItems_data(); void movingItems(); + void connectedToSceneRectChanged(); private: void common_data(); @@ -214,6 +215,18 @@ void tst_QGraphicsSceneIndex::movingItems() QCOMPARE(scene.items(QRectF(0, 0, 1000, 1000)).count(), 11); } +void tst_QGraphicsSceneIndex::connectedToSceneRectChanged() +{ + + class MyScene : public QGraphicsScene + { public: using QGraphicsScene::receivers; }; + + MyScene scene; // Uses QGraphicsSceneBspTreeIndex by default. + QCOMPARE(scene.receivers(SIGNAL(sceneRectChanged(const QRectF&))), 1); + + scene.setItemIndexMethod(QGraphicsScene::NoIndex); // QGraphicsSceneLinearIndex + QCOMPARE(scene.receivers(SIGNAL(sceneRectChanged(const QRectF&))), 1); +} QTEST_MAIN(tst_QGraphicsSceneIndex) #include "tst_qgraphicssceneindex.moc" -- cgit v0.12 From 5fc3fe2e3f04475ac8c0e3287af6042bd8b67c57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 2 Jul 2009 09:56:13 +0200 Subject: Dont include untransformable graphics items twice. This revertes d39a62720ba67a0fa6e4e37519d22f14c7b7404e (we had to do it with the old implementation, but the new one have untransformable items included in the indexed list. The only difference is that untransformable items are also in the untransformable list; otherwise in the bsp tree). Auto-test included. --- .../graphicsview/qgraphicsscenebsptreeindex.cpp | 1 - .../tst_qgraphicssceneindex.cpp | 39 ++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index ff9a3da..c8d755e 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -606,7 +606,6 @@ QList QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order) co itemList << item; } } - itemList += d->untransformableItems; if (order != -1) { //We sort descending order d->sortItems(&itemList, order, d->sortCacheEnabled); diff --git a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp index 9d0675d..3ce5b16 100644 --- a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -65,6 +65,7 @@ private slots: void movingItems_data(); void movingItems(); void connectedToSceneRectChanged(); + void items(); private: void common_data(); @@ -228,5 +229,43 @@ void tst_QGraphicsSceneIndex::connectedToSceneRectChanged() QCOMPARE(scene.receivers(SIGNAL(sceneRectChanged(const QRectF&))), 1); } +void tst_QGraphicsSceneIndex::items() +{ + QGraphicsScene scene; + QGraphicsItem *item1 = scene.addRect(0, 0, 10, 10); + QGraphicsItem *item2 = scene.addRect(10, 10, 10, 10); + QCOMPARE(scene.items().size(), 2); + + // Move from unindexed items into bsp tree. + QTest::qWait(50); + QCOMPARE(scene.items().size(), 2); + + // Add untransformable item. + QGraphicsItem *item3 = new QGraphicsRectItem(QRectF(20, 20, 10, 10)); + item3->setFlag(QGraphicsItem::ItemIgnoresTransformations); + scene.addItem(item3); + QCOMPARE(scene.items().size(), 3); + + // Move from unindexed items into untransformable items. + QTest::qWait(50); + QCOMPARE(scene.items().size(), 3); + + // Move from untransformable items into unindexed items. + item3->setFlag(QGraphicsItem::ItemIgnoresTransformations, false); + QCOMPARE(scene.items().size(), 3); + QTest::qWait(50); + QCOMPARE(scene.items().size(), 3); + + // Make all items untransformable. + item1->setFlag(QGraphicsItem::ItemIgnoresTransformations); + item2->setParentItem(item1); + item3->setParentItem(item2); + QCOMPARE(scene.items().size(), 3); + + // Move from unindexed items into untransformable items. + QTest::qWait(50); + QCOMPARE(scene.items().size(), 3); +} + QTEST_MAIN(tst_QGraphicsSceneIndex) #include "tst_qgraphicssceneindex.moc" -- cgit v0.12 From 6d71de4283c05b1b42ef26fe4c23334ad34c8a54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 2 Jul 2009 10:46:37 +0200 Subject: Kill dead BSP tree code in graphics view. --- src/gui/graphicsview/qgraphicsscene_bsp.cpp | 41 ----------------------------- src/gui/graphicsview/qgraphicsscene_bsp_p.h | 3 --- 2 files changed, 44 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene_bsp.cpp b/src/gui/graphicsview/qgraphicsscene_bsp.cpp index 5858eab..7d30749 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp.cpp +++ b/src/gui/graphicsview/qgraphicsscene_bsp.cpp @@ -154,17 +154,6 @@ QList QGraphicsSceneBspTree::items(const QRectF &rect) const return tmp; } -QList QGraphicsSceneBspTree::items(const QPointF &pos) const -{ - QList tmp; - findVisitor->foundItems = &tmp; - climbTree(findVisitor, pos); - // Reset discovery bits. - for (int i = 0; i < tmp.size(); ++i) - tmp.at(i)->d_ptr->itemDiscovered = 0; - return tmp; -} - int QGraphicsSceneBspTree::leafCount() const { return leafCnt; @@ -241,36 +230,6 @@ void QGraphicsSceneBspTree::initialize(const QRectF &rect, int depth, int index) } } -void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QPointF &pos, int index) const -{ - if (nodes.isEmpty()) - return; - - const Node &node = nodes.at(index); - const int childIndex = firstChildIndex(index); - - switch (node.type) { - case Node::Leaf: { - visitor->visit(const_cast*>(&leaves[node.leafIndex])); - break; - } - case Node::Vertical: - if (pos.x() < node.offset) { - climbTree(visitor, pos, childIndex); - } else { - climbTree(visitor, pos, childIndex + 1); - } - break; - case Node::Horizontal: - if (pos.y() < node.offset) { - climbTree(visitor, pos, childIndex); - } else { - climbTree(visitor, pos, childIndex + 1); - } - break; - } -} - void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index) const { if (nodes.isEmpty()) diff --git a/src/gui/graphicsview/qgraphicsscene_bsp_p.h b/src/gui/graphicsview/qgraphicsscene_bsp_p.h index 323cf04..24b926c 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp_p.h +++ b/src/gui/graphicsview/qgraphicsscene_bsp_p.h @@ -93,7 +93,6 @@ public: void removeItems(const QSet &items); QList items(const QRectF &rect) const; - QList items(const QPointF &pos) const; int leafCount() const; inline int firstChildIndex(int index) const @@ -106,11 +105,9 @@ public: private: void initialize(const QRectF &rect, int depth, int index); - void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QPointF &pos, int index = 0) const; void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index = 0) const; void findItems(QList *foundItems, const QRectF &rect, int index); - void findItems(QList *foundItems, const QPointF &pos, int index); QRectF rectForIndex(int index) const; QVector nodes; -- cgit v0.12 From bd3c9e428af5a804fd4631c941fb642c99f6430b Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 2 Jul 2009 13:28:17 +0200 Subject: Add a note about this method not being safe in multithreaded contexts --- src/dbus/qdbusconnection.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp index 6777aa5..14cadd9 100644 --- a/src/dbus/qdbusconnection.cpp +++ b/src/dbus/qdbusconnection.cpp @@ -973,8 +973,15 @@ QDBusConnection QDBusConnection::systemBus() } /*! + \nonreentrant + Returns the connection that sent the signal, if called in a slot activated by QDBus; otherwise it returns 0. + + \note Please avoid this function. This function is not thread-safe, so if + there's any other thread delivering a D-Bus call, this function may return + the wrong connection. In new code, please use QDBusContext::connection() + (see that class for a description on how to use it). */ QDBusConnection QDBusConnection::sender() { -- cgit v0.12 From b3a0229d70ac87d2ae1fd70a7489e3caf66a2f6f Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 2 Jul 2009 14:06:04 +0200 Subject: Fix oops in strcmp in QBuffer. Reported via qt-bugs. Reviewed-By: Peter Hartmann --- src/corelib/io/qbuffer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/io/qbuffer.cpp b/src/corelib/io/qbuffer.cpp index aed5b82..3883d30 100644 --- a/src/corelib/io/qbuffer.cpp +++ b/src/corelib/io/qbuffer.cpp @@ -452,7 +452,7 @@ qint64 QBuffer::writeData(const char *data, qint64 len) */ void QBuffer::connectNotify(const char *signal) { - if (strcmp(signal + 1, "readyRead()") == 0 || strcmp(signal + 1, "bytesWritten(qint64)")) + if (strcmp(signal + 1, "readyRead()") == 0 || strcmp(signal + 1, "bytesWritten(qint64)") == 0) d_func()->signalConnectionCount++; } -- cgit v0.12 From 349997b5c4167b07d0bdc55beff175b39f3abe75 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 2 Jul 2009 14:18:47 +0200 Subject: Minor: fix spelling in configure.exe -help output. Reported via qt-bugs --- tools/configure/configureapp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 9ee5eef..1e501c5 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -1531,7 +1531,7 @@ bool Configure::displayHelp() desc( "-graphicssystem ", "Specify which graphicssystem should be used.\n" "Available values for :"); desc("GRAPHICS_SYSTEM", "raster", "", " raster - Software rasterizer", ' '); - desc("GRAPHICS_SYSTEM", "opengl", "", " opengl - Using OpenGL accelleration, experimental!", ' '); + desc("GRAPHICS_SYSTEM", "opengl", "", " opengl - Using OpenGL acceleration, experimental!", ' '); desc( "-help, -h, -?", "Display this information.\n"); -- cgit v0.12 From 3473453dda9f40bf94733bc971b0cc1658e7c3c8 Mon Sep 17 00:00:00 2001 From: Norwegian Rock Cat Date: Thu, 2 Jul 2009 14:28:46 +0200 Subject: Fix a regression where dynamic tooltips wouldn't show up in Cocoa. Tracking of mouse events was only enabled when enableMouseTracking or Hover or a tooltip had been set explictly on the item, but this meant that the dynamic QEvent::Tooltips would never get dispatched. So, in order to help out people that might use this feature, all QCocoaViews must pay the mouse move event tax *sigh*. I added comments in the proper places so that we DO the right thing for a release where we can force the change in behavior. Task-number: 257320 Reviewed-by: Denis --- src/gui/kernel/qapplication.cpp | 7 +++++++ src/gui/kernel/qcocoaview_mac.mm | 12 ++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 40795d1..c6af728 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -3724,6 +3724,13 @@ bool QApplication::notify(QObject *receiver, QEvent *e) } } + // ### Qt 5 These dynamic tool tips should be an OPT-IN feature. Some platforms + // like Mac OS X (probably others too), can optimize their views by not + // dispatching mouse move events. We have attributes to control hover, + // and mouse tracking, but as long as we are deciding to implement this + // feature without choice of opting-in or out, you ALWAYS have to have + // tracking enabled. Therefore, the other properties give a false sense of + // performance enhancement. if (e->type() == QEvent::MouseMove && mouse->buttons() == 0) { d->toolTipWidget = w; d->toolTipPos = relpos; diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index ae3265b..17e3313 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -564,11 +564,15 @@ extern "C" { [self removeTrackingArea:t]; } } + + // Ideally, we shouldn't have NSTrackingMouseMoved events included below, it should + // only be turned on if mouseTracking, hover is on or a tool tip is set. + // Unfortunately, Qt will send "tooltip" events on mouse moves, so we need to + // turn it on in ALL case. That means EVERY QCocoaView gets to pay the cost of + // mouse moves delivered to it (Apple recommends keeping it OFF because there + // is a performance hit). So it goes. NSUInteger trackingOptions = NSTrackingMouseEnteredAndExited | NSTrackingActiveInActiveApp - | NSTrackingInVisibleRect; - if (qwidget->hasMouseTracking() || !qwidgetprivate->toolTip.isEmpty() - || qwidget->testAttribute(Qt::WA_Hover)) - trackingOptions |= NSTrackingMouseMoved; + | NSTrackingInVisibleRect | NSTrackingMouseMoved; NSTrackingArea *ta = [[NSTrackingArea alloc] initWithRect:NSMakeRect(0, 0, qwidget->width(), qwidget->height()) -- cgit v0.12 From c4ae87721e011fe44f301c4039f0651a05394162 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 2 Jul 2009 14:59:51 +0200 Subject: Speedup item-lookup in Graphics View. We don't have to do a stable sort anymore because the lessThan operator now accounts for the insertion order. This also means we don't have to sort all top-level items to preserve the insertion order in QGraphicsScenePrivate::topLevelItemsInStackingOrder. Reviewed-by: Andreas --- src/gui/graphicsview/qgraphicsitem.cpp | 5 +++ src/gui/graphicsview/qgraphicsitem_p.h | 17 +++++++ src/gui/graphicsview/qgraphicsscene.cpp | 52 ++++++++++------------ src/gui/graphicsview/qgraphicsscene_p.h | 8 ++++ .../graphicsview/qgraphicsscenebsptreeindex.cpp | 12 ++--- .../graphicsview/qgraphicsscenebsptreeindex_p.h | 18 +++----- src/gui/graphicsview/qgraphicssceneindex.cpp | 5 +-- 7 files changed, 65 insertions(+), 52 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 002eab9..9a27ef5 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -4310,6 +4310,7 @@ void QGraphicsItemPrivate::resolveDepth(int parentDepth) void QGraphicsItemPrivate::addChild(QGraphicsItem *child) { needSortChildren = 1; + child->d_ptr->siblingIndex = children.size(); children.append(child); } @@ -4319,6 +4320,10 @@ void QGraphicsItemPrivate::addChild(QGraphicsItem *child) void QGraphicsItemPrivate::removeChild(QGraphicsItem *child) { 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()). + child->d_ptr->siblingIndex = -1; } /*! diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index a4b2c25..99865b0 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -126,6 +126,7 @@ public: parent(0), transformData(0), index(-1), + siblingIndex(-1), depth(0), acceptedMouseButtons(0x1f), visible(1), @@ -386,6 +387,7 @@ public: } inline QTransform transformToParent() const; + inline void ensureSortedChildren(); QPainterPath cachedClipPath; QRectF childrenBoundingRect; @@ -401,6 +403,7 @@ public: TransformData *transformData; QTransform sceneTransform; int index; + int siblingIndex; int depth; inline QGestureExtraData* extraGestures() const @@ -517,6 +520,12 @@ struct QGraphicsItemPrivate::TransformData { } }; +/*! + \internal +*/ +static inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) +{ return qt_closestLeaf(item2, item1); } + /* return the full transform of the item to the parent. This include the position and all the transform data */ @@ -527,6 +536,14 @@ inline QTransform QGraphicsItemPrivate::transformToParent() const return matrix; } +inline void QGraphicsItemPrivate::ensureSortedChildren() +{ + if (needSortChildren) { + qSort(children.begin(), children.end(), qt_notclosestLeaf); + needSortChildren = 0; + } +} + QT_END_NAMESPACE #endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 8a032f4..3b1c8ad 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -375,6 +375,7 @@ void QGraphicsScenePrivate::_q_emitUpdated() void QGraphicsScenePrivate::registerTopLevelItem(QGraphicsItem *item) { needSortTopLevelItems = true; + item->d_ptr->siblingIndex = topLevelItems.size(); topLevelItems.append(item); } @@ -384,6 +385,10 @@ void QGraphicsScenePrivate::registerTopLevelItem(QGraphicsItem *item) void QGraphicsScenePrivate::unregisterTopLevelItem(QGraphicsItem *item) { 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; } /*! @@ -1084,37 +1089,29 @@ QList QGraphicsScenePrivate::topLevelItemsInStackingOrder(const const QRectF &sceneRect) { if (indexMethod == QGraphicsScene::NoIndex || sceneRect.isNull()) { - if (needSortTopLevelItems) { - needSortTopLevelItems = false; - qStableSort(topLevelItems.begin(), topLevelItems.end(), qt_notclosestLeaf); - } + ensureSortedTopLevelItems(); return topLevelItems; } - QList tmp = index->estimateItems(sceneRect, Qt::SortOrder(-1), - viewTransform ? *viewTransform : QTransform()); - for (int i = 0; i < tmp.size(); ++i) - tmp.at(i)->topLevelItem()->d_ptr->itemDiscovered = 1; - - // Sort if the toplevel list is unsorted. - if (needSortTopLevelItems) { - needSortTopLevelItems = false; - qStableSort(topLevelItems.begin(), topLevelItems.end(), qt_notclosestLeaf); - } - + const QList tmp = index->estimateItems(sceneRect, Qt::SortOrder(-1), + viewTransform ? *viewTransform : QTransform()); + // estimateItems returns a list of *all* items, but we are only interested + // in the top-levels (those that are within the rect themselves and those that + // have descendants within the rect). + // ### Look into how we can add this feature to the BSP. QList tli; - for (int i = 0; i < topLevelItems.size(); ++i) { - // ### Investigate smarter ways. Looping through all top level - // items is not optimal. If the BSP tree is to have maximum - // effect, it should be possible to sort the subset of items - // quickly. We must use this approach for now, as it's the only - // current way to keep the stable sorting order (insertion order). - QGraphicsItem *item = topLevelItems.at(i); - if (item->d_ptr->itemDiscovered) { - item->d_ptr->itemDiscovered = 0; - tli << item; + for (int i = 0; i < tmp.size(); ++i) { + QGraphicsItem *topLevelItem = tmp.at(i)->topLevelItem(); + if (!topLevelItem->d_ptr->itemDiscovered) { + tli << topLevelItem; + topLevelItem->d_ptr->itemDiscovered = 1; } } + // Reset discovered bit. + for (int i = 0; i < tli.size(); ++i) + tli.at(i)->d_ptr->itemDiscovered = 0; + + qSort(tli.begin(), tli.end(), qt_notclosestLeaf); return tli; } @@ -4283,10 +4280,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * int i = 0; if (itemHasChildren) { - if (item->d_ptr->needSortChildren) { - item->d_ptr->needSortChildren = 0; - qStableSort(item->d_ptr->children.begin(), item->d_ptr->children.end(), qt_notclosestLeaf); - } + item->d_ptr->ensureSortedChildren(); if (itemClipsChildrenToShape) { painter->save(); diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 4842e72..23b0dd5 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -234,6 +234,14 @@ public: item->d_ptr->ignoreOpacity = 0; } + inline void ensureSortedTopLevelItems() + { + if (needSortTopLevelItems) { + qSort(topLevelItems.begin(), topLevelItems.end(), qt_notclosestLeaf); + needSortTopLevelItems = false; + } + } + QStyle *style; QFont font; void setFont_helper(const QFont &font); diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index c8d755e..0688cb1 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -242,7 +242,7 @@ void QGraphicsSceneBspTreeIndexPrivate::climbTree(QGraphicsItem *item, int *stac { if (!item->d_ptr->children.isEmpty()) { QList childList = item->d_ptr->children; - qStableSort(childList.begin(), childList.end(), qt_closestLeaf); + qSort(childList.begin(), childList.end(), qt_closestLeaf); for (int i = 0; i < childList.size(); ++i) { QGraphicsItem *item = childList.at(i); if (!(item->flags() & QGraphicsItem::ItemStacksBehindParent)) @@ -281,7 +281,7 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateSortCache() topLevels << item; } - qStableSort(topLevels.begin(), topLevels.end(), qt_closestLeaf); + qSort(topLevels.begin(), topLevels.end(), qt_closestLeaf); for (int i = 0; i < topLevels.size(); ++i) climbTree(topLevels.at(i), &stackingOrder); } @@ -446,15 +446,15 @@ void QGraphicsSceneBspTreeIndexPrivate::sortItems(QList *itemLi { if (sortCacheEnabled) { if (order == Qt::AscendingOrder) { - qStableSort(itemList->begin(), itemList->end(), closestItemFirst_withCache); + qSort(itemList->begin(), itemList->end(), closestItemFirst_withCache); } else if (order == Qt::DescendingOrder) { - qStableSort(itemList->begin(), itemList->end(), closestItemLast_withCache); + qSort(itemList->begin(), itemList->end(), closestItemLast_withCache); } } else { if (order == Qt::AscendingOrder) { - qStableSort(itemList->begin(), itemList->end(), closestItemFirst_withoutCache); + qSort(itemList->begin(), itemList->end(), closestItemFirst_withoutCache); } else if (order == Qt::DescendingOrder) { - qStableSort(itemList->begin(), itemList->end(), closestItemLast_withoutCache); + qSort(itemList->begin(), itemList->end(), closestItemLast_withoutCache); } } } diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index 7b431e6..437b17d 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -173,21 +173,13 @@ inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item const QGraphicsItemPrivate *d2 = item2->d_ptr; bool f1 = d1->flags & QGraphicsItem::ItemStacksBehindParent; bool f2 = d2->flags & QGraphicsItem::ItemStacksBehindParent; - if (f1 != f2) return f2; - qreal z1 = d1->z; - qreal z2 = d2->z; - return z1 > z2; + if (f1 != f2) + return f2; + if (d1->z != d2->z) + return d1->z > d2->z; + return d1->siblingIndex > d2->siblingIndex; } -/*! - \internal -*/ -static inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) -{ - return qt_closestLeaf(item2, item1); -} - - static inline bool QRectF_intersects(const QRectF &s, const QRectF &r) { qreal xp = s.left(); diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index b317e8e..d6281e2 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -266,10 +266,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe int i = 0; if (itemHasChildren) { // Sort children. - if (item->d_ptr->needSortChildren) { - item->d_ptr->needSortChildren = 0; - qStableSort(item->d_ptr->children.begin(), item->d_ptr->children.end(), qt_notclosestLeaf); - } + item->d_ptr->ensureSortedChildren(); // Clip to shape. if (itemClipsChildrenToShape) -- cgit v0.12 From 097476afe24d69bac65b84b70ed2f93e88875b40 Mon Sep 17 00:00:00 2001 From: Norwegian Rock Cat Date: Wed, 1 Jul 2009 14:34:21 +0200 Subject: Implement hitTest Cocoa calls hitTest on our view to determine if the view should get the mouse press. We always said, "yes" and did all the logic ourselves. Turns out that we can say "no" if I'm transparent to mouse events and remove all that code where we do all the work ourselves. Big maintenance win! For the time being I've kept the "transparentViewForEvent" method since it might be useful for others, but no one is using it at the moment and we may just kill it soon. HitTest should handle this situation correctly. --- src/gui/kernel/qcocoaview_mac.mm | 17 ++++++------- src/gui/kernel/qt_cocoa_helpers_mac.mm | 44 ---------------------------------- 2 files changed, 7 insertions(+), 54 deletions(-) diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index 17e3313..81e06a9 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -554,6 +554,13 @@ extern "C" { return !qwidget->testAttribute(Qt::WA_MacNoClickThrough); } +- (NSView *)hitTest:(NSPoint)aPoint +{ + if (qwidget->testAttribute(Qt::WA_TransparentForMouseEvents)) + return nil; // You cannot hit a transparent for mouse event widget. + return [super hitTest:aPoint]; +} + - (void)updateTrackingAreas { QMacCocoaAutoReleasePool pool; @@ -794,16 +801,6 @@ extern "C" { Qt::KeyboardModifiers keyMods = qt_cocoaModifiers2QtModifiers([theEvent modifierFlags]); QWidget *widgetToGetMouse = qwidget; - if (widgetToGetMouse->testAttribute(Qt::WA_TransparentForMouseEvents)) { - // Simulate passing the event through since Cocoa doesn't do that for us. - // Start by building a tree up. - NSView *candidateView = [self viewUnderTransparentForMouseView:self - widget:widgetToGetMouse - withWindowPoint:windowPoint]; - if (candidateView != nil) { - widgetToGetMouse = QWidget::find(WId(candidateView)); - } - } // Mouse wheel deltas seem to tick in at increments of 0.1. Qt widgets // expect the delta to be a multiple of 120. diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index 2dd4fdf..241ea44 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -851,50 +851,6 @@ bool qt_mac_handleMouseEvent(void * /* NSView * */view, void * /* NSEvent * */ev NSPoint localPoint = [tmpView convertPoint:windowPoint fromView:nil]; QPoint qlocalPoint(localPoint.x, localPoint.y); - if (widgetToGetMouse->testAttribute(Qt::WA_TransparentForMouseEvents)) { - // Simulate passing the event through since Cocoa doesn't do that for us. - // Start by building a tree up. - NSView *candidateView = [theView viewUnderTransparentForMouseView:tmpView - widget:widgetToGetMouse - withWindowPoint:windowPoint]; - if (candidateView != nil) { - // Fast-track our views, since dispatching trough the normal ways - // would just end up going through here anyway. - if ([candidateView isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaView) class]]) { - return qt_mac_handleMouseEvent(candidateView, theEvent, eventType, button); - } else { - switch (eventType) { - default: - qWarning("not handled! %d", eventType); - break; - case QEvent::MouseMove: - [candidateView mouseMoved:theEvent]; - break; - case QEvent::MouseButtonPress: - if (button == Qt::LeftButton) - [candidateView mouseDown:theEvent]; - else if (button == Qt::RightButton) - [candidateView rightMouseDown:theEvent]; - else - [candidateView otherMouseDown:theEvent]; - break; - case QEvent::MouseButtonRelease: - if (button == Qt::LeftButton) - [candidateView mouseUp:theEvent]; - else if (button == Qt::RightButton) - [candidateView rightMouseUp:theEvent]; - else - [candidateView otherMouseUp:theEvent]; - break; - } - return true; // We've done the dispatching, no need go further. - } - } - // Nothing below me return false - return false; - } - - EventRef carbonEvent = static_cast(const_cast([theEvent eventRef])); if (qt_mac_sendMacEventToWidget(widgetToGetMouse, carbonEvent)) return true; -- cgit v0.12 From c6cc00316b2ce95adddc9fdb658d737057b40682 Mon Sep 17 00:00:00 2001 From: Prasanth Ullattil Date: Thu, 2 Jul 2009 16:25:44 +0200 Subject: Drag and drop events are not delivered correctly in Cocoa Drag and drop events should consider the WA_TransparentForMouseEvents attribute like the mouse events. If this attribute is set for a widget, the event has to be passed to right widget under mouse. The widget is identified by calling hitTest. In such cases the leave event has to be delivered to the widget which actually accepted the enter event. Task-number: 252088 Reviewed-by: Norwegian Rock Cat --- src/gui/kernel/qcocoaview_mac.mm | 49 ++++++++++++++++++++++++++++++++------- src/gui/kernel/qcocoaview_mac_p.h | 2 ++ 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index 81e06a9..4479531 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -288,11 +288,18 @@ extern "C" { { if (qwidget->testAttribute(Qt::WA_DropSiteRegistered) == false) return NSDragOperationNone; + NSPoint windowPoint = [sender draggingLocation]; + if (qwidget->testAttribute(Qt::WA_TransparentForMouseEvents)) { + // pass the drag enter event to the view underneath. + NSView *candidateView = [[[self window] contentView] hitTest:windowPoint]; + if (candidateView && candidateView != self) + return [candidateView draggingEntered:sender]; + } + dragEnterSequence = [sender draggingSequenceNumber]; [self addDropData:sender]; QMimeData *mimeData = dropData; if (QDragManager::self()->source()) mimeData = QDragManager::self()->dragPrivate()->data; - NSPoint windowPoint = [sender draggingLocation]; NSPoint globalPoint = [[sender draggingDestinationWindow] convertBaseToScreen:windowPoint]; NSPoint localPoint = [self convertPoint:windowPoint fromView:nil]; QPoint posDrag(localPoint.x, localPoint.y); @@ -316,6 +323,9 @@ extern "C" { [self removeDropData]; return NSDragOperationNone; } else { + // save the mouse position, used by draggingExited handler. + DnDParams *dndParams = [QCocoaView currentMouseEvent]; + dndParams->activeDragEnterPos = windowPoint; // send a drag move event immediately after a drag enter event (as per documentation). QDragMoveEvent qDMEvent(posDrag, qtAllowed, mimeData, QApplication::mouseButtons(), modifiers); qDMEvent.setDropAction(qDEEvent.dropAction()); @@ -336,11 +346,22 @@ extern "C" { - (NSDragOperation)draggingUpdated:(id < NSDraggingInfo >)sender { - // drag enter event was rejected, so ignore the move event. + NSPoint windowPoint = [sender draggingLocation]; + if (qwidget->testAttribute(Qt::WA_TransparentForMouseEvents)) { + // pass the drag move event to the view underneath. + NSView *candidateView = [[[self window] contentView] hitTest:windowPoint]; + if (candidateView && candidateView != self) + return [candidateView draggingUpdated:sender]; + } + // in cases like QFocusFrame, the view under the mouse might + // not have received the drag enter. Generate a synthetic + // drag enter event for that view. + if (dragEnterSequence != [sender draggingSequenceNumber]) + [self draggingEntered:sender]; + // drag enter event was rejected, so ignore the move event. if (dropData == 0) return NSDragOperationNone; // return last value, if we are still in the answerRect. - NSPoint windowPoint = [sender draggingLocation]; NSPoint globalPoint = [[sender draggingDestinationWindow] convertBaseToScreen:windowPoint]; NSPoint localPoint = [self convertPoint:windowPoint fromView:nil]; NSDragOperation nsActions = [sender draggingSourceOperationMask]; @@ -379,21 +400,34 @@ extern "C" { - (void)draggingExited:(id < NSDraggingInfo >)sender { - Q_UNUSED(sender) - // drag enter event was rejected, so ignore the move event. + dragEnterSequence = -1; + if (qwidget->testAttribute(Qt::WA_TransparentForMouseEvents)) { + // try sending the leave event to the last view which accepted drag enter. + DnDParams *dndParams = [QCocoaView currentMouseEvent]; + NSView *candidateView = [[[self window] contentView] hitTest:dndParams->activeDragEnterPos]; + if (candidateView && candidateView != self) + return [candidateView draggingExited:sender]; + } + // drag enter event was rejected, so ignore the move event. if (dropData) { QDragLeaveEvent de; QApplication::sendEvent(qwidget, &de); [self removeDropData]; } - } - (BOOL)performDragOperation:(id )sender { + NSPoint windowPoint = [sender draggingLocation]; + dragEnterSequence = -1; + if (qwidget->testAttribute(Qt::WA_TransparentForMouseEvents)) { + // pass the drop event to the view underneath. + NSView *candidateView = [[[self window] contentView] hitTest:windowPoint]; + if (candidateView && candidateView != self) + return [candidateView performDragOperation:sender]; + } [self addDropData:sender]; - NSPoint windowPoint = [sender draggingLocation]; NSPoint globalPoint = [[sender draggingDestinationWindow] convertBaseToScreen:windowPoint]; NSPoint localPoint = [self convertPoint:windowPoint fromView:nil]; QPoint posDrop(localPoint.x, localPoint.y); @@ -688,7 +722,6 @@ extern "C" { } if (!lowerView) // Low as we can be at this point. candidateView = viewForDescent; - // Try to go deeper, will also exit out of the loop, if we found the point. viewForDescent = lowerView; lowerView = nil; diff --git a/src/gui/kernel/qcocoaview_mac_p.h b/src/gui/kernel/qcocoaview_mac_p.h index b4a60b6..7c227cc 100644 --- a/src/gui/kernel/qcocoaview_mac_p.h +++ b/src/gui/kernel/qcocoaview_mac_p.h @@ -68,6 +68,7 @@ struct DnDParams NSEvent *theEvent; NSPoint localPoint; NSDragOperation performedAction; + NSPoint activeDragEnterPos; }; QT_END_NAMESPACE @@ -85,6 +86,7 @@ Q_GUI_EXPORT int composingLength; bool sendKeyEvents; QStringList *currentCustomTypes; + NSInteger dragEnterSequence; } - (id)initWithQWidget:(QWidget *)widget widgetPrivate:(QWidgetPrivate *)widgetprivate; - (void) finishInitWithQWidget:(QWidget *)widget widgetPrivate:(QWidgetPrivate *)widgetprivate; -- cgit v0.12 From d2bfae633e99a818c9086846bf330d722afd86f4 Mon Sep 17 00:00:00 2001 From: Prasanth Ullattil Date: Thu, 2 Jul 2009 16:55:38 +0200 Subject: Remove unused function viewUnderTransparentForMouseView in QCocoaView. After we implemented hitTest for QCocoaView, this function is no longer used. Reviewed-by: Norwegian Rock Cat --- src/gui/kernel/qcocoaview_mac.mm | 55 --------------------------------------- src/gui/kernel/qcocoaview_mac_p.h | 2 -- 2 files changed, 57 deletions(-) diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index 4479531..e3ec30a 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -678,61 +678,6 @@ extern "C" { qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, Qt::NoButton); } -- (NSView *)viewUnderTransparentForMouseView:(NSView *)mouseView widget:(QWidget *)widgetToGetMouse - withWindowPoint:(NSPoint)windowPoint -{ - NSMutableArray *viewsToLookAt = [NSMutableArray arrayWithCapacity:5]; - [viewsToLookAt addObject:mouseView]; - QWidget *parentWidget = widgetToGetMouse->parentWidget(); - while (parentWidget) { - [viewsToLookAt addObject:qt_mac_nativeview_for(parentWidget)]; - parentWidget = parentWidget->parentWidget(); - } - - // Now walk through the subviews of each view and determine which subview should - // get the event. We look through all the subviews at a given level with - // the assumption that the last item to be found the candidate has a higher z-order. - // Unfortunately, fast enumeration doesn't go backwards in 10.5, so assume go fast - // forward is quicker than the slow normal way backwards. - NSView *candidateView = nil; - for (NSView *lookView in viewsToLookAt) { - NSPoint tmpPoint = [lookView convertPoint:windowPoint fromView:nil]; - for (NSView *view in [lookView subviews]) { - if (view == mouseView || [view isHidden]) - continue; - NSRect frameRect = [view frame]; - if (NSMouseInRect(tmpPoint, [view frame], [view isFlipped])) - candidateView = view; - } - if (candidateView) - break; - } - - - if (candidateView != nil) { - // Now that we've got a candidate, we have to dig into it's tree and see where it is. - NSView *lowerView = nil; - NSView *viewForDescent = candidateView; - while (viewForDescent) { - NSPoint tmpPoint = [viewForDescent convertPoint:windowPoint fromView:nil]; - // Apply same rule as above wrt z-order. - for (NSView *view in [viewForDescent subviews]) { - if (![view isHidden] && NSMouseInRect(tmpPoint, [view frame], [view isFlipped])) - lowerView = view; - } - if (!lowerView) // Low as we can be at this point. - candidateView = viewForDescent; - // Try to go deeper, will also exit out of the loop, if we found the point. - viewForDescent = lowerView; - lowerView = nil; - } - } - // I am transparent, so I can't be a candidate. - if (candidateView == mouseView) - candidateView = nil; - return candidateView; -} - - (void)mouseDown:(NSEvent *)theEvent { qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonPress, Qt::LeftButton); diff --git a/src/gui/kernel/qcocoaview_mac_p.h b/src/gui/kernel/qcocoaview_mac_p.h index 7c227cc..24040ba 100644 --- a/src/gui/kernel/qcocoaview_mac_p.h +++ b/src/gui/kernel/qcocoaview_mac_p.h @@ -105,8 +105,6 @@ Q_GUI_EXPORT - (QWidget *)qt_qwidget; - (BOOL)qt_leftButtonIsRightButton; - (void)qt_setLeftButtonIsRightButton:(BOOL)isSwapped; -- (NSView *)viewUnderTransparentForMouseView:(NSView *)mouseView widget:(QWidget *)widgetToGetMouse - withWindowPoint:(NSPoint)windowPoint; + (DnDParams*)currentMouseEvent; @end -- cgit v0.12 From 1d651e82459c0480cb3e803a9d9452092ac9d502 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 2 Jul 2009 18:01:33 +0200 Subject: More re-factoring of QGraphicsSceneIndex. New method: QGraphicsSceneIndex::estimateTopLevelItems. QGraphicsSceneIndex::estimateItems returns *all* items within the rect, but we are only interested in the top-levels (those that are within the rect themselves or have descendants within the rect) when doing recursive drawing/item-lookup. All auto-tests pass. Demos/examples/manualtests run fine. --- src/gui/graphicsview/qgraphicsscene.cpp | 46 +++++--------- src/gui/graphicsview/qgraphicsscene_bsp.cpp | 8 ++- src/gui/graphicsview/qgraphicsscene_bsp_p.h | 4 +- src/gui/graphicsview/qgraphicsscene_p.h | 17 +---- .../graphicsview/qgraphicsscenebsptreeindex.cpp | 72 ++++++++++++++-------- .../graphicsview/qgraphicsscenebsptreeindex_p.h | 8 ++- src/gui/graphicsview/qgraphicssceneindex.cpp | 21 +++++-- src/gui/graphicsview/qgraphicssceneindex_p.h | 10 +-- src/gui/graphicsview/qgraphicsscenelinearindex.cpp | 5 +- src/gui/graphicsview/qgraphicsscenelinearindex_p.h | 3 +- 10 files changed, 98 insertions(+), 96 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 3b1c8ad..85d05e9 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1085,36 +1085,6 @@ QGraphicsWidget *QGraphicsScenePrivate::windowForItem(const QGraphicsItem *item) return 0; } -QList QGraphicsScenePrivate::topLevelItemsInStackingOrder(const QTransform *const viewTransform, - const QRectF &sceneRect) -{ - if (indexMethod == QGraphicsScene::NoIndex || sceneRect.isNull()) { - ensureSortedTopLevelItems(); - return topLevelItems; - } - - const QList tmp = index->estimateItems(sceneRect, Qt::SortOrder(-1), - viewTransform ? *viewTransform : QTransform()); - // estimateItems returns a list of *all* items, but we are only interested - // in the top-levels (those that are within the rect themselves and those that - // have descendants within the rect). - // ### Look into how we can add this feature to the BSP. - QList tli; - for (int i = 0; i < tmp.size(); ++i) { - QGraphicsItem *topLevelItem = tmp.at(i)->topLevelItem(); - if (!topLevelItem->d_ptr->itemDiscovered) { - tli << topLevelItem; - topLevelItem->d_ptr->itemDiscovered = 1; - } - } - // Reset discovered bit. - for (int i = 0; i < tli.size(); ++i) - tli.at(i)->d_ptr->itemDiscovered = 0; - - qSort(tli.begin(), tli.end(), qt_notclosestLeaf); - return tli; -} - /*! \internal @@ -1759,7 +1729,7 @@ QList QGraphicsScene::collidingItems(const QGraphicsItem *item, // Does not support ItemIgnoresTransformations. QList tmp; - foreach (QGraphicsItem *itemInVicinity, d->index->estimateItems(item->sceneBoundingRect(), Qt::AscendingOrder, QTransform())) { + foreach (QGraphicsItem *itemInVicinity, d->index->estimateItems(item->sceneBoundingRect(), Qt::AscendingOrder)) { if (item != itemInVicinity && item->collidesWithItem(itemInVicinity, mode)) tmp << itemInVicinity; } @@ -4209,6 +4179,20 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte } } +void QGraphicsScenePrivate::drawItems(QPainter *painter, const QTransform *const viewTransform, + QRegion *exposedRegion, QWidget *widget) +{ + QRectF exposedSceneRect; + if (exposedRegion && indexMethod != QGraphicsScene::NoIndex) { + exposedSceneRect = exposedRegion->boundingRect().adjusted(-1, -1, 1, 1); + if (viewTransform) + exposedSceneRect = viewTransform->inverted().mapRect(exposedSceneRect); + } + const QList tli = index->estimateTopLevelItems(exposedSceneRect, Qt::DescendingOrder); + for (int i = 0; i < tli.size(); ++i) + drawSubtreeRecursive(tli.at(i), painter, viewTransform, exposedRegion, widget); +} + void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform *const viewTransform, QRegion *exposedRegion, QWidget *widget, diff --git a/src/gui/graphicsview/qgraphicsscene_bsp.cpp b/src/gui/graphicsview/qgraphicsscene_bsp.cpp index 7d30749..fb4b9a4 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp.cpp +++ b/src/gui/graphicsview/qgraphicsscene_bsp.cpp @@ -70,12 +70,15 @@ class QGraphicsSceneFindItemBspTreeVisitor : public QGraphicsSceneBspTreeVisitor { public: QList *foundItems; + bool onlyTopLevelItems; void visit(QList *items) { for (int i = 0; i < items->size(); ++i) { QGraphicsItem *item = items->at(i); - if (!item->d_func()->itemDiscovered && item->isVisible()) { + if (onlyTopLevelItems && item->d_ptr->parent) + item = item->topLevelItem(); + if (!item->d_func()->itemDiscovered && item->d_ptr->visible) { item->d_func()->itemDiscovered = 1; foundItems->prepend(item); } @@ -143,10 +146,11 @@ void QGraphicsSceneBspTree::removeItems(const QSet &items) } } -QList QGraphicsSceneBspTree::items(const QRectF &rect) const +QList QGraphicsSceneBspTree::items(const QRectF &rect, bool onlyTopLevelItems) const { QList tmp; findVisitor->foundItems = &tmp; + findVisitor->onlyTopLevelItems = onlyTopLevelItems; climbTree(findVisitor, rect); // Reset discovery bits. for (int i = 0; i < tmp.size(); ++i) diff --git a/src/gui/graphicsview/qgraphicsscene_bsp_p.h b/src/gui/graphicsview/qgraphicsscene_bsp_p.h index 24b926c..4cac64a 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp_p.h +++ b/src/gui/graphicsview/qgraphicsscene_bsp_p.h @@ -92,7 +92,7 @@ public: void removeItem(QGraphicsItem *item, const QRectF &rect); void removeItems(const QSet &items); - QList items(const QRectF &rect) const; + QList items(const QRectF &rect, bool onlyTopLevelItems = false) const; int leafCount() const; inline int firstChildIndex(int index) const @@ -106,8 +106,6 @@ public: private: void initialize(const QRectF &rect, int depth, int index); void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index = 0) const; - - void findItems(QList *foundItems, const QRectF &rect, int index); QRectF rectForIndex(int index) const; QVector nodes; diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 23b0dd5..245380f 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -191,26 +191,13 @@ public: QGraphicsWidget *windowForItem(const QGraphicsItem *item) const; bool sortCacheEnabled; // for compatibility - QList topLevelItemsInStackingOrder(const QTransform *const, const QRectF&); void drawItemHelper(QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget, bool painterStateProtection); - inline void drawItems(QPainter *painter, const QTransform *const viewTransform, - QRegion *exposedRegion, QWidget *widget) - { - QRectF exposedSceneRect; - if (exposedRegion && indexMethod != QGraphicsScene::NoIndex) { - exposedSceneRect = exposedRegion->boundingRect().adjusted(-1, -1, 1, 1); - if (viewTransform) - exposedSceneRect = viewTransform->inverted().mapRect(exposedSceneRect); - } - const QList tli = topLevelItemsInStackingOrder(viewTransform, exposedSceneRect); - for (int i = 0; i < tli.size(); ++i) - drawSubtreeRecursive(tli.at(i), painter, viewTransform, exposedRegion, widget); - return; - } + void drawItems(QPainter *painter, const QTransform *const viewTransform, + QRegion *exposedRegion, QWidget *widget); void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform *const, QRegion *exposedRegion, QWidget *widget, qreal parentOpacity = qreal(1.0)); diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 0688cb1..a7b4828 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -372,6 +372,32 @@ void QGraphicsSceneBspTreeIndexPrivate::removeItem(QGraphicsItem *item, bool rec } } +QList QGraphicsSceneBspTreeIndexPrivate::estimateItems(const QRectF &rect, Qt::SortOrder order, + bool onlyTopLevelItems) +{ + Q_Q(QGraphicsSceneBspTreeIndex); + if (onlyTopLevelItems && rect.isNull()) + return q->QGraphicsSceneIndex::estimateTopLevelItems(rect, order); + + purgeRemovedItems(); + _q_updateSortCache(); + Q_ASSERT(unindexedItems.isEmpty()); + + QList rectItems = bsp.items(rect, onlyTopLevelItems); + if (onlyTopLevelItems) { + for (int i = 0; i < untransformableItems.size(); ++i) { + QGraphicsItem *item = untransformableItems.at(i); + if (!item->d_ptr->parent) + rectItems << item; + } + } else { + rectItems += untransformableItems; + } + + sortItems(&rectItems, order, sortCacheEnabled, onlyTopLevelItems); + return rectItems; +} + /*! Returns true if \a item1 is on top of \a item2. @@ -442,8 +468,19 @@ bool QGraphicsSceneBspTreeIndexPrivate::closestItemLast_withoutCache(const QGrap \internal */ void QGraphicsSceneBspTreeIndexPrivate::sortItems(QList *itemList, Qt::SortOrder order, - bool sortCacheEnabled) + bool sortCacheEnabled, bool onlyTopLevelItems) { + if (order == Qt::SortOrder(-1)) + return; + + if (onlyTopLevelItems) { + if (order == Qt::AscendingOrder) + qSort(itemList->begin(), itemList->end(), qt_closestLeaf); + else if (order == Qt::DescendingOrder) + qSort(itemList->begin(), itemList->end(), qt_notclosestLeaf); + return; + } + if (sortCacheEnabled) { if (order == Qt::AscendingOrder) { qSort(itemList->begin(), itemList->end(), closestItemFirst_withCache); @@ -548,36 +585,17 @@ void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem * \a deviceTransform is the transformation apply to the view. */ -QList QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &rect, Qt::SortOrder order, - const QTransform &deviceTransform) const +QList QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &rect, Qt::SortOrder order) const { Q_D(const QGraphicsSceneBspTreeIndex); - const_cast(d)->purgeRemovedItems(); - const_cast(d)->_q_updateSortCache(); - - // ### Handle items that ignore transformations - Q_UNUSED(deviceTransform); - - QList rectItems = d->bsp.items(rect); - - // Fill in with any unindexed items - for (int i = 0; i < d->unindexedItems.size(); ++i) { - if (QGraphicsItem *item = d->unindexedItems.at(i)) { - if (item->d_ptr->visible - && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { - QRectF boundingRect = item->sceneBoundingRect(); - if (QRectF_intersects(boundingRect, rect)) - rectItems << item; - } - } - } - - rectItems += d->untransformableItems; - d->sortItems(&rectItems, order, d->sortCacheEnabled); - - return rectItems; + return const_cast(d)->estimateItems(rect, order); } +QList QGraphicsSceneBspTreeIndex::estimateTopLevelItems(const QRectF &rect, Qt::SortOrder order) const +{ + Q_D(const QGraphicsSceneBspTreeIndex); + return const_cast(d)->estimateItems(rect, order, /*onlyTopLevels=*/true); +} /*! \fn QList QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order = Qt::AscendingOrder) const; diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index 437b17d..3ac922b 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -82,8 +82,8 @@ public: QGraphicsSceneBspTreeIndex(QGraphicsScene *scene = 0); ~QGraphicsSceneBspTreeIndex(); - QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const; - + QList estimateItems(const QRectF &rect, Qt::SortOrder order) const; + QList estimateTopLevelItems(const QRectF &rect, Qt::SortOrder order) const; QList items(Qt::SortOrder order = Qt::AscendingOrder) const; int bspTreeDepth(); @@ -145,6 +145,7 @@ public: void invalidateSortCache(); void addItem(QGraphicsItem *item, bool recursive = false); void removeItem(QGraphicsItem *item, bool recursive = false, bool moveToUnindexedItems = false); + QList estimateItems(const QRectF &, Qt::SortOrder, bool b = false); static void climbTree(QGraphicsItem *item, int *stackingOrder); static bool closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2); @@ -159,7 +160,8 @@ public: return item1->d_ptr->globalStackingOrder >= item2->d_ptr->globalStackingOrder; } - static void sortItems(QList *itemList, Qt::SortOrder order, bool cached); + static void sortItems(QList *itemList, Qt::SortOrder order, + bool cached, bool onlyTopLevelItems = false); }; diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index d6281e2..5626051 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -482,12 +482,25 @@ QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt:: /*! This virtual function return an estimation of items at position \a point. This method return a list sorted using \a order. - \a deviceTransform is the transformation apply to the view. */ -QList QGraphicsSceneIndex::estimateItems(const QPointF &point, Qt::SortOrder order, - const QTransform &deviceTransform) const +QList QGraphicsSceneIndex::estimateItems(const QPointF &point, Qt::SortOrder order) const +{ + return estimateItems(QRectF(point, QSize(1, 1)), order); +} + +QList QGraphicsSceneIndex::estimateTopLevelItems(const QRectF &rect, Qt::SortOrder order) const { - return estimateItems(QRectF(point, QSize(1,1)), order, deviceTransform); + Q_D(const QGraphicsSceneIndex); + Q_UNUSED(rect); + QGraphicsScenePrivate *scened = d->scene->d_func(); + scened->ensureSortedTopLevelItems(); + if (order == Qt::AscendingOrder) { + QList sorted; + for (int i = scened->topLevelItems.size() - 1; i >= 0; --i) + sorted << scened->topLevelItems.at(i); + return sorted; + } + return scened->topLevelItems; } /*! diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h index aabfa79..6521765 100644 --- a/src/gui/graphicsview/qgraphicssceneindex_p.h +++ b/src/gui/graphicsview/qgraphicssceneindex_p.h @@ -97,10 +97,9 @@ public: Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; virtual QList items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; - virtual QList estimateItems(const QPointF &point, - Qt::SortOrder order, const QTransform &deviceTransform) const; - virtual QList estimateItems(const QRectF &rect, - Qt::SortOrder order, const QTransform &deviceTransform) const = 0; + virtual QList estimateItems(const QPointF &point, Qt::SortOrder order) const; + virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order) const = 0; + virtual QList estimateTopLevelItems(const QRectF &, Qt::SortOrder order) const; protected Q_SLOTS: virtual void updateSceneRect(const QRectF &rect); @@ -154,7 +153,8 @@ inline void QGraphicsSceneIndexPrivate::items_helper(const QRectF &rect, QGraphi QList *items, const QTransform &viewTransform, Qt::ItemSelectionMode mode, Qt::SortOrder order) const { - const QList tli = scene->d_func()->topLevelItemsInStackingOrder(&viewTransform, rect); + Q_Q(const QGraphicsSceneIndex); + const QList tli = q->estimateTopLevelItems(rect, Qt::DescendingOrder); const QTransform identity; for (int i = 0; i < tli.size(); ++i) recursive_items_helper(tli.at(i), rect, intersector, items, identity, viewTransform, mode, order); diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex.cpp b/src/gui/graphicsview/qgraphicsscenelinearindex.cpp index bc401f2..5e6ac30 100644 --- a/src/gui/graphicsview/qgraphicsscenelinearindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenelinearindex.cpp @@ -30,13 +30,10 @@ /*! - \fn virtual QList QGraphicsSceneLinearIndex::estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const; + \fn virtual QList QGraphicsSceneLinearIndex::estimateItems(const QRectF &rect, Qt::SortOrder order) const; Returns an estimation visible items that are either inside or intersect with the specified \a rect and return a list sorted using \a order. - - \a deviceTransform is the transformation apply to the view. - */ /*! diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h index 9463487..56dde3a 100644 --- a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h @@ -79,11 +79,10 @@ public: QList items(Qt::SortOrder order = Qt::AscendingOrder) const { Q_UNUSED(order); return m_items; } - virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const + virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order) const { Q_UNUSED(rect); Q_UNUSED(order); - Q_UNUSED(deviceTransform); return m_items; } -- cgit v0.12 From 9c64e8f7a5e19e241deaa7e426534dc6761a6890 Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Thu, 2 Jul 2009 11:47:10 -0700 Subject: Better debug output for QDirectFBPaintEngine Add unsupportedCompositionMode to the output. Reviewed-by: TrustMe --- src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp index e4ce230..df341fb 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp @@ -81,7 +81,7 @@ template <> inline const bool* ptr(const bool &) { return 0; } template static void rasterFallbackWarn(const char *msg, const char *func, const device *dev, int scale, bool matrixRotShear, bool simplePen, - bool dfbHandledClip, + bool dfbHandledClip, bool unsupportedCompositionMode, const char *nameOne, const T1 &one, const char *nameTwo, const T2 &two, const char *nameThree, const T3 &three) @@ -98,7 +98,8 @@ static void rasterFallbackWarn(const char *msg, const char *func, const device * dbg << "scale" << scale << "matrixRotShear" << matrixRotShear << "simplePen" << simplePen - << "dfbHandledClip" << dfbHandledClip; + << "dfbHandledClip" << dfbHandledClip + << "unsupportedCompositionMode" << unsupportedCompositionMode; const T1 *t1 = ptr(one); const T2 *t2 = ptr(two); @@ -124,6 +125,7 @@ static void rasterFallbackWarn(const char *msg, const char *func, const device * __FUNCTION__, state()->painter->device(), \ d_func()->scale, d_func()->matrixRotShear, \ d_func()->simplePen, d_func()->dfbCanHandleClip(), \ + d_func()->unsupportedCompositionMode, \ #one, one, #two, two, #three, three); \ if (op & (QT_DIRECTFB_DISABLE_RASTERFALLBACKS)) \ return; @@ -138,6 +140,7 @@ static void rasterFallbackWarn(const char *msg, const char *func, const device * __FUNCTION__, state()->painter->device(), \ d_func()->scale, d_func()->matrixRotShear, \ d_func()->simplePen, d_func()->dfbCanHandleClip(), \ + d_func()->unsupportedCompositionMode, \ #one, one, #two, two, #three, three); #else #define RASTERFALLBACK(op, one, two, three) -- cgit v0.12 From b0f18119b4559a2b425222c2d63671422c014783 Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Thu, 2 Jul 2009 18:25:03 -0700 Subject: QDirectFBPaintEngine return if destRect is null Reviewed-by: Donald --- src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp index df341fb..947cc76 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp @@ -1062,6 +1062,8 @@ void QDirectFBPaintEnginePrivate::blit(const QRectF &dest, IDirectFBSurface *s, { const QRect sr = src.toRect(); const QRect dr = transform.mapRect(dest).toRect(); + if (dr.isEmpty()) + return; const DFBRectangle sRect = { sr.x(), sr.y(), sr.width(), sr.height() }; DFBResult result; -- cgit v0.12 From 5b701c1bbbbf4993117bd0311717b73fafae02fd Mon Sep 17 00:00:00 2001 From: Bill King Date: Fri, 3 Jul 2009 13:08:17 +1000 Subject: Fixes invalid length for numeric fields in oracle. When the precisionpolicy is high, and the field is numeric, it was getting confused as a string field and pulling the wrong length value. --- src/sql/drivers/oci/qsql_oci.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sql/drivers/oci/qsql_oci.cpp b/src/sql/drivers/oci/qsql_oci.cpp index 8d34dd8..1ffd999 100644 --- a/src/sql/drivers/oci/qsql_oci.cpp +++ b/src/sql/drivers/oci/qsql_oci.cpp @@ -611,7 +611,7 @@ static QSqlField qFromOraInf(const OraFieldInfo &ofi) QSqlField f(ofi.name, ofi.type); f.setRequired(ofi.oraIsNull == 0); - if (ofi.type == QVariant::String) + if (ofi.type == QVariant::String && ofi.oraType != SQLT_NUM && ofi.oraType != SQLT_VNU) f.setLength(ofi.oraFieldLength); else f.setLength(ofi.oraPrecision == 0 ? 38 : int(ofi.oraPrecision)); -- cgit v0.12 From e0912dad8095adb8da4bd27128a5baacfda59eb5 Mon Sep 17 00:00:00 2001 From: Bill King Date: Fri, 3 Jul 2009 15:31:54 +1000 Subject: Fixes ::record for dialect 3 named tables in interbase/firebird. The comparison was mistakenly only uppercasing one side, so mixed case table names were reporting back as if they weren't found for both QSqlDatabase::record() and QSqlDatabase::primaryIndex() --- src/sql/drivers/ibase/qsql_ibase.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sql/drivers/ibase/qsql_ibase.cpp b/src/sql/drivers/ibase/qsql_ibase.cpp index 0033418..5e94c81 100644 --- a/src/sql/drivers/ibase/qsql_ibase.cpp +++ b/src/sql/drivers/ibase/qsql_ibase.cpp @@ -1583,7 +1583,7 @@ QSqlRecord QIBaseDriver::record(const QString& tablename) const "b.RDB$FIELD_SCALE, b.RDB$FIELD_PRECISION, a.RDB$NULL_FLAG " "FROM RDB$RELATION_FIELDS a, RDB$FIELDS b " "WHERE b.RDB$FIELD_NAME = a.RDB$FIELD_SOURCE " - "AND a.RDB$RELATION_NAME = '") + tablename.toUpper() + QLatin1String("' " + "AND UPPER(a.RDB$RELATION_NAME) = '") + tablename.toUpper() + QLatin1String("' " "ORDER BY a.RDB$FIELD_POSITION")); while (q.next()) { @@ -1616,7 +1616,7 @@ QSqlIndex QIBaseDriver::primaryIndex(const QString &table) const q.exec(QLatin1String("SELECT a.RDB$INDEX_NAME, b.RDB$FIELD_NAME, d.RDB$FIELD_TYPE, d.RDB$FIELD_SCALE " "FROM RDB$RELATION_CONSTRAINTS a, RDB$INDEX_SEGMENTS b, RDB$RELATION_FIELDS c, RDB$FIELDS d " "WHERE a.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY' " - "AND a.RDB$RELATION_NAME = '") + table.toUpper() + + "AND UPPER(a.RDB$RELATION_NAME) = '") + table.toUpper() + QLatin1String(" 'AND a.RDB$INDEX_NAME = b.RDB$INDEX_NAME " "AND c.RDB$RELATION_NAME = a.RDB$RELATION_NAME " "AND c.RDB$FIELD_NAME = b.RDB$FIELD_NAME " -- cgit v0.12 From 238c5e3025d8f48dd73f1c4060d08701444eac0d Mon Sep 17 00:00:00 2001 From: Bill King Date: Fri, 3 Jul 2009 15:34:44 +1000 Subject: Fix up two more qsqldatabase autotests. --- tests/auto/qsqldatabase/tst_qsqldatabase.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/auto/qsqldatabase/tst_qsqldatabase.cpp b/tests/auto/qsqldatabase/tst_qsqldatabase.cpp index 28a2191..21064c3 100644 --- a/tests/auto/qsqldatabase/tst_qsqldatabase.cpp +++ b/tests/auto/qsqldatabase/tst_qsqldatabase.cpp @@ -188,7 +188,7 @@ private slots: void oci_fieldLength_data() { generic_data("QOCI"); } void oci_fieldLength(); - void sqlite_bindAndFetchUInt_data() { generic_data("QSQLITE3"); } + void sqlite_bindAndFetchUInt_data() { generic_data("QSQLITE"); } void sqlite_bindAndFetchUInt(); void sqlStatementUseIsNull_189093_data() { generic_data(); } @@ -1526,6 +1526,7 @@ void tst_QSqlDatabase::psql_escapedIdentifiers() QString field1Name = QString("fIeLdNaMe"); QString field2Name = QString("ZuLu"); + q.exec(QString("DROP SCHEMA \"%1\" CASCADE").arg(schemaName)); QString createSchema = QString("CREATE SCHEMA \"%1\"").arg(schemaName); QVERIFY_SQL(q, exec(createSchema)); QString createTable = QString("CREATE TABLE \"%1\".\"%2\" (\"%3\" int PRIMARY KEY, \"%4\" varchar(20))").arg(schemaName).arg(tableName).arg(field1Name).arg(field2Name); @@ -1681,6 +1682,8 @@ void tst_QSqlDatabase::precisionPolicy() q.setNumericalPrecisionPolicy(QSql::LowPrecisionInt32); QVERIFY_SQL(q, exec(query)); + if(db.driverName().startsWith("QOCI")) + QEXPECT_FAIL("", "Oracle fails to move to next when data columns are oversize", Abort); QVERIFY_SQL(q, next()); QCOMPARE(q.value(0).type(), QVariant::Invalid); } @@ -2262,6 +2265,10 @@ void tst_QSqlDatabase::sqlite_bindAndFetchUInt() QFETCH(QString, dbName); QSqlDatabase db = QSqlDatabase::database(dbName); CHECK_DATABASE(db); + if (db.driverName().startsWith("QSQLITE2")) { + QSKIP("SQLite3 specific test", SkipSingle); + return; + } QSqlQuery q(db); QString tableName = qTableName("uint_test"); -- cgit v0.12 From 012d133b2093e0949872263297c23277d0ce30d9 Mon Sep 17 00:00:00 2001 From: Rohan McGovern Date: Fri, 3 Jul 2009 16:47:56 +1000 Subject: Fixed dead code possibly leading to crash. Looks like this `&&' was meant to be `||'. QNetworkProxy::FtpCachingProxy is 5 so it's clearly impossible for type to be less than 0 and greater than QNetworkProxy::FtpCachingProxy. Reviewed-by: Aaron Kennedy --- src/network/kernel/qnetworkproxy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/kernel/qnetworkproxy.cpp b/src/network/kernel/qnetworkproxy.cpp index c2743ef..103b948 100644 --- a/src/network/kernel/qnetworkproxy.cpp +++ b/src/network/kernel/qnetworkproxy.cpp @@ -366,7 +366,7 @@ static QNetworkProxy::Capabilities defaultCapabilitiesForType(QNetworkProxy::Pro int(QNetworkProxy::HostNameLookupCapability)), }; - if (int(type) < 0 && int(type) > int(QNetworkProxy::FtpCachingProxy)) + if (int(type) < 0 || int(type) > int(QNetworkProxy::FtpCachingProxy)) type = QNetworkProxy::DefaultProxy; return QNetworkProxy::Capabilities(defaults[int(type)]); } -- cgit v0.12 From 17f814ce07a4d82563012a15a46dfe6acb2edcc5 Mon Sep 17 00:00:00 2001 From: Harald Fernengel Date: Fri, 3 Jul 2009 09:41:00 +0200 Subject: Add a specialization for QByteArray It tries to keep the semantics of QString::append(QByteArray) as much as possible. --- src/corelib/tools/qstringbuilder.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h index 4d6b64b..127c183 100644 --- a/src/corelib/tools/qstringbuilder.h +++ b/src/corelib/tools/qstringbuilder.h @@ -202,6 +202,18 @@ template <> struct QConcatenable *out++ = QLatin1Char(*a++); } }; + +template <> struct QConcatenable +{ + typedef QByteArray type; + static int size(const QByteArray &ba) { qstrnlen(ba.constData(), ba.size()); } + static inline void appendTo(const QByteArray &ba, QChar *&out) + { + const char *data = ba.constData(); + while (*data) + *out++ = *data++; + } +}; #endif template -- cgit v0.12 From 8a0b05f71d2a9481a21143d1b87e2b18d427d1d5 Mon Sep 17 00:00:00 2001 From: Harald Fernengel Date: Fri, 3 Jul 2009 10:08:52 +0200 Subject: fix the test _and_ the class :) --- src/corelib/tools/qstringbuilder.h | 2 +- tests/auto/qstringbuilder/tst_qstringbuilder.cpp | 17 ++++++----------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h index 127c183..97f13ee 100644 --- a/src/corelib/tools/qstringbuilder.h +++ b/src/corelib/tools/qstringbuilder.h @@ -206,7 +206,7 @@ template <> struct QConcatenable template <> struct QConcatenable { typedef QByteArray type; - static int size(const QByteArray &ba) { qstrnlen(ba.constData(), ba.size()); } + static int size(const QByteArray &ba) { return qstrnlen(ba.constData(), ba.size()); } static inline void appendTo(const QByteArray &ba, QChar *&out) { const char *data = ba.constData(); diff --git a/tests/auto/qstringbuilder/tst_qstringbuilder.cpp b/tests/auto/qstringbuilder/tst_qstringbuilder.cpp index fdbaf21..72889bc 100644 --- a/tests/auto/qstringbuilder/tst_qstringbuilder.cpp +++ b/tests/auto/qstringbuilder/tst_qstringbuilder.cpp @@ -85,28 +85,18 @@ #undef QT_NO_CAST_TO_ASCII #endif - #include //TESTED_CLASS=QStringBuilder //TESTED_FILES=qstringbuilder.cpp -#include - #define LITERAL "some literal" class tst_QStringBuilder : public QObject { Q_OBJECT -public: - tst_QStringBuilder() {} - ~tst_QStringBuilder() {} - -public slots: - void init() {} - void cleanup() {} - +private slots: void scenario(); }; @@ -119,6 +109,7 @@ void tst_QStringBuilder::scenario() QLatin1Char achar('c'); QString r2(QLatin1String(LITERAL LITERAL)); QString r; + QByteArray ba(LITERAL); r = l1literal P l1literal; QCOMPARE(r, r2); @@ -139,6 +130,10 @@ void tst_QStringBuilder::scenario() QCOMPARE(r, r2); r = LITERAL P string; QCOMPARE(r, r2); + r = ba P string; + QCOMPARE(r, r2); + r = string P ba; + QCOMPARE(r, r2); #endif } -- cgit v0.12 From d228015c67614051df8ae0b2f0483572fd667b83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 3 Jul 2009 17:38:38 +0200 Subject: Simplify QGraphicsScenePrivate::processDirtyItemsRecursive. This version is easier to read and is slightly faster than the old one. All auto-tests pass. --- src/gui/graphicsview/qgraphicsscene.cpp | 135 +++++++++++++++++--------------- src/gui/graphicsview/qgraphicsscene_p.h | 8 +- 2 files changed, 81 insertions(+), 62 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 85d05e9..bae1afd 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -414,9 +414,22 @@ void QGraphicsScenePrivate::_q_processDirtyItems() { processDirtyItemsEmitted = false; + if (updateAll) { + Q_ASSERT(calledEmitUpdated); + // No need for further processing (except resetting the dirty states). + // The growingItemsBoundingRect is updated in _q_emitUpdated. + for (int i = 0; i < topLevelItems.size(); ++i) + resetDirtyItem(topLevelItems.at(i), /*recursive=*/true); + return; + } + const bool wasPendingSceneUpdate = calledEmitUpdated; const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect; - processDirtyItemsRecursive(0); + + // Process items recursively. + for (int i = 0; i < topLevelItems.size(); ++i) + processDirtyItemsRecursive(topLevelItems.at(i)); + dirtyGrowingItemsBoundingRect = false; if (!hasSceneRect && oldGrowingItemsBoundingRect != growingItemsBoundingRect) emit q_func()->sceneRectChanged(growingItemsBoundingRect); @@ -4416,48 +4429,67 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool qreal parentOpacity) { Q_Q(QGraphicsScene); + Q_ASSERT(item); + Q_ASSERT(!updateAll); - bool wasDirtyParentViewBoundingRects = false; - bool wasDirtyParentSceneTransform = false; - qreal opacity = parentOpacity; + if (!item->d_ptr->dirty && !item->d_ptr->dirtyChildren) { + resetDirtyItem(item); + return; + } - if (item) { - wasDirtyParentViewBoundingRects = item->d_ptr->paintedViewBoundingRectsNeedRepaint; - opacity = item->d_ptr->combineOpacityFromParent(parentOpacity); - const bool itemIsHidden = !item->d_ptr->ignoreVisible && !item->d_ptr->visible; - const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity && opacity == 0.0; - - if (item->d_ptr->dirtySceneTransform && !itemIsHidden && !item->d_ptr->itemIsUntransformable() - && !(itemIsFullyTransparent && item->d_ptr->childrenCombineOpacity())) { - // Calculate the full scene transform for this item. - item->d_ptr->sceneTransform = item->d_ptr->parent ? item->d_ptr->parent->d_ptr->sceneTransform - : QTransform(); - item->d_ptr->combineTransformFromParent(&item->d_ptr->sceneTransform); - item->d_ptr->dirtySceneTransform = 0; - wasDirtyParentSceneTransform = true; - } + const bool itemIsHidden = !item->d_ptr->ignoreVisible && !item->d_ptr->visible; + if (itemIsHidden) { + resetDirtyItem(item, /*recursive=*/true); + return; + } - if (itemIsHidden || itemIsFullyTransparent || (item->d_ptr->flags & QGraphicsItem::ItemHasNoContents)) { - // Make sure we don't process invisible items or items with no content. - item->d_ptr->dirty = 0; + const bool itemHasContents = !(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents); + const bool itemHasChildren = !item->d_ptr->children.isEmpty(); + if (!itemHasContents && !itemHasChildren) { + resetDirtyItem(item); + return; // Item has neither contents nor children!(?) + } + + const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity); + const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity && opacity < 0.0001; + if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) { + resetDirtyItem(item, /*recursive=*/itemHasChildren); + return; + } + + bool wasDirtyParentSceneTransform = item->d_ptr->dirtySceneTransform; + const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable(); + if (wasDirtyParentSceneTransform && !itemIsUntransformable) { + // Calculate the full scene transform for this item. + item->d_ptr->sceneTransform = item->d_ptr->parent ? item->d_ptr->parent->d_ptr->sceneTransform + : QTransform(); + item->d_ptr->combineTransformFromParent(&item->d_ptr->sceneTransform); + item->d_ptr->dirtySceneTransform = 0; + } + + const bool wasDirtyParentViewBoundingRects = item->d_ptr->paintedViewBoundingRectsNeedRepaint; + if (itemIsFullyTransparent || !itemHasContents || dirtyAncestorContainsChildren) { + // Make sure we don't process invisible items or items with no content. + item->d_ptr->dirty = 0; + item->d_ptr->fullUpdatePending = 0; + // Might have a dirty view bounding rect otherwise. + if (itemIsFullyTransparent || !itemHasContents) item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0; - } + } - if (item->d_ptr->geometryChanged) { - // Update growingItemsBoundingRect. - if (!hasSceneRect && !itemIsHidden) - growingItemsBoundingRect |= item->d_ptr->sceneTransform.mapRect(item->boundingRect()); - item->d_ptr->geometryChanged = 0; - } + if (item->d_ptr->geometryChanged) { + // Update growingItemsBoundingRect. + if (!hasSceneRect) + growingItemsBoundingRect |= item->d_ptr->sceneTransform.mapRect(item->boundingRect()); + item->d_ptr->geometryChanged = 0; } // Process item. - if (item && (item->d_ptr->dirty || item->d_ptr->paintedViewBoundingRectsNeedRepaint)) { + if (item->d_ptr->dirty || item->d_ptr->paintedViewBoundingRectsNeedRepaint) { const bool useCompatUpdate = views.isEmpty() || (connectedSignals & changedSignalMask); - const bool untransformableItem = item->d_ptr->itemIsUntransformable(); const QRectF itemBoundingRect = adjustedItemBoundingRect(item); - if (useCompatUpdate && !untransformableItem && qFuzzyIsNull(item->boundingRegionGranularity())) { + if (useCompatUpdate && !itemIsUntransformable && qFuzzyIsNull(item->boundingRegionGranularity())) { // This block of code is kept for compatibility. Since 4.5, by default // QGraphicsView does not connect the signal and we use the below // method of delivering updates. @@ -4484,7 +4516,6 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool QRect &paintedViewBoundingRect = item->d_ptr->paintedViewBoundingRects[viewPrivate->viewport]; if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) { - wasDirtyParentViewBoundingRects = true; paintedViewBoundingRect.translate(viewPrivate->dirtyScrollOffset); if (!viewPrivate->updateRect(paintedViewBoundingRect)) paintedViewBoundingRect = QRect(); @@ -4506,7 +4537,7 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool continue; // Discard updates outside the bounding rect. bool valid = false; - if (untransformableItem) { + if (itemIsUntransformable) { valid = updateHelper(viewPrivate, item->d_ptr, dirtyRect, item->deviceTransform(view->viewportTransform())); } else if (!view->isTransformed()) { @@ -4522,18 +4553,17 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool } } - // Process root items / children. - if (!item || item->d_ptr->dirtyChildren) { - QList *children = item ? &item->d_ptr->children : &topLevelItems; - const bool allChildrenDirty = item && item->d_ptr->allChildrenDirty; + // Process children. + if (itemHasChildren && item->d_ptr->dirtyChildren) { if (!dirtyAncestorContainsChildren) { - dirtyAncestorContainsChildren = item && item->d_ptr->fullUpdatePending + dirtyAncestorContainsChildren = item->d_ptr->fullUpdatePending && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape); } - const bool parentIgnoresVisible = item && item->d_ptr->ignoreVisible; - const bool parentIgnoresOpacity = item && item->d_ptr->ignoreOpacity; - for (int i = 0; i < children->size(); ++i) { - QGraphicsItem *child = children->at(i); + const bool allChildrenDirty = item->d_ptr->allChildrenDirty; + const bool parentIgnoresVisible = item->d_ptr->ignoreVisible; + const bool parentIgnoresOpacity = item->d_ptr->ignoreOpacity; + for (int i = 0; i < item->d_ptr->children.size(); ++i) { + QGraphicsItem *child = item->d_ptr->children.at(i); if (wasDirtyParentSceneTransform) child->d_ptr->dirtySceneTransform = 1; if (wasDirtyParentViewBoundingRects) @@ -4542,36 +4572,19 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool child->d_ptr->ignoreVisible = 1; if (parentIgnoresOpacity) child->d_ptr->ignoreOpacity = 1; - if (allChildrenDirty) { child->d_ptr->dirty = 1; child->d_ptr->fullUpdatePending = 1; child->d_ptr->dirtyChildren = 1; child->d_ptr->allChildrenDirty = 1; - } else if (!child->d_ptr->dirty && !child->d_ptr->dirtyChildren) { - resetDirtyItem(child); - continue; } - - if (dirtyAncestorContainsChildren || updateAll) { - // No need to process this child's dirty rect, hence reset the dirty state. - // However, we have to continue the recursion because it might have a dirty - // view bounding rect that needs repaint. We also have to reset the dirty - // state of its descendants. - child->d_ptr->dirty = 0; - child->d_ptr->fullUpdatePending = 0; - if (updateAll) - child->d_ptr->paintedViewBoundingRectsNeedRepaint = 0; - } - processDirtyItemsRecursive(child, dirtyAncestorContainsChildren, opacity); } } else if (wasDirtyParentSceneTransform) { item->d_ptr->invalidateChildrenSceneTransform(); } - if (item) - resetDirtyItem(item); + resetDirtyItem(item); } /*! diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 245380f..bd72a71 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -207,18 +207,24 @@ public: void processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren = false, qreal parentOpacity = qreal(1.0)); - inline void resetDirtyItem(QGraphicsItem *item) + inline void resetDirtyItem(QGraphicsItem *item, bool recursive = false) { Q_ASSERT(item); item->d_ptr->dirty = 0; item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0; item->d_ptr->geometryChanged = 0; + if (!item->d_ptr->dirtyChildren) + recursive = false; item->d_ptr->dirtyChildren = 0; item->d_ptr->needsRepaint = QRectF(); item->d_ptr->allChildrenDirty = 0; item->d_ptr->fullUpdatePending = 0; item->d_ptr->ignoreVisible = 0; item->d_ptr->ignoreOpacity = 0; + if (recursive) { + for (int i = 0; i < item->d_ptr->children.size(); ++i) + resetDirtyItem(item->d_ptr->children.at(i), recursive); + } } inline void ensureSortedTopLevelItems() -- cgit v0.12 From 8fa9744b1b18f97b98fc434b8b8057434118e3db Mon Sep 17 00:00:00 2001 From: Bill King Date: Mon, 6 Jul 2009 12:30:32 +1000 Subject: Fix precision autotest for SqlServer Sql Server can't count. Reduce the expected length of string when we're on sql server. --- tests/auto/q3sqlcursor/tst_q3sqlcursor.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tests/auto/q3sqlcursor/tst_q3sqlcursor.cpp b/tests/auto/q3sqlcursor/tst_q3sqlcursor.cpp index 91533dd..812c862 100644 --- a/tests/auto/q3sqlcursor/tst_q3sqlcursor.cpp +++ b/tests/auto/q3sqlcursor/tst_q3sqlcursor.cpp @@ -155,11 +155,9 @@ void tst_Q3SqlCursor::createTestTables( QSqlDatabase db ) } if (tst_Databases::isMSAccess(db)) { - QVERIFY_SQL(q, exec("create table " + qTableName("qtest_precision") + " (col1 number)")); - } else if (db.driverName().startsWith("QIBASE")) { - QVERIFY_SQL(q, exec("create table " + qTableName("qtest_precision") + " (col1 numeric(15, 14))")); + QVERIFY_SQL(q, exec("create table " + qTableName("qtest_precision") + " (col1 number)")); } else { - QVERIFY_SQL(q, exec("create table " + qTableName("qtest_precision") + " (col1 numeric(15, 14))")); + QVERIFY_SQL(q, exec("create table " + qTableName("qtest_precision") + " (col1 numeric(15, 14))")); } } @@ -555,7 +553,7 @@ void tst_Q3SqlCursor::unicode() void tst_Q3SqlCursor::precision() { - static const QString precStr = "1.23456789012345"; + static const QString precStr = QLatin1String("1.23456789012345"); static const double precDbl = 2.23456789012345; QFETCH( QString, dbName ); @@ -574,7 +572,10 @@ void tst_Q3SqlCursor::precision() QVERIFY_SQL(cur, select()); QVERIFY( cur.next() ); - QCOMPARE( cur.value( 0 ).asString(), QString( precStr ) ); + if(!tst_Databases::isSqlServer(db)) + QCOMPARE( cur.value( 0 ).asString(), precStr ); + else + QCOMPARE( cur.value( 0 ).asString(), precStr.left(precStr.size()-1) ); QVERIFY( cur.next() ); QCOMPARE( cur.value( 0 ).asDouble(), precDbl ); } -- cgit v0.12 From 8915977e56b58c4631dfb2b8616585b664e55f38 Mon Sep 17 00:00:00 2001 From: Bill King Date: Mon, 6 Jul 2009 15:57:41 +1000 Subject: Fix more sql autotest failures. Sql server fails at numeric field calculations. (Confirmed by running against MySql via odbc). Also, quote fields properly. The drivers know how to do it correctly, so let them handle it. --- tests/auto/q3sqlcursor/tst_q3sqlcursor.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/auto/q3sqlcursor/tst_q3sqlcursor.cpp b/tests/auto/q3sqlcursor/tst_q3sqlcursor.cpp index 812c862..360c3b7 100644 --- a/tests/auto/q3sqlcursor/tst_q3sqlcursor.cpp +++ b/tests/auto/q3sqlcursor/tst_q3sqlcursor.cpp @@ -575,7 +575,7 @@ void tst_Q3SqlCursor::precision() if(!tst_Databases::isSqlServer(db)) QCOMPARE( cur.value( 0 ).asString(), precStr ); else - QCOMPARE( cur.value( 0 ).asString(), precStr.left(precStr.size()-1) ); + QCOMPARE( cur.value( 0 ).asString(), precStr.left(precStr.size()-1) ); // Sql server fails at counting. QVERIFY( cur.next() ); QCOMPARE( cur.value( 0 ).asDouble(), precDbl ); } @@ -759,8 +759,9 @@ void tst_Q3SqlCursor::insertFieldNameContainsWS() { QSqlQuery q(db); q.exec(QString("DROP TABLE %1").arg(tableName)); - QString query = QString("CREATE TABLE %1 (id int, \"first Name\" varchar(20), " - "lastName varchar(20))"); + QString query = "CREATE TABLE %1 (id int, " + + db.driver()->escapeIdentifier("first Name", QSqlDriver::FieldName) + + " varchar(20), lastName varchar(20))"; QVERIFY_SQL(q, exec(query.arg(tableName))); Q3SqlCursor cur(QString("%1").arg(tableName), true, db); -- cgit v0.12 From bf5112c6673d32cbaad33c388d38690264adf107 Mon Sep 17 00:00:00 2001 From: ck Date: Mon, 6 Jul 2009 10:20:02 +0200 Subject: Fixed race condition in search module. Task-number: 257441 Reviewed-by: kh --- tools/assistant/lib/qhelpsearchengine.cpp | 10 ++++------ .../lib/qhelpsearchindexreader_clucene.cpp | 21 +++++++++++++++------ .../lib/qhelpsearchindexreader_clucene_p.h | 5 ++--- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/tools/assistant/lib/qhelpsearchengine.cpp b/tools/assistant/lib/qhelpsearchengine.cpp index 9faafe0..15f7f9e 100644 --- a/tools/assistant/lib/qhelpsearchengine.cpp +++ b/tools/assistant/lib/qhelpsearchengine.cpp @@ -96,6 +96,7 @@ private: delete indexWriter; } + int hitsCount() const { int count = 0; @@ -107,12 +108,9 @@ private: QList hits(int start, int end) const { - QList returnValue; - if (indexReader) { - for (int i = start; i < end && i < hitsCount(); ++i) - returnValue.append(indexReader->hit(i)); - } - return returnValue; + return indexReader ? + indexReader->hits(start, end) : + QList(); } void updateIndex(bool reindex = false) diff --git a/tools/assistant/lib/qhelpsearchindexreader_clucene.cpp b/tools/assistant/lib/qhelpsearchindexreader_clucene.cpp index 227e558..867e060 100644 --- a/tools/assistant/lib/qhelpsearchindexreader_clucene.cpp +++ b/tools/assistant/lib/qhelpsearchindexreader_clucene.cpp @@ -86,8 +86,8 @@ void QHelpSearchIndexReader::cancelSearching() void QHelpSearchIndexReader::search(const QString &collectionFile, const QString &indexFilesFolder, const QList &queryList) { - QMutexLocker lock(&mutex); - + wait(); + this->hitList.clear(); this->m_cancel = false; this->m_query = queryList; @@ -99,12 +99,18 @@ void QHelpSearchIndexReader::search(const QString &collectionFile, const QString int QHelpSearchIndexReader::hitsCount() const { + QMutexLocker lock(&mutex); return hitList.count(); } -QHelpSearchEngine::SearchHit QHelpSearchIndexReader::hit(int index) const +QList QHelpSearchIndexReader::hits(int start, + int end) const { - return hitList.at(index); + QList hits; + QMutexLocker lock(&mutex); + for (int i = start; i < end && i < hitList.count(); ++i) + hits.append(hitList.at(i)); + return hits; } void QHelpSearchIndexReader::run() @@ -135,7 +141,7 @@ void QHelpSearchIndexReader::run() if(QCLuceneIndexReader::indexExists(indexPath)) { mutex.lock(); if (m_cancel) { - mutex.unlock(); + mutex.unlock(); return; } mutex.unlock(); @@ -213,7 +219,9 @@ void QHelpSearchIndexReader::run() #if !defined(QT_NO_EXCEPTIONS) } catch(...) { + mutex.lock(); hitList.clear(); + mutex.unlock(); emit searchingFinished(0); } #endif @@ -416,8 +424,9 @@ void QHelpSearchIndexReader::boostSearchHits(const QHelpEngineCore &engine, boostedList.append(it.value()); } while (it != hitMap.constBegin()); boostedList += hitList.mid(count, hitList.count()); - + mutex.lock(); hitList = boostedList; + mutex.unlock(); } } diff --git a/tools/assistant/lib/qhelpsearchindexreader_clucene_p.h b/tools/assistant/lib/qhelpsearchindexreader_clucene_p.h index 47af43f..e7ac0eb 100644 --- a/tools/assistant/lib/qhelpsearchindexreader_clucene_p.h +++ b/tools/assistant/lib/qhelpsearchindexreader_clucene_p.h @@ -85,9 +85,8 @@ public: void search(const QString &collectionFile, const QString &indexFilesFolder, const QList &queryList); - int hitsCount() const; - QHelpSearchEngine::SearchHit hit(int index) const; + QList hits(int start, int end) const; signals: void searchingStarted(); @@ -105,7 +104,7 @@ private: const QList &queryList); private: - QMutex mutex; + mutable QMutex mutex; QList hitList; QWaitCondition waitCondition; -- cgit v0.12 From 18a717b3f2e6a19a5ad631b68b26d09ba934bece Mon Sep 17 00:00:00 2001 From: ck Date: Mon, 6 Jul 2009 10:24:37 +0200 Subject: Removed superfluous code in assistant's search module. Reviewed-by: kh --- tools/assistant/lib/qhelpsearchengine.cpp | 19 ++++++------------- .../assistant/lib/qhelpsearchindexreader_clucene.cpp | 1 - .../assistant/lib/qhelpsearchindexreader_clucene_p.h | 2 -- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/tools/assistant/lib/qhelpsearchengine.cpp b/tools/assistant/lib/qhelpsearchengine.cpp index 15f7f9e..2a41d04 100644 --- a/tools/assistant/lib/qhelpsearchengine.cpp +++ b/tools/assistant/lib/qhelpsearchengine.cpp @@ -84,14 +84,12 @@ private: , resultWidget(0) , helpEngine(helpEngine) { - hitList.clear(); indexReader = 0; indexWriter = 0; } ~QHelpSearchEnginePrivate() { - hitList.clear(); delete indexReader; delete indexWriter; } @@ -129,11 +127,9 @@ private: connect(indexWriter, SIGNAL(indexingFinished()), this, SLOT(optimizeIndex())); } - if (indexWriter) { - indexWriter->cancelIndexing(); - indexWriter->updateIndex(helpEngine->collectionFile(), - indexFilesFolder(), reindex); - } + indexWriter->cancelIndexing(); + indexWriter->updateIndex(helpEngine->collectionFile(), + indexFilesFolder(), reindex); } void cancelIndexing() @@ -157,11 +153,9 @@ private: connect(indexReader, SIGNAL(searchingFinished(int)), this, SIGNAL(searchingFinished(int))); } - if (indexReader) { - m_queryList = queryList; - indexReader->cancelSearching(); - indexReader->search(helpEngine->collectionFile(), indexFilesFolder(), queryList); - } + m_queryList = queryList; + indexReader->cancelSearching(); + indexReader->search(helpEngine->collectionFile(), indexFilesFolder(), queryList); } void cancelSearching() @@ -202,7 +196,6 @@ private: QHelpSearchIndexWriter *indexWriter; QPointer helpEngine; - QList hitList; QList m_queryList; }; diff --git a/tools/assistant/lib/qhelpsearchindexreader_clucene.cpp b/tools/assistant/lib/qhelpsearchindexreader_clucene.cpp index 867e060..89d6040 100644 --- a/tools/assistant/lib/qhelpsearchindexreader_clucene.cpp +++ b/tools/assistant/lib/qhelpsearchindexreader_clucene.cpp @@ -70,7 +70,6 @@ QHelpSearchIndexReader::~QHelpSearchIndexReader() { mutex.lock(); this->m_cancel = true; - waitCondition.wakeOne(); mutex.unlock(); wait(); diff --git a/tools/assistant/lib/qhelpsearchindexreader_clucene_p.h b/tools/assistant/lib/qhelpsearchindexreader_clucene_p.h index e7ac0eb..8876d80 100644 --- a/tools/assistant/lib/qhelpsearchindexreader_clucene_p.h +++ b/tools/assistant/lib/qhelpsearchindexreader_clucene_p.h @@ -106,8 +106,6 @@ private: private: mutable QMutex mutex; QList hitList; - QWaitCondition waitCondition; - bool m_cancel; QString m_collectionFile; QList m_query; -- cgit v0.12 From fd181167709283a2ceefa5285d6189fa7de23bb6 Mon Sep 17 00:00:00 2001 From: Norwegian Rock Cat Date: Mon, 6 Jul 2009 14:08:41 +0200 Subject: Implement QApplication::setOverrideCursor to use pure Cocoa calls Seems this was a victim of our cursor fixing. Cocoa does a lot for us with setting cursors. This meant that we didn't need to do as much meddling and as a result qt_mac_set_cursor does nothing in Cocoa. Unfortunately, this broke setOverrideCursor. Luckily Cocoa has a stack that works exactly like Qt, so we can just use that. Task-number: 257507 Reviewed-by: Prasanth Ullattil --- src/gui/kernel/qapplication_mac.mm | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm index 5ded153..0d86c8e 100644 --- a/src/gui/kernel/qapplication_mac.mm +++ b/src/gui/kernel/qapplication_mac.mm @@ -1294,8 +1294,13 @@ void QApplication::setOverrideCursor(const QCursor &cursor) { qApp->d_func()->cursor_list.prepend(cursor); +#ifdef QT_MAC_USE_COCOA + QMacCocoaAutoReleasePool pool; + [static_cast(qt_mac_nsCursorForQCursor(cursor)) push]; +#else if (qApp && qApp->activeWindow()) qt_mac_set_cursor(&qApp->d_func()->cursor_list.first(), QCursor::pos()); +#endif } void QApplication::restoreOverrideCursor() @@ -1304,12 +1309,17 @@ void QApplication::restoreOverrideCursor() return; qApp->d_func()->cursor_list.removeFirst(); +#ifdef QT_MAC_USE_COCOA + QMacCocoaAutoReleasePool pool; + [NSCursor pop]; +#else if (qApp && qApp->activeWindow()) { const QCursor def(Qt::ArrowCursor); qt_mac_set_cursor(qApp->d_func()->cursor_list.isEmpty() ? &def : &qApp->d_func()->cursor_list.first(), QCursor::pos()); } -} #endif +} +#endif // QT_NO_CURSOR QWidget *QApplication::topLevelAt(const QPoint &p) { -- cgit v0.12 From e07e95da3d35a2ea1ab2b325df6c91620f948497 Mon Sep 17 00:00:00 2001 From: Norwegian Rock Cat Date: Mon, 6 Jul 2009 15:43:03 +0200 Subject: Fix issue where a mainwindow would show two size grips in Cocoa. OK. this is a bit strange. It seems the topdata->resizer value is used to control whether or not we should show a resize handle based on a count (0 no, non-zero yes). Since we somehow decided that this value will never be larger than 15, we made it 4-bits wide. There's a "Qt/Mac" API, QWidgetPrivate::qt_mac_update_sizer(QWidget *, int = 0) which would adjust this value by the int passed in.. We use that in several places, not excluding the QStatusBar where we would pass 1 if we want to show, and -1 if we didn't. Now if you subtract -1 from zero when you are 4 bits wide, well, bad things happen. Therefore protect that (since if it's at zero we have succeeded, we don't want to show the resizer). This seems to work well. The private API is certainly an interesting way of solving the problem, but is easy to abuse (for example, this code will break if resizer = 1 and we are passed -2 in the function. Task-number: 257485 Reviewed-by: Prasanth Ullattil --- src/gui/kernel/qwidget_mac.mm | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index ec9a049..f96d061 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -1526,12 +1526,16 @@ void QWidgetPrivate::toggleDrawers(bool visible) *****************************************************************************/ bool QWidgetPrivate::qt_mac_update_sizer(QWidget *w, int up) { + // I'm not sure what "up" is if(!w || !w->isWindow()) return false; QTLWExtra *topData = w->d_func()->topData(); QWExtra *extraData = w->d_func()->extraData(); - topData->resizer += up; + // topData->resizer is only 4 bits, so subtracting -1 from zero causes bad stuff + // to happen, prevent that here (you really want the thing hidden). + if (up >= 0 || topData->resizer != 0) + topData->resizer += up; OSWindowRef windowRef = qt_mac_window_for(OSViewRef(w->winId())); { #ifndef QT_MAC_USE_COCOA @@ -1544,7 +1548,6 @@ bool QWidgetPrivate::qt_mac_update_sizer(QWidget *w, int up) bool remove_grip = (topData->resizer || (w->windowFlags() & Qt::FramelessWindowHint) || (extraData->maxw && extraData->maxh && extraData->maxw == extraData->minw && extraData->maxh == extraData->minh)); - #ifndef QT_MAC_USE_COCOA WindowAttributes attr; GetWindowAttributes(windowRef, &attr); -- cgit v0.12 From 1222ea208587ed039e436d58aa6d7ea6ea6c014e Mon Sep 17 00:00:00 2001 From: Ritt Konstantin Date: Mon, 6 Jul 2009 19:29:07 +0200 Subject: Update Russian Qt phrase book Merge-request: 803 Reviewed-by: Oswald Buddenhagen --- tools/linguist/phrasebooks/russian.qph | 52 +++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/tools/linguist/phrasebooks/russian.qph b/tools/linguist/phrasebooks/russian.qph index 629c60b..69af041 100644 --- a/tools/linguist/phrasebooks/russian.qph +++ b/tools/linguist/phrasebooks/russian.qph @@ -10,7 +10,7 @@ accessibility - удобство + специальные возможности action handle @@ -345,8 +345,8 @@ активная зона - icon - пиктограмма + Icon + Значок inactive @@ -402,7 +402,7 @@ list view - древовидный список + список manual link @@ -901,10 +901,6 @@ панель инструментов - tooltip - всплывающая подсказка - - tree view control древовидный список @@ -1054,10 +1050,46 @@ Case Sensitive - Регистрозависимо + Учитывать регистр Whole words - Слова полностью + Слова целиком + + + Find Next + Найти следующее + + + Find Previous + Найти предыдущее + + + Case Sensitive + Учитывать регистр символов + + + Whole words only + Только слова целиком + + + Subwindow + Дочернее окно + + + Next + Далее + + + tree view + древовидный список + + + ToolTip + Подсказка + + + Checkable + Переключаемое -- cgit v0.12 From e1d2dffc8cfe4195210ce435c394d8af9b9823e8 Mon Sep 17 00:00:00 2001 From: Ritt Konstantin Date: Mon, 6 Jul 2009 19:29:08 +0200 Subject: Update Russian translation for Qt libraries. almost done; only few strings left untranslated. Merge-request: 803 Reviewed-by: Oswald Buddenhagen --- translations/qt_ru.ts | 212 +++++++++++++++++++++++++------------------------- 1 file changed, 104 insertions(+), 108 deletions(-) diff --git a/translations/qt_ru.ts b/translations/qt_ru.ts index 1e6a4eb..9529c33 100644 --- a/translations/qt_ru.ts +++ b/translations/qt_ru.ts @@ -57,7 +57,7 @@ Accessibility - Средства для людей с ограниченными возможностями + Специальные возможности @@ -87,7 +87,7 @@ Check your Gstreamer installation and make sure you have libgstreamer-plugins-base installed. Невозможно начать воспроизведение. -Проверьте установку Gstreamer и убедитесь, +Проверьте установку Gstreamer и убедитесь, что пакет libgstreamer-plugins-base установлен. @@ -917,22 +917,22 @@ to QAxSelect - + Select ActiveX Control Выбор компоненты ActiveX - + OK Выбрать - + &Cancel &Отмена - + COM &Object: COM &Объект: @@ -1022,7 +1022,7 @@ to Открыть - + False Нет @@ -1491,32 +1491,32 @@ Please verify the correct file name was given. Показать скр&ытые файлы - - + + Back Назад - - + + Parent Directory Родительский каталог - - + + List View Список - - + + Detail View Подробный вид - - + + Files of type: Типы файлов: @@ -1595,8 +1595,8 @@ Do you want to delete it anyway? Показать - - + + Forward Вперёд @@ -1628,14 +1628,14 @@ Do you want to delete it anyway? &Имя файла: - - + + Look in: Перейти к: - - + + Create New Folder Создать папку @@ -1799,7 +1799,7 @@ Do you want to delete it anyway? Arabic - + Арабская @@ -1809,57 +1809,57 @@ Do you want to delete it anyway? Thaana - + Таана Devanagari - + Деванагири Bengali - + Бенгальская Gurmukhi - + Гурмукхи Gujarati - + Гуджарати Oriya - + Ория Tamil - + Тамильская Telugu - + Телугу Kannada - + Каннада Malayalam - + Малайялам Sinhala - + Сингальская @@ -1869,7 +1869,7 @@ Do you want to delete it anyway? Lao - + Лаосская @@ -1879,7 +1879,7 @@ Do you want to delete it anyway? Myanmar - + Мьянма @@ -1924,7 +1924,7 @@ Do you want to delete it anyway? Ogham - + Огамическая @@ -2210,7 +2210,7 @@ Do you want to delete it anyway? Ошибка записи ответа на устройство - + Connection refused Отказано в соединении @@ -2372,7 +2372,7 @@ Do you want to delete it anyway? QIBaseDriver - + Error opening database Ошибка открытия базы данных @@ -2395,7 +2395,7 @@ Do you want to delete it anyway? QIBaseResult - + Unable to create BLOB Невозможно создать BLOB @@ -2441,7 +2441,7 @@ Do you want to delete it anyway? Невозможно выполнить транзакцию - + Could not allocate statement Не удалось получить ресурсы для создания выражения @@ -2452,12 +2452,12 @@ Do you want to delete it anyway? - + Could not describe input statement Не удалось описать входящее выражение - + Could not describe statement Не удалось описать выражение @@ -3223,7 +3223,7 @@ Do you want to delete it anyway? Ошибка загрузки %1 - ответ сервера: %2 - + Protocol "%1" is unknown Неизвестный протокол "%1" @@ -3231,7 +3231,7 @@ Do you want to delete it anyway? QNetworkReplyImpl - + Operation canceled Операция отменена @@ -3240,7 +3240,7 @@ Do you want to delete it anyway? QOCIDriver - + Unable to logon Невозможно авторизоваться @@ -3269,7 +3269,7 @@ Do you want to delete it anyway? QOCIResult - + Unable to bind column for batch execute @@ -3281,7 +3281,7 @@ Do you want to delete it anyway? Невозможно выполнить пакетное выражение - + Unable to goto next Невозможно перейти к следующей строке @@ -3314,7 +3314,7 @@ Do you want to delete it anyway? QODBCDriver - + Unable to connect Невозможно соединиться @@ -3324,7 +3324,7 @@ Do you want to delete it anyway? Невозможно соединиться - Драйвер не поддерживает требуемый функционал - + Unable to disable autocommit Невозможно отключить автовыполнение транзакции @@ -3347,7 +3347,7 @@ Do you want to delete it anyway? QODBCResult - + QODBCResult::reset: Unable to set 'SQL_CURSOR_STATIC' as statement attribute. Please check your ODBC driver configuration QODBCResult::reset: Невозможно установить 'SQL_CURSOR_STATIC' атрибутом выражение. Проверьте настройки драйвера ODBC @@ -3376,12 +3376,12 @@ Do you want to delete it anyway? - + Unable to fetch last Невозможно получить последнюю строку - + Unable to fetch Невозможно получить данные @@ -3471,7 +3471,7 @@ Do you want to delete it anyway? Не удалось начать транзакцию - + Could not commit transaction Не удалось выполнить транзакцию @@ -3494,7 +3494,7 @@ Do you want to delete it anyway? QPSQLResult - + Unable to create query Невозможно создать запрос @@ -3527,86 +3527,82 @@ Do you want to delete it anyway? Точки (pt) - + Form Форма - + Paper Бумага - + Page size: Размер страницы: - + Width: Ширина: - + Height: Высота: - + Paper source: Источник бумаги: - + Orientation Ориентация - + Portrait Книжная - + Landscape Альбомная - + Reverse landscape Перевёрнутая альбомная - + Reverse portrait Перевёрнутая книжная - + Margins Поля - - + top margin верхнее поле - - + left margin левое поле - - + right margin правое поле - - + bottom margin нижнее поле @@ -4165,17 +4161,17 @@ Please choose a different file name. QPrintPropertiesWidget - + Form Форма - + Page Страница - + Advanced Дополнительно @@ -4183,97 +4179,97 @@ Please choose a different file name. QPrintSettingsOutput - + Form Форма - + Copies Копии - + Print range Диапазон печати - + Print all Все - + Pages from Страницы от - + to до - + Selection Выделенный фрагмент - + Output Settings Настройки вывода - + Copies: Количество копий: - + Collate Разобрать про копиям - + Reverse Обратный порядок - + Options Параметры - + Color Mode Режим цвета - + Color Цвет - + Grayscale Оттенки серого - + Duplex Printing Двусторонняя печать - + None Нет - + Long side По длинной стороне - + Short side По короткой стороне @@ -4281,47 +4277,47 @@ Please choose a different file name. QPrintWidget - + Form Форма - + Printer Принтер - + &Name: &Название: - + P&roperties С&войства - + Location: Расположение: - + Preview Просмотр - + Type: Тип: - + Output &file: Выходной &файл: - + ... ... @@ -6258,7 +6254,7 @@ Please choose a different file name. QWizard - + Go Back Назад -- cgit v0.12 From 16f03cce9fc898e751c04ef590e91e82e0c1f79d Mon Sep 17 00:00:00 2001 From: Ritt Konstantin Date: Mon, 6 Jul 2009 19:29:09 +0200 Subject: Update Russian translation for Qt Linguist. typo fixes; clarify several strings; use 'own languages' hack Merge-request: 803 Reviewed-by: Oswald Buddenhagen --- translations/linguist_ru.ts | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/translations/linguist_ru.ts b/translations/linguist_ru.ts index 058d86a..86c7434 100644 --- a/translations/linguist_ru.ts +++ b/translations/linguist_ru.ts @@ -42,7 +42,7 @@ Note that the modified entries will be reset to unfinished if 'Set translated entries to finished' above is unchecked. - Имейте в виду, что изменённые записи будут отмечены как незавершённые, если не включен параметр "Помечать переведенные записи как завершённые". + Имейте в виду, что изменённые записи будут отмечены как незавершённые, если не включён параметр "Помечать переведенные записи как завершённые". @@ -289,7 +289,7 @@ Will assume a single universal form. LRelease - + Generated %n translation(s) (%1 finished and %2 unfinished) @@ -617,7 +617,7 @@ All files (*) <center><img src=":/images/splash.png"/></img><p>%1</p></center><p>Qt Linguist is a tool for adding translations to Qt applications.</p><p>%2</p><p>Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).</p><p>The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.</p> - <center><img src=":/images/splash.png"/></img><p>%1</p></center><p>Qt Linguist - инструмент для добавления переводов в приложения на основе Qt.</p><p>%2</p><p>Copyright (C) 2009 Корпорация Nokia и/или её дочерние подразделения.</p><p>Программа предоставляется "как есть" без гарантий любого рода, включая гарантии дизайна, коммерческой ценности и пригодности для определённой цели.</p> + @@ -1250,7 +1250,7 @@ All files (*) Toggle checking that phrase suggestions are used. - Переключение проверки использования предложений для фраз. Если выявлено несовпадение, будет показано сообщение в окне предупреждений. + Переключение проверки использования предложений для фраз. @@ -1466,6 +1466,11 @@ All files (*) + Russian + Русский + + + German Немецкий @@ -1517,7 +1522,7 @@ All files (*) Developer comments - Комментарии разработчика + Комментарий разработчика @@ -1547,7 +1552,7 @@ All files (*) %1 translator comments - Комментарий переводчика на %1 + %1 перевод: комментарий переводчика @@ -1583,10 +1588,11 @@ Line: %2 MsgEdit - + This is the right panel of the main window. - + Правая панель главного окна + @@ -1800,17 +1806,17 @@ Line: %2 C++ source files - Исходные коды C++ + Файлы исходных кодов C++ Java source files - Исходные коды Java + Файлы исходных кодов Java Qt Script source files - Исходные коды Qt Script + Файлы исходных кодов Qt Script -- cgit v0.12 From bcc679a7a06f64459b942b001ae7df2d27b43746 Mon Sep 17 00:00:00 2001 From: Ritt Konstantin Date: Mon, 6 Jul 2009 19:29:09 +0200 Subject: Add Russian translation for qvfb Merge-request: 803 Reviewed-by: Oswald Buddenhagen --- tools/qvfb/translations/translations.pro | 1 + translations/qvfb_ru.ts | 328 +++++++++++++++++++++++++++++++ 2 files changed, 329 insertions(+) create mode 100644 translations/qvfb_ru.ts diff --git a/tools/qvfb/translations/translations.pro b/tools/qvfb/translations/translations.pro index 736a72c..f667bb8 100644 --- a/tools/qvfb/translations/translations.pro +++ b/tools/qvfb/translations/translations.pro @@ -27,6 +27,7 @@ SOURCES = ../qvfb.cpp \ ../../shared/deviceskin/deviceskin.cpp TRANSLATIONS=$$[QT_INSTALL_TRANSLATIONS]/qvfb_pl.ts \ + $$[QT_INSTALL_TRANSLATIONS]/qvfb_ru.ts \ $$[QT_INSTALL_TRANSLATIONS]/qvfb_untranslated.ts \ $$[QT_INSTALL_TRANSLATIONS]/qvfb_zh_CN.ts \ $$[QT_INSTALL_TRANSLATIONS]/qvfb_zh_TW.ts diff --git a/translations/qvfb_ru.ts b/translations/qvfb_ru.ts new file mode 100644 index 0000000..b084380 --- /dev/null +++ b/translations/qvfb_ru.ts @@ -0,0 +1,328 @@ + + + + + AnimationSaveWidget + + + + Record + Записать + + + + Reset + Сбросить + + + + Save + Сохранить + + + + Save in MPEG format (requires netpbm package installed) + Сохранить в формат MPEG (требуется установленный пакет netpbm) + + + + + Click record to begin recording. + Нажмите "Записать" для начала записи. + + + + + Finished saving. + Сохранение завершено. + + + + Paused. Click record to resume, or save if done. + Приостановлено. Нажмите "Записать" для продолжения или "Сохранить", если готово. + + + + Pause + Пауза + + + + Recording... + Идёт запись... + + + + Saving... + Сохранение... + + + + + Save animation... + Сохранение анимации... + + + + Save canceled. + Сохранение отменено. + + + + Save failed! + Сохранение не удалось! + + + + Config + + + Configure + Настройка + + + + Size + Размер + + + + 176x220 "SmartPhone" + + + + + 240x320 "PDA" + + + + + 320x240 "TV" / "QVGA" + + + + + 640x480 "VGA" + + + + + 800x600 + + + + + 1024x768 + + + + + Custom + Особый + + + + Depth + Глубина + + + + 1 bit monochrome + 1 бит (монохромный) + + + + 4 bit grayscale + 4 бита (градации серого) + + + + 8 bit + 8 бит + + + + 12 (16) bit + 12 (16) бит + + + + 15 bit + 15 бит + + + + 16 bit + 16 бит + + + + 18 bit + 18 бит + + + + 24 bit + 24 бита + + + + 32 bit + 32 бита + + + + 32 bit ARGB + 32 бита (ARGB) + + + + Skin + Обложка + + + + None + Нет + + + + Emulate touch screen (no mouse move) + Эмулировать тачскрин (без перемещения мыши) + + + + Emulate LCD screen (Only with fixed zoom of 3.0 times magnification) + Эмулировать ж/к экран (только с 3-х кратным увеличением) + + + + <p>Note that any applications using the virtual framebuffer will be terminated if you change the Size or Depth <i>above</i>. You may freely modify the Gamma <i>below</i>. + <p>Имейте в виду, что любая программа будет завершена, если изменится размер или глубина экрана. Параметр Гамма можно менять свободно. + + + + Gamma + Гамма + + + + Blue + Синий + + + + + + + 1.0 + + + + + Green + Зеленый + + + + All + Все + + + + Red + Красный + + + + Set all to 1.0 + Выставить все в 1.0 + + + + &OK + &Готово + + + + &Cancel + &Отмена + + + + DeviceSkin + + + The image file '%1' could not be loaded. + Не удалось загрузить изображение '%1'. + + + + The skin directory '%1' does not contain a configuration file. + Каталог обложки '%1' не содержит файла настроек. + + + + The skin configuration file '%1' could not be opened. + Не удалось открыть файл настроек обложки '%1'. + + + + The skin configuration file '%1' could not be read: %2 + Не удалось прочитать файл настроек обложки '%1': %2 + + + + Syntax error: %1 + Синтаксическая ошибка: %1 + + + + The skin "up" image file '%1' does not exist. + Файл изображения "up" '%1' не существует. + + + + The skin "down" image file '%1' does not exist. + Файл изображения "down" '%1' не существует. + + + + The skin "closed" image file '%1' does not exist. + Файл изображения "closed" '%1' не существует. + + + + The skin cursor image file '%1' does not exist. + Файл изображения курсора '%1' не существует. + + + + Syntax error in area definition: %1 + Синтаксическая ошибка в определении области: %1 + + + + Mismatch in number of areas, expected %1, got %2. + Несовпадение количества зон: ожидается %1, указано %2. + + + + QVFb + + + Browse... + Обзор... + + + + Load Custom Skin... + Загрузить обложку пользователя... + + + + All QVFB Skins (*.skin) + Все обложки QVFB (*.skin) + + + -- cgit v0.12 From 962bdf2eb305c5dd01fc03dbe0c17afb4a42c8aa Mon Sep 17 00:00:00 2001 From: Ritt Konstantin Date: Mon, 6 Jul 2009 19:29:10 +0200 Subject: Add basic Russian translation for qtconfig Merge-request: 803 Reviewed-by: Oswald Buddenhagen --- tools/qtconfig/translations/translations.pro | 1 + translations/qtconfig_ru.ts | 906 +++++++++++++++++++++++++++ 2 files changed, 907 insertions(+) create mode 100644 translations/qtconfig_ru.ts diff --git a/tools/qtconfig/translations/translations.pro b/tools/qtconfig/translations/translations.pro index fbbdb2bba2..1f9f572 100644 --- a/tools/qtconfig/translations/translations.pro +++ b/tools/qtconfig/translations/translations.pro @@ -8,6 +8,7 @@ HEADERS += ../colorbutton.h ../previewframe.h ../previewwidget.h ../mainw FORMS = ../mainwindowbase.ui ../paletteeditoradvancedbase.ui ../previewwidgetbase.ui TRANSLATIONS=$$[QT_INSTALL_TRANSLATIONS]/qtconfig_pl.ts \ + $$[QT_INSTALL_TRANSLATIONS]/qtconfig_ru.ts \ $$[QT_INSTALL_TRANSLATIONS]/qtconfig_untranslated.ts \ $$[QT_INSTALL_TRANSLATIONS]/qtconfig_zh_CN.ts \ $$[QT_INSTALL_TRANSLATIONS]/qtconfig_zh_TW.ts diff --git a/translations/qtconfig_ru.ts b/translations/qtconfig_ru.ts new file mode 100644 index 0000000..b1965f2 --- /dev/null +++ b/translations/qtconfig_ru.ts @@ -0,0 +1,906 @@ + + + + + MainWindow + + + Desktop Settings (Default) + Настройки рабочего стола (по умолчанию) + + + + Choose style and palette based on your desktop settings. + Выбор стиля и палитры на основе настроек рабочего стола. + + + + On The Spot + + + + + + + + Auto (default) + Автоматически (по умолчанию) + + + + Choose audio output automatically. + Автоматический выбор звукового выхода. + + + + + aRts + aRts + + + + Experimental aRts support for GStreamer. + Экспериментальная поддержка aRts в GStreamer. + + + + Phonon GStreamer backend not available. + Модуль Phonon поддержки GStreamer не доступен. + + + + Choose render method automatically + Автоматический выбор метода отрисовки + + + + + X11 + + + + + Use X11 Overlays + Использовать оверлеи X11 + + + + + OpenGL + + + + + Use OpenGL if avaiable + Использовать OpenGL, если доступен + + + + + Software + Программный + + + + Use simple software rendering + Использовать простую программную отрисовку + + + + No changes to be saved. + Нет изменений для сохранения. + + + + Saving changes... + Сохранение изменений... + + + + Over The Spot + + + + + Off The Spot + + + + + Root + + + + + Select a Directory + Выбор каталога + + + + <h3>%1</h3><br/>Version %2<br/><br/>Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).<br/><br/>The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.<br/> + + + + + + + Qt Configuration + Конфигурация Qt + + + + Save Changes + Сохранение изменений + + + + Save changes to settings? + Сохранить изменения настроек? + + + + &Yes + &Да + + + + &No + &Нет + + + + &Cancel + &Отмена + + + + MainWindowBase + + + Qt Configuration + Конфигурация Qt + + + + Appearance + Внешний вид + + + + GUI Style + Стиль пользовательского графического интерфейса + + + + Select GUI &Style: + &Стиль интерфейса: + + + + Build Palette + Палитра + + + + &3-D Effects: + Эффекты &3-D: + + + + Window Back&ground: + &Фон окна: + + + + &Tune Palette... + &Настроить палитру... + + + + Please use the KDE Control Center to set the palette. + Используйте Центр управления KDE для настройки цветов. + + + + Preview + Предпросмотр + + + + Select &Palette: + Выбор &палитры: + + + + Active Palette + Палитра активных элементов + + + + Inactive Palette + Палитра неактивных элементов + + + + Disabled Palette + Палитра выключенных элементов + + + + Fonts + Шрифты + + + + Default Font + Шрифт по умолчанию + + + + &Style: + &Стиль: + + + + &Point Size: + &Размер в точках: + + + + F&amily: + Семе&йство: + + + + Sample Text + Текст для примера (Sample Text) + + + + Font Substitution + Подстановка шрифтов + + + + S&elect or Enter a Family: + &Выберите или введите семейство: + + + + Current Substitutions: + Текущие замены: + + + + + Up + Выше + + + + + Down + Ниже + + + + + Remove + Удалить + + + + Select s&ubstitute Family: + Выберите п&одставляемое семейство: + + + + + Add + Добавить + + + + Interface + Интерфейс + + + + Feel Settings + Настройка указателя + + + + + ms + мс + + + + &Double Click Interval: + &Интервал двойного щелчка: + + + + No blinking + Без мигания + + + + &Cursor Flash Time: + &Период мигания курсора: + + + + lines + строк + + + + Wheel &Scroll Lines: + &Прокручивать строк при повороте колёсика: + + + + Resolve symlinks in URLs + Разрешать символьные ссылки в URL-ах + + + + GUI Effects + Эффекты пользовательского интерфейса + + + + &Enable + &Включить + + + + Alt+E + Alt+D + + + + &Menu Effect: + Эффект &меню: + + + + C&omboBox Effect: + Эффект C&omboBox: + + + + &ToolTip Effect: + Эффект &ToolTip: + + + + Tool&Box Effect: + Эффект Tool&Box: + + + + + + + Disable + Выключен + + + + + + + Animate + Анимация + + + + + Fade + Затухание + + + + Global Strut + Специальные возможности + + + + Minimum &Width: + Минимальная &ширина: + + + + Minimum Hei&ght: + Минимальная в&ысота: + + + + + pixels + пикселей + + + + Enhanced support for languages written right-to-left + Расширенная поддержка письма справа налево + + + + XIM Input Style: + Стиль ввода XIM: + + + + On The Spot + + + + + Over The Spot + + + + + Off The Spot + + + + + Root + + + + + Default Input Method: + Метод ввода по умолчанию: + + + + Printer + Принтер + + + + Enable Font embedding + Разрешить встраивание шрифтов + + + + Font Paths + Пути к шрифтам + + + + Browse... + Обзор... + + + + Press the <b>Browse</b> button or enter a directory and press Enter to add them to the list. + Нажмите кнопку <b>Обзор...</b> или укажите каталог и нажмите Ввод для добавления его в список. + + + + Phonon + Phonon + + + + About Phonon + О Phonon + + + + + Current Version: + Текущая версия: + + + + + Not available + Недоступно + + + + + Website: + Вэб-сайт: + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://phonon.kde.org"><span style=" text-decoration: underline; color:#0000ff;">http://phonon.kde.org</span></a></p></body></html> + + + + + About GStreamer + О GStreamer + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://gstreamer.freedesktop.org/"><span style=" text-decoration: underline; color:#0000ff;">http://gstreamer.freedesktop.org/</span></a></p></body></html> + + + + + GStreamer backend settings + Настройки модуля GStreamer + + + + Preferred audio sink: + Предпочитаемое звуковое устройство: + + + + Preferred render method: + Предпочитаемый метод отрисовки: + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-style:italic;">Note: changes to these settings may prevent applications from starting up correctly.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-style:italic;">Внимание: Изменение данных настроек может повлечь невозможность корректного запуска приложений.</span></p></body></html> + + + + &File + &Файл + + + + &Help + &Справка + + + + &Save + &Сохранить + + + + Save + Сохранить + + + + Ctrl+S + + + + + E&xit + В&ыход + + + + Exit + Выход + + + + &About + &О программе + + + + About + О программе + + + + About &Qt + О &Qt + + + + About Qt + О Qt + + + + PaletteEditorAdvancedBase + + + Tune Palette + Настройка палитры + + + + <b>Edit Palette</b><p>Change the palette of the current widget or form.</p><p>Use a generated palette or select colors for each color group and each color role.</p><p>The palette can be tested with different widget layouts in the preview section.</p> + <b>Изменение палитры</b><p>Изменение палитры текущего виджета или формы.</p><p>Используйте сформированную палитру или выберите цвета для каждой группы цветов и каждой их роли.</p><p>Палитру можно проверить на виджетах в разных режимах отображения в разделе предпросмотра.</p> + + + + Select &Palette: + Выбор &палитры: + + + + Active Palette + Палитра активных элементов + + + + Inactive Palette + Палитра неактивных элементов + + + + Disabled Palette + Палитра выключенных элементов + + + + Auto + Автоматически + + + + Build inactive palette from active + Создать неактивную палитру из активной + + + + Build disabled palette from active + Создать выключенную палитру из активной + + + + Central color &roles + Роли &цветов + + + + Choose central color role + Выберите роль цвета + + + + <b>Select a color role.</b><p>Available central roles are: <ul> <li>Window - general background color.</li> <li>WindowText - general foreground color. </li> <li>Base - used as background color for e.g. text entry widgets, usually white or another light color. </li> <li>Text - the foreground color used with Base. Usually this is the same as WindowText, in what case it must provide good contrast both with Window and Base. </li> <li>Button - general button background color, where buttons need a background different from Window, as in the Macintosh style. </li> <li>ButtonText - a foreground color used with the Button color. </li> <li>Highlight - a color to indicate a selected or highlighted item. </li> <li>HighlightedText - a text color that contrasts to Highlight. </li> <li>BrightText - a text color that is very different from WindowText and contrasts well with e.g. black. </li> </ul> </p> + <b>Выбор роли цвета.</b><p>Доступны следующие роли: <ul><li>Window - основной цвет фона.</li> <li>WindowText - основной цвет текста.</li> <li>Base - используется в качестве фона для, например, виджетов с текстовыми полями, обычно, белый или другой светлый цвет.</li> <li>Text - цвет текста используемый совместно с Base. Обычно, он совпадает с WindowText, так как в этом случае получается максимальный контраст и с Window, и с Base.</li> <li>Button - основной цвет фона кнопки, которой требуется цвет отличный от Window, например, в стиле Macintosh.</li> <li>ButtonText - цвет текста используемый совместно с Button.</li> <li>Highlight - цвет для обозначения выбранного или выделенного элемента.</li> <li>HighlightedText - цвет текста контрастирующий с Highlight.</li> <li>BrightText - цвет текста, который отличается от WindowText и хорошо контрастирует с черным.</li></ul></p> + + + + Window + + + + + WindowText + + + + + Button + + + + + Base + + + + + Text + + + + + BrightText + + + + + ButtonText + + + + + Highlight + + + + + HighlightedText + + + + + &Select Color: + &Выбор цвета: + + + + + Choose a color + Выберите цвет + + + + Choose a color for the selected central color role. + Выберите цвет для указанной роли. + + + + 3-D shadow &effects + Эффекты т&рехмерной тени + + + + Build &from button color + Получ&ить из цвета кнопки + + + + Generate shadings + Создание полутонов + + + + Check to let 3D-effect colors be calculated from button-color. + Включите, чтобы цвета эффекта трёхмерности были получены из цвета кнопки. + + + + Choose 3D-effect color role + Выбор роли цвета дял эффекта трёхмерности + + + + <b>Select a color role.</b><p>Available effect roles are: <ul> <li>Light - lighter than Button color. </li> <li>Midlight - between Button and Light. </li> <li>Mid - between Button and Dark. </li> <li>Dark - darker than Button. </li> <li>Shadow - a very dark color. </li> </ul> + <b>Выбор роли цвета.</b><p>Доступны следующие роли: <ul> <li>Light - светлее цвета Button. </li> <li>Midlight - среднее между Light и Button. </li> <li>Mid - среднее между Button и Dark. </li> <li>Dark - темнее цвета Button. </li> <li>Shadow - очень темный цвет. </li> </ul> + + + + Light + + + + + Midlight + + + + + Mid + + + + + Dark + + + + + Shadow + + + + + Select Co&lor: + Выбор &цвета: + + + + Choose a color for the selected effect color role. + Выбор цвета для указанной роли. + + + + OK + Принять + + + + Close dialog and apply all changes. + Закрыть окно с применением изменений. + + + + Cancel + Отмена + + + + Close dialog and discard all changes. + Закрыть окно с отменой изменений. + + + + PreviewFrame + + + Desktop settings will only take effect after an application restart. + Настройки рабочего стола применятся после перезапуска приложения. + + + + PreviewWidgetBase + + + Preview Window + Окно предпросмотра + + + + ButtonGroup + + + + + RadioButton1 + + + + + RadioButton2 + + + + + RadioButton3 + + + + + ButtonGroup2 + + + + + CheckBox1 + + + + + CheckBox2 + + + + + LineEdit + + + + + ComboBox + + + + + PushButton + + + + + <p> +<a href="http://qtsoftware.com">http://qtsoftware.com</a> +</p> +<p> +<a href="http://www.kde.org">http://www.kde.org</a> +</p> + + + + -- cgit v0.12 From 4a5340fbe4d6ca3df4573fe4147103fb8379cb55 Mon Sep 17 00:00:00 2001 From: Ritt Konstantin Date: Mon, 6 Jul 2009 19:29:11 +0200 Subject: Update Russian translation for Qt Help Merge-request: 803 Reviewed-by: Oswald Buddenhagen --- translations/qt_help_ru.ts | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/translations/qt_help_ru.ts b/translations/qt_help_ru.ts index 16748fb..c2dc041 100644 --- a/translations/qt_help_ru.ts +++ b/translations/qt_help_ru.ts @@ -6,17 +6,17 @@ Search Results - Результаты поиска + Результат поиска Note: - Замечание: + Примечание: The search results may not be complete since the documentation is still being indexed! - Могли быть показаны не все результаты, так как документация ещё индексируется! + Результат поиска может быть неполным, так как документация ещё индексируется! @@ -45,7 +45,7 @@ Cannot open collection file: %1 - Не удалось открыть файл набора: %1 + Не удалось открыть файл набора: %1 @@ -168,12 +168,12 @@ Insert custom filters... - Вставка индивидуальных фильтров... + Добавление индивидуальных фильтров... Insert help data for filter section (%1 of %2)... - Вставка данных справки для секции фильтра (%1 из %2)... + Добавление данных справки для раздела фильтра (%1 из %2)... @@ -198,7 +198,7 @@ Insert files... - Вставка файлов... + Добавление файлов... @@ -228,22 +228,22 @@ Insert indices... - Вставка указателей... + Добавление указателей... Insert contents... - Вставка оглавления... + Добавление содержания... Cannot insert contents! - Не удаётся вставить оглавление! + Не удалось добавить содержание! Cannot register contents! - Не удаётся зарегистрировать оглавление! + Не удалось зарегистрировать содержание! @@ -271,12 +271,12 @@ <B>without</B> the words: - <B>не содержит</B> слова: + <B>не содержит</B> слов: with <B>exact phrase</B>: - содержит <B>фразу полностью</B>: + содержит <B>точную фразу</B>: @@ -286,7 +286,7 @@ with <B>at least one</B> of the words: - содержит <B> минимум одно</B> из слов: + содержит <B>хотя бы одно</B> из слов: @@ -294,7 +294,7 @@ 0 - 0 of 0 Hits - 0 - 0 из 0 соответствий + 0 - 0 из 0 совпадений @@ -302,7 +302,7 @@ %1 - %2 of %3 Hits - %1 - %2 из %3 соответствий + %1 - %2 из %3 совпадений @@ -315,12 +315,12 @@ Unknown token. - Неизвестный токен. + Неизвестный идентификатор. Unknown token. Expected "QtHelpProject"! - Неизвестный токен. Ожидается "QtHelpProject"! + Неизвестный идентификатор. Ожидается "QtHelpProject"! -- cgit v0.12 From 034e15917bb81b65de7828466dbc15b2e2a84b47 Mon Sep 17 00:00:00 2001 From: Ritt Konstantin Date: Mon, 6 Jul 2009 19:29:12 +0200 Subject: Update Russian translation for Qt Assistant Merge-request: 803 Reviewed-by: Oswald Buddenhagen --- translations/assistant_ru.ts | 80 ++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 43 deletions(-) diff --git a/translations/assistant_ru.ts b/translations/assistant_ru.ts index 32aa739..ecec0f8 100644 --- a/translations/assistant_ru.ts +++ b/translations/assistant_ru.ts @@ -57,16 +57,16 @@ Новая папка - + - - - + + + Bookmarks Закладки - + Delete Folder Удалить папку @@ -79,12 +79,12 @@ BookmarkManager - + Bookmarks Закладки - + Remove Удалить @@ -94,7 +94,7 @@ Удаление папки приведёт к удалению её содержимого.<br>Желаете продолжить? - + New Folder Новая папка @@ -103,7 +103,7 @@ BookmarkWidget - + Delete Folder Удалить папку @@ -138,7 +138,7 @@ Фильтр: - + Add Добавить @@ -161,7 +161,7 @@ Закрыть текущую страницу - + Print Document Печать документа @@ -226,24 +226,24 @@ FindWidget - + Previous - Предыдущее совпадение + Предыдущее Next - Следующее совпадение + Следующее Case Sensitive - Регистрозависимо + Учитывать регистр Whole words - Слова полностью + Слова целиком @@ -441,31 +441,31 @@ MainWindow - + Index - Индекс + Указатель - - + + Contents Содержание - - + + Bookmarks Закладки - - - + + + Qt Assistant Qt Assistant - + Unfiltered Без фильтрации @@ -473,10 +473,10 @@ Looking for Qt Documentation... - Поиск по документации Qt... + Поиск документации по Qt... - + &File &Файл @@ -656,7 +656,7 @@ Добавить закладку... - + CTRL+D @@ -723,12 +723,12 @@ Could not find the associated content item. - Не удалось найти элемент, связанный с содержанием. + Не удалось найти элемент, связанный с содержанием. About %1 - О %1 + О %1 @@ -767,7 +767,7 @@ Some documents currently opened in Assistant reference the documentation you are attempting to remove. Removing the documentation will close those documents. - Некоторые открытые в Qt Assistant документы ссылаются на документацию, которую вы пытаетесь удалить. Удаление данной документации приведёт к закрытию таких документов. + Некоторые открытые в Qt Assistant документы ссылаются на документацию, которую вы пытаетесь удалить. Её удаление приведёт к закрытию этих документов. @@ -830,7 +830,7 @@ 1 - + 1 @@ -876,18 +876,12 @@ Restore to default - Восстановить по умолчанию + Страница по умолчанию QObject - - - Bookmark - Закладка - - The specified collection file does not exist! Указанный файл набора отсутствует! @@ -1037,17 +1031,17 @@ Reason: Choose a topic for <b>%1</b>: - Выберите статью для <b>%1</b>: + Выберите раздел для <b>%1</b>: Choose Topic - Выбор статьи + Выбор раздела &Topics - &Статьи + &Разделы -- cgit v0.12 From 283b1ba1cf6cd34d07d9f2b2bb0d40223e172339 Mon Sep 17 00:00:00 2001 From: Ritt Konstantin Date: Mon, 6 Jul 2009 19:29:12 +0200 Subject: Update Russian translation for Qt Assistant adp Merge-request: 803 Reviewed-by: Oswald Buddenhagen --- translations/assistant_adp_ru.ts | 289 ++++++++++++++++++++++++++++++++------- 1 file changed, 243 insertions(+), 46 deletions(-) diff --git a/translations/assistant_adp_ru.ts b/translations/assistant_adp_ru.ts index a587a91..c47798b 100644 --- a/translations/assistant_adp_ru.ts +++ b/translations/assistant_adp_ru.ts @@ -4,10 +4,12 @@ AssistantServer + Failed to bind to port %1 Не удалось открыть порт %1 + Qt Assistant Qt Assistant @@ -15,22 +17,27 @@ FontPanel + &Family Се&мейство + &Style &Стиль + Font Шрифт + &Writing system Система &письма + &Point size &Размер в пикселях @@ -38,22 +45,27 @@ FontSettingsDialog + Application Приложение + Browser Обозреватель + Font settings for: Настройки шрифта для: + Use custom settings Использование индивидуальных настроек + Font Settings Настройки шрифта @@ -61,202 +73,261 @@ HelpDialog + &Index &Указатель + &Look For: &Искать: + &New - &Создать + &Новая + + &Search &Поиск + <b>Enter a keyword.</b><p>The list will select an item that matches the entered string best.</p> - <b>Ввод слова.</b><p>В список попадет то, что лучше соответствует введенной строке.</p> + <b>Указание ключевого слова.</b><p>Список заполняется элементами, лучше соответствующими указанному ключевому слову.</p> + <b>Enter search word(s).</b><p>Enter here the word(s) you are looking for. The words may contain wildcards (*). For a sequence of words quote them.</p> - <b>Ввод одного или более слов для поиска.</b><p>Сюда следует ввести одно или несколько слов, которые требуется найти. Слова могут содержкать символы-заменители (*). Если требуется найти словосочетание, то его нужно заключить в кавычки.</p> + <b>Указание слов для поиска.</b><p>Введите одно или несколько слов, по которым требуется осуществить поиск. Слова могут содержкать символы-заменители (*). Если требуется найти сочетание слов, заключите искомую фразу в кавычки.</p> + <b>Found documents</b><p>This list contains all found documents from the last search. The documents are ordered, i.e. the first document has the most matches.</p> - <b>Найденные документы</b><p>В этом списке представлены все найденные при последнем поиске документы. Документы упорядочены по релевантности, т.е. чем выше, тем чаще в нём встречаются указанные слова.</p> + <b>Найденные документы</b><p>В данном списке представлены все найденные при последнем поиске документы. Документы упорядочены по релевантности, т.е. чем выше в списке, тем чаще в нём встречаются искомые слова.</p> + <b>Help topics organized by category.</b><p>Double-click an item to see the topics in that category. To view a topic, just double-click it.</p> - <b>Статьи справки распределённые по разделам.</b><p>Дважды кликните по одному из пунктов, чтобы увидеть какие статьи содержатся в данном разделе. Для открытия статьи просто дважды щелкните на ней.</p> + <b>Разделы справки, распределённые по категориям.</b><p>Дважды щёлкните по одному из пунктов для отображения разделов в данной категории. Для открытия раздела дважды щёлкните по нему.</p> + <b>Help</b><p>Choose the topic you want help on from the contents list, or search the index for keywords.</p> - <b>Справка</b><p>Выберите необходимую статью справки из списка разделов или воспользуйтесь поиском по предметному указателю.</p> + <b>Справка</b><p>Выберите раздел справки из содержания или воспользуйтесь поиском по предметному указателю.</p> + <b>List of available help topics.</b><p>Double-click on an item to open its help page. If more than one is found, you must specify which page you want.</p> - <b>Список доступных статей справки.</b><p>Дважды щёлкните на пункте для открытия страницы помощи. Если найдено более одной, то потребуется выбрать желаемую страницу.</p> + <b>Список доступных разделов справки.</b><p>Дважды щёлкните по одному из пунктов для открытия страницы справки. Если найдено более одной страницы, выберите желаемую.</p> + Add new bookmark - Добавить новую закладку + Добавить закладку + Add the currently displayed page as a new bookmark. - Добавление текущей открытой страницы в закладки. + Добавить отображаемую страницу в закладки. + Cannot open the index file %1 Не удаётся открыть файл индекса %1 + Con&tents Содер&жание + Delete bookmark Удалить закладку + Delete the selected bookmark. - Удаление выбранной закладки. + Удалить выбранную закладку. + Display the help page for the full text search. - Открытие справки по полнотекстовому поиску. + Показать справку по полнотекстовому поиску. + Display the help page. - Открыть страницу справки. + Показать страницу справки. + Displays help topics organized by category, index or bookmarks. Another tab inherits the full text search. - Здесь отображается список тем, распределенных по разделам, указатель или закладки. Последняя вкладка содержит полнотекстовый поиск. + Отображает список разделов, распредёленных по категориям, указатель или закладки. Последняя вкладка содержит панель полнотекстового поиска. + Displays the list of bookmarks. Отображает список закладок. + + Documentation file %1 does not exist! Skipping file. Файл документации %1 не существует! Пропущен. + Documentation file %1 is not compatible! Skipping file. - Файл документации %1 не совместим! + Несовместимый файл документации %1! Пропущен. + + Done Готово + Enter keyword Введите ключевое слово + Enter searchword(s). - Введите одно или более слов для поиска. + Введите одно или несколько слов для поиска. + Failed to load keyword index file Assistant will not work! Не удалось загрузить файл индекса ключевых слов -Assistant не будет работать! +Qt Assistant не будет работать! + Failed to save fulltext search index Assistant will not work! Не удалось сохранить индекс полнотекстового поиска -Assistant не будет работать! +Qt Assistant не будет работать! + Found &Documents: Найденные &документы: + + Full Text Search Полнотекстовый поиск + He&lp &Справка + Help Справка + Indexing files... Индексирование файлов... + Open Link in New Tab Открыть ссылку в новой вкладке + Open Link in New Window Открыть ссылку в новом окне + + Parse Error Ошибка обработки + + Prepare... Подготовка... + Preparing... Подготовка... + Pressing this button starts the search. Нажатие на эту кнопку запустит процесс поиска. + + + Qt Assistant Qt Assistant + Reading dictionary... Чтение каталога... + Searching f&or: &Искать: + Start searching. Начать поиск. + The closing quotation mark is missing. Пропущена закрывающая кавычка. + Using a wildcard within phrases is not allowed. - Использование символов-заменителей внутри фраз не допустимо. + Использование символов-заменителей внутри фраз недопустимо. + + + Warning Предупреждение + + column 1 столбец 1 + Open Link in Current Tab Открыть ссылку в текущей вкладке + %n document(s) found. Найден %n документ. @@ -265,10 +336,12 @@ Assistant не будет работать! + &Bookmarks &Закладки + &Delete &Удалить @@ -276,38 +349,47 @@ Assistant не будет работать! HelpWindow + <div align="center"><h1>The page could not be found</h1><br><h3>'%1'</h3></div> <div align="center"><h1>Страница не найдена</h1><br><h3>'%1'</h3></div> + Copy &Link Location Копировать &адрес ссылки + Error... Ошибка... + Failed to open link: '%1' Не удалось открыть ссылку: '%1' + Help Справка + OK Закрыть + Open Link in New Tab Открыть ссылку в новой вкладке + Open Link in New Window Shift+LMB Открыть ссылку в новом окне Shift+LMB + Unable to launch web browser. Невозможно запустить вэб-браузер. @@ -317,6 +399,7 @@ Assistant не будет работать! Index + Untitled Неозаглавлено @@ -324,354 +407,445 @@ Assistant не будет работать! MainWindow + + "What's This?" context sensitive help. - "Что это?" - контекстная справка. + Контекстная справка "Что это?". + &Add Bookmark - &Добавление закладки + &Добавить закладку + &Close &Закрыть + &Copy &Копировать + &Edit &Правка + &File &Файл + &Find in Text... П&оиск по тексту... + &Go &Перейти + &Help &Справка + &Home &Домой + &Next - &Вперёд + Сл&едующий + &Previous - &Назад + &Предыдущий + &Print... &Печать... + &View &Вид + &Window &Окно + ... ... + About Qt О Qt + About Qt Assistant О Qt Assistant + Add Tab Добавить вкладку + Add the currently displayed page as a new bookmark. - Добавление текущей открытой страницы в закладки. + Добавить отображаемую страницу в закладки. + Boo&kmarks &Закладки + Cannot open file for writing! - Не удается открыть файл для записи! + Не удалось открыть файл для записи! + Close Tab Закрыть вкладку + Close the current window. Закрыть текущее окно. + Display further information about Qt Assistant. Показать дополнительную информацию о Qt Assistant. + Displays the main page of a specific documentation set. - Открывает главную страницу выбранного набора документации. + Открывает стартовую страницу выбранного набора документации. + E&xit - Вы&ход + В&ыход + Failed to open about application contents in file: '%1' Не удалось получить информацию о приложении из файла: '%1' + Find &Next - Продолжить п&оиск + Найти &следующее + Find &Previous Найти &предыдущее + Font Settings... Настройки шрифта... + Go Перейти + Go to the home page. Qt Assistant's home page is the Qt Reference Documentation. Перейти на домашнюю страницу. Домашная страница Qt Assistant - Справочная документация по Qt. + Go to the next page. Переход на следующую страницу. + Initializing Qt Assistant... Инициализация Qt Assistant... + Minimize Свернуть + New Window Новое окно + Next Tab Следующая вкладка + Open a new window. Открыть новое окно. + Open the Find dialog. Qt Assistant will search the currently displayed page for the text you enter. - Открыть окно поиска. Qt Assistant произведёт поиск введённого текста на текущей открытой странице. + Открыть окно поиска. Qt Assistant произведёт поиск введённого текста на отображаемой странице. + Previous Tab Предыдущая вкладка + Print the currently displayed page. - Печать текущей открытой страницы. + Печатать отображаемую страницу. + + Qt Assistant Qt Assistant + Qt Assistant Manual Руководство по Qt Assistant + Qt Assistant by Nokia Qt Assistant от Nokia + Quit Qt Assistant. Выйти из Qt Assistant. + + Save Page Сохранить страницу + Save Page As... Сохранить страницу как... + Select the page in contents tab. - Выбор страницы в оглавлении. + Выбрать страницу во вкладке содержания. + Sidebar Боковая панель + Sync with Table of Contents - Синхронизировать с оглавлением + Синхронизировать с содержанием + Toolbar Панель инструментов + Views Виды + What's This? Что это? + Zoom &in У&величить + Zoom &out У&меньшить + Zoom in on the document, i.e. increase the font size. - Увеличение масштаба документа, т.е. увеличение размера шрифта. + Увеличить размер шрифта. + Zoom out on the document, i.e. decrease the font size. - Уменьшение масштаба документа, т.е. уменьшение размера шрифта. + Уменьшить размер шрифта. + Ctrl+M + SHIFT+CTRL+= + Ctrl+T + Ctrl+I + Ctrl+B + Ctrl+S + Ctrl+] + Ctrl+[ + Ctrl+P + Ctrl+Q + Copy the selected text to the clipboard. Скопировать выделенный текст в буфер обмена. + Ctrl+C + Ctrl+F + F3 + Shift+F3 + Ctrl+Home + Go to the previous page. Переход на предыдущую страницу. + Alt+Left + Alt+Right + Ctrl++ + Ctrl+- + Ctrl+N + Ctrl+W + Shift+F1 + Ctrl+Alt+N + Ctrl+Alt+Right + Ctrl+Alt+Left + Ctrl+Alt+Q + F1 + Ctrl+Alt+S @@ -679,6 +853,7 @@ Assistant не будет работать! QObject + Qt Assistant by Nokia Qt Assistant от Nokia @@ -686,54 +861,67 @@ Assistant не будет работать! TabbedBrowser + ... ... + <img src=":/trolltech/assistant/images/wrap.png">&nbsp;Search wrapped <img src=":/trolltech/assistant/images/wrap.png">&nbsp;Поиск с начала + Add page - Добавить страницу + Добавить вкладку + Case Sensitive - Регистрозависимо + Учитывать регистр + Close Other Tabs Закрыть остальные вкладки + Close Tab Закрыть вкладку + Close page - Закрыть страницу + Закрыть вкладку + New Tab Новая вкладка + Next - Следующий + Следующее + Previous - Предыдущий + Предыдущее + Untitled Безымянный + Whole words - Слова полностью + Слова целиком + TabbedBrowser @@ -741,40 +929,49 @@ Assistant не будет работать! TopicChooser + &Close &Закрыть + &Display &Показать + &Topics - &Статьи + &Разделы + Choose Topic - Выбор статьи + Выбор раздела + Choose a topic for <b>%1</b> - Выберите статью для <b>%1</b> + Выберите раздел для <b>%1</b> + Close the Dialog. - Закрытие окна. + Закрыть диалог. + Displays a list of available help topics for the keyword. - Показывает список доступных статей справки, соответствующих ключевому слову. + Показывает список доступных разделов справки, найденных по ключевому слову. + Open the topic selected in the list. - Открытие выбранной в списке темы. + Открыть выбранный раздел. + Select a topic from the list and click the <b>Display</b>-button to open the online help. - Выберите статью из списка и нажмите на кнопку <b>Показать</b> для открытия онлайн справки. + Выберите раздел из списка и нажмите на кнопку <b>Показать</b> для открытия онлайн справки. -- cgit v0.12 From 3814b2adf50b5724e3375ea2048d13960c8aed82 Mon Sep 17 00:00:00 2001 From: Derick Hawcroft Date: Tue, 7 Jul 2009 14:44:52 +1000 Subject: Handle all PostgreSQL notifications sitting in the queue Task-number: 257247 Reviewed-by: trustme --- src/sql/drivers/psql/qsql_psql.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sql/drivers/psql/qsql_psql.cpp b/src/sql/drivers/psql/qsql_psql.cpp index 770df4c..69697da 100644 --- a/src/sql/drivers/psql/qsql_psql.cpp +++ b/src/sql/drivers/psql/qsql_psql.cpp @@ -1248,15 +1248,15 @@ QStringList QPSQLDriver::subscribedToNotificationsImplementation() const void QPSQLDriver::_q_handleNotification(int) { PQconsumeInput(d->connection); - PGnotify *notify = PQnotifies(d->connection); - if (notify) { - QString name(QLatin1String(notify->relname)); + PGnotify *notify = 0; + while((notify = PQnotifies(d->connection)) != 0) { + QString name(QLatin1String(notify->relname)); if (d->seid.contains(name)) emit notification(name); else qWarning("QPSQLDriver: received notification for '%s' which isn't subscribed to.", - qPrintable(name)); + qPrintable(name)); qPQfreemem(notify); } -- cgit v0.12 From 343e8b7e75c98a4fd1b692a230de8d1132988705 Mon Sep 17 00:00:00 2001 From: Norwegian Rock Cat Date: Tue, 7 Jul 2009 10:05:02 +0200 Subject: Fix typo in color calculation. Argh! It's divide by 256 not 265. The worst part was that I used the same values in Cocoa as well, so they were both "damaged." It should be good now. Task-number: 257499 Reviewed-by: Prasanth Ullattil --- src/gui/kernel/qt_mac.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gui/kernel/qt_mac.cpp b/src/gui/kernel/qt_mac.cpp index 27df5d1..0c3b707 100644 --- a/src/gui/kernel/qt_mac.cpp +++ b/src/gui/kernel/qt_mac.cpp @@ -134,7 +134,7 @@ QColor qcolorForThemeTextColor(ThemeTextColor themeColor) #ifdef Q_OS_MAC32 RGBColor c; GetThemeTextColor(themeColor, 32, true, &c); - QColor color = QColor(c.red / 265, c.green / 256, c.blue / 256); + QColor color = QColor(c.red / 256, c.green / 256, c.blue / 256); return color; #else // There is no equivalent to GetThemeTextColor in 64-bit and it was rather bad that @@ -156,13 +156,13 @@ QColor qcolorForThemeTextColor(ThemeTextColor themeColor) case kThemeTextColorAlertInactive: case kThemeTextColorDialogInactive: case kThemeTextColorPlacardInactive: - return QColor(67, 69, 69, 255); + return QColor(69, 69, 69, 255); case kThemeTextColorPopupButtonInactive: case kThemeTextColorPopupLabelInactive: case kThemeTextColorPushButtonInactive: case kThemeTextColorTabFrontInactive: case kThemeTextColorBevelButtonInactive: - return QColor(123, 127, 127, 255); + return QColor(127, 127, 127, 255); default: { QNativeImage nativeImage(16,16, QNativeImage::systemFormat()); CGRect cgrect = CGRectMake(0, 0, 16, 16); -- cgit v0.12 From 20b2c6bd8e6f6a7ef384f4b478623768c11e01ae Mon Sep 17 00:00:00 2001 From: Norwegian Rock Cat Date: Tue, 7 Jul 2009 13:45:15 +0200 Subject: Document limitation in Cocoa cursor handling. It seems there is a bug in AppKit which will automatically reset a cursor even when it is grabbed, but won't reset it when it's brought back into the window. The upshot of this is that doing a setCursor() inside of mouse handling behaves slightly different than on the other platforms (including Carbon). However, we are at the mercy of Cocoa here and I would rather have all the other things AppKit does right and live with this bug which they may fix some day. --- src/gui/kernel/qwidget.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index e6a5ae0..9d40b00 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -4590,6 +4590,11 @@ void QWidget::unsetLayoutDirection() By default, this property contains a cursor with the Qt::ArrowCursor shape. + Some underlying window implementations will reset the cursor if it + leaves a widget even if the mouse is grabbed. If you want to have + a cursor set for all widgets, even when outside the window, consider + QApplication::setOverrideCursor(). + \sa QApplication::setOverrideCursor() */ -- cgit v0.12 From f37bd111f7622a34b3a7bd63f5a82f6042dc0f0d Mon Sep 17 00:00:00 2001 From: Norwegian Rock Cat Date: Tue, 7 Jul 2009 16:46:30 +0200 Subject: Stop showing then hiding windows on starting designer in top-level mode. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We've had this since 4.5 and it's very annoying to see the window show and quickly hide itself. I was hoping it wasn't a bug in Qt, and it turns it isn't and it was happening on all platforms. Reviewed-by: Friedemann Kleint Shout outs: João for testing. --- tools/designer/src/designer/qdesigner_workbench.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/designer/src/designer/qdesigner_workbench.cpp b/tools/designer/src/designer/qdesigner_workbench.cpp index 923687a2..ce8dde6 100644 --- a/tools/designer/src/designer/qdesigner_workbench.cpp +++ b/tools/designer/src/designer/qdesigner_workbench.cpp @@ -462,8 +462,7 @@ void QDesignerWorkbench::switchToTopLevelMode() // make sure that the widgetbox is visible if it is different from neutral. QDesignerToolWindow *widgetBoxWrapper = widgetBoxToolWindow(); Q_ASSERT(widgetBoxWrapper); - if (!widgetBoxWrapper->action()->isChecked()) - widgetBoxWrapper->action()->trigger(); + const bool needWidgetBoxWrapperVisible = widgetBoxWrapper->action()->isChecked(); switchToNeutralMode(); const QPoint desktopOffset = desktopGeometry().topLeft(); @@ -502,7 +501,7 @@ void QDesignerWorkbench::switchToTopLevelMode() found_visible_window |= tw->isVisible(); } - if (!widgetBoxWrapper->action()->isChecked()) + if (needWidgetBoxWrapperVisible) widgetBoxWrapper->action()->trigger(); if (!m_toolWindows.isEmpty() && !found_visible_window) -- cgit v0.12 From e5049ecc4590896a75dedcb098da9e991e1764ee Mon Sep 17 00:00:00 2001 From: Derick Hawcroft Date: Wed, 8 Jul 2009 09:20:31 +1000 Subject: Handle special number cases (nan,{+-}infinity) in PostgreSQL When contructing the EXECUTE statement, there is a special case that we need to handle whereby we explicitly put quotes around the special float values before submutting the statement for execution Task-number:233829 Reviewed-by: Bill King --- src/sql/drivers/psql/qsql_psql.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/sql/drivers/psql/qsql_psql.cpp b/src/sql/drivers/psql/qsql_psql.cpp index 69697da..64b2a23 100644 --- a/src/sql/drivers/psql/qsql_psql.cpp +++ b/src/sql/drivers/psql/qsql_psql.cpp @@ -54,6 +54,8 @@ #include #include +#include + #include #include @@ -1144,6 +1146,21 @@ QString QPSQLDriver::formatValue(const QSqlField &field, bool trimStrings) const qPQfreemem(data); break; } + case QVariant::Double: { + double val = field.value().toDouble(); + if (isnan(val)) + r = QLatin1String("'NaN'"); + else { + int res = isinf(val); + if (res == 1) + r = QLatin1String("'Infinity'"); + else if (res == -1) + r = QLatin1String("'-Infinity'"); + else + r = QSqlDriver::formatValue(field, trimStrings); + } + break; + } default: r = QSqlDriver::formatValue(field, trimStrings); break; -- cgit v0.12 From c2198e1c7884b835807e45ff53c3c54e86900211 Mon Sep 17 00:00:00 2001 From: Derick Hawcroft Date: Wed, 8 Jul 2009 09:29:33 +1000 Subject: Auto test for task 233829 - postgreSQL specific autotest. Task-number:233829 --- tests/auto/qsqlquery/tst_qsqlquery.cpp | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/tests/auto/qsqlquery/tst_qsqlquery.cpp b/tests/auto/qsqlquery/tst_qsqlquery.cpp index ed19e91..4b41eaf 100644 --- a/tests/auto/qsqlquery/tst_qsqlquery.cpp +++ b/tests/auto/qsqlquery/tst_qsqlquery.cpp @@ -188,6 +188,9 @@ private slots: void task_205701_data() { generic_data("QMYSQL"); } void task_205701(); + void task_233829_data() { generic_data(); } + void task_233829(); + private: // returns all database connections @@ -301,7 +304,7 @@ void tst_QSqlQuery::dropTestTables( QSqlDatabase db ) tablenames << qTableName( "qtest_lockedtable" ); tablenames << qTableName( "Planet" ); - + tablenames << qTableName( "task_250026" ); tst_Databases::safeDropTables( db, tablenames ); @@ -2814,5 +2817,30 @@ void tst_QSqlQuery::task_234422() #endif +void tst_QSqlQuery::task_233829() +{ + QFETCH( QString, dbName ); + QSqlDatabase db = QSqlDatabase::database( dbName ); + CHECK_DATABASE( db ); + + if (!db.driverName().startsWith( "QPSQL" )) { + QSKIP( "This is a PostgreSQL specific test", SkipSingle ); + } + + QSqlQuery q( db ); + QString tableName = qTableName("task_233829"); + q.exec("DROP TABLE " + tableName); + QVERIFY_SQL(q,exec("CREATE TABLE " + tableName + " (dbl1 double precision,dbl2 double precision) without oids;")); + + QString queryString("INSERT INTO " + tableName +"(dbl1, dbl2) VALUES(?,?)"); + + double k = 0.0; + QVERIFY_SQL(q,prepare(queryString)); + q.bindValue(0,0.0 / k); // nan + q.bindValue(1,0.0 / k); // nan + QVERIFY_SQL(q,exec()); + q.exec("DROP TABLE " + tableName); +} + QTEST_MAIN( tst_QSqlQuery ) #include "tst_qsqlquery.moc" -- cgit v0.12 From 529df6f1dbcf8992417d03ef2c9c3ec3f2d7bc4b Mon Sep 17 00:00:00 2001 From: Derick Hawcroft Date: Wed, 8 Jul 2009 09:39:53 +1000 Subject: remove debug --- src/sql/drivers/psql/qsql_psql.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sql/drivers/psql/qsql_psql.cpp b/src/sql/drivers/psql/qsql_psql.cpp index 64b2a23..8de79a3 100644 --- a/src/sql/drivers/psql/qsql_psql.cpp +++ b/src/sql/drivers/psql/qsql_psql.cpp @@ -54,7 +54,6 @@ #include #include -#include #include #include -- cgit v0.12 From 355d058a0c7eba3ae3b2a54dda566d94a4134941 Mon Sep 17 00:00:00 2001 From: Derick Hawcroft Date: Wed, 8 Jul 2009 10:50:09 +1000 Subject: safely drop tables. --- tests/auto/qsqlquery/tst_qsqlquery.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/auto/qsqlquery/tst_qsqlquery.cpp b/tests/auto/qsqlquery/tst_qsqlquery.cpp index 4b41eaf..30b85e8 100644 --- a/tests/auto/qsqlquery/tst_qsqlquery.cpp +++ b/tests/auto/qsqlquery/tst_qsqlquery.cpp @@ -295,6 +295,9 @@ void tst_QSqlQuery::dropTestTables( QSqlDatabase db ) << qTableName( "blobstest" ) << qTableName( "oraRowId" ); + if ( db.driverName().startsWith("QPSQL") ) + tablenames <<"task_233829"; + if ( db.driverName().startsWith("QSQLITE") ) tablenames << qTableName( "record_sqlite" ); @@ -2839,7 +2842,6 @@ void tst_QSqlQuery::task_233829() q.bindValue(0,0.0 / k); // nan q.bindValue(1,0.0 / k); // nan QVERIFY_SQL(q,exec()); - q.exec("DROP TABLE " + tableName); } QTEST_MAIN( tst_QSqlQuery ) -- cgit v0.12 From 5ff22b1ed4da11dc16a236825c939b5ae38d27cc Mon Sep 17 00:00:00 2001 From: Bill King Date: Wed, 8 Jul 2009 11:09:42 +1000 Subject: Fixes Dericks inf/nan patch for msvc --- src/sql/drivers/psql/qsql_psql.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/sql/drivers/psql/qsql_psql.cpp b/src/sql/drivers/psql/qsql_psql.cpp index 8de79a3..33f2e2b 100644 --- a/src/sql/drivers/psql/qsql_psql.cpp +++ b/src/sql/drivers/psql/qsql_psql.cpp @@ -59,7 +59,20 @@ #include #include +#if defined(_MSC_VER) +#include +#define isnan(x) _isnan(x) +int isinf(double x) +{ + if(_fpclass(x) == _FPCLASS_NINF) + return -1; + else if(_fpclass(x) == _FPCLASS_PINF) + return 1; + else return 0; +} +#else #include +#endif // workaround for postgres defining their OIDs in a private header file #define QBOOLOID 16 -- cgit v0.12 From b2e62931f1b2968a69aa013b27a50d2e6beb4e27 Mon Sep 17 00:00:00 2001 From: Bill King Date: Wed, 8 Jul 2009 11:17:40 +1000 Subject: Cleanup more SQL autotest failures. --- tests/auto/qsqldatabase/tst_databases.h | 13 +++++++++++++ tests/auto/qsqldatabase/tst_qsqldatabase.cpp | 7 ++++++- tests/auto/qsqlquery/tst_qsqlquery.cpp | 20 +++++++++----------- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/tests/auto/qsqldatabase/tst_databases.h b/tests/auto/qsqldatabase/tst_databases.h index bd51b97..8ee74df 100644 --- a/tests/auto/qsqldatabase/tst_databases.h +++ b/tests/auto/qsqldatabase/tst_databases.h @@ -249,12 +249,15 @@ public: // addDb( "QODBC3", "DRIVER={SQL Native Client};SERVER=silence.nokia.troll.no\\SQLEXPRESS", "troll", "trond", "" ); // addDb( "QODBC", "DRIVER={MySQL ODBC 3.51 Driver};SERVER=mysql5-nokia.trolltech.com.au;DATABASE=testdb", "testuser", "Ee4Gabf6_", "" ); +// addDb( "QODBC", "DRIVER={MySQL ODBC 5.1 Driver};SERVER=mysql4-nokia.trolltech.com.au;DATABASE=testdb", "testuser", "Ee4Gabf6_", "" ); // addDb( "QODBC", "DRIVER={FreeTDS};SERVER=horsehead.nokia.troll.no;DATABASE=testdb;PORT=4101;UID=troll;PWD=trondk", "troll", "trondk", "" ); // addDb( "QODBC", "DRIVER={FreeTDS};SERVER=silence.nokia.troll.no;DATABASE=testdb;PORT=2392;UID=troll;PWD=trond", "troll", "trond", "" ); // addDb( "QODBC", "DRIVER={FreeTDS};SERVER=bq-winserv2003-x86-01.apac.nokia.com;DATABASE=testdb;PORT=1433;UID=testuser;PWD=Ee4Gabf6_;TDS_Version=8.0", "", "", "" ); // addDb( "QODBC", "DRIVER={FreeTDS};SERVER=bq-winserv2008-x86-01.apac.nokia.com;DATABASE=testdb;PORT=1433;UID=testuser;PWD=Ee4Gabf6_;TDS_Version=8.0", "", "", "" ); // addDb( "QTDS7", "testdb", "testuser", "Ee4Gabf6_", "bq-winserv2003" ); // addDb( "QTDS7", "testdb", "testuser", "Ee4Gabf6_", "bq-winserv2008" ); +// addDb( "QODBC3", "DRIVER={SQL SERVER};SERVER=bq-winserv2003-x86-01.apac.nokia.com;DATABASE=testdb;PORT=1433", "testuser", "Ee4Gabf6_", "" ); +// addDb( "QODBC3", "DRIVER={SQL SERVER};SERVER=bq-winserv2008-x86-01.apac.nokia.com;DATABASE=testdb;PORT=1433", "testuser", "Ee4Gabf6_", "" ); } void open() @@ -438,6 +441,16 @@ public: return db.databaseName().contains( "Access Driver", Qt::CaseInsensitive ); } + static bool isPostgreSQL( QSqlDatabase db ) + { + return db.driverName().startsWith("QPSQL") || (db.driverName().startsWith("QODBC") && db.databaseName().contains("PostgreSQL") ); + } + + static bool isMySQL( QSqlDatabase db ) + { + return db.driverName().startsWith("QMYSQL") || (db.driverName().startsWith("QODBC") && db.databaseName().contains("MySQL") ); + } + // -1 on fail, else Oracle version static int getOraVersion( QSqlDatabase db ) { diff --git a/tests/auto/qsqldatabase/tst_qsqldatabase.cpp b/tests/auto/qsqldatabase/tst_qsqldatabase.cpp index 21064c3..025e895 100644 --- a/tests/auto/qsqldatabase/tst_qsqldatabase.cpp +++ b/tests/auto/qsqldatabase/tst_qsqldatabase.cpp @@ -256,6 +256,8 @@ static int createFieldTable(const FieldDef fieldDefs[], QSqlDatabase db) QString autoName = tst_Databases::autoFieldName(db); if (tst_Databases::isMSAccess(db)) qs.append(" (id int not null"); + else if (tst_Databases::isPostgreSQL(db)) + qs.append(" (id serial not null"); else qs.append(QString("(id integer not null %1 primary key").arg(autoName)); @@ -1350,6 +1352,8 @@ void tst_QSqlDatabase::transaction() } QVERIFY_SQL(q, exec("select * from " + qTableName("qtest") + " where id = 41")); + if(db.driverName().startsWith("QODBC") && dbName.contains("MySQL")) + QEXPECT_FAIL("", "Some odbc drivers don't actually roll back despite telling us they do, especially the mysql driver", Continue); QVERIFY(!q.next()); populateTestTables(db); @@ -1427,7 +1431,8 @@ void tst_QSqlDatabase::caseSensivity() bool cs = false; if (db.driverName().startsWith("QMYSQL") || db.driverName().startsWith("QSQLITE") - || db.driverName().startsWith("QTDS")) + || db.driverName().startsWith("QTDS") + || db.driverName().startsWith("QODBC")) cs = true; QSqlRecord rec = db.record(qTableName("qtest")); diff --git a/tests/auto/qsqlquery/tst_qsqlquery.cpp b/tests/auto/qsqlquery/tst_qsqlquery.cpp index 30b85e8..5e782ca 100644 --- a/tests/auto/qsqlquery/tst_qsqlquery.cpp +++ b/tests/auto/qsqlquery/tst_qsqlquery.cpp @@ -188,7 +188,7 @@ private slots: void task_205701_data() { generic_data("QMYSQL"); } void task_205701(); - void task_233829_data() { generic_data(); } + void task_233829_data() { generic_data("QPSQL"); } void task_233829(); @@ -322,7 +322,10 @@ void tst_QSqlQuery::createTestTables( QSqlDatabase db ) // in the MySQL server startup script q.exec( "set table_type=innodb" ); - QVERIFY_SQL( q, exec( "create table " + qTableName( "qtest" ) + " (id int "+tst_Databases::autoFieldName(db) +" NOT NULL, t_varchar varchar(20), t_char char(20), primary key(id))" ) ); + if(tst_Databases::isPostgreSQL(db)) + QVERIFY_SQL( q, exec( "create table " + qTableName( "qtest" ) + " (id serial NOT NULL, t_varchar varchar(20), t_char char(20), primary key(id)) WITH OIDS" ) ); + else + QVERIFY_SQL( q, exec( "create table " + qTableName( "qtest" ) + " (id int "+tst_Databases::autoFieldName(db) +" NOT NULL, t_varchar varchar(20), t_char char(20), primary key(id))" ) ); if ( tst_Databases::isSqlServer( db ) || db.driverName().startsWith( "QTDS" ) ) QVERIFY_SQL( q, exec( "create table " + qTableName( "qtest_null" ) + " (id int null, t_varchar varchar(20) null)" ) ); @@ -1874,7 +1877,7 @@ void tst_QSqlQuery::invalidQuery() QVERIFY( !q.next() ); QVERIFY( !q.isActive() ); - if ( !db.driverName().startsWith( "QOCI" ) && !db.driverName().startsWith( "QDB2" ) ) { + if ( !db.driverName().startsWith( "QOCI" ) && !db.driverName().startsWith( "QDB2" ) && !db.driverName().startsWith( "QODBC" ) ) { // oracle and db2 just prepares everything without complaining if ( db.driver()->hasFeature( QSqlDriver::PreparedQueries ) ) QVERIFY( !q.prepare( "blahfasel" ) ); @@ -2034,7 +2037,7 @@ void tst_QSqlQuery::oraArrayBind() q.bindValue( 0, list, QSql::In ); - QVERIFY_SQL( q, execBatch( QSqlQuery::ValuesAsRows ) ); + QVERIFY_SQL( q, execBatch( QSqlQuery::ValuesAsColumns ) ); QVERIFY_SQL( q, prepare( "BEGIN " "ora_array_test.get_table(?); " @@ -2046,7 +2049,7 @@ void tst_QSqlQuery::oraArrayBind() q.bindValue( 0, list, QSql::Out ); - QVERIFY_SQL( q, execBatch( QSqlQuery::ValuesAsRows ) ); + QVERIFY_SQL( q, execBatch( QSqlQuery::ValuesAsColumns ) ); QVariantList out_list = q.boundValue( 0 ).toList(); @@ -2593,7 +2596,7 @@ void tst_QSqlQuery::blobsPreparedQuery() if ( db.driverName().startsWith( "QPSQL" ) ) typeName = "BYTEA"; - else if ( db.driverName().startsWith( "QODBC" ) ) + else if ( db.driverName().startsWith( "QODBC" ) && tst_Databases::isSqlServer( db )) typeName = "IMAGE"; QVERIFY_SQL( q, exec( QString( "CREATE TABLE %1(id INTEGER, data %2)" ).arg( tableName ).arg( typeName ) ) ); @@ -2826,13 +2829,8 @@ void tst_QSqlQuery::task_233829() QSqlDatabase db = QSqlDatabase::database( dbName ); CHECK_DATABASE( db ); - if (!db.driverName().startsWith( "QPSQL" )) { - QSKIP( "This is a PostgreSQL specific test", SkipSingle ); - } - QSqlQuery q( db ); QString tableName = qTableName("task_233829"); - q.exec("DROP TABLE " + tableName); QVERIFY_SQL(q,exec("CREATE TABLE " + tableName + " (dbl1 double precision,dbl2 double precision) without oids;")); QString queryString("INSERT INTO " + tableName +"(dbl1, dbl2) VALUES(?,?)"); -- cgit v0.12 From 291279cc24aa543454953b93b1db026caf0d7eb6 Mon Sep 17 00:00:00 2001 From: Bill King Date: Wed, 8 Jul 2009 11:52:38 +1000 Subject: Make the table actually delete before the autotest --- tests/auto/qsqlquery/tst_qsqlquery.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/qsqlquery/tst_qsqlquery.cpp b/tests/auto/qsqlquery/tst_qsqlquery.cpp index 5e782ca..c94b693 100644 --- a/tests/auto/qsqlquery/tst_qsqlquery.cpp +++ b/tests/auto/qsqlquery/tst_qsqlquery.cpp @@ -296,7 +296,7 @@ void tst_QSqlQuery::dropTestTables( QSqlDatabase db ) << qTableName( "oraRowId" ); if ( db.driverName().startsWith("QPSQL") ) - tablenames <<"task_233829"; + tablenames << qTableName("task_233829"); if ( db.driverName().startsWith("QSQLITE") ) tablenames << qTableName( "record_sqlite" ); -- cgit v0.12 From 9e2b47da3b88c63acb1b3a8cb7566f2a1e0e18ff Mon Sep 17 00:00:00 2001 From: Derick Hawcroft Date: Wed, 8 Jul 2009 14:47:21 +1000 Subject: make test behave like others --- tests/auto/qsqlquery/tst_qsqlquery.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/qsqlquery/tst_qsqlquery.cpp b/tests/auto/qsqlquery/tst_qsqlquery.cpp index c94b693..0e30873 100644 --- a/tests/auto/qsqlquery/tst_qsqlquery.cpp +++ b/tests/auto/qsqlquery/tst_qsqlquery.cpp @@ -2831,7 +2831,7 @@ void tst_QSqlQuery::task_233829() QSqlQuery q( db ); QString tableName = qTableName("task_233829"); - QVERIFY_SQL(q,exec("CREATE TABLE " + tableName + " (dbl1 double precision,dbl2 double precision) without oids;")); + QVERIFY_SQL(q,exec("CREATE TABLE " + tableName + "(dbl1 double precision,dbl2 double precision) without oids;")); QString queryString("INSERT INTO " + tableName +"(dbl1, dbl2) VALUES(?,?)"); -- cgit v0.12 From ed4c85c33683ce541590639f19adcef8dcd001a8 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 8 Jul 2009 12:09:08 +0200 Subject: don't drop all location tags after the first file without any Task-number: 256647 --- tools/linguist/lupdate/main.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/linguist/lupdate/main.cpp b/tools/linguist/lupdate/main.cpp index c28bf8b..52a57fb 100644 --- a/tools/linguist/lupdate/main.cpp +++ b/tools/linguist/lupdate/main.cpp @@ -178,9 +178,10 @@ static void updateTsFiles(const Translator &fetchedTor, const QStringList &tsFil if (options & Verbose) printOut(QObject::tr("Updating '%1'...\n").arg(fn)); + UpdateOptions theseOptions = options; if (tor.locationsType() == Translator::NoLocations) // Could be set from file - options |= NoLocations; - Translator out = merge(tor, fetchedTor, options, err); + theseOptions |= NoLocations; + Translator out = merge(tor, fetchedTor, theseOptions, err); if (!codecForTr.isEmpty()) out.setCodecName(codecForTr); -- cgit v0.12 From 48f049d6fbddd60d99fb6ebc15fd5b52a3b515ec Mon Sep 17 00:00:00 2001 From: Benjamin Poulain Date: Wed, 8 Jul 2009 16:23:21 +0200 Subject: Update QGroupBox on focus We cannot assume the position of the decorations when a QGroupBox get the focus. Task-number: 257660 Reviewed-by: Thierry --- src/gui/widgets/qgroupbox.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/gui/widgets/qgroupbox.cpp b/src/gui/widgets/qgroupbox.cpp index fe882a6..022c377 100644 --- a/src/gui/widgets/qgroupbox.cpp +++ b/src/gui/widgets/qgroupbox.cpp @@ -479,11 +479,7 @@ void QGroupBox::focusInEvent(QFocusEvent *fe) if (focusPolicy() == Qt::NoFocus) { d->_q_fixFocus(fe->reason()); } else { - QStyleOptionGroupBox box; - initStyleOption(&box); - QRect rect = style()->subControlRect(QStyle::CC_GroupBox, &box, QStyle::SC_GroupBoxCheckBox, this) - | style()->subControlRect(QStyle::CC_GroupBox, &box, QStyle::SC_GroupBoxLabel, this); - update(rect); + QWidget::focusInEvent(fe); } } -- cgit v0.12 From 1336f8268512a4ad29732acf75f2e6c4d41683ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 7 Jul 2009 10:31:52 +0200 Subject: Reduce QTransform operations in Graphics View. Use the item's cached scene transform directly instead of always making a copy of it. Moreover, we don't have to use the transform at all if the scene transform is a "translate only" transform :-). QTransform already use the same cut-offs, but it must update the type() before it can find out. We don't have to check the type() because that is already stored (and we usually don't call type() when we store the value either). All auto-tests pass. --- src/gui/graphicsview/qgraphicsitem.cpp | 140 +++++++++++++++++++++++++------- src/gui/graphicsview/qgraphicsitem_p.h | 16 +++- src/gui/graphicsview/qgraphicsscene.cpp | 86 +++++++++++++------- src/gui/graphicsview/qgraphicsview.cpp | 7 +- 4 files changed, 188 insertions(+), 61 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 9a27ef5..85d76d4 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -821,6 +821,42 @@ void QGraphicsItemPrivate::combineTransformFromParent(QTransform *x, const QTran } } +void QGraphicsItemPrivate::updateSceneTransformFromParent() +{ + if (parent) { + Q_ASSERT(!parent->d_ptr->dirtySceneTransform); + if (parent->d_ptr->sceneTransformTranslateOnly) { + sceneTransform = QTransform::fromTranslate(parent->d_ptr->sceneTransform.dx() + pos.x(), + parent->d_ptr->sceneTransform.dy() + pos.y()); + } else { + sceneTransform = parent->d_ptr->sceneTransform; + sceneTransform.translate(pos.x(), pos.y()); + } + if (transformData) { + sceneTransform = transformData->computedFullTransform(&sceneTransform); + sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate); + } else { + sceneTransformTranslateOnly = parent->d_ptr->sceneTransformTranslateOnly; + } + } else if (!transformData) { + sceneTransform = QTransform::fromTranslate(pos.x(), pos.y()); + sceneTransformTranslateOnly = 1; + } else if (transformData->onlyTransform) { + sceneTransform = transformData->transform; + if (!pos.isNull()) + sceneTransform *= QTransform::fromTranslate(pos.x(), pos.y()); + sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate); + } else if (pos.isNull()) { + sceneTransform = transformData->computedFullTransform(); + sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate); + } else { + sceneTransform = QTransform::fromTranslate(pos.x(), pos.y()); + sceneTransform = transformData->computedFullTransform(&sceneTransform); + sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate); + } + dirtySceneTransform = 0; +} + /*! \internal @@ -3145,7 +3181,8 @@ void QGraphicsItem::setTransformOrigin(const QPointF &origin) */ QMatrix QGraphicsItem::sceneMatrix() const { - return sceneTransform().toAffine(); + d_ptr->ensureSceneTransform(); + return d_ptr->sceneTransform.toAffine(); } @@ -3168,16 +3205,7 @@ QMatrix QGraphicsItem::sceneMatrix() const */ QTransform QGraphicsItem::sceneTransform() const { - if (d_ptr->dirtySceneTransform) { - // This item and all its descendants have dirty scene transforms. - // We're about to validate this item's scene transform, so we have to - // invalidate all the children; otherwise there's no way for the descendants - // to detect that the ancestor has changed. - d_ptr->invalidateChildrenSceneTransform(); - } - - QGraphicsItem *that = const_cast(this); - d_ptr->ensureSceneTransformRecursive(&that); + d_ptr->ensureSceneTransform(); return d_ptr->sceneTransform; } @@ -3207,8 +3235,10 @@ QTransform QGraphicsItem::sceneTransform() const QTransform QGraphicsItem::deviceTransform(const QTransform &viewportTransform) const { // Ensure we return the standard transform if we're not untransformable. - if (!d_ptr->itemIsUntransformable()) - return sceneTransform() * viewportTransform; + if (!d_ptr->itemIsUntransformable()) { + d_ptr->ensureSceneTransform(); + return d_ptr->sceneTransform * viewportTransform; + } // Find the topmost item that ignores view transformations. const QGraphicsItem *untransformedAncestor = this; @@ -3227,7 +3257,8 @@ QTransform QGraphicsItem::deviceTransform(const QTransform &viewportTransform) c } // First translate the base untransformable item. - QPointF mappedPoint = (untransformedAncestor->sceneTransform() * viewportTransform).map(QPointF(0, 0)); + untransformedAncestor->d_ptr->ensureSceneTransform(); + QPointF mappedPoint = (untransformedAncestor->d_ptr->sceneTransform * viewportTransform).map(QPointF(0, 0)); // COMBINE QTransform matrix = QTransform::fromTranslate(mappedPoint.x(), mappedPoint.y()); @@ -3320,8 +3351,11 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co // Find the closest common ancestor. If the two items don't share an // ancestor, then the only way is to combine their scene transforms. const QGraphicsItem *commonAncestor = commonAncestorItem(other); - if (!commonAncestor) - return sceneTransform() * other->sceneTransform().inverted(ok); + if (!commonAncestor) { + d_ptr->ensureSceneTransform(); + other->d_ptr->ensureSceneTransform(); + return d_ptr->sceneTransform * other->d_ptr->sceneTransform.inverted(ok); + } // If the two items are cousins (in sibling branches), map both to the // common ancestor, and combine the two transforms. @@ -3716,7 +3750,13 @@ QRectF QGraphicsItem::sceneBoundingRect() const QRectF br = boundingRect(); br.translate(offset); - return !parentItem ? br : parentItem->sceneTransform().mapRect(br); + if (!parentItem) + return br; + if (parentItem->d_ptr->hasTranslateOnlySceneTransform()) { + br.translate(parentItem->d_ptr->sceneTransform.dx(), parentItem->d_ptr->sceneTransform.dy()); + return br; + } + return parentItem->d_ptr->sceneTransform.mapRect(br); } /*! @@ -4484,9 +4524,22 @@ void QGraphicsItemPrivate::ensureSceneTransformRecursive(QGraphicsItem **topMost } // COMBINE my transform with the parent's scene transform. - sceneTransform = parent ? parent->d_ptr->sceneTransform : QTransform(); - combineTransformFromParent(&sceneTransform); - dirtySceneTransform = 0; + updateSceneTransformFromParent(); + Q_ASSERT(!dirtySceneTransform); +} + +void QGraphicsItemPrivate::ensureSceneTransform() +{ + if (dirtySceneTransform) { + // This item and all its descendants have dirty scene transforms. + // We're about to validate this item's scene transform, so we have to + // invalidate all the children; otherwise there's no way for the descendants + // to detect that the ancestor has changed. + invalidateChildrenSceneTransform(); + } + + QGraphicsItem *that = q_func(); + ensureSceneTransformRecursive(&that); } /*! @@ -4827,7 +4880,9 @@ QPointF QGraphicsItem::mapToParent(const QPointF &point) const */ QPointF QGraphicsItem::mapToScene(const QPointF &point) const { - return sceneTransform().map(point); + if (d_ptr->hasTranslateOnlySceneTransform()) + return QPointF(point.x() + d_ptr->sceneTransform.dx(), point.y() + d_ptr->sceneTransform.dy()); + return d_ptr->sceneTransform.map(point); } /*! @@ -4894,7 +4949,9 @@ QPolygonF QGraphicsItem::mapToParent(const QRectF &rect) const */ QPolygonF QGraphicsItem::mapToScene(const QRectF &rect) const { - return sceneTransform().map(rect); + if (d_ptr->hasTranslateOnlySceneTransform()) + return rect.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy()); + return d_ptr->sceneTransform.map(rect); } /*! @@ -4967,7 +5024,9 @@ QRectF QGraphicsItem::mapRectToParent(const QRectF &rect) const */ QRectF QGraphicsItem::mapRectToScene(const QRectF &rect) const { - return sceneTransform().mapRect(rect); + if (d_ptr->hasTranslateOnlySceneTransform()) + return rect.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy()); + return d_ptr->sceneTransform.mapRect(rect); } /*! @@ -5041,7 +5100,9 @@ QRectF QGraphicsItem::mapRectFromParent(const QRectF &rect) const */ QRectF QGraphicsItem::mapRectFromScene(const QRectF &rect) const { - return sceneTransform().inverted().mapRect(rect); + if (d_ptr->hasTranslateOnlySceneTransform()) + return rect.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy()); + return d_ptr->sceneTransform.inverted().mapRect(rect); } /*! @@ -5093,7 +5154,9 @@ QPolygonF QGraphicsItem::mapToParent(const QPolygonF &polygon) const */ QPolygonF QGraphicsItem::mapToScene(const QPolygonF &polygon) const { - return sceneTransform().map(polygon); + if (d_ptr->hasTranslateOnlySceneTransform()) + return polygon.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy()); + return d_ptr->sceneTransform.map(polygon); } /*! @@ -5138,7 +5201,9 @@ QPainterPath QGraphicsItem::mapToParent(const QPainterPath &path) const */ QPainterPath QGraphicsItem::mapToScene(const QPainterPath &path) const { - return sceneTransform().map(path); + if (d_ptr->hasTranslateOnlySceneTransform()) + return path.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy()); + return d_ptr->sceneTransform.map(path); } /*! @@ -5199,7 +5264,9 @@ QPointF QGraphicsItem::mapFromParent(const QPointF &point) const */ QPointF QGraphicsItem::mapFromScene(const QPointF &point) const { - return sceneTransform().inverted().map(point); + if (d_ptr->hasTranslateOnlySceneTransform()) + return QPointF(point.x() - d_ptr->sceneTransform.dx(), point.y() - d_ptr->sceneTransform.dy()); + return d_ptr->sceneTransform.inverted().map(point); } /*! @@ -5267,7 +5334,9 @@ QPolygonF QGraphicsItem::mapFromParent(const QRectF &rect) const */ QPolygonF QGraphicsItem::mapFromScene(const QRectF &rect) const { - return sceneTransform().inverted().map(rect); + if (d_ptr->hasTranslateOnlySceneTransform()) + return rect.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy()); + return d_ptr->sceneTransform.inverted().map(rect); } /*! @@ -5317,7 +5386,9 @@ QPolygonF QGraphicsItem::mapFromParent(const QPolygonF &polygon) const */ QPolygonF QGraphicsItem::mapFromScene(const QPolygonF &polygon) const { - return sceneTransform().inverted().map(polygon); + if (d_ptr->hasTranslateOnlySceneTransform()) + return polygon.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy()); + return d_ptr->sceneTransform.inverted().map(polygon); } /*! @@ -5360,7 +5431,9 @@ QPainterPath QGraphicsItem::mapFromParent(const QPainterPath &path) const */ QPainterPath QGraphicsItem::mapFromScene(const QPainterPath &path) const { - return sceneTransform().inverted().map(path); + if (d_ptr->hasTranslateOnlySceneTransform()) + return path.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy()); + return d_ptr->sceneTransform.inverted().map(path); } /*! @@ -6492,7 +6565,12 @@ void QGraphicsItem::prepareGeometryChange() // _q_processDirtyItems is called before _q_emitUpdated. if ((scenePrivate->connectedSignals & scenePrivate->changedSignalMask) || scenePrivate->views.isEmpty()) { - d_ptr->scene->update(sceneTransform().mapRect(boundingRect())); + if (d_ptr->hasTranslateOnlySceneTransform()) { + d_ptr->scene->update(boundingRect().translated(d_ptr->sceneTransform.dx(), + d_ptr->sceneTransform.dy())); + } else { + d_ptr->scene->update(d_ptr->sceneTransform.mapRect(boundingRect())); + } } } diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 99865b0..3ba77b7 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -164,6 +164,7 @@ public: ignoreOpacity(0), acceptTouchEvents(0), acceptedTouchBeginEvent(0), + sceneTransformTranslateOnly(0), globalStackingOrder(-1), q_ptr(0) { @@ -194,6 +195,7 @@ public: void combineTransformToParent(QTransform *x, const QTransform *viewTransform = 0) const; void combineTransformFromParent(QTransform *x, const QTransform *viewTransform = 0) const; + void updateSceneTransformFromParent(); // ### Qt 5: Remove. Workaround for reimplementation added after Qt 4.4. virtual QVariant inputMethodQueryHelper(Qt::InputMethodQuery query) const; @@ -303,6 +305,13 @@ public: void invalidateCachedClipPathRecursively(bool childrenOnly = false, const QRectF &emptyIfOutsideThisRect = QRectF()); void updateCachedClipPathFromSetPosHelper(const QPointF &newPos); void ensureSceneTransformRecursive(QGraphicsItem **topMostDirtyItem); + void ensureSceneTransform(); + + inline bool hasTranslateOnlySceneTransform() + { + ensureSceneTransform(); + return sceneTransformTranslateOnly; + } inline void invalidateChildrenSceneTransform() { @@ -469,7 +478,8 @@ public: quint32 ignoreOpacity : 1; quint32 acceptTouchEvents : 1; quint32 acceptedTouchBeginEvent : 1; - quint32 unused : 10; // feel free to use + quint32 sceneTransformTranslateOnly : 1; + quint32 unused : 9; // feel free to use // Optional stacking order int globalStackingOrder; @@ -500,6 +510,10 @@ struct QGraphicsItemPrivate::TransformData { if (onlyTransform) { if (!postmultiplyTransform) return transform; + if (postmultiplyTransform->isIdentity()) + return transform; + if (transform.isIdentity()) + return *postmultiplyTransform; QTransform x(transform); x *= *postmultiplyTransform; return x; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index bae1afd..ae6c53c 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4228,6 +4228,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * QTransform transform(Qt::Uninitialized); QTransform *transformPtr = 0; + bool translateOnlyTransform = false; #define ENSURE_TRANSFORM_PTR \ if (!transformPtr) { \ Q_ASSERT(!itemIsUntransformable); \ @@ -4237,6 +4238,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * transformPtr = &transform; \ } else { \ transformPtr = &item->d_ptr->sceneTransform; \ + translateOnlyTransform = item->d_ptr->sceneTransformTranslateOnly; \ } \ } @@ -4248,10 +4250,8 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * transform = item->deviceTransform(viewTransform ? *viewTransform : QTransform()); transformPtr = &transform; } else if (item->d_ptr->dirtySceneTransform) { - item->d_ptr->sceneTransform = item->d_ptr->parent ? item->d_ptr->parent->d_ptr->sceneTransform - : QTransform(); - item->d_ptr->combineTransformFromParent(&item->d_ptr->sceneTransform); - item->d_ptr->dirtySceneTransform = 0; + item->d_ptr->updateSceneTransformFromParent(); + Q_ASSERT(!item->d_ptr->dirtySceneTransform); wasDirtyParentSceneTransform = true; } @@ -4260,7 +4260,8 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (drawItem) { const QRectF brect = adjustedItemBoundingRect(item); ENSURE_TRANSFORM_PTR - QRect viewBoundingRect = transformPtr->mapRect(brect).toRect(); + QRect viewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy()).toRect() + : transformPtr->mapRect(brect).toRect(); item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect); viewBoundingRect.adjust(-1, -1, 1, 1); drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect) : !viewBoundingRect.isEmpty(); @@ -4416,13 +4417,45 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b } static inline bool updateHelper(QGraphicsViewPrivate *view, QGraphicsItemPrivate *item, - const QRectF &rect, const QTransform &xform) + const QRectF &rect, bool itemIsUntransformable) { Q_ASSERT(view); Q_ASSERT(item); - if (item->hasBoundingRegionGranularity) + + QGraphicsItem *itemq = static_cast(item->q_ptr); + QGraphicsView *viewq = static_cast(view->q_ptr); + + if (itemIsUntransformable) { + const QTransform xform = itemq->deviceTransform(viewq->viewportTransform()); + if (!item->hasBoundingRegionGranularity) + return view->updateRect(xform.mapRect(rect).toRect()); return view->updateRegion(xform.map(QRegion(rect.toRect()))); - return view->updateRect(xform.mapRect(rect).toRect()); + } + + if (item->sceneTransformTranslateOnly && view->identityMatrix) { + const qreal dx = item->sceneTransform.dx(); + const qreal dy = item->sceneTransform.dy(); + if (!item->hasBoundingRegionGranularity) { + QRectF r(rect); + r.translate(dx - view->horizontalScroll(), dy - view->verticalScroll()); + return view->updateRect(r.toRect()); + } + QRegion r(rect.toRect()); + r.translate(qRound(dx) - view->horizontalScroll(), qRound(dy) - view->verticalScroll()); + return view->updateRegion(r); + } + + if (!viewq->isTransformed()) { + if (!item->hasBoundingRegionGranularity) + return view->updateRect(item->sceneTransform.mapRect(rect).toRect()); + return view->updateRegion(item->sceneTransform.map(QRegion(rect.toRect()))); + } + + QTransform xform = item->sceneTransform; + xform *= viewq->viewportTransform(); + if (!item->hasBoundingRegionGranularity) + return view->updateRect(xform.mapRect(rect).toRect()); + return view->updateRegion(xform.map(QRegion(rect.toRect()))); } void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren, @@ -4460,11 +4493,8 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool bool wasDirtyParentSceneTransform = item->d_ptr->dirtySceneTransform; const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable(); if (wasDirtyParentSceneTransform && !itemIsUntransformable) { - // Calculate the full scene transform for this item. - item->d_ptr->sceneTransform = item->d_ptr->parent ? item->d_ptr->parent->d_ptr->sceneTransform - : QTransform(); - item->d_ptr->combineTransformFromParent(&item->d_ptr->sceneTransform); - item->d_ptr->dirtySceneTransform = 0; + item->d_ptr->updateSceneTransformFromParent(); + Q_ASSERT(!item->d_ptr->dirtySceneTransform); } const bool wasDirtyParentViewBoundingRects = item->d_ptr->paintedViewBoundingRectsNeedRepaint; @@ -4479,8 +4509,14 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool if (item->d_ptr->geometryChanged) { // Update growingItemsBoundingRect. - if (!hasSceneRect) - growingItemsBoundingRect |= item->d_ptr->sceneTransform.mapRect(item->boundingRect()); + if (!hasSceneRect) { + if (item->d_ptr->sceneTransformTranslateOnly) { + growingItemsBoundingRect |= item->boundingRect().translated(item->d_ptr->sceneTransform.dx(), + item->d_ptr->sceneTransform.dy()); + } else { + growingItemsBoundingRect |= item->d_ptr->sceneTransform.mapRect(item->boundingRect()); + } + } item->d_ptr->geometryChanged = 0; } @@ -4493,7 +4529,12 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool // This block of code is kept for compatibility. Since 4.5, by default // QGraphicsView does not connect the signal and we use the below // method of delivering updates. - q->update(item->d_ptr->sceneTransform.mapRect(itemBoundingRect)); + if (item->d_ptr->sceneTransformTranslateOnly) { + q->update(itemBoundingRect.translated(item->d_ptr->sceneTransform.dx(), + item->d_ptr->sceneTransform.dy())); + } else { + q->update(item->d_ptr->sceneTransform.mapRect(itemBoundingRect)); + } } else { QRectF dirtyRect; bool uninitializedDirtyRect = true; @@ -4536,18 +4577,7 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool if (dirtyRect.isEmpty()) continue; // Discard updates outside the bounding rect. - bool valid = false; - if (itemIsUntransformable) { - valid = updateHelper(viewPrivate, item->d_ptr, dirtyRect, - item->deviceTransform(view->viewportTransform())); - } else if (!view->isTransformed()) { - valid = updateHelper(viewPrivate, item->d_ptr, dirtyRect, item->d_ptr->sceneTransform); - } else { - QTransform deviceTransform = item->d_ptr->sceneTransform; - deviceTransform *= view->viewportTransform(); - valid = updateHelper(viewPrivate, item->d_ptr, dirtyRect, deviceTransform); - } - if (!valid) + if (!updateHelper(viewPrivate, item->d_ptr, dirtyRect, itemIsUntransformable)) paintedViewBoundingRect = QRect(); } } diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 995f3f3..1e34320 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -1864,7 +1864,12 @@ void QGraphicsView::fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRati void QGraphicsView::fitInView(const QGraphicsItem *item, Qt::AspectRatioMode aspectRatioMode) { QPainterPath path = item->isClipped() ? item->clipPath() : item->shape(); - fitInView(item->sceneTransform().map(path).boundingRect(), aspectRatioMode); + if (item->d_ptr->hasTranslateOnlySceneTransform()) { + path.translate(item->d_ptr->sceneTransform.dx(), item->d_ptr->sceneTransform.dy()); + fitInView(path.boundingRect(), aspectRatioMode); + } else { + fitInView(item->d_ptr->sceneTransform.map(path).boundingRect(), aspectRatioMode); + } } /*! -- cgit v0.12 From 8ca44447283deb333591c6354f16f01f30d74e21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 7 Jul 2009 18:05:51 +0200 Subject: Reduce QTransform operations in QGraphicsSceneIndex. Update the scene transform and use it directly in the same fashion as we do in processDirtyItemsRecursive/drawSubtreeRecursive. All auto-tests pass --- src/gui/graphicsview/qgraphicssceneindex.cpp | 97 +++++++++++++++++++++------- src/gui/graphicsview/qgraphicssceneindex_p.h | 7 +- 2 files changed, 76 insertions(+), 28 deletions(-) diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 5626051..01efde4 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -72,7 +72,7 @@ class QGraphicsSceneIndexRectIntersector : public QGraphicsSceneIndexIntersector { public: bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode, - const QTransform &transform, const QTransform &deviceTransform) const + const QTransform &deviceTransform) const { QRectF brect = item->boundingRect(); _q_adjustRect(&brect); @@ -81,8 +81,10 @@ public: Q_UNUSED(exposeRect); bool keep = true; - if (QGraphicsItemPrivate::get(item)->itemIsUntransformable()) { + const QGraphicsItemPrivate *itemd = QGraphicsItemPrivate::get(item); + if (itemd->itemIsUntransformable()) { // Untransformable items; map the scene rect to item coordinates. + const QTransform transform = item->deviceTransform(deviceTransform); QRectF itemRect = (deviceTransform * transform.inverted()).mapRect(sceneRect); if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) keep = itemRect.contains(brect) && itemRect != brect; @@ -94,14 +96,23 @@ public: keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, itemPath, mode); } } else { + Q_ASSERT(!itemd->dirtySceneTransform); + const QRectF itemSceneBoundingRect = itemd->sceneTransformTranslateOnly + ? brect.translated(itemd->sceneTransform.dx(), + itemd->sceneTransform.dy()) + : itemd->sceneTransform.mapRect(brect); if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) - keep = sceneRect.contains(transform.mapRect(brect)) && sceneRect != brect; + keep = sceneRect != brect && sceneRect.contains(itemSceneBoundingRect); else - keep = sceneRect.intersects(transform.mapRect(brect)); + keep = sceneRect.intersects(itemSceneBoundingRect); if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { QPainterPath rectPath; rectPath.addRect(sceneRect); - keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, transform.inverted().map(rectPath), mode); + if (itemd->sceneTransformTranslateOnly) + rectPath.translate(-itemd->sceneTransform.dx(), -itemd->sceneTransform.dy()); + else + rectPath = itemd->sceneTransform.inverted().map(rectPath); + keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, rectPath, mode); } } return keep; @@ -114,7 +125,7 @@ class QGraphicsSceneIndexPointIntersector : public QGraphicsSceneIndexIntersecto { public: bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode, - const QTransform &transform, const QTransform &deviceTransform) const + const QTransform &deviceTransform) const { QRectF brect = item->boundingRect(); _q_adjustRect(&brect); @@ -123,8 +134,10 @@ public: Q_UNUSED(exposeRect); bool keep = false; - if (QGraphicsItemPrivate::get(item)->itemIsUntransformable()) { + const QGraphicsItemPrivate *itemd = QGraphicsItemPrivate::get(item); + if (itemd->itemIsUntransformable()) { // Untransformable items; map the scene point to item coordinates. + const QTransform transform = item->deviceTransform(deviceTransform); QPointF itemPoint = (deviceTransform * transform.inverted()).map(scenePoint); keep = brect.contains(itemPoint); if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { @@ -133,8 +146,19 @@ public: keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, pointPath, mode); } } else { - QRectF sceneBoundingRect = transform.mapRect(brect); - keep = sceneBoundingRect.intersects(QRectF(scenePoint, QSizeF(1, 1))) && item->contains(transform.inverted().map(scenePoint)); + Q_ASSERT(!itemd->dirtySceneTransform); + QRectF sceneBoundingRect = itemd->sceneTransformTranslateOnly + ? brect.translated(itemd->sceneTransform.dx(), + itemd->sceneTransform.dy()) + : itemd->sceneTransform.mapRect(brect); + keep = sceneBoundingRect.intersects(QRectF(scenePoint, QSizeF(1, 1))); + if (keep) { + QPointF p = itemd->sceneTransformTranslateOnly + ? QPointF(scenePoint.x() - itemd->sceneTransform.dx(), + scenePoint.y() - itemd->sceneTransform.dy()) + : itemd->sceneTransform.inverted().map(scenePoint); + keep = item->contains(p); + } } return keep; @@ -147,7 +171,7 @@ class QGraphicsSceneIndexPathIntersector : public QGraphicsSceneIndexIntersector { public: bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode, - const QTransform &transform, const QTransform &deviceTransform) const + const QTransform &deviceTransform) const { QRectF brect = item->boundingRect(); _q_adjustRect(&brect); @@ -156,8 +180,10 @@ public: Q_UNUSED(exposeRect); bool keep = true; - if (QGraphicsItemPrivate::get(item)->itemIsUntransformable()) { + const QGraphicsItemPrivate *itemd = QGraphicsItemPrivate::get(item); + if (itemd->itemIsUntransformable()) { // Untransformable items; map the scene rect to item coordinates. + const QTransform transform = item->deviceTransform(deviceTransform); QPainterPath itemPath = (deviceTransform * transform.inverted()).map(scenePath); if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) keep = itemPath.contains(brect); @@ -166,12 +192,20 @@ public: if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, itemPath, mode); } else { + Q_ASSERT(!itemd->dirtySceneTransform); + const QRectF itemSceneBoundingRect = itemd->sceneTransformTranslateOnly + ? brect.translated(itemd->sceneTransform.dx(), + itemd->sceneTransform.dy()) + : itemd->sceneTransform.mapRect(brect); if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) - keep = scenePath.contains(transform.mapRect(brect)); + keep = scenePath.contains(itemSceneBoundingRect); else - keep = scenePath.intersects(transform.mapRect(brect)); + keep = scenePath.intersects(itemSceneBoundingRect); if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { - QPainterPath itemPath = transform.inverted().map(scenePath); + QPainterPath itemPath = itemd->sceneTransformTranslateOnly + ? scenePath.translated(-itemd->sceneTransform.dx(), + -itemd->sceneTransform.dy()) + : itemd->sceneTransform.inverted().map(scenePath); keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, itemPath, mode); } } @@ -236,7 +270,6 @@ bool QGraphicsSceneIndexPrivate::itemCollidesWithPath(const QGraphicsItem *item, void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRectF exposeRect, QGraphicsSceneIndexIntersector *intersector, QList *items, - const QTransform &parentTransform, const QTransform &viewTransform, Qt::ItemSelectionMode mode, Qt::SortOrder order, qreal parentOpacity) const @@ -251,16 +284,23 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) return; - // Calculate the full transform for this item. - QTransform transform(parentTransform); - item->d_ptr->combineTransformFromParent(&transform, &viewTransform); + // Update the item's scene transform if dirty. + const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable(); + const bool wasDirtyParentSceneTransform = item->d_ptr->dirtySceneTransform && !itemIsUntransformable; + if (wasDirtyParentSceneTransform) { + item->d_ptr->updateSceneTransformFromParent(); + Q_ASSERT(!item->d_ptr->dirtySceneTransform); + } const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape); bool processItem = !itemIsFullyTransparent; if (processItem) { - processItem = intersector->intersect(item, exposeRect, mode, transform, viewTransform); - if (!processItem && (!itemHasChildren || itemClipsChildrenToShape)) + processItem = intersector->intersect(item, exposeRect, mode, viewTransform); + if (!processItem && (!itemHasChildren || itemClipsChildrenToShape)) { + if (wasDirtyParentSceneTransform) + item->d_ptr->invalidateChildrenSceneTransform(); return; + } } // else we know for sure this item has children we must process. int i = 0; @@ -269,17 +309,24 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe item->d_ptr->ensureSortedChildren(); // Clip to shape. - if (itemClipsChildrenToShape) - exposeRect &= transform.map(item->shape()).controlPointRect(); + if (itemClipsChildrenToShape && !itemIsUntransformable) { + QPainterPath mappedShape = item->d_ptr->sceneTransformTranslateOnly + ? item->shape().translated(item->d_ptr->sceneTransform.dx(), + item->d_ptr->sceneTransform.dy()) + : item->d_ptr->sceneTransform.map(item->shape()); + exposeRect &= mappedShape.controlPointRect(); + } // Process children behind for (i = 0; i < item->d_ptr->children.size(); ++i) { QGraphicsItem *child = item->d_ptr->children.at(i); + if (wasDirtyParentSceneTransform) + child->d_ptr->dirtySceneTransform = 1; if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent)) break; if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)) continue; - recursive_items_helper(child, exposeRect, intersector, items, transform, viewTransform, + recursive_items_helper(child, exposeRect, intersector, items, viewTransform, mode, order, opacity); } } @@ -292,9 +339,11 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe if (itemHasChildren) { for (; i < item->d_ptr->children.size(); ++i) { QGraphicsItem *child = item->d_ptr->children.at(i); + if (wasDirtyParentSceneTransform) + child->d_ptr->dirtySceneTransform = 1; if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)) continue; - recursive_items_helper(child, exposeRect, intersector, items, transform, viewTransform, + recursive_items_helper(child, exposeRect, intersector, items, viewTransform, mode, order, opacity); } } diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h index 6521765..8cf0294 100644 --- a/src/gui/graphicsview/qgraphicssceneindex_p.h +++ b/src/gui/graphicsview/qgraphicssceneindex_p.h @@ -137,7 +137,7 @@ public: void recursive_items_helper(QGraphicsItem *item, QRectF exposeRect, QGraphicsSceneIndexIntersector *intersector, QList *items, - const QTransform &parentTransform, const QTransform &viewTransform, + const QTransform &viewTransform, Qt::ItemSelectionMode mode, Qt::SortOrder order, qreal parentOpacity = 1.0) const; inline void items_helper(const QRectF &rect, QGraphicsSceneIndexIntersector *intersector, QList *items, const QTransform &viewTransform, @@ -155,9 +155,8 @@ inline void QGraphicsSceneIndexPrivate::items_helper(const QRectF &rect, QGraphi { Q_Q(const QGraphicsSceneIndex); const QList tli = q->estimateTopLevelItems(rect, Qt::DescendingOrder); - const QTransform identity; for (int i = 0; i < tli.size(); ++i) - recursive_items_helper(tli.at(i), rect, intersector, items, identity, viewTransform, mode, order); + recursive_items_helper(tli.at(i), rect, intersector, items, viewTransform, mode, order); if (order == Qt::AscendingOrder) { const int n = items->size(); for (int i = 0; i < n / 2; ++i) @@ -171,7 +170,7 @@ public: QGraphicsSceneIndexIntersector() { } virtual ~QGraphicsSceneIndexIntersector() { } virtual bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode, - const QTransform &transform, const QTransform &deviceTransform) const = 0; + const QTransform &deviceTransform) const = 0; }; #endif // QT_NO_GRAPHICSVIEW -- cgit v0.12 From e1b6cd9170d9a20fd3ee1b8d7ef11dcd3364e16d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 8 Jul 2009 12:18:10 +0200 Subject: Optimize QGraphicsViewPrivate::updateRect/updateRegion. We can do QRect::intersects/contains/operator| faster than QRect because we can assume the rects are normalized. Another important factor is our knowledge about the viewport rect, which is always QRect(0, 0, viewport->width(), viewport->height()). Auto-tests included. --- src/gui/graphicsview/qgraphicsview.cpp | 28 ++++-- src/gui/graphicsview/qgraphicsview_p.h | 2 +- tests/auto/qgraphicsview/tst_qgraphicsview.cpp | 115 +++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 7 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 1e34320..b2cc478 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -839,13 +839,29 @@ void QGraphicsViewPrivate::processPendingUpdates() dirtyRegion = QRegion(); } +static inline bool intersectsViewport(const QRect &r, int width, int height) +{ return !(r.left() > width) && !(r.right() < 0) && !(r.top() >= height) && !(r.bottom() < 0); } + +static inline bool containsViewport(const QRect &r, int width, int height) +{ return r.left() <= 0 && r.top() <= 0 && r.right() >= width - 1 && r.bottom() >= height - 1; } + +static inline void QRect_unite(QRect *rect, const QRect &other) +{ + if (rect->isEmpty()) { + *rect = other; + } else { + rect->setCoords(qMin(rect->left(), other.left()), qMin(rect->top(), other.top()), + qMax(rect->right(), other.right()), qMax(rect->bottom(), other.bottom())); + } +} + bool QGraphicsViewPrivate::updateRegion(const QRegion &r) { if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate || r.isEmpty()) return false; const QRect boundingRect = r.boundingRect(); - if (!boundingRect.intersects(viewport->rect())) + if (!intersectsViewport(boundingRect, viewport->width(), viewport->height())) return false; // Update region outside viewport. switch (viewportUpdateMode) { @@ -854,8 +870,8 @@ bool QGraphicsViewPrivate::updateRegion(const QRegion &r) viewport->update(); break; case QGraphicsView::BoundingRectViewportUpdate: - dirtyBoundingRect |= boundingRect; - if (dirtyBoundingRect.contains(viewport->rect())) { + QRect_unite(&dirtyBoundingRect, boundingRect); + if (containsViewport(dirtyBoundingRect, viewport->width(), viewport->height())) { fullUpdatePending = true; viewport->update(); } @@ -882,7 +898,7 @@ bool QGraphicsViewPrivate::updateRegion(const QRegion &r) bool QGraphicsViewPrivate::updateRect(const QRect &r) { if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate - || !r.intersects(viewport->rect())) { + || !intersectsViewport(r, viewport->width(), viewport->height())) { return false; } @@ -892,8 +908,8 @@ bool QGraphicsViewPrivate::updateRect(const QRect &r) viewport->update(); break; case QGraphicsView::BoundingRectViewportUpdate: - dirtyBoundingRect |= r; - if (dirtyBoundingRect.contains(viewport->rect())) { + QRect_unite(&dirtyBoundingRect, r); + if (containsViewport(dirtyBoundingRect, viewport->width(), viewport->height())) { fullUpdatePending = true; viewport->update(); } diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h index 7b9fd5e..6617622 100644 --- a/src/gui/graphicsview/qgraphicsview_p.h +++ b/src/gui/graphicsview/qgraphicsview_p.h @@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE -class QGraphicsViewPrivate : public QAbstractScrollAreaPrivate +class Q_AUTOTEST_EXPORT QGraphicsViewPrivate : public QAbstractScrollAreaPrivate { Q_DECLARE_PUBLIC(QGraphicsView) public: diff --git a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp index 6db8f27..297c437 100644 --- a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp @@ -63,6 +63,7 @@ #include #include #include +#include //TESTED_CLASS= //TESTED_FILES= @@ -175,6 +176,7 @@ private slots: void transformationAnchor(); void resizeAnchor(); void viewportUpdateMode(); + void viewportUpdateMode2(); void acceptDrops(); void optimizationFlags(); void optimizationFlags_dontSavePainterState(); @@ -195,6 +197,8 @@ private slots: void mouseTracking2(); void render(); void exposeRegion(); + void update_data(); + void update(); // task specific tests below me void task172231_untransformableItems(); @@ -2229,6 +2233,52 @@ void tst_QGraphicsView::viewportUpdateMode() QCOMPARE(view.lastUpdateRegions.size(), 0); } +void tst_QGraphicsView::viewportUpdateMode2() +{ + // Create a view with viewport rect equal to QRect(0, 0, 200, 200). + QGraphicsScene dummyScene; + CustomView view; + view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); + view.setScene(&dummyScene); + int left, top, right, bottom; + view.getContentsMargins(&left, &top, &right, &bottom); + view.resize(200 + left + right, 200 + top + bottom); + view.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&view); +#endif + QTest::qWait(300); + const QRect viewportRect = view.viewport()->rect(); + QCOMPARE(viewportRect, QRect(0, 0, 200, 200)); + QGraphicsViewPrivate *viewPrivate = static_cast(qt_widget_private(&view)); + + QRect boundingRect; + const QRect rect1(0, 0, 10, 10); + QVERIFY(viewPrivate->updateRect(rect1)); + QVERIFY(!viewPrivate->fullUpdatePending); + boundingRect |= rect1; + QCOMPARE(viewPrivate->dirtyBoundingRect, boundingRect); + + const QRect rect2(50, 50, 10, 10); + QVERIFY(viewPrivate->updateRect(rect2)); + QVERIFY(!viewPrivate->fullUpdatePending); + boundingRect |= rect2; + QCOMPARE(viewPrivate->dirtyBoundingRect, boundingRect); + + const QRect rect3(190, 190, 10, 10); + QVERIFY(viewPrivate->updateRect(rect3)); + QVERIFY(viewPrivate->fullUpdatePending); + boundingRect |= rect3; + QCOMPARE(viewPrivate->dirtyBoundingRect, boundingRect); + + view.lastUpdateRegions.clear(); + viewPrivate->processPendingUpdates(); + QTest::qWait(50); + QCOMPARE(view.lastUpdateRegions.size(), 1); + // Note that we adjust by 2 for antialiasing. + QCOMPARE(view.lastUpdateRegions.at(0), QRegion(boundingRect.adjusted(-2, -2, 2, 2) & viewportRect)); +} + void tst_QGraphicsView::acceptDrops() { QGraphicsView view; @@ -3351,6 +3401,71 @@ void tst_QGraphicsView::exposeRegion() QCOMPARE(item->paints, 0); } +void tst_QGraphicsView::update_data() +{ + // In view.viewport() coordinates. (viewport rect: QRect(0, 0, 200, 200)) + QTest::addColumn("updateRect"); + QTest::newRow("empty") << QRect(); + QTest::newRow("outside left") << QRect(-200, 0, 100, 100); + QTest::newRow("outside right") << QRect(400, 0 ,100, 100); + QTest::newRow("outside top") << QRect(0, -200, 100, 100); + QTest::newRow("outside bottom") << QRect(0, 400, 100, 100); + QTest::newRow("partially inside left") << QRect(-50, 0, 100, 100); + QTest::newRow("partially inside right") << QRect(-150, 0, 100, 100); + QTest::newRow("partially inside top") << QRect(0, -150, 100, 100); + QTest::newRow("partially inside bottom") << QRect(0, 150, 100, 100); + QTest::newRow("on topLeft edge") << QRect(-100, -100, 100, 100); + QTest::newRow("on topRight edge") << QRect(200, -100, 100, 100); + QTest::newRow("on bottomRight edge") << QRect(200, 200, 100, 100); + QTest::newRow("on bottomLeft edge") << QRect(-200, 200, 100, 100); + QTest::newRow("inside topLeft") << QRect(-99, -99, 100, 100); + QTest::newRow("inside topRight") << QRect(199, -99, 100, 100); + QTest::newRow("inside bottomRight") << QRect(199, 199, 100, 100); + QTest::newRow("inside bottomLeft") << QRect(-199, 199, 100, 100); + QTest::newRow("large1") << QRect(50, -100, 100, 400); + QTest::newRow("large2") << QRect(-100, 50, 400, 100); + QTest::newRow("large3") << QRect(-100, -100, 400, 400); + QTest::newRow("viewport rect") << QRect(0, 0, 200, 200); +} +void tst_QGraphicsView::update() +{ + QFETCH(QRect, updateRect); + + // Create a view with viewport rect equal to QRect(0, 0, 200, 200). + QGraphicsScene dummyScene; + CustomView view; + view.setScene(&dummyScene); + int left, top, right, bottom; + view.getContentsMargins(&left, &top, &right, &bottom); + view.resize(200 + left + right, 200 + top + bottom); + view.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&view); +#endif + QTest::qWait(300); + const QRect viewportRect = view.viewport()->rect(); + QCOMPARE(viewportRect, QRect(0, 0, 200, 200)); + + const bool intersects = updateRect.intersects(viewportRect); + QGraphicsViewPrivate *viewPrivate = static_cast(qt_widget_private(&view)); + QCOMPARE(viewPrivate->updateRect(updateRect), intersects); + QCOMPARE(viewPrivate->updateRegion(updateRect), intersects); + + view.lastUpdateRegions.clear(); + viewPrivate->processPendingUpdates(); + QVERIFY(viewPrivate->dirtyRegion.isEmpty()); + QVERIFY(viewPrivate->dirtyBoundingRect.isEmpty()); + QTest::qWait(50); + if (!intersects) { + QVERIFY(view.lastUpdateRegions.isEmpty()); + } else { + QCOMPARE(view.lastUpdateRegions.size(), 1); + // Note that we adjust by 2 for antialiasing. + QCOMPARE(view.lastUpdateRegions.at(0), QRegion(updateRect.adjusted(-2, -2, 2, 2) & viewportRect)); + } + QVERIFY(!viewPrivate->fullUpdatePending); +} + void tst_QGraphicsView::task253415_reconnectUpdateSceneOnSceneChanged() { QGraphicsView view; -- cgit v0.12 From 34357998f38614a7c724ba4561c0e68b19fffc4a Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Wed, 8 Jul 2009 18:19:21 +0200 Subject: Fix possible crash in QDockAreas --- src/gui/widgets/qdockarealayout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/widgets/qdockarealayout.cpp b/src/gui/widgets/qdockarealayout.cpp index b905ccd..ee29b55 100644 --- a/src/gui/widgets/qdockarealayout.cpp +++ b/src/gui/widgets/qdockarealayout.cpp @@ -1707,7 +1707,7 @@ QDockAreaLayoutItem &QDockAreaLayoutInfo::item(const QList &path) Q_ASSERT(!path.isEmpty()); const int index = path.first(); if (path.count() > 1) { - const QDockAreaLayoutItem &item = item_list.at(index); + const QDockAreaLayoutItem &item = item_list[index]; Q_ASSERT(item.subinfo != 0); return item.subinfo->item(path.mid(1)); } -- cgit v0.12 From cfacb284593008094136905a2497843a4bbac639 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Wed, 8 Jul 2009 18:22:09 +0200 Subject: QPropertyAnimation: save a Q_GLOBAL_STATIC This is possible because we anyway use a Mutex to access the static hash --- src/corelib/animation/qpropertyanimation.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/corelib/animation/qpropertyanimation.cpp b/src/corelib/animation/qpropertyanimation.cpp index 7526a81..5f224aa 100644 --- a/src/corelib/animation/qpropertyanimation.cpp +++ b/src/corelib/animation/qpropertyanimation.cpp @@ -100,10 +100,6 @@ QT_BEGIN_NAMESPACE -typedef QPair QPropertyAnimationPair; -typedef QHash QPropertyAnimationHash; -Q_GLOBAL_STATIC(QPropertyAnimationHash, _q_runningAnimations) - void QPropertyAnimationPrivate::updateMetaProperty() { if (!target || propertyName.isEmpty()) @@ -286,19 +282,21 @@ void QPropertyAnimation::updateState(QAbstractAnimation::State oldState, QPropertyAnimation *animToStop = 0; { - QPropertyAnimationHash * hash = _q_runningAnimations(); - QMutexLocker locker(QMutexPool::globalInstanceGet(hash)); + QMutexLocker locker(QMutexPool::globalInstanceGet(&staticMetaObject)); + typedef QPair QPropertyAnimationPair; + typedef QHash QPropertyAnimationHash; + static QPropertyAnimationHash hash; QPropertyAnimationPair key(d->target, d->propertyName); if (newState == Running) { d->updateMetaProperty(); - animToStop = hash->value(key, 0); - hash->insert(key, this); + animToStop = hash.value(key, 0); + hash.insert(key, this); // update the default start value if (oldState == Stopped) { d->setDefaultStartValue(d->target->property(d->propertyName.constData())); } - } else if (hash->value(key) == this) { - hash->remove(key); + } else if (hash.value(key) == this) { + hash.remove(key); } } -- cgit v0.12 From 6e35b15d75aeb140bf56690ce7369f54342c2739 Mon Sep 17 00:00:00 2001 From: Bill King Date: Thu, 9 Jul 2009 08:41:56 +1000 Subject: Make compile --- src/gui/widgets/qwidgetanimator_p.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/widgets/qwidgetanimator_p.h b/src/gui/widgets/qwidgetanimator_p.h index 64697a9..5a3e39d 100644 --- a/src/gui/widgets/qwidgetanimator_p.h +++ b/src/gui/widgets/qwidgetanimator_p.h @@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE class QWidget; class QMainWindowLayout; class QPropertyAnimation; +class QRect; class QWidgetAnimator : public QObject { -- cgit v0.12 From 53228e1b1993524fb1422a8363647b468b3c7c8d Mon Sep 17 00:00:00 2001 From: Bill King Date: Thu, 9 Jul 2009 09:41:21 +1000 Subject: Hopefully fix isnan/isinf for good (for all platforms) --- src/sql/drivers/psql/qsql_psql.cpp | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/sql/drivers/psql/qsql_psql.cpp b/src/sql/drivers/psql/qsql_psql.cpp index 33f2e2b..4eccf4b 100644 --- a/src/sql/drivers/psql/qsql_psql.cpp +++ b/src/sql/drivers/psql/qsql_psql.cpp @@ -59,21 +59,29 @@ #include #include -#if defined(_MSC_VER) -#include -#define isnan(x) _isnan(x) -int isinf(double x) -{ - if(_fpclass(x) == _FPCLASS_NINF) - return -1; - else if(_fpclass(x) == _FPCLASS_PINF) - return 1; - else return 0; -} -#else #include +// below code taken from an example at http://www.gnu.org/software/hello/manual/autoconf/Function-Portability.html +#ifndef isnan + # define isnan(x) \ + (sizeof (x) == sizeof (long double) ? isnan_ld (x) \ + : sizeof (x) == sizeof (double) ? isnan_d (x) \ + : isnan_f (x)) + static inline int isnan_f (float x) { return x != x; } + static inline int isnan_d (double x) { return x != x; } + static inline int isnan_ld (long double x) { return x != x; } #endif +#ifndef isinf + # define isinf(x) \ + (sizeof (x) == sizeof (long double) ? isinf_ld (x) \ + : sizeof (x) == sizeof (double) ? isinf_d (x) \ + : isinf_f (x)) + static inline int isinf_f (float x) { return isnan (x - x); } + static inline int isinf_d (double x) { return isnan (x - x); } + static inline int isinf_ld (long double x) { return isnan (x - x); } +#endif + + // workaround for postgres defining their OIDs in a private header file #define QBOOLOID 16 #define QINT8OID 20 -- cgit v0.12 From 6cb86a552f4f320b47232ef745ae897ad5ead591 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Thu, 9 Jul 2009 10:56:15 +1000 Subject: Remove some left-over mentions of fixed-point in math3d Reviewed-by: trustme --- src/gui/math3d/qmatrix4x4.cpp | 7 +---- src/gui/math3d/qquaternion.cpp | 4 --- src/gui/math3d/qvector2d.cpp | 4 +-- src/gui/math3d/qvector3d.cpp | 4 +-- src/gui/math3d/qvector4d.cpp | 4 --- tests/auto/math3d/qmatrixnxn/tst_qmatrixnxn.cpp | 35 +++++++++++------------ tests/auto/math3d/qquaternion/tst_qquaternion.cpp | 4 +-- tests/auto/math3d/qvectornd/tst_qvectornd.cpp | 4 +-- 8 files changed, 23 insertions(+), 43 deletions(-) diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp index b998353..88f58c8 100644 --- a/src/gui/math3d/qmatrix4x4.cpp +++ b/src/gui/math3d/qmatrix4x4.cpp @@ -53,10 +53,6 @@ QT_BEGIN_NAMESPACE \brief The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space. \since 4.6 - The matrix elements are stored internally using the most efficient - numeric representation for the underlying hardware: floating-point - or fixed-point. - \sa QVector3D, QGenericMatrix */ @@ -308,8 +304,7 @@ QMatrix4x4::QMatrix4x4(const QTransform& transform) // The 4x4 matrix inverse algorithm is based on that described at: // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q24 // Some optimization has been done to avoid making copies of 3x3 -// sub-matrices, to do calculations in fixed-point where required, -// and to unroll the loops. +// sub-matrices and to unroll the loops. // Calculate the determinant of a 3x3 sub-matrix. // | A B C | diff --git a/src/gui/math3d/qquaternion.cpp b/src/gui/math3d/qquaternion.cpp index 9988e2b..d9d4160 100644 --- a/src/gui/math3d/qquaternion.cpp +++ b/src/gui/math3d/qquaternion.cpp @@ -55,10 +55,6 @@ QT_BEGIN_NAMESPACE Quaternions are used to represent rotations in 3D space, and consist of a 3D rotation axis specified by the x, y, and z coordinates, and a scalar representing the rotation angle. - - The components of a quaternion are stored internally using the most - efficient representation for the GL rendering engine, which will be - either floating-point or fixed-point. */ /*! diff --git a/src/gui/math3d/qvector2d.cpp b/src/gui/math3d/qvector2d.cpp index 9b5d123..b492aa8 100644 --- a/src/gui/math3d/qvector2d.cpp +++ b/src/gui/math3d/qvector2d.cpp @@ -57,9 +57,7 @@ QT_BEGIN_NAMESPACE The QVector2D class can also be used to represent vertices in 2D space. We therefore do not need to provide a separate vertex class. - The coordinates are stored internally using the most efficient - representation for the GL rendering engine, which will be either - floating-point or fixed-point. + \sa QVector3D, QVector4D, QQuaternion */ /*! diff --git a/src/gui/math3d/qvector3d.cpp b/src/gui/math3d/qvector3d.cpp index 977152a..95550cd 100644 --- a/src/gui/math3d/qvector3d.cpp +++ b/src/gui/math3d/qvector3d.cpp @@ -61,9 +61,7 @@ QT_BEGIN_NAMESPACE The QVector3D class can also be used to represent vertices in 3D space. We therefore do not need to provide a separate vertex class. - The coordinates are stored internally using the most efficient - representation for the GL rendering engine, which will be either - floating-point or fixed-point. + \sa QVector2D, QVector4D, QQuaternion */ /*! diff --git a/src/gui/math3d/qvector4d.cpp b/src/gui/math3d/qvector4d.cpp index a28d2a1..1f7d921 100644 --- a/src/gui/math3d/qvector4d.cpp +++ b/src/gui/math3d/qvector4d.cpp @@ -57,10 +57,6 @@ QT_BEGIN_NAMESPACE The QVector4D class can also be used to represent vertices in 4D space. We therefore do not need to provide a separate vertex class. - The coordinates are stored internally using the most efficient - representation for the GL rendering engine, which will be either - floating-point or fixed-point. - \sa QQuaternion, QVector2D, QVector3D */ diff --git a/tests/auto/math3d/qmatrixnxn/tst_qmatrixnxn.cpp b/tests/auto/math3d/qmatrixnxn/tst_qmatrixnxn.cpp index 7facf4a..d799c1b 100644 --- a/tests/auto/math3d/qmatrixnxn/tst_qmatrixnxn.cpp +++ b/tests/auto/math3d/qmatrixnxn/tst_qmatrixnxn.cpp @@ -172,22 +172,22 @@ private slots: private: static void setMatrix(QMatrix2x2& m, const qreal *values); - static void setMatrixFixed(QMatrix2x2& m, const qreal *values); + static void setMatrixDirect(QMatrix2x2& m, const qreal *values); static bool isSame(const QMatrix2x2& m, const qreal *values); static bool isIdentity(const QMatrix2x2& m); static void setMatrix(QMatrix3x3& m, const qreal *values); - static void setMatrixFixed(QMatrix3x3& m, const qreal *values); + static void setMatrixDirect(QMatrix3x3& m, const qreal *values); static bool isSame(const QMatrix3x3& m, const qreal *values); static bool isIdentity(const QMatrix3x3& m); static void setMatrix(QMatrix4x4& m, const qreal *values); - static void setMatrixFixed(QMatrix4x4& m, const qreal *values); + static void setMatrixDirect(QMatrix4x4& m, const qreal *values); static bool isSame(const QMatrix4x4& m, const qreal *values); static bool isIdentity(const QMatrix4x4& m); static void setMatrix(QMatrix4x3& m, const qreal *values); - static void setMatrixFixed(QMatrix4x3& m, const qreal *values); + static void setMatrixDirect(QMatrix4x3& m, const qreal *values); static bool isSame(const QMatrix4x3& m, const qreal *values); static bool isIdentity(const QMatrix4x3& m); }; @@ -321,8 +321,9 @@ void tst_QMatrix::setMatrix(QMatrix4x3& m, const qreal *values) } // Set a matrix to a specified array of values, which are assumed -// to be in row-major order. This sets the values using fixed-point. -void tst_QMatrix::setMatrixFixed(QMatrix2x2& m, const qreal *values) +// to be in row-major order. This sets the values directly into +// the internal data() array. +void tst_QMatrix::setMatrixDirect(QMatrix2x2& m, const qreal *values) { float *data = m.data(); for (int row = 0; row < 2; ++row) { @@ -331,7 +332,7 @@ void tst_QMatrix::setMatrixFixed(QMatrix2x2& m, const qreal *values) } } } -void tst_QMatrix::setMatrixFixed(QMatrix3x3& m, const qreal *values) +void tst_QMatrix::setMatrixDirect(QMatrix3x3& m, const qreal *values) { float *data = m.data(); for (int row = 0; row < 3; ++row) { @@ -340,7 +341,7 @@ void tst_QMatrix::setMatrixFixed(QMatrix3x3& m, const qreal *values) } } } -void tst_QMatrix::setMatrixFixed(QMatrix4x4& m, const qreal *values) +void tst_QMatrix::setMatrixDirect(QMatrix4x4& m, const qreal *values) { float *data = m.data(); for (int row = 0; row < 4; ++row) { @@ -349,7 +350,7 @@ void tst_QMatrix::setMatrixFixed(QMatrix4x4& m, const qreal *values) } } } -void tst_QMatrix::setMatrixFixed(QMatrix4x3& m, const qreal *values) +void tst_QMatrix::setMatrixDirect(QMatrix4x3& m, const qreal *values) { float *data = m.data(); for (int row = 0; row < 3; ++row) { @@ -359,8 +360,8 @@ void tst_QMatrix::setMatrixFixed(QMatrix4x3& m, const qreal *values) } } -// qFuzzyCompare isn't quite "fuzzy" enough to handle conversion -// to fixed-point and back again. So create "fuzzier" compares. +// qFuzzyCompare isn't always "fuzzy" enough to handle conversion +// between float, double, and qreal. So create "fuzzier" compares. static bool fuzzyCompare(float x, float y, qreal epsilon = 0.001) { float diff = x - y; @@ -511,7 +512,7 @@ void tst_QMatrix::create2x2() QVERIFY(!m2.isIdentity()); QMatrix2x2 m3; - setMatrixFixed(m3, uniqueValues2); + setMatrixDirect(m3, uniqueValues2); QVERIFY(isSame(m3, uniqueValues2)); QMatrix2x2 m4(m3); @@ -546,7 +547,7 @@ void tst_QMatrix::create3x3() QVERIFY(!m2.isIdentity()); QMatrix3x3 m3; - setMatrixFixed(m3, uniqueValues3); + setMatrixDirect(m3, uniqueValues3); QVERIFY(isSame(m3, uniqueValues3)); QMatrix3x3 m4(m3); @@ -581,7 +582,7 @@ void tst_QMatrix::create4x4() QVERIFY(!m2.isIdentity()); QMatrix4x4 m3; - setMatrixFixed(m3, uniqueValues4); + setMatrixDirect(m3, uniqueValues4); QVERIFY(isSame(m3, uniqueValues4)); QMatrix4x4 m4(m3); @@ -623,7 +624,7 @@ void tst_QMatrix::create4x3() QVERIFY(!m2.isIdentity()); QMatrix4x3 m3; - setMatrixFixed(m3, uniqueValues4x3); + setMatrixDirect(m3, uniqueValues4x3); QVERIFY(isSame(m3, uniqueValues4x3)); QMatrix4x3 m4(m3); @@ -2961,10 +2962,6 @@ void tst_QMatrix::extractTranslation() QVERIFY(fuzzyCompare(vec.y(), y, epsilon)); QVERIFY(fuzzyCompare(vec.z(), z, epsilon)); - // Have to be careful with numbers here, it is really easy to blow away - // the precision of a fixed pointer number, especially when doing distance - // formula for vector normalization - QMatrix4x4 lookAt; QVector3D eye(1.5f, -2.5f, 2.5f); lookAt.lookAt(eye, diff --git a/tests/auto/math3d/qquaternion/tst_qquaternion.cpp b/tests/auto/math3d/qquaternion/tst_qquaternion.cpp index 395032f..16b87a1 100644 --- a/tests/auto/math3d/qquaternion/tst_qquaternion.cpp +++ b/tests/auto/math3d/qquaternion/tst_qquaternion.cpp @@ -95,8 +95,8 @@ private slots: void nlerp(); }; -// qFuzzyCompare isn't quite "fuzzy" enough to handle conversion -// to fixed-point and back again. So create "fuzzier" compares. +// qFuzzyCompare isn't always "fuzzy" enough to handle conversion +// between float, double, and qreal. So create "fuzzier" compares. static bool fuzzyCompare(float x, float y) { float diff = x - y; diff --git a/tests/auto/math3d/qvectornd/tst_qvectornd.cpp b/tests/auto/math3d/qvectornd/tst_qvectornd.cpp index 0eb5b07..9c1ea83 100644 --- a/tests/auto/math3d/qvectornd/tst_qvectornd.cpp +++ b/tests/auto/math3d/qvectornd/tst_qvectornd.cpp @@ -139,8 +139,8 @@ private slots: void dotProduct4(); }; -// qFuzzyCompare isn't quite "fuzzy" enough to handle conversion -// to fixed-point and back again. So create "fuzzier" compares. +// qFuzzyCompare isn't always "fuzzy" enough to handle conversion +// between float, double, and qreal. So create "fuzzier" compares. static bool fuzzyCompare(float x, float y) { float diff = x - y; -- cgit v0.12 From 3e50d680a37401c05d753982eb5d43c0f1225f63 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Thu, 9 Jul 2009 11:11:35 +1000 Subject: Directly copy QGenericMatrix members instead of using qMemCopy() Using qMemCopy limits QGenericMatrix to plain old types like float and double. Copying the values normally will allow copy constructors to work on non plain types. Reviewed-by: trustme --- src/gui/math3d/qgenericmatrix.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/gui/math3d/qgenericmatrix.h b/src/gui/math3d/qgenericmatrix.h index 1131f9b..7bdf70a 100644 --- a/src/gui/math3d/qgenericmatrix.h +++ b/src/gui/math3d/qgenericmatrix.h @@ -119,7 +119,9 @@ Q_INLINE_TEMPLATE QGenericMatrix::QGenericMatrix() template Q_INLINE_TEMPLATE QGenericMatrix::QGenericMatrix(const QGenericMatrix& other) { - qMemCopy(m, other.m, sizeof(m)); + for (int col = 0; col < N; ++col) + for (int row = 0; row < M; ++row) + m[col][row] = other.m[col][row]; } template -- cgit v0.12 From 99cda3446c6ff5c3da4fe8fb4bc8869497f8da8b Mon Sep 17 00:00:00 2001 From: Stian Sandvik Thomassen Date: Thu, 9 Jul 2009 13:26:18 +1000 Subject: Plugged possible memory leak in getPSQLVersion() Call PQclear() regardless of the status of the result returned by PQexec(). Reviewed-by: Bill King --- src/sql/drivers/psql/qsql_psql.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sql/drivers/psql/qsql_psql.cpp b/src/sql/drivers/psql/qsql_psql.cpp index 4eccf4b..147cd6d 100644 --- a/src/sql/drivers/psql/qsql_psql.cpp +++ b/src/sql/drivers/psql/qsql_psql.cpp @@ -626,10 +626,9 @@ static QPSQLDriver::Protocol getPSQLVersion(PGconn* connection) { QPSQLDriver::Protocol serverVersion = QPSQLDriver::Version6; PGresult* result = PQexec(connection, "select version()"); - int status = PQresultStatus(result); + int status = PQresultStatus(result); if (status == PGRES_COMMAND_OK || status == PGRES_TUPLES_OK) { QString val = QString::fromAscii(PQgetvalue(result, 0, 0)); - PQclear(result); QRegExp rx(QLatin1String("(\\d+)\\.(\\d+)")); rx.setMinimal(true); // enforce non-greedy RegExp if (rx.indexIn(val) != -1) { @@ -670,6 +669,7 @@ static QPSQLDriver::Protocol getPSQLVersion(PGconn* connection) } } } + PQclear(result); if (serverVersion < QPSQLDriver::Version71) qWarning("This version of PostgreSQL is not supported and may not work."); -- cgit v0.12 From 5142a27c19fb01ec80010d2d1de12b0e3082751f Mon Sep 17 00:00:00 2001 From: Derick Hawcroft Date: Thu, 9 Jul 2009 13:58:28 +1000 Subject: emit dataChanged() signal Task-number:207874 --- src/sql/models/qsqltablemodel.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index 1acc846..591b506 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -538,6 +538,7 @@ bool QSqlTableModel::setData(const QModelIndex &index, const QVariant &value, in isOk = updateRowInTable(index.row(), d->editBuffer); if (isOk) select(); + emit dataChanged(index, index); break; } case OnRowChange: if (index.row() == d->insertIndex) { -- cgit v0.12 From bae8bc5d23946036b2c1079fc6f1b3bceeaa19ca Mon Sep 17 00:00:00 2001 From: Rohan McGovern Date: Wed, 8 Jul 2009 10:18:56 +1000 Subject: Disable private unit tests when Qt is configured without -developer-build, part 1. Adds QT_CONFIG+=private_tests to qconfig.pri when Qt is configured with -developer-build. Reviewed-by: Michael Goddard --- configure | 4 +++- tools/configure/configureapp.cpp | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/configure b/configure index f9b3030..bd8b0ca 100755 --- a/configure +++ b/configure @@ -6256,7 +6256,6 @@ esac # debug release # dll staticlib # -# internal # nocrosscompiler # GNUmake # largefile @@ -6736,6 +6735,9 @@ fi if [ "$PLATFORM_MAC" = "yes" ]; then QT_CONFIG="$QT_CONFIG $CFG_MAC_ARCHS" fi +if [ "$CFG_DEV" = "yes" ]; then + QT_CONFIG="$QT_CONFIG private_tests" +fi # Make the application arch follow the Qt arch for single arch builds. # (for multiple-arch builds, set CONFIG manually in the application .pro file) diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index ce9fe6b..80cfc64 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -1135,6 +1135,10 @@ void Configure::parseCmdLine() useUnixSeparators = (dictionary["QMAKESPEC"] == "win32-g++"); + // Allow tests for private classes to be compiled against internal builds + if (dictionary["BUILDDEV"] == "yes") + qtConfig += "private_tests"; + #if !defined(EVAL) for( QStringList::Iterator dis = disabledModules.begin(); dis != disabledModules.end(); ++dis ) { @@ -1997,7 +2001,6 @@ bool Configure::verifyConfiguration() no-gif gif dll staticlib - internal nocrosscompiler GNUmake largefile -- cgit v0.12 From 87df094ed204c237393eac1dd0b2fb907e642dcb Mon Sep 17 00:00:00 2001 From: Rohan McGovern Date: Mon, 6 Jul 2009 16:40:59 +1000 Subject: Disable private unit tests when Qt is configured without -developer-build, part 2. Some autotests use private (unexported) code, either because they're testing private classes or because that's the easiest way to test the public classes. Configuring Qt with `-developer-build' is needed for these tests. This commit fixes the tests so configuring without `-developer-build' only builds the tests which strictly use public API. --- tests/auto/qcombobox/tst_qcombobox.cpp | 6 ++++ tests/auto/qcssparser/qcssparser.pro | 1 + tests/auto/qfiledialog/tst_qfiledialog.cpp | 18 ++++++++++-- .../auto/qfilesystemmodel/tst_qfilesystemmodel.cpp | 2 ++ tests/auto/qgl/qgl.pro | 3 +- tests/auto/qgl/tst_qgl.cpp | 23 ++-------------- .../qhttpnetworkconnection.pro | 2 ++ tests/auto/qhttpnetworkreply/qhttpnetworkreply.pro | 2 ++ .../qitemeditorfactory/tst_qitemeditorfactory.cpp | 10 +++---- tests/auto/qkeysequence/tst_qkeysequence.cpp | 2 +- tests/auto/qmainwindow/tst_qmainwindow.cpp | 6 ++++ .../qnativesocketengine/qnativesocketengine.pro | 2 ++ tests/auto/qnetworkreply/qnetworkreply.pro | 2 ++ tests/auto/qpathclipper/qpathclipper.pro | 2 ++ tests/auto/qplaintextedit/tst_qplaintextedit.cpp | 2 ++ tests/auto/qregion/tst_qregion.cpp | 6 ++-- tests/auto/qsettings/tst_qsettings.cpp | 22 +++++++++++++-- tests/auto/qsharedpointer/qsharedpointer.pro | 1 + tests/auto/qsocketnotifier/qsocketnotifier.pro | 2 ++ .../qsocks5socketengine/qsocks5socketengine.pro | 1 + .../qstandarditemmodel/tst_qstandarditemmodel.cpp | 4 +++ tests/auto/qstatemachine/tst_qstatemachine.cpp | 2 ++ tests/auto/qstylesheetstyle/qstylesheetstyle.pro | 1 + tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp | 4 +++ tests/auto/qtextedit/tst_qtextedit.cpp | 4 +++ tests/auto/qtextpiecetable/qtextpiecetable.pro | 5 ++-- tests/auto/qtextpiecetable/tst_qtextpiecetable.cpp | 32 +--------------------- tests/auto/qurl/tst_qurl.cpp | 4 +++ .../xmlpatternsdiagnosticsts.pro | 1 + tests/auto/xmlpatternsview/xmlpatternsview.pro | 1 + tests/auto/xmlpatternsxqts/xmlpatternsxqts.pro | 3 ++ tests/auto/xmlpatternsxslts/xmlpatternsxslts.pro | 1 + 32 files changed, 108 insertions(+), 69 deletions(-) diff --git a/tests/auto/qcombobox/tst_qcombobox.cpp b/tests/auto/qcombobox/tst_qcombobox.cpp index c94ace0..67c9ac9 100644 --- a/tests/auto/qcombobox/tst_qcombobox.cpp +++ b/tests/auto/qcombobox/tst_qcombobox.cpp @@ -1973,6 +1973,7 @@ void tst_QComboBox::task190351_layout() listCombo.showPopup(); QTest::qWait(100); +#ifdef QT_BUILD_INTERNAL QFrame *container = qFindChild(&listCombo); QVERIFY(container); QCOMPARE(static_cast(list), qFindChild(container)); @@ -1980,6 +1981,7 @@ void tst_QComboBox::task190351_layout() QVERIFY(top); QVERIFY(top->isVisible()); QCOMPARE(top->mapToGlobal(QPoint(0, top->height())).y(), list->mapToGlobal(QPoint()).y()); +#endif QApplication::setStyle(oldStyle); #else @@ -2045,6 +2047,7 @@ void tst_QComboBox::task191329_size() tableCombo.showPopup(); QTest::qWait(100); +#ifdef QT_BUILD_INTERNAL QFrame *container = qFindChild(&tableCombo); QVERIFY(container); QCOMPARE(static_cast(table), qFindChild(container)); @@ -2052,6 +2055,7 @@ void tst_QComboBox::task191329_size() //the popup should be large enough to contains everithing so the top and left button are hidden QVERIFY(!button->isVisible()); } +#endif QApplication::setStyle(oldStyle); #else @@ -2107,9 +2111,11 @@ void tst_QComboBox::task248169_popupWithMinimalSize() comboBox.showPopup(); QTest::qWait(100); +#ifdef QT_BUILD_INTERNAL QFrame *container = qFindChild(&comboBox); QVERIFY(container); QVERIFY(desktop.screenGeometry(container).contains(container->geometry())); +#endif } void tst_QComboBox::task247863_keyBoardSelection() diff --git a/tests/auto/qcssparser/qcssparser.pro b/tests/auto/qcssparser/qcssparser.pro index 57d6804..723e4d3 100644 --- a/tests/auto/qcssparser/qcssparser.pro +++ b/tests/auto/qcssparser/qcssparser.pro @@ -3,6 +3,7 @@ SOURCES += tst_cssparser.cpp DEFINES += SRCDIR=\\\"$$PWD\\\" QT += xml +requires(contains(QT_CONFIG,private_tests)) wince*: { addFiles.sources = testdata diff --git a/tests/auto/qfiledialog/tst_qfiledialog.cpp b/tests/auto/qfiledialog/tst_qfiledialog.cpp index e4fec1d..8bb81e7 100644 --- a/tests/auto/qfiledialog/tst_qfiledialog.cpp +++ b/tests/auto/qfiledialog/tst_qfiledialog.cpp @@ -231,6 +231,7 @@ void tst_QFiledialog::currentChangedSignal() // only emited from the views, sidebar, or lookin combo void tst_QFiledialog::directoryEnteredSignal() { +#if defined QT_BUILD_INTERNAL QNonNativeFileDialog fd(0, "", QDir::root().path()); fd.setOptions(QFileDialog::DontUseNativeDialog); fd.show(); @@ -274,6 +275,7 @@ void tst_QFiledialog::directoryEnteredSignal() QTest::mouseDClick(listView->viewport(), Qt::LeftButton, 0, listView->visualRect(folder).center()); QTRY_COMPARE(spyDirectoryEntered.count(), 1); */ +#endif } Q_DECLARE_METATYPE(QFileDialog::FileMode) @@ -1314,16 +1316,14 @@ void tst_QFiledialog::hooks() void tst_QFiledialog::listRoot() { +#if defined QT_BUILD_INTERNAL QFileInfoGatherer::fetchedRoot = false; QString dir(QDir::currentPath()); QNonNativeFileDialog fd(0, QString(), dir); fd.show(); -#if defined Q_AUTOTEST_EXPORT QCOMPARE(QFileInfoGatherer::fetchedRoot,false); -#endif fd.setDirectory(""); QTest::qWait(500); -#if defined Q_AUTOTEST_EXPORT QCOMPARE(QFileInfoGatherer::fetchedRoot,true); #endif } @@ -1347,6 +1347,7 @@ struct FriendlyQFileDialog : public QFileDialog void tst_QFiledialog::deleteDirAndFiles() { +#if defined QT_BUILD_INTERNAL QString tempPath = QDir::tempPath() + '/' + "QFileDialogTestDir4FullDelete"; QDir dir; QVERIFY(dir.mkpath(tempPath + "/foo")); @@ -1373,6 +1374,7 @@ void tst_QFiledialog::deleteDirAndFiles() QFileInfo info(tempPath); QTest::qWait(2000); QVERIFY(!info.exists()); +#endif } void tst_QFiledialog::filter() @@ -1583,6 +1585,7 @@ QString &dir, const QString &filter) void tst_QFiledialog::task227304_proxyOnFileDialog() { +#if defined QT_BUILD_INTERNAL QNonNativeFileDialog fd(0, "", QDir::currentPath(), 0); fd.setProxyModel(new FilterDirModel(QDir::currentPath())); fd.show(); @@ -1616,6 +1619,7 @@ void tst_QFiledialog::task227304_proxyOnFileDialog() QTest::mouseClick(sidebar->viewport(), Qt::LeftButton, 0, sidebar->visualRect(sidebar->model()->index(1, 0)).center()); QTest::qWait(250); //We shouldn't crash +#endif } void tst_QFiledialog::task227930_correctNavigationKeyboardBehavior() @@ -1727,6 +1731,7 @@ void tst_QFiledialog::task235069_hideOnEscape() void tst_QFiledialog::task236402_dontWatchDeletedDir() { +#if defined QT_BUILD_INTERNAL //THIS TEST SHOULD NOT DISPLAY WARNINGS QDir current = QDir::currentPath(); //make sure it is the first on the list @@ -1746,6 +1751,7 @@ void tst_QFiledialog::task236402_dontWatchDeletedDir() QTest::qWait(200); fd.d_func()->removeDirectory(current.absolutePath() + "/aaaaaaaaaa/"); QTest::qWait(1000); +#endif } void tst_QFiledialog::task203703_returnProperSeparator() @@ -1870,6 +1876,7 @@ void tst_QFiledialog::task218353_relativePaths() void tst_QFiledialog::task251321_sideBarHiddenEntries() { +#if defined QT_BUILD_INTERNAL QNonNativeFileDialog fd; QDir current = QDir::currentPath(); @@ -1899,8 +1906,10 @@ void tst_QFiledialog::task251321_sideBarHiddenEntries() hiddenSubDir.rmdir("happy"); hiddenDir.rmdir("subdir"); current.rmdir(".hidden"); +#endif } +#if defined QT_BUILD_INTERNAL class MyQSideBar : public QSidebar { public : @@ -1918,9 +1927,11 @@ public : model()->removeRow(indexes.at(i).row()); } }; +#endif void tst_QFiledialog::task251341_sideBarRemoveEntries() { +#if defined QT_BUILD_INTERNAL QNonNativeFileDialog fd; QDir current = QDir::currentPath(); @@ -1980,6 +1991,7 @@ void tst_QFiledialog::task251341_sideBarRemoveEntries() QCOMPARE(mySideBar.urls(), expected); current.rmdir("testDir"); +#endif } void tst_QFiledialog::task254490_selectFileMultipleTimes() diff --git a/tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp index e415b02..d49083f 100644 --- a/tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp +++ b/tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp @@ -254,6 +254,7 @@ void tst_QFileSystemModel::naturalCompare_data() void tst_QFileSystemModel::naturalCompare() { +#ifdef QT_BUILD_INTERNAL QFETCH(QString, s1); QFETCH(QString, s2); QFETCH(int, caseSensitive); @@ -271,6 +272,7 @@ void tst_QFileSystemModel::naturalCompare() // created. The scheduler takes its time to recognize ended threads. QTest::qWait(300); #endif +#endif } void tst_QFileSystemModel::readOnly() diff --git a/tests/auto/qgl/qgl.pro b/tests/auto/qgl/qgl.pro index 55e329d..420c4bb 100644 --- a/tests/auto/qgl/qgl.pro +++ b/tests/auto/qgl/qgl.pro @@ -3,7 +3,8 @@ ############################################################ load(qttest_p4) -contains(QT_CONFIG, opengl):QT += opengl +requires(contains(QT_CONFIG,opengl)) +QT += opengl SOURCES += tst_qgl.cpp diff --git a/tests/auto/qgl/tst_qgl.cpp b/tests/auto/qgl/tst_qgl.cpp index 078c559..96f5ddd 100644 --- a/tests/auto/qgl/tst_qgl.cpp +++ b/tests/auto/qgl/tst_qgl.cpp @@ -44,9 +44,7 @@ #include #include -#ifndef QT_NO_OPENGL #include -#endif #include #include @@ -78,7 +76,6 @@ tst_QGL::~tst_QGL() { } -#ifndef QT_NO_OPENGL class MyGLContext : public QGLContext { public: @@ -96,13 +93,10 @@ public: bool autoBufferSwap() const { return QGLWidget::autoBufferSwap(); } void setAutoBufferSwap(bool on) { QGLWidget::setAutoBufferSwap(on); } }; -#endif + // Testing get/set functions void tst_QGL::getSetCheck() { -#ifdef QT_NO_OPENGL - QSKIP("QGL not yet supported", SkipAll); -#else if (!QGLFormat::hasOpenGL()) QSKIP("QGL not supported on this platform", SkipAll); @@ -246,10 +240,9 @@ void tst_QGL::getSetCheck() QCOMPARE(false, obj3.autoBufferSwap()); obj3.setAutoBufferSwap(true); QCOMPARE(true, obj3.autoBufferSwap()); -#endif } -#ifndef QT_NO_OPENGL +#ifdef QT_BUILD_INTERNAL QT_BEGIN_NAMESPACE extern QGLFormat::OpenGLVersionFlags qOpenGLVersionFlagsFromString(const QString &versionString); QT_END_NAMESPACE @@ -257,9 +250,7 @@ QT_END_NAMESPACE void tst_QGL::openGLVersionCheck() { -#ifdef QT_NO_OPENGL - QSKIP("QGL not yet supported", SkipAll); -#else +#ifdef QT_BUILD_INTERNAL if (!QGLFormat::hasOpenGL()) QSKIP("QGL not supported on this platform", SkipAll); @@ -366,9 +357,6 @@ public: void tst_QGL::graphicsViewClipping() { -#ifdef QT_NO_OPENGL - QSKIP("QGL not supported", SkipAll); -#else const int size = 64; UnclippedWidget *widget = new UnclippedWidget; widget->setFixedSize(size, size); @@ -403,7 +391,6 @@ void tst_QGL::graphicsViewClipping() p.end(); QCOMPARE(image, expected); -#endif } void tst_QGL::partialGLWidgetUpdates_data() @@ -420,9 +407,6 @@ void tst_QGL::partialGLWidgetUpdates_data() void tst_QGL::partialGLWidgetUpdates() { -#ifdef QT_NO_OPENGL - QSKIP("QGL not yet supported", SkipAll); -#else if (!QGLFormat::hasOpenGL()) QSKIP("QGL not supported on this platform", SkipAll); @@ -466,7 +450,6 @@ void tst_QGL::partialGLWidgetUpdates() QCOMPARE(widget.paintEventRegion, QRegion(50, 50, 50, 50)); else QCOMPARE(widget.paintEventRegion, QRegion(widget.rect())); -#endif } QTEST_MAIN(tst_QGL) diff --git a/tests/auto/qhttpnetworkconnection/qhttpnetworkconnection.pro b/tests/auto/qhttpnetworkconnection/qhttpnetworkconnection.pro index 3283873..e19d962 100644 --- a/tests/auto/qhttpnetworkconnection/qhttpnetworkconnection.pro +++ b/tests/auto/qhttpnetworkconnection/qhttpnetworkconnection.pro @@ -2,4 +2,6 @@ load(qttest_p4) SOURCES += tst_qhttpnetworkconnection.cpp INCLUDEPATH += $$(QTDIR)/src/3rdparty/zlib +requires(contains(QT_CONFIG,private_tests)) + QT = core network diff --git a/tests/auto/qhttpnetworkreply/qhttpnetworkreply.pro b/tests/auto/qhttpnetworkreply/qhttpnetworkreply.pro index 2e41fcd..f86250a 100644 --- a/tests/auto/qhttpnetworkreply/qhttpnetworkreply.pro +++ b/tests/auto/qhttpnetworkreply/qhttpnetworkreply.pro @@ -2,4 +2,6 @@ load(qttest_p4) SOURCES += tst_qhttpnetworkreply.cpp INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/zlib +requires(contains(QT_CONFIG,private_tests)) + QT = core network diff --git a/tests/auto/qitemeditorfactory/tst_qitemeditorfactory.cpp b/tests/auto/qitemeditorfactory/tst_qitemeditorfactory.cpp index d9a7d56..e235ff5 100644 --- a/tests/auto/qitemeditorfactory/tst_qitemeditorfactory.cpp +++ b/tests/auto/qitemeditorfactory/tst_qitemeditorfactory.cpp @@ -59,13 +59,13 @@ void tst_QItemEditorFactory::createEditor() QCOMPARE(w->metaObject()->className(), "QExpandingLineEdit"); } -void tst_QItemEditorFactory::createCustomEditor() +//we make it inherit from QObject so that we can use QPointer +class MyEditor : public QObject, public QStandardItemEditorCreator { - //we make it inherit from QObject so that we can use QPointer - class MyEditor : public QObject, public QStandardItemEditorCreator - { - }; +}; +void tst_QItemEditorFactory::createCustomEditor() +{ QPointer creator = new MyEditor; QPointer creator2 = new MyEditor; diff --git a/tests/auto/qkeysequence/tst_qkeysequence.cpp b/tests/auto/qkeysequence/tst_qkeysequence.cpp index aeb57ef..2e4b850 100644 --- a/tests/auto/qkeysequence/tst_qkeysequence.cpp +++ b/tests/auto/qkeysequence/tst_qkeysequence.cpp @@ -270,7 +270,7 @@ void tst_QKeySequence::checkMultipleNames() void tst_QKeySequence::ensureSorted() { //### accessing static members from private classes does not work on msvc at the moment -#ifndef Q_WS_WIN +#if defined(QT_BUILD_INTERNAL) && !defined(Q_WS_WIN) uint N = QKeySequencePrivate::numberOfKeyBindings; uint val = QKeySequencePrivate::keyBindings[0].shortcut; for ( uint i = 1 ; i < N ; ++i) { diff --git a/tests/auto/qmainwindow/tst_qmainwindow.cpp b/tests/auto/qmainwindow/tst_qmainwindow.cpp index e46c2e1..6ae7a3e 100644 --- a/tests/auto/qmainwindow/tst_qmainwindow.cpp +++ b/tests/auto/qmainwindow/tst_qmainwindow.cpp @@ -1400,6 +1400,7 @@ void AddDockWidget::apply(QMainWindow *mw) const } } +#ifdef QT_BUILD_INTERNAL struct MoveSeparator { MoveSeparator() {} @@ -1436,6 +1437,7 @@ void MoveSeparator::apply(QMainWindow *mw) const l->layoutState.dockAreaLayout.separatorMove(path, QPoint(0, 0), QPoint(delta, delta)); } +#endif QMap dockWidgetGeometries(QMainWindow *mw) { @@ -1463,6 +1465,7 @@ QMap dockWidgetGeometries(QMainWindow *mw) void tst_QMainWindow::saveRestore_data() { +#ifdef QT_BUILD_INTERNAL QTest::addColumn("addList"); QTest::addColumn("moveList"); @@ -1497,10 +1500,12 @@ void tst_QMainWindow::saveRestore_data() << MoveSeparator(-30, "right1") << MoveSeparator(30, "right2a") ); +#endif } void tst_QMainWindow::saveRestore() { +#ifdef QT_BUILD_INTERNAL QFETCH(AddList, addList); QFETCH(MoveList, moveList); @@ -1570,6 +1575,7 @@ void tst_QMainWindow::saveRestore() mainWindow.show(); COMPARE_DOCK_WIDGET_GEOS(dockWidgetGeos, dockWidgetGeometries(&mainWindow)); } +#endif } void tst_QMainWindow::iconSizeChanged() diff --git a/tests/auto/qnativesocketengine/qnativesocketengine.pro b/tests/auto/qnativesocketengine/qnativesocketengine.pro index 320f24c..ad40d53 100644 --- a/tests/auto/qnativesocketengine/qnativesocketengine.pro +++ b/tests/auto/qnativesocketengine/qnativesocketengine.pro @@ -3,6 +3,8 @@ SOURCES += tst_qnativesocketengine.cpp include(../qnativesocketengine/qsocketengine.pri) +requires(contains(QT_CONFIG,private_tests)) + MOC_DIR=tmp QT = core network diff --git a/tests/auto/qnetworkreply/qnetworkreply.pro b/tests/auto/qnetworkreply/qnetworkreply.pro index 0bcf067..fd8454c 100644 --- a/tests/auto/qnetworkreply/qnetworkreply.pro +++ b/tests/auto/qnetworkreply/qnetworkreply.pro @@ -1,4 +1,6 @@ TEMPLATE = subdirs SUBDIRS = test +requires(contains(QT_CONFIG,private_tests)) + !wince*:SUBDIRS += echo diff --git a/tests/auto/qpathclipper/qpathclipper.pro b/tests/auto/qpathclipper/qpathclipper.pro index 675e463..dc9d60f 100644 --- a/tests/auto/qpathclipper/qpathclipper.pro +++ b/tests/auto/qpathclipper/qpathclipper.pro @@ -3,6 +3,8 @@ INCLUDEPATH += . HEADERS += paths.h SOURCES += tst_qpathclipper.cpp paths.cpp +requires(contains(QT_CONFIG,private_tests)) + unix:!mac:LIBS+=-lm diff --git a/tests/auto/qplaintextedit/tst_qplaintextedit.cpp b/tests/auto/qplaintextedit/tst_qplaintextedit.cpp index fceefd2..40ad539 100644 --- a/tests/auto/qplaintextedit/tst_qplaintextedit.cpp +++ b/tests/auto/qplaintextedit/tst_qplaintextedit.cpp @@ -1106,6 +1106,7 @@ void tst_QPlainTextEdit::mimeDataReimplementations() QCOMPARE(ed.canInsertCallCount, 0); QCOMPARE(ed.insertCallCount, 0); +#ifdef QT_BUILD_INTERNAL QTextControl *control = qFindChild(&ed); QVERIFY(control); @@ -1120,6 +1121,7 @@ void tst_QPlainTextEdit::mimeDataReimplementations() QCOMPARE(ed.createMimeDataCallCount, 1); QCOMPARE(ed.canInsertCallCount, 1); QCOMPARE(ed.insertCallCount, 1); +#endif } void tst_QPlainTextEdit::shiftEnterShouldInsertLineSeparator() diff --git a/tests/auto/qregion/tst_qregion.cpp b/tests/auto/qregion/tst_qregion.cpp index 3ffa87e..2ad202d 100644 --- a/tests/auto/qregion/tst_qregion.cpp +++ b/tests/auto/qregion/tst_qregion.cpp @@ -96,7 +96,7 @@ private slots: #ifdef Q_OS_WIN void handle(); #endif -#ifdef Q_WS_X11 +#if defined(Q_WS_X11) && defined(QT_BUILD_INTERNAL) void clipRectangles(); #endif @@ -865,7 +865,7 @@ void tst_QRegion::handle() } #endif -#ifdef Q_WS_X11 +#if defined(Q_WS_X11) && defined(QT_BUILD_INTERNAL) void tst_QRegion::clipRectangles() { QRegion region(30, 30, 30, 30); @@ -967,6 +967,7 @@ void tst_QRegion::regionToPath_data() void tst_QRegion::regionToPath() { +#ifdef QT_BUILD_INTERNAL extern QPainterPath qt_regionToPath(const QRegion ®ion); QFETCH(QPainterPath, path); @@ -1002,6 +1003,7 @@ void tst_QRegion::regionToPath() QCOMPARE(ia, ib); QCOMPARE(a.boundingRect(), b.boundingRect()); } +#endif } QTEST_MAIN(tst_QRegion) diff --git a/tests/auto/qsettings/tst_qsettings.cpp b/tests/auto/qsettings/tst_qsettings.cpp index f0f446d..77fef1f 100644 --- a/tests/auto/qsettings/tst_qsettings.cpp +++ b/tests/auto/qsettings/tst_qsettings.cpp @@ -713,6 +713,7 @@ void tst_QSettings::testErrorHandling_data() void tst_QSettings::testErrorHandling() { +#ifdef QT_BUILD_INTERNAL #ifdef Q_OS_WIN QSKIP("Windows doesn't support most file modes, including read-only directories, so this test is moot.", SkipAll); #else @@ -776,6 +777,7 @@ void tst_QSettings::testErrorHandling() QCOMPARE((int)settings.status(), statusAfterSetAndSync); } #endif // !Q_OS_WIN +#endif } Q_DECLARE_METATYPE(QVariant) @@ -821,6 +823,7 @@ void tst_QSettings::testIniParsing_data() void tst_QSettings::testIniParsing() { +#ifdef QT_BUILD_INTERNAL qRegisterMetaType("QVariant"); qRegisterMetaType("QSettings::Status"); @@ -854,6 +857,7 @@ void tst_QSettings::testIniParsing() } QCOMPARE(settings.status(), status); +#endif } /* @@ -1058,6 +1062,7 @@ void tst_QSettings::testVariantTypes_data() void tst_QSettings::testVariantTypes() { +#ifdef QT_BUILD_INTERNAL #define testVal(key, val, tp, rtype) \ { \ QSettings settings1(format, QSettings::UserScope, "software.org", "KillerAPP"); \ @@ -1141,6 +1146,7 @@ void tst_QSettings::testVariantTypes() } #undef testVal +#endif } void tst_QSettings::remove() @@ -1801,9 +1807,7 @@ void tst_QSettings::testNormalizedKey_data() void tst_QSettings::testNormalizedKey() { -#ifdef QTEST_REDUCED_EXPORTS - QSKIP("We can't test QSettingsPrivate on Windows", SkipAll); -#else +#ifdef QT_BUILD_INTERNAL QFETCH(QString, inKey); QFETCH(QString, outKey); @@ -1981,6 +1985,7 @@ void tst_QSettings::fromFile() void tst_QSettings::setIniCodec() { +#ifdef QT_BUILD_INTERNAL QByteArray expeContents4, expeContents5; QByteArray actualContents4, actualContents5; @@ -2040,6 +2045,7 @@ void tst_QSettings::setIniCodec() QCOMPARE(settings4.allKeys().first(), settings5.allKeys().first()); QCOMPARE(settings4.value(settings4.allKeys().first()).toString(), settings5.value(settings5.allKeys().first()).toString()); +#endif } static bool containsSubList(QStringList mom, QStringList son) @@ -2316,6 +2322,7 @@ void tst_QSettings::testArrays() settings1.endArray(); } +#ifdef QT_BUILD_INTERNAL static QByteArray iniEscapedKey(const QString &str) { QByteArray result; @@ -2360,6 +2367,7 @@ static QStringList iniUnescapedStringList(const QByteArray &ba) #endif return result; } +#endif QString escapeWeirdChars(const QString &s) { @@ -2383,6 +2391,7 @@ QString escapeWeirdChars(const QString &s) void tst_QSettings::testEscapes() { +#ifdef QT_BUILD_INTERNAL QSettings settings(QSettings::UserScope, "software.org", "KillerAPP"); #define testEscapedKey(plainKey, escKey) \ @@ -2505,6 +2514,7 @@ void tst_QSettings::testEscapes() testBadEscape("@Rect)", "@Rect)"); testBadEscape("@Rect(1 2 3)", "@Rect(1 2 3)"); testBadEscape("@@Rect(1 2 3)", "@Rect(1 2 3)"); +#endif } void tst_QSettings::testCompatFunctions() @@ -3355,6 +3365,7 @@ void tst_QSettings::childGroups_data() void tst_QSettings::childGroups() { +#ifdef QT_BUILD_INTERNAL QFETCH(QSettings::Format, format); { @@ -3408,6 +3419,7 @@ void tst_QSettings::childGroups() QCOMPARE(settings.childGroups(), QStringList() << "alpha" << "gamma" << "omicron" << "zeta"); } +#endif } void tst_QSettings::childKeys_data() @@ -3417,6 +3429,7 @@ void tst_QSettings::childKeys_data() void tst_QSettings::childKeys() { +#ifdef QT_BUILD_INTERNAL QFETCH(QSettings::Format, format); { @@ -3470,6 +3483,7 @@ void tst_QSettings::childKeys() QCOMPARE(settings.childKeys(), QStringList() << "alpha" << "beta" << "gamma"); } +#endif } void tst_QSettings::allKeys_data() @@ -3479,6 +3493,7 @@ void tst_QSettings::allKeys_data() void tst_QSettings::allKeys() { +#ifdef QT_BUILD_INTERNAL QFETCH(QSettings::Format, format); QStringList allKeys; @@ -3527,6 +3542,7 @@ void tst_QSettings::allKeys() QCOMPARE(settings.allKeys(), allKeys); } +#endif } void tst_QSettings::registerFormat() diff --git a/tests/auto/qsharedpointer/qsharedpointer.pro b/tests/auto/qsharedpointer/qsharedpointer.pro index 30c81cb..90fde06 100644 --- a/tests/auto/qsharedpointer/qsharedpointer.pro +++ b/tests/auto/qsharedpointer/qsharedpointer.pro @@ -4,5 +4,6 @@ SOURCES += tst_qsharedpointer.cpp \ forwarddeclared.cpp QT = core DEFINES += SRCDIR=\\\"$$PWD/\\\" +requires(contains(QT_CONFIG,private_tests)) include(externaltests.pri) HEADERS += forwarddeclared.h diff --git a/tests/auto/qsocketnotifier/qsocketnotifier.pro b/tests/auto/qsocketnotifier/qsocketnotifier.pro index 10ed3a5..ec924c1 100644 --- a/tests/auto/qsocketnotifier/qsocketnotifier.pro +++ b/tests/auto/qsocketnotifier/qsocketnotifier.pro @@ -2,6 +2,8 @@ load(qttest_p4) SOURCES += tst_qsocketnotifier.cpp QT = core network +requires(contains(QT_CONFIG,private_tests)) + include(../qnativesocketengine/qsocketengine.pri) diff --git a/tests/auto/qsocks5socketengine/qsocks5socketengine.pro b/tests/auto/qsocks5socketengine/qsocks5socketengine.pro index 2949ee2..d19b732 100644 --- a/tests/auto/qsocks5socketengine/qsocks5socketengine.pro +++ b/tests/auto/qsocks5socketengine/qsocks5socketengine.pro @@ -11,3 +11,4 @@ QT = core network +requires(contains(QT_CONFIG,private_tests)) diff --git a/tests/auto/qstandarditemmodel/tst_qstandarditemmodel.cpp b/tests/auto/qstandarditemmodel/tst_qstandarditemmodel.cpp index fa44034..fba7b1b 100644 --- a/tests/auto/qstandarditemmodel/tst_qstandarditemmodel.cpp +++ b/tests/auto/qstandarditemmodel/tst_qstandarditemmodel.cpp @@ -1454,6 +1454,7 @@ static QStandardItem *itemFromText(QStandardItem *parent, const QString &text) return item; } +#ifdef QT_BUILD_INTERNAL static QModelIndex indexFromText(QStandardItemModel *model, const QString &text) { QStandardItem *item = itemFromText(model->invisibleRootItem(), text); @@ -1467,9 +1468,11 @@ struct FriendlyTreeView : public QTreeView friend class tst_QStandardItemModel; Q_DECLARE_PRIVATE(QTreeView) }; +#endif void tst_QStandardItemModel::treeDragAndDrop() { +#ifdef QT_BUILD_INTERNAL const int nRow = 5; const int nCol = 3; @@ -1605,6 +1608,7 @@ void tst_QStandardItemModel::treeDragAndDrop() QVERIFY(compareModels(&model, &checkModel)); } +#endif } void tst_QStandardItemModel::removeRowsAndColumns() diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index a859866..efcb983 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -1015,6 +1015,7 @@ void tst_QStateMachine::rootState() void tst_QStateMachine::addAndRemoveState() { +#ifdef QT_BUILD_INTERNAL QStateMachine machine; QStatePrivate *root_d = QStatePrivate::get(machine.rootState()); QCOMPARE(root_d->childStates().size(), 0); @@ -1075,6 +1076,7 @@ void tst_QStateMachine::addAndRemoveState() delete s2; // ### how to deal with this? // machine.removeState(machine.errorState()); +#endif } void tst_QStateMachine::stateEntryAndExit() diff --git a/tests/auto/qstylesheetstyle/qstylesheetstyle.pro b/tests/auto/qstylesheetstyle/qstylesheetstyle.pro index 6acb0b4..f6101f4 100644 --- a/tests/auto/qstylesheetstyle/qstylesheetstyle.pro +++ b/tests/auto/qstylesheetstyle/qstylesheetstyle.pro @@ -13,3 +13,4 @@ contains(QT_CONFIG, qt3support): QT += qt3support # Input SOURCES += tst_qstylesheetstyle.cpp RESOURCES += resources.qrc +requires(contains(QT_CONFIG,private_tests)) diff --git a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp index 7b62eae..3f658ec 100644 --- a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp +++ b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp @@ -625,9 +625,11 @@ void tst_QSvgRenderer::testGzLoading() QVERIFY(autoDetectGzData.isValid()); } +#ifdef QT_BUILD_INTERNAL QT_BEGIN_NAMESPACE QByteArray qt_inflateGZipDataFrom(QIODevice *device); QT_END_NAMESPACE +#endif void tst_QSvgRenderer::testGzHelper_data() { @@ -660,6 +662,7 @@ void tst_QSvgRenderer::testGzHelper_data() void tst_QSvgRenderer::testGzHelper() { +#ifdef QT_BUILD_INTERNAL QFETCH(QByteArray, in); QFETCH(QByteArray, out); @@ -668,6 +671,7 @@ void tst_QSvgRenderer::testGzHelper() QVERIFY(buffer.isReadable()); QByteArray result = qt_inflateGZipDataFrom(&buffer); QCOMPARE(result, out); +#endif } #endif diff --git a/tests/auto/qtextedit/tst_qtextedit.cpp b/tests/auto/qtextedit/tst_qtextedit.cpp index 3bc1517..d54645c 100644 --- a/tests/auto/qtextedit/tst_qtextedit.cpp +++ b/tests/auto/qtextedit/tst_qtextedit.cpp @@ -1460,6 +1460,7 @@ void tst_QTextEdit::mimeDataReimplementations() QCOMPARE(ed.canInsertCallCount, 0); QCOMPARE(ed.insertCallCount, 0); +#ifdef QT_BUILD_INTERNAL QTextControl *control = qFindChild(&ed); QVERIFY(control); @@ -1474,6 +1475,7 @@ void tst_QTextEdit::mimeDataReimplementations() QCOMPARE(ed.createMimeDataCallCount, 1); QCOMPARE(ed.canInsertCallCount, 1); QCOMPARE(ed.insertCallCount, 1); +#endif } void tst_QTextEdit::ctrlEnterShouldInsertLineSeparator_NOT() @@ -2066,6 +2068,7 @@ void tst_QTextEdit::cursorRect() void tst_QTextEdit::setDocumentPreservesPalette() { +#ifdef QT_BUILD_INTERNAL QTextControl *control = qFindChild(ed); QVERIFY(control); @@ -2085,6 +2088,7 @@ void tst_QTextEdit::setDocumentPreservesPalette() QVERIFY(control->document() == newDoc); QVERIFY(whitePal.color(QPalette::Active, QPalette::Text) == control->palette().color(QPalette::Active, QPalette::Text)); +#endif } class PublicTextEdit : public QTextEdit diff --git a/tests/auto/qtextpiecetable/qtextpiecetable.pro b/tests/auto/qtextpiecetable/qtextpiecetable.pro index 318a8c7..0926b83 100644 --- a/tests/auto/qtextpiecetable/qtextpiecetable.pro +++ b/tests/auto/qtextpiecetable/qtextpiecetable.pro @@ -2,7 +2,6 @@ load(qttest_p4) SOURCES += tst_qtextpiecetable.cpp HEADERS += ../qtextdocument/common.h -!win32:DEFINES += QTEST_REDUCED_EXPORTS - - +requires(!win32) +requires(contains(QT_CONFIG,private_tests)) diff --git a/tests/auto/qtextpiecetable/tst_qtextpiecetable.cpp b/tests/auto/qtextpiecetable/tst_qtextpiecetable.cpp index accbabb..0e60c16 100644 --- a/tests/auto/qtextpiecetable/tst_qtextpiecetable.cpp +++ b/tests/auto/qtextpiecetable/tst_qtextpiecetable.cpp @@ -42,9 +42,7 @@ #include -#ifdef QTEST_REDUCED_EXPORTS #define private public -#endif #include #include @@ -65,7 +63,6 @@ public: tst_QTextPieceTable(); -#ifdef QTEST_REDUCED_EXPORTS public slots: void init(); void cleanup(); @@ -112,13 +109,7 @@ private slots: void removeFrameDirect(); void removeWithChildFrame(); void clearWithFrames(); -#else -public slots: - void init(); - void cleanup(); -private slots: - void skip(); -#endif + private: QTextDocument *doc; QTextDocumentPrivate *table; @@ -130,8 +121,6 @@ tst_QTextPieceTable::tst_QTextPieceTable() { doc = 0; table = 0; } -#ifdef QTEST_REDUCED_EXPORTS - void tst_QTextPieceTable::init() { doc = new QTextDocument(0); @@ -1148,25 +1137,6 @@ void tst_QTextPieceTable::clearWithFrames() QVERIFY(true); } -#else // QTEST_REDUCED_EXPORTS - -void tst_QTextPieceTable::init() -{ -} - -void tst_QTextPieceTable::cleanup() -{ -} - -void tst_QTextPieceTable::skip() -{ - QSKIP( "Not tested on win32", SkipAll ); -} - - -#endif // QTEST_REDUCED_EXPORTS - - QTEST_MAIN(tst_QTextPieceTable) diff --git a/tests/auto/qurl/tst_qurl.cpp b/tests/auto/qurl/tst_qurl.cpp index ea551da..723f882 100644 --- a/tests/auto/qurl/tst_qurl.cpp +++ b/tests/auto/qurl/tst_qurl.cpp @@ -3057,12 +3057,15 @@ void tst_QUrl::nameprep_testsuite_data() << QString() << 0 << 0; } +#ifdef QT_BUILD_INTERNAL QT_BEGIN_NAMESPACE extern QString qt_nameprep(const QString &source); QT_END_NAMESPACE +#endif void tst_QUrl::nameprep_testsuite() { +#ifdef QT_BUILD_INTERNAL QFETCH(QString, in); QFETCH(QString, out); QFETCH(QString, profile); @@ -3082,6 +3085,7 @@ void tst_QUrl::nameprep_testsuite() QEXPECT_FAIL("Larger test (expanding)", "Investigate further", Continue); QCOMPARE(qt_nameprep(in), out); +#endif } void tst_QUrl::ace_testsuite_data() diff --git a/tests/auto/xmlpatternsdiagnosticsts/xmlpatternsdiagnosticsts.pro b/tests/auto/xmlpatternsdiagnosticsts/xmlpatternsdiagnosticsts.pro index e90b335..3d82eaf 100644 --- a/tests/auto/xmlpatternsdiagnosticsts/xmlpatternsdiagnosticsts.pro +++ b/tests/auto/xmlpatternsdiagnosticsts/xmlpatternsdiagnosticsts.pro @@ -2,3 +2,4 @@ TEMPLATE = subdirs CONFIG += ordered SUBDIRS = ../xmlpatternsxqts test +requires(contains(QT_CONFIG,private_tests)) diff --git a/tests/auto/xmlpatternsview/xmlpatternsview.pro b/tests/auto/xmlpatternsview/xmlpatternsview.pro index 3544264..04ee4d0 100644 --- a/tests/auto/xmlpatternsview/xmlpatternsview.pro +++ b/tests/auto/xmlpatternsview/xmlpatternsview.pro @@ -6,3 +6,4 @@ SUBDIRS = ../xmlpatternsxqts test contains(QT_CONFIG,xmlpatterns) { SUBDIRS += view } +requires(contains(QT_CONFIG,private_tests)) diff --git a/tests/auto/xmlpatternsxqts/xmlpatternsxqts.pro b/tests/auto/xmlpatternsxqts/xmlpatternsxqts.pro index 368a028..a3b13da 100644 --- a/tests/auto/xmlpatternsxqts/xmlpatternsxqts.pro +++ b/tests/auto/xmlpatternsxqts/xmlpatternsxqts.pro @@ -9,3 +9,6 @@ contains(QT_CONFIG,xmlpatterns) { # Needed on the win32-g++ setup and on the test machine arsia. INCLUDEPATH += $$QT_BUILD_TREE/include/QtXmlPatterns/private \ ../../../include/QtXmlPatterns/private + +requires(contains(QT_CONFIG,private_tests)) + diff --git a/tests/auto/xmlpatternsxslts/xmlpatternsxslts.pro b/tests/auto/xmlpatternsxslts/xmlpatternsxslts.pro index 4a688c4..9b63a52 100644 --- a/tests/auto/xmlpatternsxslts/xmlpatternsxslts.pro +++ b/tests/auto/xmlpatternsxslts/xmlpatternsxslts.pro @@ -23,3 +23,4 @@ wince*: { DEPLOYMENT += testdata } +requires(contains(QT_CONFIG,private_tests)) -- cgit v0.12 From 21b32a69fc4607e60677b978fbcdc6424cc4f63b Mon Sep 17 00:00:00 2001 From: Rohan McGovern Date: Thu, 9 Jul 2009 14:36:26 +1000 Subject: New configure.exe. Includes: 9b532a999944c70c2e8f57d9156c1887867ad9f1 - qtlibinfix bb8e25a5074a378d5003577fefbeabb1de846a81 - cetest fix 5ea86cfac34f65b2321ceeeb651e4e7099bf59a0 - QT_WA removal 349997b5c4167b07d0bdc55beff175b39f3abe75 - spelling fix bae8bc5d23946036b2c1079fc6f1b3bceeaa19ca - QT_CONFIG+=private_tests --- configure.exe | Bin 835584 -> 1101312 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/configure.exe b/configure.exe index a139116..10b926e 100644 Binary files a/configure.exe and b/configure.exe differ -- cgit v0.12 From 458c547aefcb529fe807a220109e2a7ce6bd9105 Mon Sep 17 00:00:00 2001 From: Rohan McGovern Date: Thu, 9 Jul 2009 16:51:41 +1000 Subject: Improved cetest error reporting. Now, if you try to run an unsigned test on a locked device, you'll get: "Error invoking qRemoteLaunch on \Windows\QtRemote.dll: Invalid Signature. (0x80090006)" Instead of what you would previously get: "Error: Could not execute target file" --- tools/qtestlib/wince/cetest/activesyncconnection.cpp | 12 ++++++++---- tools/qtestlib/wince/cetest/remoteconnection.cpp | 4 ++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/tools/qtestlib/wince/cetest/activesyncconnection.cpp b/tools/qtestlib/wince/cetest/activesyncconnection.cpp index 0f98619..1080477 100644 --- a/tools/qtestlib/wince/cetest/activesyncconnection.cpp +++ b/tools/qtestlib/wince/cetest/activesyncconnection.cpp @@ -385,10 +385,14 @@ bool ActiveSyncConnection::execute(QString program, QString arguments, int timeo DWORD error = 0; HRESULT res = CeRapiInvoke(dllLocation.utf16(), functionName.utf16(), 0, 0, &outputSize, &output, &stream, 0); if (S_OK != res) { - if (S_OK != CeGetLastError()) - debugOutput(QString::fromLatin1("Error: Could not invoke method on QtRemote"),1); - else - debugOutput(QString::fromLatin1("Error: QtRemote return unexpectedly with error Code %1").arg(res), 1); + DWORD ce_error = CeGetLastError(); + if (S_OK != ce_error) { + qWarning("Error invoking %s on %s: %s", qPrintable(functionName), + qPrintable(dllLocation), strwinerror(ce_error).constData()); + } else { + qWarning("Error: %s on %s unexpectedly returned %d", qPrintable(functionName), + qPrintable(dllLocation), res); + } } else { DWORD written; int strSize = program.length(); diff --git a/tools/qtestlib/wince/cetest/remoteconnection.cpp b/tools/qtestlib/wince/cetest/remoteconnection.cpp index 75788e2..3d0c3f3 100644 --- a/tools/qtestlib/wince/cetest/remoteconnection.cpp +++ b/tools/qtestlib/wince/cetest/remoteconnection.cpp @@ -66,8 +66,8 @@ QByteArray strwinerror(DWORD errorcode) out.chop(2); /* Append error number to error message for good measure */ - out.append(" ("); - out.append(QByteArray::number((int)errorcode)); + out.append(" (0x"); + out.append(QByteArray::number(uint(errorcode), 16).rightJustified(8, '0')); out.append(")"); } return out; -- cgit v0.12 From c365e7e91feab7d07653e0086ba297bb1f8a6234 Mon Sep 17 00:00:00 2001 From: Rohan McGovern Date: Thu, 9 Jul 2009 17:03:58 +1000 Subject: Let cetest return nonzero when it fails to run a test. --- tools/qtestlib/wince/cetest/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/qtestlib/wince/cetest/main.cpp b/tools/qtestlib/wince/cetest/main.cpp index ba3ef8d..782f6d9 100644 --- a/tools/qtestlib/wince/cetest/main.cpp +++ b/tools/qtestlib/wince/cetest/main.cpp @@ -320,6 +320,7 @@ int main(int argc, char **argv) cout << endl << "Remote Launch:" << qPrintable(TestConfiguration::remoteExecutable) << " " << qPrintable(launchArguments.join(" ")) << endl; if (!connection.execute(TestConfiguration::remoteExecutable, launchArguments.join(" "), timeout)) { cout << "Error: Could not execute target file" << endl; + return -1; } -- cgit v0.12 From 13bc92c6c9c0b1b7b6c9915848175a77ec082a85 Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Wed, 8 Jul 2009 16:02:55 -0700 Subject: Pass the device arg to the keyboard drivers. We didn't use to pass the device in to the keyboard handlers rendering them mostly useless. Reviewed-by: TrustMe --- src/plugins/kbddrivers/sl5000/main.cpp | 3 +-- src/plugins/kbddrivers/usb/main.cpp | 3 +-- src/plugins/kbddrivers/vr41xx/main.cpp | 3 +-- src/plugins/kbddrivers/yopy/main.cpp | 3 +-- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/plugins/kbddrivers/sl5000/main.cpp b/src/plugins/kbddrivers/sl5000/main.cpp index 4d61266..cc68747 100644 --- a/src/plugins/kbddrivers/sl5000/main.cpp +++ b/src/plugins/kbddrivers/sl5000/main.cpp @@ -66,10 +66,9 @@ QStringList QSL5000KbdDriver::keys() const QWSKeyboardHandler* QSL5000KbdDriver::create(const QString &driver, const QString &device) { - Q_UNUSED(device); if (driver.compare(QLatin1String("SL5000"), Qt::CaseInsensitive)) return 0; - return new QWSSL5000KeyboardHandler(driver); + return new QWSSL5000KeyboardHandler(device); } Q_EXPORT_PLUGIN2(qwssl5000kbddriver, QSL5000KbdDriver) diff --git a/src/plugins/kbddrivers/usb/main.cpp b/src/plugins/kbddrivers/usb/main.cpp index 8f49366..38d460c 100644 --- a/src/plugins/kbddrivers/usb/main.cpp +++ b/src/plugins/kbddrivers/usb/main.cpp @@ -66,10 +66,9 @@ QStringList QUsbKbdDriver::keys() const QWSKeyboardHandler* QUsbKbdDriver::create(const QString &driver, const QString &device) { - Q_UNUSED(device); if (driver.compare(QLatin1String("Usb"), Qt::CaseInsensitive)) return 0; - return new QWSUsbKeyboardHandler(driver); + return new QWSUsbKeyboardHandler(device); } Q_EXPORT_PLUGIN2(qwsusbkbddriver, QUsbKbdDriver) diff --git a/src/plugins/kbddrivers/vr41xx/main.cpp b/src/plugins/kbddrivers/vr41xx/main.cpp index 2cba1f7..c9ba4d7 100644 --- a/src/plugins/kbddrivers/vr41xx/main.cpp +++ b/src/plugins/kbddrivers/vr41xx/main.cpp @@ -66,10 +66,9 @@ QStringList QVr41xxKbdDriver::keys() const QWSKeyboardHandler* QVr41xxKbdDriver::create(const QString &driver, const QString &device) { - Q_UNUSED(device); if (driver.compare(QLatin1String("VR41xx"), Qt::CaseInsensitive)) return 0; - return new QWSVr41xxKeyboardHandler(driver); + return new QWSVr41xxKeyboardHandler(device); } Q_EXPORT_PLUGIN2(qwsvr41xxkbddriver, QVr41xxKbdDriver) diff --git a/src/plugins/kbddrivers/yopy/main.cpp b/src/plugins/kbddrivers/yopy/main.cpp index bfddabe..7079d88 100644 --- a/src/plugins/kbddrivers/yopy/main.cpp +++ b/src/plugins/kbddrivers/yopy/main.cpp @@ -66,10 +66,9 @@ QStringList QYopyKbdDriver::keys() const QWSKeyboardHandler* QYopyKbdDriver::create(const QString &driver, const QString &device) { - Q_UNUSED(device); if (driver.compare(QLatin1String("Yopy"), Qt::CaseInsensitive)) return 0; - return new QWSYopyKeyboardHandler(driver); + return new QWSYopyKeyboardHandler(device); } Q_EXPORT_PLUGIN2(qwsyopykbddriver, QYopyKbdDriver) -- cgit v0.12 From dc2b39a866190e302eed171381c2c0384e152800 Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Thu, 9 Jul 2009 09:25:30 +0200 Subject: qdoc: Removed unnecessary error report/rule qdoc reported an error if you used \section2 on its owin, i.e. with no outer \section1. While strictly speaking correct, it imposed an unnecessary restriction, e.g. sometimes you just want to use \section2 to get a smaller title for a section. --- tools/qdoc3/doc.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/qdoc3/doc.cpp b/tools/qdoc3/doc.cpp index 222b9a1..d5aca0e 100644 --- a/tools/qdoc3/doc.cpp +++ b/tools/qdoc3/doc.cpp @@ -1677,10 +1677,13 @@ void DocParser::startSection(Doc::SectioningUnit unit, int cmd) leavePara(); if (currentSectioningUnit == Doc::Book) { +#if 0 + // mws didn't think this was necessary. if (unit > Doc::Section1) location().warning(tr("Unexpected '\\%1' without '\\%2'") .arg(cmdName(cmd)) .arg(cmdName(CMD_SECTION1))); +#endif currentSectioningUnit = (Doc::SectioningUnit) (unit - 1); priv->constructExtra(); priv->extra->sectioningUnit = currentSectioningUnit; -- cgit v0.12 From d0a36a9e33937066866ef1ecfde3eaecd578d0b7 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Thu, 9 Jul 2009 10:37:26 +0200 Subject: Add QT_END_HEADER to fix compile on PowerPC Mac and make autotest pass. --- src/corelib/tools/qstring.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 6bb0d8e..235c603 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -1235,6 +1235,8 @@ inline int QStringRef::localeAwareCompare(const QStringRef &s1, const QStringRef QT_END_NAMESPACE +QT_END_HEADER + #ifdef QT_USE_FAST_CONCATENATION #include #endif -- cgit v0.12 From 015946b60c991593d28cd1d9383f0eb7e8c30334 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 9 Jul 2009 10:40:13 +0200 Subject: Remove unneeded assert. Triggered on Designer startup on Linux. Acked-by: Thierry Bastian --- src/gui/widgets/qwidgetanimator.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gui/widgets/qwidgetanimator.cpp b/src/gui/widgets/qwidgetanimator.cpp index 26cf905..1a93b51 100644 --- a/src/gui/widgets/qwidgetanimator.cpp +++ b/src/gui/widgets/qwidgetanimator.cpp @@ -100,7 +100,6 @@ void QWidgetAnimator::animate(QWidget *widget, const QRect &_final_geometry, boo m_animation_map[widget] = anim; connect(anim, SIGNAL(finished()), SLOT(animationFinished())); anim->start(QPropertyAnimation::DeleteWhenStopped); - Q_ASSERT(animate || widget->geometry() == final_geometry); #else //we do it in one shot widget->setGeometry(final_geometry); -- cgit v0.12 From def00d15449551cd2e98b1f3f5b4199ad8be92c2 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Thu, 9 Jul 2009 12:14:38 +0200 Subject: autotest fix On the font from the font dialog, we can only test family, size and style --- tests/auto/qfontdialog/tst_qfontdialog.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/auto/qfontdialog/tst_qfontdialog.cpp b/tests/auto/qfontdialog/tst_qfontdialog.cpp index 5f1797b..cbdd440 100644 --- a/tests/auto/qfontdialog/tst_qfontdialog.cpp +++ b/tests/auto/qfontdialog/tst_qfontdialog.cpp @@ -170,8 +170,12 @@ void tst_QFontDialog::task256466_wrongStyle() for (int i = 0; i < familyList->model()->rowCount(); ++i) { QModelIndex currentFamily = familyList->model()->index(i, 0); familyList->setCurrentIndex(currentFamily); - QCOMPARE(dialog.currentFont(), fdb.font(currentFamily.data().toString(), - styleList->currentIndex().data().toString(), sizeList->currentIndex().data().toInt())); + const QFont current = dialog.currentFont(), + expected = fdb.font(currentFamily.data().toString(), + styleList->currentIndex().data().toString(), sizeList->currentIndex().data().toInt()); + QCOMPARE(current.family(), expected.family()); + QCOMPARE(current.style(), expected.style()); + QCOMPARE(current.pointSizeF(), expected.pointSizeF()); } } -- cgit v0.12 From ce770ef755e2dae405ea3c91bd0dedda2f267716 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Thu, 9 Jul 2009 10:52:50 +0200 Subject: QRingBuffer micro optimization --- src/corelib/tools/qringbuffer_p.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h index f3daca7..008c068 100644 --- a/src/corelib/tools/qringbuffer_p.h +++ b/src/corelib/tools/qringbuffer_p.h @@ -303,6 +303,9 @@ public: // read an unspecified amount (will read the first buffer) inline QByteArray read() { + if (bufferSize == 0) + return QByteArray(); + // multiple buffers, just take the first one if (head == 0 && tailBuffer != 0) { QByteArray qba = buffers.takeFirst(); @@ -325,7 +328,7 @@ public: // We can avoid by initializing the QRingBuffer with basicBlockSize of 0 // and only using this read() function. QByteArray qba(readPointer(), nextDataBlockSize()); - buffers.takeFirst(); + buffers.removeFirst(); head = 0; if (tailBuffer == 0) { buffers << QByteArray(); -- cgit v0.12 From cdedc4374b02c0c291c110fd03c77eb6cd1ce69d Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Thu, 2 Jul 2009 13:42:09 +0200 Subject: QNAM: httpDownloadPerformance auto test Reviewed-by: Peter Hartmann --- tests/auto/qnetworkreply/tst_qnetworkreply.cpp | 126 +++++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp index 0dd3cd1..18919a7 100644 --- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp @@ -219,6 +219,9 @@ private Q_SLOTS: void proxyChange(); void authorizationError_data(); void authorizationError(); + + void httpDownloadPerformance_data(); + void httpDownloadPerformance(); }; QT_BEGIN_NAMESPACE @@ -3066,5 +3069,128 @@ void tst_QNetworkReply::authorizationError() QCOMPARE(QString(reply->readAll()), httpBody); } +class HttpDownloadPerformanceClient : QObject { + Q_OBJECT; + QIODevice *device; + public: + HttpDownloadPerformanceClient (QIODevice *dev) : device(dev){ + connect(dev, SIGNAL(readyRead()), this, SLOT(readyReadSlot())); + } + + public slots: + void readyReadSlot() { + device->readAll(); + } + +}; + +class HttpDownloadPerformanceServer : QObject { + Q_OBJECT; + qint64 dataSize; + qint64 dataSent; + QTcpServer server; + QTcpSocket *client; + bool serverSendsContentLength; + bool chunkedEncoding; + +public: + HttpDownloadPerformanceServer (qint64 ds, bool sscl, bool ce) : dataSize(ds), dataSent(0), + client(0), serverSendsContentLength(sscl), chunkedEncoding(ce) { + server.listen(); + connect(&server, SIGNAL(newConnection()), this, SLOT(newConnectionSlot())); + } + + int serverPort() { + return server.serverPort(); + } + +public slots: + + void newConnectionSlot() { + client = server.nextPendingConnection(); + client->setParent(this); + connect(client, SIGNAL(readyRead()), this, SLOT(readyReadSlot())); + connect(client, SIGNAL(bytesWritten(qint64)), this, SLOT(bytesWrittenSlot(qint64))); + } + + void readyReadSlot() { + client->readAll(); + client->write("HTTP/1.0 200 OK\n"); + if (serverSendsContentLength) + client->write(QString("Content-Length: " + QString::number(dataSize) + "\n").toAscii()); + if (chunkedEncoding) + client->write(QString("Transfer-Encoding: chunked\n").toAscii()); + client->write("Connection: close\n\n"); + } + + void bytesWrittenSlot(qint64 amount) { + if (dataSent == dataSize && client) { + // close eventually + + // chunked encoding: we have to send a last "empty" chunk + if (chunkedEncoding) + client->write(QString("0\r\n\r\n").toAscii()); + + client->disconnectFromHost(); + server.close(); + client = 0; + return; + } + + // send data + if (client && client->bytesToWrite() < 100*1024 && dataSent < dataSize) { + qint64 amount = qMin(qint64(16*1024), dataSize - dataSent); + QByteArray data(amount, '@'); + + if (chunkedEncoding) { + client->write(QString(QString("%1").arg(amount,0,16).toUpper() + "\r\n").toAscii()); + client->write(data.constData(), amount); + client->write(QString("\r\n").toAscii()); + } else { + client->write(data.constData(), amount); + } + + dataSent += amount; + } + } +}; + +void tst_QNetworkReply::httpDownloadPerformance_data() +{ + QTest::addColumn("serverSendsContentLength"); + QTest::addColumn("chunkedEncoding"); + + QTest::newRow("Server sends no Content-Length") << false << false; + QTest::newRow("Server sends Content-Length") << true << false; + QTest::newRow("Server uses chunked encoding") << false << true; + +} + +void tst_QNetworkReply::httpDownloadPerformance() +{ + QFETCH(bool, serverSendsContentLength); + QFETCH(bool, chunkedEncoding); + + enum {UploadSize = 1000*1024*1024}; // 1000 MB + HttpDownloadPerformanceServer server(UploadSize, serverSendsContentLength, chunkedEncoding); + + QNetworkRequest request(QUrl("http://127.0.0.1:" + QString::number(server.serverPort()) + "/?bare=1")); + QNetworkReply* reply = manager.get(request); + + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection); + HttpDownloadPerformanceClient client(reply); + + QTime time; + time.start(); + QTestEventLoop::instance().enterLoop(40); + QVERIFY(!QTestEventLoop::instance().timeout()); + + qint64 elapsed = time.elapsed(); + qWarning() << "tst_QNetworkReply::httpDownloadPerformance" << elapsed << "msec, " + << ((UploadSize/1024.0)/(elapsed/1000.0)) << " kB/sec"; + + delete reply; +} + QTEST_MAIN(tst_QNetworkReply) #include "tst_qnetworkreply.moc" -- cgit v0.12 From bdb6d461f4889e38296c859446283c0f9397dbdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 9 Jul 2009 11:08:48 +0200 Subject: Rendering artifacts when hiding a QGraphicsItem. The problem was that update() followed by hide() didn't work as expected because the update() caused all sub-sequent update requests to be discareded. This is correct, however, we have to make sure the ignoreVisible/ignoreOpacity bit is set properly; we won't process a hidden item otherwise. Auto-test included. --- src/gui/graphicsview/qgraphicsscene.cpp | 10 ++++++++++ tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 11 +++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index ae6c53c..0ca72b7 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4358,6 +4358,16 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b /*ignoreVisibleBit=*/force, /*ignoreDirtyBit=*/removingItemFromScene || invalidateChildren, /*ignoreOpacity=*/ignoreOpacity)) { + if (item->d_ptr->dirty) { + // The item is already marked as dirty and will be processed later. However, + // we have to make sure ignoreVisible and ignoreOpacity are set properly; + // otherwise things like: item->update(); item->hide() (force is now true) + // won't work as expected. + if (force) + item->d_ptr->ignoreVisible = 1; + if (ignoreOpacity) + item->d_ptr->ignoreOpacity = 1; + } return; } diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 3f7a50b..d689293 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -6625,6 +6625,17 @@ void tst_QGraphicsItem::update() qApp->processEvents(); QCOMPARE(item->repaints, 0); QCOMPARE(view.repaints, 0); + + // Make sure the area occupied by an item is repainted when hiding it. + view.reset(); + item->repaints = 0; + item->update(); // Full update; all sub-sequent update requests are discarded. + item->hide(); // visible set to 0. ignoreVisible must be set to 1; the item won't be processed otherwise. + qApp->processEvents(); + QCOMPARE(item->repaints, 0); + QCOMPARE(view.repaints, 1); + // The entire item's bounding rect (adjusted for antialiasing) should have been painted. + QCOMPARE(view.paintedRegion, expectedRegion); } void tst_QGraphicsItem::setTransformProperties_data() -- cgit v0.12 From 259575734a52c27018f26e1f7c857ae25a27d39a Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Thu, 9 Jul 2009 11:35:56 +0200 Subject: doc: Clarified the meanings in Qt for reentrant and thread-safe. Task-number: 189232 --- doc/src/threads.qdoc | 82 ++++++++++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 38 deletions(-) diff --git a/doc/src/threads.qdoc b/doc/src/threads.qdoc index 9f7f857..e3da0d4 100644 --- a/doc/src/threads.qdoc +++ b/doc/src/threads.qdoc @@ -262,48 +262,41 @@ \keyword thread-safe \section1 Reentrancy and Thread-Safety - Throughout the Qt documentation, the terms \e reentrant and \e - thread-safe are used to specify how a function can be used in - multithreaded applications: + Throughout the documentation, the terms \e{reentrant} and + \e{thread-safe} are used to mark classes and functions to indicate + how they can be used in multithread applications: \list - \o A \e reentrant function can be called simultaneously by - multiple threads provided that each invocation of the function - references unique data. - \o A \e thread-safe function can be called simultaneously by - multiple threads when each invocation references shared data. - All access to the shared data is serialized. + \o A \e thread-safe function can be called simultaneously from + multiple threads, even when the invocations use shared data, + because all references to the shared data are serialized. + \o A \e reentrant function can also be called simultaneously from + multiple threads, but only if each invocation uses its own data. \endlist - By extension, a class is said to be reentrant if each and every - one of its functions can be called simultaneously by multiple - threads on different instances of the class. Similarly, the class - is said to be thread-safe if the functions can be called by - different threads on the same instance. + Hence, a \e{thread-safe} function is always \e{reentrant}, but a + \e{reentrant} function is not always \e{thread-safe}. - Classes in the documentation will be documented as thread-safe only - if they are intended to be used by multiple threads. + By extension, a class is said to be \e{reentrant} if its member + functions can be called safely from multiple threads as long as + each thread uses a \e{different} instance of the class. The class + is \e{thread-safe} if its member functions can be called safely + from multiple threads, even if all the threads use the \e{same} + instance of the class. - Note that the terminology in this domain isn't entirely - standardized. POSIX uses a somewhat different definition of - reentrancy and thread-safety for its C APIs. When dealing with an - object-oriented C++ class library such as Qt, the definitions - must be adapted. - - Most C++ classes are inherently reentrant, since they typically - only reference member data. Any thread can call such a member - function on an instance of the class, as long as no other thread - is calling a member function on the same instance. For example, - the \c Counter class below is reentrant: + C++ classes are often reentrant, simply because they only access + their own member data. Any thread can call a member function on an + instance of a reentrant class, as long as no other thread can call + a member function on the \e{same} instance of the class at the + same time. For example, the \c Counter class below is reentrant: \snippet doc/src/snippets/threads/threads.cpp 3 \snippet doc/src/snippets/threads/threads.cpp 4 The class isn't thread-safe, because if multiple threads try to modify the data member \c n, the result is undefined. This is - because C++'s \c ++ and \c -- operators aren't necessarily - atomic. Indeed, they usually expand to three machine - instructions: + because the \c ++ and \c -- operators aren't always atomic. + Indeed, they usually expand to three machine instructions: \list 1 \o Load the variable's value in a register. @@ -332,14 +325,27 @@ declared with the \c mutable qualifier because we need to lock and unlock the mutex in \c value(), which is a const function. - Most Qt classes are reentrant and not thread-safe, to avoid the - overhead of repeatedly locking and unlocking a QMutex. For - example, QString is reentrant, meaning that you can use it in - different threads, but you can't access the same QString object - from different threads simultaneously (unless you protect it with - a mutex yourself). A few classes and functions are thread-safe; - these are mainly thread-related classes such as QMutex, or - fundamental functions such as QCoreApplication::postEvent(). + Most Qt classes are \e{reentrant}, but they are not made + \e{thread-safe}, because making them thread-safe would incur the + extra overhead of repeatedly locking and unlocking a QMutex. For + example, QString is reentrant but not thread-safe. You can safely + access \e{different} instances of QString from multiple threads + simultaneously, but you can't access the \e{same} instance of + QString from multiple threads simultaneously (unless you protect + the accesses yourself with a QMutex). + + Some Qt classes and functions are thread-safe. These are mainly + the thread-related classes (e.g. QMutex) and fundamental functions + (e.g. QCoreApplication::postEvent()). + + \note Qt Classes are only documented as \e{thread-safe} if they + are intended to be used by multiple threads. + + \note Terminology in the multithreading domain isn't entirely + standardized. POSIX uses definitions of reentrant and thread-safe + that are somewhat different for its C APIs. When using other + object-oriented C++ class libraries with Qt, be sure the + definitions in use are understood. \section1 Threads and QObjects -- cgit v0.12 From d64754db278e9fe07dbd6c8b7d297600a10d3ae5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= Date: Wed, 8 Jul 2009 19:21:37 +0200 Subject: Stop showing then hiding windows on starting designer in top-level mode Kind of like f37bd111f7622a34b3a7bd63f5a82f6042dc0f0d, but the real thing. The widget box wasn't showing on Linux when switching to top-level mode. Incidentally, this was the main window there... Reviewed-by: Friedemann Kleint After some persuasion the Cat also came to see things this way. --- tools/designer/src/designer/qdesigner_workbench.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tools/designer/src/designer/qdesigner_workbench.cpp b/tools/designer/src/designer/qdesigner_workbench.cpp index ce8dde6..5f8d2a9 100644 --- a/tools/designer/src/designer/qdesigner_workbench.cpp +++ b/tools/designer/src/designer/qdesigner_workbench.cpp @@ -462,7 +462,6 @@ void QDesignerWorkbench::switchToTopLevelMode() // make sure that the widgetbox is visible if it is different from neutral. QDesignerToolWindow *widgetBoxWrapper = widgetBoxToolWindow(); Q_ASSERT(widgetBoxWrapper); - const bool needWidgetBoxWrapperVisible = widgetBoxWrapper->action()->isChecked(); switchToNeutralMode(); const QPoint desktopOffset = desktopGeometry().topLeft(); @@ -501,9 +500,6 @@ void QDesignerWorkbench::switchToTopLevelMode() found_visible_window |= tw->isVisible(); } - if (needWidgetBoxWrapperVisible) - widgetBoxWrapper->action()->trigger(); - if (!m_toolWindows.isEmpty() && !found_visible_window) m_toolWindows.first()->show(); -- cgit v0.12 From ed99255e8e998ef3f51de22b31c76107bb9aa0df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= Date: Thu, 9 Jul 2009 10:55:37 +0200 Subject: Designer: Restore Widget box title when switching to docked mode Reviewed-by: Friedemann Kleint --- tools/designer/src/designer/qdesigner_workbench.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/designer/src/designer/qdesigner_workbench.cpp b/tools/designer/src/designer/qdesigner_workbench.cpp index 5f8d2a9..c9d9fc4 100644 --- a/tools/designer/src/designer/qdesigner_workbench.cpp +++ b/tools/designer/src/designer/qdesigner_workbench.cpp @@ -410,6 +410,12 @@ void QDesignerWorkbench::switchToDockedMode() switchToNeutralMode(); +#ifndef Q_WS_MAC + QDesignerToolWindow *widgetBoxWrapper = widgetBoxToolWindow(); + widgetBoxWrapper->action()->setVisible(true); + widgetBoxWrapper->setWindowTitle(tr("Widget Box")); +#endif + m_mode = DockedMode; const QDesignerSettings settings(m_core); m_dockedMainWindow = new DockedMainWindow(this, m_toolbarMenu, m_toolWindows); -- cgit v0.12 From 14ef40f9b96c5afea9d08701a2a1856388349f9e Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 3 Jul 2009 16:32:26 +0200 Subject: Use 'struct QConcatenable' instead of 'class QConcatenable' to make compiler distinguishing both happy. --- src/corelib/tools/qstringbuilder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h index 852c072..4d6b64b 100644 --- a/src/corelib/tools/qstringbuilder.h +++ b/src/corelib/tools/qstringbuilder.h @@ -69,7 +69,7 @@ private: }; -template class QConcatenable {}; +template struct QConcatenable {}; template class QStringBuilder -- cgit v0.12 From 6574240d8ea657d02c3d5bf5567da7d28f42d69b Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Thu, 9 Jul 2009 12:40:22 +0200 Subject: QHttpNetworkReply: Cache isChunked Cache return value of expensive function. Reviewed-by: Peter Hartmann --- src/network/access/qhttpnetworkreply.cpp | 6 +++++- src/network/access/qhttpnetworkreply_p.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp index 483589b..7a616aa 100644 --- a/src/network/access/qhttpnetworkreply.cpp +++ b/src/network/access/qhttpnetworkreply.cpp @@ -201,6 +201,7 @@ bool QHttpNetworkReply::isFinished() const QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl) : QHttpNetworkHeaderPrivate(newUrl), state(NothingDoneState), statusCode(100), majorVersion(0), minorVersion(0), bodyLength(0), contentRead(0), totalProgress(0), + chunkedTransferEncoding(0), currentChunkSize(0), currentChunkRead(0), connection(0), initInflate(false), autoDecompress(false), responseData(0), requestIsPrepared(false) { @@ -506,6 +507,9 @@ qint64 QHttpNetworkReplyPrivate::readHeader(QAbstractSocket *socket) state = ReadingDataState; fragment.clear(); // next fragment bodyLength = contentLength(); // cache the length + + // cache isChunked() since it is called often + chunkedTransferEncoding = headerField("transfer-encoding").toLower().contains("chunked"); } return bytes; } @@ -546,7 +550,7 @@ void QHttpNetworkReplyPrivate::parseHeader(const QByteArray &header) bool QHttpNetworkReplyPrivate::isChunked() { - return headerField("transfer-encoding").toLower().contains("chunked"); + return chunkedTransferEncoding; } bool QHttpNetworkReplyPrivate::connectionCloseEnabled() diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h index b86cfaa..5eb70ce 100644 --- a/src/network/access/qhttpnetworkreply_p.h +++ b/src/network/access/qhttpnetworkreply_p.h @@ -198,6 +198,7 @@ public: qint64 contentRead; qint64 totalProgress; QByteArray fragment; // used for header, status, chunk header etc, not for reply data + bool chunkedTransferEncoding; qint64 currentChunkSize; qint64 currentChunkRead; QPointer connection; -- cgit v0.12 From 1c6edd28d528dbb946fcf2a9e0d4349075ca6f9b Mon Sep 17 00:00:00 2001 From: Suneel BS Date: Tue, 7 Jul 2009 14:57:02 +0530 Subject: Fixed inheritence of SVG fill attributes. Fixed inheritence of fill-opacity, fill-rule and fill. Autotest included. Reviewed-by: Kim --- src/svg/qsvghandler.cpp | 57 ++++++++++++++--------- src/svg/qsvgstyle.cpp | 14 +++++- src/svg/qsvgstyle_p.h | 28 +++++++----- tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp | 68 ++++++++++++++++++++++++++++ 4 files changed, 132 insertions(+), 35 deletions(-) diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp index 5950fac..f64fb3e 100644 --- a/src/svg/qsvghandler.cpp +++ b/src/svg/qsvghandler.cpp @@ -631,15 +631,32 @@ static void parseBrush(QSvgNode *node, QString opacity = attributes.value(QLatin1String("fill-opacity")).toString(); QString myId = someId(attributes); - value = value.trimmed(); - fillRule = fillRule.trimmed(); - if (!value.isEmpty() || !fillRule.isEmpty()) { - Qt::FillRule f = Qt::WindingFill; + QSvgFillStyle *inherited = + static_cast(node->parent()->styleProperty( + QSvgStyleProperty::FILL)); + QSvgFillStyle *prop = new QSvgFillStyle(QColor(Qt::black)); + + //fill-rule attribute handling + Qt::FillRule f = Qt::WindingFill; + if (!fillRule.isEmpty() && fillRule != QLatin1String("inherit")) { if (fillRule == QLatin1String("evenodd")) f = Qt::OddEvenFill; + } else if (inherited) { + f = inherited->fillRule(); + } + + //fill-opacity atttribute handling + qreal fillOpacity = 1.0; + if (!opacity.isEmpty() && opacity != QLatin1String("inherit")) { + fillOpacity = qMin(qreal(1.0), qMax(qreal(0.0), toDouble(opacity))); + } else if (inherited) { + fillOpacity = inherited->fillOpacity(); + } + + //fill attribute handling + if ((!value.isEmpty()) && (value != QLatin1String("inherit")) ) { if (value.startsWith(QLatin1String("url"))) { value = value.remove(0, 3); - QSvgFillStyle *prop = new QSvgFillStyle(0); QSvgStyleProperty *style = styleFromUrl(node, value); if (style) { prop->setFillStyle(style); @@ -648,30 +665,26 @@ static void parseBrush(QSvgNode *node, prop->setGradientId(id); prop->setGradientResolved(false); } - if (!opacity.isEmpty()) { - qreal clampedOpacity = qMin(qreal(1.0), qMax(qreal(0.0), toDouble(opacity))); - prop->setFillOpacity(clampedOpacity); - } - if (!fillRule.isEmpty()) - prop->setFillRule(f); - node->appendStyleProperty(prop,myId); } else if (value != QLatin1String("none")) { QColor color; - if (constructColor(value, opacity, color, handler)) { - QSvgFillStyle *prop = new QSvgFillStyle(QBrush(color)); - if (!fillRule.isEmpty()) - prop->setFillRule(f); - node->appendStyleProperty(prop, myId); - } + if (resolveColor(value, color, handler)) + prop->setBrush(QBrush(color)); } else { - QSvgFillStyle *prop = new QSvgFillStyle(QBrush(Qt::NoBrush)); - if (!fillRule.isEmpty()) - prop->setFillRule(f); - node->appendStyleProperty(prop, myId); + prop->setBrush(QBrush(Qt::NoBrush)); + } + } else if (inherited) { + if (inherited->style()) { + prop->setFillStyle(inherited->style()); + } else { + prop->setBrush(inherited->qbrush()); } } + prop->setFillOpacity(fillOpacity); + prop->setFillRule(f); + node->appendStyleProperty(prop,myId); } + static void parseQPen(QPen &pen, QSvgNode *node, const QSvgAttributes &attributes, QSvgHandler *handler) diff --git a/src/svg/qsvgstyle.cpp b/src/svg/qsvgstyle.cpp index 556201b..4c8247b 100644 --- a/src/svg/qsvgstyle.cpp +++ b/src/svg/qsvgstyle.cpp @@ -81,12 +81,12 @@ void QSvgQualityStyle::revert(QPainter *, QSvgExtraStates &) } QSvgFillStyle::QSvgFillStyle(const QBrush &brush) - : m_fill(brush), m_style(0), m_fillRuleSet(false), m_fillOpacitySet(false), m_gradientResolved (true) + : m_fill(brush), m_style(0), m_fillRuleSet(false), m_fillOpacitySet(false), m_fillRule(Qt::WindingFill), m_fillOpacity(1.0), m_gradientResolved (true) { } QSvgFillStyle::QSvgFillStyle(QSvgStyleProperty *style) - : m_style(style), m_fillRuleSet(false), m_fillOpacitySet(false), m_gradientResolved (true) + : m_style(style), m_fillRuleSet(false), m_fillOpacitySet(false), m_fillRule(Qt::WindingFill), m_fillOpacity(1.0), m_gradientResolved (true) { } @@ -102,6 +102,16 @@ void QSvgFillStyle::setFillOpacity(qreal opacity) m_fillOpacity = opacity; } +void QSvgFillStyle::setFillStyle(QSvgStyleProperty* style) +{ + m_style = style; +} + +void QSvgFillStyle::setBrush(QBrush brush) +{ + m_fill = brush; +} + static void recursivelySetFill(QSvgNode *node, Qt::FillRule f) { if (node->type() == QSvgNode::PATH) { diff --git a/src/svg/qsvgstyle_p.h b/src/svg/qsvgstyle_p.h index f1d0811..ac5e109 100644 --- a/src/svg/qsvgstyle_p.h +++ b/src/svg/qsvgstyle_p.h @@ -224,12 +224,29 @@ public: void setFillRule(Qt::FillRule f); void setFillOpacity(qreal opacity); + void setFillStyle(QSvgStyleProperty* style); + void setBrush(QBrush brush); const QBrush & qbrush() const { return m_fill; } + qreal fillOpacity() const + { + return m_fillOpacity; + } + + Qt::FillRule fillRule() const + { + return m_fillRule; + } + + QSvgStyleProperty* style() const + { + return m_style; + } + void setGradientId(const QString &Id) { m_gradientId = Id; @@ -240,7 +257,6 @@ public: return m_gradientId; } - void setGradientResolved(bool resolved) { m_gradientResolved = resolved; @@ -251,16 +267,6 @@ public: return m_gradientResolved; } - void setFillStyle(QSvgStyleProperty* style) - { - m_style = style; - } - - void setBrush(QBrush brush) - { - m_fill = brush; - } - private: // fill v v 'inherit' | // fill-opacity v v 'inherit' | diff --git a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp index 3f658ec..68539ef 100644 --- a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp +++ b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp @@ -81,6 +81,7 @@ private slots: void paths(); void displayMode(); void strokeInherit(); + void testFillInheritance(); #ifndef QT_NO_COMPRESS void testGzLoading(); @@ -1053,5 +1054,72 @@ void tst_QSvgRenderer::strokeInherit() } } +void tst_QSvgRenderer::testFillInheritance() +{ + static const char *svgs[] = { + //reference + "" + " " + "", + "" + " " + " " + "", + "" + " " + " " + " " + " " + "", + "" + " " + " " + " " + " " + " " + " " + "", + "" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + "", + "" + " " + " " + " " + " " + " " + " " + "" + }; + + const int COUNT = sizeof(svgs) / sizeof(svgs[0]); + QImage images[COUNT]; + QPainter p; + + for (int i = 0; i < COUNT; ++i) { + QByteArray data(svgs[i]); + QSvgRenderer renderer(data); + QVERIFY(renderer.isValid()); + images[i] = QImage(200, 200, QImage::Format_ARGB32_Premultiplied); + images[i].fill(-1); + p.begin(&images[i]); + renderer.render(&p); + p.end(); + if (i != 0) { + QCOMPARE(images[0], images[i]); + } + } +} QTEST_MAIN(tst_QSvgRenderer) #include "tst_qsvgrenderer.moc" -- cgit v0.12 From ed564a3fef39b649bd38a181126711431f0b40ab Mon Sep 17 00:00:00 2001 From: Suneel BS Date: Thu, 14 May 2009 14:25:16 +0530 Subject: Fixed handling of some SVG attributes when value is invalid. When the parsing of an SVG attribute fails, it should be given the default value. Fixed handling of invalid viewBox, stop-opacity and stop-offset. Autotest included. Reviewed-by: Kim --- src/svg/qsvghandler.cpp | 48 +++++++++++----- tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp | 84 ++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 14 deletions(-) diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp index f64fb3e..5f9d1dd 100644 --- a/src/svg/qsvghandler.cpp +++ b/src/svg/qsvghandler.cpp @@ -68,6 +68,7 @@ QT_BEGIN_NAMESPACE + double qstrtod(const char *s00, char const **se, bool *ok); static bool parsePathDataFast(const QStringRef &data, QPainterPath &path); @@ -320,6 +321,7 @@ static qreal toDouble(const QChar *&str) ++str; } } + temp[pos] = '\0'; qreal val; @@ -365,16 +367,24 @@ static qreal toDouble(const QChar *&str) return val; } -static qreal toDouble(const QString &str) +static qreal toDouble(const QString &str, bool *ok = NULL) { const QChar *c = str.constData(); - return toDouble(c); + qreal res = toDouble(c); + if (ok) { + *ok = ((*c) == QLatin1Char('\0')); + } + return res; } -static qreal toDouble(const QStringRef &str) +static qreal toDouble(const QStringRef &str, bool *ok = NULL) { const QChar *c = str.constData(); - return toDouble(c); + qreal res = toDouble(c); + if (ok) { + *ok = (c == (str.constData() + str.length())); + } + return res; } static QVector parseNumbersList(const QChar *&str) @@ -497,14 +507,17 @@ static bool constructColor(const QString &colorStr, const QString &opacity, if (!resolveColor(colorStr, color, handler)) return false; if (!opacity.isEmpty()) { - qreal op = qMin(qreal(1.0), qMax(qreal(0.0), toDouble(opacity))); + bool ok = true; + qreal op = qMin(qreal(1.0), qMax(qreal(0.0), toDouble(opacity, &ok))); + if (!ok) + op = 1.0; color.setAlphaF(op); } return true; } static qreal parseLength(const QString &str, QSvgHandler::LengthType &type, - QSvgHandler *handler) + QSvgHandler *handler, bool *ok = NULL) { QString numStr = str.trimmed(); @@ -533,15 +546,15 @@ static qreal parseLength(const QString &str, QSvgHandler::LengthType &type, type = handler->defaultCoordinateSystem(); //type = QSvgHandler::LT_OTHER; } - qreal len = toDouble(numStr); + qreal len = toDouble(numStr, ok); //qDebug()<<"len is "<setViewBox(QRectF(x, y, w, h)); - } else if (width && height){ + + } else if (width && height) { if (type == QSvgHandler::LT_PT) { width = convertToPixels(width, false, type); height = convertToPixels(height, false, type); } - node->setViewBox(QRectF(0, 0, width, height)); } - handler->setDefaultCoordinateSystem(QSvgHandler::LT_PX); return node; diff --git a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp index 68539ef..2bbe897 100644 --- a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp +++ b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp @@ -82,6 +82,7 @@ private slots: void displayMode(); void strokeInherit(); void testFillInheritance(); + void testStopOffsetOpacity(); #ifndef QT_NO_COMPRESS void testGzLoading(); @@ -1121,5 +1122,88 @@ void tst_QSvgRenderer::testFillInheritance() } } } +void tst_QSvgRenderer::testStopOffsetOpacity() +{ + static const char *svgs[] = { + //reference + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "", + //Stop Offset + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "", + //Stop Opacity + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "", + //Stop offset and Stop opacity + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + }; + + QImage images[4]; + QPainter p; + + for (int i = 0; i < 4; ++i) { + QByteArray data(svgs[i]); + QSvgRenderer renderer(data); + QVERIFY(renderer.isValid()); + images[i] = QImage(64, 64, QImage::Format_ARGB32_Premultiplied); + images[i].fill(-1); + p.begin(&images[i]); + renderer.render(&p); + p.end(); + } + QCOMPARE(images[0], images[1]); + QCOMPARE(images[0], images[2]); + QCOMPARE(images[0], images[3]); +} + QTEST_MAIN(tst_QSvgRenderer) #include "tst_qsvgrenderer.moc" -- cgit v0.12 From cae93bf07958ea065f4fefd729099bac59a1bf14 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Thu, 9 Jul 2009 13:18:28 +0200 Subject: Fixes a memory corruption when converting data with QIconvCodec This partially reverts 9a5b40a011bd1b15a67d83564af55011761f8ad9 for the QIconvCodec. Reviewed-by: hjk --- src/corelib/codecs/qiconvcodec.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/corelib/codecs/qiconvcodec.cpp b/src/corelib/codecs/qiconvcodec.cpp index 1bf76ea..188ac8c 100644 --- a/src/corelib/codecs/qiconvcodec.cpp +++ b/src/corelib/codecs/qiconvcodec.cpp @@ -225,10 +225,11 @@ QString QIconvCodec::convertToUnicode(const char* chars, int len, ConverterState char *inBytes = const_cast(chars); #endif + QByteArray in; if (remainingCount) { // we have to prepend the remaining bytes from the previous conversion inBytesLeft += remainingCount; - QByteArray in(inBytesLeft, Qt::Uninitialized); + in.resize(inBytesLeft); inBytes = in.data(); memcpy(in.data(), remainingBuffer, remainingCount); @@ -362,9 +363,10 @@ QByteArray QIconvCodec::convertFromUnicode(const QChar *uc, int len, ConverterSt inBytes = const_cast(reinterpret_cast(uc)); inBytesLeft = len * sizeof(QChar); + QByteArray in; if (convState && convState->remainingChars) { // we have one surrogate char to be prepended - QByteArray in(sizeof(QChar) + len, Qt::Uninitialized); + in.resize(sizeof(QChar) + len); inBytes = in.data(); QChar remaining = convState->state_data[0]; -- cgit v0.12 From 916b5c69e1ed5667e4fe97a21e7e15abfd60ec3d Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Thu, 9 Jul 2009 13:41:40 +0200 Subject: doc: Minor edits of reentrant/thread-safe expalantion. Task-number: 189232 --- doc/src/threads.qdoc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/src/threads.qdoc b/doc/src/threads.qdoc index e3da0d4..8469f51 100644 --- a/doc/src/threads.qdoc +++ b/doc/src/threads.qdoc @@ -278,7 +278,7 @@ \e{reentrant} function is not always \e{thread-safe}. By extension, a class is said to be \e{reentrant} if its member - functions can be called safely from multiple threads as long as + functions can be called safely from multiple threads, as long as each thread uses a \e{different} instance of the class. The class is \e{thread-safe} if its member functions can be called safely from multiple threads, even if all the threads use the \e{same} @@ -325,14 +325,14 @@ declared with the \c mutable qualifier because we need to lock and unlock the mutex in \c value(), which is a const function. - Most Qt classes are \e{reentrant}, but they are not made + Many Qt classes are \e{reentrant}, but they are not made \e{thread-safe}, because making them thread-safe would incur the extra overhead of repeatedly locking and unlocking a QMutex. For example, QString is reentrant but not thread-safe. You can safely access \e{different} instances of QString from multiple threads - simultaneously, but you can't access the \e{same} instance of - QString from multiple threads simultaneously (unless you protect - the accesses yourself with a QMutex). + simultaneously, but you can't safely access the \e{same} instance + of QString from multiple threads simultaneously (unless you + protect the accesses yourself with a QMutex). Some Qt classes and functions are thread-safe. These are mainly the thread-related classes (e.g. QMutex) and fundamental functions @@ -345,7 +345,7 @@ standardized. POSIX uses definitions of reentrant and thread-safe that are somewhat different for its C APIs. When using other object-oriented C++ class libraries with Qt, be sure the - definitions in use are understood. + definitions are understood. \section1 Threads and QObjects -- cgit v0.12 From c5371bd1f3df4467ca17350ec7c3e3635d16e393 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Thu, 9 Jul 2009 12:10:18 +0200 Subject: QTreeView: use QVariantAnimation over QTimeLine --- src/gui/itemviews/qabstractitemview_p.h | 3 -- src/gui/itemviews/qtreeview.cpp | 74 ++++++++++++++------------------- src/gui/itemviews/qtreeview.h | 2 - src/gui/itemviews/qtreeview_p.h | 43 ++++++++++--------- 4 files changed, 55 insertions(+), 67 deletions(-) diff --git a/src/gui/itemviews/qabstractitemview_p.h b/src/gui/itemviews/qabstractitemview_p.h index 2950bcd..3119c9d 100644 --- a/src/gui/itemviews/qabstractitemview_p.h +++ b/src/gui/itemviews/qabstractitemview_p.h @@ -61,8 +61,6 @@ #include "QtGui/qmime.h" #include "QtGui/qpainter.h" #include "QtCore/qpair.h" -#include "QtCore/qtimer.h" -#include "QtCore/qtimeline.h" #include "QtGui/qregion.h" #include "QtCore/qdebug.h" #include "QtGui/qpainter.h" @@ -376,7 +374,6 @@ public: QBasicTimer updateTimer; QBasicTimer delayedEditing; QBasicTimer delayedAutoScroll; //used when an item is clicked - QTimeLine timeline; QAbstractItemView::ScrollMode verticalScrollMode; QAbstractItemView::ScrollMode horizontalScrollMode; diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp index 7c319dc..ab700e9 100644 --- a/src/gui/itemviews/qtreeview.cpp +++ b/src/gui/itemviews/qtreeview.cpp @@ -1267,10 +1267,13 @@ void QTreeView::paintEvent(QPaintEvent *event) Q_D(QTreeView); d->executePostedLayout(); QPainter painter(viewport()); +#ifndef QT_NO_ANIMATION if (d->isAnimating()) { - drawTree(&painter, event->region() - d->animationRect()); + drawTree(&painter, event->region() - d->animatedOperation.rect()); d->drawAnimatedOperation(&painter); - } else { + } else +#endif //QT_NO_ANIMATION + { drawTree(&painter, event->region()); #ifndef QT_NO_DRAGANDDROP d->paintDropIndicator(&painter); @@ -2851,10 +2854,6 @@ void QTreeViewPrivate::initialize() header->setStretchLastSection(true); header->setDefaultAlignment(Qt::AlignLeft|Qt::AlignVCenter); q->setHeader(header); - - // animation - QObject::connect(&timeline, SIGNAL(frameChanged(int)), q, SLOT(_q_animate())); - QObject::connect(&timeline, SIGNAL(finished()), q, SLOT(_q_endAnimatedOperation()), Qt::QueuedConnection); } void QTreeViewPrivate::expand(int item, bool emitSignal) @@ -2864,9 +2863,10 @@ void QTreeViewPrivate::expand(int item, bool emitSignal) if (item == -1 || viewItems.at(item).expanded) return; +#ifndef QT_NO_ANIMATION if (emitSignal && animationsEnabled) - prepareAnimatedOperation(item, AnimatedOperation::Expand); - + prepareAnimatedOperation(item, QVariantAnimation::Forward); +#endif //QT_NO_ANIMATION QAbstractItemView::State oldState = q->state(); q->setState(QAbstractItemView::ExpandingState); const QModelIndex index = viewItems.at(item).index; @@ -2877,8 +2877,10 @@ void QTreeViewPrivate::expand(int item, bool emitSignal) if (emitSignal) { emit q->expanded(index); +#ifndef QT_NO_ANIMATION if (animationsEnabled) beginAnimatedOperation(); +#endif //QT_NO_ANIMATION } if (model->canFetchMore(index)) model->fetchMore(index); @@ -2902,8 +2904,10 @@ void QTreeViewPrivate::collapse(int item, bool emitSignal) if (it == expandedIndexes.end() || viewItems.at(item).expanded == false) return; // nothing to do +#ifndef QT_NO_ANIMATION if (emitSignal && animationsEnabled) - prepareAnimatedOperation(item, AnimatedOperation::Collapse); + prepareAnimatedOperation(item, QVariantAnimation::Backward); +#endif //QT_NO_ANIMATION QAbstractItemView::State oldState = q->state(); q->setState(QAbstractItemView::CollapsingState); @@ -2922,29 +2926,33 @@ void QTreeViewPrivate::collapse(int item, bool emitSignal) if (emitSignal) { emit q->collapsed(modelIndex); +#ifndef QT_NO_ANIMATION if (animationsEnabled) beginAnimatedOperation(); +#endif //QT_NO_ANIMATION } } -void QTreeViewPrivate::prepareAnimatedOperation(int item, AnimatedOperation::Type type) +#ifndef QT_NO_ANIMATION +void QTreeViewPrivate::prepareAnimatedOperation(int item, QVariantAnimation::Direction direction) { animatedOperation.item = item; - animatedOperation.type = type; + animatedOperation.view = q_func(); + animatedOperation.setDirection(direction); int top = coordinateForItem(item) + itemHeight(item); QRect rect = viewport->rect(); rect.setTop(top); - if (type == AnimatedOperation::Collapse) { + if (direction == QVariantAnimation::Backward) { const int limit = rect.height() * 2; int h = 0; int c = item + viewItems.at(item).total + 1; for (int i = item + 1; i < c && h < limit; ++i) h += itemHeight(i); rect.setHeight(h); - animatedOperation.duration = h; + animatedOperation.setEndValue(top + h); } - animatedOperation.top = top; + animatedOperation.setStartValue(top); animatedOperation.before = renderTreeToPixmapForAnimation(rect); } @@ -2953,50 +2961,29 @@ void QTreeViewPrivate::beginAnimatedOperation() Q_Q(QTreeView); QRect rect = viewport->rect(); - rect.setTop(animatedOperation.top); - if (animatedOperation.type == AnimatedOperation::Expand) { + rect.setTop(animatedOperation.top()); + if (animatedOperation.direction() == QVariantAnimation::Forward) { const int limit = rect.height() * 2; int h = 0; int c = animatedOperation.item + viewItems.at(animatedOperation.item).total + 1; for (int i = animatedOperation.item + 1; i < c && h < limit; ++i) h += itemHeight(i); rect.setHeight(h); - animatedOperation.duration = h; + animatedOperation.setEndValue(animatedOperation.top() + h); } animatedOperation.after = renderTreeToPixmapForAnimation(rect); q->setState(QAbstractItemView::AnimatingState); - - timeline.stop(); - timeline.setDuration(250); - timeline.setFrameRange(animatedOperation.top, animatedOperation.top + animatedOperation.duration); - timeline.start(); -} - -void QTreeViewPrivate::_q_endAnimatedOperation() -{ - Q_Q(QTreeView); - animatedOperation.before = QPixmap(); - animatedOperation.after = QPixmap(); - q->setState(QAbstractItemView::NoState); - q->updateGeometries(); - viewport->update(); -} - -void QTreeViewPrivate::_q_animate() -{ - QRect rect = viewport->rect(); - rect.moveTop(animatedOperation.top); - viewport->repaint(rect); + animatedOperation.start(); //let's start the animation } void QTreeViewPrivate::drawAnimatedOperation(QPainter *painter) const { - int start = timeline.startFrame(); - int end = timeline.endFrame(); - bool collapsing = animatedOperation.type == AnimatedOperation::Collapse; - int current = collapsing ? end - timeline.currentFrame() + start : timeline.currentFrame(); + const int start = animatedOperation.startValue().toInt(), + end = animatedOperation.endValue().toInt(), + current = animatedOperation.currentValue().toInt(); + bool collapsing = animatedOperation.direction() == QVariantAnimation::Backward; const QPixmap top = collapsing ? animatedOperation.before : animatedOperation.after; painter->drawPixmap(0, start, top, 0, end - current - 1, top.width(), top.height()); const QPixmap bottom = collapsing ? animatedOperation.after : animatedOperation.before; @@ -3038,6 +3025,7 @@ QPixmap QTreeViewPrivate::renderTreeToPixmapForAnimation(const QRect &rect) cons return pixmap; } +#endif //QT_NO_ANIMATION void QTreeViewPrivate::_q_currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { diff --git a/src/gui/itemviews/qtreeview.h b/src/gui/itemviews/qtreeview.h index 0347645..34f7630 100644 --- a/src/gui/itemviews/qtreeview.h +++ b/src/gui/itemviews/qtreeview.h @@ -223,8 +223,6 @@ private: Q_DECLARE_PRIVATE(QTreeView) Q_DISABLE_COPY(QTreeView) - Q_PRIVATE_SLOT(d_func(), void _q_endAnimatedOperation()) - Q_PRIVATE_SLOT(d_func(), void _q_animate()) Q_PRIVATE_SLOT(d_func(), void _q_currentChanged(const QModelIndex&, const QModelIndex &)) Q_PRIVATE_SLOT(d_func(), void _q_modelAboutToBeReset()) Q_PRIVATE_SLOT(d_func(), void _q_sortIndicatorChanged(int column, Qt::SortOrder order)) diff --git a/src/gui/itemviews/qtreeview_p.h b/src/gui/itemviews/qtreeview_p.h index 6a1dfe5..77e57d6 100644 --- a/src/gui/itemviews/qtreeview_p.h +++ b/src/gui/itemviews/qtreeview_p.h @@ -54,6 +54,7 @@ // #include "private/qabstractitemview_p.h" +#include #ifndef QT_NO_TREEVIEW @@ -81,42 +82,48 @@ public: uniformRowHeights(false), rootDecoration(true), itemsExpandable(true), sortingEnabled(false), expandsOnDoubleClick(true), - allColumnsShowFocus(false), + allColumnsShowFocus(false), current(0), animationsEnabled(false), columnResizeTimerID(0), autoExpandDelay(-1), hoverBranch(-1), geometryRecursionBlock(false) {} ~QTreeViewPrivate() {} void initialize(); - struct AnimatedOperation +#ifndef QT_NO_ANIMATION + struct AnimatedOperation : public QVariantAnimation { - enum Type { Expand, Collapse }; int item; - int top; - int duration; - Type type; QPixmap before; QPixmap after; - }; - - void expand(int item, bool emitSignal); - void collapse(int item, bool emitSignal); - - void prepareAnimatedOperation(int item, AnimatedOperation::Type type); + QTreeView *view; + AnimatedOperation() : item(0) { setEasingCurve(QEasingCurve::InOutQuad); } + int top() const { return startValue().toInt(); } + QRect rect() const { QRect rect = view->viewport()->rect(); rect.moveTop(top()); return rect; } + void updateCurrentValue(const QVariant &) { view->viewport()->update(rect()); } + void updateState(State, State state) + { + if (state == Stopped) { + before = after = QPixmap(); + view->setState(QAbstractItemView::NoState); + view->updateGeometries(); + view->viewport()->update(); + } + } + } animatedOperation; + void prepareAnimatedOperation(int item, QVariantAnimation::Direction d); void beginAnimatedOperation(); - void _q_endAnimatedOperation(); void drawAnimatedOperation(QPainter *painter) const; QPixmap renderTreeToPixmapForAnimation(const QRect &rect) const; +#endif //QT_NO_ANIMATION + + void expand(int item, bool emitSignal); + void collapse(int item, bool emitSignal); - inline QRect animationRect() const - { return QRect(0, animatedOperation.top, viewport->width(), - viewport->height() - animatedOperation.top); } void _q_currentChanged(const QModelIndex&, const QModelIndex&); void _q_columnsAboutToBeRemoved(const QModelIndex &, int, int); void _q_columnsRemoved(const QModelIndex &, int, int); void _q_modelAboutToBeReset(); - void _q_animate(); void _q_sortIndicatorChanged(int column, Qt::SortOrder order); void _q_modelDestroyed(); @@ -177,8 +184,6 @@ public: // used when expanding and collapsing items QSet expandedIndexes; - QStack expandParent; - AnimatedOperation animatedOperation; bool animationsEnabled; inline bool storeExpanded(const QPersistentModelIndex &idx) { -- cgit v0.12 From 17cd046cfd7ab8ff3eaf0c09ae083ff8b2c89c89 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Thu, 9 Jul 2009 13:45:35 +0200 Subject: QTreeView: cleanup of useless private slots currentChange is slot in the public class (QAbstractItemView --- src/gui/dialogs/qfiledialog_p.h | 1 - src/gui/itemviews/qtreeview.cpp | 63 +++++++++++++---------------------------- src/gui/itemviews/qtreeview.h | 2 -- src/gui/itemviews/qtreeview_p.h | 2 -- 4 files changed, 20 insertions(+), 48 deletions(-) diff --git a/src/gui/dialogs/qfiledialog_p.h b/src/gui/dialogs/qfiledialog_p.h index d798f9d..4c599cc 100644 --- a/src/gui/dialogs/qfiledialog_p.h +++ b/src/gui/dialogs/qfiledialog_p.h @@ -73,7 +73,6 @@ #include #include #include -#include #include #include "qsidebar_p.h" diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp index ab700e9..e4c7cd3 100644 --- a/src/gui/itemviews/qtreeview.cpp +++ b/src/gui/itemviews/qtreeview.cpp @@ -262,10 +262,6 @@ void QTreeView::setSelectionModel(QItemSelectionModel *selectionModel) Q_D(QTreeView); Q_ASSERT(selectionModel); if (d->selectionModel) { - if (d->allColumnsShowFocus) { - QObject::disconnect(d->selectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)), - this, SLOT(_q_currentChanged(QModelIndex,QModelIndex))); - } // support row editing disconnect(d->selectionModel, SIGNAL(currentRowChanged(QModelIndex,QModelIndex)), d->model, SLOT(submit())); @@ -275,10 +271,6 @@ void QTreeView::setSelectionModel(QItemSelectionModel *selectionModel) QAbstractItemView::setSelectionModel(selectionModel); if (d->selectionModel) { - if (d->allColumnsShowFocus) { - QObject::connect(d->selectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)), - this, SLOT(_q_currentChanged(QModelIndex,QModelIndex))); - } // support row editing connect(d->selectionModel, SIGNAL(currentRowChanged(QModelIndex,QModelIndex)), d->model, SLOT(submit())); @@ -901,15 +893,6 @@ void QTreeView::setAllColumnsShowFocus(bool enable) Q_D(QTreeView); if (d->allColumnsShowFocus == enable) return; - if (d->selectionModel) { - if (enable) { - QObject::connect(d->selectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)), - this, SLOT(_q_currentChanged(QModelIndex,QModelIndex))); - } else { - QObject::disconnect(d->selectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)), - this, SLOT(_q_currentChanged(QModelIndex,QModelIndex))); - } - } d->allColumnsShowFocus = enable; d->viewport->update(); } @@ -1309,13 +1292,13 @@ bool QTreeViewPrivate::expandOrCollapseItemAtPos(const QPoint &pos) { Q_Q(QTreeView); // we want to handle mousePress in EditingState (persistent editors) - if ((q->state() != QAbstractItemView::NoState - && q->state() != QAbstractItemView::EditingState) + if ((state != QAbstractItemView::NoState + && state != QAbstractItemView::EditingState) || !viewport->rect().contains(pos)) return true; int i = itemDecorationAt(pos); - if ((i != -1) && q->itemsExpandable() && hasVisibleChildren(viewItems.at(i).index)) { + if ((i != -1) && itemsExpandable && hasVisibleChildren(viewItems.at(i).index)) { if (viewItems.at(i).expanded) collapse(i, true); else @@ -2867,7 +2850,7 @@ void QTreeViewPrivate::expand(int item, bool emitSignal) if (emitSignal && animationsEnabled) prepareAnimatedOperation(item, QVariantAnimation::Forward); #endif //QT_NO_ANIMATION - QAbstractItemView::State oldState = q->state(); + QAbstractItemView::State oldState = state; q->setState(QAbstractItemView::ExpandingState); const QModelIndex index = viewItems.at(item).index; storeExpanded(index); @@ -2909,7 +2892,7 @@ void QTreeViewPrivate::collapse(int item, bool emitSignal) prepareAnimatedOperation(item, QVariantAnimation::Backward); #endif //QT_NO_ANIMATION - QAbstractItemView::State oldState = q->state(); + QAbstractItemView::State oldState = state; q->setState(QAbstractItemView::CollapsingState); expandedIndexes.erase(it); viewItems[item].expanded = false; @@ -3027,27 +3010,6 @@ QPixmap QTreeViewPrivate::renderTreeToPixmapForAnimation(const QRect &rect) cons } #endif //QT_NO_ANIMATION -void QTreeViewPrivate::_q_currentChanged(const QModelIndex ¤t, const QModelIndex &previous) -{ - Q_Q(QTreeView); - if (previous.isValid()) { - QRect previousRect = q->visualRect(previous); - if (allColumnsShowFocus) { - previousRect.setX(0); - previousRect.setWidth(viewport->width()); - } - viewport->update(previousRect); - } - if (current.isValid()) { - QRect currentRect = q->visualRect(current); - if (allColumnsShowFocus) { - currentRect.setX(0); - currentRect.setWidth(viewport->width()); - } - viewport->update(currentRect); - } -} - void QTreeViewPrivate::_q_modelAboutToBeReset() { viewItems.clear(); @@ -3775,6 +3737,21 @@ void QTreeView::currentChanged(const QModelIndex ¤t, const QModelIndex &pr } #endif QAbstractItemView::currentChanged(current, previous); + + if (allColumnsShowFocus()) { + if (previous.isValid()) { + QRect previousRect = visualRect(previous); + previousRect.setX(0); + previousRect.setWidth(viewport()->width()); + viewport()->update(previousRect); + } + if (current.isValid()) { + QRect currentRect = visualRect(current); + currentRect.setX(0); + currentRect.setWidth(viewport()->width()); + viewport()->update(currentRect); + } + } } /*! diff --git a/src/gui/itemviews/qtreeview.h b/src/gui/itemviews/qtreeview.h index 34f7630..b2a9de2f 100644 --- a/src/gui/itemviews/qtreeview.h +++ b/src/gui/itemviews/qtreeview.h @@ -223,10 +223,8 @@ private: Q_DECLARE_PRIVATE(QTreeView) Q_DISABLE_COPY(QTreeView) - Q_PRIVATE_SLOT(d_func(), void _q_currentChanged(const QModelIndex&, const QModelIndex &)) Q_PRIVATE_SLOT(d_func(), void _q_modelAboutToBeReset()) Q_PRIVATE_SLOT(d_func(), void _q_sortIndicatorChanged(int column, Qt::SortOrder order)) - Q_PRIVATE_SLOT(d_func(), void _q_modelDestroyed()) }; #endif // QT_NO_TREEVIEW diff --git a/src/gui/itemviews/qtreeview_p.h b/src/gui/itemviews/qtreeview_p.h index 77e57d6..38f6fd3 100644 --- a/src/gui/itemviews/qtreeview_p.h +++ b/src/gui/itemviews/qtreeview_p.h @@ -119,8 +119,6 @@ public: void expand(int item, bool emitSignal); void collapse(int item, bool emitSignal); - - void _q_currentChanged(const QModelIndex&, const QModelIndex&); void _q_columnsAboutToBeRemoved(const QModelIndex &, int, int); void _q_columnsRemoved(const QModelIndex &, int, int); void _q_modelAboutToBeReset(); -- cgit v0.12 From 8b5f25ef98d29859e14d992ed90d976e64dc6382 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Thu, 9 Jul 2009 15:23:58 +0200 Subject: autotest: removed tons of warnings --- tests/auto/qmenubar/tst_qmenubar.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/auto/qmenubar/tst_qmenubar.cpp b/tests/auto/qmenubar/tst_qmenubar.cpp index 500465c..1245de1 100644 --- a/tests/auto/qmenubar/tst_qmenubar.cpp +++ b/tests/auto/qmenubar/tst_qmenubar.cpp @@ -1576,8 +1576,9 @@ void tst_QMenuBar::menubarSizeHint() return 11; case PM_MenuBarPanelWidth: return 1; + default: + return QWindowsStyle::pixelMetric(metric, option, widget); } - return QWindowsStyle::pixelMetric(metric, option, widget); } } style; -- cgit v0.12 From 43760604b1e08792938449885a938a641669c11d Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Thu, 9 Jul 2009 14:20:54 +0200 Subject: Added some links to the appropriate functions to the doc. Reviewed-by: trustme --- doc/src/dnd.qdoc | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/doc/src/dnd.qdoc b/doc/src/dnd.qdoc index b5039f6..5ede20c 100644 --- a/doc/src/dnd.qdoc +++ b/doc/src/dnd.qdoc @@ -141,15 +141,17 @@ types of data that the widget accepts. You must reimplement this function if you want to receive either QDragMoveEvent or QDropEvent in your reimplementations of - \l{QWidget::dragMoveEvent()}{dragMoveEvent()} and dropEvent(). + \l{QWidget::dragMoveEvent()}{dragMoveEvent()} and + \l{QWidget::dropEvent()}{dropEvent()}. - The following code shows how dragEnterEvent() can be reimplemented to + The following code shows how \l{QWidget::dragEnterEvent()}{dragEnterEvent()} + can be reimplemented to tell the drag and drop system that we can only handle plain text: \snippet doc/src/snippets/dropevents/window.cpp 3 - The dropEvent() is used to unpack dropped data and handle it in way that - is suitable for your application. + The \l{QWidget::dropEvent()}{dropEvent()} is used to unpack dropped data + and handle it in way that is suitable for your application. In the following code, the text supplied in the event is passed to a QTextBrowser and a QComboBox is filled with the list of MIME types that @@ -159,7 +161,8 @@ In this case, we accept the proposed action without checking what it is. In a real world application, it may be necessary to return from the - dropEvent() function without accepting the proposed action or handling + \l{QWidget::dropEvent()}{dropEvent()} function without accepting the + proposed action or handling the data if the action is not relevant. For example, we may choose to ignore Qt::LinkAction actions if we do not support links to external sources in our application. -- cgit v0.12 From b89e878003c5732482a8afb1be66a42cb9122b9e Mon Sep 17 00:00:00 2001 From: Pierre Rossi Date: Thu, 9 Jul 2009 16:12:49 +0200 Subject: Updated the french phrasebook (some translations from Qt Creator) Reviewed-by: TrustMe --- tools/linguist/phrasebooks/french.qph | 227 +++++++++++++++++++++++++++++++++- 1 file changed, 226 insertions(+), 1 deletion(-) diff --git a/tools/linguist/phrasebooks/french.qph b/tools/linguist/phrasebooks/french.qph index f244013..d38da5a 100644 --- a/tools/linguist/phrasebooks/french.qph +++ b/tools/linguist/phrasebooks/french.qph @@ -1,4 +1,5 @@ - + + About A propos @@ -1101,4 +1102,228 @@ Yes Oui + + Split + Scinder + + + &Edit + &Édition + + + &Redo + Re&faire + + + debugger + débogueur + + + Start Debugger + Lancer le débogueur + + + Executable: + Exécutable: + + + Filter: + Filtre: + + + Clear + Effacer + + + Host and port: + Hôte et port: + + + Architecture: + Architecture: + + + Server start script: + Script de démarrage du serveur: + + + &Undo + Annu&ler + + + Add Bookmark + Ajouter un signet + + + Bookmark: + Signet: + + + Add in Folder: + Ajouter dans le dossier: + + + + + + + + + New Folder + Nouveau dossier + + + Bookmarks + Signets + + + Rename Folder + Renommer le dossier + + + Bookmark + Signet + + + Remove + Retirer + + + Delete Folder + Supprimer le dossier + + + Add + Ajouter + + + Move Up + Vers le Haut + + + Move Down + Vers le Bas + + + Show Bookmark + Afficher le signet + + + Show Bookmark in New Tab + Afficher le signet dans un nouvel onglet + + + Delete Bookmark + Supprimer le signet + + + Rename Bookmark + Renommer le signet + + + Previous Bookmark + Signet précédent + + + Next Bookmark + Signet suivant + + + Condition: + Condition: + + + Working Directory: + Répertoire de travail: + + + Environment + Environnement + + + Arguments + Arguments + + + Build directory: + Répertoire de compilation: + + + Path: + Chemin: + + + General + Général + + + Username: + Nom d'utilisateur: + + + User interface + Interface utilisateur + + + Open Link + Ouvrir le lien + + + [read only] + [lecture seule] + + + [directory] + [répertoire] + + + Close All + Fermer tout + + + Failed! + Échec! + + + Proceed + Continuer + + + Make writable + Rendre inscriptible + + + Qt Creator + Qt Creator + + + &File + &Fichier + + + Activate %1 + Activer %1 + + + New Project + Nouveau projet + + + Close %1 + Fermer %1 + + + * + * + + + &Change + &Modifier + + + Close Other Editors + Fermer les autres éditeurs + + + Close All Except %1 + Fermer tout sauf %1 + -- cgit v0.12 From e96c108e7f71f3e1bd08dc739e6ec46fe4603332 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Thu, 9 Jul 2009 15:58:20 +0200 Subject: QTabBar: now uses QVariantAnimation over QTimeLine QTimeLine is now no more used in private APIs --- src/gui/widgets/qprogressbar.cpp | 2 +- src/gui/widgets/qtabbar.cpp | 66 ++++++++++++++------------------------ src/gui/widgets/qtabbar.h | 2 -- src/gui/widgets/qtabbar_p.h | 68 ++++++++++++++++++++++++---------------- 4 files changed, 65 insertions(+), 73 deletions(-) diff --git a/src/gui/widgets/qprogressbar.cpp b/src/gui/widgets/qprogressbar.cpp index ac3338b..d168028 100644 --- a/src/gui/widgets/qprogressbar.cpp +++ b/src/gui/widgets/qprogressbar.cpp @@ -204,7 +204,7 @@ bool QProgressBarPrivate::repaintRequired() const \o A progress bar shown in the Plastique widget style. \endtable - \sa QTimeLine, QProgressDialog, {fowler}{GUI Design Handbook: Progress Indicator} + \sa QProgressDialog, {fowler}{GUI Design Handbook: Progress Indicator} */ /*! diff --git a/src/gui/widgets/qtabbar.cpp b/src/gui/widgets/qtabbar.cpp index 11cb6a1..690e624 100644 --- a/src/gui/widgets/qtabbar.cpp +++ b/src/gui/widgets/qtabbar.cpp @@ -663,7 +663,7 @@ void QTabBarPrivate::refresh() if (pressedIndex != -1 && movable && QApplication::mouseButtons() == Qt::NoButton) { - _q_moveTabFinished(pressedIndex); + moveTabFinished(pressedIndex); if (!validIndex(pressedIndex)) pressedIndex = -1; } @@ -1662,26 +1662,17 @@ void QTabBarPrivate::slide(int from, int to) q->setUpdatesEnabled(true); int postLocation = vertical ? q->tabRect(to).y() : q->tabRect(to).x(); int length = postLocation - preLocation; - tabList[to].makeTimeLine(q); - tabList[to].dragOffset += -1 * length; - tabList[to].timeLine->setFrameRange(tabList[to].dragOffset, 0); - animations[tabList[to].timeLine] = to; - tabList[to].timeLine->setDuration(ANIMATION_DURATION); - if (tabList[to].timeLine->state() != QTimeLine::Running) - tabList[to].timeLine->start(); + tabList[to].dragOffset -= length; + tabList[to].startAnimation(this, ANIMATION_DURATION); } -void QTabBarPrivate::_q_moveTab(int offset) +void QTabBarPrivate::moveTab(int index, int offset) { - Q_Q(QTabBar); - if (QTimeLine *timeLine = qobject_cast(q->sender())) { - int index = animations[timeLine]; - if (!validIndex(index)) - return; - tabList[index].dragOffset = offset; - layoutTab(index); // Make buttons follow tab - q->update(); - } + if (!validIndex(index)) + return; + tabList[index].dragOffset = offset; + layoutTab(index); // Make buttons follow tab + q_func()->update(); } /*!\reimp @@ -1695,7 +1686,7 @@ void QTabBar::mousePressEvent(QMouseEvent *event) } // Be safe! if (d->pressedIndex != -1 && d->movable) - d->_q_moveTabFinished(d->pressedIndex); + d->moveTabFinished(d->pressedIndex); d->pressedIndex = d->indexAtPos(event->pos()); if (d->validIndex(d->pressedIndex)) { @@ -1721,7 +1712,7 @@ void QTabBar::mouseMoveEvent(QMouseEvent *event) // Be safe! if (d->pressedIndex != -1 && event->buttons() == Qt::NoButton) - d->_q_moveTabFinished(d->pressedIndex); + d->moveTabFinished(d->pressedIndex); // Start drag if (!d->dragInProgress && d->pressedIndex != -1) { @@ -1789,16 +1780,6 @@ void QTabBar::mouseMoveEvent(QMouseEvent *event) optTabBase.documentMode = d->documentMode; } -void QTabBarPrivate::_q_moveTabFinished() -{ - Q_Q(QTabBar); - if (QTimeLine *timeLine = qobject_cast(q->sender())) { - int index = animations[timeLine]; - animations.remove(timeLine); - _q_moveTabFinished(index); - } -} - void QTabBarPrivate::setupMovableTab() { Q_Q(QTabBar); @@ -1838,11 +1819,19 @@ void QTabBarPrivate::setupMovableTab() movingTab->setVisible(true); } -void QTabBarPrivate::_q_moveTabFinished(int index) +void QTabBarPrivate::moveTabFinished(int index) { Q_Q(QTabBar); bool cleanup = (pressedIndex == index) || (pressedIndex == -1) || !validIndex(index); - if (animations.isEmpty() && cleanup) { + bool allAnimationsFinished = true; +#ifndef QT_NO_ANIMATION + for(int i = 0; allAnimationsFinished && i < tabList.count(); ++i) { + const Tab &t = tabList.at(i); + if (t.animation && t.animation->state() == QAbstractAnimation::Running) + allAnimationsFinished = false; + } +#endif //QT_NO_ANIMATION + if (allAnimationsFinished && cleanup) { movingTab->setVisible(false); // We might not get a mouse release for (int i = 0; i < tabList.count(); ++i) { tabList[i].dragOffset = 0; @@ -1877,17 +1866,8 @@ void QTabBar::mouseReleaseEvent(QMouseEvent *event) ? tabRect(d->pressedIndex).height() : tabRect(d->pressedIndex).width(); int duration = qMin(ANIMATION_DURATION, - ((length < 0 ? (-1 * length) : length) * ANIMATION_DURATION) / width); - if (duration > 0) { - d->tabList[d->pressedIndex].makeTimeLine(this); - d->tabList[d->pressedIndex].timeLine->setFrameRange(length, 0); - d->animations[d->tabList[d->pressedIndex].timeLine] = d->pressedIndex; - d->tabList[d->pressedIndex].timeLine->setDuration(duration); - if (d->tabList[d->pressedIndex].timeLine->state() != QTimeLine::Running) - d->tabList[d->pressedIndex].timeLine->start(); - } else { - d->_q_moveTabFinished(d->pressedIndex); - } + (qAbs(length) * ANIMATION_DURATION) / width); + d->tabList[d->pressedIndex].startAnimation(d, duration); d->dragInProgress = false; d->movingTab->setVisible(false); d->dragStartPosition = QPoint(); diff --git a/src/gui/widgets/qtabbar.h b/src/gui/widgets/qtabbar.h index 7514486..402f54b 100644 --- a/src/gui/widgets/qtabbar.h +++ b/src/gui/widgets/qtabbar.h @@ -215,8 +215,6 @@ private: Q_DECLARE_PRIVATE(QTabBar) Q_PRIVATE_SLOT(d_func(), void _q_scrollTabs()) Q_PRIVATE_SLOT(d_func(), void _q_closeTab()) - Q_PRIVATE_SLOT(d_func(), void _q_moveTab(int)) - Q_PRIVATE_SLOT(d_func(), void _q_moveTabFinished()) }; #endif // QT_NO_TABBAR diff --git a/src/gui/widgets/qtabbar_p.h b/src/gui/widgets/qtabbar_p.h index dbae055..b9b9fba 100644 --- a/src/gui/widgets/qtabbar_p.h +++ b/src/gui/widgets/qtabbar_p.h @@ -58,9 +58,8 @@ #include #include -#include -#include #include +#include #ifndef QT_NO_TABBAR @@ -75,9 +74,10 @@ class QTabBarPrivate : public QWidgetPrivate Q_DECLARE_PUBLIC(QTabBar) public: QTabBarPrivate() - :currentIndex(-1), pressedIndex(-1), - shape(QTabBar::RoundedNorth), - layoutDirty(false), drawBase(true), scrollOffset(0), expanding(true), closeButtonOnTabs(false), selectionBehaviorOnRemove(QTabBar::SelectRightTab), paintWithOffsets(true), movable(false), dragInProgress(false), documentMode(false), movingTab(0) {} + :currentIndex(-1), pressedIndex(-1), shape(QTabBar::RoundedNorth), layoutDirty(false), + drawBase(true), scrollOffset(0), expanding(true), closeButtonOnTabs(false), + selectionBehaviorOnRemove(QTabBar::SelectRightTab), paintWithOffsets(true), movable(false), + dragInProgress(false), documentMode(false), movingTab(0) {} int currentIndex; int pressedIndex; @@ -88,16 +88,13 @@ public: struct Tab { inline Tab(const QIcon &ico, const QString &txt) - : enabled(true) - , shortcutId(0) - , text(txt) - , icon(ico) - , leftWidget(0) - , rightWidget(0) - , lastTab(-1) - , timeLine(0) - , dragOffset(0) + : enabled(true) , shortcutId(0), text(txt), icon(ico), + leftWidget(0), rightWidget(0), lastTab(-1), dragOffset(0) +#ifndef QT_NO_ANIMATION + , animation(0) +#endif //QT_NO_ANIMATION {} + bool operator==(const Tab &other) const { return &other == this; } bool enabled; int shortcutId; QString text; @@ -117,21 +114,39 @@ public: QWidget *leftWidget; QWidget *rightWidget; int lastTab; - - QTimeLine *timeLine; int dragOffset; - void makeTimeLine(QWidget *q) { - if (timeLine) - return; - timeLine = new QTimeLine(ANIMATION_DURATION, q); - q->connect(timeLine, SIGNAL(frameChanged(int)), q, SLOT(_q_moveTab(int))); - q->connect(timeLine, SIGNAL(finished()), q, SLOT(_q_moveTabFinished())); +#ifndef QT_NO_ANIMATION + ~Tab() { delete animation; } + struct TabBarAnimation : public QVariantAnimation { + TabBarAnimation(Tab *t, QTabBarPrivate *_priv) : tab(t), priv(_priv) + { setEasingCurve(QEasingCurve::InOutQuad); } + + void updateCurrentValue(const QVariant ¤t) + { priv->moveTab(priv->tabList.indexOf(*tab), current.toInt()); } + + void updateState(State, State newState) + { if (newState == Stopped) priv->moveTabFinished(priv->tabList.indexOf(*tab)); } + private: + //these are needed for the callbacks + Tab *tab; + QTabBarPrivate *priv; + } *animation; + + void startAnimation(QTabBarPrivate *priv, int duration) { + if (!animation) + animation = new TabBarAnimation(this, priv); + animation->setStartValue(dragOffset); + animation->setEndValue(0); + animation->setDuration(duration); + animation->start(); } - +#else + void startAnimation(QTabBarPrivate *priv, int duration) + { Q_UNUSED(duration); priv->moveTabFinished(priv->tabList.indexOf(*this)); } +#endif //QT_NO_ANIMATION }; QList tabList; - QHash animations; int calculateNewPosition(int from, int to, int index) const; void slide(int from, int to); @@ -152,9 +167,8 @@ public: void _q_scrollTabs(); void _q_closeTab(); - void _q_moveTab(int); - void _q_moveTabFinished(); - void _q_moveTabFinished(int offset); + void moveTab(int index, int offset); + void moveTabFinished(int index); QRect hoverRect; void refresh(); -- cgit v0.12 From 93c5eddcead6d0fa9601d3ec992086ddcc5656e9 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Thu, 9 Jul 2009 16:23:26 +0200 Subject: Fix compile issue --- src/gui/itemviews/qtreeview.cpp | 13 ++++++++++++- src/gui/itemviews/qtreeview.h | 3 +++ src/gui/itemviews/qtreeview_p.h | 17 +++++------------ 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp index e4c7cd3..f13ff0c 100644 --- a/src/gui/itemviews/qtreeview.cpp +++ b/src/gui/itemviews/qtreeview.cpp @@ -2837,6 +2837,9 @@ void QTreeViewPrivate::initialize() header->setStretchLastSection(true); header->setDefaultAlignment(Qt::AlignLeft|Qt::AlignVCenter); q->setHeader(header); +#ifndef QT_NO_ANIMATION + QObject::connect(&animatedOperation, SIGNAL(finished()), q, SLOT(_q_endAnimatedOperation())); +#endif //QT_NO_ANIMATION } void QTreeViewPrivate::expand(int item, bool emitSignal) @@ -2920,7 +2923,7 @@ void QTreeViewPrivate::collapse(int item, bool emitSignal) void QTreeViewPrivate::prepareAnimatedOperation(int item, QVariantAnimation::Direction direction) { animatedOperation.item = item; - animatedOperation.view = q_func(); + animatedOperation.viewport = viewport; animatedOperation.setDirection(direction); int top = coordinateForItem(item) + itemHeight(item); @@ -3008,6 +3011,14 @@ QPixmap QTreeViewPrivate::renderTreeToPixmapForAnimation(const QRect &rect) cons return pixmap; } + +void QTreeViewPrivate::_q_endAnimatedOperation() +{ + Q_Q(QTreeView); + q->setState(QAbstractItemView::NoState); + q->updateGeometries(); + viewport->update(); +} #endif //QT_NO_ANIMATION void QTreeViewPrivate::_q_modelAboutToBeReset() diff --git a/src/gui/itemviews/qtreeview.h b/src/gui/itemviews/qtreeview.h index b2a9de2f..4411781 100644 --- a/src/gui/itemviews/qtreeview.h +++ b/src/gui/itemviews/qtreeview.h @@ -223,6 +223,9 @@ private: Q_DECLARE_PRIVATE(QTreeView) Q_DISABLE_COPY(QTreeView) +#ifndef QT_NO_ANIMATION + Q_PRIVATE_SLOT(d_func(), void _q_endAnimatedOperation()) +#endif //QT_NO_ANIMATION Q_PRIVATE_SLOT(d_func(), void _q_modelAboutToBeReset()) Q_PRIVATE_SLOT(d_func(), void _q_sortIndicatorChanged(int column, Qt::SortOrder order)) }; diff --git a/src/gui/itemviews/qtreeview_p.h b/src/gui/itemviews/qtreeview_p.h index 38f6fd3..6fb2e41 100644 --- a/src/gui/itemviews/qtreeview_p.h +++ b/src/gui/itemviews/qtreeview_p.h @@ -95,25 +95,18 @@ public: int item; QPixmap before; QPixmap after; - QTreeView *view; + QWidget *viewport; AnimatedOperation() : item(0) { setEasingCurve(QEasingCurve::InOutQuad); } int top() const { return startValue().toInt(); } - QRect rect() const { QRect rect = view->viewport()->rect(); rect.moveTop(top()); return rect; } - void updateCurrentValue(const QVariant &) { view->viewport()->update(rect()); } - void updateState(State, State state) - { - if (state == Stopped) { - before = after = QPixmap(); - view->setState(QAbstractItemView::NoState); - view->updateGeometries(); - view->viewport()->update(); - } - } + QRect rect() const { QRect rect = viewport->rect(); rect.moveTop(top()); return rect; } + void updateCurrentValue(const QVariant &) { viewport->update(rect()); } + void updateState(State, State state) { if (state == Stopped) before = after = QPixmap(); } } animatedOperation; void prepareAnimatedOperation(int item, QVariantAnimation::Direction d); void beginAnimatedOperation(); void drawAnimatedOperation(QPainter *painter) const; QPixmap renderTreeToPixmapForAnimation(const QRect &rect) const; + void _q_endAnimatedOperation(); #endif //QT_NO_ANIMATION void expand(int item, bool emitSignal); -- cgit v0.12 From f4fb6207a91b62526b31e0f77c0713bdc243e4f2 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Thu, 9 Jul 2009 16:51:59 +0200 Subject: Compile fix. --- src/gui/itemviews/qabstractitemview_p.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/itemviews/qabstractitemview_p.h b/src/gui/itemviews/qabstractitemview_p.h index 3119c9d..00647f6 100644 --- a/src/gui/itemviews/qabstractitemview_p.h +++ b/src/gui/itemviews/qabstractitemview_p.h @@ -64,6 +64,7 @@ #include "QtGui/qregion.h" #include "QtCore/qdebug.h" #include "QtGui/qpainter.h" +#include "QtCore/qbasictimer.h" #ifndef QT_NO_ITEMVIEWS -- cgit v0.12 From 4bec76fceb2297cdbde765b74075046b94bfaf75 Mon Sep 17 00:00:00 2001 From: Nils Christian Roscher-Nielsen Date: Thu, 9 Jul 2009 17:29:46 +0200 Subject: Add the complex control SC_SpinBoxEditField to style option Reviewed-by: Thierry --- src/gui/widgets/qabstractspinbox.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/widgets/qabstractspinbox.cpp b/src/gui/widgets/qabstractspinbox.cpp index da18d13..433406c 100644 --- a/src/gui/widgets/qabstractspinbox.cpp +++ b/src/gui/widgets/qabstractspinbox.cpp @@ -1577,7 +1577,7 @@ void QAbstractSpinBox::initStyleOption(QStyleOptionSpinBox *option) const option->initFrom(this); option->activeSubControls = QStyle::SC_None; option->buttonSymbols = d->buttonSymbols; - option->subControls = QStyle::SC_SpinBoxFrame; + option->subControls = QStyle::SC_SpinBoxFrame | QStyle::SC_SpinBoxEditField; if (d->buttonSymbols != QAbstractSpinBox::NoButtons) { option->subControls |= QStyle::SC_SpinBoxUp | QStyle::SC_SpinBoxDown; if (d->buttonState & Up) { -- cgit v0.12 From 020ed5b7caaba5cf877cdb9ebaa575db1d15b7f0 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Thu, 9 Jul 2009 18:09:12 +0200 Subject: QLocalSocket WriteOnly mode fixed on Windows Write only local sockets silently disconnected after some time. Reason: we cannot call PeekNamedPipe on a write only pipe. Task-number: 257714 Reviewed-by: ossi Autotest: tst_QLocalSocket::writeOnlySocket --- src/network/socket/qlocalsocket_win.cpp | 10 ++++++---- tests/auto/qlocalsocket/tst_qlocalsocket.cpp | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp index 1a971f0..794b2b7 100644 --- a/src/network/socket/qlocalsocket_win.cpp +++ b/src/network/socket/qlocalsocket_win.cpp @@ -168,7 +168,7 @@ void QLocalSocket::connectToServer(const QString &name, OpenMode openMode) // we have a valid handle d->serverName = name; - if (setSocketDescriptor((quintptr)localSocket), openMode) { + if (setSocketDescriptor((quintptr)localSocket, ConnectedState, openMode)) { d->handle = localSocket; emit connected(); } @@ -299,8 +299,6 @@ void QLocalSocket::abort() DWORD QLocalSocketPrivate::bytesAvailable() { Q_Q(QLocalSocket); - if (q->state() != QLocalSocket::ConnectedState) - return 0; DWORD bytes; if (PeekNamedPipe(handle, NULL, 0, NULL, &bytes, NULL)) { return bytes; @@ -410,7 +408,7 @@ bool QLocalSocket::setSocketDescriptor(quintptr socketDescriptor, d->handle = (int*)socketDescriptor; d->state = socketState; emit stateChanged(d->state); - if (d->state == ConnectedState) { + if (d->state == ConnectedState && openMode.testFlag(QIODevice::ReadOnly)) { d->startAsyncRead(); d->checkReadyRead(); } @@ -471,6 +469,10 @@ bool QLocalSocket::waitForDisconnected(int msecs) Q_D(QLocalSocket); if (state() == UnconnectedState) return false; + if (!openMode().testFlag(QIODevice::ReadOnly)) { + qWarning("QLocalSocket::waitForDisconnected isn't supported for write only pipes."); + return false; + } QIncrementalSleepTimer timer(msecs); forever { d->bytesAvailable(); // to check if PeekNamedPipe fails diff --git a/tests/auto/qlocalsocket/tst_qlocalsocket.cpp b/tests/auto/qlocalsocket/tst_qlocalsocket.cpp index 0f636a4..a41eecd 100644 --- a/tests/auto/qlocalsocket/tst_qlocalsocket.cpp +++ b/tests/auto/qlocalsocket/tst_qlocalsocket.cpp @@ -104,6 +104,7 @@ private slots: void recycleServer(); void multiConnect(); + void writeOnlySocket(); void debug(); @@ -906,6 +907,22 @@ void tst_QLocalSocket::multiConnect() QVERIFY(server.nextPendingConnection() != 0); } +void tst_QLocalSocket::writeOnlySocket() +{ + QLocalServer server; + QVERIFY(server.listen("writeOnlySocket")); + + QLocalSocket client; + client.connectToServer("writeOnlySocket", QIODevice::WriteOnly); + QVERIFY(client.waitForConnected()); + + QVERIFY(server.waitForNewConnection()); + QLocalSocket* serverSocket = server.nextPendingConnection(); + + QCOMPARE(client.bytesAvailable(), qint64(0)); + QCOMPARE(client.state(), QLocalSocket::ConnectedState); +} + void tst_QLocalSocket::debug() { // Make sure this compiles -- cgit v0.12 From 5c11a5a38bcc68c17da8fe59e8db03d43ea55ac1 Mon Sep 17 00:00:00 2001 From: Norwegian Rock Cat Date: Wed, 8 Jul 2009 17:21:51 +0200 Subject: Ensure that when we hide QToolBar in unified, unified follows. Basically if you would hide a toolbar in the unified toolbar, you would still see a little bit of area at the top instead of having everything flush with the titlebar. This change basically unsures that the unified toolbar makes a decision to hide itself if all the toolbars inside it are hidden. It makes the behavior of clicking on the toolbar button behave more or less correctly since we are going to show the unified toolbar whether we want to or not. This all will get the toolbar button switch event to be dispatched in Cocoa as well. Also add an optimization for checking if we need to change the geometry. If we don't have any items the other toolbar areas, we can skip the set geometry call, which wrecks havoc with things in Cocoa. We still don't solve the case of someone who has hidden the items with the toolbar button then goes full-screen, then goes back out. I'm not motivated to solve it as is because we need to keep track of the hides we do on the button press vs. other hides from the user and still people can workaround it easy enough by handling window state change and doing what is recommended in the docs. Task-number: 208439 Rev-by: Denis --- src/gui/kernel/qcocoapanel_mac.mm | 6 +++ src/gui/kernel/qcocoawindow_mac.mm | 6 +++ src/gui/kernel/qt_cocoa_helpers_mac.mm | 34 +++++++------- src/gui/kernel/qt_cocoa_helpers_mac_p.h | 3 +- src/gui/kernel/qwidget_mac.mm | 3 +- src/gui/widgets/qmainwindow.cpp | 13 ++++-- src/gui/widgets/qmainwindowlayout.cpp | 76 ++++++++++++++++++++++++++++---- src/gui/widgets/qmainwindowlayout_mac.mm | 31 ++++++++++--- src/gui/widgets/qmainwindowlayout_p.h | 2 + src/gui/widgets/qtoolbar.cpp | 29 +++++++++--- 10 files changed, 161 insertions(+), 42 deletions(-) diff --git a/src/gui/kernel/qcocoapanel_mac.mm b/src/gui/kernel/qcocoapanel_mac.mm index bdc7ecb..1e0bbdf 100644 --- a/src/gui/kernel/qcocoapanel_mac.mm +++ b/src/gui/kernel/qcocoapanel_mac.mm @@ -85,6 +85,12 @@ QT_USE_NAMESPACE last resort (i.e., this is code that can potentially be removed). */ +- (void)toggleToolbarShown:(id)sender +{ + macSendToolbarChangeEvent([self QT_MANGLE_NAMESPACE(qt_qwidget)]); + [super toggleToolbarShown:sender]; +} + - (void)keyDown:(NSEvent *)theEvent { bool keyOK = qt_dispatchKeyEvent(theEvent, [self QT_MANGLE_NAMESPACE(qt_qwidget)]); diff --git a/src/gui/kernel/qcocoawindow_mac.mm b/src/gui/kernel/qcocoawindow_mac.mm index 7084416..eb08982 100644 --- a/src/gui/kernel/qcocoawindow_mac.mm +++ b/src/gui/kernel/qcocoawindow_mac.mm @@ -104,6 +104,12 @@ QT_USE_NAMESPACE last resort (i.e., this is code that can potentially be removed). */ +- (void)toggleToolbarShown:(id)sender +{ + macSendToolbarChangeEvent([self QT_MANGLE_NAMESPACE(qt_qwidget)]); + [super toggleToolbarShown:sender]; +} + - (void)keyDown:(NSEvent *)theEvent { bool keyOK = qt_dispatchKeyEvent(theEvent, [self QT_MANGLE_NAMESPACE(qt_qwidget)]); diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index 13b0e50..a98a7f8 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -177,11 +177,10 @@ void macWindowToolbarShow(const QWidget *widget, bool show ) { OSWindowRef wnd = qt_mac_window_for(widget); #if QT_MAC_USE_COCOA - NSToolbar *toolbar = [wnd toolbar]; - if (toolbar) { + if (NSToolbar *toolbar = [wnd toolbar]) { QMacCocoaAutoReleasePool pool; if (show != [toolbar isVisible]) { - [wnd toggleToolbarShown:wnd]; + [toolbar setVisible:show]; } else { // The toolbar may be in sync, but we are not, update our framestrut. qt_widget_private(const_cast(widget))->updateFrameStrut(); @@ -197,22 +196,21 @@ void macWindowToolbarSet( void * /*OSWindowRef*/ window, void *toolbarRef ) { OSWindowRef wnd = static_cast(window); #if QT_MAC_USE_COCOA - [wnd setToolbar:static_cast(toolbarRef)]; + [wnd setToolbar:static_cast(toolbarRef)]; #else SetWindowToolbar(wnd, static_cast(toolbarRef)); #endif } -bool macWindowToolbarVisible( void * /*OSWindowRef*/ window ) +bool macWindowToolbarIsVisible( void * /*OSWindowRef*/ window ) { OSWindowRef wnd = static_cast(window); #if QT_MAC_USE_COCOA - NSToolbar *toolbar = [wnd toolbar]; - if (toolbar) + if (NSToolbar *toolbar = [wnd toolbar]) return [toolbar isVisible]; return false; #else - return IsWindowToolbarVisible(wnd); + return IsWindowToolbarVisible(wnd); #endif } @@ -220,12 +218,12 @@ void macWindowSetHasShadow( void * /*OSWindowRef*/ window, bool hasShadow ) { OSWindowRef wnd = static_cast(window); #if QT_MAC_USE_COCOA - [wnd setHasShadow:BOOL(hasShadow)]; + [wnd setHasShadow:BOOL(hasShadow)]; #else - if (hasShadow) - ChangeWindowAttributes(wnd, 0, kWindowNoShadowAttribute); - else - ChangeWindowAttributes(wnd, kWindowNoShadowAttribute, 0); + if (hasShadow) + ChangeWindowAttributes(wnd, 0, kWindowNoShadowAttribute); + else + ChangeWindowAttributes(wnd, kWindowNoShadowAttribute, 0); #endif } @@ -233,9 +231,9 @@ void macWindowFlush(void * /*OSWindowRef*/ window) { OSWindowRef wnd = static_cast(window); #if QT_MAC_USE_COCOA - [wnd flushWindowIfNeeded]; + [wnd flushWindowIfNeeded]; #else - HIWindowFlush(wnd); + HIWindowFlush(wnd); #endif } @@ -352,6 +350,12 @@ Qt::MouseButton qt_mac_get_button(EventMouseButton button) return Qt::NoButton; } +void macSendToolbarChangeEvent(QWidget *widget) +{ + QToolBarChangeEvent ev(!(GetCurrentKeyModifiers() & cmdKey)); + qt_sendSpontaneousEvent(widget, &ev); +} + Q_GLOBAL_STATIC(QMacTabletHash, tablet_hash) QMacTabletHash *qt_mac_tablet_hash() { diff --git a/src/gui/kernel/qt_cocoa_helpers_mac_p.h b/src/gui/kernel/qt_cocoa_helpers_mac_p.h index 3881ccd..5f6204f 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac_p.h +++ b/src/gui/kernel/qt_cocoa_helpers_mac_p.h @@ -118,9 +118,10 @@ void macWindowFade(void * /*OSWindowRef*/ window, float durationSeconds = 0); bool macWindowIsTextured(void * /*OSWindowRef*/ window); void macWindowToolbarShow(const QWidget *widget, bool show ); void macWindowToolbarSet( void * /*OSWindowRef*/ window, void* toolbarRef ); -bool macWindowToolbarVisible( void * /*OSWindowRef*/ window ); +bool macWindowToolbarIsVisible( void * /*OSWindowRef*/ window ); void macWindowSetHasShadow( void * /*OSWindowRef*/ window, bool hasShadow ); void macWindowFlush(void * /*OSWindowRef*/ window); +void macSendToolbarChangeEvent(QWidget *widget); struct HIContentBorderMetrics; void qt_mac_updateContentBorderMetricts(void * /*OSWindowRef */window, const ::HIContentBorderMetrics &metrics); void * /*NSImage */qt_mac_create_nsimage(const QPixmap &pm); diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index dcc5056..5e2dfb6 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -843,8 +843,7 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event, extern QPointer qt_button_down; //qapplication_mac.cpp qt_button_down = 0; } else if(ekind == kEventWindowToolbarSwitchMode) { - QToolBarChangeEvent ev(!(GetCurrentKeyModifiers() & cmdKey)); - QApplication::sendSpontaneousEvent(widget, &ev); + macSendToolbarChangeEvent(widget); HIToolbarRef toolbar; if (GetWindowToolbar(wid, &toolbar) == noErr) { if (toolbar) { diff --git a/src/gui/widgets/qmainwindow.cpp b/src/gui/widgets/qmainwindow.cpp index 0c841eb..c51bed9 100644 --- a/src/gui/widgets/qmainwindow.cpp +++ b/src/gui/widgets/qmainwindow.cpp @@ -1369,20 +1369,25 @@ bool QMainWindow::event(QEvent *event) #ifdef Q_WS_MAC case QEvent::Show: if (unifiedTitleAndToolBarOnMac()) - macWindowToolbarShow(this, true); + d->layout->syncUnifiedToolbarVisibility(); + d->layout->blockVisiblityCheck = false; break; -# ifdef QT_MAC_USE_COCOA case QEvent::WindowStateChange: { + if (isHidden()) { + // We are coming out of a minimize, leave things as is. + d->layout->blockVisiblityCheck = true; + } +# ifdef QT_MAC_USE_COCOA // We need to update the HIToolbar status when we go out of or into fullscreen. QWindowStateChangeEvent *wce = static_cast(event); if ((windowState() & Qt::WindowFullScreen) || (wce->oldState() & Qt::WindowFullScreen)) { d->layout->updateHIToolBarStatus(); } +# endif // Cocoa } break; -# endif // Cocoa -#endif +#endif // Q_WS_MAC #if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_CURSOR) case QEvent::CursorChange: if (d->cursorAdjusted) { diff --git a/src/gui/widgets/qmainwindowlayout.cpp b/src/gui/widgets/qmainwindowlayout.cpp index aba9120..541907e 100644 --- a/src/gui/widgets/qmainwindowlayout.cpp +++ b/src/gui/widgets/qmainwindowlayout.cpp @@ -939,15 +939,70 @@ void QMainWindowLayout::getStyleOptionInfo(QStyleOptionToolBar *option, QToolBar void QMainWindowLayout::toggleToolBarsVisible() { - layoutState.toolBarAreaLayout.visible = !layoutState.toolBarAreaLayout.visible; - if (!layoutState.mainWindow->isMaximized()){ - QPoint topLeft = parentWidget()->geometry().topLeft(); - QRect r = parentWidget()->geometry(); - r = layoutState.toolBarAreaLayout.rectHint(r); - r.moveTo(topLeft); - parentWidget()->setGeometry(r); - } else{ - update(); + bool updateNonUnifiedParts = true; +#ifdef Q_WS_MAC + if (layoutState.mainWindow->unifiedTitleAndToolBarOnMac()) { + // If we hit this case, someone has pressed the "toolbar button" which will + // toggle the unified toolbar visiblity, because that's what the user wants. + // We might be in a situation where someone has hidden all the toolbars + // beforehand (maybe in construction), but now they've hit this button and + // and are expecting the items to show. What do we do? + // 1) Check the visibility of all the toolbars, if one is visible, do nothing, this + // preserves what people would expect (these toolbars were visible when I clicked last time). + // 2) If NONE are visible, then show them all. Again, this preserves the user expectation + // of, "I want to see the toolbars." The user may get more toolbars than expected, but this + // is better seeing nothing. + // Don't worry about any of this if we are going invisible. This does mean we may get + // into issues when switching into and out of fullscreen mode, but this is probably minor. + // If we ever need to do hiding, that would have to be taken care of after the unified toolbar + // has finished hiding. + // People can of course handle the QEvent::ToolBarChange event themselves and do + // WHATEVER they want if they don't like what we are doing (though the unified toolbar + // will fire regardless). + + // Check if we REALLY need to update the geometry below. If we only have items in the + // unified toolbar, all the docks will be empty, so there's very little point + // in doing the geometry as Apple will do it (we also avoid flicker in Cocoa as well). + // FWIW, layoutState.toolBarAreaLayout.visible and the state of the unified toolbar + // visibility can get out of sync. I really don't think it's a big issue. It is kept + // to a minimum because we only change the visibility if we absolutely must. + // update the "non unified parts." + updateNonUnifiedParts = !layoutState.toolBarAreaLayout.isEmpty(); + + // We get this function before the unified toolbar does its thing. + // So, the value will be opposite of what we expect. + bool goingVisible = !macWindowToolbarIsVisible(qt_mac_window_for(layoutState.mainWindow)); + if (goingVisible) { + const int ToolBarCount = qtoolbarsInUnifiedToolbarList.size(); + bool needAllVisible = true; + for (int i = 0; i < ToolBarCount; ++i) { + if (!qtoolbarsInUnifiedToolbarList.at(i)->isHidden()) { + needAllVisible = false; + break; + } + } + if (needAllVisible) { + QBoolBlocker blocker(blockVisiblityCheck); // Disable the visibilty check because + // the toggle has already happened. + for (int i = 0; i < ToolBarCount; ++i) + qtoolbarsInUnifiedToolbarList.at(i)->setVisible(true); + } + } + if (!updateNonUnifiedParts) + layoutState.toolBarAreaLayout.visible = goingVisible; + } +#endif + if (updateNonUnifiedParts) { + layoutState.toolBarAreaLayout.visible = !layoutState.toolBarAreaLayout.visible; + if (!layoutState.mainWindow->isMaximized()) { + QPoint topLeft = parentWidget()->geometry().topLeft(); + QRect r = parentWidget()->geometry(); + r = layoutState.toolBarAreaLayout.rectHint(r); + r.moveTo(topLeft); + parentWidget()->setGeometry(r); + } else { + update(); + } } } @@ -1641,6 +1696,9 @@ QMainWindowLayout::QMainWindowLayout(QMainWindow *mainwindow) #ifndef QT_NO_RUBBERBAND , gapIndicator(new QRubberBand(QRubberBand::Rectangle, mainwindow)) #endif //QT_NO_RUBBERBAND +#ifdef Q_WS_MAC + , blockVisiblityCheck(false) +#endif { #ifndef QT_NO_DOCKWIDGET #ifndef QT_NO_TABBAR diff --git a/src/gui/widgets/qmainwindowlayout_mac.mm b/src/gui/widgets/qmainwindowlayout_mac.mm index 6632be7..61719c2 100644 --- a/src/gui/widgets/qmainwindowlayout_mac.mm +++ b/src/gui/widgets/qmainwindowlayout_mac.mm @@ -338,18 +338,16 @@ void QMainWindowLayout::updateHIToolBarStatus() 0, kWindowUnifiedTitleAndToolbarAttribute); } #endif - macWindowToolbarShow(layoutState.mainWindow, useMacToolbar); layoutState.mainWindow->setUpdatesEnabled(false); // reduces a little bit of flicker, not all though if (!useMacToolbar) { - OSWindowRef windowRef = qt_mac_window_for(parentWidget()); - macWindowToolbarShow(parentWidget(), false); + macWindowToolbarShow(layoutState.mainWindow, false); // Move everything out of the HIToolbar into the main toolbar. while (!qtoolbarsInUnifiedToolbarList.isEmpty()) { // Should shrink the list by one every time. layoutState.mainWindow->addToolBar(Qt::TopToolBarArea, qtoolbarsInUnifiedToolbarList.first()); } - macWindowToolbarSet(windowRef, NULL); + macWindowToolbarSet(qt_mac_window_for(layoutState.mainWindow), 0); } else { QList toolbars = layoutState.mainWindow->findChildren(); for (int i = 0; i < toolbars.size(); ++i) { @@ -359,6 +357,7 @@ void QMainWindowLayout::updateHIToolBarStatus() layoutState.mainWindow->addToolBar(Qt::TopToolBarArea, toolbar); } } + syncUnifiedToolbarVisibility(); } layoutState.mainWindow->setUpdatesEnabled(true); } @@ -439,7 +438,7 @@ void QMainWindowLayout::insertIntoMacToolbar(QToolBar *before, QToolBar *toolbar #else NSString *toolbarID = kQToolBarNSToolbarIdentifier; toolbarID = [toolbarID stringByAppendingFormat:@"%p", toolbar]; - cocoaItemIDToToolbarHash.insert(QCFString::toQString(CFStringRef(toolbarID)), toolbar); + cocoaItemIDToToolbarHash.insert(qt_mac_NSStringToQString(toolbarID), toolbar); [macToolbar insertItemWithItemIdentifier:toolbarID atIndex:beforeIndex]; #endif } @@ -487,6 +486,7 @@ void QMainWindowLayout::cleanUpMacToolbarItems() void QMainWindowLayout::fixSizeInUnifiedToolbar(QToolBar *tb) const { +#ifdef QT_MAC_USE_COCOA QHash::const_iterator it = unifiedToolbarHash.constBegin(); NSToolbarItem *item = nil; while (it != unifiedToolbarHash.constEnd()) { @@ -507,5 +507,26 @@ void QMainWindowLayout::fixSizeInUnifiedToolbar(QToolBar *tb) const nssize.height = size.height() - 2; [item setMinSize:nssize]; } +#else + Q_UNUSED(tb); +#endif } + +void QMainWindowLayout::syncUnifiedToolbarVisibility() +{ + if (blockVisiblityCheck) + return; + + Q_ASSERT(layoutState.mainWindow->unifiedTitleAndToolBarOnMac()); + bool show = false; + const int ToolBarCount = qtoolbarsInUnifiedToolbarList.count(); + for (int i = 0; i < ToolBarCount; ++i) { + if (qtoolbarsInUnifiedToolbarList.at(i)->isVisible()) { + show = true; + break; + } + } + macWindowToolbarShow(layoutState.mainWindow, show); +} + QT_END_NAMESPACE diff --git a/src/gui/widgets/qmainwindowlayout_p.h b/src/gui/widgets/qmainwindowlayout_p.h index 45f62cd..524fdbf 100644 --- a/src/gui/widgets/qmainwindowlayout_p.h +++ b/src/gui/widgets/qmainwindowlayout_p.h @@ -335,6 +335,8 @@ public: void cleanUpMacToolbarItems(); void fixSizeInUnifiedToolbar(QToolBar *tb) const; bool useHIToolBar; + void syncUnifiedToolbarVisibility(); + bool blockVisiblityCheck; #endif }; QT_END_NAMESPACE diff --git a/src/gui/widgets/qtoolbar.cpp b/src/gui/widgets/qtoolbar.cpp index b249915..b65f1ba 100644 --- a/src/gui/widgets/qtoolbar.cpp +++ b/src/gui/widgets/qtoolbar.cpp @@ -1074,6 +1074,15 @@ static bool waitForPopup(QToolBar *tb, QWidget *popup) return false; } +#if defined(Q_WS_MAC) +static bool toolbarInUnifiedToolBar(QToolBar *toolbar) +{ + const QMainWindow *mainWindow = qobject_cast(toolbar->parentWidget()); + return mainWindow && mainWindow->unifiedTitleAndToolBarOnMac() + && mainWindow->toolBarArea(toolbar) == Qt::TopToolBarArea; +} +#endif + /*! \reimp */ bool QToolBar::event(QEvent *event) { @@ -1096,7 +1105,15 @@ bool QToolBar::event(QEvent *event) // fallthrough intended case QEvent::Show: d->toggleViewAction->setChecked(event->type() == QEvent::Show); -#if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA) +#if defined(Q_WS_MAC) + if (toolbarInUnifiedToolBar(this)) { + // I can static_cast because I did the qobject_cast in the if above, therefore + // we must have a QMainWindowLayout here. + QMainWindowLayout *mwLayout = static_cast(parentWidget()->layout()); + mwLayout->fixSizeInUnifiedToolbar(this); + mwLayout->syncUnifiedToolbarVisibility(); + } +# if !defined(QT_MAC_USE_COCOA) // Fall through case QEvent::LayoutRequest: { // There's currently no way to invalidate the size and let @@ -1111,10 +1128,9 @@ bool QToolBar::event(QEvent *event) } if (needUpdate) { - OSWindowRef windowRef = qt_mac_window_for(this); - if (mainWindow->unifiedTitleAndToolBarOnMac() - && mainWindow->toolBarArea(this) == Qt::TopToolBarArea - && macWindowToolbarVisible(windowRef)) { + OSWindowRef windowRef = qt_mac_window_for(mainWindow); + if (toolbarInUnifiedToolBar(this) + && macWindowToolbarIsVisible(windowRef)) { DisableScreenUpdates(); macWindowToolbarShow(this, false); macWindowToolbarShow(this, true); @@ -1126,7 +1142,8 @@ bool QToolBar::event(QEvent *event) return earlyResult; } } -#endif +# endif // !QT_MAC_USE_COCOA +#endif // Q_WS_MAC break; case QEvent::ParentChange: d->layout->checkUsePopupMenu(); -- cgit v0.12 From a21230152c4ea8cd2e641f436230e76a835384c2 Mon Sep 17 00:00:00 2001 From: Bill King Date: Fri, 10 Jul 2009 12:07:38 +1000 Subject: Fixes a heisenbug when using two ODBC connections with diff quoters. Can have situations where 2 odbc connections are active, that have differing quoting charachters. Before this fix, everything fell over. Reviewed-by: Justin McPherson --- src/sql/drivers/odbc/qsql_odbc.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/sql/drivers/odbc/qsql_odbc.cpp b/src/sql/drivers/odbc/qsql_odbc.cpp index 50defdf..fa9031a 100644 --- a/src/sql/drivers/odbc/qsql_odbc.cpp +++ b/src/sql/drivers/odbc/qsql_odbc.cpp @@ -89,7 +89,8 @@ public: enum DefaultCase{Lower, Mixed, Upper, Sensitive}; QODBCDriverPrivate() : hEnv(0), hDbc(0), useSchema(false), disconnectCount(0), isMySqlServer(false), - isMSSqlServer(false), hasSQLFetchScroll(true), hasMultiResultSets(false) + isMSSqlServer(false), hasSQLFetchScroll(true), hasMultiResultSets(false), + isQuoteInitialized(false), quote(QLatin1Char('"')) { unicode = false; } @@ -116,7 +117,10 @@ public: QString &schema, QString &table); DefaultCase defaultCase() const; QString adjustCase(const QString&) const; - QChar quoteChar() const; + QChar quoteChar(); +private: + bool isQuoteInitialized; + QChar quote; }; class QODBCPrivate @@ -566,10 +570,8 @@ static int qGetODBCVersion(const QString &connOpts) return SQL_OV_ODBC2; } -QChar QODBCDriverPrivate::quoteChar() const +QChar QODBCDriverPrivate::quoteChar() { - static bool isQuoteInitialized = false; - static QChar quote = QChar::fromLatin1('"'); if (!isQuoteInitialized) { char driverResponse[4]; SQLSMALLINT length; @@ -579,9 +581,9 @@ QChar QODBCDriverPrivate::quoteChar() const sizeof(driverResponse), &length); if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) { - quote = QChar::fromLatin1(driverResponse[0]); + quote = QLatin1Char(driverResponse[0]); } else { - quote = QChar::fromLatin1('"'); + quote = QLatin1Char('"'); } isQuoteInitialized = true; } -- cgit v0.12 From 0d156972b868c951fa33f21735040ab1e7a76f21 Mon Sep 17 00:00:00 2001 From: Bill King Date: Fri, 10 Jul 2009 12:12:45 +1000 Subject: Get more sql autotests passing or expect-failing. --- tests/auto/qsqlquery/tst_qsqlquery.cpp | 2 ++ .../tst_qsqlrelationaltablemodel.cpp | 18 ++++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/tests/auto/qsqlquery/tst_qsqlquery.cpp b/tests/auto/qsqlquery/tst_qsqlquery.cpp index 9a873cb..f3dd920 100644 --- a/tests/auto/qsqlquery/tst_qsqlquery.cpp +++ b/tests/auto/qsqlquery/tst_qsqlquery.cpp @@ -495,7 +495,9 @@ void tst_QSqlQuery::mysqlOutValues() QVERIFY_SQL( q, exec( "create procedure " + qTableName( "qtestproc" ) + " () " "BEGIN select * from " + qTableName( "qtest" ) + " order by id; END" ) ); QVERIFY_SQL( q, exec( "call " + qTableName( "qtestproc" ) + "()" ) ); + QEXPECT_FAIL("", "There's a mysql bug that means only selects think they return data when running in prepared mode", Continue); QVERIFY_SQL( q, next() ); + QEXPECT_FAIL("", "There's a mysql bug that means only selects think they return data when running in prepared mode", Continue); QCOMPARE( q.value( 1 ).toString(), QString( "VarChar1" ) ); QVERIFY_SQL( q, exec( "drop procedure " + qTableName( "qtestproc" ) ) ); diff --git a/tests/auto/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp b/tests/auto/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp index d934b35..1e23d3d 100644 --- a/tests/auto/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp +++ b/tests/auto/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp @@ -145,8 +145,17 @@ void tst_QSqlRelationalTableModel::recreateTestTables(QSqlDatabase db) void tst_QSqlRelationalTableModel::initTestCase() { - foreach (const QString &dbname, dbs.dbNames) - recreateTestTables(QSqlDatabase::database(dbname)); + foreach (const QString &dbname, dbs.dbNames) { + QSqlDatabase db=QSqlDatabase::database(dbname); + if (db.driverName().startsWith("QIBASE")) + db.exec("SET DIALECT 3"); + else if (tst_Databases::isSqlServer(db)) { + QSqlQuery q(db); + QVERIFY_SQL(q, exec("SET ANSI_DEFAULTS ON")); + QVERIFY_SQL(q, exec("SET IMPLICIT_TRANSACTIONS OFF")); + } + recreateTestTables(db); + } } void tst_QSqlRelationalTableModel::cleanupTestCase() @@ -490,6 +499,7 @@ void tst_QSqlRelationalTableModel::insertWithStrategies() model.setTable(qTableName("reltest1")); model.setRelation(2, QSqlRelation(qTableName("reltest2"), "tid", "title")); + model.setSort(0, Qt::AscendingOrder); if (!db.driverName().startsWith("QTDS")) model.setRelation(3, QSqlRelation(qTableName("reltest2"), "tid", "title")); @@ -914,8 +924,8 @@ void tst_QSqlRelationalTableModel::casing() QSqlDatabase db = QSqlDatabase::database(dbName); CHECK_DATABASE(db); - if (db.driverName().startsWith("QSQLITE")) - QSKIP("The casing test for SQLITE is irrelevant since SQLITE is case insensitive", SkipAll); + if (db.driverName().startsWith("QSQLITE") || db.driverName().startsWith("QIBASE") || tst_Databases::isSqlServer(db)) + QSKIP("The casing test for this database is irrelevant since this database does not treat different cases as separate entities", SkipAll); QSqlQuery q(db); QVERIFY_SQL( q, exec("create table " + qTableName("CASETEST1", db.driver()).toUpper() + -- cgit v0.12 From 5f798ce8208fd5b1f2212246bc6b8ee2ec4652f0 Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Thu, 2 Jul 2009 18:16:42 -0700 Subject: Fix QDFBPaintEngine::drawTiledPixmap/fillRect Until this fix very few cases of drawTiledPixmap and fillRect(r, textureBrush) have been handled by DirectFB. This patch makes it possible to accelerate such operations. Reviewed-By: Donald --- .../gfxdrivers/directfb/qdirectfbpaintengine.cpp | 168 ++++++++++++++------- 1 file changed, 111 insertions(+), 57 deletions(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp index 947cc76..27df0da 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp @@ -241,7 +241,7 @@ public: void fillRects(const QRectF *rects, int count); void drawRects(const QRectF *rects, int count); - void drawTiledPixmap(const QRectF &dest, const QPixmap &pixmap); + void drawTiledPixmap(const QRectF &dest, const QPixmap &pixmap, const QPointF &pos); void blit(const QRectF &dest, IDirectFBSurface *surface, const QRectF &src); inline void updateClip(); @@ -284,6 +284,7 @@ private: bool unsupportedCompositionMode; QDirectFBPaintEngine *q; + QRect currentClip; friend class QDirectFBPaintEngine; }; @@ -343,6 +344,7 @@ bool QDirectFBPaintEngine::end() #if (Q_DIRECTFB_VERSION >= 0x010000) d->surface->ReleaseSource(d->surface); #endif + d->currentClip = QRect(); d->surface->SetClip(d->surface, NULL); d->surface = 0; return QRasterPaintEngine::end(); @@ -613,30 +615,26 @@ void QDirectFBPaintEngine::drawPixmap(const QPointF &p, const QPixmap &pm) void QDirectFBPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, - const QPointF &sp) + const QPointF &offset) { Q_D(QDirectFBPaintEngine); d->updateClip(); if (pixmap.pixmapData()->classId() != QPixmapData::DirectFBClass) { - RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), sp); + RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), offset); d->lock(); - QRasterPaintEngine::drawTiledPixmap(r, pixmap, sp); - } else if (d->unsupportedCompositionMode || !d->dfbCanHandleClip(r) || d->matrixRotShear || !sp.isNull() + QRasterPaintEngine::drawTiledPixmap(r, pixmap, offset); + } else if (d->unsupportedCompositionMode || !d->dfbCanHandleClip(r) || d->matrixRotShear || d->scale == QDirectFBPaintEnginePrivate::NegativeScale) { - RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), sp); + RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), offset); const QImage *img = static_cast(pixmap.pixmapData())->buffer(DSLF_READ); d->lock(); QRasterPixmapData *data = new QRasterPixmapData(QPixmapData::PixmapType); data->fromImage(*img, Qt::AutoColor); const QPixmap pix(data); - QRasterPaintEngine::drawTiledPixmap(r, pix, sp); + QRasterPaintEngine::drawTiledPixmap(r, pix, offset); } else { d->unlock(); - QPixmapData *data = pixmap.pixmapData(); - Q_ASSERT(data->classId() == QPixmapData::DirectFBClass); - QDirectFBPixmapData *dfbData = static_cast(data); - dfbData->unlockDirectFB(); - d->drawTiledPixmap(r, pixmap); + d->drawTiledPixmap(r, pixmap, offset); } } @@ -733,14 +731,17 @@ void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QBrush &brush) d->surface->FillRectangle(d->surface, r.x(), r.y(), r.width(), r.height()); return; } - case Qt::TexturePattern: - if (state()->brushOrigin == QPointF() && brush.transform().isIdentity()) { - //could handle certain types of brush.transform() E.g. scale - d->unlock(); - d->drawTiledPixmap(rect, brush.texture()); - return; - } - break; + case Qt::TexturePattern: { + if (d->scale == QDirectFBPaintEnginePrivate::NegativeScale) + break; + + const QPixmap texture = brush.texture(); + if (texture.pixmapData()->classId() != QPixmapData::DirectFBClass) + break; + + d->unlock(); + d->drawTiledPixmap(rect, texture, rect.topLeft() - state()->brushOrigin); + return; } default: break; } @@ -1077,55 +1078,105 @@ void QDirectFBPaintEnginePrivate::blit(const QRectF &dest, IDirectFBSurface *s, DirectFBError("QDirectFBPaintEngine::drawPixmap()", result); } -void QDirectFBPaintEnginePrivate::drawTiledPixmap(const QRectF &dest, - const QPixmap &pixmap) +static inline qreal fixCoord(qreal rect_pos, qreal pixmapSize, qreal offset) { + qreal pos = rect_pos - offset; + while (pos > rect_pos) + pos -= pixmapSize; + while (pos + pixmapSize < rect_pos) + pos += pixmapSize; + return pos; +} + +void QDirectFBPaintEnginePrivate::drawTiledPixmap(const QRectF &dest, const QPixmap &pixmap, const QPointF &off) +{ + Q_ASSERT(!dirtyClip); + const QRect destinationRect = transform.mapRect(dest).toRect().normalized(); + QRect newClip = destinationRect; + if (!currentClip.isEmpty()) + newClip &= currentClip; + + if (newClip.isNull()) + return; + + const DFBRegion clip = { + newClip.x(), + newClip.y(), + newClip.x() + newClip.width() - 1, + newClip.y() + newClip.height() - 1 + }; + surface->SetClip(surface, &clip); + + QPointF offset = off; + Q_ASSERT(transform.type() <= QTransform::TxScale); prepareForBlit(pixmap.hasAlphaChannel()); QPixmapData *data = pixmap.pixmapData(); Q_ASSERT(data->classId() == QPixmapData::DirectFBClass); QDirectFBPixmapData *dfbData = static_cast(data); - IDirectFBSurface *s = dfbData->directFBSurface(); - const QRect dr = transform.mapRect(dest).toRect(); - DFBResult result = DFB_OK; - - if (scale == NoScale && dr == QRect(0, 0, fbWidth, fbHeight)) { - result = surface->TileBlit(surface, s, 0, 0, 0); - } else if (scale == NoScale) { - const int dx = pixmap.width(); - const int dy = pixmap.height(); - const DFBRectangle rect = { 0, 0, dx, dy }; - QVarLengthArray rects; - QVarLengthArray points; - - for (int y = dr.y(); y <= dr.bottom(); y += dy) { - for (int x = dr.x(); x <= dr.right(); x += dx) { - rects.append(rect); - const DFBPoint point = { x, y }; - points.append(point); + dfbData->unlockDirectFB(); + const QSize pixmapSize = dfbData->size(); + IDirectFBSurface *sourceSurface = dfbData->directFBSurface(); + if (transform.isScaling()) { + Q_ASSERT(qMin(transform.m11(), transform.m22()) >= 0); + offset.rx() *= transform.m11(); + offset.ry() *= transform.m22(); + + const QSizeF mappedSize(pixmapSize.width() * transform.m11(), pixmapSize.height() * transform.m22()); + qreal y = ::fixCoord(destinationRect.y(), mappedSize.height(), offset.y()); + const qreal startX = ::fixCoord(destinationRect.x(), mappedSize.width(), offset.x()); + while (y < destinationRect.bottom()) { + qreal x = startX; + while (x < destinationRect.right()) { + const DFBRectangle destination = { qRound(x), qRound(y), mappedSize.width(), mappedSize.height() }; + surface->StretchBlit(surface, sourceSurface, 0, &destination); + x += mappedSize.width(); } + y += mappedSize.height(); } - result = surface->BatchBlit(surface, s, rects.constData(), - points.constData(), points.size()); } else { - const QRect sr = transform.mapRect(QRect(0, 0, pixmap.width(), pixmap.height())); - const int dx = sr.width(); - const int dy = sr.height(); - const DFBRectangle sRect = { 0, 0, dx, dy }; - - for (int y = dr.y(); y <= dr.bottom(); y += dy) { - for (int x = dr.x(); x <= dr.right(); x += dx) { - const DFBRectangle dRect = { x, y, dx, dy }; - result = surface->StretchBlit(surface, s, &sRect, &dRect); - if (result != DFB_OK) { - y = dr.bottom() + 1; - break; - } + qreal y = ::fixCoord(destinationRect.y(), pixmapSize.height(), offset.y()); + const qreal startX = ::fixCoord(destinationRect.x(), pixmapSize.width(), offset.x()); + int horizontal = qMax(1, destinationRect.width() / pixmapSize.width()) + 1; + if (startX != destinationRect.x()) + ++horizontal; + int vertical = qMax(1, destinationRect.height() / pixmapSize.height()) + 1; + if (y != destinationRect.y()) + ++vertical; + + const int maxCount = (vertical * horizontal); + QVarLengthArray sourceRects(maxCount); + QVarLengthArray points(maxCount); + + int i = 0; + while (y < destinationRect.bottom()) { + Q_ASSERT(i < maxCount); + qreal x = startX; + while (x < destinationRect.right()) { + points[i].x = qRound(x); + points[i].y = qRound(y); + sourceRects[i].x = 0; + sourceRects[i].y = 0; + sourceRects[i].w = int(pixmapSize.width()); + sourceRects[i].h = int(pixmapSize.height()); + x += pixmapSize.width(); + ++i; } + y += pixmapSize.height(); } + surface->BatchBlit(surface, sourceSurface, sourceRects.constData(), points.constData(), i); } - if (result != DFB_OK) - DirectFBError("QDirectFBPaintEngine::drawTiledPixmap()", result); + if (currentClip.isEmpty()) { + surface->SetClip(surface, 0); + } else { + const DFBRegion clip = { + currentClip.x(), + currentClip.y(), + currentClip.x() + currentClip.width(), + currentClip.y() + currentClip.height() + }; + surface->SetClip(surface, &clip); + } } void QDirectFBPaintEnginePrivate::updateClip() @@ -1133,6 +1184,7 @@ void QDirectFBPaintEnginePrivate::updateClip() if (!dirtyClip) return; + currentClip = QRect(); const QClipData *clipData = clip(); if (!clipData || !clipData->enabled) { surface->SetClip(surface, NULL); @@ -1145,6 +1197,8 @@ void QDirectFBPaintEnginePrivate::updateClip() clipData->clipRect.y() + clipData->clipRect.height() }; surface->SetClip(surface, &r); + currentClip = clipData->clipRect.normalized(); + // ### is this guaranteed to always be normalized? dfbHandledClip = true; } else if (clipData->hasRegionClip && ignoreSystemClip && clipData->clipRegion == systemClip) { dfbHandledClip = true; -- cgit v0.12 From f3acf50b1410d7756788b8f9b6144bf7af61a24e Mon Sep 17 00:00:00 2001 From: Bill King Date: Fri, 10 Jul 2009 13:13:44 +1000 Subject: Update test db definitions. --- tests/auto/qsqldatabase/tst_databases.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/auto/qsqldatabase/tst_databases.h b/tests/auto/qsqldatabase/tst_databases.h index 5b19023..9c8c313 100644 --- a/tests/auto/qsqldatabase/tst_databases.h +++ b/tests/auto/qsqldatabase/tst_databases.h @@ -105,7 +105,11 @@ inline static QString qTableName( const QString& prefix, QSqlDriver* driver = 0 inline static bool testWhiteSpaceNames( const QString &name ) { - return name != QLatin1String("QTDS7"); +/* return name.startsWith( "QPSQL" ) + || name.startsWith( "QODBC" ) + || name.startsWith( "QSQLITE" ) + || name.startsWith( "QMYSQL" );*/ + return name != QLatin1String("QSQLITE2"); } inline static QString toHex( const QString& binary ) @@ -246,10 +250,10 @@ public: // addDb( "QODBC", "DRIVER={MySQL ODBC 3.51 Driver};SERVER=mysql5-nokia.trolltech.com.au;DATABASE=testdb", "testuser", "Ee4Gabf6_", "" ); // addDb( "QODBC", "DRIVER={MySQL ODBC 5.1 Driver};SERVER=mysql4-nokia.trolltech.com.au;DATABASE=testdb", "testuser", "Ee4Gabf6_", "" ); -// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=horsehead.nokia.troll.no;DATABASE=testdb;PORT=4101;UID=troll;PWD=trondk;TDS_Version=8.0", "troll", "trondk", "" ); -// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=silence.nokia.troll.no;DATABASE=testdb;PORT=2392;UID=troll;PWD=trond;TDS_Version=8.0", "troll", "trond", "" ); -// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=bq-winserv2003-x86-01.apac.nokia.com;DATABASE=testdb;PORT=1433;UID=testuser;PWD=Ee4Gabf6_;TDS_Version=8.0", "testuser", "Ee4Gabf6_", "" ); -// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=bq-winserv2008-x86-01.apac.nokia.com;DATABASE=testdb;PORT=1433;UID=testuser;PWD=Ee4Gabf6_;TDS_Version=8.0", "testuser", "Ee4Gabf6_", "" ); +// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=horsehead.nokia.troll.no;DATABASE=testdb;PORT=4101;UID=troll;PWD=trondk", "troll", "trondk", "" ); +// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=silence.nokia.troll.no;DATABASE=testdb;PORT=2392;UID=troll;PWD=trond", "troll", "trond", "" ); +// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=bq-winserv2003-x86-01.apac.nokia.com;DATABASE=testdb;PORT=1433;UID=testuser;PWD=Ee4Gabf6_;TDS_Version=8.0", "", "", "" ); +// addDb( "QODBC", "DRIVER={FreeTDS};SERVER=bq-winserv2008-x86-01.apac.nokia.com;DATABASE=testdb;PORT=1433;UID=testuser;PWD=Ee4Gabf6_;TDS_Version=8.0", "", "", "" ); // addDb( "QTDS7", "testdb", "testuser", "Ee4Gabf6_", "bq-winserv2003" ); // addDb( "QTDS7", "testdb", "testuser", "Ee4Gabf6_", "bq-winserv2008" ); // addDb( "QODBC3", "DRIVER={SQL SERVER};SERVER=bq-winserv2003-x86-01.apac.nokia.com;DATABASE=testdb;PORT=1433", "testuser", "Ee4Gabf6_", "" ); -- cgit v0.12 From 64b485855637ef4fa31d3a4efca694db888ae612 Mon Sep 17 00:00:00 2001 From: Luc Devallonne Date: Fri, 10 Jul 2009 10:10:02 +0200 Subject: Support Tablet coordinate on Windows with non-zero physical origin Most Wacom tablet have a coordinate origin at 0 (Bamboo,Intous), but some tablet (like DTF 720, which have an integrated screen) have a non zero coordinate origin. Which lead to an errounous y/a tablet pos reported by Qt tablet event. Merge-request: 822 Reviewed-by: Norwegian Rock Cat --- src/gui/kernel/qapplication_p.h | 10 ++++++---- src/gui/kernel/qapplication_win.cpp | 20 +++++++++++--------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index db77b07..90eaba0 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -158,17 +158,19 @@ inline QPointF QTabletDeviceData::scaleCoord(int coordX, int coordY, int outOriginY, int outExtentY) const { QPointF ret; + if (sign(outExtentX) == sign(maxX)) - ret.setX(((coordX - minX) * qAbs(outExtentX) / qAbs(qreal(maxX))) + outOriginX); + ret.setX(((coordX - minX) * qAbs(outExtentX) / qAbs(qreal(maxX - minX))) + outOriginX); else - ret.setX(((qAbs(maxX) - (coordX - minX)) * qAbs(outExtentX) / qAbs(qreal(maxX))) + ret.setX(((qAbs(maxX) - (coordX - minX)) * qAbs(outExtentX) / qAbs(qreal(maxX - minX))) + outOriginX); if (sign(outExtentY) == sign(maxY)) - ret.setY(((coordY - minY) * qAbs(outExtentY) / qAbs(qreal(maxY))) + outOriginY); + ret.setY(((coordY - minY) * qAbs(outExtentY) / qAbs(qreal(maxY - minY))) + outOriginY); else - ret.setY(((qAbs(maxY) - (coordY - minY)) * qAbs(outExtentY) / qAbs(qreal(maxY))) + ret.setY(((qAbs(maxY) - (coordY - minY)) * qAbs(outExtentY) / qAbs(qreal(maxY - minY))) + outOriginY); + return ret; } #endif diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index e0eda82..e26d82e 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -3324,17 +3324,19 @@ static void tabletInit(UINT wActiveCsr, HCTX hTab) tdd.minTanPressure = int(np.axMin); tdd.maxTanPressure = int(np.axMax); - ptrWTInfo(WTI_DEVICES + lc.lcDevice, DVC_X, &np); - tdd.minX = int(np.axMin); - tdd.maxX = int(np.axMax); + LOGCONTEXT lcMine; - ptrWTInfo(WTI_DEVICES + lc.lcDevice, DVC_Y, &np); - tdd.minY = int(np.axMin); - tdd.maxY = int(np.axMax); + /* get default region */ + ptrWTInfo(WTI_DEFCONTEXT, 0, &lcMine); - ptrWTInfo(WTI_DEVICES + lc.lcDevice, DVC_Z, &np); - tdd.minZ = int(np.axMin); - tdd.maxZ = int(np.axMax); + tdd.minX = 0; + tdd.maxX = int(lcMine.lcInExtX) - int(lcMine.lcInOrgX); + + tdd.minY = 0; + tdd.maxY = int(lcMine.lcInExtY) - int(lcMine.lcInOrgY); + + tdd.minZ = 0; + tdd.maxZ = int(lcMine.lcInExtZ) - int(lcMine.lcInOrgZ); int csr_type, csr_physid; -- cgit v0.12 From 28f31572b95a28e14f7ed4cebb907cfe1e257177 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 10 Jul 2009 10:37:29 +0200 Subject: Painting artifacts when moving an item with partial updates. Found during manual testing (dndrobotinproxy). The problem was that the paintedViewBoundingRect was set to an empty rect because the partial update area didn't intersect with the viewport. The item itself was partially inside the viewport. Then, when the item was moved, its old area was not repainted due to this empty paintedViewBoundingRect. Auto-test included. --- src/gui/graphicsview/qgraphicsitem.cpp | 1 + src/gui/graphicsview/qgraphicsscene.cpp | 49 +++++++++++++------------- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 47 ++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 24 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 85d76d4..2f646f7 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1821,6 +1821,7 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo if (q_ptr->isSelected()) q_ptr->setSelected(false); } else { + geometryChanged = 1; if (isWidget && scene) { QGraphicsWidget *widget = static_cast(q_ptr); if (widget->windowType() == Qt::Popup) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 0ca72b7..c7c0865 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4517,17 +4517,14 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0; } - if (item->d_ptr->geometryChanged) { + if (!hasSceneRect && item->d_ptr->geometryChanged && item->d_ptr->visible) { // Update growingItemsBoundingRect. - if (!hasSceneRect) { - if (item->d_ptr->sceneTransformTranslateOnly) { - growingItemsBoundingRect |= item->boundingRect().translated(item->d_ptr->sceneTransform.dx(), - item->d_ptr->sceneTransform.dy()); - } else { - growingItemsBoundingRect |= item->d_ptr->sceneTransform.mapRect(item->boundingRect()); - } + if (item->d_ptr->sceneTransformTranslateOnly) { + growingItemsBoundingRect |= item->boundingRect().translated(item->d_ptr->sceneTransform.dx(), + item->d_ptr->sceneTransform.dy()); + } else { + growingItemsBoundingRect |= item->d_ptr->sceneTransform.mapRect(item->boundingRect()); } - item->d_ptr->geometryChanged = 0; } // Process item. @@ -4552,29 +4549,31 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool for (int j = 0; j < views.size(); ++j) { QGraphicsView *view = views.at(j); QGraphicsViewPrivate *viewPrivate = view->d_func(); - if (viewPrivate->fullUpdatePending) - continue; - switch (viewPrivate->viewportUpdateMode) { - case QGraphicsView::NoViewportUpdate: - continue; - case QGraphicsView::FullViewportUpdate: - view->viewport()->update(); - viewPrivate->fullUpdatePending = 1; + QRect &paintedViewBoundingRect = item->d_ptr->paintedViewBoundingRects[viewPrivate->viewport]; + if (viewPrivate->fullUpdatePending + || viewPrivate->viewportUpdateMode == QGraphicsView::NoViewportUpdate) { + // Okay, if we have a full update pending or no viewport update, this item's + // paintedViewBoundingRect will be updated correctly in the next paintEvent if + // it is inside the viewport, but for now we can pretend that it is outside. + paintedViewBoundingRect = QRect(-1, -1, -1, -1); continue; - default: - break; } - QRect &paintedViewBoundingRect = item->d_ptr->paintedViewBoundingRects[viewPrivate->viewport]; - if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) { + if (item->d_ptr->paintedViewBoundingRectsNeedRepaint && !paintedViewBoundingRect.isEmpty()) { paintedViewBoundingRect.translate(viewPrivate->dirtyScrollOffset); if (!viewPrivate->updateRect(paintedViewBoundingRect)) - paintedViewBoundingRect = QRect(); + paintedViewBoundingRect = QRect(-1, -1, -1, -1); // Outside viewport. } if (!item->d_ptr->dirty) continue; + if (!item->d_ptr->geometryChanged + && paintedViewBoundingRect.x() == -1 && paintedViewBoundingRect.y() == -1 + && paintedViewBoundingRect.width() == -1 && paintedViewBoundingRect.height() == -1) { + continue; // Outside viewport. + } + if (uninitializedDirtyRect) { dirtyRect = itemBoundingRect; if (!item->d_ptr->fullUpdatePending) { @@ -4587,8 +4586,10 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool if (dirtyRect.isEmpty()) continue; // Discard updates outside the bounding rect. - if (!updateHelper(viewPrivate, item->d_ptr, dirtyRect, itemIsUntransformable)) - paintedViewBoundingRect = QRect(); + if (!updateHelper(viewPrivate, item->d_ptr, dirtyRect, itemIsUntransformable) + && item->d_ptr->geometryChanged) { + paintedViewBoundingRect = QRect(-1, -1, -1, -1); // Outside viewport. + } } } } diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index d689293..2dbd5f1 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -6580,6 +6580,7 @@ public: void tst_QGraphicsItem::update() { QGraphicsScene scene; + scene.setSceneRect(-100, -100, 200, 200); MyGraphicsView view(&scene); view.show(); @@ -6636,6 +6637,52 @@ void tst_QGraphicsItem::update() QCOMPARE(view.repaints, 1); // The entire item's bounding rect (adjusted for antialiasing) should have been painted. QCOMPARE(view.paintedRegion, expectedRegion); + + // Make sure item is repainted when shown (after being hidden). + view.reset(); + item->repaints = 0; + item->show(); + qApp->processEvents(); + QCOMPARE(item->repaints, 1); + QCOMPARE(view.repaints, 1); + // The entire item's bounding rect (adjusted for antialiasing) should have been painted. + QCOMPARE(view.paintedRegion, expectedRegion); + + item->repaints = 0; + item->hide(); + qApp->processEvents(); + view.reset(); + const QPointF originalPos = item->pos(); + item->setPos(5000, 5000); + qApp->processEvents(); + QCOMPARE(item->repaints, 0); + QCOMPARE(view.repaints, 0); + qApp->processEvents(); + + item->setPos(originalPos); + qApp->processEvents(); + QCOMPARE(item->repaints, 0); + QCOMPARE(view.repaints, 0); + item->show(); + qApp->processEvents(); + QCOMPARE(item->repaints, 1); + QCOMPARE(view.repaints, 1); + // The entire item's bounding rect (adjusted for antialiasing) should have been painted. + QCOMPARE(view.paintedRegion, expectedRegion); + + QGraphicsViewPrivate *viewPrivate = static_cast(qt_widget_private(&view)); + item->setPos(originalPos + QPoint(50, 50)); + viewPrivate->updateAll(); + QVERIFY(viewPrivate->fullUpdatePending); + QTest::qWait(50); + item->repaints = 0; + view.reset(); + item->setPos(originalPos); + QTest::qWait(50); + qApp->processEvents(); + QCOMPARE(item->repaints, 1); + QCOMPARE(view.repaints, 1); + QCOMPARE(view.paintedRegion, expectedRegion + expectedRegion.translated(50, 50)); } void tst_QGraphicsItem::setTransformProperties_data() -- cgit v0.12 From 00cc4c9cfc83fa2a20fc72712c7caf9f8bc6f7bb Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Fri, 10 Jul 2009 11:08:24 +0200 Subject: Phonon videos on windows would not show with video acceleration disabled Task-number: 257805 --- src/3rdparty/phonon/ds9/videowidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/3rdparty/phonon/ds9/videowidget.cpp b/src/3rdparty/phonon/ds9/videowidget.cpp index 0ef653f..34ff8cb 100644 --- a/src/3rdparty/phonon/ds9/videowidget.cpp +++ b/src/3rdparty/phonon/ds9/videowidget.cpp @@ -153,7 +153,7 @@ namespace Phonon } } else if (!isEmbedded()) { m_currentRenderer = m_node->switchRendering(m_currentRenderer); - setAttribute(Qt::WA_PaintOnScreen, true); + setAttribute(Qt::WA_PaintOnScreen, false); } } -- cgit v0.12 From f9128d973f60e225045bebb97a19d292395b865d Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Fri, 10 Jul 2009 11:24:35 +0200 Subject: QDoubleSpinBox: make sure people can't choose too many decimals Maximum number of decimals is DBL_MAX_10_EXP + DBL_DIG Task-number: 257291 --- src/gui/widgets/qspinbox.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/gui/widgets/qspinbox.cpp b/src/gui/widgets/qspinbox.cpp index e069a21..3933272 100644 --- a/src/gui/widgets/qspinbox.cpp +++ b/src/gui/widgets/qspinbox.cpp @@ -50,6 +50,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -823,8 +824,8 @@ void QDoubleSpinBox::setRange(double minimum, double maximum) Sets how many decimals the spinbox will use for displaying and interpreting doubles. - \warning The results might not be reliable with very high values - for \a decimals. + \warning The maximum value for \a decimals is DBL_MAX_10_EXP + + DBL_DIG (ie. 323) because of the limitations of the double type. Note: The maximum, minimum and value might change as a result of changing this property. @@ -840,7 +841,7 @@ int QDoubleSpinBox::decimals() const void QDoubleSpinBox::setDecimals(int decimals) { Q_D(QDoubleSpinBox); - d->decimals = qMax(0, decimals); + d->decimals = qBound(0, decimals, DBL_MAX_10_EXP + DBL_DIG); setRange(minimum(), maximum()); // make sure values are rounded setValue(value()); -- cgit v0.12 From fdf5fd0cc63c20579250087905331eb76385d528 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Fri, 10 Jul 2009 12:32:26 +0200 Subject: QFileDialog: the side urls are now always cleaned when they are local Task-number: 257579 --- src/gui/dialogs/qsidebar.cpp | 13 +++++++++---- tests/auto/qfiledialog/tst_qfiledialog.cpp | 21 +++++++++++++++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/gui/dialogs/qsidebar.cpp b/src/gui/dialogs/qsidebar.cpp index 1915e21..e4821ad 100644 --- a/src/gui/dialogs/qsidebar.cpp +++ b/src/gui/dialogs/qsidebar.cpp @@ -247,11 +247,16 @@ void QUrlModel::addUrls(const QList &list, int row, bool move) QUrl url = list.at(i); if (!url.isValid() || url.scheme() != QLatin1String("file")) continue; + //this makes sure the url is clean + const QString cleanUrl = QDir::cleanPath(url.toLocalFile()); + url = QUrl::fromLocalFile(cleanUrl); + for (int j = 0; move && j < rowCount(); ++j) { + QString local = index(j, 0).data(UrlRole).toUrl().toLocalFile(); #if defined(Q_OS_WIN) - if (QDir::cleanPath(index(j, 0).data(UrlRole).toUrl().toLocalFile()).toLower() == QDir::cleanPath(url.toLocalFile()).toLower()) { + if (index(j, 0).data(UrlRole).toUrl().toLocalFile().toLower() == cleanUrl.toLower()) { #else - if (QDir::cleanPath(index(j, 0).data(UrlRole).toUrl().toLocalFile()) == QDir::cleanPath(url.toLocalFile())) { + if (index(j, 0).data(UrlRole).toUrl().toLocalFile() == cleanUrl) { #endif removeRow(j); if (j <= row) @@ -260,12 +265,12 @@ void QUrlModel::addUrls(const QList &list, int row, bool move) } } row = qMax(row, 0); - QModelIndex idx = fileSystemModel->index(url.toLocalFile()); + QModelIndex idx = fileSystemModel->index(cleanUrl); if (!fileSystemModel->isDir(idx)) continue; insertRows(row, 1); setUrl(index(row, 0), url, idx); - watching.append(QPair(idx, url.toLocalFile())); + watching.append(qMakePair(idx, cleanUrl)); } } diff --git a/tests/auto/qfiledialog/tst_qfiledialog.cpp b/tests/auto/qfiledialog/tst_qfiledialog.cpp index 8bb81e7..50cab0e 100644 --- a/tests/auto/qfiledialog/tst_qfiledialog.cpp +++ b/tests/auto/qfiledialog/tst_qfiledialog.cpp @@ -160,6 +160,7 @@ private slots: void task251321_sideBarHiddenEntries(); void task251341_sideBarRemoveEntries(); void task254490_selectFileMultipleTimes(); + void task257579_sideBarWithNonCleanUrls(); private: QByteArray userSettings; @@ -2026,5 +2027,25 @@ void tst_QFiledialog::task254490_selectFileMultipleTimes() t->deleteLater(); } +void tst_QFiledialog::task257579_sideBarWithNonCleanUrls() +{ + QDir tempDir = QDir::temp(); + QLatin1String dirname("autotest_task257579"); + tempDir.rmdir(dirname); //makes sure it doesn't exist any more + QVERIFY(tempDir.mkdir(dirname)); + QString url = QString::fromLatin1("%1/%2/..").arg(tempDir.absolutePath()).arg(dirname); + QNonNativeFileDialog fd; + fd.setSidebarUrls(QList() << QUrl::fromLocalFile(url)); + QSidebar *sidebar = qFindChild(&fd, "sidebar"); + QCOMPARE(sidebar->urls().count(), 1); + QVERIFY(sidebar->urls().first().toLocalFile() != url); + QCOMPARE(sidebar->urls().first().toLocalFile(), QDir::cleanPath(url)); + QCOMPARE(sidebar->model()->index(0,0).data().toString(), tempDir.dirName()); + + //all tests are finished, we can remove the temporary dir + QVERIFY(tempDir.rmdir(dirname)); +} + + QTEST_MAIN(tst_QFiledialog) #include "tst_qfiledialog.moc" -- cgit v0.12 From 9d073c3c92f732ec73587b0696e8994107a98402 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 10 Jul 2009 11:54:53 +0200 Subject: Fix compilation support with namespaces for QtLibcSupplement Reviewed-By: hjk --- src/corelib/kernel/qcore_unix_p.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h index 1bf2425..8d43897 100644 --- a/src/corelib/kernel/qcore_unix_p.h +++ b/src/corelib/kernel/qcore_unix_p.h @@ -69,19 +69,19 @@ struct sockaddr; -QT_BEGIN_NAMESPACE - #if defined(Q_OS_LINUX) && defined(O_CLOEXEC) && defined(__GLIBC__) && (__GLIBC__ * 0x100 + __GLIBC_MINOR__) >= 0x0204 // Linux supports thread-safe FD_CLOEXEC # define QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC 1 +QT_BEGIN_NAMESPACE namespace QtLibcSupplement { Q_CORE_EXPORT int accept4(int, sockaddr *, QT_SOCKLEN_T *, int flags); Q_CORE_EXPORT int dup3(int oldfd, int newfd, int flags); Q_CORE_EXPORT int pipe2(int pipes[], int flags); } +QT_END_NAMESPACE +using namespace QT_PREPEND_NAMESPACE(QtLibcSupplement); -using namespace QtLibcSupplement; #else # define QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC 0 #endif @@ -91,6 +91,7 @@ using namespace QtLibcSupplement; var = cmd; \ } while (var == -1 && errno == EINTR) +QT_BEGIN_NAMESPACE // don't call QT_OPEN or ::open // call qt_safe_open -- cgit v0.12 From c1cf0eb65e87386d1875ed309e5c13cdc0f33e3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 10 Jul 2009 12:50:10 +0200 Subject: Painting artifacts when closing an embedded popup in Graphics View. Found during manual testing (demos/embeddeddialogs). The problem was that a full update (right before hiding/deleting an item) caused the update request made from the destructor to be discarded. Auto-test included. --- src/gui/graphicsview/qgraphicsitem.cpp | 7 ++-- .../tst_qgraphicsproxywidget.cpp | 39 ++++++++++++++++++++++ 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 2f646f7..0cfaab7 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -4325,12 +4325,11 @@ bool QGraphicsItemPrivate::discardUpdateRequest(bool ignoreClipping, bool ignore { // No scene, or if the scene is updating everything, means we have nothing // to do. The only exception is if the scene tracks the growing scene rect. - return (!visible && !ignoreVisibleBit) + return !scene + || (!visible && !ignoreVisibleBit && !this->ignoreVisible) || (!ignoreDirtyBit && fullUpdatePending) - || !scene - || (scene->d_func()->updateAll && scene->d_func()->hasSceneRect) || (!ignoreClipping && (childrenClippedToShape() && isClippedAway())) - || (!ignoreOpacity && childrenCombineOpacity() && isFullyTransparent()); + || (!ignoreOpacity && !this->ignoreOpacity && childrenCombineOpacity() && isFullyTransparent()); } /*! diff --git a/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp index 0b1d5cf..3b13bcc 100644 --- a/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp +++ b/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp @@ -178,6 +178,7 @@ private slots: void windowFlags_data(); void windowFlags(); void comboboxWindowFlags(); + void updateAndDelete(); }; // Subclass that exposes the protected functions. @@ -3217,6 +3218,44 @@ void tst_QGraphicsProxyWidget::comboboxWindowFlags() QVERIFY((static_cast(popupProxy)->windowFlags() & Qt::Popup) == Qt::Popup); } +void tst_QGraphicsProxyWidget::updateAndDelete() +{ + QGraphicsScene scene; + QGraphicsProxyWidget *proxy = scene.addWidget(new QPushButton("Hello World")); + View view(&scene); + view.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&view); +#endif + QTest::qWait(200); + + const QRect itemDeviceBoundingRect = proxy->deviceTransform(view.viewportTransform()) + .mapRect(proxy->boundingRect()).toRect(); + const QRegion expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2); + + view.npaints = 0; + view.paintEventRegion = QRegion(); + + // Update and hide. + proxy->update(); + proxy->hide(); + QTest::qWait(50); + QCOMPARE(view.npaints, 1); + QCOMPARE(view.paintEventRegion, expectedRegion); + + proxy->show(); + QTest::qWait(50); + view.npaints = 0; + view.paintEventRegion = QRegion(); + + // Update and delete. + proxy->update(); + delete proxy; + QTest::qWait(50); + QCOMPARE(view.npaints, 1); + QCOMPARE(view.paintEventRegion, expectedRegion); +} + QTEST_MAIN(tst_QGraphicsProxyWidget) #include "tst_qgraphicsproxywidget.moc" -- cgit v0.12 From b420385f15f109765fc31c5bcc5b4ea9498b82d4 Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Fri, 10 Jul 2009 13:17:43 +0200 Subject: doc: Clarified that native messages are being handled. Task-number: 214026 --- src/corelib/kernel/qabstracteventdispatcher.cpp | 25 ++++++++------- src/corelib/kernel/qcoreapplication.cpp | 42 +++++++++++++++++-------- 2 files changed, 43 insertions(+), 24 deletions(-) diff --git a/src/corelib/kernel/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp index a98d005..e2682f5 100644 --- a/src/corelib/kernel/qabstracteventdispatcher.cpp +++ b/src/corelib/kernel/qabstracteventdispatcher.cpp @@ -398,20 +398,23 @@ void QAbstractEventDispatcher::closingDown() */ /*! - Sets the event filter \a filter. Returns a pointer to the filter - function previously defined. - - The event filter is a function that receives all messages taken - from the system event loop before the event is dispatched to the - respective target. This includes messages that are not sent to Qt + Replaces the event filter function for this + QAbstractEventDispatcher with \a filter and returns the replaced + event filter function. Only the current event filter function is + called. If you want to use both filter functions, save the + replaced EventFilter in a place where yours can call it. + + The event filter function set here is called for all messages + taken from the system event loop before the event is dispatched to + the respective target, including the messages not meant for Qt objects. - The function can return true to stop the event to be processed by - Qt, or false to continue with the standard event processing. + The event filter function should return true if the message should + be filtered, (i.e. stopped). It should return false to allow + processing the message to continue. - Only one filter can be defined, but the filter can use the return - value to call the previously set event filter. By default, no - filter is set (i.e. the function returns 0). + By default, no event filter function is set (i.e., this function + returns a null EventFilter the first time it is called). */ QAbstractEventDispatcher::EventFilter QAbstractEventDispatcher::setEventFilter(EventFilter filter) { diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 054be70..706dc54 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -2183,21 +2183,37 @@ void QCoreApplication::removeLibraryPath(const QString &path) /*! \fn EventFilter QCoreApplication::setEventFilter(EventFilter filter) - Sets the event filter \a filter. Returns a pointer to the filter - function previously defined. - - The event filter is a function that is called for every message - received in all threads. This does \e not include messages to + Replaces the event filter function for the QCoreApplication with + \a filter and returns the pointer to the replaced event filter + function. Only the current event filter function is called. If you + want to use both filter functions, save the replaced EventFilter + in a place where yours can call it. + + The event filter function set here is called for all messages + received by all threads meant for all Qt objects. It is \e not + called for messages that are not meant for Qt objects. + + The event filter function should return true if the message should + be filtered, (i.e. stopped). It should return false to allow + processing the message to continue. + + By default, no event filter function is set (i.e., this function + returns a null EventFilter the first time it is called). + + \note The filter function set here receives native messages, + i.e. MSG or XEvent structs, that are going to Qt objects. It is + called by QCoreApplication::filterEvent(). If the filter function + returns false to indicate the message should be processed further, + the native message can then be translated into a QEvent and + handled by the standard Qt \l{QEvent} {event} filering, e.g. + QObject::installEventFilter(). + + \note The filter function set here is different form the filter + function set via QAbstractEventDispatcher::setEventFilter(), which + gets all messages received by its thread, even messages meant for objects that are not handled by Qt. - The function can return true to stop the event to be processed by - Qt, or false to continue with the standard event processing. - - Only one filter can be defined, but the filter can use the return - value to call the previously set event filter. By default, no - filter is set (i.e., the function returns 0). - - \sa installEventFilter() + \sa QObject::installEventFilter(), QAbstractEventDispatcher::setEventFilter() */ QCoreApplication::EventFilter QCoreApplication::setEventFilter(QCoreApplication::EventFilter filter) -- cgit v0.12 From bc747a81f4f6f0978f71cd8d19f69060fc8a8041 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Fri, 10 Jul 2009 14:30:05 +0200 Subject: QMainWindow: it is useless to apply the stte after a call to plug The layoutState is already current (ie. already applied). --- src/gui/widgets/qmainwindowlayout.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/gui/widgets/qmainwindowlayout.cpp b/src/gui/widgets/qmainwindowlayout.cpp index 541907e..3936a67 100644 --- a/src/gui/widgets/qmainwindowlayout.cpp +++ b/src/gui/widgets/qmainwindowlayout.cpp @@ -1629,9 +1629,6 @@ void QMainWindowLayout::animationFinished(QWidget *widget) #ifndef QT_NO_DOCKWIDGET #ifndef QT_NO_TABBAR - //it is important to set the current tab before applying the layout - //so that applyState will not try to counter the result of the animation - //by putting the item in negative space if (qobject_cast(widget) != 0) { // info() might return null if the widget is destroyed while // animating but before the animationFinished signal is received. @@ -1641,8 +1638,6 @@ void QMainWindowLayout::animationFinished(QWidget *widget) #endif #endif - applyState(layoutState, false); - savedState.clear(); currentGapPos.clear(); pluggingWidget = 0; -- cgit v0.12 From e2bf5eeee12329ad4aee941b5bb70af4ee5bb32f Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Fri, 10 Jul 2009 15:30:01 +0200 Subject: QTableView: horizontal scrollbar could be inoperent with big columns Task-number: 240266 --- src/gui/itemviews/qtableview.cpp | 4 ++++ tests/auto/qtableview/tst_qtableview.cpp | 26 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/gui/itemviews/qtableview.cpp b/src/gui/itemviews/qtableview.cpp index c676237..882a213 100644 --- a/src/gui/itemviews/qtableview.cpp +++ b/src/gui/itemviews/qtableview.cpp @@ -1528,6 +1528,8 @@ void QTableView::updateGeometries() ++columnsInViewport; } } + columnsInViewport = qMax(columnsInViewport, 1); //there must be always at least 1 column + if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) { const int visibleColumns = columnCount - d->horizontalHeader->hiddenSectionCount(); horizontalScrollBar()->setRange(0, visibleColumns - columnsInViewport); @@ -1554,6 +1556,8 @@ void QTableView::updateGeometries() ++rowsInViewport; } } + rowsInViewport = qMax(rowsInViewport, 1); //there must be always at least 1 row + if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) { const int visibleRows = rowCount - d->verticalHeader->hiddenSectionCount(); verticalScrollBar()->setRange(0, visibleRows - rowsInViewport); diff --git a/tests/auto/qtableview/tst_qtableview.cpp b/tests/auto/qtableview/tst_qtableview.cpp index ae023ba..0a69b75 100644 --- a/tests/auto/qtableview/tst_qtableview.cpp +++ b/tests/auto/qtableview/tst_qtableview.cpp @@ -175,6 +175,7 @@ private slots: // task-specific tests: void task173773_updateVerticalHeader(); void task227953_setRootIndex(); + void task240266_veryBigColumn(); void mouseWheel_data(); void mouseWheel(); @@ -3127,6 +3128,31 @@ void tst_QTableView::task227953_setRootIndex() QVERIFY(!tableView.verticalHeader()->isHidden()); } +void tst_QTableView::task240266_veryBigColumn() +{ + QTableView table; + table.setFixedSize(500, 300); //just to make sure we have the 2 first columns visible + QStandardItemModel model(1, 3); + table.setModel(&model); + table.setColumnWidth(0, 100); //normal column + table.setColumnWidth(1, 100); //normal column + table.setColumnWidth(2, 9000); //very big column + table.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&view); +#endif + QTest::qWait(100); + + QScrollBar *scroll = table.horizontalScrollBar(); + QCOMPARE(scroll->minimum(), 0); + QCOMPARE(scroll->maximum(), model.columnCount() - 1); + QCOMPARE(scroll->singleStep(), 1); + + //1 is not always a very correct value for pageStep. Ideally this should be dynamic. + //Maybe something for Qt 5 ;-) + QCOMPARE(scroll->pageStep(), 1); + +} void tst_QTableView::mouseWheel_data() { -- cgit v0.12 From 788b8ab3eed9314310408a577d797471d392d582 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Fri, 10 Jul 2009 15:46:13 +0200 Subject: adding autotest Task-number: 248688 --- tests/auto/qtableview/tst_qtableview.cpp | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/tests/auto/qtableview/tst_qtableview.cpp b/tests/auto/qtableview/tst_qtableview.cpp index 0a69b75..6fa57f0 100644 --- a/tests/auto/qtableview/tst_qtableview.cpp +++ b/tests/auto/qtableview/tst_qtableview.cpp @@ -176,6 +176,7 @@ private slots: void task173773_updateVerticalHeader(); void task227953_setRootIndex(); void task240266_veryBigColumn(); + void task248688_autoScrollNavigation(); void mouseWheel_data(); void mouseWheel(); @@ -587,7 +588,7 @@ void tst_QTableView::keyboardNavigation() QModelIndex index = model.index(rowCount - 1, columnCount - 1); view.setCurrentIndex(index); - QApplication::instance()->processEvents(); + QApplication::processEvents(); int row = rowCount - 1; int column = columnCount - 1; @@ -619,7 +620,7 @@ void tst_QTableView::keyboardNavigation() } QTest::keyClick(&view, key); - QApplication::instance()->processEvents(); + QApplication::processEvents(); QModelIndex index = model.index(row, column); QCOMPARE(view.currentIndex(), index); @@ -3154,6 +3155,31 @@ void tst_QTableView::task240266_veryBigColumn() } +void tst_QTableView::task248688_autoScrollNavigation() +{ + //we make sure that when navigating with the keyboard the view is correctly scrolled + //to the current item + QStandardItemModel model(16, 16); + QTableView view; + view.setModel(&model); + + view.hideColumn(8); + view.hideRow(8); + view.show(); + for (int r = 0; r < model.rowCount(); ++r) { + if (view.isRowHidden(r)) + continue; + for (int c = 0; c < model.columnCount(); ++c) { + if (view.isColumnHidden(c)) + continue; + QModelIndex index = model.index(r, c); + view.setCurrentIndex(index); + QVERIFY(view.viewport()->rect().contains(view.visualRect(index))); + } + } +} + + void tst_QTableView::mouseWheel_data() { QTest::addColumn("scrollMode"); -- cgit v0.12 From 7cca54d2bd7e8e42419210c499e27a1452447330 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Fri, 10 Jul 2009 16:02:24 +0200 Subject: QTableView: auto-scrolling could be broken by invisible sections Task-number: 248688 --- src/gui/itemviews/qtableview.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/itemviews/qtableview.cpp b/src/gui/itemviews/qtableview.cpp index 882a213..2009499 100644 --- a/src/gui/itemviews/qtableview.cpp +++ b/src/gui/itemviews/qtableview.cpp @@ -2040,7 +2040,7 @@ void QTableView::scrollTo(const QModelIndex &index, ScrollHint hint) if (positionAtRight || hint == PositionAtCenter || positionAtLeft) { int hiddenSections = 0; if (d->horizontalHeader->sectionsHidden()) { - for (int s = horizontalIndex; s >= 0; --s) { + for (int s = horizontalIndex - 1; s >= 0; --s) { int column = d->horizontalHeader->logicalIndex(s); if (d->horizontalHeader->isSectionHidden(column)) ++hiddenSections; @@ -2095,7 +2095,7 @@ void QTableView::scrollTo(const QModelIndex &index, ScrollHint hint) if (hint == PositionAtBottom || hint == PositionAtCenter || hint == PositionAtTop) { int hiddenSections = 0; if (d->verticalHeader->sectionsHidden()) { - for (int s = verticalIndex; s >= 0; --s) { + for (int s = verticalIndex - 1; s >= 0; --s) { int row = d->verticalHeader->logicalIndex(s); if (d->verticalHeader->isSectionHidden(row)) ++hiddenSections; -- cgit v0.12 From 4ed3ee42bae92b0feb5c898e4f0fdf7d34e34108 Mon Sep 17 00:00:00 2001 From: Luc Devallonne Date: Fri, 10 Jul 2009 16:22:33 +0200 Subject: Tablet events get delivered to the widget where the tablet down happend. This is basically the Windows version of the bug fixed in change 82e825ed841bce324a6892fcbace03f9936d4f4f Merge-request: 855 Reviewed-by: Norwegian Rock Cat --- src/gui/kernel/qapplication_win.cpp | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index e26d82e..e0c62b7 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -2956,7 +2956,9 @@ bool QETWidget::translateMouseEvent(const MSG &msg) if (alienWidget && alienWidget->internalWinId()) alienWidget = 0; - if (type == QEvent::MouseMove || type == QEvent::NonClientAreaMouseMove) { + if (type == QEvent::MouseMove || type == QEvent::NonClientAreaMouseMove + || type == QEvent::TabletMove) { + if (!(state & Qt::MouseButtonMask)) qt_button_down = 0; #ifndef QT_NO_CURSOR @@ -3087,6 +3089,8 @@ bool QETWidget::translateMouseEvent(const MSG &msg) popupButtonFocus = popupChild; break; case QEvent::MouseButtonRelease: + case QEvent::TabletRelease: + releaseAfter = true; break; default: @@ -3446,13 +3450,34 @@ bool QETWidget::translateTabletEvent(const MSG &msg, PACKET *localPacketBuf, } QPoint globalPos(qRound(hiResGlobal.x()), qRound(hiResGlobal.y())); + if (t == QEvent::TabletPress) + { + qt_button_down = QApplication::widgetAt(globalPos); + } + // make sure the tablet event get's sent to the proper widget... - QWidget *w = QApplication::widgetAt(globalPos); + QWidget *w = 0; + if (qt_button_down) w = qt_button_down; // Pass it to the thing that's grabbed it. + else + w = QApplication::widgetAt(globalPos); if (!w) w = this; + + if (t == QEvent::TabletRelease) + { + if (qt_win_ignoreNextMouseReleaseEvent) { + qt_win_ignoreNextMouseReleaseEvent = false; + if (qt_button_down && qt_button_down->internalWinId() == autoCaptureWnd) { + releaseAutoCapture(); + qt_button_down = 0; + } + } + + } + QPoint localPos = w->mapFromGlobal(globalPos); #ifndef QT_NO_TABLETEVENT if (currentTabletPointer.currentDevice == QTabletEvent::Airbrush) { -- cgit v0.12 From 364aa2a21512d32f3f4271f438e3a6fa799c1e9e Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Fri, 10 Jul 2009 16:30:49 +0200 Subject: ItemViews: make the pixmap from drag and drop more efficient We don't need to draw all the items that are selected. We just need those whose rect intersects the one from the viewport. Task-number: 233342 --- src/gui/itemviews/qabstractitemview.cpp | 33 ++++++++++++++++++++------------- src/gui/itemviews/qabstractitemview_p.h | 2 +- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index dd84304..5f347dd 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -3883,28 +3883,35 @@ bool QAbstractItemViewPrivate::openEditor(const QModelIndex &index, QEvent *even QPixmap QAbstractItemViewPrivate::renderToPixmap(const QModelIndexList &indexes, QRect *r) const { + Q_ASSERT(r); Q_Q(const QAbstractItemView); - QRect rect = q->visualRect(indexes.at(0)); + QRect &rect = *r; + const QRect viewportRect = viewport->rect(); QList rects; + QModelIndexList paintedIndexes; for (int i = 0; i < indexes.count(); ++i) { - rects.append(q->visualRect(indexes.at(i))); - rect |= rects.at(i); + const QModelIndex &index = indexes.at(i); + const QRect current = q->visualRect(index); + if (current.intersects(viewportRect)) { + paintedIndexes += index; + rects += current; + rect |= current; + } } - rect = rect.intersected(viewport->rect()); - if (rect.width() <= 0 || rect.height() <= 0) + rect = rect.intersected(viewportRect); + if (rect.isEmpty()) return QPixmap(); - QImage image(rect.size(), QImage::Format_ARGB32_Premultiplied); - image.fill(0); - QPainter painter(&image); + QPixmap pixmap(rect.size()); + pixmap.fill(Qt::transparent); + QPainter painter(&pixmap); QStyleOptionViewItemV4 option = viewOptionsV4(); option.state |= QStyle::State_Selected; - for (int j = 0; j < indexes.count(); ++j) { + for (int j = 0; j < paintedIndexes.count(); ++j) { + const QModelIndex ¤t = paintedIndexes.at(j); option.rect = QRect(rects.at(j).topLeft() - rect.topLeft(), rects.at(j).size()); - delegateForIndex(indexes.at(j))->paint(&painter, option, indexes.at(j)); + delegateForIndex(current)->paint(&painter, option, current); } - painter.end(); - if (r) *r = rect; - return QPixmap::fromImage(image); + return pixmap; } void QAbstractItemViewPrivate::selectAll(QItemSelectionModel::SelectionFlags command) diff --git a/src/gui/itemviews/qabstractitemview_p.h b/src/gui/itemviews/qabstractitemview_p.h index 00647f6..7443d50 100644 --- a/src/gui/itemviews/qabstractitemview_p.h +++ b/src/gui/itemviews/qabstractitemview_p.h @@ -221,7 +221,7 @@ public: void clearOrRemove(); void checkPersistentEditorFocus(); - QPixmap renderToPixmap(const QModelIndexList &indexes, QRect *r = 0) const; + QPixmap renderToPixmap(const QModelIndexList &indexes, QRect *r) const; inline QPoint offset() const { const Q_Q(QAbstractItemView); -- cgit v0.12 From 577b3d7efc56f23dcf2b377816caa7d1aa3c7f88 Mon Sep 17 00:00:00 2001 From: Norwegian Rock Cat Date: Fri, 10 Jul 2009 16:36:53 +0200 Subject: Fix compilation on SnowLeopard On 64-bit an id (void *) is 64-bit also, so, it really should be a pointer, but I'll make it a 64-bit int for the time being just so stuff compiles. --- src/gui/kernel/qmultitouch_mac.mm | 6 +++--- src/gui/kernel/qmultitouch_mac_p.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gui/kernel/qmultitouch_mac.mm b/src/gui/kernel/qmultitouch_mac.mm index 3fe85a9..3d2eae6 100644 --- a/src/gui/kernel/qmultitouch_mac.mm +++ b/src/gui/kernel/qmultitouch_mac.mm @@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE #ifdef QT_MAC_USE_COCOA -QHash QCocoaTouch::_currentTouches; +QHash QCocoaTouch::_currentTouches; QPointF QCocoaTouch::_screenReferencePos; QPointF QCocoaTouch::_trackpadReferencePos; int QCocoaTouch::_idAssignmentCount = 0; @@ -62,7 +62,7 @@ QCocoaTouch::QCocoaTouch(NSTouch *nstouch) _touchPoint.setId(_idAssignmentCount++); _touchPoint.setPressure(1.0); - _identity = int([nstouch identity]); + _identity = qint64([nstouch identity]); _currentTouches.insert(_identity, this); updateTouchData(nstouch, NSTouchPhaseBegan); } @@ -100,7 +100,7 @@ void QCocoaTouch::updateTouchData(NSTouch *nstouch, NSTouchPhase phase) QCocoaTouch *QCocoaTouch::findQCocoaTouch(NSTouch *nstouch) { - int identity = int([nstouch identity]); + qint64 identity = qint64([nstouch identity]); if (_currentTouches.contains(identity)) return _currentTouches.value(identity); return 0; diff --git a/src/gui/kernel/qmultitouch_mac_p.h b/src/gui/kernel/qmultitouch_mac_p.h index 3fa8f6c..618e9ca 100644 --- a/src/gui/kernel/qmultitouch_mac_p.h +++ b/src/gui/kernel/qmultitouch_mac_p.h @@ -74,7 +74,7 @@ class QCocoaTouch static void setMouseInDraggingState(bool inDraggingState); private: - static QHash _currentTouches; + static QHash _currentTouches; static QPointF _screenReferencePos; static QPointF _trackpadReferencePos; static int _idAssignmentCount; @@ -82,7 +82,7 @@ class QCocoaTouch static bool _updateInternalStateOnly; QTouchEvent::TouchPoint _touchPoint; - int _identity; + qint64 _identity; QCocoaTouch(NSTouch *nstouch); ~QCocoaTouch(); -- cgit v0.12 From 3384aea1357a0f2e7c633701f467d5f8b0855c50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 10 Jul 2009 16:42:08 +0200 Subject: Fixes broken item-lookup for untransformable items. Found during manual testing (manualtests/graphicsview/untransformable). At some point it was not possible to click on an untransformable item. The problem was that none of the untransformable items were top-levels, and none of the transformable top-level items were in the same area, resulting in an empty list of estimated top-level items. Auto-test included. --- .../graphicsview/qgraphicsscenebsptreeindex.cpp | 7 ++- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 51 ++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index a7b4828..a54ade9 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -387,8 +387,13 @@ QList QGraphicsSceneBspTreeIndexPrivate::estimateItems(const QR if (onlyTopLevelItems) { for (int i = 0; i < untransformableItems.size(); ++i) { QGraphicsItem *item = untransformableItems.at(i); - if (!item->d_ptr->parent) + if (!item->d_ptr->parent) { rectItems << item; + } else { + item = item->topLevelItem(); + if (!rectItems.contains(item)) + rectItems << item; + } } } else { rectItems += untransformableItems; diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 2dbd5f1..4e669ae 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -231,6 +231,7 @@ private slots: void sorting_data(); void sorting(); void itemHasNoContents(); + void hitTestUntransformableItem(); // task specific tests below me void task141694_textItemEnsureVisible(); @@ -7131,5 +7132,55 @@ void tst_QGraphicsItem::itemHasNoContents() QCOMPARE(_paintedItems, QList() << item2); } +void tst_QGraphicsItem::hitTestUntransformableItem() +{ + QGraphicsScene scene; + scene.setSceneRect(-100, -100, 200, 200); + + QGraphicsView view(&scene); + view.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&view); +#endif + QTest::qWait(100); + + // Confuse the BSP with dummy items. + QGraphicsRectItem *dummy = new QGraphicsRectItem(0, 0, 20, 20); + dummy->setPos(-100, -100); + scene.addItem(dummy); + for (int i = 0; i < 100; ++i) { + QGraphicsItem *parent = dummy; + dummy = new QGraphicsRectItem(0, 0, 20, 20); + dummy->setPos(-100 + i, -100 + i); + dummy->setParentItem(parent); + } + + QGraphicsRectItem *item1 = new QGraphicsRectItem(0, 0, 20, 20); + item1->setPos(-200, -200); + + QGraphicsRectItem *item2 = new QGraphicsRectItem(0, 0, 20, 20); + item2->setFlag(QGraphicsItem::ItemIgnoresTransformations); + item2->setParentItem(item1); + item2->setPos(200, 200); + + QGraphicsRectItem *item3 = new QGraphicsRectItem(0, 0, 20, 20); + item3->setParentItem(item2); + item3->setPos(80, 80); + + scene.addItem(item1); + QTest::qWait(100); + + QList items = scene.items(QPointF(80, 80)); + QCOMPARE(items.size(), 1); + QCOMPARE(items.at(0), static_cast(item3)); + + scene.setItemIndexMethod(QGraphicsScene::NoIndex); + QTest::qWait(100); + + items = scene.items(QPointF(80, 80)); + QCOMPARE(items.size(), 1); + QCOMPARE(items.at(0), static_cast(item3)); +} + QTEST_MAIN(tst_QGraphicsItem) #include "tst_qgraphicsitem.moc" -- cgit v0.12 From 4d31527417419d4f7c1417b9360ef91d72469aa0 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Fri, 10 Jul 2009 17:13:06 +0200 Subject: QListView: improve performance on QListView::selectedIndexes Task-number: 233342 --- src/gui/itemviews/qlistview.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp index 4652b91..6ff516a 100644 --- a/src/gui/itemviews/qlistview.cpp +++ b/src/gui/itemviews/qlistview.cpp @@ -1633,14 +1633,16 @@ QRegion QListView::visualRegionForSelection(const QItemSelection &selection) con QModelIndexList QListView::selectedIndexes() const { Q_D(const QListView); - QModelIndexList viewSelected; - QModelIndexList modelSelected; - if (d->selectionModel) - modelSelected = d->selectionModel->selectedIndexes(); - for (int i = 0; i < modelSelected.count(); ++i) { - QModelIndex index = modelSelected.at(i); + if (!d->selectionModel) + return QModelIndexList(); + + QModelIndexList viewSelected = d->selectionModel->selectedIndexes(); + for (int i = 0; i < viewSelected.count(); ++i) { + const QModelIndex &index = viewSelected.at(i); if (!isIndexHidden(index) && index.parent() == d->root && index.column() == d->column) - viewSelected.append(index); + ++i; + else + viewSelected.removeAt(i); } return viewSelected; } -- cgit v0.12 From 5425853ec6a9f29af3378c982f12a0cca4bcb0e0 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 10 Jul 2009 14:46:44 +0200 Subject: make tests independent of PATH contents use absolute paths for the tested executables --- tests/auto/linguist/lconvert/tst_lconvert.cpp | 9 +++++---- tests/auto/linguist/lrelease/tst_lrelease.cpp | 16 +++++++++++----- tests/auto/linguist/lupdate/testlupdate.cpp | 5 +++-- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/tests/auto/linguist/lconvert/tst_lconvert.cpp b/tests/auto/linguist/lconvert/tst_lconvert.cpp index 40be55a..3ad2925 100644 --- a/tests/auto/linguist/lconvert/tst_lconvert.cpp +++ b/tests/auto/linguist/lconvert/tst_lconvert.cpp @@ -47,7 +47,7 @@ class tst_lconvert : public QObject Q_OBJECT public: - tst_lconvert() : dataDir("data/") {} + tst_lconvert() : dataDir("data/"), binDir(QLibraryInfo::location(QLibraryInfo::BinariesPath)) {} private slots: void initTestCase(); @@ -73,6 +73,7 @@ private: const QList &args); QString dataDir; + QString binDir; }; void tst_lconvert::initTestCase() @@ -151,7 +152,7 @@ void tst_lconvert::doCompare(QIODevice *actualDev, const QString &expectedFn) void tst_lconvert::verifyReadFail(const QString &fn) { QProcess cvt; - cvt.start("lconvert", QStringList() << (dataDir + fn)); + cvt.start(binDir + "/lconvert", QStringList() << (dataDir + fn)); QVERIFY(cvt.waitForFinished(1000)); QVERIFY(cvt.exitStatus() == QProcess::NormalExit); QVERIFY2(cvt.exitCode() == 2, "Accepted invalid input"); @@ -178,7 +179,7 @@ void tst_lconvert::convertChain(const QString &_inFileName, const QString &_outF if (!argList.isEmpty()) args += argList[i]; args << "-if" << stations[i] << "-i" << "-" << "-of" << stations[i + 1]; - cvts.at(i)->start("lconvert", args); + cvts.at(i)->start(binDir + "/lconvert", args); } int st = 0; foreach (QProcess *cvt, cvts) @@ -242,7 +243,7 @@ void tst_lconvert::converts() QString outFileNameFq = dataDir + outFileName; QProcess cvt; - cvt.start("lconvert", QStringList() << "-i" << (dataDir + inFileName) << "-of" << format); + cvt.start(binDir + "/lconvert", QStringList() << "-i" << (dataDir + inFileName) << "-of" << format); doWait(&cvt, 0); if (QTest::currentTestFailed()) return; diff --git a/tests/auto/linguist/lrelease/tst_lrelease.cpp b/tests/auto/linguist/lrelease/tst_lrelease.cpp index 512987d..858e477 100644 --- a/tests/auto/linguist/lrelease/tst_lrelease.cpp +++ b/tests/auto/linguist/lrelease/tst_lrelease.cpp @@ -49,6 +49,10 @@ class tst_lrelease : public QObject { Q_OBJECT + +public: + tst_lrelease() : binDir(QLibraryInfo::location(QLibraryInfo::BinariesPath)) {} + private: private slots: @@ -59,6 +63,8 @@ private slots: private: void doCompare(const QStringList &actual, const QString &expectedFn); + + QString binDir; }; void tst_lrelease::doCompare(const QStringList &actual, const QString &expectedFn) @@ -111,7 +117,7 @@ void tst_lrelease::doCompare(const QStringList &actual, const QString &expectedF void tst_lrelease::translate() { - QVERIFY(!QProcess::execute("lrelease testdata/translate.ts")); + QVERIFY(!QProcess::execute(binDir + "/lrelease testdata/translate.ts")); QTranslator translator; QVERIFY(translator.load("testdata/translate.qm")); @@ -161,8 +167,8 @@ void tst_lrelease::translate() void tst_lrelease::mixedcodecs() { - QVERIFY(!QProcess::execute("lrelease testdata/mixedcodecs-ts11.ts")); - QVERIFY(!QProcess::execute("lrelease testdata/mixedcodecs-ts20.ts")); + QVERIFY(!QProcess::execute(binDir + "/lrelease testdata/mixedcodecs-ts11.ts")); + QVERIFY(!QProcess::execute(binDir + "/lrelease testdata/mixedcodecs-ts20.ts")); QVERIFY(!QProcess::execute("cmp testdata/mixedcodecs-ts11.qm testdata/mixedcodecs-ts20.qm")); QTranslator translator; QVERIFY(translator.load("testdata/mixedcodecs-ts11.qm")); @@ -176,7 +182,7 @@ void tst_lrelease::mixedcodecs() void tst_lrelease::compressed() { - QVERIFY(!QProcess::execute("lrelease -compress testdata/compressed.ts")); + QVERIFY(!QProcess::execute(binDir + "/lrelease -compress testdata/compressed.ts")); QTranslator translator; QVERIFY(translator.load("testdata/compressed.qm")); @@ -194,7 +200,7 @@ void tst_lrelease::compressed() void tst_lrelease::dupes() { QProcess proc; - proc.start("lrelease testdata/dupes.ts"); + proc.start(binDir + "/lrelease testdata/dupes.ts"); QVERIFY(proc.waitForFinished()); QVERIFY(proc.exitStatus() == QProcess::NormalExit); doCompare(QString(proc.readAllStandardError()).trimmed().remove('\r').split('\n'), "testdata/dupes.errors"); diff --git a/tests/auto/linguist/lupdate/testlupdate.cpp b/tests/auto/linguist/lupdate/testlupdate.cpp index 8abc2b0..04c03f1 100644 --- a/tests/auto/linguist/lupdate/testlupdate.cpp +++ b/tests/auto/linguist/lupdate/testlupdate.cpp @@ -56,8 +56,9 @@ TestLUpdate::TestLUpdate() { childProc = 0; - m_cmdLupdate = QLatin1String("lupdate"); - m_cmdQMake = QLatin1String("qmake"); + QString binPath = QLibraryInfo::location(QLibraryInfo::BinariesPath); + m_cmdLupdate = binPath + QLatin1String("/lupdate"); + m_cmdQMake = binPath + QLatin1String("/qmake"); } TestLUpdate::~TestLUpdate() -- cgit v0.12 From 593f8a322895dc011d88fbe112987f2189d43724 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 10 Jul 2009 18:05:30 +0200 Subject: rewrite makeplurals.sh in perl ... so it works under windows as well. --- tests/auto/linguist/lconvert/data/makeplurals.pl | 42 +++++++++++++++++++++++ tests/auto/linguist/lconvert/data/makeplurals.sh | 43 ------------------------ tests/auto/linguist/lconvert/tst_lconvert.cpp | 2 +- 3 files changed, 43 insertions(+), 44 deletions(-) create mode 100755 tests/auto/linguist/lconvert/data/makeplurals.pl delete mode 100755 tests/auto/linguist/lconvert/data/makeplurals.sh diff --git a/tests/auto/linguist/lconvert/data/makeplurals.pl b/tests/auto/linguist/lconvert/data/makeplurals.pl new file mode 100755 index 0000000..19bffe0 --- /dev/null +++ b/tests/auto/linguist/lconvert/data/makeplurals.pl @@ -0,0 +1,42 @@ +#! /usr/bin/env perl + +sub makeit2($$$) +{ + for (my $i = 0; $i < (1 << $_[0]); $i++) { + print OUTFILE "\n"; + print OUTFILE "$_[2]\n" unless $3 eq ""; + print OUTFILE "msgid \"singular $_[1] $i\"\n"; + print OUTFILE "msgid_plural \"plural $_[1] $i\"\n"; + for (my $j = 0; $j < $_[0]; $j++) { + my $tr; + if (($i & (1 << $j)) == 0) { + $tr = "translated $_[1] $i $j"; + } + print OUTFILE "msgstr[$j] \"$tr\"\n"; + } + } +} + +sub makeit($$) +{ + open OUTFILE, ">${OUTDIR}plural-$_[0].po" || die "cannot write file in $OUTDIR"; + print OUTFILE < ${OUTDIR}plural-$1.po -} - -OUTDIR=$1 -makeit 1 zh_CN -makeit 2 de_DE -makeit 3 pl_PL diff --git a/tests/auto/linguist/lconvert/tst_lconvert.cpp b/tests/auto/linguist/lconvert/tst_lconvert.cpp index 3ad2925..1ed71ab 100644 --- a/tests/auto/linguist/lconvert/tst_lconvert.cpp +++ b/tests/auto/linguist/lconvert/tst_lconvert.cpp @@ -79,7 +79,7 @@ private: void tst_lconvert::initTestCase() { if (!QFile::exists(QLatin1String("data/plural-1.po"))) - QProcess::execute(QLatin1String("data/makeplurals.sh"), QStringList() << QLatin1String("data/")); + QProcess::execute(QLatin1String("perl"), QStringList() << QLatin1String("data/makeplurals.pl") << QLatin1String("data/")); QVERIFY(QFile::exists(QLatin1String("data/plural-1.po"))); } -- cgit v0.12 From 435fae071798817f57bc89bf5d1ac20aae488625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 10 Jul 2009 18:14:48 +0200 Subject: QGraphicsItem not updated properly when moving parent. Found during manual testing (manualtests/graphicsview/movableitems). Moving a child item (via its parent) outside the viewport, and then back again didn't trigger an update on the child. Reason was that we had a cut-off checking the wrong bit (geometryChanged). This bit means exactly the same as the paintedViewBoundingRectsNeedRepaint bit, except that it doesn't propagate to the children (and that's the bug). We use paintedViewBoundingRectsNeedRepaint instead. Auto-test included. --- src/gui/graphicsview/qgraphicsitem.cpp | 1 + src/gui/graphicsview/qgraphicsscene.cpp | 4 ++-- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 33 +++++++++++++++++++++++--- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 0cfaab7..b7385d4 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1822,6 +1822,7 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo q_ptr->setSelected(false); } else { geometryChanged = 1; + paintedViewBoundingRectsNeedRepaint = 1; if (isWidget && scene) { QGraphicsWidget *widget = static_cast(q_ptr); if (widget->windowType() == Qt::Popup) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index c7c0865..aa7fa4c 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4568,7 +4568,7 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool if (!item->d_ptr->dirty) continue; - if (!item->d_ptr->geometryChanged + if (!item->d_ptr->paintedViewBoundingRectsNeedRepaint && paintedViewBoundingRect.x() == -1 && paintedViewBoundingRect.y() == -1 && paintedViewBoundingRect.width() == -1 && paintedViewBoundingRect.height() == -1) { continue; // Outside viewport. @@ -4587,7 +4587,7 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool continue; // Discard updates outside the bounding rect. if (!updateHelper(viewPrivate, item->d_ptr, dirtyRect, itemIsUntransformable) - && item->d_ptr->geometryChanged) { + && item->d_ptr->paintedViewBoundingRectsNeedRepaint) { paintedViewBoundingRect = QRect(-1, -1, -1, -1); // Outside viewport. } } diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 4e669ae..4ca1b48 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -6614,9 +6614,9 @@ void tst_QGraphicsItem::update() qApp->processEvents(); QCOMPARE(item->repaints, 1); QCOMPARE(view.repaints, 1); - const QRect itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform()) - .mapRect(item->boundingRect()).toRect(); - const QRegion expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2); + QRect itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform()) + .mapRect(item->boundingRect()).toRect(); + QRegion expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2); // The entire item's bounding rect (adjusted for antialiasing) should have been painted. QCOMPARE(view.paintedRegion, expectedRegion); @@ -6684,6 +6684,33 @@ void tst_QGraphicsItem::update() QCOMPARE(item->repaints, 1); QCOMPARE(view.repaints, 1); QCOMPARE(view.paintedRegion, expectedRegion + expectedRegion.translated(50, 50)); + + // Make sure moving a parent item triggers an update on the children + // (even though the parent itself is outside the viewport). + QGraphicsRectItem *parent = new QGraphicsRectItem(0, 0, 10, 10); + parent->setPos(-400, 0); + item->setParentItem(parent); + item->setPos(400, 0); + scene.addItem(parent); + QTest::qWait(50); + itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform()) + .mapRect(item->boundingRect()).toRect(); + expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2); + view.reset(); + item->repaints = 0; + parent->translate(-400, 0); + qApp->processEvents(); + QCOMPARE(item->repaints, 0); + QCOMPARE(view.repaints, 1); + QCOMPARE(view.paintedRegion, expectedRegion); + view.reset(); + item->repaints = 0; + parent->translate(400, 0); + qApp->processEvents(); + QCOMPARE(item->repaints, 1); + QCOMPARE(view.repaints, 1); + QCOMPARE(view.paintedRegion, expectedRegion); + QCOMPARE(view.paintedRegion, expectedRegion); } void tst_QGraphicsItem::setTransformProperties_data() -- cgit v0.12 From baacf493e1c968ee2ffa59a8b87754388cb7a61a Mon Sep 17 00:00:00 2001 From: Pierre Rossi Date: Fri, 10 Jul 2009 19:15:25 +0200 Subject: Fixed a crash with input methods The inputContext's focusWidget was not reset when disabling input methods. Thanks to Benjamin P. Task-number: 257832 Reviewed-by: Denis --- src/gui/kernel/qapplication.cpp | 2 +- src/gui/kernel/qwidget.cpp | 7 ++----- tests/auto/qwidget/tst_qwidget.cpp | 15 +++++++++++++++ 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index c6af728..114ebb2 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -126,7 +126,7 @@ int QApplicationPrivate::app_compile_version = 0x040000; //we don't know exactly QApplication::Type qt_appType=QApplication::Tty; QApplicationPrivate *QApplicationPrivate::self = 0; -QInputContext *QApplicationPrivate::inputContext; +QInputContext *QApplicationPrivate::inputContext = 0; bool QApplicationPrivate::quitOnLastWindowClosed = true; diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 9d40b00..fb9084e 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -9879,11 +9879,8 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) QInputContextPrivate::updateImeStatus(this, true); #endif QInputContext *ic = d->ic; - if (!ic) { - // implicitly create input context only if we have a focus - if (hasFocus()) - ic = d->inputContext(); - } + if (!ic && (!on || hasFocus())) + ic = d->inputContext(); if (ic) { if (on && hasFocus() && ic->focusWidget() != this) { ic->setFocusWidget(this); diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp index 7b68732..1db6eb2 100644 --- a/tests/auto/qwidget/tst_qwidget.cpp +++ b/tests/auto/qwidget/tst_qwidget.cpp @@ -350,6 +350,7 @@ private slots: #endif void updateOnDestroyedSignal(); void toplevelLineEditFocus(); + void inputFocus_task257832(); private: bool ensureScreenSize(int width, int height); @@ -8965,5 +8966,19 @@ void tst_QWidget::toplevelLineEditFocus() QCOMPARE(QApplication::focusWidget(), &w); } +void tst_QWidget::inputFocus_task257832() +{ + QLineEdit *widget = new QLineEdit; + QInputContext *context = widget->inputContext(); + if (!context) + QSKIP("No input context", SkipSingle); + widget->setFocus(); + context->setFocusWidget(widget); + QCOMPARE(context->focusWidget(), widget); + widget->setReadOnly(true); + QVERIFY(!context->focusWidget()); + delete widget; +} + QTEST_MAIN(tst_QWidget) #include "tst_qwidget.moc" -- cgit v0.12 From 357d4598512b4b42fc515b4fc0d2d419db604544 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 11 May 2009 17:35:20 +0200 Subject: remove dead code cherry-picked d8b1cc5f0ecbb8de734d241d72a05b325c2bbb2c from creator --- tools/linguist/shared/profileevaluator.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/tools/linguist/shared/profileevaluator.cpp b/tools/linguist/shared/profileevaluator.cpp index 8605733..c68ac46 100644 --- a/tools/linguist/shared/profileevaluator.cpp +++ b/tools/linguist/shared/profileevaluator.cpp @@ -1511,16 +1511,6 @@ bool ProFileEvaluator::Private::evaluateFile(const QString &fileName, bool *resu if (result) *result = false; } -/* if (ok && readFeatures) { - QStringList configs = values("CONFIG"); - QSet processed; - foreach (const QString &fn, configs) { - if (!processed.contains(fn)) { - processed.insert(fn); - evaluateFeatureFile(fn, 0); - } - } - } */ return ok; } -- cgit v0.12 From b7cfdc075ce53a5aaf243161c849ee1ee079885c Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 12 May 2009 15:02:32 +0200 Subject: remove totally pointless conditional cherry-picked 167a09b20614d282ec898f69fc2a3f0bafa11229 from creator --- tools/linguist/shared/profileevaluator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/linguist/shared/profileevaluator.cpp b/tools/linguist/shared/profileevaluator.cpp index c68ac46..c56f1d4 100644 --- a/tools/linguist/shared/profileevaluator.cpp +++ b/tools/linguist/shared/profileevaluator.cpp @@ -1501,7 +1501,7 @@ bool ProFileEvaluator::Private::evaluateFile(const QString &fileName, bool *resu ProFile *pro = q->parsedProFile(fileName); if (pro) { m_profileStack.push(pro); - ok = (currentProFile() ? pro->Accept(this) : false); + ok = pro->Accept(this); m_profileStack.pop(); q->releaseParsedProFile(pro); -- cgit v0.12 From 3f9a894acb30ff3fb5907f82327af088f96a088d Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 4 Jun 2009 15:18:14 +0200 Subject: Fix memory leak in $$system() calls from .pro files cherry-picked 07730341bd739aac823ac9b4336d8294510a35e2 from creator --- tools/linguist/shared/profileevaluator.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/linguist/shared/profileevaluator.cpp b/tools/linguist/shared/profileevaluator.cpp index c56f1d4..4ea9c10 100644 --- a/tools/linguist/shared/profileevaluator.cpp +++ b/tools/linguist/shared/profileevaluator.cpp @@ -58,8 +58,10 @@ #ifdef Q_OS_WIN32 #define QT_POPEN _popen +#define QT_PCLOSE _pclose #else #define QT_POPEN popen +#define QT_PCLOSE pclose #endif QT_BEGIN_NAMESPACE @@ -1204,6 +1206,8 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun output += QLatin1String(buff); } ret += split_value_list(output); + if (proc) + QT_PCLOSE(proc); } } break; } -- cgit v0.12 From a701175aef8912b69afe61d23749dcfca765a231 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Sat, 11 Jul 2009 16:56:28 +0200 Subject: ItemViews: make dragging faster when lots of items are selected QListView know exactly what they have on their viewport and we only paint items clipped to the viewport. So we don't need to ask for each item its visualRect. NB: QTreeView and QTableView probably deservee the same treatment --- src/gui/itemviews/qabstractitemview.cpp | 33 ++++++++++++++++++++++----------- src/gui/itemviews/qabstractitemview_p.h | 5 +++++ src/gui/itemviews/qlistview.cpp | 26 ++++++++++++++++++++++++++ src/gui/itemviews/qlistview_p.h | 2 ++ 4 files changed, 55 insertions(+), 11 deletions(-) diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index 5f347dd..a4a69c3 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -3881,34 +3881,45 @@ bool QAbstractItemViewPrivate::openEditor(const QModelIndex &index, QEvent *even return true; } -QPixmap QAbstractItemViewPrivate::renderToPixmap(const QModelIndexList &indexes, QRect *r) const +/* + \internal + + returns the pair QRect/QModelIndex that should be painted on the viewports's rect + */ + +QItemViewPaintPairs QAbstractItemViewPrivate::draggablePaintPairs(const QModelIndexList &indexes, QRect *r) const { Q_ASSERT(r); Q_Q(const QAbstractItemView); QRect &rect = *r; const QRect viewportRect = viewport->rect(); - QList rects; - QModelIndexList paintedIndexes; + QItemViewPaintPairs ret; for (int i = 0; i < indexes.count(); ++i) { const QModelIndex &index = indexes.at(i); const QRect current = q->visualRect(index); if (current.intersects(viewportRect)) { - paintedIndexes += index; - rects += current; + ret += qMakePair(current, index); rect |= current; } } - rect = rect.intersected(viewportRect); - if (rect.isEmpty()) + rect &= viewportRect; + return ret; +} + +QPixmap QAbstractItemViewPrivate::renderToPixmap(const QModelIndexList &indexes, QRect *r) const +{ + Q_ASSERT(r); + QItemViewPaintPairs paintPairs = draggablePaintPairs(indexes, r); + if (paintPairs.isEmpty()) return QPixmap(); - QPixmap pixmap(rect.size()); + QPixmap pixmap(r->size()); pixmap.fill(Qt::transparent); QPainter painter(&pixmap); QStyleOptionViewItemV4 option = viewOptionsV4(); option.state |= QStyle::State_Selected; - for (int j = 0; j < paintedIndexes.count(); ++j) { - const QModelIndex ¤t = paintedIndexes.at(j); - option.rect = QRect(rects.at(j).topLeft() - rect.topLeft(), rects.at(j).size()); + for (int j = 0; j < paintPairs.count(); ++j) { + option.rect = paintPairs.at(j).first.translated(r->topLeft()); + const QModelIndex ¤t = paintPairs.at(j).second; delegateForIndex(current)->paint(&painter, option, current); } return pixmap; diff --git a/src/gui/itemviews/qabstractitemview_p.h b/src/gui/itemviews/qabstractitemview_p.h index 7443d50..557e98b 100644 --- a/src/gui/itemviews/qabstractitemview_p.h +++ b/src/gui/itemviews/qabstractitemview_p.h @@ -86,6 +86,9 @@ struct QEditorInfo }; +typedef QPair QItemViewPaintPair; +typedef QList QItemViewPaintPairs; + class QEmptyModel : public QAbstractItemModel { public: @@ -176,7 +179,9 @@ public: q_func()->style()->drawPrimitive(QStyle::PE_IndicatorItemViewItemDrop, &opt, painter, q_func()); } } + #endif + virtual QItemViewPaintPairs draggablePaintPairs(const QModelIndexList &indexes, QRect *r) const; inline void releaseEditor(QWidget *editor) const { if (editor) { diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp index 6ff516a..44bcf6f 100644 --- a/src/gui/itemviews/qlistview.cpp +++ b/src/gui/itemviews/qlistview.cpp @@ -709,6 +709,32 @@ void QListViewPrivate::selectAll(QItemSelectionModel::SelectionFlags command) selectionModel->select(selection, command); } +/*! + \reimp + + We have a QListView way of knowing what elements are on the viewport + through the intersectingSet function +*/ +QItemViewPaintPairs QListViewPrivate::draggablePaintPairs(const QModelIndexList &indexes, QRect *r) const +{ + Q_ASSERT(r); + Q_Q(const QListView); + QRect &rect = *r; + const QRect viewportRect = viewport->rect(); + QItemViewPaintPairs ret; + intersectingSet(viewportRect); + const QSet visibleIndexes = intersectVector.toList().toSet(); + for (int i = 0; i < indexes.count(); ++i) { + const QModelIndex &index = indexes.at(i); + if (visibleIndexes.contains(index)) { + const QRect current = q->visualRect(index); + ret += qMakePair(current, index); + rect |= current; + } + } + rect &= viewportRect; + return ret; +} /*! \internal diff --git a/src/gui/itemviews/qlistview_p.h b/src/gui/itemviews/qlistview_p.h index a7a7000..16f2de9 100644 --- a/src/gui/itemviews/qlistview_p.h +++ b/src/gui/itemviews/qlistview_p.h @@ -351,6 +351,8 @@ public: void scrollElasticBandBy(int dx, int dy); + QItemViewPaintPairs draggablePaintPairs(const QModelIndexList &indexes, QRect *r) const; + // ### FIXME: we only need one at a time QDynamicListViewBase *dynamicListView; QStaticListViewBase *staticListView; -- cgit v0.12 From 69a3c65d177a4a6ecc3d3fd63455dcd53d62b75f Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Sat, 11 Jul 2009 15:49:51 +0200 Subject: build fix on windows --- src/gui/graphicsview/qgraphicsview_p.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h index 28b4bdc..0fa8b34 100644 --- a/src/gui/graphicsview/qgraphicsview_p.h +++ b/src/gui/graphicsview/qgraphicsview_p.h @@ -59,6 +59,7 @@ #include #include "qgraphicssceneevent.h" +#include #include QT_BEGIN_NAMESPACE -- cgit v0.12 From cbf18d5b24e9ae541bc7e6a7b6698666cce30478 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Sat, 11 Jul 2009 16:20:40 +0200 Subject: ItemViews selection: improve performance of QItemSelection::indexes On windows it makes it 2x faster --- src/gui/itemviews/qitemselectionmodel.cpp | 35 ++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/src/gui/itemviews/qitemselectionmodel.cpp b/src/gui/itemviews/qitemselectionmodel.cpp index e4cb0f0..87825d9 100644 --- a/src/gui/itemviews/qitemselectionmodel.cpp +++ b/src/gui/itemviews/qitemselectionmodel.cpp @@ -270,24 +270,35 @@ QItemSelectionRange QItemSelectionRange::intersect(const QItemSelectionRange &ot */ -/*! - Returns the list of model index items stored in the selection. -*/ +/* + \internal -QModelIndexList QItemSelectionRange::indexes() const + utility function for getting the indexes from a range + it avoid concatenating list and works on one + */ + +static void indexesFromRange(const QItemSelectionRange &range, QModelIndexList &result) { - QModelIndex index; - QModelIndexList result; - if (isValid() && model()) { - for (int column = left(); column <= right(); ++column) { - for (int row = top(); row <= bottom(); ++row) { - index = model()->index(row, column, parent()); - Qt::ItemFlags flags = model()->flags(index); + if (range.isValid() && range.model()) { + for (int column = range.left(); column <= range.right(); ++column) { + for (int row = range.top(); row <= range.bottom(); ++row) { + QModelIndex index = range.model()->index(row, column, range.parent()); + Qt::ItemFlags flags = range.model()->flags(index); if ((flags & Qt::ItemIsSelectable) && (flags & Qt::ItemIsEnabled)) result.append(index); } } } +} + +/*! + Returns the list of model index items stored in the selection. +*/ + +QModelIndexList QItemSelectionRange::indexes() const +{ + QModelIndexList result; + indexesFromRange(*this, result); return result; } @@ -404,7 +415,7 @@ QModelIndexList QItemSelection::indexes() const QModelIndexList result; QList::const_iterator it = begin(); for (; it != end(); ++it) - result += (*it).indexes(); + indexesFromRange(*it, result); return result; } -- cgit v0.12 From e84e16954e9b96479964368e2dcb3114dd2bd5f1 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Sat, 11 Jul 2009 18:01:49 +0200 Subject: QListView: small refactoring It is useless to store the vector of modelindex from intersectingSet --- src/gui/itemviews/qlistview.cpp | 106 ++++++++++++++++++++-------------------- src/gui/itemviews/qlistview_p.h | 22 +++------ 2 files changed, 61 insertions(+), 67 deletions(-) diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp index 44bcf6f..9a94b31 100644 --- a/src/gui/itemviews/qlistview.cpp +++ b/src/gui/itemviews/qlistview.cpp @@ -723,7 +723,7 @@ QItemViewPaintPairs QListViewPrivate::draggablePaintPairs(const QModelIndexList const QRect viewportRect = viewport->rect(); QItemViewPaintPairs ret; intersectingSet(viewportRect); - const QSet visibleIndexes = intersectVector.toList().toSet(); + const QSet visibleIndexes = intersectingSet(viewportRect).toList().toSet(); for (int i = 0; i < indexes.count(); ++i) { const QModelIndex &index = indexes.at(i); if (visibleIndexes.contains(index)) { @@ -951,9 +951,9 @@ void QListView::dragMoveEvent(QDragMoveEvent *e) QModelIndex index; if (d->movement == Snap) { QRect rect(d->dynamicListView->snapToGrid(e->pos() + d->offset()), d->gridSize()); - d->intersectingSet(rect); - index = d->intersectVector.count() > 0 - ? d->intersectVector.last() : QModelIndex(); + const QVector intersectVector = d->intersectingSet(rect); + index = intersectVector.count() > 0 + ? intersectVector.last() : QModelIndex(); } else { index = indexAt(e->pos()); } @@ -1126,10 +1126,8 @@ void QListView::paintEvent(QPaintEvent *e) return; QStyleOptionViewItemV4 option = d->viewOptionsV4(); QPainter painter(d->viewport); - QRect area = e->rect(); - d->intersectingSet(e->rect().translated(horizontalOffset(), verticalOffset()), false); - const QVector toBeRendered = d->intersectVector; + const QVector toBeRendered = d->intersectingSet(e->rect().translated(horizontalOffset(), verticalOffset()), false); const QModelIndex current = currentIndex(); const QModelIndex hover = d->hover; @@ -1251,9 +1249,9 @@ QModelIndex QListView::indexAt(const QPoint &p) const { Q_D(const QListView); QRect rect(p.x() + horizontalOffset(), p.y() + verticalOffset(), 1, 1); - d->intersectingSet(rect); - QModelIndex index = d->intersectVector.count() > 0 - ? d->intersectVector.last() : QModelIndex(); + const QVector intersectVector = d->intersectingSet(rect); + QModelIndex index = intersectVector.count() > 0 + ? intersectVector.last() : QModelIndex(); if (index.isValid() && visualRect(index).contains(p)) return index; return QModelIndex(); @@ -1351,38 +1349,38 @@ QModelIndex QListView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie if (d->gridSize().isValid()) rect.setSize(d->gridSize()); QSize contents = d->contentsSize(); - d->intersectVector.clear(); + QVector intersectVector; switch (cursorAction) { case MoveLeft: - while (d->intersectVector.isEmpty()) { + while (intersectVector.isEmpty()) { rect.translate(-rect.width(), 0); if (rect.right() <= 0) return current; if (rect.left() < 0) rect.setLeft(0); - d->intersectingSet(rect); - d->removeCurrentAndDisabled(&d->intersectVector, current); + intersectVector = d->intersectingSet(rect); + d->removeCurrentAndDisabled(&intersectVector, current); } - return d->closestIndex(initialRect, d->intersectVector); + return d->closestIndex(initialRect, intersectVector); case MoveRight: - while (d->intersectVector.isEmpty()) { + while (intersectVector.isEmpty()) { rect.translate(rect.width(), 0); if (rect.left() >= contents.width()) return current; if (rect.right() > contents.width()) rect.setRight(contents.width()); - d->intersectingSet(rect); - d->removeCurrentAndDisabled(&d->intersectVector, current); + intersectVector = d->intersectingSet(rect); + d->removeCurrentAndDisabled(&intersectVector, current); } - return d->closestIndex(initialRect, d->intersectVector); + return d->closestIndex(initialRect, intersectVector); case MovePageUp: rect.moveTop(rect.top() - d->viewport->height()); if (rect.top() < rect.height()) rect.moveTop(rect.height()); case MovePrevious: case MoveUp: - while (d->intersectVector.isEmpty()) { + while (intersectVector.isEmpty()) { rect.translate(0, -rect.height()); if (rect.bottom() <= 0) { #ifdef QT_KEYPAD_NAVIGATION @@ -1398,17 +1396,17 @@ QModelIndex QListView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie } if (rect.top() < 0) rect.setTop(0); - d->intersectingSet(rect); - d->removeCurrentAndDisabled(&d->intersectVector, current); + intersectVector = d->intersectingSet(rect); + d->removeCurrentAndDisabled(&intersectVector, current); } - return d->closestIndex(initialRect, d->intersectVector); + return d->closestIndex(initialRect, intersectVector); case MovePageDown: rect.moveTop(rect.top() + d->viewport->height()); if (rect.bottom() > contents.height() - rect.height()) rect.moveBottom(contents.height() - rect.height()); case MoveNext: case MoveDown: - while (d->intersectVector.isEmpty()) { + while (intersectVector.isEmpty()) { rect.translate(0, rect.height()); if (rect.top() >= contents.height()) { #ifdef QT_KEYPAD_NAVIGATION @@ -1425,10 +1423,10 @@ QModelIndex QListView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie } if (rect.bottom() > contents.height()) rect.setBottom(contents.height()); - d->intersectingSet(rect); - d->removeCurrentAndDisabled(&d->intersectVector, current); + intersectVector = d->intersectingSet(rect); + d->removeCurrentAndDisabled(&intersectVector, current); } - return d->closestIndex(initialRect, d->intersectVector); + return d->closestIndex(initialRect, intersectVector); case MoveHome: return d->model->index(0, d->column, d->root); case MoveEnd: @@ -1503,10 +1501,10 @@ void QListView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFl QItemSelection selection; if (rect.width() == 1 && rect.height() == 1) { - d->intersectingSet(rect.translated(horizontalOffset(), verticalOffset())); + const QVector intersectVector = d->intersectingSet(rect.translated(horizontalOffset(), verticalOffset())); QModelIndex tl; - if (!d->intersectVector.isEmpty()) - tl = d->intersectVector.last(); // special case for mouse press; only select the top item + if (!intersectVector.isEmpty()) + tl = intersectVector.last(); // special case for mouse press; only select the top item if (tl.isValid() && d->isIndexEnabled(tl)) selection.select(tl, tl); } else { @@ -1516,14 +1514,14 @@ void QListView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFl QModelIndex tl, br; // get the first item const QRect topLeft(rect.left() + horizontalOffset(), rect.top() + verticalOffset(), 1, 1); - d->intersectingSet(topLeft); - if (!d->intersectVector.isEmpty()) - tl = d->intersectVector.last(); + QVector intersectVector = d->intersectingSet(topLeft); + if (!intersectVector.isEmpty()) + tl = intersectVector.last(); // get the last item const QRect bottomRight(rect.right() + horizontalOffset(), rect.bottom() + verticalOffset(), 1, 1); - d->intersectingSet(bottomRight); - if (!d->intersectVector.isEmpty()) - br = d->intersectVector.last(); + intersectVector = d->intersectingSet(bottomRight); + if (!intersectVector.isEmpty()) + br = intersectVector.last(); // get the ranges if (tl.isValid() && br.isValid() @@ -2144,8 +2142,8 @@ QItemSelection QListViewPrivate::selection(const QRect &rect) const { QItemSelection selection; QModelIndex tl, br; - intersectingSet(rect); - QVector::iterator it = intersectVector.begin(); + const QVector intersectVector = intersectingSet(rect); + QVector::const_iterator it = intersectVector.begin(); for (; it != intersectVector.end(); ++it) { if (!tl.isValid() && !br.isValid()) { tl = br = *it; @@ -2436,9 +2434,9 @@ void QStaticListViewBase::doStaticLayout(const QListViewLayoutInfo &info) Finds the set of items intersecting with \a area. In this function, itemsize is counted from topleft to the start of the next item. */ -void QStaticListViewBase::intersectingStaticSet(const QRect &area) const +QVector QStaticListViewBase::intersectingStaticSet(const QRect &area) const { - clearIntersections(); + QVector ret; int segStartPosition; int segEndPosition; int flowStartPosition; @@ -2455,7 +2453,7 @@ void QStaticListViewBase::intersectingStaticSet(const QRect &area) const flowEndPosition = area.bottom(); } if (segmentPositions.count() < 2 || flowPositions.isEmpty()) - return; + return ret; // the last segment position is actually the edge of the last segment const int segLast = segmentPositions.count() - 2; int seg = qBinarySearch(segmentPositions, segStartPosition, 0, segLast + 1); @@ -2470,13 +2468,14 @@ void QStaticListViewBase::intersectingStaticSet(const QRect &area) const continue; QModelIndex index = modelIndex(row); if (index.isValid()) - appendToIntersections(index); + ret += index; #if 0 // for debugging else qWarning("intersectingStaticSet: row %d was invalid", row); #endif } } + return ret; } int QStaticListViewBase::itemIndex(const QListViewItem &item) const @@ -2797,12 +2796,15 @@ void QDynamicListViewBase::doDynamicLayout(const QListViewLayoutInfo &info) viewport()->update(); } -void QDynamicListViewBase::intersectingDynamicSet(const QRect &area) const +QVector QDynamicListViewBase::intersectingDynamicSet(const QRect &area) const { - clearIntersections(); - QListViewPrivate *that = const_cast(dd); + QDynamicListViewBase *that = const_cast(this); QBspTree::Data data(static_cast(that)); - that->dynamicListView->tree.climbTree(area, &QDynamicListViewBase::addLeaf, data); + QVector res; + that->interSectingVector = &res; + that->tree.climbTree(area, &QDynamicListViewBase::addLeaf, data); + that->interSectingVector = 0; + return res; } void QDynamicListViewBase::createItems(int to) @@ -2879,20 +2881,20 @@ int QDynamicListViewBase::itemIndex(const QListViewItem &item) const } void QDynamicListViewBase::addLeaf(QVector &leaf, const QRect &area, - uint visited, QBspTree::Data data) + uint visited, QBspTree::Data data) { QListViewItem *vi; - QListViewPrivate *_this = static_cast(data.ptr); + QDynamicListViewBase *_this = static_cast(data.ptr); for (int i = 0; i < leaf.count(); ++i) { int idx = leaf.at(i); - if (idx < 0 || idx >= _this->dynamicListView->items.count()) + if (idx < 0 || idx >= _this->items.count()) continue; - vi = &_this->dynamicListView->items[idx]; + vi = &_this->items[idx]; Q_ASSERT(vi); if (vi->isValid() && vi->rect().intersects(area) && vi->visited != visited) { - QModelIndex index = _this->listViewItemToIndex(*vi); + QModelIndex index = _this->dd->listViewItemToIndex(*vi); Q_ASSERT(index.isValid()); - _this->intersectVector.append(index); + _this->interSectingVector->append(index); vi->visited = visited; } } diff --git a/src/gui/itemviews/qlistview_p.h b/src/gui/itemviews/qlistview_p.h index 16f2de9..1727ba4 100644 --- a/src/gui/itemviews/qlistview_p.h +++ b/src/gui/itemviews/qlistview_p.h @@ -153,9 +153,6 @@ public: inline bool isHidden(int row) const; inline int hiddenCount() const; - inline void clearIntersections() const; - inline void appendToIntersections(const QModelIndex &idx) const; - inline bool isRightToLeft() const; QListViewPrivate *dd; @@ -186,7 +183,7 @@ public: QPoint initStaticLayout(const QListViewLayoutInfo &info); void doStaticLayout(const QListViewLayoutInfo &info); - void intersectingStaticSet(const QRect &area) const; + QVector intersectingStaticSet(const QRect &area) const; int itemIndex(const QListViewItem &item) const; @@ -216,7 +213,7 @@ class QDynamicListViewBase : public QCommonListViewBase friend class QListViewPrivate; public: QDynamicListViewBase(QListView *q, QListViewPrivate *d) : QCommonListViewBase(q, d), - batchStartRow(0), batchSavedDeltaSeg(0) {} + batchStartRow(0), batchSavedDeltaSeg(0), interSectingVector(0) {} QBspTree tree; QVector items; @@ -230,6 +227,7 @@ public: // used when laying out in batches int batchStartRow; int batchSavedDeltaSeg; + QVector *interSectingVector; //used from within intersectingDynamicSet void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); bool doBatchedItemLayout(const QListViewLayoutInfo &info, int max); @@ -237,7 +235,7 @@ public: void initBspTree(const QSize &contents); QPoint initDynamicLayout(const QListViewLayoutInfo &info); void doDynamicLayout(const QListViewLayoutInfo &info); - void intersectingDynamicSet(const QRect &area) const; + QVector intersectingDynamicSet(const QRect &area) const; static void addLeaf(QVector &leaf, const QRect &area, uint visited, QBspTree::Data data); @@ -277,11 +275,11 @@ public: bool doItemsLayout(int num); - inline void intersectingSet(const QRect &area, bool doLayout = true) const { + inline QVector intersectingSet(const QRect &area, bool doLayout = true) const { if (doLayout) executePostedLayout(); QRect a = (q_func()->isRightToLeft() ? flipX(area.normalized()) : area.normalized()); - if (viewMode == QListView::ListMode) staticListView->intersectingStaticSet(a); - else dynamicListView->intersectingDynamicSet(a); + return (viewMode == QListView::ListMode) ? staticListView->intersectingStaticSet(a) + : dynamicListView->intersectingDynamicSet(a); } // ### FIXME: @@ -385,9 +383,6 @@ public: QRect layoutBounds; - // used for intersecting set - mutable QVector intersectVector; - // timers QBasicTimer batchLayoutTimer; @@ -440,9 +435,6 @@ inline QAbstractItemDelegate *QCommonListViewBase::delegate(const QModelIndex &i inline bool QCommonListViewBase::isHidden(int row) const { return dd->isHidden(row); } inline int QCommonListViewBase::hiddenCount() const { return dd->hiddenRows.count(); } -inline void QCommonListViewBase::clearIntersections() const { dd->intersectVector.clear(); } -inline void QCommonListViewBase::appendToIntersections(const QModelIndex &idx) const { dd->intersectVector.append(idx); } - inline bool QCommonListViewBase::isRightToLeft() const { return qq->isRightToLeft(); } QT_END_NAMESPACE -- cgit v0.12 From 6fbd79e45330044b059aa55873eaf2b73bdc49b2 Mon Sep 17 00:00:00 2001 From: Bill King Date: Mon, 13 Jul 2009 08:14:02 +1000 Subject: Fixes merge mixup. --- src/sql/drivers/ibase/qsql_ibase.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sql/drivers/ibase/qsql_ibase.cpp b/src/sql/drivers/ibase/qsql_ibase.cpp index c7409e1..0c4fff0 100644 --- a/src/sql/drivers/ibase/qsql_ibase.cpp +++ b/src/sql/drivers/ibase/qsql_ibase.cpp @@ -1621,7 +1621,7 @@ QSqlRecord QIBaseDriver::record(const QString& tablename) const "b.RDB$FIELD_SCALE, b.RDB$FIELD_PRECISION, a.RDB$NULL_FLAG " "FROM RDB$RELATION_FIELDS a, RDB$FIELDS b " "WHERE b.RDB$FIELD_NAME = a.RDB$FIELD_SOURCE " - "AND UPPER(a.RDB$RELATION_NAME) = '") + table.toUpper() + QLatin1String("' " + "AND a.RDB$RELATION_NAME = '") + table + QLatin1String("' " "ORDER BY a.RDB$FIELD_POSITION")); while (q.next()) { @@ -1660,7 +1660,7 @@ QSqlIndex QIBaseDriver::primaryIndex(const QString &table) const q.exec(QLatin1String("SELECT a.RDB$INDEX_NAME, b.RDB$FIELD_NAME, d.RDB$FIELD_TYPE, d.RDB$FIELD_SCALE " "FROM RDB$RELATION_CONSTRAINTS a, RDB$INDEX_SEGMENTS b, RDB$RELATION_FIELDS c, RDB$FIELDS d " "WHERE a.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY' " - "AND UPPER(a.RDB$RELATION_NAME) = '") + tablename.toUpper() + + "AND a.RDB$RELATION_NAME = '") + tablename + QLatin1String(" 'AND a.RDB$INDEX_NAME = b.RDB$INDEX_NAME " "AND c.RDB$RELATION_NAME = a.RDB$RELATION_NAME " "AND c.RDB$FIELD_NAME = b.RDB$FIELD_NAME " -- cgit v0.12 From c402f363d8502c688433eb4f21ba3528d9ac89e5 Mon Sep 17 00:00:00 2001 From: Rohan McGovern Date: Mon, 13 Jul 2009 10:36:51 +1000 Subject: Fixed linking of QtSvg with MSVC. --- src/gui/graphicsview/qgraphicsitem_p.h | 17 +++++++++++++++++ src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h | 18 ------------------ src/gui/widgets/qabstractscrollarea_p.h | 2 +- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index ed1982e..9bdd273 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -506,6 +506,23 @@ struct QGraphicsItemPrivate::TransformData { /*! \internal */ +inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) +{ + // Return true if sibling item1 is on top of item2. + const QGraphicsItemPrivate *d1 = item1->d_ptr; + const QGraphicsItemPrivate *d2 = item2->d_ptr; + bool f1 = d1->flags & QGraphicsItem::ItemStacksBehindParent; + bool f2 = d2->flags & QGraphicsItem::ItemStacksBehindParent; + if (f1 != f2) + return f2; + if (d1->z != d2->z) + return d1->z > d2->z; + return d1->siblingIndex > d2->siblingIndex; +} + +/*! + \internal +*/ static inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) { return qt_closestLeaf(item2, item1); } diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index 3ac922b..2e02458 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -164,24 +164,6 @@ public: bool cached, bool onlyTopLevelItems = false); }; - -/*! - \internal -*/ -inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) -{ - // Return true if sibling item1 is on top of item2. - const QGraphicsItemPrivate *d1 = item1->d_ptr; - const QGraphicsItemPrivate *d2 = item2->d_ptr; - bool f1 = d1->flags & QGraphicsItem::ItemStacksBehindParent; - bool f2 = d2->flags & QGraphicsItem::ItemStacksBehindParent; - if (f1 != f2) - return f2; - if (d1->z != d2->z) - return d1->z > d2->z; - return d1->siblingIndex > d2->siblingIndex; -} - static inline bool QRectF_intersects(const QRectF &s, const QRectF &r) { qreal xp = s.left(); diff --git a/src/gui/widgets/qabstractscrollarea_p.h b/src/gui/widgets/qabstractscrollarea_p.h index 7e0f444..aef8ac5 100644 --- a/src/gui/widgets/qabstractscrollarea_p.h +++ b/src/gui/widgets/qabstractscrollarea_p.h @@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE class QScrollBar; class QAbstractScrollAreaScrollBarContainer; -class QAbstractScrollAreaPrivate: public QFramePrivate +class Q_AUTOTEST_EXPORT QAbstractScrollAreaPrivate: public QFramePrivate { Q_DECLARE_PUBLIC(QAbstractScrollArea) -- cgit v0.12 From de07df9001586cc18ae267591359541b7ea494a0 Mon Sep 17 00:00:00 2001 From: Bill King Date: Mon, 13 Jul 2009 13:28:52 +1000 Subject: Fixes failure when table has null fields to update Fixes an issue where too many parameters are bound when updating QSqlTableModel where the stored record has NULLs in it. Reviewed-by: Justin McPherson --- src/sql/models/qsqltablemodel.cpp | 2 +- tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp | 62 ++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index 591b506..18d89b4 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -202,7 +202,7 @@ bool QSqlTableModelPrivate::exec(const QString &stmt, bool prepStatement, editQuery.addBindValue(rec.value(i)); } for (i = 0; i < whereValues.count(); ++i) { - if (whereValues.isGenerated(i)) + if (whereValues.isGenerated(i) && !whereValues.isNull(i)) editQuery.addBindValue(whereValues.value(i)); } diff --git a/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp b/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp index 5d1f9d4..24bc42b 100644 --- a/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp +++ b/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp @@ -116,6 +116,8 @@ private slots: void insertRecordsInLoop(); void sqlite_attachedDatabase_data() { generic_data("QSQLITE"); } void sqlite_attachedDatabase(); // For task 130799 + void tableModifyWithBlank_data() { generic_data(); } + void tableModifyWithBlank(); // For mail task private: void generic_data(const QString& engine=QString()); @@ -141,6 +143,7 @@ void tst_QSqlTableModel::dropTestTables() tableNames << qTableName("test") << qTableName("test2") << qTableName("test3") + << qTableName("test4") << qTableName("emptytable") << qTableName("bigtable") << qTableName("foo"); @@ -167,6 +170,8 @@ void tst_QSqlTableModel::createTestTables() QVERIFY_SQL( q, exec("create table " + qTableName("test3") + "(id int, random varchar(20), randomtwo varchar(20))")); + QVERIFY_SQL( q, exec("create table " + qTableName("test4") + "(column1 varchar(50), column2 varchar(50), column3 varchar(50))")); + QVERIFY_SQL( q, exec("create table " + qTableName("emptytable") + "(id int)")); if (testWhiteSpaceNames(db.driverName())) { @@ -922,5 +927,62 @@ void tst_QSqlTableModel::sqlite_attachedDatabase() QCOMPARE(model.data(model.index(0, 1), Qt::DisplayRole).toString(), QLatin1String("main")); } + +void tst_QSqlTableModel::tableModifyWithBlank() +{ + QFETCH(QString, dbName); + QSqlDatabase db = QSqlDatabase::database(dbName); + CHECK_DATABASE(db); + + QSqlTableModel model(0, db); + model.setTable(qTableName("test4")); + model.select(); + + //generate a time stamp for the test. Add one second to the current time to make sure + //it is different than the QSqlQuery test. + QString timeString=QDateTime::currentDateTime().addSecs(1).toString(Qt::ISODate); + + //insert a new row, with column0 being the timestamp. + //Should be equivalent to QSqlQuery INSERT INTO... command) + QVERIFY_SQL(model, insertRow(0)); + QVERIFY_SQL(model, setData(model.index(0,0),timeString)); + QVERIFY_SQL(model, submitAll()); + + //set a filter on the table so the only record we get is the one we just made + //I could just do another setData command, but I want to make sure the TableModel + //matches exactly what is stored in the database + model.setFilter("column1='"+timeString+"'"); //filter to get just the newly entered row + QVERIFY_SQL(model, select()); + + //Make sure we only get one record, and that it is the one we just made + QCOMPARE(model.rowCount(), 1); //verify only one entry + QCOMPARE(model.record(0).value(0).toString(), timeString); //verify correct record + + //At this point we know that the intial value (timestamp) was succsefully stored in the database + //Attempt to modify the data in the new record + //equivalent to query.exec("update test set column3="... command in direct test + //set the data in the first column to "col1ModelData" + QVERIFY_SQL(model, setData(model.index(0,1), "col1ModelData")); + + //do a quick check to make sure that the setData command properly set the value in the model + QCOMPARE(model.record(0).value(1).toString(), QLatin1String("col1ModelData")); + + //submit the changed data to the database + //This is where I have been getting errors. + QVERIFY_SQL(model, submitAll()); + + //make sure the model has the most current data for our record + QVERIFY_SQL(model, select()); + + //verify that our new record was the only record returned + QCOMPARE(model.rowCount(), 1); + + //And that the record returned is, in fact, our test record. + QCOMPARE(model.record(0).value(0).toString(), timeString); + + //Make sure the value of the first column matches what we set it to previously. + QCOMPARE(model.record(0).value(1).toString(), QLatin1String("col1ModelData")); +} + QTEST_MAIN(tst_QSqlTableModel) #include "tst_qsqltablemodel.moc" -- cgit v0.12 From c2f6c3eb4381a987df47601fcbab4e3a98d40813 Mon Sep 17 00:00:00 2001 From: Bill King Date: Mon, 13 Jul 2009 14:56:24 +1000 Subject: Fixes up the autotest for mysql over ODBC connection. --- tests/auto/qsqldriver/tst_qsqldriver.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auto/qsqldriver/tst_qsqldriver.cpp b/tests/auto/qsqldriver/tst_qsqldriver.cpp index 6d428df..b79c093 100644 --- a/tests/auto/qsqldriver/tst_qsqldriver.cpp +++ b/tests/auto/qsqldriver/tst_qsqldriver.cpp @@ -158,7 +158,7 @@ void tst_QSqlDriver::record() //check that we can't get records using incorrect tablename casing that's been quoted rec = db.driver()->record(db.driver()->escapeIdentifier(tablename,QSqlDriver::TableName)); - if (db.driverName().startsWith("QMYSQL") || db.driverName().startsWith("QSQLITE") || db.driverName().startsWith("QTDS")) + if (tst_Databases::isMySQL(db) || db.driverName().startsWith("QSQLITE") || db.driverName().startsWith("QTDS")) QCOMPARE(rec.count(), 4); //mysql, sqlite and tds will match else QCOMPARE(rec.count(), 0); @@ -204,7 +204,7 @@ void tst_QSqlDriver::primaryIndex() tablename = tablename.toUpper(); index = db.driver()->primaryIndex(db.driver()->escapeIdentifier(tablename, QSqlDriver::TableName)); - if (db.driverName().startsWith("QMYSQL") || db.driverName().startsWith("QSQLITE") || db.driverName().startsWith("QTDS")) + if (tst_Databases::isMySQL(db) || db.driverName().startsWith("QSQLITE") || db.driverName().startsWith("QTDS")) QCOMPARE(index.count(), 1); //mysql will always find the table name regardless of casing else QCOMPARE(index.count(), 0); -- cgit v0.12 From 049ff0b4f74400ab3c8571f6ba3a73106ca3a9dd Mon Sep 17 00:00:00 2001 From: Bill King Date: Mon, 13 Jul 2009 15:21:01 +1000 Subject: Fixes autotest to match the new code (db level precisionPolicy). --- tests/auto/qsqldatabase/tst_qsqldatabase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/qsqldatabase/tst_qsqldatabase.cpp b/tests/auto/qsqldatabase/tst_qsqldatabase.cpp index 82e25d7..994a3d7 100644 --- a/tests/auto/qsqldatabase/tst_qsqldatabase.cpp +++ b/tests/auto/qsqldatabase/tst_qsqldatabase.cpp @@ -918,7 +918,7 @@ void tst_QSqlDatabase::recordOCI() FieldDef("varchar(20)", QVariant::String, QString("blah2")), FieldDef("nchar(20)", QVariant::String, QString("blah3")), FieldDef("nvarchar2(20)", QVariant::String, QString("blah4")), - FieldDef("number(10,5)", QVariant::String, 1.1234567), + FieldDef("number(10,5)", QVariant::Double, 1.1234567), FieldDef("date", QVariant::DateTime, dt), #ifdef QT3_SUPPORT //X? FieldDef("long raw", QVariant::ByteArray, QByteArray(Q3CString("blah5"))), -- cgit v0.12 From f6079b8407e20942a27f1fe40c4ce0e0a11d3320 Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Mon, 13 Jul 2009 10:16:17 +0200 Subject: Fix broken tst_QGraphicsItem::sorting. A top-level window on Windows cannot have a smaller width than 120. Increase the width by 20 and expect another row of items to be painted. --- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 4ca1b48..96ee070 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -7113,7 +7113,7 @@ void tst_QGraphicsItem::sorting() QGraphicsView view(&scene); view.setResizeAnchor(QGraphicsView::NoAnchor); view.setTransformationAnchor(QGraphicsView::NoAnchor); - view.resize(100, 100); + view.resize(120, 100); view.setFrameStyle(0); view.show(); #ifdef Q_WS_X11 @@ -7130,6 +7130,7 @@ void tst_QGraphicsItem::sorting() << grid[1][0] << grid[1][1] << grid[1][2] << grid[1][3] << grid[2][0] << grid[2][1] << grid[2][2] << grid[2][3] << grid[3][0] << grid[3][1] << grid[3][2] << grid[3][3] + << grid[4][0] << grid[4][1] << grid[4][2] << grid[4][3] << item1 << item2); } -- cgit v0.12 From dacfd67ad35ed3edb079e9795088f852b98717e3 Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Mon, 13 Jul 2009 10:27:15 +0200 Subject: Stabilize tst_QGraphicsView::mouseTracking2 (on Windows). Use QApplication::sendEvent directly instead of calling the static sendMouseMove function, which also calls QTest::mouseMove. This test failed with spy.count() being 2 instead of 1 (which is correct since we both use QTest::mouseMove and QApplication::sendEvent). --- tests/auto/qgraphicsview/tst_qgraphicsview.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp index 77ab977..9a5089b 100644 --- a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp @@ -3311,7 +3311,9 @@ void tst_QGraphicsView::mouseTracking2() EventSpy spy(&scene, QEvent::GraphicsSceneMouseMove); QCOMPARE(spy.count(), 0); - sendMouseMove(view.viewport(), view.viewport()->rect().center()); + QMouseEvent event(QEvent::MouseMove,view.viewport()->rect().center(), Qt::NoButton, + Qt::MouseButtons(Qt::NoButton), 0); + QApplication::sendEvent(view.viewport(), &event); QCOMPARE(spy.count(), 1); } -- cgit v0.12 From d705f5cd9d3bac765346af361038f2f9249183e7 Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Mon, 13 Jul 2009 10:48:43 +0200 Subject: Fix crash after "Remove QT_WA and non-Unicode code paths, dropping Win9x and NT support" tst_QGraphicsProxyWidget crashed because the QAlphaWidget tried to access a deleted widget. Before we had the if check, but that was removed with this commit: 55137901. Completely wrong, we must check the widget pointer before using it. Reviewed-by: jbache --- src/gui/widgets/qeffects.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/widgets/qeffects.cpp b/src/gui/widgets/qeffects.cpp index d6d0a16..f3b1b76 100644 --- a/src/gui/widgets/qeffects.cpp +++ b/src/gui/widgets/qeffects.cpp @@ -128,7 +128,8 @@ QAlphaWidget::~QAlphaWidget() { #if defined(Q_WS_WIN) && !defined(Q_WS_WINCE) // Restore user-defined opacity value - widget->setWindowOpacity(windowOpacity); + if (widget) + widget->setWindowOpacity(windowOpacity); #endif } -- cgit v0.12 From e8e6e8c1722618a48cb4a2e46b24ecad4b056270 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Mon, 13 Jul 2009 11:03:41 +0200 Subject: Added QSyntaxHighlighter::rehighlightBlock(QTextBlock) Merge-request: 379 Reviewed-by: Simon Hausmann --- src/gui/text/qsyntaxhighlighter.cpp | 27 +++++++++++++++++++++++++++ src/gui/text/qsyntaxhighlighter.h | 1 + 2 files changed, 28 insertions(+) diff --git a/src/gui/text/qsyntaxhighlighter.cpp b/src/gui/text/qsyntaxhighlighter.cpp index db1a38e..ccf229e 100644 --- a/src/gui/text/qsyntaxhighlighter.cpp +++ b/src/gui/text/qsyntaxhighlighter.cpp @@ -356,6 +356,8 @@ QTextDocument *QSyntaxHighlighter::document() const \since 4.2 Redoes the highlighting of the whole document. + + \sa rehighlightBlock() */ void QSyntaxHighlighter::rehighlight() { @@ -375,6 +377,31 @@ void QSyntaxHighlighter::rehighlight() } /*! + \since 4.6 + + Redoes the highlighting of the given QTextBlock \a block. + + \sa rehighlight() +*/ +void QSyntaxHighlighter::rehighlightBlock(const QTextBlock &block) +{ + Q_D(QSyntaxHighlighter); + if (!d->doc) + return; + + disconnect(d->doc, SIGNAL(contentsChange(int,int,int)), + this, SLOT(_q_reformatBlocks(int,int,int))); + QTextCursor cursor(block); + cursor.beginEditBlock(); + int from = cursor.position(); + cursor.movePosition(QTextCursor::EndOfBlock); + d->_q_reformatBlocks(from, 0, cursor.position() - from); + cursor.endEditBlock(); + connect(d->doc, SIGNAL(contentsChange(int,int,int)), + this, SLOT(_q_reformatBlocks(int,int,int))); +} + +/*! \fn void QSyntaxHighlighter::highlightBlock(const QString &text) Highlights the given text block. This function is called when diff --git a/src/gui/text/qsyntaxhighlighter.h b/src/gui/text/qsyntaxhighlighter.h index 4e5271b..ee249b8 100644 --- a/src/gui/text/qsyntaxhighlighter.h +++ b/src/gui/text/qsyntaxhighlighter.h @@ -78,6 +78,7 @@ public: public Q_SLOTS: void rehighlight(); + void rehighlightBlock(const QTextBlock &block); protected: virtual void highlightBlock(const QString &text) = 0; -- cgit v0.12 From 9a46bc5f02866134fb66ff1a03863d09382f7d40 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Mon, 13 Jul 2009 11:03:42 +0200 Subject: Added QSyntaxHighlighter::rehighlightBlock() auto test Merge-request: 379 Reviewed-by: Simon Hausmann --- .../qsyntaxhighlighter/tst_qsyntaxhighlighter.cpp | 29 +++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/tests/auto/qsyntaxhighlighter/tst_qsyntaxhighlighter.cpp b/tests/auto/qsyntaxhighlighter/tst_qsyntaxhighlighter.cpp index 22e9455..1699e72 100644 --- a/tests/auto/qsyntaxhighlighter/tst_qsyntaxhighlighter.cpp +++ b/tests/auto/qsyntaxhighlighter/tst_qsyntaxhighlighter.cpp @@ -99,7 +99,8 @@ private slots: void avoidUnnecessaryRehighlight(); void noContentsChangedDuringHighlight(); void rehighlight(); - + void rehighlightBlock(); + private: QTextDocument *doc; QTestDocumentLayout *lout; @@ -517,6 +518,32 @@ void tst_QSyntaxHighlighter::rehighlight() QCOMPARE(hl->callCount, 1); } +void tst_QSyntaxHighlighter::rehighlightBlock() +{ + TestHighlighter *hl = new TestHighlighter(doc); + + cursor.movePosition(QTextCursor::Start); + cursor.beginEditBlock(); + cursor.insertText("Hello"); + cursor.insertBlock(); + cursor.insertText("World"); + cursor.endEditBlock(); + + hl->callCount = 0; + hl->highlightedText.clear(); + QTextBlock block = doc->begin(); + hl->rehighlightBlock(block); + + QCOMPARE(hl->highlightedText, QString("Hello")); + QCOMPARE(hl->callCount, 1); + + hl->callCount = 0; + hl->highlightedText.clear(); + hl->rehighlightBlock(block.next()); + + QCOMPARE(hl->highlightedText, QString("World")); + QCOMPARE(hl->callCount, 1); +} QTEST_MAIN(tst_QSyntaxHighlighter) #include "tst_qsyntaxhighlighter.moc" -- cgit v0.12 From d5c71b7ede48fd832145cc3921da77b10772053c Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Mon, 13 Jul 2009 11:03:44 +0200 Subject: Unified common code in QSyntaxHighlighter::rehighlight() and QSyntaxHighlighter::rehighlightBlock() Merge-request: 379 Reviewed-by: Simon Hausmann --- src/gui/text/qsyntaxhighlighter.cpp | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/gui/text/qsyntaxhighlighter.cpp b/src/gui/text/qsyntaxhighlighter.cpp index ccf229e..f69562d 100644 --- a/src/gui/text/qsyntaxhighlighter.cpp +++ b/src/gui/text/qsyntaxhighlighter.cpp @@ -65,6 +65,18 @@ public: void _q_reformatBlocks(int from, int charsRemoved, int charsAdded); void reformatBlock(QTextBlock block); + + inline void rehighlight(QTextCursor &cursor, QTextCursor::MoveOperation operation) { + QObject::disconnect(doc, SIGNAL(contentsChange(int,int,int)), + q_func(), SLOT(_q_reformatBlocks(int,int,int))); + cursor.beginEditBlock(); + int from = cursor.position(); + cursor.movePosition(operation); + _q_reformatBlocks(from, 0, cursor.position() - from); + cursor.endEditBlock(); + QObject::connect(doc, SIGNAL(contentsChange(int,int,int)), + q_func(), SLOT(_q_reformatBlocks(int,int,int))); + } inline void _q_delayedRehighlight() { if (!rehighlightPending) @@ -365,15 +377,8 @@ void QSyntaxHighlighter::rehighlight() if (!d->doc) return; - disconnect(d->doc, SIGNAL(contentsChange(int,int,int)), - this, SLOT(_q_reformatBlocks(int,int,int))); QTextCursor cursor(d->doc); - cursor.beginEditBlock(); - cursor.movePosition(QTextCursor::End); - d->_q_reformatBlocks(0, 0, cursor.position()); - cursor.endEditBlock(); - connect(d->doc, SIGNAL(contentsChange(int,int,int)), - this, SLOT(_q_reformatBlocks(int,int,int))); + d->rehighlight(cursor, QTextCursor::End); } /*! @@ -389,16 +394,8 @@ void QSyntaxHighlighter::rehighlightBlock(const QTextBlock &block) if (!d->doc) return; - disconnect(d->doc, SIGNAL(contentsChange(int,int,int)), - this, SLOT(_q_reformatBlocks(int,int,int))); QTextCursor cursor(block); - cursor.beginEditBlock(); - int from = cursor.position(); - cursor.movePosition(QTextCursor::EndOfBlock); - d->_q_reformatBlocks(from, 0, cursor.position() - from); - cursor.endEditBlock(); - connect(d->doc, SIGNAL(contentsChange(int,int,int)), - this, SLOT(_q_reformatBlocks(int,int,int))); + d->rehighlight(cursor, QTextCursor::EndOfBlock); } /*! -- cgit v0.12 From 839fbd22a602aa4b9fa20e6c302329008c3aab09 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Fri, 10 Jul 2009 14:44:53 +0200 Subject: Removed an assert from the QNetworkReply. It is possible that finished() function will be called several times, for example if the user calls QNetworkReply::close() as a result of the authenticationRequired() signal, the connection will be closed (which results in emitting a finished() signal), and then the authentication will be cancelled, which will also try to emit the same signal, however the connection state will already be set to Finished. The fix is to just make sure if the finished() signal has already been emitted by checking if the connection state is not Finished or Aborted. Reviewed-by: Thiago Macieira --- src/network/access/qnetworkreplyimpl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index de39970..28319bb 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -461,8 +461,8 @@ void QNetworkReplyImplPrivate::appendDownstreamData(QIODevice *data) void QNetworkReplyImplPrivate::finished() { Q_Q(QNetworkReplyImpl); - Q_ASSERT_X(state != Finished, "QNetworkReplyImpl", - "Backend called finished/finishedWithError more than once"); + if (state == Finished || state == Aborted) + return; state = Finished; pendingNotifications.clear(); -- cgit v0.12 From 5cf6c626c6a1a23291dfe65662b914497ce81c05 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Mon, 13 Jul 2009 11:36:37 +0200 Subject: Fixed the lineendings in the tst_qsqltablemodel.cpp --- tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp | 44 ++++++++++++------------ 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp b/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp index a30fbdb..576c190 100644 --- a/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp +++ b/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp @@ -943,49 +943,49 @@ void tst_QSqlTableModel::tableModifyWithBlank() model.setTable(qTableName("test4")); model.select(); - //generate a time stamp for the test. Add one second to the current time to make sure - //it is different than the QSqlQuery test. - QString timeString=QDateTime::currentDateTime().addSecs(1).toString(Qt::ISODate); - - //insert a new row, with column0 being the timestamp. - //Should be equivalent to QSqlQuery INSERT INTO... command) + //generate a time stamp for the test. Add one second to the current time to make sure + //it is different than the QSqlQuery test. + QString timeString=QDateTime::currentDateTime().addSecs(1).toString(Qt::ISODate); + + //insert a new row, with column0 being the timestamp. + //Should be equivalent to QSqlQuery INSERT INTO... command) QVERIFY_SQL(model, insertRow(0)); QVERIFY_SQL(model, setData(model.index(0,0),timeString)); QVERIFY_SQL(model, submitAll()); - - //set a filter on the table so the only record we get is the one we just made - //I could just do another setData command, but I want to make sure the TableModel - //matches exactly what is stored in the database + + //set a filter on the table so the only record we get is the one we just made + //I could just do another setData command, but I want to make sure the TableModel + //matches exactly what is stored in the database model.setFilter("column1='"+timeString+"'"); //filter to get just the newly entered row QVERIFY_SQL(model, select()); - //Make sure we only get one record, and that it is the one we just made + //Make sure we only get one record, and that it is the one we just made QCOMPARE(model.rowCount(), 1); //verify only one entry QCOMPARE(model.record(0).value(0).toString(), timeString); //verify correct record - //At this point we know that the intial value (timestamp) was succsefully stored in the database - //Attempt to modify the data in the new record - //equivalent to query.exec("update test set column3="... command in direct test - //set the data in the first column to "col1ModelData" + //At this point we know that the intial value (timestamp) was succsefully stored in the database + //Attempt to modify the data in the new record + //equivalent to query.exec("update test set column3="... command in direct test + //set the data in the first column to "col1ModelData" QVERIFY_SQL(model, setData(model.index(0,1), "col1ModelData")); - //do a quick check to make sure that the setData command properly set the value in the model + //do a quick check to make sure that the setData command properly set the value in the model QCOMPARE(model.record(0).value(1).toString(), QLatin1String("col1ModelData")); - //submit the changed data to the database - //This is where I have been getting errors. + //submit the changed data to the database + //This is where I have been getting errors. QVERIFY_SQL(model, submitAll()); - //make sure the model has the most current data for our record + //make sure the model has the most current data for our record QVERIFY_SQL(model, select()); - //verify that our new record was the only record returned + //verify that our new record was the only record returned QCOMPARE(model.rowCount(), 1); - //And that the record returned is, in fact, our test record. + //And that the record returned is, in fact, our test record. QCOMPARE(model.record(0).value(0).toString(), timeString); - //Make sure the value of the first column matches what we set it to previously. + //Make sure the value of the first column matches what we set it to previously. QCOMPARE(model.record(0).value(1).toString(), QLatin1String("col1ModelData")); } -- cgit v0.12 From b9ea022e206bad5d80b4b9a7b957e8b8521d9fb9 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 10 Jul 2009 11:33:48 +0200 Subject: fix warning in qstringbuilder.h by using QLatin1Char Reviewed-by: Volker Hilsheimer --- src/corelib/tools/qstringbuilder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h index 97f13ee..3b43253 100644 --- a/src/corelib/tools/qstringbuilder.h +++ b/src/corelib/tools/qstringbuilder.h @@ -211,7 +211,7 @@ template <> struct QConcatenable { const char *data = ba.constData(); while (*data) - *out++ = *data++; + *out++ = QLatin1Char(*data++); } }; #endif -- cgit v0.12 From 486bd135faa2c8269044f9c03597bc6b05644540 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= Date: Fri, 10 Jul 2009 15:36:02 +0200 Subject: Revert "Fixed leak of plugin instances" mjansen reported on #qt-labs that this change crashes KDE applications that were calling delete on their plugins. It turns out that is also how QPluginLoader works, so the commit was a bad idea to start with. This reverts commit 4c7004122a858cd6d891efc7923ba11484fbf997. Reviewed-by: Thiago Macieira --- src/corelib/plugin/qplugin.h | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/src/corelib/plugin/qplugin.h b/src/corelib/plugin/qplugin.h index ff2b412..233b4f9 100644 --- a/src/corelib/plugin/qplugin.h +++ b/src/corelib/plugin/qplugin.h @@ -63,21 +63,6 @@ typedef QObject *(*QtPluginInstanceFunction)(); void Q_CORE_EXPORT qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunction function); -struct qt_plugin_instance_deleter -{ - qt_plugin_instance_deleter(QPointer &instance) - : instance_(instance) - { - } - - ~qt_plugin_instance_deleter() - { - delete instance_; - } - - QPointer &instance_; -}; - #define Q_IMPORT_PLUGIN(PLUGIN) \ extern QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance_##PLUGIN(); \ class Static##PLUGIN##PluginInstance{ \ @@ -91,10 +76,8 @@ struct qt_plugin_instance_deleter #define Q_PLUGIN_INSTANCE(IMPLEMENTATION) \ { \ static QT_PREPEND_NAMESPACE(QPointer) _instance; \ - if (!_instance) { \ - static QT_PREPEND_NAMESPACE(qt_plugin_instance_deleter) deleter(_instance); \ + if (!_instance) \ _instance = new IMPLEMENTATION; \ - } \ return _instance; \ } -- cgit v0.12 From 3d55ab91148c13f1905a4c1983d144efb4315297 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Mon, 13 Jul 2009 13:00:06 +0200 Subject: Cut-off in QGraphicsView not hit if setting a scene rect. QGraphicsScene::sceneRect() returns the growingItemsBoundingRect if not a particular scene rect is set; otherwise the sceneRect is returned. This cut-off aims to do less processing when the exposed region covers the entire scene, but it won't get hit in case of a sceneRect because we always check against the growingItemsBoundingRect. Task-number: 257192 --- src/gui/graphicsview/qgraphicsview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 3a8a696..bcfd68c 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -971,7 +971,7 @@ QList QGraphicsViewPrivate::findItems(const QRegion &exposedReg // rect does not take into account untransformable items. const QRectF exposedRegionSceneBounds = q->mapToScene(exposedRegion.boundingRect().adjusted(-1, -1, 1, 1)) .boundingRect(); - if (exposedRegionSceneBounds.contains(scene->d_func()->growingItemsBoundingRect)) { + if (exposedRegionSceneBounds.contains(scene->sceneRect())) { Q_ASSERT(allItems); *allItems = true; -- cgit v0.12 From 0aca5cf05288dc4d2175d1c4a78bf62a5ea96b21 Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Mon, 13 Jul 2009 12:48:33 +0200 Subject: doc: Clarified what Qt::HANDLE is on Windows. Task-number: 193615 --- doc/src/qnamespace.qdoc | 5 +++-- src/corelib/thread/qthread.cpp | 11 ++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/doc/src/qnamespace.qdoc b/doc/src/qnamespace.qdoc index b691ac7..85b020d 100644 --- a/doc/src/qnamespace.qdoc +++ b/doc/src/qnamespace.qdoc @@ -1246,8 +1246,9 @@ /*! \typedef Qt::HANDLE Platform-specific handle type for system objects. This is - equivalent to \c{void *} on Windows and Mac OS X, and embedded - Linux, and to \c{unsigned long} on X11. + equivalent to \c{void *} on Mac OS X and embedded Linux, + and to \c{unsigned long} on X11. On Windows it is the + DWORD returned by the Win32 function getCurrentThreadId(). \warning Using this type is not portable. */ diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index 24522f2..2e31c6d 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -261,9 +261,14 @@ void QAdoptedThread::run() Returns the thread handle of the currently executing thread. \warning The handle returned by this function is used for internal - purposes and should not be used in any application code. On - Windows, the returned value is a pseudo-handle for the current - thread that cannot be used for numerical comparison. + purposes and should not be used in any application code. + + \warning On Windows, the returned value is a pseudo-handle for the + current thread. It can't be used for numerical comparison. i.e., + this function returns the DWORD (Windows-Thread ID) returned by + the Win32 function getCurrentThreadId(), not the HANDLE + (Windows-Thread HANDLE) returned by the Win32 function + getCurrentThread(). */ /*! -- cgit v0.12 From cc24c46c117248ecb98200416e7f25375e6bb476 Mon Sep 17 00:00:00 2001 From: Frans Englich Date: Mon, 13 Jul 2009 13:02:20 +0200 Subject: QFlags::testFlag(): handle the zero case appropriately. Brought up by Andy. See perforce change 314809, 17b07e3ab6192b31f77fd2f126705b9ab53b3937. Related to task 221708. Reviewed-By: Andy Shaw --- src/corelib/global/qglobal.h | 2 +- tests/auto/qflags/tst_qflags.cpp | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index a139a55..d6c708c 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -2062,7 +2062,7 @@ public: inline bool operator!() const { return !i; } - inline bool testFlag(Enum f) const { return (i & f) == f; } + inline bool testFlag(Enum f) const { return (i & f) == f && (f != 0 || i == f ); } }; #define Q_DECLARE_FLAGS(Flags, Enum)\ diff --git a/tests/auto/qflags/tst_qflags.cpp b/tests/auto/qflags/tst_qflags.cpp index a5f68dc..87d8258 100644 --- a/tests/auto/qflags/tst_qflags.cpp +++ b/tests/auto/qflags/tst_qflags.cpp @@ -45,6 +45,7 @@ class tst_QFlags: public QObject Q_OBJECT private slots: void testFlag() const; + void testFlagZeroFlag() const; void testFlagMultiBits() const; }; @@ -59,8 +60,31 @@ void tst_QFlags::testFlag() const QVERIFY(!btn.testFlag(Qt::LeftButton)); } +void tst_QFlags::testFlagZeroFlag() const +{ + { + Qt::MouseButtons btn = Qt::LeftButton | Qt::RightButton; + /* Qt::NoButton has the value 0. */ + + QVERIFY(!btn.testFlag(Qt::NoButton)); + } + + { + /* A zero enum set should test true with zero. */ + QVERIFY(Qt::MouseButtons().testFlag(Qt::NoButton)); + } + + { + Qt::MouseButtons btn = Qt::NoButton; + QVERIFY(btn.testFlag(Qt::NoButton)); + } +} + void tst_QFlags::testFlagMultiBits() const { + /* Qt::Window is 0x00000001 + * Qt::Dialog is 0x00000002 | Window + */ { const Qt::WindowFlags onlyWindow(Qt::Window); QVERIFY(!onlyWindow.testFlag(Qt::Dialog)); -- cgit v0.12