Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qlistview.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2013 Samuel Gaist <samuel.gaist@deltech.ch>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include "qlistview.h"
6
8#if QT_CONFIG(accessibility)
9#include <qaccessible.h>
10#endif
11#include <qapplication.h>
12#include <qstylepainter.h>
13#include <qbitmap.h>
14#include <qdebug.h>
15#if QT_CONFIG(draganddrop)
16#include <qdrag.h>
17#endif
18#include <qevent.h>
19#include <qlist.h>
20#if QT_CONFIG(rubberband)
21#include <qrubberband.h>
22#endif
23#include <qscrollbar.h>
24#include <qstyle.h>
25#include <private/qapplication_p.h>
26#include <private/qlistview_p.h>
27#include <private/qscrollbar_p.h>
28
29#include <algorithm>
30
32
34
147{
151 Q_D(QListView); // We rely on a qobject_cast for PM_DefaultFrameWidth to change
152 d->updateStyledFrameWidths(); // hence we have to force an update now that the object has been constructed
153}
154
160{
164 Q_D(QListView); // We rely on a qobject_cast for PM_DefaultFrameWidth to change
165 d->updateStyledFrameWidths(); // hence we have to force an update now that the object has been constructed
166}
167
172{
173}
174
195{
196 Q_D(QListView);
197 d->modeProperties |= uint(QListViewPrivate::Movement);
198 d->movement = movement;
199
200#if QT_CONFIG(draganddrop)
201 bool movable = (movement != Static);
202 setDragEnabled(movable);
203 d->viewport->setAcceptDrops(movable);
204#endif
205 d->doDelayedItemsLayout();
206}
207
209{
210 Q_D(const QListView);
211 return d->movement;
212}
213
232{
233 Q_D(QListView);
234 d->modeProperties |= uint(QListViewPrivate::Flow);
235 d->flow = flow;
236 d->doDelayedItemsLayout();
237}
238
240{
241 Q_D(const QListView);
242 return d->flow;
243}
244
261{
262 Q_D(QListView);
263 d->modeProperties |= uint(QListViewPrivate::Wrap);
264 d->setWrapping(enable);
265 d->doDelayedItemsLayout();
266}
267
269{
270 Q_D(const QListView);
271 return d->isWrapping();
272}
273
287{
288 Q_D(QListView);
289 d->modeProperties |= uint(QListViewPrivate::ResizeMode);
290 d->resizeMode = mode;
291}
292
294{
295 Q_D(const QListView);
296 return d->resizeMode;
297}
298
313{
314 Q_D(QListView);
315 d->layoutMode = mode;
316}
317
319{
320 Q_D(const QListView);
321 return d->layoutMode;
322}
323
339{
340 Q_D(QListView);
341 d->modeProperties |= uint(QListViewPrivate::Spacing);
342 d->setSpacing(space);
343 d->doDelayedItemsLayout();
344}
345
347{
348 Q_D(const QListView);
349 return d->spacing();
350}
351
362void QListView::setBatchSize(int batchSize)
363{
364 Q_D(QListView);
365 if (Q_UNLIKELY(batchSize <= 0)) {
366 qWarning("Invalid batchSize (%d)", batchSize);
367 return;
368 }
369 d->batchSize = batchSize;
370}
371
373{
374 Q_D(const QListView);
375 return d->batchSize;
376}
377
394{
395 Q_D(QListView);
396 d->modeProperties |= uint(QListViewPrivate::GridSize);
397 d->setGridSize(size);
398 d->doDelayedItemsLayout();
399}
400
402{
403 Q_D(const QListView);
404 return d->gridSize();
405}
406
423{
424 Q_D(QListView);
425 if (d->commonListView && d->viewMode == mode)
426 return;
427 d->viewMode = mode;
428
429 delete d->commonListView;
430 if (mode == ListMode) {
431 d->commonListView = new QListModeViewBase(this, d);
432 if (!(d->modeProperties & QListViewPrivate::Wrap))
433 d->setWrapping(false);
434 if (!(d->modeProperties & QListViewPrivate::Spacing))
435 d->setSpacing(0);
436 if (!(d->modeProperties & QListViewPrivate::GridSize))
437 d->setGridSize(QSize());
438 if (!(d->modeProperties & QListViewPrivate::Flow))
439 d->flow = TopToBottom;
440 if (!(d->modeProperties & QListViewPrivate::Movement))
441 d->movement = Static;
442 if (!(d->modeProperties & QListViewPrivate::ResizeMode))
443 d->resizeMode = Fixed;
444 if (!(d->modeProperties & QListViewPrivate::SelectionRectVisible))
445 d->showElasticBand = false;
446 } else {
447 d->commonListView = new QIconModeViewBase(this, d);
448 if (!(d->modeProperties & QListViewPrivate::Wrap))
449 d->setWrapping(true);
450 if (!(d->modeProperties & QListViewPrivate::Spacing))
451 d->setSpacing(0);
452 if (!(d->modeProperties & QListViewPrivate::GridSize))
453 d->setGridSize(QSize());
454 if (!(d->modeProperties & QListViewPrivate::Flow))
455 d->flow = LeftToRight;
456 if (!(d->modeProperties & QListViewPrivate::Movement))
457 d->movement = Free;
458 if (!(d->modeProperties & QListViewPrivate::ResizeMode))
459 d->resizeMode = Fixed;
460 if (!(d->modeProperties & QListViewPrivate::SelectionRectVisible))
461 d->showElasticBand = true;
462 }
463
464#if QT_CONFIG(draganddrop)
465 bool movable = (d->movement != Static);
466 setDragEnabled(movable);
467 setAcceptDrops(movable);
468#endif
469 d->clear();
470 d->doDelayedItemsLayout();
471}
472
474{
475 Q_D(const QListView);
476 return d->viewMode;
477}
478
489{
490 Q_D(QListView);
491 d->modeProperties = 0;
492}
493
498{
499 Q_D(const QListView);
500 return d->isHidden(row);
501}
502
508{
509 Q_D(QListView);
510 const bool hidden = d->isHidden(row);
511 if (hide && !hidden)
512 d->commonListView->appendHiddenRow(row);
513 else if (!hide && hidden)
514 d->commonListView->removeHiddenRow(row);
515 d->doDelayedItemsLayout();
516 d->viewport->update();
517}
518
523{
524 Q_D(const QListView);
525 return d->mapToViewport(rectForIndex(index));
526}
527
532{
533 Q_D(QListView);
534
535 if (index.parent() != d->root || index.column() != d->column)
536 return;
537
538 const QRect rect = visualRect(index);
539 if (!rect.isValid())
540 return;
541 if (hint == EnsureVisible && d->viewport->rect().contains(rect)) {
542 d->viewport->update(rect);
543 return;
544 }
545
546 if (d->flow == QListView::TopToBottom || d->isWrapping()) // vertical
547 verticalScrollBar()->setValue(d->verticalScrollToValue(index, rect, hint));
548
549 if (d->flow == QListView::LeftToRight || d->isWrapping()) // horizontal
550 horizontalScrollBar()->setValue(d->horizontalScrollToValue(index, rect, hint));
551}
552
555{
556 Q_Q(const QListView);
557 const QRect area = viewport->rect();
558 const bool leftOf = q->isRightToLeft()
559 ? (rect.left() < area.left()) && (rect.right() < area.right())
560 : rect.left() < area.left();
561 const bool rightOf = q->isRightToLeft()
562 ? rect.right() > area.right()
563 : (rect.right() > area.right()) && (rect.left() > area.left());
564 return commonListView->horizontalScrollToValue(q->visualIndex(index), hint, leftOf, rightOf, area, rect);
565}
566
569{
570 Q_Q(const QListView);
571 const QRect area = viewport->rect();
572 const bool above = (hint == QListView::EnsureVisible && rect.top() < area.top());
573 const bool below = (hint == QListView::EnsureVisible && rect.bottom() > area.bottom());
574 return commonListView->verticalScrollToValue(q->visualIndex(index), hint, above, below, area, rect);
575}
576
577void QListViewPrivate::selectAll(QItemSelectionModel::SelectionFlags command)
578{
579 if (!selectionModel)
580 return;
581
583 QModelIndex topLeft;
584 int row = 0;
585 const int colCount = model->columnCount(root);
586 for(; row < model->rowCount(root); ++row) {
587 if (isHidden(row)) {
588 //it might be the end of a selection range
589 if (topLeft.isValid()) {
590 QModelIndex bottomRight = model->index(row - 1, colCount - 1, root);
591 selection.append(QItemSelectionRange(topLeft, bottomRight));
592 topLeft = QModelIndex();
593 }
594 continue;
595 }
596
597 if (!topLeft.isValid()) //start of a new selection range
598 topLeft = model->index(row, 0, root);
599 }
600
601 if (topLeft.isValid()) {
602 //last selected range
603 QModelIndex bottomRight = model->index(row - 1, colCount - 1, root);
604 selection.append(QItemSelectionRange(topLeft, bottomRight));
605 }
606
607 if (!selection.isEmpty())
609}
610
618{
619 Q_ASSERT(r);
620 Q_Q(const QListView);
621 QRect &rect = *r;
622 const QRect viewportRect = viewport->rect();
624 QList<QModelIndex> visibleIndexes =
625 intersectingSet(viewportRect.translated(q->horizontalOffset(), q->verticalOffset()));
626 std::sort(visibleIndexes.begin(), visibleIndexes.end());
627 for (const auto &index : indexes) {
628 if (std::binary_search(visibleIndexes.cbegin(), visibleIndexes.cend(), index)) {
629 const QRect current = q->visualRect(index);
630 ret.append({current, index});
631 rect |= current;
632 }
633 }
634 QRect clipped = rect & viewportRect;
635 rect.setLeft(clipped.left());
636 rect.setRight(clipped.right());
637 return ret;
638}
639
644{
645 Q_D(QListView);
646 d->clear();
647 d->hiddenRows.clear();
649}
650
655{
656 Q_D(QListView);
657 d->column = qMax(0, qMin(d->column, d->model->columnCount(index) - 1));
659 // sometimes we get an update before reset() is called
660 d->clear();
661 d->hiddenRows.clear();
662}
663
670void QListView::scrollContentsBy(int dx, int dy)
671{
672 Q_D(QListView);
673 d->delayedAutoScroll.stop(); // auto scroll was canceled by the user scrolling
674 d->commonListView->scrollContentsBy(dx, dy, d->state == QListView::DragSelectingState);
675}
676
684{
685 Q_D(QListView);
686 d->setContentsSize(width, height);
687}
688
693{
694 Q_D(const QListView);
695 return d->contentsSize();
696}
697
701void QListView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight,
702 const QList<int> &roles)
703{
704 d_func()->commonListView->dataChanged(topLeft, bottomRight);
705 QAbstractItemView::dataChanged(topLeft, bottomRight, roles);
706}
707
712{
713 Q_D(QListView);
714 // ### be smarter about inserted items
715 d->clear();
716 d->doDelayedItemsLayout();
718}
719
724{
725 Q_D(QListView);
726 // if the parent is above d->root in the tree, nothing will happen
728 if (parent == d->root) {
729 QSet<QPersistentModelIndex>::iterator it = d->hiddenRows.begin();
730 while (it != d->hiddenRows.end()) {
731 int hiddenRow = it->row();
732 if (hiddenRow >= start && hiddenRow <= end) {
733 it = d->hiddenRows.erase(it);
734 } else {
735 ++it;
736 }
737 }
738 }
739 d->clear();
740 d->doDelayedItemsLayout();
741}
742
747{
748 if (!isVisible())
749 return;
750 Q_D(QListView);
753 && d->showElasticBand
754 && d->selectionMode != SingleSelection
755 && d->selectionMode != NoSelection) {
756 QRect rect(d->pressedPosition, e->position().toPoint() + QPoint(horizontalOffset(), verticalOffset()));
757 rect = rect.normalized();
758 d->viewport->update(d->mapToViewport(rect.united(d->elasticBand)));
759 d->elasticBand = rect;
760 }
761}
762
767{
768 Q_D(QListView);
770 // #### move this implementation into a dynamic class
771 if (d->showElasticBand && d->elasticBand.isValid()) {
772 d->viewport->update(d->mapToViewport(d->elasticBand));
773 d->elasticBand = QRect();
774 }
775}
776
777#if QT_CONFIG(wheelevent)
781void QListView::wheelEvent(QWheelEvent *e)
782{
783 Q_D(QListView);
784 if (qAbs(e->angleDelta().y()) > qAbs(e->angleDelta().x())) {
785 if (e->angleDelta().x() == 0
786 && ((d->flow == TopToBottom && d->wrap) || (d->flow == LeftToRight && !d->wrap))
787 && d->vbar->minimum() == 0 && d->vbar->maximum() == 0) {
788 QPoint pixelDelta(e->pixelDelta().y(), e->pixelDelta().x());
789 QPoint angleDelta(e->angleDelta().y(), e->angleDelta().x());
790 QWheelEvent hwe(e->position(), e->globalPosition(), pixelDelta, angleDelta,
791 e->buttons(), e->modifiers(), e->phase(), e->inverted(), e->source());
792 if (e->spontaneous())
793 qt_sendSpontaneousEvent(d->hbar, &hwe);
794 else
795 QCoreApplication::sendEvent(d->hbar, &hwe);
796 e->setAccepted(hwe.isAccepted());
797 } else {
799 }
800 } else {
802 }
803}
804#endif // QT_CONFIG(wheelevent)
805
810{
811 Q_D(QListView);
812 if (e->timerId() == d->batchLayoutTimer.timerId()) {
813 if (d->doItemsLayout(d->batchSize)) { // layout is done
814 d->batchLayoutTimer.stop();
816 d->viewport->update();
817 }
818 }
820}
821
826{
827 Q_D(QListView);
828 if (d->delayedPendingLayout)
829 return;
830
831 QSize delta = e->size() - e->oldSize();
832
833 if (delta.isNull())
834 return;
835
836 bool listWrap = (d->viewMode == ListMode) && d->wrapItemText;
837 bool flowDimensionChanged = (d->flow == LeftToRight && delta.width() != 0)
838 || (d->flow == TopToBottom && delta.height() != 0);
839
840 // We post a delayed relayout in the following cases :
841 // - we're wrapping
842 // - the state is NoState, we're adjusting and the size has changed in the flowing direction
843 if (listWrap
844 || (state() == NoState && d->resizeMode == Adjust && flowDimensionChanged)) {
845 d->doDelayedItemsLayout(100); // wait 1/10 sec before starting the layout
846 } else {
848 }
849}
850
851#if QT_CONFIG(draganddrop)
852
856void QListView::dragMoveEvent(QDragMoveEvent *e)
857{
858 Q_D(QListView);
859 if (!d->commonListView->filterDragMoveEvent(e)) {
861 static_cast<QListModeViewBase *>(d->commonListView)->dragMoveEvent(e);
862 else
863 QAbstractItemView::dragMoveEvent(e);
864 }
865}
866
867
871void QListView::dragLeaveEvent(QDragLeaveEvent *e)
872{
873 if (!d_func()->commonListView->filterDragLeaveEvent(e))
874 QAbstractItemView::dragLeaveEvent(e);
875}
876
880void QListView::dropEvent(QDropEvent *event)
881{
882 Q_D(QListView);
883
884 if (event->source() == this && (event->dropAction() == Qt::MoveAction ||
885 dragDropMode() == QAbstractItemView::InternalMove)) {
886 QModelIndex topIndex;
887 bool topIndexDropped = false;
888 int col = -1;
889 int row = -1;
890 // check whether a subclass has already accepted the event, ie. moved the data
891 if (!event->isAccepted() && d->dropOn(event, &row, &col, &topIndex)) {
892 const QList<QModelIndex> selIndexes = selectedIndexes();
894 persIndexes.reserve(selIndexes.size());
895
896 for (const auto &index : selIndexes) {
897 persIndexes.append(index);
898 if (index == topIndex) {
899 topIndexDropped = true;
900 break;
901 }
902 }
903
904 if (!topIndexDropped && !topIndex.isValid()) {
905 std::sort(persIndexes.begin(), persIndexes.end()); // The dropped items will remain in the same visual order.
906
907 QPersistentModelIndex dropRow = model()->index(row, col, topIndex);
908
909 int r = row == -1 ? model()->rowCount() : (dropRow.row() >= 0 ? dropRow.row() : row);
910 bool dataMoved = false;
911 for (int i = 0; i < persIndexes.size(); ++i) {
912 const QPersistentModelIndex &pIndex = persIndexes.at(i);
913 // only generate a move when not same row or behind itself
914 if (r != pIndex.row() && r != pIndex.row() + 1) {
915 // try to move (preserves selection)
916 dataMoved |= model()->moveRow(QModelIndex(), pIndex.row(), QModelIndex(), r);
917 if (!dataMoved) // can't move - abort and let QAbstractItemView handle this
918 break;
919 } else {
920 // move onto itself is blocked, don't delete anything
921 dataMoved = true;
922 }
923 r = pIndex.row() + 1; // Dropped items are inserted contiguously and in the right order.
924 }
925 if (dataMoved)
926 event->accept();
927 }
928 }
929
930 // either we or a subclass accepted the move event, so assume that the data was
931 // moved and that QAbstractItemView shouldn't remove the source when QDrag::exec returns
932 if (event->isAccepted())
933 d->dropEventMoved = true;
934 }
935
936 if (!d->commonListView->filterDropEvent(event) || !d->dropEventMoved) {
937 // icon view didn't move the data, and moveRows not implemented, so fall back to default
938 if (!d->dropEventMoved)
939 event->ignore();
940 QAbstractItemView::dropEvent(event);
941 }
942}
943
947void QListView::startDrag(Qt::DropActions supportedActions)
948{
949 if (!d_func()->commonListView->filterStartDrag(supportedActions))
950 QAbstractItemView::startDrag(supportedActions);
951}
952
953#endif // QT_CONFIG(draganddrop)
954
958void QListView::initViewItemOption(QStyleOptionViewItem *option) const
959{
960 Q_D(const QListView);
962 if (!d->iconSize.isValid()) { // otherwise it was already set in abstractitemview
963 int pm = (d->viewMode == QListView::ListMode
964 ? style()->pixelMetric(QStyle::PM_ListViewIconSize, nullptr, this)
965 : style()->pixelMetric(QStyle::PM_IconViewIconSize, nullptr, this));
966 option->decorationSize = QSize(pm, pm);
967 }
968 if (d->viewMode == QListView::IconMode) {
969 option->showDecorationSelected = false;
970 option->decorationPosition = QStyleOptionViewItem::Top;
971 option->displayAlignment = Qt::AlignCenter;
972 } else {
973 option->decorationPosition = QStyleOptionViewItem::Left;
974 }
975
976 if (d->gridSize().isValid()) {
977 option->rect.setSize(d->gridSize());
978 }
979}
980
981
986{
987 Q_D(QListView);
988 if (!d->itemDelegate)
989 return;
990 QStyleOptionViewItem option;
992 QStylePainter painter(d->viewport);
993
994 const QList<QModelIndex> toBeRendered =
995 d->intersectingSet(e->rect().translated(horizontalOffset(), verticalOffset()), false);
996
997 const QModelIndex current = currentIndex();
998 const QModelIndex hover = d->hover;
999 const QAbstractItemModel *itemModel = d->model;
1000 const QItemSelectionModel *selections = d->selectionModel;
1001 const bool focus = (hasFocus() || d->viewport->hasFocus()) && current.isValid();
1002 const bool alternate = d->alternatingColors;
1003 const QStyle::State state = option.state;
1004 const QAbstractItemView::State viewState = this->state();
1005 const bool enabled = (state & QStyle::State_Enabled) != 0;
1006
1007 bool alternateBase = false;
1008 int previousRow = -2; // trigger the alternateBase adjustment on first pass
1009
1010 int maxSize = (flow() == TopToBottom)
1011 ? qMax(viewport()->size().width(), d->contentsSize().width()) - 2 * d->spacing()
1012 : qMax(viewport()->size().height(), d->contentsSize().height()) - 2 * d->spacing();
1013
1015 for (QList<QModelIndex>::const_iterator it = toBeRendered.constBegin(); it != end; ++it) {
1016 Q_ASSERT((*it).isValid());
1017 option.rect = visualRect(*it);
1018
1019 if (flow() == TopToBottom)
1020 option.rect.setWidth(qMin(maxSize, option.rect.width()));
1021 else
1022 option.rect.setHeight(qMin(maxSize, option.rect.height()));
1023
1024 option.state = state;
1025 if (selections && selections->isSelected(*it))
1027 if (enabled) {
1029 if ((itemModel->flags(*it) & Qt::ItemIsEnabled) == 0) {
1030 option.state &= ~QStyle::State_Enabled;
1031 cg = QPalette::Disabled;
1032 } else {
1033 cg = QPalette::Normal;
1034 }
1035 option.palette.setCurrentColorGroup(cg);
1036 }
1037 if (focus && current == *it) {
1039 if (viewState == EditingState)
1041 }
1042 option.state.setFlag(QStyle::State_MouseOver, *it == hover);
1043
1044 if (alternate) {
1045 int row = (*it).row();
1046 if (row != previousRow + 1) {
1047 // adjust alternateBase according to rows in the "gap"
1048 if (!d->hiddenRows.isEmpty()) {
1049 for (int r = qMax(previousRow + 1, 0); r < row; ++r) {
1050 if (!d->isHidden(r))
1051 alternateBase = !alternateBase;
1052 }
1053 } else {
1054 alternateBase = (row & 1) != 0;
1055 }
1056 }
1057 option.features.setFlag(QStyleOptionViewItem::Alternate, alternateBase);
1058
1059 // draw background of the item (only alternate row). rest of the background
1060 // is provided by the delegate
1061 QStyle::State oldState = option.state;
1062 option.state &= ~QStyle::State_Selected;
1064 option.state = oldState;
1065
1066 alternateBase = !alternateBase;
1067 previousRow = row;
1068 }
1069
1071 }
1072
1073#if QT_CONFIG(draganddrop)
1074 d->commonListView->paintDragDrop(&painter);
1075#endif
1076
1077#if QT_CONFIG(rubberband)
1078 // #### move this implementation into a dynamic class
1079 if (d->showElasticBand && d->elasticBand.isValid()) {
1080 QStyleOptionRubberBand opt;
1081 opt.initFrom(this);
1083 opt.opaque = false;
1084 opt.rect = d->mapToViewport(d->elasticBand, false).intersected(
1085 d->viewport->rect().adjusted(-16, -16, 16, 16));
1086 painter.save();
1087 painter.drawControl(QStyle::CE_RubberBand, opt);
1088 painter.restore();
1089 }
1090#endif
1091}
1092
1097{
1098 Q_D(const QListView);
1099 QRect rect(p.x() + horizontalOffset(), p.y() + verticalOffset(), 1, 1);
1100 const QList<QModelIndex> intersectVector = d->intersectingSet(rect);
1101 QModelIndex index = intersectVector.size() > 0
1102 ? intersectVector.last() : QModelIndex();
1103 if (index.isValid() && visualRect(index).contains(p))
1104 return index;
1105 return QModelIndex();
1106}
1107
1112{
1113 return d_func()->commonListView->horizontalOffset();
1114}
1115
1120{
1121 return d_func()->commonListView->verticalOffset();
1122}
1123
1127QModelIndex QListView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
1128{
1129 Q_D(QListView);
1131
1132 auto findAvailableRowBackward = [d](int row) {
1133 while (row >= 0 && d->isHiddenOrDisabled(row))
1134 --row;
1135 return row;
1136 };
1137
1138 auto findAvailableRowForward = [d](int row) {
1139 int rowCount = d->model->rowCount(d->root);
1140 if (!rowCount)
1141 return -1;
1142 while (row < rowCount && d->isHiddenOrDisabled(row))
1143 ++row;
1144 if (row >= rowCount)
1145 return -1;
1146 return row;
1147 };
1148
1149 QModelIndex current = currentIndex();
1150 if (!current.isValid()) {
1151 int row = findAvailableRowForward(0);
1152 if (row == -1)
1153 return QModelIndex();
1154 return d->model->index(row, d->column, d->root);
1155 }
1156
1157 if ((d->flow == LeftToRight && cursorAction == MoveLeft) ||
1158 (d->flow == TopToBottom && (cursorAction == MoveUp || cursorAction == MovePrevious))) {
1159 const int row = findAvailableRowBackward(current.row() - 1);
1160 if (row == -1)
1161 return current;
1162 return d->model->index(row, d->column, d->root);
1163 } else if ((d->flow == LeftToRight && cursorAction == MoveRight) ||
1164 (d->flow == TopToBottom && (cursorAction == MoveDown || cursorAction == MoveNext))) {
1165 const int row = findAvailableRowForward(current.row() + 1);
1166 if (row == -1)
1167 return current;
1168 return d->model->index(row, d->column, d->root);
1169 }
1170
1171 const QRect initialRect = rectForIndex(current);
1172 QRect rect = initialRect;
1173 if (rect.isEmpty()) {
1174 return d->model->index(0, d->column, d->root);
1175 }
1176 if (d->gridSize().isValid()) rect.setSize(d->gridSize());
1177
1178 QSize contents = d->contentsSize();
1179 QList<QModelIndex> intersectVector;
1180
1181 switch (cursorAction) {
1182 case MoveLeft:
1183 while (intersectVector.isEmpty()) {
1184 rect.translate(-rect.width(), 0);
1185 if (rect.right() <= 0)
1186 return current;
1187 if (rect.left() < 0)
1188 rect.setLeft(0);
1189 intersectVector = d->intersectingSet(rect);
1190 d->removeCurrentAndDisabled(&intersectVector, current);
1191 }
1192 return d->closestIndex(initialRect, intersectVector);
1193 case MoveRight:
1194 while (intersectVector.isEmpty()) {
1195 rect.translate(rect.width(), 0);
1196 if (rect.left() >= contents.width())
1197 return current;
1198 if (rect.right() > contents.width())
1199 rect.setRight(contents.width());
1200 intersectVector = d->intersectingSet(rect);
1201 d->removeCurrentAndDisabled(&intersectVector, current);
1202 }
1203 return d->closestIndex(initialRect, intersectVector);
1204 case MovePageUp: {
1205 if (rect.height() >= d->viewport->height())
1207
1208 rect.moveTop(rect.top() - d->viewport->height() + 1);
1209 if (rect.top() < rect.height()) {
1210 rect.setTop(0);
1211 rect.setBottom(1);
1212 }
1213 QModelIndex findindex = current;
1214 while (intersectVector.isEmpty()
1215 || rectForIndex(findindex).top() <= (rectForIndex(current).bottom() - d->viewport->rect().height())
1216 || rect.top() <= 0) {
1217 rect.translate(0, 1);
1218 if (rect.bottom() <= 0) {
1219 return current;
1220 }
1221 intersectVector = d->intersectingSet(rect);
1222 findindex = d->closestIndex(initialRect, intersectVector);
1223 }
1224 return findindex;
1225 }
1226 case MovePrevious:
1227 case MoveUp:
1228 while (intersectVector.isEmpty()) {
1229 rect.translate(0, -rect.height());
1230 if (rect.bottom() <= 0) {
1231#ifdef QT_KEYPAD_NAVIGATION
1232 if (QApplicationPrivate::keypadNavigationEnabled()) {
1233 int row = d->batchStartRow() - 1;
1234 while (row >= 0 && d->isHiddenOrDisabled(row))
1235 --row;
1236 if (row >= 0)
1237 return d->model->index(row, d->column, d->root);
1238 }
1239#endif
1240 return current;
1241 }
1242 if (rect.top() < 0)
1243 rect.setTop(0);
1244 intersectVector = d->intersectingSet(rect);
1245 d->removeCurrentAndDisabled(&intersectVector, current);
1246 }
1247 return d->closestIndex(initialRect, intersectVector);
1248 case MovePageDown: {
1249 if (rect.height() >= d->viewport->height())
1251
1252 rect.moveTop(rect.top() + d->viewport->height() - 1);
1253 if (rect.bottom() > contents.height() - rect.height()) {
1254 rect.setTop(contents.height() - 1);
1255 rect.setBottom(contents.height());
1256 }
1257 QModelIndex index = current;
1258 // index's bottom() - current's top() always <= (d->viewport->rect().height()
1259 while (intersectVector.isEmpty()
1260 || rectForIndex(index).bottom() >= (d->viewport->rect().height() + rectForIndex(current).top())
1261 || rect.bottom() > contents.height()) {
1262 rect.translate(0, -1);
1263 if (rect.top() >= contents.height()) {
1264 return current;
1265 }
1266 intersectVector = d->intersectingSet(rect);
1267 index = d->closestIndex(initialRect, intersectVector);
1268 }
1269 return index;
1270 }
1271 case MoveNext:
1272 case MoveDown:
1273 while (intersectVector.isEmpty()) {
1274 rect.translate(0, rect.height());
1275 if (rect.top() >= contents.height()) {
1276#ifdef QT_KEYPAD_NAVIGATION
1277 if (QApplicationPrivate::keypadNavigationEnabled()) {
1278 int rowCount = d->model->rowCount(d->root);
1279 int row = 0;
1280 while (row < rowCount && d->isHiddenOrDisabled(row))
1281 ++row;
1282 if (row < rowCount)
1283 return d->model->index(row, d->column, d->root);
1284 }
1285#endif
1286 return current;
1287 }
1288 if (rect.bottom() > contents.height())
1289 rect.setBottom(contents.height());
1290 intersectVector = d->intersectingSet(rect);
1291 d->removeCurrentAndDisabled(&intersectVector, current);
1292 }
1293 return d->closestIndex(initialRect, intersectVector);
1294 case MoveHome:
1295 return d->model->index(0, d->column, d->root);
1296 case MoveEnd:
1297 return d->model->index(d->batchStartRow() - 1, d->column, d->root);}
1298
1299 return current;
1300}
1301
1309{
1310 return d_func()->rectForIndex(index);
1311}
1312
1322{
1323 Q_D(QListView);
1324 if (d->movement == Static
1325 || !d->isIndexValid(index)
1326 || index.parent() != d->root
1327 || index.column() != d->column)
1328 return;
1329
1330 d->executePostedLayout();
1331 d->commonListView->setPositionForIndex(position, index);
1332}
1333
1337void QListView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command)
1338{
1339 Q_D(QListView);
1340 if (!d->selectionModel)
1341 return;
1342
1343 // if we are wrapping, we can only select inside the contents rectangle
1344 int w = qMax(d->contentsSize().width(), d->viewport->width());
1345 int h = qMax(d->contentsSize().height(), d->viewport->height());
1346 if (d->wrap && !QRect(0, 0, w, h).intersects(rect))
1347 return;
1348
1350
1351 if (rect.width() == 1 && rect.height() == 1) {
1352 const QList<QModelIndex> intersectVector =
1353 d->intersectingSet(rect.translated(horizontalOffset(), verticalOffset()));
1354 QModelIndex tl;
1355 if (!intersectVector.isEmpty())
1356 tl = intersectVector.last(); // special case for mouse press; only select the top item
1357 if (tl.isValid() && d->isIndexEnabled(tl))
1358 selection.select(tl, tl);
1359 } else {
1360 if (state() == DragSelectingState) { // visual selection mode (rubberband selection)
1361 selection = d->selection(rect.translated(horizontalOffset(), verticalOffset()));
1362 } else { // logical selection mode (key and mouse click selection)
1363 QModelIndex tl, br;
1364 // get the first item
1365 const QRect topLeft(rect.left() + horizontalOffset(), rect.top() + verticalOffset(), 1, 1);
1366 QList<QModelIndex> intersectVector = d->intersectingSet(topLeft);
1367 if (!intersectVector.isEmpty())
1368 tl = intersectVector.last();
1369 // get the last item
1370 const QRect bottomRight(rect.right() + horizontalOffset(), rect.bottom() + verticalOffset(), 1, 1);
1371 intersectVector = d->intersectingSet(bottomRight);
1372 if (!intersectVector.isEmpty())
1373 br = intersectVector.last();
1374
1375 // get the ranges
1376 if (tl.isValid() && br.isValid()
1377 && d->isIndexEnabled(tl)
1378 && d->isIndexEnabled(br)) {
1379 QRect first = d->cellRectForIndex(tl);
1380 QRect last = d->cellRectForIndex(br);
1381 QRect middle;
1382 if (d->flow == LeftToRight) {
1383 QRect &top = first;
1384 QRect &bottom = last;
1385 // if bottom is above top, swap them
1386 if (top.center().y() > bottom.center().y()) {
1387 QRect tmp = top;
1388 top = bottom;
1389 bottom = tmp;
1390 }
1391 // if the rect are on different lines, expand
1392 if (top.top() != bottom.top()) {
1393 // top rectangle
1394 if (isRightToLeft())
1395 top.setLeft(0);
1396 else
1397 top.setRight(contentsSize().width());
1398 // bottom rectangle
1399 if (isRightToLeft())
1400 bottom.setRight(contentsSize().width());
1401 else
1402 bottom.setLeft(0);
1403 } else if (top.left() > bottom.right()) {
1404 if (isRightToLeft())
1405 bottom.setLeft(top.right());
1406 else
1407 bottom.setRight(top.left());
1408 } else {
1409 if (isRightToLeft())
1410 top.setLeft(bottom.right());
1411 else
1412 top.setRight(bottom.left());
1413 }
1414 // middle rectangle
1415 if (top.bottom() < bottom.top()) {
1416 if (gridSize().isValid() && !gridSize().isNull())
1417 middle.setTop(top.top() + gridSize().height());
1418 else
1419 middle.setTop(top.bottom() + 1);
1420 middle.setLeft(qMin(top.left(), bottom.left()));
1421 middle.setBottom(bottom.top() - 1);
1422 middle.setRight(qMax(top.right(), bottom.right()));
1423 }
1424 } else { // TopToBottom
1425 QRect &left = first;
1426 QRect &right = last;
1427 if (left.center().x() > right.center().x())
1428 qSwap(left, right);
1429
1430 int ch = contentsSize().height();
1431 if (left.left() != right.left()) {
1432 // left rectangle
1433 if (isRightToLeft())
1434 left.setTop(0);
1435 else
1436 left.setBottom(ch);
1437
1438 // top rectangle
1439 if (isRightToLeft())
1440 right.setBottom(ch);
1441 else
1442 right.setTop(0);
1443 // only set middle if the
1444 middle.setTop(0);
1445 middle.setBottom(ch);
1446 if (gridSize().isValid() && !gridSize().isNull())
1447 middle.setLeft(left.left() + gridSize().width());
1448 else
1449 middle.setLeft(left.right() + 1);
1450 middle.setRight(right.left() - 1);
1451 } else if (left.bottom() < right.top()) {
1452 left.setBottom(right.top() - 1);
1453 } else {
1454 right.setBottom(left.top() - 1);
1455 }
1456 }
1457
1458 // do the selections
1459 QItemSelection topSelection = d->selection(first);
1460 QItemSelection middleSelection = d->selection(middle);
1461 QItemSelection bottomSelection = d->selection(last);
1462 // merge
1466 }
1467 }
1468 }
1469
1470 d->selectionModel->select(selection, command);
1471}
1472
1480{
1481 Q_D(const QListView);
1482 // ### NOTE: this is a potential bottleneck in non-static mode
1483 int c = d->column;
1484 QRegion selectionRegion;
1485 const QRect &viewportRect = d->viewport->rect();
1486 for (const auto &elem : selection) {
1487 if (!elem.isValid())
1488 continue;
1489 QModelIndex parent = elem.topLeft().parent();
1490 //we only display the children of the root in a listview
1491 //we're not interested in the other model indexes
1492 if (parent != d->root)
1493 continue;
1494 int t = elem.topLeft().row();
1495 int b = elem.bottomRight().row();
1496 if (d->viewMode == IconMode || d->isWrapping()) { // in non-static mode, we have to go through all selected items
1497 for (int r = t; r <= b; ++r) {
1498 const QRect &rect = visualRect(d->model->index(r, c, parent));
1499 if (viewportRect.intersects(rect))
1500 selectionRegion += rect;
1501 }
1502 } else { // in static mode, we can optimize a bit
1503 while (t <= b && d->isHidden(t)) ++t;
1504 while (b >= t && d->isHidden(b)) --b;
1505 const QModelIndex top = d->model->index(t, c, parent);
1506 const QModelIndex bottom = d->model->index(b, c, parent);
1507 QRect rect(visualRect(top).topLeft(),
1508 visualRect(bottom).bottomRight());
1509 if (viewportRect.intersects(rect))
1510 selectionRegion += rect;
1511 }
1512 }
1513
1514 return selectionRegion;
1515}
1516
1521{
1522 Q_D(const QListView);
1523 if (!d->selectionModel)
1524 return QModelIndexList();
1525
1526 QModelIndexList viewSelected = d->selectionModel->selectedIndexes();
1527 auto ignorable = [this, d](const QModelIndex &index) {
1528 return index.column() != d->column || index.parent() != d->root || isIndexHidden(index);
1529 };
1530 viewSelected.removeIf(ignorable);
1531 return viewSelected;
1532}
1533
1540{
1541 Q_D(QListView);
1542 // showing the scroll bars will trigger a resize event,
1543 // so we set the state to expanding to avoid
1544 // triggering another layout
1545 QAbstractItemView::State oldState = state();
1547 if (d->model->columnCount(d->root) > 0) { // no columns means no contents
1548 d->resetBatchStartRow();
1549 if (layoutMode() == SinglePass) {
1550 d->doItemsLayout(d->model->rowCount(d->root)); // layout everything
1551 } else if (!d->batchLayoutTimer.isActive()) {
1552 if (!d->doItemsLayout(d->batchSize)) // layout is done
1553 d->batchLayoutTimer.start(0, this); // do a new batch as fast as possible
1554 }
1555 } else { // clear the QBspTree generated by the last layout
1556 d->clear();
1557 }
1559 setState(oldState); // restoring the oldState
1560}
1561
1566{
1567 Q_D(QListView);
1568 if (geometry().isEmpty() || d->model->rowCount(d->root) <= 0 || d->model->columnCount(d->root) <= 0) {
1569 horizontalScrollBar()->setRange(0, 0);
1570 verticalScrollBar()->setRange(0, 0);
1571 } else {
1572 QModelIndex index = d->model->index(0, d->column, d->root);
1573 QStyleOptionViewItem option;
1575 QSize step = d->itemSize(option, index);
1576 d->commonListView->updateHorizontalScrollBar(step);
1577 d->commonListView->updateVerticalScrollBar(step);
1578 }
1579
1581
1582 // if the scroll bars are turned off, we resize the contents to the viewport
1583 if (d->movement == Static && !d->isWrapping()) {
1584 d->layoutChildren(); // we need the viewport size to be updated
1585 if (d->flow == TopToBottom) {
1586 if (horizontalScrollBarPolicy() == Qt::ScrollBarAlwaysOff) {
1587 d->setContentsSize(viewport()->width(), contentsSize().height());
1588 horizontalScrollBar()->setRange(0, 0); // we see all the contents anyway
1589 }
1590 } else { // LeftToRight
1591 if (verticalScrollBarPolicy() == Qt::ScrollBarAlwaysOff) {
1592 d->setContentsSize(contentsSize().width(), viewport()->height());
1593 verticalScrollBar()->setRange(0, 0); // we see all the contents anyway
1594 }
1595 }
1596 }
1597
1598}
1599
1604{
1605 Q_D(const QListView);
1606 return (d->isHidden(index.row())
1607 && (index.parent() == d->root)
1608 && index.column() == d->column);
1609}
1610
1619{
1620 Q_D(QListView);
1621 if (column < 0 || column >= d->model->columnCount(d->root))
1622 return;
1623 d->column = column;
1624 d->doDelayedItemsLayout();
1625}
1626
1628{
1629 Q_D(const QListView);
1630 return d->column;
1631}
1632
1645{
1646 Q_D(QListView);
1647 d->uniformItemSizes = enable;
1648}
1649
1651{
1652 Q_D(const QListView);
1653 return d->uniformItemSizes;
1654}
1655
1671{
1672 Q_D(QListView);
1673 if (d->wrapItemText == on)
1674 return;
1675 d->wrapItemText = on;
1676 d->doDelayedItemsLayout();
1677}
1678
1680{
1681 Q_D(const QListView);
1682 return d->wrapItemText;
1683}
1684
1701{
1702 Q_D(QListView);
1703 d->modeProperties |= uint(QListViewPrivate::SelectionRectVisible);
1704 d->setSelectionRectVisible(show);
1705}
1706
1708{
1709 Q_D(const QListView);
1710 return d->isSelectionRectVisible();
1711}
1712
1724{
1725 Q_D(QListView);
1726 if (d->itemAlignment == alignment)
1727 return;
1728 d->itemAlignment = alignment;
1730 d->doDelayedItemsLayout();
1731}
1732
1733Qt::Alignment QListView::itemAlignment() const
1734{
1735 Q_D(const QListView);
1736 return d->itemAlignment;
1737}
1738
1743{
1745}
1746
1747/*
1748 * private object implementation
1749 */
1750
1753 commonListView(nullptr),
1754 wrap(false),
1755 space(0),
1756 flow(QListView::TopToBottom),
1757 movement(QListView::Static),
1758 resizeMode(QListView::Fixed),
1759 layoutMode(QListView::SinglePass),
1760 viewMode(QListView::ListMode),
1761 modeProperties(0),
1762 column(0),
1763 uniformItemSizes(false),
1764 batchSize(100),
1765 showElasticBand(false),
1766 itemAlignment(Qt::Alignment())
1767{
1768}
1769
1771{
1772 delete commonListView;
1773}
1774
1776{
1777 // initialization of data structs
1780}
1781
1783{
1784 Q_Q(QListView);
1785 clear();
1786
1787 //take the size as if there were scrollbar in order to prevent scrollbar to blink
1788 layoutBounds = QRect(QPoint(), q->maximumViewportSize());
1789
1790 int frameAroundContents = 0;
1791 if (q->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents)) {
1793 option.initFrom(q);
1794 frameAroundContents = q->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &option) * 2;
1795 }
1796
1797 // maximumViewportSize() already takes scrollbar into account if policy is
1798 // Qt::ScrollBarAlwaysOn but scrollbar extent must be deduced if policy
1799 // is Qt::ScrollBarAsNeeded
1800 int verticalMargin = (vbarpolicy == Qt::ScrollBarAsNeeded) && (flow == QListView::LeftToRight || vbar->isVisible())
1801 && !q->style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarOverlap, nullptr, vbar)
1802 ? q->style()->pixelMetric(QStyle::PM_ScrollBarExtent, nullptr, vbar) + frameAroundContents
1803 : 0;
1804 int horizontalMargin = hbarpolicy==Qt::ScrollBarAsNeeded
1805 ? q->style()->pixelMetric(QStyle::PM_ScrollBarExtent, nullptr, hbar) + frameAroundContents
1806 : 0;
1807
1808 layoutBounds.adjust(0, 0, -verticalMargin, -horizontalMargin);
1809
1810 int rowCount = model->columnCount(root) <= 0 ? 0 : model->rowCount(root);
1811 commonListView->setRowCount(rowCount);
1812}
1813
1818{
1819 int max = model->rowCount(root) - 1;
1820 int first = batchStartRow();
1821 int last = qMin(first + delta - 1, max);
1822
1823 if (first == 0) {
1824 layoutChildren(); // make sure the viewport has the right size
1826 }
1827
1828 if (max < 0 || last < first) {
1829 return true; // nothing to do
1830 }
1831
1833 info.bounds = layoutBounds;
1834 info.grid = gridSize();
1835 info.spacing = (info.grid.isValid() ? 0 : spacing());
1836 info.first = first;
1837 info.last = last;
1838 info.wrap = isWrapping();
1839 info.flow = flow;
1840 info.max = max;
1841
1843}
1844
1846{
1847 if (!index.isValid() || isHidden(index.row()))
1848 return QListViewItem();
1849
1851}
1852
1854{
1855 Q_Q(const QListView);
1856 if (!rect.isValid())
1857 return rect;
1858
1860 int dx = -q->horizontalOffset();
1861 int dy = -q->verticalOffset();
1862 return result.adjusted(dx, dy, dx, dy);
1863}
1864
1866 const QList<QModelIndex> &candidates) const
1867{
1868 int distance = 0;
1869 int shortest = INT_MAX;
1870 QModelIndex closest;
1872
1873 for (; it != candidates.end(); ++it) {
1874 if (!(*it).isValid())
1875 continue;
1876
1877 const QRect indexRect = indexToListViewItem(*it).rect();
1878
1879 //if the center x (or y) position of an item is included in the rect of the other item,
1880 //we define the distance between them as the difference in x (or y) of their respective center.
1881 // Otherwise, we use the nahattan length between the 2 items
1882 if ((target.center().x() >= indexRect.x() && target.center().x() < indexRect.right())
1883 || (indexRect.center().x() >= target.x() && indexRect.center().x() < target.right())) {
1884 //one item's center is at the vertical of the other
1885 distance = qAbs(indexRect.center().y() - target.center().y());
1886 } else if ((target.center().y() >= indexRect.y() && target.center().y() < indexRect.bottom())
1887 || (indexRect.center().y() >= target.y() && indexRect.center().y() < target.bottom())) {
1888 //one item's center is at the vertical of the other
1889 distance = qAbs(indexRect.center().x() - target.center().x());
1890 } else {
1891 distance = (indexRect.center() - target.center()).manhattanLength();
1892 }
1893 if (distance < shortest) {
1894 shortest = distance;
1895 closest = *it;
1896 }
1897 }
1898 return closest;
1899}
1900
1901QSize QListViewPrivate::itemSize(const QStyleOptionViewItem &option, const QModelIndex &index) const
1902{
1903 Q_Q(const QListView);
1904 if (!uniformItemSizes) {
1905 const QAbstractItemDelegate *delegate = q->itemDelegateForIndex(index);
1906 return delegate ? delegate->sizeHint(option, index) : QSize();
1907 }
1908 if (!cachedItemSize.isValid()) { // the last item is probably the largest, so we use its size
1909 int row = model->rowCount(root) - 1;
1910 QModelIndex sample = model->index(row, column, root);
1911 const QAbstractItemDelegate *delegate = q->itemDelegateForIndex(sample);
1912 cachedItemSize = delegate ? delegate->sizeHint(option, sample) : QSize();
1913 }
1914 return cachedItemSize;
1915}
1916
1918{
1920 QModelIndex tl, br;
1921 const QList<QModelIndex> intersectVector = intersectingSet(rect);
1922 QList<QModelIndex>::const_iterator it = intersectVector.begin();
1923 for (; it != intersectVector.end(); ++it) {
1924 if (!tl.isValid() && !br.isValid()) {
1925 tl = br = *it;
1926 } else if ((*it).row() == (tl.row() - 1)) {
1927 tl = *it; // expand current range
1928 } else if ((*it).row() == (br.row() + 1)) {
1929 br = (*it); // expand current range
1930 } else {
1931 selection.select(tl, br); // select current range
1932 tl = br = *it; // start new range
1933 }
1934 }
1935
1936 if (tl.isValid() && br.isValid())
1937 selection.select(tl, br);
1938 else if (tl.isValid())
1939 selection.select(tl, tl);
1940 else if (br.isValid())
1941 selection.select(br, br);
1942
1943 return selection;
1944}
1945
1946#if QT_CONFIG(draganddrop)
1947QAbstractItemView::DropIndicatorPosition QListViewPrivate::position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const
1948{
1950 return static_cast<QListModeViewBase *>(commonListView)->position(pos, rect, idx);
1951 else
1952 return QAbstractItemViewPrivate::position(pos, rect, idx);
1953}
1954
1955bool QListViewPrivate::dropOn(QDropEvent *event, int *dropRow, int *dropCol, QModelIndex *dropIndex)
1956{
1958 return static_cast<QListModeViewBase *>(commonListView)->dropOn(event, dropRow, dropCol, dropIndex);
1959 else
1960 return QAbstractItemViewPrivate::dropOn(event, dropRow, dropCol, dropIndex);
1961}
1962#endif
1963
1965 const QModelIndex &current) const
1966{
1967 auto isCurrentOrDisabled = [this, current](const QModelIndex &index) {
1968 return !isIndexEnabled(index) || index == current;
1969 };
1970 indexes->removeIf(isCurrentOrDisabled);
1971}
1972
1973/*
1974 * Common ListView Implementation
1975*/
1976
1978{
1980}
1981
1983{
1985}
1986
1987#if QT_CONFIG(draganddrop)
1988void QCommonListViewBase::paintDragDrop(QPainter *painter)
1989{
1990 // FIXME: Until the we can provide a proper drop indicator
1991 // in IconMode, it makes no sense to show it
1992 dd->paintDropIndicator(painter);
1993}
1994#endif
1995
1997{
1998 return v->contentsRect().marginsRemoved(v->viewportMargins()).size();
1999}
2000
2002{
2003 horizontalScrollBar()->d_func()->itemviewChangeSingleStep(step.width() + spacing());
2005
2006 // If both scroll bars are set to auto, we might end up in a situation with enough space
2007 // for the actual content. But still one of the scroll bars will become enabled due to
2008 // the other one using the space. The other one will become invisible in the same cycle.
2009 // -> Infinite loop, QTBUG-39902
2010 const bool bothScrollBarsAuto = qq->verticalScrollBarPolicy() == Qt::ScrollBarAsNeeded &&
2011 qq->horizontalScrollBarPolicy() == Qt::ScrollBarAsNeeded;
2012
2013 const QSize viewportSize = QListModeViewBase::viewportSize(qq);
2014
2015 bool verticalWantsToShow = contentsSize.height() > viewportSize.height();
2016 bool horizontalWantsToShow;
2017 if (verticalWantsToShow)
2018 horizontalWantsToShow = contentsSize.width() > viewportSize.width() - qq->verticalScrollBar()->width();
2019 else
2020 horizontalWantsToShow = contentsSize.width() > viewportSize.width();
2021
2022 if (bothScrollBarsAuto && !horizontalWantsToShow) {
2023 // break the infinite loop described above by setting the range to 0, 0.
2024 // QAbstractScrollArea will then hide the scroll bar for us
2026 } else {
2028 }
2029}
2030
2032{
2033 verticalScrollBar()->d_func()->itemviewChangeSingleStep(step.height() + spacing());
2035
2036 // If both scroll bars are set to auto, we might end up in a situation with enough space
2037 // for the actual content. But still one of the scroll bars will become enabled due to
2038 // the other one using the space. The other one will become invisible in the same cycle.
2039 // -> Infinite loop, QTBUG-39902
2040 const bool bothScrollBarsAuto = qq->verticalScrollBarPolicy() == Qt::ScrollBarAsNeeded &&
2041 qq->horizontalScrollBarPolicy() == Qt::ScrollBarAsNeeded;
2042
2043 const QSize viewportSize = QListModeViewBase::viewportSize(qq);
2044
2045 bool horizontalWantsToShow = contentsSize.width() > viewportSize.width();
2046 bool verticalWantsToShow;
2047 if (horizontalWantsToShow)
2048 verticalWantsToShow = contentsSize.height() > viewportSize.height() - qq->horizontalScrollBar()->height();
2049 else
2050 verticalWantsToShow = contentsSize.height() > viewportSize.height();
2051
2052 if (bothScrollBarsAuto && !verticalWantsToShow) {
2053 // break the infinite loop described above by setting the range to 0, 0.
2054 // QAbstractScrollArea will then hide the scroll bar for us
2055 verticalScrollBar()->setRange(0, 0);
2056 } else {
2058 }
2059}
2060
2061void QCommonListViewBase::scrollContentsBy(int dx, int dy, bool /*scrollElasticBand*/)
2062{
2063 dd->scrollContentsBy(isRightToLeft() ? -dx : dx, dy);
2064}
2065
2067 bool above, bool below, const QRect &area, const QRect &rect) const
2068{
2069 int verticalValue = verticalScrollBar()->value();
2070 QRect adjusted = rect.adjusted(-spacing(), -spacing(), spacing(), spacing());
2071 if (hint == QListView::PositionAtTop || above)
2072 verticalValue += adjusted.top();
2073 else if (hint == QListView::PositionAtBottom || below)
2074 verticalValue += qMin(adjusted.top(), adjusted.bottom() - area.height() + 1);
2076 verticalValue += adjusted.top() - ((area.height() - adjusted.height()) / 2);
2077 return verticalValue;
2078}
2079
2081{
2083}
2084
2086 bool leftOf, bool rightOf, const QRect &area, const QRect &rect) const
2087{
2088 int horizontalValue = horizontalScrollBar()->value();
2089 if (isRightToLeft()) {
2091 horizontalValue += ((area.width() - rect.width()) / 2) - rect.left();
2092 } else {
2093 if (leftOf)
2094 horizontalValue -= rect.left();
2095 else if (rightOf)
2096 horizontalValue += qMin(rect.left(), area.width() - rect.right());
2097 }
2098 } else {
2100 horizontalValue += rect.left() - ((area.width()- rect.width()) / 2);
2101 } else {
2102 if (leftOf)
2103 horizontalValue += rect.left();
2104 else if (rightOf)
2105 horizontalValue += qMin(rect.left(), rect.right() - area.width());
2106 }
2107 }
2108 return horizontalValue;
2109}
2110
2111/*
2112 * ListMode ListView Implementation
2113*/
2116{
2117#if QT_CONFIG(draganddrop)
2118 dd->defaultDropAction = Qt::CopyAction;
2119#endif
2120}
2121
2122#if QT_CONFIG(draganddrop)
2123QAbstractItemView::DropIndicatorPosition QListModeViewBase::position(const QPoint &pos, const QRect &rect, const QModelIndex &index) const
2124{
2125 QAbstractItemView::DropIndicatorPosition r = QAbstractItemView::OnViewport;
2126 if (!dd->overwrite) {
2127 const int margin = 2;
2128 if (pos.x() - rect.left() < margin) {
2129 r = QAbstractItemView::AboveItem; // Visually, on the left
2130 } else if (rect.right() - pos.x() < margin) {
2131 r = QAbstractItemView::BelowItem; // Visually, on the right
2132 } else if (rect.contains(pos, true)) {
2133 r = QAbstractItemView::OnItem;
2134 }
2135 } else {
2136 QRect touchingRect = rect;
2137 touchingRect.adjust(-1, -1, 1, 1);
2138 if (touchingRect.contains(pos, false)) {
2139 r = QAbstractItemView::OnItem;
2140 }
2141 }
2142
2143 if (r == QAbstractItemView::OnItem && (!(dd->model->flags(index) & Qt::ItemIsDropEnabled)))
2144 r = pos.x() < rect.center().x() ? QAbstractItemView::AboveItem : QAbstractItemView::BelowItem;
2145
2146 return r;
2147}
2148
2149void QListModeViewBase::dragMoveEvent(QDragMoveEvent *event)
2150{
2151 if (qq->dragDropMode() == QAbstractItemView::InternalMove
2152 && (event->source() != qq || !(event->possibleActions() & Qt::MoveAction)))
2153 return;
2154
2155 // ignore by default
2156 event->ignore();
2157
2158 // can't use indexAt, doesn't account for spacing.
2159 QPoint p = event->position().toPoint();
2160 QRect rect(p.x() + horizontalOffset(), p.y() + verticalOffset(), 1, 1);
2161 rect.adjust(-dd->spacing(), -dd->spacing(), dd->spacing(), dd->spacing());
2162 const QList<QModelIndex> intersectVector = dd->intersectingSet(rect);
2163 QModelIndex index = intersectVector.size() > 0
2164 ? intersectVector.last() : QModelIndex();
2165 dd->hover = index;
2167 && dd->canDrop(event)) {
2168
2169 if (index.isValid() && dd->showDropIndicator) {
2171 dd->dropIndicatorPosition = position(event->position().toPoint(), rect, index);
2172 // if spacing, should try to draw between items, not just next to item.
2173 switch (dd->dropIndicatorPosition) {
2174 case QAbstractItemView::AboveItem:
2175 if (dd->isIndexDropEnabled(index.parent())) {
2176 dd->dropIndicatorRect = QRect(rect.left()-dd->spacing(), rect.top(), 0, rect.height());
2177 event->accept();
2178 } else {
2179 dd->dropIndicatorRect = QRect();
2180 }
2181 break;
2182 case QAbstractItemView::BelowItem:
2183 if (dd->isIndexDropEnabled(index.parent())) {
2184 dd->dropIndicatorRect = QRect(rect.right()+dd->spacing(), rect.top(), 0, rect.height());
2185 event->accept();
2186 } else {
2187 dd->dropIndicatorRect = QRect();
2188 }
2189 break;
2190 case QAbstractItemView::OnItem:
2191 if (dd->isIndexDropEnabled(index)) {
2192 dd->dropIndicatorRect = rect;
2193 event->accept();
2194 } else {
2195 dd->dropIndicatorRect = QRect();
2196 }
2197 break;
2198 case QAbstractItemView::OnViewport:
2199 dd->dropIndicatorRect = QRect();
2200 if (dd->isIndexDropEnabled(qq->rootIndex())) {
2201 event->accept(); // allow dropping in empty areas
2202 }
2203 break;
2204 }
2205 } else {
2206 dd->dropIndicatorRect = QRect();
2207 dd->dropIndicatorPosition = QAbstractItemView::OnViewport;
2208 if (dd->isIndexDropEnabled(qq->rootIndex())) {
2209 event->accept(); // allow dropping in empty areas
2210 }
2211 }
2212 dd->viewport->update();
2213 } // can drop
2214
2215 if (dd->shouldAutoScroll(event->position().toPoint()))
2217}
2218
2230bool QListModeViewBase::dropOn(QDropEvent *event, int *dropRow, int *dropCol, QModelIndex *dropIndex)
2231{
2232 if (event->isAccepted())
2233 return false;
2234
2236 if (dd->viewport->rect().contains(event->position().toPoint())) {
2237 // can't use indexAt, doesn't account for spacing.
2238 QPoint p = event->position().toPoint();
2239 QRect rect(p.x() + horizontalOffset(), p.y() + verticalOffset(), 1, 1);
2240 rect.adjust(-dd->spacing(), -dd->spacing(), dd->spacing(), dd->spacing());
2241 const QList<QModelIndex> intersectVector = dd->intersectingSet(rect);
2242 index = intersectVector.size() > 0
2243 ? intersectVector.last() : QModelIndex();
2244 if (!index.isValid())
2245 index = dd->root;
2246 }
2247
2248 // If we are allowed to do the drop
2249 if (dd->model->supportedDropActions() & event->dropAction()) {
2250 int row = -1;
2251 int col = -1;
2252 if (index != dd->root) {
2253 dd->dropIndicatorPosition = position(event->position().toPoint(), qq->visualRect(index), index);
2254 switch (dd->dropIndicatorPosition) {
2255 case QAbstractItemView::AboveItem:
2256 row = index.row();
2257 col = index.column();
2258 index = index.parent();
2259 break;
2260 case QAbstractItemView::BelowItem:
2261 row = index.row() + 1;
2262 col = index.column();
2263 index = index.parent();
2264 break;
2265 case QAbstractItemView::OnItem:
2266 case QAbstractItemView::OnViewport:
2267 break;
2268 }
2269 } else {
2270 dd->dropIndicatorPosition = QAbstractItemView::OnViewport;
2271 }
2272 *dropIndex = index;
2273 *dropRow = row;
2274 *dropCol = col;
2276 return true;
2277 }
2278 return false;
2279}
2280
2281#endif //QT_CONFIG(draganddrop)
2282
2284{
2286 && ((flow() == QListView::TopToBottom && !isWrapping())
2287 || (flow() == QListView::LeftToRight && isWrapping()))) {
2288 const int steps = (flow() == QListView::TopToBottom ? scrollValueMap : segmentPositions).size() - 1;
2289 if (steps > 0) {
2290 const int pageSteps = perItemScrollingPageSteps(viewport()->height(), contentsSize.height(), isWrapping());
2292 verticalScrollBar()->setPageStep(pageSteps);
2293 verticalScrollBar()->setRange(0, steps - pageSteps);
2294 } else {
2295 verticalScrollBar()->setRange(0, 0);
2296 }
2297 // } else if (vertical && d->isWrapping() && d->movement == Static) {
2298 // ### wrapped scrolling in flow direction
2299 } else {
2301 }
2302}
2303
2305{
2307 && ((flow() == QListView::TopToBottom && isWrapping())
2308 || (flow() == QListView::LeftToRight && !isWrapping()))) {
2309 int steps = (flow() == QListView::TopToBottom ? segmentPositions : scrollValueMap).size() - 1;
2310 if (steps > 0) {
2311 const int pageSteps = perItemScrollingPageSteps(viewport()->width(), contentsSize.width(), isWrapping());
2313 horizontalScrollBar()->setPageStep(pageSteps);
2314 horizontalScrollBar()->setRange(0, steps - pageSteps);
2315 } else {
2317 }
2318 } else {
2320 }
2321}
2322
2324 bool above, bool below, const QRect &area, const QRect &rect) const
2325{
2327 int value;
2328 if (scrollValueMap.isEmpty()) {
2329 value = 0;
2330 } else {
2331 int scrollBarValue = verticalScrollBar()->value();
2332 int numHidden = 0;
2333 for (const auto &idx : std::as_const(dd->hiddenRows))
2334 if (idx.row() <= scrollBarValue)
2335 ++numHidden;
2336 value = qBound(0, scrollValueMap.at(verticalScrollBar()->value()) - numHidden, flowPositions.size() - 1);
2337 }
2338 if (above)
2340 else if (below)
2343 return value;
2344
2345 return perItemScrollToValue(index, value, area.height(), hint, Qt::Vertical, isWrapping(), rect.height());
2346 }
2347
2349}
2350
2352{
2354 if (isWrapping()) {
2356 const int max = segmentPositions.size() - 1;
2357 int currentValue = qBound(0, horizontalScrollBar()->value(), max);
2359 int maximumValue = qBound(0, horizontalScrollBar()->maximum(), max);
2360 int maximum = segmentPositions.at(maximumValue);
2361 return (isRightToLeft() ? maximum - position : position);
2362 }
2363 } else if (flow() == QListView::LeftToRight && !flowPositions.isEmpty()) {
2365 int maximum = flowPositions.at(scrollValueMap.at(horizontalScrollBar()->maximum()));
2366 return (isRightToLeft() ? maximum - position : position);
2367 }
2368 }
2370}
2371
2373{
2375 if (isWrapping()) {
2377 int value = verticalScrollBar()->value();
2378 if (value >= segmentPositions.size())
2379 return 0;
2380 return segmentPositions.at(value) - spacing();
2381 }
2382 } else if (flow() == QListView::TopToBottom && !flowPositions.isEmpty()) {
2383 int value = verticalScrollBar()->value();
2384 if (value > scrollValueMap.size())
2385 return 0;
2387 }
2388 }
2390}
2391
2393 bool leftOf, bool rightOf, const QRect &area, const QRect &rect) const
2394{
2397
2398 int value;
2399 if (scrollValueMap.isEmpty())
2400 value = 0;
2401 else
2403 if (leftOf)
2405 else if (rightOf)
2408 return value;
2409
2410 return perItemScrollToValue(index, value, area.width(), hint, Qt::Horizontal, isWrapping(), rect.width());
2411}
2412
2413void QListModeViewBase::scrollContentsBy(int dx, int dy, bool scrollElasticBand)
2414{
2415 // ### reorder this logic
2416 const int verticalValue = verticalScrollBar()->value();
2417 const int horizontalValue = horizontalScrollBar()->value();
2418 const bool vertical = (verticalScrollMode() == QAbstractItemView::ScrollPerItem);
2419 const bool horizontal = (horizontalScrollMode() == QAbstractItemView::ScrollPerItem);
2420
2421 if (isWrapping()) {
2423 return;
2424 const int max = segmentPositions.size() - 1;
2425 if (horizontal && flow() == QListView::TopToBottom && dx != 0) {
2426 int currentValue = qBound(0, horizontalValue, max);
2427 int previousValue = qBound(0, currentValue + dx, max);
2428 int currentCoordinate = segmentPositions.at(currentValue) - spacing();
2429 int previousCoordinate = segmentPositions.at(previousValue) - spacing();
2430 dx = previousCoordinate - currentCoordinate;
2431 } else if (vertical && flow() == QListView::LeftToRight && dy != 0) {
2432 int currentValue = qBound(0, verticalValue, max);
2433 int previousValue = qBound(0, currentValue + dy, max);
2434 int currentCoordinate = segmentPositions.at(currentValue) - spacing();
2435 int previousCoordinate = segmentPositions.at(previousValue) - spacing();
2436 dy = previousCoordinate - currentCoordinate;
2437 }
2438 } else {
2439 if (flowPositions.isEmpty())
2440 return;
2441 const int max = scrollValueMap.size() - 1;
2442 if (vertical && flow() == QListView::TopToBottom && dy != 0) {
2443 int currentValue = qBound(0, verticalValue, max);
2444 int previousValue = qBound(0, currentValue + dy, max);
2445 int currentCoordinate = flowPositions.at(scrollValueMap.at(currentValue));
2446 int previousCoordinate = flowPositions.at(scrollValueMap.at(previousValue));
2447 dy = previousCoordinate - currentCoordinate;
2448 } else if (horizontal && flow() == QListView::LeftToRight && dx != 0) {
2449 int currentValue = qBound(0, horizontalValue, max);
2450 int previousValue = qBound(0, currentValue + dx, max);
2451 int currentCoordinate = flowPositions.at(scrollValueMap.at(currentValue));
2452 int previousCoordinate = flowPositions.at(scrollValueMap.at(previousValue));
2453 dx = previousCoordinate - currentCoordinate;
2454 }
2455 }
2456 QCommonListViewBase::scrollContentsBy(dx, dy, scrollElasticBand);
2457}
2458
2460{
2461 doStaticLayout(info);
2462 return batchStartRow > max; // returning true stops items layout
2463}
2464
2466{
2469 || index.row() >= flowPositions.size() - 1)
2470 return QListViewItem();
2471
2472 const int segment = qBinarySearch<int>(segmentStartRows, index.row(),
2473 0, segmentStartRows.size() - 1);
2474
2475
2476 QStyleOptionViewItem options;
2477 initViewItemOption(&options);
2478 options.rect.setSize(contentsSize);
2480 ? cachedItemSize() : itemSize(options, index);
2481 QSize cellSize = size;
2482
2483 QPoint pos;
2484 if (flow() == QListView::LeftToRight) {
2485 pos.setX(flowPositions.at(index.row()));
2487 } else { // TopToBottom
2488 pos.setY(flowPositions.at(index.row()));
2490 if (isWrapping()) { // make the items as wide as the segment
2491 int right = (segment + 1 >= segmentPositions.size()
2493 : segmentPositions.at(segment + 1));
2494 cellSize.setWidth(right - pos.x());
2495 } else { // make the items as wide as the viewport
2496 cellSize.setWidth(qMax(size.width(), viewport()->width() - 2 * spacing()));
2497 }
2498 }
2499
2501 size.setWidth(qMin(size.width(), cellSize.width()));
2503 pos.setX(pos.x() + cellSize.width() - size.width());
2505 pos.setX(pos.x() + (cellSize.width() - size.width()) / 2);
2506 } else {
2507 size.setWidth(cellSize.width());
2508 }
2509
2510 return QListViewItem(QRect(pos, size), index.row());
2511}
2512
2513QPoint QListModeViewBase::initStaticLayout(const QListViewLayoutInfo &info)
2514{
2515 int x, y;
2516 if (info.first == 0) {
2522 x = info.bounds.left() + info.spacing;
2523 y = info.bounds.top() + info.spacing;
2526 } else if (info.wrap) {
2527 if (info.flow == QListView::LeftToRight) {
2530 } else { // flow == QListView::TopToBottom
2533 }
2534 } else { // not first and not wrap
2535 if (info.flow == QListView::LeftToRight) {
2537 y = info.bounds.top() + info.spacing;
2538 } else { // flow == QListView::TopToBottom
2539 x = info.bounds.left() + info.spacing;
2541 }
2542 }
2543 return QPoint(x, y);
2544}
2545
2549void QListModeViewBase::doStaticLayout(const QListViewLayoutInfo &info)
2550{
2551 const bool useItemSize = !info.grid.isValid();
2552 const QPoint topLeft = initStaticLayout(info);
2553 QStyleOptionViewItem option;
2555 option.rect = info.bounds;
2556 option.rect.adjust(info.spacing, info.spacing, -info.spacing, -info.spacing);
2557
2558 // The static layout data structures are as follows:
2559 // One vector contains the coordinate in the direction of layout flow.
2560 // Another vector contains the coordinates of the segments.
2561 // A third vector contains the index (model row) of the first item
2562 // of each segment.
2563
2564 int segStartPosition;
2565 int segEndPosition;
2566 int deltaFlowPosition;
2567 int deltaSegPosition;
2568 int deltaSegHint;
2569 int flowPosition;
2570 int segPosition;
2571
2572 if (info.flow == QListView::LeftToRight) {
2573 segStartPosition = info.bounds.left();
2574 segEndPosition = info.bounds.width();
2575 flowPosition = topLeft.x();
2576 segPosition = topLeft.y();
2577 deltaFlowPosition = info.grid.width(); // dx
2578 deltaSegPosition = useItemSize ? batchSavedDeltaSeg : info.grid.height(); // dy
2579 deltaSegHint = info.grid.height();
2580 } else { // flow == QListView::TopToBottom
2581 segStartPosition = info.bounds.top();
2582 segEndPosition = info.bounds.height();
2583 flowPosition = topLeft.y();
2584 segPosition = topLeft.x();
2585 deltaFlowPosition = info.grid.height(); // dy
2586 deltaSegPosition = useItemSize ? batchSavedDeltaSeg : info.grid.width(); // dx
2587 deltaSegHint = info.grid.width();
2588 }
2589
2590 for (int row = info.first; row <= info.last; ++row) {
2591 if (isHidden(row)) { // ###
2593 } else {
2594 // if we are not using a grid, we need to find the deltas
2595 if (useItemSize) {
2597 if (info.flow == QListView::LeftToRight) {
2598 deltaFlowPosition = hint.width() + info.spacing;
2599 deltaSegHint = hint.height() + info.spacing;
2600 } else { // TopToBottom
2601 deltaFlowPosition = hint.height() + info.spacing;
2602 deltaSegHint = hint.width() + info.spacing;
2603 }
2604 }
2605 // create new segment
2606 if (info.wrap && (flowPosition + deltaFlowPosition >= segEndPosition)) {
2608 flowPosition = info.spacing + segStartPosition;
2609 segPosition += info.spacing + deltaSegPosition;
2610 segmentPositions.append(segPosition);
2612 deltaSegPosition = 0;
2613 }
2614 // save the flow position of this item
2617 // prepare for the next item
2618 deltaSegPosition = qMax(deltaSegHint, deltaSegPosition);
2619 flowPosition += info.spacing + deltaFlowPosition;
2620 }
2621 }
2622 // used when laying out next batch
2624 batchSavedDeltaSeg = deltaSegPosition;
2625 batchStartRow = info.last + 1;
2626 if (info.last == info.max)
2627 flowPosition -= info.spacing; // remove extra spacing
2628 // set the contents size
2629 QRect rect = info.bounds;
2630 if (info.flow == QListView::LeftToRight) {
2631 rect.setRight(segmentPositions.size() == 1 ? flowPosition : info.bounds.right());
2632 rect.setBottom(segPosition + deltaSegPosition);
2633 } else { // TopToBottom
2634 rect.setRight(segPosition + deltaSegPosition);
2635 rect.setBottom(segmentPositions.size() == 1 ? flowPosition : info.bounds.bottom());
2636 }
2637 contentsSize = QSize(rect.right(), rect.bottom());
2638 // if it is the last batch, save the end of the segments
2639 if (info.last == info.max) {
2643 segmentPositions.append(info.wrap ? segPosition + deltaSegPosition : INT_MAX);
2644 }
2645 // if the new items are visible, update the viewport
2646 QRect changedRect(topLeft, rect.bottomRight());
2647 if (clipRect().intersects(changedRect))
2648 viewport()->update();
2649}
2650
2657{
2659 int segStartPosition;
2660 int segEndPosition;
2661 int flowStartPosition;
2662 int flowEndPosition;
2663 if (flow() == QListView::LeftToRight) {
2664 segStartPosition = area.top();
2665 segEndPosition = area.bottom();
2666 flowStartPosition = area.left();
2667 flowEndPosition = area.right();
2668 } else {
2669 segStartPosition = area.left();
2670 segEndPosition = area.right();
2671 flowStartPosition = area.top();
2672 flowEndPosition = area.bottom();
2673 }
2675 return ret;
2676 // the last segment position is actually the edge of the last segment
2677 const int segLast = segmentPositions.size() - 2;
2678 int seg = qBinarySearch<int>(segmentPositions, segStartPosition, 0, segLast + 1);
2679 for (; seg <= segLast && segmentPositions.at(seg) <= segEndPosition; ++seg) {
2680 int first = segmentStartRows.at(seg);
2681 int last = (seg < segLast ? segmentStartRows.at(seg + 1) : batchStartRow) - 1;
2682 if (segmentExtents.at(seg) < flowStartPosition)
2683 continue;
2684 int row = qBinarySearch<int>(flowPositions, flowStartPosition, first, last);
2685 for (; row <= last && flowPositions.at(row) <= flowEndPosition; ++row) {
2686 if (isHidden(row))
2687 continue;
2689 if (index.isValid()) {
2690 if (flow() == QListView::LeftToRight || dd->itemAlignment == Qt::Alignment()) {
2691 ret += index;
2692 } else {
2693 const auto viewItem = indexToListViewItem(index);
2694 const int iw = viewItem.width();
2695 const int startPos = qMax(segStartPosition, segmentPositions.at(seg));
2696 const int endPos = qMin(segmentPositions.at(seg + 1), segEndPosition);
2697 if (endPos >= viewItem.x && startPos < viewItem.x + iw)
2698 ret += index;
2699 }
2700 }
2701#if 0 // for debugging
2702 else
2703 qWarning("intersectingSet: row %d was invalid", row);
2704#endif
2705 }
2706 }
2707 return ret;
2708}
2709
2711{
2713}
2714
2715
2717{
2718 if (isWrapping())
2719 return rect;
2720 // If the listview is in "listbox-mode", the items are as wide as the view.
2721 // But we don't shrink the items.
2722 QRect result = rect;
2723 if (flow() == QListView::TopToBottom) {
2724 result.setLeft(spacing());
2725 result.setWidth(qMax(rect.width(), qMax(contentsSize.width(), viewport()->width()) - 2 * spacing()));
2726 } else { // LeftToRight
2727 result.setTop(spacing());
2728 result.setHeight(qMax(rect.height(), qMax(contentsSize.height(), viewport()->height()) - 2 * spacing()));
2729 }
2730 return result;
2731}
2732
2733int QListModeViewBase::perItemScrollingPageSteps(int length, int bounds, bool wrap) const
2734{
2736 if (wrap)
2738 else if (!flowPositions.isEmpty()) {
2739 positions.reserve(scrollValueMap.size());
2740 for (int itemShown : scrollValueMap)
2741 positions.append(flowPositions.at(itemShown));
2742 }
2743 if (positions.isEmpty() || bounds <= length)
2744 return positions.size();
2745 if (uniformItemSizes()) {
2746 for (int i = 1; i < positions.size(); ++i)
2747 if (positions.at(i) > 0)
2748 return length / positions.at(i);
2749 return 0; // all items had height 0
2750 }
2751 int pageSteps = 0;
2752 int steps = positions.size() - 1;
2753 int max = qMax(length, bounds);
2754 int min = qMin(length, bounds);
2755 int pos = min - (max - positions.constLast());
2756
2757 while (pos >= 0 && steps > 0) {
2758 pos -= (positions.at(steps) - positions.at(steps - 1));
2759 if (pos >= 0) //this item should be visible
2760 ++pageSteps;
2761 --steps;
2762 }
2763
2764 // at this point we know that positions has at least one entry
2765 return qMax(pageSteps, 1);
2766}
2767
2768int QListModeViewBase::perItemScrollToValue(int index, int scrollValue, int viewportSize,
2770 Qt::Orientation orientation, bool wrap, int itemExtent) const
2771{
2772 if (index < 0)
2773 return scrollValue;
2774
2775 itemExtent += spacing();
2776 QList<int> hiddenRows = dd->hiddenRowIds();
2777 std::sort(hiddenRows.begin(), hiddenRows.end());
2778 int hiddenRowsBefore = 0;
2779 for (int i = 0; i < hiddenRows.size() - 1; ++i)
2780 if (hiddenRows.at(i) > index + hiddenRowsBefore)
2781 break;
2782 else
2783 ++hiddenRowsBefore;
2784 if (!wrap) {
2785 int topIndex = index;
2786 const int bottomIndex = topIndex;
2787 const int bottomCoordinate = flowPositions.at(index + hiddenRowsBefore);
2788 while (topIndex > 0 &&
2789 (bottomCoordinate - flowPositions.at(topIndex + hiddenRowsBefore - 1) + itemExtent) <= (viewportSize)) {
2790 topIndex--;
2791 // will the next one be a hidden row -> skip
2792 while (hiddenRowsBefore > 0 && hiddenRows.at(hiddenRowsBefore - 1) >= topIndex + hiddenRowsBefore - 1)
2793 hiddenRowsBefore--;
2794 }
2795
2796 const int itemCount = bottomIndex - topIndex + 1;
2797 switch (hint) {
2799 return index;
2801 return index - itemCount + 1;
2803 return index - (itemCount / 2);
2804 default:
2805 break;
2806 }
2807 } else { // wrapping
2808 Qt::Orientation flowOrientation = (flow() == QListView::LeftToRight
2810 if (flowOrientation == orientation) { // scrolling in the "flow" direction
2811 // ### wrapped scrolling in the flow direction
2812 return flowPositions.at(index + hiddenRowsBefore); // ### always pixel based for now
2813 } else if (!segmentStartRows.isEmpty()) { // we are scrolling in the "segment" direction
2814 int segment = qBinarySearch<int>(segmentStartRows, index, 0, segmentStartRows.size() - 1);
2815 int leftSegment = segment;
2816 const int rightSegment = leftSegment;
2817 const int bottomCoordinate = segmentPositions.at(segment);
2818
2819 while (leftSegment > scrollValue &&
2820 (bottomCoordinate - segmentPositions.at(leftSegment-1) + itemExtent) <= (viewportSize)) {
2821 leftSegment--;
2822 }
2823
2824 const int segmentCount = rightSegment - leftSegment + 1;
2825 switch (hint) {
2827 return segment;
2829 return segment - segmentCount + 1;
2831 return segment - (segmentCount / 2);
2832 default:
2833 break;
2834 }
2835 }
2836 }
2837 return scrollValue;
2838}
2839
2841{
2847 batchStartRow = 0;
2849}
2850
2851/*
2852 * IconMode ListView Implementation
2853*/
2854
2856{
2857 if (index.row() >= items.size())
2858 return;
2859 const QSize oldContents = contentsSize;
2860 qq->update(index); // update old position
2861 moveItem(index.row(), position);
2862 qq->update(index); // update new position
2863
2864 if (contentsSize != oldContents)
2865 dd->viewUpdateGeometries(); // update the scroll bars
2866}
2867
2869{
2870 if (row >= 0 && row < items.size()) //remove item
2871 tree.removeLeaf(items.at(row).rect(), row);
2873}
2874
2876{
2878 if (row >= 0 && row < items.size()) //insert item
2879 tree.insertLeaf(items.at(row).rect(), row);
2880}
2881
2882#if QT_CONFIG(draganddrop)
2883bool QIconModeViewBase::filterStartDrag(Qt::DropActions supportedActions)
2884{
2885 // This function does the same thing as in QAbstractItemView::startDrag(),
2886 // plus adding viewitems to the draggedItems list.
2887 // We need these items to draw the drag items
2889 if (indexes.size() > 0 ) {
2890 if (viewport()->acceptDrops()) {
2892 for (; it != indexes.constEnd(); ++it)
2894 && (*it).column() == dd->column)
2896 }
2897
2898 QRect rect;
2899 QPixmap pixmap = dd->renderToPixmap(indexes, &rect);
2900 rect.adjust(horizontalOffset(), verticalOffset(), 0, 0);
2901 QDrag *drag = new QDrag(qq);
2902 drag->setMimeData(dd->model->mimeData(indexes));
2903 drag->setPixmap(pixmap);
2904 drag->setHotSpot(dd->pressedPosition - rect.topLeft());
2905 dd->dropEventMoved = false;
2906 Qt::DropAction action = drag->exec(supportedActions, dd->defaultDropAction);
2908 // delete item, unless it has already been moved internally (see filterDropEvent)
2909 if (action == Qt::MoveAction && !dd->dropEventMoved) {
2910 if (dd->dragDropMode != QAbstractItemView::InternalMove || drag->target() == qq->viewport())
2911 dd->clearOrRemove();
2912 }
2913 dd->dropEventMoved = false;
2914 }
2915 return true;
2916}
2917
2918bool QIconModeViewBase::filterDropEvent(QDropEvent *e)
2919{
2920 if (e->source() != qq)
2921 return false;
2922
2923 const QSize contents = contentsSize;
2925 QPoint end = e->position().toPoint() + offset;
2926 if (qq->acceptDrops()) {
2927 const Qt::ItemFlags dropableFlags = Qt::ItemIsDropEnabled|Qt::ItemIsEnabled;
2928 const QList<QModelIndex> &dropIndices = intersectingSet(QRect(end, QSize(1, 1)));
2929 for (const QModelIndex &index : dropIndices)
2930 if ((index.flags() & dropableFlags) == dropableFlags)
2931 return false;
2932 }
2934 QPoint delta = (dd->movement == QListView::Snap ? snapToGrid(end) - snapToGrid(start) : end - start);
2936 for (const auto &index : indexes) {
2938 viewport()->update(dd->mapToViewport(rect, false));
2939 QPoint dest = rect.topLeft() + delta;
2940 if (qq->isRightToLeft())
2941 dest.setX(dd->flipX(dest.x()) - rect.width());
2942 moveItem(index.row(), dest);
2943 qq->update(index);
2944 }
2945 dd->stopAutoScroll();
2947 dd->emitIndexesMoved(indexes);
2948 // do not delete item on internal move, see filterStartDrag()
2949 dd->dropEventMoved = true;
2950 e->accept(); // we have handled the event
2951 // if the size has not grown, we need to check if it has shrunk
2952 if (contentsSize != contents) {
2953 if ((contentsSize.width() <= contents.width()
2954 || contentsSize.height() <= contents.height())) {
2955 updateContentsSize();
2956 }
2958 }
2959 return true;
2960}
2961
2962bool QIconModeViewBase::filterDragLeaveEvent(QDragLeaveEvent *e)
2963{
2964 viewport()->update(draggedItemsRect()); // erase the area
2965 draggedItemsPos = QPoint(-1, -1); // don't draw the dragged items
2966 return QCommonListViewBase::filterDragLeaveEvent(e);
2967}
2968
2969bool QIconModeViewBase::filterDragMoveEvent(QDragMoveEvent *e)
2970{
2971 const bool wasAccepted = e->isAccepted();
2972
2973 // ignore by default
2974 e->ignore();
2975
2976 if (e->source() != qq || !dd->canDrop(e)) {
2977 // restore previous acceptance on failure
2978 e->setAccepted(wasAccepted);
2979 return false;
2980 }
2981
2982 // get old dragged items rect
2983 QRect itemsRect = this->itemsRect(draggedItems);
2984 viewport()->update(itemsRect.translated(draggedItemsDelta()));
2985 // update position
2986 draggedItemsPos = e->position().toPoint();
2987 // get new items rect
2988 viewport()->update(itemsRect.translated(draggedItemsDelta()));
2989 // set the item under the cursor to current
2991 if (movement() == QListView::Snap) {
2992 QRect rect(snapToGrid(e->position().toPoint() + offset()), gridSize());
2993 const QList<QModelIndex> intersectVector = intersectingSet(rect);
2994 index = intersectVector.size() > 0 ? intersectVector.last() : QModelIndex();
2995 } else {
2996 index = qq->indexAt(e->position().toPoint());
2997 }
2998 // check if we allow drops here
3000 e->accept(); // allow changing item position
3002 e->accept(); // allow dropping on dropenabled items
3003 else if (!index.isValid())
3004 e->accept(); // allow dropping in empty areas
3005
3006 // the event was treated. do autoscrolling
3007 if (dd->shouldAutoScroll(e->position().toPoint()))
3009 return true;
3010}
3011#endif // QT_CONFIG(draganddrop)
3012
3014{
3016}
3017
3018void QIconModeViewBase::scrollContentsBy(int dx, int dy, bool scrollElasticBand)
3019{
3020 if (scrollElasticBand)
3021 dd->scrollElasticBandBy(isRightToLeft() ? -dx : dx, dy);
3022
3023 QCommonListViewBase::scrollContentsBy(dx, dy, scrollElasticBand);
3024 if (!draggedItems.isEmpty())
3025 viewport()->update(draggedItemsRect().translated(dx, dy));
3026}
3027
3028void QIconModeViewBase::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
3029{
3030 if (column() >= topLeft.column() && column() <= bottomRight.column()) {
3031 QStyleOptionViewItem option;
3033 const int bottom = qMin(items.size(), bottomRight.row() + 1);
3034 const bool useItemSize = !dd->grid.isValid();
3035 for (int row = topLeft.row(); row < bottom; ++row)
3036 {
3038 if (!useItemSize)
3039 {
3040 s.setWidth(qMin(dd->grid.width(), s.width()));
3041 s.setHeight(qMin(dd->grid.height(), s.height()));
3042 }
3043 items[row].resize(s);
3044 }
3045 }
3046}
3047
3049{
3050 if (info.last >= items.size()) {
3051 //first we create the items
3052 QStyleOptionViewItem option;
3054 for (int row = items.size(); row <= info.last; ++row) {
3056 QListViewItem item(QRect(0, 0, size.width(), size.height()), row); // default pos
3057 items.append(item);
3058 }
3059 doDynamicLayout(info);
3060 }
3061 return (batchStartRow > max); // done
3062}
3063
3065{
3066 if (index.isValid() && index.row() < items.size())
3067 return items.at(index.row());
3068 return QListViewItem();
3069}
3070
3071void QIconModeViewBase::initBspTree(const QSize &contents)
3072{
3073 // remove all items from the tree
3074 int leafCount = tree.leafCount();
3075 for (int l = 0; l < leafCount; ++l)
3076 tree.leaf(l).clear();
3077 // we have to get the bounding rect of the items before we can initialize the tree
3079 // simple heuristics to get better bsp
3080 if (contents.height() / contents.width() >= 3)
3082 else if (contents.width() / contents.height() >= 3)
3084 // build tree for the bounding rect (not just the contents rect)
3085 tree.init(QRect(0, 0, contents.width(), contents.height()), type);
3086}
3087
3088QPoint QIconModeViewBase::initDynamicLayout(const QListViewLayoutInfo &info)
3089{
3090 int x, y;
3091 if (info.first == 0) {
3092 x = info.bounds.x() + info.spacing;
3093 y = info.bounds.y() + info.spacing;
3095 } else {
3096 int idx = info.first - 1;
3097 while (idx > 0 && !items.at(idx).isValid())
3098 --idx;
3099 const QListViewItem &item = items.at(idx);
3100 x = item.x;
3101 y = item.y;
3102 if (info.flow == QListView::LeftToRight)
3103 x += (info.grid.isValid() ? info.grid.width() : item.w) + info.spacing;
3104 else
3105 y += (info.grid.isValid() ? info.grid.height() : item.h) + info.spacing;
3106 }
3107 return QPoint(x, y);
3108}
3109
3113void QIconModeViewBase::doDynamicLayout(const QListViewLayoutInfo &info)
3114{
3115 const bool useItemSize = !info.grid.isValid();
3116 const QPoint topLeft = initDynamicLayout(info);
3117
3118 int segStartPosition;
3119 int segEndPosition;
3120 int deltaFlowPosition;
3121 int deltaSegPosition;
3122 int deltaSegHint;
3123 int flowPosition;
3124 int segPosition;
3125
3126 if (info.flow == QListView::LeftToRight) {
3127 segStartPosition = info.bounds.left() + info.spacing;
3128 segEndPosition = info.bounds.right();
3129 deltaFlowPosition = info.grid.width(); // dx
3130 deltaSegPosition = (useItemSize ? batchSavedDeltaSeg : info.grid.height()); // dy
3131 deltaSegHint = info.grid.height();
3132 flowPosition = topLeft.x();
3133 segPosition = topLeft.y();
3134 } else { // flow == QListView::TopToBottom
3135 segStartPosition = info.bounds.top() + info.spacing;
3136 segEndPosition = info.bounds.bottom();
3137 deltaFlowPosition = info.grid.height(); // dy
3138 deltaSegPosition = (useItemSize ? batchSavedDeltaSeg : info.grid.width()); // dx
3139 deltaSegHint = info.grid.width();
3140 flowPosition = topLeft.y();
3141 segPosition = topLeft.x();
3142 }
3143
3144 if (moved.size() != items.size())
3146
3147 QRect rect(QPoint(), topLeft);
3148 QListViewItem *item = nullptr;
3149 Q_ASSERT(info.first <= info.last);
3150 for (int row = info.first; row <= info.last; ++row) {
3151 item = &items[row];
3152 if (isHidden(row)) {
3153 item->invalidate();
3154 } else {
3155 // if we are not using a grid, we need to find the deltas
3156 if (useItemSize) {
3157 if (info.flow == QListView::LeftToRight)
3158 deltaFlowPosition = item->w + info.spacing;
3159 else
3160 deltaFlowPosition = item->h + info.spacing;
3161 } else {
3162 item->w = qMin<int>(info.grid.width(), item->w);
3163 item->h = qMin<int>(info.grid.height(), item->h);
3164 }
3165
3166 // create new segment
3167 if (info.wrap
3168 && flowPosition + deltaFlowPosition > segEndPosition
3169 && flowPosition > segStartPosition) {
3170 flowPosition = segStartPosition;
3171 segPosition += deltaSegPosition;
3172 if (useItemSize)
3173 deltaSegPosition = 0;
3174 }
3175 // We must delay calculation of the seg adjustment, as this item
3176 // may have caused a wrap to occur
3177 if (useItemSize) {
3178 if (info.flow == QListView::LeftToRight)
3179 deltaSegHint = item->h + info.spacing;
3180 else
3181 deltaSegHint = item->w + info.spacing;
3182 deltaSegPosition = qMax(deltaSegPosition, deltaSegHint);
3183 }
3184
3185 // set the position of the item
3186 // ### idealy we should have some sort of alignment hint for the item
3187 // ### (normally that would be a point between the icon and the text)
3188 if (!moved.testBit(row)) {
3189 if (info.flow == QListView::LeftToRight) {
3190 if (useItemSize) {
3191 item->x = flowPosition;
3192 item->y = segPosition;
3193 } else { // use grid
3194 item->x = flowPosition + ((deltaFlowPosition - item->w) / 2);
3195 item->y = segPosition;
3196 }
3197 } else { // TopToBottom
3198 if (useItemSize) {
3199 item->y = flowPosition;
3200 item->x = segPosition;
3201 } else { // use grid
3202 item->y = flowPosition + ((deltaFlowPosition - item->h) / 2);
3203 item->x = segPosition;
3204 }
3205 }
3206 }
3207
3208 // let the contents contain the new item
3209 if (useItemSize)
3210 rect |= item->rect();
3211 else if (info.flow == QListView::LeftToRight)
3212 rect |= QRect(flowPosition, segPosition, deltaFlowPosition, deltaSegPosition);
3213 else // flow == TopToBottom
3214 rect |= QRect(segPosition, flowPosition, deltaSegPosition, deltaFlowPosition);
3215
3216 // prepare for next item
3217 flowPosition += deltaFlowPosition; // current position + item width + gap
3218 }
3219 }
3220 Q_ASSERT(item);
3221 batchSavedDeltaSeg = deltaSegPosition;
3222 batchStartRow = info.last + 1;
3223 bool done = (info.last >= rowCount() - 1);
3224 // resize the content area
3225 if (done || !info.bounds.contains(item->rect())) {
3226 contentsSize = rect.size();
3227 if (info.flow == QListView::LeftToRight)
3228 contentsSize.rheight() += info.spacing;
3229 else
3230 contentsSize.rwidth() += info.spacing;
3231 }
3232 if (rect.size().isEmpty())
3233 return;
3234 // resize tree
3235 int insertFrom = info.first;
3236 if (done || info.first == 0) {
3237 initBspTree(rect.size());
3238 insertFrom = 0;
3239 }
3240 // insert items in tree
3241 for (int row = insertFrom; row <= info.last; ++row)
3242 tree.insertLeaf(items.at(row).rect(), row);
3243 // if the new items are visible, update the viewport
3244 QRect changedRect(topLeft, rect.bottomRight());
3245 if (clipRect().intersects(changedRect))
3246 viewport()->update();
3247}
3248
3250{
3251 QIconModeViewBase *that = const_cast<QIconModeViewBase*>(this);
3252 QBspTree::Data data(static_cast<void*>(that));
3254 that->interSectingVector = &res;
3255 that->tree.climbTree(area, &QIconModeViewBase::addLeaf, data);
3256 that->interSectingVector = nullptr;
3257 return res;
3258}
3259
3260QRect QIconModeViewBase::itemsRect(const QList<QModelIndex> &indexes) const
3261{
3262 QRect rect;
3263 for (const auto &index : indexes)
3265 return rect;
3266}
3267
3269{
3270 if (!item.isValid())
3271 return -1;
3272 int i = item.indexHint;
3273 if (i < items.size()) {
3274 if (items.at(i) == item)
3275 return i;
3276 } else {
3277 i = items.size() - 1;
3278 }
3279
3280 int j = i;
3281 int c = items.size();
3282 bool a = true;
3283 bool b = true;
3284
3285 while (a || b) {
3286 if (a) {
3287 if (items.at(i) == item) {
3288 items.at(i).indexHint = i;
3289 return i;
3290 }
3291 a = ++i < c;
3292 }
3293 if (b) {
3294 if (items.at(j) == item) {
3295 items.at(j).indexHint = j;
3296 return j;
3297 }
3298 b = --j > -1;
3299 }
3300 }
3301 return -1;
3302}
3303
3304void QIconModeViewBase::addLeaf(QList<int> &leaf, const QRect &area, uint visited,
3306{
3307 QListViewItem *vi;
3308 QIconModeViewBase *_this = static_cast<QIconModeViewBase *>(data.ptr);
3309 for (int i = 0; i < leaf.size(); ++i) {
3310 int idx = leaf.at(i);
3311 if (idx < 0 || idx >= _this->items.size())
3312 continue;
3313 vi = &_this->items[idx];
3314 Q_ASSERT(vi);
3315 if (vi->isValid() && vi->rect().intersects(area) && vi->visited != visited) {
3316 QModelIndex index = _this->dd->listViewItemToIndex(*vi);
3317 Q_ASSERT(index.isValid());
3319 vi->visited = visited;
3320 }
3321 }
3322}
3323
3324void QIconModeViewBase::moveItem(int index, const QPoint &dest)
3325{
3326 // does not impact on the bintree itself or the contents rect
3328 QRect rect = item->rect();
3329
3330 // move the item without removing it from the tree
3332 item->move(dest);
3333 tree.insertLeaf(QRect(dest, rect.size()), index);
3334
3335 // resize the contents area
3336 contentsSize = (QRect(QPoint(0, 0), contentsSize)|QRect(dest, rect.size())).size();
3337
3338 // mark the item as moved
3339 if (moved.size() != items.size())
3341 moved.setBit(index, true);
3342}
3343
3344QPoint QIconModeViewBase::snapToGrid(const QPoint &pos) const
3345{
3346 int x = pos.x() - (pos.x() % gridSize().width());
3347 int y = pos.y() - (pos.y() % gridSize().height());
3348 return QPoint(x, y);
3349}
3350
3351QPoint QIconModeViewBase::draggedItemsDelta() const
3352{
3353 if (movement() == QListView::Snap) {
3354 QPoint snapdelta = QPoint((offset().x() % gridSize().width()),
3355 (offset().y() % gridSize().height()));
3356 return snapToGrid(draggedItemsPos + snapdelta) - snapToGrid(pressedPosition()) - snapdelta;
3357 }
3359}
3360
3361QRect QIconModeViewBase::draggedItemsRect() const
3362{
3363 QRect rect = itemsRect(draggedItems);
3364 rect.translate(draggedItemsDelta());
3365 return rect;
3366}
3367
3369{
3370 if (dx > 0) // right
3372 else if (dx < 0) // left
3374 if (dy > 0) // down
3376 else if (dy < 0) // up
3378}
3379
3381{
3382 tree.destroy();
3383 items.clear();
3384 moved.clear();
3385 batchStartRow = 0;
3387}
3388
3389void QIconModeViewBase::updateContentsSize()
3390{
3391 QRect bounding;
3392 for (int i = 0; i < items.size(); ++i)
3393 bounding |= items.at(i).rect();
3394 contentsSize = bounding.size();
3395}
3396
3400void QListView::currentChanged(const QModelIndex &current, const QModelIndex &previous)
3401{
3402 QAbstractItemView::currentChanged(current, previous);
3403#if QT_CONFIG(accessibility)
3404 if (QAccessible::isActive()) {
3405 if (current.isValid()) {
3406 int entry = visualIndex(current);
3407 QAccessibleEvent event(this, QAccessible::Focus);
3408 event.setChild(entry);
3409 QAccessible::updateAccessibility(&event);
3410 }
3411 }
3412#endif
3413}
3414
3419 const QItemSelection &deselected)
3420{
3421#if QT_CONFIG(accessibility)
3422 if (QAccessible::isActive()) {
3423 // ### does not work properly for selection ranges.
3424 QModelIndex sel = selected.indexes().value(0);
3425 if (sel.isValid()) {
3426 int entry = visualIndex(sel);
3427 QAccessibleEvent event(this, QAccessible::SelectionAdd);
3428 event.setChild(entry);
3429 QAccessible::updateAccessibility(&event);
3430 }
3431 QModelIndex desel = deselected.indexes().value(0);
3432 if (desel.isValid()) {
3433 int entry = visualIndex(desel);
3434 QAccessibleEvent event(this, QAccessible::SelectionRemove);
3435 event.setChild(entry);
3436 QAccessible::updateAccessibility(&event);
3437 }
3438 }
3439#endif
3440 QAbstractItemView::selectionChanged(selected, deselected);
3441}
3442
3443int QListView::visualIndex(const QModelIndex &index) const
3444{
3445 Q_D(const QListView);
3446 d->executePostedLayout();
3447 QListViewItem itm = d->indexToListViewItem(index);
3448 int visualIndex = d->commonListView->itemIndex(itm);
3449 for (const auto &idx : std::as_const(d->hiddenRows)) {
3450 if (idx.row() <= index.row())
3451 --visualIndex;
3452 }
3453 return visualIndex;
3454}
3455
3456
3462{
3463 Q_D(const QListView);
3464 // We don't have a nice simple size hint for invalid or wrapping list views.
3465 if (!d->model)
3467 const int rc = d->model->rowCount();
3468 if (rc == 0 || isWrapping())
3470
3471 QStyleOptionViewItem option;
3473
3474 if (uniformItemSizes()) {
3475 QSize sz = d->cachedItemSize;
3476 if (!sz.isValid()) {
3477 QModelIndex idx = d->model->index(0, d->column, d->root);
3478 sz = d->itemSize(option, idx);
3479 }
3480 sz.setHeight(rc * sz.height());
3481 return sz;
3482 }
3483
3484 // Using AdjustToContents with a high number of rows will normally not make sense, so we limit
3485 // this to default 1000 (that is btw the default for QHeaderView::resizeContentsPrecision())
3486 // (By setting the property _q_resizeContentPrecision the user can however override this).
3487 int maximumRows = 1000;
3488 const QVariant userOverrideValue = property("_q_resizeContentPrecision");
3489 if (userOverrideValue.isValid() && userOverrideValue.toInt() > 0) {
3490 maximumRows = userOverrideValue.toInt();
3491 }
3492 const int rowCount = qMin(rc, maximumRows);
3493
3494 int h = 0;
3495 int w = 0;
3496
3497 for (int row = 0; row < rowCount; ++row) {
3498 QModelIndex idx = d->model->index(row, d->column, d->root);
3499 QSize itemSize = d->itemSize(option, idx);
3500 h += itemSize.height();
3501 w = qMax(w, itemSize.width());
3502 }
3503 return QSize(w, h);
3504}
3505
3507
3508#include "moc_qlistview.cpp"
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
This pure abstract function must be reimplemented if you want to provide custom rendering.
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const =0
This pure abstract function must be reimplemented if you want to provide custom rendering.
virtual Qt::DropActions supportedDropActions() const
virtual Q_INVOKABLE Qt::ItemFlags flags(const QModelIndex &index) const
Returns the item flags for the given index.
virtual Q_INVOKABLE int rowCount(const QModelIndex &parent=QModelIndex()) const =0
Returns the number of rows under the given parent.
virtual QMimeData * mimeData(const QModelIndexList &indexes) const
Returns an object that contains serialized items of data corresponding to the list of indexes specifi...
virtual Q_INVOKABLE int columnCount(const QModelIndex &parent=QModelIndex()) const =0
Returns the number of columns for the children of the given parent.
virtual Q_INVOKABLE QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const =0
Returns the index of the item in the model specified by the given row, column and parent index.
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
QPersistentModelIndex hover
bool isIndexEnabled(const QModelIndex &index) const
The QAbstractItemView class provides the basic functionality for item view classes.
friend class QListModeViewBase
QAbstractItemModel * model() const
Returns the model that this view is presenting.
bool event(QEvent *event) override
\reimp
void timerEvent(QTimerEvent *event) override
This function is called with the given event when a timer event is sent to the widget.
virtual void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
This slot is called when the selection is changed.
State state() const
Returns the item view's state.
virtual void reset()
Reset the internal state of the view.
void mouseReleaseEvent(QMouseEvent *event) override
This function is called with the given event when a mouse button is released, after a mouse press eve...
virtual QAbstractItemDelegate * itemDelegateForIndex(const QModelIndex &index) const
virtual void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList< int > &roles=QList< int >())
This slot is called when items with the given roles are changed in the model.
QModelIndex currentIndex() const
Returns the model index of the current item.
virtual void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
This slot is called when rows are about to be removed.
State
Describes the different states the view can be in.
virtual void setRootIndex(const QModelIndex &index)
Sets the root item to the item at the given index.
virtual void initViewItemOption(QStyleOptionViewItem *option) const
virtual void doItemsLayout()
void update(const QModelIndex &index)
QModelIndex rootIndex() const
Returns the model index of the model's root item.
CursorAction
This enum describes the different ways to navigate between items,.
virtual void currentChanged(const QModelIndex &current, const QModelIndex &previous)
This slot is called when a new item becomes the current item.
void resizeEvent(QResizeEvent *event) override
This function is called with the given event when a resize event is sent to the widget.
ScrollHint
\value EnsureVisible Scroll to ensure that the item is visible.
virtual void rowsInserted(const QModelIndex &parent, int start, int end)
This slot is called when rows are inserted.
void setState(State state)
Sets the item view's state to the given state.
void mouseMoveEvent(QMouseEvent *event) override
This function is called with the given event when a mouse move event is sent to the widget.
void setSelectionMode(QAbstractItemView::SelectionMode mode)
virtual void updateGeometries()
QSize viewportSizeHint() const override
int value
the slider's current value
void setRange(int min, int max)
Sets the slider's minimum to min and its maximum to max.
void clear()
Clears the contents of the bit array and makes it empty.
Definition qbitarray.h:42
bool testBit(qsizetype i) const
Returns true if the bit at index position i is 1; otherwise returns false.
Definition qbitarray.h:84
void resize(qsizetype size)
Resizes the bit array to size bits.
void setBit(qsizetype i)
Sets the bit at index position i to 1.
Definition qbitarray.h:88
qsizetype size() const
Returns the number of bits stored in the bit array.
Definition qbitarray.h:31
void insertLeaf(const QRect &r, int i)
Definition qbsptree_p.h:60
void create(int n, int d=-1)
Definition qbsptree.cpp:10
void destroy()
Definition qbsptree.cpp:27
void climbTree(const QRect &rect, callback *function, QBspTreeData data)
Definition qbsptree.cpp:33
void init(const QRect &area, NodeType type)
Definition qbsptree_p.h:54
void removeLeaf(const QRect &r, int i)
Definition qbsptree_p.h:61
int leafCount() const
Definition qbsptree_p.h:58
QList< int > & leaf(int i)
Definition qbsptree_p.h:59
int hiddenCount() const
virtual int horizontalScrollToValue(int index, QListView::ScrollHint hint, bool leftOf, bool rightOf, const QRect &area, const QRect &rect) const
virtual void clear()=0
QListView::Movement movement() const
QRect viewItemRect(const QListViewItem &item) const
QListView::ScrollMode horizontalScrollMode() const
QListView::ScrollMode verticalScrollMode() const
virtual void updateHorizontalScrollBar(const QSize &step)
virtual int horizontalOffset() const
QWidget * viewport() const
void initViewItemOption(QStyleOptionViewItem *option) const
virtual bool doBatchedItemLayout(const QListViewLayoutInfo &info, int max)=0
virtual void appendHiddenRow(int row)
virtual void updateVerticalScrollBar(const QSize &step)
virtual QListViewItem indexToListViewItem(const QModelIndex &index) const =0
virtual void removeHiddenRow(int row)
bool uniformItemSizes() const
QSize cachedItemSize() const
virtual void scrollContentsBy(int dx, int dy, bool scrollElasticBand)
virtual int verticalOffset() const
QPoint offset() const
bool isHidden(int row) const
QListViewPrivate * dd
QScrollBar * verticalScrollBar() const
QSize itemSize(const QStyleOptionViewItem &opt, const QModelIndex &idx) const
QRect clipRect() const
QListView::Flow flow() const
int rowCount() const
virtual void setRowCount(int)=0
virtual QRect mapToViewport(const QRect &rect) const
QScrollBar * horizontalScrollBar() const
QSize gridSize() const
int spacing() const
bool isRightToLeft() const
bool isWrapping() const
QModelIndex modelIndex(int row) const
virtual int verticalScrollToValue(int index, QListView::ScrollHint hint, bool above, bool below, const QRect &area, const QRect &rect) const
QPoint pressedPosition() const
static bool sendEvent(QObject *receiver, QEvent *event)
Sends event event directly to receiver receiver, using the notify() function.
\inmodule QtGui
Definition qdrag.h:22
void setHotSpot(const QPoint &hotspot)
Sets the position of the hot spot relative to the top-left corner of the pixmap used to the point spe...
Definition qdrag.cpp:146
Qt::DropAction exec(Qt::DropActions supportedActions=Qt::MoveAction)
Definition qdrag.cpp:199
void setMimeData(QMimeData *data)
Sets the data to be sent to the given MIME data.
Definition qdrag.cpp:99
void setPixmap(const QPixmap &)
Sets pixmap as the pixmap used to represent the data in a drag and drop operation.
Definition qdrag.cpp:123
QObject * target() const
Returns the target of the drag and drop operation.
Definition qdrag.cpp:176
\inmodule QtCore
Definition qcoreevent.h:45
qreal y() const
This convenience function is equivalent to calling pos().y().
qreal x() const
This convenience function is equivalent to calling pos().x().
QList< QListViewItem > items
int itemIndex(const QListViewItem &item) const override
QList< QModelIndex > draggedItems
QListViewItem indexToListViewItem(const QModelIndex &index) const override
void setPositionForIndex(const QPoint &position, const QModelIndex &index) override
void setRowCount(int rowCount) override
void scrollContentsBy(int dx, int dy, bool scrollElasticBand) override
QList< QModelIndex > intersectingSet(const QRect &area) const override
void appendHiddenRow(int row) override
void clear() override
QList< QModelIndex > * interSectingVector
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) override
void removeHiddenRow(int row) override
bool doBatchedItemLayout(const QListViewLayoutInfo &info, int max) override
Q_INVOKABLE bool isSelected(const QModelIndex &index) const
Returns true if the given model item index is selected.
QModelIndexList selectedIndexes
virtual void select(const QModelIndex &index, QItemSelectionModel::SelectionFlags command)
Selects the model item index using the specified command, and emits selectionChanged().
\inmodule QtCore
Q_CORE_EXPORT QModelIndexList indexes() const
Returns a list of model indexes that correspond to the selected items.
Q_CORE_EXPORT void select(const QModelIndex &topLeft, const QModelIndex &bottomRight)
Adds the items in the range that extends from the top-left model item, specified by the topLeft index...
Q_CORE_EXPORT void merge(const QItemSelection &other, QItemSelectionModel::SelectionFlags command)
Merges the other selection with this QItemSelection using the command given.
void clear() override
void updateHorizontalScrollBar(const QSize &step) override
bool doBatchedItemLayout(const QListViewLayoutInfo &info, int max) override
QList< int > segmentExtents
QList< int > segmentPositions
QList< int > flowPositions
void updateVerticalScrollBar(const QSize &step) override
void scrollContentsBy(int dx, int dy, bool scrollElasticBand) override
QList< QModelIndex > intersectingSet(const QRect &area) const override
int horizontalOffset() const override
QRect mapToViewport(const QRect &rect) const override
int verticalOffset() const override
QListViewItem indexToListViewItem(const QModelIndex &index) const override
int verticalScrollToValue(int index, QListView::ScrollHint hint, bool above, bool below, const QRect &area, const QRect &rect) const override
int horizontalScrollToValue(int index, QListView::ScrollHint hint, bool leftOf, bool rightOf, const QRect &area, const QRect &rect) const override
QListModeViewBase(QListView *q, QListViewPrivate *d)
static QSize viewportSize(const QAbstractItemView *v)
void dataChanged(const QModelIndex &, const QModelIndex &) override
QList< int > segmentStartRows
QList< int > scrollValueMap
constexpr bool isValid() const
Definition qlistview_p.h:46
QListView::ViewMode viewMode
QSet< QPersistentModelIndex > hiddenRows
int horizontalScrollToValue(const QModelIndex &index, const QRect &rect, QListView::ScrollHint hint) const
QListView::Movement movement
QModelIndex closestIndex(const QRect &target, const QList< QModelIndex > &candidates) const
int batchStartRow() const
QListView::Flow flow
QItemViewPaintPairs draggablePaintPairs(const QModelIndexList &indexes, QRect *r) const override
\reimp
int verticalScrollToValue(const QModelIndex &index, const QRect &rect, QListView::ScrollHint hint) const
void scrollElasticBandBy(int dx, int dy)
Qt::Alignment itemAlignment
QRect rectForIndex(const QModelIndex &index) const
QSize itemSize(const QStyleOptionViewItem &option, const QModelIndex &index) const
void selectAll(QItemSelectionModel::SelectionFlags command) override
bool doItemsLayout(int num)
QListViewItem indexToListViewItem(const QModelIndex &index) const
bool isWrapping() const
int spacing() const
QModelIndex listViewItemToIndex(const QListViewItem &item) const
QItemSelection selection(const QRect &rect) const
QCommonListViewBase * commonListView
int flipX(int x) const
void prepareItemsLayout()
void emitIndexesMoved(const QModelIndexList &indexes)
QList< QModelIndex > intersectingSet(const QRect &area, bool doLayout=true) const
QRect mapToViewport(const QRect &rect, bool extend=true) const
void viewUpdateGeometries()
bool isHidden(int row) const
void removeCurrentAndDisabled(QList< QModelIndex > *indexes, const QModelIndex &current) const
QList< int > hiddenRowIds() const
QSize gridSize() const
The QListView class provides a list or icon view onto a model.
Definition qlistview.h:17
LayoutMode layoutMode
determines whether the layout of items should happen immediately or be delayed.
Definition qlistview.h:23
void resizeEvent(QResizeEvent *e) override
\reimp
void setSpacing(int space)
void reset() override
bool isSelectionRectVisible() const
int spacing
the space around the items in the layout
Definition qlistview.h:24
bool isWrapping
whether the items layout should wrap.
Definition qlistview.h:21
void scrollTo(const QModelIndex &index, ScrollHint hint=EnsureVisible) override
\reimp
void initViewItemOption(QStyleOptionViewItem *option) const override
\reimp
void setRowHidden(int row, bool hide)
If hide is true, the given row will be hidden; otherwise the row will be shown.
void setLayoutMode(LayoutMode mode)
int batchSize
the number of items laid out in each batch if \l layoutMode is set to \l Batched
Definition qlistview.h:29
~QListView()
Destroys the view.
ViewMode viewMode
the view mode of the QListView.
Definition qlistview.h:26
void setWordWrap(bool on)
int verticalOffset() const override
\reimp
void timerEvent(QTimerEvent *e) override
\reimp
bool uniformItemSizes
whether all items in the listview have the same size
Definition qlistview.h:28
bool wordWrap
the item text word-wrapping policy
Definition qlistview.h:30
QSize gridSize
the size of the layout grid
Definition qlistview.h:25
QSize contentsSize() const
void setViewMode(ViewMode mode)
QListView(QWidget *parent=nullptr)
Creates a new QListView with the given parent to view a model.
QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) override
\reimp
int modelColumn
the column in the model that is visible
Definition qlistview.h:27
QRegion visualRegionForSelection(const QItemSelection &selection) const override
\reimp
void setGridSize(const QSize &size)
Movement movement
whether the items can be moved freely, are snapped to a grid, or cannot be moved at all.
Definition qlistview.h:19
QRect rectForIndex(const QModelIndex &index) const
Returns the rectangle of the item at position index in the model.
bool event(QEvent *e) override
\reimp
void setModelColumn(int column)
void setWrapping(bool enable)
bool isRowHidden(int row) const
Returns true if the row is hidden; otherwise returns false.
QRect visualRect(const QModelIndex &index) const override
\reimp
int horizontalOffset() const override
\reimp
void setMovement(Movement movement)
void setBatchSize(int batchSize)
ViewMode
\value ListMode The items are laid out using TopToBottom flow, with Small size and Static movement \v...
Definition qlistview.h:43
void setPositionForIndex(const QPoint &position, const QModelIndex &index)
Qt::Alignment itemAlignment
the alignment of each item in its cell
Definition qlistview.h:32
void clearPropertyFlags()
Clears the QListView-specific property flags.
void setItemAlignment(Qt::Alignment alignment)
void mouseReleaseEvent(QMouseEvent *e) override
\reimp
ResizeMode
\value Fixed The items will only be laid out the first time the view is shown.
Definition qlistview.h:39
void setSelectionRectVisible(bool show)
void updateGeometries() override
\reimp
void mouseMoveEvent(QMouseEvent *e) override
\reimp
void setUniformItemSizes(bool enable)
void setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command) override
\reimp
void setResizeMode(ResizeMode mode)
QModelIndexList selectedIndexes() const override
\reimp
Movement
\value Static The items cannot be moved by the user.
Definition qlistview.h:35
void scrollContentsBy(int dx, int dy) override
\reimp
QSize viewportSizeHint() const override
bool isIndexHidden(const QModelIndex &index) const override
\reimp
void resizeContents(int width, int height)
ResizeMode resizeMode
whether the items are laid out again when the view is resized.
Definition qlistview.h:22
Flow
\value LeftToRight The items are laid out in the view from the left to the right.
Definition qlistview.h:37
@ TopToBottom
Definition qlistview.h:37
@ LeftToRight
Definition qlistview.h:37
QModelIndex indexAt(const QPoint &p) const override
\reimp
void paintEvent(QPaintEvent *e) override
\reimp
LayoutMode
\value SinglePass The items are laid out all at once.
Definition qlistview.h:41
Flow flow
which direction the items layout should flow.
Definition qlistview.h:20
void setFlow(Flow flow)
void doItemsLayout() override
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
bool isEmpty() const noexcept
Definition qlist.h:390
T & last()
Definition qlist.h:631
const T & constLast() const noexcept
Definition qlist.h:633
void push_back(parameter_type t)
Definition qlist.h:672
iterator end()
Definition qlist.h:609
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
T value(qsizetype i) const
Definition qlist.h:661
const_iterator constBegin() const noexcept
Definition qlist.h:615
qsizetype removeIf(Predicate pred)
Definition qlist.h:587
iterator begin()
Definition qlist.h:608
void reserve(qsizetype size)
Definition qlist.h:746
void resize(qsizetype size)
Definition qlist.h:392
const_iterator cend() const noexcept
Definition qlist.h:614
void append(parameter_type t)
Definition qlist.h:441
const_iterator constEnd() const noexcept
Definition qlist.h:616
const_iterator cbegin() const noexcept
Definition qlist.h:613
void clear()
Definition qlist.h:417
const_iterator ConstIterator
Definition qlist.h:251
\inmodule QtCore
constexpr int row() const noexcept
Returns the row this model index refers to.
constexpr int column() const noexcept
Returns the column this model index refers to.
constexpr bool isValid() const noexcept
Returns {true} if this model index is valid; otherwise returns {false}.
\inmodule QtGui
Definition qevent.h:195
\inmodule QtCore
Definition qobject.h:90
The QPaintEvent class contains event parameters for paint events.
Definition qevent.h:485
The QPainter class performs low-level painting on widgets and other paint devices.
Definition qpainter.h:46
void restore()
Restores the current painter state (pops a saved state off the stack).
void save()
Saves the current painter state (pushes the state onto a stack).
ColorGroup
\value Disabled \value Active \value Inactive \value Normal synonym for Active
Definition qpalette.h:48
@ Disabled
Definition qpalette.h:48
int row() const
Returns the row this persistent model index refers to.
Returns a copy of the pixmap that is transformed using the given transformation transform and transfo...
Definition qpixmap.h:27
\inmodule QtCore\reentrant
Definition qpoint.h:23
constexpr int x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:127
constexpr int y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:132
constexpr void setX(int x) noexcept
Sets the x coordinate of this point to the given x coordinate.
Definition qpoint.h:137
\inmodule QtCore\reentrant
Definition qrect.h:30
bool intersects(const QRect &r) const noexcept
Returns true if this rectangle intersects with the given rectangle (i.e., there is at least one pixel...
Definition qrect.cpp:1065
constexpr void adjust(int x1, int y1, int x2, int y2) noexcept
Adds dx1, dy1, dx2 and dy2 respectively to the existing coordinates of the rectangle.
Definition qrect.h:372
constexpr void moveBottom(int pos) noexcept
Moves the rectangle vertically, leaving the rectangle's bottom edge at the given y coordinate.
Definition qrect.h:297
constexpr void moveRight(int pos) noexcept
Moves the rectangle horizontally, leaving the rectangle's right edge at the given x coordinate.
Definition qrect.h:291
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:238
constexpr int bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
Definition qrect.h:181
constexpr void setRight(int pos) noexcept
Sets the right edge of the rectangle to the given x coordinate.
Definition qrect.h:196
constexpr int top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:175
constexpr void moveLeft(int pos) noexcept
Moves the rectangle horizontally, leaving the rectangle's left edge at the given x coordinate.
Definition qrect.h:285
constexpr void setBottom(int pos) noexcept
Sets the bottom edge of the rectangle to the given y coordinate.
Definition qrect.h:199
bool contains(const QRect &r, bool proper=false) const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qrect.cpp:851
constexpr void setLeft(int pos) noexcept
Sets the left edge of the rectangle to the given x coordinate.
Definition qrect.h:190
constexpr int left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:172
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:184
constexpr QSize size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:241
constexpr QRect translated(int dx, int dy) const noexcept
Returns a copy of the rectangle that is translated dx along the x axis and dy along the y axis,...
Definition qrect.h:260
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:187
constexpr void moveTop(int pos) noexcept
Moves the rectangle vertically, leaving the rectangle's top edge at the given y coordinate.
Definition qrect.h:288
constexpr QPoint center() const noexcept
Returns the center point of the rectangle.
Definition qrect.h:232
constexpr int right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
Definition qrect.h:178
constexpr void setTop(int pos) noexcept
Sets the top edge of the rectangle to the given y coordinate.
Definition qrect.h:193
The QRegion class specifies a clip region for a painter.
Definition qregion.h:27
The QResizeEvent class contains event parameters for resize events.
Definition qevent.h:547
bool remove(const T &value)
Definition qset.h:63
iterator insert(const T &value)
Definition qset.h:155
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:132
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:129
constexpr int & rheight() noexcept
Returns a reference to the height.
Definition qsize.h:156
constexpr void setWidth(int w) noexcept
Sets the width to the given width.
Definition qsize.h:135
constexpr int & rwidth() noexcept
Returns a reference to the width.
Definition qsize.h:153
constexpr bool isNull() const noexcept
Returns true if both the width and height is 0; otherwise returns false.
Definition qsize.h:120
constexpr void setHeight(int h) noexcept
Sets the height to the given height.
Definition qsize.h:138
constexpr bool isValid() const noexcept
Returns true if both the width and height is equal to or greater than 0; otherwise returns false.
Definition qsize.h:126
The QStyleOption class stores the parameters used by QStyle functions.
void initFrom(const QWidget *w)
The QStylePainter class is a convenience class for drawing QStyle elements inside a widget.
The QStyle class is an abstract base class that encapsulates the look and feel of a GUI.
Definition qstyle.h:29
@ State_Editing
Definition qstyle.h:89
@ State_MouseOver
Definition qstyle.h:80
@ State_HasFocus
Definition qstyle.h:75
@ State_Enabled
Definition qstyle.h:67
@ State_Selected
Definition qstyle.h:82
@ SH_ScrollView_FrameOnlyAroundContents
Definition qstyle.h:600
@ CE_RubberBand
Definition qstyle.h:209
@ PM_ScrollBarExtent
Definition qstyle.h:426
@ PM_DefaultFrameWidth
Definition qstyle.h:420
@ PM_ScrollView_ScrollBarOverlap
Definition qstyle.h:524
@ PM_IconViewIconSize
Definition qstyle.h:492
@ PM_ListViewIconSize
Definition qstyle.h:491
@ PE_PanelItemViewRow
Definition qstyle.h:154
\inmodule QtCore
Definition qcoreevent.h:359
\inmodule QtCore
Definition qvariant.h:64
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:707
int toInt(bool *ok=nullptr) const
Returns the variant as an int if the variant has userType() \l QMetaType::Int, \l QMetaType::Bool,...
The QWidget class is the base class of all user interface objects.
Definition qwidget.h:99
void update()
Updates the widget unless updates are disabled or the widget is hidden.
EGLImageKHR int int EGLuint64KHR * modifiers
bool focus
[0]
qSwap(pi, e)
list append(new Employee("Blackpool", "Stephen"))
double e
QSet< QString >::iterator it
rect
[4]
uint alignment
QStyleOptionButton opt
Combined button and popup list for selecting options.
constexpr const T & min(const T &a, const T &b)
Definition qnumeric.h:366
@ AlignRight
Definition qnamespace.h:145
@ AlignHCenter
Definition qnamespace.h:147
@ AlignHorizontal_Mask
Definition qnamespace.h:150
@ AlignCenter
Definition qnamespace.h:162
@ WA_MacShowFocusRect
Definition qnamespace.h:358
Orientation
Definition qnamespace.h:97
@ Horizontal
Definition qnamespace.h:98
@ Vertical
Definition qnamespace.h:99
@ ScrollBarAlwaysOff
@ ScrollBarAsNeeded
DropAction
@ CopyAction
@ MoveAction
@ ItemIsDragEnabled
@ ItemIsEnabled
@ ItemIsDropEnabled
QList< QModelIndex > QModelIndexList
#define Q_UNLIKELY(x)
static const QCssKnownValue positions[NumKnownPositionModes - 1]
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
static int area(const QSize &s)
Definition qicon.cpp:152
bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event)
QT_BEGIN_NAMESPACE bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event)
#define qWarning
Definition qlogging.h:162
return ret
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qBound(const T &min, const T &val, const T &max)
Definition qminmax.h:44
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
constexpr T qAbs(const T &t)
Definition qnumeric.h:328
static bool contains(const QJsonArray &haystack, unsigned needle)
Definition qopengl.cpp:116
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLenum mode
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLboolean r
[2]
GLuint GLuint end
GLenum GLuint GLenum GLsizei length
GLdouble GLdouble GLdouble GLdouble top
GLdouble GLdouble right
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLsizei GLsizei GLfloat distance
GLint GLsizei width
GLint left
GLenum type
GLint GLint bottom
GLenum target
GLbitfield flags
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
struct _cl_event * event
GLuint res
const GLubyte * c
GLuint segment
GLuint entry
GLdouble GLdouble t
Definition qopenglext.h:243
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLenum GLenum GLsizei void * row
GLuint64EXT * result
[6]
GLdouble s
[6]
Definition qopenglext.h:235
GLfloat GLfloat p
[1]
GLuint GLenum option
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
static int segmentCount(const QPainterPath &path, qreal pathLength)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
static QT_BEGIN_NAMESPACE QAsn1Element wrap(quint8 type, const QAsn1Element &child)
static QT_BEGIN_NAMESPACE QVariant hint(QPlatformIntegration::StyleHint h)
static QFixed flowPosition(const QTextFrame::iterator &it)
#define Q_UNUSED(x)
unsigned int uint
Definition qtypes.h:29
const char property[13]
Definition qwizard.cpp:101
view show()
[18] //! [19]
if(qFloatDistance(a, b)<(1<< 7))
[0]
QFileInfo info(fileName)
[8]
QObject::connect nullptr
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]
QAction * at
bool contains(const AT &t) const noexcept
Definition qlist.h:44
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent