src/declarative/graphicsitems/qdeclarativetextinput.cpp
changeset 33 3e2da88830cd
parent 30 5dc02b23752f
child 37 758a864f9613
equal deleted inserted replaced
30:5dc02b23752f 33:3e2da88830cd
    44 
    44 
    45 #include <private/qdeclarativeglobal_p.h>
    45 #include <private/qdeclarativeglobal_p.h>
    46 #include <qdeclarativeinfo.h>
    46 #include <qdeclarativeinfo.h>
    47 
    47 
    48 #include <QValidator>
    48 #include <QValidator>
       
    49 #include <QTextCursor>
    49 #include <QApplication>
    50 #include <QApplication>
    50 #include <QFontMetrics>
    51 #include <QFontMetrics>
    51 #include <QPainter>
    52 #include <QPainter>
    52 
    53 
    53 QT_BEGIN_NAMESPACE
    54 QT_BEGIN_NAMESPACE
    54 
    55 
    55 /*!
    56 /*!
    56     \qmlclass TextInput QDeclarativeTextInput
    57     \qmlclass TextInput QDeclarativeTextInput
    57   \since 4.7
    58     \since 4.7
    58     \brief The TextInput item allows you to add an editable line of text to a scene.
    59     \brief The TextInput item displays an editable line of text.
    59 
    60     \inherits Item
    60     TextInput can only display a single line of text, and can only display
    61 
    61     plain text. However it can provide addition input constraints on the text.
    62     The TextInput element displays a single line of editable plain text.
    62 
    63 
    63     Input constraints include setting a QValidator, an input mask, or a
    64     TextInput is used to accept a line of text input. Input constraints
    64     maximum input length.
    65     can be placed on a TextInput item (for example, through a \l validator or \l inputMask),
       
    66     and setting \l echoMode to an appropriate value enables TextInput to be used for
       
    67     a password input field.
    65 
    68 
    66     On Mac OS X, the Up/Down key bindings for Home/End are explicitly disabled.
    69     On Mac OS X, the Up/Down key bindings for Home/End are explicitly disabled.
    67     If you want such bindings (on any platform), you will need to construct them in QML.
    70     If you want such bindings (on any platform), you will need to construct them in QML.
       
    71     
       
    72     \sa TextEdit, Text, {declarative/text/textselection}{Text Selection example}
    68 */
    73 */
    69 QDeclarativeTextInput::QDeclarativeTextInput(QDeclarativeItem* parent)
    74 QDeclarativeTextInput::QDeclarativeTextInput(QDeclarativeItem* parent)
    70     : QDeclarativePaintedItem(*(new QDeclarativeTextInputPrivate), parent)
    75     : QDeclarativePaintedItem(*(new QDeclarativeTextInputPrivate), parent)
    71 {
    76 {
    72     Q_D(QDeclarativeTextInput);
    77     Q_D(QDeclarativeTextInput);
    93 {
    98 {
    94     Q_D(QDeclarativeTextInput);
    99     Q_D(QDeclarativeTextInput);
    95     if(s == text())
   100     if(s == text())
    96         return;
   101         return;
    97     d->control->setText(s);
   102     d->control->setText(s);
    98     //emit textChanged();
       
    99 }
   103 }
   100 
   104 
   101 /*!
   105 /*!
   102     \qmlproperty string TextInput::font.family
   106     \qmlproperty string TextInput::font.family
   103 
   107 
   144 
   148 
   145     Sets whether the text is underlined.
   149     Sets whether the text is underlined.
   146 */
   150 */
   147 
   151 
   148 /*!
   152 /*!
   149     \qmlproperty bool TextInput::font.outline
       
   150 
       
   151     Sets whether the font has an outline style.
       
   152 */
       
   153 
       
   154 /*!
       
   155     \qmlproperty bool TextInput::font.strikeout
   153     \qmlproperty bool TextInput::font.strikeout
   156 
   154 
   157     Sets whether the font has a strikeout style.
   155     Sets whether the font has a strikeout style.
   158 */
   156 */
   159 
   157 
   176     \qmlproperty real TextInput::font.letterSpacing
   174     \qmlproperty real TextInput::font.letterSpacing
   177 
   175 
   178     Sets the letter spacing for the font.
   176     Sets the letter spacing for the font.
   179 
   177 
   180     Letter spacing changes the default spacing between individual letters in the font.
   178     Letter spacing changes the default spacing between individual letters in the font.
   181     A value of 100 will keep the spacing unchanged; a value of 200 will enlarge the spacing after a character by
   179     A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing.
   182     the width of the character itself.
       
   183 */
   180 */
   184 
   181 
   185 /*!
   182 /*!
   186     \qmlproperty real TextInput::font.wordSpacing
   183     \qmlproperty real TextInput::font.wordSpacing
   187 
   184 
   245 }
   242 }
   246 
   243 
   247 void QDeclarativeTextInput::setColor(const QColor &c)
   244 void QDeclarativeTextInput::setColor(const QColor &c)
   248 {
   245 {
   249     Q_D(QDeclarativeTextInput);
   246     Q_D(QDeclarativeTextInput);
   250     d->color = c;
   247     if (c != d->color) {
       
   248         d->color = c;
       
   249         clearCache();
       
   250         update();
       
   251         emit colorChanged(c);
       
   252     }
   251 }
   253 }
   252 
   254 
   253 
   255 
   254 /*!
   256 /*!
   255     \qmlproperty color TextInput::selectionColor
   257     \qmlproperty color TextInput::selectionColor
   270 
   272 
   271     d->selectionColor = color;
   273     d->selectionColor = color;
   272     QPalette p = d->control->palette();
   274     QPalette p = d->control->palette();
   273     p.setColor(QPalette::Highlight, d->selectionColor);
   275     p.setColor(QPalette::Highlight, d->selectionColor);
   274     d->control->setPalette(p);
   276     d->control->setPalette(p);
       
   277     clearCache();
       
   278     update();
   275     emit selectionColorChanged(color);
   279     emit selectionColorChanged(color);
   276 }
   280 }
   277 
   281 
   278 /*!
   282 /*!
   279     \qmlproperty color TextInput::selectedTextColor
   283     \qmlproperty color TextInput::selectedTextColor
   294 
   298 
   295     d->selectedTextColor = color;
   299     d->selectedTextColor = color;
   296     QPalette p = d->control->palette();
   300     QPalette p = d->control->palette();
   297     p.setColor(QPalette::HighlightedText, d->selectedTextColor);
   301     p.setColor(QPalette::HighlightedText, d->selectedTextColor);
   298     d->control->setPalette(p);
   302     d->control->setPalette(p);
       
   303     clearCache();
       
   304     update();
   299     emit selectedTextColorChanged(color);
   305     emit selectedTextColorChanged(color);
   300 }
   306 }
   301 
   307 
   302 /*!
   308 /*!
   303     \qmlproperty enumeration TextInput::horizontalAlignment
   309     \qmlproperty enumeration TextInput::horizontalAlignment
   325     Q_D(QDeclarativeTextInput);
   331     Q_D(QDeclarativeTextInput);
   326     if(align == d->hAlign)
   332     if(align == d->hAlign)
   327         return;
   333         return;
   328     d->hAlign = align;
   334     d->hAlign = align;
   329     updateRect();
   335     updateRect();
       
   336     d->updateHorizontalScroll();
   330     emit horizontalAlignmentChanged(d->hAlign);
   337     emit horizontalAlignmentChanged(d->hAlign);
   331 }
   338 }
   332 
   339 
   333 bool QDeclarativeTextInput::isReadOnly() const
   340 bool QDeclarativeTextInput::isReadOnly() const
   334 {
   341 {
   366 
   373 
   367 /*!
   374 /*!
   368     \qmlproperty bool TextInput::cursorVisible
   375     \qmlproperty bool TextInput::cursorVisible
   369     Set to true when the TextInput shows a cursor.
   376     Set to true when the TextInput shows a cursor.
   370 
   377 
   371     This property is set and unset when the TextInput gets focus, so that other
   378     This property is set and unset when the TextInput gets active focus, so that other
   372     properties can be bound to whether the cursor is currently showing. As it
   379     properties can be bound to whether the cursor is currently showing. As it
   373     gets set and unset automatically, when you set the value yourself you must
   380     gets set and unset automatically, when you set the value yourself you must
   374     keep in mind that your value may be overwritten.
   381     keep in mind that your value may be overwritten.
   375 
   382 
   376     It can be set directly in script, for example if a KeyProxy might
   383     It can be set directly in script, for example if a KeyProxy might
   377     forward keys to it and you desire it to look active when this happens
   384     forward keys to it and you desire it to look active when this happens
   378     (but without actually giving it the focus).
   385     (but without actually giving it active focus).
   379 
   386 
   380     It should not be set directly on the element, like in the below QML,
   387     It should not be set directly on the element, like in the below QML,
   381     as the specified value will be overridden an lost on focus changes.
   388     as the specified value will be overridden an lost on focus changes.
   382 
   389 
   383     \code
   390     \code
   386         cursorVisible: false
   393         cursorVisible: false
   387     }
   394     }
   388     \endcode
   395     \endcode
   389 
   396 
   390     In the above snippet the cursor will still become visible when the
   397     In the above snippet the cursor will still become visible when the
   391     TextInput gains focus.
   398     TextInput gains active focus.
   392 */
   399 */
   393 bool QDeclarativeTextInput::isCursorVisible() const
   400 bool QDeclarativeTextInput::isCursorVisible() const
   394 {
   401 {
   395     Q_D(const QDeclarativeTextInput);
   402     Q_D(const QDeclarativeTextInput);
   396     return d->cursorVisible;
   403     return d->cursorVisible;
   426   \internal
   433   \internal
   427 
   434 
   428   Returns a Rect which encompasses the cursor, but which may be larger than is
   435   Returns a Rect which encompasses the cursor, but which may be larger than is
   429   required. Ignores custom cursor delegates.
   436   required. Ignores custom cursor delegates.
   430 */
   437 */
   431 QRect QDeclarativeTextInput::cursorRect() const
   438 QRect QDeclarativeTextInput::cursorRectangle() const
   432 {
   439 {
   433     Q_D(const QDeclarativeTextInput);
   440     Q_D(const QDeclarativeTextInput);
   434     return d->control->cursorRect();
   441     QRect r = d->control->cursorRect();
       
   442     r.setHeight(r.height()-1); // Make consistent with TextEdit (QLineControl inexplicably adds 1)
       
   443     return r;
   435 }
   444 }
   436 
   445 
   437 /*!
   446 /*!
   438     \qmlproperty int TextInput::selectionStart
   447     \qmlproperty int TextInput::selectionStart
   439 
   448 
   451 {
   460 {
   452     Q_D(const QDeclarativeTextInput);
   461     Q_D(const QDeclarativeTextInput);
   453     return d->lastSelectionStart;
   462     return d->lastSelectionStart;
   454 }
   463 }
   455 
   464 
   456 void QDeclarativeTextInput::setSelectionStart(int s)
       
   457 {
       
   458     Q_D(QDeclarativeTextInput);
       
   459     if(d->lastSelectionStart == s || s < 0 || s > text().length())
       
   460         return;
       
   461     d->lastSelectionStart = s;
       
   462     d->control->setSelection(s, d->lastSelectionEnd - s);
       
   463 }
       
   464 
       
   465 /*!
   465 /*!
   466     \qmlproperty int TextInput::selectionEnd
   466     \qmlproperty int TextInput::selectionEnd
   467 
   467 
   468     The cursor position after the last character in the current selection.
   468     The cursor position after the last character in the current selection.
   469     Setting this and selectionStart allows you to specify a selection in the
   469     Setting this and selectionStart allows you to specify a selection in the
   479 {
   479 {
   480     Q_D(const QDeclarativeTextInput);
   480     Q_D(const QDeclarativeTextInput);
   481     return d->lastSelectionEnd;
   481     return d->lastSelectionEnd;
   482 }
   482 }
   483 
   483 
   484 void QDeclarativeTextInput::setSelectionEnd(int s)
   484 void QDeclarativeTextInput::select(int start, int end)
   485 {
   485 {
   486     Q_D(QDeclarativeTextInput);
   486     Q_D(QDeclarativeTextInput);
   487     if(d->lastSelectionEnd == s || s < 0 || s > text().length())
   487     if (start < 0 || end < 0 || start > d->control->text().length() || end > d->control->text().length())
   488         return;
   488         return;
   489     d->lastSelectionEnd = s;
   489     d->control->setSelection(start, end-start);
   490     d->control->setSelection(d->lastSelectionStart, s - d->lastSelectionStart);
       
   491 }
   490 }
   492 
   491 
   493 /*!
   492 /*!
   494     \qmlproperty string TextInput::selectedText
   493     \qmlproperty string TextInput::selectedText
   495 
   494 
   509     Q_D(const QDeclarativeTextInput);
   508     Q_D(const QDeclarativeTextInput);
   510     return d->control->selectedText();
   509     return d->control->selectedText();
   511 }
   510 }
   512 
   511 
   513 /*!
   512 /*!
   514     \qmlproperty bool TextInput::focusOnPress
   513     \qmlproperty bool TextInput::activeFocusOnPress
   515 
   514 
   516     Whether the TextInput should gain focus on a mouse press. By default this is
   515     Whether the TextInput should gain active focus on a mouse press. By default this is
   517     set to true.
   516     set to true.
   518 */
   517 */
   519 bool QDeclarativeTextInput::focusOnPress() const
   518 bool QDeclarativeTextInput::focusOnPress() const
   520 {
   519 {
   521     Q_D(const QDeclarativeTextInput);
   520     Q_D(const QDeclarativeTextInput);
   528     if (d->focusOnPress == b)
   527     if (d->focusOnPress == b)
   529         return;
   528         return;
   530 
   529 
   531     d->focusOnPress = b;
   530     d->focusOnPress = b;
   532 
   531 
   533     emit focusOnPressChanged(d->focusOnPress);
   532     emit activeFocusOnPressChanged(d->focusOnPress);
   534 }
   533 }
   535 
   534 
   536 /*!
   535 /*!
   537     \qmlproperty bool TextInput::autoScroll
   536     \qmlproperty bool TextInput::autoScroll
   538 
   537 
   550     Q_D(QDeclarativeTextInput);
   549     Q_D(QDeclarativeTextInput);
   551     if (d->autoScroll == b)
   550     if (d->autoScroll == b)
   552         return;
   551         return;
   553 
   552 
   554     d->autoScroll = b;
   553     d->autoScroll = b;
   555 
   554     //We need to repaint so that the scrolling is taking into account.
       
   555     updateSize(true);
       
   556     d->updateHorizontalScroll();
   556     emit autoScrollChanged(d->autoScroll);
   557     emit autoScrollChanged(d->autoScroll);
   557 }
   558 }
   558 
   559 
   559 /*!
   560 /*!
   560     \qmlclass IntValidator QIntValidator
   561     \qmlclass IntValidator QIntValidator
   561 
   562 
   562     This element provides a validator for integer values
   563     This element provides a validator for integer values.
   563 */
   564 */
   564 /*!
   565 /*!
   565     \qmlproperty int IntValidator::top
   566     \qmlproperty int IntValidator::top
   566 
   567 
   567     This property holds the validator's highest acceptable value.
   568     This property holds the validator's highest acceptable value.
   600 */
   601 */
   601 /*!
   602 /*!
   602     \qmlproperty enumeration DoubleValidator::notation
   603     \qmlproperty enumeration DoubleValidator::notation
   603     This property holds the notation of how a string can describe a number.
   604     This property holds the notation of how a string can describe a number.
   604 
   605 
   605     The values for this property are DoubleValidator.StandardNotation or DoubleValidator.ScientificNotation.
   606     The possible values for this property are:
   606     If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part(i.e. 1.5E-2).
   607     
   607 
   608     \list
   608     By default, this property is set to DoubleValidator.ScientificNotation.
   609     \o DoubleValidator.StandardNotation 
       
   610     \o DoubleValidator.ScientificNotation (default)
       
   611     \endlist
       
   612 
       
   613     If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part (e.g. 1.5E-2).
   609 */
   614 */
   610 
   615 
   611 /*!
   616 /*!
   612     \qmlclass RegExpValidator QRegExpValidator
   617     \qmlclass RegExpValidator QRegExpValidator
   613 
   618 
   645     }
   650     }
   646     \endcode
   651     \endcode
   647 
   652 
   648     \sa acceptableInput, inputMask
   653     \sa acceptableInput, inputMask
   649 */
   654 */
       
   655 #ifndef QT_NO_VALIDATOR
   650 QValidator* QDeclarativeTextInput::validator() const
   656 QValidator* QDeclarativeTextInput::validator() const
   651 {
   657 {
   652     Q_D(const QDeclarativeTextInput);
   658     Q_D(const QDeclarativeTextInput);
   653     //###const cast isn't good, but needed for property system?
   659     //###const cast isn't good, but needed for property system?
   654     return const_cast<QValidator*>(d->control->validator());
   660     return const_cast<QValidator*>(d->control->validator());
   666         emit acceptableInputChanged();
   672         emit acceptableInputChanged();
   667     }
   673     }
   668 
   674 
   669     emit validatorChanged();
   675     emit validatorChanged();
   670 }
   676 }
       
   677 #endif // QT_NO_VALIDATOR
   671 
   678 
   672 /*!
   679 /*!
   673     \qmlproperty string TextInput::inputMask
   680     \qmlproperty string TextInput::inputMask
   674 
   681 
   675     Allows you to set an input mask on the TextInput, restricting the allowable
   682     Allows you to set an input mask on the TextInput, restricting the allowable
   818     }
   825     }
   819 
   826 
   820     QDeclarative_setParent_noEvent(d->cursorItem, this);
   827     QDeclarative_setParent_noEvent(d->cursorItem, this);
   821     d->cursorItem->setParentItem(this);
   828     d->cursorItem->setParentItem(this);
   822     d->cursorItem->setX(d->control->cursorToX());
   829     d->cursorItem->setX(d->control->cursorToX());
   823     d->cursorItem->setHeight(d->control->height());
   830     d->cursorItem->setHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
   824 }
   831 }
   825 
   832 
   826 void QDeclarativeTextInput::moveCursor()
   833 void QDeclarativeTextInput::moveCursor()
   827 {
   834 {
   828     Q_D(QDeclarativeTextInput);
   835     Q_D(QDeclarativeTextInput);
   829     if(!d->cursorItem)
   836     if(!d->cursorItem)
   830         return;
   837         return;
       
   838     d->updateHorizontalScroll();
   831     d->cursorItem->setX(d->control->cursorToX() - d->hscroll);
   839     d->cursorItem->setX(d->control->cursorToX() - d->hscroll);
   832 }
   840 }
   833 
   841 
   834 /*!
   842 /*!
   835     \qmlmethod int TextInput::xToPosition(int x)
   843     \qmlmethod rect TextInput::positionToRectangle(int pos)
       
   844 
       
   845     This function takes a character position and returns the rectangle that the
       
   846     cursor would occupy, if it was placed at that character position.
       
   847 
       
   848     This is similar to setting the cursorPosition, and then querying the cursor
       
   849     rectangle, but the cursorPosition is not changed.
       
   850 */
       
   851 QRectF QDeclarativeTextInput::positionToRectangle(int pos) const
       
   852 {
       
   853     Q_D(const QDeclarativeTextInput);
       
   854     return QRectF(d->control->cursorToX(pos)-d->hscroll,
       
   855         0.0,
       
   856         d->control->cursorWidth(),
       
   857         cursorRectangle().height());
       
   858 }
       
   859 
       
   860 /*!
       
   861     \qmlmethod int TextInput::positionAt(int x)
   836 
   862 
   837     This function returns the character position at
   863     This function returns the character position at
   838     x pixels from the left of the textInput. Position 0 is before the
   864     x pixels from the left of the textInput. Position 0 is before the
   839     first character, position 1 is after the first character but before the second,
   865     first character, position 1 is after the first character but before the second,
   840     and so on until position text.length, which is after all characters.
   866     and so on until position text.length, which is after all characters.
   841 
   867 
   842     This means that for all x values before the first character this function returns 0,
   868     This means that for all x values before the first character this function returns 0,
   843     and for all x values after the last character this function returns text.length.
   869     and for all x values after the last character this function returns text.length.
   844 */
   870 */
   845 int QDeclarativeTextInput::xToPosition(int x)
   871 int QDeclarativeTextInput::positionAt(int x) const
   846 {
   872 {
   847     Q_D(const QDeclarativeTextInput);
   873     Q_D(const QDeclarativeTextInput);
   848     return d->control->xToPos(x - d->hscroll);
   874     return d->control->xToPos(x + d->hscroll);
   849 }
   875 }
   850 
   876 
   851 void QDeclarativeTextInputPrivate::focusChanged(bool hasFocus)
   877 void QDeclarativeTextInputPrivate::focusChanged(bool hasFocus)
   852 {
   878 {
   853     Q_Q(QDeclarativeTextInput);
   879     Q_Q(QDeclarativeTextInput);
   880     }
   906     }
   881     if (!ev->isAccepted())
   907     if (!ev->isAccepted())
   882         QDeclarativePaintedItem::keyPressEvent(ev);
   908         QDeclarativePaintedItem::keyPressEvent(ev);
   883 }
   909 }
   884 
   910 
       
   911 void QDeclarativeTextInput::inputMethodEvent(QInputMethodEvent *ev)
       
   912 {
       
   913     Q_D(QDeclarativeTextInput);
       
   914     ev->ignore();
       
   915     inputMethodPreHandler(ev);
       
   916     if (ev->isAccepted())
       
   917         return;
       
   918     if (d->control->isReadOnly()) {
       
   919         ev->ignore();
       
   920     } else {
       
   921         d->control->processInputMethodEvent(ev);
       
   922         updateSize();
       
   923     }
       
   924     if (!ev->isAccepted())
       
   925         QDeclarativePaintedItem::inputMethodEvent(ev);
       
   926 }
       
   927 
       
   928 /*!
       
   929 \overload
       
   930 Handles the given mouse \a event.
       
   931 */
       
   932 void QDeclarativeTextInput::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
       
   933 {
       
   934     Q_D(QDeclarativeTextInput);
       
   935     if (d->selectByMouse) {
       
   936         int cursor = d->xToPos(event->pos().x());
       
   937         d->control->selectWordAtPos(cursor);
       
   938         event->setAccepted(true);
       
   939     } else {
       
   940         QDeclarativePaintedItem::mouseDoubleClickEvent(event);
       
   941     }
       
   942 }
       
   943 
   885 void QDeclarativeTextInput::mousePressEvent(QGraphicsSceneMouseEvent *event)
   944 void QDeclarativeTextInput::mousePressEvent(QGraphicsSceneMouseEvent *event)
   886 {
   945 {
   887     Q_D(QDeclarativeTextInput);
   946     Q_D(QDeclarativeTextInput);
   888     bool hadFocus = hasFocus();
       
   889     if(d->focusOnPress){
   947     if(d->focusOnPress){
   890         QGraphicsItem *p = parentItem();//###Is there a better way to find my focus scope?
   948         bool hadActiveFocus = hasActiveFocus();
   891         while(p) {
   949         forceActiveFocus();
   892             if (p->flags() & QGraphicsItem::ItemIsFocusScope)
   950         if (d->showInputPanelOnFocus) {
   893                 p->setFocus();
   951             if (hasActiveFocus() && hadActiveFocus && !isReadOnly()) {
   894             p = p->parentItem();
   952                 // re-open input panel on press if already focused
       
   953                 openSoftwareInputPanel();
       
   954             }
       
   955         } else { // show input panel on click
       
   956             if (hasActiveFocus() && !hadActiveFocus) {
       
   957                 d->clickCausedFocus = true;
       
   958             }
   895         }
   959         }
   896         setFocus(true);
   960     }
   897     }
       
   898     if (!hadFocus && hasFocus())
       
   899         d->clickCausedFocus = true;
       
   900 
       
   901     bool mark = event->modifiers() & Qt::ShiftModifier;
   961     bool mark = event->modifiers() & Qt::ShiftModifier;
   902     int cursor = d->xToPos(event->pos().x());
   962     int cursor = d->xToPos(event->pos().x());
   903     d->control->moveCursor(cursor, mark);
   963     d->control->moveCursor(cursor, mark);
   904     event->setAccepted(true);
   964     event->setAccepted(true);
   905 }
   965 }
   920 Handles the given mouse \a event.
   980 Handles the given mouse \a event.
   921 */
   981 */
   922 void QDeclarativeTextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
   982 void QDeclarativeTextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
   923 {
   983 {
   924     Q_D(QDeclarativeTextInput);
   984     Q_D(QDeclarativeTextInput);
   925     QWidget *widget = event->widget();
   985     if (!d->showInputPanelOnFocus) { // input panel on click
   926     if (widget && !d->control->isReadOnly() && boundingRect().contains(event->pos()))
   986         if (d->focusOnPress && !isReadOnly() && boundingRect().contains(event->pos())) {
   927         qt_widget_private(widget)->handleSoftwareInputPanel(event->button(), d->clickCausedFocus);
   987             if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
       
   988                 if (view->scene() && view->scene() == scene()) {
       
   989                     qt_widget_private(view)->handleSoftwareInputPanel(event->button(), d->clickCausedFocus);
       
   990                 }
       
   991             }
       
   992         }
       
   993     }
   928     d->clickCausedFocus = false;
   994     d->clickCausedFocus = false;
       
   995     d->control->processEvent(event);
   929     if (!event->isAccepted())
   996     if (!event->isAccepted())
   930         QDeclarativePaintedItem::mouseReleaseEvent(event);
   997         QDeclarativePaintedItem::mouseReleaseEvent(event);
   931 }
   998 }
   932 
   999 
   933 bool QDeclarativeTextInput::event(QEvent* ev)
  1000 bool QDeclarativeTextInput::event(QEvent* ev)
   936     //Anything we don't deal with ourselves, pass to the control
  1003     //Anything we don't deal with ourselves, pass to the control
   937     bool handled = false;
  1004     bool handled = false;
   938     switch(ev->type()){
  1005     switch(ev->type()){
   939         case QEvent::KeyPress:
  1006         case QEvent::KeyPress:
   940         case QEvent::KeyRelease://###Should the control be doing anything with release?
  1007         case QEvent::KeyRelease://###Should the control be doing anything with release?
       
  1008         case QEvent::InputMethod:
   941         case QEvent::GraphicsSceneMousePress:
  1009         case QEvent::GraphicsSceneMousePress:
   942         case QEvent::GraphicsSceneMouseMove:
  1010         case QEvent::GraphicsSceneMouseMove:
   943         case QEvent::GraphicsSceneMouseRelease:
  1011         case QEvent::GraphicsSceneMouseRelease:
       
  1012         case QEvent::GraphicsSceneMouseDoubleClick:
   944             break;
  1013             break;
   945         default:
  1014         default:
   946             if (ev->type() == QEvent::GraphicsSceneMouseDoubleClick && !d->selectByMouse)
       
   947                 break;
       
   948             handled = d->control->processEvent(ev);
  1015             handled = d->control->processEvent(ev);
   949             if (ev->type() == QEvent::InputMethod)
       
   950                 updateSize();
       
   951     }
  1016     }
   952     if(!handled)
  1017     if(!handled)
   953         handled = QDeclarativePaintedItem::event(ev);
  1018         handled = QDeclarativePaintedItem::event(ev);
   954     return handled;
  1019     return handled;
   955 }
  1020 }
   956 
  1021 
   957 void QDeclarativeTextInput::geometryChanged(const QRectF &newGeometry,
  1022 void QDeclarativeTextInput::geometryChanged(const QRectF &newGeometry,
   958                                   const QRectF &oldGeometry)
  1023                                   const QRectF &oldGeometry)
   959 {
  1024 {
   960     if (newGeometry.width() != oldGeometry.width())
  1025     Q_D(QDeclarativeTextInput);
       
  1026     if (newGeometry.width() != oldGeometry.width()) {
   961         updateSize();
  1027         updateSize();
       
  1028         d->updateHorizontalScroll();
       
  1029     }
   962     QDeclarativePaintedItem::geometryChanged(newGeometry, oldGeometry);
  1030     QDeclarativePaintedItem::geometryChanged(newGeometry, oldGeometry);
       
  1031 }
       
  1032 
       
  1033 int QDeclarativeTextInputPrivate::calculateTextWidth()
       
  1034 {
       
  1035     return qRound(control->naturalTextWidth());
       
  1036 }
       
  1037 
       
  1038 void QDeclarativeTextInputPrivate::updateHorizontalScroll()
       
  1039 {
       
  1040     Q_Q(QDeclarativeTextInput);
       
  1041     int cix = qRound(control->cursorToX());
       
  1042     QRect br(q->boundingRect().toRect());
       
  1043     int widthUsed = calculateTextWidth();
       
  1044     if (autoScroll) {
       
  1045         if (widthUsed <=  br.width()) {
       
  1046             // text fits in br; use hscroll for alignment
       
  1047             switch (hAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) {
       
  1048             case Qt::AlignRight:
       
  1049                 hscroll = widthUsed - br.width() - 1;
       
  1050                 break;
       
  1051             case Qt::AlignHCenter:
       
  1052                 hscroll = (widthUsed - br.width()) / 2;
       
  1053                 break;
       
  1054             default:
       
  1055                 // Left
       
  1056                 hscroll = 0;
       
  1057                 break;
       
  1058             }
       
  1059         } else if (cix - hscroll >= br.width()) {
       
  1060             // text doesn't fit, cursor is to the right of br (scroll right)
       
  1061             hscroll = cix - br.width() + 1;
       
  1062         } else if (cix - hscroll < 0 && hscroll < widthUsed) {
       
  1063             // text doesn't fit, cursor is to the left of br (scroll left)
       
  1064             hscroll = cix;
       
  1065         } else if (widthUsed - hscroll < br.width()) {
       
  1066             // text doesn't fit, text document is to the left of br; align
       
  1067             // right
       
  1068             hscroll = widthUsed - br.width() + 1;
       
  1069         }
       
  1070     } else {
       
  1071         if(hAlign == QDeclarativeTextInput::AlignRight){
       
  1072             hscroll = q->width() - widthUsed;
       
  1073         }else if(hAlign == QDeclarativeTextInput::AlignHCenter){
       
  1074             hscroll = (q->width() - widthUsed) / 2;
       
  1075         } else {
       
  1076             hscroll = 0;
       
  1077         }
       
  1078     }
   963 }
  1079 }
   964 
  1080 
   965 void QDeclarativeTextInput::drawContents(QPainter *p, const QRect &r)
  1081 void QDeclarativeTextInput::drawContents(QPainter *p, const QRect &r)
   966 {
  1082 {
   967     Q_D(QDeclarativeTextInput);
  1083     Q_D(QDeclarativeTextInput);
   973         flags |= QLineControl::DrawCursor;
  1089         flags |= QLineControl::DrawCursor;
   974     if (d->control->hasSelectedText())
  1090     if (d->control->hasSelectedText())
   975             flags |= QLineControl::DrawSelections;
  1091             flags |= QLineControl::DrawSelections;
   976     QPoint offset = QPoint(0,0);
  1092     QPoint offset = QPoint(0,0);
   977     QFontMetrics fm = QFontMetrics(d->font);
  1093     QFontMetrics fm = QFontMetrics(d->font);
   978     int cix = qRound(d->control->cursorToX());
       
   979     QRect br(boundingRect().toRect());
  1094     QRect br(boundingRect().toRect());
   980     //###Is this using bearing appropriately?
       
   981     int minLB = qMax(0, -fm.minLeftBearing());
       
   982     int minRB = qMax(0, -fm.minRightBearing());
       
   983     int widthUsed = qRound(d->control->naturalTextWidth()) + 1 + minRB;
       
   984     if (d->autoScroll) {
  1095     if (d->autoScroll) {
   985         if ((minLB + widthUsed) <=  br.width()) {
       
   986             // text fits in br; use hscroll for alignment
       
   987             switch (d->hAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) {
       
   988             case Qt::AlignRight:
       
   989                 d->hscroll = widthUsed - br.width() + 1;
       
   990                 break;
       
   991             case Qt::AlignHCenter:
       
   992                 d->hscroll = (widthUsed - br.width()) / 2;
       
   993                 break;
       
   994             default:
       
   995                 // Left
       
   996                 d->hscroll = 0;
       
   997                 break;
       
   998             }
       
   999             d->hscroll -= minLB;
       
  1000         } else if (cix - d->hscroll >= br.width()) {
       
  1001             // text doesn't fit, cursor is to the right of br (scroll right)
       
  1002             d->hscroll = cix - br.width() + 1;
       
  1003         } else if (cix - d->hscroll < 0 && d->hscroll < widthUsed) {
       
  1004             // text doesn't fit, cursor is to the left of br (scroll left)
       
  1005             d->hscroll = cix;
       
  1006         } else if (widthUsed - d->hscroll < br.width()) {
       
  1007             // text doesn't fit, text document is to the left of br; align
       
  1008             // right
       
  1009             d->hscroll = widthUsed - br.width() + 1;
       
  1010         }
       
  1011         // the y offset is there to keep the baseline constant in case we have script changes in the text.
  1096         // the y offset is there to keep the baseline constant in case we have script changes in the text.
  1012         offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent());
  1097         offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent());
  1013     } else {
  1098     } else {
  1014         if(d->hAlign == AlignRight){
       
  1015             d->hscroll = width() - widthUsed;
       
  1016         }else if(d->hAlign == AlignHCenter){
       
  1017             d->hscroll = (width() - widthUsed) / 2;
       
  1018         }
       
  1019         d->hscroll -= minLB;
       
  1020         offset = QPoint(d->hscroll, 0);
  1099         offset = QPoint(d->hscroll, 0);
  1021     }
  1100     }
  1022 
       
  1023     d->control->draw(p, offset, r, flags);
  1101     d->control->draw(p, offset, r, flags);
  1024 
       
  1025     p->restore();
  1102     p->restore();
  1026 }
  1103 }
  1027 
  1104 
  1028 /*!
  1105 /*!
  1029 \overload
  1106 \overload
  1055     default:
  1132     default:
  1056         return QVariant();
  1133         return QVariant();
  1057     }
  1134     }
  1058 }
  1135 }
  1059 
  1136 
       
  1137 /*!
       
  1138     \qmlmethod void TextInput::selectAll()
       
  1139 
       
  1140     Causes all text to be selected.
       
  1141 */
  1060 void QDeclarativeTextInput::selectAll()
  1142 void QDeclarativeTextInput::selectAll()
  1061 {
  1143 {
  1062     Q_D(QDeclarativeTextInput);
  1144     Q_D(QDeclarativeTextInput);
  1063     d->control->setSelection(0, d->control->text().length());
  1145     d->control->setSelection(0, d->control->text().length());
  1064 }
  1146 }
  1065 
  1147 
       
  1148 #ifndef QT_NO_CLIPBOARD
       
  1149 /*!
       
  1150     \qmlmethod TextInput::cut()
       
  1151 
       
  1152     Moves the currently selected text to the system clipboard.
       
  1153 */
       
  1154 void QDeclarativeTextInput::cut()
       
  1155 {
       
  1156     Q_D(QDeclarativeTextInput);
       
  1157     d->control->copy();
       
  1158     d->control->del();
       
  1159 }
       
  1160 
       
  1161 /*!
       
  1162     \qmlmethod TextInput::copy()
       
  1163 
       
  1164     Copies the currently selected text to the system clipboard.
       
  1165 */
       
  1166 void QDeclarativeTextInput::copy()
       
  1167 {
       
  1168     Q_D(QDeclarativeTextInput);
       
  1169     d->control->copy();
       
  1170 }
       
  1171 
       
  1172 /*!
       
  1173     \qmlmethod TextInput::paste()
       
  1174 
       
  1175     Replaces the currently selected text by the contents of the system clipboard.
       
  1176 */
       
  1177 void QDeclarativeTextInput::paste()
       
  1178 {
       
  1179     Q_D(QDeclarativeTextInput);
       
  1180     d->control->paste();
       
  1181 }
       
  1182 #endif // QT_NO_CLIPBOARD
       
  1183 
       
  1184 /*!
       
  1185     \qmlmethod void TextInput::selectWord()
       
  1186 
       
  1187     Causes the word closest to the current cursor position to be selected.
       
  1188 */
       
  1189 void QDeclarativeTextInput::selectWord()
       
  1190 {
       
  1191     Q_D(QDeclarativeTextInput);
       
  1192     d->control->selectWordAtPos(d->control->cursor());
       
  1193 }
  1066 
  1194 
  1067 /*!
  1195 /*!
  1068     \qmlproperty bool TextInput::smooth
  1196     \qmlproperty bool TextInput::smooth
  1069 
  1197 
  1070     This property holds whether the text is smoothly scaled or transformed.
  1198     This property holds whether the text is smoothly scaled or transformed.
  1118     Q_D(const QDeclarativeTextInput);
  1246     Q_D(const QDeclarativeTextInput);
  1119     return d->control->displayText();
  1247     return d->control->displayText();
  1120 }
  1248 }
  1121 
  1249 
  1122 /*!
  1250 /*!
  1123     \qmlproperty string TextInput::selectByMouse
  1251     \qmlproperty bool TextInput::selectByMouse
  1124 
  1252 
  1125     Defaults to false.
  1253     Defaults to false.
  1126 
  1254 
  1127     If true, the user can use the mouse to select text in some
  1255     If true, the user can use the mouse to select text in some
  1128     platform-specific way. Note that for some platforms this may
  1256     platform-specific way. Note that for some platforms this may
  1170 */
  1298 */
  1171 void QDeclarativeTextInput::moveCursorSelection(int position)
  1299 void QDeclarativeTextInput::moveCursorSelection(int position)
  1172 {
  1300 {
  1173     Q_D(QDeclarativeTextInput);
  1301     Q_D(QDeclarativeTextInput);
  1174     d->control->moveCursor(position, true);
  1302     d->control->moveCursor(position, true);
       
  1303     d->updateHorizontalScroll();
       
  1304 }
       
  1305 
       
  1306 /*!
       
  1307     \qmlmethod void TextInput::openSoftwareInputPanel()
       
  1308 
       
  1309     Opens software input panels like virtual keyboards for typing, useful for
       
  1310     customizing when you want the input keyboard to be shown and hidden in
       
  1311     your application.
       
  1312 
       
  1313     By default the opening of input panels follows the platform style. On Symbian^1 and
       
  1314     Symbian^3 -based devices the panels are opened by clicking TextInput. On other platforms
       
  1315     the panels are automatically opened when TextInput element gains active focus. Input panels are
       
  1316     always closed if no editor has active focus.
       
  1317 
       
  1318   . You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
       
  1319     and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
       
  1320     the behavior you want.
       
  1321 
       
  1322     Only relevant on platforms, which provide virtual keyboards.
       
  1323 
       
  1324     \qml
       
  1325         import Qt 4.7
       
  1326         TextInput {
       
  1327             id: textInput
       
  1328             text: "Hello world!"
       
  1329             activeFocusOnPress: false
       
  1330             MouseArea {
       
  1331                 anchors.fill: parent
       
  1332                 onClicked: {
       
  1333                     if (!textInput.activeFocus) {
       
  1334                         textInput.forceActiveFocus()
       
  1335                         textInput.openSoftwareInputPanel();
       
  1336                     } else {
       
  1337                         textInput.focus = false;
       
  1338                     }
       
  1339                 }
       
  1340                 onPressAndHold: textInput.closeSoftwareInputPanel();
       
  1341             }
       
  1342         }
       
  1343     \endqml
       
  1344 */
       
  1345 void QDeclarativeTextInput::openSoftwareInputPanel()
       
  1346 {
       
  1347     QEvent event(QEvent::RequestSoftwareInputPanel);
       
  1348     if (qApp) {
       
  1349         if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
       
  1350             if (view->scene() && view->scene() == scene()) {
       
  1351                 QApplication::sendEvent(view, &event);
       
  1352             }
       
  1353         }
       
  1354     }
       
  1355 }
       
  1356 
       
  1357 /*!
       
  1358     \qmlmethod void TextInput::closeSoftwareInputPanel()
       
  1359 
       
  1360     Closes a software input panel like a virtual keyboard shown on the screen, useful
       
  1361     for customizing when you want the input keyboard to be shown and hidden in
       
  1362     your application.
       
  1363 
       
  1364     By default the opening of input panels follows the platform style. On Symbian^1 and
       
  1365     Symbian^3 -based devices the panels are opened by clicking TextInput. On other platforms
       
  1366     the panels are automatically opened when TextInput element gains active focus. Input panels are
       
  1367     always closed if no editor has active focus.
       
  1368 
       
  1369   . You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
       
  1370     and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
       
  1371     the behavior you want.
       
  1372 
       
  1373     Only relevant on platforms, which provide virtual keyboards.
       
  1374 
       
  1375     \qml
       
  1376         import Qt 4.7
       
  1377         TextInput {
       
  1378             id: textInput
       
  1379             text: "Hello world!"
       
  1380             activeFocusOnPress: false
       
  1381             MouseArea {
       
  1382                 anchors.fill: parent
       
  1383                 onClicked: {
       
  1384                     if (!textInput.activeFocus) {
       
  1385                         textInput.forceActiveFocus();
       
  1386                         textInput.openSoftwareInputPanel();
       
  1387                     } else {
       
  1388                         textInput.focus = false;
       
  1389                     }
       
  1390                 }
       
  1391                 onPressAndHold: textInput.closeSoftwareInputPanel();
       
  1392             }
       
  1393         }
       
  1394     \endqml
       
  1395 */
       
  1396 void QDeclarativeTextInput::closeSoftwareInputPanel()
       
  1397 {
       
  1398     QEvent event(QEvent::CloseSoftwareInputPanel);
       
  1399     if (qApp) {
       
  1400         QEvent event(QEvent::CloseSoftwareInputPanel);
       
  1401         if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
       
  1402             if (view->scene() && view->scene() == scene()) {
       
  1403                 QApplication::sendEvent(view, &event);
       
  1404             }
       
  1405         }
       
  1406     }
       
  1407 }
       
  1408 
       
  1409 void QDeclarativeTextInput::focusInEvent(QFocusEvent *event)
       
  1410 {
       
  1411     Q_D(const QDeclarativeTextInput);
       
  1412     if (d->showInputPanelOnFocus) {
       
  1413         if (d->focusOnPress && !isReadOnly()) {
       
  1414             openSoftwareInputPanel();
       
  1415         }
       
  1416     }
       
  1417     QDeclarativePaintedItem::focusInEvent(event);
  1175 }
  1418 }
  1176 
  1419 
  1177 void QDeclarativeTextInputPrivate::init()
  1420 void QDeclarativeTextInputPrivate::init()
  1178 {
  1421 {
  1179     Q_Q(QDeclarativeTextInput);
  1422     Q_Q(QDeclarativeTextInput);
  1180     control->setCursorWidth(1);
  1423     control->setCursorWidth(1);
  1181     control->setPasswordCharacter(QLatin1Char('*'));
  1424     control->setPasswordCharacter(QLatin1Char('*'));
  1182     control->setLayoutDirection(Qt::LeftToRight);
       
  1183     q->setSmooth(smooth);
  1425     q->setSmooth(smooth);
  1184     q->setAcceptedMouseButtons(Qt::LeftButton);
  1426     q->setAcceptedMouseButtons(Qt::LeftButton);
  1185     q->setFlag(QGraphicsItem::ItemHasNoContents, false);
  1427     q->setFlag(QGraphicsItem::ItemHasNoContents, false);
  1186     q->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
  1428     q->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
  1187     q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
  1429     q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
  1188                q, SLOT(cursorPosChanged()));
  1430                q, SLOT(cursorPosChanged()));
  1189     q->connect(control, SIGNAL(selectionChanged()),
  1431     q->connect(control, SIGNAL(selectionChanged()),
  1190                q, SLOT(selectionChanged()));
  1432                q, SLOT(selectionChanged()));
  1191     q->connect(control, SIGNAL(textChanged(const QString &)),
  1433     q->connect(control, SIGNAL(textChanged(const QString &)),
  1192                q, SIGNAL(displayTextChanged(const QString &)));
       
  1193     q->connect(control, SIGNAL(textChanged(const QString &)),
       
  1194                q, SLOT(q_textChanged()));
  1434                q, SLOT(q_textChanged()));
  1195     q->connect(control, SIGNAL(accepted()),
  1435     q->connect(control, SIGNAL(accepted()),
  1196                q, SIGNAL(accepted()));
  1436                q, SIGNAL(accepted()));
  1197     q->connect(control, SIGNAL(updateNeeded(QRect)),
  1437     q->connect(control, SIGNAL(updateNeeded(QRect)),
  1198                q, SLOT(updateRect(QRect)));
  1438                q, SLOT(updateRect(QRect)));
  1199     q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
       
  1200                q, SLOT(updateRect()));//TODO: Only update rect between pos's
       
  1201     q->connect(control, SIGNAL(selectionChanged()),
       
  1202                q, SLOT(updateRect()));//TODO: Only update rect in selection
       
  1203     //Note that above TODOs probably aren't that big a savings
       
  1204     q->updateSize();
  1439     q->updateSize();
  1205     oldValidity = control->hasAcceptableInput();
  1440     oldValidity = control->hasAcceptableInput();
  1206     lastSelectionStart = 0;
  1441     lastSelectionStart = 0;
  1207     lastSelectionEnd = 0;
  1442     lastSelectionEnd = 0;
  1208     QPalette p = control->palette();
  1443     QPalette p = control->palette();
  1211 }
  1446 }
  1212 
  1447 
  1213 void QDeclarativeTextInput::cursorPosChanged()
  1448 void QDeclarativeTextInput::cursorPosChanged()
  1214 {
  1449 {
  1215     Q_D(QDeclarativeTextInput);
  1450     Q_D(QDeclarativeTextInput);
       
  1451     updateRect();//TODO: Only update rect between pos's
       
  1452     updateMicroFocus();
  1216     emit cursorPositionChanged();
  1453     emit cursorPositionChanged();
  1217 
  1454 
  1218     if(!d->control->hasSelectedText()){
  1455     if(!d->control->hasSelectedText()){
  1219         if(d->lastSelectionStart != d->control->cursor()){
  1456         if(d->lastSelectionStart != d->control->cursor()){
  1220             d->lastSelectionStart = d->control->cursor();
  1457             d->lastSelectionStart = d->control->cursor();
  1228 }
  1465 }
  1229 
  1466 
  1230 void QDeclarativeTextInput::selectionChanged()
  1467 void QDeclarativeTextInput::selectionChanged()
  1231 {
  1468 {
  1232     Q_D(QDeclarativeTextInput);
  1469     Q_D(QDeclarativeTextInput);
       
  1470     updateRect();//TODO: Only update rect in selection
  1233     emit selectedTextChanged();
  1471     emit selectedTextChanged();
  1234 
  1472 
  1235     if(d->lastSelectionStart != d->control->selectionStart()){
  1473     if(d->lastSelectionStart != d->control->selectionStart()){
  1236         d->lastSelectionStart = d->control->selectionStart();
  1474         d->lastSelectionStart = d->control->selectionStart();
  1237         if(d->lastSelectionStart == -1)
  1475         if(d->lastSelectionStart == -1)
  1248 
  1486 
  1249 void QDeclarativeTextInput::q_textChanged()
  1487 void QDeclarativeTextInput::q_textChanged()
  1250 {
  1488 {
  1251     Q_D(QDeclarativeTextInput);
  1489     Q_D(QDeclarativeTextInput);
  1252     updateSize();
  1490     updateSize();
       
  1491     d->updateHorizontalScroll();
       
  1492     updateMicroFocus();
  1253     emit textChanged();
  1493     emit textChanged();
       
  1494     emit displayTextChanged();
  1254     if(hasAcceptableInput() != d->oldValidity){
  1495     if(hasAcceptableInput() != d->oldValidity){
  1255         d->oldValidity = hasAcceptableInput();
  1496         d->oldValidity = hasAcceptableInput();
  1256         emit acceptableInputChanged();
  1497         emit acceptableInputChanged();
  1257     }
  1498     }
  1258 }
  1499 }
  1265     else
  1506     else
  1266         dirtyCache(QRect(r.x() - d->hscroll, r.y(), r.width(), r.height()));
  1507         dirtyCache(QRect(r.x() - d->hscroll, r.y(), r.width(), r.height()));
  1267     update();
  1508     update();
  1268 }
  1509 }
  1269 
  1510 
       
  1511 QRectF QDeclarativeTextInput::boundingRect() const
       
  1512 {
       
  1513     Q_D(const QDeclarativeTextInput);
       
  1514     QRectF r = QDeclarativePaintedItem::boundingRect();
       
  1515 
       
  1516     int cursorWidth = d->cursorItem ? d->cursorItem->width() : d->control->cursorWidth();
       
  1517 
       
  1518     // Could include font max left/right bearings to either side of rectangle.
       
  1519 
       
  1520     r.setRight(r.right() + cursorWidth);
       
  1521     return r;
       
  1522 }
       
  1523 
  1270 void QDeclarativeTextInput::updateSize(bool needsRedraw)
  1524 void QDeclarativeTextInput::updateSize(bool needsRedraw)
  1271 {
  1525 {
  1272     Q_D(QDeclarativeTextInput);
  1526     Q_D(QDeclarativeTextInput);
  1273     int w = width();
  1527     int w = width();
  1274     int h = height();
  1528     int h = height();
  1275     setImplicitHeight(d->control->height());
  1529     setImplicitHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
  1276     int cursorWidth = d->control->cursorWidth();
  1530     setImplicitWidth(d->calculateTextWidth());
  1277     if(d->cursorItem)
       
  1278         cursorWidth = d->cursorItem->width();
       
  1279     setImplicitWidth(d->control->naturalTextWidth() + cursorWidth);
       
  1280     setContentsSize(QSize(width(), height()));//Repaints if changed
  1531     setContentsSize(QSize(width(), height()));//Repaints if changed
  1281     if(w==width() && h==height() && needsRedraw){
  1532     if(w==width() && h==height() && needsRedraw){
  1282         clearCache();
  1533         clearCache();
  1283         update();
  1534         update();
  1284     }
  1535     }