src/declarative/graphicsitems/qdeclarativepathview.cpp
changeset 33 3e2da88830cd
parent 30 5dc02b23752f
child 37 758a864f9613
equal deleted inserted replaced
30:5dc02b23752f 33:3e2da88830cd
   108         if (att) {
   108         if (att) {
   109             att->m_view = q;
   109             att->m_view = q;
   110             att->setOnPath(true);
   110             att->setOnPath(true);
   111         }
   111         }
   112         item->setParentItem(q);
   112         item->setParentItem(q);
       
   113         QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item));
       
   114         itemPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
   113     }
   115     }
   114     requestedIndex = -1;
   116     requestedIndex = -1;
   115     return item;
   117     return item;
   116 }
   118 }
   117 
   119 
   119 {
   121 {
   120     if (!item || !model)
   122     if (!item || !model)
   121         return;
   123         return;
   122     if (QDeclarativePathViewAttached *att = attached(item))
   124     if (QDeclarativePathViewAttached *att = attached(item))
   123         att->setOnPath(false);
   125         att->setOnPath(false);
       
   126     QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item));
       
   127     itemPrivate->removeItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
   124     model->release(item);
   128     model->release(item);
   125 }
   129 }
   126 
   130 
   127 QDeclarativePathViewAttached *QDeclarativePathViewPrivate::attached(QDeclarativeItem *item)
   131 QDeclarativePathViewAttached *QDeclarativePathViewPrivate::attached(QDeclarativeItem *item)
   128 {
   132 {
   278     if (QDeclarativePathViewAttached *att = attached(item)) {
   282     if (QDeclarativePathViewAttached *att = attached(item)) {
   279         foreach(const QString &attr, path->attributes())
   283         foreach(const QString &attr, path->attributes())
   280             att->setValue(attr.toUtf8(), path->attributeAt(attr, percent));
   284             att->setValue(attr.toUtf8(), path->attributeAt(attr, percent));
   281     }
   285     }
   282     QPointF pf = path->pointAt(percent);
   286     QPointF pf = path->pointAt(percent);
   283     item->setX(qRound(pf.x() - item->width()*item->scale()/2));
   287     item->setX(qRound(pf.x() - item->width()/2));
   284     item->setY(qRound(pf.y() - item->height()*item->scale()/2));
   288     item->setY(qRound(pf.y() - item->height()/2));
   285 }
   289 }
   286 
   290 
   287 void QDeclarativePathViewPrivate::regenerate()
   291 void QDeclarativePathViewPrivate::regenerate()
   288 {
   292 {
   289     Q_Q(QDeclarativePathView);
   293     Q_Q(QDeclarativePathView);
   304     \qmlclass PathView QDeclarativePathView
   308     \qmlclass PathView QDeclarativePathView
   305     \since 4.7
   309     \since 4.7
   306     \brief The PathView element lays out model-provided items on a path.
   310     \brief The PathView element lays out model-provided items on a path.
   307     \inherits Item
   311     \inherits Item
   308 
   312 
   309     The model is typically provided by a QAbstractListModel "C++ model object", but can also be created directly in QML.
   313     A PathView displays data from models created from built-in QML elements like ListModel
   310 
   314     and XmlListModel, or custom model classes defined in C++ that inherit from
       
   315     QAbstractListModel.
       
   316 
       
   317     A ListView has a \l model, which defines the data to be displayed, and
       
   318     a \l delegate, which defines how the data should be displayed.  
   311     The \l delegate is instantiated for each item on the \l path.
   319     The \l delegate is instantiated for each item on the \l path.
   312     The items may be flicked to move them along the path.
   320     The items may be flicked to move them along the path.
   313 
   321 
       
   322     For example, if there is a simple list model defined in a file \c ContactModel.qml like this:
       
   323 
       
   324     \snippet doc/src/snippets/declarative/pathview/ContactModel.qml 0
       
   325 
       
   326     This data can be represented as a PathView, like this:
       
   327 
   314     \snippet doc/src/snippets/declarative/pathview/pathview.qml 0
   328     \snippet doc/src/snippets/declarative/pathview/pathview.qml 0
   315 
   329 
   316     \image pathview.gif
   330     \image pathview.gif
       
   331 
       
   332     (Note the above example uses PathAttribute to scale and modify the
       
   333     opacity of the items as they rotate. This additional code can be seen in the
       
   334     PathAttribute documentation.)
   317 
   335 
   318     Delegates are instantiated as needed and may be destroyed at any time.
   336     Delegates are instantiated as needed and may be destroyed at any time.
   319     State should \e never be stored in a delegate.
   337     State should \e never be stored in a delegate.
   320 
   338 
   321     \bold Note that views do not enable \e clip automatically.  If the view
   339     \bold Note that views do not enable \e clip automatically.  If the view
   340     if (d->attType)
   358     if (d->attType)
   341         d->attType->release();
   359         d->attType->release();
   342     if (d->ownModel)
   360     if (d->ownModel)
   343         delete d->model;
   361         delete d->model;
   344 }
   362 }
       
   363 
       
   364 /*!
       
   365     \qmlattachedproperty PathView PathView::view
       
   366     This attached property holds the view that manages this delegate instance.
       
   367 
       
   368     It is attached to each instance of the delegate.
       
   369 */
   345 
   370 
   346 /*!
   371 /*!
   347     \qmlattachedproperty bool PathView::onPath
   372     \qmlattachedproperty bool PathView::onPath
   348     This attached property holds whether the item is currently on the path.
   373     This attached property holds whether the item is currently on the path.
   349 
   374 
   529 
   554 
   530 /*!
   555 /*!
   531     \qmlmethod PathView::incrementCurrentIndex()
   556     \qmlmethod PathView::incrementCurrentIndex()
   532 
   557 
   533     Increments the current index.
   558     Increments the current index.
       
   559 
       
   560     \bold Note: methods should only be called after the Component has completed.
   534 */
   561 */
   535 void QDeclarativePathView::incrementCurrentIndex()
   562 void QDeclarativePathView::incrementCurrentIndex()
   536 {
   563 {
   537     setCurrentIndex(currentIndex()+1);
   564     setCurrentIndex(currentIndex()+1);
   538 }
   565 }
   540 
   567 
   541 /*!
   568 /*!
   542     \qmlmethod PathView::decrementCurrentIndex()
   569     \qmlmethod PathView::decrementCurrentIndex()
   543 
   570 
   544     Decrements the current index.
   571     Decrements the current index.
       
   572 
       
   573     \bold Note: methods should only be called after the Component has completed.
   545 */
   574 */
   546 void QDeclarativePathView::decrementCurrentIndex()
   575 void QDeclarativePathView::decrementCurrentIndex()
   547 {
   576 {
   548     Q_D(QDeclarativePathView);
   577     Q_D(QDeclarativePathView);
   549     if (d->model && d->model->count()) {
   578     if (d->model && d->model->count()) {
   879     if (i == d->pathItems)
   908     if (i == d->pathItems)
   880         return;
   909         return;
   881     if (i < 1)
   910     if (i < 1)
   882         i = 1;
   911         i = 1;
   883     d->pathItems = i;
   912     d->pathItems = i;
       
   913     d->updateMappedRange();
   884     if (d->isValid() && isComponentComplete()) {
   914     if (d->isValid() && isComponentComplete()) {
   885         d->regenerate();
   915         d->regenerate();
   886     }
   916     }
   887     emit pathItemCountChanged();
   917     emit pathItemCountChanged();
   888 }
   918 }
   942 }
   972 }
   943 
   973 
   944 void QDeclarativePathView::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
   974 void QDeclarativePathView::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
   945 {
   975 {
   946     Q_D(QDeclarativePathView);
   976     Q_D(QDeclarativePathView);
   947     if (!d->interactive || d->lastPosTime.isNull())
   977     if (!d->interactive || !d->lastPosTime.isValid())
   948         return;
   978         return;
   949 
   979 
   950     if (!d->stealMouse) {
   980     if (!d->stealMouse) {
   951         QPointF delta = event->pos() - d->startPoint;
   981         QPointF delta = event->pos() - d->startPoint;
   952         if (qAbs(delta.x()) > QApplication::startDragDistance() && qAbs(delta.y()) > QApplication::startDragDistance())
   982         if (qAbs(delta.x()) > QApplication::startDragDistance() && qAbs(delta.y()) > QApplication::startDragDistance())
   976 void QDeclarativePathView::mouseReleaseEvent(QGraphicsSceneMouseEvent *)
  1006 void QDeclarativePathView::mouseReleaseEvent(QGraphicsSceneMouseEvent *)
   977 {
  1007 {
   978     Q_D(QDeclarativePathView);
  1008     Q_D(QDeclarativePathView);
   979     d->stealMouse = false;
  1009     d->stealMouse = false;
   980     setKeepMouseGrab(false);
  1010     setKeepMouseGrab(false);
   981     if (!d->interactive || d->lastPosTime.isNull())
  1011     if (!d->interactive || !d->lastPosTime.isValid())
   982         return;
  1012         return;
   983 
  1013 
   984     qreal elapsed = qreal(d->lastElapsed + QDeclarativeItemPrivate::elapsed(d->lastPosTime)) / 1000.;
  1014     qreal elapsed = qreal(d->lastElapsed + QDeclarativeItemPrivate::elapsed(d->lastPosTime)) / 1000.;
   985     qreal velocity = elapsed > 0. ? d->lastDist / elapsed : 0;
  1015     qreal velocity = elapsed > 0. ? d->lastDist / elapsed : 0;
   986     if (d->model && d->model->count() && qAbs(velocity) > 1.) {
  1016     if (d->model && d->model->count() && qAbs(velocity) > 1.) {
  1011         d->tl.callback(QDeclarativeTimeLineCallback(&d->moveOffset, d->fixOffsetCallback, d));
  1041         d->tl.callback(QDeclarativeTimeLineCallback(&d->moveOffset, d->fixOffsetCallback, d));
  1012     } else {
  1042     } else {
  1013         d->fixOffset();
  1043         d->fixOffset();
  1014     }
  1044     }
  1015 
  1045 
  1016     d->lastPosTime = QTime();
  1046     d->lastPosTime.invalidate();
  1017     ungrabMouse();
  1047     ungrabMouse();
  1018 }
  1048 }
  1019 
  1049 
  1020 bool QDeclarativePathView::sendMouseEvent(QGraphicsSceneMouseEvent *event)
  1050 bool QDeclarativePathView::sendMouseEvent(QGraphicsSceneMouseEvent *event)
  1021 {
  1051 {
  1053         grabber = qobject_cast<QDeclarativeItem*>(s->mouseGrabberItem());
  1083         grabber = qobject_cast<QDeclarativeItem*>(s->mouseGrabberItem());
  1054         if (grabber && d->stealMouse && !grabber->keepMouseGrab() && grabber != this)
  1084         if (grabber && d->stealMouse && !grabber->keepMouseGrab() && grabber != this)
  1055             grabMouse();
  1085             grabMouse();
  1056 
  1086 
  1057         return d->stealMouse;
  1087         return d->stealMouse;
  1058     } else if (!d->lastPosTime.isNull()) {
  1088     } else if (d->lastPosTime.isValid()) {
  1059         d->lastPosTime = QTime();
  1089         d->lastPosTime.invalidate();
  1060     }
  1090     }
  1061     return false;
  1091     return false;
  1062 }
  1092 }
  1063 
  1093 
  1064 bool QDeclarativePathView::sceneEventFilter(QGraphicsItem *i, QEvent *e)
  1094 bool QDeclarativePathView::sceneEventFilter(QGraphicsItem *i, QEvent *e)
  1082     }
  1112     }
  1083 
  1113 
  1084     return QDeclarativeItem::sceneEventFilter(i, e);
  1114     return QDeclarativeItem::sceneEventFilter(i, e);
  1085 }
  1115 }
  1086 
  1116 
       
  1117 bool QDeclarativePathView::event(QEvent *event)
       
  1118 {
       
  1119     if (event->type() == QEvent::User) {
       
  1120         refill();
       
  1121         return true;
       
  1122     }
       
  1123 
       
  1124     return QDeclarativeItem::event(event);
       
  1125 }
       
  1126 
  1087 void QDeclarativePathView::componentComplete()
  1127 void QDeclarativePathView::componentComplete()
  1088 {
  1128 {
  1089     Q_D(QDeclarativePathView);
  1129     Q_D(QDeclarativePathView);
  1090     QDeclarativeItem::componentComplete();
  1130     QDeclarativeItem::componentComplete();
  1091     d->createHighlight();
  1131     d->createHighlight();
  1101 {
  1141 {
  1102     Q_D(QDeclarativePathView);
  1142     Q_D(QDeclarativePathView);
  1103     if (!d->isValid() || !isComponentComplete())
  1143     if (!d->isValid() || !isComponentComplete())
  1104         return;
  1144         return;
  1105 
  1145 
       
  1146     d->layoutScheduled = false;
  1106     bool currentVisible = false;
  1147     bool currentVisible = false;
  1107 
  1148 
  1108     // first move existing items and remove items off path
  1149     // first move existing items and remove items off path
  1109     int idx = d->firstIndex;
  1150     int idx = d->firstIndex;
  1110     QList<QDeclarativeItem*>::iterator it = d->items.begin();
  1151     QList<QDeclarativeItem*>::iterator it = d->items.begin();