Notify when the TextInput cursorRectangle property changes within pre-edit
authorAndrew den Exter <andrew.den-exter@nokia.com>
Fri, 20 May 2011 04:22:39 +0000 (14:22 +1000)
committerAndrew den Exter <andrew.den-exter@nokia.com>
Thu, 9 Jun 2011 08:26:59 +0000 (18:26 +1000)
Anything that updates the horizontal scroll is also likely to change the
position of the cursor rectangle and the micro focus.  So group these
actions together and ensure they're done before emitting
cursorPositionChanged() so positionToRectangle() returns a valid value
from that handler.

Change-Id: I5fadc58efb148a8dabe88a94381c86cd64dba3bd
Task-number: QTBUG-19089
Reviewed-by: Martin Jones
(cherry picked from commit a0b2fc44ff8752193cacde52276b1822741f5374)

src/declarative/graphicsitems/qdeclarativetextinput.cpp
src/declarative/graphicsitems/qdeclarativetextinput_p.h
tests/auto/declarative/qdeclarativetextinput/tst_qdeclarativetextinput.cpp

index 98ec205..b456d07 100644 (file)
@@ -236,11 +236,11 @@ void QDeclarativeTextInput::setFont(const QFont &font)
 
     if (oldFont != d->font) {
         d->control->setFont(d->font);
+        updateSize();
+        updateCursorRectangle();
         if(d->cursorItem){
             d->cursorItem->setHeight(QFontMetrics(d->font).height());
-            moveCursor();
         }
-        updateSize();
     }
     emit fontChanged(d->sourceFont);
 }
@@ -359,8 +359,7 @@ void QDeclarativeTextInput::setHAlign(HAlignment align)
     bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror;
     d->hAlignImplicit = false;
     if (d->setHAlign(align, forceAlign) && isComponentComplete()) {
-        updateRect();
-        d->updateHorizontalScroll();
+        updateCursorRectangle();
     }
 }
 
@@ -369,8 +368,7 @@ void QDeclarativeTextInput::resetHAlign()
     Q_D(QDeclarativeTextInput);
     d->hAlignImplicit = true;
     if (d->determineHorizontalAlignment() && isComponentComplete()) {
-        updateRect();
-        d->updateHorizontalScroll();
+        updateCursorRectangle();
     }
 }
 
@@ -423,8 +421,7 @@ void QDeclarativeTextInputPrivate::mirrorChange()
     Q_Q(QDeclarativeTextInput);
     if (q->isComponentComplete()) {
         if (!hAlignImplicit && (hAlign == QDeclarativeTextInput::AlignRight || hAlign == QDeclarativeTextInput::AlignLeft)) {
-            q->updateRect();
-            updateHorizontalScroll();
+            q->updateCursorRectangle();
             emit q->effectiveHorizontalAlignmentChanged();
         }
     }
@@ -683,7 +680,7 @@ void QDeclarativeTextInput::setAutoScroll(bool b)
     d->autoScroll = b;
     //We need to repaint so that the scrolling is taking into account.
     updateSize(true);
-    d->updateHorizontalScroll();
+    updateCursorRectangle();
     emit autoScrollChanged(d->autoScroll);
 }
 
