src/declarative/graphicsitems/qdeclarativetextinput.cpp
changeset 30 5dc02b23752f
child 33 3e2da88830cd
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "private/qdeclarativetextinput_p.h"
       
    43 #include "private/qdeclarativetextinput_p_p.h"
       
    44 
       
    45 #include <private/qdeclarativeglobal_p.h>
       
    46 #include <qdeclarativeinfo.h>
       
    47 
       
    48 #include <QValidator>
       
    49 #include <QApplication>
       
    50 #include <QFontMetrics>
       
    51 #include <QPainter>
       
    52 
       
    53 QT_BEGIN_NAMESPACE
       
    54 
       
    55 /*!
       
    56     \qmlclass TextInput QDeclarativeTextInput
       
    57   \since 4.7
       
    58     \brief The TextInput item allows you to add an editable line of text to a scene.
       
    59 
       
    60     TextInput can only display a single line of text, and can only display
       
    61     plain text. However it can provide addition input constraints on the text.
       
    62 
       
    63     Input constraints include setting a QValidator, an input mask, or a
       
    64     maximum input length.
       
    65 
       
    66     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.
       
    68 */
       
    69 QDeclarativeTextInput::QDeclarativeTextInput(QDeclarativeItem* parent)
       
    70     : QDeclarativePaintedItem(*(new QDeclarativeTextInputPrivate), parent)
       
    71 {
       
    72     Q_D(QDeclarativeTextInput);
       
    73     d->init();
       
    74 }
       
    75 
       
    76 QDeclarativeTextInput::~QDeclarativeTextInput()
       
    77 {
       
    78 }
       
    79 
       
    80 /*!
       
    81     \qmlproperty string TextInput::text
       
    82 
       
    83     The text in the TextInput.
       
    84 */
       
    85 
       
    86 QString QDeclarativeTextInput::text() const
       
    87 {
       
    88     Q_D(const QDeclarativeTextInput);
       
    89     return d->control->text();
       
    90 }
       
    91 
       
    92 void QDeclarativeTextInput::setText(const QString &s)
       
    93 {
       
    94     Q_D(QDeclarativeTextInput);
       
    95     if(s == text())
       
    96         return;
       
    97     d->control->setText(s);
       
    98     //emit textChanged();
       
    99 }
       
   100 
       
   101 /*!
       
   102     \qmlproperty string TextInput::font.family
       
   103 
       
   104     Sets the family name of the font.
       
   105 
       
   106     The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]".
       
   107     If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen.
       
   108     If the family isn't available a family will be set using the font matching algorithm.
       
   109 */
       
   110 
       
   111 /*!
       
   112     \qmlproperty bool TextInput::font.bold
       
   113 
       
   114     Sets whether the font weight is bold.
       
   115 */
       
   116 
       
   117 /*!
       
   118     \qmlproperty enumeration TextInput::font.weight
       
   119 
       
   120     Sets the font's weight.
       
   121 
       
   122     The weight can be one of:
       
   123     \list
       
   124     \o Font.Light
       
   125     \o Font.Normal - the default
       
   126     \o Font.DemiBold
       
   127     \o Font.Bold
       
   128     \o Font.Black
       
   129     \endlist
       
   130 
       
   131     \qml
       
   132     TextInput { text: "Hello"; font.weight: Font.DemiBold }
       
   133     \endqml
       
   134 */
       
   135 
       
   136 /*!
       
   137     \qmlproperty bool TextInput::font.italic
       
   138 
       
   139     Sets whether the font has an italic style.
       
   140 */
       
   141 
       
   142 /*!
       
   143     \qmlproperty bool TextInput::font.underline
       
   144 
       
   145     Sets whether the text is underlined.
       
   146 */
       
   147 
       
   148 /*!
       
   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
       
   156 
       
   157     Sets whether the font has a strikeout style.
       
   158 */
       
   159 
       
   160 /*!
       
   161     \qmlproperty real TextInput::font.pointSize
       
   162 
       
   163     Sets the font size in points. The point size must be greater than zero.
       
   164 */
       
   165 
       
   166 /*!
       
   167     \qmlproperty int TextInput::font.pixelSize
       
   168 
       
   169     Sets the font size in pixels.
       
   170 
       
   171     Using this function makes the font device dependent.
       
   172     Use \c pointSize to set the size of the font in a device independent manner.
       
   173 */
       
   174 
       
   175 /*!
       
   176     \qmlproperty real TextInput::font.letterSpacing
       
   177 
       
   178     Sets the letter spacing for the font.
       
   179 
       
   180     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
       
   182     the width of the character itself.
       
   183 */
       
   184 
       
   185 /*!
       
   186     \qmlproperty real TextInput::font.wordSpacing
       
   187 
       
   188     Sets the word spacing for the font.
       
   189 
       
   190     Word spacing changes the default spacing between individual words.
       
   191     A positive value increases the word spacing by a corresponding amount of pixels,
       
   192     while a negative value decreases the inter-word spacing accordingly.
       
   193 */
       
   194 
       
   195 /*!
       
   196     \qmlproperty enumeration TextInput::font.capitalization
       
   197 
       
   198     Sets the capitalization for the text.
       
   199 
       
   200     \list
       
   201     \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied.
       
   202     \o Font.AllUppercase - This alters the text to be rendered in all uppercase type.
       
   203     \o Font.AllLowercase	 - This alters the text to be rendered in all lowercase type.
       
   204     \o Font.SmallCaps -	This alters the text to be rendered in small-caps type.
       
   205     \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character.
       
   206     \endlist
       
   207 
       
   208     \qml
       
   209     TextInput { text: "Hello"; font.capitalization: Font.AllLowercase }
       
   210     \endqml
       
   211 */
       
   212 
       
   213 QFont QDeclarativeTextInput::font() const
       
   214 {
       
   215     Q_D(const QDeclarativeTextInput);
       
   216     return d->font;
       
   217 }
       
   218 
       
   219 void QDeclarativeTextInput::setFont(const QFont &font)
       
   220 {
       
   221     Q_D(QDeclarativeTextInput);
       
   222     if (d->font == font)
       
   223         return;
       
   224 
       
   225     d->font = font;
       
   226 
       
   227     d->control->setFont(d->font);
       
   228     if(d->cursorItem){
       
   229         d->cursorItem->setHeight(QFontMetrics(d->font).height());
       
   230         moveCursor();
       
   231     }
       
   232     updateSize();
       
   233     emit fontChanged(d->font);
       
   234 }
       
   235 
       
   236 /*!
       
   237     \qmlproperty color TextInput::color
       
   238 
       
   239     The text color.
       
   240 */
       
   241 QColor QDeclarativeTextInput::color() const
       
   242 {
       
   243     Q_D(const QDeclarativeTextInput);
       
   244     return d->color;
       
   245 }
       
   246 
       
   247 void QDeclarativeTextInput::setColor(const QColor &c)
       
   248 {
       
   249     Q_D(QDeclarativeTextInput);
       
   250     d->color = c;
       
   251 }
       
   252 
       
   253 
       
   254 /*!
       
   255     \qmlproperty color TextInput::selectionColor
       
   256 
       
   257     The text highlight color, used behind selections.
       
   258 */
       
   259 QColor QDeclarativeTextInput::selectionColor() const
       
   260 {
       
   261     Q_D(const QDeclarativeTextInput);
       
   262     return d->selectionColor;
       
   263 }
       
   264 
       
   265 void QDeclarativeTextInput::setSelectionColor(const QColor &color)
       
   266 {
       
   267     Q_D(QDeclarativeTextInput);
       
   268     if (d->selectionColor == color)
       
   269         return;
       
   270 
       
   271     d->selectionColor = color;
       
   272     QPalette p = d->control->palette();
       
   273     p.setColor(QPalette::Highlight, d->selectionColor);
       
   274     d->control->setPalette(p);
       
   275     emit selectionColorChanged(color);
       
   276 }
       
   277 
       
   278 /*!
       
   279     \qmlproperty color TextInput::selectedTextColor
       
   280 
       
   281     The highlighted text color, used in selections.
       
   282 */
       
   283 QColor QDeclarativeTextInput::selectedTextColor() const
       
   284 {
       
   285     Q_D(const QDeclarativeTextInput);
       
   286     return d->selectedTextColor;
       
   287 }
       
   288 
       
   289 void QDeclarativeTextInput::setSelectedTextColor(const QColor &color)
       
   290 {
       
   291     Q_D(QDeclarativeTextInput);
       
   292     if (d->selectedTextColor == color)
       
   293         return;
       
   294 
       
   295     d->selectedTextColor = color;
       
   296     QPalette p = d->control->palette();
       
   297     p.setColor(QPalette::HighlightedText, d->selectedTextColor);
       
   298     d->control->setPalette(p);
       
   299     emit selectedTextColorChanged(color);
       
   300 }
       
   301 
       
   302 /*!
       
   303     \qmlproperty enumeration TextInput::horizontalAlignment
       
   304 
       
   305     Sets the horizontal alignment of the text within the TextInput item's
       
   306     width and height.  By default, the text is left aligned.
       
   307 
       
   308     TextInput does not have vertical alignment, as the natural height is
       
   309     exactly the height of the single line of text. If you set the height
       
   310     manually to something larger, TextInput will always be top aligned
       
   311     vertically. You can use anchors to align it however you want within
       
   312     another item.
       
   313 
       
   314     The valid values for \c horizontalAlignment are \c TextInput.AlignLeft, \c TextInput.AlignRight and
       
   315     \c TextInput.AlignHCenter.
       
   316 */
       
   317 QDeclarativeTextInput::HAlignment QDeclarativeTextInput::hAlign() const
       
   318 {
       
   319     Q_D(const QDeclarativeTextInput);
       
   320     return d->hAlign;
       
   321 }
       
   322 
       
   323 void QDeclarativeTextInput::setHAlign(HAlignment align)
       
   324 {
       
   325     Q_D(QDeclarativeTextInput);
       
   326     if(align == d->hAlign)
       
   327         return;
       
   328     d->hAlign = align;
       
   329     updateRect();
       
   330     emit horizontalAlignmentChanged(d->hAlign);
       
   331 }
       
   332 
       
   333 bool QDeclarativeTextInput::isReadOnly() const
       
   334 {
       
   335     Q_D(const QDeclarativeTextInput);
       
   336     return d->control->isReadOnly();
       
   337 }
       
   338 
       
   339 void QDeclarativeTextInput::setReadOnly(bool ro)
       
   340 {
       
   341     Q_D(QDeclarativeTextInput);
       
   342     if (d->control->isReadOnly() == ro)
       
   343         return;
       
   344 
       
   345     d->control->setReadOnly(ro);
       
   346 
       
   347     emit readOnlyChanged(ro);
       
   348 }
       
   349 
       
   350 int QDeclarativeTextInput::maxLength() const
       
   351 {
       
   352     Q_D(const QDeclarativeTextInput);
       
   353     return d->control->maxLength();
       
   354 }
       
   355 
       
   356 void QDeclarativeTextInput::setMaxLength(int ml)
       
   357 {
       
   358     Q_D(QDeclarativeTextInput);
       
   359     if (d->control->maxLength() == ml)
       
   360         return;
       
   361 
       
   362     d->control->setMaxLength(ml);
       
   363 
       
   364     emit maximumLengthChanged(ml);
       
   365 }
       
   366 
       
   367 /*!
       
   368     \qmlproperty bool TextInput::cursorVisible
       
   369     Set to true when the TextInput shows a cursor.
       
   370 
       
   371     This property is set and unset when the TextInput gets focus, so that other
       
   372     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
       
   374     keep in mind that your value may be overwritten.
       
   375 
       
   376     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
       
   378     (but without actually giving it the focus).
       
   379 
       
   380     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.
       
   382 
       
   383     \code
       
   384     TextInput {
       
   385         text: "Text"
       
   386         cursorVisible: false
       
   387     }
       
   388     \endcode
       
   389 
       
   390     In the above snippet the cursor will still become visible when the
       
   391     TextInput gains focus.
       
   392 */
       
   393 bool QDeclarativeTextInput::isCursorVisible() const
       
   394 {
       
   395     Q_D(const QDeclarativeTextInput);
       
   396     return d->cursorVisible;
       
   397 }
       
   398 
       
   399 void QDeclarativeTextInput::setCursorVisible(bool on)
       
   400 {
       
   401     Q_D(QDeclarativeTextInput);
       
   402     if (d->cursorVisible == on)
       
   403         return;
       
   404     d->cursorVisible = on;
       
   405     d->control->setCursorBlinkPeriod(on?QApplication::cursorFlashTime():0);
       
   406     //d->control should emit the cursor update regions
       
   407     emit cursorVisibleChanged(d->cursorVisible);
       
   408 }
       
   409 
       
   410 /*!
       
   411     \qmlproperty int TextInput::cursorPosition
       
   412     The position of the cursor in the TextInput.
       
   413 */
       
   414 int QDeclarativeTextInput::cursorPosition() const
       
   415 {
       
   416     Q_D(const QDeclarativeTextInput);
       
   417     return d->control->cursor();
       
   418 }
       
   419 void QDeclarativeTextInput::setCursorPosition(int cp)
       
   420 {
       
   421     Q_D(QDeclarativeTextInput);
       
   422     d->control->moveCursor(cp);
       
   423 }
       
   424 
       
   425 /*!
       
   426   \internal
       
   427 
       
   428   Returns a Rect which encompasses the cursor, but which may be larger than is
       
   429   required. Ignores custom cursor delegates.
       
   430 */
       
   431 QRect QDeclarativeTextInput::cursorRect() const
       
   432 {
       
   433     Q_D(const QDeclarativeTextInput);
       
   434     return d->control->cursorRect();
       
   435 }
       
   436 
       
   437 /*!
       
   438     \qmlproperty int TextInput::selectionStart
       
   439 
       
   440     The cursor position before the first character in the current selection.
       
   441     Setting this and selectionEnd allows you to specify a selection in the
       
   442     text edit.
       
   443 
       
   444     Note that if selectionStart == selectionEnd then there is no current
       
   445     selection. If you attempt to set selectionStart to a value outside of
       
   446     the current text, selectionStart will not be changed.
       
   447 
       
   448     \sa selectionEnd, cursorPosition, selectedText
       
   449 */
       
   450 int QDeclarativeTextInput::selectionStart() const
       
   451 {
       
   452     Q_D(const QDeclarativeTextInput);
       
   453     return d->lastSelectionStart;
       
   454 }
       
   455 
       
   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 /*!
       
   466     \qmlproperty int TextInput::selectionEnd
       
   467 
       
   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
       
   470     text edit.
       
   471 
       
   472     Note that if selectionStart == selectionEnd then there is no current
       
   473     selection. If you attempt to set selectionEnd to a value outside of
       
   474     the current text, selectionEnd will not be changed.
       
   475 
       
   476     \sa selectionStart, cursorPosition, selectedText
       
   477 */
       
   478 int QDeclarativeTextInput::selectionEnd() const
       
   479 {
       
   480     Q_D(const QDeclarativeTextInput);
       
   481     return d->lastSelectionEnd;
       
   482 }
       
   483 
       
   484 void QDeclarativeTextInput::setSelectionEnd(int s)
       
   485 {
       
   486     Q_D(QDeclarativeTextInput);
       
   487     if(d->lastSelectionEnd == s || s < 0 || s > text().length())
       
   488         return;
       
   489     d->lastSelectionEnd = s;
       
   490     d->control->setSelection(d->lastSelectionStart, s - d->lastSelectionStart);
       
   491 }
       
   492 
       
   493 /*!
       
   494     \qmlproperty string TextInput::selectedText
       
   495 
       
   496     This read-only property provides the text currently selected in the
       
   497     text input.
       
   498 
       
   499     It is equivalent to the following snippet, but is faster and easier
       
   500     to use.
       
   501 
       
   502     \qml
       
   503     myTextInput.text.toString().substring(myTextInput.selectionStart,
       
   504         myTextInput.selectionEnd);
       
   505     \endqml
       
   506 */
       
   507 QString QDeclarativeTextInput::selectedText() const
       
   508 {
       
   509     Q_D(const QDeclarativeTextInput);
       
   510     return d->control->selectedText();
       
   511 }
       
   512 
       
   513 /*!
       
   514     \qmlproperty bool TextInput::focusOnPress
       
   515 
       
   516     Whether the TextInput should gain focus on a mouse press. By default this is
       
   517     set to true.
       
   518 */
       
   519 bool QDeclarativeTextInput::focusOnPress() const
       
   520 {
       
   521     Q_D(const QDeclarativeTextInput);
       
   522     return d->focusOnPress;
       
   523 }
       
   524 
       
   525 void QDeclarativeTextInput::setFocusOnPress(bool b)
       
   526 {
       
   527     Q_D(QDeclarativeTextInput);
       
   528     if (d->focusOnPress == b)
       
   529         return;
       
   530 
       
   531     d->focusOnPress = b;
       
   532 
       
   533     emit focusOnPressChanged(d->focusOnPress);
       
   534 }
       
   535 
       
   536 /*!
       
   537     \qmlproperty bool TextInput::autoScroll
       
   538 
       
   539     Whether the TextInput should scroll when the text is longer than the width. By default this is
       
   540     set to true.
       
   541 */
       
   542 bool QDeclarativeTextInput::autoScroll() const
       
   543 {
       
   544     Q_D(const QDeclarativeTextInput);
       
   545     return d->autoScroll;
       
   546 }
       
   547 
       
   548 void QDeclarativeTextInput::setAutoScroll(bool b)
       
   549 {
       
   550     Q_D(QDeclarativeTextInput);
       
   551     if (d->autoScroll == b)
       
   552         return;
       
   553 
       
   554     d->autoScroll = b;
       
   555 
       
   556     emit autoScrollChanged(d->autoScroll);
       
   557 }
       
   558 
       
   559 /*!
       
   560     \qmlclass IntValidator QIntValidator
       
   561 
       
   562     This element provides a validator for integer values
       
   563 */
       
   564 /*!
       
   565     \qmlproperty int IntValidator::top
       
   566 
       
   567     This property holds the validator's highest acceptable value.
       
   568     By default, this property's value is derived from the highest signed integer available (typically 2147483647).
       
   569 */
       
   570 /*!
       
   571     \qmlproperty int IntValidator::bottom
       
   572 
       
   573     This property holds the validator's lowest acceptable value.
       
   574     By default, this property's value is derived from the lowest signed integer available (typically -2147483647).
       
   575 */
       
   576 
       
   577 /*!
       
   578     \qmlclass DoubleValidator QDoubleValidator
       
   579 
       
   580     This element provides a validator for non-integer numbers.
       
   581 */
       
   582 
       
   583 /*!
       
   584     \qmlproperty real DoubleValidator::top
       
   585 
       
   586     This property holds the validator's maximum acceptable value.
       
   587     By default, this property contains a value of infinity.
       
   588 */
       
   589 /*!
       
   590     \qmlproperty real DoubleValidator::bottom
       
   591 
       
   592     This property holds the validator's minimum acceptable value.
       
   593     By default, this property contains a value of -infinity.
       
   594 */
       
   595 /*!
       
   596     \qmlproperty int DoubleValidator::decimals
       
   597 
       
   598     This property holds the validator's maximum number of digits after the decimal point.
       
   599     By default, this property contains a value of 1000.
       
   600 */
       
   601 /*!
       
   602     \qmlproperty enumeration DoubleValidator::notation
       
   603     This property holds the notation of how a string can describe a number.
       
   604 
       
   605     The values for this property are DoubleValidator.StandardNotation or DoubleValidator.ScientificNotation.
       
   606     If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part(i.e. 1.5E-2).
       
   607 
       
   608     By default, this property is set to DoubleValidator.ScientificNotation.
       
   609 */
       
   610 
       
   611 /*!
       
   612     \qmlclass RegExpValidator QRegExpValidator
       
   613 
       
   614     This element provides a validator, which counts as valid any string which
       
   615     matches a specified regular expression.
       
   616 */
       
   617 /*!
       
   618    \qmlproperty regExp RegExpValidator::regExp
       
   619 
       
   620    This property holds the regular expression used for validation.
       
   621 
       
   622    Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular expression
       
   623    matching "a".
       
   624 
       
   625    By default, this property contains a regular expression with the pattern .* that matches any string.
       
   626 */
       
   627 
       
   628 /*!
       
   629     \qmlproperty Validator TextInput::validator
       
   630 
       
   631     Allows you to set a validator on the TextInput. When a validator is set
       
   632     the TextInput will only accept input which leaves the text property in
       
   633     an acceptable or intermediate state. The accepted signal will only be sent
       
   634     if the text is in an acceptable state when enter is pressed.
       
   635 
       
   636     Currently supported validators are IntValidator, DoubleValidator and
       
   637     RegExpValidator. An example of using validators is shown below, which allows
       
   638     input of integers between 11 and 31 into the text input:
       
   639 
       
   640     \code
       
   641     import Qt 4.7
       
   642     TextInput{
       
   643         validator: IntValidator{bottom: 11; top: 31;}
       
   644         focus: true
       
   645     }
       
   646     \endcode
       
   647 
       
   648     \sa acceptableInput, inputMask
       
   649 */
       
   650 QValidator* QDeclarativeTextInput::validator() const
       
   651 {
       
   652     Q_D(const QDeclarativeTextInput);
       
   653     //###const cast isn't good, but needed for property system?
       
   654     return const_cast<QValidator*>(d->control->validator());
       
   655 }
       
   656 
       
   657 void QDeclarativeTextInput::setValidator(QValidator* v)
       
   658 {
       
   659     Q_D(QDeclarativeTextInput);
       
   660     if (d->control->validator() == v)
       
   661         return;
       
   662 
       
   663     d->control->setValidator(v);
       
   664     if(!d->control->hasAcceptableInput()){
       
   665         d->oldValidity = false;
       
   666         emit acceptableInputChanged();
       
   667     }
       
   668 
       
   669     emit validatorChanged();
       
   670 }
       
   671 
       
   672 /*!
       
   673     \qmlproperty string TextInput::inputMask
       
   674 
       
   675     Allows you to set an input mask on the TextInput, restricting the allowable
       
   676     text inputs. See QLineEdit::inputMask for further details, as the exact
       
   677     same mask strings are used by TextInput.
       
   678 
       
   679     \sa acceptableInput, validator
       
   680 */
       
   681 QString QDeclarativeTextInput::inputMask() const
       
   682 {
       
   683     Q_D(const QDeclarativeTextInput);
       
   684     return d->control->inputMask();
       
   685 }
       
   686 
       
   687 void QDeclarativeTextInput::setInputMask(const QString &im)
       
   688 {
       
   689     Q_D(QDeclarativeTextInput);
       
   690     if (d->control->inputMask() == im)
       
   691         return;
       
   692 
       
   693     d->control->setInputMask(im);
       
   694     emit inputMaskChanged(d->control->inputMask());
       
   695 }
       
   696 
       
   697 /*!
       
   698     \qmlproperty bool TextInput::acceptableInput
       
   699 
       
   700     This property is always true unless a validator or input mask has been set.
       
   701     If a validator or input mask has been set, this property will only be true
       
   702     if the current text is acceptable to the validator or input mask as a final
       
   703     string (not as an intermediate string).
       
   704 */
       
   705 bool QDeclarativeTextInput::hasAcceptableInput() const
       
   706 {
       
   707     Q_D(const QDeclarativeTextInput);
       
   708     return d->control->hasAcceptableInput();
       
   709 }
       
   710 
       
   711 /*!
       
   712     \qmlproperty enumeration TextInput::echoMode
       
   713 
       
   714     Specifies how the text should be displayed in the TextInput.
       
   715     \list
       
   716     \o TextInput.Normal - Displays the text as it is. (Default)
       
   717     \o TextInput.Password - Displays asterixes instead of characters.
       
   718     \o TextInput.NoEcho - Displays nothing.
       
   719     \o TextInput.PasswordEchoOnEdit - Displays all but the current character as asterixes.
       
   720     \endlist
       
   721 */
       
   722 QDeclarativeTextInput::EchoMode QDeclarativeTextInput::echoMode() const
       
   723 {
       
   724     Q_D(const QDeclarativeTextInput);
       
   725     return (QDeclarativeTextInput::EchoMode)d->control->echoMode();
       
   726 }
       
   727 
       
   728 void QDeclarativeTextInput::setEchoMode(QDeclarativeTextInput::EchoMode echo)
       
   729 {
       
   730     Q_D(QDeclarativeTextInput);
       
   731     if (echoMode() == echo)
       
   732         return;
       
   733     Qt::InputMethodHints imHints = inputMethodHints();
       
   734     if (echo == Password || echo == NoEcho)
       
   735         imHints |= Qt::ImhHiddenText;
       
   736     else
       
   737         imHints &= ~Qt::ImhHiddenText;
       
   738     if (echo != Normal)
       
   739         imHints |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
       
   740     else
       
   741         imHints &= ~(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
       
   742     setInputMethodHints(imHints);
       
   743     d->control->setEchoMode((uint)echo);
       
   744     update();
       
   745     emit echoModeChanged(echoMode());
       
   746 }
       
   747 
       
   748 /*!
       
   749     \qmlproperty Component TextInput::cursorDelegate
       
   750     The delegate for the cursor in the TextInput.
       
   751 
       
   752     If you set a cursorDelegate for a TextInput, this delegate will be used for
       
   753     drawing the cursor instead of the standard cursor. An instance of the
       
   754     delegate will be created and managed by the TextInput when a cursor is
       
   755     needed, and the x property of delegate instance will be set so as
       
   756     to be one pixel before the top left of the current character.
       
   757 
       
   758     Note that the root item of the delegate component must be a QDeclarativeItem or
       
   759     QDeclarativeItem derived item.
       
   760 */
       
   761 QDeclarativeComponent* QDeclarativeTextInput::cursorDelegate() const
       
   762 {
       
   763     Q_D(const QDeclarativeTextInput);
       
   764     return d->cursorComponent;
       
   765 }
       
   766 
       
   767 void QDeclarativeTextInput::setCursorDelegate(QDeclarativeComponent* c)
       
   768 {
       
   769     Q_D(QDeclarativeTextInput);
       
   770     if (d->cursorComponent == c)
       
   771         return;
       
   772 
       
   773     d->cursorComponent = c;
       
   774     if(!c){
       
   775         //note that the components are owned by something else
       
   776         disconnect(d->control, SIGNAL(cursorPositionChanged(int, int)),
       
   777                 this, SLOT(moveCursor()));
       
   778         delete d->cursorItem;
       
   779     }else{
       
   780         d->startCreatingCursor();
       
   781     }
       
   782 
       
   783     emit cursorDelegateChanged();
       
   784 }
       
   785 
       
   786 void QDeclarativeTextInputPrivate::startCreatingCursor()
       
   787 {
       
   788     Q_Q(QDeclarativeTextInput);
       
   789     q->connect(control, SIGNAL(cursorPositionChanged(int, int)),
       
   790             q, SLOT(moveCursor()));
       
   791     if(cursorComponent->isReady()){
       
   792         q->createCursor();
       
   793     }else if(cursorComponent->isLoading()){
       
   794         q->connect(cursorComponent, SIGNAL(statusChanged(int)),
       
   795                 q, SLOT(createCursor()));
       
   796     }else {//isError
       
   797         qmlInfo(q, cursorComponent->errors()) << QDeclarativeTextInput::tr("Could not load cursor delegate");
       
   798     }
       
   799 }
       
   800 
       
   801 void QDeclarativeTextInput::createCursor()
       
   802 {
       
   803     Q_D(QDeclarativeTextInput);
       
   804     if(d->cursorComponent->isError()){
       
   805         qmlInfo(this, d->cursorComponent->errors()) << tr("Could not load cursor delegate");
       
   806         return;
       
   807     }
       
   808 
       
   809     if(!d->cursorComponent->isReady())
       
   810         return;
       
   811 
       
   812     if(d->cursorItem)
       
   813         delete d->cursorItem;
       
   814     d->cursorItem = qobject_cast<QDeclarativeItem*>(d->cursorComponent->create());
       
   815     if(!d->cursorItem){
       
   816         qmlInfo(this, d->cursorComponent->errors()) << tr("Could not instantiate cursor delegate");
       
   817         return;
       
   818     }
       
   819 
       
   820     QDeclarative_setParent_noEvent(d->cursorItem, this);
       
   821     d->cursorItem->setParentItem(this);
       
   822     d->cursorItem->setX(d->control->cursorToX());
       
   823     d->cursorItem->setHeight(d->control->height());
       
   824 }
       
   825 
       
   826 void QDeclarativeTextInput::moveCursor()
       
   827 {
       
   828     Q_D(QDeclarativeTextInput);
       
   829     if(!d->cursorItem)
       
   830         return;
       
   831     d->cursorItem->setX(d->control->cursorToX() - d->hscroll);
       
   832 }
       
   833 
       
   834 /*!
       
   835     \qmlmethod int TextInput::xToPosition(int x)
       
   836 
       
   837     This function returns the character position at
       
   838     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,
       
   840     and so on until position text.length, which is after all characters.
       
   841 
       
   842     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.
       
   844 */
       
   845 int QDeclarativeTextInput::xToPosition(int x)
       
   846 {
       
   847     Q_D(const QDeclarativeTextInput);
       
   848     return d->control->xToPos(x - d->hscroll);
       
   849 }
       
   850 
       
   851 void QDeclarativeTextInputPrivate::focusChanged(bool hasFocus)
       
   852 {
       
   853     Q_Q(QDeclarativeTextInput);
       
   854     focused = hasFocus;
       
   855     q->setCursorVisible(hasFocus);
       
   856     if(q->echoMode() == QDeclarativeTextInput::PasswordEchoOnEdit && !hasFocus)
       
   857         control->updatePasswordEchoEditing(false);//QLineControl sets it on key events, but doesn't deal with focus events
       
   858     if (!hasFocus)
       
   859         control->deselect();
       
   860     QDeclarativeItemPrivate::focusChanged(hasFocus);
       
   861 }
       
   862 
       
   863 void QDeclarativeTextInput::keyPressEvent(QKeyEvent* ev)
       
   864 {
       
   865     Q_D(QDeclarativeTextInput);
       
   866     keyPressPreHandler(ev);
       
   867     if (ev->isAccepted())
       
   868         return;
       
   869     if (((ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) && ev->modifiers() == Qt::NoModifier) // Don't allow MacOSX up/down support, and we don't allow a completer.
       
   870         || (((d->control->cursor() == 0 && ev->key() == Qt::Key_Left)
       
   871             || (d->control->cursor() == d->control->text().length()
       
   872                 && ev->key() == Qt::Key_Right))
       
   873             && (d->lastSelectionStart == d->lastSelectionEnd)))
       
   874     {
       
   875         //ignore when moving off the end
       
   876         //unless there is a selection, because then moving will do something (deselect)
       
   877         ev->ignore();
       
   878     }else{
       
   879         d->control->processKeyEvent(ev);
       
   880     }
       
   881     if (!ev->isAccepted())
       
   882         QDeclarativePaintedItem::keyPressEvent(ev);
       
   883 }
       
   884 
       
   885 void QDeclarativeTextInput::mousePressEvent(QGraphicsSceneMouseEvent *event)
       
   886 {
       
   887     Q_D(QDeclarativeTextInput);
       
   888     bool hadFocus = hasFocus();
       
   889     if(d->focusOnPress){
       
   890         QGraphicsItem *p = parentItem();//###Is there a better way to find my focus scope?
       
   891         while(p) {
       
   892             if (p->flags() & QGraphicsItem::ItemIsFocusScope)
       
   893                 p->setFocus();
       
   894             p = p->parentItem();
       
   895         }
       
   896         setFocus(true);
       
   897     }
       
   898     if (!hadFocus && hasFocus())
       
   899         d->clickCausedFocus = true;
       
   900 
       
   901     bool mark = event->modifiers() & Qt::ShiftModifier;
       
   902     int cursor = d->xToPos(event->pos().x());
       
   903     d->control->moveCursor(cursor, mark);
       
   904     event->setAccepted(true);
       
   905 }
       
   906 
       
   907 void QDeclarativeTextInput::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
       
   908 {
       
   909     Q_D(QDeclarativeTextInput);
       
   910     if (d->selectByMouse) {
       
   911         d->control->moveCursor(d->xToPos(event->pos().x()), true);
       
   912         event->setAccepted(true);
       
   913     } else {
       
   914         QDeclarativePaintedItem::mouseMoveEvent(event);
       
   915     }
       
   916 }
       
   917 
       
   918 /*!
       
   919 \overload
       
   920 Handles the given mouse \a event.
       
   921 */
       
   922 void QDeclarativeTextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
       
   923 {
       
   924     Q_D(QDeclarativeTextInput);
       
   925     QWidget *widget = event->widget();
       
   926     if (widget && !d->control->isReadOnly() && boundingRect().contains(event->pos()))
       
   927         qt_widget_private(widget)->handleSoftwareInputPanel(event->button(), d->clickCausedFocus);
       
   928     d->clickCausedFocus = false;
       
   929     if (!event->isAccepted())
       
   930         QDeclarativePaintedItem::mouseReleaseEvent(event);
       
   931 }
       
   932 
       
   933 bool QDeclarativeTextInput::event(QEvent* ev)
       
   934 {
       
   935     Q_D(QDeclarativeTextInput);
       
   936     //Anything we don't deal with ourselves, pass to the control
       
   937     bool handled = false;
       
   938     switch(ev->type()){
       
   939         case QEvent::KeyPress:
       
   940         case QEvent::KeyRelease://###Should the control be doing anything with release?
       
   941         case QEvent::GraphicsSceneMousePress:
       
   942         case QEvent::GraphicsSceneMouseMove:
       
   943         case QEvent::GraphicsSceneMouseRelease:
       
   944             break;
       
   945         default:
       
   946             if (ev->type() == QEvent::GraphicsSceneMouseDoubleClick && !d->selectByMouse)
       
   947                 break;
       
   948             handled = d->control->processEvent(ev);
       
   949             if (ev->type() == QEvent::InputMethod)
       
   950                 updateSize();
       
   951     }
       
   952     if(!handled)
       
   953         handled = QDeclarativePaintedItem::event(ev);
       
   954     return handled;
       
   955 }
       
   956 
       
   957 void QDeclarativeTextInput::geometryChanged(const QRectF &newGeometry,
       
   958                                   const QRectF &oldGeometry)
       
   959 {
       
   960     if (newGeometry.width() != oldGeometry.width())
       
   961         updateSize();
       
   962     QDeclarativePaintedItem::geometryChanged(newGeometry, oldGeometry);
       
   963 }
       
   964 
       
   965 void QDeclarativeTextInput::drawContents(QPainter *p, const QRect &r)
       
   966 {
       
   967     Q_D(QDeclarativeTextInput);
       
   968     p->setRenderHint(QPainter::TextAntialiasing, true);
       
   969     p->save();
       
   970     p->setPen(QPen(d->color));
       
   971     int flags = QLineControl::DrawText;
       
   972     if(!isReadOnly() && d->cursorVisible && !d->cursorItem)
       
   973         flags |= QLineControl::DrawCursor;
       
   974     if (d->control->hasSelectedText())
       
   975             flags |= QLineControl::DrawSelections;
       
   976     QPoint offset = QPoint(0,0);
       
   977     QFontMetrics fm = QFontMetrics(d->font);
       
   978     int cix = qRound(d->control->cursorToX());
       
   979     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) {
       
   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.
       
  1012         offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent());
       
  1013     } 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);
       
  1021     }
       
  1022 
       
  1023     d->control->draw(p, offset, r, flags);
       
  1024 
       
  1025     p->restore();
       
  1026 }
       
  1027 
       
  1028 /*!
       
  1029 \overload
       
  1030 Returns the value of the given \a property.
       
  1031 */
       
  1032 QVariant QDeclarativeTextInput::inputMethodQuery(Qt::InputMethodQuery property) const
       
  1033 {
       
  1034     Q_D(const QDeclarativeTextInput);
       
  1035     switch(property) {
       
  1036     case Qt::ImMicroFocus:
       
  1037         return d->control->cursorRect();
       
  1038     case Qt::ImFont:
       
  1039         return font();
       
  1040     case Qt::ImCursorPosition:
       
  1041         return QVariant(d->control->cursor());
       
  1042     case Qt::ImSurroundingText:
       
  1043         return QVariant(text());
       
  1044     case Qt::ImCurrentSelection:
       
  1045         return QVariant(selectedText());
       
  1046     case Qt::ImMaximumTextLength:
       
  1047         return QVariant(maxLength());
       
  1048     case Qt::ImAnchorPosition:
       
  1049         if (d->control->selectionStart() == d->control->selectionEnd())
       
  1050             return QVariant(d->control->cursor());
       
  1051         else if (d->control->selectionStart() == d->control->cursor())
       
  1052             return QVariant(d->control->selectionEnd());
       
  1053         else
       
  1054             return QVariant(d->control->selectionStart());
       
  1055     default:
       
  1056         return QVariant();
       
  1057     }
       
  1058 }
       
  1059 
       
  1060 void QDeclarativeTextInput::selectAll()
       
  1061 {
       
  1062     Q_D(QDeclarativeTextInput);
       
  1063     d->control->setSelection(0, d->control->text().length());
       
  1064 }
       
  1065 
       
  1066 
       
  1067 /*!
       
  1068     \qmlproperty bool TextInput::smooth
       
  1069 
       
  1070     This property holds whether the text is smoothly scaled or transformed.
       
  1071 
       
  1072     Smooth filtering gives better visual quality, but is slower.  If
       
  1073     the item is displayed at its natural size, this property has no visual or
       
  1074     performance effect.
       
  1075 
       
  1076     \note Generally scaling artifacts are only visible if the item is stationary on
       
  1077     the screen.  A common pattern when animating an item is to disable smooth
       
  1078     filtering at the beginning of the animation and reenable it at the conclusion.
       
  1079 */
       
  1080 
       
  1081 /*!
       
  1082    \qmlproperty string TextInput::passwordCharacter
       
  1083 
       
  1084    This is the character displayed when echoMode is set to Password or
       
  1085    PasswordEchoOnEdit. By default it is an asterisk.
       
  1086 
       
  1087    If this property is set to a string with more than one character,
       
  1088    the first character is used. If the string is empty, the value
       
  1089    is ignored and the property is not set.
       
  1090 */
       
  1091 QString QDeclarativeTextInput::passwordCharacter() const
       
  1092 {
       
  1093     Q_D(const QDeclarativeTextInput);
       
  1094     return QString(d->control->passwordCharacter());
       
  1095 }
       
  1096 
       
  1097 void QDeclarativeTextInput::setPasswordCharacter(const QString &str)
       
  1098 {
       
  1099     Q_D(QDeclarativeTextInput);
       
  1100     if(str.length() < 1)
       
  1101         return;
       
  1102     emit passwordCharacterChanged();
       
  1103     d->control->setPasswordCharacter(str.constData()[0]);
       
  1104 }
       
  1105 
       
  1106 /*!
       
  1107    \qmlproperty string TextInput::displayText
       
  1108 
       
  1109    This is the text displayed in the TextInput.
       
  1110 
       
  1111    If \l echoMode is set to TextInput::Normal, this holds the
       
  1112    same value as the TextInput::text property. Otherwise,
       
  1113    this property holds the text visible to the user, while
       
  1114    the \l text property holds the actual entered text.
       
  1115 */
       
  1116 QString QDeclarativeTextInput::displayText() const
       
  1117 {
       
  1118     Q_D(const QDeclarativeTextInput);
       
  1119     return d->control->displayText();
       
  1120 }
       
  1121 
       
  1122 /*!
       
  1123     \qmlproperty string TextInput::selectByMouse
       
  1124 
       
  1125     Defaults to false.
       
  1126 
       
  1127     If true, the user can use the mouse to select text in some
       
  1128     platform-specific way. Note that for some platforms this may
       
  1129     not be an appropriate interaction (eg. may conflict with how
       
  1130     the text needs to behave inside a Flickable.
       
  1131 */
       
  1132 bool QDeclarativeTextInput::selectByMouse() const
       
  1133 {
       
  1134     Q_D(const QDeclarativeTextInput);
       
  1135     return d->selectByMouse;
       
  1136 }
       
  1137 
       
  1138 void QDeclarativeTextInput::setSelectByMouse(bool on)
       
  1139 {
       
  1140     Q_D(QDeclarativeTextInput);
       
  1141     if (d->selectByMouse != on) {
       
  1142         d->selectByMouse = on;
       
  1143         emit selectByMouseChanged(on);
       
  1144     }
       
  1145 }
       
  1146 
       
  1147 
       
  1148 /*!
       
  1149     \qmlmethod void TextInput::moveCursorSelection(int position)
       
  1150 
       
  1151     Moves the cursor to \a position and updates the selection accordingly.
       
  1152     (To only move the cursor, set the \l cursorPosition property.)
       
  1153 
       
  1154     When this method is called it additionally sets either the
       
  1155     selectionStart or the selectionEnd (whichever was at the previous cursor position)
       
  1156     to the specified position. This allows you to easily extend and contract the selected
       
  1157     text range.
       
  1158 
       
  1159     For example, take this sequence of calls:
       
  1160 
       
  1161     \code
       
  1162         cursorPosition = 5
       
  1163         moveCursorSelection(9)
       
  1164         moveCursorSelection(7)
       
  1165     \endcode
       
  1166 
       
  1167     This moves the cursor to position 5, extend the selection end from 5 to 9
       
  1168     and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
       
  1169     selected (the 6th and 7th characters).
       
  1170 */
       
  1171 void QDeclarativeTextInput::moveCursorSelection(int position)
       
  1172 {
       
  1173     Q_D(QDeclarativeTextInput);
       
  1174     d->control->moveCursor(position, true);
       
  1175 }
       
  1176 
       
  1177 void QDeclarativeTextInputPrivate::init()
       
  1178 {
       
  1179     Q_Q(QDeclarativeTextInput);
       
  1180     control->setCursorWidth(1);
       
  1181     control->setPasswordCharacter(QLatin1Char('*'));
       
  1182     control->setLayoutDirection(Qt::LeftToRight);
       
  1183     q->setSmooth(smooth);
       
  1184     q->setAcceptedMouseButtons(Qt::LeftButton);
       
  1185     q->setFlag(QGraphicsItem::ItemHasNoContents, false);
       
  1186     q->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
       
  1187     q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
       
  1188                q, SLOT(cursorPosChanged()));
       
  1189     q->connect(control, SIGNAL(selectionChanged()),
       
  1190                q, SLOT(selectionChanged()));
       
  1191     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()));
       
  1195     q->connect(control, SIGNAL(accepted()),
       
  1196                q, SIGNAL(accepted()));
       
  1197     q->connect(control, SIGNAL(updateNeeded(QRect)),
       
  1198                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();
       
  1205     oldValidity = control->hasAcceptableInput();
       
  1206     lastSelectionStart = 0;
       
  1207     lastSelectionEnd = 0;
       
  1208     QPalette p = control->palette();
       
  1209     selectedTextColor = p.color(QPalette::HighlightedText);
       
  1210     selectionColor = p.color(QPalette::Highlight);
       
  1211 }
       
  1212 
       
  1213 void QDeclarativeTextInput::cursorPosChanged()
       
  1214 {
       
  1215     Q_D(QDeclarativeTextInput);
       
  1216     emit cursorPositionChanged();
       
  1217 
       
  1218     if(!d->control->hasSelectedText()){
       
  1219         if(d->lastSelectionStart != d->control->cursor()){
       
  1220             d->lastSelectionStart = d->control->cursor();
       
  1221             emit selectionStartChanged();
       
  1222         }
       
  1223         if(d->lastSelectionEnd != d->control->cursor()){
       
  1224             d->lastSelectionEnd = d->control->cursor();
       
  1225             emit selectionEndChanged();
       
  1226         }
       
  1227     }
       
  1228 }
       
  1229 
       
  1230 void QDeclarativeTextInput::selectionChanged()
       
  1231 {
       
  1232     Q_D(QDeclarativeTextInput);
       
  1233     emit selectedTextChanged();
       
  1234 
       
  1235     if(d->lastSelectionStart != d->control->selectionStart()){
       
  1236         d->lastSelectionStart = d->control->selectionStart();
       
  1237         if(d->lastSelectionStart == -1)
       
  1238             d->lastSelectionStart = d->control->cursor();
       
  1239         emit selectionStartChanged();
       
  1240     }
       
  1241     if(d->lastSelectionEnd != d->control->selectionEnd()){
       
  1242         d->lastSelectionEnd = d->control->selectionEnd();
       
  1243         if(d->lastSelectionEnd == -1)
       
  1244             d->lastSelectionEnd = d->control->cursor();
       
  1245         emit selectionEndChanged();
       
  1246     }
       
  1247 }
       
  1248 
       
  1249 void QDeclarativeTextInput::q_textChanged()
       
  1250 {
       
  1251     Q_D(QDeclarativeTextInput);
       
  1252     updateSize();
       
  1253     emit textChanged();
       
  1254     if(hasAcceptableInput() != d->oldValidity){
       
  1255         d->oldValidity = hasAcceptableInput();
       
  1256         emit acceptableInputChanged();
       
  1257     }
       
  1258 }
       
  1259 
       
  1260 void QDeclarativeTextInput::updateRect(const QRect &r)
       
  1261 {
       
  1262     Q_D(QDeclarativeTextInput);
       
  1263     if(r == QRect())
       
  1264         clearCache();
       
  1265     else
       
  1266         dirtyCache(QRect(r.x() - d->hscroll, r.y(), r.width(), r.height()));
       
  1267     update();
       
  1268 }
       
  1269 
       
  1270 void QDeclarativeTextInput::updateSize(bool needsRedraw)
       
  1271 {
       
  1272     Q_D(QDeclarativeTextInput);
       
  1273     int w = width();
       
  1274     int h = height();
       
  1275     setImplicitHeight(d->control->height());
       
  1276     int cursorWidth = d->control->cursorWidth();
       
  1277     if(d->cursorItem)
       
  1278         cursorWidth = d->cursorItem->width();
       
  1279     setImplicitWidth(d->control->naturalTextWidth() + cursorWidth);
       
  1280     setContentsSize(QSize(width(), height()));//Repaints if changed
       
  1281     if(w==width() && h==height() && needsRedraw){
       
  1282         clearCache();
       
  1283         update();
       
  1284     }
       
  1285 }
       
  1286 
       
  1287 QT_END_NAMESPACE
       
  1288