QAbstractItemView: fix rendering centered/right aligned item text

Commit 5712c62d1c introduced a regression
for item texts which were aligned right or horizontally centered. The
layoutRect was calculated wrong and started below zero and later the
correct x offset could not be calculated since QTextLine::x() does not
return a calculated value.
Fix it by first calculating the complete string and pass it completely
to QTextLayout::draw() instead trying to draw the single lines on our
own - QTextLayout has a better working algorithm so no need to reinvent
the wheel here.

[ChangeLog][QtWidgets][ItemViews] Fixed a regression with wrongly drawn
centered/right aligned item texts

Fixes: QTBUG-34133
Fixes: QTBUG-56759
Fixes: QTBUG-72805
Fixes: QTBUG-72869
Change-Id: I0ed521c3a9d35446d190ac22aa9f2374814fd278
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
This commit is contained in:
Christian Ehrlicher 2019-01-02 21:24:46 +01:00
parent 7511697efe
commit 25133a1b77

View File

@ -943,17 +943,20 @@ void QCommonStylePrivate::viewItemDrawText(QPainter *p, const QStyleOptionViewIt
const QRectF boundingRect = textLayout.boundingRect(); const QRectF boundingRect = textLayout.boundingRect();
const QRect layoutRect = QStyle::alignedRect(option->direction, option->displayAlignment, const QRect layoutRect = QStyle::alignedRect(option->direction, option->displayAlignment,
boundingRect.size().toSize(), textRect); boundingRect.size().toSize(), textRect);
const QPointF position = layoutRect.topLeft(); QPointF paintPosition = QPointF(textRect.x(), layoutRect.top());
const int lineCount = textLayout.lineCount();
QString newText;
qreal height = 0; qreal height = 0;
const int lineCount = textLayout.lineCount();
for (int i = 0; i < lineCount; ++i) { for (int i = 0; i < lineCount; ++i) {
const QTextLine line = textLayout.lineAt(i); const QTextLine line = textLayout.lineAt(i);
height += line.height(); height += line.height();
// above visible rect // above visible rect
if (height + layoutRect.top() <= textRect.top()) if (height + layoutRect.top() <= textRect.top()) {
paintPosition.ry() += line.height();
continue; continue;
}
const int start = line.textStart(); const int start = line.textStart();
const int length = line.textLength(); const int length = line.textLength();
@ -968,26 +971,33 @@ void QCommonStylePrivate::viewItemDrawText(QPainter *p, const QStyleOptionViewIt
elideLastVisibleLine = true; elideLastVisibleLine = true;
} }
if (drawElided || elideLastVisibleLine) {
QString text = textLayout.text().mid(start, length); QString text = textLayout.text().mid(start, length);
if (elideLastVisibleLine) if (drawElided || elideLastVisibleLine) {
if (elideLastVisibleLine) {
if (text.endsWith(QChar::LineSeparator))
text.chop(1);
text += QChar(0x2026); text += QChar(0x2026);
}
const QStackTextEngine engine(text, option->font); const QStackTextEngine engine(text, option->font);
const QString elidedText = engine.elidedText(option->textElideMode, textRect.width()); newText += engine.elidedText(option->textElideMode, textRect.width());
const QPointF pos(position.x() + line.x(), // sometimes drawElided is true but no eliding is done so the text ends
position.y() + line.y() + line.ascent()); // with QChar::LineSeparator - don't add another one. This happened with
p->save(); // arabic text in the testcase for QTBUG-72805
p->setFont(option->font); if (i < lineCount - 1 &&
p->drawText(pos, elidedText); !newText.endsWith(QChar::LineSeparator))
p->restore(); newText += QChar::LineSeparator;
} else { } else {
line.draw(p, position); newText += text;
} }
// below visible text, can stop // below visible text, can stop
if (height + layoutRect.top() >= textRect.bottom()) if (height + layoutRect.top() >= textRect.bottom())
break; break;
} }
textLayout.setText(newText);
viewItemTextLayout(textLayout, textRect.width());
textLayout.draw(p, paintPosition);
} }
/*! \internal /*! \internal