Initial import from the monolithic Qt.
[profile/ivi/qtdeclarative.git] / src / declarative / graphicsitems / qdeclarativepositioners.cpp
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 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
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 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "private/qdeclarativepositioners_p.h"
43 #include "private/qdeclarativepositioners_p_p.h"
44
45 #include <qdeclarative.h>
46 #include <qdeclarativestate_p.h>
47 #include <qdeclarativestategroup_p.h>
48 #include <qdeclarativestateoperations_p.h>
49 #include <qdeclarativeinfo.h>
50 #include <QtCore/qmath.h>
51
52 #include <QDebug>
53 #include <QCoreApplication>
54
55 QT_BEGIN_NAMESPACE
56
57 static const QDeclarativeItemPrivate::ChangeTypes watchedChanges
58     = QDeclarativeItemPrivate::Geometry
59     | QDeclarativeItemPrivate::SiblingOrder
60     | QDeclarativeItemPrivate::Visibility
61     | QDeclarativeItemPrivate::Opacity
62     | QDeclarativeItemPrivate::Destroyed;
63
64 void QDeclarativeBasePositionerPrivate::watchChanges(QGraphicsObject *other)
65 {
66     if (QGraphicsItemPrivate::get(other)->isDeclarativeItem) {
67         QDeclarativeItemPrivate *otherPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(other));
68         otherPrivate->addItemChangeListener(this, watchedChanges);
69     } else {
70         Q_Q(QDeclarativeBasePositioner);
71         QObject::connect(other, SIGNAL(widthChanged()), q, SLOT(graphicsWidgetGeometryChanged()));
72         QObject::connect(other, SIGNAL(heightChanged()), q, SLOT(graphicsWidgetGeometryChanged()));
73         QObject::connect(other, SIGNAL(opacityChanged()), q, SLOT(graphicsWidgetGeometryChanged()));
74         QObject::connect(other, SIGNAL(visibleChanged()), q, SLOT(graphicsWidgetGeometryChanged()));
75     }
76 }
77
78 void QDeclarativeBasePositionerPrivate::unwatchChanges(QGraphicsObject* other)
79 {
80     if (QGraphicsItemPrivate::get(other)->isDeclarativeItem) {
81         QDeclarativeItemPrivate *otherPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(other));
82         otherPrivate->removeItemChangeListener(this, watchedChanges);
83     } else {
84         Q_Q(QDeclarativeBasePositioner);
85         QObject::disconnect(other, SIGNAL(widthChanged()), q, SLOT(graphicsWidgetGeometryChanged()));
86         QObject::disconnect(other, SIGNAL(heightChanged()), q, SLOT(graphicsWidgetGeometryChanged()));
87         QObject::disconnect(other, SIGNAL(opacityChanged()), q, SLOT(graphicsWidgetGeometryChanged()));
88         QObject::disconnect(other, SIGNAL(visibleChanged()), q, SLOT(graphicsWidgetGeometryChanged()));
89     }
90 }
91
92 void QDeclarativeBasePositioner::graphicsWidgetGeometryChanged()
93 {
94     prePositioning();
95 }
96
97 /*!
98     \internal
99     \class QDeclarativeBasePositioner
100     \brief The QDeclarativeBasePositioner class provides a base for QDeclarativeGraphics layouts.
101
102     To create a QDeclarativeGraphics Positioner, simply subclass QDeclarativeBasePositioner and implement
103     doLayout(), which is automatically called when the layout might need
104     updating. In doLayout() use the setX and setY functions from QDeclarativeBasePositioner, and the
105     base class will apply the positions along with the appropriate transitions. The items to
106     position are provided in order as the protected member positionedItems.
107
108     You also need to set a PositionerType, to declare whether you are positioning the x, y or both
109     for the child items. Depending on the chosen type, only x or y changes will be applied.
110
111     Note that the subclass is responsible for adding the spacing in between items.
112 */
113 QDeclarativeBasePositioner::QDeclarativeBasePositioner(PositionerType at, QDeclarativeItem *parent)
114     : QDeclarativeImplicitSizeItem(*(new QDeclarativeBasePositionerPrivate), parent)
115 {
116     Q_D(QDeclarativeBasePositioner);
117     d->init(at);
118 }
119
120 QDeclarativeBasePositioner::QDeclarativeBasePositioner(QDeclarativeBasePositionerPrivate &dd, PositionerType at, QDeclarativeItem *parent)
121     : QDeclarativeImplicitSizeItem(dd, parent)
122 {
123     Q_D(QDeclarativeBasePositioner);
124     d->init(at);
125 }
126
127 QDeclarativeBasePositioner::~QDeclarativeBasePositioner()
128 {
129     Q_D(QDeclarativeBasePositioner);
130     for (int i = 0; i < positionedItems.count(); ++i)
131         d->unwatchChanges(positionedItems.at(i).item);
132     positionedItems.clear();
133 }
134
135 int QDeclarativeBasePositioner::spacing() const
136 {
137     Q_D(const QDeclarativeBasePositioner);
138     return d->spacing;
139 }
140
141 void QDeclarativeBasePositioner::setSpacing(int s)
142 {
143     Q_D(QDeclarativeBasePositioner);
144     if (s==d->spacing)
145         return;
146     d->spacing = s;
147     prePositioning();
148     emit spacingChanged();
149 }
150
151 QDeclarativeTransition *QDeclarativeBasePositioner::move() const
152 {
153     Q_D(const QDeclarativeBasePositioner);
154     return d->moveTransition;
155 }
156
157 void QDeclarativeBasePositioner::setMove(QDeclarativeTransition *mt)
158 {
159     Q_D(QDeclarativeBasePositioner);
160     if (mt == d->moveTransition)
161         return;
162     d->moveTransition = mt;
163     emit moveChanged();
164 }
165
166 QDeclarativeTransition *QDeclarativeBasePositioner::add() const
167 {
168     Q_D(const QDeclarativeBasePositioner);
169     return d->addTransition;
170 }
171
172 void QDeclarativeBasePositioner::setAdd(QDeclarativeTransition *add)
173 {
174     Q_D(QDeclarativeBasePositioner);
175     if (add == d->addTransition)
176         return;
177
178     d->addTransition = add;
179     emit addChanged();
180 }
181
182 void QDeclarativeBasePositioner::componentComplete()
183 {
184     Q_D(QDeclarativeBasePositioner);
185     QDeclarativeItem::componentComplete();
186     positionedItems.reserve(d->QGraphicsItemPrivate::children.count());
187     prePositioning();
188     reportConflictingAnchors();
189 }
190
191 QVariant QDeclarativeBasePositioner::itemChange(GraphicsItemChange change,
192                                        const QVariant &value)
193 {
194     Q_D(QDeclarativeBasePositioner);
195     if (change == ItemChildAddedChange){
196         QGraphicsItem* item = value.value<QGraphicsItem*>();
197         QGraphicsObject* child = 0;
198         if(item)
199             child = item->toGraphicsObject();
200         if (child)
201             prePositioning();
202     } else if (change == ItemChildRemovedChange) {
203         QGraphicsItem* item = value.value<QGraphicsItem*>();
204         QGraphicsObject* child = 0;
205         if(item)
206             child = item->toGraphicsObject();
207         if (child) {
208             QDeclarativeBasePositioner::PositionedItem posItem(child);
209             int idx = positionedItems.find(posItem);
210             if (idx >= 0) {
211                 d->unwatchChanges(child);
212                 positionedItems.remove(idx);
213             }
214             prePositioning();
215         }
216     }
217     return QDeclarativeItem::itemChange(change, value);
218 }
219
220 void QDeclarativeBasePositioner::prePositioning()
221 {
222     Q_D(QDeclarativeBasePositioner);
223     if (!isComponentComplete())
224         return;
225
226     if (d->doingPositioning)
227         return;
228
229     d->queuedPositioning = false;
230     d->doingPositioning = true;
231     //Need to order children by creation order modified by stacking order
232     QList<QGraphicsItem *> children = d->QGraphicsItemPrivate::children;
233     qSort(children.begin(), children.end(), d->insertionOrder);
234
235     QPODVector<PositionedItem,8> oldItems;
236     positionedItems.copyAndClear(oldItems);
237     for (int ii = 0; ii < children.count(); ++ii) {
238         QGraphicsObject *child = children.at(ii)->toGraphicsObject();
239         if (!child)
240             continue;
241         QGraphicsItemPrivate *childPrivate = static_cast<QGraphicsItemPrivate*>(QGraphicsItemPrivate::get(child));
242         PositionedItem *item = 0;
243         PositionedItem posItem(child);
244         int wIdx = oldItems.find(posItem);
245         if (wIdx < 0) {
246             d->watchChanges(child);
247             positionedItems.append(posItem);
248             item = &positionedItems[positionedItems.count()-1];
249             item->isNew = true;
250             if (child->opacity() <= 0.0 || childPrivate->explicitlyHidden || !childPrivate->width() || !childPrivate->height())
251                 item->isVisible = false;
252         } else {
253             item = &oldItems[wIdx];
254             // Items are only omitted from positioning if they are explicitly hidden
255             // i.e. their positioning is not affected if an ancestor is hidden.
256             if (child->opacity() <= 0.0 || childPrivate->explicitlyHidden || !childPrivate->width() || !childPrivate->height()) {
257                 item->isVisible = false;
258             } else if (!item->isVisible) {
259                 item->isVisible = true;
260                 item->isNew = true;
261             } else {
262                 item->isNew = false;
263             }
264             positionedItems.append(*item);
265         }
266     }
267     QSizeF contentSize;
268     doPositioning(&contentSize);
269     if(d->addTransition || d->moveTransition)
270         finishApplyTransitions();
271     d->doingPositioning = false;
272     //Set implicit size to the size of its children
273     setImplicitHeight(contentSize.height());
274     setImplicitWidth(contentSize.width());
275 }
276
277 void QDeclarativeBasePositioner::positionX(int x, const PositionedItem &target)
278 {
279     Q_D(QDeclarativeBasePositioner);
280     if(d->type == Horizontal || d->type == Both){
281         if (target.isNew) {
282             if (!d->addTransition)
283                 target.item->setX(x);
284             else
285                 d->addActions << QDeclarativeAction(target.item, QLatin1String("x"), QVariant(x));
286         } else if (x != target.item->x()) {
287             if (!d->moveTransition)
288                 target.item->setX(x);
289             else
290                 d->moveActions << QDeclarativeAction(target.item, QLatin1String("x"), QVariant(x));
291         }
292     }
293 }
294
295 void QDeclarativeBasePositioner::positionY(int y, const PositionedItem &target)
296 {
297     Q_D(QDeclarativeBasePositioner);
298     if(d->type == Vertical || d->type == Both){
299         if (target.isNew) {
300             if (!d->addTransition)
301                 target.item->setY(y);
302             else
303                 d->addActions << QDeclarativeAction(target.item, QLatin1String("y"), QVariant(y));
304         } else if (y != target.item->y()) {
305             if (!d->moveTransition)
306                 target.item->setY(y);
307             else
308                 d->moveActions << QDeclarativeAction(target.item, QLatin1String("y"), QVariant(y));
309         }
310     }
311 }
312
313 void QDeclarativeBasePositioner::finishApplyTransitions()
314 {
315     Q_D(QDeclarativeBasePositioner);
316     // Note that if a transition is not set the transition manager will
317     // apply the changes directly, in the case add/move aren't set
318     d->addTransitionManager.transition(d->addActions, d->addTransition);
319     d->moveTransitionManager.transition(d->moveActions, d->moveTransition);
320     d->addActions.clear();
321     d->moveActions.clear();
322 }
323
324 /*!
325   \qmlclass Column QDeclarativeColumn
326   \ingroup qml-positioning-elements
327   \since 4.7
328   \brief The Column item arranges its children vertically.
329   \inherits Item
330
331   The Column item positions its child items so that they are vertically
332   aligned and not overlapping.
333
334   Spacing between items can be added using the \l spacing property.
335   Transitions can be used for cases where items managed by a Column are
336   added or moved. These are stored in the \l add and \l move properties
337   respectively.
338
339   See \l{Using QML Positioner and Repeater Items} for more details about this item and other
340   related items.
341
342   \section1 Example Usage
343
344   The following example positions differently shaped rectangles using a Column
345   item.
346
347   \image verticalpositioner_example.png
348
349   \snippet doc/src/snippets/declarative/column/vertical-positioner.qml document
350
351   \section1 Using Transitions
352
353   Transitions can be used to animate items that are added to, moved within,
354   or removed from a Column item. The \l add and \l move properties can be set to
355   the transitions that will be applied when items are added to, removed from,
356   or re-positioned within a Column item.
357
358   The use of transitions with positioners is described in more detail in the
359   \l{Using QML Positioner and Repeater Items#Using Transitions}{Using QML
360   Positioner and Repeater Items} document.
361
362   \image verticalpositioner_transition.gif
363
364   \qml
365   Column {
366       spacing: 2
367       add: Transition {
368           // Define an animation for adding a new item...
369       }
370       move: Transition {
371           // Define an animation for moving items within the column...
372       }
373       // ...
374   }
375   \endqml
376
377   \section1 Limitations
378
379   Note that the positioner assumes that the x and y positions of its children
380   will not change. If you manually change the x or y properties in script, bind
381   the x or y properties, use anchors on a child of a positioner, or have the
382   height of a child depend on the position of a child, then the
383   positioner may exhibit strange behavior. If you need to perform any of these
384   actions, consider positioning the items without the use of a Column.
385
386   Items with a width or height of 0 will not be positioned.
387
388   \sa Row, Grid, Flow, {declarative/positioners}{Positioners example}
389 */
390 /*!
391     \qmlproperty Transition Column::add
392
393     This property holds the transition to be applied when adding an
394     item to the positioner. The transition will only be applied to the
395     added item(s).  Positioner transitions will only affect the
396     position (x, y) of items.
397
398     For a positioner, adding an item can mean that either the object
399     has been created or reparented, and thus is now a child or the
400     positioner, or that the object has had its opacity increased from
401     zero, and thus is now visible.
402
403     \sa move
404 */
405 /*!
406     \qmlproperty Transition Column::move
407
408     This property holds the transition to apply when moving an item
409     within the positioner.  Positioner transitions will only affect
410     the position (x, y) of items.
411
412     This transition can be performed when other items are added or removed
413     from the positioner, or when items resize themselves.
414
415     \image positioner-move.gif
416
417     \qml
418     Column {
419         move: Transition {
420             NumberAnimation {
421                 properties: "y"
422                 easing.type: Easing.OutBounce
423             }
424         }
425     }
426     \endqml
427
428     \sa add, {declarative/positioners}{Positioners example}
429 */
430 /*!
431   \qmlproperty int Column::spacing
432
433   The spacing is the amount in pixels left empty between adjacent
434   items. The default spacing is 0.
435
436   \sa Grid::spacing
437 */
438 QDeclarativeColumn::QDeclarativeColumn(QDeclarativeItem *parent)
439 : QDeclarativeBasePositioner(Vertical, parent)
440 {
441 }
442
443 void QDeclarativeColumn::doPositioning(QSizeF *contentSize)
444 {
445     int voffset = 0;
446
447     for (int ii = 0; ii < positionedItems.count(); ++ii) {
448         const PositionedItem &child = positionedItems.at(ii);
449         if (!child.item || !child.isVisible)
450             continue;
451
452         if(child.item->y() != voffset)
453             positionY(voffset, child);
454
455         contentSize->setWidth(qMax(contentSize->width(), QGraphicsItemPrivate::get(child.item)->width()));
456
457         voffset += QGraphicsItemPrivate::get(child.item)->height();
458         voffset += spacing();
459     }
460
461     contentSize->setHeight(voffset - spacing());
462 }
463
464 void QDeclarativeColumn::reportConflictingAnchors()
465 {
466     QDeclarativeBasePositionerPrivate *d = static_cast<QDeclarativeBasePositionerPrivate*>(QDeclarativeBasePositionerPrivate::get(this));
467     for (int ii = 0; ii < positionedItems.count(); ++ii) {
468         const PositionedItem &child = positionedItems.at(ii);
469         if (child.item && QGraphicsItemPrivate::get(child.item)->isDeclarativeItem) {
470             QDeclarativeAnchors *anchors = QDeclarativeItemPrivate::get(static_cast<QDeclarativeItem *>(child.item))->_anchors;
471             if (anchors) {
472                 QDeclarativeAnchors::Anchors usedAnchors = anchors->usedAnchors();
473                 if (usedAnchors & QDeclarativeAnchors::TopAnchor ||
474                     usedAnchors & QDeclarativeAnchors::BottomAnchor ||
475                     usedAnchors & QDeclarativeAnchors::VCenterAnchor ||
476                     anchors->fill() || anchors->centerIn()) {
477                     d->anchorConflict = true;
478                     break;
479                 }
480             }
481         }
482     }
483     if (d->anchorConflict) {
484         qmlInfo(this) << "Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column";
485     }
486 }
487
488 /*!
489   \qmlclass Row QDeclarativeRow
490   \ingroup qml-positioning-elements
491   \since 4.7
492   \brief The Row item arranges its children horizontally.
493   \inherits Item
494
495   The Row item positions its child items so that they are horizontally
496   aligned and not overlapping. 
497
498   Use \l spacing to set the spacing between items in a Row, and use the
499   \l add and \l move properties to set the transitions that should be applied
500   when items are added to, removed from, or re-positioned within the Row.
501
502   See \l{Using QML Positioner and Repeater Items} for more details about this item and other
503   related items.
504
505   \section1 Example Usage
506
507   The following example lays out differently shaped rectangles using a Row.
508
509   \image horizontalpositioner_example.png
510
511   \snippet doc/src/snippets/declarative/row/row.qml document
512
513   \section1 Using Transitions
514
515   Transitions can be used to animate items that are added to, moved within,
516   or removed from a Grid item. The \l add and \l move properties can be set to
517   the transitions that will be applied when items are added to, removed from,
518   or re-positioned within a Row item.
519
520   \section1 Limitations
521
522   Note that the positioner assumes that the x and y positions of its children
523   will not change. If you manually change the x or y properties in script, bind
524   the x or y properties, use anchors on a child of a positioner, or have the
525   width of a child depend on the position of a child, then the
526   positioner may exhibit strange behaviour. If you need to perform any of these
527   actions, consider positioning the items without the use of a Row.
528
529   Items with a width or height of 0 will not be positioned.
530
531   \sa Column, Grid, Flow, {declarative/positioners}{Positioners example}
532 */
533 /*!
534     \qmlproperty Transition Row::add
535
536     This property holds the transition to be applied when adding an
537     item to the positioner. The transition will only be applied to the
538     added item(s).  Positioner transitions will only affect the
539     position (x, y) of items.
540
541     For a positioner, adding an item can mean that either the object
542     has been created or reparented, and thus is now a child or the
543     positioner, or that the object has had its opacity increased from
544     zero, and thus is now visible.
545
546     \sa move
547 */
548 /*!
549     \qmlproperty Transition Row::move
550
551     This property holds the transition to be applied when moving an
552     item within the positioner. Positioner transitions will only affect
553     the position (x, y) of items.
554
555     This transition can be performed when other items are added or removed
556     from the positioner, or when items resize themselves.
557
558     \qml
559     Row {
560         id: positioner
561         move: Transition {
562             NumberAnimation {
563                 properties: "x"
564                 ease: "easeOutBounce"
565             }
566         }
567     }
568     \endqml
569
570     \sa add, {declarative/positioners}{Positioners example}
571 */
572 /*!
573   \qmlproperty int Row::spacing
574
575   The spacing is the amount in pixels left empty between adjacent
576   items. The default spacing is 0.
577
578   \sa Grid::spacing
579 */
580 QDeclarativeRow::QDeclarativeRow(QDeclarativeItem *parent)
581 : QDeclarativeBasePositioner(Horizontal, parent)
582 {
583 }
584
585 /*!
586     \qmlproperty enumeration Row::layoutDirection
587     \since Quick 1.1
588
589     This property holds the layoutDirection of the row.
590
591     Possible values:
592
593     \list
594     \o Qt.LeftToRight (default) - Items are laid out from left to right. If the width of the row is explicitly set,
595     the left anchor remains to the left of the row.
596     \o Qt.RightToLeft - Items are laid out from right to left. If the width of the row is explicitly set,
597     the right anchor remains to the right of the row.
598     \endlist
599
600     \sa Grid::layoutDirection, Flow::layoutDirection, {declarative/righttoleft/layoutdirection}{Layout directions example}
601 */
602 Qt::LayoutDirection QDeclarativeRow::layoutDirection() const
603 {
604     return QDeclarativeBasePositionerPrivate::getLayoutDirection(this);
605 }
606
607 void QDeclarativeRow::setLayoutDirection(Qt::LayoutDirection layoutDirection)
608 {
609     QDeclarativeBasePositionerPrivate *d = static_cast<QDeclarativeBasePositionerPrivate* >(QDeclarativeBasePositionerPrivate::get(this));
610     if (d->layoutDirection != layoutDirection) {
611         d->layoutDirection = layoutDirection;
612         // For RTL layout the positioning changes when the width changes.
613         if (d->layoutDirection == Qt::RightToLeft)
614             d->addItemChangeListener(d, QDeclarativeItemPrivate::Geometry);
615         else
616             d->removeItemChangeListener(d, QDeclarativeItemPrivate::Geometry);
617         prePositioning();
618         emit layoutDirectionChanged();
619         emit effectiveLayoutDirectionChanged();
620     }
621 }
622
623 /*!
624     \qmlproperty enumeration Row::effectiveLayoutDirection
625     This property holds the effective layout direction of the row positioner.
626
627     When using the attached property \l {LayoutMirroring::enabled}{LayoutMirroring::enabled} for locale layouts,
628     the visual layout direction of the row positioner will be mirrored. However, the
629     property \l {Row::layoutDirection}{layoutDirection} will remain unchanged.
630
631     \sa Row::layoutDirection, {LayoutMirroring}{LayoutMirroring}
632 */
633
634 Qt::LayoutDirection QDeclarativeRow::effectiveLayoutDirection() const
635 {
636     return QDeclarativeBasePositionerPrivate::getEffectiveLayoutDirection(this);
637 }
638
639 void QDeclarativeRow::doPositioning(QSizeF *contentSize)
640 {
641     QDeclarativeBasePositionerPrivate *d = static_cast<QDeclarativeBasePositionerPrivate*>(QDeclarativeBasePositionerPrivate::get(this));
642     int hoffset = 0;
643
644     QList<int> hoffsets;
645     for (int ii = 0; ii < positionedItems.count(); ++ii) {
646         const PositionedItem &child = positionedItems.at(ii);
647         if (!child.item || !child.isVisible)
648             continue;
649
650         if(d->isLeftToRight()){
651             if(child.item->x() != hoffset)
652                 positionX(hoffset, child);
653         }else{
654             hoffsets << hoffset;
655         }
656
657         contentSize->setHeight(qMax(contentSize->height(), QGraphicsItemPrivate::get(child.item)->height()));
658
659         hoffset += QGraphicsItemPrivate::get(child.item)->width();
660         hoffset += spacing();
661     }
662
663     contentSize->setWidth(hoffset - spacing());
664
665     if(d->isLeftToRight())
666         return;
667
668     //Right to Left layout
669     int end = 0;
670     if(!widthValid())
671         end = contentSize->width();
672     else
673         end = width();
674
675     int acc = 0;
676     for (int ii = 0; ii < positionedItems.count(); ++ii) {
677         const PositionedItem &child = positionedItems.at(ii);
678         if (!child.item || !child.isVisible)
679             continue;
680         hoffset = end - hoffsets[acc++] - QGraphicsItemPrivate::get(child.item)->width();
681         if(child.item->x() != hoffset)
682             positionX(hoffset, child);
683     }
684 }
685
686 void QDeclarativeRow::reportConflictingAnchors()
687 {
688     QDeclarativeBasePositionerPrivate *d = static_cast<QDeclarativeBasePositionerPrivate*>(QDeclarativeBasePositionerPrivate::get(this));
689     for (int ii = 0; ii < positionedItems.count(); ++ii) {
690         const PositionedItem &child = positionedItems.at(ii);
691         if (child.item && QGraphicsItemPrivate::get(child.item)->isDeclarativeItem) {
692             QDeclarativeAnchors *anchors = QDeclarativeItemPrivate::get(static_cast<QDeclarativeItem *>(child.item))->_anchors;
693             if (anchors) {
694                 QDeclarativeAnchors::Anchors usedAnchors = anchors->usedAnchors();
695                 if (usedAnchors & QDeclarativeAnchors::LeftAnchor ||
696                     usedAnchors & QDeclarativeAnchors::RightAnchor ||
697                     usedAnchors & QDeclarativeAnchors::HCenterAnchor ||
698                     anchors->fill() || anchors->centerIn()) {
699                     d->anchorConflict = true;
700                     break;
701                 }
702             }
703         }
704     }
705     if (d->anchorConflict)
706         qmlInfo(this) << "Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row";
707 }
708
709 /*!
710   \qmlclass Grid QDeclarativeGrid
711   \ingroup qml-positioning-elements
712   \since 4.7
713   \brief The Grid item positions its children in a grid.
714   \inherits Item
715
716   The Grid item positions its child items so that they are
717   aligned in a grid and are not overlapping. 
718
719   The grid positioner calculates a grid of rectangular cells of sufficient
720   size to hold all items, placing the items in the cells, from left to right
721   and top to bottom. Each item is positioned in the top-left corner of its
722   cell with position (0, 0).
723
724   A Grid defaults to four columns, and as many rows as are necessary to
725   fit all child items. The number of rows and columns can be constrained
726   by setting the \l rows and \l columns properties.
727
728   Spacing can be added between child items by setting the \l spacing
729   property. The amount of spacing applied will be the same in the
730   horizontal and vertical directions.
731
732   See \l{Using QML Positioner and Repeater Items} for more details about this item and other
733   related items.
734
735   \section1 Example Usage
736
737   The following example demonstrates this.
738
739   \image gridLayout_example.png
740
741   \snippet doc/src/snippets/declarative/grid/grid.qml document
742
743   \section1 Using Transitions
744
745   Transitions can be used to animate items that are added to, moved within,
746   or removed from a Grid item. The \l add and \l move properties can be set to
747   the transitions that will be applied when items are added to, removed from,
748   or re-positioned within a Grid item.
749
750   \section1 Limitations
751
752   Note that the positioner assumes that the x and y positions of its children
753   will not change. If you manually change the x or y properties in script, bind
754   the x or y properties, use anchors on a child of a positioner, or have the
755   width or height of a child depend on the position of a child, then the
756   positioner may exhibit strange behaviour. If you need to perform any of these
757   actions, consider positioning the items without the use of a Grid.
758
759   Items with a width or height of 0 will not be positioned.
760
761   \sa Flow, Row, Column, {declarative/positioners}{Positioners example}
762 */
763 /*!
764     \qmlproperty Transition Grid::add
765
766     This property holds the transition to be applied when adding an
767     item to the positioner. The transition will only be applied to the
768     added item(s).  Positioner transitions will only affect the
769     position (x, y) of items.
770
771     For a positioner, adding an item can mean that either the object
772     has been created or reparented, and thus is now a child or the
773     positioner, or that the object has had its opacity increased from
774     zero, and thus is now visible.
775
776     \sa move
777 */
778 /*!
779     \qmlproperty Transition Grid::move
780
781     This property holds the transition to be applied when moving an
782     item within the positioner. Positioner transitions will only affect
783     the position (x, y) of items.
784
785     This transition can be performed when other items are added or removed
786     from the positioner, or when items resize themselves.
787
788     \qml
789     Grid {
790         move: Transition {
791             NumberAnimation {
792                 properties: "x,y"
793                 ease: "easeOutBounce"
794             }
795         }
796     }
797     \endqml
798
799     \sa add, {declarative/positioners}{Positioners example}
800 */
801 /*!
802   \qmlproperty int Grid::spacing
803
804   The spacing is the amount in pixels left empty between adjacent
805   items. The default spacing is 0.
806
807   The below example places a Grid containing a red, a blue and a
808   green rectangle on a gray background. The area the grid positioner
809   occupies is colored white. The positioner on the left has the
810   no spacing (the default), and the positioner on the right has
811   a spacing of 6.
812
813   \inlineimage qml-grid-no-spacing.png
814   \inlineimage qml-grid-spacing.png
815
816   \sa rows, columns
817 */
818 QDeclarativeGrid::QDeclarativeGrid(QDeclarativeItem *parent) :
819     QDeclarativeBasePositioner(Both, parent), m_rows(-1), m_columns(-1), m_flow(LeftToRight)
820 {
821 }
822
823 /*!
824     \qmlproperty int Grid::columns
825
826     This property holds the number of columns in the grid. The default
827     number of columns is 4.
828
829     If the grid does not have enough items to fill the specified
830     number of columns, some columns will be of zero width.
831 */
832
833 /*!
834     \qmlproperty int Grid::rows
835     This property holds the number of rows in the grid.
836
837     If the grid does not have enough items to fill the specified
838     number of rows, some rows will be of zero width.
839 */
840
841 void QDeclarativeGrid::setColumns(const int columns)
842 {
843     if (columns == m_columns)
844         return;
845     m_columns = columns;
846     prePositioning();
847     emit columnsChanged();
848 }
849
850 void QDeclarativeGrid::setRows(const int rows)
851 {
852     if (rows == m_rows)
853         return;
854     m_rows = rows;
855     prePositioning();
856     emit rowsChanged();
857 }
858
859 /*!
860     \qmlproperty enumeration Grid::flow
861     This property holds the flow of the layout.
862
863     Possible values are:
864
865     \list
866     \o Grid.LeftToRight (default) - Items are positioned next to
867        each other in the \l layoutDirection, then wrapped to the next line.
868     \o Grid.TopToBottom - Items are positioned next to each
869        other from top to bottom, then wrapped to the next column.
870     \endlist
871 */
872 QDeclarativeGrid::Flow QDeclarativeGrid::flow() const
873 {
874     return m_flow;
875 }
876
877 void QDeclarativeGrid::setFlow(Flow flow)
878 {
879     if (m_flow != flow) {
880         m_flow = flow;
881         prePositioning();
882         emit flowChanged();
883     }
884 }
885
886 /*!
887     \qmlproperty enumeration Grid::layoutDirection
888     \since Quick 1.1
889
890     This property holds the layout direction of the layout.
891
892     Possible values are:
893
894     \list
895     \o Qt.LeftToRight (default) - Items are positioned from the top to bottom,
896     and left to right. The flow direction is dependent on the
897     \l Grid::flow property.
898     \o Qt.RightToLeft - Items are positioned from the top to bottom,
899     and right to left. The flow direction is dependent on the
900     \l Grid::flow property.
901     \endlist
902
903     \sa Flow::layoutDirection, Row::layoutDirection, {declarative/righttoleft/layoutdirection}{Layout directions example}
904 */
905 Qt::LayoutDirection QDeclarativeGrid::layoutDirection() const
906 {
907     return QDeclarativeBasePositionerPrivate::getLayoutDirection(this);
908 }
909
910 void QDeclarativeGrid::setLayoutDirection(Qt::LayoutDirection layoutDirection)
911 {
912     QDeclarativeBasePositionerPrivate *d = static_cast<QDeclarativeBasePositionerPrivate*>(QDeclarativeBasePositionerPrivate::get(this));
913     if (d->layoutDirection != layoutDirection) {
914         d->layoutDirection = layoutDirection;
915         // For RTL layout the positioning changes when the width changes.
916         if (d->layoutDirection == Qt::RightToLeft)
917             d->addItemChangeListener(d, QDeclarativeItemPrivate::Geometry);
918         else
919             d->removeItemChangeListener(d, QDeclarativeItemPrivate::Geometry);
920         prePositioning();
921         emit layoutDirectionChanged();
922         emit effectiveLayoutDirectionChanged();
923     }
924 }
925
926 /*!
927     \qmlproperty enumeration Grid::effectiveLayoutDirection
928     This property holds the effective layout direction of the grid positioner.
929
930     When using the attached property \l {LayoutMirroring::enabled}{LayoutMirroring::enabled} for locale layouts,
931     the visual layout direction of the grid positioner will be mirrored. However, the
932     property \l {Grid::layoutDirection}{layoutDirection} will remain unchanged.
933
934     \sa Grid::layoutDirection, {LayoutMirroring}{LayoutMirroring}
935 */
936
937 Qt::LayoutDirection QDeclarativeGrid::effectiveLayoutDirection() const
938 {
939     return QDeclarativeBasePositionerPrivate::getEffectiveLayoutDirection(this);
940 }
941
942 void QDeclarativeGrid::doPositioning(QSizeF *contentSize)
943 {
944     QDeclarativeBasePositionerPrivate *d = static_cast<QDeclarativeBasePositionerPrivate*>(QDeclarativeBasePositionerPrivate::get(this));
945     int c = m_columns;
946     int r = m_rows;
947     //Is allocating the extra QPODVector too much overhead?
948     QPODVector<PositionedItem, 8> visibleItems;//we aren't concerned with invisible items
949     visibleItems.reserve(positionedItems.count());
950     for(int i=0; i<positionedItems.count(); i++)
951         if(positionedItems[i].item && positionedItems[i].isVisible)
952             visibleItems.append(positionedItems[i]);
953
954     int numVisible = visibleItems.count();
955     if (m_columns <= 0 && m_rows <= 0){
956         c = 4;
957         r = (numVisible+3)/4;
958     } else if (m_rows <= 0){
959         r = (numVisible+(m_columns-1))/m_columns;
960     } else if (m_columns <= 0){
961         c = (numVisible+(m_rows-1))/m_rows;
962     }
963
964     if(r==0 || c==0)
965         return; //Nothing to do
966
967     QList<int> maxColWidth;
968     QList<int> maxRowHeight;
969     int childIndex =0;
970     if (m_flow == LeftToRight) {
971         for (int i=0; i < r; i++){
972             for (int j=0; j < c; j++){
973                 if (j==0)
974                     maxRowHeight << 0;
975                 if (i==0)
976                     maxColWidth << 0;
977
978                 if (childIndex == visibleItems.count())
979                     break;
980
981                 const PositionedItem &child = visibleItems.at(childIndex++);
982                 QGraphicsItemPrivate *childPrivate = QGraphicsItemPrivate::get(child.item);
983                 if (childPrivate->width() > maxColWidth[j])
984                     maxColWidth[j] = childPrivate->width();
985                 if (childPrivate->height() > maxRowHeight[i])
986                     maxRowHeight[i] = childPrivate->height();
987             }
988         }
989     } else {
990         for (int j=0; j < c; j++){
991             for (int i=0; i < r; i++){
992                 if (j==0)
993                     maxRowHeight << 0;
994                 if (i==0)
995                     maxColWidth << 0;
996
997                 if (childIndex == visibleItems.count())
998                     break;
999
1000                 const PositionedItem &child = visibleItems.at(childIndex++);
1001                 QGraphicsItemPrivate *childPrivate = QGraphicsItemPrivate::get(child.item);
1002                 if (childPrivate->width() > maxColWidth[j])
1003                     maxColWidth[j] = childPrivate->width();
1004                 if (childPrivate->height() > maxRowHeight[i])
1005                     maxRowHeight[i] = childPrivate->height();
1006             }
1007         }
1008     }
1009
1010     int widthSum = 0;
1011     for(int j=0; j < maxColWidth.size(); j++){
1012         if(j)
1013             widthSum += spacing();
1014         widthSum += maxColWidth[j];
1015     }
1016
1017     int heightSum = 0;
1018     for(int i=0; i < maxRowHeight.size(); i++){
1019         if(i)
1020             heightSum += spacing();
1021         heightSum += maxRowHeight[i];
1022     }
1023
1024     contentSize->setHeight(heightSum);
1025     contentSize->setWidth(widthSum);
1026
1027     int end = 0;
1028     if(widthValid())
1029         end = width();
1030     else
1031         end = widthSum;
1032
1033     int xoffset=0;
1034     if(!d->isLeftToRight())
1035         xoffset=end;
1036     int yoffset=0;
1037     int curRow =0;
1038     int curCol =0;
1039     for (int i = 0; i < visibleItems.count(); ++i) {
1040         const PositionedItem &child = visibleItems.at(i);
1041         int childXOffset = xoffset;
1042         if(!d->isLeftToRight())
1043             childXOffset -= QGraphicsItemPrivate::get(child.item)->width();
1044         if((child.item->x()!=childXOffset)||(child.item->y()!=yoffset)){
1045             positionX(childXOffset, child);
1046             positionY(yoffset, child);
1047         }
1048
1049         if (m_flow == LeftToRight) {
1050             if(d->isLeftToRight())
1051                 xoffset+=maxColWidth[curCol]+spacing();
1052             else
1053                 xoffset-=maxColWidth[curCol]+spacing();
1054             curCol++;
1055             curCol%=c;
1056             if (!curCol){
1057                 yoffset+=maxRowHeight[curRow]+spacing();
1058                 if(d->isLeftToRight())
1059                     xoffset=0;
1060                 else
1061                     xoffset=end;
1062                 curRow++;
1063                 if (curRow>=r)
1064                     break;
1065             }
1066         } else {
1067             yoffset+=maxRowHeight[curRow]+spacing();
1068             curRow++;
1069             curRow%=r;
1070             if (!curRow){
1071                 if(d->isLeftToRight())
1072                     xoffset+=maxColWidth[curCol]+spacing();
1073                 else
1074                     xoffset-=maxColWidth[curCol]+spacing();
1075                 yoffset=0;
1076                 curCol++;
1077                 if (curCol>=c)
1078                     break;
1079             }
1080         }
1081     }
1082 }
1083
1084 void QDeclarativeGrid::reportConflictingAnchors()
1085 {
1086     QDeclarativeBasePositionerPrivate *d = static_cast<QDeclarativeBasePositionerPrivate*>(QDeclarativeBasePositionerPrivate::get(this));
1087     for (int ii = 0; ii < positionedItems.count(); ++ii) {
1088         const PositionedItem &child = positionedItems.at(ii);
1089         if (child.item && QGraphicsItemPrivate::get(child.item)->isDeclarativeItem) {
1090             QDeclarativeAnchors *anchors = QDeclarativeItemPrivate::get(static_cast<QDeclarativeItem *>(child.item))->_anchors;
1091             if (anchors && (anchors->usedAnchors() || anchors->fill() || anchors->centerIn())) {
1092                 d->anchorConflict = true;
1093                 break;
1094             }
1095         }
1096     }
1097     if (d->anchorConflict)
1098         qmlInfo(this) << "Cannot specify anchors for items inside Grid";
1099 }
1100
1101 /*!
1102   \qmlclass Flow QDeclarativeFlow
1103   \ingroup qml-positioning-elements
1104   \since 4.7
1105   \brief The Flow item arranges its children side by side, wrapping as necessary.
1106   \inherits Item
1107
1108   The Flow item positions its child items like words on a page, wrapping them
1109   to create rows or columns of items that do not overlap.
1110
1111   Spacing between items can be added using the \l spacing property.
1112   Transitions can be used for cases where items managed by a Column are
1113   added or moved. These are stored in the \l add and \l move properties
1114   respectively.
1115
1116   See \l{Using QML Positioner and Repeater Items} for more details about this item and other
1117   related items.
1118
1119   \section1 Example Usage
1120
1121   The following example positions \l Text items within a parent item using
1122   a Flow item.
1123
1124   \image qml-flow-snippet.png
1125
1126   \snippet doc/src/snippets/declarative/flow.qml flow item
1127
1128   \section1 Using Transitions
1129
1130   Transitions can be used to animate items that are added to, moved within,
1131   or removed from a Flow item. The \l add and \l move properties can be set to
1132   the transitions that will be applied when items are added to, removed from,
1133   or re-positioned within a Flow item.
1134
1135   The use of transitions with positioners is described in more detail in the
1136   \l{Using QML Positioner and Repeater Items#Using Transitions}{Using QML
1137   Positioner and Repeater Items} document.
1138
1139   \section1 Limitations
1140
1141   Note that the positioner assumes that the x and y positions of its children
1142   will not change. If you manually change the x or y properties in script, bind
1143   the x or y properties, use anchors on a child of a positioner, or have the
1144   width or height of a child depend on the position of a child, then the
1145   positioner may exhibit strange behaviour.  If you need to perform any of these
1146   actions, consider positioning the items without the use of a Flow.
1147
1148   Items with a width or height of 0 will not be positioned.
1149
1150   \sa Column, Row, Grid, {declarative/positioners}{Positioners example}
1151 */
1152 /*!
1153     \qmlproperty Transition Flow::add
1154
1155     This property holds the transition to be applied when adding an
1156     item to the positioner. The transition will only be applied to the
1157     added item(s).  Positioner transitions will only affect the
1158     position (x, y) of items.
1159
1160     For a positioner, adding an item can mean that either the object
1161     has been created or reparented, and thus is now a child or the
1162     positioner, or that the object has had its opacity increased from
1163     zero, and thus is now visible.
1164
1165     \sa move
1166 */
1167 /*!
1168     \qmlproperty Transition Flow::move
1169
1170     This property holds the transition to be applied when moving an
1171     item within the positioner. Positioner transitions will only affect
1172     the position (x, y) of items.
1173
1174     This transition can be performed when other items are added or removed
1175     from the positioner, or when items resize themselves.
1176
1177     \qml
1178     Flow {
1179         id: positioner
1180         move: Transition {
1181             NumberAnimation {
1182                 properties: "x,y"
1183                 ease: "easeOutBounce"
1184             }
1185         }
1186     }
1187     \endqml
1188
1189     \sa add, {declarative/positioners}{Positioners example}
1190 */
1191 /*!
1192   \qmlproperty int Flow::spacing
1193
1194   spacing is the amount in pixels left empty between each adjacent
1195   item, and defaults to 0.
1196
1197   \sa Grid::spacing
1198 */
1199
1200 class QDeclarativeFlowPrivate : public QDeclarativeBasePositionerPrivate
1201 {
1202     Q_DECLARE_PUBLIC(QDeclarativeFlow)
1203
1204 public:
1205     QDeclarativeFlowPrivate()
1206         : QDeclarativeBasePositionerPrivate(), flow(QDeclarativeFlow::LeftToRight)
1207     {}
1208
1209     QDeclarativeFlow::Flow flow;
1210 };
1211
1212 QDeclarativeFlow::QDeclarativeFlow(QDeclarativeItem *parent)
1213 : QDeclarativeBasePositioner(*(new QDeclarativeFlowPrivate), Both, parent)
1214 {
1215     Q_D(QDeclarativeFlow);
1216     // Flow layout requires relayout if its own size changes too.
1217     d->addItemChangeListener(d, QDeclarativeItemPrivate::Geometry);
1218 }
1219
1220 /*!
1221     \qmlproperty enumeration Flow::flow
1222     This property holds the flow of the layout.
1223
1224     Possible values are:
1225
1226     \list
1227     \o Flow.LeftToRight (default) - Items are positioned next to
1228     to each other according to the \l layoutDirection until the width of the Flow
1229     is exceeded, then wrapped to the next line.
1230     \o Flow.TopToBottom - Items are positioned next to each
1231     other from top to bottom until the height of the Flow is exceeded,
1232     then wrapped to the next column.
1233     \endlist
1234 */
1235 QDeclarativeFlow::Flow QDeclarativeFlow::flow() const
1236 {
1237     Q_D(const QDeclarativeFlow);
1238     return d->flow;
1239 }
1240
1241 void QDeclarativeFlow::setFlow(Flow flow)
1242 {
1243     Q_D(QDeclarativeFlow);
1244     if (d->flow != flow) {
1245         d->flow = flow;
1246         prePositioning();
1247         emit flowChanged();
1248     }
1249 }
1250
1251 /*!
1252     \qmlproperty enumeration Flow::layoutDirection
1253     \since Quick 1.1
1254
1255     This property holds the layout direction of the layout.
1256
1257     Possible values are:
1258
1259     \list
1260     \o Qt.LeftToRight (default) - Items are positioned from the top to bottom,
1261     and left to right. The flow direction is dependent on the
1262     \l Flow::flow property.
1263     \o Qt.RightToLeft - Items are positioned from the top to bottom,
1264     and right to left. The flow direction is dependent on the
1265     \l Flow::flow property.
1266     \endlist
1267
1268     \sa Grid::layoutDirection, Row::layoutDirection, {declarative/righttoleft/layoutdirection}{Layout directions example}
1269 */
1270
1271 Qt::LayoutDirection QDeclarativeFlow::layoutDirection() const
1272 {
1273     Q_D(const QDeclarativeFlow);
1274     return d->layoutDirection;
1275 }
1276
1277 void QDeclarativeFlow::setLayoutDirection(Qt::LayoutDirection layoutDirection)
1278 {
1279     Q_D(QDeclarativeFlow);
1280     if (d->layoutDirection != layoutDirection) {
1281         d->layoutDirection = layoutDirection;
1282         prePositioning();
1283         emit layoutDirectionChanged();
1284         emit effectiveLayoutDirectionChanged();
1285     }
1286 }
1287
1288 /*!
1289     \qmlproperty enumeration Flow::effectiveLayoutDirection
1290     This property holds the effective layout direction of the flow positioner.
1291
1292     When using the attached property \l {LayoutMirroring::enabled}{LayoutMirroring::enabled} for locale layouts,
1293     the visual layout direction of the grid positioner will be mirrored. However, the
1294     property \l {Flow::layoutDirection}{layoutDirection} will remain unchanged.
1295
1296     \sa Flow::layoutDirection, {LayoutMirroring}{LayoutMirroring}
1297 */
1298
1299 Qt::LayoutDirection QDeclarativeFlow::effectiveLayoutDirection() const
1300 {
1301     return QDeclarativeBasePositionerPrivate::getEffectiveLayoutDirection(this);
1302 }
1303
1304 void QDeclarativeFlow::doPositioning(QSizeF *contentSize)
1305 {
1306     Q_D(QDeclarativeFlow);
1307
1308     int hoffset = 0;
1309     int voffset = 0;
1310     int linemax = 0;
1311     QList<int> hoffsets;
1312
1313     for (int i = 0; i < positionedItems.count(); ++i) {
1314         const PositionedItem &child = positionedItems.at(i);
1315         if (!child.item || !child.isVisible)
1316             continue;
1317
1318         QGraphicsItemPrivate *childPrivate = QGraphicsItemPrivate::get(child.item);
1319         if (d->flow == LeftToRight)  {
1320             if (widthValid() && hoffset && hoffset + childPrivate->width() > width()) {
1321                 hoffset = 0;
1322                 voffset += linemax + spacing();
1323                 linemax = 0;
1324             }
1325         } else {
1326             if (heightValid() && voffset && voffset + childPrivate->height() > height()) {
1327                 voffset = 0;
1328                 hoffset += linemax + spacing();
1329                 linemax = 0;
1330             }
1331         }
1332
1333         if(d->isLeftToRight()){
1334             if(child.item->x() != hoffset)
1335                 positionX(hoffset, child);
1336         }else{
1337             hoffsets << hoffset;
1338         }
1339         if(child.item->y() != voffset)
1340             positionY(voffset, child);
1341
1342         contentSize->setWidth(qMax(contentSize->width(), hoffset + childPrivate->width()));
1343         contentSize->setHeight(qMax(contentSize->height(), voffset + childPrivate->height()));
1344
1345         if (d->flow == LeftToRight)  {
1346             hoffset += childPrivate->width();
1347             hoffset += spacing();
1348             linemax = qMax(linemax, qCeil(childPrivate->height()));
1349         } else {
1350             voffset += childPrivate->height();
1351             voffset += spacing();
1352             linemax = qMax(linemax, qCeil(childPrivate->width()));
1353         }
1354     }
1355
1356     if(d->isLeftToRight())
1357         return;
1358
1359     int end;
1360     if(widthValid())
1361         end = width();
1362     else
1363         end = contentSize->width();
1364     int acc = 0;
1365     for (int i = 0; i < positionedItems.count(); ++i) {
1366         const PositionedItem &child = positionedItems.at(i);
1367         if (!child.item || !child.isVisible)
1368             continue;
1369         hoffset = end - hoffsets[acc++] - QGraphicsItemPrivate::get(child.item)->width();
1370         if(child.item->x() != hoffset)
1371             positionX(hoffset, child);
1372     }
1373 }
1374
1375 void QDeclarativeFlow::reportConflictingAnchors()
1376 {
1377     Q_D(QDeclarativeFlow);
1378     for (int ii = 0; ii < positionedItems.count(); ++ii) {
1379         const PositionedItem &child = positionedItems.at(ii);
1380         if (child.item && QGraphicsItemPrivate::get(child.item)->isDeclarativeItem) {
1381             QDeclarativeAnchors *anchors = QDeclarativeItemPrivate::get(static_cast<QDeclarativeItem *>(child.item))->_anchors;
1382             if (anchors && (anchors->usedAnchors() || anchors->fill() || anchors->centerIn())) {
1383                 d->anchorConflict = true;
1384                 break;
1385             }
1386         }
1387     }
1388     if (d->anchorConflict)
1389         qmlInfo(this) << "Cannot specify anchors for items inside Flow";
1390 }
1391
1392 QT_END_NAMESPACE