184void QTreeView::setModel(QAbstractItemModel *model)
187 if (model == d->model)
189 if (d->model && d->model != QAbstractItemModelPrivate::staticEmptyModel()) {
190 for (
const QMetaObject::Connection &connection : d->modelConnections)
191 QObject::disconnect(connection);
194 if (d->selectionModel) {
195 QObject::disconnect(d->selectionmodelConnection);
197 d->viewItems.clear();
198 d->expandedIndexes.clear();
199 d->hiddenIndexes.clear();
200 d->geometryRecursionBlock =
true;
201 d->header->setModel(model);
202 d->geometryRecursionBlock =
false;
203 QAbstractItemView::setModel(model);
207 QObjectPrivate::disconnect(d->model, &QAbstractItemModel::rowsRemoved,
208 d, &QAbstractItemViewPrivate::rowsRemoved);
210 QObjectPrivate::disconnect(d->model, &QAbstractItemModel::layoutChanged,
211 d->header->d_func(), &QAbstractItemViewPrivate::layoutChanged);
213 d->modelConnections = {
215 QObject::connect(d->model, &QAbstractItemModel::rowsRemoved,
216 this, &QTreeView::rowsRemoved),
217 QObjectPrivate::connect(d->model, &QAbstractItemModel::modelAboutToBeReset,
218 d, &QTreeViewPrivate::modelAboutToBeReset)
221 if (d->sortingEnabled)
222 d->sortIndicatorChanged(header()->sortIndicatorSection(), header()->sortIndicatorOrder());
277void QTreeView::setHeader(QHeaderView *header)
280 if (header == d->header || !header)
282 if (d->header && d->header->parent() ==
this)
285 d->header->setParent(
this);
286 d->header->setFirstSectionMovable(
false);
288 if (!d->header->model()) {
289 d->header->setModel(d->model);
290 if (d->selectionModel)
291 d->header->setSelectionModel(d->selectionModel);
294 d->headerConnections = {
295 connect(d->header, &QHeaderView::sectionResized,
296 this, &QTreeView::columnResized),
297 connect(d->header, &QHeaderView::sectionMoved,
298 this, &QTreeView::columnMoved),
299 connect(d->header, &QHeaderView::sectionCountChanged,
300 this, &QTreeView::columnCountChanged),
301 connect(d->header, &QHeaderView::sectionHandleDoubleClicked,
302 this, &QTreeView::resizeColumnToContents),
303 connect(d->header, &QHeaderView::geometriesChanged,
304 this, &QTreeView::updateGeometries)
307 setSortingEnabled(d->sortingEnabled);
965void QTreeView::keyboardSearch(
const QString &search)
968 if (!d->model->rowCount(d->root) || !d->model->columnCount(d->root))
972 d->executePostedLayout();
973 if (d->viewItems.isEmpty())
977 if (currentIndex().isValid())
978 start = currentIndex();
980 start = d->viewItems.at(0).index;
982 bool skipRow =
false;
983 bool keyboardTimeWasValid = d->keyboardInputTime.isValid();
984 qint64 keyboardInputTimeElapsed;
985 if (keyboardTimeWasValid)
986 keyboardInputTimeElapsed = d->keyboardInputTime.restart();
988 d->keyboardInputTime.start();
989 if (search.isEmpty() || !keyboardTimeWasValid
990 || keyboardInputTimeElapsed > QApplication::keyboardInputInterval()) {
991 d->keyboardInput = search;
992 skipRow = currentIndex().isValid();
994 d->keyboardInput += search;
998 bool sameKey =
false;
999 if (d->keyboardInput.size() > 1) {
1000 int c = d->keyboardInput.count(d->keyboardInput.at(d->keyboardInput.size() - 1));
1001 sameKey = (c == d->keyboardInput.size());
1008 if (indexBelow(start).isValid()) {
1009 start = indexBelow(start);
1011 const int origCol = start.column();
1012 start = d->viewItems.at(0).index;
1013 if (origCol != start.column())
1014 start = start.sibling(start.row(), origCol);
1018 int startIndex = d->viewIndex(start);
1019 if (startIndex <= -1)
1022 int previousLevel = -1;
1025 QString searchString = sameKey ? QString(d->keyboardInput.at(0)) : d->keyboardInput;
1026 for (
int i = 0; i < d->viewItems.size(); ++i) {
1027 if ((
int)d->viewItems.at(i).level > previousLevel) {
1028 QModelIndex searchFrom = d->viewItems.at(i).index;
1029 if (start.column() > 0)
1030 searchFrom = searchFrom.sibling(searchFrom.row(), start.column());
1031 if (searchFrom.parent() == start.parent())
1033 QModelIndexList match = d->model->match(searchFrom, Qt::DisplayRole, searchString, 1,
1034 keyboardSearchFlags());
1036 int hitIndex = d->viewIndex(match.at(0));
1037 if (hitIndex >= 0 && hitIndex < startIndex)
1038 bestAbove = bestAbove == -1 ? hitIndex : qMin(hitIndex, bestAbove);
1039 else if (hitIndex >= startIndex)
1040 bestBelow = bestBelow == -1 ? hitIndex : qMin(hitIndex, bestBelow);
1043 previousLevel = d->viewItems.at(i).level;
1048 index = d->viewItems.at(bestBelow).index;
1049 else if (bestAbove > -1)
1050 index = d->viewItems.at(bestAbove).index;
1052 if (start.column() > 0)
1053 index = index.sibling(index.row(), start.column());
1055 if (index.isValid())
1056 setCurrentIndex(index);
1134void QTreeView::scrollTo(
const QModelIndex &index, ScrollHint hint)
1138 if (!d->isIndexValid(index))
1141 d->executePostedLayout();
1142 d->updateScrollBars();
1145 QModelIndex parent = index.parent();
1146 while (parent != d->root && parent.isValid() && state() == NoState && d->itemsExpandable) {
1147 if (!isExpanded(parent))
1149 parent = d->model->parent(parent);
1152 int item = d->viewIndex(index);
1156 QRect area = d->viewport->rect();
1159 if (verticalScrollMode() == QAbstractItemView::ScrollPerItem) {
1160 int top = verticalScrollBar()->value();
1161 int bottom = top + verticalScrollBar()->pageStep();
1162 if (hint == EnsureVisible && item >= top && item < bottom) {
1164 }
else if (hint == PositionAtTop || (hint == EnsureVisible && item < top)) {
1165 verticalScrollBar()->setValue(item);
1167 const int currentItemHeight = d->itemHeight(item);
1168 int y = (hint == PositionAtCenter
1170 ? area.height() / 2 + currentItemHeight - 1
1173 if (y > currentItemHeight) {
1175 y -= d->itemHeight(item);
1183 verticalScrollBar()->setValue(item);
1186 QRect rect(columnViewportPosition(index.column()),
1187 d->coordinateForItem(item),
1188 columnWidth(index.column()),
1189 d->itemHeight(item));
1191 if (rect.isEmpty()) {
1193 }
else if (hint == EnsureVisible && area.contains(rect)) {
1194 d->viewport->update(rect);
1197 bool above = (hint == EnsureVisible
1198 && (rect.top() < area.top()
1199 || area.height() < rect.height()));
1200 bool below = (hint == EnsureVisible
1201 && rect.bottom() > area.bottom()
1202 && rect.height() < area.height());
1204 int verticalValue = verticalScrollBar()->value();
1205 if (hint == PositionAtTop || above)
1206 verticalValue += rect.top();
1207 else if (hint == PositionAtBottom || below)
1208 verticalValue += rect.bottom() - area.height();
1209 else if (hint == PositionAtCenter)
1210 verticalValue += rect.top() - ((area.height() - rect.height()) / 2);
1211 verticalScrollBar()->setValue(verticalValue);
1215 int viewportWidth = d->viewport->width();
1216 int horizontalOffset = d->header->offset();
1217 int horizontalPosition = d->header->sectionPosition(index.column());
1218 int cellWidth = d->header->sectionSize(index.column());
1220 if (hint == PositionAtCenter) {
1221 horizontalScrollBar()->setValue(horizontalPosition - ((viewportWidth - cellWidth) / 2));
1223 if (horizontalPosition - horizontalOffset < 0 || cellWidth > viewportWidth)
1224 horizontalScrollBar()->setValue(horizontalPosition);
1225 else if (horizontalPosition - horizontalOffset + cellWidth > viewportWidth)
1226 horizontalScrollBar()->setValue(horizontalPosition - viewportWidth + cellWidth);
1402QRect QTreeViewPrivate::intersectedRect(
const QRect rect,
const QModelIndex &topLeft,
const QModelIndex &bottomRight)
const
1404 const auto parentIdx = topLeft.parent();
1405 executePostedLayout();
1407 int left = std::numeric_limits<
int>::max();
1408 int right = std::numeric_limits<
int>::min();
1409 for (
int row = topLeft.row(); row <= bottomRight.row(); ++row) {
1410 const auto idxCol0 = model->index(row, 0, parentIdx);
1411 if (isRowHidden(idxCol0))
1414 if (left != std::numeric_limits<
int>::max()) {
1416 rowRect = visualRect(idxCol0, FullRow);
1417 if (!rowRect.intersects(rect))
1419 rowRect = QRect(left, rowRect.top(), right, rowRect.bottom());
1420 }
else if (!spanningIndexes.isEmpty() && spanningIndexes.contains(idxCol0)) {
1423 rowRect = visualRect(idxCol0, FullRow);
1424 if (!rowRect.intersects(rect))
1427 for (
int col = topLeft.column(); col <= bottomRight.column(); ++col) {
1428 if (header->isSectionHidden(col))
1430 const QModelIndex idx(model->index(row, col, parentIdx));
1431 const QRect idxRect = visualRect(idx, SingleSection);
1432 if (idxRect.isNull())
1435 if (idxRect.top() > rect.bottom() || idxRect.bottom() < rect.top())
1437 if (!idxRect.intersects(rect))
1439 rowRect = rowRect.united(idxRect);
1440 if (rowRect.left() < rect.left() && rowRect.right() > rect.right())
1443 if (rowRect.isValid()) {
1444 left = std::min(left, rowRect.left());
1445 right = std::max(right, rowRect.right());
1448 updateRect = updateRect.united(rowRect);
1449 if (updateRect.contains(rect))
1452 return rect.intersected(updateRect);
1512void QTreeView::drawTree(QPainter *painter,
const QRegion ®ion)
const
1514 Q_D(
const QTreeView);
1516 const QList<QTreeViewItem> &viewItems = d->viewItems;
1518 QStyleOptionViewItem option;
1519 initViewItemOption(&option);
1520 const QStyle::State state = option.state;
1523 if (viewItems.size() == 0 || d->header->count() == 0 || !d->itemDelegate) {
1524 d->paintAlternatingRowColors(painter, &option, 0, region.boundingRect().bottom()+1);
1528 int firstVisibleItemOffset = 0;
1529 const int firstVisibleItem = d->firstVisibleItem(&firstVisibleItemOffset);
1530 if (firstVisibleItem < 0) {
1531 d->paintAlternatingRowColors(painter, &option, 0, region.boundingRect().bottom()+1);
1535 const int viewportWidth = d->viewport->width();
1537 QPoint hoverPos = d->viewport->mapFromGlobal(QCursor::pos());
1538 d->hoverBranch = d->itemDecorationAt(hoverPos);
1541 bool multipleRects = (region.rectCount() > 1);
1542 for (
const QRect &a : region) {
1543 const QRect area = (multipleRects
1544 ? QRect(0, a.y(), viewportWidth, a.height())
1546 d->leftAndRight = d->startAndEndColumns(area);
1548 int i = firstVisibleItem;
1549 int y = firstVisibleItemOffset;
1552 for (; i < viewItems.size(); ++i) {
1553 const int itemHeight = d->itemHeight(i);
1554 if (y + itemHeight > area.top())
1560 for (; i < viewItems.size() && y <= area.bottom(); ++i) {
1561 const QModelIndex &index = viewItems.at(i).index;
1562 const int itemHeight = d->itemHeight(i);
1563 option.rect = d->visualRect(index, QTreeViewPrivate::FullRow);
1564 option.state = state | (viewItems.at(i).expanded ? QStyle::State_Open : QStyle::State_None)
1565 | (viewItems.at(i).hasChildren ? QStyle::State_Children : QStyle::State_None)
1566 | (viewItems.at(i).hasMoreSiblings ? QStyle::State_Sibling : QStyle::State_None);
1568 d->spanning = viewItems.at(i).spanning;
1569 if (!multipleRects || !drawn.contains(i)) {
1570 drawRow(painter, option, viewItems.at(i).index);
1577 if (y <= area.bottom()) {
1579 d->paintAlternatingRowColors(painter, &option, y, area.bottom());
1594void QTreeViewPrivate::calcLogicalIndices(
1595 QList<
int> *logicalIndices, QList<QStyleOptionViewItem::ViewItemPosition> *itemPositions,
1596 int left,
int right)
const
1598 const int columnCount = header->count();
1600
1601
1602 int logicalIndexBeforeLeft = -1, logicalIndexAfterRight = -1;
1603 for (
int visualIndex = left - 1; visualIndex >= 0; --visualIndex) {
1604 int logicalIndex = header->logicalIndex(visualIndex);
1605 if (!header->isSectionHidden(logicalIndex)) {
1606 logicalIndexBeforeLeft = logicalIndex;
1611 for (
int visualIndex = left; visualIndex < columnCount; ++visualIndex) {
1612 int logicalIndex = header->logicalIndex(visualIndex);
1613 if (!header->isSectionHidden(logicalIndex)) {
1614 if (visualIndex > right) {
1615 logicalIndexAfterRight = logicalIndex;
1618 logicalIndices->append(logicalIndex);
1622 const auto indicesCount = logicalIndices->size();
1623 itemPositions->resize(indicesCount);
1624 for (qsizetype currentLogicalSection = 0; currentLogicalSection < indicesCount; ++currentLogicalSection) {
1626 int nextLogicalSection = currentLogicalSection + 1 >= indicesCount
1627 ? logicalIndexAfterRight
1628 : logicalIndices->at(currentLogicalSection + 1);
1629 int prevLogicalSection = currentLogicalSection - 1 < 0
1630 ? logicalIndexBeforeLeft
1631 : logicalIndices->at(currentLogicalSection - 1);
1632 const int headerSection = logicalIndices->at(currentLogicalSection);
1633 QStyleOptionViewItem::ViewItemPosition pos;
1634 if ((nextLogicalSection == -1 && prevLogicalSection == -1) || spanning) {
1635 pos = QStyleOptionViewItem::OnlyOne;
1636 }
else if ((nextLogicalSection != 0 && prevLogicalSection == -1) || isTreePosition(headerSection))
1637 pos = QStyleOptionViewItem::Beginning;
1638 else if (nextLogicalSection == 0 || nextLogicalSection == -1)
1639 pos = QStyleOptionViewItem::End;
1641 pos = QStyleOptionViewItem::Middle;
1642 (*itemPositions)[currentLogicalSection] = pos;
1672void QTreeView::drawRow(QPainter *painter,
const QStyleOptionViewItem &option,
1673 const QModelIndex &index)
const
1675 Q_D(
const QTreeView);
1676 QStyleOptionViewItem opt = option;
1677 const QPoint offset = d->scrollDelayOffset;
1678 const int y = option.rect.y() + offset.y();
1679 const QModelIndex parent = index.parent();
1680 const QHeaderView *header = d->header;
1681 const QModelIndex current = currentIndex();
1682 const QModelIndex hover = d->hover;
1683 const bool reverse = isRightToLeft();
1684 const QStyle::State state = opt.state;
1685 const bool spanning = d->spanning;
1686 const int left = (spanning ? header->visualIndex(0) : d->leftAndRight.first);
1687 const int right = (spanning ? header->visualIndex(0) : d->leftAndRight.second);
1688 const bool alternate = d->alternatingColors;
1689 const bool enabled = (state & QStyle::State_Enabled) != 0;
1690 const bool allColumnsShowFocus = d->allColumnsShowFocus;
1695 bool indexWidgetHasFocus =
false;
1696 if ((current.row() == index.row()) && !d->editorIndexHash.isEmpty()) {
1697 const int r = index.row();
1698 QWidget *fw = QApplication::focusWidget();
1699 for (
int c = 0; c < header->count(); ++c) {
1700 QModelIndex idx = d->model->index(r, c, parent);
1701 if (QWidget *editor = indexWidget(idx)) {
1702 if (ancestorOf(editor, fw)) {
1703 indexWidgetHasFocus =
true;
1710 const bool widgetHasFocus = hasFocus();
1711 bool currentRowHasFocus =
false;
1712 if (allColumnsShowFocus && widgetHasFocus && current.isValid()) {
1714 const int r = index.row();
1715 for (
int c = 0; c < left && !currentRowHasFocus; ++c) {
1716 QModelIndex idx = d->model->index(r, c, parent);
1717 currentRowHasFocus = (idx == current);
1719 QModelIndex parent = d->model->parent(index);
1720 for (
int c = right; c < header->count() && !currentRowHasFocus; ++c) {
1721 currentRowHasFocus = (d->model->index(r, c, parent) == current);
1730 opt.showDecorationSelected = (d->selectionBehavior & SelectRows)
1731 || option.showDecorationSelected;
1733 int width, height = option.rect.height();
1735 QModelIndex modelIndex;
1736 const bool hoverRow = selectionBehavior() == QAbstractItemView::SelectRows
1737 && index.parent() == hover.parent()
1738 && index.row() == hover.row();
1740 QList<
int> logicalIndices;
1741 QList<QStyleOptionViewItem::ViewItemPosition>
1743 d->calcLogicalIndices(&logicalIndices, &viewItemPosList, left, right);
1745 for (
int currentLogicalSection = 0; currentLogicalSection < logicalIndices.size(); ++currentLogicalSection) {
1746 int headerSection = logicalIndices.at(currentLogicalSection);
1747 position = columnViewportPosition(headerSection) + offset.x();
1748 width = header->sectionSize(headerSection);
1751 int lastSection = header->logicalIndex(header->count() - 1);
1753 width = columnViewportPosition(lastSection) + header->sectionSize(lastSection) - position;
1755 width += position - columnViewportPosition(lastSection);
1756 position = columnViewportPosition(lastSection);
1760 modelIndex = d->model->index(index.row(), headerSection, parent);
1761 if (!modelIndex.isValid())
1765 opt.viewItemPosition = viewItemPosList.at(currentLogicalSection);
1768 if (indexWidgetHasFocus)
1769 opt.state |= QStyle::State_Active;
1771 if (d->selectionModel->isSelected(modelIndex))
1772 opt.state |= QStyle::State_Selected;
1773 if (widgetHasFocus && (current == modelIndex)) {
1774 if (allColumnsShowFocus)
1775 currentRowHasFocus =
true;
1777 opt.state |= QStyle::State_HasFocus;
1779 opt.state.setFlag(QStyle::State_MouseOver,
1780 (hoverRow || modelIndex == hover)
1781 && (option.showDecorationSelected || d->hoverBranch == -1));
1784 QPalette::ColorGroup cg;
1785 if ((d->model->flags(modelIndex) & Qt::ItemIsEnabled) == 0) {
1786 opt.state &= ~QStyle::State_Enabled;
1787 cg = QPalette::Disabled;
1788 }
else if (opt.state & QStyle::State_Active) {
1789 cg = QPalette::Active;
1791 cg = QPalette::Inactive;
1793 opt.palette.setCurrentColorGroup(cg);
1797 opt.features.setFlag(QStyleOptionViewItem::Alternate, d->current & 1);
1799 opt.features &= ~QStyleOptionViewItem::IsDecoratedRootColumn;
1802
1803
1804
1805 if (d->isTreePosition(headerSection)) {
1806 const int i = d->indentationForItem(d->current);
1807 QRect branches(reverse ? position + width - i : position, y, i, height);
1808 const bool setClipRect = branches.width() > width;
1811 painter->setClipRect(QRect(position, y, width, height));
1820 const bool oldShowDecorationSelected = opt.showDecorationSelected;
1821 opt.showDecorationSelected = style()->styleHint(QStyle::SH_ItemView_ShowDecorationSelected,
1823 opt.rect = branches;
1824 if (opt.rect.width() > 0) {
1826 opt.features |= QStyleOptionViewItem::IsDecoratedRootColumn;
1828 opt.features |= QStyleOptionViewItem::IsDecorationForRootColumn;
1829 style()->drawPrimitive(QStyle::PE_PanelItemViewRow, &opt, painter,
this);
1830 opt.features &= ~QStyleOptionViewItem::IsDecorationForRootColumn;
1835 QStyle::State oldState = opt.state;
1836 opt.state &= ~QStyle::State_Selected;
1837 opt.rect.setRect(reverse ? position : i + position, y, width - i, height);
1838 style()->drawPrimitive(QStyle::PE_PanelItemViewRow, &opt, painter,
this);
1839 opt.state = oldState;
1840 opt.showDecorationSelected = oldShowDecorationSelected;
1843 drawBranches(painter, branches, index);
1847 QStyle::State oldState = opt.state;
1848 opt.state &= ~QStyle::State_Selected;
1849 opt.rect.setRect(position, y, width, height);
1850 style()->drawPrimitive(QStyle::PE_PanelItemViewRow, &opt, painter,
this);
1851 opt.state = oldState;
1854 itemDelegateForIndex(modelIndex)->paint(painter, opt, modelIndex);
1857 if (currentRowHasFocus) {
1858 QStyleOptionFocusRect o;
1859 o.QStyleOption::operator=(option);
1860 o.state |= QStyle::State_KeyboardFocusChange;
1861 QPalette::ColorGroup cg = (option.state & QStyle::State_Enabled)
1862 ? QPalette::Normal : QPalette::Disabled;
1863 o.backgroundColor = option.palette.color(cg, d->selectionModel->isSelected(index)
1864 ? QPalette::Highlight : QPalette::Window);
1866 if (!option.showDecorationSelected)
1867 x = header->sectionPosition(0) + d->indentationForItem(d->current);
1868 QRect focusRect(x - header->offset(), y, header->length() - x, height);
1869 o.rect = style()->visualRect(layoutDirection(), d->viewport->rect(), focusRect);
1870 style()->drawPrimitive(QStyle::PE_FrameFocusRect, &o, painter);
1873 if (allColumnsShowFocus && !option.showDecorationSelected
1874 && header->sectionsMoved() && (header->visualIndex(0) != 0)) {
1875 QRect sectionRect(0, y, header->sectionPosition(0), height);
1876 o.rect = style()->visualRect(layoutDirection(), d->viewport->rect(), sectionRect);
1877 style()->drawPrimitive(QStyle::PE_FrameFocusRect, &o, painter);
1887void QTreeView::drawBranches(QPainter *painter,
const QRect &rect,
1888 const QModelIndex &index)
const
1890 Q_D(
const QTreeView);
1891 const bool reverse = isRightToLeft();
1892 const int indent = d->indent;
1893 const int outer = d->rootDecoration ? 0 : 1;
1894 const int item = d->current;
1895 const QTreeViewItem &viewItem = d->viewItems.at(item);
1896 int level = viewItem.level;
1897 QRect primitive(reverse ? rect.left() : rect.right() + 1, rect.top(), indent, rect.height());
1899 QModelIndex parent = index.parent();
1900 QModelIndex current = parent;
1901 QModelIndex ancestor = current.parent();
1903 QStyleOptionViewItem opt;
1904 initViewItemOption(&opt);
1905 QStyle::State extraFlags = QStyle::State_None;
1907 extraFlags |= QStyle::State_Enabled;
1909 extraFlags |= QStyle::State_Active;
1910 QPainterStateGuard psg(painter, QPainterStateGuard::InitialState::NoSave);
1911 if (verticalScrollMode() == QAbstractItemView::ScrollPerPixel) {
1913 painter->setBrushOrigin(QPoint(0, verticalOffset()));
1916 if (d->alternatingColors) {
1917 opt.features.setFlag(QStyleOptionViewItem::Alternate, d->current & 1);
1922 bool hoverRow = selectionBehavior() == QAbstractItemView::SelectRows
1923 && opt.showDecorationSelected
1924 && index.parent() == d->hover.parent()
1925 && index.row() == d->hover.row();
1927 if (d->selectionModel->isSelected(index))
1928 extraFlags |= QStyle::State_Selected;
1930 if (level >= outer) {
1932 primitive.moveLeft(reverse ? primitive.left() : primitive.left() - indent);
1933 opt.rect = primitive;
1935 const bool expanded = viewItem.expanded;
1936 const bool children = viewItem.hasChildren;
1937 bool moreSiblings = viewItem.hasMoreSiblings;
1939 opt.state = QStyle::State_Item | extraFlags
1940 | (moreSiblings ? QStyle::State_Sibling : QStyle::State_None)
1941 | (children ? QStyle::State_Children : QStyle::State_None)
1942 | (expanded ? QStyle::State_Open : QStyle::State_None);
1943 opt.state.setFlag(QStyle::State_MouseOver, hoverRow || item == d->hoverBranch);
1945 style()->drawPrimitive(QStyle::PE_IndicatorBranch, &opt, painter,
this);
1948 for (--level; level >= outer; --level) {
1949 primitive.moveLeft(reverse ? primitive.left() + indent : primitive.left() - indent);
1950 opt.rect = primitive;
1951 opt.state = extraFlags;
1952 bool moreSiblings =
false;
1953 if (d->hiddenIndexes.isEmpty()) {
1954 moreSiblings = (d->model->rowCount(ancestor) - 1 > current.row());
1956 int successor = item + viewItem.total + 1;
1957 while (successor < d->viewItems.size()
1958 && d->viewItems.at(successor).level >= uint(level)) {
1959 const QTreeViewItem &successorItem = d->viewItems.at(successor);
1960 if (successorItem.level == uint(level)) {
1961 moreSiblings =
true;
1964 successor += successorItem.total + 1;
1968 opt.state |= QStyle::State_Sibling;
1969 opt.state.setFlag(QStyle::State_MouseOver, hoverRow || item == d->hoverBranch);
1971 style()->drawPrimitive(QStyle::PE_IndicatorBranch, &opt, painter,
this);
1973 ancestor = current.parent();
2255QModelIndex QTreeView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
2258 Q_UNUSED(modifiers);
2260 d->executePostedLayout();
2262 QModelIndex current = currentIndex();
2263 if (!current.isValid()) {
2264 int i = d->below(-1);
2266 while (c < d->header->count() && d->header->isSectionHidden(d->header->logicalIndex(c)))
2268 if (i < d->viewItems.size() && c < d->header->count()) {
2269 return d->modelIndex(i, d->header->logicalIndex(c));
2271 return QModelIndex();
2274 const int vi = qMax(0, d->viewIndex(current));
2276 if (isRightToLeft()) {
2277 if (cursorAction == MoveRight)
2278 cursorAction = MoveLeft;
2279 else if (cursorAction == MoveLeft)
2280 cursorAction = MoveRight;
2282 switch (cursorAction) {
2285#ifdef QT_KEYPAD_NAVIGATION
2286 if (vi == d->viewItems.count()-1 && QApplicationPrivate::keypadNavigationEnabled())
2287 return d->model->index(0, current.column(), d->root);
2289 return d->modelIndex(d->below(vi), current.column());
2292#ifdef QT_KEYPAD_NAVIGATION
2293 if (vi == 0 && QApplicationPrivate::keypadNavigationEnabled())
2294 return d->modelIndex(d->viewItems.count() - 1, current.column());
2296 return d->modelIndex(d->above(vi), current.column());
2298 QScrollBar *sb = horizontalScrollBar();
2299 if (vi < d->viewItems.size() && d->viewItems.at(vi).expanded && d->itemsExpandable && sb->value() == sb->minimum()) {
2300 d->collapse(vi,
true);
2301 d->moveCursorUpdatedView =
true;
2303 bool descend = style()->styleHint(QStyle::SH_ItemView_ArrowKeysNavigateIntoChildren,
nullptr,
this);
2305 QModelIndex par = current.parent();
2306 if (par.isValid() && par != rootIndex())
2312 if (d->selectionBehavior == SelectItems || d->selectionBehavior == SelectColumns) {
2313 int visualColumn = d->header->visualIndex(current.column()) - 1;
2314 while (visualColumn >= 0 && isColumnHidden(d->header->logicalIndex(visualColumn)))
2316 int newColumn = d->header->logicalIndex(visualColumn);
2317 QModelIndex next = current.sibling(current.row(), newColumn);
2322 int oldValue = sb->value();
2323 sb->setValue(sb->value() - sb->singleStep());
2324 if (oldValue != sb->value())
2325 d->moveCursorUpdatedView =
true;
2330 viewport()->update();
2334 if (vi < d->viewItems.size() && !d->viewItems.at(vi).expanded && d->itemsExpandable
2335 && d->hasVisibleChildren(d->viewItems.at(vi).index)) {
2336 d->expand(vi,
true);
2337 d->moveCursorUpdatedView =
true;
2339 bool descend = style()->styleHint(QStyle::SH_ItemView_ArrowKeysNavigateIntoChildren,
nullptr,
this);
2341 QModelIndex idx = d->modelIndex(d->below(vi));
2342 if (idx.parent() == current)
2348 if (d->selectionBehavior == SelectItems || d->selectionBehavior == SelectColumns) {
2349 int visualColumn = d->header->visualIndex(current.column()) + 1;
2350 while (visualColumn < d->model->columnCount(current.parent()) && isColumnHidden(d->header->logicalIndex(visualColumn)))
2352 const int newColumn = d->header->logicalIndex(visualColumn);
2353 const QModelIndex next = current.sibling(current.row(), newColumn);
2359 QScrollBar *sb = horizontalScrollBar();
2360 int oldValue = sb->value();
2361 sb->setValue(sb->value() + sb->singleStep());
2362 if (oldValue != sb->value())
2363 d->moveCursorUpdatedView =
true;
2367 viewport()->update();
2370 return d->modelIndex(d->pageUp(vi), current.column());
2372 return d->modelIndex(d->pageDown(vi), current.column());
2374 return d->modelIndex(d->itemForKeyHome(), current.column());
2376 return d->modelIndex(d->itemForKeyEnd(), current.column());
2387void QTreeView::setSelection(
const QRect &rect, QItemSelectionModel::SelectionFlags command)
2390 if (!selectionModel() || rect.isNull())
2393 d->executePostedLayout();
2394 QPoint tl(isRightToLeft() ? qMax(rect.left(), rect.right())
2395 : qMin(rect.left(), rect.right()), qMin(rect.top(), rect.bottom()));
2396 QPoint br(isRightToLeft() ? qMin(rect.left(), rect.right()) :
2397 qMax(rect.left(), rect.right()), qMax(rect.top(), rect.bottom()));
2398 QModelIndex topLeft = indexAt(tl);
2399 QModelIndex bottomRight = indexAt(br);
2400 if (!topLeft.isValid() && !bottomRight.isValid()) {
2401 if (command & QItemSelectionModel::Clear)
2402 selectionModel()->clear();
2405 if (!topLeft.isValid() && !d->viewItems.isEmpty())
2406 topLeft = d->viewItems.constFirst().index;
2407 if (!bottomRight.isValid() && !d->viewItems.isEmpty()) {
2408 const int column = d->header->logicalIndex(d->header->count() - 1);
2409 const QModelIndex index = d->viewItems.constLast().index;
2410 bottomRight = index.sibling(index.row(), column);
2413 if (!d->isIndexEnabled(topLeft) || !d->isIndexEnabled(bottomRight))
2416 d->select(topLeft, bottomRight, command);
2426QRegion QTreeView::visualRegionForSelection(
const QItemSelection &selection)
const
2428 Q_D(
const QTreeView);
2429 if (selection.isEmpty())
2432 QRegion selectionRegion;
2433 const QRect &viewportRect = d->viewport->rect();
2434 for (
const auto &range : selection) {
2435 if (!range.isValid())
2437 QModelIndex parent = range.parent();
2438 QModelIndex leftIndex = range.topLeft();
2439 int columnCount = d->model->columnCount(parent);
2440 while (leftIndex.isValid() && isIndexHidden(leftIndex)) {
2441 if (leftIndex.column() + 1 < columnCount)
2442 leftIndex = d->model->index(leftIndex.row(), leftIndex.column() + 1, parent);
2444 leftIndex = QModelIndex();
2446 if (!leftIndex.isValid())
2448 const QRect leftRect = d->visualRect(leftIndex, QTreeViewPrivate::SingleSection);
2449 int top = leftRect.top();
2450 QModelIndex rightIndex = range.bottomRight();
2451 while (rightIndex.isValid() && isIndexHidden(rightIndex)) {
2452 if (rightIndex.column() - 1 >= 0)
2453 rightIndex = d->model->index(rightIndex.row(), rightIndex.column() - 1, parent);
2455 rightIndex = QModelIndex();
2457 if (!rightIndex.isValid())
2459 const QRect rightRect = d->visualRect(rightIndex, QTreeViewPrivate::SingleSection);
2460 int bottom = rightRect.bottom();
2462 qSwap<
int>(top, bottom);
2463 int height = bottom - top + 1;
2464 if (d->header->sectionsMoved()) {
2465 for (
int c = range.left(); c <= range.right(); ++c) {
2466 const QRect rangeRect(columnViewportPosition(c), top, columnWidth(c), height);
2467 if (viewportRect.intersects(rangeRect))
2468 selectionRegion += rangeRect;
2471 QRect combined = leftRect|rightRect;
2472 combined.setX(columnViewportPosition(isRightToLeft() ? range.right() : range.left()));
2473 if (viewportRect.intersects(combined))
2474 selectionRegion += combined;
2477 return selectionRegion;
2504void QTreeView::scrollContentsBy(
int dx,
int dy)
2508 d->delayedAutoScroll.stop();
2510 dx = isRightToLeft() ? -dx : dx;
2512 int oldOffset = d->header->offset();
2513 d->header->d_func()->setScrollOffset(horizontalScrollBar(), horizontalScrollMode());
2514 if (horizontalScrollMode() == QAbstractItemView::ScrollPerItem) {
2515 int newOffset = d->header->offset();
2516 dx = isRightToLeft() ? newOffset - oldOffset : oldOffset - newOffset;
2520 const int itemHeight = d->defaultItemHeight <= 0 ? sizeHintForRow(0) : d->defaultItemHeight;
2521 if (d->viewItems.isEmpty() || itemHeight == 0)
2525 int viewCount = d->viewport->height() / itemHeight;
2526 int maxDeltaY = qMin(d->viewItems.size(), viewCount);
2528 if (qAbs(dy) > qAbs(maxDeltaY) && d->editorIndexHash.isEmpty()) {
2529 verticalScrollBar()->update();
2530 d->viewport->update();
2534 if (dy && verticalScrollMode() == QAbstractItemView::ScrollPerItem) {
2535 int currentScrollbarValue = verticalScrollBar()->value();
2536 int previousScrollbarValue = currentScrollbarValue + dy;
2537 int currentViewIndex = currentScrollbarValue;
2538 int previousViewIndex = previousScrollbarValue;
2540 if (previousViewIndex < currentViewIndex) {
2541 for (
int i = previousViewIndex; i < currentViewIndex; ++i) {
2542 if (i < d->viewItems.size())
2543 dy -= d->itemHeight(i);
2545 }
else if (previousViewIndex > currentViewIndex) {
2546 for (
int i = previousViewIndex - 1; i >= currentViewIndex; --i) {
2547 if (i < d->viewItems.size())
2548 dy += d->itemHeight(i);
2553 d->scrollContentsBy(dx, dy);
2835void QTreeView::expandToDepth(
int depth)
2838 d->viewItems.clear();
2839 QSet<QPersistentModelIndex> old_expandedIndexes;
2840 old_expandedIndexes = d->expandedIndexes;
2841 d->expandedIndexes.clear();
2842 d->interruptDelayedItemsLayout();
2844 for (
int i = 0; i < d->viewItems.size(); ++i) {
2845 if (q20::cmp_less_equal(d->viewItems.at(i).level, depth)) {
2846 d->viewItems[i].expanded =
true;
2848 d->storeExpanded(d->viewItems.at(i).index);
2852 bool someSignalEnabled = isSignalConnected(QMetaMethod::fromSignal(&QTreeView::collapsed));
2853 someSignalEnabled |= isSignalConnected(QMetaMethod::fromSignal(&QTreeView::expanded));
2855 if (!signalsBlocked() && someSignalEnabled) {
2857 QSet<QPersistentModelIndex> collapsedIndexes = old_expandedIndexes - d->expandedIndexes;
2858 QSet<QPersistentModelIndex>::const_iterator i = collapsedIndexes.constBegin();
2859 for (; i != collapsedIndexes.constEnd(); ++i) {
2860 const QPersistentModelIndex &mi = (*i);
2861 if (mi.isValid() && !(mi.flags() & Qt::ItemNeverHasChildren))
2865 QSet<QPersistentModelIndex> expandedIndexs = d->expandedIndexes - old_expandedIndexes;
2866 i = expandedIndexs.constBegin();
2867 for (; i != expandedIndexs.constEnd(); ++i) {
2868 const QPersistentModelIndex &mi = (*i);
2869 if (mi.isValid() && !(mi.flags() & Qt::ItemNeverHasChildren))
2875 d->viewport->update();
2876 d->updateAccessibility();
2934int QTreeView::sizeHintForColumn(
int column)
const
2936 Q_D(
const QTreeView);
2937 d->executePostedLayout();
2938 if (d->viewItems.isEmpty())
2942 QStyleOptionViewItem option;
2943 initViewItemOption(&option);
2944 const QList<QTreeViewItem> viewItems = d->viewItems;
2946 const int maximumProcessRows = d->header->resizeContentsPrecision();
2949 int start = d->firstVisibleItem(&offset);
2950 int end = d->lastVisibleItem(start, offset);
2951 if (start < 0 || end < 0 || end == viewItems.size() - 1) {
2952 end = viewItems.size() - 1;
2953 if (maximumProcessRows < 0) {
2955 }
else if (maximumProcessRows == 0) {
2956 start = qMax(0, end - 1);
2957 int remainingHeight = viewport()->height();
2958 while (start > 0 && remainingHeight > 0) {
2959 remainingHeight -= d->itemHeight(start);
2963 start = qMax(0, end - maximumProcessRows);
2967 int rowsProcessed = 0;
2969 for (
int i = start; i <= end; ++i) {
2970 if (viewItems.at(i).spanning)
2972 QModelIndex index = viewItems.at(i).index;
2973 index = index.sibling(index.row(), column);
2974 w = d->widthHintForIndex(index, w, option, i);
2976 if (rowsProcessed == maximumProcessRows)
2981 int actualBottom = viewItems.size() - 1;
2983 if (maximumProcessRows == 0)
2986 while (rowsProcessed != maximumProcessRows && (start > 0 || end < actualBottom)) {
2989 if ((rowsProcessed % 2 && start > 0) || end == actualBottom) {
2992 if (viewItems.at(start).spanning)
2998 while (end < actualBottom) {
3000 if (viewItems.at(end).spanning)
3009 QModelIndex index = viewItems.at(idx).index;
3010 index = index.sibling(index.row(), column);
3011 w = d->widthHintForIndex(index, w, option, idx);
3022int QTreeView::indexRowSizeHint(
const QModelIndex &index)
const
3024 Q_D(
const QTreeView);
3025 if (!d->isIndexValid(index) || !d->itemDelegate)
3030 int indexRow = index.row();
3031 int count = d->header->count();
3032 bool emptyHeader = (count == 0);
3033 QModelIndex parent = index.parent();
3035 if (count && isVisible()) {
3037 start = d->header->visualIndexAt(0);
3040 count = d->model->columnCount(parent);
3043 if (isRightToLeft()) {
3044 start = (start == -1 ? count - 1 : start);
3047 start = (start == -1 ? 0 : start);
3055 QStyleOptionViewItem option;
3056 initViewItemOption(&option);
3062 option.rect.setWidth(-1);
3064 for (
int column = start; column <= end; ++column) {
3065 int logicalColumn = emptyHeader ? column : d->header->logicalIndex(column);
3066 if (d->header->isSectionHidden(logicalColumn))
3068 QModelIndex idx = d->model->index(indexRow, logicalColumn, parent);
3069 if (idx.isValid()) {
3070 QWidget *editor = d->editorForIndex(idx).widget.data();
3071 if (editor && d->persistent.contains(editor)) {
3072 height = qMax(height, editor->sizeHint().height());
3073 int min = editor->minimumSize().height();
3074 int max = editor->maximumSize().height();
3075 height = qBound(min, height, max);
3077 int hint = itemDelegateForIndex(idx)->sizeHint(option, idx).height();
3078 height = qMax(height, hint);
3419void QTreeViewPrivate::layout(
int i,
bool recursiveExpanding,
bool afterIsUninitialized)
3422 QModelIndex current;
3423 QModelIndex parent = (i < 0) ? (QModelIndex)root : modelIndex(i);
3425 if (i>=0 && !parent.isValid()) {
3432#if QT_CONFIG(accessibility)
3436 const auto resetModelIfNeeded = qScopeGuard([oldViewItemsSize = viewItems.size(),
this]{
3437 pendingAccessibilityUpdate |= oldViewItemsSize != viewItems.size();
3442 if (model->hasChildren(parent)) {
3443 if (model->canFetchMore(parent)) {
3445 model->fetchMore(parent);
3447 const int itemHeight = defaultItemHeight <= 0 ? q->sizeHintForRow(0) : defaultItemHeight;
3448 const int viewCount = itemHeight ? viewport->height() / itemHeight : 0;
3450 while ((count = model->rowCount(parent)) < viewCount &&
3451 count != lastCount && model->canFetchMore(parent)) {
3452 model->fetchMore(parent);
3456 count = model->rowCount(parent);
3460 bool expanding =
true;
3462 if (uniformRowHeights) {
3463 QModelIndex index = model->index(0, 0, parent);
3464 defaultItemHeight = q->indexRowSizeHint(index);
3466 viewItems.resize(count);
3467 afterIsUninitialized =
true;
3468 }
else if (q20::cmp_not_equal(viewItems[i].total, count)) {
3469 if (!afterIsUninitialized)
3470 insertViewItems(i + 1, count, QTreeViewItem());
3472 viewItems.resize(viewItems.size() + count);
3478 int level = (i >= 0 ? viewItems.at(i).level + 1 : 0);
3482 QTreeViewItem *item =
nullptr;
3483 for (
int j = first; j < first + count; ++j) {
3484 current = model->index(j - first, 0, parent);
3485 if (isRowHidden(current)) {
3487 last = j - hidden + children;
3489 last = j - hidden + children;
3491 item->hasMoreSiblings =
true;
3492 item = &viewItems[last];
3493 item->index = current;
3494 item->parentItem = i;
3495 item->level = level;
3497 item->spanning = q->isFirstColumnSpanned(current.row(), parent);
3498 item->expanded =
false;
3500 item->hasMoreSiblings =
false;
3501 if ((recursiveExpanding && !(current.flags() & Qt::ItemNeverHasChildren)) || isIndexExpanded(current)) {
3502 if (recursiveExpanding && storeExpanded(current) && !q->signalsBlocked())
3503 emit q->expanded(current);
3504 item->expanded =
true;
3505 layout(last, recursiveExpanding, afterIsUninitialized);
3506 item = &viewItems[last];
3507 children += item->total;
3508 item->hasChildren = item->total > 0;
3509 last = j - hidden + children;
3511 item->hasChildren = hasVisibleChildren(current);
3518 if (!afterIsUninitialized)
3519 removeViewItems(last + 1, hidden);
3521 viewItems.resize(viewItems.size() - hidden);
3528 viewItems[i].total += count - hidden;
3529 i = viewItems[i].parentItem;
3657int QTreeViewPrivate::itemAtCoordinate(
int coordinate)
const
3659 const int itemCount = viewItems.size();
3662 if (uniformRowHeights && defaultItemHeight <= 0)
3664 if (verticalScrollMode == QAbstractItemView::ScrollPerPixel) {
3665 if (uniformRowHeights) {
3666 const int viewItemIndex = (coordinate + vbar->value()) / defaultItemHeight;
3667 return ((viewItemIndex >= itemCount || viewItemIndex < 0) ? -1 : viewItemIndex);
3670 int viewItemCoordinate = 0;
3671 const int contentsCoordinate = coordinate + vbar->value();
3672 for (
int viewItemIndex = 0; viewItemIndex < viewItems.size(); ++viewItemIndex) {
3673 viewItemCoordinate += itemHeight(viewItemIndex);
3674 if (viewItemCoordinate > contentsCoordinate)
3675 return (viewItemIndex >= itemCount ? -1 : viewItemIndex);
3678 int topViewItemIndex = vbar->value();
3679 if (uniformRowHeights) {
3681 coordinate -= defaultItemHeight - 1;
3682 const int viewItemIndex = topViewItemIndex + (coordinate / defaultItemHeight);
3683 return ((viewItemIndex >= itemCount || viewItemIndex < 0) ? -1 : viewItemIndex);
3685 if (coordinate >= 0) {
3687 int viewItemCoordinate = 0;
3688 for (
int viewItemIndex = topViewItemIndex; viewItemIndex < viewItems.size(); ++viewItemIndex) {
3689 viewItemCoordinate += itemHeight(viewItemIndex);
3690 if (viewItemCoordinate > coordinate)
3691 return (viewItemIndex >= itemCount ? -1 : viewItemIndex);
3695 int viewItemCoordinate = 0;
3696 for (
int viewItemIndex = topViewItemIndex; viewItemIndex >= 0; --viewItemIndex) {
3697 if (viewItemCoordinate <= coordinate)
3698 return (viewItemIndex >= itemCount ? -1 : viewItemIndex);
3699 viewItemCoordinate -= itemHeight(viewItemIndex);
3813void QTreeViewPrivate::updateScrollBars()
3816 QSize viewportSize = viewport->size();
3817 if (!viewportSize.isValid())
3818 viewportSize = QSize(0, 0);
3820 executePostedLayout();
3821 if (viewItems.isEmpty()) {
3825 int itemsInViewport = 0;
3826 if (uniformRowHeights) {
3827 if (defaultItemHeight <= 0)
3828 itemsInViewport = viewItems.size();
3830 itemsInViewport = viewportSize.height() / defaultItemHeight;
3832 const int itemsCount = viewItems.size();
3833 const int viewportHeight = viewportSize.height();
3834 for (
int height = 0, item = itemsCount - 1; item >= 0; --item) {
3835 height += itemHeight(item);
3836 if (height > viewportHeight)
3841 if (verticalScrollMode == QAbstractItemView::ScrollPerItem) {
3842 if (!viewItems.isEmpty())
3843 itemsInViewport = qMax(1, itemsInViewport);
3844 vbar->setRange(0, viewItems.size() - itemsInViewport);
3845 vbar->setPageStep(itemsInViewport);
3846 vbar->setSingleStep(1);
3848 int contentsHeight = 0;
3849 if (uniformRowHeights) {
3850 contentsHeight = defaultItemHeight * viewItems.size();
3852 for (
int i = 0; i < viewItems.size(); ++i)
3853 contentsHeight += itemHeight(i);
3855 vbar->setRange(0, contentsHeight - viewportSize.height());
3856 vbar->setPageStep(viewportSize.height());
3857 vbar->d_func()->itemviewChangeSingleStep(qMax(viewportSize.height() / (itemsInViewport + 1), 2));
3860 const int columnCount = header->count();
3861 const int viewportWidth = viewportSize.width();
3862 int columnsInViewport = 0;
3863 for (
int width = 0, column = columnCount - 1; column >= 0; --column) {
3864 int logical = header->logicalIndex(column);
3865 width += header->sectionSize(logical);
3866 if (width > viewportWidth)
3868 ++columnsInViewport;
3870 if (columnCount > 0)
3871 columnsInViewport = qMax(1, columnsInViewport);
3872 if (horizontalScrollMode == QAbstractItemView::ScrollPerItem) {
3873 hbar->setRange(0, columnCount - columnsInViewport);
3874 hbar->setPageStep(columnsInViewport);
3875 hbar->setSingleStep(1);
3877 const int horizontalLength = header->length();
3878 const QSize maxSize = q->maximumViewportSize();
3879 if (maxSize.width() >= horizontalLength && vbar->maximum() <= 0)
3880 viewportSize = maxSize;
3881 hbar->setPageStep(viewportSize.width());
3882 hbar->setRange(0, qMax(horizontalLength - viewportSize.width(), 0));
3883 hbar->d_func()->itemviewChangeSingleStep(qMax(viewportSize.width() / (columnsInViewport + 1), 2));
3983void QTreeViewPrivate::select(
const QModelIndex &topIndex,
const QModelIndex &bottomIndex,
3984 QItemSelectionModel::SelectionFlags command)
3987 QItemSelection selection;
3988 const int top = viewIndex(topIndex),
3989 bottom = viewIndex(bottomIndex);
3991 const QList<std::pair<
int,
int>> colRanges = columnRanges(topIndex, bottomIndex);
3992 QList<std::pair<
int,
int>>::const_iterator it;
3993 for (it = colRanges.begin(); it != colRanges.end(); ++it) {
3994 const int left = (*it).first,
3995 right = (*it).second;
3997 QModelIndex previous;
3998 QItemSelectionRange currentRange;
3999 QStack<QItemSelectionRange> rangeStack;
4000 for (
int i = top; i <= bottom; ++i) {
4001 QModelIndex index = modelIndex(i);
4002 QModelIndex parent = index.parent();
4003 QModelIndex previousParent = previous.parent();
4004 if (previous.isValid() && parent == previousParent) {
4006 if (qAbs(previous.row() - index.row()) > 1) {
4008 if (currentRange.isValid()) {
4009 selection.append(currentRange);
4012 currentRange = QItemSelectionRange(index.sibling(index.row(), left), index.sibling(index.row(), right));
4014 QModelIndex tl = model->index(currentRange.top(), currentRange.left(),
4015 currentRange.parent());
4016 currentRange = QItemSelectionRange(tl, index.sibling(index.row(), right));
4018 }
else if (previous.isValid() && parent == model->index(previous.row(), 0, previousParent)) {
4020 rangeStack.push(currentRange);
4021 currentRange = QItemSelectionRange(index.sibling(index.row(), left), index.sibling(index.row(), right));
4023 if (currentRange.isValid())
4024 selection.append(currentRange);
4025 if (rangeStack.isEmpty()) {
4026 currentRange = QItemSelectionRange(index.sibling(index.row(), left), index.sibling(index.row(), right));
4028 currentRange = rangeStack.pop();
4029 index = currentRange.bottomRight();
4035 if (currentRange.isValid())
4036 selection.append(currentRange);
4037 for (
int i = 0; i < rangeStack.size(); ++i)
4038 selection.append(rangeStack.at(i));
4040 q->selectionModel()->select(selection, command);