diff options
author | Joona Petrell <joona.t.petrell@nokia.com> | 2011-02-24 02:33:11 (GMT) |
---|---|---|
committer | Joona Petrell <joona.t.petrell@nokia.com> | 2011-03-01 07:17:41 (GMT) |
commit | 2c7cab4172f1acc86fd49345a2847417e162f2c3 (patch) | |
tree | 2df2e2bfccd17ed94980db0221ed3aec83afccb2 /src | |
parent | a4b37abd96860a5bc46f88205bb11706cbaec228 (diff) | |
download | Qt-2c7cab4172f1acc86fd49345a2847417e162f2c3.zip Qt-2c7cab4172f1acc86fd49345a2847417e162f2c3.tar.gz Qt-2c7cab4172f1acc86fd49345a2847417e162f2c3.tar.bz2 |
Add LayoutMirroring attached property for mirroring QML layouts
Task-number: QTBUG-17280
Reviewed-by: Martin Jones
Change-Id: I34a623b49ce0fd5c05ae7a7ea5d0437c107b8a9b
Diffstat (limited to 'src')
13 files changed, 472 insertions, 122 deletions
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 |