From 2c7cab4172f1acc86fd49345a2847417e162f2c3 Mon Sep 17 00:00:00 2001
From: Joona Petrell <joona.t.petrell@nokia.com>
Date: Thu, 24 Feb 2011 12:33:11 +1000
Subject: Add LayoutMirroring attached property for mirroring QML layouts

Task-number: QTBUG-17280
Reviewed-by: Martin Jones
Change-Id: I34a623b49ce0fd5c05ae7a7ea5d0437c107b8a9b
---
 doc/src/snippets/declarative/layoutmirroring.qml   |  64 ++++++++
 .../layoutdirection/layoutdirection.qml            |  22 ++-
 .../graphicsitems/qdeclarativeanchors.cpp          |  40 ++---
 .../graphicsitems/qdeclarativeanchors_p.h          |  10 +-
 .../graphicsitems/qdeclarativeanchors_p_p.h        |   4 +-
 .../graphicsitems/qdeclarativegridview.cpp         |  69 +++++---
 .../graphicsitems/qdeclarativegridview_p.h         |   7 +-
 src/declarative/graphicsitems/qdeclarativeitem.cpp | 154 +++++++++++++++++-
 src/declarative/graphicsitems/qdeclarativeitem_p.h |  53 +++++-
 .../graphicsitems/qdeclarativeitemsmodule.cpp      |   1 +
 .../graphicsitems/qdeclarativelistview.cpp         |  90 ++++++++---
 .../graphicsitems/qdeclarativelistview_p.h         |   7 +-
 .../graphicsitems/qdeclarativepositioners.cpp      | 114 +++++++++----
 .../graphicsitems/qdeclarativepositioners_p.h      |  15 +-
 .../graphicsitems/qdeclarativepositioners_p_p.h    |  30 +++-
 .../tst_qdeclarativeanchors.cpp                    |  12 +-
 .../data/gridview-enforcerange.qml                 |   2 +-
 .../qdeclarativegridview/data/gridview1.qml        |   2 +-
 .../qdeclarativegridview/data/mirroring.qml        |  43 +++++
 .../tst_qdeclarativegridview.cpp                   |  65 ++++++++
 .../qdeclarativeitem/data/layoutmirroring.qml      |  54 +++++++
 .../qdeclarativeitem/tst_qdeclarativeitem.cpp      | 180 +++++++++++++++++----
 .../qdeclarativelistview/data/rightToLeft.qml      |   8 +-
 .../tst_qdeclarativelistview.cpp                   |  69 +++++++-
 .../data/grid-righttoleft.qml                      |  41 -----
 .../qdeclarativepositioners/data/gridtest.qml      |   6 +-
 .../qdeclarativepositioners/data/horizontal.qml    |   1 -
 .../tst_qdeclarativepositioners.cpp                |  78 ++++++++-
 .../qdeclarativestates/tst_qdeclarativestates.cpp  |   2 +-
 29 files changed, 1027 insertions(+), 216 deletions(-)
 create mode 100644 doc/src/snippets/declarative/layoutmirroring.qml
 create mode 100644 tests/auto/declarative/qdeclarativegridview/data/mirroring.qml
 create mode 100644 tests/auto/declarative/qdeclarativeitem/data/layoutmirroring.qml
 delete mode 100644 tests/auto/declarative/qdeclarativepositioners/data/grid-righttoleft.qml

diff --git a/doc/src/snippets/declarative/layoutmirroring.qml b/doc/src/snippets/declarative/layoutmirroring.qml
new file mode 100644
index 0000000..23eecd6
--- /dev/null
+++ b/doc/src/snippets/declarative/layoutmirroring.qml
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**   * Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in
+**     the documentation and/or other materials provided with the
+**     distribution.
+**   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+**     the names of its contributors may be used to endorse or promote
+**     products derived from this software without specific prior written
+**     permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//![0]
+import QtQuick 1.1
+
+Rectangle {
+    LayoutMirroring.enabled: true
+    LayoutMirroring.childrenInherit: true
+    width: 240; height: 50
+    Row {
+        anchors { left: parent.left; margins: 5 }
+        y: 5; spacing: 5
+        Repeater {
+            model: 5
+            Rectangle {
+                color: "red"
+                opacity: (5-index) / 5
+                width: 40; height: 40
+                Text {
+                    text: index+1
+                    anchors.centerIn: parent
+                }
+            }
+        }
+    }
+}
+//![0]
diff --git a/examples/declarative/positioners/layoutdirection/layoutdirection.qml b/examples/declarative/positioners/layoutdirection/layoutdirection.qml
index 3e23b15..080010e 100644
--- a/examples/declarative/positioners/layoutdirection/layoutdirection.qml
+++ b/examples/declarative/positioners/layoutdirection/layoutdirection.qml
@@ -41,10 +41,13 @@
 import QtQuick 1.1
 
 Rectangle {
+    property bool mirror
+    property int direction: Qt.application.layoutDirection
+    LayoutMirroring.enabled: mirror
+    LayoutMirroring.childrenInherit: true
 
     width: column.width + 100
     height: column.height + 100
-    property int direction: Qt.application.layoutDirection
 
     Column {
         id: column
@@ -133,6 +136,23 @@ Rectangle {
                 anchors.fill: parent
             }
         }
+        Rectangle {
+           height: 50; width: parent.width
+           color: mouseArea2.pressed ? "black" : "gray"
+           Text {
+                text: mirror ? "Mirrored" : "Normal"
+                color: "white"
+                font.pixelSize: 16
+                anchors.centerIn: parent
+            }
+            MouseArea {
+                id: mouseArea2
+                onClicked: {
+                    mirror = !mirror;
+                }
+                anchors.fill: parent
+            }
+        }
     }
     
     Component {
diff --git a/src/declarative/graphicsitems/qdeclarativeanchors.cpp b/src/declarative/graphicsitems/qdeclarativeanchors.cpp
index a2d6261..5ff6d2c 100644
--- a/src/declarative/graphicsitems/qdeclarativeanchors.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeanchors.cpp
@@ -175,13 +175,14 @@ QDeclarativeAnchors::~QDeclarativeAnchors()
 
 void QDeclarativeAnchorsPrivate::fillChanged()
 {
+    Q_Q(QDeclarativeAnchors);
     if (!fill || !isItemComplete())
         return;
 
     if (updatingFill < 2) {
         ++updatingFill;
 
-        qreal horizontalMargin = isMirrored() ? rightMargin : leftMargin;
+        qreal horizontalMargin = q->mirrored() ? rightMargin : leftMargin;
 
         if (fill == item->parentItem()) {                         //child-parent
             setItemPos(QPointF(horizontalMargin, topMargin));
@@ -201,13 +202,14 @@ void QDeclarativeAnchorsPrivate::fillChanged()
 
 void QDeclarativeAnchorsPrivate::centerInChanged()
 {
+    Q_Q(QDeclarativeAnchors);
     if (!centerIn || fill || !isItemComplete())
         return;
 
     if (updatingCenterIn < 2) {
         ++updatingCenterIn;
 
-        qreal effectiveHCenterOffset = isMirrored() ? -hCenterOffset : hCenterOffset;
+        qreal effectiveHCenterOffset = q->mirrored() ? -hCenterOffset : hCenterOffset;
         if (centerIn == item->parentItem()) {
             QPointF p(hcenter(item->parentItem()) - hcenter(item) + effectiveHCenterOffset,
                       vcenter(item->parentItem()) - vcenter(item) + vCenterOffset);
@@ -315,6 +317,13 @@ void QDeclarativeAnchors::componentComplete()
     d->componentComplete = true;
 }
 
+bool QDeclarativeAnchors::mirrored()
+{
+    Q_D(QDeclarativeAnchors);
+    QGraphicsItemPrivate * itemPrivate = QGraphicsItemPrivate::get(d->item);
+    return itemPrivate->isDeclarativeItem ? static_cast<QDeclarativeItemPrivate *>(itemPrivate)->effectiveLayoutMirror : false;
+}
+
 void QDeclarativeAnchorsPrivate::setItemHeight(qreal v)
 {
     updatingMe = true;
@@ -502,11 +511,6 @@ bool QDeclarativeAnchorsPrivate::calcStretch(const QDeclarativeAnchorLine &edge1
     return invalid;
 }
 
-bool QDeclarativeAnchorsPrivate::isMirrored() const
-{
-    return layoutDirection == Qt::RightToLeft;
-}
-
 void QDeclarativeAnchorsPrivate::updateVerticalAnchors()
 {
     if (fill || centerIn || !isItemComplete())
@@ -591,6 +595,7 @@ inline QDeclarativeAnchorLine::AnchorLine reverseAnchorLine(QDeclarativeAnchorLi
 
 void QDeclarativeAnchorsPrivate::updateHorizontalAnchors()
 {
+    Q_Q(QDeclarativeAnchors);
     if (fill || centerIn || !isItemComplete())
         return;
 
@@ -599,7 +604,7 @@ void QDeclarativeAnchorsPrivate::updateHorizontalAnchors()
         qreal effectiveRightMargin, effectiveLeftMargin, effectiveHorizontalCenterOffset;
         QDeclarativeAnchorLine effectiveLeft, effectiveRight, effectiveHorizontalCenter;
         QDeclarativeAnchors::Anchor effectiveLeftAnchor, effectiveRightAnchor;
-        if (isMirrored()) {
+        if (q->mirrored()) {
             effectiveLeftAnchor = QDeclarativeAnchors::RightAnchor;
             effectiveRightAnchor = QDeclarativeAnchors::LeftAnchor;
             effectiveLeft.item = right.item;
@@ -1086,25 +1091,6 @@ QDeclarativeAnchors::Anchors QDeclarativeAnchors::usedAnchors() const
     return d->usedAnchors;
 }
 
-
-Qt::LayoutDirection QDeclarativeAnchors::layoutDirection() const
-{
-    Q_D(const QDeclarativeAnchors);
-    return d->layoutDirection;
-}
-
-void QDeclarativeAnchors::setLayoutDirection(Qt::LayoutDirection layoutDirection)
-{
-    Q_D(QDeclarativeAnchors);
-    if (d->layoutDirection != layoutDirection) {
-        d->layoutDirection = layoutDirection;
-        d->fillChanged();
-        d->centerInChanged();
-        d->updateHorizontalAnchors();
-        emit layoutDirectionChanged();
-    }
-}
-
 bool QDeclarativeAnchorsPrivate::checkHValid() const
 {
     if (usedAnchors & QDeclarativeAnchors::LeftAnchor &&
diff --git a/src/declarative/graphicsitems/qdeclarativeanchors_p.h b/src/declarative/graphicsitems/qdeclarativeanchors_p.h
index 90a3508..388d6b9 100644
--- a/src/declarative/graphicsitems/qdeclarativeanchors_p.h
+++ b/src/declarative/graphicsitems/qdeclarativeanchors_p.h
@@ -79,7 +79,7 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeAnchors : public QObject
     Q_PROPERTY(qreal baselineOffset READ baselineOffset WRITE setBaselineOffset NOTIFY baselineOffsetChanged)
     Q_PROPERTY(QGraphicsObject *fill READ fill WRITE setFill RESET resetFill NOTIFY fillChanged)
     Q_PROPERTY(QGraphicsObject *centerIn READ centerIn WRITE setCenterIn RESET resetCenterIn NOTIFY centerInChanged)
-    Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged REVISION 1)
+    Q_PROPERTY(bool mirrored READ mirrored NOTIFY mirroredChanged REVISION 1)
 
 public:
     QDeclarativeAnchors(QObject *parent=0);
@@ -161,12 +161,11 @@ public:
 
     Anchors usedAnchors() const;
 
-    Qt::LayoutDirection layoutDirection() const;
-    void setLayoutDirection (Qt::LayoutDirection);
-
     void classBegin();
     void componentComplete();
 
+    bool mirrored();
+
 Q_SIGNALS:
     void leftChanged();
     void rightChanged();
@@ -185,10 +184,11 @@ Q_SIGNALS:
     void verticalCenterOffsetChanged();
     void horizontalCenterOffsetChanged();
     void baselineOffsetChanged();
-    Q_REVISION(1) void layoutDirectionChanged();
+    Q_REVISION(1) void mirroredChanged();
 
 private:
     friend class QDeclarativeItem;
+    friend class QDeclarativeItemPrivate;
     friend class QDeclarativeGraphicsWidget;
     Q_DISABLE_COPY(QDeclarativeAnchors)
     Q_DECLARE_PRIVATE(QDeclarativeAnchors)
diff --git a/src/declarative/graphicsitems/qdeclarativeanchors_p_p.h b/src/declarative/graphicsitems/qdeclarativeanchors_p_p.h
index ec96582..d8d2f15 100644
--- a/src/declarative/graphicsitems/qdeclarativeanchors_p_p.h
+++ b/src/declarative/graphicsitems/qdeclarativeanchors_p_p.h
@@ -94,7 +94,7 @@ public:
       : componentComplete(true), updatingMe(false), updatingHorizontalAnchor(0),
         updatingVerticalAnchor(0), updatingFill(0), updatingCenterIn(0), item(i), usedAnchors(0), fill(0),
         centerIn(0), leftMargin(0), rightMargin(0), topMargin(0), bottomMargin(0),
-        margins(0), vCenterOffset(0), hCenterOffset(0), baselineOffset(0), layoutDirection(Qt::LeftToRight)
+        margins(0), vCenterOffset(0), hCenterOffset(0), baselineOffset(0)
     {
     }
 
@@ -161,8 +161,6 @@ public:
     qreal vCenterOffset;
     qreal hCenterOffset;
     qreal baselineOffset;
-
-    Qt::LayoutDirection layoutDirection;
 };
 
 QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qdeclarativegridview.cpp b/src/declarative/graphicsitems/qdeclarativegridview.cpp
index 2eeadf4..f6810ed 100644
--- a/src/declarative/graphicsitems/qdeclarativegridview.cpp
+++ b/src/declarative/graphicsitems/qdeclarativegridview.cpp
@@ -73,7 +73,7 @@ public:
         if (view->flow() == QDeclarativeGridView::LeftToRight) {
             rowPos = item->y();
         } else {
-            if (view->layoutDirection() == Qt::RightToLeft)
+            if (view->effectiveLayoutDirection() == Qt::RightToLeft)
                 rowPos = -view->cellWidth()-item->x();
             else
                 rowPos = item->x();
@@ -83,7 +83,7 @@ public:
     qreal colPos() const {
         qreal colPos = 0;
         if (view->flow() == QDeclarativeGridView::LeftToRight) {
-            if (view->layoutDirection() == Qt::RightToLeft) {
+            if (view->effectiveLayoutDirection() == Qt::RightToLeft) {
                 int colSize = view->cellWidth();
                 int columns = view->width()/colSize;
                 colPos = colSize * (columns-1) - item->x();
@@ -101,14 +101,14 @@ public:
         if (view->flow() == QDeclarativeGridView::LeftToRight) {
             return item->y() + view->cellHeight() - 1;
         } else {
-            if (view->layoutDirection() == Qt::RightToLeft)
+            if (view->effectiveLayoutDirection() == Qt::RightToLeft)
                 return -item->x() - 1;
             else
                 return item->x() + view->cellWidth() - 1;
         }
     }
     void setPosition(qreal col, qreal row) {
-        if (view->layoutDirection() == Qt::RightToLeft) {
+        if (view->effectiveLayoutDirection() == Qt::RightToLeft) {
             if (view->flow() == QDeclarativeGridView::LeftToRight) {
                 int columns = view->width()/view->cellWidth();
                 item->setPos(QPointF((view->cellWidth() * (columns-1) - col), row));
@@ -188,7 +188,24 @@ public:
     }
 
     bool isRightToLeftTopToBottom() const {
-        return flow == QDeclarativeGridView::TopToBottom && layoutDirection == Qt::RightToLeft;
+        Q_Q(const QDeclarativeGridView);
+        return flow == QDeclarativeGridView::TopToBottom && q->effectiveLayoutDirection() == Qt::RightToLeft;
+    }
+
+    void regenerate() {
+        Q_Q(QDeclarativeGridView);
+        if (q->isComponentComplete()) {
+            clear();
+            updateGrid();
+            q->refill();
+            updateCurrent(currentIndex);
+        }
+    }
+
+    void mirrorChange() {
+        Q_Q(QDeclarativeGridView);
+        regenerate();
+        emit q->effectiveLayoutDirectionChanged();
     }
 
     qreal position() const {
@@ -201,7 +218,7 @@ public:
             q->QDeclarativeFlickable::setContentY(pos);
             q->QDeclarativeFlickable::setContentX(0);
         } else {
-            if (layoutDirection == Qt::LeftToRight)
+            if (q->effectiveLayoutDirection() == Qt::LeftToRight)
                 q->QDeclarativeFlickable::setContentX(pos);
             else
                 q->QDeclarativeFlickable::setContentX(-pos-size());
@@ -918,7 +935,7 @@ void QDeclarativeGridViewPrivate::updateFooter()
             rowOffset = footer->item->width()-cellWidth;
         } else {
             rowOffset = 0;
-            if (layoutDirection == Qt::RightToLeft)
+            if (q->effectiveLayoutDirection() == Qt::RightToLeft)
                 colOffset = footer->item->width()-cellWidth;
         }
         if (visibleItems.count()) {
@@ -971,7 +988,7 @@ void QDeclarativeGridViewPrivate::updateHeader()
             rowOffset = -cellWidth;
         } else {
             rowOffset = -headerSize();
-            if (layoutDirection == Qt::RightToLeft)
+            if (q->effectiveLayoutDirection() == Qt::RightToLeft)
                 colOffset = header->item->width()-cellWidth;
         }
         if (visibleItems.count()) {
@@ -1761,7 +1778,6 @@ void QDeclarativeGridView::setHighlightRangeMode(HighlightRangeMode mode)
   \bold Note: If GridView::flow is set to GridView.LeftToRight, this is not to be confused if
   GridView::layoutDirection is set to Qt.RightToLeft. The GridView.LeftToRight flow value simply
   indicates that the flow is horizontal.
-
 */
 
 Qt::LayoutDirection QDeclarativeGridView::layoutDirection() const
@@ -1775,15 +1791,33 @@ void QDeclarativeGridView::setLayoutDirection(Qt::LayoutDirection layoutDirectio
     Q_D(QDeclarativeGridView);
     if (d->layoutDirection != layoutDirection) {
         d->layoutDirection = layoutDirection;
-        d->clear();
-        d->updateGrid();
-        refill();
-        d->updateCurrent(d->currentIndex);
+        d->regenerate();
         emit layoutDirectionChanged();
+        emit effectiveLayoutDirectionChanged();
     }
 }
 
 /*!
+    \qmlproperty enumeration GridView::effectiveLayoutDirection
+    This property holds the effective layout direction of the grid.
+
+    When using the attached property \l {LayoutMirroring::mirror}{LayoutMirroring::mirror} for locale layouts,
+    the visual layout direction of the grid will be mirrored. However, the
+    property \l {GridView::layoutDirection}{layoutDirection} will remain unchanged.
+
+    \sa GridView::layoutDirection, {LayoutMirroring}{LayoutMirroring}
+*/
+
+Qt::LayoutDirection QDeclarativeGridView::effectiveLayoutDirection() const
+{
+    Q_D(const QDeclarativeGridView);
+    if (d->effectiveLayoutMirror)
+        return d->layoutDirection == Qt::RightToLeft ? Qt::LeftToRight : Qt::RightToLeft;
+    else
+        return d->layoutDirection;
+}
+
+/*!
   \qmlproperty enumeration GridView::flow
   This property holds the flow of the grid.
 
@@ -1814,10 +1848,7 @@ void QDeclarativeGridView::setFlow(Flow flow)
         }
         setContentX(0);
         setContentY(0);
-        d->clear();
-        d->updateGrid();
-        refill();
-        d->updateCurrent(d->currentIndex);
+        d->regenerate();
         emit flowChanged();
     }
 }
@@ -2338,7 +2369,7 @@ void QDeclarativeGridView::moveCurrentIndexLeft()
     if (!count)
         return;
 
-    if (d->layoutDirection == Qt::LeftToRight) {
+    if (effectiveLayoutDirection() == Qt::LeftToRight) {
         if (d->flow == QDeclarativeGridView::LeftToRight) {
             if (currentIndex() > 0 || d->wrap) {
                 int index = currentIndex() - 1;
@@ -2381,7 +2412,7 @@ void QDeclarativeGridView::moveCurrentIndexRight()
     if (!count)
         return;
 
-    if (d->layoutDirection == Qt::LeftToRight) {
+    if (effectiveLayoutDirection() == Qt::LeftToRight) {
         if (d->flow == QDeclarativeGridView::LeftToRight) {
             if (currentIndex() < count - 1 || d->wrap) {
                 int index = currentIndex() + 1;
diff --git a/src/declarative/graphicsitems/qdeclarativegridview_p.h b/src/declarative/graphicsitems/qdeclarativegridview_p.h
index fc9e6b4..ad0c609 100644
--- a/src/declarative/graphicsitems/qdeclarativegridview_p.h
+++ b/src/declarative/graphicsitems/qdeclarativegridview_p.h
@@ -74,7 +74,8 @@ class Q_AUTOTEST_EXPORT QDeclarativeGridView : public QDeclarativeFlickable
     Q_PROPERTY(HighlightRangeMode highlightRangeMode READ highlightRangeMode WRITE setHighlightRangeMode NOTIFY highlightRangeModeChanged)
 
     Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged)
-    Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged) //Versioning support?
+    Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged REVISION 1)
+    Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged REVISION 1)
     Q_PROPERTY(bool keyNavigationWraps READ isWrapEnabled WRITE setWrapEnabled NOTIFY keyNavigationWrapsChanged)
     Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged)
     Q_PROPERTY(int cellWidth READ cellWidth WRITE setCellWidth NOTIFY cellWidthChanged)
@@ -132,6 +133,7 @@ public:
 
     Qt::LayoutDirection layoutDirection() const;
     void setLayoutDirection(Qt::LayoutDirection);
+    Qt::LayoutDirection effectiveLayoutDirection() const;
 
     enum Flow { LeftToRight, TopToBottom };
     Flow flow() const;
@@ -191,7 +193,8 @@ Q_SIGNALS:
     void modelChanged();
     void delegateChanged();
     void flowChanged();
-    void layoutDirectionChanged();
+    Q_REVISION(1) void layoutDirectionChanged();
+    Q_REVISION(1) void effectiveLayoutDirectionChanged();
     void keyNavigationWrapsChanged();
     void cacheBufferChanged();
     void snapModeChanged();
diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp
index ac5d55c..d16025d 100644
--- a/src/declarative/graphicsitems/qdeclarativeitem.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp
@@ -39,12 +39,12 @@
 **
 ****************************************************************************/
 
-#include "private/qdeclarativeitem_p.h"
 #include "qdeclarativeitem.h"
 
 #include "private/qdeclarativeevents_p_p.h"
 #include <private/qdeclarativeengine_p.h>
 #include <private/qgraphicsitem_p.h>
+#include <QtDeclarative/private/qdeclarativeitem_p.h>
 
 #include <qdeclarativeengine.h>
 #include <qdeclarativeopenmetaobject_p.h>
@@ -731,6 +731,152 @@ void QDeclarativeKeyNavigationAttached::setFocusNavigation(QDeclarativeItem *cur
 }
 
 /*!
+    \qmlclass LayoutMirroring QDeclarativeLayoutMirroringAttached
+    \since QtQuick 1.1
+    \ingroup qml-utility-elements
+    \brief The LayoutMirroring is used for mirroring the Qt Quick application layouts.
+
+    LayoutMirroring \l enabled property can be used to horizontally mirror \l {anchor-layout}{Item anchors},
+    \l{Using QML Positioner and Repeater Items}{Positioner} elements and QML views like \l {GridView}{GridView}
+    and horizontal \l {ListView}{ListView}. Mirroring is a visual change, left anchors will become
+    right anchors and left-to-right positioner will instead position child items from right to left.
+    By default setting the \l enabled property to true only affects the item in question. You can set property
+    LayoutDirection \l childrenInherit to true if you want the item children also inherit the mirror setting.
+    If no attached property has been defined, mirroring is disabled.
+
+    The following example shows mirroring in action. When \l enabled is set to true, left anchor
+    becomes right, and \l {Row}{Row} starts positioning items in a reverse order:
+
+    \snippet doc/src/snippets/declarative/layoutmirroring.qml 0
+
+    Layout mirroring is useful when you need to support both left-to-right and right-to-left
+    layout versions of your application that target different language areas. Inheritance saves
+    you from having to mirror the layouts manually for each layout item in your application. Keep
+    in mind however that the mirroring does not affect the positioning done by modifying Item's x
+    co-ordinate directly, so even with the mirroring enabled you will often need to do some layout
+    fixes to support the other reading direction. Also, there are cases where you need to disable
+    mirroring of individual child items, either because mirroring is not the wanted behavior or
+    because the item already implements mirroring in some custom way.
+*/
+
+/*!
+    \qmlproperty bool LayoutMirroring::enabled
+
+    Setting this property to true mirrors item's layout horizontally, whether the layout is done
+    using \l {anchor-layout}{anchors}, \l{Using QML Positioner and Repeater Items}{Positioners}
+    or as a QML view \l {GridView}{GridView} or \l {ListView}{ListView}.
+*/
+
+/*!
+    \qmlproperty bool LayoutMirroring::childrenInherit
+
+    This property can be set to true if you want the item children
+    to inherit the item's mirror setting.
+*/
+
+QDeclarativeLayoutMirroringAttached::QDeclarativeLayoutMirroringAttached(QObject *parent) : QObject(parent), itemPrivate(0)
+{
+    if (QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(parent)) {
+        itemPrivate = QDeclarativeItemPrivate::get(item);
+        itemPrivate->attachedLayoutDirection = this;
+    } else
+        qmlInfo(parent) << tr("LayoutDirection attached property only works with Items");
+}
+
+QDeclarativeLayoutMirroringAttached * QDeclarativeLayoutMirroringAttached::qmlAttachedProperties(QObject *object)
+{
+    return new QDeclarativeLayoutMirroringAttached(object);
+}
+
+bool QDeclarativeLayoutMirroringAttached::enabled() const
+{
+    return itemPrivate ? itemPrivate->effectiveLayoutMirror : false;
+}
+
+void QDeclarativeLayoutMirroringAttached::setEnabled(bool enabled)
+{
+    if (!itemPrivate)
+        return;
+
+    itemPrivate->isMirrorImplicit = false;
+    if (enabled != itemPrivate->effectiveLayoutMirror) {
+        itemPrivate->setLayoutMirror(enabled);
+        if (itemPrivate->inheritMirrorFromItem)
+             itemPrivate->resolveLayoutMirror();
+    }
+}
+
+void QDeclarativeLayoutMirroringAttached::resetEnabled()
+{
+    if (itemPrivate && !itemPrivate->isMirrorImplicit) {
+        itemPrivate->isMirrorImplicit = true;
+        itemPrivate->resolveLayoutMirror();
+    }
+}
+
+bool QDeclarativeLayoutMirroringAttached::childrenInherit() const
+{
+    return itemPrivate ? itemPrivate->inheritMirrorFromItem : false;
+}
+
+void QDeclarativeLayoutMirroringAttached::setChildrenInherit(bool childrenInherit) {
+    if (itemPrivate && childrenInherit != itemPrivate->inheritMirrorFromItem) {
+        itemPrivate->inheritMirrorFromItem = childrenInherit;
+        itemPrivate->resolveLayoutMirror();
+        childrenInheritChanged();
+    }
+}
+
+void QDeclarativeItemPrivate::resolveLayoutMirror()
+{
+    Q_Q(QDeclarativeItem);
+    if (QDeclarativeItem *parentItem = q->parentItem()) {
+        QDeclarativeItemPrivate *parentPrivate = QDeclarativeItemPrivate::get(parentItem);
+        setImplicitLayoutMirror(parentPrivate->inheritedLayoutMirror, parentPrivate->inheritMirrorFromParent);
+    } else {
+        setImplicitLayoutMirror(isMirrorImplicit ? false : effectiveLayoutMirror, inheritMirrorFromItem);
+    }
+}
+
+void QDeclarativeItemPrivate::setImplicitLayoutMirror(bool mirror, bool inherit)
+{
+    inherit = inherit || inheritMirrorFromItem;
+    if (!isMirrorImplicit && inheritMirrorFromItem)
+        mirror = effectiveLayoutMirror;
+    if (mirror == inheritedLayoutMirror && inherit == inheritMirrorFromParent)
+        return;
+
+    inheritMirrorFromParent = inherit;
+    inheritedLayoutMirror = inheritMirrorFromParent ? mirror : false;
+
+    if (isMirrorImplicit)
+        setLayoutMirror(inherit ? inheritedLayoutMirror : false);
+    for (int i = 0; i < children.count(); ++i) {
+        if (QDeclarativeItem *child = qobject_cast<QDeclarativeItem *>(children.at(i))) {
+            QDeclarativeItemPrivate *childPrivate = QDeclarativeItemPrivate::get(child);
+            childPrivate->setImplicitLayoutMirror(inheritedLayoutMirror, inheritMirrorFromParent);
+        }
+    }
+}
+
+void QDeclarativeItemPrivate::setLayoutMirror(bool mirror)
+{
+    if (mirror != effectiveLayoutMirror) {
+        effectiveLayoutMirror = mirror;
+        if (_anchors) {
+            _anchors->d_func()->fillChanged();
+            _anchors->d_func()->centerInChanged();
+            _anchors->d_func()->updateHorizontalAnchors();
+            emit _anchors->mirroredChanged();
+        }
+        mirrorChange();
+        if (attachedLayoutDirection) {
+            emit attachedLayoutDirection->enabledChanged();
+        }
+    }
+}
+
+/*!
     \qmlclass Keys QDeclarativeKeysAttached
     \ingroup qml-basic-interaction-elements
     \since 4.7
@@ -1389,6 +1535,11 @@ QDeclarativeKeysAttached *QDeclarativeKeysAttached::qmlAttachedProperties(QObjec
     \endqml
 
     See the \l {Keys}{Keys} attached property for detailed documentation.
+
+    \section1 Layout Mirroring
+
+    Item layouts can be mirrored using \l {LayoutMirroring}{LayoutMirroring} attached property.
+
 */
 
 /*!
@@ -2782,6 +2933,7 @@ QVariant QDeclarativeItem::itemChange(GraphicsItemChange change,
     Q_D(QDeclarativeItem);
     switch (change) {
     case ItemParentHasChanged:
+        d->resolveLayoutMirror();
         emit parentChanged(parentItem());
         d->parentNotifier.notify();
         break;
diff --git a/src/declarative/graphicsitems/qdeclarativeitem_p.h b/src/declarative/graphicsitems/qdeclarativeitem_p.h
index 4303c0a..b204d7f 100644
--- a/src/declarative/graphicsitems/qdeclarativeitem_p.h
+++ b/src/declarative/graphicsitems/qdeclarativeitem_p.h
@@ -77,6 +77,7 @@ QT_BEGIN_NAMESPACE
 
 class QNetworkReply;
 class QDeclarativeItemKeyFilter;
+class QDeclarativeLayoutMirroringAttached;
 
 //### merge into private?
 class QDeclarativeContents : public QObject, public QDeclarativeItemChangeListener
@@ -125,8 +126,10 @@ public:
       _stateGroup(0), origin(QDeclarativeItem::Center),
       widthValid(false), heightValid(false),
       componentComplete(true), keepMouse(false),
-      smooth(false), transformOriginDirty(true), doneEventPreHandler(false), keyHandler(0),
-      mWidth(0), mHeight(0), mImplicitWidth(0), mImplicitHeight(0), hadSubFocusItem(false)
+      smooth(false), transformOriginDirty(true), doneEventPreHandler(false),
+      inheritedLayoutMirror(false), effectiveLayoutMirror(false), isMirrorImplicit(true),
+      inheritMirrorFromParent(false), inheritMirrorFromItem(false), keyHandler(0),
+      mWidth(0), mHeight(0), mImplicitWidth(0), mImplicitHeight(0), attachedLayoutDirection(0), hadSubFocusItem(false)
     {
         QGraphicsItemPrivate::acceptedMouseButtons = 0;
         isDeclarativeItem = 1;
@@ -134,7 +137,6 @@ public:
                                       QGraphicsItem::ItemHasNoContents
                                       | QGraphicsItem::ItemIsFocusable
                                       | QGraphicsItem::ItemNegativeZStacksBehindParent);
-
     }
 
     void init(QDeclarativeItem *parent)
@@ -146,6 +148,11 @@ public:
         }
         baselineOffset.invalidate();
         mouseSetsFocus = false;
+        resolveLayoutMirror();
+    }
+
+    bool isMirrored() const {
+        return effectiveLayoutMirror;
     }
 
     // Private Properties
@@ -162,6 +169,10 @@ public:
     virtual void implicitWidthChanged();
     virtual void implicitHeightChanged();
 
+    void resolveLayoutMirror();
+    void setImplicitLayoutMirror(bool mirror, bool inherit);
+    void setLayoutMirror(bool mirror);
+
     QDeclarativeListProperty<QObject> data();
     QDeclarativeListProperty<QObject> resources();
 
@@ -272,6 +283,11 @@ public:
     bool smooth:1;
     bool transformOriginDirty : 1;
     bool doneEventPreHandler : 1;
+    bool inheritedLayoutMirror:1;
+    bool effectiveLayoutMirror:1;
+    bool isMirrorImplicit:1;
+    bool inheritMirrorFromParent:1;
+    bool inheritMirrorFromItem:1;
 
     QDeclarativeItemKeyFilter *keyHandler;
 
@@ -280,6 +296,8 @@ public:
     qreal mImplicitWidth;
     qreal mImplicitHeight;
 
+    QDeclarativeLayoutMirroringAttached* attachedLayoutDirection;
+
     bool hadSubFocusItem;
 
     QPointF computeTransformOrigin() const;
@@ -326,6 +344,8 @@ public:
 
     virtual void focusChanged(bool);
 
+    virtual void mirrorChange() {};
+
     static qint64 consistentTime;
     static void setConsistentTime(qint64 t);
     static void start(QElapsedTimer &);
@@ -423,6 +443,31 @@ private:
     void setFocusNavigation(QDeclarativeItem *currentItem, const char *dir);
 };
 
+class QDeclarativeLayoutMirroringAttached : public QObject
+{
+    Q_OBJECT
+    Q_PROPERTY(bool enabled READ enabled WRITE setEnabled RESET resetEnabled NOTIFY enabledChanged)
+    Q_PROPERTY(bool childrenInherit READ childrenInherit WRITE setChildrenInherit NOTIFY childrenInheritChanged)
+
+public:
+    explicit QDeclarativeLayoutMirroringAttached(QObject *parent = 0);
+
+    bool enabled() const;
+    void setEnabled(bool);
+    void resetEnabled();
+
+    bool childrenInherit() const;
+    void setChildrenInherit(bool);
+
+    static QDeclarativeLayoutMirroringAttached *qmlAttachedProperties(QObject *);
+Q_SIGNALS:
+    void enabledChanged();
+    void childrenInheritChanged();
+private:
+    friend class QDeclarativeItemPrivate;
+    QDeclarativeItemPrivate *itemPrivate;
+};
+
 class QDeclarativeKeysAttachedPrivate : public QObjectPrivate
 {
 public:
@@ -572,5 +617,7 @@ QML_DECLARE_TYPE(QDeclarativeKeysAttached)
 QML_DECLARE_TYPEINFO(QDeclarativeKeysAttached, QML_HAS_ATTACHED_PROPERTIES)
 QML_DECLARE_TYPE(QDeclarativeKeyNavigationAttached)
 QML_DECLARE_TYPEINFO(QDeclarativeKeyNavigationAttached, QML_HAS_ATTACHED_PROPERTIES)
+QML_DECLARE_TYPE(QDeclarativeLayoutMirroringAttached)
+QML_DECLARE_TYPEINFO(QDeclarativeLayoutMirroringAttached, QML_HAS_ATTACHED_PROPERTIES)
 
 #endif // QDECLARATIVEITEM_P_H
diff --git a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp
index 3c8f64e..c4a9030 100644
--- a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp
@@ -198,6 +198,7 @@ void QDeclarativeItemModule::defineModule()
     qmlRegisterRevision<QDeclarativeImplicitSizeItem,1>("QtQuick",1,1);
     qmlRegisterRevision<QDeclarativeImplicitSizePaintedItem,0>("QtQuick",1,0);
     qmlRegisterRevision<QDeclarativeImplicitSizePaintedItem,1>("QtQuick",1,1);
+    qmlRegisterUncreatableType<QDeclarativeLayoutMirroringAttached>("QtQuick",1,1,"LayoutMirroring", QDeclarativeLayoutMirroringAttached::tr("LayoutMirroring is only available via attached properties"));
 
 #ifndef QT_NO_IMPORT_QT47_QML
 #ifdef QT_NO_MOVIE
diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp
index 486cec8..879b99b 100644
--- a/src/declarative/graphicsitems/qdeclarativelistview.cpp
+++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp
@@ -104,16 +104,17 @@ public:
             if (view->orientation() == QDeclarativeListView::Vertical)
                 return section->y();
             else
-                return (view->layoutDirection() == Qt::RightToLeft ? -section->width()-section->x() : section->x());
+                return (view->effectiveLayoutDirection() == Qt::RightToLeft ? -section->width()-section->x() : section->x());
         } else {
             return itemPosition();
         }
     }
+
     qreal itemPosition() const {
         if (view->orientation() == QDeclarativeListView::Vertical)
             return item->y();
         else
-            return (view->layoutDirection() == Qt::RightToLeft ? -item->width()-item->x() : item->x());
+            return (view->effectiveLayoutDirection() == Qt::RightToLeft ? -item->width()-item->x() : item->x());
     }
     qreal size() const {
         if (section)
@@ -133,7 +134,7 @@ public:
         if (view->orientation() == QDeclarativeListView::Vertical) {
             return item->y() + (item->height() >= 1.0 ? item->height() : 1) - 1;
         } else {
-            return (view->layoutDirection() == Qt::RightToLeft
+            return (view->effectiveLayoutDirection() == Qt::RightToLeft
                     ? -item->width()-item->x() + (item->width() >= 1.0 ? item->width() : 1)
                     : item->x() + (item->width() >= 1.0 ? item->width() : 1)) - 1;
         }
@@ -146,7 +147,7 @@ public:
             }
             item->setY(pos);
         } else {
-            if (view->layoutDirection() == Qt::RightToLeft) {
+            if (view->effectiveLayoutDirection() == Qt::RightToLeft) {
                 if (section) {
                     section->setX(-section->width()-pos);
                     pos += section->width();
@@ -248,8 +249,25 @@ public:
         return 0;
     }
 
+    void regenerate() {
+        Q_Q(QDeclarativeListView);
+        if (q->isComponentComplete()) {
+            clear();
+            setPosition(0);
+            q->refill();
+            updateCurrent(currentIndex);
+        }
+    }
+
+    void mirrorChange() {
+        Q_Q(QDeclarativeListView);
+        regenerate();
+        emit q->effectiveLayoutDirectionChanged();
+    }
+
     bool isRightToLeft() const {
-        return (layoutDirection == Qt::RightToLeft && orient == QDeclarativeListView::Horizontal);
+        Q_Q(const QDeclarativeListView);
+        return orient == QDeclarativeListView::Horizontal && q->effectiveLayoutDirection() == Qt::RightToLeft;
     }
 
     qreal position() const {
@@ -262,7 +280,7 @@ public:
         if (orient == QDeclarativeListView::Vertical) {
             q->QDeclarativeFlickable::setContentY(pos);
         } else {
-            if (layoutDirection == Qt::RightToLeft)
+            if (isRightToLeft())
                 q->QDeclarativeFlickable::setContentX(-pos-size());
             else
                 q->QDeclarativeFlickable::setContentX(pos);
@@ -2064,14 +2082,25 @@ void QDeclarativeListView::setOrientation(QDeclarativeListView::Orientation orie
             setContentHeight(-1);
             setFlickableDirection(HorizontalFlick);
         }
-        d->clear();
-        d->setPosition(0);
-        refill();
+        d->regenerate();
         emit orientationChanged();
-        d->updateCurrent(d->currentIndex);
     }
 }
 
+/*!
+  \qmlproperty enumeration ListView::layoutDirection
+  This property holds the layout direction of the horizontal list.
+
+  Possible values:
+
+  \list
+  \o Qt.LeftToRight (default) - Items will be laid out from left to right.
+  \o Qt.RightToLeft - Items will be laid out from right to let.
+  \endlist
+
+  \sa ListView::effectiveLayoutDirection
+*/
+
 Qt::LayoutDirection QDeclarativeListView::layoutDirection() const
 {
     Q_D(const QDeclarativeListView);
@@ -2083,15 +2112,33 @@ void QDeclarativeListView::setLayoutDirection(Qt::LayoutDirection layoutDirectio
     Q_D(QDeclarativeListView);
     if (d->layoutDirection != layoutDirection) {
         d->layoutDirection = layoutDirection;
-        d->clear();
-        d->setPosition(0);
-        refill();
+        d->regenerate();
         emit layoutDirectionChanged();
-        d->updateCurrent(d->currentIndex);
+        emit effectiveLayoutDirectionChanged();
     }
 }
 
 /*!
+    \qmlproperty enumeration ListView::effectiveLayoutDirection
+    This property holds the effective layout direction of the horizontal list.
+
+    When using the attached property \l {LayoutMirroring::mirror}{LayoutMirroring::mirror} for locale layouts,
+    the visual layout direction of the horizontal list will be mirrored. However, the
+    property \l {ListView::layoutDirection}{layoutDirection} will remain unchanged.
+
+    \sa ListView::layoutDirection, {LayoutMirroring}{LayoutMirroring}
+*/
+
+Qt::LayoutDirection QDeclarativeListView::effectiveLayoutDirection() const
+{
+    Q_D(const QDeclarativeListView);
+    if (d->effectiveLayoutMirror)
+        return d->layoutDirection == Qt::RightToLeft ? Qt::LeftToRight : Qt::RightToLeft;
+    else
+        return d->layoutDirection;
+}
+
+/*!
     \qmlproperty bool ListView::keyNavigationWraps
     This property holds whether the list wraps key navigation. 
 
@@ -2671,8 +2718,8 @@ void QDeclarativeListView::keyPressEvent(QKeyEvent *event)
         return;
 
     if (d->model && d->model->count() && d->interactive) {
-        if ((d->orient == QDeclarativeListView::Horizontal && d->layoutDirection == Qt::LeftToRight && event->key() == Qt::Key_Left)
-                    || (d->orient == QDeclarativeListView::Horizontal && d->layoutDirection == Qt::RightToLeft && event->key() == Qt::Key_Right)
+        if ((!d->isRightToLeft() && event->key() == Qt::Key_Left)
+                    || (d->orient == QDeclarativeListView::Horizontal && d->isRightToLeft() && event->key() == Qt::Key_Right)
                     || (d->orient == QDeclarativeListView::Vertical && event->key() == Qt::Key_Up)) {
             if (currentIndex() > 0 || (d->wrap && !event->isAutoRepeat())) {
                 decrementCurrentIndex();
@@ -2682,8 +2729,8 @@ void QDeclarativeListView::keyPressEvent(QKeyEvent *event)
                 event->accept();
                 return;
             }
-        } else if ((d->orient == QDeclarativeListView::Horizontal && d->layoutDirection == Qt::LeftToRight && event->key() == Qt::Key_Right)
-                    || (d->orient == QDeclarativeListView::Horizontal && d->layoutDirection == Qt::RightToLeft && event->key() == Qt::Key_Left)
+        } else if ((!d->isRightToLeft() && event->key() == Qt::Key_Right)
+                    || (d->orient == QDeclarativeListView::Horizontal && d->isRightToLeft() && event->key() == Qt::Key_Left)
                     || (d->orient == QDeclarativeListView::Vertical && event->key() == Qt::Key_Down)) {
             if (currentIndex() < d->model->count() - 1 || (d->wrap && !event->isAutoRepeat())) {
                 incrementCurrentIndex();
@@ -2970,7 +3017,7 @@ void QDeclarativeListView::updateSections()
 void QDeclarativeListView::refill()
 {
     Q_D(QDeclarativeListView);
-    if (layoutDirection() == Qt::RightToLeft && orientation() == QDeclarativeListView::Horizontal)
+    if (d->isRightToLeft())
         d->refill(-d->position()-d->size()+1, -d->position());
     else
         d->refill(d->position(), d->position()+d->size()-1);
@@ -3416,11 +3463,8 @@ void QDeclarativeListView::itemsChanged(int, int)
 void QDeclarativeListView::modelReset()
 {
     Q_D(QDeclarativeListView);
-    d->clear();
-    d->setPosition(0);
-    refill();
     d->moveReason = QDeclarativeListViewPrivate::SetIndex;
-    d->updateCurrent(d->currentIndex);
+    d->regenerate();
     if (d->highlight && d->currentItem) {
         if (d->autoHighlight)
             d->highlight->setPosition(d->currentItem->position());
diff --git a/src/declarative/graphicsitems/qdeclarativelistview_p.h b/src/declarative/graphicsitems/qdeclarativelistview_p.h
index 6b72240..30171f8 100644
--- a/src/declarative/graphicsitems/qdeclarativelistview_p.h
+++ b/src/declarative/graphicsitems/qdeclarativelistview_p.h
@@ -113,7 +113,8 @@ class Q_AUTOTEST_EXPORT QDeclarativeListView : public QDeclarativeFlickable
 
     Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged)
     Q_PROPERTY(Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged)
-    Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged)
+    Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged REVISION 1)
+    Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged REVISION 1)
     Q_PROPERTY(bool keyNavigationWraps READ isWrapEnabled WRITE setWrapEnabled NOTIFY keyNavigationWrapsChanged)
     Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged)
     Q_PROPERTY(QDeclarativeViewSection *section READ sectionCriteria CONSTANT)
@@ -174,6 +175,7 @@ public:
 
     Qt::LayoutDirection layoutDirection() const;
     void setLayoutDirection(Qt::LayoutDirection);
+    Qt::LayoutDirection effectiveLayoutDirection() const;
 
     bool isWrapEnabled() const;
     void setWrapEnabled(bool);
@@ -226,7 +228,8 @@ Q_SIGNALS:
     void countChanged();
     void spacingChanged();
     void orientationChanged();
-    void layoutDirectionChanged();
+    Q_REVISION(1) void layoutDirectionChanged();
+    Q_REVISION(1) void effectiveLayoutDirectionChanged();
     void currentIndexChanged();
     void currentSectionChanged();
     void highlightMoveSpeedChanged();
diff --git a/src/declarative/graphicsitems/qdeclarativepositioners.cpp b/src/declarative/graphicsitems/qdeclarativepositioners.cpp
index 4560d32..f57f501 100644
--- a/src/declarative/graphicsitems/qdeclarativepositioners.cpp
+++ b/src/declarative/graphicsitems/qdeclarativepositioners.cpp
@@ -574,7 +574,7 @@ void QDeclarativeColumn::reportConflictingAnchors()
   \sa Grid::spacing
 */
 QDeclarativeRow::QDeclarativeRow(QDeclarativeItem *parent)
-: QDeclarativeBasePositioner(Horizontal, parent), m_layoutDirection(Qt::LeftToRight)
+: QDeclarativeBasePositioner(Horizontal, parent)
 {
 }
 
@@ -595,20 +595,39 @@ QDeclarativeRow::QDeclarativeRow(QDeclarativeItem *parent)
 */
 Qt::LayoutDirection QDeclarativeRow::layoutDirection() const
 {
-    return m_layoutDirection;
+    return QDeclarativeBasePositionerPrivate::getLayoutDirection(this);
 }
 
 void QDeclarativeRow::setLayoutDirection(Qt::LayoutDirection layoutDirection)
 {
-    if (m_layoutDirection != layoutDirection) {
-        m_layoutDirection = layoutDirection;
+    QDeclarativeBasePositionerPrivate *d = static_cast<QDeclarativeBasePositionerPrivate* >(QDeclarativeBasePositionerPrivate::get(this));
+    if (d->layoutDirection != layoutDirection) {
+        d->layoutDirection = layoutDirection;
         prePositioning();
         emit layoutDirectionChanged();
+        emit effectiveLayoutDirectionChanged();
     }
 }
 
+/*!
+    \qmlproperty enumeration Row::effectiveLayoutDirection
+    This property holds the effective layout direction of the row positioner.
+
+    When using the attached property {LayoutMirroring::mirror}{LayoutMirroring::mirror} for locale layouts,
+    the visual layout direction of the row positioner will be mirrored. However, the
+    property \l {Row::layoutDirection}{layoutDirection} will remain unchanged.
+
+    \sa Row::layoutDirection, {LayoutMirroring}{LayoutMirroring}
+*/
+
+Qt::LayoutDirection QDeclarativeRow::effectiveLayoutDirection() const
+{
+    return QDeclarativeBasePositionerPrivate::getEffectiveLayoutDirection(this);
+}
+
 void QDeclarativeRow::doPositioning(QSizeF *contentSize)
 {
+    QDeclarativeBasePositionerPrivate *d = static_cast<QDeclarativeBasePositionerPrivate*>(QDeclarativeBasePositionerPrivate::get(this));
     int hoffset = 0;
 
     QList<int> hoffsets;
@@ -617,7 +636,7 @@ void QDeclarativeRow::doPositioning(QSizeF *contentSize)
         if (!child.item || !child.isVisible)
             continue;
 
-        if(m_layoutDirection == Qt::LeftToRight){
+        if(d->isLeftToRight()){
             if(child.item->x() != hoffset)
                 positionX(hoffset, child);
         }else{
@@ -632,7 +651,7 @@ void QDeclarativeRow::doPositioning(QSizeF *contentSize)
 
     contentSize->setWidth(hoffset - spacing());
 
-    if(m_layoutDirection == Qt::LeftToRight)
+    if(d->isLeftToRight())
         return;
 
     //Right to Left layout
@@ -786,7 +805,7 @@ void QDeclarativeRow::reportConflictingAnchors()
   \sa rows, columns
 */
 QDeclarativeGrid::QDeclarativeGrid(QDeclarativeItem *parent) :
-    QDeclarativeBasePositioner(Both, parent), m_rows(-1), m_columns(-1), m_flow(LeftToRight), m_layoutDirection(Qt::LeftToRight)
+    QDeclarativeBasePositioner(Both, parent), m_rows(-1), m_columns(-1), m_flow(LeftToRight)
 {
 }
 
@@ -860,11 +879,11 @@ void QDeclarativeGrid::setFlow(Flow flow)
     Possible values are:
 
     \list
-    \o Qt.LeftToRight (default) - Items are positioned beginning
-    from the top, left anchor. The flow direction is dependent
-    on the \l Grid::flow property.
-    \o Qt.RightToLeft - Items are positioned beginning from the
-    top, right anchor. The flow direction is dependent on the
+    \o Qt.LeftToRight (default) - Items are positioned from the top to bottom,
+    and left to right. The flow direction is dependent on the
+    \l Grid::flow property.
+    \o Qt.RightToLeft - Items are positioned from the top to bottom,
+    and right to left. The flow direction is dependent on the
     \l Grid::flow property.
     \endlist
 
@@ -872,21 +891,39 @@ void QDeclarativeGrid::setFlow(Flow flow)
 */
 Qt::LayoutDirection QDeclarativeGrid::layoutDirection() const
 {
-    return m_layoutDirection;
+    return QDeclarativeBasePositionerPrivate::getLayoutDirection(this);
 }
 
 void QDeclarativeGrid::setLayoutDirection(Qt::LayoutDirection layoutDirection)
 {
-    if (m_layoutDirection != layoutDirection) {
-        m_layoutDirection = layoutDirection;
+    QDeclarativeBasePositionerPrivate *d = static_cast<QDeclarativeBasePositionerPrivate*>(QDeclarativeBasePositionerPrivate::get(this));
+    if (d->layoutDirection != layoutDirection) {
+        d->layoutDirection = layoutDirection;
         prePositioning();
         emit layoutDirectionChanged();
+        emit effectiveLayoutDirectionChanged();
     }
 }
 
-void QDeclarativeGrid::doPositioning(QSizeF *contentSize)
+/*!
+    \qmlproperty enumeration Grid::effectiveLayoutDirection
+    This property holds the effective layout direction of the grid positioner.
+
+    When using the attached property {LayoutMirroring::mirror}{LayoutMirroring::mirror} for locale layouts,
+    the visual layout direction of the grid positioner will be mirrored. However, the
+    property \l {Grid::layoutDirection}{layoutDirection} will remain unchanged.
+
+    \sa Grid::layoutDirection, {LayoutMirroring}{LayoutMirroring}
+*/
+
+Qt::LayoutDirection QDeclarativeGrid::effectiveLayoutDirection() const
 {
+    return QDeclarativeBasePositionerPrivate::getEffectiveLayoutDirection(this);
+}
 
+void QDeclarativeGrid::doPositioning(QSizeF *contentSize)
+{
+    QDeclarativeBasePositionerPrivate *d = static_cast<QDeclarativeBasePositionerPrivate*>(QDeclarativeBasePositionerPrivate::get(this));
     int c = m_columns;
     int r = m_rows;
     //Is allocating the extra QPODVector too much overhead?
@@ -976,7 +1013,7 @@ void QDeclarativeGrid::doPositioning(QSizeF *contentSize)
         end = widthSum;
 
     int xoffset=0;
-    if(m_layoutDirection == Qt::RightToLeft)
+    if(!d->isLeftToRight())
         xoffset=end;
     int yoffset=0;
     int curRow =0;
@@ -984,7 +1021,7 @@ void QDeclarativeGrid::doPositioning(QSizeF *contentSize)
     for (int i = 0; i < visibleItems.count(); ++i) {
         const PositionedItem &child = visibleItems.at(i);
         int childXOffset = xoffset;
-        if(m_layoutDirection == Qt::RightToLeft)
+        if(!d->isLeftToRight())
             childXOffset -= QGraphicsItemPrivate::get(child.item)->width();
         if((child.item->x()!=childXOffset)||(child.item->y()!=yoffset)){
             positionX(childXOffset, child);
@@ -992,7 +1029,7 @@ void QDeclarativeGrid::doPositioning(QSizeF *contentSize)
         }
 
         if (m_flow == LeftToRight) {
-            if(m_layoutDirection == Qt::LeftToRight)
+            if(d->isLeftToRight())
                 xoffset+=maxColWidth[curCol]+spacing();
             else
                 xoffset-=maxColWidth[curCol]+spacing();
@@ -1000,7 +1037,7 @@ void QDeclarativeGrid::doPositioning(QSizeF *contentSize)
             curCol%=c;
             if (!curCol){
                 yoffset+=maxRowHeight[curRow]+spacing();
-                if(m_layoutDirection == Qt::LeftToRight)
+                if(d->isLeftToRight())
                     xoffset=0;
                 else
                     xoffset=end;
@@ -1013,7 +1050,7 @@ void QDeclarativeGrid::doPositioning(QSizeF *contentSize)
             curRow++;
             curRow%=r;
             if (!curRow){
-                if(m_layoutDirection == Qt::LeftToRight)
+                if(d->isLeftToRight())
                     xoffset+=maxColWidth[curCol]+spacing();
                 else
                     xoffset-=maxColWidth[curCol]+spacing();
@@ -1148,12 +1185,10 @@ class QDeclarativeFlowPrivate : public QDeclarativeBasePositionerPrivate
 
 public:
     QDeclarativeFlowPrivate()
-        : QDeclarativeBasePositionerPrivate(), flow(QDeclarativeFlow::LeftToRight),
-            layoutDirection(Qt::LeftToRight)
+        : QDeclarativeBasePositionerPrivate(), flow(QDeclarativeFlow::LeftToRight)
     {}
 
     QDeclarativeFlow::Flow flow;
-    Qt::LayoutDirection layoutDirection;
 };
 
 QDeclarativeFlow::QDeclarativeFlow(QDeclarativeItem *parent)
@@ -1202,11 +1237,11 @@ void QDeclarativeFlow::setFlow(Flow flow)
     Possible values are:
 
     \list
-    \o Qt.LeftToRight (default) - Items are positioned beginning
-    from the top, left anchor. The flow direction is dependent
-    on the \l Flow::flow property.
-    \o Qt.RightToLeft - Items are positioned beginning from the
-    top, right anchor. The flow direction is dependent on the
+    \o Qt.LeftToRight (default) - Items are positioned from the top to bottom,
+    and left to right. The flow direction is dependent on the
+    \l Flow::flow property.
+    \o Qt.RightToLeft - Items are positioned from the top to bottom,
+    and right to left. The flow direction is dependent on the
     \l Flow::flow property.
     \endlist
 
@@ -1226,9 +1261,26 @@ void QDeclarativeFlow::setLayoutDirection(Qt::LayoutDirection layoutDirection)
         d->layoutDirection = layoutDirection;
         prePositioning();
         emit layoutDirectionChanged();
+        emit effectiveLayoutDirectionChanged();
     }
 }
 
+/*!
+    \qmlproperty enumeration Flow::effectiveLayoutDirection
+    This property holds the effective layout direction of the flow positioner.
+
+    When using the attached property {LayoutMirroring::mirror}{LayoutMirroring::mirror} for locale layouts,
+    the visual layout direction of the grid positioner will be mirrored. However, the
+    property \l {Flow::layoutDirection}{layoutDirection} will remain unchanged.
+
+    \sa Flow::layoutDirection, {LayoutMirroring}{LayoutMirroring}
+*/
+
+Qt::LayoutDirection QDeclarativeFlow::effectiveLayoutDirection() const
+{
+    return QDeclarativeBasePositionerPrivate::getEffectiveLayoutDirection(this);
+}
+
 void QDeclarativeFlow::doPositioning(QSizeF *contentSize)
 {
     Q_D(QDeclarativeFlow);
@@ -1258,7 +1310,7 @@ void QDeclarativeFlow::doPositioning(QSizeF *contentSize)
             }
         }
 
-        if(d->layoutDirection == Qt::LeftToRight){
+        if(d->isLeftToRight()){
             if(child.item->x() != hoffset)
                 positionX(hoffset, child);
         }else{
@@ -1281,7 +1333,7 @@ void QDeclarativeFlow::doPositioning(QSizeF *contentSize)
         }
     }
 
-    if(d->layoutDirection == Qt::LeftToRight)
+    if(d->isLeftToRight())
         return;
 
     int end;
diff --git a/src/declarative/graphicsitems/qdeclarativepositioners_p.h b/src/declarative/graphicsitems/qdeclarativepositioners_p.h
index 55d8fa1..214c04f 100644
--- a/src/declarative/graphicsitems/qdeclarativepositioners_p.h
+++ b/src/declarative/graphicsitems/qdeclarativepositioners_p.h
@@ -130,20 +130,22 @@ class Q_AUTOTEST_EXPORT QDeclarativeRow: public QDeclarativeBasePositioner
 {
     Q_OBJECT
     Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged REVISION 1)
+    Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged REVISION 1)
 public:
     QDeclarativeRow(QDeclarativeItem *parent=0);
 
     Qt::LayoutDirection layoutDirection() const;
     void setLayoutDirection (Qt::LayoutDirection);
+    Qt::LayoutDirection effectiveLayoutDirection() const;
 
 Q_SIGNALS:
     Q_REVISION(1) void layoutDirectionChanged();
+    Q_REVISION(1) void effectiveLayoutDirectionChanged();
 
 protected:
     virtual void doPositioning(QSizeF *contentSize);
     virtual void reportConflictingAnchors();
 private:
-    Qt::LayoutDirection m_layoutDirection;
     Q_DISABLE_COPY(QDeclarativeRow)
 };
 
@@ -154,7 +156,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeGrid : public QDeclarativeBasePositioner
     Q_PROPERTY(int columns READ columns WRITE setColumns NOTIFY columnsChanged)
     Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged)
     Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged REVISION 1)
-
+    Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged REVISION 1)
 public:
     QDeclarativeGrid(QDeclarativeItem *parent=0);
 
@@ -171,12 +173,14 @@ public:
 
     Qt::LayoutDirection layoutDirection() const;
     void setLayoutDirection (Qt::LayoutDirection);
+    Qt::LayoutDirection effectiveLayoutDirection() const;
 
 Q_SIGNALS:
     void rowsChanged();
     void columnsChanged();
     void flowChanged();
     Q_REVISION(1) void layoutDirectionChanged();
+    Q_REVISION(1) void effectiveLayoutDirectionChanged();
 
 protected:
     virtual void doPositioning(QSizeF *contentSize);
@@ -186,7 +190,6 @@ private:
     int m_rows;
     int m_columns;
     Flow m_flow;
-    Qt::LayoutDirection m_layoutDirection;
     Q_DISABLE_COPY(QDeclarativeGrid)
 };
 
@@ -194,8 +197,9 @@ class QDeclarativeFlowPrivate;
 class Q_AUTOTEST_EXPORT QDeclarativeFlow: public QDeclarativeBasePositioner
 {
     Q_OBJECT
-    Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged REVISION 1)
     Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged)
+    Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged REVISION 1)
+    Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged REVISION 1)
 public:
     QDeclarativeFlow(QDeclarativeItem *parent=0);
 
@@ -206,10 +210,11 @@ public:
 
     Qt::LayoutDirection layoutDirection() const;
     void setLayoutDirection (Qt::LayoutDirection);
-
+    Qt::LayoutDirection effectiveLayoutDirection() const;
 Q_SIGNALS:
     void flowChanged();
     Q_REVISION(1) void layoutDirectionChanged();
+    Q_REVISION(1) void effectiveLayoutDirectionChanged();
 
 protected:
     virtual void doPositioning(QSizeF *contentSize);
diff --git a/src/declarative/graphicsitems/qdeclarativepositioners_p_p.h b/src/declarative/graphicsitems/qdeclarativepositioners_p_p.h
index df105c6..e80129d 100644
--- a/src/declarative/graphicsitems/qdeclarativepositioners_p_p.h
+++ b/src/declarative/graphicsitems/qdeclarativepositioners_p_p.h
@@ -75,7 +75,7 @@ public:
     QDeclarativeBasePositionerPrivate()
         : spacing(0), type(QDeclarativeBasePositioner::None)
         , moveTransition(0), addTransition(0), queuedPositioning(false)
-        , doingPositioning(false), anchorConflict(false)
+        , doingPositioning(false), anchorConflict(false), layoutDirection(Qt::LeftToRight)
     {
     }
 
@@ -100,6 +100,9 @@ public:
     bool doingPositioning : 1;
     bool anchorConflict : 1;
 
+    Qt::LayoutDirection layoutDirection;
+
+
     void schedulePositioning()
     {
         Q_Q(QDeclarativeBasePositioner);
@@ -109,6 +112,18 @@ public:
         }
     }
 
+    void mirrorChange() {
+        Q_Q(QDeclarativeBasePositioner);
+        if (type != QDeclarativeBasePositioner::Vertical)
+            q->prePositioning();
+    }
+    bool isLeftToRight() const {
+        if (type == QDeclarativeBasePositioner::Vertical)
+            return true;
+        else
+            return effectiveLayoutMirror ? layoutDirection == Qt::RightToLeft : layoutDirection == Qt::LeftToRight;
+    }
+
     virtual void itemSiblingOrderChanged(QDeclarativeItem* other)
     {
         Q_UNUSED(other);
@@ -139,6 +154,19 @@ public:
         Q_Q(QDeclarativeBasePositioner);
         q->positionedItems.removeOne(QDeclarativeBasePositioner::PositionedItem(item));
     }
+
+    static Qt::LayoutDirection getLayoutDirection(const QDeclarativeBasePositioner *positioner)
+    {
+        return positioner->d_func()->layoutDirection;
+    }
+
+    static Qt::LayoutDirection getEffectiveLayoutDirection(const QDeclarativeBasePositioner *positioner)
+    {
+        if (positioner->d_func()->effectiveLayoutMirror)
+            return positioner->d_func()->layoutDirection == Qt::RightToLeft ? Qt::LeftToRight : Qt::RightToLeft;
+        else
+            return positioner->d_func()->layoutDirection;
+    }
 };
 
 QT_END_NAMESPACE
diff --git a/tests/auto/declarative/qdeclarativeanchors/tst_qdeclarativeanchors.cpp b/tests/auto/declarative/qdeclarativeanchors/tst_qdeclarativeanchors.cpp
index 79e233b..0442350 100644
--- a/tests/auto/declarative/qdeclarativeanchors/tst_qdeclarativeanchors.cpp
+++ b/tests/auto/declarative/qdeclarativeanchors/tst_qdeclarativeanchors.cpp
@@ -279,7 +279,7 @@ qreal offsetParentRTL(QDeclarativeItem *rootItem, const char * itemString) {
 
 void mirrorAnchors(QDeclarativeItem *item) {
     QDeclarativeItemPrivate *itemPrivate = QDeclarativeItemPrivate::get(item);
-    itemPrivate->anchors()->setLayoutDirection(Qt::RightToLeft);
+    itemPrivate->setLayoutMirror(true);
 }
 
 void tst_qdeclarativeanchors::basicAnchorsRTL()
@@ -290,9 +290,19 @@ void tst_qdeclarativeanchors::basicAnchorsRTL()
     qApp->processEvents();
 
     QDeclarativeItem* rootItem = qobject_cast<QDeclarativeItem*>(view->rootObject());
+    foreach(QObject *child, rootItem->children()) {
+        bool mirrored = QDeclarativeItemPrivate::get(qobject_cast<QDeclarativeItem*>(child))->anchors()->property("mirrored").toBool();
+        QCOMPARE(mirrored, false);
+    }
+
     foreach(QObject *child, rootItem->children())
         mirrorAnchors(qobject_cast<QDeclarativeItem*>(child));
 
+    foreach(QObject *child, rootItem->children()) {
+        bool mirrored = QDeclarativeItemPrivate::get(qobject_cast<QDeclarativeItem*>(child))->anchors()->property("mirrored").toBool();
+        QCOMPARE(mirrored, true);
+    }
+
     //sibling horizontal
     QCOMPARE(childItem(rootItem, "rect1")->x(), offsetMasterRTL(rootItem, "rect1")-26.0);
     QCOMPARE(childItem(rootItem, "rect2")->x(), offsetMasterRTL(rootItem, "rect2")-122.0);
diff --git a/tests/auto/declarative/qdeclarativegridview/data/gridview-enforcerange.qml b/tests/auto/declarative/qdeclarativegridview/data/gridview-enforcerange.qml
index 164103d..69eaa47 100644
--- a/tests/auto/declarative/qdeclarativegridview/data/gridview-enforcerange.qml
+++ b/tests/auto/declarative/qdeclarativegridview/data/gridview-enforcerange.qml
@@ -1,4 +1,4 @@
-import QtQuick 1.0
+import QtQuick 1.1
 
 Rectangle {
     width: 240
diff --git a/tests/auto/declarative/qdeclarativegridview/data/gridview1.qml b/tests/auto/declarative/qdeclarativegridview/data/gridview1.qml
index 1f5943d..caa28d6 100644
--- a/tests/auto/declarative/qdeclarativegridview/data/gridview1.qml
+++ b/tests/auto/declarative/qdeclarativegridview/data/gridview1.qml
@@ -1,4 +1,4 @@
-import QtQuick 1.0
+import QtQuick 1.1
 
 Rectangle {
     id: root
diff --git a/tests/auto/declarative/qdeclarativegridview/data/mirroring.qml b/tests/auto/declarative/qdeclarativegridview/data/mirroring.qml
new file mode 100644
index 0000000..54de16b
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativegridview/data/mirroring.qml
@@ -0,0 +1,43 @@
+// This example demonstrates how item positioning
+// changes in right-to-left layout direction
+
+import QtQuick 1.1
+
+Rectangle {
+    color: "lightgray"
+    width: 340
+    height: 370
+
+    VisualItemModel {
+        id: itemModel
+        objectName: "itemModel"
+        Rectangle {
+            objectName: "item1"
+            height: 110; width: 120; color: "#FFFEF0"
+            Text { objectName: "text1"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent }
+        }
+        Rectangle {
+            objectName: "item2"
+            height: 130; width: 150; color: "#F0FFF7"
+            Text { objectName: "text2"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent }
+        }
+        Rectangle {
+            objectName: "item3"
+            height: 170; width: 190; color: "#F4F0FF"
+            Text { objectName: "text3"; text: "index: " + parent.VisualItemModel.index; font.bold: true; anchors.centerIn: parent }
+        }
+    }
+
+    GridView {
+        id: view
+        objectName: "view"
+        cellWidth: 190
+        cellHeight: 170
+        anchors.fill: parent
+        anchors.bottomMargin: 30
+        model: itemModel
+        highlightRangeMode: "StrictlyEnforceRange"
+        flow: GridView.TopToBottom
+        flickDeceleration: 2000
+    }
+}
diff --git a/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp b/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp
index 4fcaed6..5ced02b 100644
--- a/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp
+++ b/tests/auto/declarative/qdeclarativegridview/tst_qdeclarativegridview.cpp
@@ -46,6 +46,7 @@
 #include <QtDeclarative/qdeclarativecomponent.h>
 #include <QtDeclarative/qdeclarativecontext.h>
 #include <QtDeclarative/qdeclarativeexpression.h>
+#include <QtDeclarative/private/qdeclarativeitem_p.h>
 #include <QtDeclarative/private/qlistmodelinterface_p.h>
 #include <QtDeclarative/private/qdeclarativegridview_p.h>
 #include <QtDeclarative/private/qdeclarativetext_p.h>
@@ -79,6 +80,7 @@ private slots:
     void modelChanges();
     void positionViewAtIndex();
     void positionViewAtIndex_rightToLeft();
+    void mirroring();
     void snapping();
     void resetModel();
     void enforceRange();
@@ -1347,6 +1349,67 @@ void tst_QDeclarativeGridView::snapping()
 
 }
 
+void tst_QDeclarativeGridView::mirroring()
+{
+    QDeclarativeView *canvasA = createView();
+    canvasA->setSource(QUrl::fromLocalFile(SRCDIR "/data/mirroring.qml"));
+    QDeclarativeGridView *gridviewA = findItem<QDeclarativeGridView>(canvasA->rootObject(), "view");
+    QTRY_VERIFY(gridviewA != 0);
+
+    QDeclarativeView *canvasB = createView();
+    canvasB->setSource(QUrl::fromLocalFile(SRCDIR "/data/mirroring.qml"));
+    QDeclarativeGridView *gridviewB = findItem<QDeclarativeGridView>(canvasB->rootObject(), "view");
+    QTRY_VERIFY(gridviewA != 0);
+    qApp->processEvents();
+
+    QList<QString> objectNames;
+    objectNames << "item1" << "item2"; // << "item3"
+
+    gridviewA->setProperty("layoutDirection", Qt::LeftToRight);
+    gridviewB->setProperty("layoutDirection", Qt::RightToLeft);
+    QCOMPARE(gridviewA->layoutDirection(), gridviewA->effectiveLayoutDirection());
+
+    // LTR != RTL
+    foreach(const QString objectName, objectNames)
+        QVERIFY(findItem<QDeclarativeItem>(gridviewA, objectName)->x() != findItem<QDeclarativeItem>(gridviewB, objectName)->x());
+
+    gridviewA->setProperty("layoutDirection", Qt::LeftToRight);
+    gridviewB->setProperty("layoutDirection", Qt::LeftToRight);
+
+    // LTR == LTR
+    foreach(const QString objectName, objectNames)
+        QCOMPARE(findItem<QDeclarativeItem>(gridviewA, objectName)->x(), findItem<QDeclarativeItem>(gridviewB, objectName)->x());
+
+    QVERIFY(gridviewB->layoutDirection() == gridviewB->effectiveLayoutDirection());
+    QDeclarativeItemPrivate::get(gridviewB)->setLayoutMirror(true);
+    QVERIFY(gridviewB->layoutDirection() != gridviewB->effectiveLayoutDirection());
+
+    // LTR != LTR+mirror
+    foreach(const QString objectName, objectNames)
+        QVERIFY(findItem<QDeclarativeItem>(gridviewA, objectName)->x() != findItem<QDeclarativeItem>(gridviewB, objectName)->x());
+
+    gridviewA->setProperty("layoutDirection", Qt::RightToLeft);
+
+    // RTL == LTR+mirror
+    foreach(const QString objectName, objectNames)
+        QCOMPARE(findItem<QDeclarativeItem>(gridviewA, objectName)->x(), findItem<QDeclarativeItem>(gridviewB, objectName)->x());
+
+    gridviewB->setProperty("layoutDirection", Qt::RightToLeft);
+
+    // RTL != RTL+mirror
+    foreach(const QString objectName, objectNames)
+        QVERIFY(findItem<QDeclarativeItem>(gridviewA, objectName)->x() != findItem<QDeclarativeItem>(gridviewB, objectName)->x());
+
+    gridviewA->setProperty("layoutDirection", Qt::LeftToRight);
+
+    // LTR == RTL+mirror
+    foreach(const QString objectName, objectNames)
+        QCOMPARE(findItem<QDeclarativeItem>(gridviewA, objectName)->x(), findItem<QDeclarativeItem>(gridviewB, objectName)->x());
+
+    delete canvasA;
+    delete canvasB;
+}
+
 void tst_QDeclarativeGridView::positionViewAtIndex_rightToLeft()
 {
     QDeclarativeView *canvas = createView();
@@ -1535,6 +1598,7 @@ void tst_QDeclarativeGridView::enforceRange()
 
     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview-enforcerange.qml"));
     qApp->processEvents();
+    QVERIFY(canvas->rootObject() != 0);
 
     QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid");
     QTRY_VERIFY(gridview != 0);
@@ -1590,6 +1654,7 @@ void tst_QDeclarativeGridView::enforceRange_rightToLeft()
 
     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview-enforcerange.qml"));
     qApp->processEvents();
+    QVERIFY(canvas->rootObject() != 0);
 
     QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid");
     QTRY_VERIFY(gridview != 0);
diff --git a/tests/auto/declarative/qdeclarativeitem/data/layoutmirroring.qml b/tests/auto/declarative/qdeclarativeitem/data/layoutmirroring.qml
new file mode 100644
index 0000000..866b615
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativeitem/data/layoutmirroring.qml
@@ -0,0 +1,54 @@
+import QtQuick 1.1
+
+Item {
+    property bool childrenInherit: true
+    Item {
+        objectName: "mirrored1"
+        LayoutMirroring.enabled: true
+        LayoutMirroring.childrenInherit: parent.childrenInherit
+        Item {
+            Item {
+                objectName: "notMirrored1"
+                LayoutMirroring.enabled: false
+                Item {
+                    objectName: "inheritedMirror1"
+                }
+            }
+            Item {
+                objectName: "inheritedMirror2"
+            }
+        }
+    }
+    Item {
+        objectName: "mirrored2"
+        LayoutMirroring.enabled: true
+        LayoutMirroring.childrenInherit: false
+        Item {
+            objectName: "notMirrored2"
+        }
+    }
+    Item {
+        LayoutMirroring.enabled: true
+        LayoutMirroring.childrenInherit: true
+        Loader {
+            id: loader
+        }
+    }
+    states: State {
+        name: "newContent"
+        PropertyChanges {
+            target: loader
+            sourceComponent: component
+        }
+    }
+    Component {
+        id: component
+        Item {
+            objectName: "notMirrored3"
+            LayoutMirroring.enabled: false
+            Item {
+                objectName: "inheritedMirror3"
+            }
+        }
+    }
+}
diff --git a/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp b/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp
index 137522d..f83207c 100644
--- a/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp
+++ b/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp
@@ -66,6 +66,8 @@ private slots:
     void keysProcessingOrder();
     void keyNavigation();
     void keyNavigation_skipNotVisible();
+    void layoutMirroring();
+    void layoutMirroringIllegalParent();
     void smooth();
     void clip();
     void mapCoordinates();
@@ -87,13 +89,33 @@ private slots:
     void testQtQuick11Attributes();
     void testQtQuick11Attributes_data();
     void qtbug_16871();
-
 private:
-    template<typename T>
-    T *findItem(QGraphicsObject *parent, const QString &objectName);
     QDeclarativeEngine engine;
 };
 
+template<typename T>
+T *findItem(QGraphicsObject *parent, const QString &objectName)
+{
+    if (!parent)
+        return 0;
+
+    const QMetaObject &mo = T::staticMetaObject;
+    //qDebug() << parent->QGraphicsObject::children().count() << "children";
+    for (int i = 0; i < parent->childItems().count(); ++i) {
+        QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(parent->childItems().at(i));
+        if(!item)
+            continue;
+        //qDebug() << "try" << item;
+        if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName))
+            return static_cast<T*>(item);
+        item = findItem<T>(item, objectName);
+        if (item)
+            return static_cast<T*>(item);
+    }
+
+    return 0;
+}
+
 class KeysTestObject : public QObject
 {
     Q_OBJECT
@@ -380,6 +402,132 @@ void tst_QDeclarativeItem::keysProcessingOrder()
     delete testObject;
 }
 
+QDeclarativeItemPrivate *childPrivate(QGraphicsObject *rootItem, const char * itemString)
+{
+    QDeclarativeItem *item = findItem<QDeclarativeItem>(rootItem, QString(QLatin1String(itemString)));
+    QDeclarativeItemPrivate* itemPrivate = QDeclarativeItemPrivate::get(item);
+    return itemPrivate;
+}
+
+QVariant childProperty(QGraphicsObject *rootItem, const char * itemString, const char * property)
+{
+    QDeclarativeItem *item = findItem<QDeclarativeItem>(rootItem, QString(QLatin1String(itemString)));
+    return item->property(property);
+}
+
+bool anchorsMirrored(QGraphicsObject *rootItem, const char * itemString)
+{
+    QDeclarativeItem *item = findItem<QDeclarativeItem>(rootItem, QString(QLatin1String(itemString)));
+    QDeclarativeItemPrivate* itemPrivate = QDeclarativeItemPrivate::get(item);
+    return itemPrivate->anchors()->mirrored();
+}
+
+void tst_QDeclarativeItem::layoutMirroring()
+{
+    QDeclarativeView *canvas = new QDeclarativeView(0);
+    canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/layoutmirroring.qml"));
+    canvas->show();
+
+    QDeclarativeItem *rootItem = qobject_cast<QDeclarativeItem*>(canvas->rootObject());
+    QVERIFY(rootItem);
+    QDeclarativeItemPrivate *rootPrivate = QDeclarativeItemPrivate::get(rootItem);
+    QVERIFY(rootPrivate);
+
+    QCOMPARE(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror, true);
+    QCOMPARE(childPrivate(rootItem, "mirrored2")->effectiveLayoutMirror, true);
+    QCOMPARE(childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror, false);
+    QCOMPARE(childPrivate(rootItem, "notMirrored2")->effectiveLayoutMirror, false);
+    QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror, true);
+    QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror, true);
+
+    QCOMPARE(anchorsMirrored(rootItem, "mirrored1"), true);
+    QCOMPARE(anchorsMirrored(rootItem, "mirrored2"), true);
+    QCOMPARE(anchorsMirrored(rootItem, "notMirrored1"), false);
+    QCOMPARE(anchorsMirrored(rootItem, "notMirrored2"), false);
+    QCOMPARE(anchorsMirrored(rootItem, "inheritedMirror1"), true);
+    QCOMPARE(anchorsMirrored(rootItem, "inheritedMirror2"), true);
+
+    QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror, true);
+    QCOMPARE(childPrivate(rootItem, "mirrored2")->inheritedLayoutMirror, false);
+    QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror, true);
+    QCOMPARE(childPrivate(rootItem, "notMirrored2")->inheritedLayoutMirror, false);
+    QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror, true);
+    QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror, true);
+
+    QCOMPARE(childPrivate(rootItem, "mirrored1")->isMirrorImplicit, false);
+    QCOMPARE(childPrivate(rootItem, "mirrored2")->isMirrorImplicit, false);
+    QCOMPARE(childPrivate(rootItem, "notMirrored1")->isMirrorImplicit, false);
+    QCOMPARE(childPrivate(rootItem, "notMirrored2")->isMirrorImplicit, true);
+    QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->isMirrorImplicit, true);
+    QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->isMirrorImplicit, true);
+
+    QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritMirrorFromParent, true);
+    QCOMPARE(childPrivate(rootItem, "mirrored2")->inheritMirrorFromParent, false);
+    QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritMirrorFromParent, true);
+    QCOMPARE(childPrivate(rootItem, "notMirrored2")->inheritMirrorFromParent, false);
+    QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritMirrorFromParent, true);
+    QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritMirrorFromParent, true);
+
+    QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritMirrorFromItem, true);
+    QCOMPARE(childPrivate(rootItem, "mirrored2")->inheritMirrorFromItem, false);
+    QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritMirrorFromItem, false);
+    QCOMPARE(childPrivate(rootItem, "notMirrored2")->inheritMirrorFromItem, false);
+    QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritMirrorFromItem, false);
+    QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritMirrorFromItem, false);
+
+    // load dynamic content using Loader that needs to inherit mirroring
+    rootItem->setProperty("state", "newContent");
+    QCOMPARE(childPrivate(rootItem, "notMirrored3")->effectiveLayoutMirror, false);
+    QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->effectiveLayoutMirror, true);
+
+    QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritedLayoutMirror, true);
+    QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->inheritedLayoutMirror, true);
+
+    QCOMPARE(childPrivate(rootItem, "notMirrored3")->isMirrorImplicit, false);
+    QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->isMirrorImplicit, true);
+
+    QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromParent, true);
+    QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->inheritMirrorFromParent, true);
+
+    QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromItem, false);
+    QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromItem, false);
+
+    // disable inheritance
+    rootItem->setProperty("childrenInherit", false);
+
+    QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror, false);
+    QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror, false);
+    QCOMPARE(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror, true);
+    QCOMPARE(childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror, false);
+
+    QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror, false);
+    QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror, false);
+    QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror, false);
+    QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror, false);
+
+    // re-enable inheritance
+    rootItem->setProperty("childrenInherit", true);
+
+    QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror, true);
+    QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror, true);
+    QCOMPARE(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror, true);
+    QCOMPARE(childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror, false);
+
+    QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror, true);
+    QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror, true);
+    QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror, true);
+    QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror, true);
+}
+
+void tst_QDeclarativeItem::layoutMirroringIllegalParent()
+{
+    QDeclarativeComponent component(&engine);
+    component.setData("import QtQuick 1.1; QtObject { LayoutMirroring.enabled: true; LayoutMirroring.childrenInherit: true }", QUrl::fromLocalFile(""));
+    QTest::ignoreMessage(QtWarningMsg, "file::1:21: QML QtObject: LayoutDirection attached property only works with Items");
+    QObject *object = component.create();
+    QVERIFY(object != 0);
+}
+
 void tst_QDeclarativeItem::keyNavigation()
 {
     QDeclarativeView *canvas = new QDeclarativeView(0);
@@ -1003,32 +1151,6 @@ void tst_QDeclarativeItem::qtbug_16871()
     delete o;
 }
 
