diff -r 56cd8111b7f7 -r 41300fa6a67c src/gui/itemviews/qlistview.cpp --- a/src/gui/itemviews/qlistview.cpp Tue Jan 26 12:42:25 2010 +0200 +++ b/src/gui/itemviews/qlistview.cpp Tue Feb 02 00:43:10 2010 +0200 @@ -357,7 +357,7 @@ /*! \property QListView::spacing - \brief the space between items in the layout + \brief the space around the items in the layout This property is the size of the empty space that is padded around an item in the layout. @@ -773,7 +773,7 @@ void QListView::mouseMoveEvent(QMouseEvent *e) { if (!isVisible()) - return; + return; Q_D(QListView); QAbstractItemView::mouseMoveEvent(e); if (state() == DragSelectingState @@ -832,16 +832,16 @@ return; bool listWrap = (d->viewMode == ListMode) && d->wrapItemText; - bool flowDimensionChanged = (d->flow == LeftToRight && delta.width() != 0) - || (d->flow == TopToBottom && delta.height() != 0); + bool flowDimensionChanged = (d->flow == LeftToRight && delta.width() != 0) + || (d->flow == TopToBottom && delta.height() != 0); // We post a delayed relayout in the following cases : // - we're wrapping // - the state is NoState, we're adjusting and the size has changed in the flowing direction - if (listWrap + if (listWrap || (state() == NoState && d->resizeMode == Adjust && flowDimensionChanged)) { - d->doDelayedItemsLayout(100); // wait 1/10 sec before starting the layout - } else { + d->doDelayedItemsLayout(100); // wait 1/10 sec before starting the layout + } else { QAbstractItemView::resizeEvent(e); } } @@ -853,8 +853,13 @@ */ void QListView::dragMoveEvent(QDragMoveEvent *e) { - if (!d_func()->commonListView->filterDragMoveEvent(e)) - QAbstractItemView::dragMoveEvent(e); + Q_D(QListView); + if (!d->commonListView->filterDragMoveEvent(e)) { + if (viewMode() == QListView::ListMode && flow() == QListView::LeftToRight) + static_cast(d->commonListView)->dragMoveEvent(e); + else + QAbstractItemView::dragMoveEvent(e); + } } @@ -961,15 +966,19 @@ bool alternateBase = false; int previousRow = -2; // trigger the alternateBase adjustment on first pass + int maxSize = (flow() == TopToBottom) + ? qMax(viewport()->size().width(), d->contentsSize().width()) - 2 * d->spacing() + : qMax(viewport()->size().height(), d->contentsSize().height()) - 2 * d->spacing(); + QVector::const_iterator end = toBeRendered.constEnd(); for (QVector::const_iterator it = toBeRendered.constBegin(); it != end; ++it) { Q_ASSERT((*it).isValid()); option.rect = visualRect(*it); if (flow() == TopToBottom) - option.rect.setWidth(qMin(viewport()->size().width(), option.rect.width())); + option.rect.setWidth(qMin(maxSize, option.rect.width())); else - option.rect.setHeight(qMin(viewport()->size().height(), option.rect.height())); + option.rect.setHeight(qMin(maxSize, option.rect.height())); option.state = state; if (selections && selections->isSelected(*it)) @@ -1142,7 +1151,9 @@ } return d->closestIndex(initialRect, intersectVector); case MovePageUp: - rect.moveTop(rect.top() - d->viewport->height()); + // move current by (visibileRowCount - 1) items. + // rect.translate(0, -rect.height()); will happen in the switch fallthrough for MoveUp. + rect.moveTop(rect.top() - d->viewport->height() + 2 * rect.height()); if (rect.top() < rect.height()) rect.moveTop(rect.height()); case MovePrevious: @@ -1168,7 +1179,9 @@ } return d->closestIndex(initialRect, intersectVector); case MovePageDown: - rect.moveTop(rect.top() + d->viewport->height()); + // move current by (visibileRowCount - 1) items. + // rect.translate(0, rect.height()); will happen in the switch fallthrough for MoveDown. + rect.moveTop(rect.top() + d->viewport->height() - 2 * rect.height()); if (rect.bottom() > contents.height() - rect.height()) rect.moveBottom(contents.height() - rect.height()); case MoveNext: @@ -1440,7 +1453,7 @@ // so we set the state to expanding to avoid // triggering another layout QAbstractItemView::State oldState = state(); - setState(ExpandingState); + setState(ExpandingState); if (d->model->columnCount(d->root) > 0) { // no columns means no contents d->resetBatchStartRow(); if (layoutMode() == SinglePass) @@ -1804,6 +1817,16 @@ return selection; } +#ifndef QT_NO_DRAGANDDROP +QAbstractItemView::DropIndicatorPosition QListViewPrivate::position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const +{ + if (viewMode == QListView::ListMode && flow == QListView::LeftToRight) + return static_cast(commonListView)->position(pos, rect, idx); + else + return QAbstractItemViewPrivate::position(pos, rect, idx); +} +#endif + /* * Common ListView Implementation */ @@ -1822,14 +1845,14 @@ { horizontalScrollBar()->setSingleStep(step.width() + spacing()); horizontalScrollBar()->setPageStep(viewport()->width()); - horizontalScrollBar()->setRange(0, contentsSize.width() - viewport()->width()); + horizontalScrollBar()->setRange(0, contentsSize.width() - viewport()->width() - 2 * spacing()); } void QCommonListViewBase::updateVerticalScrollBar(const QSize &step) { verticalScrollBar()->setSingleStep(step.height() + spacing()); verticalScrollBar()->setPageStep(viewport()->height()); - verticalScrollBar()->setRange(0, contentsSize.height() - viewport()->height()); + verticalScrollBar()->setRange(0, contentsSize.height() - viewport()->height() - 2 * spacing()); } void QCommonListViewBase::scrollContentsBy(int dx, int dy, bool /*scrollElasticBand*/) @@ -1893,6 +1916,96 @@ // in IconMode, it makes no sense to show it dd->paintDropIndicator(painter); } + +QAbstractItemView::DropIndicatorPosition QListModeViewBase::position(const QPoint &pos, const QRect &rect, const QModelIndex &index) const +{ + QAbstractItemView::DropIndicatorPosition r = QAbstractItemView::OnViewport; + if (!dd->overwrite) { + const int margin = 2; + if (pos.x() - rect.left() < margin) { + r = QAbstractItemView::AboveItem; // Visually, on the left + } else if (rect.right() - pos.x() < margin) { + r = QAbstractItemView::BelowItem; // Visually, on the right + } else if (rect.contains(pos, true)) { + r = QAbstractItemView::OnItem; + } + } else { + QRect touchingRect = rect; + touchingRect.adjust(-1, -1, 1, 1); + if (touchingRect.contains(pos, false)) { + r = QAbstractItemView::OnItem; + } + } + + if (r == QAbstractItemView::OnItem && (!(dd->model->flags(index) & Qt::ItemIsDropEnabled))) + r = pos.x() < rect.center().x() ? QAbstractItemView::AboveItem : QAbstractItemView::BelowItem; + + return r; +} + +void QListModeViewBase::dragMoveEvent(QDragMoveEvent *event) +{ + if (qq->dragDropMode() == QAbstractItemView::InternalMove + && (event->source() != qq || !(event->possibleActions() & Qt::MoveAction))) + return; + + // ignore by default + event->ignore(); + + QModelIndex index = qq->indexAt(event->pos()); + dd->hover = index; + if (!dd->droppingOnItself(event, index) + && dd->canDecode(event)) { + + if (index.isValid() && dd->showDropIndicator) { + QRect rect = qq->visualRect(index); + dd->dropIndicatorPosition = position(event->pos(), rect, index); + switch (dd->dropIndicatorPosition) { + case QAbstractItemView::AboveItem: + if (dd->isIndexDropEnabled(index.parent())) { + dd->dropIndicatorRect = QRect(rect.left(), rect.top(), 0, rect.height()); + event->accept(); + } else { + dd->dropIndicatorRect = QRect(); + } + break; + case QAbstractItemView::BelowItem: + if (dd->isIndexDropEnabled(index.parent())) { + dd->dropIndicatorRect = QRect(rect.right(), rect.top(), 0, rect.height()); + event->accept(); + } else { + dd->dropIndicatorRect = QRect(); + } + break; + case QAbstractItemView::OnItem: + if (dd->isIndexDropEnabled(index)) { + dd->dropIndicatorRect = rect; + event->accept(); + } else { + dd->dropIndicatorRect = QRect(); + } + break; + case QAbstractItemView::OnViewport: + dd->dropIndicatorRect = QRect(); + if (dd->isIndexDropEnabled(qq->rootIndex())) { + event->accept(); // allow dropping in empty areas + } + break; + } + } else { + dd->dropIndicatorRect = QRect(); + dd->dropIndicatorPosition = QAbstractItemView::OnViewport; + if (dd->isIndexDropEnabled(qq->rootIndex())) { + event->accept(); // allow dropping in empty areas + } + } + dd->viewport->update(); + } // can decode + + if (dd->shouldAutoScroll(event->pos())) + qq->startAutoScroll(); +} + #endif //QT_NO_DRAGANDDROP void QListModeViewBase::updateVerticalScrollBar(const QSize &step) @@ -2298,6 +2411,12 @@ return ret; } +void QListModeViewBase::dataChanged(const QModelIndex &, const QModelIndex &) +{ + dd->doDelayedItemsLayout(); +} + + QRect QListModeViewBase::mapToViewport(const QRect &rect) const { if (isWrapping())