summaryrefslogtreecommitdiffstats
path: root/src/declarative/graphicsitems/qmlgraphicspathview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/graphicsitems/qmlgraphicspathview.cpp')
-rw-r--r--src/declarative/graphicsitems/qmlgraphicspathview.cpp979
1 files changed, 0 insertions, 979 deletions
diff --git a/src/declarative/graphicsitems/qmlgraphicspathview.cpp b/src/declarative/graphicsitems/qmlgraphicspathview.cpp
deleted file mode 100644
index 9a2c24d..0000000
--- a/src/declarative/graphicsitems/qmlgraphicspathview.cpp
+++ /dev/null
@@ -1,979 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 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$
-**
-****************************************************************************/
-
-#include "qmlgraphicspathview_p.h"
-#include "qmlgraphicspathview_p_p.h"
-
-#include <qmlstate_p.h>
-#include <qmlopenmetaobject_p.h>
-
-#include <QDebug>
-#include <QEvent>
-#include <qlistmodelinterface_p.h>
-#include <QGraphicsSceneEvent>
-
-#include <math.h>
-
-QT_BEGIN_NAMESPACE
-
-inline qreal qmlMod(qreal x, qreal y)
-{
-#ifdef QT_USE_MATH_H_FLOATS
- if(sizeof(qreal) == sizeof(float))
- return fmodf(float(x), float(y));
- else
-#endif
- return fmod(x, y);
-}
-
-
-class QmlGraphicsPathViewAttached : public QObject
-{
- Q_OBJECT
-
- Q_PROPERTY(bool onPath READ isOnPath NOTIFY onPathChanged)
-public:
- QmlGraphicsPathViewAttached(QObject *parent)
- : QObject(parent), mo(new QmlOpenMetaObject(this)), onPath(false)
- {
- }
-
- ~QmlGraphicsPathViewAttached()
- {
- QmlGraphicsPathView::attachedProperties.remove(parent());
- }
-
- QVariant value(const QByteArray &name) const
- {
- return mo->value(name);
- }
- void setValue(const QByteArray &name, const QVariant &val)
- {
- mo->setValue(name, val);
- }
-
- bool isOnPath() const { return onPath; }
- void setOnPath(bool on) {
- if (on != onPath) {
- onPath = on;
- emit onPathChanged();
- }
- }
-
-Q_SIGNALS:
- void onPathChanged();
-
-private:
- QmlOpenMetaObject *mo;
- bool onPath;
-};
-
-
-QmlGraphicsItem *QmlGraphicsPathViewPrivate::getItem(int modelIndex)
-{
- Q_Q(QmlGraphicsPathView);
- requestedIndex = modelIndex;
- QmlGraphicsItem *item = model->item(modelIndex);
- if (item) {
- if (QObject *obj = QmlGraphicsPathView::qmlAttachedProperties(item))
- static_cast<QmlGraphicsPathViewAttached *>(obj)->setOnPath(true);
- item->setParentItem(q);
- }
- requestedIndex = -1;
- return item;
-}
-
-void QmlGraphicsPathViewPrivate::releaseItem(QmlGraphicsItem *item)
-{
- if (!item || !model)
- return;
- if (QObject *obj = QmlGraphicsPathView::qmlAttachedProperties(item))
- static_cast<QmlGraphicsPathViewAttached *>(obj)->setOnPath(false);
- if (model->release(item) == 0) {
- if (QObject *obj = QmlGraphicsPathView::qmlAttachedProperties(item))
- static_cast<QmlGraphicsPathViewAttached *>(obj)->setOnPath(false);
- }
-}
-
-/*!
- \qmlclass PathView QmlGraphicsPathView
- \since 4.7
- \brief The PathView element lays out model-provided items on a path.
- \inherits Item
-
- The model is typically provided by a QAbstractListModel "C++ model object", but can also be created directly in QML.
-
- The items are laid out along a path defined by a \l Path and may be flicked to scroll.
-
- \snippet doc/src/snippets/declarative/pathview/pathview.qml 0
-
- \image pathview.gif
-
- \sa Path
-*/
-
-QmlGraphicsPathView::QmlGraphicsPathView(QmlGraphicsItem *parent)
- : QmlGraphicsItem(*(new QmlGraphicsPathViewPrivate), parent)
-{
- Q_D(QmlGraphicsPathView);
- d->init();
-}
-
-QmlGraphicsPathView::~QmlGraphicsPathView()
-{
- Q_D(QmlGraphicsPathView);
- if (d->ownModel)
- delete d->model;
-}
-
-/*!
- \qmlattachedproperty bool PathView::onPath
- This attached property holds whether the item is currently on the path.
-
- If a pathItemCount has been set, it is possible that some items may
- be instantiated, but not considered to be currently on the path.
- Usually, these items would be set invisible, for example:
-
- \code
- Component {
- Rectangle {
- visible: PathView.onPath
- ...
- }
- }
- \endcode
-
- It is attached to each instance of the delegate.
-*/
-
-/*!
- \qmlproperty model PathView::model
- This property holds the model providing data for the view.
-
- 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.
- Models can also be created directly in XML, using the ListModel element.
-
- \sa {qmlmodels}{Data Models}
-*/
-QVariant QmlGraphicsPathView::model() const
-{
- Q_D(const QmlGraphicsPathView);
- return d->modelVariant;
-}
-
-void QmlGraphicsPathView::setModel(const QVariant &model)
-{
- Q_D(QmlGraphicsPathView);
- 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)));
- disconnect(d->model, SIGNAL(createdItem(int, QmlGraphicsItem*)), this, SLOT(createdItem(int,QmlGraphicsItem*)));
- for (int i=0; i<d->items.count(); i++){
- QmlGraphicsItem *p = d->items[i];
- d->model->release(p);
- }
- d->items.clear();
- }
-
- d->modelVariant = model;
- QObject *object = qvariant_cast<QObject*>(model);
- QmlGraphicsVisualModel *vim = 0;
- if (object && (vim = qobject_cast<QmlGraphicsVisualModel *>(object))) {
- if (d->ownModel) {
- delete d->model;
- d->ownModel = false;
- }
- d->model = vim;
- } else {
- if (!d->ownModel) {
- d->model = new QmlGraphicsVisualDataModel(qmlContext(this));
- d->ownModel = true;
- }
- if (QmlGraphicsVisualDataModel *dataModel = qobject_cast<QmlGraphicsVisualDataModel*>(d->model))
- dataModel->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)));
- connect(d->model, SIGNAL(createdItem(int, QmlGraphicsItem*)), this, SLOT(createdItem(int,QmlGraphicsItem*)));
- }
- d->firstIndex = 0;
- d->pathOffset = 0;
- d->regenerate();
- d->fixOffset();
-}
-
-/*!
- \qmlproperty int PathView::count
- This property holds the number of items in the model.
-*/
-int QmlGraphicsPathView::count() const
-{
- Q_D(const QmlGraphicsPathView);
- return d->model ? d->model->count() : 0;
-}
-
-/*!
- \qmlproperty Path PathView::path
- \default
- This property holds the path used to lay out the items.
- For more information see the \l Path documentation.
-*/
-QmlGraphicsPath *QmlGraphicsPathView::path() const
-{
- Q_D(const QmlGraphicsPathView);
- return d->path;
-}
-
-void QmlGraphicsPathView::setPath(QmlGraphicsPath *path)
-{
- Q_D(QmlGraphicsPathView);
- d->path = path;
- connect(d->path, SIGNAL(changed()), this, SLOT(refill()));
- d->regenerate();
-}
-
-/*!
- \qmlproperty int PathView::currentIndex
- This property holds the index of the current item.
-*/
-int QmlGraphicsPathView::currentIndex() const
-{
- Q_D(const QmlGraphicsPathView);
- return d->currentIndex;
-}
-
-void QmlGraphicsPathView::setCurrentIndex(int idx)
-{
- Q_D(QmlGraphicsPathView);
- if (d->model && d->model->count())
- idx = qAbs(idx % d->model->count());
- if (d->model && idx != d->currentIndex) {
- d->currentIndex = idx;
- if (d->model->count()) {
- d->snapToCurrent();
- int itemIndex = (idx - d->firstIndex + d->model->count()) % d->model->count();
- if (itemIndex < d->items.count())
- d->items.at(itemIndex)->setFocus(true);
- }
- emit currentIndexChanged();
- }
-}
-
-/*!
- \qmlproperty real PathView::offset
-
- The offset specifies how far along the path the items are from their initial positions.
-*/
-qreal QmlGraphicsPathView::offset() const
-{
- Q_D(const QmlGraphicsPathView);
- return d->_offset;
-}
-
-void QmlGraphicsPathView::setOffset(qreal offset)
-{
- Q_D(QmlGraphicsPathView);
- d->setOffset(offset);
- d->updateCurrent();
-}
-
-void QmlGraphicsPathViewPrivate::setOffset(qreal o)
-{
- Q_Q(QmlGraphicsPathView);
- if (_offset != o) {
- _offset = qmlMod(o, qreal(100.0));
- if (_offset < 0)
- _offset = 100.0 + _offset;
- q->refill();
- }
-}
-
-/*!
- \qmlproperty real PathView::snapPosition
-
- This property determines the position (0-100) the nearest item will snap to.
-*/
-qreal QmlGraphicsPathView::snapPosition() const
-{
- Q_D(const QmlGraphicsPathView);
- return d->snapPos;
-}
-
-void QmlGraphicsPathView::setSnapPosition(qreal pos)
-{
- Q_D(QmlGraphicsPathView);
- d->snapPos = pos/100;
- d->fixOffset();
-}
-
-/*!
- \qmlproperty real PathView::dragMargin
- This property holds the maximum distance from the path that initiate mouse dragging.
-
- By default the path can only be dragged by clicking on an item. If
- dragMargin is greater than zero, a drag can be initiated by clicking
- within dragMargin pixels of the path.
-*/
-qreal QmlGraphicsPathView::dragMargin() const
-{
- Q_D(const QmlGraphicsPathView);
- return d->dragMargin;
-}
-
-void QmlGraphicsPathView::setDragMargin(qreal dragMargin)
-{
- Q_D(QmlGraphicsPathView);
- d->dragMargin = dragMargin;
-}
-
-/*!
- \qmlproperty component PathView::delegate
-
- The delegate provides a template defining each item instantiated by the view.
- The index is exposed as an accessible \c index property. Properties of the
- model are also available depending upon the type of \l {qmlmodels}{Data Model}.
-
- Note that the PathView will layout the items based on the size of the root
- item in the delegate.
-
- Here is an example delegate:
- \snippet doc/src/snippets/declarative/pathview/pathview.qml 1
-*/
-QmlComponent *QmlGraphicsPathView::delegate() const
-{
- Q_D(const QmlGraphicsPathView);
- if (d->model) {
- if (QmlGraphicsVisualDataModel *dataModel = qobject_cast<QmlGraphicsVisualDataModel*>(d->model))
- return dataModel->delegate();
- }
-
- return 0;
-}
-
-void QmlGraphicsPathView::setDelegate(QmlComponent *c)
-{
- Q_D(QmlGraphicsPathView);
- if (!d->ownModel) {
- d->model = new QmlGraphicsVisualDataModel(qmlContext(this));
- d->ownModel = true;
- }
- if (QmlGraphicsVisualDataModel *dataModel = qobject_cast<QmlGraphicsVisualDataModel*>(d->model)) {
- dataModel->setDelegate(c);
- d->regenerate();
- }
-}
-
-/*!
- \qmlproperty int PathView::pathItemCount
- This property holds the number of items visible on the path at any one time
-*/
-int QmlGraphicsPathView::pathItemCount() const
-{
- Q_D(const QmlGraphicsPathView);
- return d->pathItems;
-}
-
-void QmlGraphicsPathView::setPathItemCount(int i)
-{
- Q_D(QmlGraphicsPathView);
- if (i == d->pathItems)
- return;
- d->pathItems = i;
- d->regenerate();
-}
-
-QPointF QmlGraphicsPathViewPrivate::pointNear(const QPointF &point, qreal *nearPercent) const
-{
- //XXX maybe do recursively at increasing resolution.
- qreal mindist = 1e10; // big number
- QPointF nearPoint = path->pointAt(0);
- qreal nearPc = 0;
- for (qreal i=1; i < 1000; i++) {
- QPointF pt = path->pointAt(i/1000.0);
- QPointF diff = pt - point;
- qreal dist = diff.x()*diff.x() + diff.y()*diff.y();
- if (dist < mindist) {
- nearPoint = pt;
- nearPc = i;
- mindist = dist;
- }
- }
-
- if (nearPercent)
- *nearPercent = nearPc / 10.0;
-
- return nearPoint;
-}
-
-
-void QmlGraphicsPathView::mousePressEvent(QGraphicsSceneMouseEvent *event)
-{
- Q_D(QmlGraphicsPathView);
- if (!d->items.count())
- return;
- QPointF scenePoint = mapToScene(event->pos());
- int idx = 0;
- for (; idx < d->items.count(); ++idx) {
- QRectF rect = d->items.at(idx)->boundingRect();
- rect = d->items.at(idx)->mapToScene(rect).boundingRect();
- if (rect.contains(scenePoint))
- break;
- }
- if (idx == d->items.count() && d->dragMargin == 0.) // didn't click on an item
- return;
-
- d->startPoint = d->pointNear(event->pos(), &d->startPc);
- if (idx == d->items.count()) {
- qreal distance = qAbs(event->pos().x() - d->startPoint.x()) + qAbs(event->pos().y() - d->startPoint.y());
- if (distance > d->dragMargin)
- return;
- }
-
- d->stealMouse = false;
- d->lastElapsed = 0;
- d->lastDist = 0;
- QmlGraphicsItemPrivate::start(d->lastPosTime);
- d->tl.clear();
-}
-
-void QmlGraphicsPathView::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
-{
- Q_D(QmlGraphicsPathView);
- if (d->lastPosTime.isNull())
- return;
-
- if (!d->stealMouse) {
- QPointF delta = event->pos() - d->startPoint;
- if (qAbs(delta.x()) > QApplication::startDragDistance() && qAbs(delta.y()) > QApplication::startDragDistance())
- d->stealMouse = true;
- }
-
- if (d->stealMouse) {
- d->moveReason = QmlGraphicsPathViewPrivate::Mouse;
- qreal newPc;
- d->pointNear(event->pos(), &newPc);
- qreal diff = newPc - d->startPc;
- if (diff) {
- setOffset(d->_offset + diff);
-
- if (diff > 50)
- diff -= 100;
- else if (diff < -50)
- diff += 100;
-
- d->lastElapsed = QmlGraphicsItemPrivate::restart(d->lastPosTime);
- d->lastDist = diff;
- d->startPc = newPc;
- }
- }
-}
-
-void QmlGraphicsPathView::mouseReleaseEvent(QGraphicsSceneMouseEvent *)
-{
- Q_D(QmlGraphicsPathView);
- if (d->lastPosTime.isNull())
- return;
-
- qreal elapsed = qreal(d->lastElapsed + QmlGraphicsItemPrivate::elapsed(d->lastPosTime)) / 1000.;
- qreal velocity = elapsed > 0. ? d->lastDist / elapsed : 0;
- if (d->model && d->model->count() && qAbs(velocity) > 5) {
- if (velocity > 100)
- velocity = 100;
- else if (velocity < -100)
- velocity = -100;
- qreal inc = qmlMod(d->_offset - d->snapPos, qreal(100.0 / d->model->count()));
- qreal dist = qAbs(velocity/2 - qmlMod(velocity/2, qreal(100.0 / d->model->count()) - inc));
- d->moveOffset.setValue(d->_offset);
- d->tl.accel(d->moveOffset, velocity, 10, dist);
- d->tl.callback(QmlTimeLineCallback(&d->moveOffset, d->fixOffsetCallback, d));
- } else {
- d->fixOffset();
- }
-
- d->lastPosTime = QTime();
- d->stealMouse = false;
- ungrabMouse();
-}
-
-bool QmlGraphicsPathView::sendMouseEvent(QGraphicsSceneMouseEvent *event)
-{
- Q_D(QmlGraphicsPathView);
- QGraphicsSceneMouseEvent mouseEvent(event->type());
- QRectF myRect = mapToScene(QRectF(0, 0, width(), height())).boundingRect();
- QGraphicsScene *s = scene();
- QmlGraphicsItem *grabber = s ? qobject_cast<QmlGraphicsItem*>(s->mouseGrabberItem()) : 0;
- if ((d->stealMouse || myRect.contains(event->scenePos().toPoint())) && (!grabber || !grabber->keepMouseGrab())) {
- mouseEvent.setAccepted(false);
- for (int i = 0x1; i <= 0x10; i <<= 1) {
- if (event->buttons() & i) {
- Qt::MouseButton button = Qt::MouseButton(i);
- mouseEvent.setButtonDownPos(button, mapFromScene(event->buttonDownPos(button)));
- }
- }
- mouseEvent.setScenePos(event->scenePos());
- mouseEvent.setLastScenePos(event->lastScenePos());
- mouseEvent.setPos(mapFromScene(event->scenePos()));
- mouseEvent.setLastPos(mapFromScene(event->lastScenePos()));
-
- switch(mouseEvent.type()) {
- case QEvent::GraphicsSceneMouseMove:
- mouseMoveEvent(&mouseEvent);
- break;
- case QEvent::GraphicsSceneMousePress:
- mousePressEvent(&mouseEvent);
- break;
- case QEvent::GraphicsSceneMouseRelease:
- mouseReleaseEvent(&mouseEvent);
- break;
- default:
- break;
- }
- grabber = qobject_cast<QmlGraphicsItem*>(s->mouseGrabberItem());
- if (grabber && d->stealMouse && !grabber->keepMouseGrab() && grabber != this)
- grabMouse();
-
- return d->stealMouse;
- } else if (!d->lastPosTime.isNull()) {
- d->lastPosTime = QTime();
- }
- return false;
-}
-
-bool QmlGraphicsPathView::sceneEventFilter(QGraphicsItem *i, QEvent *e)
-{
- if (!isVisible())
- return QmlGraphicsItem::sceneEventFilter(i, e);
-
- switch (e->type()) {
- case QEvent::GraphicsSceneMousePress:
- case QEvent::GraphicsSceneMouseMove:
- case QEvent::GraphicsSceneMouseRelease:
- {
- bool ret = sendMouseEvent(static_cast<QGraphicsSceneMouseEvent *>(e));
- if (e->type() == QEvent::GraphicsSceneMouseRelease)
- return ret;
- break;
- }
- default:
- break;
- }
-
- return QmlGraphicsItem::sceneEventFilter(i, e);
-}
-
-void QmlGraphicsPathView::componentComplete()
-{
- Q_D(QmlGraphicsPathView);
- QmlGraphicsItem::componentComplete();
- d->regenerate();
-
- // move to correct offset
- if (d->items.count()) {
- int itemIndex = (d->currentIndex - d->firstIndex + d->model->count()) % d->model->count();
-
- itemIndex += d->pathOffset;
- itemIndex %= d->items.count();
- qreal targetOffset = qmlMod(100 + (d->snapPos*100) - 100.0 * itemIndex / d->items.count(), qreal(100.0));
-
- if (targetOffset < 0)
- targetOffset = 100.0 + targetOffset;
- if (targetOffset != d->_offset) {
- d->moveOffset.setValue(targetOffset);
- }
- }
-}
-
-void QmlGraphicsPathViewPrivate::regenerate()
-{
- Q_Q(QmlGraphicsPathView);
- if (!q->isComponentComplete())
- return;
-
- for (int i=0; i<items.count(); i++){
- QmlGraphicsItem *p = items[i];
- releaseItem(p);
- }
- items.clear();
-
- if (!isValid())
- return;
-
- 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){
- int index = (i + firstIndex) % model->count();
- QmlGraphicsItem *item = getItem(index);
- if (!item) {
- qWarning() << "PathView: Cannot create item, index" << (i + firstIndex) % model->count();
- return;
- }
- items.append(item);
- item->setZValue(i);
- if (currentIndex == index)
- item->setFocus(true);
- }
- q->refill();
-}
-
-void QmlGraphicsPathViewPrivate::updateItem(QmlGraphicsItem *item, qreal percent)
-{
- if (QObject *obj = QmlGraphicsPathView::qmlAttachedProperties(item)) {
- foreach(const QString &attr, path->attributes())
- static_cast<QmlGraphicsPathViewAttached *>(obj)->setValue(attr.toUtf8(), path->attributeAt(attr, percent));
- }
- QPointF pf = path->pointAt(percent);
- item->setX(pf.x() - item->width()*item->scale()/2);
- item->setY(pf.y() - item->height()*item->scale()/2);
-}
-
-void QmlGraphicsPathView::refill()
-{
- Q_D(QmlGraphicsPathView);
- if (!d->isValid() || !isComponentComplete())
- return;
-
- QList<qreal> positions;
- for (int i=0; i<d->items.count(); i++){
- qreal percent = i * (100. / d->items.count());
- percent = percent + d->_offset;
- percent = qmlMod(percent, qreal(100.0));
- positions << qAbs(percent/100.0);
- }
-
- if (d->pathItems==-1) {
- for (int i=0; i<positions.count(); i++)
- d->updateItem(d->items.at(i), positions[i]);
- return;
- }
-
- QList<qreal> rotatedPositions;
- for (int i=0; i<d->items.count(); i++)
- rotatedPositions << positions[(i + d->pathOffset + d->items.count()) % d->items.count()];
-
- int wrapIndex= -1;
- for (int i=0; i<d->items.count()-1; i++) {
- if (rotatedPositions[i] > rotatedPositions[i+1]){
- wrapIndex = i;
- break;
- }
- }
- if (wrapIndex != -1 ){
- //A wraparound has occured
- if (wrapIndex < d->items.count()/2){
- while(wrapIndex-- >= 0){
- QmlGraphicsItem* p = d->items.takeFirst();
- d->updateItem(p, 0.0);
- d->releaseItem(p);
- d->firstIndex++;
- d->firstIndex %= d->model->count();
- int index = (d->firstIndex + d->items.count())%d->model->count();
- QmlGraphicsItem *item = d->getItem(index);
- item->setZValue(wrapIndex);
- if (d->currentIndex == index)
- item->setFocus(true);
- d->items << item;
- d->pathOffset++;
- d->pathOffset=d->pathOffset % d->items.count();
- }
- } else {
- while(wrapIndex++ < d->items.count()-1){
- QmlGraphicsItem* p = d->items.takeLast();
- d->updateItem(p, 1.0);
- d->releaseItem(p);
- d->firstIndex--;
- if (d->firstIndex < 0)
- d->firstIndex = d->model->count() - 1;
- QmlGraphicsItem *item = d->getItem(d->firstIndex);
- item->setZValue(d->firstIndex);
- if (d->currentIndex == d->firstIndex)
- item->setFocus(true);
- d->items.prepend(item);
- d->pathOffset--;
- if (d->pathOffset < 0)
- d->pathOffset = d->items.count() - 1;
- }
- }
- for (int i=0; i<d->items.count(); i++)
- rotatedPositions[i] = positions[(i + d->pathOffset + d->items.count())
- % d->items.count()];
- }
- for (int i=0; i<d->items.count(); i++)
- d->updateItem(d->items.at(i), rotatedPositions[i]);
-}
-
-void QmlGraphicsPathView::itemsInserted(int modelIndex, int count)
-{
- //XXX support animated insertion
- Q_D(QmlGraphicsPathView);
- if (!d->isValid() || !isComponentComplete())
- return;
- if (d->pathItems == -1) {
- for (int i = 0; i < count; ++i) {
- QmlGraphicsItem *item = d->getItem(modelIndex + i);
- item->setZValue(modelIndex + i);
- 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 = qmlMod(100 + (d->snapPos*100) - 100.0 * itemIndex / d->items.count(), qreal(100.0));
-
- if (targetOffset < 0)
- targetOffset = 100.0 + targetOffset;
- if (targetOffset != d->_offset)
- d->moveOffset.setValue(targetOffset);
-}
-
-void QmlGraphicsPathView::itemsRemoved(int modelIndex, int count)
-{
- //XXX support animated removal
- Q_D(QmlGraphicsPathView);
- if (!d->isValid() || !isComponentComplete())
- return;
- if (d->pathItems == -1) {
- for (int i = 0; i < count; ++i) {
- QmlGraphicsItem* p = d->items.takeAt(modelIndex);
- d->model->release(p);
- }
- d->snapToCurrent();
- refill();
- } else {
- d->regenerate();
- }
-
- if (d->model->count() == 0) {
- d->currentIndex = -1;
- d->moveOffset.setValue(0);
- return;
- }
-
- // 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 = qmlMod(100 + (d->snapPos*100) - 100.0 * itemIndex / d->items.count(), qreal(100.0));
-
- if (targetOffset < 0)
- targetOffset = 100.0 + targetOffset;
- if (targetOffset != d->_offset)
- d->moveOffset.setValue(targetOffset);
-}
-
-void QmlGraphicsPathView::createdItem(int index, QmlGraphicsItem *item)
-{
- Q_D(QmlGraphicsPathView);
- if (d->requestedIndex != index) {
- item->setParentItem(this);
- d->updateItem(item, index < d->firstIndex ? 0.0 : 1.0);
- }
-}
-
-void QmlGraphicsPathView::destroyingItem(QmlGraphicsItem *item)
-{
- Q_UNUSED(item);
-}
-
-void QmlGraphicsPathView::ticked()
-{
- Q_D(QmlGraphicsPathView);
- d->updateCurrent();
-}
-
-// find the item closest to the snap position
-int QmlGraphicsPathViewPrivate::calcCurrentIndex()
-{
- int current = -1;
- if (model && items.count()) {
- _offset = qmlMod(_offset, qreal(100.0));
- if (_offset < 0)
- _offset += 100.0;
-
- if (pathItems == -1) {
- qreal delta = qmlMod(_offset - snapPos, qreal(100.0));
- if (delta < 0)
- delta = 100.0 + delta;
- int ii = model->count() - qRound(delta * model->count() / 100);
- if (ii < 0)
- ii = 0;
- current = ii;
- } else {
- qreal bestDiff=1e9;
- int bestI=-1;
- for (int i=0; i<items.count(); i++){
- qreal percent = i * (100. / items.count());
- percent = percent + _offset;
- percent = qmlMod(percent, qreal(100.0));
- qreal diff = qAbs(snapPos - (percent/100.0));
- if (diff < bestDiff){
- bestDiff = diff;
- bestI = i;
- }
- }
- int modelIndex = (bestI - pathOffset + items.count())%items.count();
- modelIndex += firstIndex;
- current = modelIndex;
- }
- current = qAbs(current % model->count());
- }
-
- return current;
-}
-
-void QmlGraphicsPathViewPrivate::updateCurrent()
-{
- Q_Q(QmlGraphicsPathView);
- if (moveReason != Mouse)
- return;
- int idx = calcCurrentIndex();
- if (model && idx != currentIndex) {
- currentIndex = idx;
- int itemIndex = (idx - firstIndex + model->count()) % model->count();
- if (itemIndex < items.count())
- items.at(itemIndex)->setFocus(true);
- emit q->currentIndexChanged();
- }
-}
-
-void QmlGraphicsPathViewPrivate::fixOffsetCallback(void *d)
-{
- ((QmlGraphicsPathViewPrivate *)d)->fixOffset();
-}
-
-void QmlGraphicsPathViewPrivate::fixOffset()
-{
- Q_Q(QmlGraphicsPathView);
- if (model && items.count()) {
- int curr = calcCurrentIndex();
- if (curr != currentIndex)
- q->setCurrentIndex(curr);
- else
- snapToCurrent();
- }
-}
-
-void QmlGraphicsPathViewPrivate::snapToCurrent()
-{
- if (!model || model->count() <= 0)
- return;
-
- 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();
- if (otherWayRounds < rounds)
- rounds = -otherWayRounds;
-
- itemIndex += pathOffset;
- if(model->count() % items.count() && itemIndex - model->count() + items.count() > 0){
- //When model.count() is not a multiple of pathItemCount we need to manually
- //fix the index so that going backwards one step works correctly.
- itemIndex = itemIndex - model->count() + items.count();
- }
- itemIndex %= items.count();
- qreal targetOffset = qmlMod(100 + (snapPos*100) - 100.0 * itemIndex / items.count(), qreal(100.0));
-
- if (targetOffset < 0)
- targetOffset = 100.0 + targetOffset;
- if (targetOffset == _offset && rounds == 0)
- return;
-
- moveReason = Other;
- tl.clear();
- moveOffset.setValue(_offset);
-
- if (rounds!=0){
- //Compensate if the targetOffset would bring the target in from off the screen
- qreal distance = targetOffset - _offset;
- if (distance <= -50)
- rounds--;
- if (distance > 50)
- rounds++;
- tl.move(moveOffset, targetOffset + 100.0*(-rounds), QEasingCurve(QEasingCurve::InOutQuad),
- int(100*items.count()*qMax((qreal)(2.0/items.count()),(qreal)qAbs(rounds))));
- tl.callback(QmlTimeLineCallback(&moveOffset, fixOffsetCallback, this));
- return;
- }
-
- if (targetOffset - _offset > 50.0) {
- qreal distance = 100 - targetOffset + _offset;
- tl.move(moveOffset, 0.0, QEasingCurve(QEasingCurve::OutQuad), int(200 * _offset / distance));
- tl.set(moveOffset, 100.0);
- tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InQuad), int(200 * (100-targetOffset) / distance));
- } else if (targetOffset - _offset <= -50.0) {
- qreal distance = 100 - _offset + targetOffset;
- tl.move(moveOffset, 100.0, QEasingCurve(QEasingCurve::OutQuad), int(200 * (100-_offset) / distance));
- tl.set(moveOffset, 0.0);
- tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InQuad), int(200 * targetOffset / distance));
- } else {
- tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InOutQuad), 200);
- }
-}
-
-QHash<QObject*, QObject*> QmlGraphicsPathView::attachedProperties;
-QObject *QmlGraphicsPathView::qmlAttachedProperties(QObject *obj)
-{
- QObject *rv = attachedProperties.value(obj);
- if (!rv) {
- rv = new QmlGraphicsPathViewAttached(obj);
- attachedProperties.insert(obj, rv);
- }
- return rv;
-}
-
-QT_END_NAMESPACE
-
-#include <qmlgraphicspathview.moc>