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