00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "qlistview.h"
00025
00026 #ifndef QT_NO_LISTVIEW
00027 #include <qabstractitemdelegate.h>
00028 #include <qapplication.h>
00029 #include <qpainter.h>
00030 #include <qbitmap.h>
00031 #include <qvector.h>
00032 #include <qstyle.h>
00033 #include <qevent.h>
00034 #include <qscrollbar.h>
00035 #include <qrubberband.h>
00036 #include <private/qlistview_p.h>
00037 #include <qdebug.h>
00038
00148 QListView::QListView(QWidget *parent)
00149 : QAbstractItemView(*new QListViewPrivate, parent)
00150 {
00151 setViewMode(ListMode);
00152 setSelectionMode(SingleSelection);
00153 }
00154
00158 QListView::QListView(QListViewPrivate &dd, QWidget *parent)
00159 : QAbstractItemView(dd, parent)
00160 {
00161 setViewMode(ListMode);
00162 setSelectionMode(SingleSelection);
00163 }
00164
00168 QListView::~QListView()
00169 {
00170 }
00171
00189 void QListView::setMovement(Movement movement)
00190 {
00191 Q_D(QListView);
00192 d->modeProperties |= uint(QListViewPrivate::Movement);
00193 d->movement = movement;
00194
00195 #ifndef QT_NO_DRAGANDDROP
00196 bool movable = (movement != Static);
00197 setDragEnabled(movable);
00198 d->viewport->setAcceptDrops(movable);
00199 #endif
00200
00201 d->doDelayedItemsLayout();
00202 }
00203
00204 QListView::Movement QListView::movement() const
00205 {
00206 Q_D(const QListView);
00207 return d->movement;
00208 }
00209
00225 void QListView::setFlow(Flow flow)
00226 {
00227 Q_D(QListView);
00228 d->modeProperties |= uint(QListViewPrivate::Flow);
00229 d->flow = flow;
00230 d->doDelayedItemsLayout();
00231 }
00232
00233 QListView::Flow QListView::flow() const
00234 {
00235 Q_D(const QListView);
00236 return d->flow;
00237 }
00238
00252 void QListView::setWrapping(bool enable)
00253 {
00254 Q_D(QListView);
00255 d->modeProperties |= uint(QListViewPrivate::Wrap);
00256 d->wrap = enable;
00257 d->doDelayedItemsLayout();
00258 }
00259
00260 bool QListView::isWrapping() const
00261 {
00262 Q_D(const QListView);
00263 return d->wrap;
00264 }
00265
00276 void QListView::setResizeMode(ResizeMode mode)
00277 {
00278 Q_D(QListView);
00279 d->modeProperties |= uint(QListViewPrivate::ResizeMode);
00280 d->resizeMode = mode;
00281 }
00282
00283 QListView::ResizeMode QListView::resizeMode() const
00284 {
00285 Q_D(const QListView);
00286 return d->resizeMode;
00287 }
00288
00302 void QListView::setLayoutMode(LayoutMode mode)
00303 {
00304 Q_D(QListView);
00305 d->layoutMode = mode;
00306 }
00307
00308 QListView::LayoutMode QListView::layoutMode() const
00309 {
00310 Q_D(const QListView);
00311 return d->layoutMode;
00312 }
00313
00326 void QListView::setSpacing(int space)
00327 {
00328 Q_D(QListView);
00329 d->modeProperties |= uint(QListViewPrivate::Spacing);
00330 d->spacing = space;
00331 d->doDelayedItemsLayout();
00332 }
00333
00334 int QListView::spacing() const
00335 {
00336 Q_D(const QListView);
00337 return d->spacing;
00338 }
00339
00350 void QListView::setBatchSize(int batchSize)
00351 {
00352 Q_D(QListView);
00353 if (batchSize <= 0) {
00354 qWarning("Invalid batchSize (%d)", batchSize);
00355 return;
00356 }
00357 d->batchSize = batchSize;
00358 }
00359
00360 int QListView::batchSize() const
00361 {
00362 Q_D(const QListView);
00363 return d->batchSize;
00364 }
00365
00381 void QListView::setGridSize(const QSize &size)
00382 {
00383 Q_D(QListView);
00384 d->modeProperties |= uint(QListViewPrivate::GridSize);
00385 d->gridSize = size;
00386 d->doDelayedItemsLayout();
00387 }
00388
00389 QSize QListView::gridSize() const
00390 {
00391 Q_D(const QListView);
00392 return d->gridSize;
00393 }
00394
00410 void QListView::setViewMode(ViewMode mode)
00411 {
00412 Q_D(QListView);
00413 d->viewMode = mode;
00414
00415 if (mode == ListMode) {
00416 if (!(d->modeProperties & QListViewPrivate::Wrap))
00417 d->wrap = false;
00418 if (!(d->modeProperties & QListViewPrivate::Spacing))
00419 d->spacing = 0;
00420 if (!(d->modeProperties & QListViewPrivate::GridSize))
00421 d->gridSize = QSize();
00422 if (!(d->modeProperties & QListViewPrivate::Flow))
00423 d->flow = TopToBottom;
00424 if (!(d->modeProperties & QListViewPrivate::Movement))
00425 d->movement = Static;
00426 if (!(d->modeProperties & QListViewPrivate::ResizeMode))
00427 d->resizeMode = Fixed;
00428 } else {
00429 if (!(d->modeProperties & QListViewPrivate::Wrap))
00430 d->wrap = true;
00431 if (!(d->modeProperties & QListViewPrivate::Spacing))
00432 d->spacing = 0;
00433 if (!(d->modeProperties & QListViewPrivate::GridSize))
00434 d->gridSize = QSize();
00435 if (!(d->modeProperties & QListViewPrivate::Flow))
00436 d->flow = LeftToRight;
00437 if (!(d->modeProperties & QListViewPrivate::Movement))
00438 d->movement = Free;
00439 if (!(d->modeProperties & QListViewPrivate::ResizeMode))
00440 d->resizeMode = Fixed;
00441 }
00442
00443 #ifndef QT_NO_DRAGANDDROP
00444 bool movable = (d->movement != Static);
00445 setDragEnabled(movable);
00446 setAcceptDrops(movable);
00447 #endif
00448 d->doDelayedItemsLayout();
00449 }
00450
00451 QListView::ViewMode QListView::viewMode() const
00452 {
00453 Q_D(const QListView);
00454 return d->viewMode;
00455 }
00456
00464 void QListView::clearPropertyFlags()
00465 {
00466 Q_D(QListView);
00467 d->modeProperties = 0;
00468 }
00469
00473 bool QListView::isRowHidden(int row) const
00474 {
00475 Q_D(const QListView);
00476 return d->hiddenRows.contains(row);
00477 }
00478
00483 void QListView::setRowHidden(int row, bool hide)
00484 {
00485 Q_D(QListView);
00486 if (hide && !isRowHidden(row)) {
00487 d->removeItem(row);
00488 d->hiddenRows.append(row);
00489 } else if (!hide && isRowHidden(row)) {
00490 d->hiddenRows.remove(d->hiddenRows.indexOf(row));
00491 d->insertItem(row);
00492 }
00493 if (d->movement == Static)
00494 d->doDelayedItemsLayout();
00495 else
00496 d->viewport->update();
00497 }
00498
00502 QRect QListView::visualRect(const QModelIndex &index) const
00503 {
00504 Q_D(const QListView);
00505 return d->mapToViewport(rectForIndex(index));
00506 }
00507
00511 void QListView::scrollTo(const QModelIndex &index, ScrollHint hint)
00512 {
00513 Q_D(QListView);
00514
00515 if (index.parent() != d->root || index.column() != d->column)
00516 return;
00517
00518 const QRect area = d->viewport->rect();
00519 const QRect rect = visualRect(index);
00520 if (hint == EnsureVisible && area.contains(rect)) {
00521 d->setDirtyRegion(rect);
00522 return;
00523 }
00524
00525
00526 if (d->flow == QListView::TopToBottom || d->wrap) {
00527 const bool above = (hint == EnsureVisible && rect.top() < area.top());
00528 const bool below = (hint == EnsureVisible && rect.bottom() > area.bottom());
00529 int verticalValue = verticalScrollBar()->value();
00530 if (verticalScrollMode() == QAbstractItemView::ScrollPerItem && d->movement == Static) {
00531 const QListViewItem item = d->indexToListViewItem(index);
00532 const int itemIndex = d->itemIndex(item);
00533 verticalValue = qBound(0, verticalValue, d->flowPositions.count() - 1);
00534 if (above)
00535 verticalValue = d->perItemScrollToValue(itemIndex, verticalValue,
00536 area.height(), PositionAtTop,
00537 Qt::Vertical);
00538 else if (below)
00539 verticalValue = d->perItemScrollToValue(itemIndex, verticalValue,
00540 area.height(), PositionAtBottom,
00541 Qt::Vertical);
00542 else if (hint != EnsureVisible)
00543 verticalValue = d->perItemScrollToValue(itemIndex, verticalValue,
00544 area.height(), hint,
00545 Qt::Vertical);
00546 } else {
00547 if (hint == PositionAtTop || above)
00548 verticalValue += rect.top();
00549 else if (hint == PositionAtBottom || below)
00550 verticalValue += rect.bottom() - area.height();
00551 else if (hint == PositionAtCenter)
00552 verticalValue += rect.top() - ((area.height() - rect.height()) / 2);
00553 }
00554 verticalScrollBar()->setValue(verticalValue);
00555 }
00556
00557
00558 if (d->flow == QListView::LeftToRight || d->wrap) {
00559 const bool leftOf = isRightToLeft()
00560 ? (rect.left() < area.left()) && (rect.right() < area.right())
00561 : rect.left() < area.left();
00562 const bool rightOf = isRightToLeft()
00563 ? rect.right() > area.right()
00564 : (rect.right() > area.right()) && (rect.left() > area.left());
00565 int horizontalValue = horizontalScrollBar()->value();
00566
00567 if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem && d->movement == Static) {
00568 const QListViewItem item = d->indexToListViewItem(index);
00569 const int itemIndex = d->itemIndex(item);
00570 horizontalValue = qBound(0, horizontalValue, d->flowPositions.count() - 1);
00571 if (leftOf)
00572 horizontalValue = d->perItemScrollToValue(itemIndex, horizontalValue,
00573 area.width(), PositionAtTop,
00574 Qt::Horizontal);
00575 else if (rightOf)
00576 horizontalValue = d->perItemScrollToValue(itemIndex, horizontalValue,
00577 area.width(), PositionAtBottom,
00578 Qt::Horizontal);
00579 else if (hint != EnsureVisible) {
00580 horizontalValue = d->perItemScrollToValue(itemIndex, horizontalValue,
00581 area.width(), hint,
00582 Qt::Horizontal);
00583 }
00584 } else {
00585 if (isRightToLeft()) {
00586 if (hint == PositionAtCenter) {
00587 horizontalValue += ((area.width() - rect.width()) / 2) - rect.left();
00588 } else {
00589 if (leftOf)
00590 horizontalValue -= rect.left();
00591 else if (rightOf)
00592 horizontalValue += area.width() - rect.right();
00593 }
00594 } else {
00595 if (hint == PositionAtCenter) {
00596 horizontalValue += rect.left() - ((area.width()- rect.width()) / 2);
00597 } else {
00598 if (leftOf)
00599 horizontalValue += rect.left();
00600 else if (rightOf)
00601 horizontalValue += rect.right() - area.width();
00602 }
00603 }
00604 }
00605 horizontalScrollBar()->setValue(horizontalValue);
00606 }
00607 }
00608
00612 void QListView::reset()
00613 {
00614 Q_D(QListView);
00615 d->clear();
00616 d->hiddenRows.clear();
00617 QAbstractItemView::reset();
00618 }
00619
00623 void QListView::setRootIndex(const QModelIndex &index)
00624 {
00625 Q_D(QListView);
00626 d->column = qBound(0, d->column, d->model->columnCount(index) - 1);
00627 QAbstractItemView::setRootIndex(index);
00628 }
00629
00635 void QListView::scrollContentsBy(int dx, int dy)
00636 {
00637 Q_D(QListView);
00638
00639 dx = isRightToLeft() ? -dx : dx;
00640
00641
00642 if (d->movement == Static) {
00643 const bool vertical = verticalScrollMode() == QAbstractItemView::ScrollPerItem;
00644 const bool horizontal = horizontalScrollMode() == QAbstractItemView::ScrollPerItem;
00645 if (d->wrap) {
00646 if (d->segmentPositions.isEmpty())
00647 return;
00648 const int max = d->segmentPositions.count() - 1;
00649 if (horizontal && d->flow == TopToBottom && dx != 0) {
00650 int currentValue = qBound(0, horizontalScrollBar()->value(), max);
00651 int previousValue = qBound(0, currentValue + dx, max);
00652 int currentCoordinate = d->segmentPositions.at(currentValue);
00653 int previousCoordinate = d->segmentPositions.at(previousValue);
00654 dx = previousCoordinate - currentCoordinate;
00655 } else if (vertical && d->flow == LeftToRight && dy != 0) {
00656 int currentValue = qBound(0, verticalScrollBar()->value(), max);
00657 int previousValue = qBound(0, currentValue + dy, max);
00658 int currentCoordinate = d->segmentPositions.at(currentValue);
00659 int previousCoordinate = d->segmentPositions.at(previousValue);
00660 dy = previousCoordinate - currentCoordinate;
00661 }
00662 } else {
00663 if (d->flowPositions.isEmpty())
00664 return;
00665 const int max = d->flowPositions.count() - 1;
00666 if (vertical && d->flow == TopToBottom && dy != 0) {
00667 int currentValue = qBound(0, verticalScrollBar()->value(), max);
00668 int previousValue = qBound(0, currentValue + dy, max);
00669 int currentCoordinate = d->flowPositions.at(currentValue);
00670 int previousCoordinate = d->flowPositions.at(previousValue);
00671 dy = previousCoordinate - currentCoordinate;
00672 } else if (horizontal && d->flow == LeftToRight && dx != 0) {
00673 int currentValue = qBound(0, horizontalScrollBar()->value(), max);
00674 int previousValue = qBound(0, currentValue + dx, max);
00675 int currentCoordinate = d->flowPositions.at(currentValue);
00676 int previousCoordinate = d->flowPositions.at(previousValue);
00677 dx = previousCoordinate - currentCoordinate;
00678 }
00679 }
00680 }
00681
00682 if (state() == DragSelectingState) {
00683 if (dx > 0)
00684 d->elasticBand.moveRight(d->elasticBand.right() + dx);
00685 else if (dx < 0)
00686 d->elasticBand.moveLeft(d->elasticBand.left() - dx);
00687 if (dy > 0)
00688 d->elasticBand.moveBottom(d->elasticBand.bottom() + dy);
00689 else if (dy < 0)
00690 d->elasticBand.moveTop(d->elasticBand.top() - dy);
00691 }
00692
00693 d->scrollContentsBy(dx, dy);
00694
00695
00696 if (!d->draggedItems.isEmpty())
00697 d->setDirtyRegion(d->draggedItemsRect().translated(dx, dy));
00698 }
00699
00706 void QListView::resizeContents(int width, int height)
00707 {
00708 Q_D(QListView);
00709 d->contentsSize = QSize(width, height);
00710 }
00711
00715 QSize QListView::contentsSize() const
00716 {
00717 return d_func()->contentsSize;
00718 }
00719
00723 void QListView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
00724 {
00725 Q_D(QListView);
00726 if (d->movement != Static
00727 && d->column >= topLeft.column()
00728 && d->column <= bottomRight.column()) {
00729 QStyleOptionViewItemV2 option = d->viewOptionsV2();
00730 int bottom = qMin(d->items.count(), bottomRight.row() + 1);
00731 for (int row = topLeft.row(); row < bottom; ++row) {
00732 QModelIndex idx = d->model->index(row, d->column, d->root);
00733 d->items[row].resize(d->itemSize(option, idx));
00734 }
00735 }
00736 QAbstractItemView::dataChanged(topLeft, bottomRight);
00737 }
00738
00742 void QListView::rowsInserted(const QModelIndex &parent, int start, int end)
00743 {
00744 Q_D(QListView);
00745
00746 if (parent == d->root) {
00747 int count = (end - start + 1);
00748 for (int i = d->hiddenRows.count() - 1; i >= 0; --i)
00749 if (d->hiddenRows.at(i) >= start)
00750 d->hiddenRows[i] += count;
00751 }
00752 d->clear();
00753 d->doDelayedItemsLayout();
00754 QAbstractItemView::rowsInserted(parent, start, end);
00755 }
00756
00760 void QListView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
00761 {
00762 Q_D(QListView);
00763
00764 QAbstractItemView::rowsAboutToBeRemoved(parent, start, end);
00765 if (parent == d->root) {
00766 int count = (end - start + 1);
00767 for (int i = d->hiddenRows.count() - 1; i >= 0; --i) {
00768 if (d->hiddenRows.at(i) >= start) {
00769 if (d->hiddenRows.at(i) <= end) {
00770 d->hiddenRows.remove(i);
00771 } else {
00772 d->hiddenRows[i] -= count;
00773 }
00774 }
00775 }
00776 }
00777 d->clear();
00778 d->doDelayedItemsLayout();
00779 }
00780
00784 void QListView::mouseMoveEvent(QMouseEvent *e)
00785 {
00786 Q_D(QListView);
00787 QAbstractItemView::mouseMoveEvent(e);
00788 if (d->movement != Static
00789 && state() == DragSelectingState
00790 && d->selectionMode != SingleSelection) {
00791 QRect rect(d->pressedPosition, e->pos() + QPoint(horizontalOffset(), verticalOffset()));
00792 rect = rect.normalized();
00793 d->setDirtyRegion(d->mapToViewport(rect.united(d->elasticBand)));
00794 d->elasticBand = rect;
00795 }
00796 }
00797
00801 void QListView::mouseReleaseEvent(QMouseEvent *e)
00802 {
00803 Q_D(QListView);
00804 QAbstractItemView::mouseReleaseEvent(e);
00805 if (d->elasticBand.isValid()) {
00806 d->setDirtyRegion(d->mapToViewport(d->elasticBand));
00807 d->elasticBand = QRect();
00808 }
00809 }
00810
00814 void QListView::timerEvent(QTimerEvent *e)
00815 {
00816 Q_D(QListView);
00817 if (e->timerId() == d->delayedLayout.timerId()) {
00818 setState(ExpandingState);
00819 doItemsLayout();
00820 setState(NoState);
00821 } else if (e->timerId() == d->batchLayoutTimer.timerId()) {
00822 if (d->doItemsLayout(d->batchSize)) {
00823 d->batchLayoutTimer.stop();
00824 updateGeometries();
00825 d->viewport->update();
00826 }
00827 }
00828 QAbstractItemView::timerEvent(e);
00829 }
00830
00834 void QListView::resizeEvent(QResizeEvent *e)
00835 {
00836 Q_D(QListView);
00837 QAbstractItemView::resizeEvent(e);
00838 if (state() == NoState) {
00839
00840 if (d->resizeMode == Adjust) {
00841 QSize delta = e->size() - e->oldSize();
00842 if (!d->delayedLayout.isActive()
00843 && ((d->flow == LeftToRight && delta.width() != 0)
00844 || (d->flow == TopToBottom && delta.height() != 0))) {
00845 d->delayedLayout.start(100, this);
00846 }
00847 }
00848 }
00849 }
00850
00851 #ifndef QT_NO_DRAGANDDROP
00852
00856 void QListView::dragMoveEvent(QDragMoveEvent *e)
00857 {
00858 Q_D(QListView);
00859 if (e->source() == this && d->movement != Static) {
00860
00861 e->ignore();
00862 if (d->canDecode(e)) {
00863
00864 QRect itemsRect = d->itemsRect(d->draggedItems);
00865 d->setDirtyRegion(itemsRect.translated(d->draggedItemsDelta()));
00866
00867 d->draggedItemsPos = e->pos();
00868
00869 d->setDirtyRegion(itemsRect.translated(d->draggedItemsDelta()));
00870
00871 QModelIndex index = indexAt(e->pos());
00872
00873 if (e->source() == this && d->draggedItems.contains(index))
00874 e->accept();
00875 else if (d->model->flags(index) & Qt::ItemIsDropEnabled)
00876 e->accept();
00877 else if (!index.isValid())
00878 e->accept();
00879 }
00880
00881 if (d->shouldAutoScroll(e->pos()))
00882 startAutoScroll();
00883 } else {
00884 QAbstractItemView::dragMoveEvent(e);
00885 }
00886 }
00887
00891 void QListView::dragLeaveEvent(QDragLeaveEvent *e)
00892 {
00893 Q_D(QListView);
00894 if (d->movement != Static) {
00895 d->viewport->update(d->draggedItemsRect());
00896 d->draggedItemsPos = QPoint(-1, -1);
00897 }
00898 QAbstractItemView::dragLeaveEvent(e);
00899 }
00900
00904 void QListView::dropEvent(QDropEvent *event)
00905 {
00906 Q_D(QListView);
00907 if (event->source() == this && d->movement != Static)
00908 internalDrop(event);
00909 else
00910 QAbstractItemView::dropEvent(event);
00911 }
00912
00916 void QListView::startDrag(Qt::DropActions supportedActions)
00917 {
00918 Q_D(QListView);
00919 if (d->movement != Static)
00920 internalDrag(supportedActions);
00921 else
00922 QAbstractItemView::startDrag(supportedActions);
00923 }
00924
00931 void QListView::internalDrop(QDropEvent *event)
00932 {
00933 Q_D(QListView);
00934 QPoint offset(horizontalOffset(), verticalOffset());
00935 QPoint end = event->pos() + offset;
00936 QPoint start = d->pressedPosition;
00937 QPoint delta = (d->movement == Snap ?
00938 d->snapToGrid(end) - d->snapToGrid(start) : end - start);
00939 QList<QModelIndex> indexes = d->selectionModel->selectedIndexes();
00940 for (int i = 0; i < indexes.count(); ++i) {
00941 QModelIndex index = indexes.at(i);
00942 QRect rect = rectForIndex(index);
00943 d->setDirtyRegion(d->mapToViewport(rect));
00944 QPoint dest = rect.topLeft() + delta;
00945 if (isRightToLeft())
00946 dest.setX(d->flipX(dest.x()) - rect.width());
00947 d->moveItem(index.row(), dest);
00948 d->setDirtyRegion(visualRect(index));
00949 }
00950 stopAutoScroll();
00951 d->draggedItems.clear();
00952 emit indexesMoved(indexes);
00953 event->accept();
00954 }
00955
00962 void QListView::internalDrag(Qt::DropActions supportedActions)
00963 {
00964
00965
00966
00967 Q_D(QListView);
00968 QModelIndexList indexes = d->selectionModel->selectedIndexes();
00969 if (indexes.count() > 0 ) {
00970 QModelIndexList::ConstIterator it = indexes.constBegin();
00971 for (; it != indexes.constEnd(); ++it)
00972 if (d->model->flags(*it) & Qt::ItemIsDragEnabled)
00973 d->draggedItems.push_back(*it);
00974 QDrag *drag = new QDrag(this);
00975 drag->setMimeData(d->model->mimeData(indexes));
00976 Qt::DropAction action = drag->start(supportedActions);
00977 d->draggedItems.clear();
00978 if (action == Qt::MoveAction)
00979 d->clearOrRemove();
00980 }
00981 }
00982
00983 #endif // QT_NO_DRAGANDDROP
00984
00988 QStyleOptionViewItem QListView::viewOptions() const
00989 {
00990 Q_D(const QListView);
00991 QStyleOptionViewItem option = QAbstractItemView::viewOptions();
00992 if (!d->iconSize.isValid()) {
00993 int pm = (d->viewMode == ListMode
00994 ? style()->pixelMetric(QStyle::PM_ListViewIconSize)
00995 : style()->pixelMetric(QStyle::PM_IconViewIconSize));
00996 option.decorationSize = QSize(pm, pm);
00997 }
00998 if (d->viewMode == IconMode) {
00999 option.showDecorationSelected = false;
01000 option.decorationPosition = QStyleOptionViewItem::Top;
01001 option.displayAlignment = Qt::AlignCenter;
01002 } else {
01003 option.decorationPosition = QStyleOptionViewItem::Left;
01004 }
01005 return option;
01006 }
01007
01011 void QListView::paintEvent(QPaintEvent *e)
01012 {
01013 Q_D(QListView);
01014 if (!d->itemDelegate)
01015 return;
01016 QStyleOptionViewItemV2 option = d->viewOptionsV2();
01017 QPainter painter(d->viewport);
01018 QRect area = e->rect();
01019
01020 QVector<QModelIndex> toBeRendered;
01021
01022
01023
01024
01025
01026 d->intersectingSet(e->rect().translated(horizontalOffset(), verticalOffset()), false);
01027 toBeRendered = d->intersectVector;
01028
01029 const QModelIndex current = currentIndex();
01030 const QModelIndex hover = d->hover;
01031 const QAbstractItemModel *itemModel = d->model;
01032 const QItemSelectionModel *selections = d->selectionModel;
01033 const bool focus = (hasFocus() || d->viewport->hasFocus()) && current.isValid();
01034 const bool alternate = d->alternatingColors;
01035 const QStyle::State state = option.state;
01036 const QAbstractItemView::State viewState = this->state();
01037 const bool enabled = (state & QStyle::State_Enabled) != 0;
01038
01039 bool alternateBase = false;
01040 int previousRow = -2;
01041
01042 QVector<QModelIndex>::const_iterator end = toBeRendered.constEnd();
01043 for (QVector<QModelIndex>::const_iterator it = toBeRendered.constBegin(); it != end; ++it) {
01044 Q_ASSERT((*it).isValid());
01045 option.rect = visualRect(*it);
01046 option.state = state;
01047 if (selections && selections->isSelected(*it))
01048 option.state |= QStyle::State_Selected;
01049 if (enabled) {
01050 QPalette::ColorGroup cg;
01051 if ((itemModel->flags(*it) & Qt::ItemIsEnabled) == 0) {
01052 option.state &= ~QStyle::State_Enabled;
01053 cg = QPalette::Disabled;
01054 } else {
01055 cg = QPalette::Normal;
01056 }
01057 option.palette.setCurrentColorGroup(cg);
01058 }
01059 if (focus && current == *it) {
01060 option.state |= QStyle::State_HasFocus;
01061 if (viewState == EditingState)
01062 option.state |= QStyle::State_Editing;
01063 }
01064 if (*it == hover)
01065 option.state |= QStyle::State_MouseOver;
01066 else
01067 option.state &= ~QStyle::State_MouseOver;
01068
01069 if (alternate) {
01070 int row = (*it).row();
01071 if (row != previousRow + 1) {
01072
01073 if (!d->hiddenRows.isEmpty()) {
01074 for (int r = qMax(previousRow + 1, 0); r < row; ++r) {
01075 if (!d->hiddenRows.contains(r))
01076 alternateBase = !alternateBase;
01077 }
01078 } else {
01079 alternateBase = (row & 1) != 0;
01080 }
01081 }
01082 QBrush fill;
01083 if (alternateBase) {
01084 option.features |= QStyleOptionViewItemV2::Alternate;
01085 fill = option.palette.brush(QPalette::AlternateBase);
01086 } else {
01087 option.features &= ~QStyleOptionViewItemV2::Alternate;
01088 fill = option.palette.brush(QPalette::Base);
01089 }
01090 alternateBase = !alternateBase;
01091 painter.fillRect(option.rect, fill);
01092 previousRow = row;
01093 }
01094
01095 d->delegateForIndex(*it)->paint(&painter, option, *it);
01096 }
01097
01098 #ifndef QT_NO_DRAGANDDROP
01099 if (!d->draggedItems.isEmpty() && d->viewport->rect().contains(d->draggedItemsPos)) {
01100 QPoint delta = d->draggedItemsDelta();
01101 painter.translate(delta.x(), delta.y());
01102 d->drawItems(&painter, d->draggedItems);
01103 }
01104
01105
01106 if (d->viewMode == ListMode)
01107 d->paintDropIndicator(&painter);
01108 #endif
01109
01110 #ifndef QT_NO_RUBBERBAND
01111 if (d->elasticBand.isValid()) {
01112 QStyleOptionRubberBand opt;
01113 opt.initFrom(this);
01114 opt.shape = QRubberBand::Rectangle;
01115 opt.opaque = false;
01116 opt.rect = d->mapToViewport(d->elasticBand).intersected(
01117 d->viewport->rect().adjusted(-16, -16, 16, 16));
01118 painter.save();
01119 style()->drawControl(QStyle::CE_RubberBand, &opt, &painter);
01120 painter.restore();
01121 }
01122 #endif
01123 }
01124
01128 QModelIndex QListView::indexAt(const QPoint &p) const
01129 {
01130 Q_D(const QListView);
01131 QRect rect(p.x() + horizontalOffset(), p.y() + verticalOffset(), 1, 1);
01132 d->intersectingSet(rect);
01133 QModelIndex index = d->intersectVector.count() > 0
01134 ? d->intersectVector.last() : QModelIndex();
01135 if (index.isValid() && visualRect(index).contains(p))
01136 return index;
01137 return QModelIndex();
01138 }
01139
01143 int QListView::horizontalOffset() const
01144 {
01145 Q_D(const QListView);
01146 if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem && d->movement == Static ) {
01147 if (d->wrap) {
01148 if (d->flow == TopToBottom && !d->segmentPositions.isEmpty()) {
01149 const int max = d->segmentPositions.count() - 1;
01150 int currentValue = qBound(0, horizontalScrollBar()->value(), max);
01151 int position = d->segmentPositions.at(currentValue);
01152 int maximumValue = qBound(0, horizontalScrollBar()->maximum(), max);
01153 int maximum = d->segmentPositions.at(maximumValue);
01154 return (isRightToLeft() ? maximum - position : position);
01155 }
01156
01157 } else {
01158 if (d->flow == LeftToRight && !d->flowPositions.isEmpty()) {
01159 int position = d->flowPositions.at(horizontalScrollBar()->value());
01160 int maximum = d->flowPositions.at(horizontalScrollBar()->maximum());
01161 return (isRightToLeft() ? maximum - position : position);
01162 }
01163
01164 }
01165 }
01166 return (isRightToLeft()
01167 ? horizontalScrollBar()->maximum() - horizontalScrollBar()->value()
01168 : horizontalScrollBar()->value());
01169 }
01170
01174 int QListView::verticalOffset() const
01175 {
01176 Q_D(const QListView);
01177 if (verticalScrollMode() == QAbstractItemView::ScrollPerItem && d->movement == Static) {
01178 if (d->wrap) {
01179 if (d->flow == LeftToRight && !d->segmentPositions.isEmpty()) {
01180 int value = verticalScrollBar()->value();
01181 if (value >= d->segmentPositions.count()) {
01182 qWarning("QListView: Vertical scrollbar is out of bounds");
01183 return 0;
01184 }
01185 return d->segmentPositions.at(value);
01186 }
01187 } else {
01188 if (d->flow == TopToBottom && !d->flowPositions.isEmpty()) {
01189 int value = verticalScrollBar()->value();
01190 if (value >= d->flowPositions.count()) {
01191 qWarning("QListView: Vertical scrollbar is out of bounds");
01192 return 0;
01193 }
01194 return d->flowPositions.at(value);
01195 }
01196 }
01197 }
01198 return verticalScrollBar()->value();
01199 }
01200
01204 QModelIndex QListView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
01205 {
01206 Q_D(QListView);
01207 Q_UNUSED(modifiers);
01208
01209 QModelIndex current = currentIndex();
01210 if (!current.isValid()) {
01211 int rowCount = d->model->rowCount(d->root);
01212 if (!rowCount)
01213 return QModelIndex();
01214 int row = 0;
01215 while (row < rowCount && isRowHidden(row))
01216 ++row;
01217 if (row >= rowCount)
01218 return QModelIndex();
01219 return d->model->index(row, 0, d->root);
01220 }
01221
01222 QRect rect = rectForIndex(current);
01223 if (rect.isEmpty()) {
01224 return d->model->index(0, 0, d->root);
01225 }
01226 if (d->gridSize.isValid()) rect.setSize(d->gridSize);
01227
01228 QSize contents = d->contentsSize;
01229 QPoint pos = rect.center();
01230 d->intersectVector.clear();
01231
01232 switch (cursorAction) {
01233 case MoveLeft:
01234 while (d->intersectVector.isEmpty()) {
01235 rect.translate(-rect.width(), 0);
01236 if (rect.right() <= 0)
01237 return current;
01238 if (rect.left() < 0)
01239 rect.setLeft(0);
01240 d->intersectingSet(rect);
01241
01242 int idx = d->intersectVector.indexOf(current);
01243 if (idx > -1)
01244 d->intersectVector.remove(idx);
01245 }
01246 return d->closestIndex(pos, d->intersectVector);
01247 case MoveRight:
01248 while (d->intersectVector.isEmpty()) {
01249 rect.translate(rect.width(), 0);
01250 if (rect.left() >= contents.width())
01251 return current;
01252 if (rect.right() > contents.width())
01253 rect.setRight(contents.width());
01254 d->intersectingSet(rect);
01255
01256 int idx = d->intersectVector.indexOf(current);
01257 if (idx > -1)
01258 d->intersectVector.remove(idx);
01259 }
01260 return d->closestIndex(pos, d->intersectVector);
01261 case MovePageUp:
01262 rect.moveTop(rect.top() - d->viewport->height());
01263 if (rect.top() < rect.height())
01264 rect.moveTop(rect.height());
01265 case MovePrevious:
01266 case MoveUp:
01267 while (d->intersectVector.isEmpty()) {
01268 rect.translate(0, -rect.height());
01269 if (rect.bottom() <= 0) {
01270 #ifdef QT_KEYPAD_NAVIGATION
01271 if (QApplication::keypadNavigationEnabled())
01272 return d->model->index(d->batchStartRow - 1, d->column, d->root);
01273 #endif
01274 return current;
01275 }
01276 if (rect.top() < 0)
01277 rect.setTop(0);
01278 d->intersectingSet(rect);
01279
01280 int idx = d->intersectVector.indexOf(current);
01281 if (idx > -1)
01282 d->intersectVector.remove(idx);
01283 }
01284 return d->closestIndex(pos, d->intersectVector);
01285 case MovePageDown:
01286 rect.moveTop(rect.top() + d->viewport->height());
01287 if (rect.bottom() > contents.height() - rect.height())
01288 rect.moveBottom(contents.height() - rect.height());
01289 case MoveNext:
01290 case MoveDown:
01291 while (d->intersectVector.isEmpty()) {
01292 rect.translate(0, rect.height());
01293 if (rect.top() >= contents.height()) {
01294 #ifdef QT_KEYPAD_NAVIGATION
01295 if (QApplication::keypadNavigationEnabled())
01296 return d->model->index(0, d->column, d->root);
01297 #endif
01298 return current;
01299 }
01300 if (rect.bottom() > contents.height())
01301 rect.setBottom(contents.height());
01302 d->intersectingSet(rect);
01303
01304 int idx = d->intersectVector.indexOf(current);
01305 if (idx > -1)
01306 d->intersectVector.remove(idx);
01307 }
01308 return d->closestIndex(pos, d->intersectVector);
01309 case MoveHome:
01310 return d->model->index(0, d->column, d->root);
01311 case MoveEnd:
01312 return d->model->index(d->batchStartRow - 1, d->column, d->root);
01313 }
01314
01315 return current;
01316 }
01317
01324 QRect QListView::rectForIndex(const QModelIndex &index) const
01325 {
01326 Q_D(const QListView);
01327 if (!d->isIndexValid(index)
01328 || index.parent() != d->root
01329 || index.column() != d->column
01330 || isIndexHidden(index))
01331 return QRect();
01332 d->executePostedLayout();
01333 QListViewItem item = d->indexToListViewItem(index);
01334 return d->viewItemRect(item);
01335 }
01336
01345 void QListView::setPositionForIndex(const QPoint &position, const QModelIndex &index)
01346 {
01347 Q_D(QListView);
01348 if (d->movement == Static
01349 || !d->isIndexValid(index)
01350 || index.parent() != d->root
01351 || index.column() != d->column)
01352 return;
01353 d->executePostedLayout();
01354 if (index.row() >= d->items.count())
01355 return;
01356 d->setDirtyRegion(visualRect(index));
01357 d->moveItem(index.row(), position);
01358 d->setDirtyRegion(visualRect(index));
01359 }
01360
01364 void QListView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command)
01365 {
01366 Q_D(QListView);
01367 if (!d->selectionModel)
01368 return;
01369
01370 d->intersectingSet(rect.translated(horizontalOffset(), verticalOffset()));
01371
01372 QItemSelection selection;
01373 QModelIndex tl;
01374 QModelIndex br;
01375
01376 if (rect.width() == 1 && rect.height() == 1 && !d->intersectVector.isEmpty()) {
01377 tl = br = d->intersectVector.last();
01378 } else {
01379 if (state() == DragSelectingState) {
01380 QVector<QModelIndex>::iterator it = d->intersectVector.begin();
01381 for (; it != d->intersectVector.end(); ++it) {
01382 if (!tl.isValid() && !br.isValid()) {
01383 tl = br = *it;
01384 } else if ((*it).row() == (tl.row() - 1)) {
01385 tl = *it;
01386 } else if ((*it).row() == (br.row() + 1)) {
01387 br = (*it);
01388 } else {
01389 selection.select(tl, br);
01390 tl = br = *it;
01391 }
01392 }
01393 } else {
01394 QVector<QModelIndex>::iterator it = d->intersectVector.begin();
01395 for (; it != d->intersectVector.end(); ++it) {
01396 if (!tl.isValid() && !br.isValid())
01397 tl = br = *it;
01398 else if ((*it).row() < tl.row())
01399 tl = (*it);
01400 else if ((*it).row() > br.row())
01401 br = (*it);
01402 }
01403 }
01404 }
01405
01406 if (tl.isValid() && br.isValid())
01407 selection.select(tl, br);
01408 d->selectionModel->select(selection, command);
01409 }
01410
01414 QRegion QListView::visualRegionForSelection(const QItemSelection &selection) const
01415 {
01416 Q_D(const QListView);
01417
01418 int c = d->column;
01419 QRegion selectionRegion;
01420 for (int i = 0; i < selection.count(); ++i) {
01421 if (!selection.at(i).isValid())
01422 continue;
01423 QModelIndex parent = selection.at(i).topLeft().parent();
01424 int t = selection.at(i).topLeft().row();
01425 int b = selection.at(i).bottomRight().row();
01426 if (d->movement != Static || d->wrap) {
01427 for (int r = t; r <= b; ++r)
01428 selectionRegion += QRegion(visualRect(d->model->index(r, c, parent)));
01429 } else {
01430 QRect rect(visualRect(d->model->index(t, c, parent)).topLeft(),
01431 visualRect(d->model->index(b, c, parent)).bottomRight());
01432 selectionRegion += QRegion(rect);
01433 }
01434 }
01435
01436 return selectionRegion;
01437 }
01438
01442 QModelIndexList QListView::selectedIndexes() const
01443 {
01444 Q_D(const QListView);
01445 QModelIndexList viewSelected;
01446 QModelIndexList modelSelected;
01447 if (d->selectionModel)
01448 modelSelected = d->selectionModel->selectedIndexes();
01449 for (int i = 0; i < modelSelected.count(); ++i) {
01450 QModelIndex index = modelSelected.at(i);
01451 if (!isIndexHidden(index) && index.parent() == d->root && index.column() == d->column)
01452 viewSelected.append(index);
01453 }
01454 return viewSelected;
01455 }
01456
01462 void QListView::doItemsLayout()
01463 {
01464 Q_D(QListView);
01465 d->layoutChildren();
01466 d->prepareItemsLayout();
01467 if (d->model->columnCount(d->root) > 0) {
01468 if (layoutMode() == SinglePass)
01469 d->doItemsLayout(d->model->rowCount(d->root));
01470 else if (!d->batchLayoutTimer.isActive())
01471 d->batchLayoutTimer.start(0, this);
01472 }
01473 QAbstractItemView::doItemsLayout();
01474 }
01475
01479 void QListView::updateGeometries()
01480 {
01481 Q_D(QListView);
01482 if (d->model->rowCount(d->root) <= 0 || d->model->columnCount(d->root) <= 0) {
01483 horizontalScrollBar()->setRange(0, 0);
01484 verticalScrollBar()->setRange(0, 0);
01485 } else {
01486 QModelIndex index = d->model->index(0, d->column, d->root);
01487 QStyleOptionViewItemV2 option = d->viewOptionsV2();
01488 QSize step = d->itemSize(option, index);
01489
01490 QSize csize = d->contentsSize;
01491 QSize vsize = d->viewport->size();
01492 QSize max = maximumViewportSize();
01493 if (max.width() >= d->contentsSize.width() && max.height() >= d->contentsSize.height())
01494 vsize = max;
01495
01496
01497
01498 const bool vertical = verticalScrollMode() == QAbstractItemView::ScrollPerItem;
01499 const bool horizontal = horizontalScrollMode() == QAbstractItemView::ScrollPerItem;
01500
01501 if (d->flow == TopToBottom) {
01502 if (horizontal && d->wrap && d->movement == Static) {
01503 int steps = d->segmentPositions.count();
01504 int pageSteps = d->perItemScrollingPageSteps(vsize.width(), csize.width());
01505 horizontalScrollBar()->setSingleStep(1);
01506 horizontalScrollBar()->setPageStep(pageSteps);
01507 horizontalScrollBar()->setRange(0, steps - pageSteps);
01508 } else {
01509 horizontalScrollBar()->setSingleStep(step.width() + d->spacing);
01510 horizontalScrollBar()->setPageStep(vsize.width());
01511 horizontalScrollBar()->setRange(0, d->contentsSize.width() - vsize.width());
01512 }
01513 if (vertical && !d->wrap && d->movement == Static) {
01514 int steps = d->flowPositions.count();
01515 int pageSteps = d->perItemScrollingPageSteps(vsize.height(), csize.height());
01516 verticalScrollBar()->setSingleStep(1);
01517 verticalScrollBar()->setPageStep(pageSteps);
01518 verticalScrollBar()->setRange(0, steps - pageSteps);
01519
01520
01521 } else {
01522 verticalScrollBar()->setSingleStep(step.height() + d->spacing);
01523 verticalScrollBar()->setPageStep(vsize.height());
01524 verticalScrollBar()->setRange(0, d->contentsSize.height() - vsize.height());
01525 }
01526 } else {
01527 if (horizontal && !d->wrap && d->movement == Static) {
01528 int steps = d->flowPositions.count();
01529 int pageSteps = d->perItemScrollingPageSteps(vsize.width(), csize.width());
01530 horizontalScrollBar()->setSingleStep(1);
01531 horizontalScrollBar()->setPageStep(pageSteps);
01532 horizontalScrollBar()->setRange(0, steps - pageSteps);
01533
01534
01535 } else {
01536 horizontalScrollBar()->setSingleStep(step.width() + d->spacing);
01537 horizontalScrollBar()->setPageStep(vsize.width());
01538 horizontalScrollBar()->setRange(0, d->contentsSize.width() - vsize.width());
01539 }
01540 if (vertical && d->wrap && d->movement == Static) {
01541 int steps = d->segmentPositions.count();
01542 int pageSteps = d->perItemScrollingPageSteps(vsize.height(), csize.height());
01543 verticalScrollBar()->setSingleStep(1);
01544 verticalScrollBar()->setPageStep(pageSteps);
01545 verticalScrollBar()->setRange(0, steps - pageSteps);
01546 } else {
01547 verticalScrollBar()->setSingleStep(step.height() + d->spacing);
01548 verticalScrollBar()->setPageStep(vsize.height());
01549 verticalScrollBar()->setRange(0, d->contentsSize.height() - vsize.height());
01550 }
01551 }
01552 }
01553
01554 if (d->movement == Static && !d->wrap) {
01555 if (d->flow == TopToBottom) {
01556 if (horizontalScrollBarPolicy() == Qt::ScrollBarAlwaysOff)
01557 d->contentsSize = QSize(viewport()->width(), contentsSize().height());
01558 } else {
01559 if (verticalScrollBarPolicy() == Qt::ScrollBarAlwaysOff)
01560 d->contentsSize = QSize(contentsSize().width(), viewport()->height());
01561 }
01562 }
01563
01564 QAbstractItemView::updateGeometries();
01565 }
01566
01570 bool QListView::isIndexHidden(const QModelIndex &index) const
01571 {
01572 Q_D(const QListView);
01573 return (d->hiddenRows.contains(index.row())
01574 && (index.parent() == d->root)
01575 && index.column() == d->column);
01576 }
01577
01582 void QListView::setModelColumn(int column)
01583 {
01584 Q_D(QListView);
01585 if (column < 0 || column >= d->model->columnCount(d->root))
01586 return;
01587 d->column = column;
01588 d->doDelayedItemsLayout();
01589 }
01590
01591 int QListView::modelColumn() const
01592 {
01593 Q_D(const QListView);
01594 return d->column;
01595 }
01596
01606 void QListView::setUniformItemSizes(bool enable)
01607 {
01608 Q_D(QListView);
01609 d->uniformItemSizes = enable;
01610 }
01611
01612 bool QListView::uniformItemSizes() const
01613 {
01614 Q_D(const QListView);
01615 return d->uniformItemSizes;
01616 }
01617
01627 void QListView::setWordWrap(bool on)
01628 {
01629 Q_D(QListView);
01630 if (d->wrapItemText == on)
01631 return;
01632 d->wrapItemText = on;
01633 d->doDelayedItemsLayout();
01634 }
01635
01636 bool QListView::wordWrap() const
01637 {
01638 Q_D(const QListView);
01639 return d->wrapItemText;
01640 }
01641
01645 bool QListView::event(QEvent *e)
01646 {
01647 return QAbstractItemView::event(e);
01648 }
01649
01650
01651
01652
01653
01654 QListViewPrivate::QListViewPrivate()
01655 : QAbstractItemViewPrivate(),
01656 layoutMode(QListView::SinglePass),
01657 modeProperties(0),
01658 batchStartRow(0),
01659 batchSavedDeltaSeg(0),
01660 batchSavedPosition(0),
01661 column(0),
01662 uniformItemSizes(false),
01663 batchSize(100),
01664 wrapItemText(false)
01665 {}
01666
01667 void QListViewPrivate::clear()
01668 {
01669
01670 batchStartRow = 0;
01671 batchSavedPosition = 0;
01672 batchSavedDeltaSeg = 0;
01673 cachedItemSize = QSize();
01674 tree.destroy();
01675 items.clear();
01676 moved.clear();
01677 flowPositions.clear();
01678 segmentPositions.clear();
01679 segmentStartRows.clear();
01680 }
01681
01682 void QListViewPrivate::prepareItemsLayout()
01683 {
01684 Q_Q(QListView);
01685 clear();
01686 layoutBounds = QRect(QPoint(0,0), q->maximumViewportSize());
01687
01688 int verticalMargin = q->style()->pixelMetric(QStyle::PM_ScrollBarExtent, 0, q->verticalScrollBar());
01689 int horizontalMargin = q->style()->pixelMetric(QStyle::PM_ScrollBarExtent, 0, q->horizontalScrollBar());
01690 layoutBounds.adjust(0, 0, -verticalMargin, -horizontalMargin);
01691
01692 int rowCount = model->rowCount(root);
01693 int colCount = model->columnCount(root);
01694 if (colCount <= 0)
01695 rowCount = 0;
01696 if (movement == QListView::Static) {
01697 flowPositions.resize(rowCount);
01698 } else {
01699 tree.create(qMax(rowCount - hiddenRows.count(), 0));
01700 }
01701 }
01702
01703 QPoint QListViewPrivate::initStaticLayout(const QRect &bounds, int spacing, int first)
01704 {
01705 int x, y;
01706 if (first == 0) {
01707 flowPositions.clear();
01708 segmentPositions.clear();
01709 segmentStartRows.clear();
01710 x = bounds.left() + spacing;
01711 y = bounds.top() + spacing;
01712 segmentPositions.append(flow == QListView::LeftToRight ? y : x);
01713 segmentStartRows.append(0);
01714 } else if (wrap) {
01715 if (flow == QListView::LeftToRight) {
01716 x = batchSavedPosition;
01717 y = segmentPositions.last();
01718 } else {
01719 x = segmentPositions.last();
01720 y = batchSavedPosition;
01721 }
01722 } else {
01723 if (flow == QListView::LeftToRight) {
01724 x = batchSavedPosition;
01725 y = bounds.top() + spacing;
01726 } else {
01727 x = bounds.left() + spacing;
01728 y = batchSavedPosition;
01729 }
01730 }
01731 return QPoint(x, y);
01732 }
01733
01734 QPoint QListViewPrivate::initDynamicLayout(const QRect &bounds, int spacing, int first)
01735 {
01736 int x, y;
01737 if (first == 0) {
01738 x = bounds.x() + spacing;
01739 y = bounds.y() + spacing;
01740 items.reserve(model->rowCount(root) - hiddenRows.count());
01741 } else {
01742 const QListViewItem item = items.at(first - 1);
01743 x = item.x;
01744 y = item.y;
01745 if (flow == QListView::LeftToRight)
01746 x += (gridSize.isValid() ? gridSize.width() : item.w) + spacing;
01747 else
01748 y += (gridSize.isValid() ? gridSize.height() : item.h) + spacing;
01749 }
01750 return QPoint(x, y);
01751 }
01752
01753 void QListViewPrivate::initBspTree(const QSize &contents)
01754 {
01755
01756 int leafCount = tree.leafCount();
01757 for (int l = 0; l < leafCount; ++l)
01758 tree.leaf(l).clear();
01759
01760 QBspTree::Node::Type type = QBspTree::Node::Both;
01761
01762 if (contents.height() / contents.width() >= 3)
01763 type = QBspTree::Node::HorizontalPlane;
01764 else if (contents.width() / contents.height() >= 3)
01765 type = QBspTree::Node::VerticalPlane;
01766
01767 tree.init(QRect(0, 0, contents.width(), contents.height()), type);
01768 }
01769
01773 bool QListViewPrivate::doItemsLayout(int delta)
01774 {
01775 int max = model->rowCount(root) - 1;
01776 int first = batchStartRow;
01777 int last = qMin(first + delta - 1, max);
01778
01779 if (max < 0)
01780 return true;
01781
01782 if (movement == QListView::Static) {
01783 doStaticLayout(layoutBounds, first, last);
01784 } else {
01785 if (last >= items.count())
01786 createItems(last + 1);
01787 doDynamicLayout(layoutBounds, first, last);
01788 }
01789
01790 if (batchStartRow >= max) {
01791 flowPositions.resize(flowPositions.count());
01792 segmentPositions.resize(segmentPositions.count());
01793 segmentStartRows.resize(segmentStartRows.count());
01794 return true;
01795 }
01796 return false;
01797 }
01798
01802 void QListViewPrivate::doItemsLayout(const QRect &bounds,
01803 const QModelIndex &first,
01804 const QModelIndex &last)
01805 {
01806 if (first.row() >= last.row() || !first.isValid() || !last.isValid())
01807 return;
01808 if (movement == QListView::Static)
01809 doStaticLayout(bounds, first.row(), last.row());
01810 else
01811 doDynamicLayout(bounds, first.row(), last.row());
01812 }
01813
01817 void QListViewPrivate::doStaticLayout(const QRect &bounds, int first, int last)
01818 {
01819 const bool useItemSize = !gridSize.isValid();
01820 const int gap = useItemSize ? spacing : 0;
01821 const QPoint topLeft = initStaticLayout(bounds, gap, first);
01822 const QStyleOptionViewItemV2 option = viewOptionsV2();
01823
01824
01825
01826
01827
01828
01829
01830 int segStartPosition;
01831 int segEndPosition;
01832 int deltaFlowPosition;
01833 int deltaSegPosition;
01834 int deltaSegHint;
01835 int flowPosition;
01836 int segPosition;
01837
01838 if (flow == QListView::LeftToRight) {
01839 segStartPosition = bounds.left();
01840 segEndPosition = bounds.width();
01841 flowPosition = topLeft.x();
01842 segPosition = topLeft.y();
01843 deltaFlowPosition = gridSize.width();
01844 deltaSegPosition = useItemSize ? batchSavedDeltaSeg : gridSize.height();
01845 deltaSegHint = gridSize.height();
01846 } else {
01847 segStartPosition = bounds.top();
01848 segEndPosition = bounds.height();
01849 flowPosition = topLeft.y();
01850 segPosition = topLeft.x();
01851 deltaFlowPosition = gridSize.height();
01852 deltaSegPosition = useItemSize ? batchSavedDeltaSeg : gridSize.width();
01853 deltaSegHint = gridSize.width();
01854 }
01855
01856 for (int row = first; row <= last; ++row) {
01857 if (hiddenRows.contains(row)) {
01858 flowPositions.append(flowPosition);
01859 } else {
01860
01861 if (useItemSize) {
01862 QSize hint = itemSize(option, model->index(row, column, root));
01863 if (flow == QListView::LeftToRight) {
01864 deltaFlowPosition = hint.width() + gap;
01865 deltaSegHint = hint.height() + gap;
01866 } else {
01867 deltaFlowPosition = hint.height() + gap;
01868 deltaSegHint = hint.width() + gap;
01869 }
01870 }
01871
01872 if (wrap && (flowPosition + deltaFlowPosition >= segEndPosition)) {
01873 flowPosition = gap + segStartPosition;
01874 segPosition += deltaSegPosition;
01875 segmentPositions.append(segPosition);
01876 segmentStartRows.append(row);
01877 deltaSegPosition = 0;
01878 }
01879
01880 flowPositions.append(flowPosition);
01881
01882 deltaSegPosition = qMax(deltaSegHint, deltaSegPosition);
01883 flowPosition += gap + deltaFlowPosition;
01884 }
01885 }
01886
01887 batchSavedPosition = flowPosition;
01888 batchSavedDeltaSeg = deltaSegPosition;
01889 batchStartRow = last + 1;
01890
01891 QRect rect = bounds;
01892 if (flow == QListView::LeftToRight) {
01893 rect.setRight(segmentPositions.count() == 1 ? flowPosition : bounds.right());
01894 rect.setBottom(segPosition + deltaSegPosition);
01895 } else {
01896 rect.setRight(segPosition + deltaSegPosition);
01897 rect.setBottom(segmentPositions.count() == 1 ? flowPosition : bounds.bottom());
01898 }
01899 contentsSize = QSize(rect.right(), rect.bottom());
01900
01901 QRect changedRect(topLeft, rect.bottomRight());
01902 if (clipRect().intersects(changedRect))
01903 viewport->update();
01904 }
01905
01909 void QListViewPrivate::doDynamicLayout(const QRect &bounds, int first, int last)
01910 {
01911 const bool useItemSize = !gridSize.isValid();
01912 const int gap = useItemSize ? spacing : 0;
01913 const QPoint topLeft = initDynamicLayout(bounds, spacing, first);
01914
01915 int segStartPosition;
01916 int segEndPosition;
01917 int deltaFlowPosition;
01918 int deltaSegPosition;
01919 int deltaSegHint;
01920 int flowPosition;
01921 int segPosition;
01922
01923 if (flow == QListView::LeftToRight) {
01924 segStartPosition = bounds.left() + spacing;
01925 segEndPosition = bounds.right();
01926 deltaFlowPosition = gridSize.width();
01927 deltaSegPosition = (useItemSize ? batchSavedDeltaSeg : gridSize.height());
01928 deltaSegHint = gridSize.height();
01929 flowPosition = topLeft.x();
01930 segPosition = topLeft.y();
01931 } else {
01932 segStartPosition = bounds.top() + spacing;
01933 segEndPosition = bounds.bottom();
01934 deltaFlowPosition = gridSize.height();
01935 deltaSegPosition = (useItemSize ? batchSavedDeltaSeg : gridSize.width());
01936 deltaSegHint = gridSize.width();
01937 flowPosition = topLeft.y();
01938 segPosition = topLeft.x();
01939 }
01940
01941 if (moved.count() != items.count())
01942 moved.resize(items.count());
01943
01944 QRect rect(QPoint(0, 0), topLeft);
01945 QListViewItem *item = 0;
01946 for (int row = first; row <= last; ++row) {
01947 item = &items[row];
01948 if (hiddenRows.contains(row)) {
01949 item->invalidate();
01950 } else {
01951
01952 if (useItemSize) {
01953 if (flow == QListView::LeftToRight)
01954 deltaFlowPosition = item->w + gap;
01955 else
01956 deltaFlowPosition = item->h + gap;
01957 } else {
01958 item->w = qMin<int>(gridSize.width(), item->w);
01959 item->h = qMin<int>(gridSize.height(), item->h);
01960 }
01961
01962
01963 if (wrap
01964 && flowPosition + deltaFlowPosition > segEndPosition
01965 && flowPosition > segStartPosition) {
01966 flowPosition = segStartPosition;
01967 segPosition += deltaSegPosition;
01968 if (useItemSize)
01969 deltaSegPosition = 0;
01970 }
01971
01972
01973 if (useItemSize) {
01974 if (flow == QListView::LeftToRight)
01975 deltaSegHint = item->h + gap;
01976 else
01977 deltaSegHint = item->w + gap;
01978 deltaSegPosition = qMax(deltaSegPosition, deltaSegHint);
01979 }
01980
01981
01982 if (!moved.testBit(row)) {
01983 if (flow == QListView::LeftToRight) {
01984 if (useItemSize) {
01985 item->x = flowPosition;
01986 item->y = segPosition;
01987 } else {
01988 item->x = flowPosition + ((deltaFlowPosition - item->w) / 2);
01989 item->y = segPosition + ((deltaSegPosition - item->h) / 2);
01990 }
01991 } else {
01992 if (useItemSize) {
01993 item->y = flowPosition;
01994 item->x = segPosition;
01995 } else {
01996 item->y = flowPosition + ((deltaFlowPosition - item->h) / 2);
01997 item->x = segPosition + ((deltaSegPosition - item->w) / 2);
01998 }
01999 }
02000 }
02001
02002
02003 if (useItemSize)
02004 rect |= item->rect();
02005 else if (flow == QListView::LeftToRight)
02006 rect |= QRect(flowPosition, segPosition, deltaFlowPosition, deltaSegPosition);
02007 else
02008 rect |= QRect(segPosition, flowPosition, deltaSegPosition, deltaFlowPosition);
02009
02010
02011 flowPosition += deltaFlowPosition;
02012 }
02013 }
02014 batchSavedDeltaSeg = deltaSegPosition;
02015 batchStartRow = last + 1;
02016 bool done = (last >= model->rowCount(root) - 1);
02017
02018 if (done || !bounds.contains(item->rect()))
02019 contentsSize = QSize(rect.width(), rect.height());
02020
02021 int insertFrom = first;
02022 if (done || first == 0) {
02023 initBspTree(rect.size());
02024 insertFrom = 0;
02025 }
02026
02027 for (int row = insertFrom; row <= last; ++row)
02028 tree.insertLeaf(items.at(row).rect(), row);
02029
02030 QRect changedRect(topLeft, rect.bottomRight());
02031 if (clipRect().intersects(changedRect))
02032 viewport->update();
02033 }
02034
02041 void QListViewPrivate::intersectingStaticSet(const QRect &area) const
02042 {
02043 intersectVector.clear();
02044 int segStartPosition;
02045 int segEndPosition;
02046 int flowStartPosition;
02047 int flowEndPosition;
02048 if (flow == QListView::LeftToRight) {
02049 segStartPosition = area.top();
02050 segEndPosition = area.bottom();
02051 flowStartPosition = area.left();
02052 flowEndPosition = area.right();
02053 } else {
02054 segStartPosition = area.left();
02055 segEndPosition = area.right();
02056 flowStartPosition = area.top();
02057 flowEndPosition = area.bottom();
02058 }
02059 if (segmentPositions.isEmpty() || flowPositions.isEmpty())
02060 return;
02061 const int segLast = segmentPositions.count() - 1;
02062 Q_ASSERT(segLast > -1);
02063 int seg = qBinarySearch<int>(segmentPositions, segStartPosition, 0, segLast);
02064 for (; seg <= segLast && segmentPositions.at(seg) <= segEndPosition; ++seg) {
02065 int first = segmentStartRows.at(seg);
02066 int last = (seg < segLast ? segmentStartRows.at(seg + 1) : batchStartRow) - 1;
02067 int row = qBinarySearch<int>(flowPositions, flowStartPosition, first, last);
02068 for (; row <= last && flowPositions.at(row) <= flowEndPosition; ++row) {
02069 if (hiddenRows.contains(row))
02070 continue;
02071 QModelIndex index = model->index(row, column, root);
02072 if (index.isValid())
02073 intersectVector.append(index);
02074 else
02075 qWarning("intersectingStaticSet: row %d was invalid", row);
02076 }
02077 }
02078 }
02079
02080 void QListViewPrivate::intersectingDynamicSet(const QRect &area) const
02081 {
02082 intersectVector.clear();
02083 QListViewPrivate *that = const_cast<QListViewPrivate*>(this);
02084 QBspTree::Data data(static_cast<void*>(that));
02085 that->tree.climbTree(area, &QListViewPrivate::addLeaf, data);
02086 }
02087
02088 void QListViewPrivate::createItems(int to)
02089 {
02090 int count = items.count();
02091 QSize size;
02092 QStyleOptionViewItemV2 option = viewOptionsV2();
02093 for (int row = count; row < to; ++row) {
02094 size = itemSize(option, model->index(row, column, root));
02095 QListViewItem item(QRect(0, 0, size.width(), size.height()), row);
02096 items.append(item);
02097 }
02098 }
02099
02100 void QListViewPrivate::drawItems(QPainter *painter, const QVector<QModelIndex> &indexes) const
02101 {
02102 QStyleOptionViewItemV2 option = viewOptionsV2();
02103 option.state &= ~QStyle::State_MouseOver;
02104 QVector<QModelIndex>::const_iterator it = indexes.begin();
02105 QListViewItem item = indexToListViewItem(*it);
02106 for (; it != indexes.end(); ++it) {
02107 item = indexToListViewItem(*it);
02108 option.rect = viewItemRect(item);
02109 delegateForIndex(*it)->paint(painter, option, *it);
02110 }
02111 }
02112
02113 QRect QListViewPrivate::itemsRect(const QVector<QModelIndex> &indexes) const
02114 {
02115 QVector<QModelIndex>::const_iterator it = indexes.begin();
02116 QListViewItem item = indexToListViewItem(*it);
02117 QRect rect(item.x, item.y, item.w, item.h);
02118 for (; it != indexes.end(); ++it) {
02119 item = indexToListViewItem(*it);
02120 rect |= viewItemRect(item);
02121 }
02122 return rect;
02123 }
02124
02125 QListViewItem QListViewPrivate::indexToListViewItem(const QModelIndex &index) const
02126 {
02127 if (!index.isValid() || hiddenRows.contains(index.row()))
02128 return QListViewItem();
02129
02130 if (movement != QListView::Static)
02131 if (index.row() < items.count())
02132 return items.at(index.row());
02133 else
02134 return QListViewItem();
02135
02136
02137 if (flowPositions.isEmpty()
02138 || segmentPositions.isEmpty()
02139 || index.row() >= flowPositions.count())
02140 return QListViewItem();
02141
02142 const int segment = qBinarySearch<int>(segmentStartRows, index.row(),
02143 0, segmentStartRows.count() - 1);
02144
02145
02146 QSize size = (uniformItemSizes && cachedItemSize.isValid())
02147 ? cachedItemSize : itemSize(viewOptionsV2(), index);
02148
02149 QPoint pos;
02150 if (flow == QListView::LeftToRight) {
02151 pos.setX(flowPositions.at(index.row()));
02152 pos.setY(segmentPositions.at(segment));
02153 } else {
02154 pos.setY(flowPositions.at(index.row()));
02155 pos.setX(segmentPositions.at(segment));
02156 if (wrap) {
02157 int right = (segment + 1 >= segmentPositions.count()
02158 ? contentsSize.width()
02159 : segmentPositions.at(segment + 1));
02160 size.setWidth(right - pos.x());
02161 }
02162 }
02163
02164 return QListViewItem(QRect(pos, size), index.row());
02165 }
02166
02167 int QListViewPrivate::itemIndex(const QListViewItem &item) const
02168 {
02169 int i = item.indexHint;
02170 if (movement == QListView::Static || items.at(i) == item)
02171 return i;
02172 if (i >= items.count())
02173 i = items.count() - 1;
02174
02175 int j = i;
02176 int c = items.count();
02177 bool a = true;
02178 bool b = true;
02179
02180 while (a || b) {
02181 if (a) {
02182 if (items.at(i) == item) {
02183 items.at(i).indexHint = i;
02184 return i;
02185 }
02186 a = ++i < c;
02187 }
02188 if (b) {
02189 if (items.at(j) == item) {
02190 items.at(j).indexHint = j;
02191 return j;
02192 }
02193 b = --j > -1;
02194 }
02195 }
02196 return -1;
02197 }
02198
02199 void QListViewPrivate::addLeaf(QVector<int> &leaf, const QRect &area,
02200 uint visited, QBspTree::Data data)
02201 {
02202 QListViewItem *vi;
02203 QListViewPrivate *_this = static_cast<QListViewPrivate *>(data.ptr);
02204 for (int i = 0; i < leaf.count(); ++i) {
02205 int idx = leaf.at(i);
02206 if (idx < 0 || idx >= _this->items.count())
02207 continue;
02208 vi = &_this->items[idx];
02209 Q_ASSERT(vi);
02210 if (vi->rect().intersects(area) && vi->visited != visited) {
02211 QModelIndex index = _this->listViewItemToIndex(*vi);
02212 Q_ASSERT(index.isValid());
02213 _this->intersectVector.append(index);
02214 vi->visited = visited;
02215 }
02216 }
02217 }
02218
02219 void QListViewPrivate::insertItem(int index)
02220 {
02221 if (index >= 0 && index < items.count())
02222 tree.insertLeaf(items.at(index).rect(), index);
02223 }
02224
02225 void QListViewPrivate::removeItem(int index)
02226 {
02227 if (index >= 0 && index < items.count())
02228 tree.removeLeaf(items.at(index).rect(), index);
02229 }
02230
02231 void QListViewPrivate::moveItem(int index, const QPoint &dest)
02232 {
02233
02234 QListViewItem *item = &items[index];
02235 QRect rect = item->rect();
02236
02237
02238 tree.removeLeaf(rect, index);
02239 item->move(dest);
02240 tree.insertLeaf(QRect(dest, rect.size()), index);
02241
02242
02243 int w = rect.x() + rect.width();
02244 int h = rect.y() + rect.height();
02245 w = w > contentsSize.width() ? w : contentsSize.width();
02246 h = h > contentsSize.height() ? h : contentsSize.height();
02247 contentsSize = QSize(w, h);
02248
02249 if (moved.count() != items.count())
02250 moved.resize(items.count());
02251 moved.setBit(index, true);
02252 }
02253
02254 QPoint QListViewPrivate::snapToGrid(const QPoint &pos) const
02255 {
02256 int x = pos.x() - (pos.x() % gridSize.width());
02257 int y = pos.y() - (pos.y() % gridSize.height());
02258 return QPoint(x, y);
02259 }
02260
02261 QRect QListViewPrivate::mapToViewport(const QRect &rect) const
02262 {
02263 Q_Q(const QListView);
02264 if (!rect.isValid())
02265 return rect;
02266 QRect result = rect;
02267
02268
02269 if (!wrap && movement == QListView::Static) {
02270 QSize vsize = viewport->size();
02271 QSize csize = (q->horizontalScrollBarPolicy() == Qt::ScrollBarAlwaysOff ? vsize : contentsSize);
02272 if (flow == QListView::TopToBottom) {
02273 if (q_func()->isRightToLeft())
02274 result.setLeft(result.right() - qMax(csize.width(), vsize.width()));
02275 else
02276 result.setWidth(qMax(csize.width(), vsize.width()));
02277 } else {
02278 result.setHeight(qMax(csize.height(), vsize.height()));
02279 }
02280 }
02281
02282 int dx = -q->horizontalOffset();
02283 int dy = -q->verticalOffset();
02284 result.adjust(dx, dy, dx, dy);
02285 return result;
02286 }
02287
02288 QPoint QListViewPrivate::draggedItemsDelta() const
02289 {
02290 if (movement == QListView::Snap) {
02291 QPoint snapdelta = QPoint((offset().x() % gridSize.width()),
02292 (offset().y() % gridSize.height()));
02293 return snapToGrid(draggedItemsPos + snapdelta) - snapToGrid(pressedPosition) - snapdelta;
02294 }
02295 return draggedItemsPos - pressedPosition;
02296 }
02297
02298 QRect QListViewPrivate::draggedItemsRect() const
02299 {
02300 QRect rect = itemsRect(draggedItems);
02301 rect.translate(draggedItemsDelta());
02302 return rect;
02303 }
02304
02305 QModelIndex QListViewPrivate::closestIndex(const QPoint &target,
02306 const QVector<QModelIndex> &candidates) const
02307 {
02308 int distance = 0;
02309 int shortest = -1;
02310 QModelIndex closest;
02311 QVector<QModelIndex>::const_iterator it = candidates.begin();
02312 for (; it != candidates.end(); ++it) {
02313 if (!(*it).isValid())
02314 continue;
02315 distance = (indexToListViewItem(*it).rect().center() - target).manhattanLength();
02316 if (distance < shortest || shortest == -1) {
02317 shortest = distance;
02318 closest = *it;
02319 }
02320 }
02321 return closest;
02322 }
02323
02324 QSize QListViewPrivate::itemSize(const QStyleOptionViewItem &option, const QModelIndex &index) const
02325 {
02326 if (!uniformItemSizes) {
02327 const QAbstractItemDelegate *delegate = delegateForIndex(index);
02328 return delegate ? delegate->sizeHint(option, index) : QSize();
02329 }
02330 if (!cachedItemSize.isValid()) {
02331 int row = model->rowCount(root) - 1;
02332 QModelIndex sample = model->index(row, column, root);
02333 const QAbstractItemDelegate *delegate = delegateForIndex(sample);
02334 cachedItemSize = delegate ? delegate->sizeHint(option, sample) : QSize();
02335 }
02336 return cachedItemSize;
02337 }
02338
02339 int QListViewPrivate::perItemScrollingPageSteps(int length, int bounds) const
02340 {
02341 const QVector<int> positions = (wrap ? segmentPositions : flowPositions);
02342 if (positions.isEmpty() || bounds <= length)
02343 return positions.count();
02344 if (uniformItemSizes) {
02345 for (int i = 1; i < positions.count(); ++i)
02346 if (positions.at(i) > 0)
02347 return length / positions.at(i);
02348 return 0;
02349 }
02350 int pageSteps = 0;
02351 int steps = positions.count() - 1;
02352 int max = qMax(length, bounds);
02353 int min = qMin(length, bounds);
02354 int pos = min - (max - positions.last());
02355 while (pos >= 0 && steps > 0) {
02356 pos -= (positions.at(steps) - positions.at(steps - 1));
02357 ++pageSteps;
02358 --steps;
02359 }
02360
02361 return qMax(pageSteps, 1);
02362 }
02363
02364 int QListViewPrivate::perItemScrollToValue(int index, int scrollValue, int viewportSize,
02365 QAbstractItemView::ScrollHint hint,
02366 Qt::Orientation orientation) const
02367 {
02368 if (index < 0)
02369 return scrollValue;
02370 if (!wrap) {
02371 const int flowCount = flowPositions.count() - 2;
02372 const int topIndex = scrollValue;
02373 const int topCoordinate = flowPositions.at(topIndex);
02374 int bottomIndex = topIndex;
02375 int bottomCoordinate = topCoordinate;
02376 while ((bottomCoordinate - topCoordinate) <= (viewportSize)
02377 && bottomIndex <= flowCount)
02378 bottomCoordinate = flowPositions.at(++bottomIndex);
02379 const int itemCount = bottomIndex - topIndex - 1;
02380 switch (hint) {
02381 case QAbstractItemView::PositionAtTop:
02382 return index;
02383 case QAbstractItemView::PositionAtBottom:
02384 return index - itemCount + 1;
02385 case QAbstractItemView::PositionAtCenter:
02386 return index - (itemCount / 2);
02387 default:
02388 break;
02389 }
02390 } else {
02391 Qt::Orientation flowOrientation =
02392 (flow == QListView::LeftToRight ? Qt::Horizontal : Qt::Vertical);
02393 if (flowOrientation == orientation) {
02394
02395 return flowPositions.at(index);
02396 } else if (!segmentStartRows.isEmpty()) {
02397 int segment = qBinarySearch<int>(segmentStartRows, index,
02398 0, segmentStartRows.count() - 1);
02399 const int segmentPositionCount = segmentPositions.count() - 2;
02400 const int leftSegment = segment;
02401 const int leftCoordinate = segmentPositions.at(leftSegment);
02402 int rightSegment = leftSegment;
02403 int rightCoordinate = leftCoordinate;
02404 while ((rightCoordinate - leftCoordinate) < (viewportSize - 1)
02405 && rightSegment < segmentPositionCount)
02406 rightCoordinate = segmentPositions.at(++rightSegment);
02407 const int segmentCount = rightSegment - leftSegment - 1;
02408 switch (hint) {
02409 case QAbstractItemView::PositionAtTop:
02410 return segment;
02411 case QAbstractItemView::PositionAtBottom:
02412 return segment - segmentCount + 1;
02413 case QAbstractItemView::PositionAtCenter:
02414 return segment - (segmentCount / 2);
02415 default:
02416 break;
02417 }
02418 }
02419 }
02420 return scrollValue;
02421 }
02422
02423 QStyleOptionViewItemV2 QListViewPrivate::viewOptionsV2() const
02424 {
02425 Q_Q(const QListView);
02426 QStyleOptionViewItemV2 option = q->viewOptions();
02427 if (wrapItemText)
02428 option.features = QStyleOptionViewItemV2::WrapText;
02429 return option;
02430 }
02431
02432 #endif // QT_NO_LISTVIEW