📄 qtreeview.cpp
字号:
int i = d->itemAt(v); // first item if (i < 0) // couldn't find the first item return; int y = d->topItemDelta(v, d->height(i)); int w = d->viewport->width(); while (y < b && i < c) { int h = d->height(i); // actual height if (y + h >= t) { // we are in the update area option.rect.setRect(0, y, 0, h); option.state = state | (viewItems.at(i).expanded ? QStyle::State_Open : QStyle::State_None); d->current = i; drawRow(&painter, option, viewItems.at(i).index); } y += h; ++i; } int x = d->header->length(); QRect bottom(0, y, w, b - y); if (y < b && area.intersects(bottom)) painter.fillRect(bottom, option.palette.brush(QPalette::Base)); if (isRightToLeft()) { QRect right(0, 0, w - x, b); if (x < w && area.intersects(right)) painter.fillRect(right, option.palette.brush(QPalette::Base)); } else { QRect left(x, 0, w - x, b); if (x < w && area.intersects(left)) painter.fillRect(left, option.palette.brush(QPalette::Base)); } }#ifndef QT_NO_DRAGANDDROP // Paint the dropIndicator d_func()->paintDropIndicator(&painter);#endif}/*! Draws the row in the tree view that contains the model item \a index, using the \a painter given. The \a option control how the item is displayed. \sa QStyleOptionViewItem(), setAlternatingRowColors()*/void QTreeView::drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const{ Q_D(const QTreeView); const QPoint offset = d->scrollDelayOffset; QStyleOptionViewItem opt = option; const int y = option.rect.y() + offset.y(); const QModelIndex parent = index.parent(); const QHeaderView *header = d->header; const QModelIndex current = currentIndex(); const QModelIndex hover = d->hover; const bool focus = (hasFocus() || d->viewport->hasFocus()) && current.isValid(); const bool reverse = isRightToLeft(); const QStyle::State state = opt.state; const int left = d->left; const int right = d->right; const bool alternate = d->alternatingColors; const bool enabled = (state & QStyle::State_Enabled) != 0; // ### special case: treeviews with multiple columns draw the selections differently than with only one column opt.showDecorationSelected = (d->selectionBehavior & SelectRows) || option.showDecorationSelected; int width, height = option.rect.height(); int position; int headerSection; QModelIndex modelIndex; for (int headerIndex = left; headerIndex <= right; ++headerIndex) { headerSection = d->header->logicalIndex(headerIndex); if (header->isSectionHidden(headerSection)) continue; position = columnViewportPosition(headerSection) + offset.x(); width = header->sectionSize(headerSection); modelIndex = d->model->index(index.row(), headerSection, parent); opt.state = state; if (!modelIndex.isValid()) { opt.rect.setRect(position, y, width, height); painter->fillRect(opt.rect, opt.palette.brush(QPalette::Base)); continue; } if (selectionModel()->isSelected(modelIndex)) opt.state |= QStyle::State_Selected; if (focus && current == modelIndex) opt.state |= QStyle::State_HasFocus; if (modelIndex == hover) opt.state |= QStyle::State_MouseOver; else opt.state &= ~QStyle::State_MouseOver; if (enabled) { QPalette::ColorGroup cg; if ((model()->flags(index) & Qt::ItemIsEnabled) == 0) { opt.state &= ~QStyle::State_Enabled; cg = QPalette::Disabled; } else { cg = QPalette::Normal; } opt.palette.setCurrentColorGroup(cg); } QBrush fill; if (alternate) { fill = d->current & 1 ? opt.palette.brush(QPalette::AlternateBase) : opt.palette.brush(QPalette::Base); } else { fill = opt.palette.brush(QPalette::Base); } if (headerSection == 0) { int i = d->indentation(d->current); opt.rect.setRect(reverse ? position : i + position, y, width - i, height); painter->fillRect(opt.rect, fill); QRect branches(reverse ? position + width - i : position, y, i, height); if ((opt.state & QStyle::State_Selected) && option.showDecorationSelected) painter->fillRect(branches, option.palette.brush(QPalette::Highlight)); else painter->fillRect(branches, fill); drawBranches(painter, branches, index); } else { opt.rect.setRect(position, y, width, height); painter->fillRect(opt.rect, fill); } itemDelegate()->paint(painter, opt, modelIndex); }}/*! Draws the branches in the tree view on the same row as the model item \a index, using the \a painter given. The branches are drawn in the rectangle specified by \a rect.*/void QTreeView::drawBranches(QPainter *painter, const QRect &rect, const QModelIndex &index) const{ Q_D(const QTreeView); const bool reverse = isRightToLeft(); const int indent = d->indent; const int outer = d->rootDecoration ? 0 : 1; const int item = d->current; int level = d->viewItems.at(item).level; QRect primitive(reverse ? rect.left() : rect.right(), rect.top(), indent, rect.height()); const QModelIndex parent = index.parent(); QModelIndex current = parent; QModelIndex ancestor = current.parent(); QStyleOption opt; opt.initFrom(this); QStyle::State extraFlags = QStyle::State_None; if (isEnabled()) extraFlags |= QStyle::State_Enabled; if (window()->isActiveWindow()) extraFlags |= QStyle::State_Active; QPoint oldBO = painter->brushOrigin(); int v = verticalScrollBar()->value(); int i = d->itemAt(v); if (i >= 0) { int delta = d->topItemDelta(v, d->height(i)); int offset = verticalOffset(); painter->setBrushOrigin(QPoint(0, -1 * offset - delta)); } if (level >= outer) { // start with the innermost branch primitive.moveLeft(reverse ? primitive.left() : primitive.left() - indent); opt.rect = primitive; const bool expanded = d->viewItems.at(item).expanded; const bool children = (expanded // already layed out ? d->viewItems.at(item).total // this also covers the hidden items : d->model->hasChildren(index)); // not layed out yet, so we don't know bool moreSiblings = false; if (d->hiddenIndexes.isEmpty()) moreSiblings = (d->model->rowCount(parent) - 1 > index.row()); else moreSiblings = ((d->viewItems.size() > item +1) && (d->viewItems.at(item + 1).index.parent() == parent)); opt.state = QStyle::State_Item | extraFlags | (moreSiblings ? QStyle::State_Sibling : QStyle::State_None) | (children ? QStyle::State_Children : QStyle::State_None) | (expanded ? QStyle::State_Open : QStyle::State_None); style()->drawPrimitive(QStyle::PE_IndicatorBranch, &opt, painter, this); } // then go out level by level for (--level; level >= outer; --level) { // we have already drawn the innermost branch primitive.moveLeft(reverse ? primitive.left() + indent : primitive.left() - indent); opt.rect = primitive; opt.state = extraFlags; if (d->model->rowCount(ancestor) - 1 > current.row()) opt.state |= QStyle::State_Sibling; style()->drawPrimitive(QStyle::PE_IndicatorBranch, &opt, painter, this); current = ancestor; ancestor = current.parent(); } painter->setBrushOrigin(oldBO);}/*! \reimp*/void QTreeView::mousePressEvent(QMouseEvent *event){ Q_D(QTreeView); if (!d->viewport->rect().contains(event->pos())) return; int i = d->itemDecorationAt(event->pos()); if (i == -1) { QAbstractItemView::mousePressEvent(event); } else if (itemsExpandable() && model()->hasChildren(d->viewItems.at(i).index)) { if (d->viewItems.at(i).expanded) d->collapse(i, true); else d->expand(i, true); updateGeometries(); viewport()->update(); }}/*! \reimp*/void QTreeView::mouseReleaseEvent(QMouseEvent *event){ Q_D(QTreeView); if (d->itemDecorationAt(event->pos()) == -1) QAbstractItemView::mouseReleaseEvent(event);}/*! \reimp*/void QTreeView::mouseDoubleClickEvent(QMouseEvent *event){ Q_D(QTreeView); if (!d->viewport->rect().contains(event->pos())) return; int i = d->itemDecorationAt(event->pos()); if (i == -1) { i = d->item(event->y()); if (i == -1) return; // user clicked outside the items // signal handlers may change the model QModelIndex index = d->viewItems.at(i).index; int column = d->header->logicalIndexAt(event->x()); QPersistentModelIndex persistent = index.sibling(index.row(), column); emit doubleClicked(persistent); if (edit(persistent, DoubleClicked, event) || state() != NoState) return; // the double click triggered editing if (!style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick)) emit activated(persistent); d->executePostedLayout(); // we need to make sure viewItems is updated if (d->itemsExpandable && model()->hasChildren(d->viewItems.at(i).index)) { if (d->viewItems.at(i).expanded) d->collapse(i, true); else d->expand(i, true); updateGeometries(); viewport()->update(); } }}/*! \reimp*/QModelIndex QTreeView::indexAt(const QPoint &point) const{ Q_D(const QTreeView); d->executePostedLayout(); int visualIndex = d->item(point.y()); QModelIndex idx = d->modelIndex(visualIndex); int column = d->columnAt(point.x()); if (idx.isValid() && column >= 0) return model()->sibling(idx.row(), column, idx); return QModelIndex();}/*! Returns the model index of the item above \a index.*/QModelIndex QTreeView::indexAbove(const QModelIndex &index) const{ Q_D(const QTreeView); if (!index.isValid()) return QModelIndex(); d->executePostedLayout(); int i = d->viewIndex(index); if (--i < 0) return QModelIndex(); return d->viewItems.at(i).index;}/*! Returns the model index of the item below \a index.*/QModelIndex QTreeView::indexBelow(const QModelIndex &index) const{ Q_D(const QTreeView); d->executePostedLayout(); int i = d->viewIndex(index); if (++i >= d->viewItems.count()) return QModelIndex(); return d->viewItems.at(i).index;}/*! Lays out the items in the tree view.*/void QTreeView::doItemsLayout(){ Q_D(QTreeView); d->viewItems.clear(); // prepare for new layout QStyleOptionViewItem option = viewOptions(); QModelIndex parent = rootIndex(); if (model() && model()->hasChildren(parent)) { QModelIndex index = model()->index(0, 0, parent); d->itemHeight = indexRowSizeHint(index); d->layout(-1); d->reexpandChildren(parent); } QAbstractItemView::doItemsLayout();}/*! \reimp*/void QTreeView::reset(){ Q_D(QTreeView); d->expandedIndexes.clear(); d->hiddenIndexes.clear(); d->viewItems.clear(); QAbstractItemView::reset();}/*! Returns the horizontal offset of the items in the treeview. Note that the tree view uses the horizontal header section positions to determine the positions of columns in the view. \sa verticalOffset()*/int QTreeView::horizontalOffset() const{ Q_D(const QTreeView); return d->header->offset();}/*! Returns the vertical offset of the items in the tree view. \sa horizontalOffset()*/int QTreeView::verticalOffset() const{ Q_D(const QTreeView); // gives an estimate if (model() && model()->rowCount(rootIndex()) > 0) { float items = float(verticalScrollBar()->value()) / float(verticalStepsPerItem()); return int(items * d->itemHeight); } // no items, no offset return 0;}/*! Move the cursor in the way described by \a cursorAction, using the information provided by the button \a modifiers.*/QModelIndex QTreeView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers){ Q_D(QTreeView); Q_UNUSED(modifiers); QModelIndex current = currentIndex(); if (!current.isValid()) { int i = 0; while (i < d->viewItems.count() && d->hiddenIndexes.contains(d->viewItems.at(i).index)) ++i; return d->viewItems.value(i).index; } int vi = qMax(0, d->viewIndex(current)); switch (cursorAction) { case MoveNext: case MoveDown:#ifdef QT_KEYPAD_NAVIGATION if (vi == d->viewItems.count()-1 && QApplication::keypadNavigationEnabled()) return model()->index(0, 0, rootIndex());#endif return d->modelIndex(d->below(vi)); case MovePrevious: case MoveUp:#ifdef QT_KEYPAD_NAVIGATION if (vi == 0 && QApplication::keypadNavigationEnabled()) return d->modelIndex(d->viewItems.count() - 1);#endif return d->modelIndex(d->above(vi)); case MoveLeft: if (d->viewItems.at(vi).expanded && d->itemsExpandable) d->collapse(vi, true); updateGeometries(); viewport()->update(); break; case MoveRight: if (!d->viewItems.at(vi).expanded && d->itemsExpandable)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -