summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Jones <martin.jones@nokia.com>2011-03-11 02:39:04 (GMT)
committerMartin Jones <martin.jones@nokia.com>2011-03-11 03:36:38 (GMT)
commit68415b0bcc3e531dc16516aa6788aeef8bced6f2 (patch)
tree28c05887fd6889545b47618121f89070c2b1c61b
parentc7787f7df7a507d29b49f66b430e251d1a879ccd (diff)
downloadQt-68415b0bcc3e531dc16516aa6788aeef8bced6f2.zip
Qt-68415b0bcc3e531dc16516aa6788aeef8bced6f2.tar.gz
Qt-68415b0bcc3e531dc16516aa6788aeef8bced6f2.tar.bz2
Fix ListView boundary extents for RTL layout.
The delegates were laid out RTL, but the first item was not aligned with the right edge. Also fixes QTBUG-18037. Change-Id: I6387c2f1ad37385376304f8cc76407b34d9fb834 Task-number: QTBUG-16010 Reviewed-by: Joona Petrell
-rw-r--r--src/declarative/graphicsitems/qdeclarativelistview.cpp48
-rw-r--r--tests/auto/declarative/qdeclarativelistview/data/headerfooter.qml26
-rw-r--r--tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp117
3 files changed, 182 insertions, 9 deletions
diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp
index f9f1a48..2c23a1b 100644
--- a/src/declarative/graphicsitems/qdeclarativelistview.cpp
+++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp
@@ -272,6 +272,22 @@ public:
void regenerate() {
Q_Q(QDeclarativeListView);
if (q->isComponentComplete()) {
+ if (header) {
+ if (q->scene())
+ q->scene()->removeItem(header->item);
+ header->item->deleteLater();
+ delete header;
+ header = 0;
+ }
+ if (footer) {
+ if (q->scene())
+ q->scene()->removeItem(footer->item);
+ footer->item->deleteLater();
+ delete footer;
+ footer = 0;
+ }
+ updateHeader();
+ updateFooter();
clear();
setPosition(0);
q->refill();
@@ -2633,7 +2649,8 @@ qreal QDeclarativeListView::maxYExtent() const
return height();
if (d->maxExtentDirty) {
if (!d->model || !d->model->count()) {
- d->maxExtent = 0;
+ d->maxExtent = d->header ? -d->header->size() : 0;
+ d->maxExtent += height();
} else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
d->maxExtent = -(d->positionAt(d->model->count()-1) - d->highlightRangeStart);
if (d->highlightRangeEnd != d->highlightRangeStart)
@@ -2661,21 +2678,26 @@ qreal QDeclarativeListView::minXExtent() const
qreal highlightStart;
qreal highlightEnd;
- qreal endPositionFirstItem;
+ qreal endPositionFirstItem = 0;
if (d->isRightToLeft()) {
if (d->model && d->model->count())
endPositionFirstItem = d->positionAt(d->model->count()-1);
+ else if (d->header)
+ d->minExtent += d->header->size();
highlightStart = d->highlightRangeStartValid
? d->highlightRangeStart - (d->lastPosition()-endPositionFirstItem)
: d->size() - (d->lastPosition()-endPositionFirstItem);
highlightEnd = d->highlightRangeEndValid ? d->highlightRangeEnd : d->size();
if (d->footer)
d->minExtent += d->footer->size();
+ qreal maxX = maxXExtent();
+ if (d->minExtent < maxX)
+ d->minExtent = maxX;
} else {
endPositionFirstItem = d->endPositionAt(0);
highlightStart = d->highlightRangeStart;
highlightEnd = d->highlightRangeEnd;
- if (d->header)
+ if (d->header && d->visibleItems.count())
d->minExtent += d->header->size();
}
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
@@ -2696,7 +2718,8 @@ qreal QDeclarativeListView::maxXExtent() const
if (d->maxExtentDirty) {
qreal highlightStart;
qreal highlightEnd;
- qreal lastItemPosition;
+ qreal lastItemPosition = 0;
+ d->maxExtent = 0;
if (d->isRightToLeft()) {
highlightStart = d->highlightRangeStartValid ? d->highlightRangeEnd : d->size();
highlightEnd = d->highlightRangeEndValid ? d->highlightRangeStart : d->size();
@@ -2708,7 +2731,9 @@ qreal QDeclarativeListView::maxXExtent() const
lastItemPosition = d->positionAt(d->model->count()-1);
}
if (!d->model || !d->model->count()) {
- d->maxExtent = 0;
+ if (!d->isRightToLeft())
+ d->maxExtent = d->header ? -d->header->size() : 0;
+ d->maxExtent += width();
} else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
d->maxExtent = -(lastItemPosition - highlightStart);
if (highlightEnd != highlightStart) {
@@ -2720,15 +2745,15 @@ qreal QDeclarativeListView::maxXExtent() const
d->maxExtent = -(d->endPosition() - width() + 1);
}
if (d->isRightToLeft()) {
- if (d->header)
+ if (d->header && d->visibleItems.count())
d->maxExtent -= d->header->size();
} else {
if (d->footer)
d->maxExtent -= d->footer->size();
+ qreal minX = minXExtent();
+ if (d->maxExtent > minX)
+ d->maxExtent = minX;
}
- qreal minX = minXExtent();
- if (d->maxExtent > minX)
- d->maxExtent = minX;
d->maxExtentDirty = false;
}
return d->maxExtent;
@@ -2776,6 +2801,11 @@ void QDeclarativeListView::geometryChanged(const QRectF &newGeometry,
Q_D(QDeclarativeListView);
d->maxExtentDirty = true;
d->minExtentDirty = true;
+ if (d->isRightToLeft() && d->orient == Qt::Horizontal) {
+ // maintain position relative to the right edge
+ int dx = newGeometry.width() - oldGeometry.width();
+ setContentX(contentX() - dx);
+ }
QDeclarativeFlickable::geometryChanged(newGeometry, oldGeometry);
}
diff --git a/tests/auto/declarative/qdeclarativelistview/data/headerfooter.qml b/tests/auto/declarative/qdeclarativelistview/data/headerfooter.qml
new file mode 100644
index 0000000..5633831
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativelistview/data/headerfooter.qml
@@ -0,0 +1,26 @@
+import QtQuick 1.1
+
+ListView {
+ id: view
+ property bool horizontal: false
+ property bool rtl: false
+ width: 240
+ height: 320
+
+ orientation: horizontal ? ListView.Horizontal : ListView.Vertical
+ header: Rectangle {
+ objectName: "header"
+ width: horizontal ? 20 : view.width
+ height: horizontal ? view.height : 20
+ color: "red"
+ }
+ footer: Rectangle {
+ objectName: "footer"
+ width: horizontal ? 30 : view.width
+ height: horizontal ? view.height : 30
+ color: "blue"
+ }
+// model: testModel
+ delegate: Text { width: 30; height: 30; text: index + "(" + x + ")" }
+ layoutDirection: rtl ? Qt.RightToLeft : Qt.LeftToRight
+}
diff --git a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp
index a699bbe..c87318e 100644
--- a/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp
+++ b/tests/auto/declarative/qdeclarativelistview/tst_qdeclarativelistview.cpp
@@ -103,6 +103,7 @@ private slots:
void QTBUG_11105();
void header();
void footer();
+ void headerFooter();
void resizeView();
void sizeLessThan1();
void QTBUG_14821();
@@ -1958,6 +1959,112 @@ void tst_QDeclarativeListView::footer()
delete canvas;
}
+class LVAccessor : public QDeclarativeListView
+{
+public:
+ qreal minY() const { return minYExtent(); }
+ qreal maxY() const { return maxYExtent(); }
+ qreal minX() const { return minXExtent(); }
+ qreal maxX() const { return maxXExtent(); }
+};
+
+void tst_QDeclarativeListView::headerFooter()
+{
+ {
+ // Vertical
+ QDeclarativeView *canvas = createView();
+
+ TestModel model;
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/headerfooter.qml"));
+ qApp->processEvents();
+
+ QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(canvas->rootObject());
+ QTRY_VERIFY(listview != 0);
+
+ QDeclarativeItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QDeclarativeItem *header = findItem<QDeclarativeItem>(contentItem, "header");
+ QVERIFY(header);
+ QCOMPARE(header->y(), 0.0);
+
+ QDeclarativeItem *footer = findItem<QDeclarativeItem>(contentItem, "footer");
+ QVERIFY(footer);
+ QCOMPARE(footer->y(), 20.0);
+
+ QVERIFY(static_cast<LVAccessor*>(listview)->minY() == 0);
+ QVERIFY(static_cast<LVAccessor*>(listview)->maxY() == 0);
+
+ delete canvas;
+ }
+ {
+ // Horizontal
+ QDeclarativeView *canvas = createView();
+
+ TestModel model;
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/headerfooter.qml"));
+ canvas->rootObject()->setProperty("horizontal", true);
+ qApp->processEvents();
+
+ QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(canvas->rootObject());
+ QTRY_VERIFY(listview != 0);
+
+ QDeclarativeItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QDeclarativeItem *header = findItem<QDeclarativeItem>(contentItem, "header");
+ QVERIFY(header);
+ QCOMPARE(header->x(), 0.0);
+
+ QDeclarativeItem *footer = findItem<QDeclarativeItem>(contentItem, "footer");
+ QVERIFY(footer);
+ QCOMPARE(footer->x(), 20.0);
+
+ QVERIFY(static_cast<LVAccessor*>(listview)->minX() == 0);
+ QVERIFY(static_cast<LVAccessor*>(listview)->maxX() == 0);
+
+ delete canvas;
+ }
+ {
+ // Horizontal RTL
+ QDeclarativeView *canvas = createView();
+
+ TestModel model;
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/headerfooter.qml"));
+ canvas->rootObject()->setProperty("horizontal", true);
+ canvas->rootObject()->setProperty("rtl", true);
+ qApp->processEvents();
+
+ QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(canvas->rootObject());
+ QTRY_VERIFY(listview != 0);
+
+ QDeclarativeItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QDeclarativeItem *header = findItem<QDeclarativeItem>(contentItem, "header");
+ QVERIFY(header);
+ QCOMPARE(header->x(), -20.0);
+
+ QDeclarativeItem *footer = findItem<QDeclarativeItem>(contentItem, "footer");
+ QVERIFY(footer);
+ QCOMPARE(footer->x(), -50.0);
+
+ QCOMPARE(static_cast<LVAccessor*>(listview)->minX(), 240.);
+ QCOMPARE(static_cast<LVAccessor*>(listview)->maxX(), 240.);
+
+ delete canvas;
+ }
+}
+
void tst_QDeclarativeListView::resizeView()
{
QDeclarativeView *canvas = createView();
@@ -2360,6 +2467,7 @@ void tst_QDeclarativeListView::testQtQuick11Attributes_data()
void tst_QDeclarativeListView::rightToLeft()
{
QDeclarativeView *canvas = createView();
+ canvas->setFixedSize(640,320);
canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/rightToLeft.qml"));
qApp->processEvents();
@@ -2376,6 +2484,9 @@ void tst_QDeclarativeListView::rightToLeft()
QTRY_VERIFY(model->count() == 3);
QTRY_COMPARE(listview->currentIndex(), 0);
+ // initial position at first item, right edge aligned
+ QCOMPARE(listview->contentX(), -640.);
+
QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "item1");
QTRY_VERIFY(item);
QTRY_COMPARE(item->x(), -100.0);
@@ -2395,6 +2506,12 @@ void tst_QDeclarativeListView::rightToLeft()
QTRY_VERIFY(text);
QTRY_COMPARE(text->text(), QLatin1String("index: 2"));
+ QCOMPARE(listview->contentX(), -640.);
+
+ // Ensure resizing maintains position relative to right edge
+ qobject_cast<QDeclarativeItem*>(canvas->rootObject())->setWidth(600);
+ QTRY_COMPARE(listview->contentX(), -600.);
+
delete canvas;
}