-
-template<typename T>
-T *tst_QDeclarativeItem::findItem(QGraphicsObject *parent, const QString &objectName)
-{
-    if (!parent)
-        return 0;
-
-    const QMetaObject &mo = T::staticMetaObject;
-    //qDebug() << parent->QGraphicsObject::children().count() << "children";
-    for (int i = 0; i < parent->childItems().count(); ++i) {
-        QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(parent->childItems().at(i));
-        if(!item)
-            continue;
-        //qDebug() << "try" << item;
-        if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName))
-            return static_cast<T*>(item);
-        item = findItem<T>(item, objectName);
-        if (item)
-            return static_cast<T*>(item);
-    }
-
-    return 0;
-}
-
-
-
 QTEST_MAIN(tst_QDeclarativeItem)
 
 #include "tst_qdeclarativeitem.moc"
diff --git a/tests/auto/declarative/qdeclarativelistview/data/rightToLeft.qml b/tests/auto/declarative/qdeclarativelistview/data/rightToLeft.qml
index e31d923..1e92bb3 100644
--- a/tests/auto/declarative/qdeclarativelistview/data/rightToLeft.qml
+++ b/tests/auto/declarative/qdeclarativelistview/data/rightToLeft.qml
@@ -1,11 +1,11 @@
-// This example demonstrates placing items in a view using
-// a VisualItemModel
+// This example demonstrates how item positioning
+// changes in right-to-left layout direction
 