@@ -947,10 +944,6 @@ void QDeclarativeTextInput::setCursorDelegate(QDeclarativeComponent* c)
     d->cursorComponent = c;
     if(!c){
         //note that the components are owned by something else
-        disconnect(d->control, SIGNAL(cursorPositionChanged(int,int)),
-                this, SLOT(moveCursor()));
-        disconnect(d->control, SIGNAL(updateMicroFocus()),
-                this, SLOT(moveCursor()));
         delete d->cursorItem;
     }else{
         d->startCreatingCursor();
@@ -962,10 +955,6 @@ void QDeclarativeTextInput::setCursorDelegate(QDeclarativeComponent* c)
 void QDeclarativeTextInputPrivate::startCreatingCursor()
 {
     Q_Q(QDeclarativeTextInput);
-    q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
-               q, SLOT(moveCursor()), Qt::UniqueConnection);
-    q->connect(control, SIGNAL(updateMicroFocus()),
-            q, SLOT(moveCursor()), Qt::UniqueConnection);
     if(cursorComponent->isReady()){
         q->createCursor();
     }else if(cursorComponent->isLoading()){
@@ -1001,15 +990,6 @@ void QDeclarativeTextInput::createCursor()
     d->cursorItem->setHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
 }
 
-void QDeclarativeTextInput::moveCursor()
-{
-    Q_D(QDeclarativeTextInput);
-    if(!d->cursorItem)
-        return;
-    d->updateHorizontalScroll();
-    d->cursorItem->setX(d->control->cursorToX() - d->hscroll);
-}
-
 /*!
     \qmlmethod rect TextInput::positionToRectangle(int pos)
 
@@ -1118,8 +1098,6 @@ void QDeclarativeTextInput::inputMethodEvent(QInputMethodEvent *ev)
             ev->ignore();
         } else {
             d->control->processInputMethodEvent(ev);
-            updateSize();
-            d->updateHorizontalScroll();
         }
     }
     if (!ev->isAccepted())
@@ -1297,7 +1275,7 @@ void QDeclarativeTextInput::geometryChanged(const QRectF &newGeometry,
     Q_D(QDeclarativeTextInput);
     if (newGeometry.width() != oldGeometry.width()) {
         updateSize();
-        d->updateHorizontalScroll();
+        updateCursorRectangle();
     }
     QDeclarativePaintedItem::geometryChanged(newGeometry, oldGeometry);
 }
@@ -1643,7 +1621,6 @@ void QDeclarativeTextInput::moveCursorSelection(int position)
 {
     Q_D(QDeclarativeTextInput);
     d->control->moveCursor(position, true);
-    d->updateHorizontalScroll();
 }
 
 /*!
@@ -1901,7 +1878,7 @@ void QDeclarativeTextInputPrivate::init()
     canPaste = !control->isReadOnly() && QApplication::clipboard()->text().length() != 0;
 #endif // QT_NO_CLIPBOARD
     q->connect(control, SIGNAL(updateMicroFocus()),
-               q, SLOT(updateMicroFocus()));
+               q, SLOT(updateCursorRectangle()));
     q->connect(control, SIGNAL(displayTextChanged(QString)),
                q, SLOT(updateRect()));
     q->updateSize();
@@ -1917,9 +1894,7 @@ void QDeclarativeTextInputPrivate::init()
 void QDeclarativeTextInput::cursorPosChanged()
 {
     Q_D(QDeclarativeTextInput);
-    d->updateHorizontalScroll();
-    updateRect();//TODO: Only update rect between pos's
-    updateMicroFocus();
+    updateCursorRectangle();
     emit cursorPositionChanged();
     d->control->resetCursorBlinkTimer();
 
@@ -1935,6 +1910,17 @@ void QDeclarativeTextInput::cursorPosChanged()
     }
 }
 
+void QDeclarativeTextInput::updateCursorRectangle()
+{
+    Q_D(QDeclarativeTextInput);
+    d->updateHorizontalScroll();
+    updateRect();//TODO: Only update rect between pos's
+    updateMicroFocus();
+    emit cursorRectangleChanged();
+    if (d->cursorItem)
+        d->cursorItem->setX(d->control->cursorToX() - d->hscroll);
+}
+
 void QDeclarativeTextInput::selectionChanged()
 {
     Q_D(QDeclarativeTextInput);
index aaf8859..8b7fff9 100644 (file)
@@ -75,7 +75,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeTextInput : public QDeclarativeImplicitSizeP
     Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly NOTIFY readOnlyChanged)
     Q_PROPERTY(bool cursorVisible READ isCursorVisible WRITE setCursorVisible NOTIFY cursorVisibleChanged)
     Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged)
-    Q_PROPERTY(QRect cursorRectangle READ cursorRectangle NOTIFY cursorPositionChanged)
+    Q_PROPERTY(QRect cursorRectangle READ cursorRectangle NOTIFY cursorRectangleChanged)
     Q_PROPERTY(QDeclarativeComponent *cursorDelegate READ cursorDelegate WRITE setCursorDelegate NOTIFY cursorDelegateChanged)
     Q_PROPERTY(int selectionStart READ selectionStart NOTIFY selectionStartChanged)
     Q_PROPERTY(int selectionEnd READ selectionEnd NOTIFY selectionEndChanged)
@@ -221,6 +221,7 @@ public:
 Q_SIGNALS:
     void textChanged();
     void cursorPositionChanged();
+    void cursorRectangleChanged();
     void selectionStartChanged();
     void selectionEndChanged();
     void selectedTextChanged();
@@ -279,8 +280,8 @@ private Q_SLOTS:
     void q_textChanged();
     void selectionChanged();
     void createCursor();
-    void moveCursor();
     void cursorPosChanged();
+    void updateCursorRectangle();
     void updateRect(const QRect &r = QRect());
     void q_canPasteChanged();
 
index f1f23af..63b768c 100644 (file)
@@ -2439,15 +2439,20 @@ void tst_qdeclarativetextinput::preeditAutoScroll()
     QTest::qWaitForWindowShown(&view);
     QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
 
+    QSignalSpy cursorRectangleSpy(&input, SIGNAL(cursorRectangleChanged()));
+    int cursorRectangleChanges = 0;
+
     // test the text is scrolled so the preedit is visible.
     ic.sendPreeditText(preeditText.mid(0, 3), 1);
     QVERIFY(input.positionAt(0) != 0);
     QVERIFY(input.cursorRectangle().left() < input.boundingRect().width());
+    QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
 
     // test the text is scrolled back when the preedit is removed.
     ic.sendEvent(QInputMethodEvent());
     QCOMPARE(input.positionAt(0), 0);
     QCOMPARE(input.positionAt(input.width()), 5);
+    QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
 
     // some tolerance for different fonts.
 #ifdef Q_OS_LINUX
@@ -2463,26 +2468,31 @@ void tst_qdeclarativetextinput::preeditAutoScroll()
         ic.sendPreeditText(preeditText, i + 1);
         QVERIFY(input.cursorRectangle().right() >= fm.width(preeditText.at(i)) - error);
         QVERIFY(input.positionToRectangle(0).x() < x);
+        QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
         x = input.positionToRectangle(0).x();
     }
     for (int i = 1; i >= 0; --i) {
         ic.sendPreeditText(preeditText, i + 1);
         QVERIFY(input.cursorRectangle().right() >= fm.width(preeditText.at(i)) - error);
         QVERIFY(input.positionToRectangle(0).x() > x);
+        QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
         x = input.positionToRectangle(0).x();
     }
 
     // Test incrementing the preedit cursor doesn't cause further
     // scrolling when right most text is visible.
     ic.sendPreeditText(preeditText, preeditText.length() - 3);
+    QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
     x = input.positionToRectangle(0).x();
     for (int i = 2; i >= 0; --i) {
         ic.sendPreeditText(preeditText, preeditText.length() - i);
         QCOMPARE(input.positionToRectangle(0).x(), x);
+        QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
     }
     for (int i = 1; i <  3; ++i) {
         ic.sendPreeditText(preeditText, preeditText.length() - i);
         QCOMPARE(input.positionToRectangle(0).x(), x);
+        QCOMPARE(cursorRectangleSpy.count(), ++cursorRectangleChanges);
     }
 
     // Test disabling auto scroll.