113 const QRect &decorationRect,
const QRect &checkRect)
const
115 QRect rect = option.rect;
116 const QWidget *w = widget(option);
117 QStyle *style = w ? w->style() : QApplication::style();
118 const bool wrapText = option.features & QStyleOptionViewItem::WrapText;
120 const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin,
nullptr, w) + 1;
121 switch (option.decorationPosition) {
122 case QStyleOptionViewItem::Left:
123 case QStyleOptionViewItem::Right:
124 rect.setWidth(wrapText && rect.isValid() ? rect.width() - 2 * textMargin : (QFIXED_MAX));
126 case QStyleOptionViewItem::Top:
127 case QStyleOptionViewItem::Bottom:
128 rect.setWidth(wrapText ? option.decorationSize.width() - 2 * textMargin : (QFIXED_MAX));
133 if (!decorationRect.isNull())
134 rect.setWidth(rect.width() - decorationRect.width() - 2 * textMargin);
135 if (!checkRect.isNull())
136 rect.setWidth(rect.width() - checkRect.width() - 2 * textMargin);
138 const QSizeF size = doTextLayout(rect.width());
139 rect.setHeight(qCeil(size.height()));
368void QItemDelegate::paint(QPainter *painter,
369 const QStyleOptionViewItem &option,
370 const QModelIndex &index)
const
372 Q_D(
const QItemDelegate);
373 Q_ASSERT(index.isValid());
375 QStyleOptionViewItem opt = setOptions(index, option);
380 painter->setClipRect(opt.rect);
387 QRect decorationRect;
388 value = index.data(Qt::DecorationRole);
389 if (value.isValid()) {
391 pixmap = decoration(opt, value);
392 if (value.userType() == QMetaType::QIcon) {
393 d->tmp.icon = qvariant_cast<QIcon>(value);
394 d->tmp.mode = d->iconMode(option.state);
395 d->tmp.state = d->iconState(option.state);
396 const QSize size = d->tmp.icon.actualSize(option.decorationSize,
397 d->tmp.mode, d->tmp.state);
398 decorationRect = QRect(QPoint(0, 0), size);
400 d->tmp.icon = QIcon();
401 decorationRect = QRect(QPoint(0, 0), pixmap.size());
404 d->tmp.icon = QIcon();
405 decorationRect = QRect();
409 Qt::CheckState checkState = Qt::Unchecked;
410 value = index.data(Qt::CheckStateRole);
411 if (value.isValid()) {
412 checkState = QtPrivate::legacyEnumValueFromModelData<Qt::CheckState>(value);
413 checkRect = doCheck(opt, opt.rect, value);
418 value = index.data(Qt::DisplayRole);
419 if (value.isValid() && !value.isNull()) {
420 text = d->valueToText(value, opt);
421 displayRect = d->displayRect(index, opt, decorationRect, checkRect);
426 doLayout(opt, &checkRect, &decorationRect, &displayRect,
false);
430 drawBackground(painter, opt, index);
431 drawCheck(painter, opt, checkRect, checkState);
432 drawDecoration(painter, opt, decorationRect, pixmap);
433 drawDisplay(painter, opt, displayRect, text);
434 drawFocus(painter, opt, displayRect);
543void QItemDelegate::updateEditorGeometry(QWidget *editor,
544 const QStyleOptionViewItem &option,
545 const QModelIndex &index)
const
549 Q_ASSERT(index.isValid());
550 QPixmap pixmap = decoration(option, index.data(Qt::DecorationRole));
551 QString text = QItemDelegatePrivate::replaceNewLine(index.data(Qt::DisplayRole).toString());
552 QRect pixmapRect = QRect(QPoint(0, 0), option.decorationSize).intersected(pixmap.rect());
553 QRect textRect = textRectangle(
nullptr, option.rect, option.font, text);
554 QRect checkRect = doCheck(option, textRect, index.data(Qt::CheckStateRole));
555 QStyleOptionViewItem opt = option;
556 opt.showDecorationSelected =
true;
557 doLayout(opt, &checkRect, &pixmapRect, &textRect,
false);
558 editor->setGeometry(textRect);
591void QItemDelegate::drawDisplay(QPainter *painter,
const QStyleOptionViewItem &option,
592 const QRect &rect,
const QString &text)
const
594 Q_D(
const QItemDelegate);
596 QPalette::ColorGroup cg = option.state & QStyle::State_Enabled
597 ? QPalette::Normal : QPalette::Disabled;
598 if (cg == QPalette::Normal && !(option.state & QStyle::State_Active))
599 cg = QPalette::Inactive;
600 if (option.state & QStyle::State_Selected) {
601 painter->fillRect(rect, option.palette.brush(cg, QPalette::Highlight));
602 painter->setPen(option.palette.color(cg, QPalette::HighlightedText));
604 painter->setPen(option.palette.color(cg, QPalette::Text));
610 const QStyleOptionViewItem opt = option;
612 const QWidget *widget = d->widget(option);
613 QStyle *style = widget ? widget->style() : QApplication::style();
614 const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin,
nullptr, widget) + 1;
615 QRect textRect = rect.adjusted(textMargin, 0, -textMargin, 0);
616 const bool wrapText = opt.features & QStyleOptionViewItem::WrapText;
617 d->textOption.setWrapMode(wrapText ? QTextOption::WordWrap : QTextOption::ManualWrap);
618 d->textOption.setTextDirection(option.direction);
619 d->textOption.setAlignment(QStyle::visualAlignment(option.direction, option.displayAlignment));
620 d->textLayout.setTextOption(d->textOption);
621 d->textLayout.setFont(option.font);
622 d->textLayout.setText(QItemDelegatePrivate::replaceNewLine(text));
624 QSizeF textLayoutSize = d->doTextLayout(textRect.width());
626 if (textRect.width() < textLayoutSize.width()
627 || textRect.height() < textLayoutSize.height()) {
630 int end = text.indexOf(QChar::LineSeparator, start);
632 elided += option.fontMetrics.elidedText(text, option.textElideMode, textRect.width());
635 elided += option.fontMetrics.elidedText(text.mid(start, end - start),
636 option.textElideMode, textRect.width());
637 elided += QChar::LineSeparator;
639 end = text.indexOf(QChar::LineSeparator, start);
642 elided += option.fontMetrics.elidedText(text.mid(start),
643 option.textElideMode, textRect.width());
645 d->textLayout.setText(elided);
646 textLayoutSize = d->doTextLayout(textRect.width());
649 const QSize layoutSize(textRect.width(),
int(textLayoutSize.height()));
650 const QRect layoutRect = QStyle::alignedRect(option.direction, option.displayAlignment,
651 layoutSize, textRect);
653 if (!hasClipping() && (textRect.width() < textLayoutSize.width()
654 || textRect.height() < textLayoutSize.height())) {
656 painter->setClipRect(layoutRect);
657 d->textLayout.draw(painter, layoutRect.topLeft(), QList<QTextLayout::FormatRange>(),
661 d->textLayout.draw(painter, layoutRect.topLeft(), QList<QTextLayout::FormatRange>(),
670void QItemDelegate::drawDecoration(QPainter *painter,
const QStyleOptionViewItem &option,
671 const QRect &rect,
const QPixmap &pixmap)
const
673 Q_D(
const QItemDelegate);
675 if (!d->tmp.icon.isNull()) {
676 d->tmp.icon.paint(painter, rect, option.decorationAlignment,
677 d->tmp.mode, d->tmp.state);
681 if (pixmap.isNull() || !rect.isValid())
683 QPoint p = QStyle::alignedRect(option.direction, option.decorationAlignment,
684 pixmap.size(), rect).topLeft();
685 if (option.state & QStyle::State_Selected) {
686 const QPixmap pm = selectedPixmap(pixmap, option.palette, option.state & QStyle::State_Enabled);
687 painter->drawPixmap(p, pm);
689 painter->drawPixmap(p, pixmap);
787void QItemDelegate::doLayout(
const QStyleOptionViewItem &option,
788 QRect *checkRect, QRect *pixmapRect, QRect *textRect,
791 Q_ASSERT(checkRect && pixmapRect && textRect);
792 Q_D(
const QItemDelegate);
793 const QWidget *widget = d->widget(option);
794 QStyle *style = widget ? widget->style() : QApplication::style();
795 const bool hasCheck = checkRect->isValid();
796 const bool hasPixmap = pixmapRect->isValid();
797 const bool hasText = textRect->isValid();
798 const bool hasMargin = (hasText | hasPixmap | hasCheck);
799 const int frameHMargin = hasMargin ?
800 style->pixelMetric(QStyle::PM_FocusFrameHMargin,
nullptr, widget) + 1 : 0;
801 const int textMargin = hasText ? frameHMargin : 0;
802 const int pixmapMargin = hasPixmap ? frameHMargin : 0;
803 const int checkMargin = hasCheck ? frameHMargin : 0;
804 const int x = option.rect.left();
805 const int y = option.rect.top();
808 textRect->adjust(-textMargin, 0, textMargin, 0);
809 if (textRect->height() == 0 && (!hasPixmap || !hint)) {
811 textRect->setHeight(option.fontMetrics.height());
816 pm = pixmapRect->size();
817 pm.rwidth() += 2 * pixmapMargin;
820 h = qMax(checkRect->height(), qMax(textRect->height(), pm.height()));
821 if (option.decorationPosition == QStyleOptionViewItem::Left
822 || option.decorationPosition == QStyleOptionViewItem::Right) {
823 w = textRect->width() + pm.width();
825 w = qMax(textRect->width(), pm.width());
828 w = option.rect.width();
829 h = option.rect.height();
835 cw = checkRect->width() + 2 * checkMargin;
837 if (option.direction == Qt::RightToLeft) {
838 check.setRect(x + w - cw, y, cw, h);
840 check.setRect(x, y, cw, h);
848 switch (option.decorationPosition) {
849 case QStyleOptionViewItem::Top: {
851 pm.setHeight(pm.height() + pixmapMargin);
852 h = hint ? textRect->height() : h - pm.height();
854 if (option.direction == Qt::RightToLeft) {
855 decoration.setRect(x, y, w - cw, pm.height());
856 display.setRect(x, y + pm.height(), w - cw, h);
858 decoration.setRect(x + cw, y, w - cw, pm.height());
859 display.setRect(x + cw, y + pm.height(), w - cw, h);
862 case QStyleOptionViewItem::Bottom: {
864 textRect->setHeight(textRect->height() + textMargin);
865 h = hint ? textRect->height() + pm.height() : h;
867 if (option.direction == Qt::RightToLeft) {
868 display.setRect(x, y, w - cw, textRect->height());
869 decoration.setRect(x, y + textRect->height(), w - cw, h - textRect->height());
871 display.setRect(x + cw, y, w - cw, textRect->height());
872 decoration.setRect(x + cw, y + textRect->height(), w - cw, h - textRect->height());
875 case QStyleOptionViewItem::Left: {
876 if (option.direction == Qt::LeftToRight) {
877 decoration.setRect(x + cw, y, pm.width(), h);
878 display.setRect(decoration.right() + 1, y, w - pm.width() - cw, h);
880 display.setRect(x, y, w - pm.width() - cw, h);
881 decoration.setRect(display.right() + 1, y, pm.width(), h);
884 case QStyleOptionViewItem::Right: {
885 if (option.direction == Qt::LeftToRight) {
886 display.setRect(x + cw, y, w - pm.width() - cw, h);
887 decoration.setRect(display.right() + 1, y, pm.width(), h);
889 decoration.setRect(x, y, pm.width(), h);
890 display.setRect(decoration.right() + 1, y, w - pm.width() - cw, h);
894 qWarning(
"doLayout: decoration position is invalid");
895 decoration = *pixmapRect;
900 *checkRect = QStyle::alignedRect(option.direction, Qt::AlignCenter,
901 checkRect->size(), check);
902 *pixmapRect = QStyle::alignedRect(option.direction, option.decorationAlignment,
903 pixmapRect->size(), decoration);
905 if (option.showDecorationSelected)
908 *textRect = QStyle::alignedRect(option.direction, option.displayAlignment,
909 textRect->size().boundedTo(display.size()), display);
912 *pixmapRect = decoration;
998QRect QItemDelegate::rect(
const QStyleOptionViewItem &option,
999 const QModelIndex &index,
int role)
const
1001 Q_D(
const QItemDelegate);
1002 QVariant value = index.data(role);
1003 if (role == Qt::CheckStateRole)
1004 return doCheck(option, option.rect, value);
1005 if (value.isValid() && !value.isNull()) {
1006 switch (value.userType()) {
1007 case QMetaType::UnknownType:
1009 case QMetaType::QPixmap: {
1010 const QPixmap &pixmap = qvariant_cast<QPixmap>(value);
1011 return QRect(QPoint(0, 0), pixmap.deviceIndependentSize().toSize()); }
1012 case QMetaType::QImage: {
1013 const QImage &image = qvariant_cast<QImage>(value);
1014 return QRect(QPoint(0, 0), image.deviceIndependentSize().toSize()); }
1015 case QMetaType::QIcon: {
1016 QIcon::Mode mode = d->iconMode(option.state);
1017 QIcon::State state = d->iconState(option.state);
1018 QIcon icon = qvariant_cast<QIcon>(value);
1019 QSize size = icon.actualSize(option.decorationSize, mode, state);
1020 return QRect(QPoint(0, 0), size); }
1021 case QMetaType::QColor:
1022 return QRect(QPoint(0, 0), option.decorationSize);
1023 case QMetaType::QString:
1025 const QString text = d->valueToText(value, option);
1026 value = index.data(Qt::FontRole);
1027 QFont fnt = qvariant_cast<QFont>(value).resolve(option.font);
1028 return textRectangle(
nullptr,
1029 d->textLayoutBounds(option, QRect(), QRect()),
1087bool QItemDelegate::editorEvent(QEvent *event,
1088 QAbstractItemModel *model,
1089 const QStyleOptionViewItem &option,
1090 const QModelIndex &index)
1096 Qt::ItemFlags flags = model->flags(index);
1097 if (!(flags & Qt::ItemIsUserCheckable) || !(option.state & QStyle::State_Enabled)
1098 || !(flags & Qt::ItemIsEnabled))
1102 QVariant value = index.data(Qt::CheckStateRole);
1103 if (!value.isValid())
1107 if ((event->type() == QEvent::MouseButtonRelease)
1108 || (event->type() == QEvent::MouseButtonDblClick)
1109 || (event->type() == QEvent::MouseButtonPress)) {
1110 QRect checkRect = doCheck(option, option.rect, Qt::Checked);
1112 doLayout(option, &checkRect, &emptyRect, &emptyRect,
false);
1113 QMouseEvent *me =
static_cast<QMouseEvent*>(event);
1114 if (me->button() != Qt::LeftButton || !checkRect.contains(me->position().toPoint()))
1118 if ((event->type() == QEvent::MouseButtonPress)
1119 || (event->type() == QEvent::MouseButtonDblClick))
1122 }
else if (event->type() == QEvent::KeyPress) {
1123 if (
static_cast<QKeyEvent*>(event)->key() != Qt::Key_Space
1124 &&
static_cast<QKeyEvent*>(event)->key() != Qt::Key_Select)
1130 Qt::CheckState state = QtPrivate::legacyEnumValueFromModelData<Qt::CheckState>(value);
1131 if (flags & Qt::ItemIsUserTristate)
1132 state = ((Qt::CheckState)((state + 1) % 3));
1134 state = (state == Qt::Checked) ? Qt::Unchecked : Qt::Checked;
1135 return model->setData(index, state, Qt::CheckStateRole);