Ignore:
Timestamp:
May 5, 2011, 5:36:53 AM (14 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

Location:
trunk
Files:
52 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/gui/graphicsview/qgraph_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/graphicsview/qgraphicsanchorlayout.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/graphicsview/qgraphicsanchorlayout.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/graphicsview/qgraphicsanchorlayout_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/graphicsview/qgraphicsgridlayout.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6565    destroying it.
    6666
     67    \section1 Size Hints and Size Policies in QGraphicsGridLayout
     68
     69    QGraphicsGridLayout respects each item's size hints and size policies,
     70    and when a cell in the grid has more space than the items can fill, each item
     71    is arranged according to the layout's alignment for that item. You can set
     72    an alignment for each item by calling setAlignment(), and check the
     73    alignment for any item by calling alignment(). You can also set the alignment
     74    for an entire row or column by calling setRowAlignment() and setColumnAlignment()
     75    respectively.  By default, items are aligned to the top left.
     76
     77
    6778    \sa QGraphicsLinearLayout, QGraphicsWidget
    6879*/
     
    95106};
    96107
     108Q_GLOBAL_STATIC(QWidget, globalStyleInfoWidget);
     109
    97110QLayoutStyleInfo QGraphicsGridLayoutPrivate::styleInfo() const
    98111{
    99     static QWidget *wid = 0;
    100     if (!wid)
    101         wid = new QWidget;
    102112    QGraphicsItem *item = parentItem();
    103113    QStyle *style = (item && item->isWidget()) ? static_cast<QGraphicsWidget*>(item)->style() : QApplication::style();
    104     return QLayoutStyleInfo(style, wid);
     114    return QLayoutStyleInfo(style, globalStyleInfoWidget());
    105115}
    106116
     
    573583            layoutItem->setParentLayoutItem(0);
    574584        d->engine.removeItem(gridItem);
     585
     586        // recalculate rowInfo.count if we remove an item that is on the right/bottommost row
     587        for (int j = 0; j < NOrientations; ++j) {
     588            // 0: Hor, 1: Ver
     589            const Qt::Orientation orient = (j == 0 ? Qt::Horizontal : Qt::Vertical);
     590            const int oldCount = d->engine.rowCount(orient);
     591            if (gridItem->lastRow(orient) == oldCount - 1) {
     592                const int newCount = d->engine.effectiveLastRow(orient) + 1;
     593                d->engine.removeRows(newCount, oldCount - newCount, orient);
     594            }
     595        }
     596
    575597        delete gridItem;
    576598        invalidate();
     
    631653    qreal left, top, right, bottom;
    632654    getContentsMargins(&left, &top, &right, &bottom);
    633     return d->engine.sizeHint(d->styleInfo(), which , constraint) + QSizeF(left + right, top + bottom);
     655    const QSizeF extraMargins(left + right, top + bottom);
     656    return d->engine.sizeHint(d->styleInfo(), which , constraint - extraMargins) + extraMargins;
    634657}
    635658
  • trunk/src/gui/graphicsview/qgraphicsgridlayout.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/graphicsview/qgraphicsitem.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5151    This includes defining the item's geometry, collision detection, its
    5252    painting implementation and item interaction through its event handlers.
    53     QGraphicsItem is part of \l{The Graphics View Framework}
     53    QGraphicsItem is part of the \l{Graphics View Framework}
    5454
    5555    \image graphicsview-items.png
     
    134134    \img graphicsview-parentchild.png
    135135
    136     \section1 Transformation
     136    \target Transformations
     137    \section1 Transformations
    137138
    138139    QGraphicsItem supports projective transformations in addition to its base
     
    265266    user's convenience.
    266267
    267     \sa QGraphicsScene, QGraphicsView, {The Graphics View Framework}
     268    \sa QGraphicsScene, QGraphicsView, {Graphics View Framework}
    268269*/
    269270
     
    382383    \value ItemSendsGeometryChanges The item enables itemChange()
    383384    notifications for ItemPositionChange, ItemPositionHasChanged,
    384     ItemMatrixChange, ItemTransformChange, and ItemTransformHasChanged. For
     385    ItemMatrixChange, ItemTransformChange, ItemTransformHasChanged,
     386    ItemRotationChange, ItemRotationHasChanged, ItemScaleChange, ItemScaleHasChanged,
     387    ItemTransformOriginPointChange, and ItemTransformOriginPointHasChanged. For
    385388    performance reasons, these notifications are disabled by default. You must
    386389    enable this flag to receive notifications for position and transform
     
    410413    to receive notifications for scene position changes. This flag was
    411414    introduced in Qt 4.6.
     415
     416    \omitvalue ItemStopsClickFocusPropagation \omit The item stops propagating
     417    click focus to items underneath when being clicked on. This flag
     418    allows you create a non-focusable item that can be clicked on without
     419    changing the focus. \endomit
    412420*/
    413421
     
    475483    (same as transform()), and QGraphicsItem ignores the return value for this
    476484    notification (i.e., a read-only notification).
     485
     486    \value ItemRotationChange The item's rotation property changes. This
     487    notification is sent if the ItemSendsGeometryChanges flag is enabled, and
     488    when the item's rotation property changes (i.e., as a result of calling
     489    setRotation()). The value argument is the new rotation (i.e., a double);
     490    to get the old rotation, call rotation(). Do not call setRotation() in
     491    itemChange() as this notification is delivered; instead, you can return
     492    the new rotation from itemChange().
     493
     494    \value ItemRotationHasChanged The item's rotation property has changed.
     495    This notification is sent if the ItemSendsGeometryChanges flag is enabled,
     496    and after the item's rotation property has changed. The value argument is
     497    the new rotation (i.e., a double), and QGraphicsItem ignores the return
     498    value for this notification (i.e., a read-only notification). Do not call
     499    setRotation() in itemChange() as this notification is delivered.
     500
     501    \value ItemScaleChange The item's scale property changes. This notification
     502    is sent if the ItemSendsGeometryChanges flag is enabled, and when the item's
     503    scale property changes (i.e., as a result of calling setScale()). The value
     504    argument is the new scale (i.e., a double); to get the old scale, call
     505    scale(). Do not call setScale() in itemChange() as this notification is
     506    delivered; instead, you can return the new scale from itemChange().
     507
     508    \value ItemScaleHasChanged The item's scale property has changed. This
     509    notification is sent if the ItemSendsGeometryChanges flag is enabled, and
     510    after the item's scale property has changed. The value argument is the new
     511    scale (i.e., a double), and QGraphicsItem ignores the return value for this
     512    notification (i.e., a read-only notification). Do not call setScale() in
     513    itemChange() as this notification is delivered.
     514
     515    \value ItemTransformOriginPointChange The item's transform origin point
     516    property changes. This notification is sent if the ItemSendsGeometryChanges
     517    flag is enabled, and when the item's transform origin point property changes
     518    (i.e., as a result of calling setTransformOriginPoint()). The value argument
     519    is the new origin point (i.e., a QPointF); to get the old origin point, call
     520    transformOriginPoint(). Do not call setTransformOriginPoint() in itemChange()
     521    as this notification is delivered; instead, you can return the new transform
     522    origin point from itemChange().
     523
     524    \value ItemTransformOriginPointHasChanged The item's transform origin point
     525    property has changed. This notification is sent if the ItemSendsGeometryChanges
     526    flag is enabled, and after the item's transform origin point property has
     527    changed. The value argument is the new origin point (i.e., a QPointF), and
     528    QGraphicsItem ignores the return value for this notification (i.e., a read-only
     529    notification). Do not call setTransformOriginPoint() in itemChange() as this
     530    notification is delivered.
    477531
    478532    \value ItemSelectedChange The item's selected state changes. If the item is
     
    674728#include <QtCore/qvariant.h>
    675729#include <QtCore/qvarlengtharray.h>
     730#include <QtCore/qnumeric.h>
    676731#include <QtGui/qapplication.h>
    677732#include <QtGui/qbitmap.h>
     
    683738#include <QtGui/qinputcontext.h>
    684739#include <QtGui/qgraphicseffect.h>
     740#ifndef QT_NO_ACCESSIBILITY
     741# include "qaccessible.h"
     742#endif
    685743
    686744#include <private/qgraphicsitem_p.h>
     
    690748#include <private/qtextengine_p.h>
    691749#include <private/qwidget_p.h>
     750#include <private/qapplication_p.h>
    692751
    693752#ifdef Q_WS_X11
     
    10381097        return;
    10391098
     1099    if (isWidget)
     1100        static_cast<QGraphicsWidgetPrivate *>(this)->fixFocusChainBeforeReparenting((newParent &&
     1101                                                        newParent->isWidget()) ? static_cast<QGraphicsWidget *>(newParent) : 0,
     1102                                                        scene);
    10401103    if (scene) {
    10411104        // Deliver the change to the index
     
    10881151                parentFocusScopeItem = fsi;
    10891152                p->d_ptr->focusScopeItem = 0;
     1153                fsi->d_ptr->focusScopeItemChange(false);
    10901154            }
    10911155            break;
     
    11201184            if (p->d_ptr->flags & QGraphicsItem::ItemIsFocusScope) {
    11211185                p->d_ptr->focusScopeItem = newFocusScopeItem;
     1186                newFocusScopeItem->d_ptr->focusScopeItemChange(true);
    11221187                // Ensure the new item is no longer the subFocusItem. The
    11231188                // only way to set focus on a child of a focus scope is
     
    11851250
    11861251    dirtySceneTransform = 1;
     1252    if (!inDestructor && (transformData || (newParent && newParent->d_ptr->transformData)))
     1253        transformChanged();
    11871254
    11881255    // Restore the sub focus chain.
     
    12061273    Returns the bounding rect of this item's children (excluding itself).
    12071274*/
    1208 void QGraphicsItemPrivate::childrenBoundingRectHelper(QTransform *x, QRectF *rect)
    1209 {
     1275void QGraphicsItemPrivate::childrenBoundingRectHelper(QTransform *x, QRectF *rect, QGraphicsItem *topMostEffectItem)
     1276{
     1277    Q_Q(QGraphicsItem);
     1278
     1279    QRectF childrenRect;
     1280    QRectF *result = rect;
     1281    rect = &childrenRect;
     1282    const bool setTopMostEffectItem = !topMostEffectItem;
     1283
    12101284    for (int i = 0; i < children.size(); ++i) {
    12111285        QGraphicsItem *child = children.at(i);
    12121286        QGraphicsItemPrivate *childd = child->d_ptr.data();
     1287        if (setTopMostEffectItem)
     1288            topMostEffectItem = child;
    12131289        bool hasPos = !childd->pos.isNull();
    12141290        if (hasPos || childd->transformData) {
     
    12171293            if (x)
    12181294                matrix *= *x;
    1219             *rect |= matrix.mapRect(child->boundingRect());
     1295            *rect |= matrix.mapRect(child->d_ptr->effectiveBoundingRect(topMostEffectItem));
    12201296            if (!childd->children.isEmpty())
    1221                 childd->childrenBoundingRectHelper(&matrix, rect);
     1297                childd->childrenBoundingRectHelper(&matrix, rect, topMostEffectItem);
    12221298        } else {
    12231299            if (x)
    1224                 *rect |= x->mapRect(child->boundingRect());
     1300                *rect |= x->mapRect(child->d_ptr->effectiveBoundingRect(topMostEffectItem));
    12251301            else
    1226                 *rect |= child->boundingRect();
     1302                *rect |= child->d_ptr->effectiveBoundingRect(topMostEffectItem);
    12271303            if (!childd->children.isEmpty())
    1228                 childd->childrenBoundingRectHelper(x, rect);
     1304                childd->childrenBoundingRectHelper(x, rect, topMostEffectItem);
    12291305        }
    12301306    }
     1307
     1308    if (flags & QGraphicsItem::ItemClipsChildrenToShape){
     1309        if (x)
     1310            *rect &= x->mapRect(q->boundingRect());
     1311        else
     1312            *rect &= q->boundingRect();
     1313    }
     1314
     1315    *result |= *rect;
    12311316}
    12321317
     
    13561441QGraphicsItem::~QGraphicsItem()
    13571442{
    1358     if (d_ptr->isObject)
    1359         QObjectPrivate::get(static_cast<QGraphicsObject *>(this))->wasDeleted = true;
     1443    if (d_ptr->isObject) {
     1444        QGraphicsObject *o = static_cast<QGraphicsObject *>(this);
     1445        QObjectPrivate *p = QObjectPrivate::get(o);
     1446        p->wasDeleted = true;
     1447        if (p->declarativeData) {
     1448            QAbstractDeclarativeData::destroyed(p->declarativeData, o);
     1449            p->declarativeData = 0;
     1450        }
     1451    }
     1452
    13601453    d_ptr->inDestructor = 1;
    13611454    d_ptr->removeExtraItemCache();
     1455
     1456#ifndef QT_NO_GESTURES
     1457    if (d_ptr->isObject && !d_ptr->gestureContext.isEmpty()) {
     1458        QGraphicsObject *o = static_cast<QGraphicsObject *>(this);
     1459        if (QGestureManager *manager = QGestureManager::instance()) {
     1460            foreach (Qt::GestureType type, d_ptr->gestureContext.keys())
     1461                manager->cleanupCachedGestures(o, type);
     1462        }
     1463    }
     1464#endif
    13621465
    13631466    clearFocus();
     
    17341837void QGraphicsItem::setFlags(GraphicsItemFlags flags)
    17351838{
    1736     if (isWindow())
    1737         flags |= ItemIsPanel;
    1738 
    17391839    // Notify change and check for adjustment.
    17401840    if (quint32(d_ptr->flags) == quint32(flags))
     
    17501850    bool fullUpdate = (quint32(flags) & geomChangeFlagsMask) != (d_ptr->flags & geomChangeFlagsMask);
    17511851    if (fullUpdate)
    1752         d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
     1852        d_ptr->updatePaintedViewBoundingRects(/*children=*/true);
    17531853
    17541854    // Keep the old flags to compare the diff.
     
    17741874        // all children.
    17751875        d_ptr->updateAncestorFlag(ItemClipsChildrenToShape);
     1876        // The childrenBoundingRect is clipped to the boundingRect in case of ItemClipsChildrenToShape,
     1877        // which means we have to invalidate the cached childrenBoundingRect whenever this flag changes.
     1878        d_ptr->dirtyChildrenBoundingRect = 1;
     1879        d_ptr->markParentDirty(true);
    17761880    }
    17771881
     
    20222126    \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 2
    20232127
    2024     If no cursor has been set, the parent's cursor is used.
     2128    If no cursor has been set, the cursor of the item beneath is used.
    20252129
    20262130    \sa setCursor(), hasCursor(), unsetCursor(), QWidget::cursor,
     
    22622366                            fsi = fsi->d_ptr->focusScopeItem;
    22632367                        fsi->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ true,
    2264                                                    /* focusFromShow = */ true);
     2368                                                   /* focusFromHide = */ false);
    22652369                    }
    22662370                    break;
     
    22722376                if (fi && fi != scene->focusItem()) {
    22732377                    scene->setFocusItem(fi);
     2378                } else if (flags & QGraphicsItem::ItemIsFocusScope &&
     2379                           !scene->focusItem() &&
     2380                           q->isAncestorOf(scene->d_func()->lastFocusItem)) {
     2381                    q_ptr->setFocus();
    22742382                }
    22752383            }
     
    22822390                        if (p->d_ptr->visible) {
    22832391                            p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ true,
    2284                                                      /* focusFromShow = */ true);
     2392                                                     /* focusFromHide = */ true);
    22852393                        }
    22862394                        break;
     
    27042812    QGraphicsEffect *effect = graphicsEffect;
    27052813    if (scene && effect && effect->isEnabled()) {
     2814        if (scene->d_func()->views.isEmpty())
     2815            return effect->boundingRectFor(rect);
    27062816        QRectF sceneRect = q->mapRectToScene(rect);
    27072817        QRectF sceneEffectRect;
     
    27272837    \sa boundingRect()
    27282838*/
    2729 QRectF QGraphicsItemPrivate::effectiveBoundingRect() const
     2839QRectF QGraphicsItemPrivate::effectiveBoundingRect(QGraphicsItem *topMostEffectItem) const
    27302840{
    27312841#ifndef QT_NO_GRAPHICSEFFECT
    27322842    Q_Q(const QGraphicsItem);
    27332843    QRectF brect = effectiveBoundingRect(q_ptr->boundingRect());
    2734     if (ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
     2844    if (ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren || topMostEffectItem == q)
    27352845        return brect;
    27362846
     
    27432853            brect = effectParent->mapRectToItem(q, effectRectInParentSpace);
    27442854        }
    2745         if (effectParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
     2855        if (effectParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren
     2856            || topMostEffectItem == effectParent) {
    27462857            return brect;
     2858        }
    27472859        effectParent = effectParent->d_ptr->parent;
    27482860    }
     
    31383250void QGraphicsItem::setFocus(Qt::FocusReason focusReason)
    31393251{
    3140     d_ptr->setFocusHelper(focusReason, /* climb = */ true, /* focusFromShow = */ false);
     3252    d_ptr->setFocusHelper(focusReason, /* climb = */ true, /* focusFromHide = */ false);
    31413253}
    31423254
     
    31443256    \internal
    31453257*/
    3146 void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool climb, bool focusFromShow)
     3258void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool climb, bool focusFromHide)
    31473259{
    31483260    // Disabled / unfocusable items cannot accept focus.
     
    31633275    while (p) {
    31643276        if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
     3277            QGraphicsItem *oldFocusScopeItem = p->d_ptr->focusScopeItem;
    31653278            p->d_ptr->focusScopeItem = q_ptr;
    3166             if (!p->focusItem() && !focusFromShow) {
     3279            if (!p->focusItem() && !focusFromHide) {
     3280                if (oldFocusScopeItem)
     3281                    oldFocusScopeItem->d_ptr->focusScopeItemChange(false);
     3282                focusScopeItemChange(true);
    31673283                // If you call setFocus on a child of a focus scope that
    31683284                // doesn't currently have a focus item, then stop.
     
    31803296
    31813297    // Update the child focus chain.
    3182     f->d_ptr->setSubFocus();
     3298    QGraphicsItem *commonAncestor = 0;
     3299    if (scene && scene->focusItem()) {
     3300        commonAncestor = scene->focusItem()->commonAncestorItem(f);
     3301        scene->focusItem()->d_ptr->clearSubFocus(scene->focusItem(), commonAncestor);
     3302    }
     3303
     3304    f->d_ptr->setSubFocus(f, commonAncestor);
    31833305
    31843306    // Update the scene's focus item.
     
    32193341            while (p) {
    32203342                if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
    3221                     p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ false,
    3222                                              /* focusFromShow = */ false);
     3343                    if (p->d_ptr->focusScopeItem == q_ptr) {
     3344                        p->d_ptr->focusScopeItem = 0;
     3345                        if (!q_ptr->hasFocus()) //if it has focus, focusScopeItemChange is called elsewhere
     3346                            focusScopeItemChange(false);
     3347                    }
     3348                    if (q_ptr->hasFocus())
     3349                        p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ false,
     3350                                                 /* focusFromHide = */ false);
    32233351                    return;
    32243352                }
     
    32283356    }
    32293357
    3230     // Invisible items with focus must explicitly clear subfocus.
    3231     clearSubFocus(q_ptr);
    3232 
    32333358    if (q_ptr->hasFocus()) {
     3359        // Invisible items with focus must explicitly clear subfocus.
     3360        clearSubFocus(q_ptr);
     3361
    32343362        // If this item has the scene's input focus, clear it.
    32353363        scene->setFocusItem(0);
     
    34853613        return;
    34863614
    3487     d_ptr->setPosHelper(QPointF(x, d_ptr->pos.y()));
     3615    if (qIsNaN(x))
     3616        return;
     3617
     3618    setPos(QPointF(x, d_ptr->pos.y()));
    34883619}
    34893620
     
    35093640        return;
    35103641
    3511     d_ptr->setPosHelper(QPointF(d_ptr->pos.x(), y));
     3642    if (qIsNaN(y))
     3643        return;
     3644
     3645    setPos(QPointF(d_ptr->pos.x(), y));
    35123646}
    35133647
     
    35563690    transformData->transform = transform;
    35573691    dirtySceneTransform = 1;
     3692    transformChanged();
    35583693}
    35593694
     
    35773712
    35783713    // Update and repositition.
    3579     if (!(d_ptr->flags & ItemSendsGeometryChanges)) {
     3714    if (!(d_ptr->flags & (ItemSendsGeometryChanges | ItemSendsScenePositionChanges))) {
    35803715        d_ptr->setPosHelper(pos);
    35813716        if (d_ptr->isWidget)
    35823717            static_cast<QGraphicsWidget *>(this)->d_func()->setGeometryFromSetPos();
     3718        if (d_ptr->scenePosDescendants)
     3719            d_ptr->sendScenePosChange();
    35833720        return;
    35843721    }
     
    37243861{
    37253862    prepareGeometryChange();
     3863    qreal newRotation = angle;
     3864
     3865    if (d_ptr->flags & ItemSendsGeometryChanges) {
     3866        // Notify the item that the rotation is changing.
     3867        const QVariant newRotationVariant(itemChange(ItemRotationChange, angle));
     3868        newRotation = newRotationVariant.toReal();
     3869    }
     3870
    37263871    if (!d_ptr->transformData)
    37273872        d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
    3728     d_ptr->transformData->rotation = angle;
     3873
     3874    if (d_ptr->transformData->rotation == newRotation)
     3875        return;
     3876
     3877    d_ptr->transformData->rotation = newRotation;
    37293878    d_ptr->transformData->onlyTransform = false;
    37303879    d_ptr->dirtySceneTransform = 1;
    37313880
     3881    // Send post-notification.
     3882    if (d_ptr->flags & ItemSendsGeometryChanges)
     3883        itemChange(ItemRotationHasChanged, newRotation);
     3884
    37323885    if (d_ptr->isObject)
    37333886        emit static_cast<QGraphicsObject *>(this)->rotationChanged();
     3887
     3888    d_ptr->transformChanged();
    37343889}
    37353890
     
    37673922    transformations() to map the item's coordinate system to the parent item.
    37683923
    3769     \sa scale(), setTransformOriginPoint(), {Transformations}
     3924    \sa scale(), setTransformOriginPoint(), {Transformations Example}
    37703925*/
    37713926void QGraphicsItem::setScale(qreal factor)
    37723927{
    37733928    prepareGeometryChange();
     3929    qreal newScale = factor;
     3930
     3931    if (d_ptr->flags & ItemSendsGeometryChanges) {
     3932        // Notify the item that the scale is changing.
     3933        const QVariant newScaleVariant(itemChange(ItemScaleChange, factor));
     3934        newScale = newScaleVariant.toReal();
     3935    }
     3936
    37743937    if (!d_ptr->transformData)
    37753938        d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
    3776     d_ptr->transformData->scale = factor;
     3939
     3940    if (d_ptr->transformData->scale == newScale)
     3941        return;
     3942
     3943    d_ptr->transformData->scale = newScale;
    37773944    d_ptr->transformData->onlyTransform = false;
    37783945    d_ptr->dirtySceneTransform = 1;
    37793946
     3947    // Send post-notification.
     3948    if (d_ptr->flags & ItemSendsGeometryChanges)
     3949        itemChange(ItemScaleHasChanged, newScale);
     3950
    37803951    if (d_ptr->isObject)
    37813952        emit static_cast<QGraphicsObject *>(this)->scaleChanged();
     3953
     3954    d_ptr->transformChanged();
    37823955}
    37833956
     
    37893962
    37903963    QGraphicsTransform is for applying and controlling a chain of individual
    3791     transformation operations on an item. It's particularily useful in
     3964    transformation operations on an item. It's particularly useful in
    37923965    animations, where each transform operation needs to be interpolated
    37933966    independently, or differently.
     
    38163989
    38173990    QGraphicsTransform is for applying and controlling a chain of individual
    3818     transformation operations on an item. It's particularily useful in
     3991    transformation operations on an item. It's particularly useful in
    38193992    animations, where each transform operation needs to be interpolated
    38203993    independently, or differently.
     
    38354008    d_ptr->transformData->onlyTransform = false;
    38364009    d_ptr->dirtySceneTransform = 1;
     4010    d_ptr->transformChanged();
     4011}
     4012
     4013/*!
     4014    \internal
     4015*/
     4016void QGraphicsItemPrivate::prependGraphicsTransform(QGraphicsTransform *t)
     4017{
     4018    if (!transformData)
     4019        transformData = new QGraphicsItemPrivate::TransformData;
     4020    if (!transformData->graphicsTransforms.contains(t))
     4021        transformData->graphicsTransforms.prepend(t);
     4022
     4023    Q_Q(QGraphicsItem);
     4024    t->d_func()->setItem(q);
     4025    transformData->onlyTransform = false;
     4026    dirtySceneTransform = 1;
     4027    transformChanged();
    38374028}
    38384029
     
    38514042    transformData->onlyTransform = false;
    38524043    dirtySceneTransform = 1;
     4044    transformChanged();
    38534045}
    38544046
     
    38794071{
    38804072    prepareGeometryChange();
     4073    QPointF newOrigin = origin;
     4074
     4075    if (d_ptr->flags & ItemSendsGeometryChanges) {
     4076        // Notify the item that the origin point is changing.
     4077        const QVariant newOriginVariant(itemChange(ItemTransformOriginPointChange,
     4078                                                   qVariantFromValue<QPointF>(origin)));
     4079        newOrigin = newOriginVariant.toPointF();
     4080    }
     4081
    38814082    if (!d_ptr->transformData)
    38824083        d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
    3883     d_ptr->transformData->xOrigin = origin.x();
    3884     d_ptr->transformData->yOrigin = origin.y();
     4084
     4085    if (d_ptr->transformData->xOrigin == newOrigin.x()
     4086        && d_ptr->transformData->yOrigin == newOrigin.y()) {
     4087        return;
     4088    }
     4089
     4090    d_ptr->transformData->xOrigin = newOrigin.x();
     4091    d_ptr->transformData->yOrigin = newOrigin.y();
    38854092    d_ptr->transformData->onlyTransform = false;
    38864093    d_ptr->dirtySceneTransform = 1;
     4094
     4095    // Send post-notification.
     4096    if (d_ptr->flags & ItemSendsGeometryChanges)
     4097        itemChange(ItemTransformOriginPointHasChanged, qVariantFromValue<QPointF>(newOrigin));
    38874098}
    38884099
     
    41894400
    41904401    // Update and set the new transformation.
    4191     if (!(d_ptr->flags & ItemSendsGeometryChanges)) {
     4402    if (!(d_ptr->flags & (ItemSendsGeometryChanges | ItemSendsScenePositionChanges))) {
    41924403        d_ptr->setTransformHelper(newTransform);
     4404        if (d_ptr->scenePosDescendants)
     4405            d_ptr->sendScenePosChange();
    41934406        return;
    41944407    }
     
    45314744
    45324745    d_ptr->childrenBoundingRect = QRectF();
    4533     d_ptr->childrenBoundingRectHelper(0, &d_ptr->childrenBoundingRect);
     4746    d_ptr->childrenBoundingRectHelper(0, &d_ptr->childrenBoundingRect, 0);
    45344747    d_ptr->dirtyChildrenBoundingRect = 0;
    45354748    return d_ptr->childrenBoundingRect;
     
    49725185    contents. Although it's expensive to calculate, it's also more precise
    49735186    than boundingRect(), and it can help to avoid unnecessary repainting when
    4974     an item is updated. This is particularily efficient for thin items (e.g.,
     5187    an item is updated. This is particularly efficient for thin items (e.g.,
    49755188    lines or simple polygons). You can tune the granularity for the bounding
    49765189    region by calling setBoundingRegionGranularity(). The default granularity
     
    52285441    child->d_ptr->siblingIndex = children.size();
    52295442    children.append(child);
     5443    if (isObject)
     5444        emit static_cast<QGraphicsObject *>(q_ptr)->childrenChanged();
    52305445}
    52315446
     
    52505465    // (see ensureSortedChildren()).
    52515466    child->d_ptr->siblingIndex = -1;
     5467    if (isObject)
     5468        emit static_cast<QGraphicsObject *>(q_ptr)->childrenChanged();
    52525469}
    52535470
     
    52855502    }
    52865503    unsetExtra(ExtraCacheData);
     5504}
     5505
     5506void QGraphicsItemPrivate::updatePaintedViewBoundingRects(bool updateChildren)
     5507{
     5508    if (!scene)
     5509        return;
     5510
     5511    for (int i = 0; i < scene->d_func()->views.size(); ++i) {
     5512        QGraphicsViewPrivate *viewPrivate = scene->d_func()->views.at(i)->d_func();
     5513        QRect rect = paintedViewBoundingRects.value(viewPrivate->viewport);
     5514        rect.translate(viewPrivate->dirtyScrollOffset);
     5515        viewPrivate->updateRect(rect);
     5516    }
     5517
     5518    if (updateChildren) {
     5519        for (int i = 0; i < children.size(); ++i)
     5520            children.at(i)->d_ptr->updatePaintedViewBoundingRects(true);
     5521    }
    52875522}
    52885523
     
    53245559    \internal
    53255560*/
    5326 void QGraphicsItemPrivate::setSubFocus(QGraphicsItem *rootItem)
     5561void QGraphicsItemPrivate::setSubFocus(QGraphicsItem *rootItem, QGraphicsItem *stopItem)
    53275562{
    53285563    // Update focus child chain. Stop at panels, or if this item
    53295564    // is hidden, stop at the first item with a visible parent.
    53305565    QGraphicsItem *parent = rootItem ? rootItem : q_ptr;
     5566    if (parent->panel() != q_ptr->panel())
     5567        return;
     5568
    53315569    do {
    53325570        // Clear any existing ancestor's subFocusItem.
     
    53345572            if (parent->d_ptr->subFocusItem == q_ptr)
    53355573                break;
    5336             parent->d_ptr->subFocusItem->d_ptr->clearSubFocus();
     5574            parent->d_ptr->subFocusItem->d_ptr->clearSubFocus(0, stopItem);
    53375575        }
    53385576        parent->d_ptr->subFocusItem = q_ptr;
     
    53475585    \internal
    53485586*/
    5349 void QGraphicsItemPrivate::clearSubFocus(QGraphicsItem *rootItem)
     5587void QGraphicsItemPrivate::clearSubFocus(QGraphicsItem *rootItem, QGraphicsItem *stopItem)
    53505588{
    53515589    // Reset sub focus chain.
     
    53555593            break;
    53565594        parent->d_ptr->subFocusItem = 0;
    5357         parent->d_ptr->subFocusItemChange();
     5595        if (parent != stopItem && !parent->isAncestorOf(stopItem))
     5596            parent->d_ptr->subFocusItemChange();
    53585597    } while (!parent->isPanel() && (parent = parent->d_ptr->parent));
    53595598}
     
    53805619void QGraphicsItemPrivate::subFocusItemChange()
    53815620{
     5621}
     5622
     5623/*!
     5624    \internal
     5625
     5626    Subclasses can reimplement this function to be notified when an item
     5627    becomes a focusScopeItem (or is no longer a focusScopeItem).
     5628*/
     5629void QGraphicsItemPrivate::focusScopeItemChange(bool isSubFocusItem)
     5630{
     5631    Q_UNUSED(isSubFocusItem);
    53825632}
    53835633
     
    54465696    }
    54475697
    5448     if (d_ptr->discardUpdateRequest())
    5449         return;
    5450 
    54515698    if (d_ptr->scene)
    54525699        d_ptr->scene->d_func()->markDirty(this, rect);
     
    54705717    is equivalent to calling update(\a rect).
    54715718
     5719    \bold{Note:} Scrolling is only supported when QGraphicsItem::ItemCoordinateCache
     5720    is enabled; in all other cases calling this function is equivalent to calling
     5721    update(\a rect). If you for sure know that the item is opaque and not overlapped
     5722    by other items, you can map the \a rect to viewport coordinates and scroll the
     5723    viewport.
     5724
     5725    \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 19
     5726
    54725727    \sa boundingRect()
    54735728*/
     
    54795734    if (!d->scene)
    54805735        return;
    5481     if (d->cacheMode != NoCache) {
    5482         QGraphicsItemCache *c;
    5483         bool scrollCache = qFuzzyIsNull(dx - int(dx)) && qFuzzyIsNull(dy - int(dy))
    5484                            && (c = (QGraphicsItemCache *)qVariantValue<void *>(d_ptr->extra(QGraphicsItemPrivate::ExtraCacheData)))
    5485                            && (d->cacheMode == ItemCoordinateCache && !c->fixedSize.isValid());
    5486         if (scrollCache) {
    5487             QPixmap pix;
    5488             if (QPixmapCache::find(c->key, &pix)) {
    5489                 // Adjust with 2 pixel margin. Notice the loss of precision
    5490                 // when converting to QRect.
    5491                 int adjust = 2;
    5492                 QRectF br = boundingRect().adjusted(-adjust, -adjust, adjust, adjust);
    5493                 QRect irect = rect.toRect().translated(-br.x(), -br.y());
    5494 
    5495                 pix.scroll(dx, dy, irect);
    5496 
    5497                 QPixmapCache::replace(c->key, pix);
    5498 
    5499                 // Translate the existing expose.
    5500                 foreach (QRectF exposedRect, c->exposed)
    5501                     c->exposed += exposedRect.translated(dx, dy) & rect;
    5502 
    5503                 // Calculate exposure.
    5504                 QRegion exposed;
    5505                 QRect r = rect.toRect();
    5506                 exposed += r;
    5507                 exposed -= r.translated(dx, dy);
    5508                 foreach (QRect rect, exposed.rects())
    5509                     update(rect);
    5510                 d->scene->d_func()->markDirty(this);
    5511             } else {
    5512                 update(rect);
    5513             }
    5514         } else {
    5515             // ### This is very slow, and can be done much better. If the cache is
    5516             // local and matches the below criteria for rotation and scaling, we
    5517             // can easily scroll. And if the cache is in device coordinates, we
    5518             // can scroll both the viewport and the cache.
    5519             update(rect);
    5520         }
     5736
     5737    // Accelerated scrolling means moving pixels from one location to another
     5738    // and only redraw the newly exposed area. The following requirements must
     5739    // be fulfilled in order to do that:
     5740    //
     5741    // 1) Item is opaque.
     5742    // 2) Item is not overlapped by other items.
     5743    //
     5744    // There's (yet) no way to detect whether an item is opaque or not, which means
     5745    // we cannot do accelerated scrolling unless the cache is enabled. In case of using
     5746    // DeviceCoordinate cache we also have to take the device transform into account in
     5747    // order to determine whether we can do accelerated scrolling or not. That's left out
     5748    // for simplicity here, but it is definitely something we can consider in the future
     5749    // as a performance improvement.
     5750    if (d->cacheMode != QGraphicsItem::ItemCoordinateCache
     5751        || !qFuzzyIsNull(dx - int(dx)) || !qFuzzyIsNull(dy - int(dy))) {
     5752        update(rect);
    55215753        return;
    55225754    }
    55235755
    5524     QRectF scrollRect = !rect.isNull() ? rect : boundingRect();
    5525     int couldntScroll = d->scene->views().size();
    5526     foreach (QGraphicsView *view, d->scene->views()) {
    5527         if (view->viewport()->inherits("QGLWidget")) {
    5528             // ### Please replace with a widget attribute; any widget that
    5529             // doesn't support partial updates / doesn't support scrolling
    5530             // should be skipped in this code. Qt::WA_NoPartialUpdates or so.
     5756    QGraphicsItemCache *cache = d->extraItemCache();
     5757    if (cache->allExposed || cache->fixedSize.isValid()) {
     5758        // Cache is either invalidated or item is scaled (see QGraphicsItem::setCacheMode).
     5759        update(rect);
     5760        return;
     5761    }
     5762
     5763    // Find pixmap in cache.
     5764    QPixmap cachedPixmap;
     5765    if (!QPixmapCache::find(cache->key, &cachedPixmap)) {
     5766        update(rect);
     5767        return;
     5768    }
     5769
     5770    QRect scrollRect = (rect.isNull() ? boundingRect() : rect).toAlignedRect();
     5771    if (!scrollRect.intersects(cache->boundingRect))
     5772        return; // Nothing to scroll.
     5773
     5774    // Remove from cache to avoid deep copy when modifying.
     5775    QPixmapCache::remove(cache->key);
     5776
     5777    QRegion exposed;
     5778    cachedPixmap.scroll(dx, dy, scrollRect.translated(-cache->boundingRect.topLeft()), &exposed);
     5779
     5780    // Reinsert into cache.
     5781    cache->key = QPixmapCache::insert(cachedPixmap);
     5782
     5783    // Translate the existing expose.
     5784    for (int i = 0; i < cache->exposed.size(); ++i) {
     5785        QRectF &e = cache->exposed[i];
     5786        if (!rect.isNull() && !e.intersects(rect))
    55315787            continue;
    5532         }
    5533 
    5534         static const QLineF up(0, 0, 0, -1);
    5535         static const QLineF down(0, 0, 0, 1);
    5536         static const QLineF left(0, 0, -1, 0);
    5537         static const QLineF right(0, 0, 1, 0);
    5538 
    5539         QTransform deviceTr = deviceTransform(view->viewportTransform());
    5540         QRect deviceScrollRect = deviceTr.mapRect(scrollRect).toRect();
    5541         QLineF v1 = deviceTr.map(right);
    5542         QLineF v2 = deviceTr.map(down);
    5543         QLineF u1 = v1.unitVector(); u1.translate(-v1.p1());
    5544         QLineF u2 = v2.unitVector(); u2.translate(-v2.p1());
    5545         bool noScroll = false;
    5546 
    5547         // Check if the delta resolves to ints in device space.
    5548         QPointF deviceDelta = deviceTr.map(QPointF(dx, dy));
    5549         if ((deviceDelta.x() - int(deviceDelta.x()))
    5550             || (deviceDelta.y() - int(deviceDelta.y()))) {
    5551             noScroll = true;
    5552         } else {
    5553             // Check if the unit vectors have no fraction in device space.
    5554             qreal v1l = v1.length();
    5555             if (v1l - int(v1l)) {
    5556                 noScroll = true;
    5557             } else {
    5558                 dx *= v1.length();
    5559             }
    5560             qreal v2l = v2.length();
    5561             if (v2l - int(v2l)) {
    5562                 noScroll = true;
    5563             } else {
    5564                 dy *= v2.length();
    5565             }
    5566         }
    5567 
    5568         if (!noScroll) {
    5569             if (u1 == right) {
    5570                 if (u2 == up) {
    5571                     // flipped
    5572                     dy = -dy;
    5573                 } else if (u2 == down) {
    5574                     // normal
    5575                 } else {
    5576                     noScroll = true;
    5577                 }
    5578             } else if (u1 == left) {
    5579                 if (u2 == up) {
    5580                     // mirrored & flipped / rotated 180 degrees
    5581                     dx = -dx;
    5582                     dy = -dy;
    5583                 } else if (u2 == down) {
    5584                     // mirrored
    5585                     dx = -dx;
    5586                 } else {
    5587                     noScroll = true;
    5588                 }
    5589             } else if (u1 == up) {
    5590                 if (u2 == left) {
    5591                     // rotated -90 & mirrored
    5592                     qreal tmp = dy;
    5593                     dy = -dx;
    5594                     dx = -tmp;
    5595                 } else if (u2 == right) {
    5596                     // rotated -90
    5597                     qreal tmp = dy;
    5598                     dy = -dx;
    5599                     dx = tmp;
    5600                 } else {
    5601                     noScroll = true;
    5602                 }
    5603             } else if (u1 == down) {
    5604                 if (u2 == left) {
    5605                     // rotated 90
    5606                     qreal tmp = dy;
    5607                     dy = dx;
    5608                     dx = -tmp;
    5609                 } else if (u2 == right) {
    5610                     // rotated 90 & mirrored
    5611                     qreal tmp = dy;
    5612                     dy = dx;
    5613                     dx = tmp;
    5614                 } else {
    5615                     noScroll = true;
    5616                 }
    5617             }
    5618         }
    5619 
    5620         if (!noScroll) {
    5621             view->viewport()->scroll(int(dx), int(dy), deviceScrollRect);
    5622             --couldntScroll;
    5623         }
    5624     }
    5625     if (couldntScroll)
    5626         update(rect);
     5788        e.translate(dx, dy);
     5789    }
     5790
     5791    // Append newly exposed areas. Note that the exposed region is currently
     5792    // in pixmap coordinates, so we have to translate it to item coordinates.
     5793    exposed.translate(cache->boundingRect.topLeft());
     5794    const QVector<QRect> exposedRects = exposed.rects();
     5795    for (int i = 0; i < exposedRects.size(); ++i)
     5796        cache->exposed += exposedRects.at(i);
     5797
     5798    // Trigger update. This will redraw the newly exposed area and make sure
     5799    // the pixmap is re-blitted in case there are overlapping items.
     5800    d->scene->d_func()->markDirty(this, rect);
    56275801}
    56285802
     
    65006674    }
    65016675
     6676    if (event->type() == QEvent::FocusOut) {
     6677        focusOutEvent(static_cast<QFocusEvent *>(event));
     6678        return true;
     6679    }
     6680
    65026681    if (!d_ptr->visible) {
    65036682        // Eaten
     
    65086687    case QEvent::FocusIn:
    65096688        focusInEvent(static_cast<QFocusEvent *>(event));
    6510         break;
    6511     case QEvent::FocusOut:
    6512         focusOutEvent(static_cast<QFocusEvent *>(event));
    65136689        break;
    65146690    case QEvent::GraphicsSceneContextMenu:
     
    69857161                    // calculate their diff by mapping viewport coordinates
    69867162                    // directly to parent coordinates.
    6987                     QTransform viewToParentTransform = (item->transform().translate(item->d_ptr->pos.x(), item->d_ptr->pos.y()))
     7163                    // COMBINE
     7164                    QTransform itemTransform;
     7165                    if (item->d_ptr->transformData)
     7166                        itemTransform = item->d_ptr->transformData->computedFullTransform();
     7167                    itemTransform.translate(item->d_ptr->pos.x(), item->d_ptr->pos.y());
     7168                    QTransform viewToParentTransform = itemTransform
    69887169                                                       * (item->sceneTransform() * view->viewportTransform()).inverted();
    69897170                    currentParentPos = viewToParentTransform.map(QPointF(view->mapFromGlobal(event->screenPos())));
     
    71797360    Q_D(QGraphicsItem);
    71807361    d->imHints = hints;
     7362    if (!hasFocus())
     7363        return;
     7364    d->scene->d_func()->updateInputMethodSensitivityInViews();
     7365#if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN))
     7366    QWidget *fw = QApplication::focusWidget();
     7367    if (!fw)
     7368        return;
     7369    for (int i = 0 ; i < scene()->views().count() ; ++i)
     7370        if (scene()->views().at(i) == fw)
     7371            if (QInputContext *inputContext = fw->inputContext())
     7372                inputContext->update();
     7373#endif
     7374}
     7375
     7376/*!
     7377    Updates the item's micro focus.
     7378
     7379    \since 4.7
     7380
     7381    \sa QInputContext
     7382*/
     7383void QGraphicsItem::updateMicroFocus()
     7384{
     7385#if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN))
     7386    if (QWidget *fw = QApplication::focusWidget()) {
     7387        if (scene()) {
     7388            for (int i = 0 ; i < scene()->views().count() ; ++i) {
     7389                if (scene()->views().at(i) == fw)
     7390                    if (QInputContext *inputContext = fw->inputContext())
     7391                        inputContext->update();
     7392            }
     7393        }
     7394#ifndef QT_NO_ACCESSIBILITY
     7395        // ##### is this correct
     7396        QAccessible::updateAccessibility(fw, 0, QAccessible::StateChanged);
     7397#endif
     7398    }
     7399#endif
    71817400}
    71827401
     
    74317650}
    74327651
     7652#ifndef QT_NO_GESTURES
    74337653/*!
    74347654    Subscribes the graphics object to the given \a gesture with specific \a flags.
     
    74387658void QGraphicsObject::grabGesture(Qt::GestureType gesture, Qt::GestureFlags flags)
    74397659{
    7440     QGraphicsItemPrivate * const d = QGraphicsItem::d_func();
    7441     d->gestureContext.insert(gesture, flags);
    7442     (void)QGestureManager::instance(); // create a gesture manager
     7660    bool contains = QGraphicsItem::d_ptr->gestureContext.contains(gesture);
     7661    QGraphicsItem::d_ptr->gestureContext.insert(gesture, flags);
     7662    if (!contains && QGraphicsItem::d_ptr->scene)
     7663        QGraphicsItem::d_ptr->scene->d_func()->grabGesture(this, gesture);
    74437664}
    74447665
     
    74507671void QGraphicsObject::ungrabGesture(Qt::GestureType gesture)
    74517672{
    7452     QGraphicsItemPrivate * const d = QGraphicsItem::d_func();
    7453     if (d->gestureContext.remove(gesture)) {
    7454         QGestureManager *manager = QGestureManager::instance();
    7455         manager->cleanupCachedGestures(this, gesture);
    7456     }
    7457 }
     7673    if (QGraphicsItem::d_ptr->gestureContext.remove(gesture) && QGraphicsItem::d_ptr->scene)
     7674        QGraphicsItem::d_ptr->scene->d_func()->ungrabGesture(this, gesture);
     7675}
     7676#endif // QT_NO_GESTURES
     7677
     7678/*!
     7679    Updates the item's micro focus. This is slot for convenience.
     7680
     7681    \since 4.7
     7682
     7683    \sa QInputContext
     7684*/
     7685void QGraphicsObject::updateMicroFocus()
     7686{
     7687    QGraphicsItem::updateMicroFocus();
     7688}
     7689
     7690void QGraphicsItemPrivate::children_append(QDeclarativeListProperty<QGraphicsObject> *list, QGraphicsObject *item)
     7691{
     7692    QGraphicsObject *graphicsObject = static_cast<QGraphicsObject *>(list->object);
     7693    if (QGraphicsItemPrivate::get(graphicsObject)->sendParentChangeNotification) {
     7694        item->setParentItem(graphicsObject);
     7695    } else {
     7696        QGraphicsItemPrivate::get(item)->setParentItemHelper(graphicsObject, 0, 0);
     7697    }
     7698}
     7699
     7700int QGraphicsItemPrivate::children_count(QDeclarativeListProperty<QGraphicsObject> *list)
     7701{
     7702    QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(static_cast<QGraphicsObject *>(list->object));
     7703    return d->children.count();
     7704}
     7705
     7706QGraphicsObject *QGraphicsItemPrivate::children_at(QDeclarativeListProperty<QGraphicsObject> *list, int index)
     7707{
     7708    QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(static_cast<QGraphicsObject *>(list->object));
     7709    if (index >= 0 && index < d->children.count())
     7710        return d->children.at(index)->toGraphicsObject();
     7711    else
     7712        return 0;
     7713}
     7714
     7715void QGraphicsItemPrivate::children_clear(QDeclarativeListProperty<QGraphicsObject> *list)
     7716{
     7717    QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(static_cast<QGraphicsObject *>(list->object));
     7718    int childCount = d->children.count();
     7719    if (d->sendParentChangeNotification) {
     7720        for (int index = 0; index < childCount; index++)
     7721            d->children.at(0)->setParentItem(0);
     7722    } else {
     7723        for (int index = 0; index < childCount; index++)
     7724            QGraphicsItemPrivate::get(d->children.at(0))->setParentItemHelper(0, 0, 0);
     7725    }
     7726}
     7727
     7728/*!
     7729    Returns a list of this item's children.
     7730
     7731    The items are sorted by stacking order. This takes into account both the
     7732    items' insertion order and their Z-values.
     7733
     7734*/
     7735QDeclarativeListProperty<QGraphicsObject> QGraphicsItemPrivate::childrenList()
     7736{
     7737    Q_Q(QGraphicsItem);
     7738    if (isObject) {
     7739        QGraphicsObject *that = static_cast<QGraphicsObject *>(q);
     7740        return QDeclarativeListProperty<QGraphicsObject>(that, &children, children_append,
     7741                                                         children_count, children_at, children_clear);
     7742    } else {
     7743        //QGraphicsItem is not supported for this property
     7744        return QDeclarativeListProperty<QGraphicsObject>();
     7745    }
     7746}
     7747
     7748/*!
     7749  \internal
     7750  Returns the width of the item
     7751  Reimplemented by QGraphicsWidget
     7752*/
     7753qreal QGraphicsItemPrivate::width() const
     7754{
     7755    return 0;
     7756}
     7757
     7758/*!
     7759  \internal
     7760  Set the width of the item
     7761  Reimplemented by QGraphicsWidget
     7762*/
     7763void QGraphicsItemPrivate::setWidth(qreal w)
     7764{
     7765    Q_UNUSED(w);
     7766}
     7767
     7768/*!
     7769  \internal
     7770  Reset the width of the item
     7771  Reimplemented by QGraphicsWidget
     7772*/
     7773void QGraphicsItemPrivate::resetWidth()
     7774{
     7775}
     7776
     7777/*!
     7778  \internal
     7779  Returns the height of the item
     7780  Reimplemented by QGraphicsWidget
     7781*/
     7782qreal QGraphicsItemPrivate::height() const
     7783{
     7784    return 0;
     7785}
     7786
     7787/*!
     7788  \internal
     7789  Set the height of the item
     7790  Reimplemented by QGraphicsWidget
     7791*/
     7792void QGraphicsItemPrivate::setHeight(qreal h)
     7793{
     7794    Q_UNUSED(h);
     7795}
     7796
     7797/*!
     7798  \internal
     7799  Reset the height of the item
     7800  Reimplemented by QGraphicsWidget
     7801*/
     7802void QGraphicsItemPrivate::resetHeight()
     7803{
     7804}
     7805
     7806/*!
     7807    \property QGraphicsObject::children
     7808    \since 4.7
     7809    \internal
     7810*/
     7811
     7812/*!
     7813    \property QGraphicsObject::width
     7814    \since 4.7
     7815    \internal
     7816*/
     7817
     7818/*!
     7819    \property QGraphicsObject::height
     7820    \since 4.7
     7821    \internal
     7822*/
    74587823
    74597824/*!
     
    76438008*/
    76448009
     8010/*!
     8011    \fn void QGraphicsObject::widthChanged()
     8012    \internal
     8013*/
     8014
     8015/*!
     8016    \fn void QGraphicsObject::heightChanged()
     8017    \internal
     8018*/
     8019
     8020/*!
     8021
     8022  \fn QGraphicsObject::childrenChanged()
     8023
     8024  This signal gets emitted whenever the children list changes
     8025  \internal
     8026*/
     8027
     8028/*!
     8029  \property QGraphicsObject::effect
     8030  \since 4.7
     8031  \brief the effect attached to this item
     8032
     8033  \sa QGraphicsItem::setGraphicsEffect(), QGraphicsItem::graphicsEffect()
     8034*/
    76458035
    76468036/*!
     
    76608050    \sa QGraphicsRectItem, QGraphicsEllipseItem, QGraphicsPathItem,
    76618051    QGraphicsPolygonItem, QGraphicsTextItem, QGraphicsLineItem,
    7662     QGraphicsPixmapItem, {The Graphics View Framework}
     8052    QGraphicsPixmapItem, {Graphics View Framework}
    76638053*/
    76648054
     
    77998189
    78008190    \sa QGraphicsRectItem, QGraphicsEllipseItem, QGraphicsPolygonItem,
    7801     QGraphicsTextItem, QGraphicsLineItem, QGraphicsPixmapItem, {The Graphics
     8191    QGraphicsTextItem, QGraphicsLineItem, QGraphicsPixmapItem, {Graphics
    78028192    View Framework}
    78038193*/
     
    80088398
    80098399    \sa QGraphicsPathItem, QGraphicsEllipseItem, QGraphicsPolygonItem,
    8010     QGraphicsTextItem, QGraphicsLineItem, QGraphicsPixmapItem, {The Graphics
     8400    QGraphicsTextItem, QGraphicsLineItem, QGraphicsPixmapItem, {Graphics
    80118401    View Framework}
    80128402*/
     
    82528642
    82538643    \sa QGraphicsPathItem, QGraphicsRectItem, QGraphicsPolygonItem,
    8254     QGraphicsTextItem, QGraphicsLineItem, QGraphicsPixmapItem, {The Graphics
     8644    QGraphicsTextItem, QGraphicsLineItem, QGraphicsPixmapItem, {Graphics
    82558645    View Framework}
    82568646*/
     
    85618951
    85628952    \sa QGraphicsPathItem, QGraphicsRectItem, QGraphicsEllipseItem,
    8563     QGraphicsTextItem, QGraphicsLineItem, QGraphicsPixmapItem, {The Graphics
     8953    QGraphicsTextItem, QGraphicsLineItem, QGraphicsPixmapItem, {Graphics
    85648954    View Framework}
    85658955*/
     
    87939183
    87949184    \sa QGraphicsPathItem, QGraphicsRectItem, QGraphicsEllipseItem,
    8795     QGraphicsTextItem, QGraphicsPolygonItem, QGraphicsPixmapItem, {The
    8796     Graphics View Framework}
     9185    QGraphicsTextItem, QGraphicsPolygonItem, QGraphicsPixmapItem,
     9186    {Graphics View Framework}
    87979187*/
    87989188
     
    90639453
    90649454    \sa QGraphicsPathItem, QGraphicsRectItem, QGraphicsEllipseItem,
    9065     QGraphicsTextItem, QGraphicsPolygonItem, QGraphicsLineItem, {The
    9066     Graphics View Framework}
     9455    QGraphicsTextItem, QGraphicsPolygonItem, QGraphicsLineItem,
     9456    {Graphics View Framework}
    90679457*/
    90689458
     
    94349824    \sa QGraphicsSimpleTextItem, QGraphicsPathItem, QGraphicsRectItem,
    94359825        QGraphicsEllipseItem, QGraphicsPixmapItem, QGraphicsPolygonItem,
    9436         QGraphicsLineItem, {The Graphics View Framework}
     9826        QGraphicsLineItem, {Graphics View Framework}
    94379827*/
    94389828
     
    980510195        }
    980610196        break;
     10197    case QEvent::ShortcutOverride:
     10198        dd->sendControlEvent(event);
     10199        return true;
    980710200    default:
    980810201        break;
     
    1034710740    \img graphicsview-simpletextitem.png
    1034810741
    10349     \sa QGraphicsTextItem, QGraphicsPathItem, QGraphicsRectItem, QGraphicsEllipseItem,
    10350     QGraphicsPixmapItem, QGraphicsPolygonItem, QGraphicsLineItem, {The
    10351     Graphics View Framework}
     10742    \sa QGraphicsTextItem, QGraphicsPathItem, QGraphicsRectItem,
     10743    QGraphicsEllipseItem, QGraphicsPixmapItem, QGraphicsPolygonItem,
     10744    QGraphicsLineItem, {Graphics View Framework}
    1035210745*/
    1035310746
     
    1055710950/*!
    1055810951    \class QGraphicsItemGroup
    10559     \brief The QGraphicsItemGroup class provides treating a group of items as
    10560     one.
     10952    \brief The QGraphicsItemGroup class provides a container that treats
     10953    a group of items as a single item.
    1056110954    \since 4.2
    1056210955    \ingroup graphicsview-api
     
    1061011003    position and transformation remain intact.
    1061111004
    10612     \sa QGraphicsItem, {The Graphics View Framework}
     11005    \sa QGraphicsItem, {Graphics View Framework}
    1061311006*/
    1061411007
     
    1093111324    } else if (deviceCoordinates) {
    1093211325        // Device coordinates with info.
    10933         scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, info->exposedRegion,
     11326        scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, 0,
    1093411327                     info->widget, info->opacity, &effectTransform, info->wasDirtySceneTransform,
    1093511328                     info->drawItem);
     
    1093811331        QTransform newEffectTransform = info->transformPtr->inverted();
    1093911332        newEffectTransform *= effectTransform;
    10940         scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, info->exposedRegion,
     11333        scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, 0,
    1094111334                     info->widget, info->opacity, &newEffectTransform, info->wasDirtySceneTransform,
    1094211335                     info->drawItem);
     
    1107411467        str = "ItemScenePositionHasChanged";
    1107511468        break;
     11469    case QGraphicsItem::ItemRotationChange:
     11470        str = "ItemRotationChange";
     11471        break;
     11472    case QGraphicsItem::ItemRotationHasChanged:
     11473        str = "ItemRotationHasChanged";
     11474        break;
     11475    case QGraphicsItem::ItemScaleChange:
     11476        str = "ItemScaleChange";
     11477        break;
     11478    case QGraphicsItem::ItemScaleHasChanged:
     11479        str = "ItemScaleHasChanged";
     11480        break;
     11481    case QGraphicsItem::ItemTransformOriginPointChange:
     11482        str = "ItemTransformOriginPointChange";
     11483        break;
     11484    case QGraphicsItem::ItemTransformOriginPointHasChanged:
     11485        str = "ItemTransformOriginPointHasChanged";
     11486        break;
    1107611487    }
    1107711488    debug << str;
     
    1113411545        str = "ItemSendsScenePositionChanges";
    1113511546        break;
     11547    case QGraphicsItem::ItemStopsClickFocusPropagation:
     11548        str = "ItemStopsClickFocusPropagation";
     11549        break;
    1113611550    }
    1113711551    debug << str;
     
    1114311557    debug << '(';
    1114411558    bool f = false;
    11145     for (int i = 0; i < 16; ++i) {
     11559    for (int i = 0; i < 17; ++i) {
    1114611560        if (flags & (1 << i)) {
    1114711561            if (f)
  • trunk/src/gui/graphicsview/qgraphicsitem.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    107107        ItemIsPanel = 0x4000,
    108108        ItemIsFocusScope = 0x8000, // internal
    109         ItemSendsScenePositionChanges = 0x10000
     109        ItemSendsScenePositionChanges = 0x10000,
     110        ItemStopsClickFocusPropagation = 0x20000
    110111        // NB! Don't forget to increase the d_ptr->flags bit field by 1 when adding a new flag.
    111112    };
     
    140141        ItemOpacityChange,
    141142        ItemOpacityHasChanged,
    142         ItemScenePositionHasChanged
     143        ItemScenePositionHasChanged,
     144        ItemRotationChange,
     145        ItemRotationHasChanged,
     146        ItemScaleChange,
     147        ItemScaleHasChanged,
     148        ItemTransformOriginPointChange,
     149        ItemTransformOriginPointHasChanged
    143150    };
    144151
     
    419426
    420427protected:
     428    void updateMicroFocus();
    421429    virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event);
    422430    virtual bool sceneEvent(QEvent *event);
     
    479487    friend class QGraphicsItemEffectSourcePrivate;
    480488    friend class QGraphicsTransformPrivate;
     489#ifndef QT_NO_GESTURES
    481490    friend class QGestureManager;
     491#endif
    482492    friend class ::tst_QGraphicsItem;
    483493    friend bool qt_closestLeaf(const QGraphicsItem *, const QGraphicsItem *);
     
    541551    Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged)
    542552    Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged FINAL)
    543     Q_PROPERTY(QPointF pos READ pos WRITE setPos)
    544     Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
    545     Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
    546     Q_PROPERTY(qreal z READ zValue WRITE setZValue NOTIFY zChanged)
     553    Q_PROPERTY(QPointF pos READ pos WRITE setPos FINAL)
     554    Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged FINAL)
     555    Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged FINAL)
     556    Q_PROPERTY(qreal z READ zValue WRITE setZValue NOTIFY zChanged FINAL)
    547557    Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged)
    548558    Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged)
    549559    Q_PROPERTY(QPointF transformOriginPoint READ transformOriginPoint WRITE setTransformOriginPoint)
     560#ifndef QT_NO_GRAPHICSEFFECT
     561    Q_PROPERTY(QGraphicsEffect *effect READ graphicsEffect WRITE setGraphicsEffect)
     562#endif
     563    Q_PRIVATE_PROPERTY(QGraphicsItem::d_func(), QDeclarativeListProperty<QGraphicsObject> children READ childrenList DESIGNABLE false NOTIFY childrenChanged)
     564    Q_PRIVATE_PROPERTY(QGraphicsItem::d_func(), qreal width READ width WRITE setWidth NOTIFY widthChanged RESET resetWidth FINAL)
     565    Q_PRIVATE_PROPERTY(QGraphicsItem::d_func(), qreal height READ height WRITE setHeight NOTIFY heightChanged RESET resetHeight FINAL)
     566    Q_CLASSINFO("DefaultProperty", "children")
    550567    Q_INTERFACES(QGraphicsItem)
    551568public:
     
    559576#endif
    560577
     578#ifndef QT_NO_GESTURES
    561579    void grabGesture(Qt::GestureType type, Qt::GestureFlags flags = Qt::GestureFlags());
    562580    void ungrabGesture(Qt::GestureType type);
     581#endif
     582
     583protected Q_SLOTS:
     584    void updateMicroFocus();
    563585
    564586Q_SIGNALS:
     
    572594    void rotationChanged();
    573595    void scaleChanged();
     596    void childrenChanged();
     597    void widthChanged();
     598    void heightChanged();
    574599
    575600protected:
  • trunk/src/gui/graphicsview/qgraphicsitem_p.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    7171
    7272class QGraphicsItemPrivate;
     73
     74#ifndef QDECLARATIVELISTPROPERTY
     75#define QDECLARATIVELISTPROPERTY
     76template<typename T>
     77class QDeclarativeListProperty {
     78public:
     79    typedef void (*AppendFunction)(QDeclarativeListProperty<T> *, T*);
     80    typedef int (*CountFunction)(QDeclarativeListProperty<T> *);
     81    typedef T *(*AtFunction)(QDeclarativeListProperty<T> *, int);
     82    typedef void (*ClearFunction)(QDeclarativeListProperty<T> *);
     83
     84    QDeclarativeListProperty()
     85        : object(0), data(0), append(0), count(0), at(0), clear(0), dummy1(0), dummy2(0) {}
     86    QDeclarativeListProperty(QObject *o, QList<T *> &list)
     87        : object(o), data(&list), append(qlist_append), count(qlist_count), at(qlist_at),
     88          clear(qlist_clear), dummy1(0), dummy2(0) {}
     89    QDeclarativeListProperty(QObject *o, void *d, AppendFunction a, CountFunction c = 0, AtFunction t = 0,
     90                    ClearFunction r = 0)
     91        : object(o), data(d), append(a), count(c), at(t), clear(r), dummy1(0), dummy2(0) {}
     92
     93    bool operator==(const QDeclarativeListProperty &o) const {
     94        return object == o.object &&
     95               data == o.data &&
     96               append == o.append &&
     97               count == o.count &&
     98               at == o.at &&
     99               clear == o.clear;
     100    }
     101
     102    QObject *object;
     103    void *data;
     104
     105    AppendFunction append;
     106
     107    CountFunction count;
     108    AtFunction at;
     109
     110    ClearFunction clear;
     111
     112    void *dummy1;
     113    void *dummy2;
     114
     115private:
     116    static void qlist_append(QDeclarativeListProperty *p, T *v) {
     117        ((QList<T *> *)p->data)->append(v);
     118    }
     119    static int qlist_count(QDeclarativeListProperty *p) {
     120        return ((QList<T *> *)p->data)->count();
     121    }
     122    static T *qlist_at(QDeclarativeListProperty *p, int idx) {
     123        return ((QList<T *> *)p->data)->at(idx);
     124    }
     125    static void qlist_clear(QDeclarativeListProperty *p) {
     126        return ((QList<T *> *)p->data)->clear();
     127    }
     128};
     129#endif
    73130
    74131class QGraphicsItemCache
     
    157214        allChildrenDirty(0),
    158215        fullUpdatePending(0),
     216        dirtyChildrenBoundingRect(1),
    159217        flags(0),
    160         dirtyChildrenBoundingRect(1),
    161218        paintedViewBoundingRectsNeedRepaint(0),
    162219        dirtySceneTransform(1),
     
    181238        pendingPolish(0),
    182239        mayHaveChildWithGraphicsEffect(0),
     240        isDeclarativeItem(0),
     241        sendParentChangeNotification(0),
    183242        globalStackingOrder(-1),
    184243        q_ptr(0)
     
    221280    virtual void setPosHelper(const QPointF &pos);
    222281    void setTransformHelper(const QTransform &transform);
     282    void prependGraphicsTransform(QGraphicsTransform *t);
    223283    void appendGraphicsTransform(QGraphicsTransform *t);
    224284    void setVisibleHelper(bool newVisible, bool explicitly, bool update = true);
     
    226286    bool discardUpdateRequest(bool ignoreVisibleBit = false,
    227287                              bool ignoreDirtyBit = false, bool ignoreOpacity = false) const;
     288    virtual void transformChanged() {}
    228289    int depth() const;
    229290#ifndef QT_NO_GRAPHICSEFFECT
     
    238299    void addChild(QGraphicsItem *child);
    239300    void removeChild(QGraphicsItem *child);
     301    QDeclarativeListProperty<QGraphicsObject> childrenList();
    240302    void setParentItemHelper(QGraphicsItem *parent, const QVariant *newParentVariant,
    241303                             const QVariant *thisPointerVariant);
    242     void childrenBoundingRectHelper(QTransform *x, QRectF *rect);
     304    void childrenBoundingRectHelper(QTransform *x, QRectF *rect, QGraphicsItem *topMostEffectItem);
    243305    void initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform,
    244306                         const QRegion &exposedRegion, bool allItems = false) const;
    245     QRectF effectiveBoundingRect() const;
     307    QRectF effectiveBoundingRect(QGraphicsItem *topMostEffectItem = 0) const;
    246308    QRectF sceneEffectiveBoundingRect() const;
    247309
     
    317379    void removeExtraItemCache();
    318380
     381    void updatePaintedViewBoundingRects(bool updateChildren);
    319382    void ensureSceneTransformRecursive(QGraphicsItem **topMostDirtyItem);
    320383    inline void ensureSceneTransform()
     
    415478    inline void markParentDirty(bool updateBoundingRect = false);
    416479
    417     void setFocusHelper(Qt::FocusReason focusReason, bool climb, bool focusFromShow);
     480    void setFocusHelper(Qt::FocusReason focusReason, bool climb, bool focusFromHide);
    418481    void clearFocusHelper(bool giveFocusToParent);
    419     void setSubFocus(QGraphicsItem *rootItem = 0);
    420     void clearSubFocus(QGraphicsItem *rootItem = 0);
     482    void setSubFocus(QGraphicsItem *rootItem = 0, QGraphicsItem *stopItem = 0);
     483    void clearSubFocus(QGraphicsItem *rootItem = 0, QGraphicsItem *stopItem = 0);
    421484    void resetFocusProxy();
    422485    virtual void subFocusItemChange();
     486    virtual void focusScopeItemChange(bool isSubFocusItem);
     487
     488    static void children_append(QDeclarativeListProperty<QGraphicsObject> *list, QGraphicsObject *item);
     489    static int children_count(QDeclarativeListProperty<QGraphicsObject> *list);
     490    static QGraphicsObject *children_at(QDeclarativeListProperty<QGraphicsObject> *list, int);
     491    static void children_clear(QDeclarativeListProperty<QGraphicsObject> *list);
    423492
    424493    inline QTransform transformToParent() const;
     
    428497    inline void sendScenePosChange();
    429498    virtual void siblingOrderChange();
     499
     500    // Private Properties
     501    virtual qreal width() const;
     502    virtual void setWidth(qreal);
     503    virtual void resetWidth();
     504
     505    virtual qreal height() const;
     506    virtual void setHeight(qreal);
     507    virtual void resetHeight();
    430508
    431509    QRectF childrenBoundingRect;
     
    451529    Qt::InputMethodHints imHints;
    452530    QGraphicsItem::PanelModality panelModality;
     531#ifndef QT_NO_GESTURES
    453532    QMap<Qt::GestureType, Qt::GestureFlags> gestureContext;
     533#endif
    454534
    455535    // Packed 32 bits
     
    476556    quint32 needSortChildren : 1;
    477557    quint32 allChildrenDirty : 1;
     558    quint32 fullUpdatePending : 1;
     559    quint32 dirtyChildrenBoundingRect : 1;
    478560
    479561    // Packed 32 bits
    480     quint32 fullUpdatePending : 1;
    481     quint32 flags : 17;
    482     quint32 dirtyChildrenBoundingRect : 1;
     562    quint32 flags : 18;
    483563    quint32 paintedViewBoundingRectsNeedRepaint : 1;
    484564    quint32 dirtySceneTransform : 1;
     
    494574    quint32 notifyBoundingRectChanged : 1;
    495575    quint32 notifyInvalidated : 1;
     576    quint32 mouseSetsFocus : 1;
    496577
    497578    // New 32 bits
    498     quint32 mouseSetsFocus : 1;
    499579    quint32 explicitActivate : 1;
    500580    quint32 wantsActive : 1;
     
    505585    quint32 pendingPolish : 1;
    506586    quint32 mayHaveChildWithGraphicsEffect : 1;
     587    quint32 isDeclarativeItem : 1;
     588    quint32 sendParentChangeNotification : 1;
     589    quint32 padding : 22;
    507590
    508591    // Optional stacking order
     
    610693               && !(item->flags() & QGraphicsItem::ItemIsSelectable)
    611694               && item->d_ptr->children.size() == 0;
    612             //|| (item->d_ptr->isObject && qobject_cast<QmlGraphicsImage *>(q_func()));
     695            //|| (item->d_ptr->isObject && qobject_cast<QDeclarativeImage *>(q_func()));
    613696    }
    614697
     
    640723/*!
    641724    Returns true if \a item1 is on top of \a item2.
    642     The items dont need to be siblings.
     725    The items don't need to be siblings.
    643726
    644727    \internal
     
    694777/*!
    695778    Returns true if \a item2 is on top of \a item1.
    696     The items dont need to be siblings.
     779    The items don't need to be siblings.
    697780
    698781    \internal
     
    789872        if (parentp->graphicsEffect) {
    790873            if (updateBoundingRect) {
    791                 parentp->notifyInvalidated = 1;
    792874                static_cast<QGraphicsItemEffectSourcePrivate *>(parentp->graphicsEffect->d_func()
    793875                                                                ->source->d_func())->invalidateCache();
     876                parentp->notifyInvalidated = 1;
    794877            }
    795             if (parentp->graphicsEffect->isEnabled()) {
     878            if (parentp->scene && parentp->graphicsEffect->isEnabled()) {
    796879                parentp->dirty = 1;
    797880                parentp->fullUpdatePending = 1;
  • trunk/src/gui/graphicsview/qgraphicsitemanimation.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    7878    rotations) at the same step is not recommended.
    7979
    80     \sa QTimeLine, {The Graphics View Framework}
     80    \sa QTimeLine, {Graphics View Framework}
    8181*/
    8282
  • trunk/src/gui/graphicsview/qgraphicsitemanimation.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/graphicsview/qgraphicslayout.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    308308        // does more than we need.
    309309        layoutItem->d_func()->sizeHintCacheDirty = true;
    310         layoutItem = layoutItem->parentLayoutItem();       
    311     }
    312     if (layoutItem)
     310        layoutItem->d_func()->sizeHintWithConstraintCacheDirty = true;
     311        layoutItem = layoutItem->parentLayoutItem();
     312    }
     313    if (layoutItem) {
    313314        layoutItem->d_func()->sizeHintCacheDirty = true;
     315        layoutItem->d_func()->sizeHintWithConstraintCacheDirty = true;
     316    }
    314317
    315318    bool postIt = layoutItem ? !layoutItem->isLayout() : false;
  • trunk/src/gui/graphicsview/qgraphicslayout.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/graphicsview/qgraphicslayout_p.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/graphicsview/qgraphicslayout_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/graphicsview/qgraphicslayoutitem.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4949#include "qgraphicslayoutitem_p.h"
    5050#include "qwidget.h"
     51#include "qgraphicswidget.h"
    5152
    5253#include <QtDebug>
     
    128129{
    129130    sizeHintCacheDirty = true;
    130     sizePolicy = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
     131    sizeHintWithConstraintCacheDirty = true;
    131132}
    132133
     
    137138{
    138139    Q_Q(const QGraphicsLayoutItem);
    139     if (!sizeHintCacheDirty && cachedConstraint == constraint)
    140         return cachedSizeHints;
     140    QSizeF *sizeHintCache;
     141    const bool hasConstraint = constraint.width() >= 0 || constraint.height() >= 0;
     142    if (hasConstraint) {
     143        if (!sizeHintWithConstraintCacheDirty && constraint == cachedConstraint)
     144            return cachedSizeHintsWithConstraints;
     145        sizeHintCache = cachedSizeHintsWithConstraints;
     146    } else {
     147        if (!sizeHintCacheDirty)
     148            return cachedSizeHints;
     149        sizeHintCache = cachedSizeHints;
     150    }
    141151
    142152    for (int i = 0; i < Qt::NSizeHints; ++i) {
    143         cachedSizeHints[i] = constraint;
     153        sizeHintCache[i] = constraint;
    144154        if (userSizeHints)
    145             combineSize(cachedSizeHints[i], userSizeHints[i]);
     155            combineSize(sizeHintCache[i], userSizeHints[i]);
    146156    }
    147157
    148     QSizeF &minS = cachedSizeHints[Qt::MinimumSize];
    149     QSizeF &prefS = cachedSizeHints[Qt::PreferredSize];
    150     QSizeF &maxS = cachedSizeHints[Qt::MaximumSize];
    151     QSizeF &descentS = cachedSizeHints[Qt::MinimumDescent];
     158    QSizeF &minS = sizeHintCache[Qt::MinimumSize];
     159    QSizeF &prefS = sizeHintCache[Qt::PreferredSize];
     160    QSizeF &maxS = sizeHintCache[Qt::MaximumSize];
     161    QSizeF &descentS = sizeHintCache[Qt::MinimumDescent];
    152162
    153163    normalizeHints(minS.rwidth(), prefS.rwidth(), maxS.rwidth(), descentS.rwidth());
     
    175185    // COMBINE_SIZE(descentS, q->sizeHint(Qt::MinimumDescent, constraint));
    176186
    177     cachedConstraint = constraint;
    178     sizeHintCacheDirty = false;
    179     return cachedSizeHints;
     187    if (hasConstraint) {
     188        cachedConstraint = constraint;
     189        sizeHintWithConstraintCacheDirty = false;
     190    } else {
     191        sizeHintCacheDirty = false;
     192    }
     193    return sizeHintCache;
    180194}
    181195
     
    232246        if (size == userSizeHints[which])
    233247            return;
    234     } else if (!size.isValid()) {
     248    } else if (size.width() < 0 && size.height() < 0) {
    235249        return;
    236250    }
     
    260274}
    261275
     276
     277bool QGraphicsLayoutItemPrivate::hasHeightForWidth() const
     278{
     279    Q_Q(const QGraphicsLayoutItem);
     280    if (isLayout) {
     281        const QGraphicsLayout *l = static_cast<const QGraphicsLayout *>(q);
     282        for (int i = l->count() - 1; i >= 0; --i) {
     283            if (QGraphicsLayoutItemPrivate::get(l->itemAt(i))->hasHeightForWidth())
     284                return true;
     285        }
     286    } else if (QGraphicsItem *item = q->graphicsItem()) {
     287        if (item->isWidget()) {
     288            QGraphicsWidget *w = static_cast<QGraphicsWidget *>(item);
     289            if (w->layout()) {
     290                return QGraphicsLayoutItemPrivate::get(w->layout())->hasHeightForWidth();
     291            }
     292        }
     293    }
     294    return q->sizePolicy().hasHeightForWidth();
     295}
     296
     297bool QGraphicsLayoutItemPrivate::hasWidthForHeight() const
     298{
     299    // enable this code when we add QSizePolicy::hasWidthForHeight() (For 4.8)
     300#if 1
     301    return false;
     302#else
     303    Q_Q(const QGraphicsLayoutItem);
     304    if (isLayout) {
     305        const QGraphicsLayout *l = static_cast<const QGraphicsLayout *>(q);
     306        for (int i = l->count() - 1; i >= 0; --i) {
     307            if (QGraphicsLayoutItemPrivate::get(l->itemAt(i))->hasWidthForHeight())
     308                return true;
     309        }
     310    } else if (QGraphicsItem *item = q->graphicsItem()) {
     311        if (item->isWidget()) {
     312            QGraphicsWidget *w = static_cast<QGraphicsWidget *>(item);
     313            if (w->layout()) {
     314                return QGraphicsLayoutItemPrivate::get(w->layout())->hasWidthForHeight();
     315            }
     316        }
     317    }
     318    return q->sizePolicy().hasWidthForHeight();
     319#endif
     320}
     321
    262322/*!
    263323    \class QGraphicsLayoutItem
     
    323383
    324384    Qt uses QGraphicsLayoutItem to provide layout functionality in the
    325     \l{The Graphics View Framework}, but in the future its use may spread
     385    \l{Graphics View Framework}, but in the future its use may spread
    326386    throughout Qt itself.
    327387
     
    340400    Q_D(QGraphicsLayoutItem);
    341401    d->init();
     402    d->sizePolicy = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
    342403    d->q_ptr = this;
    343404}
     
    350411{
    351412    Q_D(QGraphicsLayoutItem);
     413    d->init();
    352414    d->q_ptr = this;
    353415}
     
    769831    Q_D(QGraphicsLayoutItem);
    770832    d->sizeHintCacheDirty = true;
     833    d->sizeHintWithConstraintCacheDirty = true;
    771834}
    772835
  • trunk/src/gui/graphicsview/qgraphicslayoutitem.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/graphicsview/qgraphicslayoutitem_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6666    virtual ~QGraphicsLayoutItemPrivate();
    6767    QGraphicsLayoutItemPrivate(QGraphicsLayoutItem *parent, bool isLayout);
     68    static QGraphicsLayoutItemPrivate *get(QGraphicsLayoutItem *q) { return q->d_func();}
     69    static const QGraphicsLayoutItemPrivate *get(const QGraphicsLayoutItem *q) { return q->d_func();}
     70
    6871    void init();
    6972    QSizeF *effectiveSizeHints(const QSizeF &constraint) const;
     
    7477    void setSizeComponent(Qt::SizeHint which, SizeComponent component, qreal value);
    7578
     79    bool hasHeightForWidth() const;
     80    bool hasWidthForHeight() const;
     81
    7682    QSizePolicy sizePolicy;
    7783    QGraphicsLayoutItem *parent;
     
    8086    mutable QSizeF cachedSizeHints[Qt::NSizeHints];
    8187    mutable QSizeF cachedConstraint;
     88    mutable QSizeF cachedSizeHintsWithConstraints[Qt::NSizeHints];
    8289
    8390    mutable quint32 sizeHintCacheDirty : 1;
     91    mutable quint32 sizeHintWithConstraintCacheDirty : 1;
    8492    quint32 isLayout : 1;
    8593    quint32 ownedByLayout : 1;
  • trunk/src/gui/graphicsview/qgraphicslinearlayout.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    7676    an alignment for each item by calling setAlignment(), and check the
    7777    alignment for any item by calling alignment(). By default, items are
    78     centered both vertically and horizontally.
     78    aligned to the top left.
    7979
    8080    \section1 Spacing within QGraphicsLinearLayout
     
    148148    int index = gridItem->firstRow(orientation);
    149149    engine.removeItem(gridItem);
    150     engine.removeRow(index, orientation);
     150    engine.removeRows(index, 1, orientation);
    151151}
    152152
     
    172172}
    173173
     174Q_GLOBAL_STATIC(QWidget, globalStyleInfoWidget)
     175
    174176QLayoutStyleInfo QGraphicsLinearLayoutPrivate::styleInfo() const
    175177{
    176     static QWidget *wid = 0;
    177     if (!wid)
    178         wid = new QWidget;
    179178    QGraphicsItem *item = parentItem();
    180179    QStyle *style = (item && item->isWidget()) ? static_cast<QGraphicsWidget*>(item)->style() : QApplication::style();
    181     return QLayoutStyleInfo(style, wid);
     180    return QLayoutStyleInfo(style, globalStyleInfoWidget());
    182181}
    183182
     
    277276        return;
    278277    }
     278    Q_ASSERT(item);
     279
     280    //the order of the following instructions is very important because
     281    //invalidating the layout before adding the child item will make the layout happen
     282    //before we try to paint the item
     283    invalidate();
    279284    d->addChildLayoutItem(item);
    280285
    281     Q_ASSERT(item);
    282286    d->fixIndex(&index);
    283287    d->engine.insertRow(index, d->orientation);
    284288    new QGridLayoutItem(&d->engine, item, d->gridRow(index), d->gridColumn(index), 1, 1, 0, index);
    285     invalidate();
    286289}
    287290
     
    444447/*!
    445448    Returns the alignment for \a item. The default alignment is
    446     Qt::AlignCenter.
     449    Qt::AlignTop | Qt::AlignLeft.
    447450
    448451    The alignment decides how the item is positioned within its assigned space
     
    530533    qreal left, top, right, bottom;
    531534    getContentsMargins(&left, &top, &right, &bottom);
    532     return d->engine.sizeHint(d->styleInfo(), which , constraint) + QSizeF(left + right, top + bottom);
     535    const QSizeF extraMargins(left + right, top + bottom);
     536    return d->engine.sizeHint(d->styleInfo(), which , constraint - extraMargins) + extraMargins;
    533537}
    534538
     
    555559        d->engine.dump(indent + 1);
    556560    }
     561#else
     562    Q_UNUSED(indent);
    557563#endif
    558564}
  • trunk/src/gui/graphicsview/qgraphicslinearlayout.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/graphicsview/qgraphicsproxywidget.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    976976            }
    977977            break;
     978#ifndef QT_NO_TOOLTIP
    978979        case QEvent::ToolTipChange:
    979980            // Propagate tooltip change to the proxy.
     
    984985            }
    985986            break;
     987#endif
    986988        default:
    987989            break;
     
    10251027    pos = d->mapToReceiver(pos, receiver);
    10261028
     1029    QPoint globalPos = receiver->mapToGlobal(pos.toPoint());
     1030    //If the receiver by-pass the proxy its popups
     1031    //will be top level QWidgets therefore they need
     1032    //the screen position. mapToGlobal expect the widget to
     1033    //have proper coordinates in regards of the windowing system
     1034    //but it's not true because the widget is embedded.
     1035    if (bypassGraphicsProxyWidget(receiver))
     1036        globalPos = event->screenPos();
     1037
    10271038    // Send mouse event. ### Doesn't propagate the event.
    10281039    QContextMenuEvent contextMenuEvent(QContextMenuEvent::Reason(event->reason()),
    1029                                        pos.toPoint(), receiver->mapToGlobal(pos.toPoint()), event->modifiers());
     1040                                       pos.toPoint(), globalPos, event->modifiers());
    10301041    QApplication::sendEvent(receiver, &contextMenuEvent);
    10311042
     
    14981509  contained in this proxy.
    14991510
    1500   This function makes it possible to aquire proxies for
     1511  This function makes it possible to acquire proxies for
    15011512  non top-level widgets. For instance, you can embed a dialog,
    15021513  and then transform only one of its widgets.
  • trunk/src/gui/graphicsview/qgraphicsproxywidget.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/graphicsview/qgraphicsproxywidget_p.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/graphicsview/qgraphicsscene.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5151    with QGraphicsView for visualizing graphical items, such as lines,
    5252    rectangles, text, or even custom items, on a 2D surface. QGraphicsScene is
    53     part of \l{The Graphics View Framework}.
     53    part of the \l{Graphics View Framework}.
    5454
    5555    QGraphicsScene also provides functionality that lets you efficiently
     
    229229#include <QtCore/qtimer.h>
    230230#include <QtCore/qvarlengtharray.h>
     231#include <QtCore/QMetaMethod>
    231232#include <QtGui/qapplication.h>
    232233#include <QtGui/qdesktopwidget.h>
     
    278279}
    279280
    280 int QGraphicsScenePrivate::changedSignalIndex;
    281 
    282281/*!
    283282    \internal
     
    292291      calledEmitUpdated(false),
    293292      processDirtyItemsEmitted(false),
    294       selectionChanging(0),
    295293      needSortTopLevelItems(true),
    296294      holesInTopLevelSiblingIndex(false),
     
    299297      stickyFocus(false),
    300298      hasFocus(false),
     299      lastMouseGrabberItemHasImplicitMouseGrab(false),
     300      allItemsIgnoreHoverEvents(true),
     301      allItemsUseDefaultCursor(true),
     302      painterStateProtection(true),
     303      sortCacheEnabled(false),
     304      allItemsIgnoreTouchEvents(true),
     305      selectionChanging(0),
     306      rectAdjust(2),
    301307      focusItem(0),
    302308      lastFocusItem(0),
     
    307313      childExplicitActivation(0),
    308314      lastMouseGrabberItem(0),
    309       lastMouseGrabberItemHasImplicitMouseGrab(false),
    310315      dragDropItem(0),
    311316      enterWidget(0),
    312317      lastDropAction(Qt::IgnoreAction),
    313       allItemsIgnoreHoverEvents(true),
    314       allItemsUseDefaultCursor(true),
    315       painterStateProtection(true),
    316       sortCacheEnabled(false),
    317       style(0),
    318       allItemsIgnoreTouchEvents(true)
     318      style(0)
    319319{
    320320}
     
    330330
    331331    // Keep this index so we can check for connected slots later on.
    332     if (!changedSignalIndex) {
    333         changedSignalIndex = signalIndex("changed(QList<QRectF>)");
    334     }
     332    changedSignalIndex = signalIndex("changed(QList<QRectF>)");
     333    processDirtyItemsIndex = q->metaObject()->indexOfSlot("_q_processDirtyItems()");
     334    polishItemsIndex = q->metaObject()->indexOfSlot("_q_polishItems()");
     335
    335336    qApp->d_func()->scene_list.append(q);
    336337    q->update();
     
    690691        lastMouseGrabberItem = 0;
    691692
     693    // Reset the current drop item
     694    if (item == dragDropItem)
     695        dragDropItem = 0;
     696
    692697    // Reenable selectionChanged() for individual items
    693698    --selectionChanging;
     
    695700        emit q->selectionChanged();
    696701
     702#ifndef QT_NO_GESTURES
    697703    QHash<QGesture *, QGraphicsObject *>::iterator it;
    698704    for (it = gestureTargets.begin(); it != gestureTargets.end();) {
     
    702708            ++it;
    703709    }
     710
     711    QGraphicsObject *dummy = static_cast<QGraphicsObject *>(item);
     712    cachedTargetItems.removeOne(dummy);
     713    cachedItemGestures.remove(dummy);
     714    cachedAlreadyDeliveredGestures.remove(dummy);
     715
     716    foreach (Qt::GestureType gesture, item->d_ptr->gestureContext.keys())
     717        ungrabGesture(item, gesture);
     718#endif // QT_NO_GESTURES
    704719}
    705720
     
    816831#endif //QT_NO_IM
    817832    }
     833
     834    // This handles the case that the item has been removed from the
     835    // scene in response to the FocusOut event.
     836    if (item && item->scene() != q)
     837        item = 0;
    818838
    819839    if (item)
     
    871891        }
    872892        if (!itemIsDying && widget->isVisible()) {
    873             widget->hide();
    874             widget->QGraphicsItem::d_ptr->explicitlyHidden = 0;
     893            widget->QGraphicsItem::d_ptr->setVisibleHelper(false, /* explicit = */ false);
    875894        }
    876895    }
     
    10561075    Returns all items for the screen position in \a event.
    10571076*/
    1058 QList<QGraphicsItem *> QGraphicsScenePrivate::itemsAtPosition(const QPoint &screenPos,
     1077QList<QGraphicsItem *> QGraphicsScenePrivate::itemsAtPosition(const QPoint &/*screenPos*/,
    10591078                                                              const QPointF &scenePos,
    10601079                                                              QWidget *widget) const
     
    10651084        return q->items(scenePos, Qt::IntersectsItemShape, Qt::DescendingOrder, QTransform());
    10661085
    1067     const QRectF pointRect(QPointF(widget->mapFromGlobal(screenPos)), QSizeF(1, 1));
     1086    const QRectF pointRect(scenePos, QSizeF(1, 1));
    10681087    if (!view->isTransformed())
    10691088        return q->items(pointRect, Qt::IntersectsItemShape, Qt::DescendingOrder);
    10701089
    10711090    const QTransform viewTransform = view->viewportTransform();
    1072     if (viewTransform.type() <= QTransform::TxScale) {
    1073         return q->items(viewTransform.inverted().mapRect(pointRect), Qt::IntersectsItemShape,
    1074                         Qt::DescendingOrder, viewTransform);
    1075     }
    1076     return q->items(viewTransform.inverted().map(pointRect), Qt::IntersectsItemShape,
     1091    return q->items(pointRect, Qt::IntersectsItemShape,
    10771092                    Qt::DescendingOrder, viewTransform);
    10781093}
     
    11691184{
    11701185    if (QGraphicsObject *object = item->toGraphicsObject()) {
     1186#ifndef QT_NO_GESTURES
    11711187        QGestureManager *gestureManager = QApplicationPrivate::instance()->gestureManager;
    11721188        if (gestureManager) {
     
    11741190                return true;
    11751191        }
     1192#endif // QT_NO_GESTURES
    11761193    }
    11771194
     
    13121329            break;
    13131330        }
    1314         if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) {
     1331        if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable))) {
    13151332            if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) {
    13161333                setFocus = true;
    1317                 if (item != q->focusItem())
     1334                if (item != q->focusItem() && item->d_ptr->mouseSetsFocus)
    13181335                    q->setFocusItem(item, Qt::MouseFocusReason);
    13191336                break;
    13201337            }
    13211338        }
     1339        if (item->d_ptr->flags & QGraphicsItem::ItemStopsClickFocusPropagation)
     1340            break;
    13221341        if (item->isPanel())
    13231342            break;
     
    17411760
    17421761    // Transform the painter.
    1743     painter->setClipRect(targetRect);
     1762    painter->setClipRect(targetRect, Qt::IntersectClip);
    17441763    QTransform painterTransform;
    17451764    painterTransform *= QTransform()
     
    25342553    }
    25352554
    2536     if (d->unpolishedItems.isEmpty())
    2537         QMetaObject::invokeMethod(this, "_q_polishItems", Qt::QueuedConnection);
    2538     d->unpolishedItems.append(item);
    2539     item->d_ptr->pendingPolish = true;
     2555    // QDeclarativeItems do not rely on initial itemChanged message, as the componentComplete
     2556    // function allows far more opportunity for delayed-construction optimization.
     2557    if (!item->d_ptr->isDeclarativeItem) {
     2558        if (d->unpolishedItems.isEmpty()) {
     2559            QMetaMethod method = metaObject()->method(d->polishItemsIndex);
     2560            method.invoke(this, Qt::QueuedConnection);
     2561        }
     2562        d->unpolishedItems.append(item);
     2563        item->d_ptr->pendingPolish = true;
     2564    }
    25402565
    25412566    // Detach this item from its parent if the parent's scene is different
     
    25842609        d->enableTouchEventsOnViews();
    25852610    }
     2611
     2612#ifndef QT_NO_GESTURES
     2613    foreach (Qt::GestureType gesture, item->d_ptr->gestureContext.keys())
     2614        d->grabGesture(item, gesture);
     2615#endif
    25862616
    25872617    // Update selection lists
     
    32123242            for (int i = 0; i < d->views.size(); ++i) {
    32133243                QGraphicsView *view = d->views.at(i);
    3214                 view->d_func()->updateRegion(QRegion(view->mapFromScene(rect).boundingRect()));
     3244                if (view->isTransformed())
     3245                    view->d_func()->updateRectF(view->viewportTransform().mapRect(rect));
     3246                else
     3247                    view->d_func()->updateRectF(rect);
    32153248            }
    32163249        } else {
     
    35023535        d->touchEventHandler(static_cast<QTouchEvent *>(event));
    35033536        break;
     3537#ifndef QT_NO_GESTURES
    35043538    case QEvent::Gesture:
    35053539    case QEvent::GestureOverride:
    35063540        d->gestureEventHandler(static_cast<QGestureEvent *>(event));
    35073541        break;
     3542#endif // QT_NO_GESTURES
    35083543    default:
    35093544        return QObject::event(event);
     
    41314166                                                                wheelEvent->widget());
    41324167
     4168#ifdef Q_WS_MAC
     4169    // On Mac, ignore the event if the first item under the mouse is not the last opened
     4170    // popup (or one of its descendant)
     4171    if (!d->popupWidgets.isEmpty() && !wheelCandidates.isEmpty() && wheelCandidates.first() != d->popupWidgets.back() && !d->popupWidgets.back()->isAncestorOf(wheelCandidates.first())) {
     4172        wheelEvent->accept();
     4173        return;
     4174    }
     4175#else
     4176    // Find the first popup under the mouse (including the popup's descendants) starting from the last.
     4177    // Remove all popups after the one found, or all or them if no popup is under the mouse.
     4178    // Then continue with the event.
     4179    QList<QGraphicsWidget *>::const_iterator iter = d->popupWidgets.end();
     4180    while (--iter >= d->popupWidgets.begin() && !wheelCandidates.isEmpty()) {
     4181        if (wheelCandidates.first() == *iter || (*iter)->isAncestorOf(wheelCandidates.first()))
     4182            break;
     4183        d->removePopup(*iter);
     4184    }
     4185#endif
     4186
    41334187    bool hasSetFocus = false;
    41344188    foreach (QGraphicsItem *item, wheelCandidates) {
     
    42544308        if (painterStateProtection)
    42554309            painter->restore();
     4310    } else if (widgetItem->autoFillBackground()) {
     4311        painter->fillRect(option->exposedRect, widgetItem->palette().window());
    42564312    }
    42574313
     
    43074363}
    43084364
     4365// Copied from qpaintengine_vg.cpp
     4366// Returns true for 90, 180, and 270 degree rotations.
     4367static inline bool transformIsSimple(const QTransform& transform)
     4368{
     4369    QTransform::TransformationType type = transform.type();
     4370    if (type == QTransform::TxNone || type == QTransform::TxTranslate) {
     4371        return true;
     4372    } else if (type == QTransform::TxScale) {
     4373        // Check for 0 and 180 degree rotations.
     4374        // (0 might happen after 4 rotations of 90 degrees).
     4375        qreal m11 = transform.m11();
     4376        qreal m12 = transform.m12();
     4377        qreal m21 = transform.m21();
     4378        qreal m22 = transform.m22();
     4379        if (m12 == 0.0f && m21 == 0.0f) {
     4380            if (m11 == 1.0f && m22 == 1.0f)
     4381                return true; // 0 degrees
     4382            else if (m11 == -1.0f && m22 == -1.0f)
     4383                return true; // 180 degrees.
     4384            if(m11 == 1.0f && m22 == -1.0f)
     4385                return true; // 0 degrees inverted y.
     4386            else if(m11 == -1.0f && m22 == 1.0f)
     4387                return true; // 180 degrees inverted y.
     4388        }
     4389    } else if (type == QTransform::TxRotate) {
     4390        // Check for 90, and 270 degree rotations.
     4391        qreal m11 = transform.m11();
     4392        qreal m12 = transform.m12();
     4393        qreal m21 = transform.m21();
     4394        qreal m22 = transform.m22();
     4395        if (m11 == 0.0f && m22 == 0.0f) {
     4396            if (m12 == 1.0f && m21 == -1.0f)
     4397                return true; // 90 degrees.
     4398            else if (m12 == -1.0f && m21 == 1.0f)
     4399                return true; // 270 degrees.
     4400            else if (m12 == -1.0f && m21 == -1.0f)
     4401                return true; // 90 degrees inverted y.
     4402            else if (m12 == 1.0f && m21 == 1.0f)
     4403                return true; // 270 degrees inverted y.
     4404        }
     4405    }
     4406    return false;
     4407}
     4408
    43094409/*!
    43104410    \internal
     
    43514451    QGraphicsItemCache *itemCache = itemd->extraItemCache();
    43524452    if (cacheMode == QGraphicsItem::ItemCoordinateCache) {
    4353         if (itemCache->boundingRect != brect.toRect()) {
    4354             itemCache->boundingRect = brect.toRect();
    4355             itemCache->allExposed = true;
    4356             itemCache->exposed.clear();
    4357         }
    43584453        pixmapKey = itemCache->key;
    43594454    } else {
     
    43684463        QSize pixmapSize;
    43694464        bool fixedCacheSize = false;
    4370         QRectF brectAligned = brect.toAlignedRect();
     4465        QRect br = brect.toAlignedRect();
    43714466        if ((fixedCacheSize = itemCache->fixedSize.isValid())) {
    43724467            pixmapSize = itemCache->fixedSize;
    43734468        } else {
    4374             pixmapSize = brectAligned.size().toSize();
     4469            pixmapSize = br.size();
    43754470        }
    43764471
     
    43784473        int adjust = itemCache->fixedSize.isValid() ? 0 : 2;
    43794474        QSize adjustSize(adjust*2, adjust*2);
    4380         QRectF br = brectAligned.adjusted(-adjust, -adjust, adjust, adjust);
     4475        br.adjust(-adjust, -adjust, adjust, adjust);
    43814476        if (pix.isNull() || (!fixedCacheSize && (pixmapSize + adjustSize) != pix.size())) {
    43824477            pix = QPixmap(pixmapSize + adjustSize);
     4478            itemCache->boundingRect = br;
     4479            itemCache->exposed.clear();
     4480            itemCache->allExposed = true;
     4481        } else if (itemCache->boundingRect != br) {
     4482            itemCache->boundingRect = br;
    43834483            itemCache->exposed.clear();
    43844484            itemCache->allExposed = true;
     
    44344534        if (newPainterOpacity != oldPainterOpacity) {
    44354535            painter->setOpacity(newPainterOpacity);
    4436             painter->drawPixmap(br, pix, QRectF(QPointF(), pix.size()));
     4536            painter->drawPixmap(br.topLeft(), pix);
    44374537            painter->setOpacity(oldPainterOpacity);
    44384538        } else {
    4439             painter->drawPixmap(br, pix, QRectF(QPointF(), pix.size()));
     4539            painter->drawPixmap(br.topLeft(), pix);
    44404540        }
    44414541        return;
     
    44754575            diff *= painter->worldTransform();
    44764576        deviceData->lastTransform = painter->worldTransform();
    4477         if (!invertable
    4478             || diff.type() > QTransform::TxTranslate
    4479             || painter->worldTransform().type() > QTransform::TxScale) {
     4577        bool allowPartialCacheExposure = false;
     4578        bool simpleTransform = invertable && diff.type() <= QTransform::TxTranslate
     4579                               && transformIsSimple(painter->worldTransform());
     4580        if (!simpleTransform) {
    44804581            pixModified = true;
    44814582            itemCache->allExposed = true;
    44824583            itemCache->exposed.clear();
     4584            deviceData->cacheIndent = QPoint();
    44834585            pix = QPixmap();
    4484         }
    4485 
    4486         // ### This is a pretty bad way to determine when to start partial
    4487         // exposure for DeviceCoordinateCache but it's the least intrusive
    4488         // approach for now.
    4489 #if 0
    4490         // Only if the device rect isn't fully contained.
    4491         bool allowPartialCacheExposure = !viewRect.contains(deviceRect);
    4492 #else
    4493         // Only if deviceRect is 20% taller or wider than the desktop.
    4494         bool allowPartialCacheExposure = false;
    4495         if (widget) {
    4496             QRect desktopRect = QApplication::desktop()->availableGeometry(widget);
    4497             allowPartialCacheExposure = (desktopRect.width() * 1.2 < deviceRect.width()
    4498                                          || desktopRect.height() * 1.2 < deviceRect.height());
    4499         }
    4500 #endif
     4586        } else if (!viewRect.isNull()) {
     4587            allowPartialCacheExposure = deviceData->cacheIndent != QPoint();
     4588        }
     4589
     4590        // Allow partial cache exposure if the device rect isn't fully contained and
     4591        // deviceRect is 20% taller or wider than the viewRect.
     4592        if (!allowPartialCacheExposure && !viewRect.isNull() && !viewRect.contains(deviceRect)) {
     4593            allowPartialCacheExposure = (viewRect.width() * 1.2 < deviceRect.width())
     4594                                         || (viewRect.height() * 1.2 < deviceRect.height());
     4595        }
     4596
    45014597        QRegion scrollExposure;
    4502         if (deviceData->cacheIndent != QPoint() || allowPartialCacheExposure) {
     4598        if (allowPartialCacheExposure) {
    45034599            // Part of pixmap is drawn. Either device contains viewrect (big
    45044600            // item covers whole screen) or parts of device are outside the
     
    46944790        const QRectF brect = adjustedItemEffectiveBoundingRect(item);
    46954791        ENSURE_TRANSFORM_PTR
    4696         QRect viewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy()).toRect()
    4697                                                         : transformPtr->mapRect(brect).toRect();
     4792        QRect viewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy()).toAlignedRect()
     4793                                                        : transformPtr->mapRect(brect).toAlignedRect();
     4794        viewBoundingRect.adjust(-int(rectAdjust), -int(rectAdjust), rectAdjust, rectAdjust);
    46984795        if (widget)
    46994796            item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect);
    4700         viewBoundingRect.adjust(-1, -1, 1, 1);
    47014797        drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect)
    47024798                                 : !viewBoundingRect.normalized().isEmpty();
     
    47194815        ENSURE_TRANSFORM_PTR;
    47204816        QGraphicsItemPaintInfo info(viewTransform, transformPtr, effectTransform, exposedRegion, widget, &styleOptionTmp,
    4721                                     painter, opacity, wasDirtyParentSceneTransform, drawItem);
     4817                                    painter, opacity, wasDirtyParentSceneTransform, itemHasContents && !itemIsFullyTransparent);
    47224818        QGraphicsEffectSource *source = item->d_ptr->graphicsEffect->d_func()->source;
    47234819        QGraphicsItemEffectSourcePrivate *sourced = static_cast<QGraphicsItemEffectSourcePrivate *>
     
    47594855}
    47604856
     4857static inline void setClip(QPainter *painter, QGraphicsItem *item)
     4858{
     4859    painter->save();
     4860    QRectF clipRect;
     4861    const QPainterPath clipPath(item->shape());
     4862    if (QPathClipper::pathToRect(clipPath, &clipRect))
     4863        painter->setClipRect(clipRect, Qt::IntersectClip);
     4864    else
     4865        painter->setClipPath(clipPath, Qt::IntersectClip);
     4866}
     4867
     4868static inline void setWorldTransform(QPainter *painter, const QTransform *const transformPtr,
     4869                                     const QTransform *effectTransform)
     4870{
     4871    Q_ASSERT(transformPtr);
     4872    if (effectTransform)
     4873        painter->setWorldTransform(*transformPtr * *effectTransform);
     4874    else
     4875        painter->setWorldTransform(*transformPtr);
     4876}
     4877
    47614878void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const QTransform *const viewTransform,
    47624879                                 const QTransform *const transformPtr, QRegion *exposedRegion, QWidget *widget,
     
    47674884    const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
    47684885    const bool itemHasChildren = !item->d_ptr->children.isEmpty();
     4886    bool setChildClip = itemClipsChildrenToShape;
     4887    bool itemHasChildrenStackedBehind = false;
    47694888
    47704889    int i = 0;
    47714890    if (itemHasChildren) {
     4891        if (itemClipsChildrenToShape)
     4892            setWorldTransform(painter, transformPtr, effectTransform);
     4893
    47724894        item->d_ptr->ensureSortedChildren();
    4773 
    4774         if (itemClipsChildrenToShape) {
    4775             painter->save();
    4776             Q_ASSERT(transformPtr);
    4777             if (effectTransform)
    4778                 painter->setWorldTransform(*transformPtr * *effectTransform);
    4779             else
    4780                 painter->setWorldTransform(*transformPtr);
    4781             QRectF clipRect;
    4782             const QPainterPath clipPath(item->shape());
    4783             if (QPathClipper::pathToRect(clipPath, &clipRect))
    4784                 painter->setClipRect(clipRect, Qt::IntersectClip);
    4785             else
    4786                 painter->setClipPath(clipPath, Qt::IntersectClip);
    4787         }
    4788 
    4789         // Draw children behind
    4790         for (i = 0; i < item->d_ptr->children.size(); ++i) {
    4791             QGraphicsItem *child = item->d_ptr->children.at(i);
    4792             if (wasDirtyParentSceneTransform)
    4793                 child->d_ptr->dirtySceneTransform = 1;
    4794             if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent))
    4795                 break;
    4796             if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
    4797                 continue;
    4798             drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform);
     4895        // Items with the 'ItemStacksBehindParent' flag are put in front of the list
     4896        // so all we have to do is to check the first item.
     4897        itemHasChildrenStackedBehind = (item->d_ptr->children.at(0)->d_ptr->flags
     4898                                        & QGraphicsItem::ItemStacksBehindParent);
     4899
     4900        if (itemHasChildrenStackedBehind) {
     4901            if (itemClipsChildrenToShape) {
     4902                setClip(painter, item);
     4903                setChildClip = false;
     4904            }
     4905
     4906            // Draw children behind
     4907            for (i = 0; i < item->d_ptr->children.size(); ++i) {
     4908                QGraphicsItem *child = item->d_ptr->children.at(i);
     4909                if (wasDirtyParentSceneTransform)
     4910                    child->d_ptr->dirtySceneTransform = 1;
     4911                if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent))
     4912                    break;
     4913                if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
     4914                    continue;
     4915                drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform);
     4916            }
    47994917        }
    48004918    }
     
    48094927
    48104928        const bool itemClipsToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsToShape;
    4811         const bool savePainter = itemClipsToShape || painterStateProtection;
    4812         if (savePainter)
     4929        bool restorePainterClip = false;
     4930
     4931        if (!itemHasChildren || !itemClipsChildrenToShape) {
     4932            // Item does not have children or clip children to shape.
     4933            setWorldTransform(painter, transformPtr, effectTransform);
     4934            if ((restorePainterClip = itemClipsToShape))
     4935                setClip(painter, item);
     4936        } else if (itemHasChildrenStackedBehind){
     4937            // Item clips children to shape and has children stacked behind, which means
     4938            // the painter is already clipped to the item's shape.
     4939            if (itemClipsToShape) {
     4940                // The clip is already correct. Ensure correct world transform.
     4941                setWorldTransform(painter, transformPtr, effectTransform);
     4942            } else {
     4943                // Remove clip (this also ensures correct world transform).
     4944                painter->restore();
     4945                setChildClip = true;
     4946            }
     4947        } else if (itemClipsToShape) {
     4948            // Item clips children and itself to shape. It does not have hildren stacked
     4949            // behind, which means the clip has not yet been set. We set it now and re-use it
     4950            // for the children.
     4951            setClip(painter, item);
     4952            setChildClip = false;
     4953        }
     4954
     4955        if (painterStateProtection && !restorePainterClip)
    48134956            painter->save();
    48144957
    4815         if (!itemHasChildren || !itemClipsChildrenToShape) {
    4816             if (effectTransform)
    4817                 painter->setWorldTransform(*transformPtr * *effectTransform);
    4818             else
    4819                 painter->setWorldTransform(*transformPtr);
    4820         }
    4821 
    4822         if (itemClipsToShape) {
    4823             QRectF clipRect;
    4824             const QPainterPath clipPath(item->shape());
    4825             if (QPathClipper::pathToRect(clipPath, &clipRect))
    4826                 painter->setClipRect(clipRect, Qt::IntersectClip);
    4827             else
    4828                 painter->setClipPath(clipPath, Qt::IntersectClip);
    4829         }
    48304958        painter->setOpacity(opacity);
    4831 
    48324959        if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget)
    48334960            item->paint(painter, &styleOptionTmp, widget);
     
    48354962            drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection);
    48364963
    4837         if (savePainter)
     4964        if (painterStateProtection || restorePainterClip)
    48384965            painter->restore();
    48394966    }
     
    48414968    // Draw children in front
    48424969    if (itemHasChildren) {
     4970        if (setChildClip)
     4971            setClip(painter, item);
     4972
    48434973        for (; i < item->d_ptr->children.size(); ++i) {
    48444974            QGraphicsItem *child = item->d_ptr->children.at(i);
     
    48494979            drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform);
    48504980        }
    4851     }
    4852 
    4853     // Restore child clip
    4854     if (itemHasChildren && itemClipsChildrenToShape)
    4855         painter->restore();
     4981
     4982        // Restore child clip
     4983        if (itemClipsChildrenToShape)
     4984            painter->restore();
     4985    }
    48564986}
    48574987
     
    48634993    if (updateAll)
    48644994        return;
     4995
     4996    if (removingItemFromScene && !ignoreOpacity && !item->d_ptr->ignoreOpacity) {
     4997        // If any of the item's ancestors ignore opacity, it means that the opacity
     4998        // was set to 0 (and the update request has not yet been processed). That
     4999        // also means that we have to ignore the opacity for the item itself; otherwise
     5000        // things like: parent->setOpacity(0); scene->removeItem(child) won't work.
     5001        // Note that we only do this when removing items from the scene. In all other
     5002        // cases the ignoreOpacity bit propagates properly in processDirtyItems, but
     5003        // since the item is removed immediately it won't be processed there.
     5004        QGraphicsItem *p = item->d_ptr->parent;
     5005        while (p) {
     5006            if (p->d_ptr->ignoreOpacity) {
     5007                item->d_ptr->ignoreOpacity = true;
     5008                break;
     5009            }
     5010            p = p->d_ptr->parent;
     5011        }
     5012    }
    48655013
    48665014    if (item->d_ptr->discardUpdateRequest(/*ignoreVisibleBit=*/force,
     
    48855033
    48865034    if (!processDirtyItemsEmitted) {
    4887         QMetaObject::invokeMethod(q_ptr, "_q_processDirtyItems", Qt::QueuedConnection);
     5035        QMetaMethod method = q_ptr->metaObject()->method(processDirtyItemsIndex);
     5036        method.invoke(q_ptr, Qt::QueuedConnection);
     5037//        QMetaObject::invokeMethod(q_ptr, "_q_processDirtyItems", Qt::QueuedConnection);
    48885038        processDirtyItemsEmitted = true;
    48895039    }
     
    49095059    }
    49105060
    4911     bool hasNoContents = item->d_ptr->flags & QGraphicsItem::ItemHasNoContents
    4912                          && !item->d_ptr->graphicsEffect;
     5061    bool hasNoContents = item->d_ptr->flags & QGraphicsItem::ItemHasNoContents;
    49135062    if (!hasNoContents) {
    49145063        item->d_ptr->dirty = 1;
     
    49175066        else if (!item->d_ptr->fullUpdatePending)
    49185067            item->d_ptr->needsRepaint |= rect;
     5068    } else if (item->d_ptr->graphicsEffect) {
     5069        invalidateChildren = true;
    49195070    }
    49205071
     
    49455096        const QTransform xform = itemq->deviceTransform(viewq->viewportTransform());
    49465097        if (!item->hasBoundingRegionGranularity)
    4947             return view->updateRect(xform.mapRect(rect).toRect());
    4948         return view->updateRegion(xform.map(QRegion(rect.toRect())));
     5098            return view->updateRectF(xform.mapRect(rect));
     5099        return view->updateRegion(rect, xform);
    49495100    }
    49505101
     
    49525103        const qreal dx = item->sceneTransform.dx();
    49535104        const qreal dy = item->sceneTransform.dy();
    4954         if (!item->hasBoundingRegionGranularity) {
    4955             QRectF r(rect);
    4956             r.translate(dx - view->horizontalScroll(), dy - view->verticalScroll());
    4957             return view->updateRect(r.toRect());
    4958         }
    4959         QRegion r(rect.toRect());
    4960         r.translate(qRound(dx) - view->horizontalScroll(), qRound(dy) - view->verticalScroll());
    4961         return view->updateRegion(r);
     5105        QRectF r(rect);
     5106        r.translate(dx - view->horizontalScroll(), dy - view->verticalScroll());
     5107        return view->updateRectF(r);
    49625108    }
    49635109
    49645110    if (!viewq->isTransformed()) {
    49655111        if (!item->hasBoundingRegionGranularity)
    4966             return view->updateRect(item->sceneTransform.mapRect(rect).toRect());
    4967         return view->updateRegion(item->sceneTransform.map(QRegion(rect.toRect())));
     5112            return view->updateRectF(item->sceneTransform.mapRect(rect));
     5113        return view->updateRegion(rect, item->sceneTransform);
    49685114    }
    49695115
     
    49715117    xform *= viewq->viewportTransform();
    49725118    if (!item->hasBoundingRegionGranularity)
    4973         return view->updateRect(xform.mapRect(rect).toRect());
    4974     return view->updateRegion(xform.map(QRegion(rect.toRect())));
     5119        return view->updateRectF(xform.mapRect(rect));
     5120    return view->updateRegion(rect, xform);
    49755121}
    49765122
     
    50525198                                                      item->d_ptr->sceneTransform.dy()));
    50535199            } else {
    5054                 q->update(item->d_ptr->sceneTransform.mapRect(itemBoundingRect));
     5200                QRectF rect = item->d_ptr->sceneTransform.mapRect(itemBoundingRect);
     5201                if (!rect.isEmpty())
     5202                    q->update(rect);
    50555203            }
    50565204        } else {
     
    51085256    // Process children.
    51095257    if (itemHasChildren && item->d_ptr->dirtyChildren) {
     5258        const bool itemClipsChildrenToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape;
     5259        // Items with no content are threated as 'dummy' items which means they are never drawn and
     5260        // 'processed', so the painted view bounding rect is never up-to-date. This means that whenever
     5261        // such an item changes geometry, its children have to take care of the update regardless
     5262        // of whether the item clips children to shape or not.
     5263        const bool bypassUpdateClip = !itemHasContents && wasDirtyParentViewBoundingRects;
     5264        if (itemClipsChildrenToShape && !bypassUpdateClip) {
     5265            // Make sure child updates are clipped to the item's bounding rect.
     5266            for (int i = 0; i < views.size(); ++i)
     5267                views.at(i)->d_func()->setUpdateClip(item);
     5268        }
    51105269        if (!dirtyAncestorContainsChildren) {
    51115270            dirtyAncestorContainsChildren = item->d_ptr->fullUpdatePending
    5112                                             && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
     5271                                            && itemClipsChildrenToShape;
    51135272        }
    51145273        const bool allChildrenDirty = item->d_ptr->allChildrenDirty;
     
    51335292            processDirtyItemsRecursive(child, dirtyAncestorContainsChildren, opacity);
    51345293        }
     5294
     5295        if (itemClipsChildrenToShape) {
     5296            // Reset updateClip.
     5297            for (int i = 0; i < views.size(); ++i)
     5298                views.at(i)->d_func()->setUpdateClip(0);
     5299        }
    51355300    } else if (wasDirtyParentSceneTransform) {
    51365301        item->d_ptr->invalidateChildrenSceneTransform();
     
    51815346        d->_q_polishItems();
    51825347
    5183     d->updateAll = false;
     5348    const qreal opacity = painter->opacity();
    51845349    QTransform viewTransform = painter->worldTransform();
    51855350    Q_UNUSED(options);
     
    51885353    QGraphicsView *view = widget ? qobject_cast<QGraphicsView *>(widget->parentWidget()) : 0;
    51895354    QRegion *expose = 0;
    5190     if (view)
     5355    const quint32 oldRectAdjust = d->rectAdjust;
     5356    if (view) {
     5357        d->updateAll = false;
    51915358        expose = &view->d_func()->exposedRegion;
     5359        if (view->d_func()->optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)
     5360            d->rectAdjust = 1;
     5361        else
     5362            d->rectAdjust = 2;
     5363    }
    51925364
    51935365    // Find all toplevels, they are already sorted.
     
    52025374    }
    52035375
     5376    d->rectAdjust = oldRectAdjust;
    52045377    // Reset discovery bits.
    52055378    for (int i = 0; i < topLevelItems.size(); ++i)
     
    52075380
    52085381    painter->setWorldTransform(viewTransform);
     5382    painter->setOpacity(opacity);
    52095383}
    52105384
     
    55785752{
    55795753    views << view;
     5754#ifndef QT_NO_GESTURES
     5755    foreach (Qt::GestureType gesture, grabbedGestures.keys())
     5756        view->viewport()->grabGesture(gesture);
     5757#endif
    55805758}
    55815759
     
    56385816
    56395817            if (sceneTouchEvent->deviceType() == QTouchEvent::TouchScreen) {
    5640                 // on touch-screens, combine this touch point with the closest one we find if it
    5641                 // is a a direct descendent or ancestor (
     5818                // on touch-screens, combine this touch point with the closest one we find
    56425819                int closestTouchPointId = findClosestTouchPointId(touchPoint.scenePos());
    56435820                QGraphicsItem *closestItem = itemForTouchPointId.value(closestTouchPointId);
    5644                 if (!item
    5645                     || (closestItem
    5646                         && (item->isAncestorOf(closestItem)
    5647                             || closestItem->isAncestorOf(item)))) {
     5821                if (!item || (closestItem && cachedItemsUnderMouse.contains(closestItem)))
    56485822                    item = closestItem;
    5649                 }
    56505823            }
    56515824            if (!item)
     
    59076080}
    59086081
    5909 void QGraphicsScenePrivate::getGestureTargets(const QSet<QGesture *> &gestures,
    5910                                               QWidget *viewport,
    5911                                               QMap<Qt::GestureType, QGesture *> *conflictedGestures,
    5912                                               QList<QList<QGraphicsObject *> > *conflictedItems,
    5913                                               QHash<QGesture *, QGraphicsObject *> *normalGestures)
    5914 {
     6082#ifndef QT_NO_GESTURES
     6083void QGraphicsScenePrivate::gestureTargetsAtHotSpots(const QSet<QGesture *> &gestures,
     6084                                              Qt::GestureFlag flag,
     6085                                              QHash<QGraphicsObject *, QSet<QGesture *> > *targets,
     6086                                              QSet<QGraphicsObject *> *itemsSet,
     6087                                              QSet<QGesture *> *normal,
     6088                                              QSet<QGesture *> *conflicts)
     6089{
     6090    QSet<QGesture *> normalGestures; // that are not in conflicted state.
    59156091    foreach (QGesture *gesture, gestures) {
    5916         Qt::GestureType gestureType = gesture->gestureType();
    5917         if (gesture->hasHotSpot()) {
    5918             QPoint screenPos = gesture->hotSpot().toPoint();
    5919             QList<QGraphicsItem *> items = itemsAtPosition(screenPos, QPointF(), viewport);
    5920             QList<QGraphicsObject *> result;
    5921             for (int j = 0; j < items.size(); ++j) {
    5922                 QGraphicsItem *item = items.at(j);
    5923 
    5924                 // Check if the item is blocked by a modal panel and use it as
    5925                 // a target instead of this item.
    5926                 (void) item->isBlockedByModalPanel(&item);
    5927 
    5928                 if (QGraphicsObject *itemobj = item->toGraphicsObject()) {
    5929                     QGraphicsItemPrivate *d = item->d_func();
    5930                     if (d->gestureContext.contains(gestureType)) {
    5931                         result.append(itemobj);
     6092        if (!gesture->hasHotSpot())
     6093            continue;
     6094        const Qt::GestureType gestureType = gesture->gestureType();
     6095        QList<QGraphicsItem *> items = itemsAtPosition(QPoint(), gesture->d_func()->sceneHotSpot, 0);
     6096        for (int j = 0; j < items.size(); ++j) {
     6097            QGraphicsItem *item = items.at(j);
     6098
     6099            // Check if the item is blocked by a modal panel and use it as
     6100            // a target instead of this item.
     6101            (void) item->isBlockedByModalPanel(&item);
     6102
     6103            if (QGraphicsObject *itemobj = item->toGraphicsObject()) {
     6104                QGraphicsItemPrivate *d = item->QGraphicsItem::d_func();
     6105                QMap<Qt::GestureType, Qt::GestureFlags>::const_iterator it =
     6106                        d->gestureContext.find(gestureType);
     6107                if (it != d->gestureContext.end() && (!flag || (it.value() & flag))) {
     6108                    if (normalGestures.contains(gesture)) {
     6109                        normalGestures.remove(gesture);
     6110                        if (conflicts)
     6111                            conflicts->insert(gesture);
     6112                    } else {
     6113                        normalGestures.insert(gesture);
    59326114                    }
     6115                    if (targets)
     6116                        (*targets)[itemobj].insert(gesture);
     6117                    if (itemsSet)
     6118                        (*itemsSet).insert(itemobj);
    59336119                }
    5934                 // Don't propagate through panels.
    5935                 if (item->isPanel())
    5936                     break;
    59376120            }
    5938             DEBUG() << "QGraphicsScenePrivate::getGestureTargets:"
    5939                     << gesture << result;
    5940             if (result.size() == 1) {
    5941                 normalGestures->insert(gesture, result.first());
    5942             } else if (!result.isEmpty()) {
    5943                 conflictedGestures->insert(gestureType, gesture);
    5944                 conflictedItems->append(result);
    5945             }
    5946         }
    5947     }
     6121            // Don't propagate through panels.
     6122            if (item->isPanel())
     6123                break;
     6124        }
     6125    }
     6126    if (normal)
     6127        *normal = normalGestures;
    59486128}
    59496129
     
    59536133    if (!viewport)
    59546134        return;
     6135    QGraphicsView *graphicsView = qobject_cast<QGraphicsView *>(viewport->parent());
     6136    if (!graphicsView)
     6137        return;
     6138
    59556139    QList<QGesture *> allGestures = event->gestures();
    59566140    DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
    5957             << "Delivering gestures:" <<  allGestures;
    5958 
    5959     typedef QHash<QGraphicsObject *, QList<QGesture *> > GesturesPerItem;
    5960     GesturesPerItem gesturesPerItem;
     6141            << "Gestures:" <<  allGestures;
    59616142
    59626143    QSet<QGesture *> startedGestures;
     6144    QPoint delta = viewport->mapFromGlobal(QPoint());
     6145    QTransform toScene = QTransform::fromTranslate(delta.x(), delta.y())
     6146                         * graphicsView->viewportTransform().inverted();
    59636147    foreach (QGesture *gesture, allGestures) {
     6148        // cache scene coordinates of the hot spot
     6149        if (gesture->hasHotSpot()) {
     6150            gesture->d_func()->sceneHotSpot = toScene.map(gesture->hotSpot());
     6151        } else {
     6152            gesture->d_func()->sceneHotSpot = QPointF();
     6153        }
     6154
    59646155        QGraphicsObject *target = gestureTargets.value(gesture, 0);
    59656156        if (!target) {
     
    59686159            if (gesture->state() == Qt::GestureStarted)
    59696160                startedGestures.insert(gesture);
    5970         } else {
    5971             gesturesPerItem[target].append(gesture);
    5972         }
    5973     }
    5974 
    5975     QMap<Qt::GestureType, QGesture *> conflictedGestures;
    5976     QList<QList<QGraphicsObject *> > conflictedItems;
    5977     QHash<QGesture *, QGraphicsObject *> normalGestures;
    5978     getGestureTargets(startedGestures, viewport, &conflictedGestures, &conflictedItems,
    5979                       &normalGestures);
    5980     DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
    5981             << "Conflicting gestures:" <<  conflictedGestures.values() << conflictedItems;
    5982     Q_ASSERT((conflictedGestures.isEmpty() && conflictedItems.isEmpty()) ||
    5983               (!conflictedGestures.isEmpty() && !conflictedItems.isEmpty()));
    5984 
    5985     // gestures that were sent as override events, but no one accepted them
    5986     QHash<QGesture *, QGraphicsObject *> ignoredConflictedGestures;
    5987 
    5988     // deliver conflicted gestures as override events first
    5989     while (!conflictedGestures.isEmpty() && !conflictedItems.isEmpty()) {
    5990         // get the topmost item to deliver the override event
    5991         Q_ASSERT(!conflictedItems.isEmpty());
    5992         Q_ASSERT(!conflictedItems.first().isEmpty());
    5993         QGraphicsObject *topmost = conflictedItems.first().first();
    5994         for (int i = 1; i < conflictedItems.size(); ++i) {
    5995             QGraphicsObject *item = conflictedItems.at(i).first();
    5996             if (qt_closestItemFirst(item, topmost)) {
    5997                 topmost = item;
     6161        }
     6162    }
     6163
     6164    if (!startedGestures.isEmpty()) {
     6165        QSet<QGesture *> normalGestures; // that have just one target
     6166        QSet<QGesture *> conflictedGestures; // that have multiple possible targets
     6167        gestureTargetsAtHotSpots(startedGestures, Qt::GestureFlag(0), &cachedItemGestures, 0,
     6168                                 &normalGestures, &conflictedGestures);
     6169        cachedTargetItems = cachedItemGestures.keys();
     6170        qSort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst);
     6171        DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
     6172                << "Normal gestures:" << normalGestures
     6173                << "Conflicting gestures:" << conflictedGestures;
     6174
     6175        // deliver conflicted gestures as override events AND remember
     6176        // initial gesture targets
     6177        if (!conflictedGestures.isEmpty()) {
     6178            for (int i = 0; i < cachedTargetItems.size(); ++i) {
     6179                QWeakPointer<QGraphicsObject> item = cachedTargetItems.at(i);
     6180
     6181                // get gestures to deliver to the current item
     6182                QSet<QGesture *> gestures = conflictedGestures & cachedItemGestures.value(item.data());
     6183                if (gestures.isEmpty())
     6184                    continue;
     6185
     6186                DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
     6187                        << "delivering override to"
     6188                        << item.data() << gestures;
     6189                // send gesture override
     6190                QGestureEvent ev(gestures.toList());
     6191                ev.t = QEvent::GestureOverride;
     6192                ev.setWidget(event->widget());
     6193                // mark event and individual gestures as ignored
     6194                ev.ignore();
     6195                foreach(QGesture *g, gestures)
     6196                    ev.setAccepted(g, false);
     6197                sendEvent(item.data(), &ev);
     6198                // mark all accepted gestures to deliver them as normal gesture events
     6199                foreach (QGesture *g, gestures) {
     6200                    if (ev.isAccepted() || ev.isAccepted(g)) {
     6201                        conflictedGestures.remove(g);
     6202                        // mark the item as a gesture target
     6203                        if (item) {
     6204                            gestureTargets.insert(g, item.data());
     6205                            QHash<QGraphicsObject *, QSet<QGesture *> >::iterator it, e;
     6206                            it = cachedItemGestures.begin();
     6207                            e = cachedItemGestures.end();
     6208                            for(; it != e; ++it)
     6209                                it.value().remove(g);
     6210                            cachedItemGestures[item.data()].insert(g);
     6211                        }
     6212                        DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
     6213                                << "override was accepted:"
     6214                                << g << item.data();
     6215                    }
     6216                    // remember the first item that received the override event
     6217                    // as it most likely become a target if no one else accepts
     6218                    // the override event
     6219                    if (!gestureTargets.contains(g) && item)
     6220                        gestureTargets.insert(g, item.data());
     6221
     6222                }
     6223                if (conflictedGestures.isEmpty())
     6224                    break;
    59986225            }
    59996226        }
    6000         // get a list of gestures to send to the item
    6001         QList<Qt::GestureType> grabbedGestures =
    6002                 topmost->QGraphicsItem::d_func()->gestureContext.keys();
    6003         QList<QGesture *> gestures;
    6004         for (int i = 0; i < grabbedGestures.size(); ++i) {
    6005             if (QGesture *g = conflictedGestures.value(grabbedGestures.at(i), 0)) {
    6006                 gestures.append(g);
    6007                 if (!ignoredConflictedGestures.contains(g))
    6008                     ignoredConflictedGestures.insert(g, topmost);
    6009             }
    6010         }
    6011 
    6012         // send gesture override to the topmost item
    6013         QGestureEvent ev(gestures);
    6014         ev.t = QEvent::GestureOverride;
    6015         ev.setWidget(event->widget());
    6016         // mark event and individual gestures as ignored
    6017         ev.ignore();
    6018         foreach(QGesture *g, gestures)
    6019             ev.setAccepted(g, false);
    6020         DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
    6021                 << "delivering override to"
    6022                 << topmost << gestures;
    6023         sendEvent(topmost, &ev);
    6024         // mark all accepted gestures to deliver them as normal gesture events
    6025         foreach (QGesture *g, gestures) {
    6026             if (ev.isAccepted() || ev.isAccepted(g)) {
    6027                 conflictedGestures.remove(g->gestureType());
    6028                 gestureTargets.remove(g);
    6029                 // add the gesture to the list of normal delivered gestures
    6030                 normalGestures.insert(g, topmost);
    6031                 DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
    6032                         << "override was accepted:"
    6033                         << g << topmost;
    6034                 ignoredConflictedGestures.remove(g);
    6035             }
    6036         }
    6037         // remove the item that we've already delivered from the list
    6038         for (int i = 0; i < conflictedItems.size(); ) {
    6039             QList<QGraphicsObject *> &items = conflictedItems[i];
    6040             if (items.first() == topmost) {
    6041                 items.removeFirst();
    6042                 if (items.isEmpty()) {
    6043                     conflictedItems.removeAt(i);
    6044                     continue;
     6227        // remember the initial target item for each gesture that was not in
     6228        // the conflicted state.
     6229        if (!normalGestures.isEmpty()) {
     6230            for (int i = 0; i < cachedTargetItems.size() && !normalGestures.isEmpty(); ++i) {
     6231                QGraphicsObject *item = cachedTargetItems.at(i);
     6232
     6233                // get gestures to deliver to the current item
     6234                foreach (QGesture *g, cachedItemGestures.value(item)) {
     6235                    if (!gestureTargets.contains(g)) {
     6236                        gestureTargets.insert(g, item);
     6237                        normalGestures.remove(g);
     6238                    }
    60456239                }
    60466240            }
    6047             ++i;
    6048         }
    6049     }
    6050 
    6051     // put back those started gestures that are not in the conflicted state
    6052     // and remember their targets
    6053     QHash<QGesture *, QGraphicsObject *>::const_iterator it = normalGestures.begin(),
    6054                                                           e = normalGestures.end();
    6055     for (; it != e; ++it) {
    6056         QGesture *g = it.key();
    6057         QGraphicsObject *receiver = it.value();
    6058         Q_ASSERT(!gestureTargets.contains(g));
    6059         gestureTargets.insert(g, receiver);
    6060         gesturesPerItem[receiver].append(g);
    6061     }
    6062     it = ignoredConflictedGestures.begin();
    6063     e = ignoredConflictedGestures.end();
    6064     for (; it != e; ++it) {
    6065         QGesture *g = it.key();
    6066         QGraphicsObject *receiver = it.value();
    6067         Q_ASSERT(!gestureTargets.contains(g));
    6068         gestureTargets.insert(g, receiver);
    6069         gesturesPerItem[receiver].append(g);
    6070     }
    6071 
    6072     DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
    6073             << "Started gestures:" << normalGestures.keys()
    6074             << "All gestures:" << gesturesPerItem.values();
    6075 
    6076     // deliver all events
    6077     QList<QGesture *> alreadyIgnoredGestures;
    6078     QHash<QGraphicsObject *, QSet<QGesture *> > itemIgnoredGestures;
    6079     QList<QGraphicsObject *> targetItems = gesturesPerItem.keys();
    6080     qSort(targetItems.begin(), targetItems.end(), qt_closestItemFirst);
    6081     for (int i = 0; i < targetItems.size(); ++i) {
    6082         QGraphicsObject *item = targetItems.at(i);
    6083         QList<QGesture *> gestures = gesturesPerItem.value(item);
    6084         // remove gestures that were already delivered once and were ignored
    6085         DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
    6086                 << "already ignored gestures for item"
    6087                 << item << ":" << itemIgnoredGestures.value(item);
    6088 
    6089         if (itemIgnoredGestures.contains(item)) // don't deliver twice to the same item
    6090             continue;
    6091 
    6092         QGraphicsItemPrivate *gid = item->QGraphicsItem::d_func();
    6093         foreach(QGesture *g, alreadyIgnoredGestures) {
    6094             QMap<Qt::GestureType, Qt::GestureFlags>::iterator contextit =
    6095                     gid->gestureContext.find(g->gestureType());
    6096             bool deliver = contextit != gid->gestureContext.end() &&
    6097                 (g->state() == Qt::GestureStarted ||
    6098                  (contextit.value() & Qt::ReceivePartialGestures));
    6099             if (deliver)
    6100                 gestures += g;
    6101         }
     6241        }
     6242    }
     6243
     6244
     6245    // deliver all gesture events
     6246    QSet<QGesture *> undeliveredGestures;
     6247    QSet<QGesture *> parentPropagatedGestures;
     6248    foreach (QGesture *gesture, allGestures) {
     6249        if (QGraphicsObject *target = gestureTargets.value(gesture, 0)) {
     6250            cachedItemGestures[target].insert(gesture);
     6251            cachedTargetItems.append(target);
     6252            undeliveredGestures.insert(gesture);
     6253            QGraphicsItemPrivate *d = target->QGraphicsItem::d_func();
     6254            const Qt::GestureFlags flags = d->gestureContext.value(gesture->gestureType());
     6255            if (flags & Qt::IgnoredGesturesPropagateToParent)
     6256                parentPropagatedGestures.insert(gesture);
     6257        } else {
     6258            DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
     6259                    << "no target for" << gesture << "at"
     6260                    << gesture->hotSpot() << gesture->d_func()->sceneHotSpot;
     6261        }
     6262    }
     6263    qSort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst);
     6264    for (int i = 0; i < cachedTargetItems.size(); ++i) {
     6265        QWeakPointer<QGraphicsObject> receiver = cachedTargetItems.at(i);
     6266        QSet<QGesture *> gestures =
     6267                undeliveredGestures & cachedItemGestures.value(receiver.data());
     6268        gestures -= cachedAlreadyDeliveredGestures.value(receiver.data());
     6269
    61026270        if (gestures.isEmpty())
    61036271            continue;
     6272
     6273        cachedAlreadyDeliveredGestures[receiver.data()] += gestures;
     6274        const bool isPanel = receiver.data()->isPanel();
     6275
    61046276        DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
    61056277                << "delivering to"
    6106                 << item << gestures;
    6107         QGestureEvent ev(gestures);
     6278                << receiver.data() << gestures;
     6279        QGestureEvent ev(gestures.toList());
    61086280        ev.setWidget(event->widget());
    6109         sendEvent(item, &ev);
     6281        sendEvent(receiver.data(), &ev);
    61106282        QSet<QGesture *> ignoredGestures;
    61116283        foreach (QGesture *g, gestures) {
    61126284            if (!ev.isAccepted() && !ev.isAccepted(g)) {
    6113                 ignoredGestures.insert(g);
     6285                // if the gesture was ignored by its target, we will update the
     6286                // targetItems list with a possible target items (items that
     6287                // want to receive partial gestures).
     6288                // ### wont' work if the target was destroyed in the event
     6289                //     we will just stop delivering it.
     6290                if (receiver && receiver.data() == gestureTargets.value(g, 0))
     6291                    ignoredGestures.insert(g);
    61146292            } else {
    6115                 if (g->state() == Qt::GestureStarted)
    6116                     gestureTargets[g] = item;
     6293                if (receiver && g->state() == Qt::GestureStarted) {
     6294                    // someone accepted the propagated initial GestureStarted
     6295                    // event, let it be the new target for all following events.
     6296                    gestureTargets[g] = receiver.data();
     6297                }
     6298                undeliveredGestures.remove(g);
    61176299            }
    61186300        }
    6119         if (!ignoredGestures.isEmpty()) {
    6120             // get a list of items under the (current) hotspot of each ignored
    6121             // gesture and start delivery again from the beginning
     6301        if (undeliveredGestures.isEmpty())
     6302            break;
     6303
     6304        // ignoredGestures list is only filled when delivering to the gesture
     6305        // target item, so it is safe to assume item == target.
     6306        if (!ignoredGestures.isEmpty() && !isPanel) {
     6307            // look for new potential targets for gestures that were ignored
     6308            // and should be propagated.
     6309
     6310            QSet<QGraphicsObject *> targetsSet = cachedTargetItems.toSet();
     6311
     6312            if (receiver) {
     6313                // first if the gesture should be propagated to parents only
     6314                for (QSet<QGesture *>::iterator it = ignoredGestures.begin();
     6315                     it != ignoredGestures.end();) {
     6316                    if (parentPropagatedGestures.contains(*it)) {
     6317                        QGesture *gesture = *it;
     6318                        const Qt::GestureType gestureType = gesture->gestureType();
     6319                        QGraphicsItem *item = receiver.data();
     6320                        while (item) {
     6321                            if (QGraphicsObject *obj = item->toGraphicsObject()) {
     6322                                if (item->d_func()->gestureContext.contains(gestureType)) {
     6323                                    targetsSet.insert(obj);
     6324                                    cachedItemGestures[obj].insert(gesture);
     6325                                }
     6326                            }
     6327                            if (item->isPanel())
     6328                                break;
     6329                            item = item->parentItem();
     6330                        }
     6331
     6332                        it = ignoredGestures.erase(it);
     6333                        continue;
     6334                    }
     6335                    ++it;
     6336                }
     6337            }
     6338
     6339            gestureTargetsAtHotSpots(ignoredGestures, Qt::ReceivePartialGestures,
     6340                                     &cachedItemGestures, &targetsSet, 0, 0);
     6341
     6342            cachedTargetItems = targetsSet.toList();
     6343            qSort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst);
    61226344            DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
    6123                     << "item has ignored the event, will propagate."
    6124                     << item << ignoredGestures;
    6125             itemIgnoredGestures[item] += ignoredGestures;
    6126             QMap<Qt::GestureType, QGesture *> conflictedGestures;
    6127             QList<QList<QGraphicsObject *> > itemsForConflictedGestures;
    6128             QHash<QGesture *, QGraphicsObject *> normalGestures;
    6129             getGestureTargets(ignoredGestures, viewport,
    6130                               &conflictedGestures, &itemsForConflictedGestures,
    6131                               &normalGestures);
    6132             QSet<QGraphicsObject *> itemsSet = targetItems.toSet();
    6133             for (int k = 0; k < itemsForConflictedGestures.size(); ++k)
    6134                 itemsSet += itemsForConflictedGestures.at(k).toSet();
    6135             targetItems = itemsSet.toList();
    6136             qSort(targetItems.begin(), targetItems.end(), qt_closestItemFirst);
    6137             alreadyIgnoredGestures = conflictedGestures.values();
    6138             DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
    6139                     << "new targets:" << targetItems;
     6345                    << "new targets:" << cachedTargetItems;
    61406346            i = -1; // start delivery again
    61416347            continue;
    61426348        }
    61436349    }
     6350
    61446351    foreach (QGesture *g, startedGestures) {
    61456352        if (g->gestureCancelPolicy() == QGesture::CancelAllInContext) {
    61466353            DEBUG() << "lets try to cancel some";
    61476354            // find gestures in context in Qt::GestureStarted or Qt::GestureUpdated state and cancel them
    6148             cancelGesturesForChildren(g, event->widget());
     6355            cancelGesturesForChildren(g);
    61496356        }
    61506357    }
     
    61616368        }
    61626369    }
    6163 }
    6164 
    6165 void QGraphicsScenePrivate::cancelGesturesForChildren(QGesture *original, QWidget *viewport)
     6370
     6371    cachedTargetItems.clear();
     6372    cachedItemGestures.clear();
     6373    cachedAlreadyDeliveredGestures.clear();
     6374}
     6375
     6376void QGraphicsScenePrivate::cancelGesturesForChildren(QGesture *original)
    61666377{
    61676378    Q_ASSERT(original);
    61686379    QGraphicsItem *originalItem = gestureTargets.value(original);
    6169     Q_ASSERT(originalItem);
     6380    if (originalItem == 0) // we only act on accepted gestures, which implies it has a target.
     6381        return;
    61706382
    61716383    // iterate over all active gestures and for each find the owner
     
    62196431                continue;
    62206432
    6221             QPoint screenPos = g->hotSpot().toPoint();
    6222             QList<QGraphicsItem *> items = itemsAtPosition(screenPos, QPointF(), viewport);
     6433            QList<QGraphicsItem *> items = itemsAtPosition(QPoint(), g->d_func()->sceneHotSpot, 0);
    62236434            for (int j = 0; j < items.size(); ++j) {
    62246435                QGraphicsObject *item = items.at(j)->toGraphicsObject();
     
    62466457}
    62476458
     6459void QGraphicsScenePrivate::grabGesture(QGraphicsItem *, Qt::GestureType gesture)
     6460{
     6461    (void)QGestureManager::instance(); // create a gesture manager
     6462    if (!grabbedGestures[gesture]++) {
     6463        foreach (QGraphicsView *view, views)
     6464            view->viewport()->grabGesture(gesture);
     6465    }
     6466}
     6467
     6468void QGraphicsScenePrivate::ungrabGesture(QGraphicsItem *item, Qt::GestureType gesture)
     6469{
     6470    // we know this can only be an object
     6471    Q_ASSERT(item->d_ptr->isObject);
     6472    QGraphicsObject *obj = static_cast<QGraphicsObject *>(item);
     6473    QGestureManager::instance()->cleanupCachedGestures(obj, gesture);
     6474    if (!--grabbedGestures[gesture]) {
     6475        foreach (QGraphicsView *view, views)
     6476            view->viewport()->ungrabGesture(gesture);
     6477    }
     6478}
     6479#endif // QT_NO_GESTURES
     6480
    62486481QT_END_NAMESPACE
    62496482
  • trunk/src/gui/graphicsview/qgraphicsscene.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    303303    friend class QGraphicsItem;
    304304    friend class QGraphicsItemPrivate;
     305    friend class QGraphicsObject;
    305306    friend class QGraphicsView;
    306307    friend class QGraphicsViewPrivate;
     
    313314    friend class QGraphicsSceneBspTreeIndexPrivate;
    314315    friend class QGraphicsItemEffectSourcePrivate;
     316#ifndef QT_NO_GESTURES
    315317    friend class QGesture;
     318#endif
    316319};
    317320
  • trunk/src/gui/graphicsview/qgraphicsscene_bsp.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/graphicsview/qgraphicsscene_bsp_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/graphicsview/qgraphicsscene_p.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    8888    static QGraphicsScenePrivate *get(QGraphicsScene *q);
    8989
    90     static int changedSignalIndex;
     90    int changedSignalIndex;
     91    int processDirtyItemsIndex;
     92    int polishItemsIndex;
    9193
    9294    QGraphicsScene::ItemIndexMethod indexMethod;
     
    9698
    9799    QRectF sceneRect;
    98     bool hasSceneRect;
    99     bool dirtyGrowingItemsBoundingRect;
     100
     101    quint32 hasSceneRect : 1;
     102    quint32 dirtyGrowingItemsBoundingRect : 1;
     103    quint32 updateAll : 1;
     104    quint32 calledEmitUpdated : 1;
     105    quint32 processDirtyItemsEmitted : 1;
     106    quint32 needSortTopLevelItems : 1;
     107    quint32 holesInTopLevelSiblingIndex : 1;
     108    quint32 topLevelSequentialOrdering : 1;
     109    quint32 scenePosDescendantsUpdatePending : 1;
     110    quint32 stickyFocus : 1;
     111    quint32 hasFocus : 1;
     112    quint32 lastMouseGrabberItemHasImplicitMouseGrab : 1;
     113    quint32 allItemsIgnoreHoverEvents : 1;
     114    quint32 allItemsUseDefaultCursor : 1;
     115    quint32 painterStateProtection : 1;
     116    quint32 sortCacheEnabled : 1; // for compatibility
     117    quint32 allItemsIgnoreTouchEvents : 1;
     118    quint32 padding : 15;
     119
    100120    QRectF growingItemsBoundingRect;
    101121
    102122    void _q_emitUpdated();
    103123    QList<QRectF> updatedRects;
    104     bool updateAll;
    105     bool calledEmitUpdated;
    106     bool processDirtyItemsEmitted;
    107124
    108125    QPainterPath selectionArea;
     
    111128    QVector<QGraphicsItem *> unpolishedItems;
    112129    QList<QGraphicsItem *> topLevelItems;
    113     bool needSortTopLevelItems;
    114     bool holesInTopLevelSiblingIndex;
    115     bool topLevelSequentialOrdering;
    116130
    117131    QMap<QGraphicsItem *, QPointF> movingItemsInitialPositions;
     
    124138
    125139    QSet<QGraphicsItem *> scenePosItems;
    126     bool scenePosDescendantsUpdatePending;
    127140    void setScenePosItemEnabled(QGraphicsItem *item, bool enabled);
    128141    void registerScenePosItem(QGraphicsItem *item);
     
    135148    QBrush foregroundBrush;
    136149
    137     bool stickyFocus;
    138     bool hasFocus;
     150    quint32 rectAdjust;
    139151    QGraphicsItem *focusItem;
    140152    QGraphicsItem *lastFocusItem;
     
    152164
    153165    QGraphicsItem *lastMouseGrabberItem;
    154     bool lastMouseGrabberItemHasImplicitMouseGrab;
    155166    QList<QGraphicsItem *> mouseGrabberItems;
    156167    void grabMouse(QGraphicsItem *item, bool implicit = false);
     
    169180    QList<QGraphicsItem *> hoverItems;
    170181    QPointF lastSceneMousePos;
    171     bool allItemsIgnoreHoverEvents;
    172     bool allItemsUseDefaultCursor;
    173182    void enableMouseTrackingOnViews();
    174183    QMap<Qt::MouseButton, QPointF> mouseGrabberButtonDownPos;
     
    183192    void addView(QGraphicsView *view);
    184193    void removeView(QGraphicsView *view);
    185 
    186     bool painterStateProtection;
    187194
    188195    QMultiMap<QGraphicsItem *, QGraphicsItem *> sceneEventFilters;
     
    206213    void mousePressEventHandler(QGraphicsSceneMouseEvent *mouseEvent);
    207214    QGraphicsWidget *windowForItem(const QGraphicsItem *item) const;
    208 
    209     bool sortCacheEnabled; // for compatibility
    210215
    211216    void drawItemHelper(QGraphicsItem *item, QPainter *painter,
     
    292297    void touchEventHandler(QTouchEvent *touchEvent);
    293298    bool sendTouchBeginEvent(QGraphicsItem *item, QTouchEvent *touchEvent);
    294     bool allItemsIgnoreTouchEvents;
    295299    void enableTouchEventsOnViews();
    296300
     301    QList<QGraphicsObject *> cachedTargetItems;
     302#ifndef QT_NO_GESTURES
     303    QHash<QGraphicsObject *, QSet<QGesture *> > cachedItemGestures;
     304    QHash<QGraphicsObject *, QSet<QGesture *> > cachedAlreadyDeliveredGestures;
    297305    QHash<QGesture *, QGraphicsObject *> gestureTargets;
     306    QHash<Qt::GestureType, int>  grabbedGestures;
    298307    void gestureEventHandler(QGestureEvent *event);
    299     void getGestureTargets(const QSet<QGesture *> &gestures, QWidget *viewport,
    300                            QMap<Qt::GestureType, QGesture *> *conflictedGestures,
    301                            QList<QList<QGraphicsObject *> > *conflictedItems,
    302                            QHash<QGesture *, QGraphicsObject *> *normalGestures);
    303     void cancelGesturesForChildren(QGesture *original, QWidget *viewport);
     308    void gestureTargetsAtHotSpots(const QSet<QGesture *> &gestures,
     309                           Qt::GestureFlag flag,
     310                           QHash<QGraphicsObject *, QSet<QGesture *> > *targets,
     311                           QSet<QGraphicsObject *> *itemsSet = 0,
     312                           QSet<QGesture *> *normal = 0,
     313                           QSet<QGesture *> *conflicts = 0);
     314    void cancelGesturesForChildren(QGesture *original);
     315    void grabGesture(QGraphicsItem *, Qt::GestureType gesture);
     316    void ungrabGesture(QGraphicsItem *, Qt::GestureType gesture);
     317#endif // QT_NO_GESTURES
    304318
    305319    void updateInputMethodSensitivityInViews();
  • trunk/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/graphicsview/qgraphicssceneevent.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    16301630
    16311631/*!
    1632     Returns the old position (i.e., the position immediatly before the widget
     1632    Returns the old position (i.e., the position immediately before the widget
    16331633    was moved).
    16341634
  • trunk/src/gui/graphicsview/qgraphicssceneevent.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/graphicsview/qgraphicssceneindex.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/graphicsview/qgraphicssceneindex_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/graphicsview/qgraphicsscenelinearindex.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/graphicsview/qgraphicsscenelinearindex_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/graphicsview/qgraphicstransform.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5555    order, one at a time, to the QGraphicsItem it's assigned to.
    5656
    57     QGraphicsTransform is particularily useful for animations. Whereas
     57    QGraphicsTransform is particularly useful for animations. Whereas
    5858    QGraphicsItem::setTransform() lets you assign any transform directly to an
    5959    item, there is no direct way to interpolate between two different
     
    268268    d->xScale = scale;
    269269    update();
     270    emit xScaleChanged();
    270271    emit scaleChanged();
    271272}
     
    294295    d->yScale = scale;
    295296    update();
     297    emit yScaleChanged();
    296298    emit scaleChanged();
    297299}
     
    320322    d->zScale = scale;
    321323    update();
     324    emit zScaleChanged();
    322325    emit scaleChanged();
    323326}
     
    340343
    341344    \sa QGraphicsScale::origin
     345*/
     346
     347/*!
     348    \fn QGraphicsScale::xScaleChanged()
     349    \since 4.7
     350
     351    This signal is emitted whenever the \l xScale property changes.
     352*/
     353
     354/*!
     355    \fn QGraphicsScale::yScaleChanged()
     356    \since 4.7
     357
     358    This signal is emitted whenever the \l yScale property changes.
     359*/
     360
     361/*!
     362    \fn QGraphicsScale::zScaleChanged()
     363    \since 4.7
     364
     365    This signal is emitted whenever the \l zScale property changes.
    342366*/
    343367
  • trunk/src/gui/graphicsview/qgraphicstransform.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    8686
    8787    Q_PROPERTY(QVector3D origin READ origin WRITE setOrigin NOTIFY originChanged)
    88     Q_PROPERTY(qreal xScale READ xScale WRITE setXScale NOTIFY scaleChanged)
    89     Q_PROPERTY(qreal yScale READ yScale WRITE setYScale NOTIFY scaleChanged)
    90     Q_PROPERTY(qreal zScale READ zScale WRITE setZScale NOTIFY scaleChanged)
     88    Q_PROPERTY(qreal xScale READ xScale WRITE setXScale NOTIFY xScaleChanged)
     89    Q_PROPERTY(qreal yScale READ yScale WRITE setYScale NOTIFY yScaleChanged)
     90    Q_PROPERTY(qreal zScale READ zScale WRITE setZScale NOTIFY zScaleChanged)
    9191public:
    9292    QGraphicsScale(QObject *parent = 0);
     
    109109Q_SIGNALS:
    110110    void originChanged();
     111    void xScaleChanged();
     112    void yScaleChanged();
     113    void zScaleChanged();
    111114    void scaleChanged();
    112115
  • trunk/src/gui/graphicsview/qgraphicstransform_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/graphicsview/qgraphicsview.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5454    QGraphicsView visualizes the contents of a QGraphicsScene in a scrollable
    5555    viewport. To create a scene with geometrical items, see QGraphicsScene's
    56     documentation. QGraphicsView is part of \l{The Graphics View Framework}.
     56    documentation. QGraphicsView is part of the \l{Graphics View Framework}.
    5757
    5858    To visualize a scene, you start by constructing a QGraphicsView object,
     
    328328      sceneInteractionAllowed(true), hasSceneRect(false),
    329329      connectedToScene(false),
    330       mousePressButton(Qt::NoButton),
     330      useLastMouseEvent(false),
    331331      identityMatrix(true),
    332332      dirtyScroll(true),
    333333      accelerateScrolling(true),
     334      keepLastCenterPoint(true),
     335      transforming(false),
     336      handScrolling(false),
     337      mustAllocateStyleOptions(false),
     338      mustResizeBackgroundPixmap(true),
     339      fullUpdatePending(true),
     340      hasUpdateClip(false),
     341      mousePressButton(Qt::NoButton),
    334342      leftIndent(0), topIndent(0),
    335343      lastMouseEvent(QEvent::None, QPoint(), Qt::NoButton, 0, 0),
    336       useLastMouseEvent(false),
    337       keepLastCenterPoint(true),
    338344      alignment(Qt::AlignCenter),
    339       transforming(false),
    340345      transformationAnchor(QGraphicsView::AnchorViewCenter), resizeAnchor(QGraphicsView::NoAnchor),
    341346      viewportUpdateMode(QGraphicsView::MinimalViewportUpdate),
     
    346351      rubberBandSelectionMode(Qt::IntersectsItemShape),
    347352#endif
    348       handScrolling(false), handScrollMotions(0), cacheMode(0),
    349       mustAllocateStyleOptions(false),
    350       mustResizeBackgroundPixmap(true),
     353      handScrollMotions(0), cacheMode(0),
    351354#ifndef QT_NO_CURSOR
    352355      hasStoredOriginalCursor(false),
    353356#endif
    354357      lastDragDropEvent(0),
    355       fullUpdatePending(true),
    356358      updateSceneSlotReimplementedChecked(false)
    357359{
     
    734736
    735737    // Restore the original viewport cursor.
    736     hasStoredOriginalCursor = false;
    737     if (dragMode == QGraphicsView::ScrollHandDrag)
    738         viewport->setCursor(Qt::OpenHandCursor);
    739     else
    740         viewport->setCursor(originalCursor);
     738    if (hasStoredOriginalCursor) {
     739        hasStoredOriginalCursor = false;
     740        if (dragMode == QGraphicsView::ScrollHandDrag)
     741            viewport->setCursor(Qt::OpenHandCursor);
     742        else
     743            viewport->setCursor(originalCursor);
     744    }
    741745}
    742746#endif
     
    853857        viewport->update();
    854858    } else if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) {
    855         if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)
    856             viewport->update(dirtyBoundingRect.adjusted(-1, -1, 1, 1));
    857         else
    858             viewport->update(dirtyBoundingRect.adjusted(-2, -2, 2, 2));
     859        viewport->update(dirtyBoundingRect);
    859860    } else {
    860861        viewport->update(dirtyRegion); // Already adjusted in updateRect/Region.
     
    881882}
    882883
    883 bool QGraphicsViewPrivate::updateRegion(const QRegion &r)
    884 {
    885     if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate || r.isEmpty())
     884/*
     885   Calling this function results in update rects being clipped to the item's
     886   bounding rect. Note that updates prior to this function call is not clipped.
     887   The clip is removed by passing 0.
     888*/
     889void QGraphicsViewPrivate::setUpdateClip(QGraphicsItem *item)
     890{
     891    Q_Q(QGraphicsView);
     892    // We simply ignore the request if the update mode is either FullViewportUpdate
     893    // or NoViewportUpdate; in that case there's no point in clipping anything.
     894    if (!item || viewportUpdateMode == QGraphicsView::NoViewportUpdate
     895        || viewportUpdateMode == QGraphicsView::FullViewportUpdate) {
     896        hasUpdateClip = false;
     897        return;
     898    }
     899
     900    // Calculate the clip (item's bounding rect in view coordinates).
     901    // Optimized version of:
     902    // QRect clip = item->deviceTransform(q->viewportTransform())
     903    //              .mapRect(item->boundingRect()).toAlignedRect();
     904    QRect clip;
     905    if (item->d_ptr->itemIsUntransformable()) {
     906        QTransform xform = item->deviceTransform(q->viewportTransform());
     907        clip = xform.mapRect(item->boundingRect()).toAlignedRect();
     908    } else if (item->d_ptr->sceneTransformTranslateOnly && identityMatrix) {
     909        QRectF r(item->boundingRect());
     910        r.translate(item->d_ptr->sceneTransform.dx() - horizontalScroll(),
     911                    item->d_ptr->sceneTransform.dy() - verticalScroll());
     912        clip = r.toAlignedRect();
     913    } else if (!q->isTransformed()) {
     914        clip = item->d_ptr->sceneTransform.mapRect(item->boundingRect()).toAlignedRect();
     915    } else {
     916        QTransform xform = item->d_ptr->sceneTransform;
     917        xform *= q->viewportTransform();
     918        clip = xform.mapRect(item->boundingRect()).toAlignedRect();
     919    }
     920
     921    if (hasUpdateClip) {
     922        // Intersect with old clip.
     923        updateClip &= clip;
     924    } else {
     925        updateClip = clip;
     926        hasUpdateClip = true;
     927    }
     928}
     929
     930bool QGraphicsViewPrivate::updateRegion(const QRectF &rect, const QTransform &xform)
     931{
     932    if (rect.isEmpty())
    886933        return false;
    887934
    888     const QRect boundingRect = r.boundingRect();
    889     if (!intersectsViewport(boundingRect, viewport->width(), viewport->height()))
    890         return false; // Update region outside viewport.
     935    if (viewportUpdateMode != QGraphicsView::MinimalViewportUpdate
     936        && viewportUpdateMode != QGraphicsView::SmartViewportUpdate) {
     937        // No point in updating with QRegion granularity; use the rect instead.
     938        return updateRectF(xform.mapRect(rect));
     939    }
     940
     941    // Update mode is either Minimal or Smart, so we have to do a potentially slow operation,
     942    // which is clearly documented here: QGraphicsItem::setBoundingRegionGranularity.
     943    const QRegion region = xform.map(QRegion(rect.toAlignedRect()));
     944    QRect viewRect = region.boundingRect();
     945    const bool dontAdjustForAntialiasing = optimizationFlags & QGraphicsView::DontAdjustForAntialiasing;
     946    if (dontAdjustForAntialiasing)
     947        viewRect.adjust(-1, -1, 1, 1);
     948    else
     949        viewRect.adjust(-2, -2, 2, 2);
     950    if (!intersectsViewport(viewRect, viewport->width(), viewport->height()))
     951        return false; // Update region for sure outside viewport.
     952
     953    const QVector<QRect> &rects = region.rects();
     954    for (int i = 0; i < rects.size(); ++i) {
     955        viewRect = rects.at(i);
     956        if (dontAdjustForAntialiasing)
     957            viewRect.adjust(-1, -1, 1, 1);
     958        else
     959            viewRect.adjust(-2, -2, 2, 2);
     960        if (hasUpdateClip)
     961            viewRect &= updateClip;
     962        dirtyRegion += viewRect;
     963    }
     964
     965    return true;
     966}
     967
     968// NB! Assumes the rect 'r' is already aligned and adjusted for antialiasing.
     969// For QRectF use updateRectF(const QRectF &) to ensure proper adjustments.
     970bool QGraphicsViewPrivate::updateRect(const QRect &r)
     971{
     972    if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate
     973        || !intersectsViewport(r, viewport->width(), viewport->height())) {
     974        return false;
     975    }
    891976
    892977    switch (viewportUpdateMode) {
     
    896981        break;
    897982    case QGraphicsView::BoundingRectViewportUpdate:
    898         QRect_unite(&dirtyBoundingRect, boundingRect);
     983        if (hasUpdateClip)
     984            QRect_unite(&dirtyBoundingRect, r & updateClip);
     985        else
     986            QRect_unite(&dirtyBoundingRect, r);
    899987        if (containsViewport(dirtyBoundingRect, viewport->width(), viewport->height())) {
    900988            fullUpdatePending = true;
     
    904992    case QGraphicsView::SmartViewportUpdate: // ### DEPRECATE
    905993    case QGraphicsView::MinimalViewportUpdate:
    906     {
    907         const QVector<QRect> &rects = r.rects();
    908         for (int i = 0; i < rects.size(); ++i) {
    909             if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)
    910                 dirtyRegion += rects.at(i).adjusted(-1, -1, 1, 1);
    911             else
    912                 dirtyRegion += rects.at(i).adjusted(-2, -2, 2, 2);
    913         }
    914         break;
    915     }
    916     default:
    917         break;
    918     }
    919 
    920     return true;
    921 }
    922 
    923 bool QGraphicsViewPrivate::updateRect(const QRect &r)
    924 {
    925     if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate
    926         || !intersectsViewport(r, viewport->width(), viewport->height())) {
    927         return false;
    928     }
    929 
    930     switch (viewportUpdateMode) {
    931     case QGraphicsView::FullViewportUpdate:
    932         fullUpdatePending = true;
    933         viewport->update();
    934         break;
    935     case QGraphicsView::BoundingRectViewportUpdate:
    936         QRect_unite(&dirtyBoundingRect, r);
    937         if (containsViewport(dirtyBoundingRect, viewport->width(), viewport->height())) {
    938             fullUpdatePending = true;
    939             viewport->update();
    940         }
    941         break;
    942     case QGraphicsView::SmartViewportUpdate: // ### DEPRECATE
    943     case QGraphicsView::MinimalViewportUpdate:
    944         if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)
    945             dirtyRegion += r.adjusted(-1, -1, 1, 1);
     994        if (hasUpdateClip)
     995            dirtyRegion += r & updateClip;
    946996        else
    947             dirtyRegion += r.adjusted(-2, -2, 2, 2);
     997            dirtyRegion += r;
    948998        break;
    949999    default:
     
    10361086{
    10371087    Q_Q(QGraphicsView);
    1038     bool enabled = scene && scene->focusItem()
    1039                    && (scene->focusItem()->flags() & QGraphicsItem::ItemAcceptsInputMethod);
     1088    QGraphicsItem *focusItem = 0;
     1089    bool enabled = scene && (focusItem = scene->focusItem())
     1090                   && (focusItem->d_ptr->flags & QGraphicsItem::ItemAcceptsInputMethod);
    10401091    q->setAttribute(Qt::WA_InputMethodEnabled, enabled);
    10411092    q->viewport()->setAttribute(Qt::WA_InputMethodEnabled, enabled);
     1093
     1094    if (!enabled) {
     1095        q->setInputMethodHints(0);
     1096        return;
     1097    }
     1098
     1099    QGraphicsProxyWidget *proxy = focusItem->d_ptr->isWidget && focusItem->d_ptr->isProxyWidget()
     1100                                    ? static_cast<QGraphicsProxyWidget *>(focusItem) : 0;
     1101    if (!proxy) {
     1102        q->setInputMethodHints(focusItem->inputMethodHints());
     1103    } else if (QWidget *widget = proxy->widget()) {
     1104    if (QWidget *fw = widget->focusWidget())
     1105        widget = fw;
     1106        q->setInputMethodHints(widget->inputMethodHints());
     1107    } else {
     1108        q->setInputMethodHints(0);
     1109    }
    10421110}
    10431111
     
    18081876{
    18091877    Q_D(QGraphicsView);
    1810     Q_UNUSED(xmargin);
    1811     Q_UNUSED(ymargin);
    18121878    qreal width = viewport()->width();
    18131879    qreal height = viewport()->height();
     
    24292495    QVariant value = d->scene->inputMethodQuery(query);
    24302496    if (value.type() == QVariant::RectF)
    2431         value = mapFromScene(value.toRectF()).boundingRect();
     2497        value = d->mapRectFromScene(value.toRectF());
    24322498    else if (value.type() == QVariant::PointF)
    24332499        value = mapFromScene(value.toPointF());
     
    25312597    // Convert scene rects to viewport rects.
    25322598    foreach (const QRectF &rect, rects) {
    2533         QRect xrect = transform.mapRect(rect).toRect();
     2599        QRect xrect = transform.mapRect(rect).toAlignedRect();
    25342600        if (!(d->optimizationFlags & DontAdjustForAntialiasing))
    25352601            xrect.adjust(-2, -2, 2, 2);
     2602        else
     2603            xrect.adjust(-1, -1, 1, 1);
    25362604        if (!viewportRect.intersects(xrect))
    25372605            continue;
     
    26222690    if (d->scene && !d->scene->d_func()->allItemsIgnoreTouchEvents)
    26232691        widget->setAttribute(Qt::WA_AcceptTouchEvents);
     2692
     2693#ifndef QT_NO_GESTURES
     2694    if (d->scene) {
     2695        foreach (Qt::GestureType gesture, d->scene->d_func()->grabbedGestures.keys())
     2696            widget->grabGesture(gesture);
     2697    }
     2698#endif
    26242699
    26252700    widget->setAcceptDrops(acceptDrops());
     
    27682843        return true;
    27692844    }
     2845#ifndef QT_NO_GESTURES
    27702846    case QEvent::Gesture:
    27712847    case QEvent::GestureOverride:
     
    27812857        return true;
    27822858    }
     2859#endif // QT_NO_GESTURES
    27832860    default:
    27842861        break;
     
    33843461    // Items
    33853462    if (!(d->optimizationFlags & IndirectPainting)) {
     3463        const quint32 oldRectAdjust = d->scene->d_func()->rectAdjust;
     3464        if (d->optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)
     3465            d->scene->d_func()->rectAdjust = 1;
     3466        else
     3467            d->scene->d_func()->rectAdjust = 2;
    33863468        d->scene->d_func()->drawItems(&painter, viewTransformed ? &viewTransform : 0,
    33873469                                      &d->exposedRegion, viewport());
     3470        d->scene->d_func()->rectAdjust = oldRectAdjust;
    33883471        // Make sure the painter's world transform is restored correctly when
    33893472        // drawing without painter state protection (DontSavePainterState).
     
    33933476        // and restore() in QGraphicsScene::drawItems().
    33943477        if (!d->scene->d_func()->painterStateProtection)
    3395             painter.setWorldTransform(viewTransform);
     3478            painter.setOpacity(1.0);
     3479        painter.setWorldTransform(viewTransform);
    33963480    } else {
    33973481        // Make sure we don't have unpolished items before we draw
  • trunk/src/gui/graphicsview/qgraphicsview.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/graphicsview/qgraphicsview_p.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6666QT_BEGIN_NAMESPACE
    6767
    68 class Q_AUTOTEST_EXPORT QGraphicsViewPrivate : public QAbstractScrollAreaPrivate
     68class Q_GUI_EXPORT QGraphicsViewPrivate : public QAbstractScrollAreaPrivate
    6969{
    7070    Q_DECLARE_PUBLIC(QGraphicsView)
     
    7878
    7979    QGraphicsView::DragMode dragMode;
    80     bool sceneInteractionAllowed;
     80
     81    quint32 sceneInteractionAllowed : 1;
     82    quint32 hasSceneRect : 1;
     83    quint32 connectedToScene : 1;
     84    quint32 useLastMouseEvent : 1;
     85    quint32 identityMatrix : 1;
     86    quint32 dirtyScroll : 1;
     87    quint32 accelerateScrolling : 1;
     88    quint32 keepLastCenterPoint : 1;
     89    quint32 transforming : 1;
     90    quint32 handScrolling : 1;
     91    quint32 mustAllocateStyleOptions : 1;
     92    quint32 mustResizeBackgroundPixmap : 1;
     93    quint32 fullUpdatePending : 1;
     94    quint32 hasUpdateClip : 1;
     95    quint32 padding : 18;
     96
    8197    QRectF sceneRect;
    82     bool hasSceneRect;
    8398    void updateLastCenterPoint();
    84     bool connectedToScene;
    8599
    86100    qint64 horizontalScroll() const;
     
    90104    QRectF mapRectFromScene(const QRectF &rect) const;
    91105
     106    QRect updateClip;
    92107    QPointF mousePressItemPoint;
    93108    QPointF mousePressScenePoint;
     
    99114    Qt::MouseButton mousePressButton;
    100115    QTransform matrix;
    101     bool identityMatrix;
    102116    qint64 scrollX, scrollY;
    103     bool dirtyScroll;
    104117    void updateScroll();
    105118
    106     bool accelerateScrolling;
    107119    qreal leftIndent;
    108120    qreal topIndent;
     
    110122    // Replaying mouse events
    111123    QMouseEvent lastMouseEvent;
    112     bool useLastMouseEvent;
    113124    void replayLastMouseEvent();
    114125    void storeMouseEvent(QMouseEvent *event);
     
    116127
    117128    QPointF lastCenterPoint;
    118     bool keepLastCenterPoint;
    119129    Qt::Alignment alignment;
    120     bool transforming;
    121130
    122131    QGraphicsView::ViewportAnchor transformationAnchor;
     
    132141    Qt::ItemSelectionMode rubberBandSelectionMode;
    133142#endif
    134     bool handScrolling;
    135143    int handScrollMotions;
    136144
     
    138146
    139147    QVector<QStyleOptionGraphicsItem> styleOptions;
    140     bool mustAllocateStyleOptions;
    141148    QStyleOptionGraphicsItem *allocStyleOptionsArray(int numItems);
    142149    void freeStyleOptionsArray(QStyleOptionGraphicsItem *array);
     
    145152    QBrush foregroundBrush;
    146153    QPixmap backgroundPixmap;
    147     bool mustResizeBackgroundPixmap;
    148154    QRegion backgroundPixmapExposed;
    149155
     
    162168    QRect mapToViewRect(const QGraphicsItem *item, const QRectF &rect) const;
    163169    QRegion mapToViewRegion(const QGraphicsItem *item, const QRectF &rect) const;
    164     bool fullUpdatePending;
    165170    QRegion dirtyRegion;
    166171    QRect dirtyBoundingRect;
     
    193198    }
    194199
     200    void setUpdateClip(QGraphicsItem *);
     201
     202    inline bool updateRectF(const QRectF &rect)
     203    {
     204        if (rect.isEmpty())
     205            return false;
     206        if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)
     207            return updateRect(rect.toAlignedRect().adjusted(-1, -1, 1, 1));
     208        return updateRect(rect.toAlignedRect().adjusted(-2, -2, 2, 2));
     209    }
     210
    195211    bool updateRect(const QRect &rect);
    196     bool updateRegion(const QRegion &region);
     212    bool updateRegion(const QRectF &rect, const QTransform &xform);
    197213    bool updateSceneSlotReimplementedChecked;
    198214    QRegion exposedRegion;
  • trunk/src/gui/graphicsview/qgraphicswidget.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    325325
    326326/*!
     327  \fn QGraphicsWidget::geometryChanged()
     328
     329  This signal gets emitted whenever the geometry is changed in setGeometry().
     330*/
     331
     332/*!
    327333    \property QGraphicsWidget::geometry
    328334    \brief the geometry of the widget
     
    380386            //set the new pos
    381387            d->geom.moveTopLeft(pos());
     388            emit geometryChanged();
    382389            return;
    383390        }
     
    385392    QSizeF oldSize = size();
    386393    QGraphicsLayoutItem::setGeometry(newGeom);
    387 
    388394    // Send resize event
    389395    bool resized = newGeom.size() != oldSize;
     
    392398        re.setOldSize(oldSize);
    393399        re.setNewSize(newGeom.size());
     400        if (oldSize.width() != newGeom.size().width())
     401            emit widthChanged();
     402        if (oldSize.height() != newGeom.size().height())
     403            emit heightChanged();
    394404        QApplication::sendEvent(this, &re);
    395405    }
     406    emit geometryChanged();
    396407}
    397408
     
    440451
    441452    Contents margins are used by the assigned layout to define the placement
    442     of subwidgets and layouts. Margins are particularily useful for widgets
     453    of subwidgets and layouts. Margins are particularly useful for widgets
    443454    that constrain subwidgets to only a section of its own geometry. For
    444455    example, a group box with a layout will place subwidgets inside its frame,
     
    738749
    739750/*!
     751    \property QGraphicsWidget::layout
     752    \brief The layout of the widget
     753
     754    Any existing layout manager is deleted before the new layout is assigned. If
     755     \a layout is 0, the widget is left without a layout. Existing subwidgets'
     756    geometries will remain unaffected.
     757
     758    QGraphicsWidget takes ownership of \a layout.
     759
     760    All widgets that are currently managed by \a layout or all of its
     761    sublayouts, are automatically reparented to this item. The layout is then
     762    invalidated, and the child widget geometries are adjusted according to
     763    this item's geometry() and contentsMargins(). Children who are not
     764    explicitly managed by \a layout remain unaffected by the layout after
     765    it has been assigned to this widget.
     766
     767    If no layout is currently managing this widget, layout() will return 0.
     768
     769*/
     770
     771/*!
     772    \fn void QGraphicsWidget::layoutChanged()
     773    This signal gets emitted whenever the layout of the item changes
     774    \internal
     775*/
     776
     777/*!
    740778    Returns this widget's layout, or 0 if no layout is currently managing this
    741779    widget.
     
    790828    l->d_func()->reparentChildItems(this);
    791829    l->invalidate();
     830    emit layoutChanged();
    792831}
    793832
     
    915954{
    916955    Q_D(const QGraphicsWidget);
    917     return d->font;
     956    QFont fnt = d->font;
     957    fnt.resolve(fnt.resolve() | d->inheritedFontResolveMask);
     958    return fnt;
    918959}
    919960void QGraphicsWidget::setFont(const QFont &font)
     
    9651006    QPalette resolvedPalette = palette.resolve(naturalPalette);
    9661007    d->setPalette_helper(resolvedPalette);
     1008}
     1009
     1010/*!
     1011    \property QGraphicsWidget::autoFillBackground
     1012    \brief whether the widget background is filled automatically
     1013    \since 4.7
     1014
     1015    If enabled, this property will cause Qt to fill the background of the
     1016    widget before invoking the paint() method. The color used is defined by the
     1017    QPalette::Window color role from the widget's \l{QPalette}{palette}.
     1018
     1019    In addition, Windows are always filled with QPalette::Window, unless the
     1020    WA_OpaquePaintEvent or WA_NoSystemBackground attributes are set.
     1021
     1022    By default, this property is false.
     1023
     1024    \sa Qt::WA_OpaquePaintEvent, Qt::WA_NoSystemBackground,
     1025*/
     1026bool QGraphicsWidget::autoFillBackground() const
     1027{
     1028    Q_D(const QGraphicsWidget);
     1029    return d->autoFillBackground;
     1030}
     1031void QGraphicsWidget::setAutoFillBackground(bool enabled)
     1032{
     1033    Q_D(QGraphicsWidget);
     1034    if (d->autoFillBackground != enabled) {
     1035        d->autoFillBackground = enabled;
     1036        update();
     1037    }
    9671038}
    9681039
     
    10481119        break;
    10491120    case ItemParentChange: {
    1050         QGraphicsItem *parent = qVariantValue<QGraphicsItem *>(value);
    1051         d->fixFocusChainBeforeReparenting((parent && parent->isWidget()) ? static_cast<QGraphicsWidget *>(parent) : 0, scene());
    1052 
    10531121        // Deliver ParentAboutToChange.
    10541122        QEvent event(QEvent::ParentAboutToChange);
  • trunk/src/gui/graphicsview/qgraphicswidget.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    7474    Q_PROPERTY(QFont font READ font WRITE setFont)
    7575    Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection RESET unsetLayoutDirection)
    76     Q_PROPERTY(QSizeF size READ size WRITE resize)
     76    Q_PROPERTY(QSizeF size READ size WRITE resize NOTIFY geometryChanged)
    7777    Q_PROPERTY(QSizeF minimumSize READ minimumSize WRITE setMinimumSize)
    7878    Q_PROPERTY(QSizeF preferredSize READ preferredSize WRITE setPreferredSize)
     
    8282    Q_PROPERTY(Qt::WindowFlags windowFlags READ windowFlags WRITE setWindowFlags)
    8383    Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle)
    84     Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry)
     84    Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry NOTIFY geometryChanged)
     85    Q_PROPERTY(bool autoFillBackground READ autoFillBackground WRITE setAutoFillBackground)
     86    Q_PROPERTY(QGraphicsLayout* layout READ layout WRITE setLayout NOTIFY layoutChanged)
    8587public:
    8688    QGraphicsWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0);
    8789    ~QGraphicsWidget();
    88 
    8990    QGraphicsLayout *layout() const;
    9091    void setLayout(QGraphicsLayout *layout);
     
    103104    QPalette palette() const;
    104105    void setPalette(const QPalette &palette);
     106
     107    bool autoFillBackground() const;
     108    void setAutoFillBackground(bool enabled);
    105109
    106110    void resize(const QSizeF &size);
     
    175179    using QObject::children;
    176180#endif
     181
     182Q_SIGNALS:
     183    void geometryChanged();
     184    void layoutChanged();
    177185
    178186public Q_SLOTS:
  • trunk/src/gui/graphicsview/qgraphicswidget_p.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4545
    4646#include <QtCore/qdebug.h>
     47#include <QtCore/qnumeric.h>
    4748#include "qgraphicswidget_p.h"
    4849#include "qgraphicslayout.h"
     
    7172    windowFlags = wFlags;
    7273
    73     q->setParentItem(parentItem);
     74    if (parentItem)
     75        setParentItemHelper(parentItem, 0, 0);
     76
    7477    q->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred, QSizePolicy::DefaultType));
    7578    q->setGraphicsItem(q);
     
    7780    resolveLayoutDirection();
    7881    q->unsetWindowFrameMargins();
    79     q->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption);
    80     q->setFlag(QGraphicsItem::ItemSendsGeometryChanges);
     82    flags |= QGraphicsItem::ItemUsesExtendedStyleOption;
     83    flags |= QGraphicsItem::ItemSendsGeometryChanges;
     84    if (windowFlags & Qt::Window)
     85        flags |= QGraphicsItem::ItemIsPanel;
    8186}
    8287
     
    250255void QGraphicsWidgetPrivate::resolveFont(uint inheritedMask)
    251256{
     257    Q_Q(QGraphicsWidget);
    252258    inheritedFontResolveMask = inheritedMask;
     259    if (QGraphicsWidget *p = q->parentWidget())
     260        inheritedFontResolveMask |= p->d_func()->inheritedFontResolveMask;
    253261    QFont naturalFont = naturalWidgetFont();
    254262    QFont resolvedFont = font.resolve(naturalFont);
     
    757765    QGraphicsWidget *firstOld = 0;
    758766    bool wasPreviousNew = true;
    759    
     767
    760768    while (w != q) {
    761769        bool isCurrentNew = q->isAncestorOf(w);
     
    792800
    793801    if (oldScene && newScene != oldScene)
    794         oldScene->d_func()->tabFocusFirst = firstOld;
     802        oldScene->d_func()->tabFocusFirst = (firstOld && firstOld->scene() == oldScene) ? firstOld : 0;
    795803
    796804    QGraphicsItem *topLevelItem = newParent ? newParent->topLevelItem() : 0;
     
    826834}
    827835
     836qreal QGraphicsWidgetPrivate::width() const
     837{
     838    Q_Q(const QGraphicsWidget);
     839    return q->geometry().width();
     840}
     841
     842void QGraphicsWidgetPrivate::setWidth(qreal w)
     843{
     844    if (qIsNaN(w))
     845        return;
     846    Q_Q(QGraphicsWidget);
     847    if (q->geometry().width() == w)
     848        return;
     849
     850    QRectF oldGeom = q->geometry();
     851
     852    q->setGeometry(QRectF(q->x(), q->y(), w, height()));
     853}
     854
     855void QGraphicsWidgetPrivate::resetWidth()
     856{
     857    Q_Q(QGraphicsWidget);
     858    q->setGeometry(QRectF(q->x(), q->y(), 0, height()));
     859}
     860
     861qreal QGraphicsWidgetPrivate::height() const
     862{
     863    Q_Q(const QGraphicsWidget);
     864    return q->geometry().height();
     865}
     866
     867void QGraphicsWidgetPrivate::setHeight(qreal h)
     868{
     869    if (qIsNaN(h))
     870        return;
     871    Q_Q(QGraphicsWidget);
     872    if (q->geometry().height() == h)
     873        return;
     874
     875    QRectF oldGeom = q->geometry();
     876
     877    q->setGeometry(QRectF(q->x(), q->y(), width(), h));
     878}
     879
     880void QGraphicsWidgetPrivate::resetHeight()
     881{
     882    Q_Q(QGraphicsWidget);
     883    q->setGeometry(QRectF(q->x(), q->y(), width(), 0));
     884}
     885
    828886void QGraphicsWidgetPrivate::setGeometryFromSetPos()
    829887{
  • trunk/src/gui/graphicsview/qgraphicswidget_p.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    8181          polished(0),
    8282          inSetPos(0),
     83          autoFillBackground(0),
    8384          focusPolicy(Qt::NoFocus),
    8485          focusNext(0),
     
    131132    bool hasDecoration() const;
    132133
     134    // Private Properties
     135    qreal width() const;
     136    void setWidth(qreal);
     137    void resetWidth();
     138
     139    qreal height() const;
     140    void setHeight(qreal);
     141    void resetHeight();
    133142    void setGeometryFromSetPos();
    134143
     
    175184    quint32 polished: 1;
    176185    quint32 inSetPos : 1;
     186    quint32 autoFillBackground : 1;
    177187
    178188    // Focus
  • trunk/src/gui/graphicsview/qgridlayoutengine.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    167167}
    168168
    169 void QGridLayoutRowData::distributeMultiCells()
     169void QGridLayoutRowData::distributeMultiCells(const QGridLayoutRowInfo &rowInfo)
    170170{
    171171    MultiCellMap::const_iterator i = multiCellMap.constBegin();
     
    186186            if (extra > 0.0) {
    187187                calculateGeometries(start, end, box.q_sizes(j), dummy.data(), newSizes.data(),
    188                                     0, totalBox);
     188                                    0, totalBox, rowInfo);
    189189
    190190                for (int k = 0; k < span; ++k)
     
    195195        for (int k = 0; k < span; ++k) {
    196196            boxes[start + k].combine(extras[k]);
    197             stretches[start + k] = qMax(stretches[start + k], stretch);
     197            if (stretch != 0)
     198                stretches[start + k] = qMax(stretches[start + k], stretch);
    198199        }
    199200    }
     
    203204void QGridLayoutRowData::calculateGeometries(int start, int end, qreal targetSize, qreal *positions,
    204205                                             qreal *sizes, qreal *descents,
    205                                              const QGridLayoutBox &totalBox)
     206                                             const QGridLayoutBox &totalBox,
     207                                             const QGridLayoutRowInfo &rowInfo)
    206208{
    207209    Q_ASSERT(end > start);
    208210
    209     targetSize = qBound(totalBox.q_minimumSize, targetSize, totalBox.q_maximumSize);
     211    targetSize = qMax(totalBox.q_minimumSize, targetSize);
    210212
    211213    int n = end - start;
     
    247249        }
    248250    } else {
    249         stealBox(start, end, PreferredSize, positions, sizes);
    250 
    251         sumAvailable = targetSize - totalBox.q_preferredSize;
     251        bool isLargerThanMaximum = (targetSize > totalBox.q_maximumSize);
     252        if (isLargerThanMaximum) {
     253            stealBox(start, end, MaximumSize, positions, sizes);
     254            sumAvailable = targetSize - totalBox.q_maximumSize;
     255        } else {
     256            stealBox(start, end, PreferredSize, positions, sizes);
     257            sumAvailable = targetSize - totalBox.q_preferredSize;
     258        }
     259
    252260        if (sumAvailable > 0.0) {
     261            qreal sumCurrentAvailable = sumAvailable;
    253262            bool somethingHasAMaximumSize = false;
    254263
    255             qreal sumPreferredSizes = 0.0;
     264            qreal sumSizes = 0.0;
    256265            for (int i = 0; i < n; ++i)
    257                 sumPreferredSizes += sizes[i];
     266                sumSizes += sizes[i];
    258267
    259268            for (int i = 0; i < n; ++i) {
     
    265274
    266275                const QGridLayoutBox &box = boxes.at(start + i);
    267                 qreal desired = box.q_maximumSize - box.q_preferredSize;
     276                qreal boxSize;
     277
     278                qreal desired;
     279                if (isLargerThanMaximum) {
     280                    boxSize = box.q_maximumSize;
     281                    desired = rowInfo.boxes.value(start + i).q_maximumSize - boxSize;
     282                } else {
     283                    boxSize = box.q_preferredSize;
     284                    desired = box.q_maximumSize - boxSize;
     285                }
    268286                if (desired == 0.0) {
    269287                    newSizes[i] = sizes[i];
     
    284302                        factors[i] = 0.0;
    285303                    } else {
    286                         qreal ultimatePreferredSize;
    287                         qreal ultimateSumPreferredSizes;
    288                         qreal x = ((stretch * sumPreferredSizes)
    289                                    - (sumStretches * box.q_preferredSize))
     304                        qreal ultimateSize;
     305                        qreal ultimateSumSizes;
     306                        qreal x = ((stretch * sumSizes)
     307                                   - (sumStretches * boxSize))
    290308                                  / (sumStretches - stretch);
    291309                        if (x >= 0.0) {
    292                             ultimatePreferredSize = box.q_preferredSize + x;
    293                             ultimateSumPreferredSizes = sumPreferredSizes + x;
     310                            ultimateSize = boxSize + x;
     311                            ultimateSumSizes = sumSizes + x;
    294312                        } else {
    295                             ultimatePreferredSize = box.q_preferredSize;
    296                             ultimateSumPreferredSizes = (sumStretches * box.q_preferredSize)
     313                            ultimateSize = boxSize;
     314                            ultimateSumSizes = (sumStretches * boxSize)
    297315                                                        / stretch;
    298316                        }
     
    303321                            during the transition).
    304322                        */
    305                         ultimatePreferredSize = ultimatePreferredSize * 3 / 2;
    306                         ultimateSumPreferredSizes = ultimateSumPreferredSizes * 3 / 2;
    307 
    308                         qreal ultimateFactor = (stretch * ultimateSumPreferredSizes
    309                                                 / sumStretches)
    310                                                - (box.q_preferredSize);
    311                         qreal transitionalFactor = sumAvailable
    312                                                    * (ultimatePreferredSize - box.q_preferredSize)
    313                                                    / (ultimateSumPreferredSizes
    314                                                       - sumPreferredSizes);
    315 
    316                         qreal alpha = qMin(sumAvailable,
    317                                            ultimateSumPreferredSizes - sumPreferredSizes);
    318                         qreal beta = ultimateSumPreferredSizes - sumPreferredSizes;
    319 
    320                         factors[i] = ((alpha * ultimateFactor)
    321                                       + ((beta - alpha) * transitionalFactor)) / beta;
     323                        ultimateSize = ultimateSize * 3 / 2;
     324                        ultimateSumSizes = ultimateSumSizes * 3 / 2;
     325
     326                        qreal beta = ultimateSumSizes - sumSizes;
     327                        if (!beta) {
     328                            factors[i] = 1;
     329                        } else {
     330                            qreal alpha = qMin(sumCurrentAvailable, beta);
     331                            qreal ultimateFactor = (stretch * ultimateSumSizes / sumStretches)
     332                                                   - (boxSize);
     333                            qreal transitionalFactor = sumCurrentAvailable * (ultimateSize - boxSize) / beta;
     334
     335                            factors[i] = ((alpha * ultimateFactor)
     336                                          + ((beta - alpha) * transitionalFactor)) / beta;
     337                        }
     338
    322339                    }
    323340                    sumFactors += factors[i];
    324                     if (desired < sumAvailable)
     341                    if (desired < sumCurrentAvailable)
    325342                        somethingHasAMaximumSize = true;
    326343
     
    337354                        continue;
    338355
    339                     const QGridLayoutBox &box = boxes.at(start + i);
    340                     qreal avail = sumAvailable * factors[i] / sumFactors;
    341                     if (sizes[i] + avail >= box.q_maximumSize) {
    342                         newSizes[i] = box.q_maximumSize;
    343                         sumAvailable -= box.q_maximumSize - sizes[i];
     356                    qreal maxBoxSize;
     357                    if (isLargerThanMaximum)
     358                        maxBoxSize = rowInfo.boxes.value(start + i).q_maximumSize;
     359                    else
     360                        maxBoxSize = boxes.at(start + i).q_maximumSize;
     361
     362                    qreal avail = sumCurrentAvailable * factors[i] / sumFactors;
     363                    if (sizes[i] + avail >= maxBoxSize) {
     364                        newSizes[i] = maxBoxSize;
     365                        sumCurrentAvailable -= maxBoxSize - sizes[i];
    344366                        sumFactors -= factors[i];
    345                         keepGoing = (sumAvailable > 0.0);
     367                        keepGoing = (sumCurrentAvailable > 0.0);
    346368                        if (!keepGoing)
    347369                            break;
     
    353375                if (newSizes[i] < 0.0) {
    354376                    qreal delta = (sumFactors == 0.0) ? 0.0
    355                                                       : sumAvailable * factors[i] / sumFactors;
     377                                                      : sumCurrentAvailable * factors[i] / sumFactors;
    356378                    newSizes[i] = sizes[i] + delta;
    357379                }
     
    546568}
    547569
     570/*
     571  returns true if the size policy returns true for either hasHeightForWidth()
     572  or hasWidthForHeight()
     573 */
     574bool QGridLayoutItem::hasDynamicConstraint() const
     575{
     576    return QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasHeightForWidth()
     577        || QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasWidthForHeight();
     578}
     579
     580Qt::Orientation QGridLayoutItem::dynamicConstraintOrientation() const
     581{
     582    if (QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasHeightForWidth())
     583        return Qt::Vertical;
     584    else //if (QGraphicsLayoutItemPrivate::get(q_layoutItem)->hasWidthForHeight())
     585        return Qt::Horizontal;
     586}
     587
    548588QSizePolicy::ControlTypes QGridLayoutItem::controlTypes(LayoutSide /* side */) const
    549589{
     
    614654        qreal cellHeight = height;
    615655
    616         QSizeF size = effectiveMaxSize().boundedTo(QSizeF(cellWidth, cellHeight));
     656
     657        QSizeF size = effectiveMaxSize(QSizeF(-1,-1));
     658        if (hasDynamicConstraint()) {
     659            if (dynamicConstraintOrientation() == Qt::Vertical) {
     660               if (size.width() > cellWidth)
     661                   size = effectiveMaxSize(QSizeF(cellWidth, -1));
     662            } else if (size.height() > cellHeight) {
     663                size = effectiveMaxSize(QSizeF(-1, cellHeight));
     664            }
     665        }
     666        size = size.boundedTo(QSizeF(cellWidth, cellHeight));
    617667        width = size.width();
    618668        height = size.height();
     
    676726    (since it only evaluates the hints, as the name implies)
    677727*/
    678 QSizeF QGridLayoutItem::effectiveMaxSize() const
    679 {
    680     QSizeF size;
     728QSizeF QGridLayoutItem::effectiveMaxSize(const QSizeF &constraint) const
     729{
     730    QSizeF size = constraint;
    681731    bool vGrow = (sizePolicy(Qt::Vertical) & QSizePolicy::GrowFlag) == QSizePolicy::GrowFlag;
    682732    bool hGrow = (sizePolicy(Qt::Horizontal) & QSizePolicy::GrowFlag) == QSizePolicy::GrowFlag;
    683733    if (!vGrow || !hGrow) {
    684         QSizeF pref = layoutItem()->effectiveSizeHint(Qt::PreferredSize);
     734        QSizeF pref = layoutItem()->effectiveSizeHint(Qt::PreferredSize, constraint);
    685735        if (!vGrow)
    686736            size.setHeight(pref.height());
     
    690740
    691741    if (!size.isValid()) {
    692         QSizeF maxSize = layoutItem()->effectiveSizeHint(Qt::MaximumSize);
     742        QSizeF maxSize = layoutItem()->effectiveSizeHint(Qt::MaximumSize, size);
    693743        if (size.width() == -1)
    694744            size.setWidth(maxSize.width());
     
    10111061    q_cachedDataForStyleInfo.invalidate();
    10121062    q_cachedSize = QSizeF();
     1063    q_cachedConstraintOrientation = UnknownConstraint;
    10131064}
    10141065
     
    10751126
    10761127QSizeF QGridLayoutEngine::sizeHint(const QLayoutStyleInfo &styleInfo, Qt::SizeHint which,
    1077                                    const QSizeF & /* constraint */) const
    1078 {
    1079     ensureColumnAndRowData(styleInfo);
     1128                                   const QSizeF &constraint) const
     1129{
     1130    QGridLayoutBox sizehint_totalBoxes[NOrientations];
     1131
     1132    bool sizeHintCalculated = false;
     1133
     1134    if (hasDynamicConstraint() && rowCount() > 0 && columnCount() > 0) {
     1135        if (constraintOrientation() == Qt::Vertical) {
     1136            //We have items whose height depends on their width
     1137            if (constraint.width() >= 0) {
     1138                if (q_cachedDataForStyleInfo != styleInfo)
     1139                    ensureColumnAndRowData(&q_columnData, &sizehint_totalBoxes[Hor], styleInfo, NULL, NULL, Qt::Horizontal);
     1140                else
     1141                    sizehint_totalBoxes[Hor] = q_totalBoxes[Hor];
     1142                QVector<qreal> sizehint_xx;
     1143                QVector<qreal> sizehint_widths;
     1144
     1145                sizehint_xx.resize(columnCount());
     1146                sizehint_widths.resize(columnCount());
     1147                qreal width = constraint.width();
     1148                //Calculate column widths and positions, and put results in q_xx.data() and q_widths.data() so that we can use this information as
     1149                //constraints to find the row heights
     1150                q_columnData.calculateGeometries(0, columnCount(), width, sizehint_xx.data(), sizehint_widths.data(),
     1151                        0, sizehint_totalBoxes[Hor], q_infos[Hor]);
     1152                ensureColumnAndRowData(&q_rowData, &sizehint_totalBoxes[Ver], styleInfo, sizehint_xx.data(), sizehint_widths.data(), Qt::Vertical);
     1153                sizeHintCalculated = true;
     1154            }
     1155        } else {
     1156            if (constraint.height() >= 0) {
     1157                //We have items whose width depends on their height
     1158                ensureColumnAndRowData(&q_rowData, &sizehint_totalBoxes[Ver], styleInfo, NULL, NULL, Qt::Vertical);
     1159                QVector<qreal> sizehint_yy;
     1160                QVector<qreal> sizehint_heights;
     1161
     1162                sizehint_yy.resize(rowCount());
     1163                sizehint_heights.resize(rowCount());
     1164                qreal height = constraint.height();
     1165                //Calculate row heights and positions, and put results in q_yy.data() and q_heights.data() so that we can use this information as
     1166                //constraints to find the column widths
     1167                q_rowData.calculateGeometries(0, rowCount(), height, sizehint_yy.data(), sizehint_heights.data(),
     1168                        0, sizehint_totalBoxes[Ver], q_infos[Ver]);
     1169                ensureColumnAndRowData(&q_columnData, &sizehint_totalBoxes[Hor], styleInfo, sizehint_yy.data(), sizehint_heights.data(), Qt::Vertical);
     1170                sizeHintCalculated = true;
     1171            }
     1172        }
     1173    }
     1174
     1175    if (!sizeHintCalculated) {
     1176        //No items with height for width, so it doesn't matter which order we do these in
     1177        if (q_cachedDataForStyleInfo != styleInfo) {
     1178            ensureColumnAndRowData(&q_columnData, &sizehint_totalBoxes[Hor], styleInfo, NULL, NULL, Qt::Horizontal);
     1179            ensureColumnAndRowData(&q_rowData, &sizehint_totalBoxes[Ver], styleInfo, NULL, NULL, Qt::Vertical);
     1180        } else {
     1181            sizehint_totalBoxes[Hor] = q_totalBoxes[Hor];
     1182            sizehint_totalBoxes[Ver] = q_totalBoxes[Ver];
     1183        }
     1184    }
    10801185
    10811186    switch (which) {
    10821187    case Qt::MinimumSize:
    1083         return QSizeF(q_totalBoxes[Hor].q_minimumSize, q_totalBoxes[Ver].q_minimumSize);
     1188        return QSizeF(sizehint_totalBoxes[Hor].q_minimumSize, sizehint_totalBoxes[Ver].q_minimumSize);
    10841189    case Qt::PreferredSize:
    1085         return QSizeF(q_totalBoxes[Hor].q_preferredSize, q_totalBoxes[Ver].q_preferredSize);
     1190        return QSizeF(sizehint_totalBoxes[Hor].q_preferredSize, sizehint_totalBoxes[Ver].q_preferredSize);
    10861191    case Qt::MaximumSize:
    1087         return QSizeF(q_totalBoxes[Hor].q_maximumSize, q_totalBoxes[Ver].q_maximumSize);
     1192        return QSizeF(sizehint_totalBoxes[Hor].q_maximumSize, sizehint_totalBoxes[Ver].q_maximumSize);
    10881193    case Qt::MinimumDescent:
    1089         return QSizeF(-1.0, q_totalBoxes[Hor].q_minimumDescent);    // ### doesn't work
     1194        return QSizeF(-1.0, sizehint_totalBoxes[Hor].q_minimumDescent);    // ### doesn't work
    10901195    default:
    10911196        break;
     
    12631368
    12641369void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData, const QLayoutStyleInfo &styleInfo,
     1370                                    qreal *colPositions, qreal *colSizes,
    12651371                                    Qt::Orientation orientation) const
    12661372{
     
    13681474                    if (effectiveRowSpan == 1) {
    13691475                        box = &rowBox;
    1370                         if (!userRowStretch)
     1476                        if (!userRowStretch && itemStretch != 0)
    13711477                            rowStretch = qMax(rowStretch, itemStretch);
    13721478                    } else {
     
    13761482                        multiCell.q_stretch = itemStretch;
    13771483                    }
    1378                     box->combine(item->box(orientation));
     1484                    // Items with constraints need to be passed the constraint
     1485                    if (colSizes && colPositions && item->hasDynamicConstraint() && orientation == item->dynamicConstraintOrientation()) {
     1486                        /* Get the width of the item by summing up the widths of the columns that it spans.
     1487                         * We need to have already calculated the widths of the columns by calling
     1488                         * q_columns->calculateGeometries() before hand and passing the value in the colSizes
     1489                         * and colPositions parameters.
     1490                         * The variable name is still colSizes even when it actually has the row sizes
     1491                         */
     1492                        qreal length = colSizes[item->lastColumn(orientation)];
     1493                        if (item->columnSpan(orientation) != 1)
     1494                            length += colPositions[item->lastColumn(orientation)] - colPositions[item->firstColumn(orientation)];
     1495                        box->combine(item->box(orientation, length));
     1496                    } else {
     1497                        box->combine(item->box(orientation));
     1498                    }
    13791499
    13801500                    if (effectiveRowSpan == 1) {
     
    15131633}
    15141634
    1515 void QGridLayoutEngine::ensureColumnAndRowData(const QLayoutStyleInfo &styleInfo) const
    1516 {
    1517     if (q_cachedDataForStyleInfo == styleInfo)
    1518         return;
    1519 
    1520     q_columnData.reset(columnCount());
    1521     q_rowData.reset(rowCount());
    1522 
    1523     fillRowData(&q_columnData, styleInfo, Qt::Horizontal);
    1524     fillRowData(&q_rowData, styleInfo, Qt::Vertical);
    1525 
    1526     q_columnData.distributeMultiCells();
    1527     q_rowData.distributeMultiCells();
    1528 
    1529     q_totalBoxes[Hor] = q_columnData.totalBox(0, columnCount());
    1530     q_totalBoxes[Ver] = q_rowData.totalBox(0, rowCount());
    1531 
    1532     q_cachedDataForStyleInfo = styleInfo;
     1635void QGridLayoutEngine::ensureColumnAndRowData(QGridLayoutRowData *rowData, QGridLayoutBox *totalBox,
     1636                                            const QLayoutStyleInfo &styleInfo,
     1637                                            qreal *colPositions, qreal *colSizes,
     1638                                            Qt::Orientation orientation) const
     1639{
     1640    rowData->reset(rowCount(orientation));
     1641    fillRowData(rowData, styleInfo, colPositions, colSizes, orientation);
     1642    const QGridLayoutRowInfo &rowInfo = q_infos[orientation == Qt::Vertical];
     1643    rowData->distributeMultiCells(rowInfo);
     1644    *totalBox = rowData->totalBox(0, rowCount(orientation));
     1645        //We have items whose width depends on their height
     1646}
     1647
     1648/**
     1649   returns false if the layout has contradicting constraints (i.e. some items with a horizontal
     1650   constraint and other items with a vertical constraint)
     1651 */
     1652bool QGridLayoutEngine::ensureDynamicConstraint() const
     1653{
     1654    if (q_cachedConstraintOrientation == UnknownConstraint) {
     1655        for (int i = q_items.count() - 1; i >= 0; --i) {
     1656            QGridLayoutItem *item = q_items.at(i);
     1657            if (item->hasDynamicConstraint()) {
     1658                Qt::Orientation itemConstraintOrientation = item->dynamicConstraintOrientation();
     1659                if (q_cachedConstraintOrientation == UnknownConstraint) {
     1660                    q_cachedConstraintOrientation = itemConstraintOrientation;
     1661                } else if (q_cachedConstraintOrientation != itemConstraintOrientation) {
     1662                    q_cachedConstraintOrientation = UnfeasibleConstraint;
     1663                    qWarning("QGridLayoutEngine: Unfeasible, cannot mix horizontal and"
     1664                             " vertical constraint in the same layout");
     1665                    return false;
     1666                }
     1667            }
     1668        }
     1669        if (q_cachedConstraintOrientation == UnknownConstraint)
     1670            q_cachedConstraintOrientation = NoConstraint;
     1671    }
     1672    return true;
     1673}
     1674
     1675bool QGridLayoutEngine::hasDynamicConstraint() const
     1676{
     1677    if (!ensureDynamicConstraint())
     1678        return false;
     1679    return q_cachedConstraintOrientation != NoConstraint;
     1680}
     1681
     1682/*
     1683 * return value is only valid if hasConstraint() returns true
     1684 */
     1685Qt::Orientation QGridLayoutEngine::constraintOrientation() const
     1686{
     1687    (void)ensureDynamicConstraint();
     1688    return (Qt::Orientation)q_cachedConstraintOrientation;
    15331689}
    15341690
     
    15361692                                         const QSizeF &size) const
    15371693{
    1538     ensureColumnAndRowData(styleInfo);
    1539     if (q_cachedSize == size)
     1694    if (q_cachedDataForStyleInfo == styleInfo && q_cachedSize == size)
    15401695        return;
    15411696
     1697    q_cachedDataForStyleInfo = styleInfo;
     1698    q_cachedSize = size;
     1699
    15421700    q_xx.resize(columnCount());
     1701    q_widths.resize(columnCount());
    15431702    q_yy.resize(rowCount());
    1544     q_widths.resize(columnCount());
    15451703    q_heights.resize(rowCount());
    15461704    q_descents.resize(rowCount());
    1547     q_columnData.calculateGeometries(0, columnCount(), size.width(), q_xx.data(), q_widths.data(),
    1548                                      0, q_totalBoxes[Hor]);
    1549     q_rowData.calculateGeometries(0, rowCount(), size.height(), q_yy.data(), q_heights.data(),
    1550                                   q_descents.data(), q_totalBoxes[Ver]);
    1551 
    1552     q_cachedSize = size;
     1705
     1706    if (constraintOrientation() != Qt::Horizontal) {
     1707        //We might have items whose width depends on their height
     1708        ensureColumnAndRowData(&q_columnData, &q_totalBoxes[Hor], styleInfo, NULL, NULL, Qt::Horizontal);
     1709        //Calculate column widths and positions, and put results in q_xx.data() and q_widths.data() so that we can use this information as
     1710        //constraints to find the row heights
     1711        q_columnData.calculateGeometries(0, columnCount(), size.width(), q_xx.data(), q_widths.data(),
     1712                0, q_totalBoxes[Hor], q_infos[Hor] );
     1713        ensureColumnAndRowData(&q_rowData, &q_totalBoxes[Ver], styleInfo, q_xx.data(), q_widths.data(), Qt::Vertical);
     1714        //Calculate row heights and positions, and put results in q_yy.data() and q_heights.data()
     1715        q_rowData.calculateGeometries(0, rowCount(), size.height(), q_yy.data(), q_heights.data(),
     1716                q_descents.data(), q_totalBoxes[Ver], q_infos[Ver]);
     1717    } else {
     1718        //We have items whose height depends on their width
     1719        ensureColumnAndRowData(&q_rowData, &q_totalBoxes[Ver], styleInfo, NULL, NULL, Qt::Vertical);
     1720        //Calculate row heights and positions, and put results in q_yy.data() and q_heights.data() so that we can use this information as
     1721        //constraints to find the column widths
     1722        q_rowData.calculateGeometries(0, rowCount(), size.height(), q_yy.data(), q_heights.data(),
     1723                q_descents.data(), q_totalBoxes[Ver], q_infos[Ver]);
     1724        ensureColumnAndRowData(&q_columnData, &q_totalBoxes[Hor], styleInfo, q_yy.data(), q_heights.data(), Qt::Horizontal);
     1725        //Calculate row heights and positions, and put results in q_yy.data() and q_heights.data()
     1726        q_columnData.calculateGeometries(0, columnCount(), size.width(), q_xx.data(), q_widths.data(),
     1727                0, q_totalBoxes[Hor], q_infos[Hor]);
     1728    }
    15531729}
    15541730
  • trunk/src/gui/graphicsview/qgridlayoutengine_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    9090    Right,
    9191    Bottom
     92};
     93
     94enum {
     95    NoConstraint,
     96    HorizontalConstraint,   // Width depends on the height
     97    VerticalConstraint,     // Height depends on the width
     98    UnknownConstraint,      // need to update cache
     99    UnfeasibleConstraint    // not feasible, it be has some items with Vertical and others with Horizontal constraints
    92100};
    93101
     
    217225typedef QMap<QPair<int, int>, QGridLayoutMultiCellData> MultiCellMap;
    218226
     227class QGridLayoutRowInfo;
     228
    219229class QGridLayoutRowData
    220230{
    221231public:
    222232    void reset(int count);
    223     void distributeMultiCells();
     233    void distributeMultiCells(const QGridLayoutRowInfo &rowInfo);
    224234    void calculateGeometries(int start, int end, qreal targetSize, qreal *positions, qreal *sizes,
    225                              qreal *descents, const QGridLayoutBox &totalBox);
     235                             qreal *descents, const QGridLayoutBox &totalBox,
     236                             const QGridLayoutRowInfo &rowInfo);
    226237    QGridLayoutBox totalBox(int start, int end) const;
    227238    void stealBox(int start, int end, int which, qreal *positions, qreal *sizes);
     
    271282
    272283    QSizePolicy::Policy sizePolicy(Qt::Orientation orientation) const;
     284
     285    bool hasDynamicConstraint() const;
     286    Qt::Orientation dynamicConstraintOrientation() const;
     287
    273288    QSizePolicy::ControlTypes controlTypes(LayoutSide side) const;
    274289    QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
     
    281296    void transpose();
    282297    void insertOrRemoveRows(int row, int delta, Qt::Orientation orientation = Qt::Vertical);
    283     QSizeF effectiveMaxSize() const;
     298    QSizeF effectiveMaxSize(const QSizeF &constraint) const;
    284299
    285300#ifdef QT_DEBUG
     
    364379    inline void insertRow(int row, Qt::Orientation orientation = Qt::Vertical)
    365380        { insertOrRemoveRows(row, +1, orientation); }
    366     inline void removeRow(int row, Qt::Orientation orientation = Qt::Vertical)
    367         { insertOrRemoveRows(row, -1, orientation); }
     381    inline void removeRows(int row, int count, Qt::Orientation orientation)
     382        { insertOrRemoveRows(row, -count, orientation); }
    368383
    369384    void invalidate();
     
    373388    QSizeF sizeHint(const QLayoutStyleInfo &styleInfo, Qt::SizeHint which,
    374389                    const QSizeF &constraint) const;
     390
     391    // heightForWidth / widthForHeight support
     392    QSizeF dynamicallyConstrainedSizeHint(Qt::SizeHint which, const QSizeF &constraint) const;
     393    bool ensureDynamicConstraint() const;
     394    bool hasDynamicConstraint() const;
     395    Qt::Orientation constraintOrientation() const;
     396
     397
    375398    QSizePolicy::ControlTypes controlTypes(LayoutSide side) const;
    376399    void transpose();
     
    391414    void insertOrRemoveRows(int row, int delta, Qt::Orientation orientation = Qt::Vertical);
    392415    void fillRowData(QGridLayoutRowData *rowData, const QLayoutStyleInfo &styleInfo,
    393                      Qt::Orientation orientation = Qt::Vertical) const;
     416                                    qreal *colPositions, qreal *colSizes,
     417                                    Qt::Orientation orientation = Qt::Vertical) const;
    394418    void ensureEffectiveFirstAndLastRows() const;
    395     void ensureColumnAndRowData(const QLayoutStyleInfo &styleInfo) const;
     419    void ensureColumnAndRowData(QGridLayoutRowData *rowData, QGridLayoutBox *totalBox,
     420                                            const QLayoutStyleInfo &styleInfo,
     421                                            qreal *colPositions, qreal *colSizes,
     422                                            Qt::Orientation orientation) const;
     423
    396424    void ensureGeometries(const QLayoutStyleInfo &styleInfo, const QSizeF &size) const;
    397425
     
    406434    mutable int q_cachedEffectiveFirstRows[NOrientations];
    407435    mutable int q_cachedEffectiveLastRows[NOrientations];
     436    mutable quint8 q_cachedConstraintOrientation : 3;
    408437
    409438    // Layout item input
  • trunk/src/gui/graphicsview/qsimplex_p.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/gui/graphicsview/qsimplex_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
Note: See TracChangeset for help on using the changeset viewer.