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);
661QRect QTableViewPrivate::intersectedRect(
const QRect rect,
const QModelIndex &topLeft,
const QModelIndex &bottomRight)
const
663 Q_Q(
const QTableView);
665 using minMaxPair = std::pair<
int,
int>;
666 const auto calcMinMax = [q](QHeaderView *hdr,
int startIdx,
int endIdx, minMaxPair bounds) -> minMaxPair
668 minMaxPair ret(std::numeric_limits<
int>::max(), std::numeric_limits<
int>::min());
669 if (hdr->sectionsMoved()) {
670 for (
int i = startIdx; i <= endIdx; ++i) {
671 const int start = hdr->sectionViewportPosition(i);
672 const int end = start + hdr->sectionSize(i);
673 ret.first = std::min(start, ret.first);
674 ret.second = std::max(end, ret.second);
675 if (ret.first <= bounds.first && ret.second >= bounds.second)
679 if (q->isRightToLeft() && q->horizontalHeader() == hdr)
680 std::swap(startIdx, endIdx);
681 ret.first = hdr->sectionViewportPosition(startIdx);
682 ret.second = hdr->sectionViewportPosition(endIdx) +
683 hdr->sectionSize(endIdx);
688 const auto yVals = calcMinMax(verticalHeader, topLeft.row(), bottomRight.row(),
689 minMaxPair(rect.top(), rect.bottom()));
690 if (yVals.first == yVals.second)
694 const QRect colRect(QPoint(rect.left(), yVals.first),
695 QPoint(rect.right(), yVals.second));
696 const QRect intersected = rect.intersected(colRect);
697 if (intersected.isNull())
700 const auto xVals = calcMinMax(horizontalHeader, topLeft.column(), bottomRight.column(),
701 minMaxPair(rect.left(), rect.right()));
702 const QRect updateRect(QPoint(xVals.first, yVals.first),
703 QPoint(xVals.second, yVals.second));
704 return rect.intersected(updateRect);
894void QTableViewPrivate::drawAndClipSpans(
const QRegion &area, QPainter *painter,
895 const QStyleOptionViewItem &option, QBitArray *drawn,
896 int firstVisualRow,
int lastVisualRow,
int firstVisualColumn,
int lastVisualColumn)
898 Q_Q(
const QTableView);
899 bool alternateBase =
false;
900 QRegion region = viewport->rect();
902 QSet<QSpanCollection::Span *> visibleSpans;
903 bool sectionMoved = verticalHeader->sectionsMoved() || horizontalHeader->sectionsMoved();
906 visibleSpans = spans.spansInRect(logicalColumn(firstVisualColumn), logicalRow(firstVisualRow),
907 lastVisualColumn - firstVisualColumn + 1, lastVisualRow - firstVisualRow + 1);
922 const auto spanList = spans.spans;
923 for (QSpanCollection::Span *span : spanList) {
924 const int spanVisualLeft = visualColumn(span->left());
925 const int spanVisualTop = visualRow(span->top());
926 const int spanVisualRight = spanVisualLeft + span->width() - 1;
927 const int spanVisualBottom = spanVisualTop + span->height() - 1;
928 if ((spanVisualLeft <= lastVisualColumn && spanVisualRight >= firstVisualColumn)
929 && (spanVisualTop <= lastVisualRow && spanVisualBottom >= firstVisualRow))
930 visibleSpans.insert(span);
934 for (QSpanCollection::Span *span : std::as_const(visibleSpans)) {
935 int row = span->top();
936 int col = span->left();
937 QModelIndex index = model->index(row, col, root);
938 if (!index.isValid())
940 QRect rect = visualSpanRect(*span);
941 rect.translate(scrollDelayOffset);
942 if (!area.intersects(rect))
944 QStyleOptionViewItem opt = option;
946 alternateBase = alternatingColors && (span->top() & 1);
947 opt.features.setFlag(QStyleOptionViewItem::Alternate, alternateBase);
948 drawCell(painter, opt, index);
952 if (horizontalHeader->visualIndex(row) == 0)
953 rect.setTop(rect.top() + 1);
954 if (verticalHeader->visualIndex(row) == 0) {
955 if (q->isLeftToRight())
956 rect.setLeft(rect.left() + 1);
958 rect.setRight(rect.right() - 1);
962 for (
int r = span->top(); r <= span->bottom(); ++r) {
963 const int vr = visualRow(r);
964 if (vr < firstVisualRow || vr > lastVisualRow)
966 for (
int c = span->left(); c <= span->right(); ++c) {
967 const int vc = visualColumn(c);
968 if (vc < firstVisualColumn || vc > lastVisualColumn)
970 drawn->setBit((vr - firstVisualRow) * (lastVisualColumn - firstVisualColumn + 1)
971 + vc - firstVisualColumn);
976 painter->setClipRegion(region);
1117int QTableViewPrivate::heightHintForIndex(
const QModelIndex &index,
int hint, QStyleOptionViewItem &option)
const
1119 Q_Q(
const QTableView);
1120 QWidget *editor = editorForIndex(index).widget.data();
1121 if (editor && persistent.contains(editor)) {
1122 hint = qMax(hint, editor->sizeHint().height());
1123 int min = editor->minimumSize().height();
1124 int max = editor->maximumSize().height();
1125 hint = qBound(min, hint, max);
1129 option.rect.setY(q->rowViewportPosition(index.row()));
1130 int height = q->rowHeight(index.row());
1139 option.rect.setHeight(height);
1140 option.rect.setX(q->columnViewportPosition(index.column()));
1141 option.rect.setWidth(q->columnWidth(index.column()));
1143 auto span = spans.spanAt(index.column(), index.row());
1144 if (span && span->m_left == index.column() && span->m_top == index.row()) {
1145 option.rect.setWidth(std::max(option.rect.width(),
1146 columnSpanWidth(span->m_left, span->width())));
1151 option.rect.setWidth(option.rect.width() - 1);
1153 hint = qMax(hint, q->itemDelegateForIndex(index)->sizeHint(option, index).height());
1394void QTableView::setHorizontalHeader(QHeaderView *header)
1398 if (!header || header == d->horizontalHeader)
1400 for (QMetaObject::Connection &connection : d->horHeaderConnections)
1401 disconnect(connection);
1402 if (d->horizontalHeader && d->horizontalHeader->parent() ==
this)
1403 delete d->horizontalHeader;
1404 d->horizontalHeader = header;
1405 d->horizontalHeader->setParent(
this);
1406 d->horizontalHeader->setFirstSectionMovable(
true);
1407 if (!d->horizontalHeader->model()) {
1408 d->horizontalHeader->setModel(d->model);
1409 if (d->selectionModel)
1410 d->horizontalHeader->setSelectionModel(d->selectionModel);
1413 d->horHeaderConnections = {
1414 connect(d->horizontalHeader,&QHeaderView::sectionResized,
1415 this, &QTableView::columnResized),
1416 connect(d->horizontalHeader, &QHeaderView::sectionMoved,
1417 this, &QTableView::columnMoved),
1418 connect(d->horizontalHeader, &QHeaderView::sectionCountChanged,
1419 this, &QTableView::columnCountChanged),
1420 connect(d->horizontalHeader, &QHeaderView::sectionHandleDoubleClicked,
1421 this, &QTableView::resizeColumnToContents),
1422 connect(d->horizontalHeader, &QHeaderView::geometriesChanged,
1423 this, &QTableView::updateGeometries),
1426 setSortingEnabled(d->sortingEnabled);
1434void QTableView::setVerticalHeader(QHeaderView *header)
1438 if (!header || header == d->verticalHeader)
1440 for (QMetaObject::Connection &connection : d->verHeaderConnections)
1441 disconnect(connection);
1442 if (d->verticalHeader && d->verticalHeader->parent() ==
this)
1443 delete d->verticalHeader;
1444 d->verticalHeader = header;
1445 d->verticalHeader->setParent(
this);
1446 d->verticalHeader->setFirstSectionMovable(
true);
1447 if (!d->verticalHeader->model()) {
1448 d->verticalHeader->setModel(d->model);
1449 if (d->selectionModel)
1450 d->verticalHeader->setSelectionModel(d->selectionModel);
1453 d->verHeaderConnections = {
1454 connect(d->verticalHeader, &QHeaderView::sectionResized,
1455 this, &QTableView::rowResized),
1456 connect(d->verticalHeader, &QHeaderView::sectionMoved,
1457 this, &QTableView::rowMoved),
1458 connect(d->verticalHeader, &QHeaderView::sectionCountChanged,
1459 this, &QTableView::rowCountChanged),
1460 connect(d->verticalHeader, &QHeaderView::sectionPressed,
1461 this, &QTableView::selectRow),
1462 connect(d->verticalHeader, &QHeaderView::sectionHandleDoubleClicked,
1463 this, &QTableView::resizeRowToContents),
1464 connect(d->verticalHeader, &QHeaderView::geometriesChanged,
1465 this, &QTableView::updateGeometries),
1466 connect(d->verticalHeader, &QHeaderView::sectionEntered,
1467 this, [d](
int row) { d->selectRow(row,
false); })
1476void QTableView::scrollContentsBy(
int dx,
int dy)
1480 d->delayedAutoScroll.stop();
1482 dx = isRightToLeft() ? -dx : dx;
1484 int oldOffset = d->horizontalHeader->offset();
1485 d->horizontalHeader->d_func()->setScrollOffset(horizontalScrollBar(), horizontalScrollMode());
1486 if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) {
1487 int newOffset = d->horizontalHeader->offset();
1488 dx = isRightToLeft() ? newOffset - oldOffset : oldOffset - newOffset;
1492 int oldOffset = d->verticalHeader->offset();
1493 d->verticalHeader->d_func()->setScrollOffset(verticalScrollBar(), verticalScrollMode());
1494 if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) {
1495 int newOffset = d->verticalHeader->offset();
1496 dy = oldOffset - newOffset;
1499 d->scrollContentsBy(dx, dy);
1505 if (dy > 0 && d->horizontalHeader->isHidden()) {
1506 d->viewport->update(0, dy, d->viewport->width(), dy);
1508 if (dx > 0 && d->verticalHeader->isHidden()) {
1509 d->viewport->update(dx, 0, dx, d->viewport->height());
1526void QTableView::paintEvent(QPaintEvent *event)
1530 QStyleOptionViewItem option;
1531 initViewItemOption(&option);
1532 const QPoint offset = d->scrollDelayOffset;
1533 const bool showGrid = d->showGrid;
1534 const int gridSize = showGrid ? 1 : 0;
1535 const int gridHint = style()->styleHint(QStyle::SH_Table_GridLineColor, &option,
this);
1536 const QColor gridColor = QColor::fromRgba(
static_cast<QRgb>(gridHint));
1537 const QPen gridPen = QPen(gridColor, 1, d->gridStyle);
1538 const QHeaderView *verticalHeader = d->verticalHeader;
1539 const QHeaderView *horizontalHeader = d->horizontalHeader;
1540 const bool alternate = d->alternatingColors;
1541 const bool rightToLeft = isRightToLeft();
1543 QPainter painter(d->viewport);
1546 if (horizontalHeader->count() == 0 || verticalHeader->count() == 0 || !d->itemDelegate)
1549 const int x = horizontalHeader->length() - horizontalHeader->offset() - (rightToLeft ? 0 : 1);
1550 const int y = verticalHeader->length() - verticalHeader->offset() - 1;
1554 int firstVisualRow = qMax(verticalHeader->visualIndexAt(0),0);
1555 int lastVisualRow = verticalHeader->visualIndexAt(verticalHeader->height());
1556 if (lastVisualRow == -1)
1557 lastVisualRow = d->model->rowCount(d->root) - 1;
1559 int firstVisualColumn = horizontalHeader->visualIndexAt(0);
1560 int lastVisualColumn = horizontalHeader->visualIndexAt(horizontalHeader->width());
1562 qSwap(firstVisualColumn, lastVisualColumn);
1563 if (firstVisualColumn == -1)
1564 firstVisualColumn = 0;
1565 if (lastVisualColumn == -1)
1566 lastVisualColumn = horizontalHeader->count() - 1;
1568 QBitArray drawn((lastVisualRow - firstVisualRow + 1) * (lastVisualColumn - firstVisualColumn + 1));
1570 const QRegion region = event->region().translated(offset);
1572 if (d->hasSpans()) {
1573 d->drawAndClipSpans(region, &painter, option, &drawn,
1574 firstVisualRow, lastVisualRow, firstVisualColumn, lastVisualColumn);
1577 for (QRect dirtyArea : region) {
1578 dirtyArea.setBottom(qMin(dirtyArea.bottom(),
int(y)));
1580 dirtyArea.setLeft(qMax(dirtyArea.left(), d->viewport->width() -
int(x)));
1582 dirtyArea.setRight(qMin(dirtyArea.right(),
int(x)));
1585 if (!dirtyArea.isValid())
1589 int left = horizontalHeader->visualIndexAt(dirtyArea.left());
1590 int right = horizontalHeader->visualIndexAt(dirtyArea.right());
1593 if (left == -1) left = 0;
1594 if (right == -1) right = horizontalHeader->count() - 1;
1597 int bottom = verticalHeader->visualIndexAt(dirtyArea.bottom());
1598 if (bottom == -1) bottom = verticalHeader->count() - 1;
1600 bool alternateBase =
false;
1601 if (alternate && verticalHeader->sectionsHidden()) {
1602 const int verticalOffset = verticalHeader->offset();
1603 int row = verticalHeader->logicalIndex(top);
1605 ((y += verticalHeader->sectionSize(top)) <= verticalOffset) && (top < bottom);
1607 row = verticalHeader->logicalIndex(top);
1608 if (alternate && !verticalHeader->isSectionHidden(row))
1609 alternateBase = !alternateBase;
1612 top = verticalHeader->visualIndexAt(dirtyArea.top());
1613 alternateBase = (top & 1) && alternate;
1615 if (top == -1 || top > bottom)
1619 for (
int visualRowIndex = top; visualRowIndex <= bottom; ++visualRowIndex) {
1620 int row = verticalHeader->logicalIndex(visualRowIndex);
1621 if (verticalHeader->isSectionHidden(row))
1623 int rowY = rowViewportPosition(row);
1625 int rowh = rowHeight(row) - gridSize;
1628 for (
int visualColumnIndex = left; visualColumnIndex <= right; ++visualColumnIndex) {
1629 int currentBit = (visualRowIndex - firstVisualRow) * (lastVisualColumn - firstVisualColumn + 1)
1630 + visualColumnIndex - firstVisualColumn;
1632 if (currentBit < 0 || currentBit >= drawn.size() || drawn.testBit(currentBit))
1634 drawn.setBit(currentBit);
1636 int col = horizontalHeader->logicalIndex(visualColumnIndex);
1637 if (horizontalHeader->isSectionHidden(col))
1639 int colp = columnViewportPosition(col);
1641 int colw = columnWidth(col) - gridSize;
1643 const QModelIndex index = d->model->index(row, col, d->root);
1644 if (index.isValid()) {
1645 option.rect = QRect(colp + (showGrid && rightToLeft ? 1 : 0), rowY, colw, rowh);
1648 option.features |= QStyleOptionViewItem::Alternate;
1650 option.features &= ~QStyleOptionViewItem::Alternate;
1652 d->drawCell(&painter, option, index);
1655 alternateBase = !alternateBase && alternate;
1660 while (verticalHeader->isSectionHidden(verticalHeader->logicalIndex(bottom))) --bottom;
1661 QPen old = painter.pen();
1662 painter.setPen(gridPen);
1664 for (
int visualIndex = top; visualIndex <= bottom; ++visualIndex) {
1665 int row = verticalHeader->logicalIndex(visualIndex);
1666 if (verticalHeader->isSectionHidden(row))
1668 int rowY = rowViewportPosition(row);
1670 int rowh = rowHeight(row) - gridSize;
1671 QLineF line(dirtyArea.left(), rowY + rowh, dirtyArea.right(), rowY + rowh);
1672 painter.drawLine(line.translated(0.5, 0.5));
1676 for (
int h = left; h <= right; ++h) {
1677 int col = horizontalHeader->logicalIndex(h);
1678 if (horizontalHeader->isSectionHidden(col))
1680 int colp = columnViewportPosition(col);
1683 colp += columnWidth(col) - gridSize;
1684 QLineF line(colp, dirtyArea.top(), colp, dirtyArea.bottom());
1685 painter.drawLine(line.translated(0.5, 0.5));
1687 const bool drawWhenHidden = style()->styleHint(QStyle::SH_Table_AlwaysDrawLeftTopGridLines,
1689 if (drawWhenHidden && horizontalHeader->isHidden()) {
1690 const int row = verticalHeader->logicalIndex(top);
1691 if (!verticalHeader->isSectionHidden(row)) {
1692 const int rowY = rowViewportPosition(row) + offset.y();
1693 if (rowY == dirtyArea.top())
1694 painter.drawLine(dirtyArea.left(), rowY, dirtyArea.right(), rowY);
1697 if (drawWhenHidden && verticalHeader->isHidden()) {
1698 const int col = horizontalHeader->logicalIndex(left);
1699 if (!horizontalHeader->isSectionHidden(col)) {
1700 int colX = columnViewportPosition(col) + offset.x();
1701 if (!isLeftToRight())
1702 colX += columnWidth(left) - 1;
1703 if (isLeftToRight() && colX == dirtyArea.left())
1704 painter.drawLine(colX, dirtyArea.top(), colX, dirtyArea.bottom());
1705 if (!isLeftToRight() && colX == dirtyArea.right())
1706 painter.drawLine(colX, dirtyArea.top(), colX, dirtyArea.bottom());
1709 painter.setPen(old);
1713#if QT_CONFIG(draganddrop)
1715 d->paintDropIndicator(&painter);
1776QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
1779 Q_UNUSED(modifiers);
1781 int bottom = d->model->rowCount(d->root) - 1;
1783 while (bottom >= 0 && isRowHidden(d->logicalRow(bottom)))
1786 int right = d->model->columnCount(d->root) - 1;
1788 while (right >= 0 && isColumnHidden(d->logicalColumn(right)))
1791 if (bottom == -1 || right == -1)
1792 return QModelIndex();
1794 QModelIndex current = currentIndex();
1796 if (!current.isValid()) {
1799 while (column < right && isColumnHidden(d->logicalColumn(column)))
1801 while (isRowHidden(d->logicalRow(row)) && row < bottom)
1803 d->visualCursor = QPoint(column, row);
1804 return d->model->index(d->logicalRow(row), d->logicalColumn(column), d->root);
1808 QPoint visualCurrent(d->visualColumn(current.column()), d->visualRow(current.row()));
1809 if (visualCurrent != d->visualCursor) {
1810 if (d->hasSpans()) {
1811 QSpanCollection::Span span = d->span(current.row(), current.column());
1812 if (span.top() > d->visualCursor.y() || d->visualCursor.y() > span.bottom()
1813 || span.left() > d->visualCursor.x() || d->visualCursor.x() > span.right())
1814 d->visualCursor = visualCurrent;
1816 d->visualCursor = visualCurrent;
1820 int visualRow = d->visualCursor.y();
1821 if (visualRow > bottom)
1823 Q_ASSERT(visualRow != -1);
1824 int visualColumn = d->visualCursor.x();
1825 if (visualColumn > right)
1826 visualColumn = right;
1827 Q_ASSERT(visualColumn != -1);
1829 if (isRightToLeft()) {
1830 if (cursorAction == MoveLeft)
1831 cursorAction = MoveRight;
1832 else if (cursorAction == MoveRight)
1833 cursorAction = MoveLeft;
1836 switch (cursorAction) {
1838 int originalRow = visualRow;
1839 int r = d->logicalRow(visualRow);
1840 int c = d->logicalColumn(visualColumn);
1841 if (r != -1 && d->hasSpans()) {
1842 QSpanCollection::Span span = d->span(r, c);
1843 if (span.width() > 1 || span.height() > 1)
1844 visualRow = d->visualRow(span.top());
1846 while (visualRow >= 0) {
1848 r = d->logicalRow(visualRow);
1849 c = d->logicalColumn(visualColumn);
1850 if (r == -1 || (!isRowHidden(r) && d->isCellEnabled(r, c)))
1854 visualRow = originalRow;
1858 int originalRow = visualRow;
1859 if (d->hasSpans()) {
1860 QSpanCollection::Span span = d->span(current.row(), current.column());
1861 visualRow = d->visualRow(d->rowSpanEndLogical(span.top(), span.height()));
1863 int r = d->logicalRow(visualRow);
1864 int c = d->logicalColumn(visualColumn);
1865 if (r != -1 && d->hasSpans()) {
1866 QSpanCollection::Span span = d->span(r, c);
1867 if (span.width() > 1 || span.height() > 1)
1868 visualRow = d->visualRow(d->rowSpanEndLogical(span.top(), span.height()));
1870 while (visualRow <= bottom) {
1872 r = d->logicalRow(visualRow);
1873 c = d->logicalColumn(visualColumn);
1874 if (r == -1 || (!isRowHidden(r) && d->isCellEnabled(r, c)))
1877 if (visualRow > bottom)
1878 visualRow = originalRow;
1883 int originalRow = visualRow;
1884 int originalColumn = visualColumn;
1885 bool firstTime =
true;
1886 bool looped =
false;
1887 bool wrapped =
false;
1889 int r = d->logicalRow(visualRow);
1890 int c = d->logicalColumn(visualColumn);
1891 if (firstTime && c != -1 && d->hasSpans()) {
1893 QSpanCollection::Span span = d->span(r, c);
1894 if (span.width() > 1 || span.height() > 1)
1895 visualColumn = d->visualColumn(span.left());
1897 while (visualColumn >= 0) {
1899 r = d->logicalRow(visualRow);
1900 c = d->logicalColumn(visualColumn);
1901 if (r == -1 || c == -1 || (!isRowHidden(r) && !isColumnHidden(c) && d->isCellEnabled(r, c)))
1903 if (wrapped && (originalRow < visualRow || (originalRow == visualRow && originalColumn <= visualColumn))) {
1908 if (cursorAction == MoveLeft || visualColumn >= 0)
1910 visualColumn = right + 1;
1911 if (visualRow == 0) {
1918 if (visualColumn < 0)
1919 visualColumn = originalColumn;
1924 int originalRow = visualRow;
1925 int originalColumn = visualColumn;
1926 bool firstTime =
true;
1927 bool looped =
false;
1928 bool wrapped =
false;
1930 int r = d->logicalRow(visualRow);
1931 int c = d->logicalColumn(visualColumn);
1932 if (firstTime && c != -1 && d->hasSpans()) {
1934 QSpanCollection::Span span = d->span(r, c);
1935 if (span.width() > 1 || span.height() > 1)
1936 visualColumn = d->visualColumn(d->columnSpanEndLogical(span.left(), span.width()));
1938 while (visualColumn <= right) {
1940 r = d->logicalRow(visualRow);
1941 c = d->logicalColumn(visualColumn);
1942 if (r == -1 || c == -1 || (!isRowHidden(r) && !isColumnHidden(c) && d->isCellEnabled(r, c)))
1944 if (wrapped && (originalRow > visualRow || (originalRow == visualRow && originalColumn >= visualColumn))) {
1949 if (cursorAction == MoveRight || visualColumn <= right)
1952 if (visualRow == bottom) {
1959 if (visualColumn > right)
1960 visualColumn = originalColumn;
1964 visualColumn = d->nextActiveVisualColumn(visualRow, 0, right,
1965 QTableViewPrivate::SearchDirection::Increasing);
1966 if (modifiers & Qt::ControlModifier)
1967 visualRow = d->nextActiveVisualRow(0, visualColumn, bottom,
1968 QTableViewPrivate::SearchDirection::Increasing);
1971 visualColumn = d->nextActiveVisualColumn(visualRow, right, -1,
1972 QTableViewPrivate::SearchDirection::Decreasing);
1973 if (modifiers & Qt::ControlModifier)
1974 visualRow = d->nextActiveVisualRow(bottom, visualColumn, -1,
1975 QTableViewPrivate::SearchDirection::Decreasing);
1978 int newLogicalRow = rowAt(visualRect(current).bottom() - d->viewport->height());
1979 int visualRow = (newLogicalRow == -1 ? 0 : d->visualRow(newLogicalRow));
1980 visualRow = d->nextActiveVisualRow(visualRow, current.column(), bottom,
1981 QTableViewPrivate::SearchDirection::Increasing);
1982 newLogicalRow = d->logicalRow(visualRow);
1983 return d->model->index(newLogicalRow, current.column(), d->root);
1985 case MovePageDown: {
1986 int newLogicalRow = rowAt(visualRect(current).top() + d->viewport->height());
1987 int visualRow = (newLogicalRow == -1 ? bottom : d->visualRow(newLogicalRow));
1988 visualRow = d->nextActiveVisualRow(visualRow, current.column(), -1,
1989 QTableViewPrivate::SearchDirection::Decreasing);
1990 newLogicalRow = d->logicalRow(visualRow);
1991 return d->model->index(newLogicalRow, current.column(), d->root);
1994 d->visualCursor = QPoint(visualColumn, visualRow);
1995 int logicalRow = d->logicalRow(visualRow);
1996 int logicalColumn = d->logicalColumn(visualColumn);
1997 if (!d->model->hasIndex(logicalRow, logicalColumn, d->root))
1998 return QModelIndex();
2000 QModelIndex result = d->model->index(logicalRow, logicalColumn, d->root);
2001 if (!d->isRowHidden(logicalRow) && !d->isColumnHidden(logicalColumn) && d->isIndexEnabled(result)) {
2002 if (d->hasSpans()) {
2003 QSpanCollection::Span span = d->span(result.row(), result.column());
2004 if (span.width() > 1 || span.height() > 1) {
2005 result = d->model->sibling(span.top(), span.left(), result);
2011 return QModelIndex();
2021void QTableView::setSelection(
const QRect &rect, QItemSelectionModel::SelectionFlags command)
2024 QModelIndex tl = indexAt(QPoint(isRightToLeft() ? qMax(rect.left(), rect.right())
2025 : qMin(rect.left(), rect.right()), qMin(rect.top(), rect.bottom())));
2026 QModelIndex br = indexAt(QPoint(isRightToLeft() ? qMin(rect.left(), rect.right()) :
2027 qMax(rect.left(), rect.right()), qMax(rect.top(), rect.bottom())));
2028 if (!d->selectionModel || !tl.isValid() || !br.isValid() || !d->isIndexEnabled(tl) || !d->isIndexEnabled(br))
2031 const bool verticalMoved = verticalHeader()->sectionsMoved();
2032 const bool horizontalMoved = horizontalHeader()->sectionsMoved();
2034 QItemSelection selection;
2036 int bottom = br.row();
2037 int left = tl.column();
2038 int right = br.column();
2040 const auto updateVisualIndices = [&]() {
2041 if (verticalMoved && horizontalMoved) {
2042 top = d->visualRow(tl.row());
2043 bottom = d->visualRow(br.row());
2044 left = d->visualColumn(tl.column());
2045 right = d->visualColumn(br.column());
2046 }
else if (horizontalMoved) {
2049 left = d->visualColumn(tl.column());
2050 right = d->visualColumn(br.column());
2051 }
else if (verticalMoved) {
2052 top = d->visualRow(tl.row());
2053 bottom = d->visualRow(br.row());
2055 right = br.column();
2059 if (d->hasSpans()) {
2063 bool intersectsSpan =
false;
2064 top = qMin(d->visualRow(tl.row()), d->visualRow(br.row()));
2065 left = qMin(d->visualColumn(tl.column()), d->visualColumn(br.column()));
2066 bottom = qMax(d->visualRow(tl.row()), d->visualRow(br.row()));
2067 right = qMax(d->visualColumn(tl.column()), d->visualColumn(br.column()));
2070 for (QSpanCollection::Span *it : d->spans.spans) {
2071 const QSpanCollection::Span &span = *it;
2072 const int t = d->visualRow(span.top());
2073 const int l = d->visualColumn(span.left());
2074 const int b = d->visualRow(d->rowSpanEndLogical(span.top(), span.height()));
2075 const int r = d->visualColumn(d->columnSpanEndLogical(span.left(), span.width()));
2076 if ((t > bottom) || (l > right) || (top > b) || (left > r))
2078 intersectsSpan =
true;
2099 if (!intersectsSpan) {
2100 updateVisualIndices();
2101 }
else if (!verticalMoved && !horizontalMoved) {
2103 tl = d->model->index(top, left, d->root);
2104 br = d->model->index(bottom, right, d->root);
2107 updateVisualIndices();
2110 if (horizontalMoved && verticalMoved) {
2111 selection.reserve((right - left + 1) * (bottom - top + 1));
2112 for (
int horizontal = left; horizontal <= right; ++horizontal) {
2113 int column = d->logicalColumn(horizontal);
2114 for (
int vertical = top; vertical <= bottom; ++vertical) {
2115 int row = d->logicalRow(vertical);
2116 QModelIndex index = d->model->index(row, column, d->root);
2117 selection.append(QItemSelectionRange(index));
2120 }
else if (horizontalMoved) {
2121 selection.reserve(right - left + 1);
2122 for (
int visual = left; visual <= right; ++visual) {
2123 int column = d->logicalColumn(visual);
2124 QModelIndex topLeft = d->model->index(top, column, d->root);
2126 selection.append(QItemSelectionRange(topLeft));
2128 selection.append({ topLeft, topLeft.siblingAtRow(bottom) });
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);
2136 selection.append(QItemSelectionRange(topLeft));
2138 selection.append({ topLeft, topLeft.siblingAtColumn(right) });
2141 QItemSelectionRange range(tl, br);
2142 if (!range.isEmpty())
2143 selection.append(range);
2146 d->selectionModel->select(selection, command);
2158QRegion QTableView::visualRegionForSelection(
const QItemSelection &selection)
const
2160 Q_D(
const QTableView);
2162 if (selection.isEmpty())
2165 QRegion selectionRegion;
2166 const QRect &viewportRect = d->viewport->rect();
2167 bool verticalMoved = verticalHeader()->sectionsMoved();
2168 bool horizontalMoved = horizontalHeader()->sectionsMoved();
2170 if ((verticalMoved && horizontalMoved) || (d->hasSpans() && (verticalMoved || horizontalMoved))) {
2171 for (
const auto &range : selection) {
2172 if (range.parent() != d->root || !range.isValid())
2174 for (
int r = range.top(); r <= range.bottom(); ++r)
2175 for (
int c = range.left(); c <= range.right(); ++c) {
2176 const QRect &rangeRect = visualRect(d->model->index(r, c, d->root));
2177 if (viewportRect.intersects(rangeRect))
2178 selectionRegion += rangeRect;
2181 }
else if (horizontalMoved) {
2182 for (
const auto &range : selection) {
2183 if (range.parent() != d->root || !range.isValid())
2185 int top = rowViewportPosition(range.top());
2186 int bottom = rowViewportPosition(range.bottom()) + rowHeight(range.bottom());
2188 qSwap<
int>(top, bottom);
2189 int height = bottom - top;
2190 for (
int c = range.left(); c <= range.right(); ++c) {
2191 const QRect rangeRect(columnViewportPosition(c), top, columnWidth(c), height);
2192 if (viewportRect.intersects(rangeRect))
2193 selectionRegion += rangeRect;
2196 }
else if (verticalMoved) {
2197 for (
const auto &range : selection) {
2198 if (range.parent() != d->root || !range.isValid())
2200 int left = columnViewportPosition(range.left());
2201 int right = columnViewportPosition(range.right()) + columnWidth(range.right());
2203 qSwap<
int>(left, right);
2204 int width = right - left;
2205 for (
int r = range.top(); r <= range.bottom(); ++r) {
2206 const QRect rangeRect(left, rowViewportPosition(r), width, rowHeight(r));
2207 if (viewportRect.intersects(rangeRect))
2208 selectionRegion += rangeRect;
2212 const int gridAdjust = showGrid() ? 1 : 0;
2213 for (
auto range : selection) {
2214 if (range.parent() != d->root || !range.isValid())
2216 d->trimHiddenSelections(&range);
2218 const int rtop = rowViewportPosition(range.top());
2219 const int rbottom = rowViewportPosition(range.bottom()) + rowHeight(range.bottom());
2222 if (isLeftToRight()) {
2223 rleft = columnViewportPosition(range.left());
2224 rright = columnViewportPosition(range.right()) + columnWidth(range.right());
2226 rleft = columnViewportPosition(range.right());
2227 rright = columnViewportPosition(range.left()) + columnWidth(range.left());
2229 const QRect rangeRect(QPoint(rleft, rtop), QPoint(rright - 1 - gridAdjust, rbottom - 1 - gridAdjust));
2230 if (viewportRect.intersects(rangeRect))
2231 selectionRegion += rangeRect;
2232 if (d->hasSpans()) {
2233 const auto spansInRect = d->spans.spansInRect(range.left(), range.top(), range.width(), range.height());
2234 for (QSpanCollection::Span *s : spansInRect) {
2235 if (range.contains(s->top(), s->left(), range.parent())) {
2236 const QRect &visualSpanRect = d->visualSpanRect(*s);
2237 if (viewportRect.intersects(visualSpanRect))
2238 selectionRegion += visualSpanRect;
2245 return selectionRegion;
2302void QTableView::updateGeometries()
2305 if (d->geometryRecursionBlock)
2307 d->geometryRecursionBlock =
true;
2310 if (!d->verticalHeader->isHidden()) {
2311 width = qMax(d->verticalHeader->minimumWidth(), d->verticalHeader->sizeHint().width());
2312 width = qMin(width, d->verticalHeader->maximumWidth());
2315 if (!d->horizontalHeader->isHidden()) {
2316 height = qMax(d->horizontalHeader->minimumHeight(), d->horizontalHeader->sizeHint().height());
2317 height = qMin(height, d->horizontalHeader->maximumHeight());
2319 bool reverse = isRightToLeft();
2321 setViewportMargins(0, height, width, 0);
2323 setViewportMargins(width, height, 0, 0);
2327 QRect vg = d->viewport->geometry();
2329 int verticalLeft = reverse ? vg.right() + 1 : (vg.left() - width);
2330 d->verticalHeader->setGeometry(verticalLeft, vg.top(), width, vg.height());
2331 if (d->verticalHeader->isHidden())
2332 QMetaObject::invokeMethod(d->verticalHeader,
"updateGeometries");
2334 int horizontalTop = vg.top() - height;
2335 d->horizontalHeader->setGeometry(vg.left(), horizontalTop, vg.width(), height);
2336 if (d->horizontalHeader->isHidden())
2337 QMetaObject::invokeMethod(d->horizontalHeader,
"updateGeometries");
2339#if QT_CONFIG(abstractbutton)
2341 if (d->horizontalHeader->isHidden() || d->verticalHeader->isHidden()) {
2342 d->cornerWidget->setHidden(
true);
2344 d->cornerWidget->setHidden(
false);
2345 d->cornerWidget->setGeometry(verticalLeft, horizontalTop, width, height);
2352 QSize vsize = d->viewport->size();
2353 QSize max = maximumViewportSize();
2354 const int horizontalLength = d->horizontalHeader->length();
2355 const int verticalLength = d->verticalHeader->length();
2356 if (max.width() >= horizontalLength && max.height() >= verticalLength)
2360 const int columnCount = d->horizontalHeader->count();
2361 const int viewportWidth = vsize.width();
2362 int columnsInViewport = 0;
2363 for (
int width = 0, column = columnCount - 1; column >= 0; --column) {
2364 int logical = d->horizontalHeader->logicalIndex(column);
2365 if (!d->horizontalHeader->isSectionHidden(logical)) {
2366 width += d->horizontalHeader->sectionSize(logical);
2367 if (width > viewportWidth)
2369 ++columnsInViewport;
2372 columnsInViewport = qMax(columnsInViewport, 1);
2374 if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) {
2375 const int visibleColumns = columnCount - d->horizontalHeader->hiddenSectionCount();
2376 horizontalScrollBar()->setRange(0, visibleColumns - columnsInViewport);
2377 horizontalScrollBar()->setPageStep(columnsInViewport);
2378 if (columnsInViewport >= visibleColumns)
2379 d->horizontalHeader->setOffset(0);
2380 horizontalScrollBar()->setSingleStep(1);
2382 horizontalScrollBar()->setPageStep(vsize.width());
2383 horizontalScrollBar()->setRange(0, horizontalLength - vsize.width());
2384 horizontalScrollBar()->d_func()->itemviewChangeSingleStep(qMax(vsize.width() / (columnsInViewport + 1), 2));
2388 const int rowCount = d->verticalHeader->count();
2389 const int viewportHeight = vsize.height();
2390 int rowsInViewport = 0;
2391 for (
int height = 0, row = rowCount - 1; row >= 0; --row) {
2392 int logical = d->verticalHeader->logicalIndex(row);
2393 if (!d->verticalHeader->isSectionHidden(logical)) {
2394 height += d->verticalHeader->sectionSize(logical);
2395 if (height > viewportHeight)
2400 rowsInViewport = qMax(rowsInViewport, 1);
2402 if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) {
2403 const int visibleRows = rowCount - d->verticalHeader->hiddenSectionCount();
2404 verticalScrollBar()->setRange(0, visibleRows - rowsInViewport);
2405 verticalScrollBar()->setPageStep(rowsInViewport);
2406 if (rowsInViewport >= visibleRows)
2407 d->verticalHeader->setOffset(0);
2408 verticalScrollBar()->setSingleStep(1);
2410 verticalScrollBar()->setPageStep(vsize.height());
2411 verticalScrollBar()->setRange(0, verticalLength - vsize.height());
2412 verticalScrollBar()->d_func()->itemviewChangeSingleStep(qMax(vsize.height() / (rowsInViewport + 1), 2));
2414 d->verticalHeader->d_func()->setScrollOffset(verticalScrollBar(), verticalScrollMode());
2416 d->geometryRecursionBlock =
false;
2417 QAbstractItemView::updateGeometries();
2434int QTableView::sizeHintForRow(
int row)
const
2436 Q_D(
const QTableView);
2442 const int maximumProcessCols = d->verticalHeader->resizeContentsPrecision();
2445 int left = qMax(0, d->horizontalHeader->visualIndexAt(0));
2446 int right = d->horizontalHeader->visualIndexAt(d->viewport->width());
2448 right = d->model->columnCount(d->root) - 1;
2450 QStyleOptionViewItem option;
2451 initViewItemOption(&option);
2455 int columnsProcessed = 0;
2457 for (; column <= right; ++column) {
2458 int logicalColumn = d->horizontalHeader->logicalIndex(column);
2459 if (d->horizontalHeader->isSectionHidden(logicalColumn))
2461 index = d->model->index(row, logicalColumn, d->root);
2462 hint = d->heightHintForIndex(index, hint, option);
2465 if (columnsProcessed == maximumProcessCols)
2469 const int actualRight = d->model->columnCount(d->root) - 1;
2471 int idxRight = column - 1;
2473 if (maximumProcessCols == 0 || actualRight < idxLeft)
2474 columnsProcessed = maximumProcessCols;
2476 while (columnsProcessed != maximumProcessCols && (idxLeft > 0 || idxRight < actualRight)) {
2477 int logicalIdx = -1;
2479 if ((columnsProcessed % 2 && idxLeft > 0) || idxRight == actualRight) {
2480 while (idxLeft > 0) {
2482 int logcol = d->horizontalHeader->logicalIndex(idxLeft);
2483 if (d->horizontalHeader->isSectionHidden(logcol))
2485 logicalIdx = logcol;
2489 while (idxRight < actualRight) {
2491 int logcol = d->horizontalHeader->logicalIndex(idxRight);
2492 if (d->horizontalHeader->isSectionHidden(logcol))
2494 logicalIdx = logcol;
2498 if (logicalIdx >= 0) {
2499 index = d->model->index(row, logicalIdx, d->root);
2500 hint = d->heightHintForIndex(index, hint, option);
2505 return d->showGrid ? hint + 1 : hint;
2523int QTableView::sizeHintForColumn(
int column)
const
2525 Q_D(
const QTableView);
2531 const int maximumProcessRows = d->horizontalHeader->resizeContentsPrecision();
2533 int top = qMax(0, d->verticalHeader->visualIndexAt(0));
2534 int bottom = d->verticalHeader->visualIndexAt(d->viewport->height());
2535 if (!isVisible() || bottom == -1)
2536 bottom = d->model->rowCount(d->root) - 1;
2538 QStyleOptionViewItem option;
2539 initViewItemOption(&option);
2542 int rowsProcessed = 0;
2545 for (; row <= bottom; ++row) {
2546 int logicalRow = d->verticalHeader->logicalIndex(row);
2547 if (d->verticalHeader->isSectionHidden(logicalRow))
2549 index = d->model->index(logicalRow, column, d->root);
2551 hint = d->widthHintForIndex(index, hint, option);
2553 if (rowsProcessed == maximumProcessRows)
2557 const int actualBottom = d->model->rowCount(d->root) - 1;
2559 int idxBottom = row - 1;
2561 if (maximumProcessRows == 0 || actualBottom < idxTop)
2562 rowsProcessed = maximumProcessRows;
2564 while (rowsProcessed != maximumProcessRows && (idxTop > 0 || idxBottom < actualBottom)) {
2565 int logicalIdx = -1;
2567 if ((rowsProcessed % 2 && idxTop > 0) || idxBottom == actualBottom) {
2568 while (idxTop > 0) {
2570 int logrow = d->verticalHeader->logicalIndex(idxTop);
2571 if (d->verticalHeader->isSectionHidden(logrow))
2573 logicalIdx = logrow;
2577 while (idxBottom < actualBottom) {
2579 int logrow = d->verticalHeader->logicalIndex(idxBottom);
2580 if (d->verticalHeader->isSectionHidden(logrow))
2582 logicalIdx = logrow;
2586 if (logicalIdx >= 0) {
2587 index = d->model->index(logicalIdx, column, d->root);
2588 hint = d->widthHintForIndex(index, hint, option);
2593 return d->showGrid ? hint + 1 : hint;
2919void QTableView::scrollTo(
const QModelIndex &index, ScrollHint hint)
2924 if (!d->isIndexValid(index)
2925 || (d->model->parent(index) != d->root)
2926 || isRowHidden(index.row()) || isColumnHidden(index.column()))
2929 QSpanCollection::Span span;
2931 span = d->span(index.row(), index.column());
2935 int viewportWidth = d->viewport->width();
2936 int horizontalOffset = d->horizontalHeader->offset();
2937 int horizontalPosition = d->horizontalHeader->sectionPosition(index.column());
2938 int horizontalIndex = d->horizontalHeader->visualIndex(index.column());
2939 int cellWidth = d->hasSpans()
2940 ? d->columnSpanWidth(index.column(), span.width())
2941 : d->horizontalHeader->sectionSize(index.column());
2943 if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) {
2945 bool positionAtLeft = (horizontalPosition - horizontalOffset < 0);
2946 bool positionAtRight = (horizontalPosition - horizontalOffset + cellWidth > viewportWidth);
2948 if (hint == PositionAtCenter || positionAtRight) {
2949 int w = (hint == PositionAtCenter ? viewportWidth / 2 : viewportWidth);
2951 while (horizontalIndex > 0) {
2952 x += columnWidth(d->horizontalHeader->logicalIndex(horizontalIndex-1));
2959 if (positionAtRight || hint == PositionAtCenter || positionAtLeft) {
2960 int hiddenSections = 0;
2961 if (d->horizontalHeader->sectionsHidden()) {
2962 for (
int s = horizontalIndex - 1; s >= 0; --s) {
2963 int column = d->horizontalHeader->logicalIndex(s);
2964 if (d->horizontalHeader->isSectionHidden(column))
2968 horizontalScrollBar()->setValue(horizontalIndex - hiddenSections);
2972 if (hint == PositionAtCenter) {
2973 horizontalScrollBar()->setValue(horizontalPosition - ((viewportWidth - cellWidth) / 2));
2975 if (horizontalPosition - horizontalOffset < 0 || cellWidth > viewportWidth)
2976 horizontalScrollBar()->setValue(horizontalPosition);
2977 else if (horizontalPosition - horizontalOffset + cellWidth > viewportWidth)
2978 horizontalScrollBar()->setValue(horizontalPosition - viewportWidth + cellWidth);
2984 int viewportHeight = d->viewport->height();
2985 int verticalOffset = d->verticalHeader->offset();
2986 int verticalPosition = d->verticalHeader->sectionPosition(index.row());
2987 int verticalIndex = d->verticalHeader->visualIndex(index.row());
2988 int cellHeight = d->hasSpans()
2989 ? d->rowSpanHeight(index.row(), span.height())
2990 : d->verticalHeader->sectionSize(index.row());
2992 if (verticalPosition - verticalOffset < 0 || cellHeight > viewportHeight) {
2993 if (hint == EnsureVisible)
2994 hint = PositionAtTop;
2995 }
else if (verticalPosition - verticalOffset + cellHeight > viewportHeight) {
2996 if (hint == EnsureVisible)
2997 hint = PositionAtBottom;
3000 if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) {
3002 if (hint == PositionAtBottom || hint == PositionAtCenter) {
3003 int h = (hint == PositionAtCenter ? viewportHeight / 2 : viewportHeight);
3005 while (verticalIndex > 0) {
3006 int row = d->verticalHeader->logicalIndex(verticalIndex - 1);
3007 y += d->verticalHeader->sectionSize(row);
3014 if (hint == PositionAtBottom || hint == PositionAtCenter || hint == PositionAtTop) {
3015 int hiddenSections = 0;
3016 if (d->verticalHeader->sectionsHidden()) {
3017 for (
int s = verticalIndex - 1; s >= 0; --s) {
3018 int row = d->verticalHeader->logicalIndex(s);
3019 if (d->verticalHeader->isSectionHidden(row))
3023 verticalScrollBar()->setValue(verticalIndex - hiddenSections);
3027 if (hint == PositionAtTop) {
3028 verticalScrollBar()->setValue(verticalPosition);
3029 }
else if (hint == PositionAtBottom) {
3030 verticalScrollBar()->setValue(verticalPosition - viewportHeight + cellHeight);
3031 }
else if (hint == PositionAtCenter) {
3032 verticalScrollBar()->setValue(verticalPosition - ((viewportHeight - cellHeight) / 2));
3072void QTableView::timerEvent(QTimerEvent *event)
3076 if (event->id() == d->columnResizeTimer.id()) {
3077 const int oldScrollMax = horizontalScrollBar()->maximum();
3078 if (horizontalHeader()->d_func()->state != QHeaderViewPrivate::ResizeSection) {
3080 d->columnResizeTimer.stop();
3082 updateEditorGeometries();
3086 int viewportHeight = d->viewport->height();
3087 int viewportWidth = d->viewport->width();
3088 if (d->hasSpans() || horizontalScrollBar()->value() == oldScrollMax) {
3089 rect = QRect(0, 0, viewportWidth, viewportHeight);
3091 for (
int i = d->columnsToUpdate.size()-1; i >= 0; --i) {
3092 int column = d->columnsToUpdate.at(i);
3093 int x = columnViewportPosition(column);
3094 if (isRightToLeft())
3095 rect |= QRect(0, 0, x + columnWidth(column), viewportHeight);
3097 rect |= QRect(x, 0, viewportWidth - x, viewportHeight);
3101 d->viewport->update(rect.normalized());
3102 d->columnsToUpdate.clear();
3105 if (event->id() == d->rowResizeTimer.id()) {
3106 const int oldScrollMax = verticalScrollBar()->maximum();
3107 if (verticalHeader()->d_func()->state != QHeaderViewPrivate::ResizeSection) {
3109 d->rowResizeTimer.stop();
3111 updateEditorGeometries();
3114 int viewportHeight = d->viewport->height();
3115 int viewportWidth = d->viewport->width();
3117 if (d->hasSpans() || verticalScrollBar()->value() == oldScrollMax) {
3120 top = viewportHeight;
3121 for (
int i = d->rowsToUpdate.size()-1; i >= 0; --i) {
3122 int y = rowViewportPosition(d->rowsToUpdate.at(i));
3127 d->viewport->update(QRect(0, top, viewportWidth, viewportHeight - top));
3128 d->rowsToUpdate.clear();
3131 QAbstractItemView::timerEvent(event);
3487void QTableViewPrivate::selectRow(
int row,
bool anchor)
3491 if (q->selectionBehavior() == QTableView::SelectColumns
3492 || (q->selectionMode() == QTableView::SingleSelection
3493 && q->selectionBehavior() == QTableView::SelectItems))
3496 if (row >= 0 && row < model->rowCount(root)) {
3497 int column = horizontalHeader->logicalIndexAt(q->isRightToLeft() ? viewport->width() : 0);
3498 QModelIndex index = model->index(row, column, root);
3499 QItemSelectionModel::SelectionFlags command = q->selectionCommand(index);
3503 const auto startIndex = currentSelectionStartIndex;
3504 selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
3505 currentSelectionStartIndex = startIndex;
3508 if ((anchor && !(command & QItemSelectionModel::Current))
3509 || (q->selectionMode() == QTableView::SingleSelection))
3510 currentSelectionStartIndex = model->index(row, column, root);
3512 if (q->selectionMode() != QTableView::SingleSelection
3513 && command.testFlag(QItemSelectionModel::Toggle)) {
3515 ctrlDragSelectionFlag = verticalHeader->selectionModel()->selectedRows(column).contains(index)
3516 ? QItemSelectionModel::Deselect : QItemSelectionModel::Select;
3517 command &= ~QItemSelectionModel::Toggle;
3518 command |= ctrlDragSelectionFlag;
3520 command |= QItemSelectionModel::Current;
3523 const auto rowSectionAnchor = currentSelectionStartIndex.row();
3524 QModelIndex upper = model->index(qMin(rowSectionAnchor, row), column, root);
3525 QModelIndex lower = model->index(qMax(rowSectionAnchor, row), column, root);
3526 if ((verticalHeader->sectionsMoved() && upper.row() != lower.row())) {
3527 q->setSelection(q->visualRect(upper) | q->visualRect(lower), command | QItemSelectionModel::Rows);
3529 selectionModel->select(QItemSelection(upper, lower), command | QItemSelectionModel::Rows);
3534void QTableViewPrivate::selectColumn(
int column,
bool anchor)
3538 if (q->selectionBehavior() == QTableView::SelectRows
3539 || (q->selectionMode() == QTableView::SingleSelection
3540 && q->selectionBehavior() == QTableView::SelectItems))
3543 if (column >= 0 && column < model->columnCount(root)) {
3544 int row = verticalHeader->logicalIndexAt(0);
3545 QModelIndex index = model->index(row, column, root);
3546 QItemSelectionModel::SelectionFlags command = q->selectionCommand(index);
3550 const auto startIndex = currentSelectionStartIndex;
3551 selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate);
3552 currentSelectionStartIndex = startIndex;
3555 if ((anchor && !(command & QItemSelectionModel::Current))
3556 || (q->selectionMode() == QTableView::SingleSelection))
3557 currentSelectionStartIndex = model->index(row, column, root);
3559 if (q->selectionMode() != QTableView::SingleSelection
3560 && command.testFlag(QItemSelectionModel::Toggle)) {
3562 ctrlDragSelectionFlag = horizontalHeader->selectionModel()->selectedColumns(row).contains(index)
3563 ? QItemSelectionModel::Deselect : QItemSelectionModel::Select;
3564 command &= ~QItemSelectionModel::Toggle;
3565 command |= ctrlDragSelectionFlag;
3567 command |= QItemSelectionModel::Current;
3570 const auto columnSectionAnchor = currentSelectionStartIndex.column();
3571 QModelIndex left = model->index(row, qMin(columnSectionAnchor, column), root);
3572 QModelIndex right = model->index(row, qMax(columnSectionAnchor, column), root);
3573 if ((horizontalHeader->sectionsMoved() && left.column() != right.column())) {
3574 q->setSelection(q->visualRect(left) | q->visualRect(right), command | QItemSelectionModel::Columns);
3576 selectionModel->select(QItemSelection(left, right), command | QItemSelectionModel::Columns);