--- a/src/declarative/graphicsitems/qdeclarativelistview.cpp Fri Sep 17 08:34:18 2010 +0300
+++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp Mon Oct 04 01:19:32 2010 +0300
@@ -60,7 +60,7 @@
{
if (property != m_property) {
m_property = property;
- emit changed();
+ emit propertyChanged();
}
}
@@ -68,7 +68,7 @@
{
if (criteria != m_criteria) {
m_criteria = criteria;
- emit changed();
+ emit criteriaChanged();
}
}
@@ -96,7 +96,7 @@
FxListItem(QDeclarativeItem *i, QDeclarativeListView *v) : item(i), section(0), view(v) {
attached = static_cast<QDeclarativeListViewAttached*>(qmlAttachedPropertiesObject<QDeclarativeListView>(item));
if (attached)
- attached->m_view = view;
+ attached->setView(view);
}
~FxListItem() {}
qreal position() const {
@@ -105,12 +105,23 @@
else
return (view->orientation() == QDeclarativeListView::Vertical ? item->y() : item->x());
}
+ qreal itemPosition() const {
+ return (view->orientation() == QDeclarativeListView::Vertical ? item->y() : item->x());
+ }
qreal size() const {
if (section)
- return (view->orientation() == QDeclarativeListView::Vertical ? item->height()+section->height() : item->width()+section->height());
+ return (view->orientation() == QDeclarativeListView::Vertical ? item->height()+section->height() : item->width()+section->width());
else
return (view->orientation() == QDeclarativeListView::Vertical ? item->height() : item->width());
}
+ qreal itemSize() const {
+ return (view->orientation() == QDeclarativeListView::Vertical ? item->height() : item->width());
+ }
+ qreal sectionSize() const {
+ if (section)
+ return (view->orientation() == QDeclarativeListView::Vertical ? section->height() : section->width());
+ return 0.0;
+ }
qreal endPosition() const {
return (view->orientation() == QDeclarativeListView::Vertical
? item->y() + (item->height() > 0 ? item->height() : 1)
@@ -131,6 +142,12 @@
item->setX(pos);
}
}
+ void setSize(qreal size) {
+ if (view->orientation() == QDeclarativeListView::Vertical)
+ item->setHeight(size);
+ else
+ item->setWidth(size);
+ }
bool contains(int x, int y) const {
return (x >= item->x() && x < item->x() + item->width() &&
y >= item->y() && y < item->y() + item->height());
@@ -256,7 +273,12 @@
if (!visibleItems.isEmpty()) {
if (modelIndex < visibleIndex) {
int count = visibleIndex - modelIndex;
- return (*visibleItems.constBegin())->position() - count * (averageSize + spacing);
+ qreal cs = 0;
+ if (modelIndex == currentIndex && currentItem) {
+ cs = currentItem->size() + spacing;
+ --count;
+ }
+ return (*visibleItems.constBegin())->position() - count * (averageSize + spacing) - cs;
} else {
int idx = visibleItems.count() - 1;
while (idx >= 0 && visibleItems.at(idx)->index == -1)
@@ -575,9 +597,11 @@
listItem->attached->m_prevSection = item->attached->section();
else
listItem->attached->m_prevSection = sectionAt(modelIndex-1);
+ }
+ if (modelIndex < model->count()-1) {
if (FxListItem *item = visibleItem(modelIndex+1))
listItem->attached->m_nextSection = item->attached->section();
- else if (modelIndex < model->count()-1)
+ else
listItem->attached->m_nextSection = sectionAt(modelIndex+1);
}
}
@@ -714,6 +738,11 @@
if (visibleItems.count())
visiblePos = (*visibleItems.constBegin())->position();
updateAverage();
+ if (currentIndex >= 0 && currentItem && !visibleItem(currentIndex)) {
+ currentItem->setPosition(positionAt(currentIndex));
+ updateHighlight();
+ }
+
if (sectionCriteria)
updateCurrentSection();
if (header)
@@ -883,8 +912,8 @@
createHighlight();
if (currentItem && autoHighlight && highlight && !movingHorizontally && !movingVertically) {
// auto-update highlight
- highlightPosAnimator->to = currentItem->position();
- highlightSizeAnimator->to = currentItem->size();
+ highlightPosAnimator->to = currentItem->itemPosition();
+ highlightSizeAnimator->to = currentItem->itemSize();
if (orient == QDeclarativeListView::Vertical) {
if (highlight->item->width() == 0)
highlight->item->setWidth(currentItem->item->width());
@@ -981,11 +1010,11 @@
void QDeclarativeListViewPrivate::updateCurrentSection()
{
if (!sectionCriteria || visibleItems.isEmpty()) {
- currentSection = QString();
+ currentSection.clear();
return;
}
int index = 0;
- while (visibleItems.at(index)->endPosition() < position() && index < visibleItems.count())
+ while (index < visibleItems.count() && visibleItems.at(index)->endPosition() < position())
++index;
if (index < visibleItems.count())
@@ -1019,7 +1048,7 @@
if (oldCurrentItem && (!currentItem || oldCurrentItem->item != currentItem->item))
oldCurrentItem->attached->setIsCurrentItem(false);
if (currentItem) {
- if (modelIndex == visibleIndex - 1) {
+ if (modelIndex == visibleIndex - 1 && visibleItems.count()) {
// We can calculate exact postion in this case
currentItem->setPosition(visibleItems.first()->position() - currentItem->size() - spacing);
} else {
@@ -1170,9 +1199,9 @@
}
if (currentItem && haveHighlightRange && highlightRange == QDeclarativeListView::StrictlyEnforceRange) {
updateHighlight();
- qreal currPos = currentItem->position();
- if (pos < currPos + currentItem->size() - highlightRangeEnd)
- pos = currPos + currentItem->size() - highlightRangeEnd;
+ qreal currPos = currentItem->itemPosition();
+ if (pos < currPos + currentItem->itemSize() - highlightRangeEnd)
+ pos = currPos + currentItem->itemSize() - highlightRangeEnd;
if (pos > currPos - highlightRangeStart)
pos = currPos - highlightRangeStart;
}
@@ -1189,10 +1218,10 @@
} else if (haveHighlightRange && highlightRange == QDeclarativeListView::StrictlyEnforceRange) {
if (currentItem) {
updateHighlight();
- qreal pos = currentItem->position();
+ qreal pos = currentItem->itemPosition();
qreal viewPos = position();
- if (viewPos < pos + currentItem->size() - highlightRangeEnd)
- viewPos = pos + currentItem->size() - highlightRangeEnd;
+ if (viewPos < pos + currentItem->itemSize() - highlightRangeEnd)
+ viewPos = pos + currentItem->itemSize() - highlightRangeEnd;
if (viewPos > pos - highlightRangeStart)
viewPos = pos - highlightRangeStart;
@@ -1355,6 +1384,7 @@
/*!
\qmlclass ListView QDeclarativeListView
+ \ingroup qml-view-elements
\since 4.7
\inherits Flickable
\brief The ListView item provides a list view of items provided by a model.
@@ -1385,14 +1415,16 @@
the delegate is able to access the model's \c name and \c number data directly.
An improved list view is shown below. The delegate is visually improved and is moved
- into a separate \c contactDelegate component. Also, the currently selected item is highlighted
- with a blue \l Rectangle using the \l highlight property, and \c focus is set to \c true
- to enable keyboard navigation for the list view.
+ into a separate \c contactDelegate component.
\snippet doc/src/snippets/declarative/listview/listview.qml classdocs advanced
\image listview-highlight.png
- In a GridView, delegates are instantiated as needed and may be destroyed at any time.
+ The currently selected item is highlighted with a blue \l Rectangle using the \l highlight property,
+ and \c focus is set to \c true to enable keyboard navigation for the list view.
+ The list view itself is a focus scope (see \l{qmlfocus#Acquiring Focus and Focus Scopes}{the focus documentation page} for more details).
+
+ Delegates are instantiated as needed and may be destroyed at any time.
State should \e never be stored in a delegate.
\note Views do not enable \e clip automatically. If the view
@@ -1616,6 +1648,8 @@
for (int i = 0; i < d->visibleItems.count(); ++i)
d->releaseItem(d->visibleItems.at(i));
d->visibleItems.clear();
+ d->releaseItem(d->currentItem);
+ d->currentItem = 0;
refill();
d->moveReason = QDeclarativeListViewPrivate::SetIndex;
d->updateCurrent(d->currentIndex);
@@ -2335,6 +2369,10 @@
d->minExtent += d->header->size();
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
d->minExtent += d->highlightRangeStart;
+ if (d->sectionCriteria) {
+ if (d->visibleItem(0))
+ d->minExtent -= d->visibleItem(0)->sectionSize();
+ }
d->minExtent = qMax(d->minExtent, -(d->endPositionAt(0) - d->highlightRangeEnd + 1));
}
d->minExtentDirty = false;
@@ -2447,6 +2485,16 @@
QDeclarativeFlickable::keyPressEvent(event);
}
+void QDeclarativeListView::geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry)
+{
+ Q_D(QDeclarativeListView);
+ d->maxExtentDirty = true;
+ d->minExtentDirty = true;
+ QDeclarativeFlickable::geometryChanged(newGeometry, oldGeometry);
+}
+
+
/*!
\qmlmethod ListView::incrementCurrentIndex()
@@ -2572,6 +2620,11 @@
d->moveReason = QDeclarativeListViewPrivate::Other;
cancelFlick();
d->setPosition(pos);
+ if (d->highlight) {
+ d->highlight->setPosition(d->currentItem->itemPosition());
+ d->highlight->setSize(d->currentItem->itemSize());
+ d->updateHighlight();
+ }
}
d->fixupPosition();
}
@@ -2632,7 +2685,12 @@
if (!d->trackedItem || !d->currentItem)
return;
if (d->moveReason == QDeclarativeListViewPrivate::SetIndex) {
- const qreal trackedPos = qCeil(d->trackedItem->position());
+ qreal trackedPos = qCeil(d->trackedItem->position());
+ qreal trackedSize = d->trackedItem->size();
+ if (d->trackedItem != d->currentItem) {
+ trackedPos -= d->currentItem->sectionSize();
+ trackedSize += d->currentItem->sectionSize();
+ }
const qreal viewPos = d->position();
qreal pos = viewPos;
if (d->haveHighlightRange) {
@@ -2645,28 +2703,28 @@
if (trackedPos < d->startPosition() + d->highlightRangeStart) {
pos = d->startPosition();
} else if (d->trackedItem->endPosition() > d->endPosition() - d->size() + d->highlightRangeEnd) {
- pos = d->endPosition() - d->size();
+ pos = d->endPosition() - d->size() + 1;
if (pos < d->startPosition())
pos = d->startPosition();
} else {
if (trackedPos < viewPos + d->highlightRangeStart) {
pos = trackedPos - d->highlightRangeStart;
- } else if (trackedPos > viewPos + d->highlightRangeEnd - d->trackedItem->size()) {
- pos = trackedPos - d->highlightRangeEnd + d->trackedItem->size();
+ } else if (trackedPos > viewPos + d->highlightRangeEnd - trackedSize) {
+ pos = trackedPos - d->highlightRangeEnd + trackedSize;
}
}
}
} else {
if (trackedPos < viewPos && d->currentItem->position() < viewPos) {
pos = d->currentItem->position() < trackedPos ? trackedPos : d->currentItem->position();
- } else if (d->trackedItem->endPosition() > viewPos + d->size()
- && d->currentItem->endPosition() > viewPos + d->size()) {
- if (d->trackedItem->endPosition() < d->currentItem->endPosition()) {
- pos = d->trackedItem->endPosition() - d->size();
- if (d->trackedItem->size() > d->size())
+ } else if (d->trackedItem->endPosition() >= viewPos + d->size()
+ && d->currentItem->endPosition() >= viewPos + d->size()) {
+ if (d->trackedItem->endPosition() <= d->currentItem->endPosition()) {
+ pos = d->trackedItem->endPosition() - d->size() + 1;
+ if (trackedSize > d->size())
pos = trackedPos;
} else {
- pos = d->currentItem->endPosition() - d->size();
+ pos = d->currentItem->endPosition() - d->size() + 1;
if (d->currentItem->size() > d->size())
pos = d->currentItem->position();
}
@@ -2899,14 +2957,18 @@
}
if (removedVisible && d->visibleItems.isEmpty()) {
- d->visibleIndex = 0;
- d->visiblePos = d->header ? d->header->size() : 0;
d->timeline.clear();
- d->setPosition(0);
if (d->itemCount == 0) {
+ d->visibleIndex = 0;
+ d->visiblePos = d->header ? d->header->size() : 0;
+ d->setPosition(0);
d->updateHeader();
d->updateFooter();
update();
+ } else {
+ if (modelIndex < d->visibleIndex)
+ d->visibleIndex = modelIndex+1;
+ d->visibleIndex = qMax(qMin(d->visibleIndex, d->itemCount-1), 0);
}
}