313void QSpanCollection::updateRemovedRows(
int start,
int end)
315#ifdef DEBUG_SPAN_UPDATE
316 qDebug() << start << end << Qt::endl << index;
321 SpanList spansToBeDeleted;
322 int delta = end - start + 1;
323#ifdef DEBUG_SPAN_UPDATE
326 for (SpanList::iterator it = spans.begin(); it != spans.end(); ) {
328#ifdef DEBUG_SPAN_UPDATE
329 qDebug() << span << *span;
331 if (span->m_bottom < start) {
335 if (span->m_top < start) {
336 if (span->m_bottom <= end)
337 span->m_bottom = start - 1;
339 span->m_bottom -= delta;
341 if (span->m_bottom > end) {
342 if (span->m_top <= end)
345 span->m_top -= delta;
346 span->m_bottom -= delta;
348 span->will_be_deleted =
true;
351 if (span->m_top == span->m_bottom && span->m_left == span->m_right)
352 span->will_be_deleted =
true;
353 if (span->will_be_deleted) {
354 spansToBeDeleted.push_back(span);
355 it = spans.erase(it);
361#ifdef DEBUG_SPAN_UPDATE
366 qDeleteAll(spansToBeDeleted);
371 Index::iterator it_y = index.end();
375 SubIndex &subindex = it_y.value();
377 if (cleanSpanSubIndex(subindex, y))
378 it_y = index.erase(it_y);
379 }
else if (y >= start && y <= end) {
380 bool span_at_start =
false;
381 SubIndex spansToBeMoved;
382 for (SubIndex::iterator it = subindex.begin(); it != subindex.end(); ++it) {
383 Span *span = it.value();
384 if (span->will_be_deleted)
386 if (!span_at_start && span->m_top == start)
387 span_at_start =
true;
388 spansToBeMoved.insert(it.key(), span);
391 if (y == start && span_at_start)
394 it_y = index.erase(it_y);
397 Index::iterator it_start;
401 it_start = index.find(-start);
402 if (it_start == index.end())
403 it_start = index.insert(-start, SubIndex());
405 SubIndex &start_subindex = it_start.value();
406 for (SubIndex::iterator it = spansToBeMoved.begin(); it != spansToBeMoved.end(); ++it)
407 start_subindex.insert(it.key(), it.value());
411 Index::iterator it_top = index.find(-y + delta);
412 if (it_top == index.end())
413 it_top = index.insert(-y + delta, SubIndex());
414 for (SubIndex::iterator it = subindex.begin(); it != subindex.end(); ) {
415 Span *span = it.value();
416 if (!span->will_be_deleted)
417 it_top.value().insert(it.key(), span);
421 index.insert(-y + delta, subindex);
423 it_y = index.erase(it_y);
425 }
while (it_y != index.begin());
427#ifdef DEBUG_SPAN_UPDATE
430 qDebug() << spansToBeDeleted;
432 qDeleteAll(spansToBeDeleted);
659QRect QTableViewPrivate::intersectedRect(
const QRect rect,
const QModelIndex &topLeft,
const QModelIndex &bottomRight)
const
661 Q_Q(
const QTableView);
663 using minMaxPair = std::pair<
int,
int>;
664 const auto calcMinMax = [q](QHeaderView *hdr,
int startIdx,
int endIdx, minMaxPair bounds) -> minMaxPair
666 minMaxPair ret(std::numeric_limits<
int>::max(), std::numeric_limits<
int>::min());
667 if (hdr->sectionsMoved()) {
668 for (
int i = startIdx; i <= endIdx; ++i) {
669 const int start = hdr->sectionViewportPosition(i);
670 const int end = start + hdr->sectionSize(i);
671 ret.first = std::min(start, ret.first);
672 ret.second = std::max(end, ret.second);
673 if (ret.first <= bounds.first && ret.second >= bounds.second)
677 if (q->isRightToLeft() && q->horizontalHeader() == hdr)
678 std::swap(startIdx, endIdx);
679 ret.first = hdr->sectionViewportPosition(startIdx);
680 ret.second = hdr->sectionViewportPosition(endIdx) +
681 hdr->sectionSize(endIdx);
686 const auto yVals = calcMinMax(verticalHeader, topLeft.row(), bottomRight.row(),
687 minMaxPair(rect.top(), rect.bottom()));
688 if (yVals.first == yVals.second)
692 const QRect colRect(QPoint(rect.left(), yVals.first),
693 QPoint(rect.right(), yVals.second));
694 const QRect intersected = rect.intersected(colRect);
695 if (intersected.isNull())
698 const auto xVals = calcMinMax(horizontalHeader, topLeft.column(), bottomRight.column(),
699 minMaxPair(rect.left(), rect.right()));
700 const QRect updateRect(QPoint(xVals.first, yVals.first),
701 QPoint(xVals.second, yVals.second));
702 return rect.intersected(updateRect);
892void QTableViewPrivate::drawAndClipSpans(
const QRegion &area, QPainter *painter,
893 const QStyleOptionViewItem &option, QBitArray *drawn,
894 int firstVisualRow,
int lastVisualRow,
int firstVisualColumn,
int lastVisualColumn)
896 Q_Q(
const QTableView);
897 bool alternateBase =
false;
898 QRegion region = viewport->rect();
900 QSet<QSpanCollection::Span *> visibleSpans;
901 bool sectionMoved = verticalHeader->sectionsMoved() || horizontalHeader->sectionsMoved();
904 visibleSpans = spans.spansInRect(logicalColumn(firstVisualColumn), logicalRow(firstVisualRow),
905 lastVisualColumn - firstVisualColumn + 1, lastVisualRow - firstVisualRow + 1);
920 const auto spanList = spans.spans;
921 for (QSpanCollection::Span *span : spanList) {
922 const int spanVisualLeft = visualColumn(span->left());
923 const int spanVisualTop = visualRow(span->top());
924 const int spanVisualRight = spanVisualLeft + span->width() - 1;
925 const int spanVisualBottom = spanVisualTop + span->height() - 1;
926 if ((spanVisualLeft <= lastVisualColumn && spanVisualRight >= firstVisualColumn)
927 && (spanVisualTop <= lastVisualRow && spanVisualBottom >= firstVisualRow))
928 visibleSpans.insert(span);
932 for (QSpanCollection::Span *span : std::as_const(visibleSpans)) {
933 int row = span->top();
934 int col = span->left();
935 QModelIndex index = model->index(row, col, root);
936 if (!index.isValid())
938 QRect rect = visualSpanRect(*span);
939 rect.translate(scrollDelayOffset);
940 if (!area.intersects(rect))
942 QStyleOptionViewItem opt = option;
944 alternateBase = alternatingColors && (span->top() & 1);
945 opt.features.setFlag(QStyleOptionViewItem::Alternate, alternateBase);
946 drawCell(painter, opt, index);
950 if (horizontalHeader->visualIndex(row) == 0)
951 rect.setTop(rect.top() + 1);
952 if (verticalHeader->visualIndex(row) == 0) {
953 if (q->isLeftToRight())
954 rect.setLeft(rect.left() + 1);
956 rect.setRight(rect.right() - 1);
960 for (
int r = span->top(); r <= span->bottom(); ++r) {
961 const int vr = visualRow(r);
962 if (vr < firstVisualRow || vr > lastVisualRow)
964 for (
int c = span->left(); c <= span->right(); ++c) {
965 const int vc = visualColumn(c);
966 if (vc < firstVisualColumn || vc > lastVisualColumn)
968 drawn->setBit((vr - firstVisualRow) * (lastVisualColumn - firstVisualColumn + 1)
969 + vc - firstVisualColumn);
974 painter->setClipRegion(region);
1390void QTableView::setHorizontalHeader(QHeaderView *header)
1394 if (!header || header == d->horizontalHeader)
1396 for (
const QMetaObject::Connection &connection : d->horHeaderConnections)
1397 disconnect(connection);
1398 if (d->horizontalHeader && d->horizontalHeader->parent() ==
this)
1399 delete d->horizontalHeader;
1400 d->horizontalHeader = header;
1401 d->horizontalHeader->setParent(
this);
1402 d->horizontalHeader->setFirstSectionMovable(
true);
1403 if (!d->horizontalHeader->model()) {
1404 d->horizontalHeader->setModel(d->model);
1405 if (d->selectionModel)
1406 d->horizontalHeader->setSelectionModel(d->selectionModel);
1409 d->horHeaderConnections = {
1410 connect(d->horizontalHeader,&QHeaderView::sectionResized,
1411 this, &QTableView::columnResized),
1412 connect(d->horizontalHeader, &QHeaderView::sectionMoved,
1413 this, &QTableView::columnMoved),
1414 connect(d->horizontalHeader, &QHeaderView::sectionCountChanged,
1415 this, &QTableView::columnCountChanged),
1416 connect(d->horizontalHeader, &QHeaderView::sectionHandleDoubleClicked,
1417 this, &QTableView::resizeColumnToContents),
1418 connect(d->horizontalHeader, &QHeaderView::geometriesChanged,
1419 this, &QTableView::updateGeometries),
1422 setSortingEnabled(d->sortingEnabled);
1430void QTableView::setVerticalHeader(QHeaderView *header)
1434 if (!header || header == d->verticalHeader)
1436 for (
const QMetaObject::Connection &connection : d->verHeaderConnections)
1437 disconnect(connection);
1438 if (d->verticalHeader && d->verticalHeader->parent() ==
this)
1439 delete d->verticalHeader;
1440 d->verticalHeader = header;
1441 d->verticalHeader->setParent(
this);
1442 d->verticalHeader->setFirstSectionMovable(
true);
1443 if (!d->verticalHeader->model()) {
1444 d->verticalHeader->setModel(d->model);
1445 if (d->selectionModel)
1446 d->verticalHeader->setSelectionModel(d->selectionModel);
1449 d->verHeaderConnections = {
1450 connect(d->verticalHeader, &QHeaderView::sectionResized,
1451 this, &QTableView::rowResized),
1452 connect(d->verticalHeader, &QHeaderView::sectionMoved,
1453 this, &QTableView::rowMoved),
1454 connect(d->verticalHeader, &QHeaderView::sectionCountChanged,
1455 this, &QTableView::rowCountChanged),
1456 connect(d->verticalHeader, &QHeaderView::sectionPressed,
1457 this, &QTableView::selectRow),
1458 connect(d->verticalHeader, &QHeaderView::sectionHandleDoubleClicked,
1459 this, &QTableView::resizeRowToContents),
1460 connect(d->verticalHeader, &QHeaderView::geometriesChanged,
1461 this, &QTableView::updateGeometries),
1462 connect(d->verticalHeader, &QHeaderView::sectionEntered,
1463 this, [d](
int row) { d->selectRow(row,
false); })
1522void QTableView::paintEvent(QPaintEvent *event)
1526 QStyleOptionViewItem option;
1527 initViewItemOption(&option);
1528 const QPoint offset = d->scrollDelayOffset;
1529 const bool showGrid = d->showGrid;
1530 const int gridSize = showGrid ? 1 : 0;
1531 const int gridHint = style()->styleHint(QStyle::SH_Table_GridLineColor, &option,
this);
1532 const QColor gridColor = QColor::fromRgba(
static_cast<QRgb>(gridHint));
1533 const QPen gridPen = QPen(gridColor, 1, d->gridStyle);
1534 const QHeaderView *verticalHeader = d->verticalHeader;
1535 const QHeaderView *horizontalHeader = d->horizontalHeader;
1536 const bool alternate = d->alternatingColors;
1537 const bool rightToLeft = isRightToLeft();
1539 QPainter painter(d->viewport);
1542 if (horizontalHeader->count() == 0 || verticalHeader->count() == 0 || !d->itemDelegate)
1545 const int x = horizontalHeader->length() - horizontalHeader->offset() - (rightToLeft ? 0 : 1);
1546 const int y = verticalHeader->length() - verticalHeader->offset() - 1;
1550 int firstVisualRow = qMax(verticalHeader->visualIndexAt(0),0);
1551 int lastVisualRow = verticalHeader->visualIndexAt(verticalHeader->height());
1552 if (lastVisualRow == -1)
1553 lastVisualRow = d->model->rowCount(d->root) - 1;
1555 int firstVisualColumn = horizontalHeader->visualIndexAt(0);
1556 int lastVisualColumn = horizontalHeader->visualIndexAt(horizontalHeader->width());
1558 qSwap(firstVisualColumn, lastVisualColumn);
1559 if (firstVisualColumn == -1)
1560 firstVisualColumn = 0;
1561 if (lastVisualColumn == -1)
1562 lastVisualColumn = horizontalHeader->count() - 1;
1564 QBitArray drawn((lastVisualRow - firstVisualRow + 1) * (lastVisualColumn - firstVisualColumn + 1));
1566 const QRegion region = event->region().translated(offset);
1568 if (d->hasSpans()) {
1569 d->drawAndClipSpans(region, &painter, option, &drawn,
1570 firstVisualRow, lastVisualRow, firstVisualColumn, lastVisualColumn);
1573 for (QRect dirtyArea : region) {
1574 dirtyArea.setBottom(qMin(dirtyArea.bottom(),
int(y)));
1576 dirtyArea.setLeft(qMax(dirtyArea.left(), d->viewport->width() -
int(x)));
1578 dirtyArea.setRight(qMin(dirtyArea.right(),
int(x)));
1581 if (!dirtyArea.isValid())
1585 int left = horizontalHeader->visualIndexAt(dirtyArea.left());
1586 int right = horizontalHeader->visualIndexAt(dirtyArea.right());
1589 if (left == -1) left = 0;
1590 if (right == -1) right = horizontalHeader->count() - 1;
1593 int bottom = verticalHeader->visualIndexAt(dirtyArea.bottom());
1594 if (bottom == -1) bottom = verticalHeader->count() - 1;
1596 bool alternateBase =
false;
1597 if (alternate && verticalHeader->sectionsHidden()) {
1598 const int verticalOffset = verticalHeader->offset();
1599 int row = verticalHeader->logicalIndex(top);
1601 ((y += verticalHeader->sectionSize(top)) <= verticalOffset) && (top < bottom);
1603 row = verticalHeader->logicalIndex(top);
1604 if (alternate && !verticalHeader->isSectionHidden(row))
1605 alternateBase = !alternateBase;
1608 top = verticalHeader->visualIndexAt(dirtyArea.top());
1609 alternateBase = (top & 1) && alternate;
1611 if (top == -1 || top > bottom)
1615 for (
int visualRowIndex = top; visualRowIndex <= bottom; ++visualRowIndex) {
1616 int row = verticalHeader->logicalIndex(visualRowIndex);
1617 if (verticalHeader->isSectionHidden(row))
1619 int rowY = rowViewportPosition(row);
1621 int rowh = rowHeight(row) - gridSize;
1624 for (
int visualColumnIndex = left; visualColumnIndex <= right; ++visualColumnIndex) {
1625 int currentBit = (visualRowIndex - firstVisualRow) * (lastVisualColumn - firstVisualColumn + 1)
1626 + visualColumnIndex - firstVisualColumn;
1628 if (currentBit < 0 || currentBit >= drawn.size() || drawn.testBit(currentBit))
1630 drawn.setBit(currentBit);
1632 int col = horizontalHeader->logicalIndex(visualColumnIndex);
1633 if (horizontalHeader->isSectionHidden(col))
1635 int colp = columnViewportPosition(col);
1637 int colw = columnWidth(col) - gridSize;
1639 const QModelIndex index = d->model->index(row, col, d->root);
1640 if (index.isValid()) {
1641 option.rect = QRect(colp + (showGrid && rightToLeft ? 1 : 0), rowY, colw, rowh);
1644 option.features |= QStyleOptionViewItem::Alternate;
1646 option.features &= ~QStyleOptionViewItem::Alternate;
1648 d->drawCell(&painter, option, index);
1651 alternateBase = !alternateBase && alternate;
1656 while (verticalHeader->isSectionHidden(verticalHeader->logicalIndex(bottom))) --bottom;
1657 QPen old = painter.pen();
1658 painter.setPen(gridPen);
1660 for (
int visualIndex = top; visualIndex <= bottom; ++visualIndex) {
1661 int row = verticalHeader->logicalIndex(visualIndex);
1662 if (verticalHeader->isSectionHidden(row))
1664 int rowY = rowViewportPosition(row);
1666 int rowh = rowHeight(row) - gridSize;
1667 QLineF line(dirtyArea.left(), rowY + rowh, dirtyArea.right(), rowY + rowh);
1668 painter.drawLine(line.translated(0.5, 0.5));
1672 for (
int h = left; h <= right; ++h) {
1673 int col = horizontalHeader->logicalIndex(h);
1674 if (horizontalHeader->isSectionHidden(col))
1676 int colp = columnViewportPosition(col);
1679 colp += columnWidth(col) - gridSize;
1680 QLineF line(colp, dirtyArea.top(), colp, dirtyArea.bottom());
1681 painter.drawLine(line.translated(0.5, 0.5));
1683 const bool drawWhenHidden = style()->styleHint(QStyle::SH_Table_AlwaysDrawLeftTopGridLines,
1685 if (drawWhenHidden && horizontalHeader->isHidden()) {
1686 const int row = verticalHeader->logicalIndex(top);
1687 if (!verticalHeader->isSectionHidden(row)) {
1688 const int rowY = rowViewportPosition(row) + offset.y();
1689 if (rowY == dirtyArea.top())
1690 painter.drawLine(dirtyArea.left(), rowY, dirtyArea.right(), rowY);
1693 if (drawWhenHidden && verticalHeader->isHidden()) {
1694 const int col = horizontalHeader->logicalIndex(left);
1695 if (!horizontalHeader->isSectionHidden(col)) {
1696 int colX = columnViewportPosition(col) + offset.x();
1697 if (!isLeftToRight())
1698 colX += columnWidth(left) - 1;
1699 if (isLeftToRight() && colX == dirtyArea.left())
1700 painter.drawLine(colX, dirtyArea.top(), colX, dirtyArea.bottom());
1701 if (!isLeftToRight() && colX == dirtyArea.right())
1702 painter.drawLine(colX, dirtyArea.top(), colX, dirtyArea.bottom());
1705 painter.setPen(old);
1709#if QT_CONFIG(draganddrop)
1711 d->paintDropIndicator(&painter);
1772QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
1775 Q_UNUSED(modifiers);
1777 int bottom = d->model->rowCount(d->root) - 1;
1779 while (bottom >= 0 && isRowHidden(d->logicalRow(bottom)))
1782 int right = d->model->columnCount(d->root) - 1;
1784 while (right >= 0 && isColumnHidden(d->logicalColumn(right)))
1787 if (bottom == -1 || right == -1)
1788 return QModelIndex();
1790 QModelIndex current = currentIndex();
1792 if (!current.isValid()) {
1795 while (column < right && isColumnHidden(d->logicalColumn(column)))
1797 while (isRowHidden(d->logicalRow(row)) && row < bottom)
1799 d->visualCursor = QPoint(column, row);
1800 return d->model->index(d->logicalRow(row), d->logicalColumn(column), d->root);
1804 QPoint visualCurrent(d->visualColumn(current.column()), d->visualRow(current.row()));
1805 if (visualCurrent != d->visualCursor) {
1806 if (d->hasSpans()) {
1807 QSpanCollection::Span span = d->span(current.row(), current.column());
1808 if (span.top() > d->visualCursor.y() || d->visualCursor.y() > span.bottom()
1809 || span.left() > d->visualCursor.x() || d->visualCursor.x() > span.right())
1810 d->visualCursor = visualCurrent;
1812 d->visualCursor = visualCurrent;
1816 int visualRow = d->visualCursor.y();
1817 if (visualRow > bottom)
1819 Q_ASSERT(visualRow != -1);
1820 int visualColumn = d->visualCursor.x();
1821 if (visualColumn > right)
1822 visualColumn = right;
1823 Q_ASSERT(visualColumn != -1);
1825 if (isRightToLeft()) {
1826 if (cursorAction == MoveLeft)
1827 cursorAction = MoveRight;
1828 else if (cursorAction == MoveRight)
1829 cursorAction = MoveLeft;
1832 switch (cursorAction) {
1834 int originalRow = visualRow;
1835#ifdef QT_KEYPAD_NAVIGATION
1836 if (QApplicationPrivate::keypadNavigationEnabled() && visualRow == 0)
1837 visualRow = d->visualRow(model()->rowCount() - 1) + 1;
1840 int r = d->logicalRow(visualRow);
1841 int c = d->logicalColumn(visualColumn);
1842 if (r != -1 && d->hasSpans()) {
1843 QSpanCollection::Span span = d->span(r, c);
1844 if (span.width() > 1 || span.height() > 1)
1845 visualRow = d->visualRow(span.top());
1847 while (visualRow >= 0) {
1849 r = d->logicalRow(visualRow);
1850 c = d->logicalColumn(visualColumn);
1851 if (r == -1 || (!isRowHidden(r) && d->isCellEnabled(r, c)))
1855 visualRow = originalRow;
1859 int originalRow = visualRow;
1860 if (d->hasSpans()) {
1861 QSpanCollection::Span span = d->span(current.row(), current.column());
1862 visualRow = d->visualRow(d->rowSpanEndLogical(span.top(), span.height()));
1864#ifdef QT_KEYPAD_NAVIGATION
1865 if (QApplicationPrivate::keypadNavigationEnabled() && visualRow >= bottom)
1868 int r = d->logicalRow(visualRow);
1869 int c = d->logicalColumn(visualColumn);
1870 if (r != -1 && d->hasSpans()) {
1871 QSpanCollection::Span span = d->span(r, c);
1872 if (span.width() > 1 || span.height() > 1)
1873 visualRow = d->visualRow(d->rowSpanEndLogical(span.top(), span.height()));
1875 while (visualRow <= bottom) {
1877 r = d->logicalRow(visualRow);
1878 c = d->logicalColumn(visualColumn);
1879 if (r == -1 || (!isRowHidden(r) && d->isCellEnabled(r, c)))
1882 if (visualRow > bottom)
1883 visualRow = originalRow;
1888 int originalRow = visualRow;
1889 int originalColumn = visualColumn;
1890 bool firstTime =
true;
1891 bool looped =
false;
1892 bool wrapped =
false;
1894 int r = d->logicalRow(visualRow);
1895 int c = d->logicalColumn(visualColumn);
1896 if (firstTime && c != -1 && d->hasSpans()) {
1898 QSpanCollection::Span span = d->span(r, c);
1899 if (span.width() > 1 || span.height() > 1)
1900 visualColumn = d->visualColumn(span.left());
1902 while (visualColumn >= 0) {
1904 r = d->logicalRow(visualRow);
1905 c = d->logicalColumn(visualColumn);
1906 if (r == -1 || c == -1 || (!isRowHidden(r) && !isColumnHidden(c) && d->isCellEnabled(r, c)))
1908 if (wrapped && (originalRow < visualRow || (originalRow == visualRow && originalColumn <= visualColumn))) {
1913 if (cursorAction == MoveLeft || visualColumn >= 0)
1915 visualColumn = right + 1;
1916 if (visualRow == 0) {
1923 if (visualColumn < 0)
1924 visualColumn = originalColumn;
1929 int originalRow = visualRow;
1930 int originalColumn = visualColumn;
1931 bool firstTime =
true;
1932 bool looped =
false;
1933 bool wrapped =
false;
1935 int r = d->logicalRow(visualRow);
1936 int c = d->logicalColumn(visualColumn);
1937 if (firstTime && c != -1 && d->hasSpans()) {
1939 QSpanCollection::Span span = d->span(r, c);
1940 if (span.width() > 1 || span.height() > 1)
1941 visualColumn = d->visualColumn(d->columnSpanEndLogical(span.left(), span.width()));
1943 while (visualColumn <= right) {
1945 r = d->logicalRow(visualRow);
1946 c = d->logicalColumn(visualColumn);
1947 if (r == -1 || c == -1 || (!isRowHidden(r) && !isColumnHidden(c) && d->isCellEnabled(r, c)))
1949 if (wrapped && (originalRow > visualRow || (originalRow == visualRow && originalColumn >= visualColumn))) {
1954 if (cursorAction == MoveRight || visualColumn <= right)
1957 if (visualRow == bottom) {
1964 if (visualColumn > right)
1965 visualColumn = originalColumn;
1969 visualColumn = d->nextActiveVisualColumn(visualRow, 0, right,
1970 QTableViewPrivate::SearchDirection::Increasing);
1971 if (modifiers & Qt::ControlModifier)
1972 visualRow = d->nextActiveVisualRow(0, visualColumn, bottom,
1973 QTableViewPrivate::SearchDirection::Increasing);
1976 visualColumn = d->nextActiveVisualColumn(visualRow, right, -1,
1977 QTableViewPrivate::SearchDirection::Decreasing);
1978 if (modifiers & Qt::ControlModifier)
1979 visualRow = d->nextActiveVisualRow(bottom, visualColumn, -1,
1980 QTableViewPrivate::SearchDirection::Decreasing);
1983 int newLogicalRow = rowAt(visualRect(current).bottom() - d->viewport->height());
1984 int visualRow = (newLogicalRow == -1 ? 0 : d->visualRow(newLogicalRow));
1985 visualRow = d->nextActiveVisualRow(visualRow, current.column(), bottom,
1986 QTableViewPrivate::SearchDirection::Increasing);
1987 newLogicalRow = d->logicalRow(visualRow);
1988 return d->model->index(newLogicalRow, current.column(), d->root);
1990 case MovePageDown: {
1991 int newLogicalRow = rowAt(visualRect(current).top() + d->viewport->height());
1992 int visualRow = (newLogicalRow == -1 ? bottom : d->visualRow(newLogicalRow));
1993 visualRow = d->nextActiveVisualRow(visualRow, current.column(), -1,
1994 QTableViewPrivate::SearchDirection::Decreasing);
1995 newLogicalRow = d->logicalRow(visualRow);
1996 return d->model->index(newLogicalRow, current.column(), d->root);
1999 d->visualCursor = QPoint(visualColumn, visualRow);
2000 int logicalRow = d->logicalRow(visualRow);
2001 int logicalColumn = d->logicalColumn(visualColumn);
2002 if (!d->model->hasIndex(logicalRow, logicalColumn, d->root))
2003 return QModelIndex();
2005 QModelIndex result = d->model->index(logicalRow, logicalColumn, d->root);
2006 if (!d->isRowHidden(logicalRow) && !d->isColumnHidden(logicalColumn) && d->isIndexEnabled(result)) {
2007 if (d->hasSpans()) {
2008 QSpanCollection::Span span = d->span(result.row(), result.column());
2009 if (span.width() > 1 || span.height() > 1) {
2010 result = d->model->sibling(span.top(), span.left(), result);
2016 return QModelIndex();
2026void QTableView::setSelection(
const QRect &rect, QItemSelectionModel::SelectionFlags command)
2029 QModelIndex tl = indexAt(QPoint(isRightToLeft() ? qMax(rect.left(), rect.right())
2030 : qMin(rect.left(), rect.right()), qMin(rect.top(), rect.bottom())));
2031 QModelIndex br = indexAt(QPoint(isRightToLeft() ? qMin(rect.left(), rect.right()) :
2032 qMax(rect.left(), rect.right()), qMax(rect.top(), rect.bottom())));
2033 if (!d->selectionModel || !tl.isValid() || !br.isValid() || !d->isIndexEnabled(tl) || !d->isIndexEnabled(br))
2036 const bool verticalMoved = verticalHeader()->sectionsMoved();
2037 const bool horizontalMoved = horizontalHeader()->sectionsMoved();
2039 QItemSelection selection;
2041 int bottom = br.row();
2042 int left = tl.column();
2043 int right = br.column();
2045 if (d->hasSpans()) {
2049 bool intersectsSpan =
false;
2050 top = qMin(d->visualRow(tl.row()), d->visualRow(br.row()));
2051 left = qMin(d->visualColumn(tl.column()), d->visualColumn(br.column()));
2052 bottom = qMax(d->visualRow(tl.row()), d->visualRow(br.row()));
2053 right = qMax(d->visualColumn(tl.column()), d->visualColumn(br.column()));
2056 for (QSpanCollection::Span *it : d->spans.spans) {
2057 const QSpanCollection::Span &span = *it;
2058 const int t = d->visualRow(span.top());
2059 const int l = d->visualColumn(span.left());
2060 const int b = d->visualRow(d->rowSpanEndLogical(span.top(), span.height()));
2061 const int r = d->visualColumn(d->columnSpanEndLogical(span.left(), span.width()));
2062 if ((t > bottom) || (l > right) || (top > b) || (left > r))
2064 intersectsSpan =
true;
2085 if (!intersectsSpan) {
2089 right = br.column();
2090 }
else if (!verticalMoved && !horizontalMoved) {
2092 tl = d->model->index(top, left, d->root);
2093 br = d->model->index(bottom, right, d->root);
2095 }
else if (verticalMoved && horizontalMoved) {
2096 top = d->visualRow(tl.row());
2097 bottom = d->visualRow(br.row());
2098 left = d->visualColumn(tl.column());
2099 right = d->visualColumn(br.column());
2100 }
else if (horizontalMoved) {
2103 left = d->visualColumn(tl.column());
2104 right = d->visualColumn(br.column());
2105 }
else if (verticalMoved) {
2106 top = d->visualRow(tl.row());
2107 bottom = d->visualRow(br.row());
2109 right = br.column();
2112 if (horizontalMoved && verticalMoved) {
2113 selection.reserve((right - left + 1) * (bottom - top + 1));
2114 for (
int horizontal = left; horizontal <= right; ++horizontal) {
2115 int column = d->logicalColumn(horizontal);
2116 for (
int vertical = top; vertical <= bottom; ++vertical) {
2117 int row = d->logicalRow(vertical);
2118 QModelIndex index = d->model->index(row, column, d->root);
2119 selection.append(QItemSelectionRange(index));
2122 }
else if (horizontalMoved) {
2123 selection.reserve(right - left + 1);
2124 for (
int visual = left; visual <= right; ++visual) {
2125 int column = d->logicalColumn(visual);
2126 QModelIndex topLeft = d->model->index(top, column, d->root);
2127 QModelIndex bottomRight = d->model->index(bottom, column, d->root);
2128 selection.append(QItemSelectionRange(topLeft, bottomRight));
2130 }
else if (verticalMoved) {
2131 selection.reserve(bottom - top + 1);
2132 for (
int visual = top; visual <= bottom; ++visual) {
2133 int row = d->logicalRow(visual);
2134 QModelIndex topLeft = d->model->index(row, left, d->root);
2135 QModelIndex bottomRight = d->model->index(row, right, d->root);
2136 selection.append(QItemSelectionRange(topLeft, bottomRight));
2139 QItemSelectionRange range(tl, br);
2140 if (!range.isEmpty())
2141 selection.append(range);
2144 d->selectionModel->select(selection, command);
2156QRegion QTableView::visualRegionForSelection(
const QItemSelection &selection)
const
2158 Q_D(
const QTableView);
2160 if (selection.isEmpty())
2163 QRegion selectionRegion;
2164 const QRect &viewportRect = d->viewport->rect();
2165 bool verticalMoved = verticalHeader()->sectionsMoved();
2166 bool horizontalMoved = horizontalHeader()->sectionsMoved();
2168 if ((verticalMoved && horizontalMoved) || (d->hasSpans() && (verticalMoved || horizontalMoved))) {
2169 for (
const auto &range : selection) {
2170 if (range.parent() != d->root || !range.isValid())
2172 for (
int r = range.top(); r <= range.bottom(); ++r)
2173 for (
int c = range.left(); c <= range.right(); ++c) {
2174 const QRect &rangeRect = visualRect(d->model->index(r, c, d->root));
2175 if (viewportRect.intersects(rangeRect))
2176 selectionRegion += rangeRect;
2179 }
else if (horizontalMoved) {
2180 for (
const auto &range : selection) {
2181 if (range.parent() != d->root || !range.isValid())
2183 int top = rowViewportPosition(range.top());
2184 int bottom = rowViewportPosition(range.bottom()) + rowHeight(range.bottom());
2186 qSwap<
int>(top, bottom);
2187 int height = bottom - top;
2188 for (
int c = range.left(); c <= range.right(); ++c) {
2189 const QRect rangeRect(columnViewportPosition(c), top, columnWidth(c), height);
2190 if (viewportRect.intersects(rangeRect))
2191 selectionRegion += rangeRect;
2194 }
else if (verticalMoved) {
2195 for (
const auto &range : selection) {
2196 if (range.parent() != d->root || !range.isValid())
2198 int left = columnViewportPosition(range.left());
2199 int right = columnViewportPosition(range.right()) + columnWidth(range.right());
2201 qSwap<
int>(left, right);
2202 int width = right - left;
2203 for (
int r = range.top(); r <= range.bottom(); ++r) {
2204 const QRect rangeRect(left, rowViewportPosition(r), width, rowHeight(r));
2205 if (viewportRect.intersects(rangeRect))
2206 selectionRegion += rangeRect;
2210 const int gridAdjust = showGrid() ? 1 : 0;
2211 for (
auto range : selection) {
2212 if (range.parent() != d->root || !range.isValid())
2214 d->trimHiddenSelections(&range);
2216 const int rtop = rowViewportPosition(range.top());
2217 const int rbottom = rowViewportPosition(range.bottom()) + rowHeight(range.bottom());
2220 if (isLeftToRight()) {
2221 rleft = columnViewportPosition(range.left());
2222 rright = columnViewportPosition(range.right()) + columnWidth(range.right());
2224 rleft = columnViewportPosition(range.right());
2225 rright = columnViewportPosition(range.left()) + columnWidth(range.left());
2227 const QRect rangeRect(QPoint(rleft, rtop), QPoint(rright - 1 - gridAdjust, rbottom - 1 - gridAdjust));
2228 if (viewportRect.intersects(rangeRect))
2229 selectionRegion += rangeRect;
2230 if (d->hasSpans()) {
2231 const auto spansInRect = d->spans.spansInRect(range.left(), range.top(), range.width(), range.height());
2232 for (QSpanCollection::Span *s : spansInRect) {
2233 if (range.contains(s->top(), s->left(), range.parent())) {
2234 const QRect &visualSpanRect = d->visualSpanRect(*s);
2235 if (viewportRect.intersects(visualSpanRect))
2236 selectionRegion += visualSpanRect;
2243 return selectionRegion;
2300void QTableView::updateGeometries()
2303 if (d->geometryRecursionBlock)
2305 d->geometryRecursionBlock =
true;
2308 if (!d->verticalHeader->isHidden()) {
2309 width = qMax(d->verticalHeader->minimumWidth(), d->verticalHeader->sizeHint().width());
2310 width = qMin(width, d->verticalHeader->maximumWidth());
2313 if (!d->horizontalHeader->isHidden()) {
2314 height = qMax(d->horizontalHeader->minimumHeight(), d->horizontalHeader->sizeHint().height());
2315 height = qMin(height, d->horizontalHeader->maximumHeight());
2317 bool reverse = isRightToLeft();
2319 setViewportMargins(0, height, width, 0);
2321 setViewportMargins(width, height, 0, 0);
2325 QRect vg = d->viewport->geometry();
2327 int verticalLeft = reverse ? vg.right() + 1 : (vg.left() - width);
2328 d->verticalHeader->setGeometry(verticalLeft, vg.top(), width, vg.height());
2329 if (d->verticalHeader->isHidden())
2330 QMetaObject::invokeMethod(d->verticalHeader,
"updateGeometries");
2332 int horizontalTop = vg.top() - height;
2333 d->horizontalHeader->setGeometry(vg.left(), horizontalTop, vg.width(), height);
2334 if (d->horizontalHeader->isHidden())
2335 QMetaObject::invokeMethod(d->horizontalHeader,
"updateGeometries");
2337#if QT_CONFIG(abstractbutton)
2339 if (d->horizontalHeader->isHidden() || d->verticalHeader->isHidden()) {
2340 d->cornerWidget->setHidden(
true);
2342 d->cornerWidget->setHidden(
false);
2343 d->cornerWidget->setGeometry(verticalLeft, horizontalTop, width, height);
2350 QSize vsize = d->viewport->size();
2351 QSize max = maximumViewportSize();
2352 const int horizontalLength = d->horizontalHeader->length();
2353 const int verticalLength = d->verticalHeader->length();
2354 if (max.width() >= horizontalLength && max.height() >= verticalLength)
2358 const int columnCount = d->horizontalHeader->count();
2359 const int viewportWidth = vsize.width();
2360 int columnsInViewport = 0;
2361 for (
int width = 0, column = columnCount - 1; column >= 0; --column) {
2362 int logical = d->horizontalHeader->logicalIndex(column);
2363 if (!d->horizontalHeader->isSectionHidden(logical)) {
2364 width += d->horizontalHeader->sectionSize(logical);
2365 if (width > viewportWidth)
2367 ++columnsInViewport;
2370 columnsInViewport = qMax(columnsInViewport, 1);
2372 if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) {
2373 const int visibleColumns = columnCount - d->horizontalHeader->hiddenSectionCount();
2374 horizontalScrollBar()->setRange(0, visibleColumns - columnsInViewport);
2375 horizontalScrollBar()->setPageStep(columnsInViewport);
2376 if (columnsInViewport >= visibleColumns)
2377 d->horizontalHeader->setOffset(0);
2378 horizontalScrollBar()->setSingleStep(1);
2380 horizontalScrollBar()->setPageStep(vsize.width());
2381 horizontalScrollBar()->setRange(0, horizontalLength - vsize.width());
2382 horizontalScrollBar()->d_func()->itemviewChangeSingleStep(qMax(vsize.width() / (columnsInViewport + 1), 2));
2386 const int rowCount = d->verticalHeader->count();
2387 const int viewportHeight = vsize.height();
2388 int rowsInViewport = 0;
2389 for (
int height = 0, row = rowCount - 1; row >= 0; --row) {
2390 int logical = d->verticalHeader->logicalIndex(row);
2391 if (!d->verticalHeader->isSectionHidden(logical)) {
2392 height += d->verticalHeader->sectionSize(logical);
2393 if (height > viewportHeight)
2398 rowsInViewport = qMax(rowsInViewport, 1);
2400 if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) {
2401 const int visibleRows = rowCount - d->verticalHeader->hiddenSectionCount();
2402 verticalScrollBar()->setRange(0, visibleRows - rowsInViewport);
2403 verticalScrollBar()->setPageStep(rowsInViewport);
2404 if (rowsInViewport >= visibleRows)
2405 d->verticalHeader->setOffset(0);
2406 verticalScrollBar()->setSingleStep(1);
2408 verticalScrollBar()->setPageStep(vsize.height());
2409 verticalScrollBar()->setRange(0, verticalLength - vsize.height());
2410 verticalScrollBar()->d_func()->itemviewChangeSingleStep(qMax(vsize.height() / (rowsInViewport + 1), 2));
2412 d->verticalHeader->d_func()->setScrollOffset(verticalScrollBar(), verticalScrollMode());
2414 d->geometryRecursionBlock =
false;
2415 QAbstractItemView::updateGeometries();
2432int QTableView::sizeHintForRow(
int row)
const
2434 Q_D(
const QTableView);
2440 const int maximumProcessCols = d->verticalHeader->resizeContentsPrecision();
2443 int left = qMax(0, d->horizontalHeader->visualIndexAt(0));
2444 int right = d->horizontalHeader->visualIndexAt(d->viewport->width());
2446 right = d->model->columnCount(d->root) - 1;
2448 QStyleOptionViewItem option;
2449 initViewItemOption(&option);
2453 int columnsProcessed = 0;
2455 for (; column <= right; ++column) {
2456 int logicalColumn = d->horizontalHeader->logicalIndex(column);
2457 if (d->horizontalHeader->isSectionHidden(logicalColumn))
2459 index = d->model->index(row, logicalColumn, d->root);
2460 hint = d->heightHintForIndex(index, hint, option);
2463 if (columnsProcessed == maximumProcessCols)
2467 const int actualRight = d->model->columnCount(d->root) - 1;
2469 int idxRight = column - 1;
2471 if (maximumProcessCols == 0 || actualRight < idxLeft)
2472 columnsProcessed = maximumProcessCols;
2474 while (columnsProcessed != maximumProcessCols && (idxLeft > 0 || idxRight < actualRight)) {
2475 int logicalIdx = -1;
2477 if ((columnsProcessed % 2 && idxLeft > 0) || idxRight == actualRight) {
2478 while (idxLeft > 0) {
2480 int logcol = d->horizontalHeader->logicalIndex(idxLeft);
2481 if (d->horizontalHeader->isSectionHidden(logcol))
2483 logicalIdx = logcol;
2487 while (idxRight < actualRight) {
2489 int logcol = d->horizontalHeader->logicalIndex(idxRight);
2490 if (d->horizontalHeader->isSectionHidden(logcol))
2492 logicalIdx = logcol;
2496 if (logicalIdx >= 0) {
2497 index = d->model->index(row, logicalIdx, d->root);
2498 hint = d->heightHintForIndex(index, hint, option);
2503 return d->showGrid ? hint + 1 : hint;
2521int QTableView::sizeHintForColumn(
int column)
const
2523 Q_D(
const QTableView);
2529 const int maximumProcessRows = d->horizontalHeader->resizeContentsPrecision();
2531 int top = qMax(0, d->verticalHeader->visualIndexAt(0));
2532 int bottom = d->verticalHeader->visualIndexAt(d->viewport->height());
2533 if (!isVisible() || bottom == -1)
2534 bottom = d->model->rowCount(d->root) - 1;
2536 QStyleOptionViewItem option;
2537 initViewItemOption(&option);
2540 int rowsProcessed = 0;
2543 for (; row <= bottom; ++row) {
2544 int logicalRow = d->verticalHeader->logicalIndex(row);
2545 if (d->verticalHeader->isSectionHidden(logicalRow))
2547 index = d->model->index(logicalRow, column, d->root);
2549 hint = d->widthHintForIndex(index, hint, option);
2551 if (rowsProcessed == maximumProcessRows)
2555 const int actualBottom = d->model->rowCount(d->root) - 1;
2557 int idxBottom = row - 1;
2559 if (maximumProcessRows == 0 || actualBottom < idxTop)
2560 rowsProcessed = maximumProcessRows;
2562 while (rowsProcessed != maximumProcessRows && (idxTop > 0 || idxBottom < actualBottom)) {
2563 int logicalIdx = -1;
2565 if ((rowsProcessed % 2 && idxTop > 0) || idxBottom == actualBottom) {
2566 while (idxTop > 0) {
2568 int logrow = d->verticalHeader->logicalIndex(idxTop);
2569 if (d->verticalHeader->isSectionHidden(logrow))
2571 logicalIdx = logrow;
2575 while (idxBottom < actualBottom) {
2577 int logrow = d->verticalHeader->logicalIndex(idxBottom);
2578 if (d->verticalHeader->isSectionHidden(logrow))
2580 logicalIdx = logrow;
2584 if (logicalIdx >= 0) {
2585 index = d->model->index(logicalIdx, column, d->root);
2586 hint = d->widthHintForIndex(index, hint, option);
2591 return d->showGrid ? hint + 1 : hint;
2918void QTableView::scrollTo(
const QModelIndex &index, ScrollHint hint)
2923 if (!d->isIndexValid(index)
2924 || (d->model->parent(index) != d->root)
2925 || isRowHidden(index.row()) || isColumnHidden(index.column()))
2928 QSpanCollection::Span span;
2930 span = d->span(index.row(), index.column());
2934 int viewportWidth = d->viewport->width();
2935 int horizontalOffset = d->horizontalHeader->offset();
2936 int horizontalPosition = d->horizontalHeader->sectionPosition(index.column());
2937 int horizontalIndex = d->horizontalHeader->visualIndex(index.column());
2938 int cellWidth = d->hasSpans()
2939 ? d->columnSpanWidth(index.column(), span.width())
2940 : d->horizontalHeader->sectionSize(index.column());
2942 if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) {
2944 bool positionAtLeft = (horizontalPosition - horizontalOffset < 0);
2945 bool positionAtRight = (horizontalPosition - horizontalOffset + cellWidth > viewportWidth);
2947 if (hint == PositionAtCenter || positionAtRight) {
2948 int w = (hint == PositionAtCenter ? viewportWidth / 2 : viewportWidth);
2950 while (horizontalIndex > 0) {
2951 x += columnWidth(d->horizontalHeader->logicalIndex(horizontalIndex-1));
2958 if (positionAtRight || hint == PositionAtCenter || positionAtLeft) {
2959 int hiddenSections = 0;
2960 if (d->horizontalHeader->sectionsHidden()) {
2961 for (
int s = horizontalIndex - 1; s >= 0; --s) {
2962 int column = d->horizontalHeader->logicalIndex(s);
2963 if (d->horizontalHeader->isSectionHidden(column))
2967 horizontalScrollBar()->setValue(horizontalIndex - hiddenSections);
2971 if (hint == PositionAtCenter) {
2972 horizontalScrollBar()->setValue(horizontalPosition - ((viewportWidth - cellWidth) / 2));
2974 if (horizontalPosition - horizontalOffset < 0 || cellWidth > viewportWidth)
2975 horizontalScrollBar()->setValue(horizontalPosition);
2976 else if (horizontalPosition - horizontalOffset + cellWidth > viewportWidth)
2977 horizontalScrollBar()->setValue(horizontalPosition - viewportWidth + cellWidth);
2983 int viewportHeight = d->viewport->height();
2984 int verticalOffset = d->verticalHeader->offset();
2985 int verticalPosition = d->verticalHeader->sectionPosition(index.row());
2986 int verticalIndex = d->verticalHeader->visualIndex(index.row());
2987 int cellHeight = d->hasSpans()
2988 ? d->rowSpanHeight(index.row(), span.height())
2989 : d->verticalHeader->sectionSize(index.row());
2991 if (verticalPosition - verticalOffset < 0 || cellHeight > viewportHeight) {
2992 if (hint == EnsureVisible)
2993 hint = PositionAtTop;
2994 }
else if (verticalPosition - verticalOffset + cellHeight > viewportHeight) {
2995 if (hint == EnsureVisible)
2996 hint = PositionAtBottom;
2999 if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) {
3001 if (hint == PositionAtBottom || hint == PositionAtCenter) {
3002 int h = (hint == PositionAtCenter ? viewportHeight / 2 : viewportHeight);
3004 while (verticalIndex > 0) {
3005 int row = d->verticalHeader->logicalIndex(verticalIndex - 1);
3006 y += d->verticalHeader->sectionSize(row);
3013 if (hint == PositionAtBottom || hint == PositionAtCenter || hint == PositionAtTop) {
3014 int hiddenSections = 0;
3015 if (d->verticalHeader->sectionsHidden()) {
3016 for (
int s = verticalIndex - 1; s >= 0; --s) {
3017 int row = d->verticalHeader->logicalIndex(s);
3018 if (d->verticalHeader->isSectionHidden(row))
3022 verticalScrollBar()->setValue(verticalIndex - hiddenSections);
3026 if (hint == PositionAtTop) {
3027 verticalScrollBar()->setValue(verticalPosition);
3028 }
else if (hint == PositionAtBottom) {
3029 verticalScrollBar()->setValue(verticalPosition - viewportHeight + cellHeight);
3030 }
else if (hint == PositionAtCenter) {
3031 verticalScrollBar()->setValue(verticalPosition - ((viewportHeight - cellHeight) / 2));
3071void QTableView::timerEvent(QTimerEvent *event)
3075 if (event->id() == d->columnResizeTimer.id()) {
3076 const int oldScrollMax = horizontalScrollBar()->maximum();
3077 if (horizontalHeader()->d_func()->state != QHeaderViewPrivate::ResizeSection) {
3079 d->columnResizeTimer.stop();
3081 updateEditorGeometries();
3085 int viewportHeight = d->viewport->height();
3086 int viewportWidth = d->viewport->width();
3087 if (d->hasSpans() || horizontalScrollBar()->value() == oldScrollMax) {
3088 rect = QRect(0, 0, viewportWidth, viewportHeight);
3090 for (
int i = d->columnsToUpdate.size()-1; i >= 0; --i) {
3091 int column = d->columnsToUpdate.at(i);
3092 int x = columnViewportPosition(column);
3093 if (isRightToLeft())
3094 rect |= QRect(0, 0, x + columnWidth(column), viewportHeight);
3096 rect |= QRect(x, 0, viewportWidth - x, viewportHeight);
3100 d->viewport->update(rect.normalized());
3101 d->columnsToUpdate.clear();
3104 if (event->id() == d->rowResizeTimer.id()) {
3105 const int oldScrollMax = verticalScrollBar()->maximum();
3106 if (verticalHeader()->d_func()->state != QHeaderViewPrivate::ResizeSection) {
3108 d->rowResizeTimer.stop();
3110 updateEditorGeometries();
3113 int viewportHeight = d->viewport->height();
3114 int viewportWidth = d->viewport->width();
3116 if (d->hasSpans() || verticalScrollBar()->value() == oldScrollMax) {
3119 top = viewportHeight;
3120 for (
int i = d->rowsToUpdate.size()-1; i >= 0; --i) {
3121 int y = rowViewportPosition(d->rowsToUpdate.at(i));
3126 d->viewport->update(QRect(0, top, viewportWidth, viewportHeight - top));
3127 d->rowsToUpdate.clear();
3130 QAbstractItemView::timerEvent(event);
3486void QTableViewPrivate::selectRow(
int row,
bool anchor)
3490 if (q->selectionBehavior() == QTableView::SelectColumns
3491 || (q->selectionMode() == QTableView::SingleSelection
3492 && q->selectionBehavior() == QTableView::SelectItems))
3495 if (row >= 0 && row < model->rowCount(root)) {
3496 int column = horizontalHeader->logicalIndexAt(q->isRightToLeft() ? viewport->width() : 0);
3497 QModelIndex index = model->index(row, column, root);
3498 QItemSelectionModel::SelectionFlags command = q->selectionCommand(index);
3502 const auto startIndex = currentSelectionStartIndex;
3503 selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
3504 currentSelectionStartIndex = startIndex;
3507 if ((anchor && !(command & QItemSelectionModel::Current))
3508 || (q->selectionMode() == QTableView::SingleSelection))
3509 currentSelectionStartIndex = model->index(row, column, root);
3511 if (q->selectionMode() != QTableView::SingleSelection
3512 && command.testFlag(QItemSelectionModel::Toggle)) {
3514 ctrlDragSelectionFlag = verticalHeader->selectionModel()->selectedRows(column).contains(index)
3515 ? QItemSelectionModel::Deselect : QItemSelectionModel::Select;
3516 command &= ~QItemSelectionModel::Toggle;
3517 command |= ctrlDragSelectionFlag;
3519 command |= QItemSelectionModel::Current;
3522 const auto rowSectionAnchor = currentSelectionStartIndex.row();
3523 QModelIndex upper = model->index(qMin(rowSectionAnchor, row), column, root);
3524 QModelIndex lower = model->index(qMax(rowSectionAnchor, row), column, root);
3525 if ((verticalHeader->sectionsMoved() && upper.row() != lower.row())) {
3526 q->setSelection(q->visualRect(upper) | q->visualRect(lower), command | QItemSelectionModel::Rows);
3528 selectionModel->select(QItemSelection(upper, lower), command | QItemSelectionModel::Rows);
3533void QTableViewPrivate::selectColumn(
int column,
bool anchor)
3537 if (q->selectionBehavior() == QTableView::SelectRows
3538 || (q->selectionMode() == QTableView::SingleSelection
3539 && q->selectionBehavior() == QTableView::SelectItems))
3542 if (column >= 0 && column < model->columnCount(root)) {
3543 int row = verticalHeader->logicalIndexAt(0);
3544 QModelIndex index = model->index(row, column, root);
3545 QItemSelectionModel::SelectionFlags command = q->selectionCommand(index);
3549 const auto startIndex = currentSelectionStartIndex;
3550 selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
3551 currentSelectionStartIndex = startIndex;
3554 if ((anchor && !(command & QItemSelectionModel::Current))
3555 || (q->selectionMode() == QTableView::SingleSelection))
3556 currentSelectionStartIndex = model->index(row, column, root);
3558 if (q->selectionMode() != QTableView::SingleSelection
3559 && command.testFlag(QItemSelectionModel::Toggle)) {
3561 ctrlDragSelectionFlag = horizontalHeader->selectionModel()->selectedColumns(row).contains(index)
3562 ? QItemSelectionModel::Deselect : QItemSelectionModel::Select;
3563 command &= ~QItemSelectionModel::Toggle;
3564 command |= ctrlDragSelectionFlag;
3566 command |= QItemSelectionModel::Current;
3569 const auto columnSectionAnchor = currentSelectionStartIndex.column();
3570 QModelIndex left = model->index(row, qMin(columnSectionAnchor, column), root);
3571 QModelIndex right = model->index(row, qMax(columnSectionAnchor, column), root);
3572 if ((horizontalHeader->sectionsMoved() && left.column() != right.column())) {
3573 q->setSelection(q->visualRect(left) | q->visualRect(right), command | QItemSelectionModel::Columns);
3575 selectionModel->select(QItemSelection(left, right), command | QItemSelectionModel::Columns);