Merge branch 'master' into refactor
[profile/ivi/qtdeclarative.git] / src / declarative / items / qsgtextinput.cpp
index 405540d..d30faad 100644 (file)
 
 #include <private/qdeclarativeglobal_p.h>
 #include <private/qwidget_p.h>
+#include <private/qsgdistancefieldglyphcache_p.h>
 
 #include <QtDeclarative/qdeclarativeinfo.h>
 #include <QtWidgets/qgraphicssceneevent.h>
 #include <QtWidgets/qinputcontext.h>
 #include <QTextBoundaryFinder>
 #include <qstyle.h>
+#include <qsgtextnode_p.h>
+#include <qsgsimplerectnode.h>
 
 QT_BEGIN_NAMESPACE
 
+DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
+
 QWidgetPrivate *qt_widget_private(QWidget *widget);
 
+/*!
+    \qmlclass TextInput QSGTextInput
+    \inqmlmodule QtQuick 2
+    \ingroup qml-basic-visual-elements
+    \brief The TextInput item displays an editable line of text.
+    \inherits Item
+
+    The TextInput element displays a single line of editable plain text.
+
+    TextInput is used to accept a line of text input. Input constraints
+    can be placed on a TextInput item (for example, through a \l validator or \l inputMask),
+    and setting \l echoMode to an appropriate value enables TextInput to be used for
+    a password input field.
+
+    On Mac OS X, the Up/Down key bindings for Home/End are explicitly disabled.
+    If you want such bindings (on any platform), you will need to construct them in QML.
+
+    \sa TextEdit, Text, {declarative/text/textselection}{Text Selection example}
+*/
 QSGTextInput::QSGTextInput(QSGItem* parent)
-: QSGImplicitSizePaintedItem(*(new QSGTextInputPrivate), parent)
+: QSGImplicitSizeItem(*(new QSGTextInputPrivate), parent)
 {
     Q_D(QSGTextInput);
     d->init();
@@ -67,6 +91,11 @@ QSGTextInput::~QSGTextInput()
 {
 }
 
+/*!
+    \qmlproperty string QtQuick2::TextInput::text
+
+    The text in the TextInput.
+*/
 QString QSGTextInput::text() const
 {
     Q_D(const QSGTextInput);
@@ -81,6 +110,111 @@ void QSGTextInput::setText(const QString &s)
     d->control->setText(s);
 }
 
+/*!
+    \qmlproperty string QtQuick2::TextInput::font.family
+
+    Sets the family name of the font.
+
+    The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]".
+    If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen.
+    If the family isn't available a family will be set using the font matching algorithm.
+*/
+
+/*!
+    \qmlproperty bool QtQuick2::TextInput::font.bold
+
+    Sets whether the font weight is bold.
+*/
+
+/*!
+    \qmlproperty enumeration QtQuick2::TextInput::font.weight
+
+    Sets the font's weight.
+
+    The weight can be one of:
+    \list
+    \o Font.Light
+    \o Font.Normal - the default
+    \o Font.DemiBold
+    \o Font.Bold
+    \o Font.Black
+    \endlist
+
+    \qml
+    TextInput { text: "Hello"; font.weight: Font.DemiBold }
+    \endqml
+*/
+
+/*!
+    \qmlproperty bool QtQuick2::TextInput::font.italic
+
+    Sets whether the font has an italic style.
+*/
+
+/*!
+    \qmlproperty bool QtQuick2::TextInput::font.underline
+
+    Sets whether the text is underlined.
+*/
+
+/*!
+    \qmlproperty bool QtQuick2::TextInput::font.strikeout
+
+    Sets whether the font has a strikeout style.
+*/
+
+/*!
+    \qmlproperty real QtQuick2::TextInput::font.pointSize
+
+    Sets the font size in points. The point size must be greater than zero.
+*/
+
+/*!
+    \qmlproperty int QtQuick2::TextInput::font.pixelSize
+
+    Sets the font size in pixels.
+
+    Using this function makes the font device dependent.
+    Use \c pointSize to set the size of the font in a device independent manner.
+*/
+
+/*!
+    \qmlproperty real QtQuick2::TextInput::font.letterSpacing
+
+    Sets the letter spacing for the font.
+
+    Letter spacing changes the default spacing between individual letters in the font.
+    A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing.
+*/
+
+/*!
+    \qmlproperty real QtQuick2::TextInput::font.wordSpacing
+
+    Sets the word spacing for the font.
+
+    Word spacing changes the default spacing between individual words.
+    A positive value increases the word spacing by a corresponding amount of pixels,
+    while a negative value decreases the inter-word spacing accordingly.
+*/
+
+/*!
+    \qmlproperty enumeration QtQuick2::TextInput::font.capitalization
+
+    Sets the capitalization for the text.
+
+    \list
+    \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied.
+    \o Font.AllUppercase - This alters the text to be rendered in all uppercase type.
+    \o Font.AllLowercase        - This alters the text to be rendered in all lowercase type.
+    \o Font.SmallCaps -        This alters the text to be rendered in small-caps type.
+    \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character.
+    \endlist
+
+    \qml
+    TextInput { text: "Hello"; font.capitalization: Font.AllLowercase }
+    \endqml
+*/
+
 QFont QSGTextInput::font() const
 {
     Q_D(const QSGTextInput);
@@ -112,6 +246,11 @@ void QSGTextInput::setFont(const QFont &font)
     emit fontChanged(d->sourceFont);
 }
 
+/*!
+    \qmlproperty color QtQuick2::TextInput::color
+
+    The text color.
+*/
 QColor QSGTextInput::color() const
 {
     Q_D(const QSGTextInput);
@@ -128,6 +267,12 @@ void QSGTextInput::setColor(const QColor &c)
     }
 }
 
+
+/*!
+    \qmlproperty color QtQuick2::TextInput::selectionColor
+
+    The text highlight color, used behind selections.
+*/
 QColor QSGTextInput::selectionColor() const
 {
     Q_D(const QSGTextInput);
@@ -144,11 +289,15 @@ void QSGTextInput::setSelectionColor(const QColor &color)
     QPalette p = d->control->palette();
     p.setColor(QPalette::Highlight, d->selectionColor);
     d->control->setPalette(p);
-    if (d->control->hasSelectedText()) 
+    if (d->control->hasSelectedText())
         update();
     emit selectionColorChanged(color);
 }
+/*!
+    \qmlproperty color QtQuick2::TextInput::selectedTextColor
 
+    The highlighted text color, used in selections.
+*/
 QColor QSGTextInput::selectedTextColor() const
 {
     Q_D(const QSGTextInput);
@@ -165,11 +314,34 @@ void QSGTextInput::setSelectedTextColor(const QColor &color)
     QPalette p = d->control->palette();
     p.setColor(QPalette::HighlightedText, d->selectedTextColor);
     d->control->setPalette(p);
-    if (d->control->hasSelectedText()) 
+    if (d->control->hasSelectedText())
         update();
     emit selectedTextColorChanged(color);
 }
 
+/*!
+    \qmlproperty enumeration QtQuick2::TextInput::horizontalAlignment
+    \qmlproperty enumeration QtQuick2::TextInput::effectiveHorizontalAlignment
+
+    Sets the horizontal alignment of the text within the TextInput item's
+    width and height. By default, the text alignment follows the natural alignment
+    of the text, for example text that is read from left to right will be aligned to
+    the left.
+
+    TextInput does not have vertical alignment, as the natural height is
+    exactly the height of the single line of text. If you set the height
+    manually to something larger, TextInput will always be top aligned
+    vertically. You can use anchors to align it however you want within
+    another item.
+
+    The valid values for \c horizontalAlignment are \c TextInput.AlignLeft, \c TextInput.AlignRight and
+    \c TextInput.AlignHCenter.
+
+    When using the attached property LayoutMirroring::enabled to mirror application
+    layouts, the horizontal alignment of text will also be mirrored. However, the property
+    \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
+    of TextInput, use the read-only property \c effectiveHorizontalAlignment.
+*/
 QSGTextInput::HAlignment QSGTextInput::hAlign() const
 {
     Q_D(const QSGTextInput);
@@ -250,6 +422,15 @@ void QSGTextInputPrivate::mirrorChange()
     }
 }
 
+/*!
+    \qmlproperty bool QtQuick2::TextInput::readOnly
+
+    Sets whether user input can modify the contents of the TextInput.
+
+    If readOnly is set to true, then user input will not affect the text
+    property. Any bindings or attempts to set the text property will still
+    work.
+*/
 bool QSGTextInput::isReadOnly() const
 {
     Q_D(const QSGTextInput);
@@ -270,6 +451,14 @@ void QSGTextInput::setReadOnly(bool ro)
     emit readOnlyChanged(ro);
 }
 
+/*!
+    \qmlproperty int QtQuick2::TextInput::maximumLength
+    The maximum permitted length of the text in the TextInput.
+
+    If the text is too long, it is truncated at the limit.
+
+    By default, this property contains a value of 32767.
+*/
 int QSGTextInput::maxLength() const
 {
     Q_D(const QSGTextInput);
@@ -287,6 +476,32 @@ void QSGTextInput::setMaxLength(int ml)
     emit maximumLengthChanged(ml);
 }
 
+/*!
+    \qmlproperty bool QtQuick2::TextInput::cursorVisible
+    Set to true when the TextInput shows a cursor.
+
+    This property is set and unset when the TextInput gets active focus, so that other
+    properties can be bound to whether the cursor is currently showing. As it
+    gets set and unset automatically, when you set the value yourself you must
+    keep in mind that your value may be overwritten.
+
+    It can be set directly in script, for example if a KeyProxy might
+    forward keys to it and you desire it to look active when this happens
+    (but without actually giving it active focus).
+
+    It should not be set directly on the element, like in the below QML,
+    as the specified value will be overridden an lost on focus changes.
+
+    \code
+    TextInput {
+        text: "Text"
+        cursorVisible: false
+    }
+    \endcode
+
+    In the above snippet the cursor will still become visible when the
+    TextInput gains active focus.
+*/
 bool QSGTextInput::isCursorVisible() const
 {
     Q_D(const QSGTextInput);
@@ -308,6 +523,10 @@ void QSGTextInput::setCursorVisible(bool on)
     emit cursorVisibleChanged(d->cursorVisible);
 }
 
+/*!
+    \qmlproperty int QtQuick2::TextInput::cursorPosition
+    The position of the cursor in the TextInput.
+*/
 int QSGTextInput::cursorPosition() const
 {
     Q_D(const QSGTextInput);
@@ -321,6 +540,10 @@ void QSGTextInput::setCursorPosition(int cp)
     d->control->moveCursor(cp);
 }
 
+/*!
+  Returns a Rect which encompasses the cursor, but which may be larger than is
+  required. Ignores custom cursor delegates.
+*/
 QRect QSGTextInput::cursorRectangle() const
 {
     Q_D(const QSGTextInput);
@@ -331,19 +554,49 @@ QRect QSGTextInput::cursorRectangle() const
     r.adjust(5 - d->hscroll, 0, -4 - d->hscroll, -1);
     return r;
 }
+/*!
+    \qmlproperty int QtQuick2::TextInput::selectionStart
+
+    The cursor position before the first character in the current selection.
+
+    This property is read-only. To change the selection, use select(start,end),
+    selectAll(), or selectWord().
 
+    \sa selectionEnd, cursorPosition, selectedText
+*/
 int QSGTextInput::selectionStart() const
 {
     Q_D(const QSGTextInput);
     return d->lastSelectionStart;
 }
+/*!
+    \qmlproperty int QtQuick2::TextInput::selectionEnd
 
+    The cursor position after the last character in the current selection.
+
+    This property is read-only. To change the selection, use select(start,end),
+    selectAll(), or selectWord().
+
+    \sa selectionStart, cursorPosition, selectedText
+*/
 int QSGTextInput::selectionEnd() const
 {
     Q_D(const QSGTextInput);
     return d->lastSelectionEnd;
 }
+/*!
+    \qmlmethod void QtQuick2::TextInput::select(int start, int end)
+
+    Causes the text from \a start to \a end to be selected.
+
+    If either start or end is out of range, the selection is not changed.
+
+    After calling this, selectionStart will become the lesser
+    and selectionEnd will become the greater (regardless of the order passed
+    to this method).
 
+    \sa selectionStart, selectionEnd
+*/
 void QSGTextInput::select(int start, int end)
 {
     Q_D(QSGTextInput);
@@ -352,12 +605,32 @@ void QSGTextInput::select(int start, int end)
     d->control->setSelection(start, end-start);
 }
 
+/*!
+    \qmlproperty string QtQuick2::TextInput::selectedText
+
+    This read-only property provides the text currently selected in the
+    text input.
+
+    It is equivalent to the following snippet, but is faster and easier
+    to use.
+
+    \js
+    myTextInput.text.toString().substring(myTextInput.selectionStart,
+        myTextInput.selectionEnd);
+    \endjs
+*/
 QString QSGTextInput::selectedText() const
 {
     Q_D(const QSGTextInput);
     return d->control->selectedText();
 }
 
+/*!
+    \qmlproperty bool QtQuick2::TextInput::activeFocusOnPress
+
+    Whether the TextInput should gain active focus on a mouse press. By default this is
+    set to true.
+*/
 bool QSGTextInput::focusOnPress() const
 {
     Q_D(const QSGTextInput);
@@ -374,7 +647,12 @@ void QSGTextInput::setFocusOnPress(bool b)
 
     emit activeFocusOnPressChanged(d->focusOnPress);
 }
+/*!
+    \qmlproperty bool QtQuick2::TextInput::autoScroll
 
+    Whether the TextInput should scroll when the text is longer than the width. By default this is
+    set to true.
+*/
 bool QSGTextInput::autoScroll() const
 {
     Q_D(const QSGTextInput);
@@ -395,6 +673,114 @@ void QSGTextInput::setAutoScroll(bool b)
 }
 
 #ifndef QT_NO_VALIDATOR
+
+/*!
+    \qmlclass IntValidator QIntValidator
+    \inqmlmodule QtQuick 2
+    \ingroup qml-basic-visual-elements
+
+    This element provides a validator for integer values.
+
+    IntValidator uses the \l {QLocale::setDefault()}{default locale} to interpret the number and
+    will accept locale specific digits, group separators, and positive and negative signs.  In
+    addition, IntValidator is always guaranteed to accept a number formatted according to the "C"
+    locale.
+*/
+/*!
+    \qmlproperty int QtQuick2::IntValidator::top
+
+    This property holds the validator's highest acceptable value.
+    By default, this property's value is derived from the highest signed integer available (typically 2147483647).
+*/
+/*!
+    \qmlproperty int QtQuick2::IntValidator::bottom
+
+    This property holds the validator's lowest acceptable value.
+    By default, this property's value is derived from the lowest signed integer available (typically -2147483647).
+*/
+
+/*!
+    \qmlclass DoubleValidator QDoubleValidator
+    \inqmlmodule QtQuick 2
+    \ingroup qml-basic-visual-elements
+
+    This element provides a validator for non-integer numbers.
+*/
+
+/*!
+    \qmlproperty real QtQuick2::DoubleValidator::top
+
+    This property holds the validator's maximum acceptable value.
+    By default, this property contains a value of infinity.
+*/
+/*!
+    \qmlproperty real QtQuick2::DoubleValidator::bottom
+
+    This property holds the validator's minimum acceptable value.
+    By default, this property contains a value of -infinity.
+*/
+/*!
+    \qmlproperty int QtQuick2::DoubleValidator::decimals
+
+    This property holds the validator's maximum number of digits after the decimal point.
+    By default, this property contains a value of 1000.
+*/
+/*!
+    \qmlproperty enumeration QtQuick2::DoubleValidator::notation
+    This property holds the notation of how a string can describe a number.
+
+    The possible values for this property are:
+
+    \list
+    \o DoubleValidator.StandardNotation
+    \o DoubleValidator.ScientificNotation (default)
+    \endlist
+
+    If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part (e.g. 1.5E-2).
+*/
+
+/*!
+    \qmlclass RegExpValidator QRegExpValidator
+    \inqmlmodule QtQuick 2
+    \ingroup qml-basic-visual-elements
+
+    This element provides a validator, which counts as valid any string which
+    matches a specified regular expression.
+*/
+/*!
+   \qmlproperty regExp QtQuick2::RegExpValidator::regExp
+
+   This property holds the regular expression used for validation.
+
+   Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular expression
+   matching "a".
+
+   By default, this property contains a regular expression with the pattern .* that matches any string.
+*/
+
+/*!
+    \qmlproperty Validator QtQuick2::TextInput::validator
+
+    Allows you to set a validator on the TextInput. When a validator is set
+    the TextInput will only accept input which leaves the text property in
+    an acceptable or intermediate state. The accepted signal will only be sent
+    if the text is in an acceptable state when enter is pressed.
+
+    Currently supported validators are IntValidator, DoubleValidator and
+    RegExpValidator. An example of using validators is shown below, which allows
+    input of integers between 11 and 31 into the text input:
+
+    \code
+    import QtQuick 1.0
+    TextInput{
+        validator: IntValidator{bottom: 11; top: 31;}
+        focus: true
+    }
+    \endcode
+
+    \sa acceptableInput, inputMask
+*/
+
 QValidator* QSGTextInput::validator() const
 {
     Q_D(const QSGTextInput);
@@ -418,6 +804,15 @@ void QSGTextInput::setValidator(QValidator* v)
 }
 #endif // QT_NO_VALIDATOR
 
+/*!
+    \qmlproperty string QtQuick2::TextInput::inputMask
+
+    Allows you to set an input mask on the TextInput, restricting the allowable
+    text inputs. See QLineEdit::inputMask for further details, as the exact
+    same mask strings are used by TextInput.
+
+    \sa acceptableInput, validator
+*/
 QString QSGTextInput::inputMask() const
 {
     Q_D(const QSGTextInput);
@@ -434,12 +829,29 @@ void QSGTextInput::setInputMask(const QString &im)
     emit inputMaskChanged(d->control->inputMask());
 }
 
+/*!
+    \qmlproperty bool QtQuick2::TextInput::acceptableInput
+
+    This property is always true unless a validator or input mask has been set.
+    If a validator or input mask has been set, this property will only be true
+    if the current text is acceptable to the validator or input mask as a final
+    string (not as an intermediate string).
+*/
 bool QSGTextInput::hasAcceptableInput() const
 {
     Q_D(const QSGTextInput);
     return d->control->hasAcceptableInput();
 }
 
+/*!
+    \qmlsignal QtQuick2::TextInput::onAccepted()
+
+    This handler is called when the Return or Enter key is pressed.
+    Note that if there is a \l validator or \l inputMask set on the text
+    input, the handler will only be emitted if the input is in an acceptable
+    state.
+*/
+
 void QSGTextInputPrivate::updateInputMethodHints()
 {
     Q_Q(QSGTextInput);
@@ -453,7 +865,18 @@ void QSGTextInputPrivate::updateInputMethodHints()
         hints |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
     q->setInputMethodHints(hints);
 }
-
+/*!
+    \qmlproperty enumeration QtQuick2::TextInput::echoMode
+
+    Specifies how the text should be displayed in the TextInput.
+    \list
+    \o TextInput.Normal - Displays the text as it is. (Default)
+    \o TextInput.Password - Displays asterixes instead of characters.
+    \o TextInput.NoEcho - Displays nothing.
+    \o TextInput.PasswordEchoOnEdit - Displays characters as they are entered
+    while editing, otherwise displays asterisks.
+    \endlist
+*/
 QSGTextInput::EchoMode QSGTextInput::echoMode() const
 {
     Q_D(const QSGTextInput);
@@ -486,6 +909,19 @@ void QSGTextInput::setIMHints(Qt::InputMethodHints hints)
     d->updateInputMethodHints();
 }
 
+/*!
+    \qmlproperty Component QtQuick2::TextInput::cursorDelegate
+    The delegate for the cursor in the TextInput.
+
+    If you set a cursorDelegate for a TextInput, this delegate will be used for
+    drawing the cursor instead of the standard cursor. An instance of the
+    delegate will be created and managed by the TextInput when a cursor is
+    needed, and the x property of delegate instance will be set so as
+    to be one pixel before the top left of the current character.
+
+    Note that the root item of the delegate component must be a QDeclarativeItem or
+    QDeclarativeItem derived item.
+*/
 QDeclarativeComponent* QSGTextInput::cursorDelegate() const
 {
     Q_D(const QSGTextInput);
@@ -547,6 +983,15 @@ void QSGTextInput::createCursor()
     d->cursorItem->setHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
 }
 
+/*!
+    \qmlmethod rect QtQuick2::TextInput::positionToRectangle(int pos)
+
+    This function takes a character position and returns the rectangle that the
+    cursor would occupy, if it was placed at that character position.
+
+    This is similar to setting the cursorPosition, and then querying the cursor
+    rectangle, but the cursorPosition is not changed.
+*/
 QRectF QSGTextInput::positionToRectangle(int pos) const
 {
     Q_D(const QSGTextInput);
@@ -558,6 +1003,24 @@ QRectF QSGTextInput::positionToRectangle(int pos) const
         cursorRectangle().height());
 }
 
+/*!
+    \qmlmethod int QtQuick2::TextInput::positionAt(int x, CursorPosition position = CursorBetweenCharacters)
+
+    This function returns the character position at
+    x pixels from the left of the textInput. Position 0 is before the
+    first character, position 1 is after the first character but before the second,
+    and so on until position text.length, which is after all characters.
+
+    This means that for all x values before the first character this function returns 0,
+    and for all x values after the last character this function returns text.length.
+
+    The cursor position type specifies how the cursor position should be resolved.
+
+    \list
+    \o TextInput.CursorBetweenCharacters - Returns the position between characters that is nearest x.
+    \o TextInput.CursorOnCharacter - Returns the position before the character that is nearest x.
+    \endlist
+*/
 int QSGTextInput::positionAt(int x) const
 {
     return positionAt(x, CursorBetweenCharacters);
@@ -597,7 +1060,7 @@ void QSGTextInput::keyPressEvent(QKeyEvent* ev)
         d->control->processKeyEvent(ev);
     }
     if (!ev->isAccepted())
-        QSGPaintedItem::keyPressEvent(ev);
+        QSGImplicitSizeItem::keyPressEvent(ev);
 }
 
 void QSGTextInput::inputMethodEvent(QInputMethodEvent *ev)
@@ -610,7 +1073,7 @@ void QSGTextInput::inputMethodEvent(QInputMethodEvent *ev)
         d->control->processInputMethodEvent(ev);
     }
     if (!ev->isAccepted())
-        QSGPaintedItem::inputMethodEvent(ev);
+        QSGImplicitSizeItem::inputMethodEvent(ev);
 
     if (wasComposing != (d->control->preeditAreaText().length() > 0))
         emit inputMethodComposingChanged();
@@ -626,7 +1089,7 @@ void QSGTextInput::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
         d->control->selectWordAtPos(cursor);
         event->setAccepted(true);
     } else {
-        QSGPaintedItem::mouseDoubleClickEvent(event);
+        QSGImplicitSizeItem::mouseDoubleClickEvent(event);
     }
 }
 
@@ -671,7 +1134,7 @@ void QSGTextInput::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
         moveCursorSelection(d->xToPos(event->pos().x()), d->mouseSelectionMode);
         event->setAccepted(true);
     } else {
-        QSGPaintedItem::mouseMoveEvent(event);
+        QSGImplicitSizeItem::mouseMoveEvent(event);
     }
 }
 
@@ -696,7 +1159,7 @@ void QSGTextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
     d->clickCausedFocus = false;
     d->control->processEvent(event);
     if (!event->isAccepted())
-        QSGPaintedItem::mouseReleaseEvent(event);
+        QSGImplicitSizeItem::mouseReleaseEvent(event);
 }
 
 bool QSGTextInputPrivate::sendMouseEventToInputContext(
@@ -762,7 +1225,7 @@ bool QSGTextInput::event(QEvent* ev)
             handled = d->control->processEvent(ev);
     }
     if(!handled)
-        handled = QSGPaintedItem::event(ev);
+        handled = QSGImplicitSizeItem::event(ev);
     return handled;
 }
 
@@ -773,7 +1236,7 @@ void QSGTextInput::geometryChanged(const QRectF &newGeometry,
         updateSize();
         updateCursorRectangle();
     }
-    QSGPaintedItem::geometryChanged(newGeometry, oldGeometry);
+    QSGImplicitSizeItem::geometryChanged(newGeometry, oldGeometry);
 }
 
 int QSGTextInputPrivate::calculateTextWidth()
@@ -827,25 +1290,73 @@ void QSGTextInputPrivate::updateHorizontalScroll()
     }
 }
 
