aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew den Exter <andrew.den-exter@nokia.com>2012-03-15 11:17:09 +1000
committerQt by Nokia <qt-info@nokia.com>2012-03-21 05:18:35 +0100
commit0e1baa28e59ccd1739ee1957035c10518aed8ece (patch)
treebdb1d141382f3eaa1c460e45d204818461d3ec84
parent122e8df400e5a8bd4df1655785e6714110ffce93 (diff)
Content size should not include trailing spaces.
Excluding trailing spaces from the content size means the cursor position also needs to considered in determining the width used by the text as unwrapped white space can push the cursor over the width of the item. Also corrects an auto scroll issue with right to left text identified in extending the tests. Task-number: QTBUG-24630 Change-Id: Iaab9eac03824b22f507154fa1d6e55376bd075a0 Reviewed-by: Yann Bodson <yann.bodson@nokia.com>
-rw-r--r--src/quick/items/qquicktextinput.cpp15
-rw-r--r--tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp149
2 files changed, 119 insertions, 45 deletions
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index cff9c58cbc..30271c770a 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -1614,14 +1614,19 @@ void QQuickTextInputPrivate::updateHorizontalScroll()
QTextLine currentLine = m_textLayout.lineForTextPosition(m_cursor + m_preeditCursor);
const int preeditLength = m_textLayout.preeditAreaText().length();
const qreal width = qMax<qreal>(0, q->width());
- qreal widthUsed = currentLine.isValid() ? currentLine.naturalTextWidth() : 0;
+ qreal cix = 0;
+ qreal widthUsed = 0;
+ if (currentLine.isValid()) {
+ cix = currentLine.cursorToX(m_cursor + preeditLength);
+ const qreal cursorWidth = cix >= 0 ? cix : width - cix;
+ widthUsed = qMax(currentLine.naturalTextWidth(), cursorWidth);
+ }
int previousScroll = hscroll;
if (!autoScroll || widthUsed <= width || m_echoMode == QQuickTextInput::NoEcho) {
hscroll = 0;
} else {
Q_ASSERT(currentLine.isValid());
- qreal cix = currentLine.cursorToX(m_cursor + preeditLength);
if (cix - hscroll >= width) {
// text doesn't fit, cursor is to the right of br (scroll right)
hscroll = cix - width;
@@ -1632,6 +1637,10 @@ void QQuickTextInputPrivate::updateHorizontalScroll()
// text doesn't fit, text document is to the left of br; align
// right
hscroll = widthUsed - width;
+ } else if (width - hscroll > widthUsed) {
+ // text doesn't fit, text document is to the right of br; align
+ // left
+ hscroll = width - widthUsed;
}
if (preeditLength > 0) {
// check to ensure long pre-edit text doesn't push the cursor
@@ -2699,7 +2708,6 @@ void QQuickTextInputPrivate::updateLayout()
QTextOption option = m_textLayout.textOption();
option.setTextDirection(layoutDirection());
- option.setFlags(QTextOption::IncludeTrailingSpaces);
option.setWrapMode(QTextOption::WrapMode(wrapMode));
option.setAlignment(Qt::Alignment(q->effectiveHAlign()));
m_textLayout.setTextOption(option);
@@ -2710,7 +2718,6 @@ void QQuickTextInputPrivate::updateLayout()
QTextLine line = m_textLayout.createLine();
qreal lineWidth = q->widthValid() ? q->width() : INT_MAX;
qreal height = 0;
- QTextLine firstLine = line;
do {
line.setLineWidth(lineWidth);
line.setPosition(QPointF(line.position().x(), height));
diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
index d08890afec..35d1eba5ba 100644
--- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
+++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
@@ -93,6 +93,8 @@ template <typename T> static T evaluate(QObject *scope, const QString &expressio
return result;
}
+template<typename T, int N> int lengthOf(const T (&)[N]) { return N; }
+
typedef QPair<int, QChar> Key;
class tst_qquicktextinput : public QQmlDataTest
@@ -140,6 +142,7 @@ private slots:
void cursorDelegate_data();
void cursorDelegate();
void cursorVisible();
+ void cursorRectangle_data();
void cursorRectangle();
void navigation();
void navigation_RTL();
@@ -2405,10 +2408,34 @@ void tst_qquicktextinput::cursorVisible()
QCOMPARE(spy.count(), 7);
}
+void tst_qquicktextinput::cursorRectangle_data()
+{
+ const quint16 arabic_str[] = { 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0638, 0x0643, 0x00646, 0x0647, 0x0633, 0x0647};
+
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<int>("positionAtWidth");
+ QTest::addColumn<int>("wrapPosition");
+ QTest::addColumn<QString>("shortText");
+ QTest::addColumn<bool>("leftToRight");
+
+ QTest::newRow("left to right")
+ << "Hello World!" << 5 << 11
+ << "Hi"
+ << true;
+ QTest::newRow("right to left")
+ << QString::fromUtf16(arabic_str, lengthOf(arabic_str)) << 5 << 11
+ << QString::fromUtf16(arabic_str, 3)
+ << false;
+}
+
void tst_qquicktextinput::cursorRectangle()
{
- QString text = "Hello World!";
+ QFETCH(QString, text);
+ QFETCH(int, positionAtWidth);
+ QFETCH(int, wrapPosition);
+ QFETCH(QString, shortText);
+ QFETCH(bool, leftToRight);
QQuickTextInput input;
input.setText(text);
@@ -2425,33 +2452,30 @@ void tst_qquicktextinput::cursorRectangle()
QTextLine line = layout.createLine();
layout.endLayout();
- input.setWidth(line.cursorToX(5, QTextLine::Leading));
+ qreal offset = 0;
+ if (leftToRight) {
+ input.setWidth(line.cursorToX(positionAtWidth, QTextLine::Leading));
+ } else {
+ input.setWidth(line.horizontalAdvance() - line.cursorToX(positionAtWidth, QTextLine::Leading));
+ offset = line.horizontalAdvance() - input.width();
+ }
input.setHeight(qCeil(line.height() * 3 / 2));
QRectF r;
- // some tolerance for different fonts.
-#ifdef Q_OS_LINUX
- const int error = 2;
-#else
- const int error = 5;
-#endif
-
- for (int i = 0; i <= 5; ++i) {
+ for (int i = 0; i <= positionAtWidth; ++i) {
input.setCursorPosition(i);
r = input.cursorRectangle();
- QVERIFY(r.left() < qCeil(line.cursorToX(i, QTextLine::Trailing)));
- QVERIFY(r.right() >= qFloor(line.cursorToX(i , QTextLine::Leading)));
+ QCOMPARE(r.left(), line.cursorToX(i, QTextLine::Leading) - offset);
QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
QCOMPARE(input.positionToRectangle(i), r);
}
// Check the cursor rectangle remains within the input bounding rect when auto scrolling.
- QVERIFY(r.left() < input.width() + error);
- QVERIFY(r.right() >= input.width() - error);
+ QCOMPARE(r.left(), leftToRight ? input.width() : 0);
- for (int i = 6; i < text.length(); ++i) {
+ for (int i = positionAtWidth + 1; i < text.length(); ++i) {
input.setCursorPosition(i);
QCOMPARE(r, input.cursorRectangle());
QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
@@ -2462,7 +2486,11 @@ void tst_qquicktextinput::cursorRectangle()
input.setCursorPosition(i);
r = input.cursorRectangle();
QCOMPARE(r.top(), 0.);
- QVERIFY(r.right() >= 0);
+ if (leftToRight) {
+ QVERIFY(r.right() >= 0);
+ } else {
+ QVERIFY(r.left() <= input.width());
+ }
QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
QCOMPARE(input.positionToRectangle(i), r);
}
@@ -2470,69 +2498,102 @@ void tst_qquicktextinput::cursorRectangle()
// Check position with word wrap.
input.setWrapMode(QQuickTextInput::WordWrap);
input.setAutoScroll(false);
- for (int i = 0; i <= 5; ++i) {
+ for (int i = 0; i < wrapPosition; ++i) {
input.setCursorPosition(i);
r = input.cursorRectangle();
- QVERIFY(r.left() < qCeil(line.cursorToX(i, QTextLine::Trailing)));
- QVERIFY(r.right() >= qFloor(line.cursorToX(i , QTextLine::Leading)));
+ if (i > positionAtWidth)
+ QEXPECT_FAIL("right to left", "QTBUG-24801", Continue);
+ QCOMPARE(r.left(), line.cursorToX(i, QTextLine::Leading) - offset);
QCOMPARE(r.top(), 0.);
QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
QCOMPARE(input.positionToRectangle(i), r);
}
- input.setCursorPosition(6);
+ input.setCursorPosition(wrapPosition);
r = input.cursorRectangle();
- QCOMPARE(r.left(), 0.);
- QVERIFY(r.top() > line.height() - error);
+ if (leftToRight) {
+ QCOMPARE(r.left(), 0.);
+ } else {
+ QCOMPARE(r.left(), input.width());
+ }
+ QVERIFY(r.top() >= line.height() - 1);
QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
- QCOMPARE(input.positionToRectangle(6), r);
+ QCOMPARE(input.positionToRectangle(11), r);
- for (int i = 7; i < text.length(); ++i) {
+ for (int i = wrapPosition + 1; i < text.length(); ++i) {
input.setCursorPosition(i);
r = input.cursorRectangle();
- QVERIFY(r.top() > line.height() - error);
+ QVERIFY(r.top() >= line.height() - 1);
QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
QCOMPARE(input.positionToRectangle(i), r);
}
// Check vertical scrolling with word wrap.
input.setAutoScroll(true);
- for (int i = 0; i <= 5; ++i) {
+ for (int i = 0; i <= positionAtWidth; ++i) {
input.setCursorPosition(i);
r = input.cursorRectangle();
- QVERIFY(r.left() < qCeil(line.cursorToX(i, QTextLine::Trailing)));
- QVERIFY(r.right() >= qFloor(line.cursorToX(i , QTextLine::Leading)));
+ QCOMPARE(r.left(), line.cursorToX(i, QTextLine::Leading) - offset);
QCOMPARE(r.top(), 0.);
QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
QCOMPARE(input.positionToRectangle(i), r);
}
- input.setCursorPosition(6);
+ // Whitespace doesn't wrap, so scroll horizontally until the until the cursor
+ // reaches the next non-whitespace character.
+ QCOMPARE(r.left(), leftToRight ? input.width() : 0);
+ for (int i = positionAtWidth + 1; i < wrapPosition && leftToRight; ++i) {
+ input.setCursorPosition(i);
+ QCOMPARE(r, input.cursorRectangle());
+ QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
+ QCOMPARE(input.positionToRectangle(i), r);
+ }
+
+ input.setCursorPosition(wrapPosition);
r = input.cursorRectangle();
- QCOMPARE(r.left(), 0.);
- QVERIFY(r.bottom() >= input.height() - error);
+ if (leftToRight) {
+ QCOMPARE(r.left(), 0.);
+ } else {
+ QCOMPARE(r.left(), input.width());
+ }
+ QVERIFY(r.bottom() >= input.height());
QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
- QCOMPARE(input.positionToRectangle(6), r);
+ QCOMPARE(input.positionToRectangle(11), r);
- for (int i = 7; i < text.length(); ++i) {
+ for (int i = wrapPosition + 1; i < text.length(); ++i) {
input.setCursorPosition(i);
r = input.cursorRectangle();
- QVERIFY(r.bottom() >= input.height() - error);
+ QVERIFY(r.bottom() >= input.height());
QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
QCOMPARE(input.positionToRectangle(i), r);
}
- for (int i = text.length() - 2; i >= 6; --i) {
+ for (int i = text.length() - 2; i >= wrapPosition; --i) {
input.setCursorPosition(i);
r = input.cursorRectangle();
- QVERIFY(r.bottom() >= input.height() - error);
+ QVERIFY(r.bottom() >= input.height());
+ QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
+ QCOMPARE(input.positionToRectangle(i), r);
+ }
+
+ input.setCursorPosition(wrapPosition - 1);
+ r = input.cursorRectangle();
+ QCOMPARE(r.top(), 0.);
+ QEXPECT_FAIL("right to left", "QTBUG-24801", Continue);
+ QCOMPARE(r.left(), leftToRight ? input.width() : 0);
+ QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
+ QCOMPARE(input.positionToRectangle(10), r);
+
+ for (int i = wrapPosition - 2; i >= positionAtWidth + 1; --i) {
+ input.setCursorPosition(i);
+ QCOMPARE(r, input.cursorRectangle());
QCOMPARE(input.inputMethodQuery(Qt::ImCursorRectangle).toRectF(), r);
QCOMPARE(input.positionToRectangle(i), r);
}
- for (int i = 5; i >= 0; --i) {
+ for (int i = positionAtWidth; i >= 0; --i) {
input.setCursorPosition(i);
r = input.cursorRectangle();
QCOMPARE(r.top(), 0.);
@@ -2540,11 +2601,10 @@ void tst_qquicktextinput::cursorRectangle()
QCOMPARE(input.positionToRectangle(i), r);
}
- input.setText("Hi!");
- input.setHAlign(QQuickTextInput::AlignRight);
+ input.setText(shortText);
+ input.setHAlign(leftToRight ? QQuickTextInput::AlignRight : QQuickTextInput::AlignLeft);
r = input.cursorRectangle();
- QVERIFY(r.left() < input.width() + error);
- QVERIFY(r.right() >= input.width() - error);
+ QCOMPARE(r.left(), leftToRight ? input.width() : 0);
}
void tst_qquicktextinput::readOnly()
@@ -2891,6 +2951,13 @@ void tst_qquicktextinput::contentSize()
QVERIFY(textObject->contentWidth() > textObject->width());
QVERIFY(textObject->contentHeight() > textObject->height());
QCOMPARE(spy.count(), 3);
+
+ textObject->setText("The quick red fox jumped over the lazy brown dog");
+ for (int w = 60; w < 120; ++w) {
+ textObject->setWidth(w);
+ QVERIFY(textObject->contentWidth() <= textObject->width());
+ QVERIFY(textObject->contentHeight() > textObject->height());
+ }
}
static void sendPreeditText(const QString &text, int cursor)