aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/items/qquicktextinput.cpp65
-rw-r--r--src/quick/items/qquicktextinput_p.h3
-rw-r--r--src/quick/items/qquicktextinput_p_p.h1
-rw-r--r--tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp46
4 files changed, 94 insertions, 21 deletions
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index 41eb5c0bde..883d0c744d 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -881,6 +881,8 @@ void QQuickTextInput::setFocusOnPress(bool b)
Whether the TextInput should scroll when the text is longer than the width. By default this is
set to true.
+
+ \sa ensureVisible()
*/
bool QQuickTextInput::autoScroll() const
{
@@ -1721,33 +1723,24 @@ void QQuickTextInput::geometryChanged(const QRectF &newGeometry,
QQuickImplicitSizeItem::geometryChanged(newGeometry, oldGeometry);
}
-void QQuickTextInputPrivate::updateHorizontalScroll()
+void QQuickTextInputPrivate::ensureVisible(int position, int preeditCursor, int preeditLength)
{
Q_Q(QQuickTextInput);
-#ifndef QT_NO_IM
- QTextLine currentLine = m_textLayout.lineForTextPosition(m_cursor + m_preeditCursor);
- const int preeditLength = m_textLayout.preeditAreaText().length();
-#else
- QTextLine currentLine = m_textLayout.lineForTextPosition(m_cursor);
-#endif
+ QTextLine textLine = m_textLayout.lineForTextPosition(position + preeditCursor);
const qreal width = qMax<qreal>(0, q->width());
qreal cix = 0;
qreal widthUsed = 0;
- if (currentLine.isValid()) {
-#ifndef QT_NO_IM
- cix = currentLine.cursorToX(m_cursor + preeditLength);
-#else
- cix = currentLine.cursorToX(m_cursor);
-#endif
+ if (textLine.isValid()) {
+ cix = textLine.cursorToX(position + preeditLength);
const qreal cursorWidth = cix >= 0 ? cix : width - cix;
- widthUsed = qMax(currentLine.naturalTextWidth(), cursorWidth);
+ widthUsed = qMax(textLine.naturalTextWidth(), cursorWidth);
}
int previousScroll = hscroll;
- if (!autoScroll || widthUsed <= width || m_echoMode == QQuickTextInput::NoEcho) {
+ if (widthUsed <= width) {
hscroll = 0;
} else {
- Q_ASSERT(currentLine.isValid());
+ Q_ASSERT(textLine.isValid());
if (cix - hscroll >= width) {
// text doesn't fit, cursor is to the right of br (scroll right)
hscroll = cix - width;
@@ -1767,7 +1760,7 @@ void QQuickTextInputPrivate::updateHorizontalScroll()
if (preeditLength > 0) {
// check to ensure long pre-edit text doesn't push the cursor
// off to the left
- cix = currentLine.cursorToX(m_cursor + qMax(0, m_preeditCursor - 1));
+ cix = textLine.cursorToX(position + qMax(0, preeditCursor - 1));
if (cix < hscroll)
hscroll = cix;
}
@@ -1777,6 +1770,20 @@ void QQuickTextInputPrivate::updateHorizontalScroll()
textLayoutDirty = true;
}
+void QQuickTextInputPrivate::updateHorizontalScroll()
+{
+ if (autoScroll && m_echoMode != QQuickTextInput::NoEcho) {
+#ifndef QT_NO_IM
+ const int preeditLength = m_textLayout.preeditAreaText().length();
+ ensureVisible(m_cursor, m_preeditCursor, preeditLength);
+#else
+ ensureVisible(m_cursor);
+#endif
+ } else {
+ hscroll = 0;
+ }
+}
+
void QQuickTextInputPrivate::updateVerticalScroll()
{
Q_Q(QQuickTextInput);
@@ -2634,14 +2641,16 @@ void QQuickTextInputPrivate::init()
}
}
-void QQuickTextInput::updateCursorRectangle()
+void QQuickTextInput::updateCursorRectangle(bool scroll)
{
Q_D(QQuickTextInput);
if (!isComponentComplete())
return;
- d->updateHorizontalScroll();
- d->updateVerticalScroll();
+ if (scroll) {
+ d->updateHorizontalScroll();
+ d->updateVerticalScroll();
+ }
d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
update();
emit cursorRectangleChanged();
@@ -4402,5 +4411,21 @@ void QQuickTextInputPrivate::deleteEndOfLine()
finishChange(priorState);
}
+/*!
+ \qmlmethod QtQuick::TextInput::ensureVisible(int position)
+ \since 5.4
+
+ Scrolls the contents of the text input so that the specified character
+ \a position is visible inside the boundaries of the text input.
+
+ \sa autoScroll
+*/
+void QQuickTextInput::ensureVisible(int position)
+{
+ Q_D(QQuickTextInput);
+ d->ensureVisible(position);
+ updateCursorRectangle(false);
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/items/qquicktextinput_p.h b/src/quick/items/qquicktextinput_p.h
index 211aba8703..66cabb9cfe 100644
--- a/src/quick/items/qquicktextinput_p.h
+++ b/src/quick/items/qquicktextinput_p.h
@@ -355,11 +355,12 @@ public Q_SLOTS:
void redo();
void insert(int position, const QString &text);
void remove(int start, int end);
+ Q_REVISION(3) void ensureVisible(int position);
private Q_SLOTS:
void selectionChanged();
void createCursor();
- void updateCursorRectangle();
+ void updateCursorRectangle(bool scroll = true);
void q_canPasteChanged();
void q_updateAlignment();
void triggerPreprocess();
diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h
index 2cf127608e..facc6356a1 100644
--- a/src/quick/items/qquicktextinput_p_p.h
+++ b/src/quick/items/qquicktextinput_p_p.h
@@ -148,6 +148,7 @@ public:
void init();
void startCreatingCursor();
+ void ensureVisible(int position, int preeditCursor = 0, int preeditLength = 0);
void updateHorizontalScroll();
void updateVerticalScroll();
bool determineHorizontalAlignment();
diff --git a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
index 8451b527ce..fc1be16bc8 100644
--- a/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
+++ b/tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp
@@ -232,6 +232,8 @@ private slots:
void baselineOffset_data();
void baselineOffset();
+ void ensureVisible();
+
private:
void simulateKey(QWindow *, int key);
@@ -6464,6 +6466,50 @@ void tst_qquicktextinput::baselineOffset()
}
}
+void tst_qquicktextinput::ensureVisible()
+{
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick 2.0\n TextInput {}", QUrl());
+ QScopedPointer<QObject> object(component.create());
+ QQuickTextInput *input = qobject_cast<QQuickTextInput *>(object.data());
+ QVERIFY(input);
+
+ input->setWidth(QFontMetrics(input->font()).averageCharWidth() * 3);
+ input->setText("Hello World");
+
+ QTextLayout layout;
+ layout.setText(input->text());
+ layout.setFont(input->font());
+
+ if (!qmlDisableDistanceField()) {
+ QTextOption option;
+ option.setUseDesignMetrics(true);
+ layout.setTextOption(option);
+ }
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ layout.endLayout();
+
+ input->ensureVisible(0);
+
+ QCOMPARE(input->boundingRect().x(), qreal(0));
+ QCOMPARE(input->boundingRect().y(), qreal(0));
+ QCOMPARE(input->boundingRect().width(), line.naturalTextWidth() + input->cursorRectangle().width());
+ QCOMPARE(input->boundingRect().height(), line.height());
+
+ QSignalSpy cursorSpy(input, SIGNAL(cursorRectangleChanged()));
+ QVERIFY(cursorSpy.isValid());
+
+ input->ensureVisible(input->length());
+
+ QCOMPARE(cursorSpy.count(), 1);
+
+ QCOMPARE(input->boundingRect().x(), input->width() - line.naturalTextWidth());
+ QCOMPARE(input->boundingRect().y(), qreal(0));
+ QCOMPARE(input->boundingRect().width(), line.naturalTextWidth() + input->cursorRectangle().width());
+ QCOMPARE(input->boundingRect().height(), line.height());
+}
+
QTEST_MAIN(tst_qquicktextinput)
#include "tst_qquicktextinput.moc"