QItemDelegate: fix text height calculation
QItemDelegate::textRectangle did not adjust the width when the item had a decoration or a checkbox. This lead to a too big width used for the layouting and therefore sometimes the calculated height was too small. This was already done for QCommonStylePrivate::viewItemSize which is used by QStyledItemDelegate before. [ChangeLog][QtWidgets][QItemDelegate] fix text height calculation when the item has a decoration or checkbox Task-number: QTBUG-16134 Change-Id: I14c47c3f2d8cc0a0b6ec2b2999e70fda213887ae Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
This commit is contained in:
parent
332ce6734d
commit
bdc36cef67
@ -103,7 +103,10 @@ public:
|
||||
QItemEditorFactory *f;
|
||||
bool clipPainting;
|
||||
|
||||
QRect textLayoutBounds(const QStyleOptionViewItem &options) const;
|
||||
QRect displayRect(const QModelIndex &index, const QStyleOptionViewItem &option,
|
||||
const QRect &decorationRect, const QRect &checkRect) const;
|
||||
QRect textLayoutBounds(const QStyleOptionViewItem &option,
|
||||
const QRect &decorationRect, const QRect &checkRect) const;
|
||||
QSizeF doTextLayout(int lineWidth) const;
|
||||
mutable QTextLayout textLayout;
|
||||
mutable QTextOption textOption;
|
||||
@ -121,21 +124,53 @@ public:
|
||||
} tmp;
|
||||
};
|
||||
|
||||
QRect QItemDelegatePrivate::textLayoutBounds(const QStyleOptionViewItem &option) const
|
||||
QRect QItemDelegatePrivate::displayRect(const QModelIndex &index, const QStyleOptionViewItem &option,
|
||||
const QRect &decorationRect, const QRect &checkRect) const
|
||||
{
|
||||
Q_Q(const QItemDelegate);
|
||||
const QVariant value = index.data(Qt::DisplayRole);
|
||||
if (!value.isValid() || value.isNull())
|
||||
return QRect();
|
||||
|
||||
const QString text = valueToText(value, option);
|
||||
const QVariant fontVal = index.data(Qt::FontRole);
|
||||
const QFont fnt = qvariant_cast<QFont>(fontVal).resolve(option.font);
|
||||
return q->textRectangle(nullptr,
|
||||
textLayoutBounds(option, decorationRect, checkRect),
|
||||
fnt, text);
|
||||
}
|
||||
|
||||
// similar to QCommonStylePrivate::viewItemSize(Qt::DisplayRole)
|
||||
QRect QItemDelegatePrivate::textLayoutBounds(const QStyleOptionViewItem &option,
|
||||
const QRect &decorationRect, const QRect &checkRect) const
|
||||
{
|
||||
QRect rect = option.rect;
|
||||
const QWidget *w = widget(option);
|
||||
QStyle *style = w ? w->style() : QApplication::style();
|
||||
const bool wrapText = option.features & QStyleOptionViewItem::WrapText;
|
||||
// see QItemDelegate::drawDisplay
|
||||
const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, w) + 1;
|
||||
switch (option.decorationPosition) {
|
||||
case QStyleOptionViewItem::Left:
|
||||
case QStyleOptionViewItem::Right:
|
||||
rect.setWidth(wrapText && rect.isValid() ? rect.width() : (QFIXED_MAX));
|
||||
rect.setWidth(wrapText && rect.isValid() ? rect.width() - 2 * textMargin : (QFIXED_MAX));
|
||||
break;
|
||||
case QStyleOptionViewItem::Top:
|
||||
case QStyleOptionViewItem::Bottom:
|
||||
rect.setWidth(wrapText ? option.decorationSize.width() : (QFIXED_MAX));
|
||||
rect.setWidth(wrapText ? option.decorationSize.width() - 2 * textMargin : (QFIXED_MAX));
|
||||
break;
|
||||
}
|
||||
|
||||
if (wrapText) {
|
||||
if (!decorationRect.isNull())
|
||||
rect.setWidth(rect.width() - decorationRect.width() - 2 * textMargin);
|
||||
if (!checkRect.isNull())
|
||||
rect.setWidth(rect.width() - checkRect.width() - 2 * textMargin);
|
||||
// adjust height to be sure that the text fits
|
||||
const QSizeF size = doTextLayout(rect.width());
|
||||
rect.setHeight(qCeil(size.height()));
|
||||
}
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
@ -395,14 +430,6 @@ void QItemDelegate::paint(QPainter *painter,
|
||||
decorationRect = QRect();
|
||||
}
|
||||
|
||||
QString text;
|
||||
QRect displayRect;
|
||||
value = index.data(Qt::DisplayRole);
|
||||
if (value.isValid() && !value.isNull()) {
|
||||
text = d->valueToText(value, opt);
|
||||
displayRect = textRectangle(painter, d->textLayoutBounds(opt), opt.font, text);
|
||||
}
|
||||
|
||||
QRect checkRect;
|
||||
Qt::CheckState checkState = Qt::Unchecked;
|
||||
value = index.data(Qt::CheckStateRole);
|
||||
@ -411,6 +438,14 @@ void QItemDelegate::paint(QPainter *painter,
|
||||
checkRect = doCheck(opt, opt.rect, value);
|
||||
}
|
||||
|
||||
QString text;
|
||||
QRect displayRect;
|
||||
value = index.data(Qt::DisplayRole);
|
||||
if (value.isValid() && !value.isNull()) {
|
||||
text = d->valueToText(value, opt);
|
||||
displayRect = d->displayRect(index, opt, decorationRect, checkRect);
|
||||
}
|
||||
|
||||
// do the layout
|
||||
|
||||
doLayout(opt, &checkRect, &decorationRect, &displayRect, false);
|
||||
@ -440,12 +475,13 @@ void QItemDelegate::paint(QPainter *painter,
|
||||
QSize QItemDelegate::sizeHint(const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
Q_D(const QItemDelegate);
|
||||
QVariant value = index.data(Qt::SizeHintRole);
|
||||
if (value.isValid())
|
||||
return qvariant_cast<QSize>(value);
|
||||
QRect decorationRect = rect(option, index, Qt::DecorationRole);
|
||||
QRect displayRect = rect(option, index, Qt::DisplayRole);
|
||||
QRect checkRect = rect(option, index, Qt::CheckStateRole);
|
||||
QRect displayRect = d->displayRect(index, option, decorationRect, checkRect);
|
||||
|
||||
doLayout(option, &checkRect, &decorationRect, &displayRect, true);
|
||||
|
||||
@ -1000,8 +1036,8 @@ QPixmap *QItemDelegate::selected(const QPixmap &pixmap, const QPalette &palette,
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Only used (and usable) for Qt::DecorationRole and Qt::CheckStateRole
|
||||
*/
|
||||
|
||||
QRect QItemDelegate::rect(const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index, int role) const
|
||||
{
|
||||
@ -1032,7 +1068,9 @@ QRect QItemDelegate::rect(const QStyleOptionViewItem &option,
|
||||
const QString text = d->valueToText(value, option);
|
||||
value = index.data(Qt::FontRole);
|
||||
QFont fnt = qvariant_cast<QFont>(value).resolve(option.font);
|
||||
return textRectangle(0, d->textLayoutBounds(option), fnt, text); }
|
||||
return textRectangle(nullptr,
|
||||
d->textLayoutBounds(option, QRect(), QRect()),
|
||||
fnt, text); }
|
||||
}
|
||||
}
|
||||
return QRect();
|
||||
|
Loading…
Reference in New Issue
Block a user