From 0b5f394208d5aaf803e2100f2ffe12bdef44a7e8 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Thu, 30 Apr 2009 17:06:10 +1000 Subject: Item insertion and removal for PathView. Not animated at the moment. --- src/declarative/fx/qfxpathview.cpp | 166 ++++++++++++++++++++++--------------- src/declarative/fx/qfxpathview.h | 2 + 2 files changed, 103 insertions(+), 65 deletions(-) diff --git a/src/declarative/fx/qfxpathview.cpp b/src/declarative/fx/qfxpathview.cpp index c0d3ab2..5c24d86 100644 --- a/src/declarative/fx/qfxpathview.cpp +++ b/src/declarative/fx/qfxpathview.cpp @@ -140,28 +140,6 @@ QFxPathView::~QFxPathView() The model provides a set of data that is used to create the items for the view. For large or dynamic datasets the model is usually provided by a C++ model object. - However, models can also be created directly in XML, for example: - \code - - - - pics/john.png - John - Smith - - - pics/bill.png - Bill - Jones - - - pics/jane.png - Jane - Doe - - - - \endcode */ /*! @@ -180,6 +158,10 @@ QVariant QFxPathView::model() const void QFxPathView::setModel(const QVariant &model) { Q_D(QFxPathView); + if (d->model) { + disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int))); + disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int))); + } if (QFxVisualItemModel *m = qvariant_cast(model)) { if (d->ownModel) { delete d->model; @@ -193,6 +175,12 @@ void QFxPathView::setModel(const QVariant &model) } d->model->setModel(model); } + if (d->model) { + connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int))); + connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int))); + } + d->firstIndex = 0; + d->pathOffset = 0; d->regenerate(); d->fixOffset(); } @@ -425,6 +413,8 @@ QPointF QFxPathViewPrivate::pointNear(const QPointF &point, qreal *nearPercent) void QFxPathView::mousePressEvent(QGraphicsSceneMouseEvent *event) { Q_D(QFxPathView); + if (!d->items.count()) + return; QPointF scenePoint = mapToScene(event->pos()); int idx = 0; for (; idx < d->items.count(); ++idx) { @@ -576,9 +566,6 @@ bool QFxPathView::mouseFilter(QGraphicsSceneMouseEvent *e) void QFxPathViewPrivate::regenerate() { Q_Q(QFxPathView); - if (!model || model->count() <= 0 || !model->delegate() || !path) - return; - for (int i=0; iattachedProperties.remove(p); @@ -586,29 +573,23 @@ void QFxPathViewPrivate::regenerate() } items.clear(); - firstIndex = 0; - pathOffset = 0; + if (!model || model->count() <= 0 || !model->delegate() || !path) + return; - int numItems = (pathItems>=0 ? pathItems : model->count()); - qreal minDiff = 1e9; - int minI = -1; - for (int i=0; iitem(i); + if (firstIndex >= model->count()) + firstIndex = model->count()-1; + if (pathOffset >= model->count()) + pathOffset = model->count()-1; + + int numItems = pathItems >= 0 ? pathItems : model->count(); + for (int i=0; i < numItems && i < model->count(); ++i){ + QFxItem *item = model->item((i + firstIndex) % model->count()); if (!item) return; items.append(item); item->setZ(i); item->setParent(q); - qreal percent = i * (100.0 / (numItems)); - percent /= 100.0; - updateItem(items.last(), percent); - qreal diff = qAbs(percent - snapPos); - if (diff < minDiff){ - minDiff = diff; - minI = i; - } } - q->setCurrentIndex(minI); q->refill(); } @@ -639,10 +620,9 @@ void QFxPathView::refill() positions << qAbs(percent/100.0); } - if (d->pathItems==-1){ - for (int i=0; ipathItems==-1) { + for (int i=0; iupdateItem(d->items.at(i), positions[i]); - } return; } @@ -650,54 +630,110 @@ void QFxPathView::refill() for (int i=0; iitems.count(); i++) rotatedPositions << positions[(i + d->pathOffset + d->items.count()) % d->items.count()]; - int firstFind = -1; - int i; - for (i=0; iitems.count()-1; i++) - { + int wrapIndex= -1; + for (int i=0; iitems.count()-1; i++) { if (rotatedPositions[i] > rotatedPositions[i+1]){ - firstFind = i; + wrapIndex = i; break; } } - if (firstFind!=-1 ){ + if (wrapIndex != -1 ){ //A wraparound has occured - if (firstFind<(d->items.count()/2)){ - while(firstFind-- >= 0){ + if (wrapIndex < d->items.count()/2){ + while(wrapIndex-- >= 0){ QFxItem* p = d->items.takeFirst(); attachedProperties.remove(p); d->model->release(p); d->firstIndex++; - d->firstIndex%=d->model->count(); + d->firstIndex %= d->model->count(); int index = (d->firstIndex + d->items.count())%d->model->count(); d->items << d->model->item(index); - d->items.last()->setZ(i); + d->items.last()->setZ(wrapIndex); d->items.last()->setParent(this); d->pathOffset++; d->pathOffset=d->pathOffset % d->items.count(); } - }else{ - while(firstFind++ < (d->items.count()-1)){ + } else { + while(wrapIndex++ < d->items.count()-1){ QFxItem* p = d->items.takeLast(); attachedProperties.remove(p); d->model->release(p); d->firstIndex--; - if (d->firstIndex<0) + if (d->firstIndex < 0) d->firstIndex = d->model->count() - 1; d->items.prepend(d->model->item(d->firstIndex)); d->items.first()->setZ(d->firstIndex); d->items.first()->setParent(this); d->pathOffset--; - if (d->pathOffset<0) + if (d->pathOffset < 0) d->pathOffset = d->items.count() - 1; } } for (int i=0; iitems.count(); i++) rotatedPositions[i] = positions[(i + d->pathOffset + d->items.count()) - % d->items.count()]; + % d->items.count()]; } - for (int i=0; iitems.count(); i++){ + for (int i=0; iitems.count(); i++) d->updateItem(d->items.at(i), rotatedPositions[i]); +} + +void QFxPathView::itemsInserted(int modelIndex, int count) +{ + //XXX support animated insertion + Q_D(QFxPathView); + if (d->pathItems == -1 || d->items.count() < d->pathItems) { + for (int i = 0; i < count; ++i) { + QFxItem *item = d->model->item(modelIndex + i); + item->setZ(modelIndex + i); + item->setParent(this); + d->items.insert(modelIndex + i, item); + } + refill(); + } else { + //XXX This is pretty heavy handed until we reference count items. + d->regenerate(); } + + // make sure the current item is still at the snap position + int itemIndex = (d->currentIndex - d->firstIndex + d->model->count())%d->model->count(); + itemIndex += d->pathOffset; + itemIndex %= d->items.count(); + qreal targetOffset = fmod(100 + (d->snapPos*100) - 100.0 * itemIndex / d->items.count(), 100); + + if (targetOffset < 0) + targetOffset = 100.0 + targetOffset; + if (targetOffset != d->_offset) + d->moveOffset.setValue(targetOffset); +} + +void QFxPathView::itemsRemoved(int modelIndex, int count) +{ + //XXX support animated removal + Q_D(QFxPathView); + if (d->pathItems == -1) { + for (int i = 0; i < count; ++i) { + QFxItem* p = d->items.takeAt(modelIndex); + attachedProperties.remove(p); + d->model->release(p); + } + d->snapToCurrent(); + refill(); + } else { + d->regenerate(); + } + + // make sure the current item is still at the snap position + if (d->currentIndex >= d->model->count()) + d->currentIndex = d->model->count() - 1; + int itemIndex = (d->currentIndex - d->firstIndex + d->model->count())%d->model->count(); + itemIndex += d->pathOffset; + itemIndex %= d->items.count(); + qreal targetOffset = fmod(100 + (d->snapPos*100) - 100.0 * itemIndex / d->items.count(), 100); + + if (targetOffset < 0) + targetOffset = 100.0 + targetOffset; + if (targetOffset != d->_offset) + d->moveOffset.setValue(targetOffset); } void QFxPathView::ticked() @@ -715,7 +751,7 @@ int QFxPathViewPrivate::calcCurrentIndex() if (_offset < 0) _offset += 100.0; - if (pathItems == -1){ + if (pathItems == -1) { qreal delta = fmod(_offset - snapPos, 100.0); if (delta < 0) delta = 100.0 + delta; @@ -723,7 +759,7 @@ int QFxPathViewPrivate::calcCurrentIndex() if (ii < 0) ii = 0; current = ii; - }else{ + } else { qreal bestDiff=1e9; int bestI=-1; for (int i=0; icount() <= 0) return; - int itemIndex = (currentIndex - firstIndex + model->count())%model->count(); + int itemIndex = (currentIndex - firstIndex + model->count()) % model->count(); //Rounds is the number of times round to make the current item visible int rounds = itemIndex / items.count(); - int otherWayRounds = (model->count() - (itemIndex))/items.count() + 1; + int otherWayRounds = (model->count() - (itemIndex)) / items.count() + 1; if (otherWayRounds < rounds) rounds = -otherWayRounds; @@ -792,7 +828,7 @@ void QFxPathViewPrivate::snapToCurrent() if (targetOffset < 0) targetOffset = 100.0 + targetOffset; - if (targetOffset == _offset && rounds==0) + if (targetOffset == _offset && rounds == 0) return; moveReason = Other; diff --git a/src/declarative/fx/qfxpathview.h b/src/declarative/fx/qfxpathview.h index 2cc0769..23f2f07 100644 --- a/src/declarative/fx/qfxpathview.h +++ b/src/declarative/fx/qfxpathview.h @@ -113,6 +113,8 @@ protected: private Q_SLOTS: void refill(); void ticked(); + void itemsInserted(int index, int count); + void itemsRemoved(int index, int count); protected: QFxPathView(QFxPathViewPrivate &dd, QFxItem *parent); -- cgit v0.12