📄 qtreeview.cpp
字号:
}/*! If \a hide is true the \a row with the given \a parent is hidden, otherwise the \a row is shown. \sa isRowHidden(), setColumnHidden()*/void QTreeView::setRowHidden(int row, const QModelIndex &parent, bool hide){ Q_D(QTreeView); if (!model()) return; QModelIndex index = model()->index(row, 0, parent); if (!index.isValid()) return; QPersistentModelIndex persistent(index); if (hide) { if (!d->hiddenIndexes.contains(persistent)) d->hiddenIndexes.append(persistent); } else { int i = d->hiddenIndexes.indexOf(persistent); if (i >= 0) d->hiddenIndexes.remove(i); } if (isVisible()) d->relayout(parent); else d->doDelayedItemsLayout();}/*! \reimp*/void QTreeView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight){ Q_D(QTreeView); // if we are going to do a complete realyout anyway, there is no need to update if (!model() || d->delayedLayout.isActive()) return; // refresh the height cache here; we don't really lose anything by getting the size hint, // since QAbstractItemView::dataChanged() will get the visualRect for the items anyway QModelIndex top = (topLeft.column() == 0) ? topLeft : model()->sibling(topLeft.row(), 0, topLeft); int topViewIndex = d->viewIndex(top); bool sizeChanged = false; if (topViewIndex != -1) { if (topLeft == bottomRight) { int oldHeight = d->height(topViewIndex); d->invalidateHeightCache(topViewIndex); sizeChanged = (oldHeight != d->height(topViewIndex)); } else { QModelIndex bottom = (bottomRight.column() == 0) ? bottomRight : model()->sibling(bottomRight.row(), 0, bottomRight); int bottomViewIndex = d->viewIndex(bottom); for (int i = topViewIndex; i <= bottomViewIndex; ++i) { int oldHeight = d->height(i); d->invalidateHeightCache(i); sizeChanged |= (oldHeight != d->height(i)); } } } if (sizeChanged) d->viewport->update(); QAbstractItemView::dataChanged(topLeft, bottomRight);}/*! Hides the \a column given. \sa showColumn(), setColumnHidden()*/void QTreeView::hideColumn(int column){ Q_D(QTreeView); d->header->hideSection(column);}/*! Shows the given \a column in the tree view. \sa hideColumn(), setColumnHidden()*/void QTreeView::showColumn(int column){ Q_D(QTreeView); d->header->showSection(column);}/*! \fn void QTreeView::expand(const QModelIndex &index) Expands the model item specified by the \a index. \sa expanded()*/void QTreeView::expand(const QModelIndex &index){ Q_D(QTreeView); if (!index.isValid()) return; int i = d->viewIndex(index); if (i != -1) { // is visible d->expand(i, true); updateGeometries(); viewport()->update(); } else { d->expandedIndexes.append(index); emit expanded(index); }}/*! \fn void QTreeView::collapse(const QModelIndex &index) Collapses the model item specified by the \a index. \sa collapsed()*/void QTreeView::collapse(const QModelIndex &index){ Q_D(QTreeView); if (!index.isValid()) return; int i = d->viewIndex(index); if (i != -1) { // is visible d->collapse(i, true); updateGeometries(); viewport()->update(); } else { int i = d->expandedIndexes.indexOf(index); if (i != -1) { d->expandedIndexes.remove(i); emit collapsed(index); } }}/*! \fn bool QTreeView::isExpanded(const QModelIndex &index) const Returns true if the model item \a index is expanded; otherwise returns false. \da expand(), expanded()*/bool QTreeView::isExpanded(const QModelIndex &index) const{ Q_D(const QTreeView); int i = d->viewIndex(index); if (i != -1) // is visible return d->viewItems.at(i).expanded; return d->expandedIndexes.contains(index);}/*! Sets the item referred to by \a index to either collapse or expanded, depending on the value of \a expanded. \sa expanded(), expand()*/void QTreeView::setExpanded(const QModelIndex &index, bool expanded){ if (expanded) this->expand(index); else this->collapse(index);}/*! \reimp */void QTreeView::keyboardSearch(const QString &search){ Q_D(QTreeView); if (!model() || !model()->rowCount(rootIndex()) || !model()->columnCount(rootIndex())) return; QModelIndex start; if (currentIndex().isValid()) start = currentIndex(); else start = model()->index(0, 0, rootIndex()); QTime now(QTime::currentTime()); bool skipRow = false; if (d->keyboardInputTime.msecsTo(now) > QApplication::keyboardInputInterval()) { d->keyboardInput = search; skipRow = true; } else { d->keyboardInput += search; } d->keyboardInputTime = now; // special case for searches with same key like 'aaaaa' bool sameKey = false; if (d->keyboardInput.length() > 1) { int c = d->keyboardInput.count(d->keyboardInput.at(d->keyboardInput.length() - 1)); sameKey = (c == d->keyboardInput.length()); if (sameKey) skipRow = true; } // skip if we are searching for the same key or a new search started if (skipRow) { if (indexBelow(start).isValid()) start = indexBelow(start); else start = model()->index(0, start.column(), rootIndex()); } int startIndex = d->viewIndex(start); if (startIndex <= -1) return; int previousLevel = -1; int bestAbove = -1; int bestBelow = -1; QString searchString = sameKey ? QString(d->keyboardInput.at(0)) : d->keyboardInput; for (int i = 0; i < d->viewItems.count(); ++i) { if ((int)d->viewItems.at(i).level > previousLevel) { QModelIndex searchFrom = d->viewItems.at(i).index; if (searchFrom.parent() == start.parent()) searchFrom = start; QModelIndexList match = model()->match(searchFrom, Qt::DisplayRole, searchString); if (match.count()) { int hitIndex = d->viewIndex(match.at(0)); if (hitIndex >= 0 && hitIndex < startIndex) bestAbove = bestAbove == -1 ? hitIndex : qMin(hitIndex, bestAbove); else if (hitIndex >= startIndex) bestBelow = bestBelow == -1 ? hitIndex : qMin(hitIndex, bestBelow); } } previousLevel = d->viewItems.at(i).level; } QModelIndex index; if (bestBelow > -1) index = d->viewItems.at(bestBelow).index; else if (bestAbove > -1) index = d->viewItems.at(bestAbove).index; if (index.isValid()) { QItemSelectionModel::SelectionFlags flags = (d->selectionMode == SingleSelection ? QItemSelectionModel::SelectionFlags( QItemSelectionModel::ClearAndSelect |d->selectionBehaviorFlags()) : QItemSelectionModel::SelectionFlags( QItemSelectionModel::NoUpdate)); selectionModel()->setCurrentIndex(index, flags); }}/*! Returns the rectangle on the viewport occupied by the item at \a index. If the index is not visible or explicitly hidden, the returned rectangle is invalid.*/QRect QTreeView::visualRect(const QModelIndex &index) const{ Q_D(const QTreeView); if (!index.isValid() || isIndexHidden(index)) return QRect(); d->executePostedLayout(); int vi = d->viewIndex(index); if (vi < 0) return QRect(); int x = columnViewportPosition(index.column()); int w = columnWidth(index.column()); if (index.column() == 0) { int i = d->indentation(vi); x += i; w -= i; } int y = d->coordinate(vi); int h = d->height(vi); return QRect(x, y, w, h);}/*! Scroll the contents of the tree view until the given model item \a index is visible. The \a hint parameter specifies more precisely where the item should be located after the operation. If any of the parents of the model item are collapsed, they will be expanded to ensure that the model item is visible.*/void QTreeView::scrollTo(const QModelIndex &index, ScrollHint hint){ Q_D(QTreeView); if (!model() || !index.isValid()) return; // Expand all parents if the parent(s) of the node are not expanded. QModelIndex parent = index.parent(); while (parent.isValid() && state() != CollapsingState && d->itemsExpandable) { if (!isExpanded(parent)) expand(parent); parent = model()->parent(parent); } QRect rect = visualRect(index); if (rect.isEmpty()) return; // check if we really need to do anything QRect area = d->viewport->rect(); if (hint == EnsureVisible && area.contains(rect)) { d->setDirtyRegion(rect); return; } // vertical int verticalSteps = verticalStepsPerItem(); bool above = (hint == EnsureVisible && rect.top() < area.top()); bool below = (hint == EnsureVisible && rect.bottom() > area.bottom()); if (hint == PositionAtTop || above) { int i = d->viewIndex(index); verticalScrollBar()->setValue(i * verticalSteps); } else if (hint == PositionAtBottom || below) { int i = d->viewIndex(index); if (i < 0) { qWarning("scrollTo: item index was illegal: %d", i); return; } int y = area.height(); while (y > 0 && i > 0) y -= d->height(i--); int h = d->height(i); int a = (-y * verticalSteps) / (h ? h : 1); verticalScrollBar()->setValue(++i * verticalSteps + a); } // horizontal int viewportWidth = d->viewport->width(); int horizontalOffset = d->header->offset(); int horizontalPosition = d->header->sectionPosition(index.column()); int cellWidth = d->header->sectionSize(index.column()); if (horizontalPosition - horizontalOffset < 0 || cellWidth > viewportWidth) horizontalScrollBar()->setValue(horizontalPosition); else if (horizontalPosition - horizontalOffset + cellWidth > viewportWidth) horizontalScrollBar()->setValue(horizontalPosition - viewportWidth + cellWidth);}/*! \reimp*/void QTreeView::timerEvent(QTimerEvent *event){ Q_D(QTreeView); if (event->timerId() == d->columnResizeTimerID) { updateGeometries(); killTimer(d->columnResizeTimerID); d->columnResizeTimerID = 0; QRect rect; int viewportHeight = d->viewport->height(); int viewportWidth = d->viewport->width(); for (int i = d->columnsToUpdate.size() - 1; i >= 0; --i) { int column = d->columnsToUpdate.at(i); int x = columnViewportPosition(column); if (isRightToLeft()) rect |= QRect(0, 0, x + columnWidth(column), viewportHeight); else rect |= QRect(x, 0, viewportWidth - x, viewportHeight); } d->viewport->update(rect.normalized()); d->columnsToUpdate.clear(); } QAbstractItemView::timerEvent(event);}/*! \reimp*/void QTreeView::paintEvent(QPaintEvent *event){ Q_D(QTreeView); QStyleOptionViewItem option = viewOptions(); const QStyle::State state = option.state; const int v = verticalScrollBar()->value(); const int c = d->viewItems.count(); const QVector<QTreeViewItem> viewItems = d->viewItems; const QPoint offset = d->scrollDelayOffset; QPainter painter(d->viewport); if (c == 0 || d->header->count() == 0) { painter.fillRect(event->rect(), option.palette.brush(QPalette::Base)); return; } QVector<QRect> rects = event->region().rects(); for (int a = 0; a < rects.size(); ++a) { QRect area = rects.at(a); area.translate(offset); const int t = area.top(); const int b = area.bottom() + 1; d->left = d->header->visualIndexAt(area.left()); d->right = d->header->visualIndexAt(area.right()); if (isRightToLeft()) { d->left = (d->left == -1 ? d->header->count() - 1 : d->left); d->right = (d->right == -1 ? 0 : d->right); } else { d->left = (d->left == -1 ? 0 : d->left); d->right = (d->right == -1 ? d->header->count() - 1 : d->right); } int tmp = d->left; d->left = qMin(d->left, d->right); d->right = qMax(tmp, d->right);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -