summaryrefslogtreecommitdiffstats
path: root/src/widgets/styles/qcommonstyle.cpp
diff options
context:
space:
mode:
authorChristian Ehrlicher <ch.ehrlicher@gmx.de>2019-01-27 21:04:25 +0100
committerChristian Ehrlicher <ch.ehrlicher@gmx.de>2019-02-07 05:32:30 +0000
commita7ba79553c364df9ab55c5c177b15606191cd568 (patch)
tree574c6de568531bc75af1ad26d7091f25f00aa0bd /src/widgets/styles/qcommonstyle.cpp
parentddb5d390450de25e510c72b17ed8124b9186a736 (diff)
QCommonStyle: factor out elided text calculation
Factor out the calculation of the elided text from QCommonStylePrivate::viewItemDrawText() so it can be used by other painting functions. Change-Id: I28e6bfd2fe4d7c552848446fa9913df78589d15b Reviewed-by: Christian Andersen <csandersen3@gmail.com> Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
Diffstat (limited to 'src/widgets/styles/qcommonstyle.cpp')
-rw-r--r--src/widgets/styles/qcommonstyle.cpp142
1 files changed, 81 insertions, 61 deletions
diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp
index 3d626a57fa..867e91ab3e 100644
--- a/src/widgets/styles/qcommonstyle.cpp
+++ b/src/widgets/styles/qcommonstyle.cpp
@@ -843,8 +843,6 @@ static void drawArrow(const QStyle *style, const QStyleOptionToolButton *toolbut
}
#endif // QT_CONFIG(toolbutton)
-#if QT_CONFIG(itemviews)
-
static QSizeF viewItemTextLayout(QTextLayout &textLayout, int lineWidth)
{
qreal height = 0;
@@ -863,6 +861,80 @@ static QSizeF viewItemTextLayout(QTextLayout &textLayout, int lineWidth)
return QSizeF(widthUsed, height);
}
+QString QCommonStylePrivate::calculateElidedText(const QString &text, const QTextOption &textOption,
+ const QFont &font, const QRect &textRect, const Qt::Alignment valign,
+ Qt::TextElideMode textElideMode, int flags,
+ bool lastVisibleLineShouldBeElided, QPointF *paintStartPosition) const
+{
+ QTextLayout textLayout(text, font);
+ textLayout.setTextOption(textOption);
+
+ viewItemTextLayout(textLayout, textRect.width());
+
+ const QRectF boundingRect = textLayout.boundingRect();
+ // don't care about LTR/RTL here, only need the height
+ const QRect layoutRect = QStyle::alignedRect(Qt::LayoutDirectionAuto, valign,
+ boundingRect.size().toSize(), textRect);
+
+ if (paintStartPosition)
+ *paintStartPosition = QPointF(textRect.x(), layoutRect.top());
+
+ QString ret;
+ qreal height = 0;
+ const int lineCount = textLayout.lineCount();
+ for (int i = 0; i < lineCount; ++i) {
+ const QTextLine line = textLayout.lineAt(i);
+ height += line.height();
+
+ // above visible rect
+ if (height + layoutRect.top() <= textRect.top()) {
+ if (paintStartPosition)
+ paintStartPosition->ry() += line.height();
+ 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 && lastVisibleLineShouldBeElided) {
+ 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;
+ }
+
+ QString text = textLayout.text().mid(start, length);
+ if (drawElided || elideLastVisibleLine) {
+ if (elideLastVisibleLine) {
+ if (text.endsWith(QChar::LineSeparator))
+ text.chop(1);
+ text += QChar(0x2026);
+ }
+ const QStackTextEngine engine(text, font);
+ ret += engine.elidedText(textElideMode, textRect.width(), flags);
+
+ // no newline for the last line (last visible or real)
+ // sometimes drawElided is true but no eliding is done so the text ends
+ // with QChar::LineSeparator - don't add another one. This happened with
+ // arabic text in the testcase for QTBUG-72805
+ if (i < lineCount - 1 &&
+ !ret.endsWith(QChar::LineSeparator))
+ ret += QChar::LineSeparator;
+ } else {
+ ret += text;
+ }
+
+ // below visible text, can stop
+ if (height + layoutRect.top() >= textRect.bottom())
+ break;
+ }
+ return ret;
+}
+
+#if QT_CONFIG(itemviews)
+
QSize QCommonStylePrivate::viewItemSize(const QStyleOptionViewItem *option, int role) const
{
const QWidget *widget = option->widget;
@@ -935,67 +1007,15 @@ void QCommonStylePrivate::viewItemDrawText(QPainter *p, const QStyleOptionViewIt
textOption.setWrapMode(wrapText ? QTextOption::WordWrap : QTextOption::ManualWrap);
textOption.setTextDirection(option->direction);
textOption.setAlignment(QStyle::visualAlignment(option->direction, option->displayAlignment));
- QTextLayout textLayout(option->text, option->font);
- textLayout.setTextOption(textOption);
-
- viewItemTextLayout(textLayout, textRect.width());
-
- const QRectF boundingRect = textLayout.boundingRect();
- const QRect layoutRect = QStyle::alignedRect(option->direction, option->displayAlignment,
- boundingRect.size().toSize(), textRect);
- QPointF paintPosition = QPointF(textRect.x(), layoutRect.top());
-
- QString newText;
- qreal height = 0;
- const int lineCount = textLayout.lineCount();
- for (int i = 0; i < lineCount; ++i) {
- const QTextLine line = textLayout.lineAt(i);
- height += line.height();
-
- // above visible rect
- if (height + layoutRect.top() <= textRect.top()) {
- paintPosition.ry() += line.height();
- 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;
- }
-
- QString text = textLayout.text().mid(start, length);
- if (drawElided || elideLastVisibleLine) {
- if (elideLastVisibleLine) {
- if (text.endsWith(QChar::LineSeparator))
- text.chop(1);
- text += QChar(0x2026);
- }
- const QStackTextEngine engine(text, option->font);
- newText += engine.elidedText(option->textElideMode, textRect.width());
- // sometimes drawElided is true but no eliding is done so the text ends
- // with QChar::LineSeparator - don't add another one. This happened with
- // arabic text in the testcase for QTBUG-72805
- if (i < lineCount - 1 &&
- !newText.endsWith(QChar::LineSeparator))
- newText += QChar::LineSeparator;
- } else {
- newText += text;
- }
- // below visible text, can stop
- if (height + layoutRect.top() >= textRect.bottom())
- break;
- }
+ QPointF paintPosition;
+ const QString newText = calculateElidedText(option->text, textOption,
+ option->font, textRect, option->displayAlignment,
+ option->textElideMode, 0,
+ true, &paintPosition);
- textLayout.setText(newText);
+ QTextLayout textLayout(newText, option->font);
+ textLayout.setTextOption(textOption);
viewItemTextLayout(textLayout, textRect.width());
textLayout.draw(p, paintPosition);
}