qtreeview.cpp

来自「奇趣公司比较新的qt/emd版本」· C++ 代码 · 共 2,004 行 · 第 1/5 页

CPP
2,004
字号
}/*!  \reimp*/void QTreeView::paintEvent(QPaintEvent *event){    Q_D(QTreeView);    d->executePostedLayout();    QPainter painter(viewport());    if (d->isAnimating()) {        drawTree(&painter, event->region() - d->animationRect());        d->drawAnimatedOperation(&painter);    } else {        drawTree(&painter, event->region());#ifndef QT_NO_DRAGANDDROP        d->paintDropIndicator(&painter);#endif    }}/*!  \since 4.2  Draws the part of the tree intersecting the given \a region using the specified  \a painter.  \sa paintEvent()*/void QTreeView::drawTree(QPainter *painter, const QRegion &region) const{    Q_D(const QTreeView);    const QVector<QTreeViewItem> viewItems = d->viewItems;    if (viewItems.count() == 0 || d->header->count() == 0 || !d->itemDelegate) {        return;    }    QStyleOptionViewItemV3 option = d->viewOptionsV3();    const QStyle::State state = option.state;    int firstVisibleItemOffset = 0;    const int firstVisibleItem = d->firstVisibleItem(&firstVisibleItemOffset);    if (firstVisibleItem < 0)        return;    const int viewportWidth = d->viewport->width();    QVector<QRect> rects = region.rects();    QVector<int> drawn;    bool multipleRects = (rects.size() > 1);    for (int a = 0; a < rects.size(); ++a) {        const QRect area = (multipleRects                            ? QRect(0, rects.at(a).y(), viewportWidth, rects.at(a).height())                            : rects.at(a));        d->leftAndRight = d->startAndEndColumns(area);        int i = firstVisibleItem; // the first item at the top of the viewport        int y = firstVisibleItemOffset; // we may only see part of the first item        // start at the top of the viewport  and iterate down to the update area        for (; i < viewItems.count(); ++i) {            const int itemHeight = d->itemHeight(i);            if (y + itemHeight >= area.top())                break;            y += itemHeight;        }        // paint the visible rows        for (; i < viewItems.count() && y <= area.bottom(); ++i) {            const int itemHeight = d->itemHeight(i);            option.rect.setRect(0, y, viewportWidth, itemHeight);            option.state = state | (viewItems.at(i).expanded                                    ? QStyle::State_Open : QStyle::State_None);            d->current = i;            d->spanning = viewItems.at(i).spanning;            if (!multipleRects || !drawn.contains(i)) {                drawRow(painter, option, viewItems.at(i).index);                if (multipleRects)   // even if the rect only intersects the item,                    drawn.append(i); // the entire item will be painted            }            y += itemHeight;        }    }}/// ### move to QObject :)static inline bool ancestorOf(QObject *widget, QObject *other){    for (QObject *parent = other; parent != 0; parent = parent->parent()) {        if (parent == widget)            return true;    }    return false;}/*!    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 setAlternatingRowColors()*/void QTreeView::drawRow(QPainter *painter, const QStyleOptionViewItem &option,                        const QModelIndex &index) const{    Q_D(const QTreeView);    QStyleOptionViewItemV3 opt = option;    const QPoint offset = d->scrollDelayOffset;    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 reverse = isRightToLeft();    const QStyle::State state = opt.state;    const bool spanning = d->spanning;    const int left = (spanning ? 0 : d->leftAndRight.first);    const int right = (spanning ? 0 : d->leftAndRight.second);    const bool alternate = d->alternatingColors;    const bool enabled = (state & QStyle::State_Enabled) != 0;    const bool allColumnsShowFocus = d->allColumnsShowFocus;    // when the row contains an index widget which has focus,    // we want to paint the entire row as active    bool indexWidgetHasFocus = false;    if ((current.row() == index.row()) && !d->editors.isEmpty()) {        const int r = index.row();        QWidget *fw = QApplication::focusWidget();        for (int c = 0; c < header->count(); ++c) {            if (QWidget *editor = indexWidget(index.sibling(r, c))) {                if (ancestorOf(editor, fw)) {                    indexWidgetHasFocus = true;                    break;                }            }        }    }    const bool widgetHasFocus = hasFocus();    bool currentRowHasFocus = false;    if (allColumnsShowFocus && widgetHasFocus && current.isValid()) { // check if the focus index is before or after the visible columns        const int r = index.row();        for (int c = 0; c < left && !currentRowHasFocus; ++c)            currentRowHasFocus = (index.sibling(r, c) == current);        QModelIndex parent = d->model->parent(index);        for (int c = right; c < header->count() && !currentRowHasFocus; ++c) {            currentRowHasFocus = (d->model->index(r, c, parent) == current);        }    }    // ### 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 = header->logicalIndex(headerIndex);        if (header->isSectionHidden(headerSection))            continue;        position = columnViewportPosition(headerSection) + offset.x();        width = (spanning ? header->length() : header->sectionSize(headerSection));        modelIndex = d->model->index(index.row(), headerSection, parent);        if (!modelIndex.isValid())            continue;        opt.state = state;        // fake activeness when row editor has focus        if (indexWidgetHasFocus)            opt.state |= QStyle::State_Active;        if (d->selectionModel->isSelected(modelIndex))            opt.state |= QStyle::State_Selected;        if (widgetHasFocus && (current == modelIndex)) {            if (allColumnsShowFocus)                currentRowHasFocus = true;            else                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 ((d->model->flags(index) & Qt::ItemIsEnabled) == 0) {                opt.state &= ~QStyle::State_Enabled;                cg = QPalette::Disabled;            } else if (opt.state & QStyle::State_Active) {                cg = QPalette::Active;            } else {                cg = QPalette::Inactive;            }            opt.palette.setCurrentColorGroup(cg);        }        if (alternate) {            if (d->current & 1) {                opt.features |= QStyleOptionViewItemV2::Alternate;            } else {                opt.features &= ~QStyleOptionViewItemV2::Alternate;            }        }        if (headerSection == 0) {            const int i = d->indentationForItem(d->current);            QRect branches(reverse ? position + width - i : position, y, i, height);            const bool setClipRect = branches.width() > width;            if (setClipRect) {                painter->save();                painter->setClipRect(QRect(position, y, width, height));            }            opt.rect.setRect(reverse ? position : i + position, y, width - i, height);            if (alternate && (d->current & 1))                painter->fillRect(opt.rect, opt.palette.alternateBase());            if ((opt.state & QStyle::State_Selected) && option.showDecorationSelected)                painter->fillRect(branches, opt.palette.highlight());            else if (alternate && (d->current & 1))                painter->fillRect(branches, opt.palette.alternateBase());            drawBranches(painter, branches, index);            if (setClipRect)                painter->restore();        } else {            opt.rect.setRect(position, y, width, height);            if (alternate & (d->current & 1)) {                painter->fillRect(opt.rect, opt.palette.alternateBase());            }        }        if (const QWidget *widget = d->editorForIndex(modelIndex)) {            painter->save();            painter->setClipRect(widget->geometry());            d->delegateForIndex(modelIndex)->paint(painter, opt, modelIndex);            painter->restore();        } else {            d->delegateForIndex(modelIndex)->paint(painter, opt, modelIndex);        }    }    if (currentRowHasFocus) {        QStyleOptionFocusRect o;        o.QStyleOption::operator=(option);        o.state |= QStyle::State_KeyboardFocusChange;        QPalette::ColorGroup cg = (option.state & QStyle::State_Enabled)                                  ? QPalette::Normal : QPalette::Disabled;        o.backgroundColor = option.palette.color(cg, d->selectionModel->isSelected(index)                                                 ? QPalette::Highlight : QPalette::Background);        int x = 0;        if (!option.showDecorationSelected)            x = header->sectionPosition(0) + d->indentationForItem(d->current);        o.rect.setRect(x - header->offset(), y, header->length() - x, height);        style()->drawPrimitive(QStyle::PE_FrameFocusRect, &o, painter);        // if we show focus on all columns and the first section is moved,        // we have to split the focus rect into two rects        if (allColumnsShowFocus && !option.showDecorationSelected            && header->sectionsMoved() && (header->visualIndex(0) != 0)) {            o.rect.setRect(0, y, header->sectionPosition(0), height);            style()->drawPrimitive(QStyle::PE_FrameFocusRect, &o, painter);        }    }}/*!  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;    const QTreeViewItem &viewItem = d->viewItems.at(item);    int level = viewItem.level;    QRect primitive(reverse ? rect.left() : rect.right(), rect.top(), indent, rect.height());    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();    if (verticalScrollMode() == QAbstractItemView::ScrollPerPixel)        painter->setBrushOrigin(QPoint(0, verticalOffset()));    if (level >= outer) {        // start with the innermost branch        primitive.moveLeft(reverse ? primitive.left() : primitive.left() - indent);        opt.rect = primitive;        const bool expanded = viewItem.expanded;        const bool children = (((expanded && viewItem.total > 0)) // already laid out and has children                                || d->hasVisibleChildren(index)); // not laid 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);        if (item == d->hoverBranch)            opt.state |= QStyle::State_MouseOver;        else            opt.state &= ~QStyle::State_MouseOver;        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;        bool moreSiblings = false;        if (d->hiddenIndexes.isEmpty()) {            moreSiblings = (d->model->rowCount(ancestor) - 1 > current.row());        } else {            int successor = item + viewItem.total + 1;            while (successor < d->viewItems.size()                   && d->viewItems.at(successor).level >= uint(level)) {                const QTreeViewItem &successorItem = d->viewItems.at(successor);                if (successorItem.level == uint(level)) {                    moreSiblings = true;                    break;                }                successor += successorItem.total + 1;            }        }        if (moreSiblings)            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);    // we want to handle mousePress in EditingState (persistent editors)    if ((state() != NoState && state() != EditingState) || !d->viewport->rect().contains(event->pos())) {        return;    }    int i = d->itemDecorationAt(event->pos());    if ((i != -1) && itemsExpandable() && d->hasVisibleChildren(d->viewItems.at(i).index)) {        if (d->viewItems.at(i).expanded)            d->collapse(i, true);        else            d->expand(i, true);        if (!d->isAnimating()) {            updateGeometries();            viewport()->update();        }    } else {        QAbstractItemView::mousePressEvent(event);    }}/*!  \reimp*/void QTreeView::mouseReleaseEvent(QMouseEvent *event){    Q_D(QTreeView);    if (d->itemDecorationAt(event->pos()) == -1) { // ### what about expanding/collapsing state ?        QAbstractItemView::mouseReleaseEvent(event);    } else {        if (state() == QAbstractItemView::DragSelectingState)            setState(QAbstractItemView::NoState);    }}/*!  \reimp*/void QTreeView::mouseDoubleClickEvent(QMouseEvent *event){    Q_D(QTreeView);    if (state() != NoState || !d->viewport->rect().contains(event->pos()))        return;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?