-import QtQuick 1.0
+import QtQuick 1.1
 
 Rectangle {
     color: "lightgray"
-    width: 240
+    width: 640
     height: 320
 
     VisualItemModel {
diff --git a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp
index 02c8dad..bba86c3 100644
--- a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp
+++ b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp
@@ -45,6 +45,7 @@
 #include <QtDeclarative/qdeclarativeengine.h>
 #include <QtDeclarative/qdeclarativecontext.h>
 #include <QtDeclarative/qdeclarativeexpression.h>
+#include <QtDeclarative/private/qdeclarativeitem_p.h>
 #include <QtDeclarative/private/qdeclarativelistview_p.h>
 #include <QtDeclarative/private/qdeclarativetext_p.h>
 #include <QtDeclarative/private/qdeclarativevisualitemmodel_p.h>
@@ -116,6 +117,7 @@ private slots:
     void testQtQuick11Attributes();
     void testQtQuick11Attributes_data();
     void rightToLeft();
+    void test_mirroring();
 
 private:
     template <class T> void items();
@@ -1697,8 +1699,6 @@ void tst_QDeclarativeListView::manualHighlight()
     QDeclarativeView *canvas = new QDeclarativeView(0);
     canvas->setFixedSize(240,320);
 
-    QDeclarativeContext *ctxt = canvas->rootContext();
-
     QString filename(SRCDIR "/data/manual-highlight.qml");
     canvas->setSource(QUrl::fromLocalFile(filename));
 
@@ -1829,8 +1829,6 @@ void tst_QDeclarativeListView::header()
 
         TestModel model;
 
-        QDeclarativeContext *ctxt = canvas->rootContext();
-
         canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/header1.qml"));
         qApp->processEvents();
 
@@ -2303,10 +2301,10 @@ void tst_QDeclarativeListView::testQtQuick11Attributes_data()
 void tst_QDeclarativeListView::rightToLeft()
 {
     QDeclarativeView *canvas = createView();
-
     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/rightToLeft.qml"));
     qApp->processEvents();
 
+    QVERIFY(canvas->rootObject() != 0);
     QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "view");
     QTRY_VERIFY(listview != 0);
 
@@ -2341,6 +2339,67 @@ void tst_QDeclarativeListView::rightToLeft()
     delete canvas;
 }
 
+void tst_QDeclarativeListView::test_mirroring()
+{
+    QDeclarativeView *canvasA = createView();
+    canvasA->setSource(QUrl::fromLocalFile(SRCDIR "/data/rightToLeft.qml"));
+    QDeclarativeListView *listviewA = findItem<QDeclarativeListView>(canvasA->rootObject(), "view");
+    QTRY_VERIFY(listviewA != 0);
+
+    QDeclarativeView *canvasB = createView();
+    canvasB->setSource(QUrl::fromLocalFile(SRCDIR "/data/rightToLeft.qml"));
+    QDeclarativeListView *listviewB = findItem<QDeclarativeListView>(canvasB->rootObject(), "view");
+    QTRY_VERIFY(listviewA != 0);
+    qApp->processEvents();
+
+    QList<QString> objectNames;
+    objectNames << "item1" << "item2"; // << "item3"
+
+    listviewA->setProperty("layoutDirection", Qt::LeftToRight);
+    listviewB->setProperty("layoutDirection", Qt::RightToLeft);
+    QCOMPARE(listviewA->layoutDirection(), listviewA->effectiveLayoutDirection());
+
+    // LTR != RTL
+    foreach(const QString objectName, objectNames)
+        QVERIFY(findItem<QDeclarativeItem>(listviewA, objectName)->x() != findItem<QDeclarativeItem>(listviewB, objectName)->x());
+
+    listviewA->setProperty("layoutDirection", Qt::LeftToRight);
+    listviewB->setProperty("layoutDirection", Qt::LeftToRight);
+
+    // LTR == LTR
+    foreach(const QString objectName, objectNames)
+        QCOMPARE(findItem<QDeclarativeItem>(listviewA, objectName)->x(), findItem<QDeclarativeItem>(listviewB, objectName)->x());
+
+    QVERIFY(listviewB->layoutDirection() == listviewB->effectiveLayoutDirection());
+    QDeclarativeItemPrivate::get(listviewB)->setLayoutMirror(true);
+    QVERIFY(listviewB->layoutDirection() != listviewB->effectiveLayoutDirection());
+
+    // LTR != LTR+mirror
+    foreach(const QString objectName, objectNames)
+        QVERIFY(findItem<QDeclarativeItem>(listviewA, objectName)->x() != findItem<QDeclarativeItem>(listviewB, objectName)->x());
+
+    listviewA->setProperty("layoutDirection", Qt::RightToLeft);
+
+    // RTL == LTR+mirror
+    foreach(const QString objectName, objectNames)
+        QCOMPARE(findItem<QDeclarativeItem>(listviewA, objectName)->x(), findItem<QDeclarativeItem>(listviewB, objectName)->x());
+
+    listviewB->setProperty("layoutDirection", Qt::RightToLeft);
+
+    // RTL != RTL+mirror
+    foreach(const QString objectName, objectNames)
+        QVERIFY(findItem<QDeclarativeItem>(listviewA, objectName)->x() != findItem<QDeclarativeItem>(listviewB, objectName)->x());
+
+    listviewA->setProperty("layoutDirection", Qt::LeftToRight);
+
+    // LTR == RTL+mirror
+    foreach(const QString objectName, objectNames)
+        QCOMPARE(findItem<QDeclarativeItem>(listviewA, objectName)->x(), findItem<QDeclarativeItem>(listviewB, objectName)->x());
+
+    delete canvasA;
+    delete canvasB;
+}
+
 void tst_QDeclarativeListView::qListModelInterface_items()
 {
     items<TestModel>();
diff --git a/tests/auto/declarative/qdeclarativepositioners/data/grid-righttoleft.qml b/tests/auto/declarative/qdeclarativepositioners/data/grid-righttoleft.qml
deleted file mode 100644
index 0ec1f37..0000000
--- a/tests/auto/declarative/qdeclarativepositioners/data/grid-righttoleft.qml
+++ /dev/null
@@ -1,41 +0,0 @@
-import QtQuick 1.1
-
-Item {
-    width: 640
-    height: 480
-    Grid {
-        objectName: "grid"
-        columns: 3
-        layoutDirection: Qt.RightToLeft
-        Rectangle {
-            objectName: "one"
-            color: "red"
-            width: 50
-            height: 50
-        }
-        Rectangle {
-            objectName: "two"
-            color: "green"
-            width: 20
-            height: 50
-        }
-        Rectangle {
-            objectName: "three"
-            color: "blue"
-            width: 50
-            height: 20
-        }
-        Rectangle {
-            objectName: "four"
-            color: "cyan"
-            width: 50
-            height: 50
-        }
-        Rectangle {
-            objectName: "five"
-            color: "magenta"
-            width: 10
-            height: 10
-        }
-    }
-}
diff --git a/tests/auto/declarative/qdeclarativepositioners/data/gridtest.qml b/tests/auto/declarative/qdeclarativepositioners/data/gridtest.qml
index f3b17dd..929b726 100644
--- a/tests/auto/declarative/qdeclarativepositioners/data/gridtest.qml
+++ b/tests/auto/declarative/qdeclarativepositioners/data/gridtest.qml
@@ -1,9 +1,11 @@
-import QtQuick 1.0
+import QtQuick 1.1
 
 Item {
     width: 640
     height: 480
+    property bool testRightToLeft: false
     Grid {
+        layoutDirection: testRightToLeft ? Qt.RightToLeft : Qt.LeftToRight
         objectName: "grid"
         columns: 3
         Rectangle {
@@ -21,7 +23,7 @@ Item {
         Rectangle {
             objectName: "three"
             color: "blue"
-            width: 50
+            width: 30
             height: 20
         }
         Rectangle {
diff --git a/tests/auto/declarative/qdeclarativepositioners/data/horizontal.qml b/tests/auto/declarative/qdeclarativepositioners/data/horizontal.qml
index e1a9652..d35c02d 100644
--- a/tests/auto/declarative/qdeclarativepositioners/data/horizontal.qml
+++ b/tests/auto/declarative/qdeclarativepositioners/data/horizontal.qml
@@ -4,7 +4,6 @@ Item {
     width: 640
     height: 480
     property bool testRightToLeft: false
-
     Row {
         objectName: "row"
         layoutDirection: testRightToLeft ? Qt.RightToLeft : Qt.LeftToRight
diff --git a/tests/auto/declarative/qdeclarativepositioners/tst_qdeclarativepositioners.cpp b/tests/auto/declarative/qdeclarativepositioners/tst_qdeclarativepositioners.cpp
index 40e533d..92ab722 100644
--- a/tests/auto/declarative/qdeclarativepositioners/tst_qdeclarativepositioners.cpp
+++ b/tests/auto/declarative/qdeclarativepositioners/tst_qdeclarativepositioners.cpp
@@ -45,6 +45,7 @@
 #include <private/qdeclarativerectangle_p.h>
 #include <private/qdeclarativepositioners_p.h>
 #include <private/qdeclarativetransition_p.h>
+#include <private/qdeclarativeitem_p.h>
 #include <qdeclarativeexpression.h>
 #include <QtGui/qgraphicswidget.h>
 #include "../../../shared/util.h"
@@ -87,6 +88,7 @@ private slots:
     void test_flow_implicit_resize();
     void test_conflictinganchors();
     void test_vertical_qgraphicswidget();
+    void test_mirroring();
     void testQtQuick11Attributes();
     void testQtQuick11Attributes_data();
 private:
@@ -452,7 +454,7 @@ void tst_QDeclarativePositioners::test_grid()
 
     QDeclarativeGrid *grid = canvas->rootObject()->findChild<QDeclarativeGrid*>("grid");
     QCOMPARE(grid->flow(), QDeclarativeGrid::LeftToRight);
-    QCOMPARE(grid->width(), 120.0);
+    QCOMPARE(grid->width(), 100.0);
     QCOMPARE(grid->height(), 100.0);
 
     delete canvas;
@@ -494,7 +496,9 @@ void tst_QDeclarativePositioners::test_grid_topToBottom()
 
 void tst_QDeclarativePositioners::test_grid_rightToLeft()
 {
-    QDeclarativeView *canvas = createView(SRCDIR "/data/grid-righttoleft.qml");
+    QDeclarativeView *canvas = createView(SRCDIR "/data/gridtest.qml");
+
+    canvas->rootObject()->setProperty("testRightToLeft", true);
 
     QDeclarativeRectangle *one = canvas->rootObject()->findChild<QDeclarativeRectangle*>("one");
     QVERIFY(one != 0);
@@ -507,20 +511,20 @@ void tst_QDeclarativePositioners::test_grid_rightToLeft()
     QDeclarativeRectangle *five = canvas->rootObject()->findChild<QDeclarativeRectangle*>("five");
     QVERIFY(five != 0);
 
-    QCOMPARE(one->x(), 70.0);
+    QCOMPARE(one->x(), 50.0);
     QCOMPARE(one->y(), 0.0);
-    QCOMPARE(two->x(), 50.0);
+    QCOMPARE(two->x(), 30.0);
     QCOMPARE(two->y(), 0.0);
     QCOMPARE(three->x(), 0.0);
     QCOMPARE(three->y(), 0.0);
-    QCOMPARE(four->x(), 70.0);
+    QCOMPARE(four->x(), 50.0);
     QCOMPARE(four->y(), 50.0);
-    QCOMPARE(five->x(), 60.0);
+    QCOMPARE(five->x(), 40.0);
     QCOMPARE(five->y(), 50.0);
 
     QDeclarativeGrid *grid = canvas->rootObject()->findChild<QDeclarativeGrid*>("grid");
     QCOMPARE(grid->layoutDirection(), Qt::RightToLeft);
-    QCOMPARE(grid->width(), 120.0);
+    QCOMPARE(grid->width(), 100.0);
     QCOMPARE(grid->height(), 100.0);
 
     delete canvas;
@@ -1198,6 +1202,66 @@ void tst_QDeclarativePositioners::test_vertical_qgraphicswidget()
     delete canvas;
 }
 
+void tst_QDeclarativePositioners::test_mirroring()
+{
+    QList<QString> qmlFiles;
+    qmlFiles << "horizontal.qml" << "gridtest.qml" << "flowtest.qml";
+    QList<QString> objectNames;
+    objectNames << "one" << "two" << "three" << "four" << "five";
+
+    foreach(const QString qmlFile, qmlFiles) {
+        QDeclarativeView *canvasA = createView(QString(SRCDIR) + "/data/" + qmlFile);
+        QDeclarativeItem *rootA = qobject_cast<QDeclarativeItem*>(canvasA->rootObject());
+
+        QDeclarativeView *canvasB = createView(QString(SRCDIR) + "/data/" + qmlFile);
+        QDeclarativeItem *rootB = qobject_cast<QDeclarativeItem*>(canvasB->rootObject());
+
+        rootA->setProperty("testRightToLeft", true); // layoutDirection: Qt.RightToLeft
+
+        // LTR != RTL
+        foreach(const QString objectName, objectNames) {
+            // horizontal.qml only has three items
+            if (qmlFile == QString("horizontal.qml") && objectName == QString("four"))
+                break;
+            QDeclarativeItem *itemA = rootA->findChild<QDeclarativeItem*>(objectName);
+            QDeclarativeItem *itemB = rootB->findChild<QDeclarativeItem*>(objectName);
+            QVERIFY(itemA->x() != itemB->x());
+        }
+
+        QDeclarativeItemPrivate* rootPrivateB = QDeclarativeItemPrivate::get(rootB);
+
+        rootPrivateB->effectiveLayoutMirror = true; // LayoutMirroring.enabled: true
+        rootPrivateB->isMirrorImplicit = false;
+        rootPrivateB->inheritMirrorFromItem = true; // LayoutMirroring.childrenInherit: true
+        rootPrivateB->resolveLayoutMirror();
+
+        // RTL == mirror
+        foreach(const QString objectName, objectNames) {
+            // horizontal.qml only has three items
+            if (qmlFile == QString("horizontal.qml") && objectName == QString("four"))
+                break;
+            QDeclarativeItem *itemA = rootA->findChild<QDeclarativeItem*>(objectName);
+            QDeclarativeItem *itemB = rootB->findChild<QDeclarativeItem*>(objectName);
+            QCOMPARE(itemA->x(), itemB->x());
+        }
+
+        rootA->setProperty("testRightToLeft", false); // layoutDirection: Qt.LeftToRight
+        rootB->setProperty("testRightToLeft", true); // layoutDirection: Qt.RightToLeft
+
+        // LTR == RTL + mirror
+        foreach(const QString objectName, objectNames) {
+            // horizontal.qml only has three items
+            if (qmlFile == QString("horizontal.qml") && objectName == QString("four"))
+                break;
+            QDeclarativeItem *itemA = rootA->findChild<QDeclarativeItem*>(objectName);
+            QDeclarativeItem *itemB = rootB->findChild<QDeclarativeItem*>(objectName);
+            QCOMPARE(itemA->x(), itemB->x());
+        }
+        delete canvasA;
+        delete canvasB;
+    }
+}
+
 void tst_QDeclarativePositioners::testQtQuick11Attributes()
 {
     QFETCH(QString, code);
diff --git a/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp b/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp
index 2220b6d..20e2640 100644
--- a/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp
+++ b/tests/auto/declarative/qdeclarativestates/tst_qdeclarativestates.cpp
@@ -818,7 +818,7 @@ void tst_qdeclarativestates::anchorChanges5()
 
 void mirrorAnchors(QDeclarativeItem *item) {
     QDeclarativeItemPrivate *itemPrivate = QDeclarativeItemPrivate::get(item);
-    itemPrivate->anchors()->setLayoutDirection(Qt::RightToLeft);
+    itemPrivate->setLayoutMirror(true);
 }
 
 qreal offsetRTL(QDeclarativeItem *anchorItem, QDeclarativeItem *item) {
-- 
cgit v0.12