summaryrefslogtreecommitdiffstats
path: root/src/gui/graphicsview
diff options
context:
space:
mode:
authorAndreas Aardal Hanssen <andreas.aardal.hanssen@nokia.com>2009-10-02 06:40:17 (GMT)
committerAndreas Aardal Hanssen <andreas.aardal.hanssen@nokia.com>2009-10-02 06:40:17 (GMT)
commit17dc26e3e7a65b6eb0c0980a76c8fbe7bd37c690 (patch)
treeee9a982c144fb636ec22cdf7dd27de37725ff320 /src/gui/graphicsview
parentb148b182b5b48d60c2b57d8b74ad0f30272bb578 (diff)
parent7ea326d796a6d2ecb13b961c576c82a797d84706 (diff)
downloadQt-17dc26e3e7a65b6eb0c0980a76c8fbe7bd37c690.zip
Qt-17dc26e3e7a65b6eb0c0980a76c8fbe7bd37c690.tar.gz
Qt-17dc26e3e7a65b6eb0c0980a76c8fbe7bd37c690.tar.bz2
Merge commit 'qt-mainline/4.6' into kinetic-declarativeui
Conflicts: configure.exe
Diffstat (limited to 'src/gui/graphicsview')
-rw-r--r--src/gui/graphicsview/qgraphicsanchorlayout.cpp118
-rw-r--r--src/gui/graphicsview/qgraphicsanchorlayout.h1
-rw-r--r--src/gui/graphicsview/qgraphicsanchorlayout_p.cpp7
-rw-r--r--src/gui/graphicsview/qgraphicsanchorlayout_p.h7
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp245
-rw-r--r--src/gui/graphicsview/qgraphicsitem.h11
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h2
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp245
-rw-r--r--src/gui/graphicsview/qgraphicsscene_p.h6
-rw-r--r--src/gui/graphicsview/qgraphicsview.cpp28
-rw-r--r--src/gui/graphicsview/qsimplex_p.cpp4
11 files changed, 506 insertions, 168 deletions
diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.cpp b/src/gui/graphicsview/qgraphicsanchorlayout.cpp
index 78b6b53..fdb1708 100644
--- a/src/gui/graphicsview/qgraphicsanchorlayout.cpp
+++ b/src/gui/graphicsview/qgraphicsanchorlayout.cpp
@@ -80,6 +80,24 @@
PM_LayoutHorizontalSpacing (or PM_LayoutVerticalSpacing for vertical anchors).
*/
+/*!
+ \class QGraphicsAnchor
+ \brief The QGraphicsAnchor class represents an anchor between two items in a
+ QGraphicsAnchorLayout.
+ \since 4.6
+ \ingroup appearance
+ \ingroup geomanagement
+ \ingroup graphicsview-api
+
+ The graphics anchor provides an API that enables you to query and manipulate the
+ properties an anchor has. When an anchor is added to the layout with
+ QGraphicsAnchorLayout::addAnchor(), a QGraphicsAnchor instance is returned where the properties
+ are initialized to their default values. The properties can then be further changed, and they
+ will be picked up the next time the layout is activated.
+
+ \sa QGraphicsAnchorLayout::anchor()
+
+*/
#include "qgraphicsanchorlayout_p.h"
QT_BEGIN_NAMESPACE
@@ -171,23 +189,23 @@ QGraphicsAnchorLayout::~QGraphicsAnchorLayout()
}
/*!
- * Creates an anchor between the edge \a firstEdge of item \a firstItem and the edge \a secondEdge
- * of item \a secondItem. The magnitude of the anchor is picked up from the style. Anchors
- * between a layout edge and an item edge will have a size of 0.
- * If there is already an anchor between the edges, the the new anchor will replace the old one.
- *
- * \a firstItem and \a secondItem are automatically added to the layout if they are not part
- * of the layout. This means that count() can increase with up to 2.
- *
- * The spacing an anchor will get depends on the type of anchor. For instance, anchors from the
- * Right edge of one item to the Left edge of another (or vice versa) will use the default
- * horizontal spacing. The same behaviour applies to Bottom to Top anchors, (but they will use
- * the default vertical spacing). For all other anchor combinations, the spacing will be 0.
- * All anchoring functions will follow this rule.
- *
- * The spacing can also be set manually by using QGraphicsAnchor::setSpacing() method.
- *
- * \sa addCornerAnchors(), addAnchors()
+ Creates an anchor between the edge \a firstEdge of item \a firstItem and the edge \a secondEdge
+ of item \a secondItem. The magnitude of the anchor is picked up from the style. Anchors
+ between a layout edge and an item edge will have a size of 0.
+ If there is already an anchor between the edges, the the new anchor will replace the old one.
+
+ \a firstItem and \a secondItem are automatically added to the layout if they are not part
+ of the layout. This means that count() can increase with up to 2.
+
+ The spacing an anchor will get depends on the type of anchor. For instance, anchors from the
+ Right edge of one item to the Left edge of another (or vice versa) will use the default
+ horizontal spacing. The same behaviour applies to Bottom to Top anchors, (but they will use
+ the default vertical spacing). For all other anchor combinations, the spacing will be 0.
+ All anchoring functions will follow this rule.
+
+ The spacing can also be set manually by using QGraphicsAnchor::setSpacing() method.
+
+ \sa addCornerAnchors(), addAnchors()
*/
QGraphicsAnchor *
QGraphicsAnchorLayout::addAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge,
@@ -200,8 +218,8 @@ QGraphicsAnchorLayout::addAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint
}
/*!
- Returns the anchor between the anchor points defined by \a firstItem and \a firstEdge and
- \a secondItem and \a secondEdge. If there is no such anchor, the function will return 0.
+ Returns the anchor between the anchor points defined by \a firstItem and \a firstEdge and
+ \a secondItem and \a secondEdge. If there is no such anchor, the function will return 0.
*/
QGraphicsAnchor *
QGraphicsAnchorLayout::anchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge,
@@ -212,30 +230,30 @@ QGraphicsAnchorLayout::anchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint fi
}
/*!
- * Creates two anchors between \a firstItem and \a secondItem, where one is for the horizontal
- * edge and another one for the vertical edge that the corners \a firstCorner and \a
- * secondCorner specifies.
- * The magnitude of the anchors is picked up from the style.
- *
- * This is a convenience function, since anchoring corners can be expressed as anchoring two edges.
- * For instance,
- * \code
- * layout->addAnchor(layout, Qt::AnchorTop, b, Qt::AnchorTop);
- * layout->addAnchor(layout, Qt::AnchorLeft, b, Qt::AnchorLeft);
- * \endcode
- *
- * has the same effect as
- *
- * \code
- * layout->addCornerAnchors(layout, Qt::TopLeft, b, Qt::TopLeft);
- * \endcode
- *
- * If there is already an anchor between the edge pairs, it will be replaced by the anchors that
- * this function specifies.
- *
- * \a firstItem and \a secondItem are automatically added to the layout if they are not part
- * of the layout. This means that count() can increase with up to 2.
- */
+ Creates two anchors between \a firstItem and \a secondItem, where one is for the horizontal
+ edge and another one for the vertical edge that the corners \a firstCorner and \a
+ secondCorner specifies.
+ The magnitude of the anchors is picked up from the style.
+
+ This is a convenience function, since anchoring corners can be expressed as anchoring two edges.
+ For instance,
+ \code
+ layout->addAnchor(layout, Qt::AnchorTop, b, Qt::AnchorTop);
+ layout->addAnchor(layout, Qt::AnchorLeft, b, Qt::AnchorLeft);
+ \endcode
+
+ has the same effect as
+
+ \code
+ layout->addCornerAnchors(layout, Qt::TopLeft, b, Qt::TopLeft);
+ \endcode
+
+ If there is already an anchor between the edge pairs, it will be replaced by the anchors that
+ this function specifies.
+
+ \a firstItem and \a secondItem are automatically added to the layout if they are not part of the
+ layout. This means that count() can increase with up to 2.
+*/
void QGraphicsAnchorLayout::addCornerAnchors(QGraphicsLayoutItem *firstItem,
Qt::Corner firstCorner,
QGraphicsLayoutItem *secondItem,
@@ -288,18 +306,6 @@ void QGraphicsAnchorLayout::addAnchors(QGraphicsLayoutItem *firstItem,
}
/*!
- Returns true if there are no arrangement that satisfies all constraints.
- Otherwise returns false.
-
- \sa addAnchor()
-*/
-bool QGraphicsAnchorLayout::hasConflicts() const
-{
- Q_D(const QGraphicsAnchorLayout);
- return d->hasConflicts();
-}
-
-/*!
Sets the default horizontal spacing for the anchor layout to \a spacing.
\sa horizontalSpacing(), setVerticalSpacing(), setSpacing()
@@ -360,7 +366,7 @@ qreal QGraphicsAnchorLayout::verticalSpacing() const
}
/*!
- \reimp
+ \reimp
*/
void QGraphicsAnchorLayout::setGeometry(const QRectF &geom)
{
diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.h b/src/gui/graphicsview/qgraphicsanchorlayout.h
index 44074d1..d9a87ba 100644
--- a/src/gui/graphicsview/qgraphicsanchorlayout.h
+++ b/src/gui/graphicsview/qgraphicsanchorlayout.h
@@ -93,7 +93,6 @@ public:
QGraphicsLayoutItem *secondItem,
Qt::Orientations orientations = Qt::Horizontal | Qt::Vertical);
- bool hasConflicts() const;
void setHorizontalSpacing(qreal spacing);
void setVerticalSpacing(qreal spacing);
void setSpacing(qreal spacing);
diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp
index 49aabf5..f75118b 100644
--- a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp
+++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp
@@ -2287,6 +2287,13 @@ bool QGraphicsAnchorLayoutPrivate::solvePreferred(QList<QSimplexConstraint *> co
return feasible;
}
+/*!
+ \internal
+ Returns true if there are no arrangement that satisfies all constraints.
+ Otherwise returns false.
+
+ \sa addAnchor()
+*/
bool QGraphicsAnchorLayoutPrivate::hasConflicts() const
{
QGraphicsAnchorLayoutPrivate *that = const_cast<QGraphicsAnchorLayoutPrivate*>(this);
diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.h b/src/gui/graphicsview/qgraphicsanchorlayout_p.h
index 4e1bcd4..c86bfa3 100644
--- a/src/gui/graphicsview/qgraphicsanchorlayout_p.h
+++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.h
@@ -343,7 +343,7 @@ public:
QGraphicsAnchorLayout private methods and attributes.
*/
-class QGraphicsAnchorLayoutPrivate : public QGraphicsLayoutPrivate
+class Q_AUTOTEST_EXPORT QGraphicsAnchorLayoutPrivate : public QGraphicsLayoutPrivate
{
Q_DECLARE_PUBLIC(QGraphicsAnchorLayout)
@@ -370,6 +370,11 @@ public:
QGraphicsAnchorLayoutPrivate();
+ static QGraphicsAnchorLayoutPrivate *get(QGraphicsAnchorLayout *q)
+ {
+ return q ? q->d_func() : 0;
+ }
+
static Qt::AnchorPoint oppositeEdge(
Qt::AnchorPoint edge);
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index 13b677c..912cfb6 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -186,6 +186,49 @@
high z-values. Stacking order applies to sibling items; parents are always
drawn before their children.
+ \section1 Sorting
+
+ All items are drawn in a defined, stable order, and this same order decides
+ which items will receive mouse input first when you click on the scene.
+ Normally you don't have to worry about sorting, as the items follow a
+ "natural order", following the logical structure of the scene.
+
+ An item's children are stacked on top of the parent, and sibling items are
+ stacked by insertion order (i.e., in the same order that they were either
+ added to the scene, or added to the same parent). If you add item A, and
+ then B, then B will be on top of A. If you then add C, the items' stacking
+ order will be A, then B, then C.
+
+ \image graphicsview-zorder.png
+
+ This example shows the stacking order of all limbs of the robot from the
+ \l{graphicsview/dragdroprobot}{Drag and Drop Robot} example. The torso is
+ the root item (all other items are children or descendants of the torso),
+ so it is drawn first. Next, the head is drawn, as it is the first item in
+ the torso's list of children. Then the upper left arm is drawn. As the
+ lower arm is a child of the upper arm, the lower arm is then drawn,
+ followed by the upper arm's next sibling, which is the upper right arm, and
+ so on.
+
+ For advanced users, there are ways to alter how your items are sorted:
+
+ \list
+ \o You can call setZValue() on an item to explicitly stack it on top of, or
+ under, other sibling items. The default Z value for an item is 0. Items
+ with the same Z value are stacked by insertion order.
+
+ \o You can call stackBefore() to reorder the list of children. This will
+ directly modify the insertion order.
+
+ \o You can set the ItemStacksBehindParent flag to stack a child item behind
+ its parent.
+ \endlist
+
+ The stacking order of two sibling items also counts for each item's
+ children and descendant items. So if one item is on top of another, then
+ all its children will also be on top of all the other item's children as
+ well.
+
\section1 Events
QGraphicsItem receives events from QGraphicsScene through the virtual
@@ -564,6 +607,21 @@
supportsExtension() and setExtension().
*/
+/*!
+ \enum QGraphicsItem::PanelModality
+
+ This enum specifies the behavior of a modal panel. A modal panel
+ is one that blocks input to other panels. Note that items that
+ are children of a modal panel are not blocked.
+
+ The values are:
+ \value NonModal The panel is not modal and does not block input to other panels.
+ \value PanelModal The panel is modal to a single item hierarchy and blocks input to its parent pane, all grandparent panels, and all siblings of its parent and grandparent panels.
+ \value SceneModal The window is modal to the entire scene and blocks input to all panels.
+
+ \sa QGraphicsItem::setPanelModality(), QGraphicsItem::panelModality(), QGraphicsItem::ItemIsPanel
+*/
+
#include "qgraphicsitem.h"
#ifndef QT_NO_GRAPHICSVIEW
@@ -1472,10 +1530,12 @@ QList<QGraphicsItem *> QGraphicsItem::children() const
/*!
\since 4.4
- Returns a list of this item's children. The items are returned in no
- particular order.
+ Returns a list of this item's children.
- \sa setParentItem()
+ The items are sorted by stacking order. This takes into account both the
+ items' insertion order and their Z-values.
+
+ \sa setParentItem(), zValue(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsItem::childItems() const
{
@@ -1649,6 +1709,16 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags)
setFlag(ItemStacksBehindParent, d_ptr->z < qreal(0.0));
}
+ if ((d_ptr->panelModality != NonModal)
+ && d_ptr->scene
+ && (flags & ItemIsPanel) != (oldFlags & ItemIsPanel)) {
+ // update the panel's modal state
+ if (flags & ItemIsPanel)
+ d_ptr->scene->d_func()->enterModal(this);
+ else
+ d_ptr->scene->d_func()->leaveModal(this);
+ }
+
if (d_ptr->scene) {
d_ptr->scene->d_func()->markDirty(this, QRectF(),
/*invalidateChildren=*/true,
@@ -1725,6 +1795,87 @@ void QGraphicsItem::setCacheMode(CacheMode mode, const QSize &logicalCacheSize)
update();
}
+/*!
+ \since 4.6
+
+ Returns the modality for this item.
+*/
+QGraphicsItem::PanelModality QGraphicsItem::panelModality() const
+{
+ return d_ptr->panelModality;
+}
+
+/*!
+ \since 4.6
+
+ Sets the modality for this item to \a panelModality.
+
+ Changing the modality of a visible item takes effect immediately.
+*/
+void QGraphicsItem::setPanelModality(PanelModality panelModality)
+{
+ if (d_ptr->panelModality == panelModality)
+ return;
+
+ PanelModality previousModality = d_ptr->panelModality;
+ bool enterLeaveModal = (isPanel() && d_ptr->scene && isVisible());
+ if (enterLeaveModal && panelModality == NonModal)
+ d_ptr->scene->d_func()->leaveModal(this);
+ d_ptr->panelModality = panelModality;
+ if (enterLeaveModal && d_ptr->panelModality != NonModal)
+ d_ptr->scene->d_func()->enterModal(this, previousModality);
+}
+
+/*!
+ \since 4.6
+
+ Returns true if this item is blocked by a modal panel, false otherwise. If \a blockingPanel is
+ non-zero, \a blockingPanel will be set to the modal panel that is blocking this item. If this
+ item is not blocked, \a blockingPanel will not be set by this function.
+
+ This function always returns false for items not in a scene.
+
+ \sa panelModality() setPanelModality() PanelModality
+*/
+bool QGraphicsItem::isBlockedByModalPanel(QGraphicsItem **blockingPanel) const
+{
+ if (!d_ptr->scene)
+ return false;
+
+
+ QGraphicsItem *dummy = 0;
+ if (!blockingPanel)
+ blockingPanel = &dummy;
+
+ QGraphicsScenePrivate *scene_d = d_ptr->scene->d_func();
+ if (scene_d->modalPanels.isEmpty())
+ return false;
+
+ // ###
+ if (!scene_d->popupWidgets.isEmpty() && scene_d->popupWidgets.first() == this)
+ return false;
+
+ for (int i = 0; i < scene_d->modalPanels.count(); ++i) {
+ QGraphicsItem *modalPanel = scene_d->modalPanels.at(i);
+ if (modalPanel->panelModality() == QGraphicsItem::SceneModal) {
+ // Scene modal panels block all non-descendents.
+ if (modalPanel != this && !modalPanel->isAncestorOf(this)) {
+ *blockingPanel = modalPanel;
+ return true;
+ }
+ } else {
+ // Window modal panels block ancestors and siblings/cousins.
+ if (modalPanel != this
+ && !modalPanel->isAncestorOf(this)
+ && commonAncestorItem(modalPanel)) {
+ *blockingPanel = modalPanel;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
#ifndef QT_NO_TOOLTIP
/*!
Returns the item's tool tip, or an empty QString if no tool tip has been
@@ -1934,6 +2085,8 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo
q->ungrabMouse();
if (scene->d_func()->keyboardGrabberItems.contains(q))
q->ungrabKeyboard();
+ if (q->isPanel() && panelModality != QGraphicsItem::NonModal)
+ scene->d_func()->leaveModal(q_ptr);
}
if (q_ptr->hasFocus() && scene) {
// Hiding the closest non-panel ancestor of the focus item
@@ -1955,10 +2108,15 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo
} else {
geometryChanged = 1;
paintedViewBoundingRectsNeedRepaint = 1;
- if (isWidget && scene) {
- QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(q_ptr);
- if (widget->windowType() == Qt::Popup)
- scene->d_func()->addPopup(widget);
+ if (scene) {
+ if (isWidget) {
+ QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(q_ptr);
+ if (widget->windowType() == Qt::Popup)
+ scene->d_func()->addPopup(widget);
+ }
+ if (q->isPanel() && panelModality != QGraphicsItem::NonModal) {
+ scene->d_func()->enterModal(q_ptr);
+ }
}
}
@@ -2781,7 +2939,7 @@ bool QGraphicsItem::hasFocus() const
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
+ 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.
@@ -3309,7 +3467,7 @@ QMatrix QGraphicsItem::matrix() const
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()
@@ -3790,7 +3948,7 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine)
// Update and set the new transformation.
d_ptr->setTransformHelper(newTransform);
-
+
// Send post-notification.
itemChange(ItemTransformHasChanged, qVariantFromValue<QTransform>(newTransform));
}
@@ -3924,7 +4082,7 @@ void QGraphicsItem::scale(qreal sx, qreal sy)
/*!
\obsolete
- Use
+ Use
\code
setTransform(QTransform().shear(sh, sv), true);
@@ -3946,7 +4104,7 @@ void QGraphicsItem::shear(qreal sh, qreal sv)
Use setPos() or setTransformOriginPoint() instead. For identical
behavior, use
-
+
\code
setTransform(QTransform::fromTranslate(dx, dy), true);
\endcode
@@ -3987,12 +4145,12 @@ void QGraphicsItem::advance(int phase)
}
/*!
- Returns the Z-value, or the elevation, of the item. The Z-value decides
- the stacking order of sibling (neighboring) items.
+ Returns the Z-value of the item. The Z-value affects the stacking order of
+ sibling (neighboring) items.
The default Z-value is 0.
- \sa setZValue()
+ \sa setZValue(), {QGraphicsItem#Sorting}{Sorting}, stackBefore(), ItemStacksBehindParent
*/
qreal QGraphicsItem::zValue() const
{
@@ -4000,33 +4158,18 @@ qreal QGraphicsItem::zValue() const
}
/*!
- Sets the Z-value, or the elevation, of the item, to \a z. The elevation
- decides the stacking order of sibling (neighboring) items. An item of high
- Z-value will be drawn on top of an item with a lower Z-value if they share
- the same parent item. In addition, children of an item will always be
- drawn on top of the parent, regardless of the child's Z-value. Sibling
- items that share the same Z-value will be drawn in order of insertion; the
- last inserted child is stacked above previous children.
-
- \img graphicsview-zorder.png
+ Sets the Z-value of the item to \a z. The Z value decides the stacking
+ order of sibling (neighboring) items. A sibling item of high Z value will
+ always be drawn on top of another sibling item with a lower Z value.
- Children of different parents are stacked according to the Z-value of
- each item's ancestor item which is an immediate child of the two
- items' closest common ancestor. For example, a robot item might
- define a torso item as the parent of a head item, two arm items,
- and two upper-leg items. The upper-leg items would each be parents
- of one lower-leg item, and each lower-leg item would be parents of
- one foot item. The stacking order of the feet is the same as the
- stacking order of each foot's ancestor that is an immediate child
- of the two feet's common ancestor (i.e., the torso item); so the
- feet are stacked in the same order as the upper-leg items,
- regardless of each foot's Z-value.
+ If you restore the Z value, the item's insertion order will decide its
+ stacking order.
The Z-value does not affect the item's size in any way.
The default Z-value is 0.
- \sa zValue()
+ \sa zValue(), {QGraphicsItem#Sorting}{Sorting}, stackBefore(), ItemStacksBehindParent
*/
void QGraphicsItem::setZValue(qreal z)
{
@@ -4089,12 +4232,13 @@ void QGraphicsItemPrivate::ensureSequentialSiblingIndex()
The \a sibling must have the same Z value as this item, otherwise calling
this function will have no effect.
- By default, all items are stacked by insertion order (i.e., the first item
- you add is drawn before the next item you add). If two items' Z values are
- different, then the item with the highest Z value is drawn on top. When the
- Z values are the same, the insertion order will decide the stacking order.
+ By default, all sibling items are stacked by insertion order (i.e., the
+ first item you add is drawn before the next item you add). If two items' Z
+ values are different, then the item with the highest Z value is drawn on
+ top. When the Z values are the same, the insertion order will decide the
+ stacking order.
- \sa setZValue(), ItemStacksBehindParent
+ \sa setZValue(), ItemStacksBehindParent, {QGraphicsItem#Sorting}{Sorting}
*/
void QGraphicsItem::stackBefore(const QGraphicsItem *sibling)
{
@@ -4456,7 +4600,7 @@ bool QGraphicsItem::collidesWithItem(const QGraphicsItem *other, Qt::ItemSelecti
Note that this function checks whether the item's shape or
bounding rectangle (depending on \a mode) is contained within \a
path, and not whether \a path is contained within the items shape
- or bounding rectangle.
+ or bounding rectangle.
\sa collidesWithItem(), contains(), shape()
*/
@@ -5150,14 +5294,8 @@ void QGraphicsItem::update(const QRectF &rect)
} while ((item = item->d_ptr->parent));
if (CacheMode(d_ptr->cacheMode) != NoCache) {
- QGraphicsItemCache *cache = d_ptr->extraItemCache();
- if (d_ptr->discardUpdateRequest(/* ignoreVisibleBit = */ false,
- /* ignoreClipping = */ false,
- /* ignoreDirtyBit = */ true)) {
- return;
- }
-
// Invalidate cache.
+ QGraphicsItemCache *cache = d_ptr->extraItemCache();
if (!cache->allExposed) {
if (rect.isNull()) {
cache->allExposed = true;
@@ -5171,6 +5309,9 @@ void QGraphicsItem::update(const QRectF &rect)
return;
}
+ if (d_ptr->discardUpdateRequest())
+ return;
+
if (d_ptr->scene)
d_ptr->scene->d_func()->markDirty(this, rect);
}
@@ -6608,7 +6749,7 @@ void QGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
if (d_ptr->isWidget) {
// Qt::Popup closes when you click outside.
QGraphicsWidget *w = static_cast<QGraphicsWidget *>(this);
- if (w->windowFlags() & Qt::Popup) {
+ if ((w->windowFlags() & Qt::Popup) == Qt::Popup) {
event->accept();
if (!w->rect().contains(event->pos()))
w->close();
@@ -7033,7 +7174,7 @@ 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->isSignalConnected(scenePrivate->changedSignalIndex)
+ if (scenePrivate->isSignalConnected(scenePrivate->changedSignalIndex)
|| scenePrivate->views.isEmpty()) {
if (d_ptr->hasTranslateOnlySceneTransform()) {
d_ptr->scene->update(boundingRect().translated(d_ptr->sceneTransform.dx(),
@@ -10537,7 +10678,7 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP
effectRect.setRight(deviceWidth - 1);
if (bottom + 1 > deviceHeight)
effectRect.setBottom(deviceHeight -1);
-
+
}
if (effectRect.isEmpty())
diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h
index 99d2e12..e6e324a 100644
--- a/src/gui/graphicsview/qgraphicsitem.h
+++ b/src/gui/graphicsview/qgraphicsitem.h
@@ -146,6 +146,13 @@ public:
DeviceCoordinateCache
};
+ enum PanelModality
+ {
+ NonModal,
+ PanelModal,
+ SceneModal
+ };
+
QGraphicsItem(QGraphicsItem *parent = 0
#ifndef Q_QDOC
// ### obsolete argument
@@ -183,6 +190,10 @@ public:
CacheMode cacheMode() const;
void setCacheMode(CacheMode mode, const QSize &cacheSize = QSize());
+ PanelModality panelModality() const;
+ void setPanelModality(PanelModality panelModality);
+ bool isBlockedByModalPanel(QGraphicsItem **blockingPanel = 0) const;
+
#ifndef QT_NO_TOOLTIP
QString toolTip() const;
void setToolTip(const QString &toolTip);
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index 3feccdc..51bfea1 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -131,6 +131,7 @@ public:
subFocusItem(0),
focusScopeItem(0),
imHints(Qt::ImhNone),
+ panelModality(QGraphicsItem::NonModal),
acceptedMouseButtons(0x1f),
visible(1),
explicitlyHidden(0),
@@ -448,6 +449,7 @@ public:
QGraphicsItem *subFocusItem;
QGraphicsItem *focusScopeItem;
Qt::InputMethodHints imHints;
+ QGraphicsItem::PanelModality panelModality;
// Packed 32 bits
quint32 acceptedMouseButtons : 5;
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 4b74b67..1226722 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -565,6 +565,9 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item)
q->removeItem(item->d_ptr->children.at(i));
}
+ if (item->isPanel() && item->isVisible() && item->panelModality() != QGraphicsItem::NonModal)
+ leaveModal(item);
+
// Reset the mouse grabber and focus item data.
if (mouseGrabberItems.contains(item))
ungrabMouse(item, /* item is dying */ item->d_ptr->inDestructor);
@@ -1111,6 +1114,9 @@ void QGraphicsScenePrivate::sendMouseEvent(QGraphicsSceneMouseEvent *mouseEvent)
}
QGraphicsItem *item = mouseGrabberItems.last();
+ if (item->isBlockedByModalPanel())
+ return;
+
for (int i = 0x1; i <= 0x10; i <<= 1) {
Qt::MouseButton button = Qt::MouseButton(i);
mouseEvent->setButtonDownPos(button, mouseGrabberButtonDownPos.value(button, item->d_ptr->genericMapFromScene(mouseEvent->scenePos(), mouseEvent->widget())));
@@ -1134,6 +1140,8 @@ void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mou
// Deliver to any existing mouse grabber.
if (!mouseGrabberItems.isEmpty()) {
+ if (mouseGrabberItems.last()->isBlockedByModalPanel())
+ return;
// The event is ignored by default, but we disregard the event's
// accepted state after delivery; the mouse is grabbed, after all.
sendMouseEvent(mouseEvent);
@@ -1151,12 +1159,22 @@ void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mou
// Update window activation.
QGraphicsItem *topItem = cachedItemsUnderMouse.value(0);
QGraphicsWidget *newActiveWindow = topItem ? topItem->window() : 0;
+ if (newActiveWindow && newActiveWindow->isBlockedByModalPanel(&topItem)) {
+ // pass activation to the blocking modal window
+ newActiveWindow = topItem ? topItem->window() : 0;
+ }
+
if (newActiveWindow != q->activeWindow())
q->setActiveWindow(newActiveWindow);
// Set focus on the topmost enabled item that can take focus.
bool setFocus = false;
foreach (QGraphicsItem *item, cachedItemsUnderMouse) {
+ if (item->isBlockedByModalPanel()) {
+ // Make sure we don't clear focus.
+ setFocus = true;
+ break;
+ }
if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) {
if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) {
setFocus = true;
@@ -1165,12 +1183,27 @@ void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mou
break;
}
}
+ if (item->isPanel())
+ break;
+ }
+
+ // Check for scene modality.
+ bool sceneModality = false;
+ for (int i = 0; i < modalPanels.size(); ++i) {
+ if (modalPanels.at(i)->panelModality() == QGraphicsItem::SceneModal) {
+ sceneModality = true;
+ break;
+ }
}
// If nobody could take focus, clear it.
- if (!stickyFocus && !setFocus)
+ if (!stickyFocus && !setFocus && !sceneModality)
q->setFocusItem(0, Qt::MouseFocusReason);
+ // Any item will do.
+ if (sceneModality && cachedItemsUnderMouse.isEmpty())
+ cachedItemsUnderMouse << modalPanels.first();
+
// Find a mouse grabber by sending mouse press events to all mouse grabber
// candidates one at a time, until the event is accepted. It's accepted by
// default, so the receiver has to explicitly ignore it for it to pass
@@ -1181,6 +1214,10 @@ void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mou
continue;
}
+ // Check if this item is blocked by a modal panel and deliver the mouse event to the
+ // blocking panel instead of this item if blocked.
+ (void) item->isBlockedByModalPanel(&item);
+
grabMouse(item, /* implicit = */ true);
mouseEvent->accept();
@@ -1723,9 +1760,9 @@ QRectF QGraphicsScene::itemsBoundingRect() const
}
/*!
- Returns a list of all items on the scene, in no particular order.
+ Returns a list of all items in the scene in descending stacking order.
- \sa addItem(), removeItem()
+ \sa addItem(), removeItem(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsScene::items() const
{
@@ -1735,9 +1772,9 @@ QList<QGraphicsItem *> QGraphicsScene::items() const
/*!
Returns an ordered list of all items on the scene. \a order decides the
- sorting.
+ stacking order.
- \sa addItem(), removeItem()
+ \sa addItem(), removeItem(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsScene::items(Qt::SortOrder order) const
{
@@ -1756,7 +1793,7 @@ QList<QGraphicsItem *> QGraphicsScene::items(Qt::SortOrder order) const
contains items that ignore transformations. Use the overload that takes
a QTransform instead.
- \sa itemAt()
+ \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos) const
{
@@ -1778,7 +1815,7 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos) const
contains items that ignore transformations. Use the overload that takes
a QTransform instead.
- \sa itemAt()
+ \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSelectionMode mode) const
{
@@ -1799,20 +1836,20 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSe
*/
/*!
- \fn QList<QGraphicsItem *> QGraphicsScene::items(qreal x, qreal y, qreal w, qreal h,
- Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const
+ \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.
+ \brief 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.
*/
/*!
+ \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode) const
\overload
\obsolete
@@ -1826,7 +1863,7 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSe
contains items that ignore transformations. Use the overload that takes
a QTransform instead.
- \sa itemAt()
+ \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode) const
{
@@ -1835,6 +1872,7 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemS
}
/*!
+ \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const
\overload
\obsolete
@@ -1848,7 +1886,7 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemS
contains items that ignore transformations. Use the overload that takes
a QTransform instead.
- \sa itemAt()
+ \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const
{
@@ -1857,10 +1895,11 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemS
}
/*!
+ \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const
\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.
+ \brief 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.
@@ -1868,7 +1907,7 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemS
\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()
+ \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos, Qt::ItemSelectionMode mode,
Qt::SortOrder order, const QTransform &deviceTransform) const
@@ -1878,11 +1917,13 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos, Qt::ItemSelecti
}
/*!
+ \fn QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, 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 specified \a rect and return a list sorted using \a order.
+ \brief 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.
@@ -1890,7 +1931,7 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos, Qt::ItemSelecti
\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()
+ \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode,
Qt::SortOrder order, const QTransform &deviceTransform) const
@@ -1900,11 +1941,13 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelecti
}
/*!
+ \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, 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 specified \a polygon and return a list sorted using \a order.
+ \brief 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.
@@ -1912,7 +1955,7 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelecti
\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()
+ \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode,
Qt::SortOrder order, const QTransform &deviceTransform) const
@@ -1922,11 +1965,13 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemS
}
/*!
+ \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, 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 specified \a path and return a list sorted using \a order.
+ \brief 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.
@@ -1934,7 +1979,7 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemS
\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()
+ \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode,
Qt::SortOrder order, const QTransform &deviceTransform) const
@@ -1949,10 +1994,11 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemS
detection is determined by \a mode. By default, all items whose shape
intersects \a item or is contained inside \a item's shape are returned.
- The items are returned 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).
+ The items are returned in descending stacking order (i.e., the first item
+ in the list is the uppermost item, and the last item is the lowermost
+ item).
- \sa items(), itemAt(), QGraphicsItem::collidesWithItem()
+ \sa items(), itemAt(), QGraphicsItem::collidesWithItem(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsScene::collidingItems(const QGraphicsItem *item,
Qt::ItemSelectionMode mode) const
@@ -1979,13 +2025,11 @@ QList<QGraphicsItem *> QGraphicsScene::collidingItems(const QGraphicsItem *item,
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()
+ \sa items(), collidingItems(), {QGraphicsItem#Sorting}{Sorting}
*/
QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position) const
{
@@ -2002,10 +2046,8 @@ QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position) const
\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()
- */
+ \sa items(), collidingItems(), {QGraphicsItem#Sorting}{Sorting}
+*/
QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position, const QTransform &deviceTransform) const
{
QList<QGraphicsItem *> itemsAtPoint = items(position, Qt::IntersectsItemShape,
@@ -2026,8 +2068,6 @@ QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position, const QTransform
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.
*/
/*!
@@ -2044,8 +2084,6 @@ QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position, const QTransform
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.
*/
/*!
@@ -2324,7 +2362,7 @@ void QGraphicsScene::destroyItemGroup(QGraphicsItemGroup *group)
in the scene, then the item will be activated.
\sa removeItem(), addEllipse(), addLine(), addPath(), addPixmap(),
- addRect(), addText(), addWidget()
+ addRect(), addText(), addWidget(), {QGraphicsItem#Sorting}{Sorting}
*/
void QGraphicsScene::addItem(QGraphicsItem *item)
{
@@ -2403,6 +2441,8 @@ void QGraphicsScene::addItem(QGraphicsItem *item)
d->selectedItems << item;
if (item->isWidget() && item->isVisible() && static_cast<QGraphicsWidget *>(item)->windowType() == Qt::Popup)
d->addPopup(static_cast<QGraphicsWidget *>(item));
+ if (item->isPanel() && item->isVisible() && item->panelModality() != QGraphicsItem::NonModal)
+ d->enterModal(item);
// Update creation order focus chain. Make sure to leave the widget's
// internal tab order intact.
@@ -3205,8 +3245,12 @@ bool QGraphicsScene::event(QEvent *event)
}
return false;
case QEvent::GraphicsSceneMouseMove:
- mouseMoveEvent(static_cast<QGraphicsSceneMouseEvent *>(event));
+ {
+ QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent *>(event);
+ d->lastSceneMousePos = mouseEvent->scenePos();
+ mouseMoveEvent(mouseEvent);
break;
+ }
case QEvent::GraphicsSceneMousePress:
mousePressEvent(static_cast<QGraphicsSceneMouseEvent *>(event));
break;
@@ -3228,8 +3272,12 @@ bool QGraphicsScene::event(QEvent *event)
case QEvent::GraphicsSceneHoverEnter:
case QEvent::GraphicsSceneHoverLeave:
case QEvent::GraphicsSceneHoverMove:
- d->dispatchHoverEvent(static_cast<QGraphicsSceneHoverEvent *>(event));
+ {
+ QGraphicsSceneHoverEvent *hoverEvent = static_cast<QGraphicsSceneHoverEvent *>(event);
+ d->lastSceneMousePos = hoverEvent->scenePos();
+ d->dispatchHoverEvent(hoverEvent);
break;
+ }
case QEvent::Leave:
d->leaveScene();
break;
@@ -3599,8 +3647,10 @@ void QGraphicsScene::helpEvent(QGraphicsSceneHelpEvent *helpEvent)
bool QGraphicsScenePrivate::itemAcceptsHoverEvents_helper(const QGraphicsItem *item) const
{
- return item->acceptHoverEvents()
- || (item->isWidget() && static_cast<const QGraphicsWidget *>(item)->d_func()->hasDecoration());
+ return (!item->isBlockedByModalPanel() &&
+ (item->acceptHoverEvents()
+ || (item->isWidget()
+ && static_cast<const QGraphicsWidget *>(item)->d_func()->hasDecoration())));
}
/*!
@@ -3674,7 +3724,9 @@ bool QGraphicsScenePrivate::dispatchHoverEvent(QGraphicsSceneHoverEvent *hoverEv
}
// Generate a move event for the item itself
- if (item && !hoverItems.isEmpty() && item == hoverItems.last()) {
+ if (item
+ && !hoverItems.isEmpty()
+ && item == hoverItems.last()) {
sendHoverEvent(QEvent::GraphicsSceneHoverMove, item, hoverEvent);
return true;
}
@@ -3708,8 +3760,7 @@ void QGraphicsScenePrivate::leaveScene()
while (!hoverItems.isEmpty()) {
QGraphicsItem *lastItem = hoverItems.takeLast();
- if (lastItem->acceptHoverEvents()
- || (lastItem->isWidget() && static_cast<QGraphicsWidget*>(lastItem)->d_func()->hasDecoration()))
+ if (itemAcceptsHoverEvents_helper(lastItem))
sendHoverEvent(QEvent::GraphicsSceneHoverLeave, lastItem, &hoverEvent);
}
}
@@ -3736,6 +3787,8 @@ void QGraphicsScene::keyPressEvent(QKeyEvent *keyEvent)
keyEvent->accept();
// Send it; QGraphicsItem::keyPressEvent ignores it. If the event
// is filtered out, stop propagating it.
+ if (p->isBlockedByModalPanel())
+ break;
if (!d->sendEvent(p, keyEvent))
break;
} while (!keyEvent->isAccepted() && !p->isPanel() && (p = p->parentItem()));
@@ -3766,6 +3819,8 @@ void QGraphicsScene::keyReleaseEvent(QKeyEvent *keyEvent)
keyEvent->accept();
// Send it; QGraphicsItem::keyPressEvent ignores it. If the event
// is filtered out, stop propagating it.
+ if (p->isBlockedByModalPanel())
+ break;
if (!d->sendEvent(p, keyEvent))
break;
} while (!keyEvent->isAccepted() && !p->isPanel() && (p = p->parentItem()));
@@ -5420,6 +5475,8 @@ void QGraphicsScenePrivate::touchEventHandler(QTouchEvent *sceneTouchEvent)
for (; it != end; ++it) {
QGraphicsItem *item = it.key();
+ (void) item->isBlockedByModalPanel(&item);
+
// determine event type from the state mask
QEvent::Type eventType;
switch (it.value().first) {
@@ -5493,6 +5550,8 @@ bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEve
break;
}
}
+ if (item->isPanel())
+ break;
}
// If nobody could take focus, clear it.
@@ -5518,6 +5577,8 @@ bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEve
}
break;
}
+ if (item->isPanel())
+ break;
}
touchEvent->setAccepted(eventAccepted);
@@ -5536,6 +5597,94 @@ void QGraphicsScenePrivate::updateInputMethodSensitivityInViews()
views.at(i)->d_func()->updateInputMethodSensitivity();
}
+void QGraphicsScenePrivate::enterModal(QGraphicsItem *panel, QGraphicsItem::PanelModality previousModality)
+{
+ Q_Q(QGraphicsScene);
+ Q_ASSERT(panel && panel->isPanel());
+
+ QGraphicsItem::PanelModality panelModality = panel->d_ptr->panelModality;
+ if (previousModality != QGraphicsItem::NonModal) {
+ // the panel is changing from one modality type to another... temporarily set it back so
+ // that blockedPanels is populated correctly
+ panel->d_ptr->panelModality = previousModality;
+ }
+
+ QSet<QGraphicsItem *> blockedPanels;
+ QList<QGraphicsItem *> items = q->items(); // ### store panels separately
+ for (int i = 0; i < items.count(); ++i) {
+ QGraphicsItem *item = items.at(i);
+ if (item->isPanel() && item->isBlockedByModalPanel())
+ blockedPanels.insert(item);
+ }
+ // blockedPanels contains all currently blocked panels
+
+ if (previousModality != QGraphicsItem::NonModal) {
+ // reset the modality to the proper value, since we changed it above
+ panel->d_ptr->panelModality = panelModality;
+ // remove this panel so that it will be reinserted at the front of the stack
+ modalPanels.removeAll(panel);
+ }
+
+ modalPanels.prepend(panel);
+
+ if (!hoverItems.isEmpty()) {
+ // send GraphicsSceneHoverLeave events to newly blocked hoverItems
+ QGraphicsSceneHoverEvent hoverEvent;
+ hoverEvent.setScenePos(lastSceneMousePos);
+ dispatchHoverEvent(&hoverEvent);
+ }
+
+ if (!mouseGrabberItems.isEmpty() && lastMouseGrabberItemHasImplicitMouseGrab) {
+ QGraphicsItem *item = mouseGrabberItems.last();
+ if (item->isBlockedByModalPanel())
+ ungrabMouse(item, /*itemIsDying =*/ false);
+ }
+
+ QEvent windowBlockedEvent(QEvent::WindowBlocked);
+ QEvent windowUnblockedEvent(QEvent::WindowUnblocked);
+ for (int i = 0; i < items.count(); ++i) {
+ QGraphicsItem *item = items.at(i);
+ if (item->isPanel()) {
+ if (!blockedPanels.contains(item) && item->isBlockedByModalPanel()) {
+ // send QEvent::WindowBlocked to newly blocked panels
+ sendEvent(item, &windowBlockedEvent);
+ } else if (blockedPanels.contains(item) && !item->isBlockedByModalPanel()) {
+ // send QEvent::WindowUnblocked to unblocked panels when downgrading
+ // a panel from SceneModal to PanelModal
+ sendEvent(item, &windowUnblockedEvent);
+ }
+ }
+ }
+}
+
+void QGraphicsScenePrivate::leaveModal(QGraphicsItem *panel)
+{
+ Q_Q(QGraphicsScene);
+ Q_ASSERT(panel && panel->isPanel());
+
+ QSet<QGraphicsItem *> blockedPanels;
+ QList<QGraphicsItem *> items = q->items(); // ### same as above
+ for (int i = 0; i < items.count(); ++i) {
+ QGraphicsItem *item = items.at(i);
+ if (item->isPanel() && item->isBlockedByModalPanel())
+ blockedPanels.insert(item);
+ }
+
+ modalPanels.removeAll(panel);
+
+ QEvent e(QEvent::WindowUnblocked);
+ for (int i = 0; i < items.count(); ++i) {
+ QGraphicsItem *item = items.at(i);
+ if (item->isPanel() && blockedPanels.contains(item) && !item->isBlockedByModalPanel())
+ sendEvent(item, &e);
+ }
+
+ // send GraphicsSceneHoverEnter events to newly unblocked items
+ QGraphicsSceneHoverEvent hoverEvent;
+ hoverEvent.setScenePos(lastSceneMousePos);
+ dispatchHoverEvent(&hoverEvent);
+}
+
QT_END_NAMESPACE
#include "moc_qgraphicsscene.cpp"
diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h
index 46917ce..5000860 100644
--- a/src/gui/graphicsview/qgraphicsscene_p.h
+++ b/src/gui/graphicsview/qgraphicsscene_p.h
@@ -160,6 +160,7 @@ public:
Qt::DropAction lastDropAction;
QList<QGraphicsItem *> cachedItemsUnderMouse;
QList<QGraphicsItem *> hoverItems;
+ QPointF lastSceneMousePos;
bool allItemsIgnoreHoverEvents;
bool allItemsUseDefaultCursor;
void enableMouseTrackingOnViews();
@@ -282,6 +283,11 @@ public:
void enableTouchEventsOnViews();
void updateInputMethodSensitivityInViews();
+
+ QList<QGraphicsItem *> modalPanels;
+ void enterModal(QGraphicsItem *item,
+ QGraphicsItem::PanelModality panelModality = QGraphicsItem::NonModal);
+ void leaveModal(QGraphicsItem *item);
};
// QRectF::intersects() returns false always if either the source or target
diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp
index 98b2c9c..32747cc 100644
--- a/src/gui/graphicsview/qgraphicsview.cpp
+++ b/src/gui/graphicsview/qgraphicsview.cpp
@@ -2016,9 +2016,11 @@ void QGraphicsView::render(QPainter *painter, const QRectF &target, const QRect
}
/*!
- Returns a list of all the items in the associated scene.
+ Returns a list of all the items in the associated scene, in descending
+ stacking order (i.e., the first item in the returned list is the uppermost
+ item).
- \sa QGraphicsScene::items()
+ \sa QGraphicsScene::items(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsView::items() const
{
@@ -2030,9 +2032,9 @@ QList<QGraphicsItem *> QGraphicsView::items() const
/*!
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
- is in viewport coordinates.
+ items are listed in descending stacking order (i.e., the first item in the
+ list is the uppermost item, and the last item is the lowermost item). \a
+ pos is in viewport coordinates.
This function is most commonly called from within mouse event handlers in
a subclass in QGraphicsView. \a pos is in untransformed viewport
@@ -2040,7 +2042,7 @@ QList<QGraphicsItem *> QGraphicsView::items() const
\snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 5
- \sa QGraphicsScene::items(), QGraphicsItem::zValue()
+ \sa QGraphicsScene::items(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsView::items(const QPoint &pos) const
{
@@ -2082,7 +2084,10 @@ QList<QGraphicsItem *> QGraphicsView::items(const QPoint &pos) const
The default value for \a mode is Qt::IntersectsItemShape; all items whose
exact shape intersects with or is contained by \a rect are returned.
- \sa itemAt(), items(), mapToScene()
+ The items are sorted in descending stacking order (i.e., the first item in
+ the returned list is the uppermost item).
+
+ \sa itemAt(), items(), mapToScene(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsView::items(const QRect &rect, Qt::ItemSelectionMode mode) const
{
@@ -2110,7 +2115,10 @@ QList<QGraphicsItem *> QGraphicsView::items(const QRect &rect, Qt::ItemSelection
The default value for \a mode is Qt::IntersectsItemShape; all items whose
exact shape intersects with or is contained by \a polygon are returned.
- \sa itemAt(), items(), mapToScene()
+ The items are sorted by descending stacking order (i.e., the first item in
+ the returned list is the uppermost item).
+
+ \sa itemAt(), items(), mapToScene(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsView::items(const QPolygon &polygon, Qt::ItemSelectionMode mode) const
{
@@ -2130,7 +2138,7 @@ QList<QGraphicsItem *> QGraphicsView::items(const QPolygon &polygon, Qt::ItemSel
The default value for \a mode is Qt::IntersectsItemShape; all items whose
exact shape intersects with or is contained by \a path are returned.
- \sa itemAt(), items(), mapToScene()
+ \sa itemAt(), items(), mapToScene(), {QGraphicsItem#Sorting}{Sorting}
*/
QList<QGraphicsItem *> QGraphicsView::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const
{
@@ -2149,7 +2157,7 @@ QList<QGraphicsItem *> QGraphicsView::items(const QPainterPath &path, Qt::ItemSe
\snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 6
- \sa items()
+ \sa items(), {QGraphicsItem#Sorting}{Sorting}
*/
QGraphicsItem *QGraphicsView::itemAt(const QPoint &pos) const
{
diff --git a/src/gui/graphicsview/qsimplex_p.cpp b/src/gui/graphicsview/qsimplex_p.cpp
index 1ba24a3..1ece8b1 100644
--- a/src/gui/graphicsview/qsimplex_p.cpp
+++ b/src/gui/graphicsview/qsimplex_p.cpp
@@ -49,6 +49,7 @@
QT_BEGIN_NAMESPACE
/*!
+ \internal
\class QSimplex
The QSimplex class is a Linear Programming problem solver based on the two-phase
@@ -111,6 +112,7 @@ void QSimplex::clearDataStructures()
}
/*!
+ \internal
Sets the new constraints in the simplex solver and returns whether the problem
is feasible.
@@ -509,6 +511,7 @@ qreal QSimplex::solver(solverFactor factor)
}
/*!
+ \internal
Minimize the original objective.
*/
qreal QSimplex::solveMin()
@@ -517,6 +520,7 @@ qreal QSimplex::solveMin()
}
/*!
+ \internal
Maximize the original objective.
*/
qreal QSimplex::solveMax()