summaryrefslogtreecommitdiffstats
path: root/src/widgets/styles
diff options
context:
space:
mode:
authorChristian Ehrlicher <ch.ehrlicher@gmx.de>2018-05-16 21:05:03 +0200
committerChristian Ehrlicher <ch.ehrlicher@gmx.de>2018-06-25 18:58:07 +0000
commit5712c62d1cfdcf56c772d8a63d52ad58945f194c (patch)
tree72d642a8b4ce954f27011453ce7bc52cab04abea /src/widgets/styles
parent2cf5c5a602af5603c9d8320aeaa1454733650e2a (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>
Diffstat (limited to 'src/widgets/styles')
-rw-r--r--src/widgets/styles/qcommonstyle.cpp79
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;
}
}