summaryrefslogtreecommitdiffstats
path: root/src/gui/graphicsview
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/graphicsview')
-rw-r--r--src/gui/graphicsview/graphicsview.pri53
-rw-r--r--src/gui/graphicsview/qgraphicsgridlayout.h2
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp1204
-rw-r--r--src/gui/graphicsview/qgraphicsitem.h140
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h156
-rw-r--r--src/gui/graphicsview/qgraphicslayout.h2
-rw-r--r--src/gui/graphicsview/qgraphicslayoutitem.cpp4
-rw-r--r--src/gui/graphicsview/qgraphicslayoutitem.h2
-rw-r--r--src/gui/graphicsview/qgraphicslinearlayout.h2
-rw-r--r--src/gui/graphicsview/qgraphicsproxywidget.cpp36
-rw-r--r--src/gui/graphicsview/qgraphicsproxywidget_p.h2
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp2205
-rw-r--r--src/gui/graphicsview/qgraphicsscene.h48
-rw-r--r--src/gui/graphicsview/qgraphicsscene_bsp.cpp56
-rw-r--r--src/gui/graphicsview/qgraphicsscene_bsp_p.h9
-rw-r--r--src/gui/graphicsview/qgraphicsscene_p.h140
-rw-r--r--src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp784
-rw-r--r--src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h208
-rw-r--r--src/gui/graphicsview/qgraphicssceneevent.cpp247
-rw-r--r--src/gui/graphicsview/qgraphicssceneevent.h61
-rw-r--r--src/gui/graphicsview/qgraphicssceneindex.cpp648
-rw-r--r--src/gui/graphicsview/qgraphicssceneindex_p.h182
-rw-r--r--src/gui/graphicsview/qgraphicsscenelinearindex.cpp95
-rw-r--r--src/gui/graphicsview/qgraphicsscenelinearindex_p.h109
-rw-r--r--src/gui/graphicsview/qgraphicstransform.cpp573
-rw-r--r--src/gui/graphicsview/qgraphicstransform.h169
-rw-r--r--src/gui/graphicsview/qgraphicstransform_p.h73
-rw-r--r--src/gui/graphicsview/qgraphicsview.cpp282
-rw-r--r--src/gui/graphicsview/qgraphicsview.h2
-rw-r--r--src/gui/graphicsview/qgraphicsview_p.h21
-rw-r--r--src/gui/graphicsview/qgraphicswidget.cpp58
-rw-r--r--src/gui/graphicsview/qgraphicswidget.h8
-rw-r--r--src/gui/graphicsview/qgraphicswidget_p.cpp34
-rw-r--r--src/gui/graphicsview/qgraphicswidget_p.h4
34 files changed, 4643 insertions, 2976 deletions
diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri
index 4cee6d6..9d232e4 100644
--- a/src/gui/graphicsview/graphicsview.pri
+++ b/src/gui/graphicsview/graphicsview.pri
@@ -1,37 +1,44 @@
# Qt graphicsview module
-HEADERS += graphicsview/qgraphicsitem.h \
+HEADERS += graphicsview/qgraphicsgridlayout.h \
+ graphicsview/qgraphicsitem.h \
graphicsview/qgraphicsitem_p.h \
graphicsview/qgraphicsitemanimation.h \
- graphicsview/qgraphicsscene.h \
- graphicsview/qgraphicsscene_p.h \
- graphicsview/qgraphicsscene_bsp_p.h \
- graphicsview/qgraphicssceneevent.h \
- graphicsview/qgraphicsview_p.h \
- graphicsview/qgraphicsview.h
-SOURCES += graphicsview/qgraphicsitem.cpp \
- graphicsview/qgraphicsitemanimation.cpp \
- graphicsview/qgraphicsscene.cpp \
- graphicsview/qgraphicsscene_bsp.cpp \
- graphicsview/qgraphicssceneevent.cpp \
- graphicsview/qgraphicsview.cpp
-
-# Widgets on the canvas
-HEADERS += graphicsview/qgraphicslayout.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_bsp_p.h \
+ graphicsview/qgraphicsscene_p.h \
+ graphicsview/qgraphicsscenebsptreeindex_p.h \
+ graphicsview/qgraphicssceneevent.h \
+ graphicsview/qgraphicssceneindex_p.h \
+ graphicsview/qgraphicsscenelinearindex_p.h \
+ graphicsview/qgraphicstransform.h \
+ graphicsview/qgraphicstransform_p.h \
+ graphicsview/qgraphicsview.h \
+ graphicsview/qgraphicsview_p.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/qgraphicstransform.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/qgraphicsgridlayout.h b/src/gui/graphicsview/qgraphicsgridlayout.h
index faa91b3..b9db03e 100644
--- a/src/gui/graphicsview/qgraphicsgridlayout.h
+++ b/src/gui/graphicsview/qgraphicsgridlayout.h
@@ -127,7 +127,7 @@ public:
private:
Q_DISABLE_COPY(QGraphicsGridLayout)
- Q_DECLARE_SCOPED_PRIVATE(QGraphicsGridLayout)
+ Q_DECLARE_PRIVATE(QGraphicsGridLayout)
};
inline void QGraphicsGridLayout::addItem(QGraphicsLayoutItem *aitem, int arow, int acolumn, Qt::Alignment aalignment)
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index 3c7593d..d529976 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -135,38 +135,39 @@
\section1 Transformation
- QGraphicsItem supports affine transformations in addition to its base
- position, pos(). To change the item's transformation, you can pass
- a transformation matrix to setTransform()
-
- Item transformations accumulate from parent to child, so if both a
- parent and child item are rotated 90 degrees, the child's total
- transformation will be 180 degrees. Similarly, if the item's
- parent is scaled to 2x its original size, its children will also
- be twice as large. An item's transformation does not affect its
- own local geometry; all geometry functions (e.g., contains(),
- update(), and all the mapping functions) still operate in local
- coordinates. For convenience, QGraphicsItem provides the functions
- sceneTransform(), which returns the item's total transformation
+ QGraphicsItem supports projective transformations in addition to its base
+ position, pos(). There are several ways to change an item's transformation.
+ For simple transformations, you can call either of the convenience
+ functions setRotation() or setScale(), or you can pass any transformation
+ matrix to setTransform(). For advanced transformation control you also have
+ the option of setting several combined transformations by calling
+ setTransformations().
+
+ Item transformations accumulate from parent to child, so if both a parent
+ and child item are rotated 90 degrees, the child's total transformation
+ will be 180 degrees. Similarly, if the item's parent is scaled to 2x its
+ original size, its children will also be twice as large. An item's
+ transformation does not affect its own local geometry; all geometry
+ functions (e.g., contains(), update(), and all the mapping functions) still
+ operate in local coordinates. For convenience, QGraphicsItem provides the
+ functions sceneTransform(), which returns the item's total transformation
matrix (including its position and all parents' positions and
- transformations), and scenePos(), which returns its position in
- scene coordinates. To reset an item's matrix, call
- resetTransform().
+ transformations), and scenePos(), which returns its position in scene
+ coordinates. To reset an item's matrix, call resetTransform().
- Another way to apply transformation to an item is to use the , or
- set the different transformation properties (transformOrigin,
- x/y/zRotation, x/yScale, horizontal/verticalShear). Those
- properties come in addition to the base transformation
+ Certain transformation operations produce a different outcome depending on
+ the order in which they are applied. For example, if you scale an
+ transform, and then rotate it, you may get a different result than if the
+ transform was rotated first. However, the order you set the transformation
+ properties on QGraphicsItem does not affect the resulting transformation;
+ QGraphicsItem always applies the properties in a fixed, defined order:
- The order you set the transformation properties does not affect
- the resulting transformation The resulting transformation is
- always computed in the following order
-
- \code
- [Origin] [Base] [RotateX] [RotateY] [RotateZ] [Shear] [Scale] [-Origin]
- \endcode
-
- Where [Base] is the stransformation set by setTransform
+ \list
+ \o The item's base transform is applied (transform())
+ \o The item's transformations list is applied in order (transformations())
+ \o The item is rotated relative to its transform origin point (rotation(), transformOriginPoint())
+ \o The item is scaled relative to its transform origin point (scale(), transformOriginPoint())
+ \endlist
\section1 Painting
@@ -303,13 +304,12 @@
drop shadow effects and for decoration objects that follow the parent
item's geometry without drawing on top of it.
- \value ItemUsesExtendedStyleOption The item makes use of either
- QStyleOptionGraphicsItem::exposedRect or QStyleOptionGraphicsItem::matrix.
+ \value ItemUsesExtendedStyleOption The item makes use of either the
+ exposedRect or matrix member of the QStyleOptionGraphicsItem. Implementers
+ of QGraphicsItem subclasses should set that flag if this data is required.
By default, the exposedRect is initialized to the item's boundingRect and
the matrix is untransformed. Enable this flag for more fine-grained values.
- Note that QStyleOptionGraphicsItem::levelOfDetail is unaffected by this flag
- and is always initialized to 1.
- Use QStyleOptionGraphicsItem::levelOfDetailFromTransform for a more
+ Use QStyleOptionGraphicsItem::levelOfDetailFromTransform() for a more
fine-grained value.
\value ItemHasNoContents The item does not paint anything (i.e., calling
@@ -323,6 +323,14 @@
performance reasons, these notifications are disabled by default. You must
enable this flag to receive notifications for position and transform
changes. This flag was introduced in Qt 4.6.
+
+ \value ItemAcceptsInputMethod The item supports input methods typically
+ used for Asian languages.
+ This flag was introduced in Qt 4.6.
+
+ \value ItemAutoDetectsFocusProxy The item will assign any child that
+ gains input focus as its focus proxy. See also focusProxy().
+ This flag was introduced in Qt 4.6.
*/
/*!
@@ -554,6 +562,7 @@
#include "qgraphicsview.h"
#include "qgraphicswidget.h"
#include "qgraphicsproxywidget.h"
+#include "qgraphicsscenebsptreeindex_p.h"
#include <QtCore/qbitarray.h>
#include <QtCore/qdebug.h>
#include <QtCore/qpoint.h>
@@ -575,7 +584,6 @@
#include <private/qtextcontrol_p.h>
#include <private/qtextdocumentlayout_p.h>
#include <private/qtextengine_p.h>
-#include <private/qgesturemanager_p.h>
#ifdef Q_WS_X11
#include <private/qt_x11_p.h>
@@ -586,17 +594,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);
@@ -616,8 +613,6 @@ public:
};
Q_GLOBAL_STATIC(QGraphicsItemCustomDataStore, qt_dataStore)
-QString qt_getStandardGestureTypeName(Qt::GestureType type);
-
/*!
\internal
@@ -660,6 +655,10 @@ void QGraphicsItemPrivate::updateAncestorFlag(QGraphicsItem::GraphicsItemFlag ch
// For root items only. This is the item that has either enabled or
// disabled \a childFlag, or has been reparented.
switch (int(childFlag)) {
+ case -2:
+ flag = AncestorFiltersChildEvents;
+ enabled = q->filtersChildEvents();
+ break;
case -1:
flag = AncestorHandlesChildEvents;
enabled = q->handlesChildEvents();
@@ -677,18 +676,22 @@ void QGraphicsItemPrivate::updateAncestorFlag(QGraphicsItem::GraphicsItemFlag ch
return;
}
- // Inherit the enabled-state from our parents.
- if ((parent && ((parent->d_ptr->ancestorFlags & flag)
- || (int(parent->d_ptr->flags & childFlag) == childFlag)
- || (childFlag == -1 && parent->d_ptr->handlesChildEvents)))) {
- enabled = true;
- ancestorFlags |= flag;
- }
-
- // Top-level root items don't have any ancestors, so there are no
- // ancestor flags either.
- if (!parent)
+ if (parent) {
+ // Inherit the enabled-state from our parents.
+ if ((parent->d_ptr->ancestorFlags & flag)
+ || (int(parent->d_ptr->flags & childFlag) == childFlag)
+ || (childFlag == -1 && parent->d_ptr->handlesChildEvents)
+ || (childFlag == -2 && parent->d_ptr->filtersDescendantEvents)) {
+ enabled = true;
+ ancestorFlags |= flag;
+ } else {
+ ancestorFlags &= ~flag;
+ }
+ } else {
+ // Top-level root items don't have any ancestors, so there are no
+ // ancestor flags either.
ancestorFlags = 0;
+ }
} else {
// Don't set or propagate the ancestor flag if it's already correct.
if (((ancestorFlags & flag) && enabled) || (!(ancestorFlags & flag) && !enabled))
@@ -701,7 +704,9 @@ void QGraphicsItemPrivate::updateAncestorFlag(QGraphicsItem::GraphicsItemFlag ch
ancestorFlags &= ~flag;
// Don't process children if the item has the main flag set on itself.
- if ((childFlag != -1 && int(flags & childFlag) == childFlag) || (int(childFlag) == -1 && handlesChildEvents))
+ if ((childFlag != -1 && int(flags & childFlag) == childFlag)
+ || (int(childFlag) == -1 && handlesChildEvents)
+ || (int(childFlag) == -2 && filtersDescendantEvents))
return;
}
@@ -832,6 +837,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
@@ -871,12 +912,17 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent)
if (newParent == parent)
return;
- if (QGraphicsWidget *w = isWidget ? static_cast<QGraphicsWidget *>(q) : q->parentWidget()) {
- // Update the child focus chain; when reparenting a widget that has a
+ if (scene) {
+ // Deliver the change to the index
+ scene->d_func()->index->itemChange(q, QGraphicsItem::ItemParentChange, newParentVariant);
+ }
+
+ QGraphicsItem *lastSubFocusItem = subFocusItem;
+ if (subFocusItem) {
+ // Update the child focus chain; when reparenting an item that has a
// focus child, ensure that that focus child clears its focus child
// chain from our parents before it's reparented.
- if (QGraphicsWidget *focusChild = w->focusWidget())
- focusChild->clearFocus();
+ subFocusItem->clearFocus();
}
// We anticipate geometry changes. If the item is deleted, it will be
@@ -922,6 +968,7 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent)
}
// Inherit ancestor flags from the new parent.
+ updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-2));
updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1));
updateAncestorFlag(QGraphicsItem::ItemClipsChildrenToShape);
updateAncestorFlag(QGraphicsItem::ItemIgnoresTransformations);
@@ -938,6 +985,7 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent)
} else {
// Inherit ancestor flags from the new parent.
+ updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-2));
updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1));
updateAncestorFlag(QGraphicsItem::ItemClipsChildrenToShape);
updateAncestorFlag(QGraphicsItem::ItemIgnoresTransformations);
@@ -958,16 +1006,25 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent)
}
}
- if (scene) {
- // Invalidate any sort caching; arrival of a new item means we need to
- // resort.
- scene->d_func()->invalidateSortCache();
- }
-
// Resolve depth.
resolveDepth(parent ? parent->d_ptr->depth : -1);
dirtySceneTransform = 1;
+ // Restore the sub focus chain.
+ if (lastSubFocusItem)
+ lastSubFocusItem->d_ptr->setSubFocus();
+
+ // Auto-update focus proxy. The closest parent that detects
+ // focus proxies is updated as the proxy gains or loses focus.
+ QGraphicsItem *p = newParent;
+ while (p) {
+ if (p->d_ptr->flags & QGraphicsItem::ItemAutoDetectsFocusProxy) {
+ p->setFocusProxy(q);
+ break;
+ }
+ p = p->d_ptr->parent;
+ }
+
// Deliver post-change notification
q->itemChange(QGraphicsItem::ItemParentHasChanged, newParentVariant);
@@ -1132,7 +1189,6 @@ QGraphicsItem::~QGraphicsItem()
{
d_ptr->inDestructor = 1;
d_ptr->removeExtraItemCache();
- d_ptr->removeExtraGestures();
clearFocus();
if (!d_ptr->children.isEmpty()) {
@@ -1146,6 +1202,13 @@ QGraphicsItem::~QGraphicsItem()
else
d_ptr->setParentItemHelper(0);
+ if (d_ptr->transformData) {
+ for(int i = 0; i < d_ptr->transformData->graphicsTransforms.size(); ++i) {
+ QGraphicsTransform *t = d_ptr->transformData->graphicsTransforms.at(i);
+ static_cast<QGraphicsTransformPrivate *>(t->d_ptr.data())->item = 0;
+ delete t;
+ }
+ }
delete d_ptr->transformData;
qt_dataStore()->data.remove(this);
@@ -1203,7 +1266,7 @@ void QGraphicsItem::setGroup(QGraphicsItemGroup *group)
Returns a pointer to this item's parent item. If this item does not have a
parent, 0 is returned.
- \sa setParentItem(), children()
+ \sa setParentItem(), childItems()
*/
QGraphicsItem *QGraphicsItem::parentItem() const
{
@@ -1226,7 +1289,7 @@ QGraphicsItem *QGraphicsItem::topLevelItem() const
}
/*!
- \since 4.4
+ \since 4.6
Returns a pointer to the item's parent, cast to a QGraphicsObject. returns 0 if the parent item
is not a QGraphicsObject.
@@ -1319,7 +1382,7 @@ const QGraphicsObject *QGraphicsItem::toGraphicsObject() const
the parent. You should not \l{QGraphicsScene::addItem()}{add} the
item to the scene yourself.
- \sa parentItem(), children()
+ \sa parentItem(), childItems()
*/
void QGraphicsItem::setParentItem(QGraphicsItem *parent)
{
@@ -1442,6 +1505,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);
@@ -1490,6 +1555,12 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags)
d_ptr->scene->d_func()->needSortTopLevelItems = 1;
}
+ if ((flags & ItemAcceptsInputMethod) != (oldFlags & ItemAcceptsInputMethod)) {
+ // Update input method sensitivity in any views.
+ if (d_ptr->scene)
+ d_ptr->scene->d_func()->updateInputMethodSensitivityInViews();
+ }
+
if (d_ptr->scene) {
d_ptr->scene->d_func()->markDirty(this, QRectF(),
/*invalidateChildren=*/true,
@@ -1794,6 +1865,8 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo
if (q_ptr->isSelected())
q_ptr->setSelected(false);
} else {
+ geometryChanged = 1;
+ paintedViewBoundingRectsNeedRepaint = 1;
if (isWidget && scene) {
QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(q_ptr);
if (widget->windowType() == Qt::Popup)
@@ -2254,10 +2327,10 @@ bool QGraphicsItem::acceptsHoverEvents() const
stays "hovered" until the cursor leaves its area, including its
children's areas.
- If a parent item handles child events (setHandlesChildEvents()), it will
- receive hover move, drag move, and drop events as the cursor passes
- through its children, but it does not receive hover enter and hover leave,
- nor drag enter and drag leave events on behalf of its children.
+ If a parent item handles child events, it will receive hover move,
+ drag move, and drop events as the cursor passes through its
+ children, but it does not receive hover enter and hover leave, nor
+ drag enter and drag leave events on behalf of its children.
A QGraphicsWidget with window decorations will accept hover events
regardless of the value of acceptHoverEvents().
@@ -2288,8 +2361,8 @@ void QGraphicsItem::setAcceptsHoverEvents(bool enabled)
/*! \since 4.6
- Returns true if an item accepts touch events (QTouchEvent); otherwise, returns false. By
- default, items do not accept touch events.
+ Returns true if an item accepts \l{QTouchEvent}{touch events};
+ otherwise, returns false. By default, items do not accept touch events.
\sa setAcceptTouchEvents()
*/
@@ -2301,7 +2374,7 @@ bool QGraphicsItem::acceptTouchEvents() const
/*!
\since 4.6
- If \a enabled is true, this item will accept touch events;
+ If \a enabled is true, this item will accept \l{QTouchEvent}{touch events};
otherwise, it will ignore them. By default, items do not accept
touch events.
*/
@@ -2317,6 +2390,44 @@ void QGraphicsItem::setAcceptTouchEvents(bool enabled)
}
/*!
+ \since 4.6
+
+ Returns true if this item filters child events (i.e., all events
+ intended for any of its children are instead sent to this item);
+ otherwise, false is returned.
+
+ The default value is false; child events are not filtered.
+
+ \sa setFiltersChildEvents()
+*/
+bool QGraphicsItem::filtersChildEvents() const
+{
+ return d_ptr->filtersDescendantEvents;
+}
+
+/*!
+ \since 4.6
+
+ If \a enabled is true, this item is set to filter all events for
+ all its children (i.e., all events intented for any of its
+ children are instead sent to this item); otherwise, if \a enabled
+ is false, this item will only handle its own events. The default
+ value is false.
+
+ \sa filtersChildEvents()
+*/
+void QGraphicsItem::setFiltersChildEvents(bool enabled)
+{
+ if (d_ptr->filtersDescendantEvents == enabled)
+ return;
+
+ d_ptr->filtersDescendantEvents = enabled;
+ d_ptr->updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-2));
+}
+
+/*!
+ \obsolete
+
Returns true if this item handles child events (i.e., all events
intended for any of its children are instead sent to this item);
otherwise, false is returned.
@@ -2337,6 +2448,8 @@ bool QGraphicsItem::handlesChildEvents() const
}
/*!
+ \obsolete
+
If \a enabled is true, this item is set to handle all events for
all its children (i.e., all events intented for any of its
children are instead sent to this item); otherwise, if \a enabled
@@ -2364,73 +2477,166 @@ void QGraphicsItem::setHandlesChildEvents(bool enabled)
}
/*!
- Returns true if this item has keyboard input focus; otherwise, returns
- false.
+ Returns true if this item or its \l{focusProxy()}{focus proxy} has keyboard
+ input focus; otherwise, returns false.
- \sa QGraphicsScene::focusItem(), setFocus(), QGraphicsScene::setFocusItem()
+ \sa focusItem(), setFocus(), QGraphicsScene::setFocusItem()
*/
bool QGraphicsItem::hasFocus() const
{
+ if (d_ptr->focusProxy)
+ return d_ptr->focusProxy->hasFocus();
return (d_ptr->scene && d_ptr->scene->focusItem() == this);
}
/*!
Gives keyboard input focus to this item. The \a focusReason argument will
- be passed into any focus event generated by this function; it is used to
- give an explanation of what caused the item to get focus.
+ be passed into any \l{QFocusEvent}{focus event} generated by this function;
+ it is used to give an explanation of what caused the item to get focus.
- Only items that set the ItemIsFocusable flag can accept keyboard focus.
+ Only enabled items that set the ItemIsFocusable flag can accept keyboard
+ focus.
- If this item is not visible (i.e., isVisible() returns false), not
- enabled, not associated with a scene, or if it already has input focus,
- this function will do nothing.
+ If this item is not visible, or not associated with a scene, it will not
+ gain immediate input focus. However, it will be registered as the preferred
+ focus item for its subtree of items, should it later become visible.
- As a result of calling this function, this item will receive a focus in
- event with \a focusReason. If another item already has focus, that item
- will first receive a focus out event indicating that it has lost input
- focus.
+ As a result of calling this function, this item will receive a
+ \l{focusInEvent()}{focus in event} with \a focusReason. If another item
+ already has focus, that item will first receive a \l{focusOutEvent()}
+ {focus out event} indicating that it has lost input focus.
- \sa clearFocus(), hasFocus()
+ \sa clearFocus(), hasFocus(), focusItem(), focusProxy()
*/
void QGraphicsItem::setFocus(Qt::FocusReason focusReason)
{
- if (!d_ptr->scene || !isEnabled() || hasFocus() || !(d_ptr->flags & ItemIsFocusable))
+ // Disabled / unfocusable items cannot accept focus.
+ if (!isEnabled() || !(d_ptr->flags & QGraphicsItem::ItemIsFocusable))
return;
- if (isVisible()) {
- // Visible items immediately gain focus from scene.
- d_ptr->scene->setFocusItem(this, focusReason);
- } else if (d_ptr->isWidget) {
- // Just set up subfocus.
- static_cast<QGraphicsWidget *>(this)->d_func()->setFocusWidget();
+
+ // Find focus proxy.
+ QGraphicsItem *f = this;
+ while (f->d_ptr->focusProxy)
+ f = f->d_ptr->focusProxy;
+
+ // Return if it already has focus.
+ if (d_ptr->scene && d_ptr->scene->focusItem() == f)
+ return;
+
+ // Update the child focus chain.
+ d_ptr->setSubFocus();
+
+ // Update the scene's focus item.
+ if (d_ptr->scene) {
+ QGraphicsWidget *w = window();
+ if (!w || w->isActiveWindow()) {
+ // Visible items immediately gain focus from scene.
+ d_ptr->scene->d_func()->setFocusItemHelper(f, focusReason);
+ }
}
}
/*!
Takes keyboard input focus from the item.
- If it has focus, a focus out event is sent to this item to tell it that it
- is about to lose the focus.
+ If it has focus, a \l{focusOutEvent()}{focus out event} is sent to this item
+ to tell it that it is about to lose the focus.
Only items that set the ItemIsFocusable flag, or widgets that set an
appropriate focus policy, can accept keyboard focus.
- \sa setFocus(), QGraphicsWidget::focusPolicy
+ \sa setFocus(), hasFocus(), QGraphicsWidget::focusPolicy
*/
void QGraphicsItem::clearFocus()
{
if (!d_ptr->scene)
return;
- if (d_ptr->isWidget) {
- // Invisible widget items with focus must explicitly clear subfocus.
- static_cast<QGraphicsWidget *>(this)->d_func()->clearFocusWidget();
- }
- if (d_ptr->scene->focusItem() == this) {
+ // Invisible items with focus must explicitly clear subfocus.
+ d_ptr->clearSubFocus();
+ if (hasFocus()) {
// If this item has the scene's input focus, clear it.
d_ptr->scene->setFocusItem(0);
}
}
/*!
+ \since 4.6
+
+ Returns this item's focus proxy, or 0 if this item has no
+ focus proxy.
+
+ \sa setFocusProxy(), ItemAutoDetectsFocusProxy, setFocus(), hasFocus()
+*/
+QGraphicsItem *QGraphicsItem::focusProxy() const
+{
+ return d_ptr->focusProxy;
+}
+
+/*!
+ \since 4.6
+
+ Sets the item's focus proxy to \a item.
+
+ If an item has a focus proxy, the focus proxy will receive
+ input focus when the item gains input focus. The item itself
+ will still have focus (i.e., hasFocus() will return true),
+ but only the focus proxy will receive the keyboard input.
+
+ A focus proxy can itself have a focus proxy, and so on. In
+ such case, keyboard input will be handled by the outermost
+ focus proxy.
+
+ The focus proxy \a item must belong to the same scene as
+ this item.
+
+ \sa focusProxy(), ItemAutoDetectsFocusProxy, setFocus(), hasFocus()
+*/
+void QGraphicsItem::setFocusProxy(QGraphicsItem *item)
+{
+ if (item == d_ptr->focusProxy)
+ return;
+ if (item == this) {
+ qWarning("QGraphicsItem::setFocusProxy: cannot assign self as focus proxy");
+ return;
+ }
+ if (item) {
+ if (item->d_ptr->scene != d_ptr->scene) {
+ qWarning("QGraphicsItem::setFocusProxy: focus proxy must be in same scene");
+ return;
+ }
+ for (QGraphicsItem *f = item->focusProxy(); f != 0; f = f->focusProxy()) {
+ if (f == this) {
+ qWarning("QGraphicsItem::setFocusProxy: %p is already in the focus proxy chain", item);
+ return;
+ }
+ }
+ }
+
+ QGraphicsItem *lastFocusProxy = d_ptr->focusProxy;
+ d_ptr->focusProxy = item;
+ if (d_ptr->scene) {
+ if (lastFocusProxy)
+ d_ptr->scene->d_func()->focusProxyReverseMap.remove(lastFocusProxy, this);
+ if (item)
+ d_ptr->scene->d_func()->focusProxyReverseMap.insert(item, this);
+ }
+}
+
+/*!
+ \since 4.6
+
+ If this item, a child or descendant of this item currently has input
+ focus, this function will return a pointer to that item. If
+ no descendant has input focus, 0 is returned.
+
+ \sa hasFocus(), setFocus(), QWidget::focusWidget()
+*/
+QGraphicsItem *QGraphicsItem::focusItem() const
+{
+ return d_ptr->subFocusItem;
+}
+
+/*!
\since 4.4
Grabs the mouse input.
@@ -2565,7 +2771,7 @@ void QGraphicsItem::ungrabKeyboard()
For convenience, you can also call scenePos() to determine the
item's position in scene coordinates, regardless of its parent.
- \sa x(), y(), setPos(), matrix(), {The Graphics View Coordinate System}
+ \sa x(), y(), setPos(), transform(), {The Graphics View Coordinate System}
*/
QPointF QGraphicsItem::pos() const
{
@@ -2581,10 +2787,12 @@ QPointF QGraphicsItem::pos() const
*/
/*!
- Set's the \a x coordinate of the item's position. Equivalent to
- calling setPos(x, y()).
+ \since 4.6
+
+ Set's the \a x coordinate of the item's position. Equivalent to
+ calling setPos(x, y()).
- \sa x(), setPos()
+ \sa x(), setPos()
*/
void QGraphicsItem::setX(qreal x)
{
@@ -2600,10 +2808,12 @@ void QGraphicsItem::setX(qreal x)
*/
/*!
- Set's the \a y coordinate of the item's position. Equivalent to
- calling setPos(x(), y).
+ \since 4.6
+
+ Set's the \a y coordinate of the item's position. Equivalent to
+ calling setPos(x(), y).
- \sa x(), setPos()
+ \sa x(), setPos()
*/
void QGraphicsItem::setY(qreal y)
{
@@ -2763,11 +2973,10 @@ QMatrix QGraphicsItem::matrix() const
Returns this item's transformation matrix.
- Either the one set by setTransform, or the resulting transformation from
- all the transfmation properties
-
- If no matrix or transformation property has been set, the
- identity matrix is returned.
+ The transformation matrix is combined with the item's rotation(), scale()
+ and transformations() into a combined transformations for the item.
+
+ The default transformation matrix is an identity matrix.
\sa setTransform(), sceneTransform()
*/
@@ -2781,333 +2990,182 @@ QTransform QGraphicsItem::transform() const
/*!
\since 4.6
- Returns the rotation around the X axis.
-
- The default is 0
+ Returns the clockwise rotation, in degrees, around the Z axis. The default
+ value is 0 (i.e., the item is not rotated).
- \warning The value doesn't take in account any rotation set with
- the setTransform() method.
+ The rotation is combined with the item's scale(), transform() and
+ transformations() to map the item's coordinate system to the parent item.
- \sa setXRotation(), {Transformations}
+ \sa setRotation(), transformOriginPoint(), {Transformations}
*/
-qreal QGraphicsItem::xRotation() const
+qreal QGraphicsItem::rotation() const
{
if (!d_ptr->transformData)
return 0;
- return d_ptr->transformData->xRotation;
-}
-
-/*!
- \since 4.6
-
- Sets the rotation around the X axis to \a angle degrees.
-
- \warning The value doesn't take in account any rotation set with the setTransform() method.
-
- \sa xRotation(), setTransformOrigin(), {Transformations}
-*/
-void QGraphicsItem::setXRotation(qreal angle)
-{
- prepareGeometryChange();
- if (!d_ptr->transformData)
- d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
- d_ptr->transformData->xRotation = angle;
- d_ptr->transformData->onlyTransform = false;
- d_ptr->dirtySceneTransform = 1;
+ return d_ptr->transformData->rotation;
}
/*!
\since 4.6
- Returns the rotation around the Y axis.
-
- The default is 0
-
- \warning The value doesn't take in account any rotation set with the setTransform() method.
-
- \sa setYRotation(), {Transformations}
-*/
-qreal QGraphicsItem::yRotation() const
-{
- if (!d_ptr->transformData)
- return 0;
- return d_ptr->transformData->yRotation;
-}
-
-/*!
- \since 4.6
+ Sets the clockwise rotation \a angle, in degrees, around the Z axis. The
+ default value is 0 (i.e., the item is not rotated). Assigning a negative
+ value will rotate the item counter-clockwise. Normally the rotation angle
+ is in the range (-360, 360), but it's also possible to assign values
+ outside of this range (e.g., a rotation of 370 degrees is the same as a
+ rotation of 10 degrees).
- Sets the rotation around the Y axis to \a angle degrees.
+ The item is rotated around its transform origin point, which by default
+ is (0, 0). You can select a different transformation origin by calling
+ setTransformOriginPoint().
- \warning The value doesn't take in account any rotation set with the setTransform() method.
+ The rotation is combined with the item's scale(), transform() and
+ transformations() to map the item's coordinate system to the parent item.
- \sa yRotation(), setTransformOrigin() {Transformations}
+ \sa rotation(), setTransformOriginPoint(), {Transformations}
*/
-void QGraphicsItem::setYRotation(qreal angle)
+void QGraphicsItem::setRotation(qreal angle)
{
prepareGeometryChange();
if (!d_ptr->transformData)
d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
- d_ptr->transformData->yRotation = angle;
+ d_ptr->transformData->rotation = angle;
d_ptr->transformData->onlyTransform = false;
d_ptr->dirtySceneTransform = 1;
-}
-/*!
- \since 4.6
-
- Returns the rotation around the Z axis.
-
- The default is 0
-
- \warning The value doesn't take in account any rotation set with the setTransform() method.
-
- \sa setZRotation(), {Transformations}
-*/
-qreal QGraphicsItem::zRotation() const
-{
- if (!d_ptr->transformData)
- return 0;
- return d_ptr->transformData->zRotation;
+ if (d_ptr->isObject)
+ emit static_cast<QGraphicsObject *>(this)->rotationChanged();
}
/*!
\since 4.6
- Sets the rotation around the Z axis to \a angle degrees.
+ Returns the scale factor of the item. The default scale factor is 1.0
+ (i.e., the item is not scaled).
- \warning The value doesn't take in account any rotation set with the setTransform() method.
+ The scale is combined with the item's rotation(), transform() and
+ transformations() to map the item's coordinate system to the parent item.
- \sa zRotation(), setTransformOrigin(), {Transformations}
+ \sa setScale(), rotation(), {Transformations}
*/
-void QGraphicsItem::setZRotation(qreal angle)
+qreal QGraphicsItem::scale() const
{
- prepareGeometryChange();
if (!d_ptr->transformData)
- d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
- d_ptr->transformData->zRotation = angle;
- d_ptr->transformData->onlyTransform = false;
- d_ptr->dirtySceneTransform = 1;
+ return 1.;
+ return d_ptr->transformData->scale;
}
/*!
\since 4.6
- This convenience function set the rotation angles around the 3 axes
- to \a x, \a y and \a z.
+ Sets the scale \a factor of the item. The default scale factor is 1.0
+ (i.e., the item is not scaled). A scale factor of 0.0 will collapse the
+ item to a single point. If you provide a negative scale factor, the
+ item will be flipped and mirrored (i.e., rotated 180 degrees).
- \sa setXRotation(), setYRotation(), setZRotation(), {Transformations}
-*/
-void QGraphicsItem::setRotation(qreal x, qreal y, qreal z)
-{
- prepareGeometryChange();
- if (!d_ptr->transformData)
- d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
- d_ptr->transformData->xRotation = x;
- d_ptr->transformData->yRotation = y;
- d_ptr->transformData->zRotation = z;
- d_ptr->transformData->onlyTransform = false;
- d_ptr->dirtySceneTransform = 1;
-}
-
-/*!
- \since 4.6
-
- Returns the scale factor on the X axis.
-
- The default is 1
-
- \warning The value doesn't take in account any scaling set with the setTransform() method.
-
- \sa setXScale(), {Transformations}
-*/
-qreal QGraphicsItem::xScale() const
-{
- if (!d_ptr->transformData)
- return 1;
- return d_ptr->transformData->xScale;
-}
-
-/*!
- \since 4.6
+ The item is scaled around its transform origin point, which by default
+ is (0, 0). You can select a different transformation origin by calling
+ setTransformOriginPoint().
- Sets the scale factor on the X axis to \a factor.
+ The scale is combined with the item's rotation(), transform() and
+ transformations() to map the item's coordinate system to the parent item.
- \warning The value doesn't take in account any scaling set with the setTransform() method.
-
- \sa xScale(), setTransformOrigin(), {Transformations}
+ \sa scale(), setTransformOriginPoint(), {Transformations}
*/
-void QGraphicsItem::setXScale(qreal factor)
+void QGraphicsItem::setScale(qreal factor)
{
prepareGeometryChange();
if (!d_ptr->transformData)
d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
- d_ptr->transformData->xScale = factor;
+ d_ptr->transformData->scale = factor;
d_ptr->transformData->onlyTransform = false;
d_ptr->dirtySceneTransform = 1;
-}
-
-/*!
- \since 4.6
-
- Returns the scale factor on the Y axis.
-
- The default is 1
-
- \warning The value doesn't take in account any scaling set with the setTransform() method.
-
- \sa setYScale(), {Transformations}
-*/
-qreal QGraphicsItem::yScale() const
-{
- if (!d_ptr->transformData)
- return 1;
- return d_ptr->transformData->yScale;
-}
-
-/*!
- \since 4.6
- Sets the scale factor on the Y axis to \a factor.
-
- \warning The value doesn't take in account any scaling set with the setTransform() method.
-
- \sa yScale(), setTransformOrigin(), {Transformations}
-*/
-void QGraphicsItem::setYScale(qreal factor)
-{
- prepareGeometryChange();
- if (!d_ptr->transformData)
- d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
- d_ptr->transformData->yScale = factor;
- d_ptr->transformData->onlyTransform = false;
- d_ptr->dirtySceneTransform = 1;
+ if (d_ptr->isObject)
+ emit static_cast<QGraphicsObject *>(this)->scaleChanged();
}
-/*!
- \since 4.6
-
- This convenience function set the scaling factors on X and Y axis to \a sx and \a sy.
-
- \warning The value doesn't take in account any scaling set with the setTransform() method.
-
- \sa setXScale(), setYScale(), {Transformations}
-*/
-void QGraphicsItem::setScale(qreal sx, qreal sy)
-{
- prepareGeometryChange();
- if (!d_ptr->transformData)
- d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
- d_ptr->transformData->xScale = sx;
- d_ptr->transformData->yScale = sy;
- d_ptr->transformData->onlyTransform = false;
- d_ptr->dirtySceneTransform = 1;
-}
/*!
\since 4.6
- Returns the horizontal shear.
+ Returns a list of graphics transforms that currently apply to this item.
- The default is 0
+ QGraphicsTransform is for applying and controlling a chain of individual
+ transformation operations on an item. It's particularily useful in
+ animations, where each transform operation needs to be interpolated
+ independently, or differently.
- \warning The value doesn't take in account any shearing set with the setTransform() method.
+ The transformations are combined with the item's rotation(), scale() and
+ transform() to map the item's coordinate system to the parent item.
- \sa setHorizontalShear(), {Transformations}
+ \sa scale(), rotation(), transformOriginPoint(), {Transformations}
*/
-qreal QGraphicsItem::horizontalShear() const
+QList<QGraphicsTransform *> QGraphicsItem::transformations() const
{
if (!d_ptr->transformData)
- return 0;
- return d_ptr->transformData->horizontalShear;
+ return QList<QGraphicsTransform *>();
+ return d_ptr->transformData->graphicsTransforms;
}
/*!
\since 4.6
- Sets the horizontal shear to \a shear.
+ Sets a list of graphics \a transformations (QGraphicsTransform) that
+ currently apply to this item.
- \warning The value doesn't take in account any shearing set with the setTransform() method.
+ If all you want is to rotate or scale an item, you should call setRotation()
+ or setScale() instead. If you want to set an arbitrary transformation on
+ an item, you can call setTransform().
- \sa horizontalShear(), {Transformations}
-*/
-void QGraphicsItem::setHorizontalShear(qreal shear)
-{
- prepareGeometryChange();
- if (!d_ptr->transformData)
- d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
- d_ptr->transformData->horizontalShear = shear;
- d_ptr->transformData->onlyTransform = false;
- d_ptr->dirtySceneTransform = 1;
-}
+ QGraphicsTransform is for applying and controlling a chain of individual
+ transformation operations on an item. It's particularily useful in
+ animations, where each transform operation needs to be interpolated
+ independently, or differently.
-/*!
- \since 4.6
+ The transformations are combined with the item's rotation(), scale() and
+ transform() to map the item's coordinate system to the parent item.
- Returns the vertical shear.
-
- The default is 0
-
- \warning The value doesn't take in account any shearing set with the setTransform() method.
-
- \sa setHorizontalShear(), {Transformations}
+ \sa scale(), setTransformOriginPoint(), {Transformations}
*/
-qreal QGraphicsItem::verticalShear() const
-{
- if (!d_ptr->transformData)
- return 0;
- return d_ptr->transformData->verticalShear;
-}
-
-/*!
- \since 4.6
-
- Sets the vertical shear to \a shear.
-
- \warning The value doesn't take in account any shearing set with the setTransform() method.
-
- \sa verticalShear(), {Transformations}
-*/
-void QGraphicsItem::setVerticalShear(qreal shear)
+void QGraphicsItem::setTransformations(const QList<QGraphicsTransform *> &transformations)
{
prepareGeometryChange();
if (!d_ptr->transformData)
d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
- d_ptr->transformData->verticalShear = shear;
+ d_ptr->transformData->graphicsTransforms = transformations;
+ for (int i = 0; i < transformations.size(); ++i)
+ transformations.at(i)->d_func()->setItem(this);
d_ptr->transformData->onlyTransform = false;
d_ptr->dirtySceneTransform = 1;
}
/*!
- \since 4.6
-
- This convenience function sets the horizontal shear to \a sh and the vertical shear to \a sv.
-
- \warning The value doesn't take in account any shearing set with the setTransform() method.
-
- \sa setHorizontalShear(), setVerticalShear()
+ \internal
*/
-void QGraphicsItem::setShear(qreal sh, qreal sv)
+void QGraphicsItemPrivate::appendGraphicsTransform(QGraphicsTransform *t)
{
- prepareGeometryChange();
- if (!d_ptr->transformData)
- d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
- d_ptr->transformData->horizontalShear = sh;
- d_ptr->transformData->verticalShear = sv;
- d_ptr->transformData->onlyTransform = false;
- d_ptr->dirtySceneTransform = 1;
+ if (!transformData)
+ transformData = new QGraphicsItemPrivate::TransformData;
+ if (!transformData->graphicsTransforms.contains(t))
+ transformData->graphicsTransforms.append(t);
+
+ Q_Q(QGraphicsItem);
+ t->d_func()->setItem(q);
+ transformData->onlyTransform = false;
+ dirtySceneTransform = 1;
}
/*!
\since 4.6
- Returns the origin point used for transformation in item coordinate.
+ Returns the origin point for the transformation in item coordinates.
The default is QPointF(0,0).
- \sa setTransformOrigin(), {Transformations}
+ \sa setTransformOriginPoint(), {Transformations}
*/
-QPointF QGraphicsItem::transformOrigin() const
+QPointF QGraphicsItem::transformOriginPoint() const
{
if (!d_ptr->transformData)
return QPointF(0,0);
@@ -3117,11 +3175,11 @@ QPointF QGraphicsItem::transformOrigin() const
/*!
\since 4.6
- Sets the \a origin for transformation in item coordinate
+ Sets the \a origin point for the transformation in item coordinates.
- \sa transformOrigin(), {Transformations}
+ \sa transformOriginPoint(), {Transformations}
*/
-void QGraphicsItem::setTransformOrigin(const QPointF &origin)
+void QGraphicsItem::setTransformOriginPoint(const QPointF &origin)
{
prepareGeometryChange();
if (!d_ptr->transformData)
@@ -3133,15 +3191,15 @@ void QGraphicsItem::setTransformOrigin(const QPointF &origin)
}
/*!
- \fn void QGraphicsItem::setTransformOrigin(qreal x, qreal y)
+ \fn void QGraphicsItem::setTransformOriginPoint(qreal x, qreal y)
\since 4.6
\overload
- Sets the origin for the transformation to the point
- composed of \a x and \a y.
-
- \sa setTransformOrigin(), {Transformations}
+ Sets the origin point for the transformation in item coordinates.
+ This is equivalent to calling setTransformOriginPoint(QPointF(\a x, \a y)).
+
+ \sa setTransformOriginPoint(), {Transformations}
*/
@@ -3154,7 +3212,8 @@ void QGraphicsItem::setTransformOrigin(const QPointF &origin)
*/
QMatrix QGraphicsItem::sceneMatrix() const
{
- return sceneTransform().toAffine();
+ d_ptr->ensureSceneTransform();
+ return d_ptr->sceneTransform.toAffine();
}
@@ -3177,16 +3236,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<QGraphicsItem *>(this);
- d_ptr->ensureSceneTransformRecursive(&that);
+ d_ptr->ensureSceneTransform();
return d_ptr->sceneTransform;
}
@@ -3216,8 +3266,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;
@@ -3236,7 +3288,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());
@@ -3329,8 +3382,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.
@@ -3420,9 +3476,11 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine)
to map an item coordiate to a scene coordinate, or mapFromScene() to map
from scene coordinates to item coordinates.
- \warning using this function doesnt affect the value of the transformation properties
+ The transformation matrix is combined with the item's rotation(), scale()
+ and transformations() into a combined transformation that maps the item's
+ coordinate system to its parent.
- \sa transform(), setRotation(), setScale(), setShear(), setTransformOrigin(), {The Graphics View Coordinate System}, {Transformations}
+ \sa transform(), setRotation(), setScale(), setTransformOriginPoint(), {The Graphics View Coordinate System}, {Transformations}
*/
void QGraphicsItem::setTransform(const QTransform &matrix, bool combine)
{
@@ -3479,7 +3537,14 @@ void QGraphicsItem::resetTransform()
/*!
\obsolete
- Use setZRotation() instead
+
+ Use
+
+ \code
+ setRotation(rotation() + angle);
+ \endcode
+
+ instead.
Rotates the current item transformation \a angle degrees clockwise around
its origin. To translate around an arbitrary point (x, y), you need to
@@ -3489,8 +3554,6 @@ void QGraphicsItem::resetTransform()
\snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 6
- \warning using this functionhas no effect on the zRotation value
-
\sa setTransform(), transform(), scale(), shear(), translate()
*/
void QGraphicsItem::rotate(qreal angle)
@@ -3500,7 +3563,14 @@ void QGraphicsItem::rotate(qreal angle)
/*!
\obsolete
- Use setScale() instead
+
+ Use
+
+ \code
+ setTransform(QTransform::fromScale(sx, sy), true);
+ \endcode
+
+ instead.
Scales the current item transformation by (\a sx, \a sy) around its
origin. To scale from an arbitrary point (x, y), you need to combine
@@ -3510,8 +3580,6 @@ void QGraphicsItem::rotate(qreal angle)
\snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 7
- \warning using this function has no effect on the xScale or yScale value
-
\sa setTransform(), transform()
*/
void QGraphicsItem::scale(qreal sx, qreal sy)
@@ -3521,11 +3589,16 @@ void QGraphicsItem::scale(qreal sx, qreal sy)
/*!
\obsolete
- Use setShear instead.
- Shears the current item transformation by (\a sh, \a sv).
+ Use
- \warning using this function has no effect on the horizontalShear or verticalShear value
+ \code
+ setTransform(QTransform().shear(sh, sv), true);
+ \endcode
+
+ instead.
+
+ Shears the current item transformation by (\a sh, \a sv).
\sa setTransform(), transform()
*/
@@ -3536,7 +3609,13 @@ void QGraphicsItem::shear(qreal sh, qreal sv)
/*!
\obsolete
- Use setPos() or setTransformOrigin() instead.
+
+ Use setPos() or setTransformOriginPoint() instead. For identical
+ behavior, use
+
+ \code
+ setTransform(QTransform::fromTranslate(dx, dy), true);
+ \endcode
Translates the current item transformation by (\a dx, \a dy).
@@ -3621,18 +3700,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);
- // Invalidate any sort caching; arrival of a new item means we need to
- // resort.
- d_ptr->scene->d_func()->invalidateSortCache();
- }
itemChange(ItemZValueHasChanged, newZVariant);
@@ -3723,7 +3804,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);
}
/*!
@@ -4098,7 +4185,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());
}
@@ -4291,12 +4378,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());
}
/*!
@@ -4317,6 +4403,7 @@ void QGraphicsItemPrivate::resolveDepth(int parentDepth)
void QGraphicsItemPrivate::addChild(QGraphicsItem *child)
{
needSortChildren = 1;
+ child->d_ptr->siblingIndex = children.size();
children.append(child);
}
@@ -4326,6 +4413,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;
}
/*!
@@ -4486,9 +4577,50 @@ 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);
+}
+
+/*!
+ \internal
+*/
+void QGraphicsItemPrivate::setSubFocus()
+{
+ // Update focus child chain.
+ QGraphicsItem *item = q_ptr;
+ QGraphicsItem *parent = item;
+ bool hidden = !visible;
+ do {
+ parent->d_func()->subFocusItem = item;
+ } while (!parent->isWindow() && (parent = parent->d_ptr->parent) && (!hidden || !parent->d_func()->visible));
+}
+
+/*!
+ \internal
+*/
+void QGraphicsItemPrivate::clearSubFocus()
+{
+ // Reset focus child chain.
+ QGraphicsItem *parent = q_ptr;
+ do {
+ if (parent->d_ptr->subFocusItem != q_ptr)
+ break;
+ parent->d_ptr->subFocusItem = 0;
+ } while (!parent->isWindow() && (parent = parent->d_ptr->parent));
}
/*!
@@ -4829,7 +4961,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);
}
/*!
@@ -4896,7 +5030,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);
}
/*!
@@ -4969,7 +5105,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);
}
/*!
@@ -5043,7 +5181,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);
}
/*!
@@ -5095,7 +5235,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);
}
/*!
@@ -5140,7 +5282,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);
}
/*!
@@ -5201,7 +5345,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);
}
/*!
@@ -5269,7 +5415,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);
}
/*!
@@ -5319,7 +5467,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);
}
/*!
@@ -5362,7 +5512,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);
}
/*!
@@ -5838,7 +5990,7 @@ void QGraphicsItem::dropEvent(QGraphicsSceneDragDropEvent *event)
focus in events for this item. The default implementation calls
ensureVisible().
- \sa focusOutEvent(), sceneEvent()
+ \sa focusOutEvent(), sceneEvent(), setFocus()
*/
void QGraphicsItem::focusInEvent(QFocusEvent *event)
{
@@ -5849,7 +6001,7 @@ void QGraphicsItem::focusInEvent(QFocusEvent *event)
This event handler, for event \a event, can be reimplemented to receive
focus out events for this item. The default implementation does nothing.
- \sa focusInEvent(), sceneEvent()
+ \sa focusInEvent(), sceneEvent(), setFocus()
*/
void QGraphicsItem::focusOutEvent(QFocusEvent *event)
{
@@ -6235,7 +6387,7 @@ void QGraphicsItem::inputMethodEvent(QInputMethodEvent *event)
surrounding text and reconversions. \a query specifies which
property is queried.
- \sa inputMethodEvent()
+ \sa inputMethodEvent(), QInputMethodEvent, QInputContext
*/
QVariant QGraphicsItem::inputMethodQuery(Qt::InputMethodQuery query) const
{
@@ -6251,99 +6403,36 @@ QVariant QGraphicsItem::inputMethodQuery(Qt::InputMethodQuery query) const
}
/*!
- \since 4.6
+ Returns the current input method hints of this item.
- Subscribes the graphics item to the specified \a gesture type.
+ Input method hints are only relevant for input items.
+ The hints are used by the input method to indicate how it should operate.
+ For example, if the Qt::ImhNumbersOnly flag is set, the input method may change
+ its visual components to reflect that only numbers can be entered.
- Returns the id of the gesture.
+ The effect may vary between input method implementations.
- \sa releaseGesture(), setGestureEnabled()
-*/
-int QGraphicsItem::grabGesture(Qt::GestureType gesture)
-{
- /// TODO: if we are QGraphicsProxyWidget we should subscribe the widget to gesture as well.
- return grabGesture(qt_getStandardGestureTypeName(gesture));
-}
-
-/*!
\since 4.6
- Subscribes the graphics item to the specified \a gesture type.
-
- Returns the id of the gesture.
-
- \sa releaseGesture(), setGestureEnabled()
+ \sa setInputMethodHints(), inputMethodQuery(), QInputContext
*/
-int QGraphicsItem::grabGesture(const QString &gesture)
+Qt::InputMethodHints QGraphicsItem::inputMethodHints() const
{
- int id = QGestureManager::instance()->makeGestureId(gesture);
- d_ptr->grabGesture(id);
- return id;
-}
-
-void QGraphicsItemPrivate::grabGesture(int id)
-{
- Q_Q(QGraphicsItem);
- extraGestures()->gestures << id;
- if (scene)
- scene->d_func()->grabGesture(q, id);
-}
-
-bool QGraphicsItemPrivate::releaseGesture(int id)
-{
- Q_Q(QGraphicsItem);
- QGestureExtraData *extra = maybeExtraGestures();
- if (extra && extra->gestures.contains(id)) {
- if (scene)
- scene->d_func()->releaseGesture(q, id);
- extra->gestures.remove(id);
- return true;
- }
- return false;
+ Q_D(const QGraphicsItem);
+ return d->imHints;
}
/*!
- \since 4.6
-
- Unsubscribes the graphics item from a gesture, which is specified
- by the \a gestureId.
+ Sets the current input method hints of this item to \a hints.
- \sa grabGesture(), setGestureEnabled()
-*/
-void QGraphicsItem::releaseGesture(int gestureId)
-{
- /// TODO: if we are QGraphicsProxyWidget we should unsubscribe the widget from gesture as well.
- if (d_ptr->releaseGesture(gestureId))
- QGestureManager::instance()->releaseGestureId(gestureId);
-}
-
-/*!
\since 4.6
- If \a enable is true, the gesture with the given \a gestureId is
- enabled; otherwise the gesture is disabled.
-
- The id of the gesture is returned by the grabGesture().
-
- \sa grabGesture(), releaseGesture()
+ \sa inputMethodHints(), inputMethodQuery(), QInputContext
*/
-void QGraphicsItem::setGestureEnabled(int gestureId, bool enable)
+void QGraphicsItem::setInputMethodHints(Qt::InputMethodHints hints)
{
- //###
-}
-
-bool QGraphicsItemPrivate::hasGesture(const QString &name) const
-{
- if (QGestureExtraData *extra = maybeExtraGestures()) {
- QGestureManager *gm = QGestureManager::instance();
- QSet<int>::const_iterator it = extra->gestures.begin(),
- e = extra->gestures.end();
- for (; it != e; ++it) {
- if (gm->gestureNameFromId(*it) == name)
- return true;
- }
- }
- return false;
+ Q_D(QGraphicsItem);
+ d->imHints = hints;
}
/*!
@@ -6370,23 +6459,6 @@ bool QGraphicsItemPrivate::hasGesture(const QString &name) const
QVariant QGraphicsItem::itemChange(GraphicsItemChange change, const QVariant &value)
{
Q_UNUSED(change);
- if (change == QGraphicsItem::ItemSceneChange) {
- QGestureExtraData *extra = d_ptr->maybeExtraGestures();
- if (!qVariantValue<QGraphicsScene*>(value) && extra) {
- // the item has been removed from a scene, unsubscribe gestures.
- Q_ASSERT(d_ptr->scene);
- foreach(int id, extra->gestures)
- d_ptr->scene->d_func()->releaseGesture(this, id);
- }
- } else if (change == QGraphicsItem::ItemSceneHasChanged) {
- QGraphicsScene *scene = qVariantValue<QGraphicsScene*>(value);
- QGestureExtraData *extra = d_ptr->maybeExtraGestures();
- if (scene && extra) {
- // item has been added to the scene
- foreach(int id, extra->gestures)
- scene->d_func()->grabGesture(this, id);
- }
- }
return value;
}
@@ -6440,7 +6512,7 @@ void QGraphicsItem::addToIndex()
return;
}
if (d_ptr->scene)
- d_ptr->scene->d_func()->addToIndex(this);
+ d_ptr->scene->d_func()->index->addItem(this);
}
/*!
@@ -6457,7 +6529,7 @@ void QGraphicsItem::removeFromIndex()
return;
}
if (d_ptr->scene)
- d_ptr->scene->d_func()->removeFromIndex(this);
+ d_ptr->scene->d_func()->index->removeItem(this);
}
/*!
@@ -6476,10 +6548,12 @@ 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;
QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func();
+ scenePrivate->index->prepareBoundingRectChange(this);
scenePrivate->markDirty(this, QRectF(),
/*invalidateChildren=*/true,
/*maybeDirtyClipPath=*/!d_ptr->inSetPosHelper);
@@ -6488,12 +6562,15 @@ void QGraphicsItem::prepareGeometryChange()
// if someone is connected to the changed signal or the scene has no views.
// Note that this has to be done *after* markDirty to ensure that
// _q_processDirtyItems is called before _q_emitUpdated.
- if ((scenePrivate->connectedSignals & scenePrivate->changedSignalMask)
+ if ((scenePrivate->connectedSignals[0] & 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()));
+ }
}
-
- scenePrivate->removeFromIndex(this);
}
QGraphicsItem *parent = this;
@@ -6695,6 +6772,41 @@ QGraphicsObject::QGraphicsObject(QGraphicsItemPrivate &dd, QGraphicsItem *parent
\sa pos()
*/
+/*!
+ \property QGraphicsObject::rotation
+ This property holds the rotation of the item in degrees.
+
+ This specifies how many degrees to rotate the item around its transformOrigin.
+ The default rotation is 0 degrees (i.e. not rotated at all).
+*/
+
+/*!
+ \fn QGraphicsObject::rotationChanged()
+
+ This signal gets emitted whenever the roation of the item changes.
+*/
+
+/*!
+ \property QGraphicsObject::scale
+ This property holds the scale of the item.
+
+ A scale of less than 1 means the item will be displayed smaller than
+ normal, and a scale of greater than 1 means the item will be
+ displayed larger than normal. A negative scale means the item will
+ be mirrored.
+
+ By default, items are displayed at a scale of 1 (i.e. at their
+ normal size).
+
+ Scaling is from the item's transformOrigin.
+*/
+
+/*!
+ \fn void QGraphicsObject::scaleChanged()
+
+ This signal is emitted when the scale of the item changes.
+*/
+
/*!
\property QGraphicsObject::enabled
@@ -6734,6 +6846,25 @@ QGraphicsObject::QGraphicsObject(QGraphicsItemPrivate &dd, QGraphicsItem *parent
\sa visible
*/
+/*!
+ \fn const QObjectList &QGraphicsObject::children() const
+ \internal
+
+ This function returns the same value as QObject::children(). It's
+ provided to differentiate between the obsolete member
+ QGraphicsItem::children() and QObject::children(). QGraphicsItem now
+ provides childItems() instead.
+*/
+
+/*!
+ \property QGraphicsObject::transformOriginPoint
+ \brief the transformation origin
+
+ This property sets a specific point in the items coordiante system as the
+ origin for scale and rotation.
+
+ \sa scale, rotation, QGraphicsItem::transformOriginPoint()
+*/
/*!
@@ -9743,13 +9874,10 @@ QVariant QGraphicsSimpleTextItem::extension(const QVariant &variant) const
setParentItem().
The boundingRect() function of QGraphicsItemGroup returns the
- bounding rectangle of all items in the item group. In addition,
- item groups have handlesChildEvents() enabled by default, so all
- events sent to a member of the group go to the item group (i.e.,
- selecting one item in a group will select them all).
- QGraphicsItemGroup ignores the ItemIgnoresTransformations flag on its
- children (i.e., with respect to the geometry of the group item, the
- children are treated as if they were transformable).
+ bounding rectangle of all items in the item group.
+ QGraphicsItemGroup ignores the ItemIgnoresTransformations flag on
+ its children (i.e., with respect to the geometry of the group
+ item, the children are treated as if they were transformable).
There are two ways to construct an item group. The easiest and
most common approach is to pass a list of items (e.g., all
@@ -9939,17 +10067,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;
}
@@ -10083,6 +10205,12 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag)
case QGraphicsItem::ItemSendsGeometryChanges:
str = "ItemSendsGeometryChanges";
break;
+ case QGraphicsItem::ItemAcceptsInputMethod:
+ str = "ItemAcceptsInputMethod";
+ break;
+ case QGraphicsItem::ItemAutoDetectsFocusProxy:
+ str = "ItemAutoDetectsFocusProxy";
+ break;
}
debug << str;
return debug;
diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h
index 0b93c27..465525f 100644
--- a/src/gui/graphicsview/qgraphicsitem.h
+++ b/src/gui/graphicsview/qgraphicsitem.h
@@ -72,6 +72,7 @@ class QGraphicsSceneHoverEvent;
class QGraphicsSceneMouseEvent;
class QGraphicsSceneWheelEvent;
class QGraphicsScene;
+class QGraphicsTransform;
class QGraphicsWidget;
class QInputMethodEvent;
class QKeyEvent;
@@ -99,7 +100,9 @@ public:
ItemStacksBehindParent = 0x100,
ItemUsesExtendedStyleOption = 0x200,
ItemHasNoContents = 0x400,
- ItemSendsGeometryChanges = 0x800
+ ItemSendsGeometryChanges = 0x800,
+ ItemAcceptsInputMethod = 0x1000,
+ ItemAutoDetectsFocusProxy = 0x2000
// NB! Don't forget to increase the d_ptr->flags bit field by 1 when adding a new flag.
};
Q_DECLARE_FLAGS(GraphicsItemFlags, GraphicsItemFlag)
@@ -142,7 +145,7 @@ public:
QGraphicsItem(QGraphicsItem *parent = 0
#ifndef Q_QDOC
- // obsolete argument
+ // ### obsolete argument
, QGraphicsScene *scene = 0
#endif
);
@@ -209,13 +212,16 @@ 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);
bool acceptTouchEvents() const;
void setAcceptTouchEvents(bool enabled);
+ bool filtersChildEvents() const;
+ void setFiltersChildEvents(bool enabled);
+
bool handlesChildEvents() const;
void setHandlesChildEvents(bool enabled);
@@ -223,6 +229,11 @@ public:
void setFocus(Qt::FocusReason focusReason = Qt::OtherFocusReason);
void clearFocus();
+ QGraphicsItem *focusProxy() const;
+ void setFocusProxy(QGraphicsItem *item);
+
+ QGraphicsItem *focusItem() const;
+
void grabMouse();
void ungrabMouse();
void grabKeyboard();
@@ -259,34 +270,19 @@ public:
void shear(qreal sh, qreal sv); // ### obsolete
void translate(qreal dx, qreal dy); // ### obsolete
- qreal xRotation() const;
- void setXRotation(qreal angle);
-
- qreal yRotation() const;
- void setYRotation(qreal angle);
-
- qreal zRotation() const;
- void setZRotation(qreal angle);
- void setRotation(qreal x, qreal y, qreal z);
+ void setRotation(qreal angle);
+ qreal rotation() const;
- qreal xScale() const;
- void setXScale(qreal factor);
+ void setScale(qreal scale);
+ qreal scale() const;
- qreal yScale() const;
- void setYScale(qreal factor);
- void setScale(qreal sx, qreal sy);
+ QList<QGraphicsTransform *> transformations() const;
+ void setTransformations(const QList<QGraphicsTransform *> &transformations);
- qreal horizontalShear() const;
- void setHorizontalShear(qreal shear);
-
- qreal verticalShear() const;
- void setVerticalShear(qreal shear);
- void setShear(qreal sh, qreal sv);
-
- QPointF transformOrigin() const;
- void setTransformOrigin(const QPointF &origin);
- inline void setTransformOrigin(qreal x, qreal y)
- { setTransformOrigin(QPointF(x,y)); }
+ QPointF transformOriginPoint() const;
+ void setTransformOriginPoint(const QPointF &origin);
+ inline void setTransformOriginPoint(qreal x, qreal y)
+ { setTransformOriginPoint(QPointF(x,y)); }
virtual void advance(int phase);
@@ -380,10 +376,8 @@ public:
QVariant data(int key) const;
void setData(int key, const QVariant &value);
- int grabGesture(Qt::GestureType gesture);
- int grabGesture(const QString &gesture);
- void releaseGesture(int gestureId);
- void setGestureEnabled(int gestureId, bool enable = true);
+ Qt::InputMethodHints inputMethodHints() const;
+ void setInputMethodHints(Qt::InputMethodHints hints);
enum {
Type = 1,
@@ -437,16 +431,22 @@ protected:
private:
Q_DISABLE_COPY(QGraphicsItem)
- Q_DECLARE_SCOPED_PRIVATE(QGraphicsItem)
+ Q_DECLARE_PRIVATE(QGraphicsItem)
friend class QGraphicsItemGroup;
friend class QGraphicsScene;
friend class QGraphicsScenePrivate;
friend class QGraphicsSceneFindItemBspTreeVisitor;
+ friend class QGraphicsSceneBspTree;
friend class QGraphicsView;
friend class QGraphicsViewPrivate;
friend class QGraphicsWidget;
friend class QGraphicsWidgetPrivate;
friend class QGraphicsProxyWidgetPrivate;
+ friend class QGraphicsSceneIndex;
+ friend class QGraphicsSceneIndexPrivate;
+ friend class QGraphicsSceneBspTreeIndex;
+ friend class QGraphicsSceneBspTreeIndexPrivate;
+ friend class QGraphicsTransformPrivate;
friend class ::tst_QGraphicsItem;
friend bool qt_closestLeaf(const QGraphicsItem *, const QGraphicsItem *);
friend bool qt_closestItemFirst(const QGraphicsItem *, const QGraphicsItem *);
@@ -512,9 +512,19 @@ class Q_GUI_EXPORT QGraphicsObject : public QObject, public QGraphicsItem
Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
Q_PROPERTY(qreal z READ zValue WRITE setZValue NOTIFY zChanged)
+ Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged)
+ Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged)
+ Q_PROPERTY(QPointF transformOriginPoint READ transformOriginPoint WRITE setTransformOriginPoint)
public:
QGraphicsObject(QGraphicsItem *parent = 0);
+ // ### Qt 5: Disambiguate
+#ifdef Q_NO_USING_KEYWORD
+ const QObjectList &children() const { return QObject::children(); }
+#else
+ using QObject::children;
+#endif
+
Q_SIGNALS:
void parentChanged();
void opacityChanged();
@@ -523,6 +533,8 @@ Q_SIGNALS:
void xChanged();
void yChanged();
void zChanged();
+ void rotationChanged();
+ void scaleChanged();
protected:
QGraphicsObject(QGraphicsItemPrivate &dd, QGraphicsItem *parent, QGraphicsScene *scene);
@@ -538,7 +550,7 @@ class Q_GUI_EXPORT QAbstractGraphicsShapeItem : public QGraphicsItem
public:
QAbstractGraphicsShapeItem(QGraphicsItem *parent = 0
#ifndef Q_QDOC
- // obsolete argument
+ // ### obsolete argument
, QGraphicsScene *scene = 0
#endif
);
@@ -559,7 +571,7 @@ protected:
private:
Q_DISABLE_COPY(QAbstractGraphicsShapeItem)
- Q_DECLARE_SCOPED_PRIVATE(QAbstractGraphicsShapeItem)
+ Q_DECLARE_PRIVATE(QAbstractGraphicsShapeItem)
};
class QGraphicsPathItemPrivate;
@@ -568,13 +580,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
);
@@ -602,7 +614,7 @@ protected:
private:
Q_DISABLE_COPY(QGraphicsPathItem)
- Q_DECLARE_SCOPED_PRIVATE(QGraphicsPathItem)
+ Q_DECLARE_PRIVATE(QGraphicsPathItem)
};
class QGraphicsRectItemPrivate;
@@ -611,19 +623,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
);
@@ -652,7 +664,7 @@ protected:
private:
Q_DISABLE_COPY(QGraphicsRectItem)
- Q_DECLARE_SCOPED_PRIVATE(QGraphicsRectItem)
+ Q_DECLARE_PRIVATE(QGraphicsRectItem)
};
inline void QGraphicsRectItem::setRect(qreal ax, qreal ay, qreal w, qreal h)
@@ -664,19 +676,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
);
@@ -711,7 +723,7 @@ protected:
private:
Q_DISABLE_COPY(QGraphicsEllipseItem)
- Q_DECLARE_SCOPED_PRIVATE(QGraphicsEllipseItem)
+ Q_DECLARE_PRIVATE(QGraphicsEllipseItem)
};
inline void QGraphicsEllipseItem::setRect(qreal ax, qreal ay, qreal w, qreal h)
@@ -723,14 +735,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
);
@@ -761,7 +773,7 @@ protected:
private:
Q_DISABLE_COPY(QGraphicsPolygonItem)
- Q_DECLARE_SCOPED_PRIVATE(QGraphicsPolygonItem)
+ Q_DECLARE_PRIVATE(QGraphicsPolygonItem)
};
class QGraphicsLineItemPrivate;
@@ -770,19 +782,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
);
@@ -815,7 +827,7 @@ protected:
private:
Q_DISABLE_COPY(QGraphicsLineItem)
- Q_DECLARE_SCOPED_PRIVATE(QGraphicsLineItem)
+ Q_DECLARE_PRIVATE(QGraphicsLineItem)
};
class QGraphicsPixmapItemPrivate;
@@ -830,13 +842,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
);
@@ -874,7 +886,7 @@ protected:
private:
Q_DISABLE_COPY(QGraphicsPixmapItem)
- Q_DECLARE_SCOPED_PRIVATE(QGraphicsPixmapItem)
+ Q_DECLARE_PRIVATE(QGraphicsPixmapItem)
};
inline void QGraphicsPixmapItem::setOffset(qreal ax, qreal ay)
@@ -892,13 +904,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
);
@@ -993,13 +1005,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
);
@@ -1030,7 +1042,7 @@ protected:
private:
Q_DISABLE_COPY(QGraphicsSimpleTextItem)
- Q_DECLARE_SCOPED_PRIVATE(QGraphicsSimpleTextItem)
+ Q_DECLARE_PRIVATE(QGraphicsSimpleTextItem)
};
class QGraphicsItemGroupPrivate;
@@ -1039,7 +1051,7 @@ class Q_GUI_EXPORT QGraphicsItemGroup : public QGraphicsItem
public:
QGraphicsItemGroup(QGraphicsItem *parent = 0
#ifndef Q_QDOC
- // obsolete argument
+ // ### obsolete argument
, QGraphicsScene *scene = 0
#endif
);
@@ -1059,7 +1071,7 @@ public:
private:
Q_DISABLE_COPY(QGraphicsItemGroup)
- Q_DECLARE_SCOPED_PRIVATE(QGraphicsItemGroup)
+ Q_DECLARE_PRIVATE(QGraphicsItemGroup)
};
template <class T> inline T qgraphicsitem_cast(QGraphicsItem *item)
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index 15b9ab6..239c250 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -57,6 +57,8 @@
#include "qset.h"
#include "qpixmapcache.h"
#include <private/qgraphicsview_p.h>
+#include "qgraphicstransform.h"
+#include <private/qgraphicstransform_p.h>
#include <QtCore/qpoint.h>
@@ -93,12 +95,6 @@ public:
void purge();
};
-class QGestureExtraData
-{
-public:
- QSet<int> gestures;
-};
-
class Q_AUTOTEST_EXPORT QGraphicsItemPrivate
{
Q_DECLARE_PUBLIC(QGraphicsItem)
@@ -108,15 +104,15 @@ public:
ExtraCursor,
ExtraCacheData,
ExtraMaxDeviceCoordCacheSize,
- ExtraBoundingRegionGranularity,
- ExtraGestures
+ ExtraBoundingRegionGranularity
};
enum AncestorFlag {
NoFlag = 0,
AncestorHandlesChildEvents = 0x1,
AncestorClipsChildren = 0x2,
- AncestorIgnoresTransformations = 0x4
+ AncestorIgnoresTransformations = 0x4,
+ AncestorFiltersChildEvents = 0x8
};
inline QGraphicsItemPrivate()
@@ -126,7 +122,11 @@ public:
parent(0),
transformData(0),
index(-1),
+ siblingIndex(-1),
depth(0),
+ focusProxy(0),
+ subFocusItem(0),
+ imHints(Qt::ImhNone),
acceptedMouseButtons(0x1f),
visible(1),
explicitlyHidden(0),
@@ -156,13 +156,15 @@ public:
dirtyChildrenBoundingRect(1),
paintedViewBoundingRectsNeedRepaint(0),
dirtySceneTransform(1),
- geometryChanged(0),
+ geometryChanged(1),
inDestructor(0),
isObject(0),
ignoreVisible(0),
ignoreOpacity(0),
acceptTouchEvents(0),
acceptedTouchBeginEvent(0),
+ filtersDescendantEvents(0),
+ sceneTransformTranslateOnly(0),
globalStackingOrder(-1),
q_ptr(0)
{
@@ -171,6 +173,15 @@ public:
inline virtual ~QGraphicsItemPrivate()
{ }
+ static const QGraphicsItemPrivate *get(const QGraphicsItem *item)
+ {
+ return item->d_ptr.data();
+ }
+ static QGraphicsItemPrivate *get(QGraphicsItem *item)
+ {
+ return item->d_ptr.data();
+ }
+
void updateAncestorFlag(QGraphicsItem::GraphicsItemFlag childFlag,
AncestorFlag flag = NoFlag, bool enabled = false, bool root = true);
void setIsMemberOfGroup(bool enabled);
@@ -184,6 +195,7 @@ public:
void combineTransformToParent(QTransform *x, const QTransform *viewTransform = 0) const;
void combineTransformFromParent(QTransform *x, const QTransform *viewTransform = 0) const;
+ virtual void updateSceneTransformFromParent();
// ### Qt 5: Remove. Workaround for reimplementation added after Qt 4.4.
virtual QVariant inputMethodQueryHelper(Qt::InputMethodQuery query) const;
@@ -191,6 +203,7 @@ public:
void setPosHelper(const QPointF &pos);
void setTransformHelper(const QTransform &transform);
+ void appendGraphicsTransform(QGraphicsTransform *t);
void setVisibleHelper(bool newVisible, bool explicitly, bool update = true);
void setEnabledHelper(bool newEnabled, bool explicitly, bool update = true);
bool discardUpdateRequest(bool ignoreClipping = false, bool ignoreVisibleBit = false,
@@ -293,6 +306,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()
{
@@ -376,7 +396,11 @@ public:
|| (childrenCombineOpacity() && isFullyTransparent());
}
+ void setSubFocus();
+ void clearSubFocus();
+
inline QTransform transformToParent() const;
+ inline void ensureSortedChildren();
QPainterPath cachedClipPath;
QRectF childrenBoundingRect;
@@ -392,33 +416,13 @@ public:
TransformData *transformData;
QTransform sceneTransform;
int index;
+ int siblingIndex;
int depth;
+ QGraphicsItem *focusProxy;
+ QGraphicsItem *subFocusItem;
+ Qt::InputMethodHints imHints;
- inline QGestureExtraData* extraGestures() const
- {
- QGestureExtraData *c = (QGestureExtraData *)qVariantValue<void *>(extra(ExtraGestures));
- if (!c) {
- QGraphicsItemPrivate *that = const_cast<QGraphicsItemPrivate *>(this);
- c = new QGestureExtraData;
- that->setExtra(ExtraGestures, qVariantFromValue<void *>(c));
- }
- return c;
- }
- QGestureExtraData* maybeExtraGestures() const
- {
- return (QGestureExtraData *)qVariantValue<void *>(extra(ExtraGestures));
- }
- inline void removeExtraGestures()
- {
- QGestureExtraData *c = (QGestureExtraData *)qVariantValue<void *>(extra(ExtraGestures));
- delete c;
- unsetExtra(ExtraGestures);
- }
- bool hasGesture(const QString &gesture) const;
- void grabGesture(int id);
- bool releaseGesture(int id);
-
- // Packed 32 bytes
+ // Packed 32 bits
quint32 acceptedMouseButtons : 5;
quint32 visible : 1;
quint32 explicitlyHidden : 1;
@@ -431,7 +435,7 @@ public:
quint32 handlesChildEvents : 1;
quint32 itemDiscovered : 1;
quint32 hasCursor : 1;
- quint32 ancestorFlags : 3;
+ quint32 ancestorFlags : 4;
quint32 cacheMode : 2;
quint32 hasBoundingRegionGranularity : 1;
quint32 isWidget : 1;
@@ -443,13 +447,13 @@ public:
quint32 inSetPosHelper : 1;
quint32 needSortChildren : 1;
quint32 allChildrenDirty : 1;
- quint32 fullUpdatePending : 1;
// New 32 bits
- quint32 flags : 12;
+ quint32 fullUpdatePending : 1;
+ quint32 flags : 14;
quint32 dirtyChildrenBoundingRect : 1;
quint32 paintedViewBoundingRectsNeedRepaint : 1;
- quint32 dirtySceneTransform : 1;
+ quint32 dirtySceneTransform : 1;
quint32 geometryChanged : 1;
quint32 inDestructor : 1;
quint32 isObject : 1;
@@ -457,50 +461,47 @@ public:
quint32 ignoreOpacity : 1;
quint32 acceptTouchEvents : 1;
quint32 acceptedTouchBeginEvent : 1;
- quint32 unused : 10; // feel free to use
+ quint32 filtersDescendantEvents : 1;
+ quint32 sceneTransformTranslateOnly : 1;
+ quint32 unused : 5; // feel free to use
// Optional stacking order
int globalStackingOrder;
QGraphicsItem *q_ptr;
};
-struct QGraphicsItemPrivate::TransformData {
+struct QGraphicsItemPrivate::TransformData
+{
QTransform transform;
- qreal xScale;
- qreal yScale;
- qreal xRotation;
- qreal yRotation;
- qreal zRotation;
- qreal horizontalShear;
- qreal verticalShear;
+ qreal scale;
+ qreal rotation;
qreal xOrigin;
qreal yOrigin;
+ QList<QGraphicsTransform *> graphicsTransforms;
bool onlyTransform;
TransformData() :
- xScale(1.0), yScale(1.0), xRotation(0.0), yRotation(0.0), zRotation(0.0),
- horizontalShear(0.0), verticalShear(0.0), xOrigin(0.0), yOrigin(0.0),
+ scale(1.0), rotation(0.0),
+ xOrigin(0.0), yOrigin(0.0),
onlyTransform(true)
- {}
+ { }
QTransform computedFullTransform(QTransform *postmultiplyTransform = 0) const
{
if (onlyTransform) {
- if (!postmultiplyTransform)
+ if (!postmultiplyTransform || postmultiplyTransform->isIdentity())
return transform;
- QTransform x(transform);
- x *= *postmultiplyTransform;
- return x;
+ if (transform.isIdentity())
+ return *postmultiplyTransform;
+ return transform * *postmultiplyTransform;
}
QTransform x(transform);
- if (xOrigin != 0 || yOrigin != 0)
- x *= QTransform::fromTranslate(xOrigin, yOrigin);
- x.rotate(xRotation, Qt::XAxis);
- x.rotate(yRotation, Qt::YAxis);
- x.rotate(zRotation, Qt::ZAxis);
- x.shear(horizontalShear, verticalShear);
- x.scale(xScale, yScale);
+ for (int i = 0; i < graphicsTransforms.size(); ++i)
+ graphicsTransforms.at(i)->applyTo(&x);
+ x.translate(xOrigin, yOrigin);
+ x.rotate(rotation, Qt::ZAxis);
+ x.scale(scale, scale);
x.translate(-xOrigin, -yOrigin);
if (postmultiplyTransform)
x *= *postmultiplyTransform;
@@ -508,6 +509,29 @@ 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.data();
+ const QGraphicsItemPrivate *d2 = item2->d_ptr.data();
+ 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); }
+
/*
return the full transform of the item to the parent. This include the position and all the transform data
*/
@@ -518,6 +542,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/qgraphicslayout.h b/src/gui/graphicsview/qgraphicslayout.h
index d2c45ab..7c758bc 100644
--- a/src/gui/graphicsview/qgraphicslayout.h
+++ b/src/gui/graphicsview/qgraphicslayout.h
@@ -81,7 +81,7 @@ protected:
private:
Q_DISABLE_COPY(QGraphicsLayout)
- Q_DECLARE_SCOPED_PRIVATE(QGraphicsLayout)
+ Q_DECLARE_PRIVATE(QGraphicsLayout)
friend class QGraphicsWidget;
};
diff --git a/src/gui/graphicsview/qgraphicslayoutitem.cpp b/src/gui/graphicsview/qgraphicslayoutitem.cpp
index 0fe648e..acf591a 100644
--- a/src/gui/graphicsview/qgraphicslayoutitem.cpp
+++ b/src/gui/graphicsview/qgraphicslayoutitem.cpp
@@ -807,6 +807,8 @@ bool QGraphicsLayoutItem::isLayout() const
}
/*!
+ \since 4.6
+
Returns whether a layout should delete this item in its destructor.
If its true, then the layout will delete it. If its false, then it is
assumed that another object has the ownership of it, and the layout won't
@@ -833,6 +835,8 @@ bool QGraphicsLayoutItem::ownedByLayout() const
return d_func()->ownedByLayout;
}
/*!
+ \since 4.6
+
Sets whether a layout should delete this item in its destructor or not.
\a ownership must be true to in order for the layout to delete it.
\sa ownedByLayout()
diff --git a/src/gui/graphicsview/qgraphicslayoutitem.h b/src/gui/graphicsview/qgraphicslayoutitem.h
index 156c843..60f894f 100644
--- a/src/gui/graphicsview/qgraphicslayoutitem.h
+++ b/src/gui/graphicsview/qgraphicslayoutitem.h
@@ -117,7 +117,7 @@ protected:
private:
QSizeF *effectiveSizeHints(const QSizeF &constraint) const;
- Q_DECLARE_SCOPED_PRIVATE(QGraphicsLayoutItem)
+ Q_DECLARE_PRIVATE(QGraphicsLayoutItem)
friend class QGraphicsLayout;
};
diff --git a/src/gui/graphicsview/qgraphicslinearlayout.h b/src/gui/graphicsview/qgraphicslinearlayout.h
index 91335db..f469680 100644
--- a/src/gui/graphicsview/qgraphicslinearlayout.h
+++ b/src/gui/graphicsview/qgraphicslinearlayout.h
@@ -108,7 +108,7 @@ protected:
private:
Q_DISABLE_COPY(QGraphicsLinearLayout)
- Q_DECLARE_SCOPED_PRIVATE(QGraphicsLinearLayout)
+ Q_DECLARE_PRIVATE(QGraphicsLinearLayout)
};
#endif
diff --git a/src/gui/graphicsview/qgraphicsproxywidget.cpp b/src/gui/graphicsview/qgraphicsproxywidget.cpp
index ab94679..5fac6cf 100644
--- a/src/gui/graphicsview/qgraphicsproxywidget.cpp
+++ b/src/gui/graphicsview/qgraphicsproxywidget.cpp
@@ -48,7 +48,6 @@
#include "private/qgraphicsproxywidget_p.h"
#include "private/qwidget_p.h"
#include "private/qapplication_p.h"
-#include "private/qgesturemanager_p.h"
#include <QtCore/qdebug.h>
#include <QtGui/qevent.h>
@@ -452,6 +451,22 @@ void QGraphicsProxyWidgetPrivate::updateProxyGeometryFromWidget()
/*!
\internal
+*/
+void QGraphicsProxyWidgetPrivate::updateProxyInputMethodAcceptanceFromWidget()
+{
+ Q_Q(QGraphicsProxyWidget);
+ if (!widget)
+ return;
+
+ QWidget *focusWidget = widget->focusWidget();
+ if (!focusWidget)
+ focusWidget = widget;
+ q->setFlag(QGraphicsItem::ItemAcceptsInputMethod,
+ focusWidget->testAttribute(Qt::WA_InputMethodEnabled));
+}
+
+/*!
+ \internal
Embeds \a subWin as a subwindow of this proxy widget. \a subWin must be a top-level
widget and a descendant of the widget managed by this proxy. A separate subproxy
@@ -649,9 +664,6 @@ void QGraphicsProxyWidgetPrivate::setWidget_helper(QWidget *newWidget, bool auto
q->setAttribute(Qt::WA_OpaquePaintEvent);
widget = newWidget;
- foreach(int gestureId, widget->d_func()->gestures) {
- grabGesture(gestureId);
- }
// Changes only go from the widget to the proxy.
enabledChangeMode = QGraphicsProxyWidgetPrivate::WidgetToProxyMode;
@@ -694,6 +706,8 @@ void QGraphicsProxyWidgetPrivate::setWidget_helper(QWidget *newWidget, bool auto
updateProxyGeometryFromWidget();
+ updateProxyInputMethodAcceptanceFromWidget();
+
// Hook up the event filter to keep the state up to date.
newWidget->installEventFilter(q);
QObject::connect(newWidget, SIGNAL(destroyed()), q, SLOT(_q_removeWidgetSlot()));
@@ -875,16 +889,6 @@ bool QGraphicsProxyWidget::event(QEvent *event)
}
break;
}
- case QEvent::GraphicsSceneGesture: {
- qDebug() << "QGraphicsProxyWidget: graphicsscenegesture";
- if (d->widget && d->widget->isVisible()) {
- QGraphicsSceneGestureEvent *ge = static_cast<QGraphicsSceneGestureEvent*>(event);
- //### TODO: widget->childAt(): decompose gesture event and find widget under hotspots.
- //QGestureManager::instance()->sendGestureEvent(d->widget, ge->gestures().toSet(), ge->cancelledGestures());
- return true;
- }
- break;
- }
default:
break;
}
@@ -1317,8 +1321,8 @@ void QGraphicsProxyWidget::focusInEvent(QFocusEvent *event)
if (d->widget && d->widget->focusWidget()) {
d->widget->focusWidget()->setFocus(event->reason());
return;
- }
- break;
+ }
+ break;
}
}
diff --git a/src/gui/graphicsview/qgraphicsproxywidget_p.h b/src/gui/graphicsview/qgraphicsproxywidget_p.h
index ec5400a..fbc9f6c 100644
--- a/src/gui/graphicsview/qgraphicsproxywidget_p.h
+++ b/src/gui/graphicsview/qgraphicsproxywidget_p.h
@@ -102,6 +102,8 @@ public:
void updateWidgetGeometryFromProxy();
void updateProxyGeometryFromWidget();
+ void updateProxyInputMethodAcceptanceFromWidget();
+
QPointF mapToReceiver(const QPointF &pos, const QWidget *receiver) const;
enum ChangeMode {
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 13d3bd6..9b9c9c2 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -39,7 +39,6 @@
**
****************************************************************************/
-
/*!
\class QGraphicsScene
\brief The QGraphicsScene class provides a surface for managing a large
@@ -218,6 +217,9 @@
#include "qgraphicsview_p.h"
#include "qgraphicswidget.h"
#include "qgraphicswidget_p.h"
+#include "qgraphicssceneindex_p.h"
+#include "qgraphicsscenebsptreeindex_p.h"
+#include "qgraphicsscenelinearindex_p.h"
#include <QtCore/qdebug.h>
#include <QtCore/qlist.h>
@@ -242,77 +244,15 @@
#include <QtGui/qtooltip.h>
#include <QtGui/qtransform.h>
#include <QtGui/qgesture.h>
+#include <QtGui/qinputcontext.h>
#include <private/qapplication_p.h>
#include <private/qobject_p.h>
#ifdef Q_WS_X11
#include <private/qt_x11_p.h>
#endif
-#include <private/qgesturemanager_p.h>
-#include <private/qgesture_p.h>
QT_BEGIN_NAMESPACE
-static inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2);
-
-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());
@@ -332,18 +272,15 @@ static void _q_hoverFromMouseEvent(QGraphicsSceneHoverEvent *hover, const QGraph
QGraphicsScenePrivate::QGraphicsScenePrivate()
: changedSignalMask(0),
indexMethod(QGraphicsScene::BspTreeIndex),
- bspTreeDepth(0),
+ index(0),
lastItemCount(0),
hasSceneRect(false),
+ dirtyGrowingItemsBoundingRect(true),
updateAll(false),
calledEmitUpdated(false),
processDirtyItemsEmitted(false),
selectionChanging(0),
needSortTopLevelItems(true),
- regenerateIndex(true),
- purgePending(false),
- indexTimerId(0),
- restartIndexTimer(false),
stickyFocus(false),
hasFocus(false),
focusItem(0),
@@ -360,7 +297,6 @@ QGraphicsScenePrivate::QGraphicsScenePrivate()
allItemsUseDefaultCursor(true),
painterStateProtection(true),
sortCacheEnabled(false),
- updatingSortCache(false),
style(0),
allItemsIgnoreTouchEvents(true)
{
@@ -373,6 +309,8 @@ void QGraphicsScenePrivate::init()
{
Q_Q(QGraphicsScene);
+ index = new QGraphicsSceneBspTreeIndex(q);
+
// Keep this index so we can check for connected slots later on.
changedSignalMask = (1 << q->metaObject()->indexOfSignal("changed(QList<QRectF>)"));
qApp->d_func()->scene_list.append(q);
@@ -382,229 +320,31 @@ void QGraphicsScenePrivate::init()
/*!
\internal
*/
-QList<QGraphicsItem *> QGraphicsScenePrivate::estimateItemsInRect(const QRectF &rect) const
+QGraphicsScenePrivate *QGraphicsScenePrivate::get(QGraphicsScene *q)
{
- const_cast<QGraphicsScenePrivate *>(this)->purgeRemovedItems();
- const_cast<QGraphicsScenePrivate *>(this)->_q_updateSortCache();
-
- if (indexMethod == QGraphicsScene::BspTreeIndex) {
- // ### Only do this once in a while.
- QGraphicsScenePrivate *that = const_cast<QGraphicsScenePrivate *>(this);
-
- // Get items from BSP tree
- QList<QGraphicsItem *> items = that->bspTree.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 (QRectF_intersects(boundingRect, rect)) {
- 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<QGraphicsItem *> 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->d_ptr->isFullyTransparent())
- itemsInRect << item;
- }
- }
- 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->d_ptr->isFullyTransparent())
- itemsInRect << item;
- }
- }
-
- return itemsInRect;
+ return q->d_func();
}
-/*!
- \internal
-*/
-void QGraphicsScenePrivate::addToIndex(QGraphicsItem *item)
-{
- if (indexMethod == QGraphicsScene::BspTreeIndex) {
- if (item->d_func()->index != -1) {
- bspTree.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();
- }
- }
-}
-
-/*!
- \internal
-*/
-void QGraphicsScenePrivate::removeFromIndex(QGraphicsItem *item)
-{
- if (indexMethod == QGraphicsScene::BspTreeIndex) {
- int index = item->d_func()->index;
- if (index != -1) {
- bspTree.removeItem(item, item->sceneBoundingRect());
- freeItemIndexes << index;
- indexedItems[index] = 0;
- item->d_func()->index = -1;
- unindexedItems << item;
-
- foreach (QGraphicsItem *child, item->children())
- child->removeFromIndex();
- }
-
- startIndexTimer();
- }
-}
-
-/*!
- \internal
-*/
-void QGraphicsScenePrivate::resetIndex()
-{
- purgeRemovedItems();
- if (indexMethod == QGraphicsScene::BspTreeIndex) {
- 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();
- }
-}
-
-static inline int intmaxlog(int n)
-{
- return (n > 0 ? qMax(qCeil(qLn(qreal(n)) / qLn(qreal(2))), 5) : 0);
-}
-
-/*!
- \internal
-*/
-void QGraphicsScenePrivate::_q_updateIndex()
+void QGraphicsScenePrivate::_q_emitUpdated()
{
- if (!indexTimerId)
- return;
-
Q_Q(QGraphicsScene);
- 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 = growingItemsBoundingRect;
- growingItemsBoundingRect |= unindexedItemsBoundingRect;
-
- // Determine whether we should regenerate the BSP tree.
- if (indexMethod == QGraphicsScene::BspTreeIndex) {
- int depth = bspTreeDepth;
- if (depth == 0) {
- int oldDepth = intmaxlog(lastItemCount);
- depth = intmaxlog(indexedItems.size());
- static const int slack = 100;
- if (bspTree.leafCount() == 0 || (oldDepth != depth && qAbs(lastItemCount - indexedItems.size()) > slack)) {
- // ### Crude algorithm.
- regenerateIndex = true;
- }
- }
+ calledEmitUpdated = false;
- // Regenerate the tree.
- if (regenerateIndex) {
- regenerateIndex = false;
- bspTree.initialize(q->sceneRect(), depth);
- unindexedItems = indexedItems;
- 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();
+ if (dirtyGrowingItemsBoundingRect) {
+ if (!hasSceneRect) {
+ const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect;
+ growingItemsBoundingRect |= q->itemsBoundingRect();
+ if (oldGrowingItemsBoundingRect != growingItemsBoundingRect)
+ emit q->sceneRectChanged(growingItemsBoundingRect);
}
+ dirtyGrowingItemsBoundingRect = false;
}
- // 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;
- if (indexMethod == QGraphicsScene::BspTreeIndex)
- bspTree.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.
- largestUntransformableItem |= item->mapToItem(topmostUntransformable, item->boundingRect()).boundingRect();
- }
- }
- }
- unindexedItems.clear();
-
- // Notify scene rect changes.
- if (!hasSceneRect && growingItemsBoundingRect != oldGrowingItemsBoundingRect)
- emit q->sceneRectChanged(growingItemsBoundingRect);
-}
-
-/*!
- \internal
-*/
-void QGraphicsScenePrivate::_q_emitUpdated()
-{
- Q_Q(QGraphicsScene);
- calledEmitUpdated = 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
// Qt 4.4 and backward.
- if (connectedSignals & changedSignalMask) {
+ if (connectedSignals[0] & changedSignalMask) {
for (int i = 0; i < views.size(); ++i) {
QGraphicsView *view = views.at(i);
if (!view->d_func()->connectedToScene) {
@@ -617,6 +357,9 @@ void QGraphicsScenePrivate::_q_emitUpdated()
updateAll = false;
for (int i = 0; i < views.size(); ++i)
views.at(i)->d_func()->processPendingUpdates();
+ // It's important that we update all views before we dispatch, hence two for-loops.
+ for (int i = 0; i < views.size(); ++i)
+ views.at(i)->d_func()->dispatchPendingUpdateRequests();
return;
}
@@ -634,6 +377,7 @@ void QGraphicsScenePrivate::_q_emitUpdated()
void QGraphicsScenePrivate::registerTopLevelItem(QGraphicsItem *item)
{
needSortTopLevelItems = true;
+ item->d_ptr->siblingIndex = topLevelItems.size();
topLevelItems.append(item);
}
@@ -643,19 +387,10 @@ void QGraphicsScenePrivate::registerTopLevelItem(QGraphicsItem *item)
void QGraphicsScenePrivate::unregisterTopLevelItem(QGraphicsItem *item)
{
topLevelItems.removeOne(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()
-{
- foreach (QGraphicsItem *item, pendingUpdateItems)
- item->update();
- pendingUpdateItems.clear();
+ // 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;
}
/*!
@@ -681,9 +416,23 @@ 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);
@@ -701,13 +450,8 @@ void QGraphicsScenePrivate::_q_processDirtyItems()
}
// Immediately dispatch all pending update requests on the views.
- for (int i = 0; i < views.size(); ++i) {
- QWidget *viewport = views.at(i)->d_func()->viewport;
- if (qt_widget_private(viewport)->paintOnScreen())
- QCoreApplication::sendPostedEvents(viewport, QEvent::UpdateRequest);
- else
- QCoreApplication::sendPostedEvents(viewport->window(), QEvent::UpdateRequest);
- }
+ for (int i = 0; i < views.size(); ++i)
+ views.at(i)->d_func()->dispatchPendingUpdateRequests();
}
/*!
@@ -728,24 +472,20 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item)
// Clear focus on the item to remove any reference in the focusWidget chain.
item->clearFocus();
+
markDirty(item, QRectF(), false, false, false, false, /*removingItemFromScene=*/true);
- if (!item->d_ptr->inDestructor) {
+ if (item->d_ptr->inDestructor) {
+ // The item is actually in its destructor, we call the special method in the index.
+ index->deleteItem(item);
+ } else {
// Can potentially call item->boundingRect() (virtual function), that's why
// we only can call this function if the item is not in its destructor.
- removeFromIndex(item);
- } else if (item->d_ptr->index != -1) {
- // Important: The index is useless until purgeRemovedItems() is called.
- indexedItems[item->d_ptr->index] = (QGraphicsItem *)0;
- if (!purgePending)
- purgePending = true;
- removedItems << item;
- } else {
- // Recently added items are purged immediately. unindexedItems() never
- // contains stale items.
- unindexedItems.removeAll(item);
+ index->removeItem(item);
}
+ item->d_ptr->clearSubFocus();
+
if (!item->d_ptr->inDestructor && item == tabFocusFirst) {
QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
widget->d_func()->fixFocusChainBeforeReparenting(0, 0);
@@ -753,6 +493,13 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item)
item->d_func()->scene = 0;
+ // Unregister focus proxy.
+ QMultiHash<QGraphicsItem *, QGraphicsItem *>::iterator it = focusProxyReverseMap.find(item);
+ while (it != focusProxyReverseMap.end() && it.key() == item) {
+ it.value()->d_ptr->focusProxy = 0;
+ it = focusProxyReverseMap.erase(it);
+ }
+
// Remove from parent, or unregister from toplevels.
if (QGraphicsItem *parentItem = item->parentItem()) {
if (parentItem->scene()) {
@@ -764,17 +511,6 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item)
unregisterTopLevelItem(item);
}
- if (!item->d_ptr->inDestructor) {
- // Remove from our item lists.
- int index = item->d_func()->index;
- if (index != -1) {
- freeItemIndexes << index;
- indexedItems[index] = 0;
- } else {
- unindexedItems.removeAll(item);
- }
- }
-
// Reset the mouse grabber and focus item data.
if (item == focusItem)
focusItem = 0;
@@ -794,7 +530,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
@@ -832,41 +567,66 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item)
/*!
\internal
-
- Removes stale pointers from all data structures.
*/
-void QGraphicsScenePrivate::purgeRemovedItems()
+void QGraphicsScenePrivate::setFocusItemHelper(QGraphicsItem *item,
+ Qt::FocusReason focusReason)
{
- if (!purgePending && removedItems.isEmpty())
+ Q_Q(QGraphicsScene);
+ if (item == focusItem)
return;
- // Remove stale items from the BSP tree.
- if (indexMethod != QGraphicsScene::NoIndex)
- bspTree.removeItems(removedItems);
+ // Clear focus if asked to set focus on something that can't
+ // accept input focus.
+ if (item && (!(item->flags() & QGraphicsItem::ItemIsFocusable)
+ || !item->isVisible() || !item->isEnabled())) {
+ item = 0;
+ }
+
+ // Set focus on the scene if an item requests focus.
+ if (item) {
+ q->setFocus(focusReason);
+ if (item == focusItem)
+ return;
+ }
- // Purge this list.
- removedItems.clear();
- freeItemIndexes.clear();
- for (int i = 0; i < indexedItems.size(); ++i) {
- if (!indexedItems.at(i))
- freeItemIndexes << i;
+ // Auto-update focus proxy. The closest parent that detects
+ // focus proxies is updated as the proxy gains or loses focus.
+ if (item) {
+ QGraphicsItem *p = item->d_ptr->parent;
+ while (p) {
+ if (p->d_ptr->flags & QGraphicsItem::ItemAutoDetectsFocusProxy) {
+ p->setFocusProxy(item);
+ break;
+ }
+ p = p->d_ptr->parent;
+ }
}
- purgePending = false;
-}
-/*!
- \internal
+ if (focusItem) {
+ QFocusEvent event(QEvent::FocusOut, focusReason);
+ lastFocusItem = focusItem;
+ focusItem = 0;
+ sendEvent(lastFocusItem, &event);
- Starts or restarts the timer used for reindexing unindexed items.
-*/
-void QGraphicsScenePrivate::startIndexTimer(int interval)
-{
- Q_Q(QGraphicsScene);
- if (indexTimerId) {
- restartIndexTimer = true;
- } else {
- indexTimerId = q->startTimer(interval);
+ if (lastFocusItem
+ && (lastFocusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod)) {
+ // Reset any visible preedit text
+ QInputMethodEvent imEvent;
+ sendEvent(lastFocusItem, &imEvent);
+
+ // Close any external input method panel
+ for (int i = 0; i < views.size(); ++i)
+ views.at(i)->inputContext()->reset();
+ }
}
+
+ if (item) {
+ focusItem = item;
+ QFocusEvent event(QEvent::FocusIn, focusReason);
+ sendEvent(item, &event);
+ }
+
+ updateInputMethodSensitivityInViews();
}
/*!
@@ -1105,41 +865,20 @@ QList<QGraphicsItem *> QGraphicsScenePrivate::itemsAtPosition(const QPoint &scre
{
Q_Q(const QGraphicsScene);
QGraphicsView *view = widget ? qobject_cast<QGraphicsView *>(widget->parentWidget()) : 0;
- QList<QGraphicsItem *> items;
- if (view)
- items = view->items(view->viewport()->mapFromGlobal(screenPos));
- else
- items = q->items(scenePos);
- return items;
-}
+ if (!view)
+ return q->items(scenePos, Qt::IntersectsItemShape, Qt::AscendingOrder, QTransform());
-/*!
- \internal
+ const QRectF pointRect(QPointF(widget->mapFromGlobal(screenPos)), QSizeF(1, 1));
+ if (!view->isTransformed())
+ return q->items(pointRect, Qt::IntersectsItemShape, Qt::AscendingOrder);
- 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<QGraphicsWidget *>(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());
- }
+ const QTransform viewTransform = view->viewportTransform();
+ if (viewTransform.type() <= QTransform::TxScale) {
+ return q->items(viewTransform.inverted().mapRect(pointRect), Qt::IntersectsItemShape,
+ Qt::AscendingOrder, viewTransform);
}
- return false;
+ return q->items(viewTransform.inverted().map(pointRect), Qt::IntersectsItemShape,
+ Qt::AscendingOrder, viewTransform);
}
/*!
@@ -1151,7 +890,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());
}
@@ -1185,6 +924,24 @@ void QGraphicsScenePrivate::removeSceneEventFilter(QGraphicsItem *watched, QGrap
}
/*!
+ \internal
+*/
+bool QGraphicsScenePrivate::filterDescendantEvent(QGraphicsItem *item, QEvent *event)
+{
+ if (item && (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorFiltersChildEvents)) {
+ QGraphicsItem *parent = item->parentItem();
+ while (parent) {
+ if (parent->d_ptr->filtersDescendantEvents && parent->sceneEventFilter(item, event))
+ return true;
+ if (!(parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorFiltersChildEvents))
+ return false;
+ parent = parent->parentItem();
+ }
+ }
+ return false;
+}
+
+/*!
\internal
*/
bool QGraphicsScenePrivate::filterEvent(QGraphicsItem *item, QEvent *event)
@@ -1216,7 +973,9 @@ bool QGraphicsScenePrivate::sendEvent(QGraphicsItem *item, QEvent *event)
{
if (filterEvent(item, event))
return false;
- return (item && item->isEnabled()) ? item->sceneEvent(event) : false;
+ if (filterDescendantEvent(item, event))
+ return false;
+ return (item && item->isEnabled() ? item->sceneEvent(event) : false);
}
/*!
@@ -1429,779 +1188,6 @@ QGraphicsWidget *QGraphicsScenePrivate::windowForItem(const QGraphicsItem *item)
return 0;
}
-QList<QGraphicsItem *> QGraphicsScenePrivate::topLevelItemsInStackingOrder(const QTransform *const viewTransform,
- QRegion *exposedRegion)
-{
- if (indexMethod == QGraphicsScene::NoIndex || !exposedRegion) {
- if (needSortTopLevelItems) {
- needSortTopLevelItems = false;
- qStableSort(topLevelItems.begin(), topLevelItems.end(), qt_notclosestLeaf);
- }
- 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);
- }
- 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 ? untr : invertedViewTransform.mapRect(untr);
- ltri.adjust(-untr.width(), -untr.height(), untr.width(), untr.height());
- sceneRect.adjust(-ltri.width(), -ltri.height(), ltri.width(), ltri.height());
- }
-
- QList<QGraphicsItem *> tmp = estimateItemsInRect(sceneRect);
- 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);
- }
-
- QList<QGraphicsItem *> 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;
- }
- }
- return tli;
-}
-
-void QGraphicsScenePrivate::recursive_items_helper(QGraphicsItem *item, QRectF rect,
- QList<QGraphicsItem *> *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<QGraphicsItem *> &children = item ? item->d_ptr->children : const_cast<QGraphicsScenePrivate *>(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<QGraphicsScenePrivate *>(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;
- }
- }
-}
-
-QList<QGraphicsItem *> QGraphicsScenePrivate::items_helper(const QPointF &pos) const
-{
- QList<QGraphicsItem *> 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<QGraphicsItem *> QGraphicsScenePrivate::items_helper(const QRectF &rect,
- Qt::ItemSelectionMode mode,
- Qt::SortOrder order) const
-{
- QList<QGraphicsItem *> 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<QGraphicsItem *> QGraphicsScenePrivate::items_helper(const QPolygonF &polygon,
- Qt::ItemSelectionMode mode,
- Qt::SortOrder order) const
-{
- QList<QGraphicsItem *> 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<QGraphicsItem *> QGraphicsScenePrivate::items_helper(const QPainterPath &path,
- Qt::ItemSelectionMode mode,
- Qt::SortOrder order) const
-{
- QList<QGraphicsItem *> 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<QGraphicsItem *> *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<QGraphicsItem *> &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 QGraphicsScenePrivate::childItems_helper(QList<QGraphicsItem *> *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<QGraphicsItem *> &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()) {
- // ### _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->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);
- }
- }
- }
-}
-
-
-void QGraphicsScenePrivate::childItems_helper(QList<QGraphicsItem *> *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<QGraphicsItem *> &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 (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<QGraphicsItem *> *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<QGraphicsItem *> &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 (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);
- 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.data();
- const QGraphicsItemPrivate *d2 = item2->d_ptr.data();
- 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;
-}
-
-static inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2)
-{
- return qt_closestLeaf(item2, item1);
-}
-
-/*!
- \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.data();
- const QGraphicsItemPrivate *d2 = item2->d_ptr.data();
- 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<QGraphicsItem *> 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()
-{
- _q_updateIndex();
-
- if (!sortCacheEnabled || !updatingSortCache)
- return;
-
- updatingSortCache = false;
- int stackingOrder = 0;
-
- QList<QGraphicsItem *> topLevels;
-
- for (int i = 0; i < indexedItems.size(); ++i) {
- QGraphicsItem *item = indexedItems.at(i);
- if (item && item->parentItem() == 0)
- topLevels << item;
- }
- for (int i = 0; i < unindexedItems.size(); ++i) {
- QGraphicsItem *item = unindexedItems.at(i);
- if (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<QGraphicsItem *> *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
@@ -2334,8 +1320,8 @@ QGraphicsScene::QGraphicsScene(QObject *parent)
QGraphicsScene::QGraphicsScene(const QRectF &sceneRect, QObject *parent)
: QObject(*new QGraphicsScenePrivate, parent)
{
- setSceneRect(sceneRect);
d_func()->init();
+ setSceneRect(sceneRect);
}
/*!
@@ -2349,8 +1335,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);
}
/*!
@@ -2387,8 +1373,19 @@ QGraphicsScene::~QGraphicsScene()
QRectF QGraphicsScene::sceneRect() const
{
Q_D(const QGraphicsScene);
- const_cast<QGraphicsScenePrivate *>(d)->_q_updateIndex();
- return d->hasSceneRect ? d->sceneRect : d->growingItemsBoundingRect;
+ if (d->hasSceneRect)
+ return d->sceneRect;
+
+ if (d->dirtyGrowingItemsBoundingRect) {
+ // Lazily update the growing items bounding rect
+ QGraphicsScenePrivate *thatd = const_cast<QGraphicsScenePrivate *>(d);
+ QRectF oldGrowingBoundingRect = thatd->growingItemsBoundingRect;
+ thatd->growingItemsBoundingRect |= itemsBoundingRect();
+ thatd->dirtyGrowingItemsBoundingRect = false;
+ if (oldGrowingBoundingRect != thatd->growingItemsBoundingRect)
+ emit const_cast<QGraphicsScene *>(this)->sceneRectChanged(thatd->growingItemsBoundingRect);
+ }
+ return d->growingItemsBoundingRect;
}
void QGraphicsScene::setSceneRect(const QRectF &rect)
{
@@ -2396,8 +1393,7 @@ void QGraphicsScene::setSceneRect(const QRectF &rect)
if (rect != d->sceneRect) {
d->hasSceneRect = !rect.isNull();
d->sceneRect = rect;
- d->resetIndex();
- emit sceneRectChanged(rect);
+ emit sceneRectChanged(d->hasSceneRect ? rect : d->growingItemsBoundingRect);
}
}
@@ -2438,6 +1434,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())
@@ -2532,8 +1530,19 @@ QGraphicsScene::ItemIndexMethod QGraphicsScene::itemIndexMethod() const
void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method)
{
Q_D(QGraphicsScene);
- d->resetIndex();
+ if (d->indexMethod == method)
+ return;
+
d->indexMethod = method;
+
+ QList<QGraphicsItem *> 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 = oldItems.size() - 1; i >= 0; --i)
+ d->index->addItem(oldItems.at(i));
}
/*!
@@ -2571,35 +1580,32 @@ void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method)
int QGraphicsScene::bspTreeDepth() const
{
Q_D(const QGraphicsScene);
- return d->bspTreeDepth;
+ QGraphicsSceneBspTreeIndex *bspTree = qobject_cast<QGraphicsSceneBspTreeIndex *>(d->index);
+ 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;
}
- d->bspTreeDepth = depth;
- d->resetIndex();
+ QGraphicsSceneBspTreeIndex *bspTree = qobject_cast<QGraphicsSceneBspTreeIndex *>(d->index);
+ if (!bspTree) {
+ qWarning("QGraphicsScene::setBspTreeDepth: can not apply if indexing method is not BSP");
+ return;
+ }
+ bspTree->setBspTreeDepth(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
{
@@ -2609,10 +1615,9 @@ bool QGraphicsScene::isSortCacheEnabled() const
void QGraphicsScene::setSortCacheEnabled(bool enabled)
{
Q_D(QGraphicsScene);
- if (enabled == d->sortCacheEnabled)
+ if (d->sortCacheEnabled == enabled)
return;
- if ((d->sortCacheEnabled = enabled))
- d->invalidateSortCache();
+ d->sortCacheEnabled = enabled;
}
/*!
@@ -2624,6 +1629,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();
@@ -2638,43 +1644,43 @@ QRectF QGraphicsScene::itemsBoundingRect() const
QList<QGraphicsItem *> QGraphicsScene::items() const
{
Q_D(const QGraphicsScene);
- const_cast<QGraphicsScenePrivate *>(d)->purgeRemovedItems();
+ return d->index->items(Qt::AscendingOrder);
+}
- // If freeItemIndexes is empty, we know there are no holes in indexedItems and
- // unindexedItems.
- if (d->freeItemIndexes.isEmpty()) {
- if (d->unindexedItems.isEmpty())
- return d->indexedItems;
- return d->indexedItems + d->unindexedItems;
- }
+/*!
+ Returns an ordered list of all items on the scene. \a order decides the
+ sorting.
- // Rebuild the list of items to avoid holes. ### We could also just
- // compress the item lists at this point.
- QList<QGraphicsItem *> itemList;
- foreach (QGraphicsItem *item, d->indexedItems + d->unindexedItems) {
- if (item)
- itemList << item;
- }
- return itemList;
+ \sa addItem(), removeItem()
+*/
+QList<QGraphicsItem *> QGraphicsScene::items(Qt::SortOrder order) const
+{
+ Q_D(const QGraphicsScene);
+ return d->index->items(order);
}
/*!
+ \obsolete
+
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).
+ This function is deprecated and returns incorrect results if the scene
+ contains items that ignore transformations. Use the overload that takes
+ a QTransform instead.
+
\sa itemAt()
*/
QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos) const
{
Q_D(const QGraphicsScene);
- return d->items_helper(pos);
+ return d->index->items(pos, Qt::IntersectsItemShape, Qt::AscendingOrder);
}
/*!
- \fn QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSelectionMode mode) const
-
\overload
+ \obsolete
Returns all visible items that, depending on \a mode, are either inside or
intersect with the specified \a rectangle.
@@ -2682,25 +1688,47 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos) const
The default value for \a mode is Qt::IntersectsItemShape; all items whose
exact shape intersects with or is contained by \a rectangle are returned.
+ This function is deprecated and returns incorrect results if the scene
+ contains items that ignore transformations. Use the overload that takes
+ a QTransform instead.
+
\sa itemAt()
*/
-QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode) const
+QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSelectionMode mode) const
{
Q_D(const QGraphicsScene);
- QList<QGraphicsItem *> itemList;
- d->recursive_items_helper(0, rect, &itemList, QTransform(), QTransform(), mode, Qt::AscendingOrder);
- return itemList;
+ return d->index->items(rectangle, mode, Qt::AscendingOrder);
}
/*!
\fn QList<QGraphicsItem *> QGraphicsScene::items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode) const
+ \obsolete
\since 4.3
This convenience function is equivalent to calling items(QRectF(\a x, \a y, \a w, \a h), \a mode).
+
+ This function is deprecated and returns incorrect results if the scene
+ contains items that ignore transformations. Use the overload that takes
+ a QTransform instead.
*/
/*!
+ \fn QList<QGraphicsItem *> QGraphicsScene::items(qreal x, qreal y, qreal w, qreal h,
+ Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const
\overload
+ \since 4.6
+
+ Returns all visible items that, depending on \a mode, are either inside or
+ intersect with the rectangle defined by \a x, \a y, \a w and \a h, in a list
+ sorted using \a order.
+
+ \a deviceTransform is the transformation that applies to the view, and needs to
+ be provided if the scene contains items that ignore transformations.
+*/
+
+/*!
+ \overload
+ \obsolete
Returns all visible items that, depending on \a mode, are either inside or
intersect with the polygon \a polygon.
@@ -2708,16 +1736,21 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelecti
The default value for \a mode is Qt::IntersectsItemShape; all items whose
exact shape intersects with or is contained by \a polygon are returned.
+ This function is deprecated and returns incorrect results if the scene
+ contains items that ignore transformations. Use the overload that takes
+ a QTransform instead.
+
\sa itemAt()
*/
QList<QGraphicsItem *> 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);
}
/*!
\overload
+ \obsolete
Returns all visible items that, depending on \a path, are either inside or
intersect with the path \a path.
@@ -2725,12 +1758,103 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemS
The default value for \a mode is Qt::IntersectsItemShape; all items whose
exact shape intersects with or is contained by \a path are returned.
+ This function is deprecated and returns incorrect results if the scene
+ contains items that ignore transformations. Use the overload that takes
+ a QTransform instead.
+
\sa itemAt()
*/
QList<QGraphicsItem *> 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);
+}
+
+/*!
+ \since 4.6
+
+ Returns all visible items that, depending on \a mode, are at the specified \a pos
+ in 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 that applies to the view, and needs to
+ be provided if the scene contains items that ignore transformations.
+
+ \sa itemAt()
+*/
+QList<QGraphicsItem *> 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);
+}
+
+/*!
+ \overload
+ \since 4.6
+
+ 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 that applies to the view, and needs to
+ be provided if the scene contains items that ignore transformations.
+
+ \sa itemAt()
+*/
+QList<QGraphicsItem *> 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
+ \since 4.6
+
+ 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 that applies to the view, and needs to
+ be provided if the scene contains items that ignore transformations.
+
+ \sa itemAt()
+*/
+QList<QGraphicsItem *> 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
+ \since 4.6
+
+ 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 that applies to the view, and needs to
+ be provided if the scene contains items that ignore transformations.
+
+ \sa itemAt()
+*/
+QList<QGraphicsItem *> 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);
}
/*!
@@ -2753,34 +1877,77 @@ QList<QGraphicsItem *> QGraphicsScene::collidingItems(const QGraphicsItem *item,
return QList<QGraphicsItem *>();
}
+ // Does not support ItemIgnoresTransformations.
QList<QGraphicsItem *> tmp;
- foreach (QGraphicsItem *itemInVicinity, d->estimateItemsInRect(item->sceneBoundingRect())) {
+ foreach (QGraphicsItem *itemInVicinity, d->index->estimateItems(item->sceneBoundingRect(), Qt::AscendingOrder)) {
if (item != itemInVicinity && item->collidesWithItem(itemInVicinity, mode))
tmp << itemInVicinity;
}
- d->sortItems(&tmp, Qt::AscendingOrder, d->sortCacheEnabled);
return tmp;
}
/*!
- \fn QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position) const
+ \overload
+ \obsolete
Returns the topmost visible item at the specified \a position, or 0 if
there are no items at this position.
\note The topmost item is the one with the highest Z-value.
+ This function is deprecated and returns incorrect results if the scene
+ contains items that ignore transformations. Use the overload that takes
+ a QTransform instead.
+
\sa items(), collidingItems(), QGraphicsItem::setZValue()
*/
-QGraphicsItem *QGraphicsScene::itemAt(const QPointF &pos) const
+QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position) const
{
- QList<QGraphicsItem *> itemsAtPoint = items(pos);
+ QList<QGraphicsItem *> itemsAtPoint = items(position);
return itemsAtPoint.isEmpty() ? 0 : itemsAtPoint.first();
}
/*!
+ \since 4.6
+
+ Returns the topmost visible item at the specified \a position, or 0
+ if there are no items at this position.
+
+ \a deviceTransform is the transformation that applies to the view, and needs to
+ be provided if the scene contains items that ignore transformations.
+
+ \note The topmost item is the one with the highest Z-value.
+
+ \sa items(), collidingItems(), QGraphicsItem::setZValue()
+ */
+QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position, const QTransform &deviceTransform) const
+{
+ QList<QGraphicsItem *> itemsAtPoint = items(position, Qt::IntersectsItemShape,
+ Qt::AscendingOrder, deviceTransform);
+ return itemsAtPoint.isEmpty() ? 0 : itemsAtPoint.first();
+}
+
+/*!
+ \fn QGraphicsScene::itemAt(qreal x, qreal y, const QTransform &deviceTransform) const
+ \overload
+ \since 4.6
+
+ Returns the topmost item at the position specified by (\a x, \a
+ y), or 0 if there are no items at this position.
+
+ \a deviceTransform is the transformation that applies to the view, and needs to
+ be provided if the scene contains items that ignore transformations.
+
+ This convenience function is equivalent to calling \c
+ {itemAt(QPointF(x, y), deviceTransform)}.
+
+ \note The topmost item is the one with the highest Z-value.
+*/
+
+/*!
\fn QGraphicsScene::itemAt(qreal x, qreal y) const
\overload
+ \obsolete
Returns the topmost item at the position specified by (\a x, \a
y), or 0 if there are no items at this position.
@@ -2788,6 +1955,10 @@ QGraphicsItem *QGraphicsScene::itemAt(const QPointF &pos) const
This convenience function is equivalent to calling \c
{itemAt(QPointF(x, y))}.
+ This function is deprecated and returns incorrect results if the scene
+ contains items that ignore transformations. Use the overload that takes
+ a QTransform instead.
+
\note The topmost item is the one with the highest Z-value.
*/
@@ -2828,21 +1999,42 @@ QPainterPath QGraphicsScene::selectionArea() const
}
/*!
+ \since 4.6
+
Sets the selection area to \a path. All items within this area are
immediately selected, and all items outside are unselected. You can get
the list of all selected items by calling selectedItems().
+ \a deviceTransform is the transformation that applies to the view, and needs to
+ be provided if the scene contains items that ignore transformations.
+
For an item to be selected, it must be marked as \e selectable
(QGraphicsItem::ItemIsSelectable).
\sa clearSelection(), selectionArea()
*/
+void QGraphicsScene::setSelectionArea(const QPainterPath &path, const QTransform &deviceTransform)
+{
+ setSelectionArea(path, Qt::IntersectsItemShape, deviceTransform);
+}
+
+/*!
+ \obsolete
+ \overload
+
+ Sets the selection area to \a path.
+
+ This function is deprecated and leads to incorrect results if the scene
+ contains items that ignore transformations. Use the overload that takes
+ a QTransform instead.
+*/
void QGraphicsScene::setSelectionArea(const QPainterPath &path)
{
- setSelectionArea(path, Qt::IntersectsItemShape);
+ setSelectionArea(path, Qt::IntersectsItemShape, QTransform());
}
/*!
+ \obsolete
\overload
\since 4.3
@@ -2853,6 +2045,24 @@ void QGraphicsScene::setSelectionArea(const QPainterPath &path)
*/
void QGraphicsScene::setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode)
{
+ setSelectionArea(path, mode, QTransform());
+}
+
+/*!
+ \overload
+ \since 4.6
+
+ Sets the selection area to \a path using \a mode to determine if items are
+ included in the selection area.
+
+ \a deviceTransform is the transformation that applies to the view, and needs to
+ be provided if the scene contains items that ignore transformations.
+
+ \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
@@ -2868,7 +2078,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;
@@ -2925,26 +2135,13 @@ void QGraphicsScene::clearSelection()
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)) {
- if (!item->parentItem())
- delete item;
- }
- }
- QList<QGraphicsItem *> unindexedParents;
- for (int i = 0; i < d->unindexedItems.size(); ++i) {
- QGraphicsItem *item = d->unindexedItems.at(i);
- if (!item->parentItem())
- unindexedParents << item;
- }
- d->unindexedItems.clear();
- qDeleteAll(unindexedParents);
- d->indexedItems.clear();
- d->freeItemIndexes.clear();
+ // 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<QGraphicsItem *> items = d->topLevelItems;
+ qDeleteAll(items);
+ Q_ASSERT(d->topLevelItems.isEmpty());
d->lastItemCount = 0;
- d->bspTree.clear();
- d->largestUntransformableItem = QRectF();
d->allItemsIgnoreHoverEvents = true;
d->allItemsUseDefaultCursor = true;
d->allItemsIgnoreTouchEvents = true;
@@ -3066,14 +2263,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();
-
// Detach this item from its parent if the parent's scene is different
// from this scene.
if (QGraphicsItem *itemParent = item->parentItem()) {
@@ -3084,29 +2273,18 @@ 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.
- d->unindexedItems << item;
- item->d_func()->index = -1;
- d->startIndexTimer(0);
+ // Add the item in the index
+ d->index->addItem(item);
// Add to list of toplevels if this item is a toplevel.
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().
- if (!d->updateAll) {
- if (d->pendingUpdateItems.isEmpty())
- QMetaObject::invokeMethod(this, "_q_updateLater", Qt::QueuedConnection);
- d->pendingUpdateItems << item;
- }
+ d->markDirty(item);
+ d->dirtyGrowingItemsBoundingRect = true;
// Disable selectionChanged() for individual items
++d->selectionChanging;
@@ -3177,6 +2355,17 @@ void QGraphicsScene::addItem(QGraphicsItem *item)
// Deliver post-change notification
item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant);
+
+ // Auto-activate the first inactive window if the scene is active.
+ if (d->activationRefCount > 0 && !d->activeWindow && item->isWindow())
+ setActiveWindow(static_cast<QGraphicsWidget *>(item));
+
+ // Ensure that newly added items that have subfocus set, gain
+ // focus automatically if there isn't a focus item already.
+ if (!d->focusItem && item->focusItem())
+ item->focusItem()->setFocus();
+
+ d->updateInputMethodSensitivityInViews();
}
/*!
@@ -3452,6 +2641,8 @@ void QGraphicsScene::removeItem(QGraphicsItem *item)
// Deliver post-change notification
item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant);
+
+ d->updateInputMethodSensitivityInViews();
}
/*!
@@ -3488,36 +2679,10 @@ QGraphicsItem *QGraphicsScene::focusItem() const
void QGraphicsScene::setFocusItem(QGraphicsItem *item, Qt::FocusReason focusReason)
{
Q_D(QGraphicsScene);
- if (item == d->focusItem)
- return;
- if (item && (!(item->flags() & QGraphicsItem::ItemIsFocusable)
- || !item->isVisible() || !item->isEnabled())) {
- item = 0;
- }
-
- if (item) {
- setFocus(focusReason);
- if (item == d->focusItem)
- return;
- }
-
- if (d->focusItem) {
- QFocusEvent event(QEvent::FocusOut, focusReason);
- d->lastFocusItem = d->focusItem;
- d->focusItem = 0;
- d->sendEvent(d->lastFocusItem, &event);
- }
-
- if (item) {
- if (item->isWidget()) {
- // Update focus child chain.
- static_cast<QGraphicsWidget *>(item)->d_func()->setFocusWidget();
- }
-
- d->focusItem = item;
- QFocusEvent event(QEvent::FocusIn, focusReason);
- d->sendEvent(item, &event);
- }
+ if (item)
+ item->setFocus(focusReason);
+ else
+ d->setFocusItemHelper(item, focusReason);
}
/*!
@@ -3572,13 +2737,17 @@ void QGraphicsScene::clearFocus()
/*!
\property QGraphicsScene::stickyFocus
- \brief whether or not clicking the scene will clear focus
+ \brief whether clicking into the scene background will clear focus
+
+ \since 4.6
- If this property is false (the default), then clicking on the scene
- background or on an item that does not accept focus, will clear
- focus. Otherwise, focus will remain unchanged.
+ In a QGraphicsScene with stickyFocus set to true, focus will remain
+ unchanged when the user clicks into the scene background or on an item
+ that does not accept focus. Otherwise, focus will be cleared.
- The focus change happens in response to a mouse press. You can reimplement
+ By default, this property is false.
+
+ Focus changes in response to a mouse press. You can reimplement
mousePressEvent() in a subclass of QGraphicsScene to toggle this property
based on where the user has clicked.
@@ -3701,7 +2870,7 @@ void QGraphicsScene::setForegroundBrush(const QBrush &brush)
QVariant QGraphicsScene::inputMethodQuery(Qt::InputMethodQuery query) const
{
Q_D(const QGraphicsScene);
- if (!d->focusItem)
+ if (!d->focusItem || !(d->focusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod))
return QVariant();
const QTransform matrix = d->focusItem->sceneTransform();
QVariant value = d->focusItem->inputMethodQuery(query);
@@ -3730,14 +2899,14 @@ void QGraphicsScene::update(const QRectF &rect)
// Check if anyone's connected; if not, we can send updates directly to
// the views. Otherwise or if there are no views, use old behavior.
- bool directUpdates = !(d->connectedSignals & d->changedSignalMask) && !d->views.isEmpty();
+ bool directUpdates = !(d->connectedSignals[0] & d->changedSignalMask) && !d->views.isEmpty();
if (rect.isNull()) {
d->updateAll = true;
d->updatedRects.clear();
if (directUpdates) {
// Update all views.
for (int i = 0; i < d->views.size(); ++i)
- d->views.at(i)->d_func()->updateAll();
+ d->views.at(i)->d_func()->fullUpdatePending = true;
}
} else {
if (directUpdates) {
@@ -4018,132 +3187,17 @@ bool QGraphicsScene::event(QEvent *event)
// geometries that do not have an explicit style set.
update();
break;
- case QEvent::GraphicsSceneGesture: {
- QGraphicsSceneGestureEvent *ev = static_cast<QGraphicsSceneGestureEvent*>(event);
- QGraphicsView *view = qobject_cast<QGraphicsView*>(ev->widget());
- if (!view) {
- qWarning("QGraphicsScene::event: gesture event was received without a view");
- break;
- }
-
- // get a list of gestures that just started.
- QSet<QGesture*> startedGestures;
- QList<QGesture*> gestures = ev->gestures();
- for(QList<QGesture*>::const_iterator it = gestures.begin(), e = gestures.end();
- it != e; ++it) {
- QGesture *g = *it;
- QGesturePrivate *gd = g->d_func();
- if (g->state() == Qt::GestureStarted || gd->singleshot) {
- startedGestures.insert(g);
- }
- }
- if (!startedGestures.isEmpty()) {
- // find a target for each started gesture.
- for(QSet<QGesture*>::const_iterator it = startedGestures.begin(), e = startedGestures.end();
- it != e; ++it) {
- QGesture *g = *it;
- QGesturePrivate *gd = g->d_func();
- gd->graphicsItem = 0;
- QList<QGraphicsItem*> itemsInGestureArea = items(g->hotSpot());
- const QString gestureName = g->type();
- foreach(QGraphicsItem *item, itemsInGestureArea) {
- if (item->d_func()->hasGesture(gestureName)) {
- Q_ASSERT(gd->graphicsItem == 0);
- gd->graphicsItem = item;
- d->itemsWithGestures[item].insert(g);
- break;
- }
- }
- }
- }
- d->sendGestureEvent(ev->gestures().toSet(), ev->cancelledGestures());
- }
- break;
case QEvent::TouchBegin:
case QEvent::TouchUpdate:
case QEvent::TouchEnd:
d->touchEventHandler(static_cast<QTouchEvent *>(event));
break;
- case QEvent::Timer:
- if (d->indexTimerId && static_cast<QTimerEvent *>(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;
}
-void QGraphicsScenePrivate::sendGestureEvent(const QSet<QGesture*> &gestures, const QSet<QString> &cancelled)
-{
- Q_Q(QGraphicsScene);
- typedef QMap<QGraphicsItem*, QSet<QGesture*> > ItemGesturesMap;
- ItemGesturesMap itemGestures;
- QSet<QGesture*> startedGestures;
- for(QSet<QGesture*>::const_iterator it = gestures.begin(), e = gestures.end();
- it != e; ++it) {
- QGesture *g = *it;
- Q_ASSERT(g != 0);
- QGesturePrivate *gd = g->d_func();
- if (gd->graphicsItem != 0) {
- itemGestures[gd->graphicsItem].insert(g);
- if (g->state() == Qt::GestureStarted || gd->singleshot)
- startedGestures.insert(g);
- }
- }
-
- QSet<QGesture*> ignoredGestures;
- for(ItemGesturesMap::const_iterator it = itemGestures.begin(), e = itemGestures.end();
- it != e; ++it) {
- QGraphicsItem *receiver = it.key();
- Q_ASSERT(receiver != 0);
- QGraphicsSceneGestureEvent event;
- event.setGestures(it.value());
- event.setCancelledGestures(cancelled);
- bool processed = sendEvent(receiver, &event);
- QSet<QGesture*> started = startedGestures.intersect(it.value());
- if (event.isAccepted())
- foreach(QGesture *g, started)
- g->accept();
- if (!started.isEmpty() && !(processed && event.isAccepted())) {
- // there are started gestures event that weren't
- // accepted, so propagating each gesture independently.
- QSet<QGesture*>::const_iterator it = started.begin(),
- e = started.end();
- for(; it != e; ++it) {
- QGesture *g = *it;
- if (processed && g->isAccepted()) {
- continue;
- }
- QGesturePrivate *gd = g->d_func();
- QGraphicsItem *item = gd->graphicsItem;
- gd->graphicsItem = 0;
-
- //### THIS IS BS, DONT FORGET TO REWRITE THIS CODE
- // need to make sure we try to deliver event just once to each widget
- const QString gestureType = g->type();
- QList<QGraphicsItem*> itemsUnderGesture = q->items(g->hotSpot());
- for (int i = 0; i < itemsUnderGesture.size(); ++i) {
- QGraphicsItem *item = itemsUnderGesture.at(i);
- if (item != receiver && item->d_func()->hasGesture(gestureType)) {
- ignoredGestures.insert(g);
- gd->graphicsItem = item;
- break;
- }
- }
- }
- }
- }
- if (!ignoredGestures.isEmpty())
- sendGestureEvent(ignoredGestures, cancelled);
-}
-
/*!
\reimp
@@ -4426,7 +3480,7 @@ void QGraphicsScene::helpEvent(QGraphicsSceneHelpEvent *helpEvent)
text = toolTipItem->toolTip();
point = helpEvent->screenPos();
}
- QToolTip::showText(point, text);
+ QToolTip::showText(point, text, helpEvent->widget());
helpEvent->setAccepted(!text.isEmpty());
#endif
}
@@ -4525,8 +3579,7 @@ void QGraphicsScenePrivate::leaveScene()
{
Q_Q(QGraphicsScene);
#ifndef QT_NO_TOOLTIP
- // Remove any tooltips
- QToolTip::showText(QPoint(), QString());
+ QToolTip::hideText();
#endif
// Send HoverLeave events to all existing hover items, topmost first.
QGraphicsView *senderWidget = qobject_cast<QGraphicsView *>(q->sender());
@@ -4629,6 +3682,13 @@ void QGraphicsScene::keyReleaseEvent(QKeyEvent *keyEvent)
void QGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
Q_D(QGraphicsScene);
+ if (d->mouseGrabberItems.isEmpty()) {
+ // Dispatch hover events
+ QGraphicsSceneHoverEvent hover;
+ _q_hoverFromMouseEvent(&hover, mouseEvent);
+ d->dispatchHoverEvent(&hover);
+ }
+
d->mousePressEventHandler(mouseEvent);
}
@@ -4769,16 +3829,16 @@ void QGraphicsScene::wheelEvent(QGraphicsSceneWheelEvent *wheelEvent)
subclass to receive input method events for the scene.
The default implementation forwards the event to the focusItem().
- If no item currently has focus, this function does nothing.
+ If no item currently has focus or the current focus item does not
+ accept input methods, this function does nothing.
\sa QGraphicsItem::inputMethodEvent()
*/
void QGraphicsScene::inputMethodEvent(QInputMethodEvent *event)
{
Q_D(QGraphicsScene);
- if (!d->focusItem)
- return;
- d->sendEvent(d->focusItem, event);
+ if (d->focusItem && (d->focusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod))
+ d->sendEvent(d->focusItem, event);
}
/*!
@@ -5226,6 +4286,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<QGraphicsItem *> 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,
@@ -5248,6 +4322,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); \
@@ -5257,6 +4332,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
transformPtr = &transform; \
} else { \
transformPtr = &item->d_ptr->sceneTransform; \
+ translateOnlyTransform = item->d_ptr->sceneTransformTranslateOnly; \
} \
}
@@ -5268,10 +4344,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;
}
@@ -5280,7 +4354,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();
@@ -5297,10 +4372,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();
@@ -5326,7 +4398,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;
@@ -5334,10 +4407,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);
@@ -5380,6 +4452,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;
}
@@ -5395,7 +4477,7 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b
if (removingItemFromScene) {
// Note that this function can be called from the item's destructor, so
// do NOT call any virtual functions on it within this block.
- if ((connectedSignals & changedSignalMask) || views.isEmpty()) {
+ if ((connectedSignals[0] & changedSignalMask) || views.isEmpty()) {
// 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.
@@ -5439,65 +4521,121 @@ 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<QGraphicsItem *>(item->q_ptr);
+ QGraphicsView *viewq = static_cast<QGraphicsView *>(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,
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;
+ }
+
+ 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!(?)
+ }
- 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 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) {
+ item->d_ptr->updateSceneTransformFromParent();
+ Q_ASSERT(!item->d_ptr->dirtySceneTransform);
+ }
+
+ 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 (!hasSceneRect && item->d_ptr->geometryChanged && item->d_ptr->visible) {
+ // Update growingItemsBoundingRect.
+ 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());
}
}
// Process item.
- if (item && (item->d_ptr->dirty || item->d_ptr->paintedViewBoundingRectsNeedRepaint)) {
- const bool useCompatUpdate = views.isEmpty() || (connectedSignals & changedSignalMask);
- const bool untransformableItem = item->d_ptr->itemIsUntransformable();
+ if (item->d_ptr->dirty || item->d_ptr->paintedViewBoundingRectsNeedRepaint) {
+ const bool useCompatUpdate = views.isEmpty() || (connectedSignals[0] & changedSignalMask);
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())) {
+ 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.
- 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;
@@ -5505,30 +4643,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) {
- wasDirtyParentViewBoundingRects = true;
+ 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->paintedViewBoundingRectsNeedRepaint
+ && paintedViewBoundingRect.x() == -1 && paintedViewBoundingRect.y() == -1
+ && paintedViewBoundingRect.width() == -1 && paintedViewBoundingRect.height() == -1) {
+ continue; // Outside viewport.
+ }
+
if (uninitializedDirtyRect) {
dirtyRect = itemBoundingRect;
if (!item->d_ptr->fullUpdatePending) {
@@ -5541,35 +4680,25 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool
if (dirtyRect.isEmpty())
continue; // Discard updates outside the bounding rect.
- bool valid = false;
- if (untransformableItem) {
- valid = updateHelper(viewPrivate, item->d_ptr.data(), dirtyRect,
- item->deviceTransform(view->viewportTransform()));
- } else if (!view->isTransformed()) {
- valid = updateHelper(viewPrivate, item->d_ptr.data(), dirtyRect, item->d_ptr->sceneTransform);
- } else {
- QTransform deviceTransform = item->d_ptr->sceneTransform;
- deviceTransform *= view->viewportTransform();
- valid = updateHelper(viewPrivate, item->d_ptr.data(), dirtyRect, deviceTransform);
+ if (!updateHelper(viewPrivate, item->d_ptr.data(), dirtyRect, itemIsUntransformable)
+ && item->d_ptr->paintedViewBoundingRectsNeedRepaint) {
+ paintedViewBoundingRect = QRect(-1, -1, -1, -1); // Outside viewport.
}
- if (!valid)
- paintedViewBoundingRect = QRect();
}
}
}
- // Process root items / children.
- if (!item || item->d_ptr->dirtyChildren) {
- QList<QGraphicsItem *> *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)
@@ -5578,36 +4707,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);
}
/*!
@@ -5615,7 +4727,7 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool
background has been drawn, and before the foreground has been
drawn. All painting is done in \e scene coordinates. Before
drawing each item, the painter must be transformed using
- QGraphicsItem::sceneMatrix().
+ QGraphicsItem::sceneTransform().
The \a options parameter is the list of style option objects for
each item in \a items. The \a numItems parameter is the number of
@@ -5988,34 +5100,42 @@ void QGraphicsScene::setActiveWindow(QGraphicsWidget *widget)
}
}
-void QGraphicsScenePrivate::addView(QGraphicsView *view)
-{
- views << view;
- foreach(int gestureId, grabbedGestures)
- view->d_func()->grabGesture(gestureId);
-}
+/*!
+ \since 4.6
-void QGraphicsScenePrivate::removeView(QGraphicsView *view)
+ Sends event \a event to item \a item through possible event filters.
+
+ The event is sent only if the item is enabled.
+
+ Returns \c false if the event was filtered or if the item is disabled.
+ Otherwise returns the value that was returned from the event handler.
+
+ \sa QGraphicsItem::sceneEvent(), QGraphicsItem::sceneEventFilter()
+*/
+bool QGraphicsScene::sendEvent(QGraphicsItem *item, QEvent *event)
{
- views.removeAll(view);
- foreach(int gestureId, grabbedGestures)
- view->releaseGesture(gestureId);
+ Q_D(QGraphicsScene);
+ if (!item) {
+ qWarning("QGraphicsScene::sendEvent: cannot send event to a null item");
+ return false;
+ }
+ if (item->scene() != this) {
+ qWarning("QGraphicsScene::sendEvent: item %p's scene (%p)"
+ " is different from this scene (%p)",
+ item, item->scene(), this);
+ return false;
+ }
+ return d->sendEvent(item, event);
}
-void QGraphicsScenePrivate::grabGesture(QGraphicsItem *item, int gestureId)
+void QGraphicsScenePrivate::addView(QGraphicsView *view)
{
- if (!grabbedGestures.contains(gestureId)) {
- foreach(QGraphicsView *view, views)
- view->d_func()->grabGesture(gestureId);
- }
- (void)itemsWithGestures[item];
- grabbedGestures << gestureId;
+ views << view;
}
-void QGraphicsScenePrivate::releaseGesture(QGraphicsItem *item, int gestureId)
+void QGraphicsScenePrivate::removeView(QGraphicsView *view)
{
- itemsWithGestures.remove(item);
- //###
+ views.removeAll(view);
}
void QGraphicsScenePrivate::updateTouchPointsForItem(QGraphicsItem *item, QTouchEvent *touchEvent)
@@ -6227,6 +5347,11 @@ void QGraphicsScenePrivate::enableTouchEventsOnViews()
view->viewport()->setAttribute(Qt::WA_AcceptTouchEvents, true);
}
+void QGraphicsScenePrivate::updateInputMethodSensitivityInViews()
+{
+ for (int i = 0; i < views.size(); ++i)
+ views.at(i)->d_func()->updateInputMethodSensitivity();
+}
QT_END_NAMESPACE
diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h
index 7c1160c..c0c6e75 100644
--- a/src/gui/graphicsview/qgraphicsscene.h
+++ b/src/gui/graphicsview/qgraphicsscene.h
@@ -79,11 +79,11 @@ class QGraphicsSceneHelpEvent;
class QGraphicsSceneHoverEvent;
class QGraphicsSceneMouseEvent;
class QGraphicsSceneWheelEvent;
-class QGraphicsSceneGestureEvent;
class QGraphicsSimpleTextItem;
class QGraphicsTextItem;
class QGraphicsView;
class QGraphicsWidget;
+class QGraphicsSceneIndex;
class QHelpEvent;
class QInputMethodEvent;
class QKeyEvent;
@@ -153,22 +153,39 @@ public:
QRectF itemsBoundingRect() const;
QList<QGraphicsItem *> items() const;
- QList<QGraphicsItem *> items(const QPointF &pos) const;
- QList<QGraphicsItem *> items(const QRectF &rect, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const;
- QList<QGraphicsItem *> items(const QPolygonF &polygon, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const;
- QList<QGraphicsItem *> items(const QPainterPath &path, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const;
+ QList<QGraphicsItem *> items(Qt::SortOrder order) const; // ### Qt 5: unify
+
+ QList<QGraphicsItem *> items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const;
+ QList<QGraphicsItem *> items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const;
+ QList<QGraphicsItem *> items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const;
+ QList<QGraphicsItem *> items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const;
+
+ QList<QGraphicsItem *> items(const QPointF &pos) const; // ### obsolete
+ QList<QGraphicsItem *> items(const QRectF &rect, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; // ### obsolete
+ QList<QGraphicsItem *> items(const QPolygonF &polygon, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; // ### obsolete
+ QList<QGraphicsItem *> items(const QPainterPath &path, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; // ### obsolete
+
QList<QGraphicsItem *> 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<QGraphicsItem *> 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<QGraphicsItem *> 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<QGraphicsItem *> selectedItems() const;
QPainterPath selectionArea() const;
- void setSelectionArea(const QPainterPath &path);
- void setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode);
+ void setSelectionArea(const QPainterPath &path); // ### obsolete
+ void setSelectionArea(const QPainterPath &path, const QTransform &deviceTransform);
+ void setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode); // ### obsolete
+ void setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode, const QTransform &deviceTransform);
QGraphicsItemGroup *createItemGroup(const QList<QGraphicsItem *> &items);
void destroyItemGroup(QGraphicsItemGroup *group);
@@ -229,6 +246,8 @@ public:
QGraphicsWidget *activeWindow() const;
void setActiveWindow(QGraphicsWidget *widget);
+ bool sendEvent(QGraphicsItem *item, QEvent *event);
+
public Q_SLOTS:
void update(const QRectF &rect = QRectF());
void invalidate(const QRectF &rect = QRectF(), SceneLayers layers = AllLayers);
@@ -272,13 +291,10 @@ Q_SIGNALS:
void selectionChanged();
private:
- Q_DECLARE_SCOPED_PRIVATE(QGraphicsScene)
+ 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_updateLater())
Q_PRIVATE_SLOT(d_func(), void _q_polishItems())
- Q_PRIVATE_SLOT(d_func(), void _q_updateSortCache())
Q_PRIVATE_SLOT(d_func(), void _q_processDirtyItems())
friend class QGraphicsItem;
friend class QGraphicsItemPrivate;
@@ -286,6 +302,10 @@ private:
friend class QGraphicsViewPrivate;
friend class QGraphicsWidget;
friend class QGraphicsWidgetPrivate;
+ 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_bsp.cpp b/src/gui/graphicsview/qgraphicsscene_bsp.cpp
index 3f3e58b..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<QGraphicsItem *> *foundItems;
+ bool onlyTopLevelItems;
void visit(QList<QGraphicsItem *> *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,19 +146,15 @@ void QGraphicsSceneBspTree::removeItems(const QSet<QGraphicsItem *> &items)
}
}
-QList<QGraphicsItem *> QGraphicsSceneBspTree::items(const QRectF &rect)
+QList<QGraphicsItem *> QGraphicsSceneBspTree::items(const QRectF &rect, bool onlyTopLevelItems) const
{
QList<QGraphicsItem *> tmp;
findVisitor->foundItems = &tmp;
+ findVisitor->onlyTopLevelItems = onlyTopLevelItems;
climbTree(findVisitor, rect);
- return tmp;
-}
-
-QList<QGraphicsItem *> QGraphicsSceneBspTree::items(const QPointF &pos)
-{
- QList<QGraphicsItem *> 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;
}
@@ -235,47 +234,17 @@ void QGraphicsSceneBspTree::initialize(const QRectF &rect, int depth, int index)
}
}
-void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QPointF &pos, int index)
-{
- if (nodes.isEmpty())
- return;
-
- const Node &node = nodes.at(index);
- int childIndex = firstChildIndex(index);
-
- switch (node.type) {
- case Node::Leaf: {
- visitor->visit(&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)
+void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index) const
{
if (nodes.isEmpty())
return;
const Node &node = nodes.at(index);
- int childIndex = firstChildIndex(index);
+ const int childIndex = firstChildIndex(index);
switch (node.type) {
case Node::Leaf: {
- visitor->visit(&leaves[node.leafIndex]);
+ visitor->visit(const_cast<QList<QGraphicsItem*>*>(&leaves[node.leafIndex]));
break;
}
case Node::Vertical:
@@ -288,7 +257,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/qgraphicsscene_bsp_p.h b/src/gui/graphicsview/qgraphicsscene_bsp_p.h
index 73a937f..4cac64a 100644
--- a/src/gui/graphicsview/qgraphicsscene_bsp_p.h
+++ b/src/gui/graphicsview/qgraphicsscene_bsp_p.h
@@ -92,8 +92,7 @@ public:
void removeItem(QGraphicsItem *item, const QRectF &rect);
void removeItems(const QSet<QGraphicsItem *> &items);
- QList<QGraphicsItem *> items(const QRectF &rect);
- QList<QGraphicsItem *> items(const QPointF &pos);
+ QList<QGraphicsItem *> items(const QRectF &rect, bool onlyTopLevelItems = false) const;
int leafCount() const;
inline int firstChildIndex(int index) const
@@ -106,11 +105,7 @@ 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 findItems(QList<QGraphicsItem *> *foundItems, const QRectF &rect, int index);
- void findItems(QList<QGraphicsItem *> *foundItems, const QPointF &pos, int index);
+ void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index = 0) const;
QRectF rectForIndex(int index) const;
QVector<Node> nodes;
diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h
index 3c3a811..a4bbdd2 100644
--- a/src/gui/graphicsview/qgraphicsscene_p.h
+++ b/src/gui/graphicsview/qgraphicsscene_p.h
@@ -59,7 +59,6 @@
#include "qgraphicssceneevent.h"
#include "qgraphicsview.h"
-#include "qgraphicsscene_bsp_p.h"
#include "qgraphicsitem_p.h"
#include <private/qobject_p.h>
@@ -72,13 +71,11 @@
#include <QtGui/qstyle.h>
#include <QtGui/qstyleoption.h>
-static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000;
-
QT_BEGIN_NAMESPACE
+class QGraphicsSceneIndex;
class QGraphicsView;
class QGraphicsWidget;
-class QGesture;
class QGraphicsScenePrivate : public QObjectPrivate
{
@@ -87,24 +84,19 @@ public:
QGraphicsScenePrivate();
void init();
+ static QGraphicsScenePrivate *get(QGraphicsScene *q);
+
quint32 changedSignalMask;
QGraphicsScene::ItemIndexMethod indexMethod;
- int bspTreeDepth;
-
- QList<QGraphicsItem *> estimateItemsInRect(const QRectF &rect) const;
- void addToIndex(QGraphicsItem *item);
- void removeFromIndex(QGraphicsItem *item);
- void resetIndex();
+ QGraphicsSceneIndex *index;
- QGraphicsSceneBspTree bspTree;
- void _q_updateIndex();
int lastItemCount;
QRectF sceneRect;
bool hasSceneRect;
+ bool dirtyGrowingItemsBoundingRect;
QRectF growingItemsBoundingRect;
- QRectF largestUntransformableItem;
void _q_emitUpdated();
QList<QRectF> updatedRects;
@@ -115,9 +107,6 @@ public:
QPainterPath selectionArea;
int selectionChanging;
QSet<QGraphicsItem *> selectedItems;
- QList<QGraphicsItem *> unindexedItems;
- QList<QGraphicsItem *> indexedItems;
- QList<QGraphicsItem *> pendingUpdateItems;
QList<QGraphicsItem *> unpolishedItems;
QList<QGraphicsItem *> topLevelItems;
bool needSortTopLevelItems;
@@ -129,21 +118,11 @@ public:
void _q_processDirtyItems();
- QList<int> freeItemIndexes;
- bool regenerateIndex;
-
- bool purgePending;
void removeItemHelper(QGraphicsItem *item);
- QSet<QGraphicsItem *> removedItems;
- void purgeRemovedItems();
QBrush backgroundBrush;
QBrush foregroundBrush;
- int indexTimerId;
- bool restartIndexTimer;
- void startIndexTimer(int interval = QGRAPHICSSCENE_INDEXTIMER_TIMEOUT);
-
bool stickyFocus;
bool hasFocus;
QGraphicsItem *focusItem;
@@ -151,6 +130,8 @@ public:
QGraphicsWidget *tabFocusFirst;
QGraphicsWidget *activeWindow;
int activationRefCount;
+ void setFocusItemHelper(QGraphicsItem *item, Qt::FocusReason focusReason);
+ QMultiHash<QGraphicsItem *, QGraphicsItem *> focusProxyReverseMap;
QList<QGraphicsWidget *> popupWidgets;
void addPopup(QGraphicsWidget *widget);
@@ -182,7 +163,6 @@ public:
QList<QGraphicsItem *> 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<QGraphicsView *> views;
@@ -194,6 +174,7 @@ public:
QMultiMap<QGraphicsItem *, QGraphicsItem *> sceneEventFilters;
void installSceneEventFilter(QGraphicsItem *watched, QGraphicsItem *filter);
void removeSceneEventFilter(QGraphicsItem *watched, QGraphicsItem *filter);
+ bool filterDescendantEvent(QGraphicsItem *item, QEvent *event);
bool filterEvent(QGraphicsItem *item, QEvent *event);
bool sendEvent(QGraphicsItem *item, QEvent *event);
@@ -211,69 +192,14 @@ public:
void mousePressEventHandler(QGraphicsSceneMouseEvent *mouseEvent);
QGraphicsWidget *windowForItem(const QGraphicsItem *item) const;
- QList<QGraphicsItem *> topLevelItemsInStackingOrder(const QTransform *const, QRegion *);
- void recursive_items_helper(QGraphicsItem *item, QRectF rect, QList<QGraphicsItem *> *items,
- const QTransform &parentTransform, const QTransform &viewTransform,
- Qt::ItemSelectionMode mode, Qt::SortOrder order, qreal parentOpacity = 1.0) const;
-
- QList<QGraphicsItem *> items_helper(const QPointF &pos) const;
- QList<QGraphicsItem *> items_helper(const QRectF &rect,
- Qt::ItemSelectionMode mode,
- Qt::SortOrder order) const;
- QList<QGraphicsItem *> items_helper(const QPolygonF &rect,
- Qt::ItemSelectionMode mode,
- Qt::SortOrder order) const;
- QList<QGraphicsItem *> items_helper(const QPainterPath &rect,
- Qt::ItemSelectionMode mode,
- Qt::SortOrder order) const;
- void childItems_helper(QList<QGraphicsItem *> *items,
- const QGraphicsItem *parent,
- const QPointF &pos) const;
- void childItems_helper(QList<QGraphicsItem *> *items,
- const QGraphicsItem *parent,
- const QRectF &rect,
- Qt::ItemSelectionMode mode) const;
- void childItems_helper(QList<QGraphicsItem *> *items,
- const QGraphicsItem *parent,
- const QPolygonF &polygon,
- Qt::ItemSelectionMode mode) const;
- void childItems_helper(QList<QGraphicsItem *> *items,
- const QGraphicsItem *parent,
- const QPainterPath &path,
- Qt::ItemSelectionMode mode) 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<QGraphicsItem *> *itemList, Qt::SortOrder order, bool cached);
+ bool sortCacheEnabled; // for compatibility
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)
- {
- const QList<QGraphicsItem *> tli = topLevelItemsInStackingOrder(viewTransform, exposedRegion);
- 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));
@@ -283,18 +209,32 @@ 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()
+ {
+ if (needSortTopLevelItems) {
+ qSort(topLevelItems.begin(), topLevelItems.end(), qt_notclosestLeaf);
+ needSortTopLevelItems = false;
+ }
}
QStyle *style;
@@ -309,13 +249,6 @@ public:
QStyleOptionGraphicsItem styleOptionTmp;
- // items with gestures -> list of started gestures.
- QMap<QGraphicsItem*, QSet<QGesture*> > itemsWithGestures;
- QSet<int> grabbedGestures;
- void grabGesture(QGraphicsItem *item, int gestureId);
- void releaseGesture(QGraphicsItem *item, int gestureId);
- void sendGestureEvent(const QSet<QGesture*> &gestures, const QSet<QString> &cancelled);
-
QMap<int, QTouchEvent::TouchPoint> sceneCurrentTouchPoints;
QMap<int, QGraphicsItem *> itemForTouchPointId;
static void updateTouchPointsForItem(QGraphicsItem *item, QTouchEvent *touchEvent);
@@ -324,8 +257,29 @@ public:
bool sendTouchBeginEvent(QGraphicsItem *item, QTouchEvent *touchEvent);
bool allItemsIgnoreTouchEvents;
void enableTouchEventsOnViews();
+
+ void updateInputMethodSensitivityInViews();
};
+// 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.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp
new file mode 100644
index 0000000..019a85e
--- /dev/null
+++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp
@@ -0,0 +1,784 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (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 http://www.qtsoftware.com/contact.
+** $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 <QtCore/qglobal.h>
+
+#ifndef QT_NO_GRAPHICSVIEW
+
+#include <private/qgraphicsscene_p.h>
+#include <private/qgraphicsscenebsptreeindex_p.h>
+#include <private/qgraphicssceneindex_p.h>
+
+#include <QtCore/qmath.h>
+#include <QtCore/qdebug.h>
+
+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;
+
+ q->killTimer(indexTimerId);
+ indexTimerId = 0;
+
+ purgeRemovedItems();
+
+ // Add unindexedItems to indexedItems
+ for (int i = 0; i < unindexedItems.size(); ++i) {
+ if (QGraphicsItem *item = unindexedItems.at(i)) {
+ Q_ASSERT(!item->d_ptr->itemDiscovered);
+ if (!freeItemIndexes.isEmpty()) {
+ int freeIndex = freeItemIndexes.takeFirst();
+ item->d_func()->index = freeIndex;
+ indexedItems[freeIndex] = item;
+ } else {
+ item->d_func()->index = indexedItems.size();
+ indexedItems << item;
+ }
+ }
+ }
+
+ // 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(sceneRect, bspTreeDepth);
+ unindexedItems = indexedItems;
+ lastItemCount = indexedItems.size();
+ }
+
+ // Insert all unindexed items into the tree.
+ for (int i = 0; i < unindexedItems.size(); ++i) {
+ if (QGraphicsItem *item = unindexedItems.at(i)) {
+ if (item->d_ptr->itemIsUntransformable()) {
+ untransformableItems << item;
+ continue;
+ }
+ if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
+ continue;
+
+ bsp.insertItem(item, item->sceneBoundingRect());
+ }
+ }
+ unindexedItems.clear();
+}
+
+
+/*!
+ \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;
+ Q_ASSERT(!item->d_ptr->itemDiscovered);
+ unindexedItems << item;
+ }
+ }
+ indexedItems.clear();
+ freeItemIndexes.clear();
+ untransformableItems.clear();
+ regenerateIndex = true;
+ startIndexTimer();
+}
+
+/*!
+ \internal
+*/
+void QGraphicsSceneBspTreeIndexPrivate::climbTree(QGraphicsItem *item, int *stackingOrder)
+{
+ if (!item->d_ptr->children.isEmpty()) {
+ QList<QGraphicsItem *> 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<QGraphicsItem *> topLevels;
+ const QList<QGraphicsItem *> items = q->items();
+ for (int i = 0; i < items.size(); ++i) {
+ QGraphicsItem *item = items.at(i);
+ if (item && !item->d_ptr->parent)
+ 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);
+}
+
+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);
+ Q_ASSERT(!item->d_ptr->itemDiscovered);
+ freeItemIndexes << item->d_ptr->index;
+ indexedItems[item->d_ptr->index] = 0;
+ item->d_ptr->index = -1;
+
+ 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);
+ }
+}
+
+QList<QGraphicsItem *> 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<QGraphicsItem *> 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 {
+ item = item->topLevelItem();
+ if (!rectItems.contains(item))
+ rectItems << item;
+ }
+ }
+ } else {
+ rectItems += untransformableItems;
+ }
+
+ sortItems(&rectItems, order, sortCacheEnabled, onlyTopLevelItems);
+ return rectItems;
+}
+
+/*!
+ 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.data();
+ const QGraphicsItemPrivate *d2 = item2->d_ptr.data();
+ 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<QGraphicsItem *> *itemList, Qt::SortOrder order,
+ 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);
+ } 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)
+{
+
+}
+
+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;
+ }
+ }
+}
+
+/*!
+ \internal
+ Clear the all the BSP index.
+*/
+void QGraphicsSceneBspTreeIndex::clear()
+{
+ Q_D(QGraphicsSceneBspTreeIndex);
+ 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)) {
+ Q_ASSERT(!item->d_ptr->itemDiscovered);
+ item->d_ptr->index = -1;
+ }
+ }
+ d->indexedItems.clear();
+ d->unindexedItems.clear();
+ d->untransformableItems.clear();
+ d->regenerateIndex = true;
+}
+
+/*!
+ Add the \a item into the BSP index.
+*/
+void QGraphicsSceneBspTreeIndex::addItem(QGraphicsItem *item)
+{
+ Q_D(QGraphicsSceneBspTreeIndex);
+ d->addItem(item);
+}
+
+/*!
+ Remove the \a item from the BSP index.
+*/
+void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item)
+{
+ Q_D(QGraphicsSceneBspTreeIndex);
+ d->removeItem(item);
+}
+
+/*!
+ \internal
+ Update the BSP when the \a item 's bounding rect has changed.
+*/
+void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem *item)
+{
+ if (!item)
+ return;
+
+ if (item->d_ptr->index == -1 || item->d_ptr->itemIsUntransformable()
+ || (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) {
+ return; // Item is not in BSP tree; nothing to do.
+ }
+
+ Q_D(QGraphicsSceneBspTreeIndex);
+ QGraphicsItem *thatItem = const_cast<QGraphicsItem *>(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));
+}
+
+/*!
+ 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<QGraphicsItem *> QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &rect, Qt::SortOrder order) const
+{
+ Q_D(const QGraphicsSceneBspTreeIndex);
+ return const_cast<QGraphicsSceneBspTreeIndexPrivate*>(d)->estimateItems(rect, order);
+}
+
+QList<QGraphicsItem *> QGraphicsSceneBspTreeIndex::estimateTopLevelItems(const QRectF &rect, Qt::SortOrder order) const
+{
+ Q_D(const QGraphicsSceneBspTreeIndex);
+ return const_cast<QGraphicsSceneBspTreeIndexPrivate*>(d)->estimateItems(rect, order, /*onlyTopLevels=*/true);
+}
+
+/*!
+ \fn QList<QGraphicsItem *> QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order = Qt::AscendingOrder) const;
+
+ Return all items in the BSP index and sort them using \a order.
+*/
+QList<QGraphicsItem *> QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order) const
+{
+ Q_D(const QGraphicsSceneBspTreeIndex);
+ const_cast<QGraphicsSceneBspTreeIndexPrivate*>(d)->purgeRemovedItems();
+ QList<QGraphicsItem *> 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);
+ if (d->bspTreeDepth == depth)
+ return;
+ d->bspTreeDepth = depth;
+ d->resetIndex();
+}
+
+/*!
+ \internal
+
+ This method react to the \a rect change of the scene and
+ reset the BSP tree index.
+*/
+void QGraphicsSceneBspTreeIndex::updateSceneRect(const QRectF &rect)
+{
+ Q_D(QGraphicsSceneBspTreeIndex);
+ d->sceneRect = rect;
+ d->resetIndex();
+}
+
+/*!
+ \internal
+
+ 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::itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value)
+{
+ Q_D(QGraphicsSceneBspTreeIndex);
+ switch (change) {
+ case QGraphicsItem::ItemFlagsChange: {
+ // Handle ItemIgnoresTransformations
+ bool ignoredTransform = item->d_ptr->flags & QGraphicsItem::ItemIgnoresTransformations;
+ bool willIgnoreTransform = value.toUInt() & QGraphicsItem::ItemIgnoresTransformations;
+ bool clipsChildren = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape;
+ bool willClipChildren = value.toUInt() & QGraphicsItem::ItemClipsChildrenToShape;
+ if ((ignoredTransform != willIgnoreTransform) || (clipsChildren != willClipChildren)) {
+ QGraphicsItem *thatItem = const_cast<QGraphicsItem *>(item);
+ // 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;
+ }
+ case QGraphicsItem::ItemZValueChange:
+ d->invalidateSortCache();
+ break;
+ case QGraphicsItem::ItemParentChange: {
+ d->invalidateSortCache();
+ // Handle ItemIgnoresTransformations
+ QGraphicsItem *newParent = qVariantValue<QGraphicsItem *>(value);
+ bool ignoredTransform = item->d_ptr->itemIsUntransformable();
+ 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<QGraphicsItem *>(item);
+ // 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;
+ }
+ default:
+ break;
+ }
+ return QGraphicsSceneIndex::itemChange(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<QTimerEvent *>(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
new file mode 100644
index 0000000..2293a8e
--- /dev/null
+++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h
@@ -0,0 +1,208 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore 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 http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// 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
+
+#include <QtCore/qglobal.h>
+
+#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 <QtCore/qrect.h>
+#include <QtCore/qlist.h>
+
+QT_BEGIN_NAMESPACE
+
+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);
+ ~QGraphicsSceneBspTreeIndex();
+
+ QList<QGraphicsItem *> estimateItems(const QRectF &rect, Qt::SortOrder order) const;
+ QList<QGraphicsItem *> estimateTopLevelItems(const QRectF &rect, Qt::SortOrder order) const;
+ QList<QGraphicsItem *> items(Qt::SortOrder order = Qt::AscendingOrder) const;
+
+ int bspTreeDepth();
+ void setBspTreeDepth(int depth);
+
+protected Q_SLOTS:
+ void updateSceneRect(const QRectF &rect);
+
+protected:
+ bool event(QEvent *event);
+ void clear();
+
+ void addItem(QGraphicsItem *item);
+ void removeItem(QGraphicsItem *item);
+ void prepareBoundingRectChange(const QGraphicsItem *item);
+
+ 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
+{
+ Q_DECLARE_PUBLIC(QGraphicsSceneBspTreeIndex)
+public:
+ QGraphicsSceneBspTreeIndexPrivate(QGraphicsScene *scene);
+
+ QGraphicsSceneBspTree bsp;
+ QRectF sceneRect;
+ int bspTreeDepth;
+ int indexTimerId;
+ bool restartIndexTimer;
+ bool regenerateIndex;
+ int lastItemCount;
+
+ QList<QGraphicsItem *> indexedItems;
+ QList<QGraphicsItem *> unindexedItems;
+ QList<QGraphicsItem *> untransformableItems;
+ QList<int> freeItemIndexes;
+
+ bool purgePending;
+ QSet<QGraphicsItem *> removedItems;
+ void purgeRemovedItems();
+
+ void _q_updateIndex();
+ void startIndexTimer(int interval = QGRAPHICSSCENE_INDEXTIMER_TIMEOUT);
+ void resetIndex();
+
+ 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);
+ QList<QGraphicsItem *> 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);
+ 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<QGraphicsItem *> *itemList, Qt::SortOrder order,
+ bool cached, bool onlyTopLevelItems = false);
+};
+
+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 // QT_NO_GRAPHICSVIEW
+
+#endif // QGRAPHICSBSPTREEINDEX_H
diff --git a/src/gui/graphicsview/qgraphicssceneevent.cpp b/src/gui/graphicsview/qgraphicssceneevent.cpp
index 987ae9a..73cc787 100644
--- a/src/gui/graphicsview/qgraphicssceneevent.cpp
+++ b/src/gui/graphicsview/qgraphicssceneevent.cpp
@@ -275,8 +275,6 @@
QT_BEGIN_NAMESPACE
-QString qt_getStandardGestureTypeName(Qt::GestureType type);
-
class QGraphicsSceneEventPrivate
{
public:
@@ -1477,7 +1475,7 @@ void QGraphicsSceneDragDropEvent::acceptProposedAction()
/*!
Returns the action that was performed in this drag and drop.
This should be set by the receiver of the drop and is
- returned by QDrag::start().
+ returned by QDrag::exec().
\sa setDropAction(), acceptProposedAction()
*/
@@ -1678,249 +1676,6 @@ void QGraphicsSceneMoveEvent::setNewPos(const QPointF &pos)
d->newPos = pos;
}
-/*!
- \class QGraphicsSceneGestureEvent
- \brief The QGraphicsSceneGestureEvent class provides gesture events for
- the graphics view framework.
- \since 4.6
- \ingroup multimedia
- \ingroup graphicsview-api
-
- QGraphicsSceneGestureEvent extends information provided by
- QGestureEvent by adding some convenience functions like
- \l{QGraphicsSceneEvent::}{widget()} to get a widget that received
- original gesture event, and convenience functions mapToScene(),
- mapToItem() for converting positions of the gesture into
- QGraphicsScene and QGraphicsItem coordinate system respectively.
-
- The scene sends the event to the first QGraphicsItem under the
- mouse cursor that accepts gestures; a graphics item is set to accept
- gestures with \l{QGraphicsItem::}{grabGesture()}.
-
- \sa QGestureEvent
-*/
-
-/*!
- Constructs a QGraphicsSceneGestureEvent.
-*/
-QGraphicsSceneGestureEvent::QGraphicsSceneGestureEvent()
- : QGraphicsSceneEvent(QEvent::GraphicsSceneGesture)
-{
- setAccepted(false);
-}
-
-/*!
- Destroys a QGraphicsSceneGestureEvent.
-*/
-QGraphicsSceneGestureEvent::~QGraphicsSceneGestureEvent()
-{
-}
-
-/*!
- Returns true if the gesture event contains gesture of specific \a
- type; returns false otherwise.
-*/
-bool QGraphicsSceneGestureEvent::contains(const QString &type) const
-{
- return gesture(type) != 0;
-}
-
-/*!
- Returns true if the gesture event contains gesture of specific \a
- type; returns false otherwise.
-*/
-bool QGraphicsSceneGestureEvent::contains(Qt::GestureType type) const
-{
- return contains(qt_getStandardGestureTypeName(type));
-}
-
-/*!
- Returns a list of gesture names that this event contains.
-*/
-QList<QString> QGraphicsSceneGestureEvent::gestureTypes() const
-{
- return m_gestures.keys();
-}
-
-/*!
- Returns extended information about a gesture of specific \a type.
-*/
-const QGesture* QGraphicsSceneGestureEvent::gesture(const QString &type) const
-{
- return m_gestures.value(type, 0);
-}
-
-/*!
- Returns extended information about a gesture of specific \a type.
-*/
-const QGesture* QGraphicsSceneGestureEvent::gesture(Qt::GestureType type) const
-{
- return gesture(qt_getStandardGestureTypeName(type));
-}
-
-/*!
- Returns extended information about all gestures in the event.
-*/
-QList<QGesture*> QGraphicsSceneGestureEvent::gestures() const
-{
- return m_gestures.values();
-}
-
-/*!
- Returns a set of gesture names that used to be executed, but were
- cancelled (i.e. they were not finished properly).
-*/
-QSet<QString> QGraphicsSceneGestureEvent::cancelledGestures() const
-{
- return m_cancelledGestures;
-}
-
-/*!
- Sets a list of gesture names \a cancelledGestures that used to be
- executed, but were cancelled (i.e. they were not finished
- properly).
-*/
-void QGraphicsSceneGestureEvent::setCancelledGestures(const QSet<QString> &cancelledGestures)
-{
- m_cancelledGestures = cancelledGestures;
-}
-
-/*!
- Maps the point \a point, which is in a view coordinate system, to
- scene coordinate system, and returns the mapped coordinate.
-
- A \a point is in coordinate system of the widget that received
- gesture event.
-
- \sa mapToItem(), {The Graphics View Coordinate System}
-*/
-QPointF QGraphicsSceneGestureEvent::mapToScene(const QPoint &point) const
-{
- if (QGraphicsView *view = qobject_cast<QGraphicsView*>(widget()))
- return view->mapToScene(point);
- return QPointF();
-}
-
-/*!
- Maps the rectangular \a rect, which is in a view coordinate system, to
- scene coordinate system, and returns the mapped coordinate.
-
- A \a rect is in coordinate system of the widget that received
- gesture event.
-
- \sa mapToItem(), {The Graphics View Coordinate System}
-*/
-QPolygonF QGraphicsSceneGestureEvent::mapToScene(const QRect &rect) const
-{
- if (QGraphicsView *view = qobject_cast<QGraphicsView*>(widget()))
- return view->mapToScene(rect);
- return QPolygonF();
-}
-
-/*!
- Maps the point \a point, which is in a view coordinate system, to
- item's \a item coordinate system, and returns the mapped coordinate.
-
- If \a item is 0, this function returns the same as mapToScene().
-
- \sa mapToScene(), {The Graphics View Coordinate System}
-*/
-QPointF QGraphicsSceneGestureEvent::mapToItem(const QPoint &point, QGraphicsItem *item) const
-{
- if (item) {
- if (QGraphicsView *view = qobject_cast<QGraphicsView*>(widget()))
- return item->mapFromScene(view->mapToScene(point));
- } else {
- return mapToScene(point);
- }
- return QPointF();
-}
-
-/*!
- Maps the rectangualar \a rect, which is in a view coordinate system, to
- item's \a item coordinate system, and returns the mapped coordinate.
-
- If \a item is 0, this function returns the same as mapToScene().
-
- \sa mapToScene(), {The Graphics View Coordinate System}
-*/
-QPolygonF QGraphicsSceneGestureEvent::mapToItem(const QRect &rect, QGraphicsItem *item) const
-{
- if (item) {
- if (QGraphicsView *view = qobject_cast<QGraphicsView*>(widget()))
- return item->mapFromScene(view->mapToScene(rect));
- } else {
- return mapToScene(rect);
- }
- return QPolygonF();
-}
-
-/*!
- Set a list of gesture objects containing extended information about \a gestures.
-*/
-void QGraphicsSceneGestureEvent::setGestures(const QList<QGesture*> &gestures)
-{
- foreach(QGesture *g, gestures)
- m_gestures.insert(g->type(), g);
-}
-
-/*!
- Set a list of gesture objects containing extended information about \a gestures.
-*/
-void QGraphicsSceneGestureEvent::setGestures(const QSet<QGesture*> &gestures)
-{
- foreach(QGesture *g, gestures)
- m_gestures.insert(g->type(), g);
-}
-
-/*!
- Sets the accept flag of the all gestures inside the event object,
- the equivalent of calling \l{QEvent::accept()}{accept()} or
- \l{QEvent::setAccepted()}{setAccepted(true)}.
-
- Setting the accept parameter indicates that the event receiver
- wants the gesture. Unwanted gestures might be propagated to the parent
- widget.
-*/
-void QGraphicsSceneGestureEvent::acceptAll()
-{
- QHash<QString, QGesture*>::iterator it = m_gestures.begin(),
- e = m_gestures.end();
- for(; it != e; ++it)
- it.value()->accept();
- setAccepted(true);
-}
-
-/*!
- Sets the accept flag of the specified gesture inside the event
- object, the equivalent of calling
- \l{QGestureEvent::gesture()}{gesture(type)}->\l{QGesture::accept()}{accept()}
-
- Setting the accept parameter indicates that the event receiver
- wants the gesture. Unwanted gestures might be propagated to the parent
- widget.
-*/
-void QGraphicsSceneGestureEvent::accept(Qt::GestureType type)
-{
- if (QGesture *g = m_gestures.value(qt_getStandardGestureTypeName(type), 0))
- g->accept();
-}
-
-/*!
- Sets the accept flag of the specified gesture inside the event
- object, the equivalent of calling
- \l{QGestureEvent::gesture()}{gesture(type)}->\l{QGesture::accept()}{accept()}
-
- Setting the accept parameter indicates that the event receiver
- wants the gesture. Unwanted gestures might be propagated to the parent
- widget.
-*/
-void QGraphicsSceneGestureEvent::accept(const QString &type)
-{
- if (QGesture *g = m_gestures.value(type, 0))
- g->accept();
-}
-
QT_END_NAMESPACE
#endif // QT_NO_GRAPHICSVIEW
diff --git a/src/gui/graphicsview/qgraphicssceneevent.h b/src/gui/graphicsview/qgraphicssceneevent.h
index 6850b3d..ea17f9d 100644
--- a/src/gui/graphicsview/qgraphicssceneevent.h
+++ b/src/gui/graphicsview/qgraphicssceneevent.h
@@ -76,7 +76,7 @@ public:
protected:
QGraphicsSceneEvent(QGraphicsSceneEventPrivate &dd, Type type = None);
QScopedPointer<QGraphicsSceneEventPrivate> d_ptr;
- Q_DECLARE_SCOPED_PRIVATE(QGraphicsSceneEvent)
+ Q_DECLARE_PRIVATE(QGraphicsSceneEvent)
};
class QGraphicsSceneMouseEventPrivate;
@@ -123,7 +123,7 @@ public:
void setModifiers(Qt::KeyboardModifiers modifiers);
private:
- Q_DECLARE_SCOPED_PRIVATE(QGraphicsSceneMouseEvent)
+ Q_DECLARE_PRIVATE(QGraphicsSceneMouseEvent)
};
class QGraphicsSceneWheelEventPrivate;
@@ -155,7 +155,7 @@ public:
void setOrientation(Qt::Orientation orientation);
private:
- Q_DECLARE_SCOPED_PRIVATE(QGraphicsSceneWheelEvent)
+ Q_DECLARE_PRIVATE(QGraphicsSceneWheelEvent)
};
class QGraphicsSceneContextMenuEventPrivate;
@@ -183,7 +183,7 @@ public:
void setReason(Reason reason);
private:
- Q_DECLARE_SCOPED_PRIVATE(QGraphicsSceneContextMenuEvent)
+ Q_DECLARE_PRIVATE(QGraphicsSceneContextMenuEvent)
};
class QGraphicsSceneHoverEventPrivate;
@@ -215,7 +215,7 @@ public:
void setModifiers(Qt::KeyboardModifiers modifiers);
private:
- Q_DECLARE_SCOPED_PRIVATE(QGraphicsSceneHoverEvent)
+ Q_DECLARE_PRIVATE(QGraphicsSceneHoverEvent)
};
class QGraphicsSceneHelpEventPrivate;
@@ -232,7 +232,7 @@ public:
void setScreenPos(const QPoint &pos);
private:
- Q_DECLARE_SCOPED_PRIVATE(QGraphicsSceneHelpEvent)
+ Q_DECLARE_PRIVATE(QGraphicsSceneHelpEvent)
};
class QGraphicsSceneDragDropEventPrivate;
@@ -274,13 +274,13 @@ public:
void setMimeData(const QMimeData *data);
private:
- Q_DECLARE_SCOPED_PRIVATE(QGraphicsSceneDragDropEvent)
+ Q_DECLARE_PRIVATE(QGraphicsSceneDragDropEvent)
};
class QGraphicsSceneResizeEventPrivate;
class Q_GUI_EXPORT QGraphicsSceneResizeEvent : public QGraphicsSceneEvent
{
- Q_DECLARE_SCOPED_PRIVATE(QGraphicsSceneResizeEvent)
+ Q_DECLARE_PRIVATE(QGraphicsSceneResizeEvent)
public:
QGraphicsSceneResizeEvent();
~QGraphicsSceneResizeEvent();
@@ -295,7 +295,7 @@ public:
class QGraphicsSceneMoveEventPrivate;
class Q_GUI_EXPORT QGraphicsSceneMoveEvent : public QGraphicsSceneEvent
{
- Q_DECLARE_SCOPED_PRIVATE(QGraphicsSceneMoveEvent)
+ Q_DECLARE_PRIVATE(QGraphicsSceneMoveEvent)
public:
QGraphicsSceneMoveEvent();
~QGraphicsSceneMoveEvent();
@@ -307,49 +307,6 @@ public:
void setNewPos(const QPointF &pos);
};
-class QGesture;
-class QGraphicsItem;
-class QGraphicsSceneGestureEventPrivate;
-class Q_GUI_EXPORT QGraphicsSceneGestureEvent : public QGraphicsSceneEvent
-{
- Q_DECLARE_SCOPED_PRIVATE(QGraphicsSceneGestureEvent)
-public:
- QGraphicsSceneGestureEvent();
- ~QGraphicsSceneGestureEvent();
-
- bool contains(const QString &type) const;
- bool contains(Qt::GestureType type) const;
-
- QList<QString> gestureTypes() const;
-
- const QGesture* gesture(Qt::GestureType type) const;
- const QGesture* gesture(const QString &type) const;
- QList<QGesture*> gestures() const;
- void setGestures(const QList<QGesture*> &gestures);
- void setGestures(const QSet<QGesture*> &gestures);
-
- QSet<QString> cancelledGestures() const;
- void setCancelledGestures(const QSet<QString> &cancelledGestures);
-
- void acceptAll();
-#ifndef Q_NO_USING_KEYWORD
- using QEvent::accept;
-#else
- inline void accept() { QEvent::accept(); }
-#endif
- void accept(Qt::GestureType type);
- void accept(const QString &type);
-
- QPointF mapToScene(const QPoint &point) const;
- QPolygonF mapToScene(const QRect &rect) const;
- QPointF mapToItem(const QPoint &point, QGraphicsItem *item) const;
- QPolygonF mapToItem(const QRect &rect, QGraphicsItem *item) const;
-
-protected:
- QHash<QString, QGesture*> m_gestures;
- QSet<QString> m_cancelledGestures;
-};
-
#endif // QT_NO_GRAPHICSVIEW
QT_END_NAMESPACE
diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp
new file mode 100644
index 0000000..a5dc363
--- /dev/null
+++ b/src/gui/graphicsview/qgraphicssceneindex.cpp
@@ -0,0 +1,648 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (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 http://www.qtsoftware.com/contact.
+** $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
+ \internal
+
+ 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 "qdebug.h"
+#include "qgraphicsscene.h"
+#include "qgraphicsitem_p.h"
+#include "qgraphicsscene_p.h"
+#include "qgraphicswidget.h"
+#include "qgraphicssceneindex_p.h"
+#include "qgraphicsscenebsptreeindex_p.h"
+
+#ifndef QT_NO_GRAPHICSVIEW
+
+QT_BEGIN_NAMESPACE
+
+class QGraphicsSceneIndexRectIntersector : public QGraphicsSceneIndexIntersector
+{
+public:
+ bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode,
+ 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;
+ 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;
+ 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 {
+ 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 != brect && sceneRect.contains(itemSceneBoundingRect);
+ else
+ keep = sceneRect.intersects(itemSceneBoundingRect);
+ if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
+ QPainterPath rectPath;
+ rectPath.addRect(sceneRect);
+ 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;
+ }
+
+ QRectF sceneRect;
+};
+
+class QGraphicsSceneIndexPointIntersector : public QGraphicsSceneIndexIntersector
+{
+public:
+ bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode,
+ 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;
+ 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)) {
+ QPainterPath pointPath;
+ pointPath.addRect(QRectF(itemPoint, QSizeF(1, 1)));
+ keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, pointPath, mode);
+ }
+ } else {
+ 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;
+ }
+
+ QPointF scenePoint;
+};
+
+class QGraphicsSceneIndexPathIntersector : public QGraphicsSceneIndexIntersector
+{
+public:
+ bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode,
+ 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;
+ 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);
+ else
+ keep = itemPath.intersects(brect);
+ 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(itemSceneBoundingRect);
+ else
+ keep = scenePath.intersects(itemSceneBoundingRect);
+ if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
+ QPainterPath itemPath = itemd->sceneTransformTranslateOnly
+ ? scenePath.translated(-itemd->sceneTransform.dx(),
+ -itemd->sceneTransform.dy())
+ : itemd->sceneTransform.inverted().map(scenePath);
+ keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, itemPath, mode);
+ }
+ }
+ return keep;
+ }
+
+ QPainterPath scenePath;
+};
+
+/*!
+ Constructs a private scene index.
+*/
+QGraphicsSceneIndexPrivate::QGraphicsSceneIndexPrivate(QGraphicsScene *scene) : scene(scene)
+{
+ pointIntersector = new QGraphicsSceneIndexPointIntersector;
+ rectIntersector = new QGraphicsSceneIndexRectIntersector;
+ pathIntersector = new QGraphicsSceneIndexPathIntersector;
+}
+
+/*!
+ Destructor of private scene index.
+*/
+QGraphicsSceneIndexPrivate::~QGraphicsSceneIndexPrivate()
+{
+ delete pointIntersector;
+ delete rectIntersector;
+ delete pathIntersector;
+}
+
+/*!
+ \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<const QGraphicsWidget *>(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, QRectF exposeRect,
+ QGraphicsSceneIndexIntersector *intersector,
+ QList<QGraphicsItem *> *items,
+ const QTransform &viewTransform,
+ Qt::ItemSelectionMode mode, Qt::SortOrder order,
+ qreal parentOpacity) const
+{
+ Q_ASSERT(item);
+ if (!item->d_ptr->visible)
+ return;
+
+ 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;
+
+ // 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, 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;
+ if (itemHasChildren) {
+ // Sort children.
+ item->d_ptr->ensureSortedChildren();
+
+ // Clip to shape.
+ 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, viewTransform,
+ mode, order, opacity);
+ }
+ }
+
+ // Process item
+ if (processItem)
+ items->append(item);
+
+ // Process children in front
+ 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, viewTransform,
+ mode, order, opacity);
+ }
+ }
+}
+
+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)
+{
+ d_func()->init();
+}
+
+/*!
+ \internal
+*/
+QGraphicsSceneIndex::QGraphicsSceneIndex(QGraphicsSceneIndexPrivate &dd, QGraphicsScene *scene)
+ : QObject(dd, scene)
+{
+ d_func()->init();
+}
+
+/*!
+ Destroys the scene index.
+*/
+QGraphicsSceneIndex::~QGraphicsSceneIndex()
+{
+
+}
+
+/*!
+ Returns the scene of this index.
+*/
+QGraphicsScene* QGraphicsSceneIndex::scene() const
+{
+ Q_D(const QGraphicsSceneIndex);
+ return d->scene;
+}
+
+/*!
+ \fn QList<QGraphicsItem *> 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.
+
+ 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.
+
+ \sa estimateItems()
+
+*/
+QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSelectionMode mode,
+ Qt::SortOrder order, const QTransform &deviceTransform) const
+{
+
+ Q_D(const QGraphicsSceneIndex);
+ QList<QGraphicsItem *> itemList;
+ d->pointIntersector->scenePoint = pos;
+ d->items_helper(QRectF(pos, QSizeF(1, 1)), d->pointIntersector, &itemList, deviceTransform, mode, order);
+ return itemList;
+}
+
+/*!
+ \fn QList<QGraphicsItem *> 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.
+
+ 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<QGraphicsItem *> QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSelectionMode mode,
+ Qt::SortOrder order, const QTransform &deviceTransform) const
+{
+ Q_D(const QGraphicsSceneIndex);
+ QRectF exposeRect = rect;
+ _q_adjustRect(&exposeRect);
+ QList<QGraphicsItem *> itemList;
+ d->rectIntersector->sceneRect = rect;
+ d->items_helper(exposeRect, d->rectIntersector, &itemList, deviceTransform, mode, order);
+ return itemList;
+}
+
+/*!
+ \fn QList<QGraphicsItem *> 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.
+
+ 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<QGraphicsItem *> QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode,
+ Qt::SortOrder order, const QTransform &deviceTransform) const
+{
+ Q_D(const QGraphicsSceneIndex);
+ QList<QGraphicsItem *> itemList;
+ QRectF exposeRect = polygon.boundingRect();
+ _q_adjustRect(&exposeRect);
+ QPainterPath path;
+ path.addPolygon(polygon);
+ d->pathIntersector->scenePath = path;
+ d->items_helper(exposeRect, d->pathIntersector, &itemList, deviceTransform, mode, order);
+ return itemList;
+}
+
+/*!
+ \fn QList<QGraphicsItem *> 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.
+
+ 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<QGraphicsItem *> QGraphicsSceneIndex::items(const QPainterPath &path, Qt::ItemSelectionMode mode,
+ Qt::SortOrder order, const QTransform &deviceTransform) const
+{
+ Q_D(const QGraphicsSceneIndex);
+ QList<QGraphicsItem *> itemList;
+ QRectF exposeRect = path.controlPointRect();
+ _q_adjustRect(&exposeRect);
+ d->pathIntersector->scenePath = path;
+ d->items_helper(exposeRect, d->pathIntersector, &itemList, deviceTransform, mode, order);
+ return itemList;
+}
+
+/*!
+ This virtual function return an estimation of items at position \a point.
+ This method return a list sorted using \a order.
+*/
+QList<QGraphicsItem *> QGraphicsSceneIndex::estimateItems(const QPointF &point, Qt::SortOrder order) const
+{
+ return estimateItems(QRectF(point, QSize(1, 1)), order);
+}
+
+QList<QGraphicsItem *> QGraphicsSceneIndex::estimateTopLevelItems(const QRectF &rect, Qt::SortOrder order) const
+{
+ Q_D(const QGraphicsSceneIndex);
+ Q_UNUSED(rect);
+ QGraphicsScenePrivate *scened = d->scene->d_func();
+ scened->ensureSortedTopLevelItems();
+ if (order == Qt::AscendingOrder) {
+ QList<QGraphicsItem *> sorted;
+ for (int i = scened->topLevelItems.size() - 1; i >= 0; --i)
+ sorted << scened->topLevelItems.at(i);
+ return sorted;
+ }
+ return scened->topLevelItems;
+}
+
+/*!
+ \fn QList<QGraphicsItem *> QGraphicsSceneIndex::items(Qt::SortOrder order = Qt::AscendingOrder) const
+
+ This pure virtual function all items in the index and sort them using
+ \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.
+*/
+void QGraphicsSceneIndex::clear()
+{
+ const QList<QGraphicsItem *> allItems = items();
+ for (int i = 0 ; i < allItems.size(); ++i)
+ removeItem(allItems.at(i));
+}
+
+/*!
+ \fn virtual void QGraphicsSceneIndex::addItem(QGraphicsItem *item) = 0
+
+ This pure virtual function inserts an \a item to the scene index.
+
+ \sa removeItem(), deleteItem()
+*/
+
+/*!
+ \fn virtual void QGraphicsSceneIndex::removeItem(QGraphicsItem *item) = 0
+
+ This pure virtual function removes an \a item to the scene index.
+
+ \sa addItem(), deleteItem()
+*/
+
+/*!
+ 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
+ this method.
+
+ \sa addItem(), removeItem()
+*/
+void QGraphicsSceneIndex::deleteItem(QGraphicsItem *item)
+{
+ removeItem(item);
+}
+
+/*!
+ This virtual function is called by QGraphicsItem to notify the index
+ 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.
+
+ \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.
+
+ The default implementation does nothing.
+
+ \sa QGraphicsItem::GraphicsItemChange
+*/
+void QGraphicsSceneIndex::itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value)
+{
+ Q_UNUSED(item);
+ Q_UNUSED(change);
+ Q_UNUSED(value);
+}
+
+/*!
+ Notify the index for a geometry change of an \a item.
+
+ \sa QGraphicsItem::prepareGeometryChange()
+*/
+void QGraphicsSceneIndex::prepareBoundingRectChange(const QGraphicsItem *item)
+{
+ Q_UNUSED(item);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qgraphicssceneindex_p.cpp"
+
+#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..37dffb8
--- /dev/null
+++ b/src/gui/graphicsview/qgraphicssceneindex_p.h
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore 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 http://www.qtsoftware.com/contact.
+** $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 "qgraphicsscene_p.h"
+#include "qgraphicsscene.h"
+#include <private/qobject_p.h>
+
+#include <QtCore/qnamespace.h>
+#include <QtCore/qobject.h>
+#include <QtGui/qtransform.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW
+
+class QGraphicsSceneIndexIntersector;
+class QGraphicsSceneIndexPointIntersector;
+class QGraphicsSceneIndexRectIntersector;
+class QGraphicsSceneIndexPathIntersector;
+class QGraphicsSceneIndexPrivate;
+class QPointF;
+class QRectF;
+template<typename T> class QList;
+
+class Q_AUTOTEST_EXPORT QGraphicsSceneIndex : public QObject
+{
+ Q_OBJECT
+
+public:
+ QGraphicsSceneIndex(QGraphicsScene *scene = 0);
+ virtual ~QGraphicsSceneIndex();
+
+ QGraphicsScene *scene() const;
+
+ virtual QList<QGraphicsItem *> items(Qt::SortOrder order = Qt::AscendingOrder) const = 0;
+ virtual QList<QGraphicsItem *> items(const QPointF &pos, Qt::ItemSelectionMode mode,
+ Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const;
+ virtual QList<QGraphicsItem *> items(const QRectF &rect, Qt::ItemSelectionMode mode,
+ Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const;
+ virtual QList<QGraphicsItem *> items(const QPolygonF &polygon, Qt::ItemSelectionMode mode,
+ Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const;
+ virtual QList<QGraphicsItem *> items(const QPainterPath &path, Qt::ItemSelectionMode mode,
+ Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const;
+ virtual QList<QGraphicsItem *> estimateItems(const QPointF &point, Qt::SortOrder order) const;
+ virtual QList<QGraphicsItem *> estimateItems(const QRectF &rect, Qt::SortOrder order) const = 0;
+ virtual QList<QGraphicsItem *> estimateTopLevelItems(const QRectF &, Qt::SortOrder order) const;
+
+protected Q_SLOTS:
+ virtual void updateSceneRect(const QRectF &rect);
+
+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);
+
+ QGraphicsSceneIndex(QGraphicsSceneIndexPrivate &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
+{
+ Q_DECLARE_PUBLIC(QGraphicsSceneIndex)
+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,
+ QGraphicsSceneIndexIntersector *intersector, QList<QGraphicsItem *> *items,
+ const QTransform &viewTransform,
+ Qt::ItemSelectionMode mode, Qt::SortOrder order, qreal parentOpacity = 1.0) const;
+ inline void items_helper(const QRectF &rect, QGraphicsSceneIndexIntersector *intersector,
+ QList<QGraphicsItem *> *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<QGraphicsItem *> *items, const QTransform &viewTransform,
+ Qt::ItemSelectionMode mode, Qt::SortOrder order) const
+{
+ Q_Q(const QGraphicsSceneIndex);
+ const QList<QGraphicsItem *> tli = q->estimateTopLevelItems(rect, Qt::DescendingOrder);
+ for (int i = 0; i < tli.size(); ++i)
+ 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)
+ items->swap(i, n - i - 1);
+ }
+}
+
+class QGraphicsSceneIndexIntersector
+{
+public:
+ QGraphicsSceneIndexIntersector() { }
+ virtual ~QGraphicsSceneIndexIntersector() { }
+ virtual bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode,
+ const QTransform &deviceTransform) const = 0;
+};
+
+#endif // QT_NO_GRAPHICSVIEW
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QGRAPHICSSCENEINDEX_H
diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex.cpp b/src/gui/graphicsview/qgraphicsscenelinearindex.cpp
new file mode 100644
index 0000000..52bbc79
--- /dev/null
+++ b/src/gui/graphicsview/qgraphicsscenelinearindex.cpp
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (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 http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QGraphicsSceneLinearIndex
+ \brief The QGraphicsSceneLinearIndex class provides an implementation of
+ a linear indexing algorithm for discovering items in QGraphicsScene.
+ \since 4.6
+ \ingroup graphicsview-api
+ \internal
+
+ 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
+*/
+
+#include <private/qgraphicsscenelinearindex_p.h>
+
+/*!
+ \fn QGraphicsSceneLinearIndex::QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0):
+
+ Construct a linear index for the given \a scene.
+*/
+
+/*!
+ \fn QList<QGraphicsItem *> QGraphicsSceneLinearIndex::items(Qt::SortOrder order = Qt::AscendingOrder) const;
+
+ Return all items in the index and sort them using \a order.
+*/
+
+
+/*!
+ \fn virtual QList<QGraphicsItem *> 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.
+*/
+
+/*!
+ \fn void QGraphicsSceneLinearIndex::clear()
+ \internal
+ 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.
+*/
+
diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h
new file mode 100644
index 0000000..1f3d58b
--- /dev/null
+++ b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore 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 http://www.qtsoftware.com/contact.
+** $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 <QtCore/qglobal.h>
+
+#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW
+
+#include <QtCore/qrect.h>
+#include <QtCore/qlist.h>
+#include <QtGui/qgraphicsitem.h>
+#include <private/qgraphicssceneindex_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex
+{
+ Q_OBJECT
+
+public:
+ QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0) : QGraphicsSceneIndex(scene)
+ { }
+
+ QList<QGraphicsItem *> items(Qt::SortOrder order = Qt::AscendingOrder) const
+ { Q_UNUSED(order); return m_items; }
+
+ virtual QList<QGraphicsItem *> estimateItems(const QRectF &rect, Qt::SortOrder order) const
+ {
+ Q_UNUSED(rect);
+ Q_UNUSED(order);
+ return m_items;
+ }
+
+protected :
+ virtual void clear()
+ { m_items.clear(); }
+
+ virtual void addItem(QGraphicsItem *item)
+ { m_items << item; }
+
+ virtual void removeItem(QGraphicsItem *item)
+ { m_items.removeOne(item); }
+
+private:
+ QList<QGraphicsItem*> m_items;
+};
+
+#endif // QT_NO_GRAPHICSVIEW
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QGRAPHICSSCENELINEARINDEX_H
diff --git a/src/gui/graphicsview/qgraphicstransform.cpp b/src/gui/graphicsview/qgraphicstransform.cpp
new file mode 100644
index 0000000..9e73176
--- /dev/null
+++ b/src/gui/graphicsview/qgraphicstransform.cpp
@@ -0,0 +1,573 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative 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 http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QGraphicsTransform
+ \brief The QGraphicsTransform class is an abstract base class for building
+ advanced transformations on QGraphicsItems.
+ \since 4.6
+
+ As an alternative to QGraphicsItem::transform, QGraphicsTransform lets you
+ create and control advanced transformations that can be configured
+ independently using specialized properties.
+
+ QGraphicsItem allows you to assign any number of QGraphicsTransform
+ instances to one QGraphicsItem. Each QGraphicsTransform is applied in
+ order, one at a time, to the QGraphicsItem it's assigned to.
+
+ QGraphicsTransform is particularily useful for animations. Whereas
+ QGraphicsItem::setTransform() lets you assign any transform directly to an
+ item, there is no direct way to interpolate between two different
+ transformations (e.g., when transitioning between two states, each for
+ which the item has a different arbitrary transform assigned). Using
+ QGraphicsTransform you can interpolate the property values of each
+ independent transformation. The resulting operation is then combined into a
+ single transform which is applied to QGraphicsItem.
+
+ If you want to create your own configurable transformation, you can create
+ a subclass of QGraphicsTransform (or any or the existing subclasses), and
+ reimplement the pure virtual applyTo() function, which takes a pointer to a
+ QTransform. Each operation you would like to apply should be exposed as
+ properties (e.g., customTransform->setVerticalShear(2.5)). Inside you
+ reimplementation of applyTo(), you can modify the provided transform
+ respectively.
+
+ QGraphicsTransform can be used together with QGraphicsItem::setTransform(),
+ QGraphicsItem::setRotation(), and QGraphicsItem::setScale().
+
+ \sa QGraphicsItem::transform(), QGraphicsScale, QGraphicsRotation, QGraphicsRotation3D
+*/
+
+#include "qgraphicstransform.h"
+#include "qgraphicsitem_p.h"
+#include "qgraphicstransform_p.h"
+#include <QDebug>
+
+#include <math.h>
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+QT_BEGIN_NAMESPACE
+
+void QGraphicsTransformPrivate::setItem(QGraphicsItem *i)
+{
+ if (item == i)
+ return;
+
+ if (item) {
+ Q_Q(QGraphicsTransform);
+ QGraphicsItemPrivate *d_ptr = item->d_ptr.data();
+
+ item->prepareGeometryChange();
+ Q_ASSERT(d_ptr->transformData);
+ d_ptr->transformData->graphicsTransforms.removeAll(q);
+ d_ptr->dirtySceneTransform = 1;
+ item = 0;
+ }
+
+ item = i;
+}
+
+void QGraphicsTransformPrivate::updateItem(QGraphicsItem *item)
+{
+ item->prepareGeometryChange();
+ item->d_ptr->dirtySceneTransform = 1;
+}
+
+/*!
+ Constructs a new QGraphicsTransform with the given \a parent.
+*/
+QGraphicsTransform::QGraphicsTransform(QObject *parent)
+ : QObject(*new QGraphicsTransformPrivate, parent)
+{
+}
+
+/*!
+ Destroys the graphics transform.
+*/
+QGraphicsTransform::~QGraphicsTransform()
+{
+ Q_D(QGraphicsTransform);
+ d->setItem(0);
+}
+
+/*!
+ \internal
+*/
+QGraphicsTransform::QGraphicsTransform(QGraphicsTransformPrivate &p, QObject *parent)
+ : QObject(p, parent)
+{
+}
+
+/*!
+ Applies this transformation to an identity transform, and returns the
+ resulting transform.
+
+ This is equivalent to passing an identity transform to applyTo().
+
+ \sa applyTo()
+*/
+QTransform QGraphicsTransform::transform() const
+{
+ QTransform t;
+ applyTo(&t);
+ return t;
+}
+
+/*!
+ \fn void QGraphicsTransform::applyTo(QTransform *transform) const
+
+ This pure virtual method has to be reimplemented in derived classes.
+
+ It applies this transformation to \a transform.
+
+ \sa QGraphicsItem::transform()
+*/
+
+/*!
+ Notifies that this transform operation has changed its parameters in such a
+ way that applyTo() will return a different result than before.
+
+ When implementing you own custom graphics transform, you must call this
+ function every time you change a parameter, to let QGraphicsItem know that
+ its transformation needs to be updated.
+
+ \sa applyTo()
+*/
+void QGraphicsTransform::update()
+{
+ Q_D(QGraphicsTransform);
+ if (d->item)
+ d->updateItem(d->item);
+}
+
+/*!
+ \class QGraphicsScale
+ \brief The QGraphicsScale class provides a scale transformation.
+ \since 4.6
+
+ QGraphicsScene provides certain parameters to help control how the scale
+ should be applied.
+
+ The origin is the point that the item is scaled from (i.e., it stays fixed
+ relative to the parent as the rest of the item grows). By default the
+ origin is QPointF(0, 0).
+
+ The two parameters xScale and yScale describe the scale factors to apply in
+ horizontal and vertical direction. They can take on any value, including 0
+ (to collapse the item to a point) or negativate value. A negative xScale
+ value will mirror the item horizontally. A negative yScale value will flip
+ the item vertically.
+
+ \sa QGraphicsTransform, QGraphicsItem::setScale(), QTransform::scale()
+*/
+
+class QGraphicsScalePrivate : public QGraphicsTransformPrivate
+{
+public:
+ QGraphicsScalePrivate()
+ : xScale(1), yScale(1) {}
+ QPointF origin;
+ qreal xScale;
+ qreal yScale;
+};
+
+/*!
+ Constructs an empty QGraphicsScale object with the given \a parent.
+*/
+QGraphicsScale::QGraphicsScale(QObject *parent)
+ : QGraphicsTransform(*new QGraphicsScalePrivate, parent)
+{
+}
+
+/*!
+ Destroys the graphics scale.
+*/
+QGraphicsScale::~QGraphicsScale()
+{
+}
+
+/*!
+ \property QGraphicsScale::origin
+ \brief The QGraphicsScene class provides the origin of the scale.
+
+ All scaling will be done relative to this point (i.e., this point
+ will stay fixed, relative to the parent, when the item is scaled).
+
+ \sa xScale, yScale
+*/
+QPointF QGraphicsScale::origin() const
+{
+ Q_D(const QGraphicsScale);
+ return d->origin;
+}
+void QGraphicsScale::setOrigin(const QPointF &point)
+{
+ Q_D(QGraphicsScale);
+ d->origin = point;
+ update();
+ emit originChanged();
+}
+
+/*!
+ \property QGraphicsScale::xScale
+ \brief the horizontal scale factor.
+
+ The scale factor can be any real number; the default value is 1.0. If you
+ set the factor to 0.0, the item will be collapsed to a single point. If you
+ provide a negative value, the item will be mirrored horizontally around its
+ origin.
+
+ \sa yScale, origin
+*/
+qreal QGraphicsScale::xScale() const
+{
+ Q_D(const QGraphicsScale);
+ return d->xScale;
+}
+void QGraphicsScale::setXScale(qreal scale)
+{
+ Q_D(QGraphicsScale);
+ if (d->xScale == scale)
+ return;
+ d->xScale = scale;
+ update();
+ emit scaleChanged();
+}
+
+/*!
+ \property QGraphicsScale::yScale
+ \brief the vertical scale factor.
+
+ The scale factor can be any real number; the default value is 1.0. If you
+ set the factor to 0.0, the item will be collapsed to a single point. If you
+ provide a negative value, the item will be flipped vertically around its
+ origin.
+
+ \sa xScale, origin
+*/
+qreal QGraphicsScale::yScale() const
+{
+ Q_D(const QGraphicsScale);
+ return d->yScale;
+}
+void QGraphicsScale::setYScale(qreal scale)
+{
+ Q_D(QGraphicsScale);
+ if (d->yScale == scale)
+ return;
+ d->yScale = scale;
+ update();
+ emit scaleChanged();
+}
+
+/*!
+ \reimp
+*/
+void QGraphicsScale::applyTo(QTransform *transform) const
+{
+ Q_D(const QGraphicsScale);
+ transform->translate(d->origin.x(), d->origin.y());
+ transform->scale(d->xScale, d->yScale);
+ transform->translate(-d->origin.x(), -d->origin.y());
+}
+
+/*!
+ \fn QGraphicsScale::originChanged()
+
+ QGraphicsScale emits this signal when its origin changes.
+
+ \sa QGraphicsScale::origin
+*/
+
+/*!
+ \fn QGraphicsScale::scaleChanged()
+
+ This signal is emitted whenever the xScale or yScale of the object
+ changes.
+
+ \sa QGraphicsScale::xScale, QGraphicsScale::yScale
+*/
+
+/*!
+ \class QGraphicsRotation
+ \brief The QGraphicsRotation class provides a rotation transformation.
+ \since 4.6
+
+ QGraphicsRotation provides certain parameters to help control how the
+ rotation should be applied.
+
+ The origin is the point that the item is rotated around (i.e., it stays
+ fixed relative to the parent as the rest of the item is rotated). By
+ default the origin is QPointF(0, 0).
+
+ The angle property provides the number of degrees to rotate the item
+ clockwise around the origin. This value also be negative, indicating a
+ counter-clockwise rotation. For animation purposes it may also be useful to
+ provide rotation angles exceeding (-360, 360) degrees, for instance to
+ animate how an item rotates several times.
+
+ \sa QGraphicsTransform, QGraphicsItem::setRotation(), QTransform::rotate()
+*/
+
+class QGraphicsRotationPrivate : public QGraphicsTransformPrivate
+{
+public:
+ QGraphicsRotationPrivate()
+ : angle(0) {}
+ QPointF origin;
+ qreal originY;
+ qreal angle;
+};
+
+/*!
+ Constructs a new QGraphicsRotation with the given \a parent.
+*/
+QGraphicsRotation::QGraphicsRotation(QObject *parent)
+ : QGraphicsTransform(*new QGraphicsRotationPrivate, parent)
+{
+}
+
+/*!
+ \internal
+*/
+QGraphicsRotation::QGraphicsRotation(QGraphicsRotationPrivate &p, QObject *parent)
+ : QGraphicsTransform(p, parent)
+{
+}
+
+/*!
+ Destroys the graphics rotation.
+*/
+QGraphicsRotation::~QGraphicsRotation()
+{
+}
+
+/*!
+ \property QGraphicsRotation::origin
+ \brief the origin of the rotation.
+
+ All rotations will be done relative to this point (i.e., this point
+ will stay fixed, relative to the parent, when the item is rotated).
+
+ \sa angle
+*/
+QPointF QGraphicsRotation::origin() const
+{
+ Q_D(const QGraphicsRotation);
+ return d->origin;
+}
+void QGraphicsRotation::setOrigin(const QPointF &point)
+{
+ Q_D(QGraphicsRotation);
+ d->origin = point;
+ update();
+ emit originChanged();
+}
+
+/*!
+ \property QGraphicsRotation::angle
+ \brief the angle for clockwise rotation, in degrees.
+
+ The angle can be any real number; the default value is 0.0. A value of 180
+ will rotate 180 degrees, clockwise. If you provide a negative number, the
+ item will be rotated counter-clockwise. Normally the rotation angle will be
+ in the range (-360, 360), but you can also provide numbers outside of this
+ range (e.g., a angle of 370 degrees gives the same result as 10 degrees).
+
+ \sa origin
+*/
+qreal QGraphicsRotation::angle() const
+{
+ Q_D(const QGraphicsRotation);
+ return d->angle;
+}
+void QGraphicsRotation::setAngle(qreal angle)
+{
+ Q_D(QGraphicsRotation);
+ if (d->angle == angle)
+ return;
+ d->angle = angle;
+ update();
+ emit angleChanged();
+}
+
+/*!
+ \reimp
+*/
+void QGraphicsRotation::applyTo(QTransform *t) const
+{
+ Q_D(const QGraphicsRotation);
+ if (d->angle) {
+ t->translate(d->origin.x(), d->origin.y());
+ t->rotate(d->angle);
+ t->translate(-d->origin.x(), -d->origin.y());
+ }
+}
+
+/*!
+ \fn QGraphicsRotation::originChanged()
+
+ This signal is emitted whenever the origin has changed.
+
+ \sa QGraphicsRotation::origin
+*/
+
+/*!
+ \fn void QGraphicsRotation::angleChanged()
+
+ This signal is emitted whenever the angle has changed.
+
+ \sa QGraphicsRotation::angle
+*/
+
+/*!
+ \class QGraphicsRotation3D
+ \brief The QGraphicsRotation3D class provides rotation in 3 dimensions.
+ \since 4.6
+
+ QGraphicsRotation3D extends QGraphicsRotation with the ability to rotate
+ around a given axis.
+
+ You can provide the desired axis by assigning a QVector3D to the axis
+ property. The angle property, which is provided by QGraphicsRotation, now
+ describes the number of degrees to rotate around this axis.
+
+ By default the axis is (0, 0, 1), giving QGraphicsRotation3D the same
+ default behavior as QGraphicsRotation (i.e., rotation around the Z axis).
+
+ \sa QGraphicsTransform, QGraphicsItem::setRotation(), QTransform::rotate()
+*/
+
+class QGraphicsRotation3DPrivate : public QGraphicsRotationPrivate
+{
+public:
+ QGraphicsRotation3DPrivate() {}
+
+ QVector3D axis;
+};
+
+/*!
+ Constructs a new QGraphicsRotation3D with the given \a parent.
+*/
+QGraphicsRotation3D::QGraphicsRotation3D(QObject *parent)
+ : QGraphicsRotation(*new QGraphicsRotation3DPrivate, parent)
+{
+}
+
+/*!
+ Destroys the 3D graphics rotation.
+*/
+QGraphicsRotation3D::~QGraphicsRotation3D()
+{
+}
+
+/*!
+ \property QGraphicsRotation3D::axis
+ \brief a rotation axis, specified by a vector in 3D space.
+
+ This can be any axis in 3D space. By default the axis is (0, 0, 1),
+ which is aligned with the Z axis and provides the same behavior
+ for the rotation angle as QGraphicsRotation. If you provide another
+ axis, QGraphicsRotation3D will provide a transformation that rotates
+ around this axis. For example, if you would like to rotate an item
+ around its X axis, you could pass (1, 0, 0) as the axis.
+
+ \sa QTransform, QGraphicsRotation::angle
+*/
+QVector3D QGraphicsRotation3D::axis()
+{
+ Q_D(QGraphicsRotation3D);
+ return d->axis;
+}
+void QGraphicsRotation3D::setAxis(const QVector3D &axis)
+{
+ Q_D(QGraphicsRotation3D);
+ d->axis = axis;
+ update();
+}
+
+static const qreal inv_dist_to_plane = 1. / 1024.;
+
+/*!
+ \reimp
+*/
+void QGraphicsRotation3D::applyTo(QTransform *t) const
+{
+ Q_D(const QGraphicsRotation3D);
+
+ if (d->angle == 0. ||
+ (d->axis.z() == 0. && d->axis.y() == 0 && d->axis.x() == 0))
+ return;
+
+ qreal rad = d->angle * 2. * M_PI / 360.;
+ qreal c = ::cos(rad);
+ qreal s = ::sin(rad);
+
+ qreal x = d->axis.x();
+ qreal y = d->axis.y();
+ qreal z = d->axis.z();
+
+ qreal len = x * x + y * y + z * z;
+ if (len != 1.) {
+ len = 1./::sqrt(len);
+ x *= len;
+ y *= len;
+ z *= len;
+ }
+
+ t->translate(d->origin.x(), d->origin.y());
+ *t = QTransform(x*x*(1-c)+c, x*y*(1-c)-z*s, x*z*(1-c)+y*s*inv_dist_to_plane,
+ y*x*(1-c)+z*s, y*y*(1-c)+c, y*z*(1-c)-x*s*inv_dist_to_plane,
+ 0, 0, 1) * *t;
+ t->translate(-d->origin.x(), -d->origin.y());
+}
+
+/*!
+ \fn void QGraphicsRotation3D::axisChanged()
+
+ This signal is emitted whenever the axis of the object changes.
+*/
+
+#include "moc_qgraphicstransform.cpp"
+
+QT_END_NAMESPACE
diff --git a/src/gui/graphicsview/qgraphicstransform.h b/src/gui/graphicsview/qgraphicstransform.h
new file mode 100644
index 0000000..d7c07d0
--- /dev/null
+++ b/src/gui/graphicsview/qgraphicstransform.h
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (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 http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGRAPHICSTRANSFORM_H
+#define QGRAPHICSTRANSFORM_H
+
+#include <QtCore/QObject>
+#include <QtGui/QTransform>
+#include <QtGui/QVector3D>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QGraphicsItem;
+class QGraphicsTransformPrivate;
+
+class Q_GUI_EXPORT QGraphicsTransform : public QObject
+{
+ Q_OBJECT
+public:
+ QGraphicsTransform(QObject *parent = 0);
+ ~QGraphicsTransform();
+
+ QTransform transform() const;
+ virtual void applyTo(QTransform *transform) const = 0;
+
+protected Q_SLOTS:
+ void update();
+
+protected:
+ QGraphicsTransform(QGraphicsTransformPrivate &p, QObject *parent);
+
+private:
+ friend class QGraphicsItem;
+ friend class QGraphicsItemPrivate;
+ Q_DECLARE_PRIVATE(QGraphicsTransform)
+};
+
+class QGraphicsScalePrivate;
+
+class Q_GUI_EXPORT QGraphicsScale : public QGraphicsTransform
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QPointF origin READ origin WRITE setOrigin NOTIFY originChanged)
+ Q_PROPERTY(qreal xScale READ xScale WRITE setXScale NOTIFY scaleChanged)
+ Q_PROPERTY(qreal yScale READ yScale WRITE setYScale NOTIFY scaleChanged)
+public:
+ QGraphicsScale(QObject *parent = 0);
+ ~QGraphicsScale();
+
+ QPointF origin() const;
+ void setOrigin(const QPointF &point);
+
+ qreal xScale() const;
+ void setXScale(qreal);
+
+ qreal yScale() const;
+ void setYScale(qreal);
+
+ void applyTo(QTransform *transform) const;
+
+Q_SIGNALS:
+ void originChanged();
+ void scaleChanged();
+
+private:
+ Q_DECLARE_PRIVATE(QGraphicsScale)
+};
+
+class QGraphicsRotationPrivate;
+
+class Q_GUI_EXPORT QGraphicsRotation : public QGraphicsTransform
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QPointF origin READ origin WRITE setOrigin NOTIFY originChanged)
+ Q_PROPERTY(qreal angle READ angle WRITE setAngle NOTIFY angleChanged)
+public:
+ QGraphicsRotation(QObject *parent = 0);
+ ~QGraphicsRotation();
+
+ QPointF origin() const;
+ void setOrigin(const QPointF &point);
+
+ qreal angle() const;
+ void setAngle(qreal);
+
+ void applyTo(QTransform *transform) const;
+
+Q_SIGNALS:
+ void originChanged();
+ void angleChanged();
+
+protected:
+ QGraphicsRotation(QGraphicsRotationPrivate &p, QObject *parent);
+private:
+ Q_DECLARE_PRIVATE(QGraphicsRotation)
+};
+
+class QGraphicsRotation3DPrivate;
+
+class Q_GUI_EXPORT QGraphicsRotation3D : public QGraphicsRotation
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QVector3D axis READ axis WRITE setAxis NOTIFY axisChanged)
+public:
+ QGraphicsRotation3D(QObject *parent = 0);
+ ~QGraphicsRotation3D();
+
+ QVector3D axis();
+ void setAxis(const QVector3D &axis);
+
+ void applyTo(QTransform *transform) const;
+
+Q_SIGNALS:
+ void axisChanged();
+
+private:
+ Q_DECLARE_PRIVATE(QGraphicsRotation3D)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFXTRANSFORM_H
diff --git a/src/gui/graphicsview/qgraphicstransform_p.h b/src/gui/graphicsview/qgraphicstransform_p.h
new file mode 100644
index 0000000..2d36eda
--- /dev/null
+++ b/src/gui/graphicsview/qgraphicstransform_p.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (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 http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGRAPHICSTRANSFORM_P_H
+#define QGRAPHICSTRANSFORM_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 "private/qobject_p.h"
+
+class QGraphicsItem;
+
+class QGraphicsTransformPrivate : public QObjectPrivate {
+public:
+ Q_DECLARE_PUBLIC(QGraphicsTransform)
+
+ QGraphicsTransformPrivate()
+ : QObjectPrivate(), item(0) {}
+
+ QGraphicsItem *item;
+
+ void setItem(QGraphicsItem *item);
+ static void updateItem(QGraphicsItem *item);
+};
+
+#endif // QGRAPHICSTRANSFORM_P_H
diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp
index 58bbdda..e1f9f62 100644
--- a/src/gui/graphicsview/qgraphicsview.cpp
+++ b/src/gui/graphicsview/qgraphicsview.cpp
@@ -97,8 +97,8 @@ static const int QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS = 503; // largest prime <
setViewport(new QGLWidget). QGraphicsView takes ownership of the viewport
widget.
- QGraphicsView supports affine transformations, using QMatrix. You can
- either pass a matrix to setMatrix(), or you can call one of the
+ QGraphicsView supports affine transformations, using QTransform. You can
+ either pass a matrix to setTransform(), or you can call one of the
convenience functions rotate(), scale(), translate() or shear(). The most
two common transformations are scaling, which is used to implement
zooming, and rotation. QGraphicsView keeps the center of the view fixed
@@ -280,6 +280,7 @@ static const int QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS = 503; // largest prime <
#include <QtGui/qpainter.h>
#include <QtGui/qscrollbar.h>
#include <QtGui/qstyleoption.h>
+#include <QtGui/qinputcontext.h>
#ifdef Q_WS_X11
#include <private/qt_x11_p.h>
#endif
@@ -812,31 +813,17 @@ 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
+*/
void QGraphicsViewPrivate::processPendingUpdates()
{
if (!scene)
return;
- if (fullUpdatePending) { // We have already called viewport->update()
- dirtyBoundingRect = QRect();
- dirtyRegion = QRegion();
- return;
- }
-
- if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) {
+ if (fullUpdatePending) {
+ viewport->update();
+ } else if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) {
if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)
viewport->update(dirtyBoundingRect.adjusted(-1, -1, 1, 1));
else
@@ -849,13 +836,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) {
@@ -864,8 +867,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();
}
@@ -892,7 +895,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;
}
@@ -902,8 +905,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();
}
@@ -954,47 +957,32 @@ extern QPainterPath qt_regionToPath(const QRegion &region);
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<QGraphicsItem *> QGraphicsViewPrivate::findItems(const QRegion &exposedRegion, bool *allItems) const
+QList<QGraphicsItem *> 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)) {
+ if (exposedRegionSceneBounds.contains(scene->sceneRect())) {
Q_ASSERT(allItems);
*allItems = true;
- // All items are guaranteed within the exposed region, don't bother using the index.
- QList<QGraphicsItem *> itemList(scene->items());
- 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;
- }
-
- // Sort the items.
- QGraphicsScenePrivate::sortItems(&itemList, Qt::DescendingOrder, scene->d_func()->sortCacheEnabled);
- 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()->items_helper(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
@@ -1004,16 +992,25 @@ QList<QGraphicsItem *> 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()->items_helper(exposedScenePath,
- Qt::IntersectsItemBoundingRect,
- Qt::DescendingOrder);
- }
+ const QPainterPath exposedScenePath(q->mapToScene(qt_regionToPath(adjustedRegion)));
+ return scene->items(exposedScenePath, Qt::IntersectsItemBoundingRect,
+ Qt::DescendingOrder, viewTransform);
+}
- // NB! Path must be in viewport coordinates.
- return itemsInArea(exposedPath, Qt::IntersectsItemBoundingRect, Qt::DescendingOrder);
+/*!
+ \internal
+
+ Enables input methods for the view if and only if the current focus item of
+ the scene accepts input methods. Call function whenever that condition has
+ potentially changed.
+*/
+void QGraphicsViewPrivate::updateInputMethodSensitivity()
+{
+ Q_Q(QGraphicsView);
+ q->setAttribute(
+ Qt::WA_InputMethodEnabled,
+ scene && scene->focusItem()
+ && scene->focusItem()->flags() & QGraphicsItem::ItemAcceptsInputMethod);
}
/*!
@@ -1553,6 +1550,8 @@ void QGraphicsView::setScene(QGraphicsScene *scene)
} else {
d->recalculateContentSize();
}
+
+ d->updateInputMethodSensitivity();
}
/*!
@@ -1599,7 +1598,7 @@ void QGraphicsView::setSceneRect(const QRectF &rect)
Returns the current transformation matrix for the view. If no current
transformation is set, the identity matrix is returned.
- \sa setMatrix(), rotate(), scale(), shear(), translate()
+ \sa setMatrix(), transform(), rotate(), scale(), shear(), translate()
*/
QMatrix QGraphicsView::matrix() const
{
@@ -1631,7 +1630,7 @@ QMatrix QGraphicsView::matrix() const
a view coordinate to a floating point scene coordinate, or mapFromScene()
to map from floating point scene coordinates to view coordinates.
- \sa matrix(), rotate(), scale(), shear(), translate()
+ \sa matrix(), setTransform(), rotate(), scale(), shear(), translate()
*/
void QGraphicsView::setMatrix(const QMatrix &matrix, bool combine)
{
@@ -1640,6 +1639,8 @@ void QGraphicsView::setMatrix(const QMatrix &matrix, bool combine)
/*!
Resets the view transformation matrix to the identity matrix.
+
+ \sa resetTransform()
*/
void QGraphicsView::resetMatrix()
{
@@ -1649,7 +1650,7 @@ void QGraphicsView::resetMatrix()
/*!
Rotates the current view transformation \a angle degrees clockwise.
- \sa setMatrix(), matrix(), scale(), shear(), translate()
+ \sa setTransform(), transform(), scale(), shear(), translate()
*/
void QGraphicsView::rotate(qreal angle)
{
@@ -1662,7 +1663,7 @@ void QGraphicsView::rotate(qreal angle)
/*!
Scales the current view transformation by (\a sx, \a sy).
- \sa setMatrix(), matrix(), rotate(), shear(), translate()
+ \sa setTransform(), transform(), rotate(), shear(), translate()
*/
void QGraphicsView::scale(qreal sx, qreal sy)
{
@@ -1675,7 +1676,7 @@ void QGraphicsView::scale(qreal sx, qreal sy)
/*!
Shears the current view transformation by (\a sh, \a sv).
- \sa setMatrix(), matrix(), rotate(), scale(), translate()
+ \sa setTransform(), transform(), rotate(), scale(), translate()
*/
void QGraphicsView::shear(qreal sh, qreal sv)
{
@@ -1688,7 +1689,7 @@ void QGraphicsView::shear(qreal sh, qreal sv)
/*!
Translates the current view transformation by (\a dx, \a dy).
- \sa setMatrix(), matrix(), rotate(), shear()
+ \sa setTransform(), transform(), rotate(), shear()
*/
void QGraphicsView::translate(qreal dx, qreal dy)
{
@@ -1846,7 +1847,7 @@ void QGraphicsView::ensureVisible(const QGraphicsItem *item, int xmargin, int ym
If \a rect is empty, or if the viewport is too small, this
function will do nothing.
- \sa setMatrix(), ensureVisible(), centerOn()
+ \sa setTransform(), ensureVisible(), centerOn()
*/
void QGraphicsView::fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRatioMode)
{
@@ -1911,7 +1912,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);
+ }
}
/*!
@@ -1937,6 +1943,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;
@@ -2033,69 +2041,6 @@ QList<QGraphicsItem *> 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<QGraphicsItem *> 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<QGraphicsItem *> allCandidates = scene->d_func()->estimateItemsInRect(adjustedRect);
-
- // Then find the minimal list of items that are inside \a path, and
- // convert it to a set.
- QList<QGraphicsItem *> regularCandidates = scene->items(q->mapToScene(path), mode);
- QSet<QGraphicsItem *> candSet = QSet<QGraphicsItem *>::fromList(regularCandidates);
-
- QTransform viewMatrix = q->viewportTransform();
-
- QList<QGraphicsItem *> result;
-
- // 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<QGraphicsItem *>::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;
- }
-
- // ### Insertion sort would be faster.
- if (order != Qt::SortOrder(-1))
- QGraphicsScenePrivate::sortItems(&result, order, scene->d_func()->sortCacheEnabled);
- 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
@@ -2114,17 +2059,22 @@ QList<QGraphicsItem *> QGraphicsView::items(const QPoint &pos) const
Q_D(const QGraphicsView);
if (!d->scene)
return QList<QGraphicsItem *>();
- 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());
}
/*!
@@ -2151,12 +2101,7 @@ QList<QGraphicsItem *> QGraphicsView::items(const QRect &rect, Qt::ItemSelection
Q_D(const QGraphicsView);
if (!d->scene)
return QList<QGraphicsItem *>();
- 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());
}
/*!
@@ -2184,13 +2129,7 @@ QList<QGraphicsItem *> QGraphicsView::items(const QPolygon &polygon, Qt::ItemSel
Q_D(const QGraphicsView);
if (!d->scene)
return QList<QGraphicsItem *>();
- 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());
}
/*!
@@ -2210,9 +2149,7 @@ QList<QGraphicsItem *> QGraphicsView::items(const QPainterPath &path, Qt::ItemSe
Q_D(const QGraphicsView);
if (!d->scene)
return QList<QGraphicsItem *>();
- 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());
}
/*!
@@ -2673,9 +2610,6 @@ bool QGraphicsView::event(QEvent *event)
}
}
break;
- case QEvent::Gesture:
- viewportEvent(event);
- return true;
default:
break;
}
@@ -2757,17 +2691,6 @@ bool QGraphicsView::viewportEvent(QEvent *event)
d->scene->d_func()->updateAll = false;
}
break;
- case QEvent::Gesture: {
- QGraphicsSceneGestureEvent gestureEvent;
- gestureEvent.setWidget(this);
- QGestureEvent *ev = static_cast<QGestureEvent*>(event);
- gestureEvent.setGestures(ev->gestures());
- gestureEvent.setCancelledGestures(ev->cancelledGestures());
- QApplication::sendEvent(d->scene, &gestureEvent);
- event->setAccepted(gestureEvent.isAccepted());
- return true;
- }
- break;
case QEvent::TouchBegin:
case QEvent::TouchUpdate:
case QEvent::TouchEnd:
@@ -2958,6 +2881,7 @@ void QGraphicsView::dragMoveEvent(QDragMoveEvent *event)
void QGraphicsView::focusInEvent(QFocusEvent *event)
{
Q_D(QGraphicsView);
+ d->updateInputMethodSensitivity();
QAbstractScrollArea::focusInEvent(event);
if (d->scene)
QApplication::sendEvent(d->scene, event);
@@ -3178,7 +3102,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
@@ -3221,7 +3146,7 @@ void QGraphicsView::mouseReleaseEvent(QMouseEvent *event)
}
} else
#endif
- if (d->dragMode == QGraphicsView::ScrollHandDrag) {
+ if (d->dragMode == QGraphicsView::ScrollHandDrag && event->button() == Qt::LeftButton) {
#ifndef QT_NO_CURSOR
// Restore the open hand cursor. ### There might be items
// under the mouse that have a valid cursor at this time, so
@@ -3391,8 +3316,7 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
} else {
// Find all exposed items
bool allItems = false;
- QList<QGraphicsItem *> itemList = d->findItems(d->exposedRegion, &allItems);
-
+ QList<QGraphicsItem *> itemList = d->findItems(d->exposedRegion, &allItems, viewTransform);
if (!itemList.isEmpty()) {
// Generate the style options.
const int numItems = itemList.size();
@@ -3645,6 +3569,8 @@ QTransform QGraphicsView::viewportTransform() const
}
/*!
+ \since 4.6
+
Returns true if the view is transformed (i.e., a non-identity transform
has been assigned, or the scrollbars are adjusted).
diff --git a/src/gui/graphicsview/qgraphicsview.h b/src/gui/graphicsview/qgraphicsview.h
index 425f174..1285e45 100644
--- a/src/gui/graphicsview/qgraphicsview.h
+++ b/src/gui/graphicsview/qgraphicsview.h
@@ -269,7 +269,7 @@ protected:
const QStyleOptionGraphicsItem options[]);
private:
- Q_DECLARE_SCOPED_PRIVATE(QGraphicsView)
+ Q_DECLARE_PRIVATE(QGraphicsView)
Q_DISABLE_COPY(QGraphicsView)
#ifndef QT_NO_CURSOR
Q_PRIVATE_SLOT(d_func(), void _q_setViewportCursor(const QCursor &))
diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h
index 8c62f73..62a2b84 100644
--- a/src/gui/graphicsview/qgraphicsview_p.h
+++ b/src/gui/graphicsview/qgraphicsview_p.h
@@ -58,12 +58,14 @@
#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW
#include <QtGui/qevent.h>
+#include <QtCore/qcoreapplication.h>
#include "qgraphicssceneevent.h"
+#include <QtGui/qstyleoption.h>
#include <private/qabstractscrollarea_p.h>
QT_BEGIN_NAMESPACE
-class QGraphicsViewPrivate : public QAbstractScrollAreaPrivate
+class Q_AUTOTEST_EXPORT QGraphicsViewPrivate : public QAbstractScrollAreaPrivate
{
Q_DECLARE_PUBLIC(QGraphicsView)
public:
@@ -84,10 +86,6 @@ public:
qint64 horizontalScroll() const;
qint64 verticalScroll() const;
- QList<QGraphicsItem *> itemsInArea(const QPainterPath &path,
- Qt::ItemSelectionMode mode = Qt::IntersectsItemShape,
- Qt::SortOrder = Qt::AscendingOrder) const;
-
QPointF mousePressItemPoint;
QPointF mousePressScenePoint;
QPoint mousePressViewPoint;
@@ -171,16 +169,27 @@ public:
dirtyBoundingRect = QRect();
dirtyRegion = QRegion();
}
+
+ inline void dispatchPendingUpdateRequests()
+ {
+ if (qt_widget_private(viewport)->paintOnScreen())
+ QCoreApplication::sendPostedEvents(viewport, QEvent::UpdateRequest);
+ else
+ QCoreApplication::sendPostedEvents(viewport->window(), QEvent::UpdateRequest);
+ }
+
bool updateRect(const QRect &rect);
bool updateRegion(const QRegion &region);
bool updateSceneSlotReimplementedChecked;
QRegion exposedRegion;
- QList<QGraphicsItem *> findItems(const QRegion &exposedRegion, bool *allItems) const;
+ QList<QGraphicsItem *> findItems(const QRegion &exposedRegion, bool *allItems,
+ const QTransform &viewTransform) const;
QPointF mapToScene(const QPointF &point) const;
QRectF mapToScene(const QRectF &rect) const;
static void translateTouchEvent(QGraphicsViewPrivate *d, QTouchEvent *touchEvent);
+ void updateInputMethodSensitivity();
};
QT_END_NAMESPACE
diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp
index b042be4..bf0acc9 100644
--- a/src/gui/graphicsview/qgraphicswidget.cpp
+++ b/src/gui/graphicsview/qgraphicswidget.cpp
@@ -971,15 +971,18 @@ void QGraphicsWidget::updateGeometry()
deliver events related to state changes in the item. Because of this, it is
very important that subclasses call the base implementation.
- For example, QGraphicsWidget uses ItemVisibleChange to deliver \l Show and
- \l Hide events, ItemPositionHasChanged to deliver \l Move events, and
- ItemParentChange both to deliver \l ParentChange events, and for managing
- the focus chain.
+ \a change specifies the type of change, and \a value is the new value.
+
+ For example, QGraphicsWidget uses ItemVisibleChange to deliver
+ \l{QEvent::Show} {Show} and \l{QEvent::Hide}{Hide} events,
+ ItemPositionHasChanged to deliver \l{QEvent::Move}{Move} events,
+ and ItemParentChange both to deliver \l{QEvent::ParentChange}
+ {ParentChange} events, and for managing the focus chain.
QGraphicsWidget enables the ItemSendsGeometryChanges flag by default in
order to track position changes.
- \sa propertyChange()
+ \sa QGraphicsItem::itemChange()
*/
QVariant QGraphicsWidget::itemChange(GraphicsItemChange change, const QVariant &value)
{
@@ -1211,7 +1214,8 @@ Qt::WindowFrameSection QGraphicsWidget::windowFrameSectionAt(const QPointF &pos)
/*!
\reimp
- QGraphicsWidget handles the following events:
+ Handles the \a event. QGraphicsWidget handles the following
+ events:
\table \o Event \o Usage
\row \o Polish
@@ -1712,49 +1716,18 @@ void QGraphicsWidget::setFocusPolicy(Qt::FocusPolicy policy)
/*!
If this widget, a child or descendant of this widget currently has input
focus, this function will return a pointer to that widget. If
- no descendant has input focus, 0 is returned.
+ no descendant widget has input focus, 0 is returned.
- \sa QWidget::focusWidget()
+ \sa QGraphicsItem::focusItem(), QWidget::focusWidget()
*/
QGraphicsWidget *QGraphicsWidget::focusWidget() const
{
Q_D(const QGraphicsWidget);
- return d->focusChild;
+ if (d->subFocusItem && d->subFocusItem->d_ptr->isWidget)
+ return static_cast<QGraphicsWidget *>(d->subFocusItem);
+ return 0;
}
-/*! \property QGraphicsWidget::horizontalShear
- \brief This property holds the horizontal shear value for the item.
- */
-
-/*! \property QGraphicsWidget::transformOrigin
- \brief This property holds the origin point used for transformations
- in item coordinates.
- */
-
-/*! \property QGraphicsWidget::verticalShear
- \brief This property holds the vertical shear value for the item.
- */
-
-/*! \property QGraphicsWidget::xRotation
- \brief This property holds the value for rotation around the x axis.
- */
-
-/*! \property QGraphicsWidget::xScale
- \brief This property holds the scale factor for the x axis.
- */
-
-/*! \property QGraphicsWidget::yRotation
- \brief This property holds the value for rotation around the y axis.
- */
-
-/*! \property QGraphicsWidget::yScale
- \brief This property holds the scale factor for the y axis.
- */
-
-/*! \property QGraphicsWidget::zRotation
- \brief This property holds the value for rotation around the z axis.
- */
-
#ifndef QT_NO_SHORTCUT
/*!
\since 4.5
@@ -2280,6 +2253,7 @@ bool QGraphicsWidget::close()
#ifdef Q_NO_USING_KEYWORD
/*!
\fn const QObjectList &QGraphicsWidget::children() const
+ \internal
This function returns the same value as QObject::children(). It's
provided to differentiate between the obsolete member
diff --git a/src/gui/graphicsview/qgraphicswidget.h b/src/gui/graphicsview/qgraphicswidget.h
index 9047310..cb5490a 100644
--- a/src/gui/graphicsview/qgraphicswidget.h
+++ b/src/gui/graphicsview/qgraphicswidget.h
@@ -77,14 +77,6 @@ class Q_GUI_EXPORT QGraphicsWidget : public QGraphicsObject, public QGraphicsLay
Q_PROPERTY(Qt::WindowFlags windowFlags READ windowFlags WRITE setWindowFlags)
Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle)
Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry)
- Q_PROPERTY(QPointF transformOrigin READ transformOrigin WRITE setTransformOrigin)
- Q_PROPERTY(qreal xRotation READ xRotation WRITE setXRotation)
- Q_PROPERTY(qreal yRotation READ yRotation WRITE setYRotation)
- Q_PROPERTY(qreal zRotation READ zRotation WRITE setZRotation)
- Q_PROPERTY(qreal xScale READ xScale WRITE setXScale)
- Q_PROPERTY(qreal yScale READ yScale WRITE setYScale)
- Q_PROPERTY(qreal horizontalShear READ horizontalShear WRITE setHorizontalShear)
- Q_PROPERTY(qreal verticalShear READ verticalShear WRITE setVerticalShear)
public:
QGraphicsWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0);
~QGraphicsWidget();
diff --git a/src/gui/graphicsview/qgraphicswidget_p.cpp b/src/gui/graphicsview/qgraphicswidget_p.cpp
index c9212f7..8eac063 100644
--- a/src/gui/graphicsview/qgraphicswidget_p.cpp
+++ b/src/gui/graphicsview/qgraphicswidget_p.cpp
@@ -626,34 +626,6 @@ bool QGraphicsWidgetPrivate::hasDecoration() const
return (windowFlags & Qt::Window) && (windowFlags & Qt::WindowTitleHint);
}
-/*!
- \internal
-*/
-void QGraphicsWidgetPrivate::setFocusWidget()
-{
- // Update focus child chain.
- QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(q_ptr);
- QGraphicsWidget *parent = widget;
- bool hidden = !visible;
- do {
- parent->d_func()->focusChild = widget;
- } while (!parent->isWindow() && (parent = parent->parentWidget()) && (!hidden || !parent->d_func()->visible));
-}
-
-/*!
- \internal
-*/
-void QGraphicsWidgetPrivate::clearFocusWidget()
-{
- // Reset focus child chain.
- QGraphicsWidget *parent = static_cast<QGraphicsWidget *>(q_ptr);
- do {
- if (parent->d_func()->focusChild != q_ptr)
- break;
- parent->d_func()->focusChild = 0;
- } while (!parent->isWindow() && (parent = parent->parentWidget()));
-}
-
/**
* is called after a reparent has taken place to fix up the focus chain(s)
*/
@@ -670,12 +642,6 @@ void QGraphicsWidgetPrivate::fixFocusChainBeforeReparenting(QGraphicsWidget *new
QGraphicsWidget *firstOld = 0;
bool wasPreviousNew = true;
-
- if (focusChild) {
- // Ensure that the current focus child doesn't leave pointers around
- // before reparenting.
- focusChild->clearFocus();
- }
while (w != q) {
bool isCurrentNew = q->isAncestorOf(w);
diff --git a/src/gui/graphicsview/qgraphicswidget_p.h b/src/gui/graphicsview/qgraphicswidget_p.h
index 0c34baa..92e520a 100644
--- a/src/gui/graphicsview/qgraphicswidget_p.h
+++ b/src/gui/graphicsview/qgraphicswidget_p.h
@@ -83,7 +83,6 @@ public:
focusPolicy(Qt::NoFocus),
focusNext(0),
focusPrev(0),
- focusChild(0),
windowFlags(0),
windowData(0),
setWindowFrameMargins(false),
@@ -178,9 +177,6 @@ public:
Qt::FocusPolicy focusPolicy;
QGraphicsWidget *focusNext;
QGraphicsWidget *focusPrev;
- QGraphicsWidget *focusChild;
- void setFocusWidget();
- void clearFocusWidget();
// Windows
Qt::WindowFlags windowFlags;