source: trunk/src/declarative/graphicsitems/qdeclarativepath.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 25.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtDeclarative module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "private/qdeclarativepath_p.h"
43#include "private/qdeclarativepath_p_p.h"
44
45#include <QSet>
46#include <QTime>
47
48#include <private/qbezier_p.h>
49#include <QtCore/qmath.h>
50#include <QtCore/qnumeric.h>
51
52QT_BEGIN_NAMESPACE
53
54/*!
55 \qmlclass PathElement QDeclarativePathElement
56 \ingroup qml-view-elements
57 \since 4.7
58 \brief PathElement is the base path type.
59
60 This type is the base for all path types. It cannot
61 be instantiated.
62
63 \sa Path, PathAttribute, PathPercent, PathLine, PathQuad, PathCubic
64*/
65
66/*!
67 \qmlclass Path QDeclarativePath
68 \ingroup qml-view-elements
69 \since 4.7
70 \brief A Path object defines a path for use by \l PathView.
71
72 A Path is composed of one or more path segments - PathLine, PathQuad,
73 PathCubic.
74
75 The spacing of the items along the Path can be adjusted via a
76 PathPercent object.
77
78 PathAttribute allows named attributes with values to be defined
79 along the path.
80
81 \sa PathView, PathAttribute, PathPercent, PathLine, PathQuad, PathCubic
82*/
83QDeclarativePath::QDeclarativePath(QObject *parent)
84 : QObject(*(new QDeclarativePathPrivate), parent)
85{
86}
87
88QDeclarativePath::~QDeclarativePath()
89{
90}
91
92/*!
93 \qmlproperty real Path::startX
94 \qmlproperty real Path::startY
95 These properties hold the starting position of the path.
96*/
97qreal QDeclarativePath::startX() const
98{
99 Q_D(const QDeclarativePath);
100 return d->startX;
101}
102
103void QDeclarativePath::setStartX(qreal x)
104{
105 Q_D(QDeclarativePath);
106 if (qFuzzyCompare(x, d->startX))
107 return;
108 d->startX = x;
109 emit startXChanged();
110 processPath();
111}
112
113qreal QDeclarativePath::startY() const
114{
115 Q_D(const QDeclarativePath);
116 return d->startY;
117}
118
119void QDeclarativePath::setStartY(qreal y)
120{
121 Q_D(QDeclarativePath);
122 if (qFuzzyCompare(y, d->startY))
123 return;
124 d->startY = y;
125 emit startYChanged();
126 processPath();
127}
128
129/*!
130 \qmlproperty bool Path::closed
131 This property holds whether the start and end of the path are identical.
132*/
133bool QDeclarativePath::isClosed() const
134{
135 Q_D(const QDeclarativePath);
136 return d->closed;
137}
138
139/*!
140 \qmlproperty list<PathElement> Path::pathElements
141 This property holds the objects composing the path.
142
143 \default
144
145 A path can contain the following path objects:
146 \list
147 \i \l PathLine - a straight line to a given position.
148 \i \l PathQuad - a quadratic Bezier curve to a given position with a control point.
149 \i \l PathCubic - a cubic Bezier curve to a given position with two control points.
150 \i \l PathAttribute - an attribute at a given position in the path.
151 \i \l PathPercent - a way to spread out items along various segments of the path.
152 \endlist
153
154 \snippet doc/src/snippets/declarative/pathview/pathattributes.qml 2
155*/
156
157QDeclarativeListProperty<QDeclarativePathElement> QDeclarativePath::pathElements()
158{
159 Q_D(QDeclarativePath);
160 return QDeclarativeListProperty<QDeclarativePathElement>(this, d->_pathElements);
161}
162
163void QDeclarativePath::interpolate(int idx, const QString &name, qreal value)
164{
165 Q_D(QDeclarativePath);
166 if (!idx)
167 return;
168
169 qreal lastValue = 0;
170 qreal lastPercent = 0;
171 int search = idx - 1;
172 while(search >= 0) {
173 const AttributePoint &point = d->_attributePoints.at(search);
174 if (point.values.contains(name)) {
175 lastValue = point.values.value(name);
176 lastPercent = point.origpercent;
177 break;
178 }
179 --search;
180 }
181
182 ++search;
183
184 const AttributePoint &curPoint = d->_attributePoints.at(idx);
185
186 for (int ii = search; ii < idx; ++ii) {
187 AttributePoint &point = d->_attributePoints[ii];
188
189 qreal val = lastValue + (value - lastValue) * (point.origpercent - lastPercent) / (curPoint.origpercent - lastPercent);
190 point.values.insert(name, val);
191 }
192}
193
194void QDeclarativePath::endpoint(const QString &name)
195{
196 Q_D(QDeclarativePath);
197 const AttributePoint &first = d->_attributePoints.first();
198 qreal val = first.values.value(name);
199 for (int ii = d->_attributePoints.count() - 1; ii >= 0; ii--) {
200 const AttributePoint &point = d->_attributePoints.at(ii);
201 if (point.values.contains(name)) {
202 for (int jj = ii + 1; jj < d->_attributePoints.count(); ++jj) {
203 AttributePoint &setPoint = d->_attributePoints[jj];
204 setPoint.values.insert(name, val);
205 }
206 return;
207 }
208 }
209}
210
211void QDeclarativePath::processPath()
212{
213 Q_D(QDeclarativePath);
214
215 if (!d->componentComplete)
216 return;
217
218 d->_pointCache.clear();
219 d->_attributePoints.clear();
220 d->_path = QPainterPath();
221
222 AttributePoint first;
223 for (int ii = 0; ii < d->_attributes.count(); ++ii)
224 first.values[d->_attributes.at(ii)] = 0;
225 d->_attributePoints << first;
226
227 d->_path.moveTo(d->startX, d->startY);
228
229 QDeclarativeCurve *lastCurve = 0;
230 foreach (QDeclarativePathElement *pathElement, d->_pathElements) {
231 if (QDeclarativeCurve *curve = qobject_cast<QDeclarativeCurve *>(pathElement)) {
232 curve->addToPath(d->_path);
233 AttributePoint p;
234 p.origpercent = d->_path.length();
235 d->_attributePoints << p;
236 lastCurve = curve;
237 } else if (QDeclarativePathAttribute *attribute = qobject_cast<QDeclarativePathAttribute *>(pathElement)) {
238 AttributePoint &point = d->_attributePoints.last();
239 point.values[attribute->name()] = attribute->value();
240 interpolate(d->_attributePoints.count() - 1, attribute->name(), attribute->value());
241 } else if (QDeclarativePathPercent *percent = qobject_cast<QDeclarativePathPercent *>(pathElement)) {
242 AttributePoint &point = d->_attributePoints.last();
243 point.values[QLatin1String("_qfx_percent")] = percent->value();
244 interpolate(d->_attributePoints.count() - 1, QLatin1String("_qfx_percent"), percent->value());
245 }
246 }
247
248 // Fixup end points
249 const AttributePoint &last = d->_attributePoints.last();
250 for (int ii = 0; ii < d->_attributes.count(); ++ii) {
251 if (!last.values.contains(d->_attributes.at(ii)))
252 endpoint(d->_attributes.at(ii));
253 }
254
255 // Adjust percent
256 qreal length = d->_path.length();
257 qreal prevpercent = 0;
258 qreal prevorigpercent = 0;
259 for (int ii = 0; ii < d->_attributePoints.count(); ++ii) {
260 const AttributePoint &point = d->_attributePoints.at(ii);
261 if (point.values.contains(QLatin1String("_qfx_percent"))) { //special string for QDeclarativePathPercent
262 if ( ii > 0) {
263 qreal scale = (d->_attributePoints[ii].origpercent/length - prevorigpercent) /
264 (point.values.value(QLatin1String("_qfx_percent"))-prevpercent);
265 d->_attributePoints[ii].scale = scale;
266 }
267 d->_attributePoints[ii].origpercent /= length;
268 d->_attributePoints[ii].percent = point.values.value(QLatin1String("_qfx_percent"));
269 prevorigpercent = d->_attributePoints[ii].origpercent;
270 prevpercent = d->_attributePoints[ii].percent;
271 } else {
272 d->_attributePoints[ii].origpercent /= length;
273 d->_attributePoints[ii].percent = d->_attributePoints[ii].origpercent;
274 }
275 }
276
277 d->closed = lastCurve && d->startX == lastCurve->x() && d->startY == lastCurve->y();
278
279 emit changed();
280}
281
282void QDeclarativePath::classBegin()
283{
284 Q_D(QDeclarativePath);
285 d->componentComplete = false;
286}
287
288void QDeclarativePath::componentComplete()
289{
290 Q_D(QDeclarativePath);
291 QSet<QString> attrs;
292 d->componentComplete = true;
293
294 // First gather up all the attributes
295 foreach (QDeclarativePathElement *pathElement, d->_pathElements) {
296 if (QDeclarativePathAttribute *attribute =
297 qobject_cast<QDeclarativePathAttribute *>(pathElement))
298 attrs.insert(attribute->name());
299 }
300 d->_attributes = attrs.toList();
301
302 processPath();
303
304 foreach (QDeclarativePathElement *pathElement, d->_pathElements)
305 connect(pathElement, SIGNAL(changed()), this, SLOT(processPath()));
306}
307
308QPainterPath QDeclarativePath::path() const
309{
310 Q_D(const QDeclarativePath);
311 return d->_path;
312}
313
314QStringList QDeclarativePath::attributes() const
315{
316 Q_D(const QDeclarativePath);
317 if (!d->componentComplete) {
318 QSet<QString> attrs;
319
320 // First gather up all the attributes
321 foreach (QDeclarativePathElement *pathElement, d->_pathElements) {
322 if (QDeclarativePathAttribute *attribute =
323 qobject_cast<QDeclarativePathAttribute *>(pathElement))
324 attrs.insert(attribute->name());
325 }
326 return attrs.toList();
327 }
328 return d->_attributes;
329}
330
331static inline QBezier nextBezier(const QPainterPath &path, int *from, qreal *bezLength)
332{
333 const int lastElement = path.elementCount() - 1;
334 for (int i=*from; i <= lastElement; ++i) {
335 const QPainterPath::Element &e = path.elementAt(i);
336
337 switch (e.type) {
338 case QPainterPath::MoveToElement:
339 break;
340 case QPainterPath::LineToElement:
341 {
342 QLineF line(path.elementAt(i-1), e);
343 *bezLength = line.length();
344 QPointF a = path.elementAt(i-1);
345 QPointF delta = e - a;
346 *from = i+1;
347 return QBezier::fromPoints(a, a + delta / 3, a + 2 * delta / 3, e);
348 }
349 case QPainterPath::CurveToElement:
350 {
351 QBezier b = QBezier::fromPoints(path.elementAt(i-1),
352 e,
353 path.elementAt(i+1),
354 path.elementAt(i+2));
355 *bezLength = b.length();
356 *from = i+3;
357 return b;
358 }
359 default:
360 break;
361 }
362 }
363 *from = lastElement;
364 *bezLength = 0;
365 return QBezier();
366}
367
368void QDeclarativePath::createPointCache() const
369{
370 Q_D(const QDeclarativePath);
371 qreal pathLength = d->_path.length();
372 if (pathLength <= 0 || qIsNaN(pathLength))
373 return;
374 // more points means less jitter between items as they move along the
375 // path, but takes longer to generate
376 const int points = qCeil(pathLength*5);
377 const int lastElement = d->_path.elementCount() - 1;
378 d->_pointCache.resize(points+1);
379
380 int currElement = 0;
381 qreal bezLength = 0;
382 QBezier currBez = nextBezier(d->_path, &currElement, &bezLength);
383 qreal currLength = bezLength;
384 qreal epc = currLength / pathLength;
385
386 for (int i = 0; i < d->_pointCache.size(); i++) {
387 //find which set we are in
388 qreal prevPercent = 0;
389 qreal prevOrigPercent = 0;
390 for (int ii = 0; ii < d->_attributePoints.count(); ++ii) {
391 qreal percent = qreal(i)/points;
392 const AttributePoint &point = d->_attributePoints.at(ii);
393 if (percent < point.percent || ii == d->_attributePoints.count() - 1) { //### || is special case for very last item
394 qreal elementPercent = (percent - prevPercent);
395
396 qreal spc = prevOrigPercent + elementPercent * point.scale;
397
398 while (spc > epc) {
399 if (currElement > lastElement)
400 break;
401 currBez = nextBezier(d->_path, &currElement, &bezLength);
402 if (bezLength == 0.0) {
403 currLength = pathLength;
404 epc = 1.0;
405 break;
406 }
407 currLength += bezLength;
408 epc = currLength / pathLength;
409 }
410 qreal realT = (pathLength * spc - (currLength - bezLength)) / bezLength;
411 d->_pointCache[i] = currBez.pointAt(qBound(qreal(0), realT, qreal(1)));
412 break;
413 }
414 prevOrigPercent = point.origpercent;
415 prevPercent = point.percent;
416 }
417 }
418}
419
420QPointF QDeclarativePath::pointAt(qreal p) const
421{
422 Q_D(const QDeclarativePath);
423 if (d->_pointCache.isEmpty()) {
424 createPointCache();
425 if (d->_pointCache.isEmpty())
426 return QPointF();
427 }
428 int idx = qRound(p*d->_pointCache.size());
429 if (idx >= d->_pointCache.size())
430 idx = d->_pointCache.size() - 1;
431 else if (idx < 0)
432 idx = 0;
433 return d->_pointCache.at(idx);
434}
435
436qreal QDeclarativePath::attributeAt(const QString &name, qreal percent) const
437{
438 Q_D(const QDeclarativePath);
439 if (percent < 0 || percent > 1)
440 return 0;
441
442 for (int ii = 0; ii < d->_attributePoints.count(); ++ii) {
443 const AttributePoint &point = d->_attributePoints.at(ii);
444
445 if (point.percent == percent) {
446 return point.values.value(name);
447 } else if (point.percent > percent) {
448 qreal lastValue =
449 ii?(d->_attributePoints.at(ii - 1).values.value(name)):0;
450 qreal lastPercent =
451 ii?(d->_attributePoints.at(ii - 1).percent):0;
452 qreal curValue = point.values.value(name);
453 qreal curPercent = point.percent;
454
455 return lastValue + (curValue - lastValue) * (percent - lastPercent) / (curPercent - lastPercent);
456 }
457 }
458
459 return 0;
460}
461
462/****************************************************************************/
463
464qreal QDeclarativeCurve::x() const
465{
466 return _x;
467}
468
469void QDeclarativeCurve::setX(qreal x)
470{
471 if (_x != x) {
472 _x = x;
473 emit xChanged();
474 emit changed();
475 }
476}
477
478qreal QDeclarativeCurve::y() const
479{
480 return _y;
481}
482
483void QDeclarativeCurve::setY(qreal y)
484{
485 if (_y != y) {
486 _y = y;
487 emit yChanged();
488 emit changed();
489 }
490}
491
492/****************************************************************************/
493
494/*!
495 \qmlclass PathAttribute QDeclarativePathAttribute
496 \ingroup qml-view-elements
497 \since 4.7
498 \brief The PathAttribute allows setting an attribute at a given position in a Path.
499
500 The PathAttribute object allows attributes consisting of a name and
501 a value to be specified for various points along a path. The
502 attributes are exposed to the delegate as
503 \l{qdeclarativeintroduction.html#attached-properties} {Attached Properties}.
504 The value of an attribute at any particular point along the path is interpolated
505 from the PathAttributes bounding that point.
506
507 The example below shows a path with the items scaled to 30% with
508 opacity 50% at the top of the path and scaled 100% with opacity
509 100% at the bottom. Note the use of the PathView.iconScale and
510 PathView.iconOpacity attached properties to set the scale and opacity
511 of the delegate.
512
513 \table
514 \row
515 \o \image declarative-pathattribute.png
516 \o
517 \snippet doc/src/snippets/declarative/pathview/pathattributes.qml 0
518 (see the PathView documentation for the specification of ContactModel.qml
519 used for ContactModel above.)
520 \endtable
521
522
523 \sa Path
524*/
525
526/*!
527 \qmlproperty string PathAttribute::name
528 This property holds the name of the attribute to change.
529
530 This attribute will be available to the delegate as PathView.<name>
531
532 Note that using an existing Item property name such as "opacity" as an
533 attribute is allowed. This is because path attributes add a new
534 \l{qdeclarativeintroduction.html#attached-properties} {Attached Property}
535 which in no way clashes with existing properties.
536*/
537
538/*!
539 the name of the attribute to change.
540*/
541
542QString QDeclarativePathAttribute::name() const
543{
544 return _name;
545}
546
547void QDeclarativePathAttribute::setName(const QString &name)
548{
549 if (_name == name)
550 return;
551 _name = name;
552 emit nameChanged();
553}
554
555/*!
556 \qmlproperty real PathAttribute::value
557 This property holds the value for the attribute.
558
559 The value specified can be used to influence the visual appearance
560 of an item along the path. For example, the following Path specifies
561 an attribute named \e itemRotation, which has the value \e 0 at the
562 beginning of the path, and the value 90 at the end of the path.
563
564 \qml
565 Path {
566 startX: 0
567 startY: 0
568 PathAttribute { name: "itemRotation"; value: 0 }
569 PathLine { x: 100; y: 100 }
570 PathAttribute { name: "itemRotation"; value: 90 }
571 }
572 \endqml
573
574 In our delegate, we can then bind the \e rotation property to the
575 \l{qdeclarativeintroduction.html#attached-properties} {Attached Property}
576 \e PathView.itemRotation created for this attribute.
577
578 \qml
579 Rectangle {
580 width: 10; height: 10
581 rotation: PathView.itemRotation
582 }
583 \endqml
584
585 As each item is positioned along the path, it will be rotated accordingly:
586 an item at the beginning of the path with be not be rotated, an item at
587 the end of the path will be rotated 90 degrees, and an item mid-way along
588 the path will be rotated 45 degrees.
589*/
590
591/*!
592 the new value of the attribute.
593*/
594qreal QDeclarativePathAttribute::value() const
595{
596 return _value;
597}
598
599void QDeclarativePathAttribute::setValue(qreal value)
600{
601 if (_value != value) {
602 _value = value;
603 emit valueChanged();
604 emit changed();
605 }
606}
607
608/****************************************************************************/
609
610/*!
611 \qmlclass PathLine QDeclarativePathLine
612 \ingroup qml-view-elements
613 \since 4.7
614 \brief The PathLine defines a straight line.
615
616 The example below creates a path consisting of a straight line from
617 0,100 to 200,100:
618
619 \qml
620 Path {
621 startX: 0; startY: 100
622 PathLine { x: 200; y: 100 }
623 }
624 \endqml
625
626 \sa Path, PathQuad, PathCubic
627*/
628
629/*!
630 \qmlproperty real PathLine::x
631 \qmlproperty real PathLine::y
632
633 Defines the end point of the line.
634*/
635
636void QDeclarativePathLine::addToPath(QPainterPath &path)
637{
638 path.lineTo(x(), y());
639}
640
641/****************************************************************************/
642
643/*!
644 \qmlclass PathQuad QDeclarativePathQuad
645 \ingroup qml-view-elements
646 \since 4.7
647 \brief The PathQuad defines a quadratic Bezier curve with a control point.
648
649 The following QML produces the path shown below:
650 \table
651 \row
652 \o \image declarative-pathquad.png
653 \o
654 \qml
655 Path {
656 startX: 0; startY: 0
657 PathQuad { x: 200; y: 0; controlX: 100; controlY: 150 }
658 }
659 \endqml
660 \endtable
661
662 \sa Path, PathCubic, PathLine
663*/
664
665/*!
666 \qmlproperty real PathQuad::x
667 \qmlproperty real PathQuad::y
668
669 Defines the end point of the curve.
670*/
671
672/*!
673 \qmlproperty real PathQuad::controlX
674 \qmlproperty real PathQuad::controlY
675
676 Defines the position of the control point.
677*/
678
679/*!
680 the x position of the control point.
681*/
682qreal QDeclarativePathQuad::controlX() const
683{
684 return _controlX;
685}
686
687void QDeclarativePathQuad::setControlX(qreal x)
688{
689 if (_controlX != x) {
690 _controlX = x;
691 emit controlXChanged();
692 emit changed();
693 }
694}
695
696
697/*!
698 the y position of the control point.
699*/
700qreal QDeclarativePathQuad::controlY() const
701{
702 return _controlY;
703}
704
705void QDeclarativePathQuad::setControlY(qreal y)
706{
707 if (_controlY != y) {
708 _controlY = y;
709 emit controlYChanged();
710 emit changed();
711 }
712}
713
714void QDeclarativePathQuad::addToPath(QPainterPath &path)
715{
716 path.quadTo(controlX(), controlY(), x(), y());
717}
718
719/****************************************************************************/
720
721/*!
722 \qmlclass PathCubic QDeclarativePathCubic
723 \ingroup qml-view-elements
724 \since 4.7
725 \brief The PathCubic defines a cubic Bezier curve with two control points.
726
727 The following QML produces the path shown below:
728 \table
729 \row
730 \o \image declarative-pathcubic.png
731 \o
732 \qml
733 Path {
734 startX: 20; startY: 0
735 PathCubic {
736 x: 180; y: 0
737 control1X: -10; control1Y: 90
738 control2X: 210; control2Y: 90
739 }
740 }
741 \endqml
742 \endtable
743
744 \sa Path, PathQuad, PathLine
745*/
746
747/*!
748 \qmlproperty real PathCubic::x
749 \qmlproperty real PathCubic::y
750
751 Defines the end point of the curve.
752*/
753
754/*!
755 \qmlproperty real PathCubic::control1X
756 \qmlproperty real PathCubic::control1Y
757
758 Defines the position of the first control point.
759*/
760qreal QDeclarativePathCubic::control1X() const
761{
762 return _control1X;
763}
764
765void QDeclarativePathCubic::setControl1X(qreal x)
766{
767 if (_control1X != x) {
768 _control1X = x;
769 emit control1XChanged();
770 emit changed();
771 }
772}
773
774qreal QDeclarativePathCubic::control1Y() const
775{
776 return _control1Y;
777}
778
779void QDeclarativePathCubic::setControl1Y(qreal y)
780{
781 if (_control1Y != y) {
782 _control1Y = y;
783 emit control1YChanged();
784 emit changed();
785 }
786}
787
788/*!
789 \qmlproperty real PathCubic::control2X
790 \qmlproperty real PathCubic::control2Y
791
792 Defines the position of the second control point.
793*/
794qreal QDeclarativePathCubic::control2X() const
795{
796 return _control2X;
797}
798
799void QDeclarativePathCubic::setControl2X(qreal x)
800{
801 if (_control2X != x) {
802 _control2X = x;
803 emit control2XChanged();
804 emit changed();
805 }
806}
807
808qreal QDeclarativePathCubic::control2Y() const
809{
810 return _control2Y;
811}
812
813void QDeclarativePathCubic::setControl2Y(qreal y)
814{
815 if (_control2Y != y) {
816 _control2Y = y;
817 emit control2YChanged();
818 emit changed();
819 }
820}
821
822void QDeclarativePathCubic::addToPath(QPainterPath &path)
823{
824 path.cubicTo(control1X(), control1Y(), control2X(), control2Y(), x(), y());
825}
826
827/****************************************************************************/
828
829/*!
830 \qmlclass PathPercent QDeclarativePathPercent
831 \ingroup qml-view-elements
832 \since 4.7
833 \brief The PathPercent manipulates the way a path is interpreted.
834
835 PathPercent allows you to manipulate the spacing between items on a
836 PathView's path. You can use it to bunch together items on part of
837 the path, and spread them out on other parts of the path.
838
839 The examples below show the normal distrubution of items along a path
840 compared to a distribution which places 50% of the items along the
841 PathLine section of the path.
842 \table
843 \row
844 \o \image declarative-nopercent.png
845 \o
846 \qml
847 PathView {
848 ...
849 Path {
850 startX: 20; startY: 0
851 PathQuad { x: 50; y: 80; controlX: 0; controlY: 80 }
852 PathLine { x: 150; y: 80 }
853 PathQuad { x: 180; y: 0; controlX: 200; controlY: 80 }
854 }
855 }
856 \endqml
857 \row
858 \o \image declarative-percent.png
859 \o
860 \qml
861 PathView {
862 ...
863 Path {
864 startX: 20; startY: 0
865 PathQuad { x: 50; y: 80; controlX: 0; controlY: 80 }
866 PathPercent { value: 0.25 }
867 PathLine { x: 150; y: 80 }
868 PathPercent { value: 0.75 }
869 PathQuad { x: 180; y: 0; controlX: 200; controlY: 80 }
870 PathPercent { value: 1 }
871 }
872 }
873 \endqml
874 \endtable
875
876 \sa Path
877*/
878
879/*!
880 \qmlproperty real PathPercent::value
881 The proporation of items that should be laid out up to this point.
882
883 This value should always be higher than the last value specified
884 by a PathPercent at a previous position in the Path.
885
886 In the following example we have a Path made up of three PathLines.
887 Normally, the items of the PathView would be laid out equally along
888 this path, with an equal number of items per line segment. PathPercent
889 allows us to specify that the first and third lines should each hold
890 10% of the laid out items, while the second line should hold the remaining
891 80%.
892
893 \qml
894 PathView {
895 ...
896 Path {
897 startX: 0; startY: 0
898 PathLine { x:100; y: 0; }
899 PathPercent { value: 0.1 }
900 PathLine { x: 100; y: 100 }
901 PathPercent { value: 0.9 }
902 PathLine { x: 100; y: 0 }
903 PathPercent { value: 1 }
904 }
905 }
906 \endqml
907*/
908
909qreal QDeclarativePathPercent::value() const
910{
911 return _value;
912}
913
914void QDeclarativePathPercent::setValue(qreal value)
915{
916 if (_value != value) {
917 _value = value;
918 emit valueChanged();
919 emit changed();
920 }
921}
922QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.