diff options
author | Christian Ehrlicher <ch.ehrlicher@gmx.de> | 2018-05-16 21:05:03 +0200 |
---|---|---|
committer | Christian Ehrlicher <ch.ehrlicher@gmx.de> | 2018-06-25 18:58:07 +0000 |
commit | 5712c62d1cfdcf56c772d8a63d52ad58945f194c (patch) | |
tree | 72d642a8b4ce954f27011453ce7bc52cab04abea | |
parent | 2cf5c5a602af5603c9d8320aeaa1454733650e2a (diff) |
QCommonStyle: properly elide last visible line
Rewrite QCommonStylePrivate::viewItemDrawText() to be able to elide
lines which are too long and the last visible line. The painting is now
done in one pass instead of two and lines which are not visible due to
a size constraint are not painted at all.
[ChangeLog][QtWidgets][Itemviews] Fixed eliding of multi-line items
Task-number: QTBUG-12129
Task-number: QTBUG-14949
Task-number: QTBUG-57891
Change-Id: I3a41938e442663ecd7e5ca56bf6bbd857edafb7d
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
-rw-r--r-- | src/widgets/styles/qcommonstyle.cpp | 79 |
1 files changed, 39 insertions, 40 deletions
diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp index f083359c06..4c01807ca7 100644 --- a/src/widgets/styles/qcommonstyle.cpp +++ b/src/widgets/styles/qcommonstyle.cpp @@ -933,54 +933,53 @@ void QCommonStylePrivate::viewItemDrawText(QPainter *p, const QStyleOptionViewIt viewItemTextLayout(textLayout, textRect.width()); - qreal height = 0; - qreal width = 0; - const int lineCount = textLayout.lineCount(); - QHash<int, QString> elidedTexts; - for (int j = 0; j < lineCount; ++j) { - const QTextLine line = textLayout.lineAt(j); - if (j + 1 <= lineCount - 1) { - const QTextLine nextLine = textLayout.lineAt(j + 1); - if ((nextLine.y() + nextLine.height()) > textRect.height()) { - int start = line.textStart(); - int length = line.textLength() + nextLine.textLength(); - const QStackTextEngine engine(textLayout.text().mid(start, length), option->font); - elidedTexts.insert(j, engine.elidedText(option->textElideMode, textRect.width())); - height += line.height(); - width = textRect.width(); - continue; - } - } - if (line.naturalTextWidth() > textRect.width()) { - int start = line.textStart(); - int length = line.textLength(); - const QStackTextEngine engine(textLayout.text().mid(start, length), option->font); - elidedTexts.insert(j, engine.elidedText(option->textElideMode, textRect.width())); - height += line.height(); - width = textRect.width(); - continue; - } - width = qMax<qreal>(width, line.width()); - height += line.height(); - } - + const QRectF boundingRect = textLayout.boundingRect(); const QRect layoutRect = QStyle::alignedRect(option->direction, option->displayAlignment, - QSize(int(width), int(height)), textRect); + boundingRect.size().toSize(), textRect); const QPointF position = layoutRect.topLeft(); + const int lineCount = textLayout.lineCount(); + + qreal height = 0; for (int i = 0; i < lineCount; ++i) { const QTextLine line = textLayout.lineAt(i); - auto it = elidedTexts.constFind(i); - if (it != elidedTexts.constEnd()) { - const QString &elidedText = it.value(); - qreal x = position.x() + line.x(); - qreal y = position.y() + line.y() + line.ascent(); + height += line.height(); + + // above visible rect + if (height + layoutRect.top() <= textRect.top()) + continue; + + const int start = line.textStart(); + const int length = line.textLength(); + + const bool drawElided = line.naturalTextWidth() > textRect.width(); + bool elideLastVisibleLine = false; + if (!drawElided && i + 1 < lineCount) { + const QTextLine nextLine = textLayout.lineAt(i + 1); + const int nextHeight = height + nextLine.height() / 2; + // elide when less than the next half line is visible + if (nextHeight + layoutRect.top() > textRect.height() + textRect.top()) + elideLastVisibleLine = true; + } + + if (drawElided || elideLastVisibleLine) { + QString text = textLayout.text().mid(start, length); + if (elideLastVisibleLine) + text += QChar(0x2026); + const QStackTextEngine engine(text, option->font); + const QString elidedText = engine.elidedText(option->textElideMode, textRect.width()); + const QPointF pos(position.x() + line.x(), + position.y() + line.y() + line.ascent()); p->save(); p->setFont(option->font); - p->drawText(QPointF(x, y), elidedText); + p->drawText(pos, elidedText); p->restore(); - continue; + } else { + line.draw(p, position); } - line.draw(p, position); + + // below visible text, can stop + if (height + layoutRect.top() >= textRect.bottom()) + break; } } |