-void QSGTextInput::paint(QPainter *p)
+QSGNode *QSGTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
 {
-    // XXX todo
-    QRect r = boundingRect().toRect();
-
+    Q_UNUSED(data);
     Q_D(QSGTextInput);
-    p->setRenderHint(QPainter::TextAntialiasing, true);
-    p->save();
-    p->setPen(QPen(d->color));
-    int flags = QLineControl::DrawText;
-    if(!isReadOnly() && d->cursorVisible && !d->cursorItem)
-        flags |= QLineControl::DrawCursor;
-    if (d->control->hasSelectedText())
-            flags |= QLineControl::DrawSelections;
-    QFontMetrics fm = QFontMetrics(d->font);
-    // the y offset is there to keep the baseline constant in case we have script changes in the text.
-    QPoint offset(-d->hscroll, fm.ascent() - d->control->ascent());
-    d->control->draw(p, offset, r, flags);
-    p->restore();
+
+    QSGTextNode *node = static_cast<QSGTextNode *>(oldNode);
+    if (node == 0)
+        node = new QSGTextNode(QSGItemPrivate::get(this)->sceneGraphContext());
+    d->textNode = node;
+
+    if (!d->textLayoutDirty) {
+        QSGSimpleRectNode *cursorNode = node->cursorNode();
+        if (cursorNode != 0 && !isReadOnly()) {
+            QFontMetrics fm = QFontMetrics(d->font);
+            // the y offset is there to keep the baseline constant in case we have script changes in the text.
+            QPoint offset(-d->hscroll, fm.ascent() - d->control->ascent());
+            offset.rx() += d->control->cursorToX();
+
+            QRect br(boundingRect().toRect());
+            cursorNode->setRect(QRectF(offset, QSizeF(d->control->cursorWidth(), br.height())));
+
+            if (!d->cursorVisible
+                    || (!d->control->cursorBlinkStatus() && d->control->cursorBlinkPeriod() > 0)) {
+                d->hideCursor();
+            } else {
+                d->showCursor();
+            }
+        }
+    } else {
+        node->deleteContent();
+        node->setMatrix(QMatrix4x4());
+
+        QPoint offset = QPoint(0,0);
+        QFontMetrics fm = QFontMetrics(d->font);
+        QRect br(boundingRect().toRect());
+        if (d->autoScroll) {
+            // the y offset is there to keep the baseline constant in case we have script changes in the text.
+            offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent());
+        } else {
+            offset = QPoint(d->hscroll, 0);
+        }
+
+        QTextLayout *textLayout = d->control->textLayout();
+        if (!textLayout->text().isEmpty()) {
+            node->addTextLayout(offset, textLayout, d->color,
+                                QSGText::Normal, QColor(),
+                                d->selectionColor, d->selectedTextColor,
+                                d->control->selectionStart(),
+                                d->control->selectionEnd() - 1); // selectionEnd() returns first char after
+                                                                 // selection
+        }
+
+        if (!isReadOnly() && d->cursorItem == 0) {
+            offset.rx() += d->control->cursorToX();
+            node->setCursor(QRectF(offset, QSizeF(d->control->cursorWidth(), br.height())), d->color);
+            if (!d->cursorVisible
+                    || (!d->control->cursorBlinkStatus() && d->control->cursorBlinkPeriod() > 0)) {
+                d->hideCursor();
+            } else {
+                d->showCursor();
+            }
+        }
+
+        d->textLayoutDirty = false;
+    }
+
+    return node;
 }
 
 QVariant QSGTextInput::inputMethodQuery(Qt::InputMethodQuery property) const
@@ -879,18 +1390,34 @@ QVariant QSGTextInput::inputMethodQuery(Qt::InputMethodQuery property) const
     }
 }
 
+/*!
+    \qmlmethod void QtQuick2::TextInput::deselect()
+
+    Removes active text selection.
+*/
 void QSGTextInput::deselect()
 {
     Q_D(QSGTextInput);
     d->control->deselect();
 }
 
+/*!
+    \qmlmethod void QtQuick2::TextInput::selectAll()
+
+    Causes all text to be selected.
+*/
 void QSGTextInput::selectAll()
 {
     Q_D(QSGTextInput);
     d->control->setSelection(0, d->control->text().length());
 }
 
+/*!
+    \qmlmethod void QtQuick2::TextInput::isRightToLeft(int start, int end)
+
+    Returns true if the natural reading direction of the editor text
+    found between positions \a start and \a end is right to left.
+*/
 bool QSGTextInput::isRightToLeft(int start, int end)
 {
     Q_D(QSGTextInput);
@@ -903,6 +1430,11 @@ bool QSGTextInput::isRightToLeft(int start, int end)
 }
 
 #ifndef QT_NO_CLIPBOARD
+/*!
+    \qmlmethod QtQuick2::TextInput::cut()
+
+    Moves the currently selected text to the system clipboard.
+*/
 void QSGTextInput::cut()
 {
     Q_D(QSGTextInput);
@@ -910,12 +1442,22 @@ void QSGTextInput::cut()
     d->control->del();
 }
 
+/*!
+    \qmlmethod QtQuick2::TextInput::copy()
+
+    Copies the currently selected text to the system clipboard.
+*/
 void QSGTextInput::copy()
 {
     Q_D(QSGTextInput);
     d->control->copy();
 }
 
+/*!
+    \qmlmethod QtQuick2::TextInput::paste()
+
+    Replaces the currently selected text by the contents of the system clipboard.
+*/
 void QSGTextInput::paste()
 {
     Q_D(QSGTextInput);
@@ -924,12 +1466,41 @@ void QSGTextInput::paste()
 }
 #endif // QT_NO_CLIPBOARD
 
+/*!
+    \qmlmethod void QtQuick2::TextInput::selectWord()
+
+    Causes the word closest to the current cursor position to be selected.
+*/
 void QSGTextInput::selectWord()
 {
     Q_D(QSGTextInput);
     d->control->selectWordAtPos(d->control->cursor());
 }
 
+/*!
+    \qmlproperty bool QtQuick2::TextInput::smooth
+
+    This property holds whether the text is smoothly scaled or transformed.
+
+    Smooth filtering gives better visual quality, but is slower.  If
+    the item is displayed at its natural size, this property has no visual or
+    performance effect.
+
+    \note Generally scaling artifacts are only visible if the item is stationary on
+    the screen.  A common pattern when animating an item is to disable smooth
+    filtering at the beginning of the animation and reenable it at the conclusion.
+*/
+
+/*!
+   \qmlproperty string QtQuick2::TextInput::passwordCharacter
+
+   This is the character displayed when echoMode is set to Password or
+   PasswordEchoOnEdit. By default it is an asterisk.
+
+   If this property is set to a string with more than one character,
+   the first character is used. If the string is empty, the value
+   is ignored and the property is not set.
+*/
 QString QSGTextInput::passwordCharacter() const
 {
     Q_D(const QSGTextInput);
@@ -949,12 +1520,32 @@ void QSGTextInput::setPasswordCharacter(const QString &str)
     emit passwordCharacterChanged();
 }
 
+/*!
+   \qmlproperty string QtQuick2::TextInput::displayText
+
+   This is the text displayed in the TextInput.
+
+   If \l echoMode is set to TextInput::Normal, this holds the
+   same value as the TextInput::text property. Otherwise,
+   this property holds the text visible to the user, while
+   the \l text property holds the actual entered text.
+*/
 QString QSGTextInput::displayText() const
 {
     Q_D(const QSGTextInput);
     return d->control->displayText();
 }
 
+/*!
+    \qmlproperty bool QtQuick2::TextInput::selectByMouse
+
+    Defaults to false.
+
+    If true, the user can use the mouse to select text in some
+    platform-specific way. Note that for some platforms this may
+    not be an appropriate interaction (eg. may conflict with how
+    the text needs to behave inside a Flickable.
+*/
 bool QSGTextInput::selectByMouse() const
 {
     Q_D(const QSGTextInput);
@@ -970,6 +1561,19 @@ void QSGTextInput::setSelectByMouse(bool on)
     }
 }
 
+/*!
+    \qmlproperty enum QtQuick2::TextInput::mouseSelectionMode
+
+    Specifies how text should be selected using a mouse.
+
+    \list
+    \o TextInput.SelectCharacters - The selection is updated with individual characters. (Default)
+    \o TextInput.SelectWords - The selection is updated with whole words.
+    \endlist
+
+    This property only applies when \l selectByMouse is true.
+*/
+
 QSGTextInput::SelectionMode QSGTextInput::mouseSelectionMode() const
 {
     Q_D(const QSGTextInput);
@@ -985,6 +1589,12 @@ void QSGTextInput::setMouseSelectionMode(SelectionMode mode)
     }
 }
 
+/*!
+    \qmlproperty bool QtQuick2::TextInput::canPaste
+
+    Returns true if the TextInput is writable and the content of the clipboard is
+    suitable for pasting into the TextEdit.
+*/
 bool QSGTextInput::canPaste() const
 {
     Q_D(const QSGTextInput);
@@ -997,6 +1607,43 @@ void QSGTextInput::moveCursorSelection(int position)
     d->control->moveCursor(position, true);
 }
 
+/*!
+    \qmlmethod void QtQuick2::TextInput::moveCursorSelection(int position, SelectionMode mode = TextInput.SelectCharacters)
+
+    Moves the cursor to \a position and updates the selection according to the optional \a mode
+    parameter.  (To only move the cursor, set the \l cursorPosition property.)
+
+    When this method is called it additionally sets either the
+    selectionStart or the selectionEnd (whichever was at the previous cursor position)
+    to the specified position. This allows you to easily extend and contract the selected
+    text range.
+
+    The selection mode specifies whether the selection is updated on a per character or a per word
+    basis.  If not specified the selection mode will default to TextInput.SelectCharacters.
+
+    \list
+    \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
+    the previous cursor position) to the specified position.
+    \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all
+    words between the specified postion and the previous cursor position.  Words partially in the
+    range are included.
+    \endlist
+
+    For example, take this sequence of calls:
+
+    \code
+        cursorPosition = 5
+        moveCursorSelection(9, TextInput.SelectCharacters)
+        moveCursorSelection(7, TextInput.SelectCharacters)
+    \endcode
+
+    This moves the cursor to position 5, extend the selection end from 5 to 9
+    and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
+    selected (the 6th and 7th characters).
+
+    The same sequence with TextInput.SelectWords will extend the selection start to a word boundary
+    before or on position 5 and extend the selection end to a word boundary on or past position 9.
+*/
 void QSGTextInput::moveCursorSelection(int pos, SelectionMode mode)
 {
     Q_D(QSGTextInput);
@@ -1054,6 +1701,45 @@ void QSGTextInput::moveCursorSelection(int pos, SelectionMode mode)
     }
 }
 
+/*!
+    \qmlmethod void QtQuick2::TextInput::openSoftwareInputPanel()
+
+    Opens software input panels like virtual keyboards for typing, useful for
+    customizing when you want the input keyboard to be shown and hidden in
+    your application.
+
+    By default the opening of input panels follows the platform style. On Symbian^1 and
+    Symbian^3 -based devices the panels are opened by clicking TextInput. On other platforms
+    the panels are automatically opened when TextInput element gains active focus. Input panels are
+    always closed if no editor has active focus.
+
+  . You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
+    and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
+    the behavior you want.
+
+    Only relevant on platforms, which provide virtual keyboards.
+
+    \qml
+        import QtQuick 1.0
+        TextInput {
+            id: textInput
+            text: "Hello world!"
+            activeFocusOnPress: false
+            MouseArea {
+                anchors.fill: parent
+                onClicked: {
+                    if (!textInput.activeFocus) {
+                        textInput.forceActiveFocus()
+                        textInput.openSoftwareInputPanel();
+                    } else {
+                        textInput.focus = false;
+                    }
+                }
+                onPressAndHold: textInput.closeSoftwareInputPanel();
+            }
+        }
+    \endqml
+*/
 void QSGTextInput::openSoftwareInputPanel()
 {
     if (qApp) {
@@ -1064,6 +1750,45 @@ void QSGTextInput::openSoftwareInputPanel()
     }
 }
 
