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