From f79e0e89ea9061bbe93f43405a1ec954a41da1cc Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Thu, 17 Dec 2009 18:13:04 +1000 Subject: Make positioners fast. --- src/declarative/graphicsitems/graphicsitems.pri | 2 +- .../graphicsitems/qmlgraphicsanchors.cpp | 4 +- .../graphicsitems/qmlgraphicsanchors_p_p.h | 4 +- src/declarative/graphicsitems/qmlgraphicsitem.cpp | 78 ++++++--- src/declarative/graphicsitems/qmlgraphicsitem_p.h | 69 ++++---- .../qmlgraphicsitemchangelistener_p.h | 76 +++++++++ .../qmlgraphicsitemgeometrylistener_p.h | 70 -------- .../graphicsitems/qmlgraphicslistview.cpp | 6 +- .../graphicsitems/qmlgraphicspositioners.cpp | 181 +++++++++++---------- .../graphicsitems/qmlgraphicspositioners_p.h | 16 +- .../graphicsitems/qmlgraphicspositioners_p_p.h | 40 +++-- .../graphicsitems/qmlgraphicsvisualitemmodel_p.h | 2 +- src/declarative/qml/qpodvector_p.h | 48 ++++-- 13 files changed, 332 insertions(+), 264 deletions(-) create mode 100644 src/declarative/graphicsitems/qmlgraphicsitemchangelistener_p.h delete mode 100644 src/declarative/graphicsitems/qmlgraphicsitemgeometrylistener_p.h diff --git a/src/declarative/graphicsitems/graphicsitems.pri b/src/declarative/graphicsitems/graphicsitems.pri index 5199c5d..eb6e0ad 100644 --- a/src/declarative/graphicsitems/graphicsitems.pri +++ b/src/declarative/graphicsitems/graphicsitems.pri @@ -48,7 +48,7 @@ HEADERS += \ $$PWD/qmlgraphicsgraphicsobjectcontainer_p.h \ $$PWD/qmlgraphicsparticles_p.h \ $$PWD/qmlgraphicslayoutitem_p.h \ - $$PWD/qmlgraphicsitemgeometrylistener_p.h \ + $$PWD/qmlgraphicsitemchangelistener_p.h \ $$PWD/qmlgraphicseffects.cpp SOURCES += \ diff --git a/src/declarative/graphicsitems/qmlgraphicsanchors.cpp b/src/declarative/graphicsitems/qmlgraphicsanchors.cpp index 0febf08..c2e1fa2 100644 --- a/src/declarative/graphicsitems/qmlgraphicsanchors.cpp +++ b/src/declarative/graphicsitems/qmlgraphicsanchors.cpp @@ -245,7 +245,7 @@ void QmlGraphicsAnchorsPrivate::addDepend(QmlGraphicsItem *item) return; QmlGraphicsItemPrivate *p = static_cast(QGraphicsItemPrivate::get(item)); - p->addGeometryListener(this); + p->addItemChangeListener(this, QmlGraphicsItemPrivate::Geometry); } void QmlGraphicsAnchorsPrivate::remDepend(QmlGraphicsItem *item) @@ -254,7 +254,7 @@ void QmlGraphicsAnchorsPrivate::remDepend(QmlGraphicsItem *item) return; QmlGraphicsItemPrivate *p = static_cast(QGraphicsItemPrivate::get(item)); - p->removeGeometryListener(this); + p->removeItemChangeListener(this, QmlGraphicsItemPrivate::Geometry); } bool QmlGraphicsAnchorsPrivate::isItemComplete() const diff --git a/src/declarative/graphicsitems/qmlgraphicsanchors_p_p.h b/src/declarative/graphicsitems/qmlgraphicsanchors_p_p.h index 91c8ff1..45c983f 100644 --- a/src/declarative/graphicsitems/qmlgraphicsanchors_p_p.h +++ b/src/declarative/graphicsitems/qmlgraphicsanchors_p_p.h @@ -54,7 +54,7 @@ // #include "qmlgraphicsanchors_p.h" -#include "qmlgraphicsitemgeometrylistener_p.h" +#include "qmlgraphicsitemchangelistener_p.h" #include QT_BEGIN_NAMESPACE @@ -91,7 +91,7 @@ Q_DECLARE_METATYPE(QmlGraphicsAnchorLine) -class QmlGraphicsAnchorsPrivate : public QObjectPrivate, public QmlGraphicsItemGeometryListener +class QmlGraphicsAnchorsPrivate : public QObjectPrivate, public QmlGraphicsItemChangeListener { Q_DECLARE_PUBLIC(QmlGraphicsAnchors) public: diff --git a/src/declarative/graphicsitems/qmlgraphicsitem.cpp b/src/declarative/graphicsitems/qmlgraphicsitem.cpp index 4d587e4d..aa73444 100644 --- a/src/declarative/graphicsitems/qmlgraphicsitem.cpp +++ b/src/declarative/graphicsitems/qmlgraphicsitem.cpp @@ -1478,18 +1478,24 @@ QmlGraphicsItem::QmlGraphicsItem(QmlGraphicsItemPrivate &dd, QmlGraphicsItem *pa QmlGraphicsItem::~QmlGraphicsItem() { Q_D(QmlGraphicsItem); - for (int ii = 0; ii < d->geometryListeners.count(); ++ii) { - QmlGraphicsAnchorsPrivate *anchor = d->geometryListeners.at(ii)->anchorPrivate(); + for (int ii = 0; ii < d->changeListeners.count(); ++ii) { + QmlGraphicsAnchorsPrivate *anchor = d->changeListeners.at(ii).listener->anchorPrivate(); if (anchor) anchor->clearItem(this); } - if (!d->parent || (parentItem() && !parentItem()->QGraphicsItem::d_ptr->inDestructor)) - for (int ii = 0; ii < d->geometryListeners.count(); ++ii) { - QmlGraphicsAnchorsPrivate *anchor = d->geometryListeners.at(ii)->anchorPrivate(); + if (!d->parent || (parentItem() && !parentItem()->QGraphicsItem::d_ptr->inDestructor)) { + for (int ii = 0; ii < d->changeListeners.count(); ++ii) { + QmlGraphicsAnchorsPrivate *anchor = d->changeListeners.at(ii).listener->anchorPrivate(); if (anchor && anchor->item && anchor->item->parentItem() != this) //child will be deleted anyway anchor->updateOnComplete(); } - d->geometryListeners.clear(); + } + for(int ii = 0; ii < d->changeListeners.count(); ++ii) { + const QmlGraphicsItemPrivate::ChangeListener &change = d->changeListeners.at(ii); + if (change.types & QmlGraphicsItemPrivate::Destroyed) + change.listener->itemDestroyed(this); + } + d->changeListeners.clear(); delete d->_anchorLines; d->_anchorLines = 0; delete d->_anchors; d->_anchors = 0; delete d->_stateGroup; d->_stateGroup = 0; @@ -1975,20 +1981,17 @@ void QmlGraphicsItem::geometryChanged(const QRectF &newGeometry, if (newGeometry.height() != oldGeometry.height()) emit heightChanged(); - for(int ii = 0; ii < d->geometryListeners.count(); ++ii) { - QmlGraphicsItemGeometryListener *listener = d->geometryListeners.at(ii); - listener->itemGeometryChanged(this, newGeometry, oldGeometry); + for(int ii = 0; ii < d->changeListeners.count(); ++ii) { + const QmlGraphicsItemPrivate::ChangeListener &change = d->changeListeners.at(ii); + if (change.types & QmlGraphicsItemPrivate::Geometry) + change.listener->itemGeometryChanged(this, newGeometry, oldGeometry); } } -void QmlGraphicsItemPrivate::addGeometryListener(QmlGraphicsItemGeometryListener *listener) -{ - geometryListeners.append(listener); -} - -void QmlGraphicsItemPrivate::removeGeometryListener(QmlGraphicsItemGeometryListener *listener) +void QmlGraphicsItemPrivate::removeItemChangeListener(QmlGraphicsItemChangeListener *listener, ChangeTypes types) { - geometryListeners.removeOne(listener); + ChangeListener change(listener, types); + changeListeners.removeOne(change); } /*! \internal */ @@ -2238,10 +2241,13 @@ void QmlGraphicsItem::setBaselineOffset(qreal offset) d->_baselineOffset = offset; emit baselineOffsetChanged(); - for(int ii = 0; ii < d->geometryListeners.count(); ++ii) { - QmlGraphicsAnchorsPrivate *anchor = d->geometryListeners.at(ii)->anchorPrivate(); - if (anchor) - anchor->updateVerticalAnchors(); + for(int ii = 0; ii < d->changeListeners.count(); ++ii) { + const QmlGraphicsItemPrivate::ChangeListener &change = d->changeListeners.at(ii); + if (change.types & QmlGraphicsItemPrivate::Geometry) { + QmlGraphicsAnchorsPrivate *anchor = change.listener->anchorPrivate(); + if (anchor) + anchor->updateVerticalAnchors(); + } } } @@ -2707,10 +2713,35 @@ bool QmlGraphicsItem::sceneEvent(QEvent *event) QVariant QmlGraphicsItem::itemChange(GraphicsItemChange change, const QVariant &value) { - if (change == ItemParentHasChanged) { + Q_D(const QmlGraphicsItem); + switch (change) { + case ItemParentHasChanged: emit parentChanged(); - } else if (change == ItemChildAddedChange || change == ItemChildRemovedChange) { + break; + case ItemChildAddedChange: + case ItemChildRemovedChange: emit childrenChanged(); + break; + case ItemVisibleHasChanged: { + for(int ii = 0; ii < d->changeListeners.count(); ++ii) { + const QmlGraphicsItemPrivate::ChangeListener &change = d->changeListeners.at(ii); + if (change.types & QmlGraphicsItemPrivate::Visibility) { + change.listener->itemVisibilityChanged(this); + } + } + } + break; + case ItemOpacityHasChanged: { + for(int ii = 0; ii < d->changeListeners.count(); ++ii) { + const QmlGraphicsItemPrivate::ChangeListener &change = d->changeListeners.at(ii); + if (change.types & QmlGraphicsItemPrivate::Opacity) { + change.listener->itemOpacityChanged(this); + } + } + } + break; + default: + break; } return QGraphicsItem::itemChange(change, value); @@ -3006,9 +3037,6 @@ QDebug operator<<(QDebug debug, QmlGraphicsItem *item) return debug; } -int QmlGraphicsItemPrivate::heightIdx = -1; -int QmlGraphicsItemPrivate::widthIdx = -1; - int QmlGraphicsItemPrivate::consistentTime = -1; void QmlGraphicsItemPrivate::setConsistentTime(int t) { diff --git a/src/declarative/graphicsitems/qmlgraphicsitem_p.h b/src/declarative/graphicsitems/qmlgraphicsitem_p.h index 9496590..07c821e 100644 --- a/src/declarative/graphicsitems/qmlgraphicsitem_p.h +++ b/src/declarative/graphicsitems/qmlgraphicsitem_p.h @@ -57,7 +57,8 @@ #include "qmlgraphicsanchors_p.h" #include "qmlgraphicsanchors_p_p.h" -#include "qmlgraphicsitemgeometrylistener_p.h" +#include "qmlgraphicsitemchangelistener_p.h" +#include "qpodvector_p.h" #include "../util/qmlstate_p.h" #include "../util/qmlnullablevalue_p_p.h" @@ -115,10 +116,6 @@ public: smooth(false), keyHandler(0), width(0), height(0), implicitWidth(0), implicitHeight(0) { - if (widthIdx == -1) { - widthIdx = QmlGraphicsItem::staticMetaObject.indexOfSignal("widthChanged()"); - heightIdx = QmlGraphicsItem::staticMetaObject.indexOfSignal("heightChanged()"); - } } void init(QmlGraphicsItem *parent) @@ -206,9 +203,28 @@ public: return _anchorLines; } - void addGeometryListener(QmlGraphicsItemGeometryListener *); - void removeGeometryListener(QmlGraphicsItemGeometryListener *); - QList geometryListeners; + enum ChangeType { + Geometry = 0x01, + SiblingOrder = 0x02, + Visibility = 0x04, + Opacity = 0x08, + Destroyed = 0x10 + }; + + Q_DECLARE_FLAGS(ChangeTypes, ChangeType) + + struct ChangeListener { + ChangeListener(QmlGraphicsItemChangeListener *l, QmlGraphicsItemPrivate::ChangeTypes t) : listener(l), types(t) {} + QmlGraphicsItemChangeListener *listener; + QmlGraphicsItemPrivate::ChangeTypes types; + bool operator==(const ChangeListener &other) const { return listener == other.listener && types == other.types; } + }; + + void addItemChangeListener(QmlGraphicsItemChangeListener *listener, ChangeTypes types) { + changeListeners.append(ChangeListener(listener, types)); + } + void removeItemChangeListener(QmlGraphicsItemChangeListener *, ChangeTypes types); + QPODVector changeListeners; QmlStateGroup *states(); QmlStateGroup *_stateGroup; @@ -246,32 +262,13 @@ public: // Reimplemented from QGraphicsItemPrivate virtual void siblingOrderChange() { - foreach(QmlGraphicsItemPrivate* other, siblingOrderNotifiees) - other->otherSiblingOrderChange(this); - } - QList siblingOrderNotifiees; - void registerSiblingOrderNotification(QmlGraphicsItemPrivate* other) - { - siblingOrderNotifiees << other; - } - void unregisterSiblingOrderNotification(QmlGraphicsItemPrivate* other) - { - siblingOrderNotifiees.removeAll(other); - } - virtual void otherSiblingOrderChange(QmlGraphicsItemPrivate* other) {Q_UNUSED(other)} - - bool connectToWidthChanged(QObject *object, int index) { - return QMetaObject::connect(q_func(), widthIdx, object, index); - } - bool disconnectFromWidthChanged(QObject *object, int index) { - return QMetaObject::disconnect(q_func(), widthIdx, object, index); - } - - bool connectToHeightChanged(QObject *object, int index) { - return QMetaObject::connect(q_func(), heightIdx, object, index); - } - bool disconnectFromHeightChanged(QObject *object, int index) { - return QMetaObject::disconnect(q_func(), heightIdx, object, index); + Q_Q(QmlGraphicsItem); + for(int ii = 0; ii < changeListeners.count(); ++ii) { + const QmlGraphicsItemPrivate::ChangeListener &change = changeListeners.at(ii); + if (change.types & QmlGraphicsItemPrivate::SiblingOrder) { + change.listener->itemSiblingOrderChanged(q); + } + } } static int consistentTime; @@ -280,10 +277,10 @@ public: static void start(QTime &); static int elapsed(QTime &); static int restart(QTime &); - static int widthIdx; - static int heightIdx; }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QmlGraphicsItemPrivate::ChangeTypes); + QT_END_NAMESPACE #endif // QMLGRAPHICSITEM_P_H diff --git a/src/declarative/graphicsitems/qmlgraphicsitemchangelistener_p.h b/src/declarative/graphicsitems/qmlgraphicsitemchangelistener_p.h new file mode 100644 index 0000000..f430df0 --- /dev/null +++ b/src/declarative/graphicsitems/qmlgraphicsitemchangelistener_p.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLGRAPHICSITEMCHANGELISTENER +#define QMLGRAPHICSITEMCHANGELISTENER + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +QT_BEGIN_NAMESPACE + +class QRectF; +class QmlGraphicsItem; +class QmlGraphicsAnchorsPrivate; +class QmlGraphicsItemChangeListener +{ +public: + virtual void itemGeometryChanged(QmlGraphicsItem *, const QRectF &, const QRectF &) {} + virtual void itemSiblingOrderChanged(QmlGraphicsItem *) {} + virtual void itemVisibilityChanged(QmlGraphicsItem *) {} + virtual void itemOpacityChanged(QmlGraphicsItem *) {} + virtual void itemDestroyed(QmlGraphicsItem *) {} + virtual QmlGraphicsAnchorsPrivate *anchorPrivate() { return 0; } +}; + +QT_END_NAMESPACE + +#endif // QMLGRAPHICSITEMCHANGELISTENER diff --git a/src/declarative/graphicsitems/qmlgraphicsitemgeometrylistener_p.h b/src/declarative/graphicsitems/qmlgraphicsitemgeometrylistener_p.h deleted file mode 100644 index 6230e93..0000000 --- a/src/declarative/graphicsitems/qmlgraphicsitemgeometrylistener_p.h +++ /dev/null @@ -1,70 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QMLGRAPHICSITEMGEOMETRYLISTENER -#define QMLGRAPHICSITEMGEOMETRYLISTENER - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -QT_BEGIN_NAMESPACE - -class QRectF; -class QmlGraphicsItem; -class QmlGraphicsAnchorsPrivate; -class QmlGraphicsItemGeometryListener -{ -public: - virtual void itemGeometryChanged(QmlGraphicsItem *, const QRectF &newGeometry, const QRectF &oldGeometry) = 0; - virtual QmlGraphicsAnchorsPrivate *anchorPrivate() { return 0; } -}; - -QT_END_NAMESPACE - -#endif // QMLGRAPHICSITEMGEOMETRYLISTENER diff --git a/src/declarative/graphicsitems/qmlgraphicslistview.cpp b/src/declarative/graphicsitems/qmlgraphicslistview.cpp index d4d201a..5db3b26 100644 --- a/src/declarative/graphicsitems/qmlgraphicslistview.cpp +++ b/src/declarative/graphicsitems/qmlgraphicslistview.cpp @@ -218,7 +218,7 @@ public: //---------------------------------------------------------------------------- -class QmlGraphicsListViewPrivate : public QmlGraphicsFlickablePrivate, private QmlGraphicsItemGeometryListener +class QmlGraphicsListViewPrivate : public QmlGraphicsFlickablePrivate, private QmlGraphicsItemChangeListener { Q_DECLARE_PUBLIC(QmlGraphicsListView) @@ -607,7 +607,7 @@ FxListItem *QmlGraphicsListViewPrivate::createItem(int modelIndex) listItem->item->setZValue(1); listItem->item->setParent(q->viewport()); QmlGraphicsItemPrivate *itemPrivate = static_cast(QGraphicsItemPrivate::get(item)); - itemPrivate->addGeometryListener(this); + itemPrivate->addItemChangeListener(this, QmlGraphicsItemPrivate::Geometry); if (sectionCriteria && sectionCriteria->delegate()) { if (listItem->attached->m_prevSection != listItem->attached->m_section) createSection(listItem); @@ -631,7 +631,7 @@ void QmlGraphicsListViewPrivate::releaseItem(FxListItem *item) trackedItem = 0; } QmlGraphicsItemPrivate *itemPrivate = static_cast(QGraphicsItemPrivate::get(item->item)); - itemPrivate->removeGeometryListener(this); + itemPrivate->removeItemChangeListener(this, QmlGraphicsItemPrivate::Geometry); if (model->release(item->item) == 0) { // item was not destroyed, and we no longer reference it. unrequestedItems.insert(item->item, model->indexOf(item->item, q)); diff --git a/src/declarative/graphicsitems/qmlgraphicspositioners.cpp b/src/declarative/graphicsitems/qmlgraphicspositioners.cpp index 17fe59f..aa724a3 100644 --- a/src/declarative/graphicsitems/qmlgraphicspositioners.cpp +++ b/src/declarative/graphicsitems/qmlgraphicspositioners.cpp @@ -54,38 +54,23 @@ QT_BEGIN_NAMESPACE -int QmlGraphicsBasePositionerPrivate::prePosIdx = -1; -int QmlGraphicsBasePositionerPrivate::visibleIdx = -1; -int QmlGraphicsBasePositionerPrivate::opacityIdx = -1; - +static const QmlGraphicsItemPrivate::ChangeTypes watchedChanges + = QmlGraphicsItemPrivate::Geometry + | QmlGraphicsItemPrivate::SiblingOrder + | QmlGraphicsItemPrivate::Visibility + | QmlGraphicsItemPrivate::Opacity + | QmlGraphicsItemPrivate::Destroyed; void QmlGraphicsBasePositionerPrivate::watchChanges(QmlGraphicsItem *other) { - Q_Q(QmlGraphicsBasePositioner); - QMetaObject::connect(other, visibleIdx, q, prePosIdx); - QMetaObject::connect(other, opacityIdx, q, prePosIdx); - QmlGraphicsItemPrivate *otherPrivate = static_cast(QGraphicsItemPrivate::get(other)); - - otherPrivate->addGeometryListener(this); - - otherPrivate->registerSiblingOrderNotification(this); - watched << other; + otherPrivate->addItemChangeListener(this, watchedChanges); } void QmlGraphicsBasePositionerPrivate::unwatchChanges(QmlGraphicsItem* other) { - Q_Q(QmlGraphicsBasePositioner); QmlGraphicsItemPrivate *otherPrivate = static_cast(QGraphicsItemPrivate::get(other)); - bool stillAlive = false; //Use the returns from disconnect to see if it was deleted or just reparented - stillAlive |= QMetaObject::disconnect(other, visibleIdx, q, prePosIdx); - stillAlive |= QMetaObject::disconnect(other, opacityIdx, q, prePosIdx); - - otherPrivate->removeGeometryListener(this); - - if(stillAlive) - otherPrivate->unregisterSiblingOrderNotification(this); - watched.removeAll(other); + otherPrivate->removeItemChangeListener(this, watchedChanges); } /*! @@ -120,6 +105,14 @@ QmlGraphicsBasePositioner::QmlGraphicsBasePositioner(QmlGraphicsBasePositionerPr d->init(at); } +QmlGraphicsBasePositioner::~QmlGraphicsBasePositioner() +{ + Q_D(QmlGraphicsBasePositioner); + for (int i = 0; i < positionedItems.count(); ++i) + d->unwatchChanges(positionedItems.at(i).item); + positionedItems.clear(); +} + int QmlGraphicsBasePositioner::spacing() const { Q_D(const QmlGraphicsBasePositioner); @@ -162,10 +155,12 @@ void QmlGraphicsBasePositioner::setAdd(QmlTransition *add) void QmlGraphicsBasePositioner::componentComplete() { + Q_D(QmlGraphicsBasePositioner); QmlGraphicsItem::componentComplete(); #ifdef Q_ENABLE_PERFORMANCE_LOG QmlPerfTimer cc; #endif + positionedItems.reserve(d->QGraphicsItemPrivate::children.count()); prePositioning(); } @@ -175,18 +170,19 @@ QVariant QmlGraphicsBasePositioner::itemChange(GraphicsItemChange change, Q_D(QmlGraphicsBasePositioner); if (change == ItemChildAddedChange){ QmlGraphicsItem* child = value.value(); - if(!child) - return QVariant(); - if(!d->watched.contains(child)) - d->watchChanges(child); - prePositioning(); - }else if (change == ItemChildRemovedChange) { + if (child) + prePositioning(); + } else if (change == ItemChildRemovedChange) { QmlGraphicsItem* child = value.value(); - if(!child) - return QVariant(); - if(d->watched.contains(child)) - d->unwatchChanges(child); - prePositioning(); + if (child) { + QmlGraphicsBasePositioner::PositionedItem posItem(child); + int idx = positionedItems.find(posItem); + if (idx >= 0) { + d->unwatchChanges(child); + positionedItems.remove(idx); + } + prePositioning(); + } } return QmlGraphicsItem::itemChange(change, value); @@ -202,29 +198,31 @@ void QmlGraphicsBasePositioner::prePositioning() //Need to order children by creation order modified by stacking order QList children = childItems(); qSort(children.begin(), children.end(), d->insertionOrder); - positionedItems.clear(); - d->newItems.clear(); for (int ii = 0; ii < children.count(); ++ii) { QmlGraphicsItem *child = qobject_cast(children.at(ii)); if (!child) continue; - if(!d->watched.contains(child)) + PositionedItem *item = 0; + PositionedItem posItem(child); + int wIdx = positionedItems.find(posItem); + if (wIdx < 0) { d->watchChanges(child); - if(child->opacity() <= 0.0 || !child->isVisible()) + positionedItems.append(posItem); + item = &positionedItems[positionedItems.count()-1]; + } else { + item = &positionedItems[wIdx]; + } + if (child->opacity() <= 0.0 || !child->isVisible()) { + item->isVisible = false; continue; - if (!d->items.contains(child)){ - d->items += child; - d->newItems += child; } - positionedItems << child; - } - if(d->items.count() > positionedItems.count()){ - //Assumed that (aside from init) every add/remove triggers this check - //thus the above check will be triggered every time an item is removed - QSet deletedItems = d->items - positionedItems.toSet(); - foreach(QmlGraphicsItem *child, deletedItems) - d->items -= child; + if (!item->isVisible) { + item->isVisible = true; + item->isNew = true; + } else { + item->isNew = false; + } } doPositioning(); if(d->addTransition || d->moveTransition) @@ -232,42 +230,43 @@ void QmlGraphicsBasePositioner::prePositioning() //Set implicit size to the size of its children qreal h = 0.0f; qreal w = 0.0f; - foreach(QmlGraphicsItem *child, d->items){ - if(!child->isVisible() || child->opacity() <= 0) - continue; - h = qMax(h, child->y() + child->height()); - w = qMax(w, child->x() + child->width()); + for (int i = 0; i < positionedItems.count(); ++i) { + const PositionedItem &posItem = positionedItems.at(i); + if (posItem.isVisible) { + h = qMax(h, posItem.item->y() + posItem.item->height()); + w = qMax(w, posItem.item->x() + posItem.item->width()); + } } setImplicitHeight(h); setImplicitWidth(w); } -void QmlGraphicsBasePositioner::positionX(int x, QmlGraphicsItem* target) +void QmlGraphicsBasePositioner::positionX(int x, const PositionedItem &target) { Q_D(QmlGraphicsBasePositioner); if(d->type == Horizontal || d->type == Both){ if(!d->addTransition && !d->moveTransition){ - target->setX(x); + target.item->setX(x); }else{ - if(d->newItems.contains(target)) - d->addActions << Action(target, QLatin1String("x"), QVariant(x)); + if(target.isNew) + d->addActions << Action(target.item, QLatin1String("x"), QVariant(x)); else - d->moveActions << Action(target, QLatin1String("x"), QVariant(x)); + d->moveActions << Action(target.item, QLatin1String("x"), QVariant(x)); } } } -void QmlGraphicsBasePositioner::positionY(int y, QmlGraphicsItem* target) +void QmlGraphicsBasePositioner::positionY(int y, const PositionedItem &target) { Q_D(QmlGraphicsBasePositioner); if(d->type == Vertical || d->type == Both){ if(!d->addTransition && !d->moveTransition){ - target->setY(y); + target.item->setY(y); }else{ - if(d->newItems.contains(target)) - d->addActions << Action(target, QLatin1String("y"), QVariant(y)); + if(target.isNew) + d->addActions << Action(target.item, QLatin1String("y"), QVariant(y)); else - d->moveActions << Action(target, QLatin1String("y"), QVariant(y)); + d->moveActions << Action(target.item, QLatin1String("y"), QVariant(y)); } } } @@ -401,14 +400,14 @@ void QmlGraphicsColumn::doPositioning() int voffset = 0; for (int ii = 0; ii < positionedItems.count(); ++ii) { - QmlGraphicsItem *child = positionedItems.at(ii); - if (!child || isInvisible(child)) + const PositionedItem &child = positionedItems.at(ii); + if (!child.item || isInvisible(child.item)) continue; - if(child->y() != voffset) + if(child.item->y() != voffset) positionY(voffset, child); - voffset += child->height(); + voffset += child.item->height(); voffset += spacing(); } } @@ -506,14 +505,14 @@ void QmlGraphicsRow::doPositioning() int hoffset = 0; for (int ii = 0; ii < positionedItems.count(); ++ii) { - QmlGraphicsItem *child = positionedItems.at(ii); - if (!child || isInvisible(child)) + const PositionedItem &child = positionedItems.at(ii); + if (!child.item || isInvisible(child.item)) continue; - if(child->x() != hoffset) + if(child.item->x() != hoffset) positionX(hoffset, child); - hoffset += child->width(); + hoffset += child.item->width(); hoffset += spacing(); } } @@ -670,13 +669,13 @@ void QmlGraphicsGrid::doPositioning() if (childIndex == positionedItems.count()) continue; - QmlGraphicsItem *child = positionedItems.at(childIndex++); - if (!child || isInvisible(child)) + const PositionedItem &child = positionedItems.at(childIndex++); + if (!child.item || isInvisible(child.item)) continue; - if (child->width() > maxColWidth[j]) - maxColWidth[j] = child->width(); - if (child->height() > maxRowHeight[i]) - maxRowHeight[i] = child->height(); + if (child.item->width() > maxColWidth[j]) + maxColWidth[j] = child.item->width(); + if (child.item->height() > maxRowHeight[i]) + maxRowHeight[i] = child.item->height(); } } @@ -684,10 +683,11 @@ void QmlGraphicsGrid::doPositioning() int yoffset=0; int curRow =0; int curCol =0; - foreach(QmlGraphicsItem* child, positionedItems){ - if (!child || isInvisible(child)) + for (int i = 0; i < positionedItems.count(); ++i) { + const PositionedItem &child = positionedItems.at(i); + if (!child.item || isInvisible(child.item)) continue; - if((child->x()!=xoffset)||(child->y()!=yoffset)){ + if((child.item->x()!=xoffset)||(child.item->y()!=yoffset)){ positionX(xoffset, child); positionY(yoffset, child); } @@ -805,37 +805,38 @@ void QmlGraphicsFlow::doPositioning() int voffset = 0; int linemax = 0; - foreach(QmlGraphicsItem* child, positionedItems){ - if (!child || isInvisible(child)) + for (int i = 0; i < positionedItems.count(); ++i) { + const PositionedItem &child = positionedItems.at(i); + if (!child.item || isInvisible(child.item)) continue; if (d->flow == LeftToRight) { - if (hoffset && hoffset + child->width() > width()) { + if (hoffset && hoffset + child.item->width() > width()) { hoffset = 0; voffset += linemax + spacing(); linemax = 0; } } else { - if (voffset && voffset + child->height() > height()) { + if (voffset && voffset + child.item->height() > height()) { voffset = 0; hoffset += linemax + spacing(); linemax = 0; } } - if(child->x() != hoffset || child->y() != voffset){ + if(child.item->x() != hoffset || child.item->y() != voffset){ positionX(hoffset, child); positionY(voffset, child); } if (d->flow == LeftToRight) { - hoffset += child->width(); + hoffset += child.item->width(); hoffset += spacing(); - linemax = qMax(linemax, qCeil(child->height())); + linemax = qMax(linemax, qCeil(child.item->height())); } else { - voffset += child->height(); + voffset += child.item->height(); voffset += spacing(); - linemax = qMax(linemax, qCeil(child->width())); + linemax = qMax(linemax, qCeil(child.item->width())); } } } diff --git a/src/declarative/graphicsitems/qmlgraphicspositioners_p.h b/src/declarative/graphicsitems/qmlgraphicspositioners_p.h index c8f846a..0e6d134 100644 --- a/src/declarative/graphicsitems/qmlgraphicspositioners_p.h +++ b/src/declarative/graphicsitems/qmlgraphicspositioners_p.h @@ -45,6 +45,7 @@ #include "qmlgraphicsitem.h" #include "../util/qmlstate_p.h" +#include "qpodvector_p.h" #include #include @@ -66,6 +67,7 @@ class Q_DECLARATIVE_EXPORT QmlGraphicsBasePositioner : public QmlGraphicsItem public: enum PositionerType { None = 0x0, Horizontal = 0x1, Vertical = 0x2, Both = 0x3 }; QmlGraphicsBasePositioner(PositionerType, QmlGraphicsItem *parent); + ~QmlGraphicsBasePositioner(); int spacing() const; void setSpacing(int); @@ -90,9 +92,17 @@ protected Q_SLOTS: void prePositioning(); protected: - QList positionedItems; - void positionX(int,QmlGraphicsItem* target); - void positionY(int,QmlGraphicsItem* target); + struct PositionedItem { + PositionedItem(QmlGraphicsItem *i) : item(i), isNew(false), isVisible(true) {} + bool operator==(const PositionedItem &other) const { return other.item == item; } + QmlGraphicsItem *item; + bool isNew; + bool isVisible; + }; + + QPODVector positionedItems; + void positionX(int,const PositionedItem &target); + void positionY(int,const PositionedItem &target); private: Q_DISABLE_COPY(QmlGraphicsBasePositioner) diff --git a/src/declarative/graphicsitems/qmlgraphicspositioners_p_p.h b/src/declarative/graphicsitems/qmlgraphicspositioners_p_p.h index 63c1c83..55a31c7 100644 --- a/src/declarative/graphicsitems/qmlgraphicspositioners_p_p.h +++ b/src/declarative/graphicsitems/qmlgraphicspositioners_p_p.h @@ -64,9 +64,10 @@ #include #include #include +#include QT_BEGIN_NAMESPACE -class QmlGraphicsBasePositionerPrivate : public QmlGraphicsItemPrivate, public QmlGraphicsItemGeometryListener +class QmlGraphicsBasePositionerPrivate : public QmlGraphicsItemPrivate, public QmlGraphicsItemChangeListener { Q_DECLARE_PUBLIC(QmlGraphicsBasePositioner) @@ -77,29 +78,15 @@ public: { } - ~QmlGraphicsBasePositionerPrivate() - { - watched.removeAll(0); - foreach(QmlGraphicsItem* other, watched) - unwatchChanges(other);//Need to deregister from a list in QmlGI Private - } - void init(QmlGraphicsBasePositioner::PositionerType at) { type = at; - if (prePosIdx == -1) { - prePosIdx = QmlGraphicsBasePositioner::staticMetaObject.indexOfSlot("prePositioning()"); - visibleIdx = QmlGraphicsItem::staticMetaObject.indexOfSignal("visibleChanged()"); - opacityIdx = QmlGraphicsItem::staticMetaObject.indexOfSignal("opacityChanged()"); - } } int spacing; QmlGraphicsBasePositioner::PositionerType type; QmlTransition *moveTransition; QmlTransition *addTransition; - QSet items; - QSet newItems; QmlStateOperation::ActionList addActions; QmlStateOperation::ActionList moveActions; QmlTransitionManager addTransitionManager; @@ -107,14 +94,9 @@ public: void watchChanges(QmlGraphicsItem *other); void unwatchChanges(QmlGraphicsItem* other); - QList > watched;//Can't have QSet and QGuard at the same time? bool queuedPositioning; - static int prePosIdx; - static int visibleIdx; - static int opacityIdx; - - virtual void otherSiblingOrderChange(QmlGraphicsItemPrivate* other) + virtual void itemSiblingOrderChanged(QmlGraphicsItem* other) { Q_Q(QmlGraphicsBasePositioner); Q_UNUSED(other); @@ -132,6 +114,22 @@ public: if (newGeometry.size() != oldGeometry.size()) q->prePositioning(); } + virtual void itemVisibilityChanged(QmlGraphicsItem *) + { + Q_Q(QmlGraphicsBasePositioner); + q->prePositioning(); + } + virtual void itemOpacityChanged(QmlGraphicsItem *) + { + Q_Q(QmlGraphicsBasePositioner); + q->prePositioning(); + } + + void itemDestroyed(QmlGraphicsItem *item) + { + Q_Q(QmlGraphicsBasePositioner); + q->positionedItems.removeOne(QmlGraphicsBasePositioner::PositionedItem(item)); + } }; QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qmlgraphicsvisualitemmodel_p.h b/src/declarative/graphicsitems/qmlgraphicsvisualitemmodel_p.h index 4e8a19b..bd9202b 100644 --- a/src/declarative/graphicsitems/qmlgraphicsvisualitemmodel_p.h +++ b/src/declarative/graphicsitems/qmlgraphicsvisualitemmodel_p.h @@ -82,7 +82,7 @@ public: virtual ReleaseFlags release(QmlGraphicsItem *item) = 0; virtual void completeItem() = 0; virtual QVariant evaluate(int index, const QString &expression, QObject *objectContext) = 0; - virtual QVariant value(int index, const QString &role) { return QVariant(); } + virtual QVariant value(int, const QString &) { return QVariant(); } virtual int indexOf(QmlGraphicsItem *item, QObject *objectContext) const = 0; diff --git a/src/declarative/qml/qpodvector_p.h b/src/declarative/qml/qpodvector_p.h index 3fe2e65..add6e98 100644 --- a/src/declarative/qml/qpodvector_p.h +++ b/src/declarative/qml/qpodvector_p.h @@ -54,10 +54,11 @@ // #include +#include QT_BEGIN_NAMESPACE -template +template class QPODVector { public: @@ -87,23 +88,28 @@ public: void insert(int idx, const T &v) { if (m_count == m_capacity) { - m_capacity += 1024; + m_capacity += Increment; m_data = (T *)realloc(m_data, m_capacity * sizeof(T)); } int moveCount = m_count - idx; - if (moveCount) + if (moveCount) { + qDebug() << "insert" << m_count << idx; ::memmove(m_data + idx + 1, m_data + idx, moveCount * sizeof(T)); + } m_count++; m_data[idx] = v; } - void insertBlank(int idx, int count) { - int newSize = m_count + count; - if (newSize >= m_capacity) { - m_capacity = (newSize + 1023) & 0xFFFFFC00; + void reserve(int count) { + if (count >= m_capacity) { + m_capacity = (count + (Increment-1)) & (0xFFFFFFFF - Increment + 1); m_data = (T *)realloc(m_data, m_capacity * sizeof(T)); } + } + void insertBlank(int idx, int count) { + int newSize = m_count + count; + reserve(newSize); int moveCount = m_count - idx; if (moveCount) ::memmove(m_data + idx + count, m_data + idx, @@ -118,12 +124,34 @@ public: moveCount * sizeof(T)); m_count -= count; } - + + void removeOne(const T &v) { + int idx = 0; + while (idx < m_count) { + if (m_data[idx] == v) { + remove(idx); + return; + } + ++idx; + } + } + + int find(const T &v) { + for (int idx = 0; idx < m_count; ++idx) + if (m_data[idx] == v) + return idx; + return -1; + } + + bool contains(const T &v) { + return find(v) != -1; + } + int count() const { return m_count; } - void copyAndClear(QPODVector &other) { + void copyAndClear(QPODVector &other) { if (other.m_data) ::free(other.m_data); other.m_count = m_count; other.m_capacity = m_capacity; @@ -133,7 +161,7 @@ public: m_data = 0; } - QPODVector &operator<<(const T &v) { append(v); return *this; } + QPODVector &operator<<(const T &v) { append(v); return *this; } private: QPODVector(const QPODVector &); QPODVector &operator=(const QPODVector &); -- cgit v0.12