Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
146 : QAbstractItemView(*new QListViewPrivate, parent)
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
159 : QAbstractItemView(dd, parent)
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
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
711void QListView::rowsInserted(const QModelIndex &parent, int start, int end)
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) {
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 const int margin = 2 * style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
759 const QRect viewPortRect = rect.united(d->elasticBand)
760 .adjusted(-margin, -margin, margin, margin);
761 d->viewport->update(d->mapToViewport(viewPortRect));
762 d->elasticBand = rect;
763 }
764}
765
770{
771 Q_D(QListView);
773 // #### move this implementation into a dynamic class
774 if (d->showElasticBand && d->elasticBand.isValid()) {
775 const int margin = 2 * style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
776 const QRect viewPortRect = d->elasticBand.adjusted(-margin, -margin, margin, margin);
777 d->viewport->update(d->mapToViewport(viewPortRect));
778 d->elasticBand = QRect();
779 }
780}
781
782#if QT_CONFIG(wheelevent)
786void QListView::wheelEvent(QWheelEvent *e)
787{
788 Q_D(QListView);
789 if (qAbs(e->angleDelta().y()) > qAbs(e->angleDelta().x())) {
790 if (e->angleDelta().x() == 0
791 && ((d->flow == TopToBottom && d->wrap) || (d->flow == LeftToRight && !d->wrap))
792 && d->vbar->minimum() == 0 && d->vbar->maximum() == 0) {
793 QPoint pixelDelta(e->pixelDelta().y(), e->pixelDelta().x());
794 QPoint angleDelta(e->angleDelta().y(), e->angleDelta().x());
795 QWheelEvent hwe(e->position(), e->globalPosition(), pixelDelta, angleDelta,
796 e->buttons(), e->modifiers(), e->phase(), e->inverted(), e->source());
797 if (e->spontaneous())
798 qt_sendSpontaneousEvent(d->hbar, &hwe);
799 else
800 QCoreApplication::sendEvent(d->hbar, &hwe);
801 e->setAccepted(hwe.isAccepted());
802 } else {
804 }
805 } else {
807 }
808}
809#endif // QT_CONFIG(wheelevent)
810
815{
816 Q_D(QListView);
817 if (e->timerId() == d->batchLayoutTimer.timerId()) {
818 if (d->doItemsLayout(d->batchSize)) { // layout is done
819 d->batchLayoutTimer.stop();
821 d->viewport->update();
822 }
823 }
825}
826
831{
832 Q_D(QListView);
833 if (d->delayedPendingLayout)
834 return;
835
836 QSize delta = e->size() - e->oldSize();
837
838 if (delta.isNull())
839 return;
840
841 bool listWrap = (d->viewMode == ListMode) && d->wrapItemText;
842 bool flowDimensionChanged = (d->flow == LeftToRight && delta.width() != 0)
843 || (d->flow == TopToBottom && delta.height() != 0);
844
845 // We post a delayed relayout in the following cases :
846 // - we're wrapping
847 // - the state is NoState, we're adjusting and the size has changed in the flowing direction
848 if (listWrap
849 || (state() == NoState && d->resizeMode == Adjust && flowDimensionChanged)) {
850 d->doDelayedItemsLayout(100); // wait 1/10 sec before starting the layout
851 } else {
853 }
854}
855
856#if QT_CONFIG(draganddrop)
857
861void QListView::dragMoveEvent(QDragMoveEvent *e)
862{
863 Q_D(QListView);
864 if (!d->commonListView->filterDragMoveEvent(e)) {
866 static_cast<QListModeViewBase *>(d->commonListView)->dragMoveEvent(e);
867 else
868 QAbstractItemView::dragMoveEvent(e);
869 }
870}
871
872
876void QListView::dragLeaveEvent(QDragLeaveEvent *e)
877{
878 if (!d_func()->commonListView->filterDragLeaveEvent(e))
879 QAbstractItemView::dragLeaveEvent(e);
880}
881
885void QListView::dropEvent(QDropEvent *event)
886{
887 Q_D(QListView);
888
889 if (event->source() == this && (event->dropAction() == Qt::MoveAction ||
890 dragDropMode() == QAbstractItemView::InternalMove)) {
891 QModelIndex topIndex;
892 bool topIndexDropped = false;
893 int col = -1;
894 int row = -1;
895 // check whether a subclass has already accepted the event, ie. moved the data
896 if (!event->isAccepted() && d->dropOn(event, &row, &col, &topIndex)) {
897 const QList<QModelIndex> selIndexes = selectedIndexes();
898 QList<QPersistentModelIndex> persIndexes;
899 persIndexes.reserve(selIndexes.size());
900
901 for (const auto &index : selIndexes) {
902 persIndexes.append(index);
903 if (index == topIndex) {
904 topIndexDropped = true;
905 break;
906 }
907 }
908
909 if (!topIndexDropped && !topIndex.isValid()) {
910 std::sort(persIndexes.begin(), persIndexes.end()); // The dropped items will remain in the same visual order.
911
912 QPersistentModelIndex dropRow = model()->index(row, col, topIndex);
913
914 int r = row == -1 ? model()->rowCount() : (dropRow.row() >= 0 ? dropRow.row() : row);
915 bool dataMoved = false;
916 for (int i = 0; i < persIndexes.size(); ++i) {
917 const QPersistentModelIndex &pIndex = persIndexes.at(i);
918 // only generate a move when not same row or behind itself
919 if (r != pIndex.row() && r != pIndex.row() + 1) {
920 // try to move (preserves selection)
921 dataMoved |= model()->moveRow(QModelIndex(), pIndex.row(), QModelIndex(), r);
922 if (!dataMoved) // can't move - abort and let QAbstractItemView handle this
923 break;
924 } else {
925 // move onto itself is blocked, don't delete anything
926 dataMoved = true;
927 }
928 r = pIndex.row() + 1; // Dropped items are inserted contiguously and in the right order.
929 }
930 if (dataMoved)
931 event->accept();
932 }
933 }
934
935 // either we or a subclass accepted the move event, so assume that the data was
936 // moved and that QAbstractItemView shouldn't remove the source when QDrag::exec returns
937 if (event->isAccepted())
938 d->dropEventMoved = true;
939 }
940
941 if (!d->commonListView->filterDropEvent(event) || !d->dropEventMoved) {
942 // icon view didn't move the data, and moveRows not implemented, so fall back to default
943 if (!d->dropEventMoved)
944 event->ignore();
945 QAbstractItemView::dropEvent(event);
946 }
947}
948
952void QListView::startDrag(Qt::DropActions supportedActions)
953{
954 if (!d_func()->commonListView->filterStartDrag(supportedActions))
955 QAbstractItemView::startDrag(supportedActions);
956}
957
958#endif // QT_CONFIG(draganddrop)
959
963void QListView::initViewItemOption(QStyleOptionViewItem *option) const
964{
965 Q_D(const QListView);
967 if (!d->iconSize.isValid()) { // otherwise it was already set in abstractitemview
968 int pm = (d->viewMode == QListView::ListMode
969 ? style()->pixelMetric(QStyle::PM_ListViewIconSize, nullptr, this)
970 : style()->pixelMetric(QStyle::PM_IconViewIconSize, nullptr, this));
971 option->decorationSize = QSize(pm, pm);
972 }
973 if (d->viewMode == QListView::IconMode) {
974 option->showDecorationSelected = false;
975 option->decorationPosition = QStyleOptionViewItem::Top;
976 option->displayAlignment = Qt::AlignCenter;
977 } else {
978 option->decorationPosition = QStyleOptionViewItem::Left;
979 }
980
981 if (d->gridSize().isValid()) {
982 option->rect.setSize(d->gridSize());
983 }
984}
985
986
991{
992 Q_D(QListView);
993 if (!d->itemDelegate)
994 return;
995 QStyleOptionViewItem option;
997 QStylePainter painter(d->viewport);
998
999 const QList<QModelIndex> toBeRendered =
1000 d->intersectingSet(e->rect().translated(horizontalOffset(), verticalOffset()), false);
1001
1002 const QModelIndex current = currentIndex();
1003 const QModelIndex hover = d->hover;
1004 const QAbstractItemModel *itemModel = d->model;
1005 const QItemSelectionModel *selections = d->selectionModel;
1006 const bool focus = (hasFocus() || d->viewport->hasFocus()) && current.isValid();
1007 const bool alternate = d->alternatingColors;
1008 const QStyle::State state = option.state;
1009 const QAbstractItemView::State viewState = this->state();
1010 const bool enabled = (state & QStyle::State_Enabled) != 0;
1011
1012 bool alternateBase = false;
1013 int previousRow = -2; // trigger the alternateBase adjustment on first pass
1014
1015 int maxSize = (flow() == TopToBottom)
1016 ? qMax(viewport()->size().width(), d->contentsSize().width()) - 2 * d->spacing()
1017 : qMax(viewport()->size().height(), d->contentsSize().height()) - 2 * d->spacing();
1018
1019 QList<QModelIndex>::const_iterator end = toBeRendered.constEnd();
1020 for (QList<QModelIndex>::const_iterator it = toBeRendered.constBegin(); it != end; ++it) {
1021 Q_ASSERT((*it).isValid());
1022 option.rect = visualRect(*it);
1023
1024 if (flow() == TopToBottom)
1025 option.rect.setWidth(qMin(maxSize, option.rect.width()));
1026 else
1027 option.rect.setHeight(qMin(maxSize, option.rect.height()));
1028
1029 option.state = state;
1030 if (selections && selections->isSelected(*it))
1032 if (enabled) {
1034 if ((itemModel->flags(*it) & Qt::ItemIsEnabled) == 0) {
1035 option.state &= ~QStyle::State_Enabled;
1036 cg = QPalette::Disabled;
1037 } else {
1038 cg = QPalette::Normal;
1039 }
1040 option.palette.setCurrentColorGroup(cg);
1041 }
1042 if (focus && current == *it) {
1044 if (viewState == EditingState)
1046 }
1047 option.state.setFlag(QStyle::State_MouseOver, *it == hover);
1048
1049 if (alternate) {
1050 int row = (*it).row();
1051 if (row != previousRow + 1) {
1052 // adjust alternateBase according to rows in the "gap"
1053 if (!d->hiddenRows.isEmpty()) {
1054 for (int r = qMax(previousRow + 1, 0); r < row; ++r) {
1055 if (!d->isHidden(r))
1056 alternateBase = !alternateBase;
1057 }
1058 } else {
1059 alternateBase = (row & 1) != 0;
1060 }
1061 }
1062 option.features.setFlag(QStyleOptionViewItem::Alternate, alternateBase);
1063
1064 // draw background of the item (only alternate row). rest of the background
1065 // is provided by the delegate
1066 QStyle::State oldState = option.state;
1067 option.state &= ~QStyle::State_Selected;
1069 option.state = oldState;
1070
1071 alternateBase = !alternateBase;
1072 previousRow = row;
1073 }
1074
1075 itemDelegateForIndex(*it)->paint(&painter, option, *it);
1076 }
1077
1078#if QT_CONFIG(draganddrop)
1079 d->commonListView->paintDragDrop(&painter);
1080#endif
1081
1082#if QT_CONFIG(rubberband)
1083 // #### move this implementation into a dynamic class
1084 if (d->showElasticBand && d->elasticBand.isValid()) {
1085 QStyleOptionRubberBand opt;
1086 opt.initFrom(this);
1088 opt.opaque = false;
1089 opt.rect = d->mapToViewport(d->elasticBand, false).intersected(
1090 d->viewport->rect().adjusted(-16, -16, 16, 16));
1091 painter.save();
1092 painter.drawControl(QStyle::CE_RubberBand, opt);
1093 painter.restore();
1094 }
1095#endif
1096}
1097
1102{
1103 Q_D(const QListView);
1104 QRect rect(p.x() + horizontalOffset(), p.y() + verticalOffset(), 1, 1);
1105 const QList<QModelIndex> intersectVector = d->intersectingSet(rect);
1106 QModelIndex index = intersectVector.size() > 0
1107 ? intersectVector.last() : QModelIndex();
1108 if (index.isValid() && visualRect(index).contains(p))
1109 return index;
1110 return QModelIndex();
1111}
1112
1117{
1118 return d_func()->commonListView->horizontalOffset();
1119}
1120
1125{
1126 return d_func()->commonListView->verticalOffset();
1127}
1128
1132QModelIndex QListView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
1133{
1134 Q_D(QListView);
1136
1137 auto findAvailableRowBackward = [d](int row) {
1138 while (row >= 0 && d->isHiddenOrDisabled(row))
1139 --row;
1140 return row;
1141 };
1142
1143 auto findAvailableRowForward = [d](int row) {
1144 int rowCount = d->model->rowCount(d->root);
1145 if (!rowCount)
1146 return -1;
1147 while (row < rowCount && d->isHiddenOrDisabled(row))
1148 ++row;
1149 if (row >= rowCount)
1150 return -1;
1151 return row;
1152 };
1153
1154 QModelIndex current = currentIndex();
1155 if (!current.isValid()) {
1156 int row = findAvailableRowForward(0);
1157 if (row == -1)
1158 return QModelIndex();
1159 return d->model->index(row, d->column, d->root);
1160 }
1161
1162 if ((d->flow == LeftToRight && cursorAction == MoveLeft) ||
1163 (d->flow == TopToBottom && (cursorAction == MoveUp || cursorAction == MovePrevious))) {
1164 const int row = findAvailableRowBackward(current.row() - 1);
1165 if (row == -1)
1166 return current;
1167 return d->model->index(row, d->column, d->root);
1168 } else if ((d->flow == LeftToRight && cursorAction == MoveRight) ||
1169 (d->flow == TopToBottom && (cursorAction == MoveDown || cursorAction == MoveNext))) {
1170 const int row = findAvailableRowForward(current.row() + 1);
1171 if (row == -1)
1172 return current;
1173 return d->model->index(row, d->column, d->root);
1174 }
1175
1176 const QRect initialRect = rectForIndex(current);
1177 QRect rect = initialRect;
1178 if (rect.isEmpty()) {
1179 return d->model->index(0, d->column, d->root);
1180 }
1181 if (d->gridSize().isValid()) rect.setSize(d->gridSize());
1182
1183 QSize contents = d->contentsSize();
1184 QList<QModelIndex> intersectVector;
1185
1186 switch (cursorAction) {
1187 case MoveLeft:
1188 while (intersectVector.isEmpty()) {
1189 rect.translate(-rect.width(), 0);
1190 if (rect.right() <= 0)
1191 return current;
1192 if (rect.left() < 0)
1193 rect.setLeft(0);
1194 intersectVector = d->intersectingSet(rect);
1195 d->removeCurrentAndDisabled(&intersectVector, current);
1196 }
1197 return d->closestIndex(initialRect, intersectVector);
1198 case MoveRight:
1199 while (intersectVector.isEmpty()) {
1200 rect.translate(rect.width(), 0);
1201 if (rect.left() >= contents.width())
1202 return current;
1203 if (rect.right() > contents.width())
1204 rect.setRight(contents.width());
1205 intersectVector = d->intersectingSet(rect);
1206 d->removeCurrentAndDisabled(&intersectVector, current);
1207 }
1208 return d->closestIndex(initialRect, intersectVector);
1209 case MovePageUp: {
1210 if (rect.height() >= d->viewport->height())
1212
1213 rect.moveTop(rect.top() - d->viewport->height() + 1);
1214 if (rect.top() < rect.height()) {
1215 rect.setTop(0);
1216 rect.setBottom(1);
1217 }
1218 QModelIndex findindex = current;
1219 while (intersectVector.isEmpty()
1220 || rectForIndex(findindex).top() <= (rectForIndex(current).bottom() - d->viewport->rect().height())
1221 || rect.top() <= 0) {
1222 rect.translate(0, 1);
1223 if (rect.bottom() <= 0) {
1224 return current;
1225 }
1226 intersectVector = d->intersectingSet(rect);
1227 findindex = d->closestIndex(initialRect, intersectVector);
1228 }
1229 return findindex;
1230 }
1231 case MovePrevious:
1232 case MoveUp:
1233 while (intersectVector.isEmpty()) {
1234 rect.translate(0, -rect.height());
1235 if (rect.bottom() <= 0) {
1236#ifdef QT_KEYPAD_NAVIGATION
1237 if (QApplicationPrivate::keypadNavigationEnabled()) {
1238 int row = d->batchStartRow() - 1;
1239 while (row >= 0 && d->isHiddenOrDisabled(row))
1240 --row;
1241 if (row >= 0)
1242 return d->model->index(row, d->column, d->root);
1243 }
1244#endif
1245 return current;
1246 }
1247 if (rect.top() < 0)
1248 rect.setTop(0);
1249 intersectVector = d->intersectingSet(rect);
1250 d->removeCurrentAndDisabled(&intersectVector, current);
1251 }
1252 return d->closestIndex(initialRect, intersectVector);
1253 case MovePageDown: {
1254 if (rect.height() >= d->viewport->height())
1256
1257 rect.moveTop(rect.top() + d->viewport->height() - 1);
1258 if (rect.bottom() > contents.height() - rect.height()) {
1259 rect.setTop(contents.height() - 1);
1260 rect.setBottom(contents.height());
1261 }
1262 QModelIndex index = current;
1263 // index's bottom() - current's top() always <= (d->viewport->rect().height()
1264 while (intersectVector.isEmpty()
1265 || rectForIndex(index).bottom() >= (d->viewport->rect().height() + rectForIndex(current).top())
1266 || rect.bottom() > contents.height()) {
1267 rect.translate(0, -1);
1268 if (rect.top() >= contents.height()) {
1269 return current;
1270 }
1271 intersectVector = d->intersectingSet(rect);
1272 index = d->closestIndex(initialRect, intersectVector);
1273 }
1274 return index;
1275 }
1276 case MoveNext:
1277 case MoveDown:
1278 while (intersectVector.isEmpty()) {
1279 rect.translate(0, rect.height());
1280 if (rect.top() >= contents.height()) {
1281#ifdef QT_KEYPAD_NAVIGATION
1282 if (QApplicationPrivate::keypadNavigationEnabled()) {
1283 int rowCount = d->model->rowCount(d->root);
1284 int row = 0;
1285 while (row < rowCount && d->isHiddenOrDisabled(row))
1286 ++row;
1287 if (row < rowCount)
1288 return d->model->index(row, d->column, d->root);
1289 }
1290#endif
1291 return current;
1292 }
1293 if (rect.bottom() > contents.height())
1294 rect.setBottom(contents.height());
1295 intersectVector = d->intersectingSet(rect);
1296 d->removeCurrentAndDisabled(&intersectVector, current);
1297 }
1298 return d->closestIndex(initialRect, intersectVector);
1299 case MoveHome:
1300 return d->model->index(0, d->column, d->root);
1301 case MoveEnd:
1302 return d->model->index(d->batchStartRow() - 1, d->column, d->root);}
1303
1304 return current;
1305}
1306
1314{
1315 return d_func()->rectForIndex(index);
1316}
1317
1327{
1328 Q_D(QListView);
1329 if (d->movement == Static
1330 || !d->isIndexValid(index)
1331 || index.parent() != d->root
1332 || index.column() != d->column)
1333 return;
1334
1335 d->executePostedLayout();
1336 d->commonListView->setPositionForIndex(position, index);
1337}
1338
1342void QListView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags command)
1343{
1344 Q_D(QListView);
1345 if (!d->selectionModel)
1346 return;
1347
1348 // if we are wrapping, we can only select inside the contents rectangle
1349 int w = qMax(d->contentsSize().width(), d->viewport->width());
1350 int h = qMax(d->contentsSize().height(), d->viewport->height());
1351 if (d->wrap && !QRect(0, 0, w, h).intersects(rect))
1352 return;
1353
1355
1356 if (rect.width() == 1 && rect.height() == 1) {
1357 const QList<QModelIndex> intersectVector =
1358 d->intersectingSet(rect.translated(horizontalOffset(), verticalOffset()));
1359 QModelIndex tl;
1360 if (!intersectVector.isEmpty())
1361 tl = intersectVector.last(); // special case for mouse press; only select the top item
1362 if (tl.isValid() && d->isIndexEnabled(tl))
1363 selection.select(tl, tl);
1364 } else {
1365 if (state() == DragSelectingState) { // visual selection mode (rubberband selection)
1366 selection = d->selection(rect.translated(horizontalOffset(), verticalOffset()));
1367 } else { // logical selection mode (key and mouse click selection)
1368 QModelIndex tl, br;
1369 // get the first item
1370 const QRect topLeft(rect.left() + horizontalOffset(), rect.top() + verticalOffset(), 1, 1);
1371 QList<QModelIndex> intersectVector = d->intersectingSet(topLeft);
1372 if (!intersectVector.isEmpty())
1373 tl = intersectVector.last();
1374 // get the last item
1375 const QRect bottomRight(rect.right() + horizontalOffset(), rect.bottom() + verticalOffset(), 1, 1);
1376 intersectVector = d->intersectingSet(bottomRight);
1377 if (!intersectVector.isEmpty())
1378 br = intersectVector.last();
1379
1380 // get the ranges
1381 if (tl.isValid() && br.isValid()
1382 && d->isIndexEnabled(tl)
1383 && d->isIndexEnabled(br)) {
1384 QRect first = d->cellRectForIndex(tl);
1385 QRect last = d->cellRectForIndex(br);
1386 QRect middle;
1387 if (d->flow == LeftToRight) {
1388 QRect &top = first;
1389 QRect &bottom = last;
1390 // if bottom is above top, swap them
1391 if (top.center().y() > bottom.center().y()) {
1392 QRect tmp = top;
1393 top = bottom;
1394 bottom = tmp;
1395 }
1396 // if the rect are on different lines, expand
1397 if (top.top() != bottom.top()) {
1398 // top rectangle
1399 if (isRightToLeft())
1400 top.setLeft(0);
1401 else
1402 top.setRight(contentsSize().width());
1403 // bottom rectangle
1404 if (isRightToLeft())
1405 bottom.setRight(contentsSize().width());
1406 else
1407 bottom.setLeft(0);
1408 } else if (top.left() > bottom.right()) {
1409 if (isRightToLeft())
1410 bottom.setLeft(top.right());
1411 else
1412 bottom.setRight(top.left());
1413 } else {
1414 if (isRightToLeft())
1415 top.setLeft(bottom.right());
1416 else
1417 top.setRight(bottom.left());
1418 }
1419 // middle rectangle
1420 if (top.bottom() < bottom.top()) {
1421 if (gridSize().isValid() && !gridSize().isNull())
1422 middle.setTop(top.top() + gridSize().height());
1423 else
1424 middle.setTop(top.bottom() + 1);
1425 middle.setLeft(qMin(top.left(), bottom.left()));
1426 middle.setBottom(bottom.top() - 1);
1427 middle.setRight(qMax(top.right(), bottom.right()));
1428 }
1429 } else { // TopToBottom
1430 QRect &left = first;
1431 QRect &right = last;
1432 if (left.center().x() > right.center().x())
1433 qSwap(left, right);
1434
1435 int ch = contentsSize().height();
1436 if (left.left() != right.left()) {
1437 // left rectangle
1438 if (isRightToLeft())
1439 left.setTop(0);
1440 else
1441 left.setBottom(ch);
1442
1443 // top rectangle
1444 if (isRightToLeft())
1445 right.setBottom(ch);
1446 else
1447 right.setTop(0);
1448 // only set middle if the
1449 middle.setTop(0);
1450 middle.setBottom(ch);
1451 if (gridSize().isValid() && !gridSize().isNull())
1452 middle.setLeft(left.left() + gridSize().width());
1453 else
1454 middle.setLeft(left.right() + 1);
1455 middle.setRight(right.left() - 1);
1456 } else if (left.bottom() < right.top()) {
1457 left.setBottom(right.top() - 1);
1458 } else {
1459 right.setBottom(left.top() - 1);
1460 }
1461 }
1462
1463 // do the selections
1464 QItemSelection topSelection = d->selection(first);
1465 QItemSelection middleSelection = d->selection(middle);
1466 QItemSelection bottomSelection = d->selection(last);
1467 // merge
1471 }
1472 }
1473 }
1474
1475 d->selectionModel->select(selection, command);
1476}
1477
1485{
1486 Q_D(const QListView);
1487 // ### NOTE: this is a potential bottleneck in non-static mode
1488 int c = d->column;
1489 QRegion selectionRegion;
1490 const QRect &viewportRect = d->viewport->rect();
1491 for (const auto &elem : selection) {
1492 if (!elem.isValid())
1493 continue;
1494 QModelIndex parent = elem.topLeft().parent();
1495 //we only display the children of the root in a listview
1496 //we're not interested in the other model indexes
1497 if (parent != d->root)
1498 continue;
1499 int t = elem.topLeft().row();
1500 int b = elem.bottomRight().row();
1501 if (d->viewMode == IconMode || d->isWrapping()) { // in non-static mode, we have to go through all selected items
1502 for (int r = t; r <= b; ++r) {
1503 const QRect &rect = visualRect(d->model->index(r, c, parent));
1504 if (viewportRect.intersects(rect))
1505 selectionRegion += rect;
1506 }
1507 } else { // in static mode, we can optimize a bit
1508 while (t <= b && d->isHidden(t)) ++t;
1509 while (b >= t && d->isHidden(b)) --b;
1510 const QModelIndex top = d->model->index(t, c, parent);
1511 const QModelIndex bottom = d->model->index(b, c, parent);
1512 QRect rect(visualRect(top).topLeft(),
1513 visualRect(bottom).bottomRight());
1514 if (viewportRect.intersects(rect))
1515 selectionRegion += rect;
1516 }
1517 }
1518
1519 return selectionRegion;
1520}
1521
1526{
1527 Q_D(const QListView);
1528 if (!d->selectionModel)
1529 return QModelIndexList();
1530
1531 QModelIndexList viewSelected = d->selectionModel->selectedIndexes();
1532 auto ignorable = [this, d](const QModelIndex &index) {
1533 return index.column() != d->column || index.parent() != d->root || isIndexHidden(index);
1534 };
1535 viewSelected.removeIf(ignorable);
1536 return viewSelected;
1537}
1538
1545{
1546 Q_D(QListView);
1547 // showing the scroll bars will trigger a resize event,
1548 // so we set the state to expanding to avoid
1549 // triggering another layout
1550 QAbstractItemView::State oldState = state();
1552 if (d->model->columnCount(d->root) > 0) { // no columns means no contents
1553 d->resetBatchStartRow();
1554 if (layoutMode() == SinglePass) {
1555 d->doItemsLayout(d->model->rowCount(d->root)); // layout everything
1556 } else if (!d->batchLayoutTimer.isActive()) {
1557 if (!d->doItemsLayout(d->batchSize)) // layout is done
1558 d->batchLayoutTimer.start(0, this); // do a new batch as fast as possible
1559 }
1560 } else { // clear the QBspTree generated by the last layout
1561 d->clear();
1562 }
1564 setState(oldState); // restoring the oldState
1565}
1566
1571{
1572 Q_D(QListView);
1573 if (geometry().isEmpty() || d->model->rowCount(d->root) <= 0 || d->model->columnCount(d->root) <= 0) {
1574 horizontalScrollBar()->setRange(0, 0);
1575 verticalScrollBar()->setRange(0, 0);
1576 } else {
1577 QModelIndex index = d->model->index(0, d->column, d->root);
1578 QStyleOptionViewItem option;
1580 QSize step = d->itemSize(option, index);
1581 d->commonListView->updateHorizontalScrollBar(step);
1582 d->commonListView->updateVerticalScrollBar(step);
1583 }
1584
1586
1587 // if the scroll bars are turned off, we resize the contents to the viewport
1588 if (d->movement == Static && !d->isWrapping()) {
1589 d->layoutChildren(); // we need the viewport size to be updated
1590 if (d->flow == TopToBottom) {
1591 if (horizontalScrollBarPolicy() == Qt::ScrollBarAlwaysOff) {
1592 d->setContentsSize(viewport()->width(), contentsSize().height());
1593 horizontalScrollBar()->setRange(0, 0); // we see all the contents anyway
1594 }
1595 } else { // LeftToRight
1596 if (verticalScrollBarPolicy() == Qt::ScrollBarAlwaysOff) {
1597 d->setContentsSize(contentsSize().width(), viewport()->height());
1598 verticalScrollBar()->setRange(0, 0); // we see all the contents anyway
1599 }
1600 }
1601 }
1602
1603}
1604
1609{
1610 Q_D(const QListView);
1611 return (d->isHidden(index.row())
1612 && (index.parent() == d->root)
1613 && index.column() == d->column);
1614}
1615
1624{
1625 Q_D(QListView);
1626 if (column < 0 || column >= d->model->columnCount(d->root))
1627 return;
1628 d->column = column;
1629 d->doDelayedItemsLayout();
1630#if QT_CONFIG(accessibility)
1631 if (QAccessible::isActive()) {
1632 QAccessibleTableModelChangeEvent event(this, QAccessibleTableModelChangeEvent::ModelReset);
1633 QAccessible::updateAccessibility(&event);
1634 }
1635#endif
1636}
1637
1639{
1640 Q_D(const QListView);
1641 return d->column;
1642}
1643
1656{
1657 Q_D(QListView);
1658 d->uniformItemSizes = enable;
1659}
1660
1662{
1663 Q_D(const QListView);
1664 return d->uniformItemSizes;
1665}
1666
1682{
1683 Q_D(QListView);
1684 if (d->wrapItemText == on)
1685 return;
1686 d->wrapItemText = on;
1687 d->doDelayedItemsLayout();
1688}
1689
1691{
1692 Q_D(const QListView);
1693 return d->wrapItemText;
1694}
1695
1712{
1713 Q_D(QListView);
1714 d->modeProperties |= uint(QListViewPrivate::SelectionRectVisible);
1715 d->setSelectionRectVisible(show);
1716}
1717
1719{
1720 Q_D(const QListView);
1721 return d->isSelectionRectVisible();
1722}
1723
1735{
1736 Q_D(QListView);
1737 if (d->itemAlignment == alignment)
1738 return;
1739 d->itemAlignment = alignment;
1741 d->doDelayedItemsLayout();
1742}
1743
1744Qt::Alignment QListView::itemAlignment() const
1745{
1746 Q_D(const QListView);
1747 return d->itemAlignment;
1748}
1749
1754{
1755 return QAbstractItemView::event(e);
1756}
1757
1758/*
1759 * private object implementation
1760 */
1761
1764 commonListView(nullptr),
1765 wrap(false),
1766 space(0),
1767 flow(QListView::TopToBottom),
1768 movement(QListView::Static),
1769 resizeMode(QListView::Fixed),
1770 layoutMode(QListView::SinglePass),
1771 viewMode(QListView::ListMode),
1772 modeProperties(0),
1773 column(0),
1774 uniformItemSizes(false),
1775 batchSize(100),
1776 showElasticBand(false),
1777 itemAlignment(Qt::Alignment())
1778{
1779}
1780
1785
1787{
1788 // initialization of data structs
1791}
1792
1794{
1795 Q_Q(QListView);
1796 clear();
1797
1798 //take the size as if there were scrollbar in order to prevent scrollbar to blink
1799 layoutBounds = QRect(QPoint(), q->maximumViewportSize());
1800
1801 int frameAroundContents = 0;
1802 if (q->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents)) {
1804 option.initFrom(q);
1805 frameAroundContents = q->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &option, q) * 2;
1806 }
1807
1808 // maximumViewportSize() already takes scrollbar into account if policy is
1809 // Qt::ScrollBarAlwaysOn but scrollbar extent must be deduced if policy
1810 // is Qt::ScrollBarAsNeeded
1811 int verticalMargin = (vbarpolicy == Qt::ScrollBarAsNeeded) && (flow == QListView::LeftToRight || vbar->isVisible())
1812 && !q->style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarOverlap, nullptr, vbar)
1813 ? q->style()->pixelMetric(QStyle::PM_ScrollBarExtent, nullptr, vbar) + frameAroundContents
1814 : 0;
1815 int horizontalMargin = hbarpolicy==Qt::ScrollBarAsNeeded
1816 ? q->style()->pixelMetric(QStyle::PM_ScrollBarExtent, nullptr, hbar) + frameAroundContents
1817 : 0;
1818
1819 layoutBounds.adjust(0, 0, -verticalMargin, -horizontalMargin);
1820
1821 int rowCount = model->columnCount(root) <= 0 ? 0 : model->rowCount(root);
1822 commonListView->setRowCount(rowCount);
1823}
1824
1829{
1830 int max = model->rowCount(root) - 1;
1831 int first = batchStartRow();
1832 int last = qMin(first + delta - 1, max);
1833
1834 if (first == 0) {
1835 layoutChildren(); // make sure the viewport has the right size
1837 }
1838
1839 if (max < 0 || last < first) {
1840 return true; // nothing to do
1841 }
1842
1844 info.bounds = layoutBounds;
1845 info.grid = gridSize();
1846 info.spacing = (info.grid.isValid() ? 0 : spacing());
1847 info.first = first;
1848 info.last = last;
1849 info.wrap = isWrapping();
1850 info.flow = flow;
1851 info.max = max;
1852
1854}
1855
1857{
1858 if (!index.isValid() || isHidden(index.row()))
1859 return QListViewItem();
1860
1862}
1863
1865{
1866 Q_Q(const QListView);
1867 if (!rect.isValid())
1868 return rect;
1869
1871 int dx = -q->horizontalOffset();
1872 int dy = -q->verticalOffset();
1873 return result.adjusted(dx, dy, dx, dy);
1874}
1875
1877 const QList<QModelIndex> &candidates) const
1878{
1879 int distance = 0;
1880 int shortest = INT_MAX;
1881 QModelIndex closest;
1883
1884 for (; it != candidates.end(); ++it) {
1885 if (!(*it).isValid())
1886 continue;
1887
1888 const QRect indexRect = indexToListViewItem(*it).rect();
1889
1890 //if the center x (or y) position of an item is included in the rect of the other item,
1891 //we define the distance between them as the difference in x (or y) of their respective center.
1892 // Otherwise, we use the nahattan length between the 2 items
1893 if ((target.center().x() >= indexRect.x() && target.center().x() < indexRect.right())
1894 || (indexRect.center().x() >= target.x() && indexRect.center().x() < target.right())) {
1895 //one item's center is at the vertical of the other
1896 distance = qAbs(indexRect.center().y() - target.center().y());
1897 } else if ((target.center().y() >= indexRect.y() && target.center().y() < indexRect.bottom())
1898 || (indexRect.center().y() >= target.y() && indexRect.center().y() < target.bottom())) {
1899 //one item's center is at the vertical of the other
1900 distance = qAbs(indexRect.center().x() - target.center().x());
1901 } else {
1902 distance = (indexRect.center() - target.center()).manhattanLength();
1903 }
1904 if (distance < shortest) {
1905 shortest = distance;
1906 closest = *it;
1907 }
1908 }
1909 return closest;
1910}
1911
1912QSize QListViewPrivate::itemSize(const QStyleOptionViewItem &option, const QModelIndex &index) const
1913{
1914 Q_Q(const QListView);
1915 if (!uniformItemSizes) {
1916 const QAbstractItemDelegate *delegate = q->itemDelegateForIndex(index);
1917 return delegate ? delegate->sizeHint(option, index) : QSize();
1918 }
1919 if (!cachedItemSize.isValid()) { // the last item is probably the largest, so we use its size
1920 int row = model->rowCount(root) - 1;
1921 QModelIndex sample = model->index(row, column, root);
1922 const QAbstractItemDelegate *delegate = q->itemDelegateForIndex(sample);
1923 cachedItemSize = delegate ? delegate->sizeHint(option, sample) : QSize();
1924 }
1925 return cachedItemSize;
1926}
1927
1929{
1931 QModelIndex tl, br;
1932 const QList<QModelIndex> intersectVector = intersectingSet(rect);
1933 QList<QModelIndex>::const_iterator it = intersectVector.begin();
1934 for (; it != intersectVector.end(); ++it) {
1935 if (!tl.isValid() && !br.isValid()) {
1936 tl = br = *it;
1937 } else if ((*it).row() == (tl.row() - 1)) {
1938 tl = *it; // expand current range
1939 } else if ((*it).row() == (br.row() + 1)) {
1940 br = (*it); // expand current range
1941 } else {
1942 selection.select(tl, br); // select current range
1943 tl = br = *it; // start new range
1944 }
1945 }
1946
1947 if (tl.isValid() && br.isValid())
1948 selection.select(tl, br);
1949 else if (tl.isValid())
1950 selection.select(tl, tl);
1951 else if (br.isValid())
1952 selection.select(br, br);
1953
1954 return selection;
1955}
1956
1957#if QT_CONFIG(draganddrop)
1958QAbstractItemView::DropIndicatorPosition QListViewPrivate::position(const QPoint &pos, const QRect &rect, const QModelIndex &idx) const
1959{
1961 return static_cast<QListModeViewBase *>(commonListView)->position(pos, rect, idx);
1962 else
1963 return QAbstractItemViewPrivate::position(pos, rect, idx);
1964}
1965
1966bool QListViewPrivate::dropOn(QDropEvent *event, int *dropRow, int *dropCol, QModelIndex *dropIndex)
1967{
1969 return static_cast<QListModeViewBase *>(commonListView)->dropOn(event, dropRow, dropCol, dropIndex);
1970 else
1971 return QAbstractItemViewPrivate::dropOn(event, dropRow, dropCol, dropIndex);
1972}
1973#endif
1974
1975void QListViewPrivate::removeCurrentAndDisabled(QList<QModelIndex> *indexes,
1976 const QModelIndex &current) const
1977{
1978 auto isCurrentOrDisabled = [this, current](const QModelIndex &index) {
1979 return !isIndexEnabled(index) || index == current;
1980 };
1981 indexes->removeIf(isCurrentOrDisabled);
1982}
1983
1984/*
1985 * Common ListView Implementation
1986*/
1987
1992
1997
1998#if QT_CONFIG(draganddrop)
1999void QCommonListViewBase::paintDragDrop(QPainter *painter)
2000{
2001 // FIXME: Until the we can provide a proper drop indicator
2002 // in IconMode, it makes no sense to show it
2003 dd->paintDropIndicator(painter);
2004}
2005#endif
2006
2008{
2009 return v->contentsRect().marginsRemoved(v->viewportMargins()).size();
2010}
2011
2013{
2014 horizontalScrollBar()->d_func()->itemviewChangeSingleStep(step.width() + spacing());
2016
2017 // If both scroll bars are set to auto, we might end up in a situation with enough space
2018 // for the actual content. But still one of the scroll bars will become enabled due to
2019 // the other one using the space. The other one will become invisible in the same cycle.
2020 // -> Infinite loop, QTBUG-39902
2021 const bool bothScrollBarsAuto = qq->verticalScrollBarPolicy() == Qt::ScrollBarAsNeeded &&
2022 qq->horizontalScrollBarPolicy() == Qt::ScrollBarAsNeeded;
2023
2024 const QSize viewportSize = QListModeViewBase::viewportSize(qq);
2025
2026 bool verticalWantsToShow = contentsSize.height() > viewportSize.height();
2027 bool horizontalWantsToShow;
2028 if (verticalWantsToShow)
2029 horizontalWantsToShow = contentsSize.width() > viewportSize.width() - qq->verticalScrollBar()->width();
2030 else
2031 horizontalWantsToShow = contentsSize.width() > viewportSize.width();
2032
2033 if (bothScrollBarsAuto && !horizontalWantsToShow) {
2034 // break the infinite loop described above by setting the range to 0, 0.
2035 // QAbstractScrollArea will then hide the scroll bar for us
2037 } else {
2039 }
2040}
2041
2043{
2044 verticalScrollBar()->d_func()->itemviewChangeSingleStep(step.height() + spacing());
2046
2047 // If both scroll bars are set to auto, we might end up in a situation with enough space
2048 // for the actual content. But still one of the scroll bars will become enabled due to
2049 // the other one using the space. The other one will become invisible in the same cycle.
2050 // -> Infinite loop, QTBUG-39902
2051 const bool bothScrollBarsAuto = qq->verticalScrollBarPolicy() == Qt::ScrollBarAsNeeded &&
2052 qq->horizontalScrollBarPolicy() == Qt::ScrollBarAsNeeded;
2053
2054 const QSize viewportSize = QListModeViewBase::viewportSize(qq);
2055
2056 bool horizontalWantsToShow = contentsSize.width() > viewportSize.width();
2057 bool verticalWantsToShow;
2058 if (horizontalWantsToShow)
2059 verticalWantsToShow = contentsSize.height() > viewportSize.height() - qq->horizontalScrollBar()->height();
2060 else
2061 verticalWantsToShow = contentsSize.height() > viewportSize.height();
2062
2063 if (bothScrollBarsAuto && !verticalWantsToShow) {
2064 // break the infinite loop described above by setting the range to 0, 0.
2065 // QAbstractScrollArea will then hide the scroll bar for us
2066 verticalScrollBar()->setRange(0, 0);
2067 } else {
2069 }
2070}
2071
2072void QCommonListViewBase::scrollContentsBy(int dx, int dy, bool /*scrollElasticBand*/)
2073{
2074 dd->scrollContentsBy(isRightToLeft() ? -dx : dx, dy);
2075}
2076
2078 bool above, bool below, const QRect &area, const QRect &rect) const
2079{
2080 int verticalValue = verticalScrollBar()->value();
2081 QRect adjusted = rect.adjusted(-spacing(), -spacing(), spacing(), spacing());
2082 if (hint == QListView::PositionAtTop || above)
2083 verticalValue += adjusted.top();
2084 else if (hint == QListView::PositionAtBottom || below)
2085 verticalValue += qMin(adjusted.top(), adjusted.bottom() - area.height() + 1);
2087 verticalValue += adjusted.top() - ((area.height() - adjusted.height()) / 2);
2088 return verticalValue;
2089}
2090
2095
2097 bool leftOf, bool rightOf, const QRect &area, const QRect &rect) const
2098{
2099 int horizontalValue = horizontalScrollBar()->value();
2100 if (isRightToLeft()) {
2102 horizontalValue += ((area.width() - rect.width()) / 2) - rect.left();
2103 } else {
2104 if (leftOf)
2105 horizontalValue -= rect.left();
2106 else if (rightOf)
2107 horizontalValue += qMin(rect.left(), area.width() - rect.right());
2108 }
2109 } else {
2111 horizontalValue += rect.left() - ((area.width()- rect.width()) / 2);
2112 } else {
2113 if (leftOf)
2114 horizontalValue += rect.left();
2115 else if (rightOf)
2116 horizontalValue += qMin(rect.left(), rect.right() - area.width());
2117 }
2118 }
2119 return horizontalValue;
2120}
2121
2122/*
2123 * ListMode ListView Implementation
2124*/
2127{
2128#if QT_CONFIG(draganddrop)
2129 dd->defaultDropAction = Qt::CopyAction;
2130#endif
2131}
2132
2133#if QT_CONFIG(draganddrop)
2134QAbstractItemView::DropIndicatorPosition QListModeViewBase::position(const QPoint &pos, const QRect &rect, const QModelIndex &index) const
2135{
2136 QAbstractItemView::DropIndicatorPosition r = QAbstractItemView::OnViewport;
2137 if (!dd->overwrite) {
2138 const int margin = 2;
2139 if (pos.x() - rect.left() < margin) {
2140 r = QAbstractItemView::AboveItem; // Visually, on the left
2141 } else if (rect.right() - pos.x() < margin) {
2142 r = QAbstractItemView::BelowItem; // Visually, on the right
2143 } else if (rect.contains(pos, true)) {
2144 r = QAbstractItemView::OnItem;
2145 }
2146 } else {
2147 QRect touchingRect = rect;
2148 touchingRect.adjust(-1, -1, 1, 1);
2149 if (touchingRect.contains(pos, false)) {
2150 r = QAbstractItemView::OnItem;
2151 }
2152 }
2153
2154 if (r == QAbstractItemView::OnItem && (!(dd->model->flags(index) & Qt::ItemIsDropEnabled)))
2155 r = pos.x() < rect.center().x() ? QAbstractItemView::AboveItem : QAbstractItemView::BelowItem;
2156
2157 return r;
2158}
2159
2160void QListModeViewBase::dragMoveEvent(QDragMoveEvent *event)
2161{
2162 if (qq->dragDropMode() == QAbstractItemView::InternalMove
2163 && (event->source() != qq || !(event->possibleActions() & Qt::MoveAction)))
2164 return;
2165
2166 // ignore by default
2167 event->ignore();
2168
2169 // can't use indexAt, doesn't account for spacing.
2170 QPoint p = event->position().toPoint();
2171 QRect rect(p.x() + horizontalOffset(), p.y() + verticalOffset(), 1, 1);
2172 rect.adjust(-dd->spacing(), -dd->spacing(), dd->spacing(), dd->spacing());
2173 const QList<QModelIndex> intersectVector = dd->intersectingSet(rect);
2174 QModelIndex index = intersectVector.size() > 0
2175 ? intersectVector.last() : QModelIndex();
2176 dd->hover = index;
2178 && dd->canDrop(event)) {
2179
2180 if (index.isValid() && dd->showDropIndicator) {
2182 dd->dropIndicatorPosition = position(event->position().toPoint(), rect, index);
2183 // if spacing, should try to draw between items, not just next to item.
2184 switch (dd->dropIndicatorPosition) {
2185 case QAbstractItemView::AboveItem:
2186 if (dd->isIndexDropEnabled(index.parent())) {
2187 dd->dropIndicatorRect = QRect(rect.left()-dd->spacing(), rect.top(), 0, rect.height());
2188 event->accept();
2189 } else {
2190 dd->dropIndicatorRect = QRect();
2191 }
2192 break;
2193 case QAbstractItemView::BelowItem:
2194 if (dd->isIndexDropEnabled(index.parent())) {
2195 dd->dropIndicatorRect = QRect(rect.right()+dd->spacing(), rect.top(), 0, rect.height());
2196 event->accept();
2197 } else {
2198 dd->dropIndicatorRect = QRect();
2199 }
2200 break;
2201 case QAbstractItemView::OnItem:
2202 if (dd->isIndexDropEnabled(index)) {
2203 dd->dropIndicatorRect = rect;
2204 event->accept();
2205 } else {
2206 dd->dropIndicatorRect = QRect();
2207 }
2208 break;
2209 case QAbstractItemView::OnViewport:
2210 dd->dropIndicatorRect = QRect();
2211 if (dd->isIndexDropEnabled(qq->rootIndex())) {
2212 event->accept(); // allow dropping in empty areas
2213 }
2214 break;
2215 }
2216 } else {
2217 dd->dropIndicatorRect = QRect();
2218 dd->dropIndicatorPosition = QAbstractItemView::OnViewport;
2219 if (dd->isIndexDropEnabled(qq->rootIndex())) {
2220 event->accept(); // allow dropping in empty areas
2221 }
2222 }
2223 dd->viewport->update();
2224 } // can drop
2225
2226 if (dd->shouldAutoScroll(event->position().toPoint()))
2228}
2229
2241bool QListModeViewBase::dropOn(QDropEvent *event, int *dropRow, int *dropCol, QModelIndex *dropIndex)
2242{
2243 if (event->isAccepted())
2244 return false;
2245
2247 if (dd->viewport->rect().contains(event->position().toPoint())) {
2248 // can't use indexAt, doesn't account for spacing.
2249 QPoint p = event->position().toPoint();
2250 QRect rect(p.x() + horizontalOffset(), p.y() + verticalOffset(), 1, 1);
2251 rect.adjust(-dd->spacing(), -dd->spacing(), dd->spacing(), dd->spacing());
2252 const QList<QModelIndex> intersectVector = dd->intersectingSet(rect);
2253 index = intersectVector.size() > 0
2254 ? intersectVector.last() : QModelIndex();
2255 if (!index.isValid())
2256 index = dd->root;
2257 }
2258
2259 // If we are allowed to do the drop
2260 if (dd->model->supportedDropActions() & event->dropAction()) {
2261 int row = -1;
2262 int col = -1;
2263 if (index != dd->root) {
2264 dd->dropIndicatorPosition = position(event->position().toPoint(), qq->visualRect(index), index);
2265 switch (dd->dropIndicatorPosition) {
2266 case QAbstractItemView::AboveItem:
2267 row = index.row();
2268 col = index.column();
2269 index = index.parent();
2270 break;
2271 case QAbstractItemView::BelowItem:
2272 row = index.row() + 1;
2273 col = index.column();
2274 index = index.parent();
2275 break;
2276 case QAbstractItemView::OnItem:
2277 case QAbstractItemView::OnViewport:
2278 break;
2279 }
2280 } else {
2281 dd->dropIndicatorPosition = QAbstractItemView::OnViewport;
2282 }
2283 *dropIndex = index;
2284 *dropRow = row;
2285 *dropCol = col;
2287 return true;
2288 }
2289 return false;
2290}
2291
2292#endif //QT_CONFIG(draganddrop)
2293
2295{
2297 && ((flow() == QListView::TopToBottom && !isWrapping())
2298 || (flow() == QListView::LeftToRight && isWrapping()))) {
2299 const int steps = (flow() == QListView::TopToBottom ? scrollValueMap : segmentPositions).size() - 1;
2300 if (steps > 0) {
2301 const int pageSteps = perItemScrollingPageSteps(viewport()->height(), contentsSize.height(), isWrapping());
2303 verticalScrollBar()->setPageStep(pageSteps);
2304 verticalScrollBar()->setRange(0, steps - pageSteps);
2305 } else {
2306 verticalScrollBar()->setRange(0, 0);
2307 }
2308 // } else if (vertical && d->isWrapping() && d->movement == Static) {
2309 // ### wrapped scrolling in flow direction
2310 } else {
2312 }
2313}
2314
2316{
2318 && ((flow() == QListView::TopToBottom && isWrapping())
2319 || (flow() == QListView::LeftToRight && !isWrapping()))) {
2320 int steps = (flow() == QListView::TopToBottom ? segmentPositions : scrollValueMap).size() - 1;
2321 if (steps > 0) {
2322 const int pageSteps = perItemScrollingPageSteps(viewport()->width(), contentsSize.width(), isWrapping());
2324 horizontalScrollBar()->setPageStep(pageSteps);
2325 horizontalScrollBar()->setRange(0, steps - pageSteps);
2326 } else {
2328 }
2329 } else {
2331 }
2332}
2333
2335 bool above, bool below, const QRect &area, const QRect &rect) const
2336{
2338 int value;
2339 if (scrollValueMap.isEmpty()) {
2340 value = 0;
2341 } else {
2342 int scrollBarValue = verticalScrollBar()->value();
2343 int numHidden = 0;
2344 for (const auto &idx : std::as_const(dd->hiddenRows))
2345 if (idx.row() <= scrollBarValue)
2346 ++numHidden;
2347 value = qBound(0, scrollValueMap.at(verticalScrollBar()->value()) - numHidden, flowPositions.size() - 1);
2348 }
2349 if (above)
2351 else if (below)
2354 return value;
2355
2356 return perItemScrollToValue(index, value, area.height(), hint, Qt::Vertical, isWrapping(), rect.height());
2357 }
2358
2360}
2361
2363{
2365 if (isWrapping()) {
2367 const int max = segmentPositions.size() - 1;
2368 int currentValue = qBound(0, horizontalScrollBar()->value(), max);
2370 int maximumValue = qBound(0, horizontalScrollBar()->maximum(), max);
2371 int maximum = segmentPositions.at(maximumValue);
2372 return (isRightToLeft() ? maximum - position : position);
2373 }
2374 } else if (flow() == QListView::LeftToRight && !flowPositions.isEmpty()) {
2376 int maximum = flowPositions.at(scrollValueMap.at(horizontalScrollBar()->maximum()));
2377 return (isRightToLeft() ? maximum - position : position);
2378 }
2379 }
2381}
2382
2384{
2386 if (isWrapping()) {
2388 int value = verticalScrollBar()->value();
2389 if (value >= segmentPositions.size())
2390 return 0;
2391 return segmentPositions.at(value) - spacing();
2392 }
2393 } else if (flow() == QListView::TopToBottom && !flowPositions.isEmpty()) {
2394 int value = verticalScrollBar()->value();
2395 if (value > scrollValueMap.size())
2396 return 0;
2398 }
2399 }
2401}
2402
2404 bool leftOf, bool rightOf, const QRect &area, const QRect &rect) const
2405{
2408
2409 int value;
2410 if (scrollValueMap.isEmpty())
2411 value = 0;
2412 else
2414 if (leftOf)
2416 else if (rightOf)
2419 return value;
2420
2421 return perItemScrollToValue(index, value, area.width(), hint, Qt::Horizontal, isWrapping(), rect.width());
2422}
2423
2424void QListModeViewBase::scrollContentsBy(int dx, int dy, bool scrollElasticBand)
2425{
2426 // ### reorder this logic
2427 const int verticalValue = verticalScrollBar()->value();
2428 const int horizontalValue = horizontalScrollBar()->value();
2429 const bool vertical = (verticalScrollMode() == QAbstractItemView::ScrollPerItem);
2430 const bool horizontal = (horizontalScrollMode() == QAbstractItemView::ScrollPerItem);
2431
2432 if (isWrapping()) {
2434 return;
2435 const int max = segmentPositions.size() - 1;
2436 if (horizontal && flow() == QListView::TopToBottom && dx != 0) {
2437 int currentValue = qBound(0, horizontalValue, max);
2438 int previousValue = qBound(0, currentValue + dx, max);
2439 int currentCoordinate = segmentPositions.at(currentValue) - spacing();
2440 int previousCoordinate = segmentPositions.at(previousValue) - spacing();
2441 dx = previousCoordinate - currentCoordinate;
2442 } else if (vertical && flow() == QListView::LeftToRight && dy != 0) {
2443 int currentValue = qBound(0, verticalValue, max);
2444 int previousValue = qBound(0, currentValue + dy, max);
2445 int currentCoordinate = segmentPositions.at(currentValue) - spacing();
2446 int previousCoordinate = segmentPositions.at(previousValue) - spacing();
2447 dy = previousCoordinate - currentCoordinate;
2448 }
2449 } else {
2450 if (flowPositions.isEmpty())
2451 return;
2452 const int max = scrollValueMap.size() - 1;
2453 if (vertical && flow() == QListView::TopToBottom && dy != 0) {
2454 int currentValue = qBound(0, verticalValue, max);
2455 int previousValue = qBound(0, currentValue + dy, max);
2456 int currentCoordinate = flowPositions.at(scrollValueMap.at(currentValue));
2457 int previousCoordinate = flowPositions.at(scrollValueMap.at(previousValue));
2458 dy = previousCoordinate - currentCoordinate;
2459 } else if (horizontal && flow() == QListView::LeftToRight && dx != 0) {
2460 int currentValue = qBound(0, horizontalValue, max);
2461 int previousValue = qBound(0, currentValue + dx, max);
2462 int currentCoordinate = flowPositions.at(scrollValueMap.at(currentValue));
2463 int previousCoordinate = flowPositions.at(scrollValueMap.at(previousValue));
2464 dx = previousCoordinate - currentCoordinate;
2465 }
2466 }
2467 QCommonListViewBase::scrollContentsBy(dx, dy, scrollElasticBand);
2468}
2469
2471{
2472 doStaticLayout(info);
2473 return batchStartRow > max; // returning true stops items layout
2474}
2475
2477{
2480 || index.row() >= flowPositions.size() - 1)
2481 return QListViewItem();
2482
2483 const int segment = qBinarySearch<int>(segmentStartRows, index.row(),
2484 0, segmentStartRows.size() - 1);
2485
2486
2487 QStyleOptionViewItem options;
2488 initViewItemOption(&options);
2489 options.rect.setSize(contentsSize);
2491 ? cachedItemSize() : itemSize(options, index);
2492 QSize cellSize = size;
2493
2494 QPoint pos;
2495 if (flow() == QListView::LeftToRight) {
2496 pos.setX(flowPositions.at(index.row()));
2498 } else { // TopToBottom
2499 pos.setY(flowPositions.at(index.row()));
2501 if (isWrapping()) { // make the items as wide as the segment
2502 int right = (segment + 1 >= segmentPositions.size()
2504 : segmentPositions.at(segment + 1));
2505 cellSize.setWidth(right - pos.x());
2506 } else { // make the items as wide as the viewport
2507 cellSize.setWidth(qMax(size.width(), viewport()->width() - 2 * spacing()));
2508 }
2509 }
2510
2512 size.setWidth(qMin(size.width(), cellSize.width()));
2514 pos.setX(pos.x() + cellSize.width() - size.width());
2516 pos.setX(pos.x() + (cellSize.width() - size.width()) / 2);
2517 } else {
2518 size.setWidth(cellSize.width());
2519 }
2520
2521 return QListViewItem(QRect(pos, size), index.row());
2522}
2523
2524QPoint QListModeViewBase::initStaticLayout(const QListViewLayoutInfo &info)
2525{
2526 int x, y;
2527 if (info.first == 0) {
2533 x = info.bounds.left() + info.spacing;
2534 y = info.bounds.top() + info.spacing;
2537 } else if (info.wrap) {
2538 if (info.flow == QListView::LeftToRight) {
2541 } else { // flow == QListView::TopToBottom
2544 }
2545 } else { // not first and not wrap
2546 if (info.flow == QListView::LeftToRight) {
2548 y = info.bounds.top() + info.spacing;
2549 } else { // flow == QListView::TopToBottom
2550 x = info.bounds.left() + info.spacing;
2552 }
2553 }
2554 return QPoint(x, y);
2555}
2556
2560void QListModeViewBase::doStaticLayout(const QListViewLayoutInfo &info)
2561{
2562 const bool useItemSize = !info.grid.isValid();
2563 const QPoint topLeft = initStaticLayout(info);
2564 QStyleOptionViewItem option;
2566 option.rect = info.bounds;
2567 option.rect.adjust(info.spacing, info.spacing, -info.spacing, -info.spacing);
2568
2569 // The static layout data structures are as follows:
2570 // One vector contains the coordinate in the direction of layout flow.
2571 // Another vector contains the coordinates of the segments.
2572 // A third vector contains the index (model row) of the first item
2573 // of each segment.
2574
2575 int segStartPosition;
2576 int segEndPosition;
2577 int deltaFlowPosition;
2578 int deltaSegPosition;
2579 int deltaSegHint;
2580 int flowPosition;
2581 int segPosition;
2582
2583 if (info.flow == QListView::LeftToRight) {
2584 segStartPosition = info.bounds.left();
2585 segEndPosition = info.bounds.width();
2586 flowPosition = topLeft.x();
2587 segPosition = topLeft.y();
2588 deltaFlowPosition = info.grid.width(); // dx
2589 deltaSegPosition = useItemSize ? batchSavedDeltaSeg : info.grid.height(); // dy
2590 deltaSegHint = info.grid.height();
2591 } else { // flow == QListView::TopToBottom
2592 segStartPosition = info.bounds.top();
2593 segEndPosition = info.bounds.height();
2594 flowPosition = topLeft.y();
2595 segPosition = topLeft.x();
2596 deltaFlowPosition = info.grid.height(); // dy
2597 deltaSegPosition = useItemSize ? batchSavedDeltaSeg : info.grid.width(); // dx
2598 deltaSegHint = info.grid.width();
2599 }
2600
2601 for (int row = info.first; row <= info.last; ++row) {
2602 if (isHidden(row)) { // ###
2604 } else {
2605 // if we are not using a grid, we need to find the deltas
2606 if (useItemSize) {
2608 if (info.flow == QListView::LeftToRight) {
2609 deltaFlowPosition = hint.width() + info.spacing;
2610 deltaSegHint = hint.height() + info.spacing;
2611 } else { // TopToBottom
2612 deltaFlowPosition = hint.height() + info.spacing;
2613 deltaSegHint = hint.width() + info.spacing;
2614 }
2615 }
2616 // create new segment
2617 if (info.wrap && (flowPosition + deltaFlowPosition >= segEndPosition)) {
2619 flowPosition = info.spacing + segStartPosition;
2620 segPosition += info.spacing + deltaSegPosition;
2621 segmentPositions.append(segPosition);
2623 deltaSegPosition = 0;
2624 }
2625 // save the flow position of this item
2628 // prepare for the next item
2629 deltaSegPosition = qMax(deltaSegHint, deltaSegPosition);
2630 flowPosition += info.spacing + deltaFlowPosition;
2631 }
2632 }
2633 // used when laying out next batch
2635 batchSavedDeltaSeg = deltaSegPosition;
2636 batchStartRow = info.last + 1;
2637 if (info.last == info.max)
2638 flowPosition -= info.spacing; // remove extra spacing
2639 // set the contents size
2640 QRect rect = info.bounds;
2641 if (info.flow == QListView::LeftToRight) {
2642 rect.setRight(segmentPositions.size() == 1 ? flowPosition : info.bounds.right());
2643 rect.setBottom(segPosition + deltaSegPosition);
2644 } else { // TopToBottom
2645 rect.setRight(segPosition + deltaSegPosition);
2646 rect.setBottom(segmentPositions.size() == 1 ? flowPosition : info.bounds.bottom());
2647 }
2648 contentsSize = QSize(rect.right(), rect.bottom());
2649 // if it is the last batch, save the end of the segments
2650 if (info.last == info.max) {
2654 segmentPositions.append(info.wrap ? segPosition + deltaSegPosition : INT_MAX);
2655 }
2656 // if the new items are visible, update the viewport
2657 QRect changedRect(topLeft, rect.bottomRight());
2658 if (clipRect().intersects(changedRect))
2659 viewport()->update();
2660}
2661
2667QList<QModelIndex> QListModeViewBase::intersectingSet(const QRect &area) const
2668{
2669 QList<QModelIndex> ret;
2670 int segStartPosition;
2671 int segEndPosition;
2672 int flowStartPosition;
2673 int flowEndPosition;
2674 if (flow() == QListView::LeftToRight) {
2675 segStartPosition = area.top();
2676 segEndPosition = area.bottom();
2677 flowStartPosition = area.left();
2678 flowEndPosition = area.right();
2679 } else {
2680 segStartPosition = area.left();
2681 segEndPosition = area.right();
2682 flowStartPosition = area.top();
2683 flowEndPosition = area.bottom();
2684 }
2686 return ret;
2687 // the last segment position is actually the edge of the last segment
2688 const int segLast = segmentPositions.size() - 2;
2689 int seg = qBinarySearch<int>(segmentPositions, segStartPosition, 0, segLast + 1);
2690 for (; seg <= segLast && segmentPositions.at(seg) <= segEndPosition; ++seg) {
2691 int first = segmentStartRows.at(seg);
2692 int last = (seg < segLast ? segmentStartRows.at(seg + 1) : batchStartRow) - 1;
2693 if (segmentExtents.at(seg) < flowStartPosition)
2694 continue;
2695 int row = qBinarySearch<int>(flowPositions, flowStartPosition, first, last);
2696 for (; row <= last && flowPositions.at(row) <= flowEndPosition; ++row) {
2697 if (isHidden(row))
2698 continue;
2700 if (index.isValid()) {
2701 if (flow() == QListView::LeftToRight || dd->itemAlignment == Qt::Alignment()) {
2702 ret += index;
2703 } else {
2704 const auto viewItem = indexToListViewItem(index);
2705 const int iw = viewItem.width();
2706 const int startPos = qMax(segStartPosition, segmentPositions.at(seg));
2707 const int endPos = qMin(segmentPositions.at(seg + 1), segEndPosition);
2708 if (endPos >= viewItem.x && startPos < viewItem.x + iw)
2709 ret += index;
2710 }
2711 }
2712#if 0 // for debugging
2713 else
2714 qWarning("intersectingSet: row %d was invalid", row);
2715#endif
2716 }
2717 }
2718 return ret;
2719}
2720
2725
2726
2728{
2729 if (isWrapping())
2730 return rect;
2731 // If the listview is in "listbox-mode", the items are as wide as the view.
2732 // But we don't shrink the items.
2733 QRect result = rect;
2734 if (flow() == QListView::TopToBottom) {
2736 result.setWidth(qMax(rect.width(), qMax(contentsSize.width(), viewport()->width()) - 2 * spacing()));
2737 } else { // LeftToRight
2738 result.setTop(spacing());
2739 result.setHeight(qMax(rect.height(), qMax(contentsSize.height(), viewport()->height()) - 2 * spacing()));
2740 }
2741 return result;
2742}
2743
2744int QListModeViewBase::perItemScrollingPageSteps(int length, int bounds, bool wrap) const
2745{
2746 QList<int> positions;
2747 if (wrap)
2749 else if (!flowPositions.isEmpty()) {
2750 positions.reserve(scrollValueMap.size());
2751 for (int itemShown : scrollValueMap)
2752 positions.append(flowPositions.at(itemShown));
2753 }
2754 if (positions.isEmpty() || bounds <= length)
2755 return positions.size();
2756 if (uniformItemSizes()) {
2757 for (int i = 1; i < positions.size(); ++i)
2758 if (positions.at(i) > 0)
2759 return length / positions.at(i);
2760 return 0; // all items had height 0
2761 }
2762 int pageSteps = 0;
2763 int steps = positions.size() - 1;
2764 int max = qMax(length, bounds);
2765 int min = qMin(length, bounds);
2766 int pos = min - (max - positions.constLast());
2767
2768 while (pos >= 0 && steps > 0) {
2769 pos -= (positions.at(steps) - positions.at(steps - 1));
2770 if (pos >= 0) //this item should be visible
2771 ++pageSteps;
2772 --steps;
2773 }
2774
2775 // at this point we know that positions has at least one entry
2776 return qMax(pageSteps, 1);
2777}
2778
2779int QListModeViewBase::perItemScrollToValue(int index, int scrollValue, int viewportSize,
2781 Qt::Orientation orientation, bool wrap, int itemExtent) const
2782{
2783 if (index < 0)
2784 return scrollValue;
2785
2786 itemExtent += spacing();
2787 QList<int> hiddenRows = dd->hiddenRowIds();
2788 std::sort(hiddenRows.begin(), hiddenRows.end());
2789 int hiddenRowsBefore = 0;
2790 for (int i = 0; i < hiddenRows.size() - 1; ++i)
2791 if (hiddenRows.at(i) > index + hiddenRowsBefore)
2792 break;
2793 else
2794 ++hiddenRowsBefore;
2795 if (!wrap) {
2796 int topIndex = index;
2797 const int bottomIndex = topIndex;
2798 const int bottomCoordinate = flowPositions.at(index + hiddenRowsBefore);
2799 while (topIndex > 0 &&
2800 (bottomCoordinate - flowPositions.at(topIndex + hiddenRowsBefore - 1) + itemExtent) <= (viewportSize)) {
2801 topIndex--;
2802 // will the next one be a hidden row -> skip
2803 while (hiddenRowsBefore > 0 && hiddenRows.at(hiddenRowsBefore - 1) >= topIndex + hiddenRowsBefore - 1)
2804 hiddenRowsBefore--;
2805 }
2806
2807 const int itemCount = bottomIndex - topIndex + 1;
2808 switch (hint) {
2810 return index;
2812 return index - itemCount + 1;
2814 return index - (itemCount / 2);
2815 default:
2816 break;
2817 }
2818 } else { // wrapping
2819 Qt::Orientation flowOrientation = (flow() == QListView::LeftToRight
2821 if (flowOrientation == orientation) { // scrolling in the "flow" direction
2822 // ### wrapped scrolling in the flow direction
2823 return flowPositions.at(index + hiddenRowsBefore); // ### always pixel based for now
2824 } else if (!segmentStartRows.isEmpty()) { // we are scrolling in the "segment" direction
2825 int segment = qBinarySearch<int>(segmentStartRows, index, 0, segmentStartRows.size() - 1);
2826 int leftSegment = segment;
2827 const int rightSegment = leftSegment;
2828 const int bottomCoordinate = segmentPositions.at(segment);
2829
2830 while (leftSegment > scrollValue &&
2831 (bottomCoordinate - segmentPositions.at(leftSegment-1) + itemExtent) <= (viewportSize)) {
2832 leftSegment--;
2833 }
2834
2835 const int segmentCount = rightSegment - leftSegment + 1;
2836 switch (hint) {
2838 return segment;
2840 return segment - segmentCount + 1;
2842 return segment - (segmentCount / 2);
2843 default:
2844 break;
2845 }
2846 }
2847 }
2848 return scrollValue;
2849}
2850
2861
2862/*
2863 * IconMode ListView Implementation
2864*/
2865
2867{
2868 if (index.row() >= items.size())
2869 return;
2870 const QSize oldContents = contentsSize;
2871 qq->update(index); // update old position
2872 moveItem(index.row(), position);
2873 qq->update(index); // update new position
2874
2875 if (contentsSize != oldContents)
2876 dd->viewUpdateGeometries(); // update the scroll bars
2877}
2878
2880{
2881 if (row >= 0 && row < items.size()) //remove item
2882 tree.removeLeaf(items.at(row).rect(), row);
2884}
2885
2887{
2889 if (row >= 0 && row < items.size()) //insert item
2890 tree.insertLeaf(items.at(row).rect(), row);
2891}
2892
2893#if QT_CONFIG(draganddrop)
2894bool QIconModeViewBase::filterStartDrag(Qt::DropActions supportedActions)
2895{
2896 // This function does the same thing as in QAbstractItemView::startDrag(),
2897 // plus adding viewitems to the draggedItems list.
2898 // We need these items to draw the drag items
2900 if (indexes.size() > 0 ) {
2901 if (viewport()->acceptDrops()) {
2903 for (; it != indexes.constEnd(); ++it)
2905 && (*it).column() == dd->column)
2907 }
2908
2909 QRect rect;
2910 QPixmap pixmap = dd->renderToPixmap(indexes, &rect);
2911 rect.adjust(horizontalOffset(), verticalOffset(), 0, 0);
2912 QDrag *drag = new QDrag(qq);
2913 drag->setMimeData(dd->model->mimeData(indexes));
2914 drag->setPixmap(pixmap);
2915 drag->setHotSpot(dd->pressedPosition - rect.topLeft());
2916 dd->dropEventMoved = false;
2917 Qt::DropAction action = drag->exec(supportedActions, dd->defaultDropAction);
2919 // delete item, unless it has already been moved internally (see filterDropEvent)
2920 if (action == Qt::MoveAction && !dd->dropEventMoved) {
2921 if (dd->dragDropMode != QAbstractItemView::InternalMove || drag->target() == qq->viewport())
2922 dd->clearOrRemove();
2923 }
2924 dd->dropEventMoved = false;
2925 }
2926 return true;
2927}
2928
2929bool QIconModeViewBase::filterDropEvent(QDropEvent *e)
2930{
2931 if (e->source() != qq)
2932 return false;
2933
2934 const QSize contents = contentsSize;
2936 QPoint end = e->position().toPoint() + offset;
2937 if (qq->acceptDrops()) {
2938 const Qt::ItemFlags dropableFlags = Qt::ItemIsDropEnabled|Qt::ItemIsEnabled;
2939 const QList<QModelIndex> &dropIndices = intersectingSet(QRect(end, QSize(1, 1)));
2940 for (const QModelIndex &index : dropIndices)
2941 if ((index.flags() & dropableFlags) == dropableFlags)
2942 return false;
2943 }
2945 QPoint delta = (dd->movement == QListView::Snap ? snapToGrid(end) - snapToGrid(start) : end - start);
2946 const QList<QModelIndex> indexes = dd->selectionModel->selectedIndexes();
2947 for (const auto &index : indexes) {
2949 viewport()->update(dd->mapToViewport(rect, false));
2950 QPoint dest = rect.topLeft() + delta;
2951 if (qq->isRightToLeft())
2952 dest.setX(dd->flipX(dest.x()) - rect.width());
2953 moveItem(index.row(), dest);
2954 qq->update(index);
2955 }
2956 dd->stopAutoScroll();
2958 dd->emitIndexesMoved(indexes);
2959 // do not delete item on internal move, see filterStartDrag()
2960 dd->dropEventMoved = true;
2961 e->accept(); // we have handled the event
2962 // if the size has not grown, we need to check if it has shrunk
2963 if (contentsSize != contents) {
2964 if ((contentsSize.width() <= contents.width()
2965 || contentsSize.height() <= contents.height())) {
2966 updateContentsSize();
2967 }
2969 }
2970 return true;
2971}
2972
2973bool QIconModeViewBase::filterDragLeaveEvent(QDragLeaveEvent *e)
2974{
2975 viewport()->update(draggedItemsRect()); // erase the area
2976 draggedItemsPos = QPoint(-1, -1); // don't draw the dragged items
2977 return QCommonListViewBase::filterDragLeaveEvent(e);
2978}
2979
2980bool QIconModeViewBase::filterDragMoveEvent(QDragMoveEvent *e)
2981{
2982 const bool wasAccepted = e->isAccepted();
2983
2984 // ignore by default
2985 e->ignore();
2986
2987 if (e->source() != qq || !dd->canDrop(e)) {
2988 // restore previous acceptance on failure
2989 e->setAccepted(wasAccepted);
2990 return false;
2991 }
2992
2993 // get old dragged items rect
2994 QRect itemsRect = this->itemsRect(draggedItems);
2995 viewport()->update(itemsRect.translated(draggedItemsDelta()));
2996 // update position
2997 draggedItemsPos = e->position().toPoint();
2998 // get new items rect
2999 viewport()->update(itemsRect.translated(draggedItemsDelta()));
3000 // set the item under the cursor to current
3002 if (movement() == QListView::Snap) {
3003 QRect rect(snapToGrid(e->position().toPoint() + offset()), gridSize());
3004 const QList<QModelIndex> intersectVector = intersectingSet(rect);
3005 index = intersectVector.size() > 0 ? intersectVector.last() : QModelIndex();
3006 } else {
3007 index = qq->indexAt(e->position().toPoint());
3008 }
3009 // check if we allow drops here
3011 e->accept(); // allow changing item position
3013 e->accept(); // allow dropping on dropenabled items
3014 else if (!index.isValid())
3015 e->accept(); // allow dropping in empty areas
3016
3017 // the event was treated. do autoscrolling
3018 if (dd->shouldAutoScroll(e->position().toPoint()))
3020 return true;
3021}
3022#endif // QT_CONFIG(draganddrop)
3023
3025{
3027}
3028
3029void QIconModeViewBase::scrollContentsBy(int dx, int dy, bool scrollElasticBand)
3030{
3031 if (scrollElasticBand)
3032 dd->scrollElasticBandBy(isRightToLeft() ? -dx : dx, dy);
3033
3034 QCommonListViewBase::scrollContentsBy(dx, dy, scrollElasticBand);
3035 if (!draggedItems.isEmpty())
3036 viewport()->update(draggedItemsRect().translated(dx, dy));
3037}
3038
3039void QIconModeViewBase::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
3040{
3041 if (column() >= topLeft.column() && column() <= bottomRight.column()) {
3042 QStyleOptionViewItem option;
3044 const int bottom = qMin(items.size(), bottomRight.row() + 1);
3045 const bool useItemSize = !dd->grid.isValid();
3046 for (int row = topLeft.row(); row < bottom; ++row)
3047 {
3049 if (!useItemSize)
3050 {
3051 s.setWidth(qMin(dd->grid.width(), s.width()));
3052 s.setHeight(qMin(dd->grid.height(), s.height()));
3053 }
3054 items[row].resize(s);
3055 }
3056 }
3057}
3058
3060{
3061 if (info.last >= items.size()) {
3062 //first we create the items
3063 QStyleOptionViewItem option;
3065 for (int row = items.size(); row <= info.last; ++row) {
3067 QListViewItem item(QRect(0, 0, size.width(), size.height()), row); // default pos
3068 items.append(item);
3069 }
3070 doDynamicLayout(info);
3071 }
3072 return (batchStartRow > max); // done
3073}
3074
3076{
3077 if (index.isValid() && index.row() < items.size())
3078 return items.at(index.row());
3079 return QListViewItem();
3080}
3081
3082void QIconModeViewBase::initBspTree(const QSize &contents)
3083{
3084 // remove all items from the tree
3085 int leafCount = tree.leafCount();
3086 for (int l = 0; l < leafCount; ++l)
3087 tree.leaf(l).clear();
3088 // we have to get the bounding rect of the items before we can initialize the tree
3090 // simple heuristics to get better bsp
3091 if (contents.height() / contents.width() >= 3)
3093 else if (contents.width() / contents.height() >= 3)
3095 // build tree for the bounding rect (not just the contents rect)
3096 tree.init(QRect(0, 0, contents.width(), contents.height()), type);
3097}
3098
3099QPoint QIconModeViewBase::initDynamicLayout(const QListViewLayoutInfo &info)
3100{
3101 int x, y;
3102 if (info.first == 0) {
3103 x = info.bounds.x() + info.spacing;
3104 y = info.bounds.y() + info.spacing;
3106 } else {
3107 int idx = info.first - 1;
3108 while (idx > 0 && !items.at(idx).isValid())
3109 --idx;
3110 const QListViewItem &item = items.at(idx);
3111 x = item.x;
3112 y = item.y;
3113 if (info.flow == QListView::LeftToRight)
3114 x += (info.grid.isValid() ? info.grid.width() : item.w) + info.spacing;
3115 else
3116 y += (info.grid.isValid() ? info.grid.height() : item.h) + info.spacing;
3117 }
3118 return QPoint(x, y);
3119}
3120
3124void QIconModeViewBase::doDynamicLayout(const QListViewLayoutInfo &info)
3125{
3126 const bool useItemSize = !info.grid.isValid();
3127 const QPoint topLeft = initDynamicLayout(info);
3128
3129 int segStartPosition;
3130 int segEndPosition;
3131 int deltaFlowPosition;
3132 int deltaSegPosition;
3133 int deltaSegHint;
3134 int flowPosition;
3135 int segPosition;
3136
3137 if (info.flow == QListView::LeftToRight) {
3138 segStartPosition = info.bounds.left() + info.spacing;
3139 segEndPosition = info.bounds.right();
3140 deltaFlowPosition = info.grid.width(); // dx
3141 deltaSegPosition = (useItemSize ? batchSavedDeltaSeg : info.grid.height()); // dy
3142 deltaSegHint = info.grid.height();
3143 flowPosition = topLeft.x();
3144 segPosition = topLeft.y();
3145 } else { // flow == QListView::TopToBottom
3146 segStartPosition = info.bounds.top() + info.spacing;
3147 segEndPosition = info.bounds.bottom();
3148 deltaFlowPosition = info.grid.height(); // dy
3149 deltaSegPosition = (useItemSize ? batchSavedDeltaSeg : info.grid.width()); // dx
3150 deltaSegHint = info.grid.width();
3151 flowPosition = topLeft.y();
3152 segPosition = topLeft.x();
3153 }
3154
3155 if (moved.size() != items.size())
3157
3158 QRect rect(QPoint(), topLeft);
3159 QListViewItem *item = nullptr;
3160 Q_ASSERT(info.first <= info.last);
3161 for (int row = info.first; row <= info.last; ++row) {
3162 item = &items[row];
3163 if (isHidden(row)) {
3164 item->invalidate();
3165 } else {
3166 // if we are not using a grid, we need to find the deltas
3167 if (useItemSize) {
3168 if (info.flow == QListView::LeftToRight)
3169 deltaFlowPosition = item->w + info.spacing;
3170 else
3171 deltaFlowPosition = item->h + info.spacing;
3172 } else {
3173 item->w = qMin<int>(info.grid.width(), item->w);
3174 item->h = qMin<int>(info.grid.height(), item->h);
3175 }
3176
3177 // create new segment
3178 if (info.wrap
3179 && flowPosition + deltaFlowPosition > segEndPosition
3180 && flowPosition > segStartPosition) {
3181 flowPosition = segStartPosition;
3182 segPosition += deltaSegPosition;
3183 if (useItemSize)
3184 deltaSegPosition = 0;
3185 }
3186 // We must delay calculation of the seg adjustment, as this item
3187 // may have caused a wrap to occur
3188 if (useItemSize) {
3189 if (info.flow == QListView::LeftToRight)
3190 deltaSegHint = item->h + info.spacing;
3191 else
3192 deltaSegHint = item->w + info.spacing;
3193 deltaSegPosition = qMax(deltaSegPosition, deltaSegHint);
3194 }
3195
3196 // set the position of the item
3197 // ### idealy we should have some sort of alignment hint for the item
3198 // ### (normally that would be a point between the icon and the text)
3199 if (!moved.testBit(row)) {
3200 if (info.flow == QListView::LeftToRight) {
3201 if (useItemSize) {
3202 item->x = flowPosition;
3203 item->y = segPosition;
3204 } else { // use grid
3205 item->x = flowPosition + ((deltaFlowPosition - item->w) / 2);
3206 item->y = segPosition;
3207 }
3208 } else { // TopToBottom
3209 if (useItemSize) {
3210 item->y = flowPosition;
3211 item->x = segPosition;
3212 } else { // use grid
3213 item->y = flowPosition + ((deltaFlowPosition - item->h) / 2);
3214 item->x = segPosition;
3215 }
3216 }
3217 }
3218
3219 // let the contents contain the new item
3220 if (useItemSize)
3221 rect |= item->rect();
3222 else if (info.flow == QListView::LeftToRight)
3223 rect |= QRect(flowPosition, segPosition, deltaFlowPosition, deltaSegPosition);
3224 else // flow == TopToBottom
3225 rect |= QRect(segPosition, flowPosition, deltaSegPosition, deltaFlowPosition);
3226
3227 // prepare for next item
3228 flowPosition += deltaFlowPosition; // current position + item width + gap
3229 }
3230 }
3231 Q_ASSERT(item);
3232 batchSavedDeltaSeg = deltaSegPosition;
3233 batchStartRow = info.last + 1;
3234 bool done = (info.last >= rowCount() - 1);
3235 // resize the content area
3236 if (done || !info.bounds.contains(item->rect())) {
3237 contentsSize = rect.size();
3238 if (info.flow == QListView::LeftToRight)
3239 contentsSize.rheight() += info.spacing;
3240 else
3241 contentsSize.rwidth() += info.spacing;
3242 }
3243 if (rect.size().isEmpty())
3244 return;
3245 // resize tree
3246 int insertFrom = info.first;
3247 if (done || info.first == 0) {
3248 initBspTree(rect.size());
3249 insertFrom = 0;
3250 }
3251 // insert items in tree
3252 for (int row = insertFrom; row <= info.last; ++row)
3253 tree.insertLeaf(items.at(row).rect(), row);
3254 // if the new items are visible, update the viewport
3255 QRect changedRect(topLeft, rect.bottomRight());
3256 if (clipRect().intersects(changedRect))
3257 viewport()->update();
3258}
3259
3260QList<QModelIndex> QIconModeViewBase::intersectingSet(const QRect &area) const
3261{
3262 QIconModeViewBase *that = const_cast<QIconModeViewBase*>(this);
3263 QBspTree::Data data(static_cast<void*>(that));
3264 QList<QModelIndex> res;
3265 that->interSectingVector = &res;
3266 that->tree.climbTree(area, &QIconModeViewBase::addLeaf, data);
3267 that->interSectingVector = nullptr;
3268 return res;
3269}
3270
3271QRect QIconModeViewBase::itemsRect(const QList<QModelIndex> &indexes) const
3272{
3273 QRect rect;
3274 for (const auto &index : indexes)
3276 return rect;
3277}
3278
3280{
3281 if (!item.isValid())
3282 return -1;
3283 int i = item.indexHint;
3284 if (i < items.size()) {
3285 if (items.at(i) == item)
3286 return i;
3287 } else {
3288 i = items.size() - 1;
3289 }
3290
3291 int j = i;
3292 int c = items.size();
3293 bool a = true;
3294 bool b = true;
3295
3296 while (a || b) {
3297 if (a) {
3298 if (items.at(i) == item) {
3299 items.at(i).indexHint = i;
3300 return i;
3301 }
3302 a = ++i < c;
3303 }
3304 if (b) {
3305 if (items.at(j) == item) {
3306 items.at(j).indexHint = j;
3307 return j;
3308 }
3309 b = --j > -1;
3310 }
3311 }
3312 return -1;
3313}
3314
3315void QIconModeViewBase::addLeaf(QList<int> &leaf, const QRect &area, uint visited,
3317{
3318 QListViewItem *vi;
3319 QIconModeViewBase *_this = static_cast<QIconModeViewBase *>(data.ptr);
3320 for (int i = 0; i < leaf.size(); ++i) {
3321 int idx = leaf.at(i);
3322 if (idx < 0 || idx >= _this->items.size())
3323 continue;
3324 vi = &_this->items[idx];
3325 Q_ASSERT(vi);
3326 if (vi->isValid() && vi->rect().intersects(area) && vi->visited != visited) {
3327 QModelIndex index = _this->dd->listViewItemToIndex(*vi);
3328 Q_ASSERT(index.isValid());
3329 _this->interSectingVector->append(index);
3330 vi->visited = visited;
3331 }
3332 }
3333}
3334
3335void QIconModeViewBase::moveItem(int index, const QPoint &dest)
3336{
3337 // does not impact on the bintree itself or the contents rect
3339 QRect rect = item->rect();
3340
3341 // move the item without removing it from the tree
3343 item->move(dest);
3344 tree.insertLeaf(QRect(dest, rect.size()), index);
3345
3346 // resize the contents area
3347 contentsSize = (QRect(QPoint(0, 0), contentsSize)|QRect(dest, rect.size())).size();
3348
3349 // mark the item as moved
3350 if (moved.size() != items.size())
3352 moved.setBit(index, true);
3353}
3354
3355QPoint QIconModeViewBase::snapToGrid(const QPoint &pos) const
3356{
3357 int x = pos.x() - (pos.x() % gridSize().width());
3358 int y = pos.y() - (pos.y() % gridSize().height());
3359 return QPoint(x, y);
3360}
3361
3362QPoint QIconModeViewBase::draggedItemsDelta() const
3363{
3364 if (movement() == QListView::Snap) {
3365 QPoint snapdelta = QPoint((offset().x() % gridSize().width()),
3366 (offset().y() % gridSize().height()));
3367 return snapToGrid(draggedItemsPos + snapdelta) - snapToGrid(pressedPosition()) - snapdelta;
3368 }
3370}
3371
3372QRect QIconModeViewBase::draggedItemsRect() const
3373{
3374 QRect rect = itemsRect(draggedItems);
3375 rect.translate(draggedItemsDelta());
3376 return rect;
3377}
3378
3380{
3381 if (dx > 0) // right
3383 else if (dx < 0) // left
3385 if (dy > 0) // down
3387 else if (dy < 0) // up
3389}
3390
3392{
3393 tree.destroy();
3394 items.clear();
3395 moved.clear();
3396 batchStartRow = 0;
3398}
3399
3400void QIconModeViewBase::updateContentsSize()
3401{
3402 QRect bounding;
3403 for (int i = 0; i < items.size(); ++i)
3404 bounding |= items.at(i).rect();
3405 contentsSize = bounding.size();
3406}
3407
3411void QListView::currentChanged(const QModelIndex &current, const QModelIndex &previous)
3412{
3413 QAbstractItemView::currentChanged(current, previous);
3414#if QT_CONFIG(accessibility)
3415 if (QAccessible::isActive()) {
3416 if (current.isValid() && hasFocus()) {
3417 int entry = visualIndex(current);
3418 QAccessibleEvent event(this, QAccessible::Focus);
3419 event.setChild(entry);
3420 QAccessible::updateAccessibility(&event);
3421 }
3422 }
3423#endif
3424}
3425
3430 const QItemSelection &deselected)
3431{
3432#if QT_CONFIG(accessibility)
3433 if (QAccessible::isActive()) {
3434 // ### does not work properly for selection ranges.
3435 QModelIndex sel = selected.indexes().value(0);
3436 if (sel.isValid()) {
3437 int entry = visualIndex(sel);
3438 QAccessibleEvent event(this, QAccessible::SelectionAdd);
3439 event.setChild(entry);
3440 QAccessible::updateAccessibility(&event);
3441 }
3442 QModelIndex desel = deselected.indexes().value(0);
3443 if (desel.isValid()) {
3444 int entry = visualIndex(desel);
3445 QAccessibleEvent event(this, QAccessible::SelectionRemove);
3446 event.setChild(entry);
3447 QAccessible::updateAccessibility(&event);
3448 }
3449 }
3450#endif
3451 QAbstractItemView::selectionChanged(selected, deselected);
3452}
3453
3454int QListView::visualIndex(const QModelIndex &index) const
3455{
3456 Q_D(const QListView);
3457 d->executePostedLayout();
3458 QListViewItem itm = d->indexToListViewItem(index);
3459 int visualIndex = d->commonListView->itemIndex(itm);
3460 for (const auto &idx : std::as_const(d->hiddenRows)) {
3461 if (idx.row() <= index.row())
3462 --visualIndex;
3463 }
3464 return visualIndex;
3465}
3466
3467
3473{
3474 Q_D(const QListView);
3475 // We don't have a nice simple size hint for invalid or wrapping list views.
3476 if (!d->model)
3478 const int rc = d->model->rowCount();
3479 if (rc == 0 || isWrapping())
3481
3482 QStyleOptionViewItem option;
3484
3485 if (uniformItemSizes()) {
3486 QSize sz = d->cachedItemSize;
3487 if (!sz.isValid()) {
3488 QModelIndex idx = d->model->index(0, d->column, d->root);
3489 sz = d->itemSize(option, idx);
3490 }
3491 sz.setHeight(rc * sz.height());
3492 return sz;
3493 }
3494
3495 // Using AdjustToContents with a high number of rows will normally not make sense, so we limit
3496 // this to default 1000 (that is btw the default for QHeaderView::resizeContentsPrecision())
3497 // (By setting the property _q_resizeContentPrecision the user can however override this).
3498 int maximumRows = 1000;
3499 const QVariant userOverrideValue = property("_q_resizeContentPrecision");
3500 if (userOverrideValue.isValid() && userOverrideValue.toInt() > 0) {
3501 maximumRows = userOverrideValue.toInt();
3502 }
3503 const int rowCount = qMin(rc, maximumRows);
3504
3505 int h = 0;
3506 int w = 0;
3507
3508 for (int row = 0; row < rowCount; ++row) {
3509 QModelIndex idx = d->model->index(row, d->column, d->root);
3510 QSize itemSize = d->itemSize(option, idx);
3511 h += itemSize.height();
3512 w = qMax(w, itemSize.width());
3513 }
3514 return QSize(w, h);
3515}
3516
3518
3519#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 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:87
bool testBit(qsizetype i) const
Returns true if the bit at index position i is 1; otherwise returns false.
Definition qbitarray.h:89
void setBit(qsizetype i)
Sets the bit at index position i to 1.
Definition qbitarray.h:91
void resize(qsizetype size)
Resizes the bit array to size bits.
qsizetype size() const
Returns the number of bits stored in the bit array.
Definition qbitarray.h:76
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 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:148
Qt::DropAction exec(Qt::DropActions supportedActions=Qt::MoveAction)
Definition qdrag.cpp:201
void setMimeData(QMimeData *data)
Sets the data to be sent to the given MIME data.
Definition qdrag.cpp:101
void setPixmap(const QPixmap &)
Sets pixmap as the pixmap used to represent the data in a drag and drop operation.
Definition qdrag.cpp:125
QObject * target() const
Returns the target of the drag and drop operation.
Definition qdrag.cpp:178
\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
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
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 dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList< int > &roles=QList< int >()) 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 currentChanged(const QModelIndex &current, const QModelIndex &previous) override
\reimp
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)
void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) override
\reimp
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
void setRootIndex(const QModelIndex &index) 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 selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) override
\reimp
void rowsInserted(const QModelIndex &parent, int start, int end) override
\reimp
void doItemsLayout() override
qsizetype size() const noexcept
Definition qlist.h:397
bool isEmpty() const noexcept
Definition qlist.h:401
const T & constLast() const noexcept
Definition qlist.h:650
void push_back(parameter_type t)
Definition qlist.h:675
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
const_iterator constBegin() const noexcept
Definition qlist.h:632
void reserve(qsizetype size)
Definition qlist.h:753
void resize(qsizetype size)
Definition qlist.h:403
void append(parameter_type t)
Definition qlist.h:458
const_iterator constEnd() const noexcept
Definition qlist.h:633
void clear()
Definition qlist.h:434
const_iterator ConstIterator
Definition qlist.h:250
\inmodule QtCore
constexpr int row() const noexcept
Returns the row this model index refers to.
QModelIndex parent() const
Returns the parent of the model index, or QModelIndex() if it has no parent.
constexpr const QAbstractItemModel * model() const noexcept
Returns a pointer to the model containing the item that this 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:196
\inmodule QtCore
Definition qobject.h:103
The QPaintEvent class contains event parameters for paint events.
Definition qevent.h:486
const QRect & rect() const
Returns the rectangle that needs to be updated.
Definition qevent.h:492
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:49
@ Disabled
Definition qpalette.h:49
Returns a copy of the pixmap that is transformed using the given transformation transform and transfo...
Definition qpixmap.h:27
constexpr QPoint toPoint() const
Rounds the coordinates of this point to the nearest integer, and returns a QPoint object with the rou...
Definition qpoint.h:404
\inmodule QtCore\reentrant
Definition qpoint.h:25
constexpr int x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:130
constexpr int y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:135
constexpr void setX(int x) noexcept
Sets the x coordinate of this point to the given x coordinate.
Definition qpoint.h:140
\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:1069
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:373
constexpr void moveBottom(int pos) noexcept
Moves the rectangle vertically, leaving the rectangle's bottom edge at the given y coordinate.
Definition qrect.h:298
constexpr void moveRight(int pos) noexcept
Moves the rectangle horizontally, leaving the rectangle's right edge at the given x coordinate.
Definition qrect.h:292
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:239
QRect intersected(const QRect &other) const noexcept
Definition qrect.h:415
constexpr int bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
Definition qrect.h:182
constexpr void setRight(int pos) noexcept
Sets the right edge of the rectangle to the given x coordinate.
Definition qrect.h:197
constexpr void setSize(const QSize &s) noexcept
Sets the size of the rectangle to the given size.
Definition qrect.h:387
constexpr QRect adjusted(int x1, int y1, int x2, int y2) const noexcept
Returns a new rectangle with dx1, dy1, dx2 and dy2 added respectively to the existing coordinates of ...
Definition qrect.h:370
constexpr int top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:176
constexpr void moveLeft(int pos) noexcept
Moves the rectangle horizontally, leaving the rectangle's left edge at the given x coordinate.
Definition qrect.h:286
constexpr void setBottom(int pos) noexcept
Sets the bottom edge of the rectangle to the given y coordinate.
Definition qrect.h:200
constexpr void setLeft(int pos) noexcept
Sets the left edge of the rectangle to the given x coordinate.
Definition qrect.h:191
constexpr int left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:173
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:261
QRect united(const QRect &other) const noexcept
Definition qrect.h:420
constexpr void moveTop(int pos) noexcept
Moves the rectangle vertically, leaving the rectangle's top edge at the given y coordinate.
Definition qrect.h:289
constexpr int right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
Definition qrect.h:179
constexpr void setTop(int pos) noexcept
Sets the top edge of the rectangle to the given y coordinate.
Definition qrect.h:194
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:548
const QSize & oldSize() const
Returns the old size of the widget.
Definition qevent.h:554
const QSize & size() const
Returns the new size of the widget.
Definition qevent.h:553
bool remove(const T &value)
Definition qset.h:63
iterator begin()
Definition qset.h:136
iterator end()
Definition qset.h:140
const_iterator constBegin() const noexcept
Definition qset.h:139
void clear()
Definition qset.h:61
iterator erase(const_iterator i)
Definition qset.h:145
iterator insert(const T &value)
Definition qset.h:155
QPointF position() const
Returns the position of the point in this event, relative to the widget or item that received the eve...
Definition qevent.h:119
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:133
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
constexpr int & rheight() noexcept
Returns a reference to the height.
Definition qsize.h:157
constexpr int & rwidth() noexcept
Returns a reference to the width.
Definition qsize.h:154
constexpr bool isNull() const noexcept
Returns true if both the width and height is 0; otherwise returns false.
Definition qsize.h:121
constexpr void setHeight(int h) noexcept
Sets the height to the given height.
Definition qsize.h:139
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:127
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:602
@ CE_RubberBand
Definition qstyle.h:209
@ PM_ScrollBarExtent
Definition qstyle.h:426
@ PM_DefaultFrameWidth
Definition qstyle.h:420
@ PM_ScrollView_ScrollBarOverlap
Definition qstyle.h:526
@ PM_IconViewIconSize
Definition qstyle.h:494
@ PM_ListViewIconSize
Definition qstyle.h:493
@ PE_PanelItemViewRow
Definition qstyle.h:154
\inmodule QtCore
Definition qcoreevent.h:366
int timerId() const
Returns the unique timer identifier, which is the same identifier as returned from QObject::startTime...
Definition qcoreevent.h:370
\inmodule QtCore
Definition qvariant.h:65
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]
list append(new Employee("Blackpool", "Stephen"))
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
Definition qcompare.h:63
@ AlignRight
Definition qnamespace.h:146
@ AlignHCenter
Definition qnamespace.h:148
@ AlignHorizontal_Mask
Definition qnamespace.h:151
@ AlignCenter
Definition qnamespace.h:163
@ WA_MacShowFocusRect
Definition qnamespace.h:359
Orientation
Definition qnamespace.h:98
@ Horizontal
Definition qnamespace.h:99
@ Vertical
Definition qnamespace.h:100
@ ScrollBarAlwaysOff
@ ScrollBarAsNeeded
DropAction
@ CopyAction
@ MoveAction
@ ItemIsDragEnabled
@ ItemIsEnabled
@ ItemIsDropEnabled
QList< QModelIndex > QModelIndexList
QList< QItemViewPaintPair > QItemViewPaintPairs
#define Q_UNLIKELY(x)
static const QCssKnownValue positions[NumKnownPositionModes - 1]
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qt_sendSpontaneousEvent(QObject *, QEvent *)
static int area(const QSize &s)
Definition qicon.cpp:153
QT_BEGIN_NAMESPACE bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event)
#define qWarning
Definition qlogging.h:166
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
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
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
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
GLdouble s
[6]
Definition qopenglext.h:235
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]
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)
QT_BEGIN_NAMESPACE constexpr void qSwap(T &value1, T &value2) noexcept(std::is_nothrow_swappable_v< T >)
Definition qswap.h:20
static QFixed flowPosition(const QTextFrame::iterator &it)
#define Q_UNUSED(x)
unsigned int uint
Definition qtypes.h:34
const char property[13]
Definition qwizard.cpp:101
view show()
[18] //! [19]
if(qFloatDistance(a, b)<(1<< 7))
[0]
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
QHostInfo info
[0]
bool contains(const AT &t) const noexcept
Definition qlist.h:45