+/*!
+    \qmlmethod void QtQuick2::TextInput::closeSoftwareInputPanel()
+
+    Closes a software input panel like a virtual keyboard shown on the screen, useful
+    for customizing when you want the input keyboard to be shown and hidden in
+    your application.
+
+    By default the opening of input panels follows the platform style. On Symbian^1 and
+    Symbian^3 -based devices the panels are opened by clicking TextInput. On other platforms
+    the panels are automatically opened when TextInput element gains active focus. Input panels are
+    always closed if no editor has active focus.
+
+  . You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
+    and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
+    the behavior you want.
+
+    Only relevant on platforms, which provide virtual keyboards.
+
+    \qml
+        import QtQuick 1.0
+        TextInput {
+            id: textInput
+            text: "Hello world!"
+            activeFocusOnPress: false
+            MouseArea {
+                anchors.fill: parent
+                onClicked: {
+                    if (!textInput.activeFocus) {
+                        textInput.forceActiveFocus();
+                        textInput.openSoftwareInputPanel();
+                    } else {
+                        textInput.focus = false;
+                    }
+                }
+                onPressAndHold: textInput.closeSoftwareInputPanel();
+            }
+        }
+    \endqml
+*/
 void QSGTextInput::closeSoftwareInputPanel()
 {
     if (qApp) {
@@ -1082,7 +1807,7 @@ void QSGTextInput::focusInEvent(QFocusEvent *event)
             openSoftwareInputPanel();
         }
     }
-    QSGPaintedItem::focusInEvent(event);
+    QSGImplicitSizeItem::focusInEvent(event);
 }
 
 void QSGTextInput::itemChange(ItemChange change, const ItemChangeData &value)
@@ -1100,6 +1825,18 @@ void QSGTextInput::itemChange(ItemChange change, const ItemChangeData &value)
     QSGItem::itemChange(change, value);
 }
 
+/*!
+    \qmlproperty bool QtQuick2::TextInput::inputMethodComposing
+
+
+    This property holds whether the TextInput has partial text input from an
+    input method.
+
+    While it is composing an input method may rely on mouse or key events from
+    the TextInput to edit or commit the partial text.  This property can be
+    used to determine when to disable events handlers that may interfere with
+    the correct operation of an input method.
+*/
 bool QSGTextInput::isInputMethodComposing() const
 {
     Q_D(const QSGTextInput);
@@ -1109,12 +1846,16 @@ bool QSGTextInput::isInputMethodComposing() const
 void QSGTextInputPrivate::init()
 {
     Q_Q(QSGTextInput);
+#if defined(Q_WS_MAC)
+    control->setThreadChecks(true);
+#endif
     control->setParent(q);//Now mandatory due to accessibility changes
     control->setCursorWidth(1);
     control->setPasswordCharacter(QLatin1Char('*'));
     q->setSmooth(smooth);
     q->setAcceptedMouseButtons(Qt::LeftButton);
     q->setFlag(QSGItem::ItemAcceptsInputMethod);
+    q->setFlag(QSGItem::ItemHasContents);
     q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
                q, SLOT(cursorPosChanged()));
     q->connect(control, SIGNAL(selectionChanged()),
@@ -1144,6 +1885,12 @@ void QSGTextInputPrivate::init()
     selectedTextColor = p.color(QPalette::HighlightedText);
     selectionColor = p.color(QPalette::Highlight);
     determineHorizontalAlignment();
+
+    if (!qmlDisableDistanceField()) {
+        QTextOption option = control->textLayout()->textOption();
+        option.setUseDesignMetrics(true);
+        control->textLayout()->setTextOption(option);
+    }
 }
 
 void QSGTextInput::cursorPosChanged()
@@ -1214,19 +1961,35 @@ void QSGTextInput::q_textChanged()
     }
 }
 
+void QSGTextInputPrivate::showCursor()
+{
+    if (textNode != 0 && textNode->cursorNode() != 0)
+        textNode->cursorNode()->setColor(color);
+}
+
+void QSGTextInputPrivate::hideCursor()
+{
+    if (textNode != 0 && textNode->cursorNode() != 0)
+        textNode->cursorNode()->setColor(QColor(0, 0, 0, 0));
+}
+
 void QSGTextInput::updateRect(const QRect &r)
 {
     Q_D(QSGTextInput);
-    if(r == QRect())
-        update();
-    else
-        update(QRect(r.x() - d->hscroll, r.y(), r.width(), r.height()));
+    if (!isComponentComplete())
+        return;
+
+    if (r.isEmpty()) {
+        d->textLayoutDirty = true;
+    }
+
+    update();
 }
 
 QRectF QSGTextInput::boundingRect() const
 {
     Q_D(const QSGTextInput);
-    QRectF r = QSGPaintedItem::boundingRect();
+    QRectF r = QSGImplicitSizeItem::boundingRect();
 
     int cursorWidth = d->cursorItem ? d->cursorItem->width() : d->control->cursorWidth();
 
@@ -1243,7 +2006,6 @@ void QSGTextInput::updateSize(bool needsRedraw)
     int h = height();
     setImplicitHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
     setImplicitWidth(d->calculateTextWidth());
-    setContentsSize(boundingRect().size().toSize());
     if(w==width() && h==height() && needsRedraw)
         update();
 }