QtBase  v6.3.1
qlistview.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Copyright (C) 2013 Samuel Gaist <samuel.gaist@deltech.ch>
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of the QtWidgets module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU Lesser General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU Lesser
20 ** General Public License version 3 as published by the Free Software
21 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
22 ** packaging of this file. Please review the following information to
23 ** ensure the GNU Lesser General Public License version 3 requirements
24 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25 **
26 ** GNU General Public License Usage
27 ** Alternatively, this file may be used under the terms of the GNU
28 ** General Public License version 2.0 or (at your option) the GNU General
29 ** Public license version 3 or any later version approved by the KDE Free
30 ** Qt Foundation. The licenses are as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32 ** included in the packaging of this file. Please review the following
33 ** information to ensure the GNU General Public License requirements will
34 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35 ** https://www.gnu.org/licenses/gpl-3.0.html.
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 #include "qlistview.h"
42 
43 #include <qabstractitemdelegate.h>
44 #ifndef QT_NO_ACCESSIBILITY
45 #include <qaccessible.h>
46 #endif
47 #include <qapplication.h>
48 #include <qpainter.h>
49 #include <qbitmap.h>
50 #include <qdebug.h>
51 #if QT_CONFIG(draganddrop)
52 #include <qdrag.h>
53 #endif
54 #include <qevent.h>
55 #include <qlist.h>
56 #if QT_CONFIG(rubberband)
57 #include <qrubberband.h>
58 #endif
59 #include <qscrollbar.h>
60 #include <qstyle.h>
61 #include <private/qapplication_p.h>
62 #include <private/qlistview_p.h>
63 #include <private/qscrollbar_p.h>
64 
65 #include <algorithm>
66 
68 
69 extern bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event);
70 
183 {
184  setViewMode(ListMode);
185  setSelectionMode(SingleSelection);
187  Q_D(QListView); // We rely on a qobject_cast for PM_DefaultFrameWidth to change
188  d->updateStyledFrameWidths(); // hence we have to force an update now that the object has been constructed
189 }
190 
196 {
200  Q_D(QListView); // We rely on a qobject_cast for PM_DefaultFrameWidth to change
201  d->updateStyledFrameWidths(); // hence we have to force an update now that the object has been constructed
202 }
203 
208 {
209 }
210 
231 {
232  Q_D(QListView);
233  d->modeProperties |= uint(QListViewPrivate::Movement);
234  d->movement = movement;
235 
236 #if QT_CONFIG(draganddrop)
237  bool movable = (movement != Static);
238  setDragEnabled(movable);
239  d->viewport->setAcceptDrops(movable);
240 #endif
241  d->doDelayedItemsLayout();
242 }
243 
245 {
246  Q_D(const QListView);
247  return d->movement;
248 }
249 
268 {
269  Q_D(QListView);
270  d->modeProperties |= uint(QListViewPrivate::Flow);
271  d->flow = flow;
272  d->doDelayedItemsLayout();
273 }
274 
276 {
277  Q_D(const QListView);
278  return d->flow;
279 }
280 
297 {
298  Q_D(QListView);
299  d->modeProperties |= uint(QListViewPrivate::Wrap);
300  d->setWrapping(enable);
301  d->doDelayedItemsLayout();
302 }
303 
305 {
306  Q_D(const QListView);
307  return d->isWrapping();
308 }
309 
323 {
324  Q_D(QListView);
325  d->modeProperties |= uint(QListViewPrivate::ResizeMode);
326  d->resizeMode = mode;
327 }
328 
330 {
331  Q_D(const QListView);
332  return d->resizeMode;
333 }
334 
349 {
350  Q_D(QListView);
351  d->layoutMode = mode;
352 }
353 
355 {
356  Q_D(const QListView);
357  return d->layoutMode;
358 }
359 
374 void QListView::setSpacing(int space)
375 {
376  Q_D(QListView);
377  d->modeProperties |= uint(QListViewPrivate::Spacing);
378  d->setSpacing(space);
379  d->doDelayedItemsLayout();
380 }
381 
383 {
384  Q_D(const QListView);
385  return d->spacing();
386 }
387 
398 void QListView::setBatchSize(int batchSize)
399 {
400  Q_D(QListView);
401  if (Q_UNLIKELY(batchSize <= 0)) {
402  qWarning("Invalid batchSize (%d)", batchSize);
403  return;
404  }
405  d->batchSize = batchSize;
406 }
407 
409 {
410  Q_D(const QListView);
411  return d->batchSize;
412 }
413 
430 {
431  Q_D(QListView);
432  d->modeProperties |= uint(QListViewPrivate::GridSize);
433  d->setGridSize(size);
434  d->doDelayedItemsLayout();
435 }
436 
438 {
439  Q_D(const QListView);
440  return d->gridSize();
441 }
442 
459 {
460  Q_D(QListView);
461  if (d->commonListView && d->viewMode == mode)
462  return;
463  d->viewMode = mode;
464 
465  delete d->commonListView;
466  if (mode == ListMode) {
467  d->commonListView = new QListModeViewBase(this, d);
468  if (!(d->modeProperties & QListViewPrivate::Wrap))
469  d->setWrapping(false);
470  if (!(d->modeProperties & QListViewPrivate::Spacing))
471  d->setSpacing(0);
472  if (!(d->modeProperties & QListViewPrivate::GridSize))
473  d->setGridSize(QSize());
474  if (!(d->modeProperties & QListViewPrivate::Flow))
475  d->flow = TopToBottom;
476  if (!(d->modeProperties & QListViewPrivate::Movement))
477  d->movement = Static;
478  if (!(d->modeProperties & QListViewPrivate::ResizeMode))
479  d->resizeMode = Fixed;
480  if (!(d->modeProperties & QListViewPrivate::SelectionRectVisible))
481  d->showElasticBand = false;
482  } else {
483  d->commonListView = new QIconModeViewBase(this, d);
484  if (!(d->modeProperties & QListViewPrivate::Wrap))
485  d->setWrapping(true);
486  if (!(d->modeProperties & QListViewPrivate::Spacing))
487  d->setSpacing(0);
488  if (!(d->modeProperties & QListViewPrivate::GridSize))
489  d->setGridSize(QSize());
490  if (!(d->modeProperties & QListViewPrivate::Flow))
491  d->flow = LeftToRight;
492  if (!(d->modeProperties & QListViewPrivate::Movement))
493  d->movement = Free;
494  if (!(d->modeProperties & QListViewPrivate::ResizeMode))
495  d->resizeMode = Fixed;
496  if (!(d->modeProperties & QListViewPrivate::SelectionRectVisible))
497  d->showElasticBand = true;
498  }
499 
500 #if QT_CONFIG(draganddrop)
501  bool movable = (d->movement != Static);
502  setDragEnabled(movable);
503  setAcceptDrops(movable);
504 #endif
505  d->clear();
506  d->doDelayedItemsLayout();
507 }
508 
510 {
511  Q_D(const QListView);
512  return d->viewMode;
513 }
514 
525 {
526  Q_D(QListView);
527  d->modeProperties = 0;
528 }
529 
534 {
535  Q_D(const QListView);
536  return d->isHidden(row);
537 }
538 
544 {
545  Q_D(QListView);
546  const bool hidden = d->isHidden(row);
547  if (hide && !hidden)
548  d->commonListView->appendHiddenRow(row);
549  else if (!hide && hidden)
550  d->commonListView->removeHiddenRow(row);
551  d->doDelayedItemsLayout();
552  d->viewport->update();
553 }
554 
559 {
560  Q_D(const QListView);
561  return d->mapToViewport(rectForIndex(index));
562 }
563 
568 {
569  Q_D(QListView);
570 
571  if (index.parent() != d->root || index.column() != d->column)
572  return;
573 
574  const QRect rect = visualRect(index);
575  if (!rect.isValid())
576  return;
577  if (hint == EnsureVisible && d->viewport->rect().contains(rect)) {
578  d->viewport->update(rect);
579  return;
580  }
581 
582  if (d->flow == QListView::TopToBottom || d->isWrapping()) // vertical
583  verticalScrollBar()->setValue(d->verticalScrollToValue(index, rect, hint));
584 
585  if (d->flow == QListView::LeftToRight || d->isWrapping()) // horizontal
586  horizontalScrollBar()->setValue(d->horizontalScrollToValue(index, rect, hint));
587 }
588 
590  QListView::ScrollHint hint) const
591 {
592  Q_Q(const QListView);
593  const QRect area = viewport->rect();
594  const bool leftOf = q->isRightToLeft()
595  ? (rect.left() < area.left()) && (rect.right() < area.right())
596  : rect.left() < area.left();
597  const bool rightOf = q->isRightToLeft()
598  ? rect.right() > area.right()
599  : (rect.right() > area.right()) && (rect.left() > area.left());
600  return commonListView->horizontalScrollToValue(q->visualIndex(index), hint, leftOf, rightOf, area, rect);
601 }
602 
604  QListView::ScrollHint hint) const
605 {
606  Q_Q(const QListView);
607  const QRect area = viewport->rect();
608  const bool above = (hint == QListView::EnsureVisible && rect.top() < area.top());
609  const bool below = (hint == QListView::EnsureVisible && rect.bottom() > area.bottom());
610  return commonListView->verticalScrollToValue(q->visualIndex(index), hint, above, below, area, rect);
611 }
612 
613 void QListViewPrivate::selectAll(QItemSelectionModel::SelectionFlags command)
614 {
615  if (!selectionModel)
616  return;
617 
619  QModelIndex topLeft;
620  int row = 0;
621  const int colCount = model->columnCount(root);
622  for(; row < model->rowCount(root); ++row) {
623  if (isHidden(row)) {
624  //it might be the end of a selection range
625  if (topLeft.isValid()) {
626  QModelIndex bottomRight = model->index(row - 1, colCount - 1, root);
627  selection.append(QItemSelectionRange(topLeft, bottomRight));
628  topLeft = QModelIndex();
629  }
630  continue;
631  }
632 
633  if (!topLeft.isValid()) //start of a new selection range
634  topLeft = model->index(row, 0, root);
635  }
636 
637  if (topLeft.isValid()) {
638  //last selected range
639  QModelIndex bottomRight = model->index(row - 1, colCount - 1, root);
640  selection.append(QItemSelectionRange(topLeft, bottomRight));
641  }
642 
643  if (!selection.isEmpty())
644  selectionModel->select(selection, command);
645 }
646 
654 {
655  Q_ASSERT(r);
656  Q_Q(const QListView);
657  QRect &rect = *r;
658  const QRect viewportRect = viewport->rect();
660  QList<QModelIndex> visibleIndexes =
661  intersectingSet(viewportRect.translated(q->horizontalOffset(), q->verticalOffset()));
662  std::sort(visibleIndexes.begin(), visibleIndexes.end());
663  for (const auto &index : indexes) {
664  if (std::binary_search(visibleIndexes.cbegin(), visibleIndexes.cend(), index)) {
665  const QRect current = q->visualRect(index);
666  ret.append({current, index});
667  rect |= current;
668  }
669  }
670  QRect clipped = rect & viewportRect;
671  rect.setLeft(clipped.left());
672  rect.setRight(clipped.right());
673  return ret;
674 }
675 
680 {
681  Q_D(QListView);
682  d->clear();
683  d->hiddenRows.clear();
685 }
686 
691 {
692  Q_D(QListView);
693  d->column = qMax(0, qMin(d->column, d->model->columnCount(index) - 1));
695  // sometimes we get an update before reset() is called
696  d->clear();
697  d->hiddenRows.clear();
698 }
699 
706 void QListView::scrollContentsBy(int dx, int dy)
707 {
708  Q_D(QListView);
709  d->delayedAutoScroll.stop(); // auto scroll was canceled by the user scrolling
710  d->commonListView->scrollContentsBy(dx, dy, d->state == QListView::DragSelectingState);
711 }
712 
720 {
721  Q_D(QListView);
722  d->setContentsSize(width, height);
723 }
724 
729 {
730  Q_D(const QListView);
731  return d->contentsSize();
732 }
733 
737 void QListView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
738  const QList<int> &roles)
739 {
740  d_func()->commonListView->dataChanged(topLeft, bottomRight);
741  QAbstractItemView::dataChanged(topLeft, bottomRight, roles);
742 }
743 
748 {
749  Q_D(QListView);
750  // ### be smarter about inserted items
751  d->clear();
752  d->doDelayedItemsLayout();
754 }
755 
760 {
761  Q_D(QListView);
762  // if the parent is above d->root in the tree, nothing will happen
764  if (parent == d->root) {
765  QSet<QPersistentModelIndex>::iterator it = d->hiddenRows.begin();
766  while (it != d->hiddenRows.end()) {
767  int hiddenRow = it->row();
768  if (hiddenRow >= start && hiddenRow <= end) {
769  it = d->hiddenRows.erase(it);
770  } else {
771  ++it;
772  }
773  }
774  }
775  d->clear();
776  d->doDelayedItemsLayout();
777 }
778 
783 {
784  if (!isVisible())
785  return;
786  Q_D(QListView);
788  if (state() == DragSelectingState
789  && d->showElasticBand
790  && d->selectionMode != SingleSelection
791  && d->selectionMode != NoSelection) {
792  QRect rect(d->pressedPosition, e->position().toPoint() + QPoint(horizontalOffset(), verticalOffset()));
793  rect = rect.normalized();
794  d->viewport->update(d->mapToViewport(rect.united(d->elasticBand)));
795  d->elasticBand = rect;
796  }
797 }
798 
803 {
804  Q_D(QListView);
806  // #### move this implementation into a dynamic class
807  if (d->showElasticBand && d->elasticBand.isValid()) {
808  d->viewport->update(d->mapToViewport(d->elasticBand));
809  d->elasticBand = QRect();
810  }
811 }
812 
813 #if QT_CONFIG(wheelevent)
817 void QListView::wheelEvent(QWheelEvent *e)
818 {
819  Q_D(QListView);
820  if (qAbs(e->angleDelta().y()) > qAbs(e->angleDelta().x())) {
821  if (e->angleDelta().x() == 0
822  && ((d->flow == TopToBottom && d->wrap) || (d->flow == LeftToRight && !d->wrap))
823  && d->vbar->minimum() == 0 && d->vbar->maximum() == 0) {
824  QPoint pixelDelta(e->pixelDelta().y(), e->pixelDelta().x());
825  QPoint angleDelta(e->angleDelta().y(), e->angleDelta().x());
826  QWheelEvent hwe(e->position(), e->globalPosition(), pixelDelta, angleDelta,
827  e->buttons(), e->modifiers(), e->phase(), e->inverted(), e->source());
828  if (e->spontaneous())
829  qt_sendSpontaneousEvent(d->hbar, &hwe);
830  else
831  QCoreApplication::sendEvent(d->hbar, &hwe);
832  e->setAccepted(hwe.isAccepted());
833  } else {
835  }
836  } else {
838  }
839 }
840 #endif // QT_CONFIG(wheelevent)
841 
846 {
847  Q_D(QListView);
848  if (e->timerId() == d->batchLayoutTimer.timerId()) {
849  if (d->doItemsLayout(d->batchSize)) { // layout is done
850  d->batchLayoutTimer.stop();
852  d->viewport->update();
853  }
854  }
856 }
857 
862 {
863  Q_D(QListView);
864  if (d->delayedPendingLayout)
865  return;
866 
867  QSize delta = e->size() - e->oldSize();
868 
869  if (delta.isNull())
870  return;
871 
872  bool listWrap = (d->viewMode == ListMode) && d->wrapItemText;
873  bool flowDimensionChanged = (d->flow == LeftToRight && delta.width() != 0)
874  || (d->flow == TopToBottom && delta.height() != 0);
875 
876  // We post a delayed relayout in the following cases :
877  // - we're wrapping
878  // - the state is NoState, we're adjusting and the size has changed in the flowing direction
879  if (listWrap
880  || (state() == NoState && d->resizeMode == Adjust && flowDimensionChanged)) {
881  d->doDelayedItemsLayout(100); // wait 1/10 sec before starting the layout
882  } else {
884  }
885 }
886 
887 #if QT_CONFIG(draganddrop)
888 
892 void QListView::dragMoveEvent(QDragMoveEvent *e)
893 {
894  Q_D(QListView);
895  if (!d->commonListView->filterDragMoveEvent(e)) {
897  static_cast<QListModeViewBase *>(d->commonListView)->dragMoveEvent(e);
898  else
899  QAbstractItemView::dragMoveEvent(e);
900  }
901 }
902 
903 
907 void QListView::dragLeaveEvent(QDragLeaveEvent *e)
908 {
909  if (!d_func()->commonListView->filterDragLeaveEvent(e))
910  QAbstractItemView::dragLeaveEvent(e);
911 }
912 
916 void QListView::dropEvent(QDropEvent *event)
917 {
918  Q_D(QListView);
919 
920  if (event->source() == this && (event->dropAction() == Qt::MoveAction ||
921  dragDropMode() == QAbstractItemView::InternalMove)) {
922  QModelIndex topIndex;
923  bool topIndexDropped = false;
924  int col = -1;
925  int row = -1;
926  // check whether a subclass has already accepted the event, ie. moved the data
927  if (!event->isAccepted() && d->dropOn(event, &row, &col, &topIndex)) {
928  const QList<QModelIndex> selIndexes = selectedIndexes();
929  QList<QPersistentModelIndex> persIndexes;
930  persIndexes.reserve(selIndexes.count());
931 
932  for (const auto &index : selIndexes) {
933  persIndexes.append(index);
934  if (index == topIndex) {
935  topIndexDropped = true;
936  break;
937  }
938  }
939 
940  if (!topIndexDropped && !topIndex.isValid()) {
941  std::sort(persIndexes.begin(), persIndexes.end()); // The dropped items will remain in the same visual order.
942 
943  QPersistentModelIndex dropRow = model()->index(row, col, topIndex);
944 
945  int r = row == -1 ? model()->rowCount() : (dropRow.row() >= 0 ? dropRow.row() : row);
946  bool dataMoved = false;
947  for (int i = 0; i < persIndexes.count(); ++i) {
948  const QPersistentModelIndex &pIndex = persIndexes.at(i);
949  if (r != pIndex.row()) {
950  // try to move (preserves selection)
951  dataMoved |= model()->moveRow(QModelIndex(), pIndex.row(), QModelIndex(), r);
952  if (!dataMoved) // can't move - abort and let QAbstractItemView handle this
953  break;
954  } else {
955  // move onto itself is blocked, don't delete anything
956  dataMoved = true;
957  }
958  r = pIndex.row() + 1; // Dropped items are inserted contiguously and in the right order.
959  }
960  if (dataMoved)
961  event->accept();
962  }
963  }
964 
965  // either we or a subclass accepted the move event, so assume that the data was
966  // moved and that QAbstractItemView shouldn't remove the source when QDrag::exec returns
967  if (event->isAccepted())
968  d->dropEventMoved = true;
969  }
970 
971  if (!d->commonListView->filterDropEvent(event) || !d->dropEventMoved) {
972  // icon view didn't move the data, and moveRows not implemented, so fall back to default
973  if (!d->dropEventMoved)
974  event->ignore();
975  QAbstractItemView::dropEvent(event);
976  }
977 }
978 
982 void QListView::startDrag(Qt::DropActions supportedActions)
983 {
984  if (!d_func()->commonListView->filterStartDrag(supportedActions))
985  QAbstractItemView::startDrag(supportedActions);
986 }
987 
988 #endif // QT_CONFIG(draganddrop)
989 
993 void QListView::initViewItemOption(QStyleOptionViewItem *option) const
994 {
995  Q_D(const QListView);
997  if (!d->iconSize.isValid()) { // otherwise it was already set in abstractitemview
998  int pm = (d->viewMode == QListView::ListMode
999  ? style()->pixelMetric(QStyle::PM_ListViewIconSize, nullptr, this)
1000  : style()->pixelMetric(QStyle::PM_IconViewIconSize, nullptr, this));
1001  option->decorationSize = QSize(pm, pm);
1002  }
1003  if (d->viewMode == QListView::IconMode) {
1004  option->showDecorationSelected = false;
1005  option->decorationPosition = QStyleOptionViewItem::Top;
1006  option->displayAlignment = Qt::AlignCenter;
1007  } else {
1008  option->decorationPosition = QStyleOptionViewItem::Left;
1009  }
1010 
1011  if (d->gridSize().isValid()) {
1012  option->rect.setSize(d->gridSize());
1013  }
1014 }
1015 
1016 
1021 {
1022  Q_D(QListView);
1023  if (!d->itemDelegate)
1024  return;
1025  QStyleOptionViewItem option;
1027  QPainter painter(d->viewport);
1028 
1029  const QList<QModelIndex> toBeRendered =
1030  d->intersectingSet(e->rect().translated(horizontalOffset(), verticalOffset()), false);
1031 
1032  const QModelIndex current = currentIndex();
1033  const QModelIndex hover = d->hover;
1034  const QAbstractItemModel *itemModel = d->model;
1035  const QItemSelectionModel *selections = d->selectionModel;
1036  const bool focus = (hasFocus() || d->viewport->hasFocus()) && current.isValid();
1037  const bool alternate = d->alternatingColors;
1038  const QStyle::State state = option.state;
1039  const QAbstractItemView::State viewState = this->state();
1040  const bool enabled = (state & QStyle::State_Enabled) != 0;
1041 
1042  bool alternateBase = false;
1043  int previousRow = -2; // trigger the alternateBase adjustment on first pass
1044 
1045  int maxSize = (flow() == TopToBottom)
1046  ? qMax(viewport()->size().width(), d->contentsSize().width()) - 2 * d->spacing()
1047  : qMax(viewport()->size().height(), d->contentsSize().height()) - 2 * d->spacing();
1048 
1050  for (QList<QModelIndex>::const_iterator it = toBeRendered.constBegin(); it != end; ++it) {
1051  Q_ASSERT((*it).isValid());
1052  option.rect = visualRect(*it);
1053 
1054  if (flow() == TopToBottom)
1055  option.rect.setWidth(qMin(maxSize, option.rect.width()));
1056  else
1057  option.rect.setHeight(qMin(maxSize, option.rect.height()));
1058 
1059  option.state = state;
1060  if (selections && selections->isSelected(*it))
1061  option.state |= QStyle::State_Selected;
1062  if (enabled) {
1064  if ((itemModel->flags(*it) & Qt::ItemIsEnabled) == 0) {
1065  option.state &= ~QStyle::State_Enabled;
1066  cg = QPalette::Disabled;
1067  } else {
1068  cg = QPalette::Normal;
1069  }
1070  option.palette.setCurrentColorGroup(cg);
1071  }
1072  if (focus && current == *it) {
1073  option.state |= QStyle::State_HasFocus;
1074  if (viewState == EditingState)
1075  option.state |= QStyle::State_Editing;
1076  }
1077  option.state.setFlag(QStyle::State_MouseOver, *it == hover);
1078 
1079  if (alternate) {
1080  int row = (*it).row();
1081  if (row != previousRow + 1) {
1082  // adjust alternateBase according to rows in the "gap"
1083  if (!d->hiddenRows.isEmpty()) {
1084  for (int r = qMax(previousRow + 1, 0); r < row; ++r) {
1085  if (!d->isHidden(r))
1086  alternateBase = !alternateBase;
1087  }
1088  } else {
1089  alternateBase = (row & 1) != 0;
1090  }
1091  }
1092  option.features.setFlag(QStyleOptionViewItem::Alternate, alternateBase);
1093 
1094  // draw background of the item (only alternate row). rest of the background
1095  // is provided by the delegate
1096  QStyle::State oldState = option.state;
1097  option.state &= ~QStyle::State_Selected;
1098  style()->drawPrimitive(QStyle::PE_PanelItemViewRow, &option, &painter, this);
1099  option.state = oldState;
1100 
1101  alternateBase = !alternateBase;
1102  previousRow = row;
1103  }
1104 
1106  }
1107 
1108 #if QT_CONFIG(draganddrop)
1109  d->commonListView->paintDragDrop(&painter);
1110 #endif
1111 
1112 #if QT_CONFIG(rubberband)
1113  // #### move this implementation into a dynamic class
1114  if (d->showElasticBand && d->elasticBand.isValid()) {
1115  QStyleOptionRubberBand opt;
1116  opt.initFrom(this);
1117  opt.shape = QRubberBand::Rectangle;
1118  opt.opaque = false;
1119  opt.rect = d->mapToViewport(d->elasticBand, false).intersected(
1120  d->viewport->rect().adjusted(-16, -16, 16, 16));
1121  painter.save();
1122  style()->drawControl(QStyle::CE_RubberBand, &opt, &painter);
1123  painter.restore();
1124  }
1125 #endif
1126 }
1127 
1132 {
1133  Q_D(const QListView);
1134  QRect rect(p.x() + horizontalOffset(), p.y() + verticalOffset(), 1, 1);
1135  const QList<QModelIndex> intersectVector = d->intersectingSet(rect);
1136  QModelIndex index = intersectVector.count() > 0
1137  ? intersectVector.last() : QModelIndex();
1138  if (index.isValid() && visualRect(index).contains(p))
1139  return index;
1140  return QModelIndex();
1141 }
1142 
1147 {
1148  return d_func()->commonListView->horizontalOffset();
1149 }
1150 
1155 {
1156  return d_func()->commonListView->verticalOffset();
1157 }
1158 
1162 QModelIndex QListView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
1163 {
1164  Q_D(QListView);
1165  Q_UNUSED(modifiers);
1166 
1167  auto findAvailableRowBackward = [d](int row) {
1168  while (row >= 0 && d->isHiddenOrDisabled(row))
1169  --row;
1170  return row;
1171  };
1172 
1173  auto findAvailableRowForward = [d](int row) {
1174  int rowCount = d->model->rowCount(d->root);
1175  if (!rowCount)
1176  return -1;
1177  while (row < rowCount && d->isHiddenOrDisabled(row))
1178  ++row;
1179  if (row >= rowCount)
1180  return -1;
1181  return row;
1182  };
1183 
1184  QModelIndex current = currentIndex();
1185  if (!current.isValid()) {
1186  int row = findAvailableRowForward(0);
1187  if (row == -1)
1188  return QModelIndex();
1189  return d->model->index(row, d->column, d->root);
1190  }
1191 
1192  if ((d->flow == LeftToRight && cursorAction == MoveLeft) ||
1193  (d->flow == TopToBottom && (cursorAction == MoveUp || cursorAction == MovePrevious))) {
1194  const int row = findAvailableRowBackward(current.row() - 1);
1195  if (row == -1)
1196  return current;
1197  return d->model->index(row, d->column, d->root);
1198  } else if ((d->flow == LeftToRight && cursorAction == MoveRight) ||
1199  (d->flow == TopToBottom && (cursorAction == MoveDown || cursorAction == MoveNext))) {
1200  const int row = findAvailableRowForward(current.row() + 1);
1201  if (row == -1)
1202  return current;
1203  return d->model->index(row, d->column, d->root);
1204  }
1205 
1206  const QRect initialRect = rectForIndex(current);
1207  QRect rect = initialRect;
1208  if (rect.isEmpty()) {
1209  return d->model->index(0, d->column, d->root);
1210  }
1211  if (d->gridSize().isValid()) rect.setSize(d->gridSize());
1212 
1213  QSize contents = d->contentsSize();
1214  QList<QModelIndex> intersectVector;
1215 
1216  switch (cursorAction) {
1217  case MoveLeft:
1218  while (intersectVector.isEmpty()) {
1219  rect.translate(-rect.width(), 0);
1220  if (rect.right() <= 0)
1221  return current;
1222  if (rect.left() < 0)
1223  rect.setLeft(0);
1224  intersectVector = d->intersectingSet(rect);
1225  d->removeCurrentAndDisabled(&intersectVector, current);
1226  }
1227  return d->closestIndex(initialRect, intersectVector);
1228  case MoveRight:
1229  while (intersectVector.isEmpty()) {
1230  rect.translate(rect.width(), 0);
1231  if (rect.left() >= contents.width())
1232  return current;
1233  if (rect.right() > contents.width())
1234  rect.setRight(contents.width());
1235  intersectVector = d->intersectingSet(rect);
1236  d->removeCurrentAndDisabled(&intersectVector, current);
1237  }
1238  return d->closestIndex(initialRect, intersectVector);
1239  case MovePageUp: {
1240  rect.moveTop(rect.top() - d->viewport->height() + 1 );
1241  if (rect.top() < rect.height()) {
1242  rect.setTop(0);
1243  rect.setBottom(1);
1244  }
1245  QModelIndex findindex = current;
1246  while (intersectVector.isEmpty()
1247  || rectForIndex(findindex).top() <= (rectForIndex(current).bottom() - d->viewport->rect().height())
1248  || rect.top() <= 0) {
1249  rect.translate(0, 1);
1250  if (rect.bottom() <= 0) {
1251  return current;
1252  }
1253  intersectVector = d->intersectingSet(rect);
1254  findindex = d->closestIndex(initialRect, intersectVector);
1255  }
1256  return findindex;
1257  }
1258  case MovePrevious:
1259  case MoveUp:
1260  while (intersectVector.isEmpty()) {
1261  rect.translate(0, -rect.height());
1262  if (rect.bottom() <= 0) {
1263 #ifdef QT_KEYPAD_NAVIGATION
1264  if (QApplicationPrivate::keypadNavigationEnabled()) {
1265  int row = d->batchStartRow() - 1;
1266  while (row >= 0 && d->isHiddenOrDisabled(row))
1267  --row;
1268  if (row >= 0)
1269  return d->model->index(row, d->column, d->root);
1270  }
1271 #endif
1272  return current;
1273  }
1274  if (rect.top() < 0)
1275  rect.setTop(0);
1276  intersectVector = d->intersectingSet(rect);
1277  d->removeCurrentAndDisabled(&intersectVector, current);
1278  }
1279  return d->closestIndex(initialRect, intersectVector);
1280  case MovePageDown: {
1281  rect.moveTop(rect.top() + d->viewport->height() - 1 );
1282  if (rect.bottom() > contents.height() - rect.height()){
1283  rect.setTop(contents.height() - 1);
1284  rect.setBottom(contents.height());
1285  }
1286  QModelIndex index = current;
1287  // index's bottom() - current's top() always <= (d->viewport->rect().height()
1288  while (intersectVector.isEmpty()
1289  || rectForIndex(index).bottom() >= (d->viewport->rect().height() + rectForIndex(current).top())
1290  || rect.bottom() > contents.height()) {
1291  rect.translate(0, -1);
1292  if (rect.top() >= contents.height()) {
1293  return current;
1294  }
1295  intersectVector = d->intersectingSet(rect);
1296  index = d->closestIndex(initialRect, intersectVector);
1297  }
1298  return index;
1299  }
1300  case MoveNext:
1301  case MoveDown:
1302  while (intersectVector.isEmpty()) {
1303  rect.translate(0, rect.height());
1304  if (rect.top() >= contents.height()) {
1305 #ifdef QT_KEYPAD_NAVIGATION
1306  if (QApplicationPrivate::keypadNavigationEnabled()) {
1307  int rowCount = d->model->rowCount(d->root);
1308  int row = 0;
1309  while (row < rowCount && d->isHiddenOrDisabled(row))
1310  ++row;
1311  if (row < rowCount)
1312  return d->model->index(row, d->column, d->root);
1313  }
1314 #endif
1315  return current;
1316  }
1317  if (rect.bottom() > contents.height())
1318  rect.setBottom(contents.height());
1319  intersectVector = d->intersectingSet(rect);
1320  d->removeCurrentAndDisabled(&intersectVector, current);
1321  }
1322  return d->closestIndex(initialRect, intersectVector);
1323  case MoveHome:
1324  return d->model->index(0, d->column, d->root);
1325  case MoveEnd:
1326  return d->model->index(d->batchStartRow() - 1, d->column, d->root);}
1327 
1328  return current;
1329 }
1330 
1338 {
1339  return d_func()->rectForIndex(index);
1340 }
1341 
1351 {
1352  Q_D(QListView);
1353  if (d->movement == Static
1354  || !d->isIndexValid(index)
1355  || index.parent() != d->root
1356  || index.column() != d->column)
1357  return;
1358 
1359  d->executePostedLayout();
1360  d->commonListView->setPositionForIndex(position, index);
1361 }
1362 
1366 void QListView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command)
1367 {
1368  Q_D(QListView);
1369  if (!d->selectionModel)
1370  return;
1371 
1372  // if we are wrapping, we can only selecte inside the contents rectangle
1373  int w = qMax(d->contentsSize().width(), d->viewport->width());
1374  int h = qMax(d->contentsSize().height(), d->viewport->height());
1375  if (d->wrap && !QRect(0, 0, w, h).intersects(rect))
1376  return;
1377 
1379 
1380  if (rect.width() == 1 && rect.height() == 1) {
1381  const QList<QModelIndex> intersectVector =
1382  d->intersectingSet(rect.translated(horizontalOffset(), verticalOffset()));
1383  QModelIndex tl;
1384  if (!intersectVector.isEmpty())
1385  tl = intersectVector.last(); // special case for mouse press; only select the top item
1386  if (tl.isValid() && d->isIndexEnabled(tl))
1387  selection.select(tl, tl);
1388  } else {
1389  if (state() == DragSelectingState) { // visual selection mode (rubberband selection)
1390  selection = d->selection(rect.translated(horizontalOffset(), verticalOffset()));
1391  } else { // logical selection mode (key and mouse click selection)
1392  QModelIndex tl, br;
1393  // get the first item
1394  const QRect topLeft(rect.left() + horizontalOffset(), rect.top() + verticalOffset(), 1, 1);
1395  QList<QModelIndex> intersectVector = d->intersectingSet(topLeft);
1396  if (!intersectVector.isEmpty())
1397  tl = intersectVector.last();
1398  // get the last item
1399  const QRect bottomRight(rect.right() + horizontalOffset(), rect.bottom() + verticalOffset(), 1, 1);
1400  intersectVector = d->intersectingSet(bottomRight);
1401  if (!intersectVector.isEmpty())
1402  br = intersectVector.last();
1403 
1404  // get the ranges
1405  if (tl.isValid() && br.isValid()
1406  && d->isIndexEnabled(tl)
1407  && d->isIndexEnabled(br)) {
1408  QRect first = d->cellRectForIndex(tl);
1409  QRect last = d->cellRectForIndex(br);
1410  QRect middle;
1411  if (d->flow == LeftToRight) {
1412  QRect &top = first;
1413  QRect &bottom = last;
1414  // if bottom is above top, swap them
1415  if (top.center().y() > bottom.center().y()) {
1416  QRect tmp = top;
1417  top = bottom;
1418  bottom = tmp;
1419  }
1420  // if the rect are on different lines, expand
1421  if (top.top() != bottom.top()) {
1422  // top rectangle
1423  if (isRightToLeft())
1424  top.setLeft(0);
1425  else
1426  top.setRight(contentsSize().width());
1427  // bottom rectangle
1428  if (isRightToLeft())
1429  bottom.setRight(contentsSize().width());
1430  else
1431  bottom.setLeft(0);
1432  } else if (top.left() > bottom.right()) {
1433  if (isRightToLeft())
1434  bottom.setLeft(top.right());
1435  else
1436  bottom.setRight(top.left());
1437  } else {
1438  if (isRightToLeft())
1439  top.setLeft(bottom.right());
1440  else
1441  top.setRight(bottom.left());
1442  }
1443  // middle rectangle
1444  if (top.bottom() < bottom.top()) {
1445  if (gridSize().isValid() && !gridSize().isNull())
1446  middle.setTop(top.top() + gridSize().height());
1447  else
1448  middle.setTop(top.bottom() + 1);
1449  middle.setLeft(qMin(top.left(), bottom.left()));
1450  middle.setBottom(bottom.top() - 1);
1451  middle.setRight(qMax(top.right(), bottom.right()));
1452  }
1453  } else { // TopToBottom
1454  QRect &left = first;
1455  QRect &right = last;
1456  if (left.center().x() > right.center().x())
1457  qSwap(left, right);
1458 
1459  int ch = contentsSize().height();
1460  if (left.left() != right.left()) {
1461  // left rectangle
1462  if (isRightToLeft())
1463  left.setTop(0);
1464  else
1465  left.setBottom(ch);
1466 
1467  // top rectangle
1468  if (isRightToLeft())
1469  right.setBottom(ch);
1470  else
1471  right.setTop(0);
1472  // only set middle if the
1473  middle.setTop(0);
1474  middle.setBottom(ch);
1475  if (gridSize().isValid() && !gridSize().isNull())
1476  middle.setLeft(left.left() + gridSize().width());
1477  else
1478  middle.setLeft(left.right() + 1);
1479  middle.setRight(right.left() - 1);
1480  } else if (left.bottom() < right.top()) {
1481  left.setBottom(right.top() - 1);
1482  } else {
1483  right.setBottom(left.top() - 1);
1484  }
1485  }
1486 
1487  // do the selections
1488  QItemSelection topSelection = d->selection(first);
1489  QItemSelection middleSelection = d->selection(middle);
1490  QItemSelection bottomSelection = d->selection(last);
1491  // merge
1493  selection.merge(middleSelection, QItemSelectionModel::Select);
1494  selection.merge(bottomSelection, QItemSelectionModel::Select);
1495  }
1496  }
1497  }
1498 
1499  d->selectionModel->select(selection, command);
1500 }
1501 
1509 {
1510  Q_D(const QListView);
1511  // ### NOTE: this is a potential bottleneck in non-static mode
1512  int c = d->column;
1513  QRegion selectionRegion;
1514  const QRect &viewportRect = d->viewport->rect();
1515  for (const auto &elem : selection) {
1516  if (!elem.isValid())
1517  continue;
1518  QModelIndex parent = elem.topLeft().parent();
1519  //we only display the children of the root in a listview
1520  //we're not interested in the other model indexes
1521  if (parent != d->root)
1522  continue;
1523  int t = elem.topLeft().row();
1524  int b = elem.bottomRight().row();
1525  if (d->viewMode == IconMode || d->isWrapping()) { // in non-static mode, we have to go through all selected items
1526  for (int r = t; r <= b; ++r) {
1527  const QRect &rect = visualRect(d->model->index(r, c, parent));
1528  if (viewportRect.intersects(rect))
1529  selectionRegion += rect;
1530  }
1531  } else { // in static mode, we can optimize a bit
1532  while (t <= b && d->isHidden(t)) ++t;
1533  while (b >= t && d->isHidden(b)) --b;
1534  const QModelIndex top = d->model->index(t, c, parent);
1535  const QModelIndex bottom = d->model->index(b, c, parent);
1536  QRect rect(visualRect(top).topLeft(),
1537  visualRect(bottom).bottomRight());
1538  if (viewportRect.intersects(rect))
1539  selectionRegion += rect;
1540  }
1541  }
1542 
1543  return selectionRegion;
1544 }
1545 
1550 {
1551  Q_D(const QListView);
1552  if (!d->selectionModel)
1553  return QModelIndexList();
1554 
1555  QModelIndexList viewSelected = d->selectionModel->selectedIndexes();
1556  auto ignorable = [this, d](const QModelIndex &index) {
1557  return index.column() != d->column || index.parent() != d->root || isIndexHidden(index);
1558  };
1559  viewSelected.removeIf(ignorable);
1560  return viewSelected;
1561 }
1562 
1569 {
1570  Q_D(QListView);
1571  // showing the scroll bars will trigger a resize event,
1572  // so we set the state to expanding to avoid
1573  // triggering another layout
1574  QAbstractItemView::State oldState = state();
1576  if (d->model->columnCount(d->root) > 0) { // no columns means no contents
1577  d->resetBatchStartRow();
1578  if (layoutMode() == SinglePass) {
1579  d->doItemsLayout(d->model->rowCount(d->root)); // layout everything
1580  } else if (!d->batchLayoutTimer.isActive()) {
1581  if (!d->doItemsLayout(d->batchSize)) // layout is done
1582  d->batchLayoutTimer.start(0, this); // do a new batch as fast as possible
1583  }
1584  } else { // clear the QBspTree generated by the last layout
1585  d->clear();
1586  }
1588  setState(oldState); // restoring the oldState
1589 }
1590 
1595 {
1596  Q_D(QListView);
1597  if (geometry().isEmpty() || d->model->rowCount(d->root) <= 0 || d->model->columnCount(d->root) <= 0) {
1598  horizontalScrollBar()->setRange(0, 0);
1599  verticalScrollBar()->setRange(0, 0);
1600  } else {
1601  QModelIndex index = d->model->index(0, d->column, d->root);
1602  QStyleOptionViewItem option;
1604  QSize step = d->itemSize(option, index);
1605  d->commonListView->updateHorizontalScrollBar(step);
1606  d->commonListView->updateVerticalScrollBar(step);
1607  }
1608 
1610 
1611  // if the scroll bars are turned off, we resize the contents to the viewport
1612  if (d->movement == Static && !d->isWrapping()) {
1613  d->layoutChildren(); // we need the viewport size to be updated
1614  if (d->flow == TopToBottom) {
1615  if (horizontalScrollBarPolicy() == Qt::ScrollBarAlwaysOff) {
1616  d->setContentsSize(viewport()->width(), contentsSize().height());
1617  horizontalScrollBar()->setRange(0, 0); // we see all the contents anyway
1618  }
1619  } else { // LeftToRight
1620  if (verticalScrollBarPolicy() == Qt::ScrollBarAlwaysOff) {
1621  d->setContentsSize(contentsSize().width(), viewport()->height());
1622  verticalScrollBar()->setRange(0, 0); // we see all the contents anyway
1623  }
1624  }
1625  }
1626 
1627 }
1628 
1633 {
1634  Q_D(const QListView);
1635  return (d->isHidden(index.row())
1636  && (index.parent() == d->root)
1637  && index.column() == d->column);
1638 }
1639 
1648 {
1649  Q_D(QListView);
1650  if (column < 0 || column >= d->model->columnCount(d->root))
1651  return;
1652  d->column = column;
1653  d->doDelayedItemsLayout();
1654 }
1655 
1657 {
1658  Q_D(const QListView);
1659  return d->column;
1660 }
1661 
1674 {
1675  Q_D(QListView);
1676  d->uniformItemSizes = enable;
1677 }
1678 
1680 {
1681  Q_D(const QListView);
1682  return d->uniformItemSizes;
1683 }
1684 
1700 {
1701  Q_D(QListView);
1702  if (d->wrapItemText == on)
1703  return;
1704  d->wrapItemText = on;
1705  d->doDelayedItemsLayout();
1706 }
1707 
1709 {
1710  Q_D(const QListView);
1711  return d->wrapItemText;
1712 }
1713 
1730 {
1731  Q_D(QListView);
1732  d->modeProperties |= uint(QListViewPrivate::SelectionRectVisible);
1733  d->setSelectionRectVisible(show);
1734 }
1735 
1737 {
1738  Q_D(const QListView);
1739  return d->isSelectionRectVisible();
1740 }
1741 
1753 {
1754  Q_D(QListView);
1755  if (d->itemAlignment == alignment)
1756  return;
1757  d->itemAlignment = alignment;
1758  if (viewMode() == ListMode && flow() == QListView::TopToBottom && isWrapping())
1759  d->doDelayedItemsLayout();
1760 }
1761 
1763 {
1764  Q_D(const QListView);
1765  return d->itemAlignment;
1766 }
1767 
1772 {
1773  return QAbstractItemView::event(e);
1774 }
1775 
1776 /*
1777  * private object implementation
1778  */
1779 
1782  commonListView(nullptr),
1783  wrap(false),
1784  space(0),
1785  flow(QListView::TopToBottom),
1786  movement(QListView::Static),
1787  resizeMode(QListView::Fixed),
1788  layoutMode(QListView::SinglePass),
1789  viewMode(QListView::ListMode),
1790  modeProperties(0),
1791  column(0),
1792  uniformItemSizes(false),
1793  batchSize(100),
1794  showElasticBand(false),
1795  itemAlignment(Qt::Alignment())
1796 {
1797 }
1798 
1800 {
1801  delete commonListView;
1802 }
1803 
1805 {
1806  // initialization of data structs
1807  cachedItemSize = QSize();
1808  commonListView->clear();
1809 }
1810 
1812 {
1813  Q_Q(QListView);
1814  clear();
1815 
1816  //take the size as if there were scrollbar in order to prevent scrollbar to blink
1817  layoutBounds = QRect(QPoint(), q->maximumViewportSize());
1818 
1819  int frameAroundContents = 0;
1820  if (q->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents)) {
1822  option.initFrom(q);
1823  frameAroundContents = q->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &option) * 2;
1824  }
1825 
1826  // maximumViewportSize() already takes scrollbar into account if policy is
1827  // Qt::ScrollBarAlwaysOn but scrollbar extent must be deduced if policy
1828  // is Qt::ScrollBarAsNeeded
1829  int verticalMargin = (vbarpolicy == Qt::ScrollBarAsNeeded) && (flow == QListView::LeftToRight || vbar->isVisible())
1830  && !q->style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarOverlap, nullptr, vbar)
1831  ? q->style()->pixelMetric(QStyle::PM_ScrollBarExtent, nullptr, vbar) + frameAroundContents
1832  : 0;
1833  int horizontalMargin = hbarpolicy==Qt::ScrollBarAsNeeded
1834  ? q->style()->pixelMetric(QStyle::PM_ScrollBarExtent, nullptr, hbar) + frameAroundContents
1835  : 0;
1836 
1837  layoutBounds.adjust(0, 0, -verticalMargin, -horizontalMargin);
1838 
1839  int rowCount = model->columnCount(root) <= 0 ? 0 : model->rowCount(root);
1841 }
1842 
1847 {
1848  int max = model->rowCount(root) - 1;
1849  int first = batchStartRow();
1850  int last = qMin(first + delta - 1, max);
1851 
1852  if (first == 0) {
1853  layoutChildren(); // make sure the viewport has the right size
1855  }
1856 
1857  if (max < 0 || last < first) {
1858  return true; // nothing to do
1859  }
1860 
1862  info.bounds = layoutBounds;
1863  info.grid = gridSize();
1864  info.spacing = (info.grid.isValid() ? 0 : spacing());
1865  info.first = first;
1866  info.last = last;
1867  info.wrap = isWrapping();
1868  info.flow = flow;
1869  info.max = max;
1870 
1871  return commonListView->doBatchedItemLayout(info, max);
1872 }
1873 
1875 {
1876  if (!index.isValid() || isHidden(index.row()))
1877  return QListViewItem();
1878 
1880 }
1881 
1883 {
1884  Q_Q(const QListView);
1885  if (!rect.isValid())
1886  return rect;
1887 
1889  int dx = -q->horizontalOffset();
1890  int dy = -q->verticalOffset();
1891  return result.adjusted(dx, dy, dx, dy);
1892 }
1893 
1895  const QList<QModelIndex> &candidates) const
1896 {
1897  int distance = 0;
1898  int shortest = INT_MAX;
1899  QModelIndex closest;
1901 
1902  for (; it != candidates.end(); ++it) {
1903  if (!(*it).isValid())
1904  continue;
1905 
1906  const QRect indexRect = indexToListViewItem(*it).rect();
1907 
1908  //if the center x (or y) position of an item is included in the rect of the other item,
1909  //we define the distance between them as the difference in x (or y) of their respective center.
1910  // Otherwise, we use the nahattan length between the 2 items
1911  if ((target.center().x() >= indexRect.x() && target.center().x() < indexRect.right())
1912  || (indexRect.center().x() >= target.x() && indexRect.center().x() < target.right())) {
1913  //one item's center is at the vertical of the other
1914  distance = qAbs(indexRect.center().y() - target.center().y());
1915  } else if ((target.center().y() >= indexRect.y() && target.center().y() < indexRect.bottom())
1916  || (indexRect.center().y() >= target.y() && indexRect.center().y() < target.bottom())) {
1917  //one item's center is at the vertical of the other
1918  distance = qAbs(indexRect.center().x() - target.center().x());
1919  } else {
1920  distance = (indexRect.center() - target.center()).manhattanLength();
1921  }
1922  if (distance < shortest) {
1923  shortest = distance;
1924  closest = *it;
1925  }
1926  }
1927  return closest;
1928 }
1929 
1930 QSize QListViewPrivate::itemSize(const QStyleOptionViewItem &option, const QModelIndex &index) const
1931 {
1932  Q_Q(const QListView);
1933  if (!uniformItemSizes) {
1934  const QAbstractItemDelegate *delegate = q->itemDelegateForIndex(index);
1935  return delegate ? delegate->sizeHint(option, index) : QSize();
1936  }
1937  if (!cachedItemSize.isValid()) { // the last item is probably the largest, so we use its size
1938  int row = model->rowCount(root) - 1;
1939  QModelIndex sample = model->index(row, column, root);
1940  const QAbstractItemDelegate *delegate = q->itemDelegateForIndex(sample);
1941  cachedItemSize = delegate ? delegate->sizeHint(option, sample) : QSize();
1942  }
1943  return cachedItemSize;
1944 }
1945 
1947 {
1949  QModelIndex tl, br;
1950  const QList<QModelIndex> intersectVector = intersectingSet(rect);
1951  QList<QModelIndex>::const_iterator it = intersectVector.begin();
1952  for (; it != intersectVector.end(); ++it) {
1953  if (!tl.isValid() && !br.isValid()) {
1954  tl = br = *it;
1955  } else if ((*it).row() == (tl.row() - 1)) {
1956  tl = *it; // expand current range
1957  } else if ((*it).row() == (br.row() + 1)) {
1958  br = (*it); // expand current range
1959  } else {
1960  selection.select(tl, br); // select current range
1961  tl = br = *it; // start new range
1962  }
1963  }
1964 
1965  if (tl.isValid() && br.isValid())
1966  selection.select(tl, br);
1967  else if (tl.isValid())
1968  selection.select(tl, tl);
1969  else if (br.isValid())
1970  selection.select(br, br);
1971 
1972  return selection;
1973 }
1974 
1975 #if QT_CONFIG(draganddrop)
1976 QAbstractItemView::DropIndicatorPosition QListViewPrivate::position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const
1977 {
1979  return static_cast<QListModeViewBase *>(commonListView)->position(pos, rect, idx);
1980  else
1982 }
1983 
1984 bool QListViewPrivate::dropOn(QDropEvent *event, int *dropRow, int *dropCol, QModelIndex *dropIndex)
1985 {
1987  return static_cast<QListModeViewBase *>(commonListView)->dropOn(event, dropRow, dropCol, dropIndex);
1988  else
1989  return QAbstractItemViewPrivate::dropOn(event, dropRow, dropCol, dropIndex);
1990 }
1991 #endif
1992 
1994  const QModelIndex &current) const
1995 {
1996  auto isCurrentOrDisabled = [this, current](const QModelIndex &index) {
1997  return !isIndexEnabled(index) || index == current;
1998  };
1999  indexes->removeIf(isCurrentOrDisabled);
2000 }
2001 
2002 /*
2003  * Common ListView Implementation
2004 */
2005 
2007 {
2009 }
2010 
2012 {
2014 }
2015 
2016 #if QT_CONFIG(draganddrop)
2017 void QCommonListViewBase::paintDragDrop(QPainter *painter)
2018 {
2019  // FIXME: Until the we can provide a proper drop indicator
2020  // in IconMode, it makes no sense to show it
2021  dd->paintDropIndicator(painter);
2022 }
2023 #endif
2024 
2026 {
2027  return v->contentsRect().marginsRemoved(v->viewportMargins()).size();
2028 }
2029 
2031 {
2032  horizontalScrollBar()->d_func()->itemviewChangeSingleStep(step.width() + spacing());
2034 
2035  // If both scroll bars are set to auto, we might end up in a situation with enough space
2036  // for the actual content. But still one of the scroll bars will become enabled due to
2037  // the other one using the space. The other one will become invisible in the same cycle.
2038  // -> Infinite loop, QTBUG-39902
2039  const bool bothScrollBarsAuto = qq->verticalScrollBarPolicy() == Qt::ScrollBarAsNeeded &&
2040  qq->horizontalScrollBarPolicy() == Qt::ScrollBarAsNeeded;
2041 
2042  const QSize viewportSize = QListModeViewBase::viewportSize(qq);
2043 
2044  bool verticalWantsToShow = contentsSize.height() > viewportSize.height();
2045  bool horizontalWantsToShow;
2046  if (verticalWantsToShow)
2047  horizontalWantsToShow = contentsSize.width() > viewportSize.width() - qq->verticalScrollBar()->width();
2048  else
2049  horizontalWantsToShow = contentsSize.width() > viewportSize.width();
2050 
2051  if (bothScrollBarsAuto && !horizontalWantsToShow) {
2052  // break the infinite loop described above by setting the range to 0, 0.
2053  // QAbstractScrollArea will then hide the scroll bar for us
2054  horizontalScrollBar()->setRange(0, 0);
2055  } else {
2057  }
2058 }
2059 
2061 {
2062  verticalScrollBar()->d_func()->itemviewChangeSingleStep(step.height() + spacing());
2064 
2065  // If both scroll bars are set to auto, we might end up in a situation with enough space
2066  // for the actual content. But still one of the scroll bars will become enabled due to
2067  // the other one using the space. The other one will become invisible in the same cycle.
2068  // -> Infinite loop, QTBUG-39902
2069  const bool bothScrollBarsAuto = qq->verticalScrollBarPolicy() == Qt::ScrollBarAsNeeded &&
2070  qq->horizontalScrollBarPolicy() == Qt::ScrollBarAsNeeded;
2071 
2072  const QSize viewportSize = QListModeViewBase::viewportSize(qq);
2073 
2074  bool horizontalWantsToShow = contentsSize.width() > viewportSize.width();
2075  bool verticalWantsToShow;
2076  if (horizontalWantsToShow)
2077  verticalWantsToShow = contentsSize.height() > viewportSize.height() - qq->horizontalScrollBar()->height();
2078  else
2079  verticalWantsToShow = contentsSize.height() > viewportSize.height();
2080 
2081  if (bothScrollBarsAuto && !verticalWantsToShow) {
2082  // break the infinite loop described above by setting the range to 0, 0.
2083  // QAbstractScrollArea will then hide the scroll bar for us
2084  verticalScrollBar()->setRange(0, 0);
2085  } else {
2087  }
2088 }
2089 
2090 void QCommonListViewBase::scrollContentsBy(int dx, int dy, bool /*scrollElasticBand*/)
2091 {
2092  dd->scrollContentsBy(isRightToLeft() ? -dx : dx, dy);
2093 }
2094 
2096  bool above, bool below, const QRect &area, const QRect &rect) const
2097 {
2098  int verticalValue = verticalScrollBar()->value();
2099  QRect adjusted = rect.adjusted(-spacing(), -spacing(), spacing(), spacing());
2100  if (hint == QListView::PositionAtTop || above)
2101  verticalValue += adjusted.top();
2102  else if (hint == QListView::PositionAtBottom || below)
2103  verticalValue += qMin(adjusted.top(), adjusted.bottom() - area.height() + 1);
2104  else if (hint == QListView::PositionAtCenter)
2105  verticalValue += adjusted.top() - ((area.height() - adjusted.height()) / 2);
2106  return verticalValue;
2107 }
2108 
2110 {
2111  return (isRightToLeft() ? horizontalScrollBar()->maximum() - horizontalScrollBar()->value() : horizontalScrollBar()->value());
2112 }
2113 
2115  bool leftOf, bool rightOf, const QRect &area, const QRect &rect) const
2116 {
2117  int horizontalValue = horizontalScrollBar()->value();
2118  if (isRightToLeft()) {
2119  if (hint == QListView::PositionAtCenter) {
2120  horizontalValue += ((area.width() - rect.width()) / 2) - rect.left();
2121  } else {
2122  if (leftOf)
2123  horizontalValue -= rect.left();
2124  else if (rightOf)
2125  horizontalValue += qMin(rect.left(), area.width() - rect.right());
2126  }
2127  } else {
2128  if (hint == QListView::PositionAtCenter) {
2129  horizontalValue += rect.left() - ((area.width()- rect.width()) / 2);
2130  } else {
2131  if (leftOf)
2132  horizontalValue += rect.left();
2133  else if (rightOf)
2134  horizontalValue += qMin(rect.left(), rect.right() - area.width());
2135  }
2136  }
2137  return horizontalValue;
2138 }
2139 
2140 /*
2141  * ListMode ListView Implementation
2142 */
2144  : QCommonListViewBase(q, d)
2145 {
2146 #if QT_CONFIG(draganddrop)
2147  dd->defaultDropAction = Qt::CopyAction;
2148 #endif
2149 }
2150 
2151 #if QT_CONFIG(draganddrop)
2152 QAbstractItemView::DropIndicatorPosition QListModeViewBase::position(const QPoint &pos, const QRect &rect, const QModelIndex &index) const
2153 {
2154  QAbstractItemView::DropIndicatorPosition r = QAbstractItemView::OnViewport;
2155  if (!dd->overwrite) {
2156  const int margin = 2;
2157  if (pos.x() - rect.left() < margin) {
2158  r = QAbstractItemView::AboveItem; // Visually, on the left
2159  } else if (rect.right() - pos.x() < margin) {
2160  r = QAbstractItemView::BelowItem; // Visually, on the right
2161  } else if (rect.contains(pos, true)) {
2162  r = QAbstractItemView::OnItem;
2163  }
2164  } else {
2165  QRect touchingRect = rect;
2166  touchingRect.adjust(-1, -1, 1, 1);
2167  if (touchingRect.contains(pos, false)) {
2168  r = QAbstractItemView::OnItem;
2169  }
2170  }
2171 
2172  if (r == QAbstractItemView::OnItem && (!(dd->model->flags(index) & Qt::ItemIsDropEnabled)))
2173  r = pos.x() < rect.center().x() ? QAbstractItemView::AboveItem : QAbstractItemView::BelowItem;
2174 
2175  return r;
2176 }
2177 
2178 void QListModeViewBase::dragMoveEvent(QDragMoveEvent *event)
2179 {
2180  if (qq->dragDropMode() == QAbstractItemView::InternalMove
2181  && (event->source() != qq || !(event->possibleActions() & Qt::MoveAction)))
2182  return;
2183 
2184  // ignore by default
2185  event->ignore();
2186 
2187  // can't use indexAt, doesn't account for spacing.
2188  QPoint p = event->position().toPoint();
2189  QRect rect(p.x() + horizontalOffset(), p.y() + verticalOffset(), 1, 1);
2190  rect.adjust(-dd->spacing(), -dd->spacing(), dd->spacing(), dd->spacing());
2191  const QList<QModelIndex> intersectVector = dd->intersectingSet(rect);
2192  QModelIndex index = intersectVector.count() > 0
2193  ? intersectVector.last() : QModelIndex();
2194  dd->hover = index;
2195  if (!dd->droppingOnItself(event, index)
2196  && dd->canDrop(event)) {
2197 
2198  if (index.isValid() && dd->showDropIndicator) {
2200  dd->dropIndicatorPosition = position(event->position().toPoint(), rect, index);
2201  // if spacing, should try to draw between items, not just next to item.
2202  switch (dd->dropIndicatorPosition) {
2203  case QAbstractItemView::AboveItem:
2204  if (dd->isIndexDropEnabled(index.parent())) {
2205  dd->dropIndicatorRect = QRect(rect.left()-dd->spacing(), rect.top(), 0, rect.height());
2206  event->accept();
2207  } else {
2208  dd->dropIndicatorRect = QRect();
2209  }
2210  break;
2211  case QAbstractItemView::BelowItem:
2212  if (dd->isIndexDropEnabled(index.parent())) {
2213  dd->dropIndicatorRect = QRect(rect.right()+dd->spacing(), rect.top(), 0, rect.height());
2214  event->accept();
2215  } else {
2216  dd->dropIndicatorRect = QRect();
2217  }
2218  break;
2219  case QAbstractItemView::OnItem:
2220  if (dd->isIndexDropEnabled(index)) {
2221  dd->dropIndicatorRect = rect;
2222  event->accept();
2223  } else {
2224  dd->dropIndicatorRect = QRect();
2225  }
2226  break;
2227  case QAbstractItemView::OnViewport:
2228  dd->dropIndicatorRect = QRect();
2229  if (dd->isIndexDropEnabled(qq->rootIndex())) {
2230  event->accept(); // allow dropping in empty areas
2231  }
2232  break;
2233  }
2234  } else {
2235  dd->dropIndicatorRect = QRect();
2236  dd->dropIndicatorPosition = QAbstractItemView::OnViewport;
2237  if (dd->isIndexDropEnabled(qq->rootIndex())) {
2238  event->accept(); // allow dropping in empty areas
2239  }
2240  }
2241  dd->viewport->update();
2242  } // can drop
2243 
2244  if (dd->shouldAutoScroll(event->position().toPoint()))
2245  qq->startAutoScroll();
2246 }
2247 
2259 bool QListModeViewBase::dropOn(QDropEvent *event, int *dropRow, int *dropCol, QModelIndex *dropIndex)
2260 {
2261  if (event->isAccepted())
2262  return false;
2263 
2265  if (dd->viewport->rect().contains(event->position().toPoint())) {
2266  // can't use indexAt, doesn't account for spacing.
2267  QPoint p = event->position().toPoint();
2268  QRect rect(p.x() + horizontalOffset(), p.y() + verticalOffset(), 1, 1);
2269  rect.adjust(-dd->spacing(), -dd->spacing(), dd->spacing(), dd->spacing());
2270  const QList<QModelIndex> intersectVector = dd->intersectingSet(rect);
2271  index = intersectVector.count() > 0
2272  ? intersectVector.last() : QModelIndex();
2273  if (!index.isValid())
2274  index = dd->root;
2275  }
2276 
2277  // If we are allowed to do the drop
2278  if (dd->model->supportedDropActions() & event->dropAction()) {
2279  int row = -1;
2280  int col = -1;
2281  if (index != dd->root) {
2282  dd->dropIndicatorPosition = position(event->position().toPoint(), qq->visualRect(index), index);
2283  switch (dd->dropIndicatorPosition) {
2284  case QAbstractItemView::AboveItem:
2285  row = index.row();
2286  col = index.column();
2287  index = index.parent();
2288  break;
2289  case QAbstractItemView::BelowItem:
2290  row = index.row() + 1;
2291  col = index.column();
2292  index = index.parent();
2293  break;
2294  case QAbstractItemView::OnItem:
2295  case QAbstractItemView::OnViewport:
2296  break;
2297  }
2298  } else {
2299  dd->dropIndicatorPosition = QAbstractItemView::OnViewport;
2300  }
2301  *dropIndex = index;
2302  *dropRow = row;
2303  *dropCol = col;
2304  if (!dd->droppingOnItself(event, index))
2305  return true;
2306  }
2307  return false;
2308 }
2309 
2310 #endif //QT_CONFIG(draganddrop)
2311 
2313 {
2315  && ((flow() == QListView::TopToBottom && !isWrapping())
2316  || (flow() == QListView::LeftToRight && isWrapping()))) {
2317  const int steps = (flow() == QListView::TopToBottom ? scrollValueMap : segmentPositions).count() - 1;
2318  if (steps > 0) {
2319  const int pageSteps = perItemScrollingPageSteps(viewport()->height(), contentsSize.height(), isWrapping());
2321  verticalScrollBar()->setPageStep(pageSteps);
2322  verticalScrollBar()->setRange(0, steps - pageSteps);
2323  } else {
2324  verticalScrollBar()->setRange(0, 0);
2325  }
2326  // } else if (vertical && d->isWrapping() && d->movement == Static) {
2327  // ### wrapped scrolling in flow direction
2328  } else {
2330  }
2331 }
2332 
2334 {
2336  && ((flow() == QListView::TopToBottom && isWrapping())
2337  || (flow() == QListView::LeftToRight && !isWrapping()))) {
2338  int steps = (flow() == QListView::TopToBottom ? segmentPositions : scrollValueMap).count() - 1;
2339  if (steps > 0) {
2340  const int pageSteps = perItemScrollingPageSteps(viewport()->width(), contentsSize.width(), isWrapping());
2342  horizontalScrollBar()->setPageStep(pageSteps);
2343  horizontalScrollBar()->setRange(0, steps - pageSteps);
2344  } else {
2345  horizontalScrollBar()->setRange(0, 0);
2346  }
2347  } else {
2349  }
2350 }
2351 
2353  bool above, bool below, const QRect &area, const QRect &rect) const
2354 {
2356  int value;
2357  if (scrollValueMap.isEmpty()) {
2358  value = 0;
2359  } else {
2360  int scrollBarValue = verticalScrollBar()->value();
2361  int numHidden = 0;
2362  for (const auto &idx : qAsConst(dd->hiddenRows))
2363  if (idx.row() <= scrollBarValue)
2364  ++numHidden;
2365  value = qBound(0, scrollValueMap.at(verticalScrollBar()->value()) - numHidden, flowPositions.count() - 1);
2366  }
2367  if (above)
2368  hint = QListView::PositionAtTop;
2369  else if (below)
2371  if (hint == QListView::EnsureVisible)
2372  return value;
2373 
2374  return perItemScrollToValue(index, value, area.height(), hint, Qt::Vertical, isWrapping(), rect.height());
2375  }
2376 
2377  return QCommonListViewBase::verticalScrollToValue(index, hint, above, below, area, rect);
2378 }
2379 
2381 {
2383  if (isWrapping()) {
2385  const int max = segmentPositions.count() - 1;
2386  int currentValue = qBound(0, horizontalScrollBar()->value(), max);
2388  int maximumValue = qBound(0, horizontalScrollBar()->maximum(), max);
2389  int maximum = segmentPositions.at(maximumValue);
2390  return (isRightToLeft() ? maximum - position : position);
2391  }
2392  } else if (flow() == QListView::LeftToRight && !flowPositions.isEmpty()) {
2394  int maximum = flowPositions.at(scrollValueMap.at(horizontalScrollBar()->maximum()));
2395  return (isRightToLeft() ? maximum - position : position);
2396  }
2397  }
2399 }
2400 
2402 {
2404  if (isWrapping()) {
2406  int value = verticalScrollBar()->value();
2407  if (value >= segmentPositions.count())
2408  return 0;
2409  return segmentPositions.at(value) - spacing();
2410  }
2411  } else if (flow() == QListView::TopToBottom && !flowPositions.isEmpty()) {
2412  int value = verticalScrollBar()->value();
2413  if (value > scrollValueMap.count())
2414  return 0;
2416  }
2417  }
2419 }
2420 
2422  bool leftOf, bool rightOf, const QRect &area, const QRect &rect) const
2423 {
2425  return QCommonListViewBase::horizontalScrollToValue(index, hint, leftOf, rightOf, area, rect);
2426 
2427  int value;
2428  if (scrollValueMap.isEmpty())
2429  value = 0;
2430  else
2432  if (leftOf)
2433  hint = QListView::PositionAtTop;
2434  else if (rightOf)
2436  if (hint == QListView::EnsureVisible)
2437  return value;
2438 
2439  return perItemScrollToValue(index, value, area.width(), hint, Qt::Horizontal, isWrapping(), rect.width());
2440 }
2441 
2442 void QListModeViewBase::scrollContentsBy(int dx, int dy, bool scrollElasticBand)
2443 {
2444  // ### reorder this logic
2445  const int verticalValue = verticalScrollBar()->value();
2446  const int horizontalValue = horizontalScrollBar()->value();
2447  const bool vertical = (verticalScrollMode() == QAbstractItemView::ScrollPerItem);
2448  const bool horizontal = (horizontalScrollMode() == QAbstractItemView::ScrollPerItem);
2449 
2450  if (isWrapping()) {
2451  if (segmentPositions.isEmpty())
2452  return;
2453  const int max = segmentPositions.count() - 1;
2454  if (horizontal && flow() == QListView::TopToBottom && dx != 0) {
2455  int currentValue = qBound(0, horizontalValue, max);
2456  int previousValue = qBound(0, currentValue + dx, max);
2457  int currentCoordinate = segmentPositions.at(currentValue) - spacing();
2458  int previousCoordinate = segmentPositions.at(previousValue) - spacing();
2459  dx = previousCoordinate - currentCoordinate;
2460  } else if (vertical && flow() == QListView::LeftToRight && dy != 0) {
2461  int currentValue = qBound(0, verticalValue, max);
2462  int previousValue = qBound(0, currentValue + dy, max);
2463  int currentCoordinate = segmentPositions.at(currentValue) - spacing();
2464  int previousCoordinate = segmentPositions.at(previousValue) - spacing();
2465  dy = previousCoordinate - currentCoordinate;
2466  }
2467  } else {
2468  if (flowPositions.isEmpty())
2469  return;
2470  const int max = scrollValueMap.count() - 1;
2471  if (vertical && flow() == QListView::TopToBottom && dy != 0) {
2472  int currentValue = qBound(0, verticalValue, max);
2473  int previousValue = qBound(0, currentValue + dy, max);
2474  int currentCoordinate = flowPositions.at(scrollValueMap.at(currentValue));
2475  int previousCoordinate = flowPositions.at(scrollValueMap.at(previousValue));
2476  dy = previousCoordinate - currentCoordinate;
2477  } else if (horizontal && flow() == QListView::LeftToRight && dx != 0) {
2478  int currentValue = qBound(0, horizontalValue, max);
2479  int previousValue = qBound(0, currentValue + dx, max);
2480  int currentCoordinate = flowPositions.at(scrollValueMap.at(currentValue));
2481  int previousCoordinate = flowPositions.at(scrollValueMap.at(previousValue));
2482  dx = previousCoordinate - currentCoordinate;
2483  }
2484  }
2485  QCommonListViewBase::scrollContentsBy(dx, dy, scrollElasticBand);
2486 }
2487 
2489 {
2490  doStaticLayout(info);
2491  return batchStartRow > max; // returning true stops items layout
2492 }
2493 
2495 {
2496  if (flowPositions.isEmpty()
2498  || index.row() >= flowPositions.count() - 1)
2499  return QListViewItem();
2500 
2501  const int segment = qBinarySearch<int>(segmentStartRows, index.row(),
2502  0, segmentStartRows.count() - 1);
2503 
2504 
2505  QStyleOptionViewItem options;
2506  initViewItemOption(&options);
2507  options.rect.setSize(contentsSize);
2509  ? cachedItemSize() : itemSize(options, index);
2510  QSize cellSize = size;
2511 
2512  QPoint pos;
2513  if (flow() == QListView::LeftToRight) {
2514  pos.setX(flowPositions.at(index.row()));
2515  pos.setY(segmentPositions.at(segment));
2516  } else { // TopToBottom
2517  pos.setY(flowPositions.at(index.row()));
2518  pos.setX(segmentPositions.at(segment));
2519  if (isWrapping()) { // make the items as wide as the segment
2520  int right = (segment + 1 >= segmentPositions.count()
2521  ? contentsSize.width()
2522  : segmentPositions.at(segment + 1));
2523  cellSize.setWidth(right - pos.x());
2524  } else { // make the items as wide as the viewport
2525  cellSize.setWidth(qMax(size.width(), viewport()->width() - 2 * spacing()));
2526  }
2527  }
2528 
2530  size.setWidth(qMin(size.width(), cellSize.width()));
2532  pos.setX(pos.x() + cellSize.width() - size.width());
2534  pos.setX(pos.x() + (cellSize.width() - size.width()) / 2);
2535  } else {
2536  size.setWidth(cellSize.width());
2537  }
2538 
2539  return QListViewItem(QRect(pos, size), index.row());
2540 }
2541 
2542 QPoint QListModeViewBase::initStaticLayout(const QListViewLayoutInfo &info)
2543 {
2544  int x, y;
2545  if (info.first == 0) {
2546  flowPositions.clear();
2551  x = info.bounds.left() + info.spacing;
2552  y = info.bounds.top() + info.spacing;
2555  } else if (info.wrap) {
2556  if (info.flow == QListView::LeftToRight) {
2559  } else { // flow == QListView::TopToBottom
2562  }
2563  } else { // not first and not wrap
2564  if (info.flow == QListView::LeftToRight) {
2566  y = info.bounds.top() + info.spacing;
2567  } else { // flow == QListView::TopToBottom
2568  x = info.bounds.left() + info.spacing;
2570  }
2571  }
2572  return QPoint(x, y);
2573 }
2574 
2578 void QListModeViewBase::doStaticLayout(const QListViewLayoutInfo &info)
2579 {
2580  const bool useItemSize = !info.grid.isValid();
2581  const QPoint topLeft = initStaticLayout(info);
2582  QStyleOptionViewItem option;
2584  option.rect = info.bounds;
2585  option.rect.adjust(info.spacing, info.spacing, -info.spacing, -info.spacing);
2586 
2587  // The static layout data structures are as follows:
2588  // One vector contains the coordinate in the direction of layout flow.
2589  // Another vector contains the coordinates of the segments.
2590  // A third vector contains the index (model row) of the first item
2591  // of each segment.
2592 
2593  int segStartPosition;
2594  int segEndPosition;
2595  int deltaFlowPosition;
2596  int deltaSegPosition;
2597  int deltaSegHint;
2598  int flowPosition;
2599  int segPosition;
2600 
2601  if (info.flow == QListView::LeftToRight) {
2602  segStartPosition = info.bounds.left();
2603  segEndPosition = info.bounds.width();
2604  flowPosition = topLeft.x();
2605  segPosition = topLeft.y();
2606  deltaFlowPosition = info.grid.width(); // dx
2607  deltaSegPosition = useItemSize ? batchSavedDeltaSeg : info.grid.height(); // dy
2608  deltaSegHint = info.grid.height();
2609  } else { // flow == QListView::TopToBottom
2610  segStartPosition = info.bounds.top();
2611  segEndPosition = info.bounds.height();
2612  flowPosition = topLeft.y();
2613  segPosition = topLeft.x();
2614  deltaFlowPosition = info.grid.height(); // dy
2615  deltaSegPosition = useItemSize ? batchSavedDeltaSeg : info.grid.width(); // dx
2616  deltaSegHint = info.grid.width();
2617  }
2618 
2619  for (int row = info.first; row <= info.last; ++row) {
2620  if (isHidden(row)) { // ###
2621  flowPositions.append(flowPosition);
2622  } else {
2623  // if we are not using a grid, we need to find the deltas
2624  if (useItemSize) {
2625  QSize hint = itemSize(option, modelIndex(row));
2626  if (info.flow == QListView::LeftToRight) {
2627  deltaFlowPosition = hint.width() + info.spacing;
2628  deltaSegHint = hint.height() + info.spacing;
2629  } else { // TopToBottom
2630  deltaFlowPosition = hint.height() + info.spacing;
2631  deltaSegHint = hint.width() + info.spacing;
2632  }
2633  }
2634  // create new segment
2635  if (info.wrap && (flowPosition + deltaFlowPosition >= segEndPosition)) {
2636  segmentExtents.append(flowPosition);
2637  flowPosition = info.spacing + segStartPosition;
2638  segPosition += info.spacing + deltaSegPosition;
2639  segmentPositions.append(segPosition);
2641  deltaSegPosition = 0;
2642  }
2643  // save the flow position of this item
2645  flowPositions.append(flowPosition);
2646  // prepare for the next item
2647  deltaSegPosition = qMax(deltaSegHint, deltaSegPosition);
2648  flowPosition += info.spacing + deltaFlowPosition;
2649  }
2650  }
2651  // used when laying out next batch
2652  batchSavedPosition = flowPosition;
2653  batchSavedDeltaSeg = deltaSegPosition;
2654  batchStartRow = info.last + 1;
2655  if (info.last == info.max)
2656  flowPosition -= info.spacing; // remove extra spacing
2657  // set the contents size
2658  QRect rect = info.bounds;
2659  if (info.flow == QListView::LeftToRight) {
2660  rect.setRight(segmentPositions.count() == 1 ? flowPosition : info.bounds.right());
2661  rect.setBottom(segPosition + deltaSegPosition);
2662  } else { // TopToBottom
2663  rect.setRight(segPosition + deltaSegPosition);
2664  rect.setBottom(segmentPositions.count() == 1 ? flowPosition : info.bounds.bottom());
2665  }
2666  contentsSize = QSize(rect.right(), rect.bottom());
2667  // if it is the last batch, save the end of the segments
2668  if (info.last == info.max) {
2669  segmentExtents.append(flowPosition);
2671  flowPositions.append(flowPosition);
2672  segmentPositions.append(info.wrap ? segPosition + deltaSegPosition : INT_MAX);
2673  }
2674  // if the new items are visible, update the viewport
2675  QRect changedRect(topLeft, rect.bottomRight());
2676  if (clipRect().intersects(changedRect))
2677  viewport()->update();
2678 }
2679 
2686 {
2688  int segStartPosition;
2689  int segEndPosition;
2690  int flowStartPosition;
2691  int flowEndPosition;
2692  if (flow() == QListView::LeftToRight) {
2693  segStartPosition = area.top();
2694  segEndPosition = area.bottom();
2695  flowStartPosition = area.left();
2696  flowEndPosition = area.right();
2697  } else {
2698  segStartPosition = area.left();
2699  segEndPosition = area.right();
2700  flowStartPosition = area.top();
2701  flowEndPosition = area.bottom();
2702  }
2704  return ret;
2705  // the last segment position is actually the edge of the last segment
2706  const int segLast = segmentPositions.count() - 2;
2707  int seg = qBinarySearch<int>(segmentPositions, segStartPosition, 0, segLast + 1);
2708  for (; seg <= segLast && segmentPositions.at(seg) <= segEndPosition; ++seg) {
2709  int first = segmentStartRows.at(seg);
2710  int last = (seg < segLast ? segmentStartRows.at(seg + 1) : batchStartRow) - 1;
2711  if (segmentExtents.at(seg) < flowStartPosition)
2712  continue;
2713  int row = qBinarySearch<int>(flowPositions, flowStartPosition, first, last);
2714  for (; row <= last && flowPositions.at(row) <= flowEndPosition; ++row) {
2715  if (isHidden(row))
2716  continue;
2718  if (index.isValid()) {
2720  ret += index;
2721  } else {
2722  const auto viewItem = indexToListViewItem(index);
2723  const int iw = viewItem.width();
2724  const int startPos = qMax(segStartPosition, segmentPositions.at(seg));
2725  const int endPos = qMin(segmentPositions.at(seg + 1), segEndPosition);
2726  if (endPos >= viewItem.x && startPos < viewItem.x + iw)
2727  ret += index;
2728  }
2729  }
2730 #if 0 // for debugging
2731  else
2732  qWarning("intersectingSet: row %d was invalid", row);
2733 #endif
2734  }
2735  }
2736  return ret;
2737 }
2738 
2740 {
2742 }
2743 
2744 
2746 {
2747  if (isWrapping())
2748  return rect;
2749  // If the listview is in "listbox-mode", the items are as wide as the view.
2750  // But we don't shrink the items.
2751  QRect result = rect;
2752  if (flow() == QListView::TopToBottom) {
2753  result.setLeft(spacing());
2754  result.setWidth(qMax(rect.width(), qMax(contentsSize.width(), viewport()->width()) - 2 * spacing()));
2755  } else { // LeftToRight
2756  result.setTop(spacing());
2757  result.setHeight(qMax(rect.height(), qMax(contentsSize.height(), viewport()->height()) - 2 * spacing()));
2758  }
2759  return result;
2760 }
2761 
2762 int QListModeViewBase::perItemScrollingPageSteps(int length, int bounds, bool wrap) const
2763 {
2764  QList<int> positions;
2765  if (wrap)
2766  positions = segmentPositions;
2767  else if (!flowPositions.isEmpty()) {
2768  positions.reserve(scrollValueMap.size());
2769  for (int itemShown : scrollValueMap)
2770  positions.append(flowPositions.at(itemShown));
2771  }
2772  if (positions.isEmpty() || bounds <= length)
2773  return positions.count();
2774  if (uniformItemSizes()) {
2775  for (int i = 1; i < positions.count(); ++i)
2776  if (positions.at(i) > 0)
2777  return length / positions.at(i);
2778  return 0; // all items had height 0
2779  }
2780  int pageSteps = 0;
2781  int steps = positions.count() - 1;
2782  int max = qMax(length, bounds);
2783  int min = qMin(length, bounds);
2784  int pos = min - (max - positions.constLast());
2785 
2786  while (pos >= 0 && steps > 0) {
2787  pos -= (positions.at(steps) - positions.at(steps - 1));
2788  if (pos >= 0) //this item should be visible
2789  ++pageSteps;
2790  --steps;
2791  }
2792 
2793  // at this point we know that positions has at least one entry
2794  return qMax(pageSteps, 1);
2795 }
2796 
2797 int QListModeViewBase::perItemScrollToValue(int index, int scrollValue, int viewportSize,
2799  Qt::Orientation orientation, bool wrap, int itemExtent) const
2800 {
2801  if (index < 0)
2802  return scrollValue;
2803 
2804  itemExtent += spacing();
2805  QList<int> hiddenRows = dd->hiddenRowIds();
2806  std::sort(hiddenRows.begin(), hiddenRows.end());
2807  int hiddenRowsBefore = 0;
2808  for (int i = 0; i < hiddenRows.size() - 1; ++i)
2809  if (hiddenRows.at(i) > index + hiddenRowsBefore)
2810  break;
2811  else
2812  ++hiddenRowsBefore;
2813  if (!wrap) {
2814  int topIndex = index;
2815  const int bottomIndex = topIndex;
2816  const int bottomCoordinate = flowPositions.at(index + hiddenRowsBefore);
2817  while (topIndex > 0 &&
2818  (bottomCoordinate - flowPositions.at(topIndex + hiddenRowsBefore - 1) + itemExtent) <= (viewportSize)) {
2819  topIndex--;
2820  // will the next one be a hidden row -> skip
2821  while (hiddenRowsBefore > 0 && hiddenRows.at(hiddenRowsBefore - 1) >= topIndex + hiddenRowsBefore - 1)
2822  hiddenRowsBefore--;
2823  }
2824 
2825  const int itemCount = bottomIndex - topIndex + 1;
2826  switch (hint) {
2828  return index;
2830  return index - itemCount + 1;
2832  return index - (itemCount / 2);
2833  default:
2834  break;
2835  }
2836  } else { // wrapping
2837  Qt::Orientation flowOrientation = (flow() == QListView::LeftToRight
2839  if (flowOrientation == orientation) { // scrolling in the "flow" direction
2840  // ### wrapped scrolling in the flow direction
2841  return flowPositions.at(index + hiddenRowsBefore); // ### always pixel based for now
2842  } else if (!segmentStartRows.isEmpty()) { // we are scrolling in the "segment" direction
2843  int segment = qBinarySearch<int>(segmentStartRows, index, 0, segmentStartRows.count() - 1);
2844  int leftSegment = segment;
2845  const int rightSegment = leftSegment;
2846  const int bottomCoordinate = segmentPositions.at(segment);
2847 
2848  while (leftSegment > scrollValue &&
2849  (bottomCoordinate - segmentPositions.at(leftSegment-1) + itemExtent) <= (viewportSize)) {
2850  leftSegment--;
2851  }
2852 
2853  const int segmentCount = rightSegment - leftSegment + 1;
2854  switch (hint) {
2856  return segment;
2858  return segment - segmentCount + 1;
2860  return segment - (segmentCount / 2);
2861  default:
2862  break;
2863  }
2864  }
2865  }
2866  return scrollValue;
2867 }
2868 
2870 {
2871  flowPositions.clear();
2875  batchSavedPosition = 0;
2876  batchStartRow = 0;
2877  batchSavedDeltaSeg = 0;
2878 }
2879 
2880 /*
2881  * IconMode ListView Implementation
2882 */
2883 
2885 {
2886  if (index.row() >= items.count())
2887  return;
2888  const QSize oldContents = contentsSize;
2889  qq->update(index); // update old position
2890  moveItem(index.row(), position);
2891  qq->update(index); // update new position
2892 
2893  if (contentsSize != oldContents)
2894  dd->viewUpdateGeometries(); // update the scroll bars
2895 }
2896 
2898 {
2899  if (row >= 0 && row < items.count()) //remove item
2900  tree.removeLeaf(items.at(row).rect(), row);
2902 }
2903 
2905 {
2907  if (row >= 0 && row < items.count()) //insert item
2908  tree.insertLeaf(items.at(row).rect(), row);
2909 }
2910 
2911 #if QT_CONFIG(draganddrop)
2912 bool QIconModeViewBase::filterStartDrag(Qt::DropActions supportedActions)
2913 {
2914  // This function does the same thing as in QAbstractItemView::startDrag(),
2915  // plus adding viewitems to the draggedItems list.
2916  // We need these items to draw the drag items
2918  if (indexes.count() > 0 ) {
2919  if (viewport()->acceptDrops()) {
2921  for (; it != indexes.constEnd(); ++it)
2923  && (*it).column() == dd->column)
2925  }
2926 
2927  QRect rect;
2928  QPixmap pixmap = dd->renderToPixmap(indexes, &rect);
2929  rect.adjust(horizontalOffset(), verticalOffset(), 0, 0);
2930  QDrag *drag = new QDrag(qq);
2931  drag->setMimeData(dd->model->mimeData(indexes));
2932  drag->setPixmap(pixmap);
2933  drag->setHotSpot(dd->pressedPosition - rect.topLeft());
2934  dd->dropEventMoved = false;
2935  Qt::DropAction action = drag->exec(supportedActions, dd->defaultDropAction);
2936  draggedItems.clear();
2937  // delete item, unless it has already been moved internally (see filterDropEvent)
2938  if (action == Qt::MoveAction && !dd->dropEventMoved) {
2939  if (dd->dragDropMode != QAbstractItemView::InternalMove || drag->target() == qq->viewport())
2940  dd->clearOrRemove();
2941  }
2942  dd->dropEventMoved = false;
2943  }
2944  return true;
2945 }
2946 
2947 bool QIconModeViewBase::filterDropEvent(QDropEvent *e)
2948 {
2949  if (e->source() != qq)
2950  return false;
2951 
2952  const QSize contents = contentsSize;
2954  QPoint end = e->position().toPoint() + offset;
2955  if (qq->acceptDrops()) {
2956  const Qt::ItemFlags dropableFlags = Qt::ItemIsDropEnabled|Qt::ItemIsEnabled;
2957  const QList<QModelIndex> &dropIndices = intersectingSet(QRect(end, QSize(1, 1)));
2958  for (const QModelIndex &index : dropIndices)
2959  if ((index.flags() & dropableFlags) == dropableFlags)
2960  return false;
2961  }
2963  QPoint delta = (dd->movement == QListView::Snap ? snapToGrid(end) - snapToGrid(start) : end - start);
2965  for (const auto &index : indexes) {
2967  viewport()->update(dd->mapToViewport(rect, false));
2968  QPoint dest = rect.topLeft() + delta;
2969  if (qq->isRightToLeft())
2970  dest.setX(dd->flipX(dest.x()) - rect.width());
2971  moveItem(index.row(), dest);
2972  qq->update(index);
2973  }
2974  dd->stopAutoScroll();
2975  draggedItems.clear();
2976  dd->emitIndexesMoved(indexes);
2977  // do not delete item on internal move, see filterStartDrag()
2978  dd->dropEventMoved = true;
2979  e->accept(); // we have handled the event
2980  // if the size has not grown, we need to check if it has shrunk
2981  if (contentsSize != contents) {
2982  if ((contentsSize.width() <= contents.width()
2983  || contentsSize.height() <= contents.height())) {
2984  updateContentsSize();
2985  }
2987  }
2988  return true;
2989 }
2990 
2991 bool QIconModeViewBase::filterDragLeaveEvent(QDragLeaveEvent *e)
2992 {
2993  viewport()->update(draggedItemsRect()); // erase the area
2994  draggedItemsPos = QPoint(-1, -1); // don't draw the dragged items
2995  return QCommonListViewBase::filterDragLeaveEvent(e);
2996 }
2997 
2998 bool QIconModeViewBase::filterDragMoveEvent(QDragMoveEvent *e)
2999 {
3000  const bool wasAccepted = e->isAccepted();
3001 
3002  // ignore by default
3003  e->ignore();
3004 
3005  if (e->source() != qq || !dd->canDrop(e)) {
3006  // restore previous acceptance on failure
3007  e->setAccepted(wasAccepted);
3008  return false;
3009  }
3010 
3011  // get old dragged items rect
3012  QRect itemsRect = this->itemsRect(draggedItems);
3013  viewport()->update(itemsRect.translated(draggedItemsDelta()));
3014  // update position
3015  draggedItemsPos = e->position().toPoint();
3016  // get new items rect
3017  viewport()->update(itemsRect.translated(draggedItemsDelta()));
3018  // set the item under the cursor to current
3020  if (movement() == QListView::Snap) {
3021  QRect rect(snapToGrid(e->position().toPoint() + offset()), gridSize());
3022  const QList<QModelIndex> intersectVector = intersectingSet(rect);
3023  index = intersectVector.count() > 0 ? intersectVector.last() : QModelIndex();
3024  } else {
3025  index = qq->indexAt(e->position().toPoint());
3026  }
3027  // check if we allow drops here
3029  e->accept(); // allow changing item position
3030  else if (dd->model->flags(index) & Qt::ItemIsDropEnabled)
3031  e->accept(); // allow dropping on dropenabled items
3032  else if (!index.isValid())
3033  e->accept(); // allow dropping in empty areas
3034 
3035  // the event was treated. do autoscrolling
3036  if (dd->shouldAutoScroll(e->position().toPoint()))
3037  dd->startAutoScroll();
3038  return true;
3039 }
3040 #endif // QT_CONFIG(draganddrop)
3041 
3043 {
3044  tree.create(qMax(rowCount - hiddenCount(), 0));
3045 }
3046 
3047 void QIconModeViewBase::scrollContentsBy(int dx, int dy, bool scrollElasticBand)
3048 {
3049  if (scrollElasticBand)
3050  dd->scrollElasticBandBy(isRightToLeft() ? -dx : dx, dy);
3051 
3052  QCommonListViewBase::scrollContentsBy(dx, dy, scrollElasticBand);
3053  if (!draggedItems.isEmpty())
3054  viewport()->update(draggedItemsRect().translated(dx, dy));
3055 }
3056 
3057 void QIconModeViewBase::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
3058 {
3059  if (column() >= topLeft.column() && column() <= bottomRight.column()) {
3060  QStyleOptionViewItem option;
3062  const int bottom = qMin(items.count(), bottomRight.row() + 1);
3063  const bool useItemSize = !dd->grid.isValid();
3064  for (int row = topLeft.row(); row < bottom; ++row)
3065  {
3067  if (!useItemSize)
3068  {
3069  s.setWidth(qMin(dd->grid.width(), s.width()));
3070  s.setHeight(qMin(dd->grid.height(), s.height()));
3071  }
3072  items[row].resize(s);
3073  }
3074  }
3075 }
3076 
3078 {
3079  if (info.last >= items.count()) {
3080  //first we create the items
3081  QStyleOptionViewItem option;
3083  for (int row = items.count(); row <= info.last; ++row) {
3085  QListViewItem item(QRect(0, 0, size.width(), size.height()), row); // default pos
3086  items.append(item);
3087  }
3088  doDynamicLayout(info);
3089  }
3090  return (batchStartRow > max); // done
3091 }
3092 
3094 {
3095  if (index.isValid() && index.row() < items.count())
3096  return items.at(index.row());
3097  return QListViewItem();
3098 }
3099 
3100 void QIconModeViewBase::initBspTree(const QSize &contents)
3101 {
3102  // remove all items from the tree
3103  int leafCount = tree.leafCount();
3104  for (int l = 0; l < leafCount; ++l)
3105  tree.leaf(l).clear();
3106  // we have to get the bounding rect of the items before we can initialize the tree
3108  // simple heuristics to get better bsp
3109  if (contents.height() / contents.width() >= 3)
3111  else if (contents.width() / contents.height() >= 3)
3113  // build tree for the bounding rect (not just the contents rect)
3114  tree.init(QRect(0, 0, contents.width(), contents.height()), type);
3115 }
3116 
3117 QPoint QIconModeViewBase::initDynamicLayout(const QListViewLayoutInfo &info)
3118 {
3119  int x, y;
3120  if (info.first == 0) {
3121  x = info.bounds.x() + info.spacing;
3122  y = info.bounds.y() + info.spacing;
3124  } else {
3125  int idx = info.first - 1;
3126  while (idx > 0 && !items.at(idx).isValid())
3127  --idx;
3128  const QListViewItem &item = items.at(idx);
3129  x = item.x;
3130  y = item.y;
3131  if (info.flow == QListView::LeftToRight)
3132  x += (info.grid.isValid() ? info.grid.width() : item.w) + info.spacing;
3133  else
3134  y += (info.grid.isValid() ? info.grid.height() : item.h) + info.spacing;
3135  }
3136  return QPoint(x, y);
3137 }
3138 
3142 void QIconModeViewBase::doDynamicLayout(const QListViewLayoutInfo &info)
3143 {
3144  const bool useItemSize = !info.grid.isValid();
3145  const QPoint topLeft = initDynamicLayout(info);
3146 
3147  int segStartPosition;
3148  int segEndPosition;
3149  int deltaFlowPosition;
3150  int deltaSegPosition;
3151  int deltaSegHint;
3152  int flowPosition;
3153  int segPosition;
3154 
3155  if (info.flow == QListView::LeftToRight) {
3156  segStartPosition = info.bounds.left() + info.spacing;
3157  segEndPosition = info.bounds.right();
3158  deltaFlowPosition = info.grid.width(); // dx
3159  deltaSegPosition = (useItemSize ? batchSavedDeltaSeg : info.grid.height()); // dy
3160  deltaSegHint = info.grid.height();
3161  flowPosition = topLeft.x();
3162  segPosition = topLeft.y();
3163  } else { // flow == QListView::TopToBottom
3164  segStartPosition = info.bounds.top() + info.spacing;
3165  segEndPosition = info.bounds.bottom();
3166  deltaFlowPosition = info.grid.height(); // dy
3167  deltaSegPosition = (useItemSize ? batchSavedDeltaSeg : info.grid.width()); // dx
3168  deltaSegHint = info.grid.width();
3169  flowPosition = topLeft.y();
3170  segPosition = topLeft.x();
3171  }
3172 
3173  if (moved.count() != items.count())
3174  moved.resize(items.count());
3175 
3176  QRect rect(QPoint(), topLeft);
3177  QListViewItem *item = nullptr;
3178  Q_ASSERT(info.first <= info.last);
3179  for (int row = info.first; row <= info.last; ++row) {
3180  item = &items[row];
3181  if (isHidden(row)) {
3182  item->invalidate();
3183  } else {
3184  // if we are not using a grid, we need to find the deltas
3185  if (useItemSize) {
3186  if (info.flow == QListView::LeftToRight)
3187  deltaFlowPosition = item->w + info.spacing;
3188  else
3189  deltaFlowPosition = item->h + info.spacing;
3190  } else {
3191  item->w = qMin<int>(info.grid.width(), item->w);
3192  item->h = qMin<int>(info.grid.height(), item->h);
3193  }
3194 
3195  // create new segment
3196  if (info.wrap
3197  && flowPosition + deltaFlowPosition > segEndPosition
3198  && flowPosition > segStartPosition) {
3199  flowPosition = segStartPosition;
3200  segPosition += deltaSegPosition;
3201  if (useItemSize)
3202  deltaSegPosition = 0;
3203  }
3204  // We must delay calculation of the seg adjustment, as this item
3205  // may have caused a wrap to occur
3206  if (useItemSize) {
3207  if (info.flow == QListView::LeftToRight)
3208  deltaSegHint = item->h + info.spacing;
3209  else
3210  deltaSegHint = item->w + info.spacing;
3211  deltaSegPosition = qMax(deltaSegPosition, deltaSegHint);
3212  }
3213 
3214  // set the position of the item
3215  // ### idealy we should have some sort of alignment hint for the item
3216  // ### (normally that would be a point between the icon and the text)
3217  if (!moved.testBit(row)) {
3218  if (info.flow == QListView::LeftToRight) {
3219  if (useItemSize) {
3220  item->x = flowPosition;
3221  item->y = segPosition;
3222  } else { // use grid
3223  item->x = flowPosition + ((deltaFlowPosition - item->w) / 2);
3224  item->y = segPosition;
3225  }
3226  } else { // TopToBottom
3227  if (useItemSize) {
3228  item->y = flowPosition;
3229  item->x = segPosition;
3230  } else { // use grid
3231  item->y = flowPosition + ((deltaFlowPosition - item->h) / 2);
3232  item->x = segPosition;
3233  }
3234  }
3235  }
3236 
3237  // let the contents contain the new item
3238  if (useItemSize)
3239  rect |= item->rect();
3240  else if (info.flow == QListView::LeftToRight)
3241  rect |= QRect(flowPosition, segPosition, deltaFlowPosition, deltaSegPosition);
3242  else // flow == TopToBottom
3243  rect |= QRect(segPosition, flowPosition, deltaSegPosition, deltaFlowPosition);
3244 
3245  // prepare for next item
3246  flowPosition += deltaFlowPosition; // current position + item width + gap
3247  }
3248  }
3249  Q_ASSERT(item);
3250  batchSavedDeltaSeg = deltaSegPosition;
3251  batchStartRow = info.last + 1;
3252  bool done = (info.last >= rowCount() - 1);
3253  // resize the content area
3254  if (done || !info.bounds.contains(item->rect())) {
3255  contentsSize = rect.size();
3256  if (info.flow == QListView::LeftToRight)
3257  contentsSize.rheight() += info.spacing;
3258  else
3259  contentsSize.rwidth() += info.spacing;
3260  }
3261  if (rect.size().isEmpty())
3262  return;
3263  // resize tree
3264  int insertFrom = info.first;
3265  if (done || info.first == 0) {
3266  initBspTree(rect.size());
3267  insertFrom = 0;
3268  }
3269  // insert items in tree
3270  for (int row = insertFrom; row <= info.last; ++row)
3271  tree.insertLeaf(items.at(row).rect(), row);
3272  // if the new items are visible, update the viewport
3273  QRect changedRect(topLeft, rect.bottomRight());
3274  if (clipRect().intersects(changedRect))
3275  viewport()->update();
3276 }
3277 
3279 {
3280  QIconModeViewBase *that = const_cast<QIconModeViewBase*>(this);
3281  QBspTree::Data data(static_cast<void*>(that));
3283  that->interSectingVector = &res;
3284  that->tree.climbTree(area, &QIconModeViewBase::addLeaf, data);
3285  that->interSectingVector = nullptr;
3286  return res;
3287 }
3288 
3289 QRect QIconModeViewBase::itemsRect(const QList<QModelIndex> &indexes) const
3290 {
3291  QRect rect;
3292  for (const auto &index : indexes)
3294  return rect;
3295 }
3296 
3298 {
3299  if (!item.isValid())
3300  return -1;
3301  int i = item.indexHint;
3302  if (i < items.count()) {
3303  if (items.at(i) == item)
3304  return i;
3305  } else {
3306  i = items.count() - 1;
3307  }
3308 
3309  int j = i;
3310  int c = items.count();
3311  bool a = true;
3312  bool b = true;
3313 
3314  while (a || b) {
3315  if (a) {
3316  if (items.at(i) == item) {
3317  items.at(i).indexHint = i;
3318  return i;
3319  }
3320  a = ++i < c;
3321  }
3322  if (b) {
3323  if (items.at(j) == item) {
3324  items.at(j).indexHint = j;
3325  return j;
3326  }
3327  b = --j > -1;
3328  }
3329  }
3330  return -1;
3331 }
3332 
3333 void QIconModeViewBase::addLeaf(QList<int> &leaf, const QRect &area, uint visited,
3335 {
3336  QListViewItem *vi;
3337  QIconModeViewBase *_this = static_cast<QIconModeViewBase *>(data.ptr);
3338  for (int i = 0; i < leaf.count(); ++i) {
3339  int idx = leaf.at(i);
3340  if (idx < 0 || idx >= _this->items.count())
3341  continue;
3342  vi = &_this->items[idx];
3343  Q_ASSERT(vi);
3344  if (vi->isValid() && vi->rect().intersects(area) && vi->visited != visited) {
3345  QModelIndex index = _this->dd->listViewItemToIndex(*vi);
3346  Q_ASSERT(index.isValid());
3347  _this->interSectingVector->append(index);
3348  vi->visited = visited;
3349  }
3350  }
3351 }
3352 
3353 void QIconModeViewBase::moveItem(int index, const QPoint &dest)
3354 {
3355  // does not impact on the bintree itself or the contents rect
3357  QRect rect = item->rect();
3358 
3359  // move the item without removing it from the tree
3361  item->move(dest);
3362  tree.insertLeaf(QRect(dest, rect.size()), index);
3363 
3364  // resize the contents area
3365  contentsSize = (QRect(QPoint(0, 0), contentsSize)|QRect(dest, rect.size())).size();
3366 
3367  // mark the item as moved
3368  if (moved.count() != items.count())
3369  moved.resize(items.count());
3370  moved.setBit(index, true);
3371 }
3372 
3373 QPoint QIconModeViewBase::snapToGrid(const QPoint &pos) const
3374 {
3375  int x = pos.x() - (pos.x() % gridSize().width());
3376  int y = pos.y() - (pos.y() % gridSize().height());
3377  return QPoint(x, y);
3378 }
3379 
3380 QPoint QIconModeViewBase::draggedItemsDelta() const
3381 {
3382  if (movement() == QListView::Snap) {
3383  QPoint snapdelta = QPoint((offset().x() % gridSize().width()),
3384  (offset().y() % gridSize().height()));
3385  return snapToGrid(draggedItemsPos + snapdelta) - snapToGrid(pressedPosition()) - snapdelta;
3386  }
3387  return draggedItemsPos - pressedPosition();
3388 }
3389 
3390 QRect QIconModeViewBase::draggedItemsRect() const
3391 {
3392  QRect rect = itemsRect(draggedItems);
3393  rect.translate(draggedItemsDelta());
3394  return rect;
3395 }
3396 
3398 {
3399  if (dx > 0) // right
3401  else if (dx < 0) // left
3403  if (dy > 0) // down
3405  else if (dy < 0) // up
3407 }
3408 
3410 {
3411  tree.destroy();
3412  items.clear();
3413  moved.clear();
3414  batchStartRow = 0;
3415  batchSavedDeltaSeg = 0;
3416 }
3417 
3418 void QIconModeViewBase::updateContentsSize()
3419 {
3420  QRect bounding;
3421  for (int i = 0; i < items.count(); ++i)
3422  bounding |= items.at(i).rect();
3423  contentsSize = bounding.size();
3424 }
3425 
3429 void QListView::currentChanged(const QModelIndex &current, const QModelIndex &previous)
3430 {
3431 #ifndef QT_NO_ACCESSIBILITY
3432  if (QAccessible::isActive()) {
3433  if (current.isValid()) {
3434  int entry = visualIndex(current);
3436  event.setChild(entry);
3438  }
3439  }
3440 #endif
3441  QAbstractItemView::currentChanged(current, previous);
3442 }
3443 
3448  const QItemSelection &deselected)
3449 {
3450 #ifndef QT_NO_ACCESSIBILITY
3451  if (QAccessible::isActive()) {
3452  // ### does not work properly for selection ranges.
3453  QModelIndex sel = selected.indexes().value(0);
3454  if (sel.isValid()) {
3455  int entry = visualIndex(sel);
3457  event.setChild(entry);
3459  }
3460  QModelIndex desel = deselected.indexes().value(0);
3461  if (desel.isValid()) {
3462  int entry = visualIndex(desel);
3464  event.setChild(entry);
3466  }
3467  }
3468 #endif
3469  QAbstractItemView::selectionChanged(selected, deselected);
3470 }
3471 
3472 int QListView::visualIndex(const QModelIndex &index) const
3473 {
3474  Q_D(const QListView);
3475  d->executePostedLayout();
3476  QListViewItem itm = d->indexToListViewItem(index);
3477  int visualIndex = d->commonListView->itemIndex(itm);
3478  for (const auto &idx : qAsConst(d->hiddenRows)) {
3479  if (idx.row() <= index.row())
3480  --visualIndex;
3481  }
3482  return visualIndex;
3483 }
3484 
3485 
3491 {
3492  Q_D(const QListView);
3493  // We don't have a nice simple size hint for invalid or wrapping list views.
3494  if (!d->model)
3496  const int rc = d->model->rowCount();
3497  if (rc == 0 || isWrapping())
3499 
3500  QStyleOptionViewItem option;
3502 
3503  if (uniformItemSizes()) {
3504  QSize sz = d->cachedItemSize;
3505  if (!sz.isValid()) {
3506  QModelIndex idx = d->model->index(0, d->column, d->root);
3507  sz = d->itemSize(option, idx);
3508  }
3509  sz.setHeight(rc * sz.height());
3510  return sz;
3511  }
3512 
3513  // Using AdjustToContents with a high number of rows will normally not make sense, so we limit
3514  // this to default 1000 (that is btw the default for QHeaderView::resizeContentsPrecision())
3515  // (By setting the property _q_resizeContentPrecision the user can however override this).
3516  int maximumRows = 1000;
3517  const QVariant userOverrideValue = property("_q_resizeContentPrecision");
3518  if (userOverrideValue.isValid() && userOverrideValue.toInt() > 0) {
3519  maximumRows = userOverrideValue.toInt();
3520  }
3521  const int rowCount = qMin(rc, maximumRows);
3522 
3523  int h = 0;
3524  int w = 0;
3525 
3526  for (int row = 0; row < rowCount; ++row) {
3527  QModelIndex idx = d->model->index(row, d->column, d->root);
3528  QSize itemSize = d->itemSize(option, idx);
3529  h += itemSize.height();
3530  w = qMax(w, itemSize.width());
3531  }
3532  return QSize(w, h);
3533 }
3534 
3536 
3537 #include "moc_qlistview.cpp"
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
Arabic default style
Definition: afstyles.h:94
enum State_ State
#define value
[5]
FT_UInt idx
Definition: cffcmap.c:135
The QAbstractItemDelegate class is used to display and edit data items from a model.
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const =0
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const =0
The QAbstractItemModel class provides the abstract interface for item model classes.
virtual Qt::DropActions supportedDropActions() const
virtual Q_INVOKABLE Qt::ItemFlags flags(const QModelIndex &index) const
virtual Q_INVOKABLE int rowCount(const QModelIndex &parent=QModelIndex()) const =0
virtual QMimeData * mimeData(const QModelIndexList &indexes) const
bool moveRow(const QModelIndex &sourceParent, int sourceRow, const QModelIndex &destinationParent, int destinationChild)
virtual Q_INVOKABLE int columnCount(const QModelIndex &parent=QModelIndex()) const =0
virtual Q_INVOKABLE QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const =0
The QAbstractItemView class provides the basic functionality for item view classes.
friend class QListModeViewBase
QAbstractItemModel * model() const
bool event(QEvent *event) override
void timerEvent(QTimerEvent *event) override
virtual void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
void mouseReleaseEvent(QMouseEvent *event) override
virtual QAbstractItemDelegate * itemDelegateForIndex(const QModelIndex &index) const
virtual void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList< int > &roles=QList< int >())
QModelIndex currentIndex() const
virtual void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
virtual void setRootIndex(const QModelIndex &index)
virtual void initViewItemOption(QStyleOptionViewItem *option) const
virtual void doItemsLayout()
void update(const QModelIndex &index)
QModelIndex rootIndex() const
virtual void currentChanged(const QModelIndex &current, const QModelIndex &previous)
void resizeEvent(QResizeEvent *event) override
virtual void rowsInserted(const QModelIndex &parent, int start, int end)
void setState(State state)
void mouseMoveEvent(QMouseEvent *event) override
void setSelectionMode(QAbstractItemView::SelectionMode mode)
virtual void updateGeometries()
QSize viewportSizeHint() const override
void doDelayedItemsLayout(int delay=0)
void scrollContentsBy(int dx, int dy)
QPointer< QItemSelectionModel > selectionModel
bool shouldAutoScroll(const QPoint &pos) const
QPersistentModelIndex root
bool droppingOnItself(QDropEvent *event, const QModelIndex &index)
QPixmap renderToPixmap(const QModelIndexList &indexes, QRect *r) const
QAbstractItemModel * model
bool isIndexDropEnabled(const QModelIndex &index) const
QPersistentModelIndex hover
bool isIndexEnabled(const QModelIndex &index) const
int value
the slider's current value
void setRange(int min, int max)
The QAccessibleEvent class is the base class for accessibility notifications.
Definition: qaccessible.h:680
static bool isActive()
static void updateAccessibility(QAccessibleEvent *event)
bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event)
void clear()
Definition: qbitarray.h:78
bool testBit(qsizetype i) const
Definition: qbitarray.h:120
qsizetype count() const
Definition: qbitarray.h:68
void resize(qsizetype size)
Definition: qbitarray.cpp:220
void setBit(qsizetype i)
Definition: qbitarray.h:124
QList< int > & leaf(int i)
Definition: qbsptree_p.h:95
void insertLeaf(const QRect &r, int i)
Definition: qbsptree_p.h:96
void create(int n, int d=-1)
Definition: qbsptree.cpp:46
void destroy()
Definition: qbsptree.cpp:63
void climbTree(const QRect &rect, callback *function, QBspTreeData data)
Definition: qbsptree.cpp:69
void init(const QRect &area, NodeType type)
Definition: qbsptree_p.h:90
void removeLeaf(const QRect &r, int i)
Definition: qbsptree_p.h:97
int leafCount() const
Definition: qbsptree_p.h:94
int hiddenCount() const
Definition: qlistview_p.h:499
virtual int horizontalScrollToValue(int index, QListView::ScrollHint hint, bool leftOf, bool rightOf, const QRect &area, const QRect &rect) const
Definition: qlistview.cpp:2114
virtual void clear()=0
QListView::Movement movement() const
Definition: qlistview_p.h:470
QRect viewItemRect(const QListViewItem &item) const
Definition: qlistview_p.h:491
QListView::ScrollMode horizontalScrollMode() const
Definition: qlistview_p.h:480
QListView::ScrollMode verticalScrollMode() const
Definition: qlistview_p.h:479
virtual void updateHorizontalScrollBar(const QSize &step)
Definition: qlistview.cpp:2030
virtual int horizontalOffset() const
Definition: qlistview.cpp:2109
QWidget * viewport() const
Definition: qlistview_p.h:487
void initViewItemOption(QStyleOptionViewItem *option) const
Definition: qlistview_p.h:486
virtual bool doBatchedItemLayout(const QListViewLayoutInfo &info, int max)=0
virtual void appendHiddenRow(int row)
Definition: qlistview.cpp:2006
virtual void updateVerticalScrollBar(const QSize &step)
Definition: qlistview.cpp:2060
virtual QListViewItem indexToListViewItem(const QModelIndex &index) const =0
virtual void removeHiddenRow(int row)
Definition: qlistview.cpp:2011
bool uniformItemSizes() const
Definition: qlistview_p.h:474
QSize cachedItemSize() const
Definition: qlistview_p.h:490
virtual void scrollContentsBy(int dx, int dy, bool scrollElasticBand)
Definition: qlistview.cpp:2090
virtual int verticalOffset() const
Definition: qlistview_p.h:139
int column() const
Definition: qlistview_p.h:475
QPoint offset() const
Definition: qlistview_p.h:472
bool isHidden(int row) const
Definition: qlistview_p.h:498
QListViewPrivate * dd
Definition: qlistview_p.h:189
QScrollBar * verticalScrollBar() const
Definition: qlistview_p.h:477
QSize itemSize(const QStyleOptionViewItem &opt, const QModelIndex &idx) const
Definition: qlistview_p.h:492
QRect clipRect() const
Definition: qlistview_p.h:488
QListView::Flow flow() const
Definition: qlistview_p.h:469
int rowCount() const
Definition: qlistview_p.h:484
virtual void setRowCount(int)=0
virtual QRect mapToViewport(const QRect &rect) const
Definition: qlistview_p.h:137
QScrollBar * horizontalScrollBar() const
Definition: qlistview_p.h:478
QSize gridSize() const
Definition: qlistview_p.h:468
int spacing() const
Definition: qlistview_p.h:466
bool isRightToLeft() const
Definition: qlistview_p.h:501
bool isWrapping() const
Definition: qlistview_p.h:467
QModelIndex modelIndex(int row) const
Definition: qlistview_p.h:482
virtual int verticalScrollToValue(int index, QListView::ScrollHint hint, bool above, bool below, const QRect &area, const QRect &rect) const
Definition: qlistview.cpp:2095
QPoint pressedPosition() const
Definition: qlistview_p.h:473
static bool sendEvent(QObject *receiver, QEvent *event)
The QDrag class provides support for MIME-based drag and drop data transfer.
Definition: qdrag.h:58
void setHotSpot(const QPoint &hotspot)
Definition: qdrag.cpp:182
Qt::DropAction exec(Qt::DropActions supportedActions=Qt::MoveAction)
Definition: qdrag.cpp:235
void setMimeData(QMimeData *data)
Definition: qdrag.cpp:135
void setPixmap(const QPixmap &)
Definition: qdrag.cpp:159
QObject * target() const
Definition: qdrag.cpp:212
The QEvent class is the base class of all event classes. Event objects contain event parameters.
Definition: qcoreevent.h:58
qreal y() const
qreal x() const
QList< QListViewItem > items
Definition: qlistview_p.h:254
int itemIndex(const QListViewItem &item) const override
Definition: qlistview.cpp:3297
QList< QModelIndex > draggedItems
Definition: qlistview_p.h:257
QListViewItem indexToListViewItem(const QModelIndex &index) const override
Definition: qlistview.cpp:3093
void setPositionForIndex(const QPoint &position, const QModelIndex &index) override
Definition: qlistview.cpp:2884
void setRowCount(int rowCount) override
Definition: qlistview.cpp:3042
void scrollContentsBy(int dx, int dy, bool scrollElasticBand) override
Definition: qlistview.cpp:3047
QList< QModelIndex > intersectingSet(const QRect &area) const override
Definition: qlistview.cpp:3278
void appendHiddenRow(int row) override
Definition: qlistview.cpp:2897
QPoint draggedItemsPos
Definition: qlistview_p.h:258
void clear() override
Definition: qlistview.cpp:3409
QList< QModelIndex > * interSectingVector
Definition: qlistview_p.h:261
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) override
Definition: qlistview.cpp:3057
void removeHiddenRow(int row) override
Definition: qlistview.cpp:2904
bool doBatchedItemLayout(const QListViewLayoutInfo &info, int max) override
Definition: qlistview.cpp:3077
The QItemSelection class manages information about selected items in a model.
Q_CORE_EXPORT QModelIndexList indexes() const
Q_CORE_EXPORT void select(const QModelIndex &topLeft, const QModelIndex &bottomRight)
Q_CORE_EXPORT void merge(const QItemSelection &other, QItemSelectionModel::SelectionFlags command)
Q_INVOKABLE bool isSelected(const QModelIndex &index) const
QModelIndexList selectedIndexes
virtual void select(const QModelIndex &index, QItemSelectionModel::SelectionFlags command)
The QItemSelectionRange class manages information about a range of selected items in a model.
Definition: qlist.h:108
qsizetype size() const noexcept
Definition: qlist.h:414
bool isEmpty() const noexcept
Definition: qlist.h:418
void push_back(parameter_type t)
Definition: qlist.h:687
iterator end()
Definition: qlist.h:624
const_reference at(qsizetype i) const noexcept
Definition: qlist.h:457
T value(qsizetype i) const
Definition: qlist.h:676
T & last()
Definition: qlist.h:646
const_iterator constBegin() const noexcept
Definition: qlist.h:630
qsizetype removeIf(Predicate pred)
Definition: qlist.h:602
qsizetype count() const noexcept
Definition: qlist.h:415
iterator begin()
Definition: qlist.h:623
void reserve(qsizetype size)
Definition: qlist.h:757
const T & constLast() const noexcept
Definition: qlist.h:648
void resize(qsizetype size)
Definition: qlist.h:420
const_iterator cend() const noexcept
Definition: qlist.h:629
void append(parameter_type t)
Definition: qlist.h:469
const_iterator constEnd() const noexcept
Definition: qlist.h:631
const_iterator cbegin() const noexcept
Definition: qlist.h:628
void clear()
Definition: qlist.h:445
const_iterator ConstIterator
Definition: qlist.h:280
void clear() override
Definition: qlistview.cpp:2869
void updateHorizontalScrollBar(const QSize &step) override
Definition: qlistview.cpp:2333
bool doBatchedItemLayout(const QListViewLayoutInfo &info, int max) override
Definition: qlistview.cpp:2488
QList< int > segmentExtents
Definition: qlistview_p.h:204
QList< int > segmentPositions
Definition: qlistview_p.h:202
QList< int > flowPositions
Definition: qlistview_p.h:201
void updateVerticalScrollBar(const QSize &step) override
Definition: qlistview.cpp:2312
void scrollContentsBy(int dx, int dy, bool scrollElasticBand) override
Definition: qlistview.cpp:2442
QList< QModelIndex > intersectingSet(const QRect &area) const override
Definition: qlistview.cpp:2685
int horizontalOffset() const override
Definition: qlistview.cpp:2380
QRect mapToViewport(const QRect &rect) const override
Definition: qlistview.cpp:2745
int verticalOffset() const override
Definition: qlistview.cpp:2401
QListViewItem indexToListViewItem(const QModelIndex &index) const override
Definition: qlistview.cpp:2494
int verticalScrollToValue(int index, QListView::ScrollHint hint, bool above, bool below, const QRect &area, const QRect &rect) const override
Definition: qlistview.cpp:2352
int horizontalScrollToValue(int index, QListView::ScrollHint hint, bool leftOf, bool rightOf, const QRect &area, const QRect &rect) const override
Definition: qlistview.cpp:2421
QListModeViewBase(QListView *q, QListViewPrivate *d)
Definition: qlistview.cpp:2143
static QSize viewportSize(const QAbstractItemView *v)
Definition: qlistview.cpp:2025
void dataChanged(const QModelIndex &, const QModelIndex &) override
Definition: qlistview.cpp:2739
QList< int > segmentStartRows
Definition: qlistview_p.h:203
QList< int > scrollValueMap
Definition: qlistview_p.h:205
The QListView class provides a list or icon view onto a model.
Definition: qlistview.h:53
LayoutMode layoutMode
determines whether the layout of items should happen immediately or be delayed.
Definition: qlistview.h:59
void resizeEvent(QResizeEvent *e) override
Definition: qlistview.cpp:861
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList< int > &roles=QList< int >()) override
Definition: qlistview.cpp:737
void setSpacing(int space)
Definition: qlistview.cpp:374
void reset() override
Definition: qlistview.cpp:679
bool isSelectionRectVisible() const
Definition: qlistview.cpp:1736
int spacing
the space around the items in the layout
Definition: qlistview.h:60
bool isWrapping
whether the items layout should wrap.
Definition: qlistview.h:57
void currentChanged(const QModelIndex &current, const QModelIndex &previous) override
Definition: qlistview.cpp:3429
void scrollTo(const QModelIndex &index, ScrollHint hint=EnsureVisible) override
Definition: qlistview.cpp:567
void initViewItemOption(QStyleOptionViewItem *option) const override
Definition: qlistview.cpp:993
void setRowHidden(int row, bool hide)
Definition: qlistview.cpp:543
void setLayoutMode(LayoutMode mode)
Definition: qlistview.cpp:348
int batchSize
the number of items laid out in each batch if \l layoutMode is set to \l Batched
Definition: qlistview.h:65
ViewMode viewMode
the view mode of the QListView.
Definition: qlistview.h:62
void setWordWrap(bool on)
Definition: qlistview.cpp:1699
void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) override
Definition: qlistview.cpp:759
int verticalOffset() const override
Definition: qlistview.cpp:1154
void timerEvent(QTimerEvent *e) override
Definition: qlistview.cpp:845
bool uniformItemSizes
whether all items in the listview have the same size
Definition: qlistview.h:64
bool wordWrap
the item text word-wrapping policy
Definition: qlistview.h:66
QSize gridSize
the size of the layout grid
Definition: qlistview.h:61
QSize contentsSize() const
Definition: qlistview.cpp:728
void setViewMode(ViewMode mode)
Definition: qlistview.cpp:458
QListView(QWidget *parent=nullptr)
Definition: qlistview.cpp:181
QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) override
Definition: qlistview.cpp:1162
void setRootIndex(const QModelIndex &index) override
Definition: qlistview.cpp:690
int modelColumn
the column in the model that is visible
Definition: qlistview.h:63
QRegion visualRegionForSelection(const QItemSelection &selection) const override
Definition: qlistview.cpp:1508
void setGridSize(const QSize &size)
Definition: qlistview.cpp:429
Movement movement
whether the items can be moved freely, are snapped to a grid, or cannot be moved at all.
Definition: qlistview.h:55
QRect rectForIndex(const QModelIndex &index) const
Definition: qlistview.cpp:1337
bool event(QEvent *e) override
Definition: qlistview.cpp:1771
void setModelColumn(int column)
Definition: qlistview.cpp:1647
void setWrapping(bool enable)
Definition: qlistview.cpp:296
bool isRowHidden(int row) const
Definition: qlistview.cpp:533
QRect visualRect(const QModelIndex &index) const override
Definition: qlistview.cpp:558
int horizontalOffset() const override
Definition: qlistview.cpp:1146
void setMovement(Movement movement)
Definition: qlistview.cpp:230
void setBatchSize(int batchSize)
Definition: qlistview.cpp:398
@ ListMode
Definition: qlistview.h:79
@ IconMode
Definition: qlistview.h:79
void setPositionForIndex(const QPoint &position, const QModelIndex &index)
Definition: qlistview.cpp:1350
Qt::Alignment itemAlignment
the alignment of each item in its cell
Definition: qlistview.h:68
void clearPropertyFlags()
Definition: qlistview.cpp:524
void setItemAlignment(Qt::Alignment alignment)
Definition: qlistview.cpp:1752
void mouseReleaseEvent(QMouseEvent *e) override
Definition: qlistview.cpp:802
void setSelectionRectVisible(bool show)
Definition: qlistview.cpp:1729
void updateGeometries() override
Definition: qlistview.cpp:1594
void mouseMoveEvent(QMouseEvent *e) override
Definition: qlistview.cpp:782
void setUniformItemSizes(bool enable)
Definition: qlistview.cpp:1673
void setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command) override
Definition: qlistview.cpp:1366
void setResizeMode(ResizeMode mode)
Definition: qlistview.cpp:322
QModelIndexList selectedIndexes() const override
Definition: qlistview.cpp:1549
void scrollContentsBy(int dx, int dy) override
Definition: qlistview.cpp:706
QSize viewportSizeHint() const override
Definition: qlistview.cpp:3490
bool isIndexHidden(const QModelIndex &index) const override
Definition: qlistview.cpp:1632
void resizeContents(int width, int height)
Definition: qlistview.cpp:719
ResizeMode resizeMode
whether the items are laid out again when the view is resized.
Definition: qlistview.h:58
@ TopToBottom
Definition: qlistview.h:73
@ LeftToRight
Definition: qlistview.h:73
QModelIndex indexAt(const QPoint &p) const override
Definition: qlistview.cpp:1131
void paintEvent(QPaintEvent *e) override
Definition: qlistview.cpp:1020
@ SinglePass
Definition: qlistview.h:77
Flow flow
which direction the items layout should flow.
Definition: qlistview.h:56
void setFlow(Flow flow)
Definition: qlistview.cpp:267
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) override
Definition: qlistview.cpp:3447
void rowsInserted(const QModelIndex &parent, int start, int end) override
Definition: qlistview.cpp:747
void doItemsLayout() override
Definition: qlistview.cpp:1568
constexpr bool isValid() const
Definition: qlistview_p.h:81
QListView::ViewMode viewMode
Definition: qlistview_p.h:429
QSet< QPersistentModelIndex > hiddenRows
Definition: qlistview_p.h:451
int horizontalScrollToValue(const QModelIndex &index, const QRect &rect, QListView::ScrollHint hint) const
Definition: qlistview.cpp:589
QListView::Movement movement
Definition: qlistview_p.h:426
QModelIndex closestIndex(const QRect &target, const QList< QModelIndex > &candidates) const
Definition: qlistview.cpp:1894
int batchStartRow() const
Definition: qlistview_p.h:319
QListView::Flow flow
Definition: qlistview_p.h:425
QItemViewPaintPairs draggablePaintPairs(const QModelIndexList &indexes, QRect *r) const override
Definition: qlistview.cpp:653
int verticalScrollToValue(const QModelIndex &index, const QRect &rect, QListView::ScrollHint hint) const
Definition: qlistview.cpp:603
void scrollElasticBandBy(int dx, int dy)
Definition: qlistview.cpp:3397
Qt::Alignment itemAlignment
Definition: qlistview_p.h:461
QRect rectForIndex(const QModelIndex &index) const
Definition: qlistview_p.h:341
QSize itemSize(const QStyleOptionViewItem &option, const QModelIndex &index) const
Definition: qlistview.cpp:1930
void selectAll(QItemSelectionModel::SelectionFlags command) override
Definition: qlistview.cpp:613
bool doItemsLayout(int num)
Definition: qlistview.cpp:1846
QListViewItem indexToListViewItem(const QModelIndex &index) const
Definition: qlistview.cpp:1874
bool isWrapping() const
Definition: qlistview_p.h:386
int spacing() const
Definition: qlistview_p.h:388
QModelIndex listViewItemToIndex(const QListViewItem &item) const
Definition: qlistview_p.h:333
QList< QModelIndex > intersectingSet(const QRect &area, bool doLayout=true) const
Definition: qlistview_p.h:311
QItemSelection selection(const QRect &rect) const
Definition: qlistview.cpp:1946
QCommonListViewBase * commonListView
Definition: qlistview_p.h:417
int flipX(int x) const
Definition: qlistview_p.h:323
void prepareItemsLayout()
Definition: qlistview.cpp:1811
void emitIndexesMoved(const QModelIndexList &indexes)
Definition: qlistview_p.h:414
QRect mapToViewport(const QRect &rect, bool extend=true) const
Definition: qlistview.cpp:1882
void viewUpdateGeometries()
Definition: qlistview_p.h:361
bool isHidden(int row) const
Definition: qlistview_p.h:393
void removeCurrentAndDisabled(QList< QModelIndex > *indexes, const QModelIndex &current) const
Definition: qlistview.cpp:1993
QList< int > hiddenRowIds() const
Definition: qlistview_p.h:398
QSize gridSize() const
Definition: qlistview_p.h:384
The QModelIndex class is used to locate data in a data model.
constexpr int row() const noexcept
constexpr int column() const noexcept
constexpr bool isValid() const noexcept
The QMouseEvent class contains parameters that describe a mouse event.
Definition: qevent.h:231
The QObject class is the base class of all Qt objects.
Definition: qobject.h:125
The QPaintEvent class contains event parameters for paint events. \inmodule QtGui.
Definition: qevent.h:539
The QPainter class performs low-level painting on widgets and other paint devices.
Definition: qpainter.h:82
void restore()
Definition: qpainter.cpp:1611
void save()
Definition: qpainter.cpp:1577
ColorGroup
Definition: qpalette.h:84
@ Normal
Definition: qpalette.h:84
@ Disabled
Definition: qpalette.h:84
The QPersistentModelIndex class is used to locate data in a data model.
The QPixmap class is an off-screen image representation that can be used as a paint device.
Definition: qpixmap.h:63
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:52
constexpr int x() const noexcept
Definition: qpoint.h:155
constexpr int y() const noexcept
Definition: qpoint.h:160
constexpr void setX(int x) noexcept
Definition: qpoint.h:165
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:59
bool intersects(const QRect &r) const noexcept
Definition: qrect.cpp:1101
constexpr void adjust(int x1, int y1, int x2, int y2) noexcept
Definition: qrect.h:400
constexpr void moveBottom(int pos) noexcept
Definition: qrect.h:325
constexpr void moveRight(int pos) noexcept
Definition: qrect.h:319
constexpr int height() const noexcept
Definition: qrect.h:266
constexpr int bottom() const noexcept
Definition: qrect.h:209
constexpr void setRight(int pos) noexcept
Definition: qrect.h:224
constexpr int top() const noexcept
Definition: qrect.h:203
constexpr void moveLeft(int pos) noexcept
Definition: qrect.h:313
constexpr void setBottom(int pos) noexcept
Definition: qrect.h:227
bool contains(const QRect &r, bool proper=false) const noexcept
Definition: qrect.cpp:887
constexpr void setLeft(int pos) noexcept
Definition: qrect.h:218
constexpr int left() const noexcept
Definition: qrect.h:200
constexpr int x() const noexcept
Definition: qrect.h:212
constexpr QSize size() const noexcept
Definition: qrect.h:269
constexpr int width() const noexcept
Definition: qrect.h:263
constexpr QRect translated(int dx, int dy) const noexcept
Definition: qrect.h:288
constexpr int y() const noexcept
Definition: qrect.h:215
constexpr void moveTop(int pos) noexcept
Definition: qrect.h:316
constexpr QPoint center() const noexcept
Definition: qrect.h:260
constexpr int right() const noexcept
Definition: qrect.h:206
constexpr void setTop(int pos) noexcept
Definition: qrect.h:221
The QRegion class specifies a clip region for a painter.
Definition: qregion.h:63
The QResizeEvent class contains event parameters for resize events. \inmodule QtGui.
Definition: qevent.h:612
Definition: qset.h:54
bool remove(const T &value)
Definition: qset.h:99
iterator insert(const T &value)
Definition: qset.h:191
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:55
constexpr int height() const noexcept
Definition: qsize.h:160
constexpr int width() const noexcept
Definition: qsize.h:157
constexpr int & rheight() noexcept
Definition: qsize.h:184
constexpr void setWidth(int w) noexcept
Definition: qsize.h:163
constexpr int & rwidth() noexcept
Definition: qsize.h:181
constexpr bool isNull() const noexcept
Definition: qsize.h:148
constexpr void setHeight(int h) noexcept
Definition: qsize.h:166
constexpr bool isValid() const noexcept
Definition: qsize.h:154
The QStyle class is an abstract base class that encapsulates the look and feel of a GUI.
Definition: qstyle.h:65
@ State_Editing
Definition: qstyle.h:125
@ State_MouseOver
Definition: qstyle.h:116
@ State_HasFocus
Definition: qstyle.h:111
@ State_Enabled
Definition: qstyle.h:103
@ State_Selected
Definition: qstyle.h:118
@ SH_ScrollView_FrameOnlyAroundContents
Definition: qstyle.h:636
@ CE_RubberBand
Definition: qstyle.h:245
@ PM_ScrollBarExtent
Definition: qstyle.h:462
@ PM_DefaultFrameWidth
Definition: qstyle.h:456
@ PM_ScrollView_ScrollBarOverlap
Definition: qstyle.h:560
@ PM_IconViewIconSize
Definition: qstyle.h:528
@ PM_ListViewIconSize
Definition: qstyle.h:527
@ PE_PanelItemViewRow
Definition: qstyle.h:190
The QStyleOption class stores the parameters used by QStyle functions.
Definition: qstyleoption.h:75
void initFrom(const QWidget *w)
The QTimerEvent class contains parameters that describe a timer event.
Definition: qcoreevent.h:367
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:95
bool isValid() const
Definition: qvariant.h:582
int toInt(bool *ok=nullptr) const
Definition: qvariant.cpp:1833
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:133
void update()
Definition: qwidget.cpp:10977
float step
bool focus
[0]
qSwap(pi, e)
double e
set contains("Julia")
rect
[4]
uint alignment
QStyleOptionButton opt
union Alignment_ Alignment
backing_store_ptr info
[4]
Definition: jmemsys.h:161
QHighDpiScaling::Point position(T, QHighDpiScaling::Point::Kind)
Definition: qnamespace.h:55
@ AlignRight
Definition: qnamespace.h:171
@ AlignHCenter
Definition: qnamespace.h:173
@ AlignHorizontal_Mask
Definition: qnamespace.h:176
@ AlignCenter
Definition: qnamespace.h:188
@ WA_MacShowFocusRect
Definition: qnamespace.h:384
Orientation
Definition: qnamespace.h:123
@ Horizontal
Definition: qnamespace.h:124
@ Vertical
Definition: qnamespace.h:125
@ ScrollBarAlwaysOff
Definition: qnamespace.h:1278
@ ScrollBarAsNeeded
Definition: qnamespace.h:1277
DropAction
Definition: qnamespace.h:1484
@ CopyAction
Definition: qnamespace.h:1485
@ MoveAction
Definition: qnamespace.h:1486
@ ItemIsDragEnabled
Definition: qnamespace.h:1534
@ ItemIsEnabled
Definition: qnamespace.h:1537
@ ItemIsDropEnabled
Definition: qnamespace.h:1535
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isRightToLeft(QStringView string) noexcept
Definition: qstring.cpp:10187
action
Definition: devices.py:78
QList< QModelIndex > QModelIndexList
#define Q_UNLIKELY(x)
EGLOutputLayerEXT EGLint EGLAttrib value
QT_BEGIN_NAMESPACE bool done
unsigned int uint
Definition: qglobal.h:334
QT_BEGIN_NAMESPACE bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event)
#define qWarning
Definition: qlogging.h:179
GLenum GLuint GLenum GLsizei length
Definition: qopengl.h:270
GLenum type
Definition: qopengl.h:270
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLenum mode
GLboolean r
[2]
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLuint GLuint end
GLdouble GLdouble GLdouble GLdouble top
GLenum GLenum GLsizei count
GLdouble GLdouble right
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLsizei GLsizei GLfloat distance
GLint GLsizei width
GLint left
GLint GLint bottom
GLenum target
GLboolean enable
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint start
GLenum GLuint GLintptr offset
GLint first
GLint y
GLfloat GLfloat GLfloat GLfloat h
GLenum GLenum GLsizei void GLsizei void * column
Definition: qopenglext.h:2747
struct _cl_event * event
Definition: qopenglext.h:2998
GLuint res
Definition: qopenglext.h:8867
const GLubyte * c
Definition: qopenglext.h:12701
GLuint segment
Definition: qopenglext.h:9597
GLuint entry
Definition: qopenglext.h:11002
GLdouble GLdouble t
[9]
Definition: qopenglext.h:243
GLdouble GLdouble GLdouble GLdouble q
Definition: qopenglext.h:259
GLenum GLenum GLsizei void * row
Definition: qopenglext.h:2747
GLuint64EXT * result
[6]
Definition: qopenglext.h:10932
GLdouble s
[6]
Definition: qopenglext.h:235
GLfloat GLfloat p
[1]
Definition: qopenglext.h:12698
GLuint GLenum option
Definition: qopenglext.h:5929
@ Top
@ Left
#define Q_ASSERT(cond)
Definition: qrandom.cpp:84
QPointF qAbs(const QPointF &p)
Definition: qscroller.cpp:119
const char property[13]
Definition: qwizard.cpp:136
Q_UNUSED(salary)
[21]
view show()
[18] //! [19]
QObject::connect nullptr
dialog setViewMode(QFileDialog::Detail)
[3]
QGraphicsItem * item
view viewport() -> scroll(dx, dy, deviceRect)
edit hide()
edit isVisible()
QItemSelection * selection
[0]
app setAttribute(Qt::AA_DontShowIconsInMenus)
widget render & pixmap
QPainter painter(this)
[7]
QStringList::Iterator it
bool contains(const AT &t) const noexcept
Definition: qlist.h:78
const int rowCount
Definition: testtable1.cpp:31
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent