diff options
author | Andreas Aardal Hanssen <andreas.aardal.hanssen@nokia.com> | 2009-06-03 14:34:58 (GMT) |
---|---|---|
committer | Andreas Aardal Hanssen <andreas.aardal.hanssen@nokia.com> | 2009-06-09 07:33:01 (GMT) |
commit | 728179ed60b43187d28c77a2d6930a74a62791d6 (patch) | |
tree | 9b48a4077f356138ce5c536b06d9cdcda2fe7af3 /src/gui/graphicsview | |
parent | 1598ef761a8c3f0c9cccf5318e3de30f6c50880f (diff) | |
download | Qt-728179ed60b43187d28c77a2d6930a74a62791d6.zip Qt-728179ed60b43187d28c77a2d6930a74a62791d6.tar.gz Qt-728179ed60b43187d28c77a2d6930a74a62791d6.tar.bz2 |
Add QGraphicsItem::itemChangeEnabled().
This function allows the user to disable notifications for item changes.
In QSimpleCanvasItem, all notifications are disabled by default, and
you can enable them one at a time. QGraphicsItem's behavior is to by
default enable all notifications.
A side effect of this change is that I've removed one optimization in
favor of another: by not constructing a QVariant at all when there's no
notification we get maximum performance, at the expense of constructing
it twice if there is a notification.
Diffstat (limited to 'src/gui/graphicsview')
-rw-r--r-- | src/gui/graphicsview/qgraphicsitem.cpp | 251 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsitem.h | 5 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsitem_p.h | 4 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsscene.cpp | 30 |
4 files changed, 202 insertions, 88 deletions
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 57ca2ef..2eb5150 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -39,8 +39,6 @@ ** ****************************************************************************/ -#define QGRAPHICSITEM_NO_ITEMCHANGE - /*! \class QGraphicsItem \brief The QGraphicsItem class is the base class for all graphical @@ -851,11 +849,13 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool de if (newParent == parent) return; - const QVariant newParentVariant(q->itemChange(QGraphicsItem::ItemParentChange, - qVariantFromValue<QGraphicsItem *>(newParent))); - newParent = qVariantValue<QGraphicsItem *>(newParentVariant); - if (newParent == parent) - return; + bool notify = q->itemChangeEnabled(QGraphicsItem::ItemParentChange); + if (notify) { + newParent = qVariantValue<QGraphicsItem *>(q->itemChange(QGraphicsItem::ItemParentChange, + qVariantFromValue<QGraphicsItem *>(newParent))); + if (newParent == parent) + return; + } if (QGraphicsWidget *w = isWidget ? static_cast<QGraphicsWidget *>(q) : q->parentWidget()) { // Update the child focus chain; when reparenting a widget that has a @@ -955,7 +955,8 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool de dirtySceneTransform = 1; // Deliver post-change notification - q->itemChange(QGraphicsItem::ItemParentHasChanged, newParentVariant); + if (notify) + q->itemChange(QGraphicsItem::ItemParentHasChanged, qVariantFromValue<QGraphicsItem *>(newParent)); } /*! @@ -1393,9 +1394,14 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) // Notify change and check for adjustment. if (quint32(d_ptr->flags) == quint32(flags)) return; - flags = GraphicsItemFlags(itemChange(ItemFlagsChange, quint32(flags)).toUInt()); - if (quint32(d_ptr->flags) == quint32(flags)) - return; + + // Notify + bool notify = itemChangeEnabled(ItemFlagsChange); + if (notify) { + flags = GraphicsItemFlags(itemChange(ItemFlagsChange, quint32(flags)).toUInt()); + if (quint32(d_ptr->flags) == quint32(flags)) + return; + } // Flags that alter the geometry of the item (or its children). const quint32 geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations); @@ -1443,7 +1449,78 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) } // Notify change. - itemChange(ItemFlagsHaveChanged, quint32(flags)); + if (notify) + itemChange(ItemFlagsHaveChanged, quint32(flags)); +} + +static const int itemChangeBits[] = { + /* ItemPositionChange */ 1 << 1, + /* ItemMatrixChange */ 1 << 2, + /* ItemVisibleChange */ 1 << 3, + /* ItemEnabledChange */ 1 << 4, + /* ItemSelectedChange */ 1 << 5, + /* ItemParentChange */ 1 << 6, + /* ItemChildAddedChange */ 1 << 7, + /* ItemChildRemovedChange */ 1 << 8, + /* ItemTransformChange */ 1 << 9, + /* ItemPositionHasChanged */ 1 << 1, + /* ItemTransformHasChanged */ 1 << 9, + /* ItemSceneChange */ 1 << 10, + /* ItemVisibleHasChanged */ 1 << 3, + /* ItemEnabledHasChanged */ 1 << 4, + /* ItemSelectedHasChanged */ 1 << 5, + /* ItemParentHasChanged */ 1 << 6, + /* ItemSceneHasChanged */ 1 << 10, + /* ItemCursorChange */ 1 << 11, + /* ItemCursorHasChanged */ 1 << 11, + /* ItemToolTipChange */ 1 << 12, + /* ItemToolTipHasChanged */ 1 << 12, + /* ItemFlagsChange */ 1 << 13, + /* ItemFlagsHaveChanged */ 1 << 13, + /* ItemZValueChange */ 1 << 14, + /* ItemZValueHasChanged */ 1 << 14, + /* ItemOpacityChange */ 1 << 15, + /* ItemOpacityHasChanged */ 1 << 15 +}; + +/*! + Returns true if \a change is enabled (i.e., QGraphicsItem will call + itemChange() whenever the respective change occurs); otherwise returns + false. + + \sa setItemChangeEnabled(), setItemChangesEnabled(), itemChange() +*/ +bool QGraphicsItem::itemChangeEnabled(GraphicsItemChange change) const +{ + return d_ptr->itemChangesEnabled & itemChangeBits[change]; +} + +/*! + If \a enabled is true, notifications for \a change are enabled; otherwise + they are disabled. By default, QGraphicsItem sends notifications for all + changes by calling itemChange(). + + \sa itemChangeEnabled(), setItemChangesEnabled(), itemChange() +*/ +void QGraphicsItem::setItemChangeEnabled(GraphicsItemChange change, bool enabled) +{ + if (enabled) { + d_ptr->itemChangesEnabled |= itemChangeBits[change]; + } else { + d_ptr->itemChangesEnabled &= itemChangeBits[change]; + } +} + +/*! + If \a enabled is true, all item change notifications are enabled; + otherwise, they are disabled. You can toggle individual notifications by + calling setItemChangeEnabled(). + + \sa itemChangeEnabled(), itemChange() +*/ +void QGraphicsItem::setItemChangesEnabled(bool enabled) +{ + d_ptr->itemChangesEnabled = enabled ? 0xffff : 0; } /*! @@ -1532,9 +1609,13 @@ QString QGraphicsItem::toolTip() const */ void QGraphicsItem::setToolTip(const QString &toolTip) { - const QVariant toolTipVariant(itemChange(ItemToolTipChange, toolTip)); - d_ptr->setExtra(QGraphicsItemPrivate::ExtraToolTip, toolTipVariant.toString()); - itemChange(ItemToolTipHasChanged, toolTipVariant); + bool notify = itemChangeEnabled(ItemToolTipChange); + QVariant toolTipVariant = toolTip; + if (notify) + toolTipVariant = itemChange(ItemToolTipChange, toolTipVariant); + d_ptr->setExtra(QGraphicsItemPrivate::ExtraToolTip, toolTipVariant); + if (notify) + itemChange(ItemToolTipHasChanged, toolTipVariant); } #endif // QT_NO_TOOLTIP @@ -1576,8 +1657,11 @@ QCursor QGraphicsItem::cursor() const */ void QGraphicsItem::setCursor(const QCursor &cursor) { - const QVariant cursorVariant(itemChange(ItemCursorChange, qVariantFromValue<QCursor>(cursor))); - d_ptr->setExtra(QGraphicsItemPrivate::ExtraCursor, qVariantValue<QCursor>(cursorVariant)); + bool notify = itemChangeEnabled(ItemCursorChange); + QVariant cursorVariant = qVariantFromValue<QCursor>(cursor); + if (notify) + cursorVariant = itemChange(ItemCursorChange, cursorVariant); + d_ptr->setExtra(QGraphicsItemPrivate::ExtraCursor, cursorVariant); d_ptr->hasCursor = 1; if (d_ptr->scene) { d_ptr->scene->d_func()->allItemsUseDefaultCursor = false; @@ -1596,7 +1680,8 @@ void QGraphicsItem::setCursor(const QCursor &cursor) } } } - itemChange(ItemCursorHasChanged, cursorVariant); + if (notify) + itemChange(ItemCursorHasChanged, cursorVariant); } /*! @@ -1693,10 +1778,12 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo if (parent && newVisible && !parent->d_ptr->visible) return; + // Notify + bool notify = q->itemChangeEnabled(QGraphicsItem::ItemVisibleChange); + if (notify) + newVisible = q_ptr->itemChange(QGraphicsItem::ItemVisibleChange, quint32(newVisible)).toBool(); + // Modify the property. - const QVariant newVisibleVariant(q_ptr->itemChange(QGraphicsItem::ItemVisibleChange, - quint32(newVisible))); - newVisible = newVisibleVariant.toBool(); if (visible == quint32(newVisible)) return; visible = newVisible; @@ -1763,7 +1850,8 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo } // Deliver post-change notification. - q_ptr->itemChange(QGraphicsItem::ItemVisibleHasChanged, newVisibleVariant); + if (notify) + q_ptr->itemChange(QGraphicsItem::ItemVisibleHasChanged, newVisible); } /*! @@ -1869,9 +1957,10 @@ void QGraphicsItemPrivate::setEnabledHelper(bool newEnabled, bool explicitly, bo } // Modify the property. - const QVariant newEnabledVariant(q_ptr->itemChange(QGraphicsItem::ItemEnabledChange, - quint32(newEnabled))); - enabled = newEnabledVariant.toBool(); + bool notify = q_ptr->itemChangeEnabled(QGraphicsItem::ItemEnabledChange); + if (notify) + newEnabled = q_ptr->itemChange(QGraphicsItem::ItemEnabledChange, quint32(newEnabled)).toBool(); + enabled = newEnabled; // Schedule redraw. if (update && scene) @@ -1883,7 +1972,8 @@ void QGraphicsItemPrivate::setEnabledHelper(bool newEnabled, bool explicitly, bo } // Deliver post-change notification. - q_ptr->itemChange(QGraphicsItem::ItemEnabledHasChanged, newEnabledVariant); + if (notify) + q_ptr->itemChange(QGraphicsItem::ItemEnabledHasChanged, newEnabled); } /*! @@ -1970,10 +2060,13 @@ void QGraphicsItem::setSelected(bool selected) selected = false; if (d_ptr->selected == selected) return; - const QVariant newSelectedVariant(itemChange(ItemSelectedChange, quint32(selected))); - bool newSelected = newSelectedVariant.toBool(); - if (d_ptr->selected == newSelected) - return; + bool notify = itemChangeEnabled(ItemSelectedChange); + bool newSelected = selected; + if (notify) { + newSelected = itemChange(ItemSelectedChange, quint32(selected)).toBool(); + if (d_ptr->selected == newSelected) + return; + } d_ptr->selected = newSelected; if (d_ptr->scene) { @@ -1990,7 +2083,8 @@ void QGraphicsItem::setSelected(bool selected) } // Deliver post-change notification. - itemChange(QGraphicsItem::ItemSelectedHasChanged, newSelectedVariant); + if (notify) + itemChange(QGraphicsItem::ItemSelectedHasChanged, newSelected); } /*! @@ -2056,13 +2150,12 @@ qreal QGraphicsItem::effectiveOpacity() const */ void QGraphicsItem::setOpacity(qreal opacity) { - // Notify change. -#ifndef QGRAPHICSITEM_NO_ITEMCHANGE - const QVariant newOpacityVariant(itemChange(ItemOpacityChange, double(opacity))); - qreal newOpacity = newOpacityVariant.toDouble(); -#else qreal newOpacity = opacity; -#endif + + // Notify + bool notify = itemChangeEnabled(ItemOpacityChange); + if (notify) + newOpacity = itemChange(ItemOpacityChange, double(newOpacity)).toDouble(); // Normalize. newOpacity = qBound<qreal>(0.0, newOpacity, 1.0); @@ -2073,10 +2166,9 @@ void QGraphicsItem::setOpacity(qreal opacity) d_ptr->opacity = newOpacity; - // Notify change. -#ifndef QGRAPHICSITEM_NO_ITEMCHANGE - itemChange(ItemOpacityHasChanged, newOpacity); -#endif + // Notify + if (notify) + itemChange(ItemOpacityHasChanged, newOpacity); // Update. if (d_ptr->scene) @@ -2525,15 +2617,15 @@ void QGraphicsItemPrivate::setPosHelper(const QPointF &pos) if (this->pos == pos) return; - // Notify the item that the position is changing. -#ifndef QGRAPHICSITEM_NO_ITEMCHANGE - const QVariant newPosVariant(q->itemChange(QGraphicsItem::ItemPositionChange, pos)); - QPointF newPos = newPosVariant.toPointF(); - if (newPos == this->pos) - return; -#else QPointF newPos = pos; -#endif + + // Notify + bool notify = q->itemChangeEnabled(QGraphicsItem::ItemPositionChange); + if (notify) { + newPos = q->itemChange(QGraphicsItem::ItemPositionChange, pos).toPointF(); + if (newPos == this->pos) + return; + } // Update and repositition. inSetPosHelper = 1; @@ -2544,9 +2636,9 @@ void QGraphicsItemPrivate::setPosHelper(const QPointF &pos) dirtySceneTransform = 1; // Send post-notification. -#ifndef QGRAPHICSITEM_NO_ITEMCHANGE - q->itemChange(QGraphicsItem::ItemPositionHasChanged, newPosVariant); -#endif + if (notify) + q->itemChange(QGraphicsItem::ItemPositionHasChanged, newPos); + inSetPosHelper = 0; } @@ -2887,21 +2979,21 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co */ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) { - if(!d_ptr->transform) + if (!d_ptr->transform) d_ptr->transform = new QTransform; QTransform newTransform(combine ? QTransform(matrix) * *d_ptr->transform : QTransform(matrix)); - if(*d_ptr->transform == newTransform) + if (*d_ptr->transform == newTransform) return; // Notify the item that the transformation matrix is changing. -#ifndef QGRAPHICSITEM_NO_ITEMCHANGE - const QVariant newTransformVariant(itemChange(ItemTransformChange, - qVariantFromValue<QTransform>(newTransform))); - newTransform = qVariantValue<QTransform>(newTransformVariant); - if (*d_ptr->transform == newTransform) - return; -#endif + bool notify = itemChangeEnabled(ItemMatrixChange); + if (notify) { + newTransform = QTransform(qVariantValue<QMatrix>(itemChange(ItemMatrixChange, + qVariantFromValue<QMatrix>(newTransform.toAffine())))); + if (*d_ptr->transform == newTransform) + return; + } // Update and set the new transformation. prepareGeometryChange(); @@ -2909,9 +3001,8 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) d_ptr->dirtySceneTransform = 1; // Send post-notification. -#ifndef QGRAPHICSITEM_NO_ITEMCHANGE - itemChange(ItemTransformHasChanged, newTransformVariant); -#endif + if (notify) + itemChange(ItemTransformHasChanged, qVariantFromValue<QTransform>(newTransform)); } /*! @@ -2936,19 +3027,20 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) */ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) { - if(!d_ptr->transform) + if (!d_ptr->transform) d_ptr->transform = new QTransform; QTransform newTransform(combine ? matrix * *d_ptr->transform : matrix); - if(*d_ptr->transform == newTransform) + if (*d_ptr->transform == newTransform) return; // Notify the item that the transformation matrix is changing. - const QVariant newTransformVariant(itemChange(ItemTransformChange, - qVariantFromValue<QTransform>(newTransform))); - newTransform = qVariantValue<QTransform>(newTransformVariant); - if (*d_ptr->transform == newTransform) - return; + bool notify = itemChangeEnabled(ItemTransformChange); + if (notify) { + newTransform = qVariantValue<QTransform>(itemChange(ItemTransformChange, qVariantFromValue<QTransform>(newTransform))); + if (*d_ptr->transform == newTransform) + return; + } // Update and set the new transformation. prepareGeometryChange(); @@ -2956,7 +3048,8 @@ void QGraphicsItem::setTransform(const QTransform &matrix, bool combine) d_ptr->dirtySceneTransform = 1; // Send post-notification. - itemChange(ItemTransformHasChanged, newTransformVariant); + if (notify) + itemChange(ItemTransformHasChanged, qVariantFromValue(newTransform)); } /*! @@ -3129,10 +3222,13 @@ qreal QGraphicsItem::zValue() const */ void QGraphicsItem::setZValue(qreal z) { - const QVariant newZVariant(itemChange(ItemZValueChange, double(z))); - qreal newZ = qreal(newZVariant.toDouble()); - if (newZ == d_ptr->z) - return; + bool notify = itemChangeEnabled(ItemZValueChange); + qreal newZ = z; + if (notify) { + newZ = itemChange(ItemZValueChange, double(z)).toDouble(); + if (newZ == d_ptr->z) + return; + } d_ptr->z = newZ; d_ptr->needSortChildren = 1; @@ -3143,7 +3239,8 @@ void QGraphicsItem::setZValue(qreal z) d_ptr->scene->d_func()->invalidateSortCache(); } - itemChange(ItemZValueHasChanged, newZVariant); + if (notify) + itemChange(ItemZValueHasChanged, newZ); } /*! diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index 737ea80..7c87176 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -129,6 +129,7 @@ public: ItemZValueHasChanged, ItemOpacityChange, ItemOpacityHasChanged + // NB! Don't forget to increase d_ptr->itemChangesEnabled when adding a new entry. }; enum CacheMode { @@ -165,6 +166,10 @@ public: void setFlag(GraphicsItemFlag flag, bool enabled = true); void setFlags(GraphicsItemFlags flags); + bool itemChangeEnabled(GraphicsItemChange change) const; + void setItemChangeEnabled(GraphicsItemChange change, bool enabled); + void setItemChangesEnabled(bool enabled); + CacheMode cacheMode() const; void setCacheMode(CacheMode mode, const QSize &cacheSize = QSize()); diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index b0b940b..2752056 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -147,6 +147,7 @@ public: dirtyChildrenBoundingRect(1), paintedViewBoundingRectsNeedRepaint(0), dirtySceneTransform(1), + itemChangesEnabled(0xffff), globalStackingOrder(-1), q_ptr(0) { @@ -396,7 +397,8 @@ public: quint32 dirtyChildrenBoundingRect : 1; quint32 paintedViewBoundingRectsNeedRepaint : 1; quint32 dirtySceneTransform : 1; - quint32 padding : 18; // feel free to use + quint32 itemChangesEnabled : 16; + quint32 padding : 3; // feel free to use // Optional stacking order int globalStackingOrder; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 8641fe2..96800a3 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -666,8 +666,10 @@ void QGraphicsScenePrivate::_q_polishItems() const QVariant booleanTrueVariant(true); foreach (QGraphicsItem *item, unpolishedItems) { if (!item->d_ptr->explicitlyHidden) { - item->itemChange(QGraphicsItem::ItemVisibleChange, booleanTrueVariant); - item->itemChange(QGraphicsItem::ItemVisibleHasChanged, booleanTrueVariant); + if (item->itemChangeEnabled(QGraphicsItem::ItemVisibleChange)) { + item->itemChange(QGraphicsItem::ItemVisibleChange, booleanTrueVariant); + item->itemChange(QGraphicsItem::ItemVisibleHasChanged, booleanTrueVariant); + } } if (item->isWidget()) { QEvent event(QEvent::Polish); @@ -2950,9 +2952,12 @@ void QGraphicsScene::addItem(QGraphicsItem *item) // Notify the item that its scene is changing, and allow the item to // react. - const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange, - qVariantFromValue<QGraphicsScene *>(this))); - QGraphicsScene *targetScene = qVariantValue<QGraphicsScene *>(newSceneVariant); + QGraphicsScene *targetScene = this; + bool notify = item->itemChangeEnabled(QGraphicsItem::ItemSceneChange); + if (notify) { + targetScene = qVariantValue<QGraphicsScene *>(item->itemChange(QGraphicsItem::ItemSceneChange, + qVariantFromValue<QGraphicsScene *>(this))); + } if (targetScene != this) { if (targetScene && item->scene() != targetScene) targetScene->addItem(item); @@ -3063,7 +3068,8 @@ void QGraphicsScene::addItem(QGraphicsItem *item) emit selectionChanged(); // Deliver post-change notification - item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant); + if (notify) + item->itemChange(QGraphicsItem::ItemSceneHasChanged, qVariantFromValue<QGraphicsScene *>(targetScene)); } /*! @@ -3327,9 +3333,12 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) // Notify the item that it's scene is changing to 0, allowing the item to // react. - const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange, - qVariantFromValue<QGraphicsScene *>(0))); - QGraphicsScene *targetScene = qVariantValue<QGraphicsScene *>(newSceneVariant); + QGraphicsScene *targetScene = 0; + bool notify = item->itemChangeEnabled(QGraphicsItem::ItemSceneChange); + if (notify) { + targetScene = qVariantValue<QGraphicsScene *>(item->itemChange(QGraphicsItem::ItemSceneChange, + qVariantFromValue<QGraphicsScene *>(0))); + } if (targetScene != 0 && targetScene != this) { targetScene->addItem(item); return; @@ -3425,7 +3434,8 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) emit selectionChanged(); // Deliver post-change notification - item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant); + if (notify) + item->itemChange(QGraphicsItem::ItemSceneHasChanged, qVariantFromValue<QGraphicsScene *>(targetScene)); } /*! |