Remove unused code from QQuickLineControl.
[profile/ivi/qtdeclarative.git] / src / quick / items / qquicktextinput.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 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 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qquicktextinput_p.h"
43 #include "qquicktextinput_p_p.h"
44 #include "qquickcanvas.h"
45
46 #include <private/qdeclarativeglobal_p.h>
47
48 #include <QtDeclarative/qdeclarativeinfo.h>
49 #include <QtGui/qevent.h>
50 #include <QTextBoundaryFinder>
51 #include "qquicktextnode_p.h"
52 #include <QtQuick/qsgsimplerectnode.h>
53
54 #include <QtGui/qstylehints.h>
55 #include <QtGui/qinputpanel.h>
56
57 QT_BEGIN_NAMESPACE
58
59 DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
60
61 /*!
62     \qmlclass TextInput QQuickTextInput
63     \inqmlmodule QtQuick 2
64     \ingroup qml-basic-visual-elements
65     \brief The TextInput item displays an editable line of text.
66     \inherits Item
67
68     The TextInput element displays a single line of editable plain text.
69
70     TextInput is used to accept a line of text input. Input constraints
71     can be placed on a TextInput item (for example, through a \l validator or \l inputMask),
72     and setting \l echoMode to an appropriate value enables TextInput to be used for
73     a password input field.
74
75     On Mac OS X, the Up/Down key bindings for Home/End are explicitly disabled.
76     If you want such bindings (on any platform), you will need to construct them in QML.
77
78     \sa TextEdit, Text, {declarative/text/textselection}{Text Selection example}
79 */
80 QQuickTextInput::QQuickTextInput(QQuickItem* parent)
81 : QQuickImplicitSizeItem(*(new QQuickTextInputPrivate), parent)
82 {
83     Q_D(QQuickTextInput);
84     d->init();
85 }
86
87 QQuickTextInput::~QQuickTextInput()
88 {
89 }
90
91 /*!
92     \qmlproperty string QtQuick2::TextInput::text
93
94     The text in the TextInput.
95 */
96 QString QQuickTextInput::text() const
97 {
98     Q_D(const QQuickTextInput);
99     return d->control->text();
100 }
101
102 void QQuickTextInput::setText(const QString &s)
103 {
104     Q_D(QQuickTextInput);
105     if (s == text())
106         return;
107     d->control->setText(s);
108 }
109
110 /*!
111     \qmlproperty string QtQuick2::TextInput::font.family
112
113     Sets the family name of the font.
114
115     The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]".
116     If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen.
117     If the family isn't available a family will be set using the font matching algorithm.
118 */
119
120 /*!
121     \qmlproperty bool QtQuick2::TextInput::font.bold
122
123     Sets whether the font weight is bold.
124 */
125
126 /*!
127     \qmlproperty enumeration QtQuick2::TextInput::font.weight
128
129     Sets the font's weight.
130
131     The weight can be one of:
132     \list
133     \o Font.Light
134     \o Font.Normal - the default
135     \o Font.DemiBold
136     \o Font.Bold
137     \o Font.Black
138     \endlist
139
140     \qml
141     TextInput { text: "Hello"; font.weight: Font.DemiBold }
142     \endqml
143 */
144
145 /*!
146     \qmlproperty bool QtQuick2::TextInput::font.italic
147
148     Sets whether the font has an italic style.
149 */
150
151 /*!
152     \qmlproperty bool QtQuick2::TextInput::font.underline
153
154     Sets whether the text is underlined.
155 */
156
157 /*!
158     \qmlproperty bool QtQuick2::TextInput::font.strikeout
159
160     Sets whether the font has a strikeout style.
161 */
162
163 /*!
164     \qmlproperty real QtQuick2::TextInput::font.pointSize
165
166     Sets the font size in points. The point size must be greater than zero.
167 */
168
169 /*!
170     \qmlproperty int QtQuick2::TextInput::font.pixelSize
171
172     Sets the font size in pixels.
173
174     Using this function makes the font device dependent.
175     Use \c pointSize to set the size of the font in a device independent manner.
176 */
177
178 /*!
179     \qmlproperty real QtQuick2::TextInput::font.letterSpacing
180
181     Sets the letter spacing for the font.
182
183     Letter spacing changes the default spacing between individual letters in the font.
184     A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing.
185 */
186
187 /*!
188     \qmlproperty real QtQuick2::TextInput::font.wordSpacing
189
190     Sets the word spacing for the font.
191
192     Word spacing changes the default spacing between individual words.
193     A positive value increases the word spacing by a corresponding amount of pixels,
194     while a negative value decreases the inter-word spacing accordingly.
195 */
196
197 /*!
198     \qmlproperty enumeration QtQuick2::TextInput::font.capitalization
199
200     Sets the capitalization for the text.
201
202     \list
203     \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied.
204     \o Font.AllUppercase - This alters the text to be rendered in all uppercase type.
205     \o Font.AllLowercase - This alters the text to be rendered in all lowercase type.
206     \o Font.SmallCaps - This alters the text to be rendered in small-caps type.
207     \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character.
208     \endlist
209
210     \qml
211     TextInput { text: "Hello"; font.capitalization: Font.AllLowercase }
212     \endqml
213 */
214
215 QFont QQuickTextInput::font() const
216 {
217     Q_D(const QQuickTextInput);
218     return d->sourceFont;
219 }
220
221 void QQuickTextInput::setFont(const QFont &font)
222 {
223     Q_D(QQuickTextInput);
224     if (d->sourceFont == font)
225         return;
226
227     d->sourceFont = font;
228     QFont oldFont = d->font;
229     d->font = font;
230     if (d->font.pointSizeF() != -1) {
231         // 0.5pt resolution
232         qreal size = qRound(d->font.pointSizeF()*2.0);
233         d->font.setPointSizeF(size/2.0);
234     }
235     if (oldFont != d->font) {
236         d->control->setFont(d->font);
237         updateSize();
238         updateCursorRectangle();
239         if (d->cursorItem) {
240             d->cursorItem->setHeight(QFontMetrics(d->font).height());
241         }
242     }
243     emit fontChanged(d->sourceFont);
244 }
245
246 /*!
247     \qmlproperty color QtQuick2::TextInput::color
248
249     The text color.
250 */
251 QColor QQuickTextInput::color() const
252 {
253     Q_D(const QQuickTextInput);
254     return d->color;
255 }
256
257 void QQuickTextInput::setColor(const QColor &c)
258 {
259     Q_D(QQuickTextInput);
260     if (c != d->color) {
261         d->color = c;
262         d->textLayoutDirty = true;
263         update();
264         emit colorChanged(c);
265     }
266 }
267
268
269 /*!
270     \qmlproperty color QtQuick2::TextInput::selectionColor
271
272     The text highlight color, used behind selections.
273 */
274 QColor QQuickTextInput::selectionColor() const
275 {
276     Q_D(const QQuickTextInput);
277     return d->selectionColor;
278 }
279
280 void QQuickTextInput::setSelectionColor(const QColor &color)
281 {
282     Q_D(QQuickTextInput);
283     if (d->selectionColor == color)
284         return;
285
286     d->selectionColor = color;
287     QPalette p = d->control->palette();
288     p.setColor(QPalette::Highlight, d->selectionColor);
289     d->control->setPalette(p);
290     if (d->control->hasSelectedText()) {
291         d->textLayoutDirty = true;
292         update();
293     }
294     emit selectionColorChanged(color);
295 }
296 /*!
297     \qmlproperty color QtQuick2::TextInput::selectedTextColor
298
299     The highlighted text color, used in selections.
300 */
301 QColor QQuickTextInput::selectedTextColor() const
302 {
303     Q_D(const QQuickTextInput);
304     return d->selectedTextColor;
305 }
306
307 void QQuickTextInput::setSelectedTextColor(const QColor &color)
308 {
309     Q_D(QQuickTextInput);
310     if (d->selectedTextColor == color)
311         return;
312
313     d->selectedTextColor = color;
314     QPalette p = d->control->palette();
315     p.setColor(QPalette::HighlightedText, d->selectedTextColor);
316     d->control->setPalette(p);
317     if (d->control->hasSelectedText()) {
318         d->textLayoutDirty = true;
319         update();
320     }
321     emit selectedTextColorChanged(color);
322 }
323
324 /*!
325     \qmlproperty enumeration QtQuick2::TextInput::horizontalAlignment
326     \qmlproperty enumeration QtQuick2::TextInput::effectiveHorizontalAlignment
327
328     Sets the horizontal alignment of the text within the TextInput item's
329     width and height. By default, the text alignment follows the natural alignment
330     of the text, for example text that is read from left to right will be aligned to
331     the left.
332
333     TextInput does not have vertical alignment, as the natural height is
334     exactly the height of the single line of text. If you set the height
335     manually to something larger, TextInput will always be top aligned
336     vertically. You can use anchors to align it however you want within
337     another item.
338
339     The valid values for \c horizontalAlignment are \c TextInput.AlignLeft, \c TextInput.AlignRight and
340     \c TextInput.AlignHCenter.
341
342     When using the attached property LayoutMirroring::enabled to mirror application
343     layouts, the horizontal alignment of text will also be mirrored. However, the property
344     \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
345     of TextInput, use the read-only property \c effectiveHorizontalAlignment.
346 */
347 QQuickTextInput::HAlignment QQuickTextInput::hAlign() const
348 {
349     Q_D(const QQuickTextInput);
350     return d->hAlign;
351 }
352
353 void QQuickTextInput::setHAlign(HAlignment align)
354 {
355     Q_D(QQuickTextInput);
356     bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror;
357     d->hAlignImplicit = false;
358     if (d->setHAlign(align, forceAlign) && isComponentComplete()) {
359         updateCursorRectangle();
360     }
361 }
362
363 void QQuickTextInput::resetHAlign()
364 {
365     Q_D(QQuickTextInput);
366     d->hAlignImplicit = true;
367     if (d->determineHorizontalAlignment() && isComponentComplete()) {
368         updateCursorRectangle();
369     }
370 }
371
372 QQuickTextInput::HAlignment QQuickTextInput::effectiveHAlign() const
373 {
374     Q_D(const QQuickTextInput);
375     QQuickTextInput::HAlignment effectiveAlignment = d->hAlign;
376     if (!d->hAlignImplicit && d->effectiveLayoutMirror) {
377         switch (d->hAlign) {
378         case QQuickTextInput::AlignLeft:
379             effectiveAlignment = QQuickTextInput::AlignRight;
380             break;
381         case QQuickTextInput::AlignRight:
382             effectiveAlignment = QQuickTextInput::AlignLeft;
383             break;
384         default:
385             break;
386         }
387     }
388     return effectiveAlignment;
389 }
390
391 bool QQuickTextInputPrivate::setHAlign(QQuickTextInput::HAlignment alignment, bool forceAlign)
392 {
393     Q_Q(QQuickTextInput);
394     if ((hAlign != alignment || forceAlign) && alignment <= QQuickTextInput::AlignHCenter) { // justify not supported
395         QQuickTextInput::HAlignment oldEffectiveHAlign = q->effectiveHAlign();
396         hAlign = alignment;
397         emit q->horizontalAlignmentChanged(alignment);
398         if (oldEffectiveHAlign != q->effectiveHAlign())
399             emit q->effectiveHorizontalAlignmentChanged();
400         return true;
401     }
402     return false;
403 }
404
405 bool QQuickTextInputPrivate::determineHorizontalAlignment()
406 {
407     if (hAlignImplicit) {
408         // if no explicit alignment has been set, follow the natural layout direction of the text
409         QString text = control->text();
410         if (text.isEmpty())
411             text = control->preeditAreaText();
412         bool isRightToLeft = text.isEmpty() ? QGuiApplication::keyboardInputDirection() == Qt::RightToLeft : text.isRightToLeft();
413         return setHAlign(isRightToLeft ? QQuickTextInput::AlignRight : QQuickTextInput::AlignLeft);
414     }
415     return false;
416 }
417
418 void QQuickTextInputPrivate::mirrorChange()
419 {
420     Q_Q(QQuickTextInput);
421     if (q->isComponentComplete()) {
422         if (!hAlignImplicit && (hAlign == QQuickTextInput::AlignRight || hAlign == QQuickTextInput::AlignLeft)) {
423             q->updateCursorRectangle();
424             emit q->effectiveHorizontalAlignmentChanged();
425         }
426     }
427 }
428
429 /*!
430     \qmlproperty bool QtQuick2::TextInput::readOnly
431
432     Sets whether user input can modify the contents of the TextInput.
433
434     If readOnly is set to true, then user input will not affect the text
435     property. Any bindings or attempts to set the text property will still
436     work.
437 */
438 bool QQuickTextInput::isReadOnly() const
439 {
440     Q_D(const QQuickTextInput);
441     return d->control->isReadOnly();
442 }
443
444 void QQuickTextInput::setReadOnly(bool ro)
445 {
446     Q_D(QQuickTextInput);
447     if (d->control->isReadOnly() == ro)
448         return;
449
450     setFlag(QQuickItem::ItemAcceptsInputMethod, !ro);
451     d->control->setReadOnly(ro);
452     if (!ro)
453         d->control->setCursorPosition(d->control->end());
454
455     emit readOnlyChanged(ro);
456 }
457
458 /*!
459     \qmlproperty int QtQuick2::TextInput::maximumLength
460     The maximum permitted length of the text in the TextInput.
461
462     If the text is too long, it is truncated at the limit.
463
464     By default, this property contains a value of 32767.
465 */
466 int QQuickTextInput::maxLength() const
467 {
468     Q_D(const QQuickTextInput);
469     return d->control->maxLength();
470 }
471
472 void QQuickTextInput::setMaxLength(int ml)
473 {
474     Q_D(QQuickTextInput);
475     if (d->control->maxLength() == ml)
476         return;
477
478     d->control->setMaxLength(ml);
479
480     emit maximumLengthChanged(ml);
481 }
482
483 /*!
484     \qmlproperty bool QtQuick2::TextInput::cursorVisible
485     Set to true when the TextInput shows a cursor.
486
487     This property is set and unset when the TextInput gets active focus, so that other
488     properties can be bound to whether the cursor is currently showing. As it
489     gets set and unset automatically, when you set the value yourself you must
490     keep in mind that your value may be overwritten.
491
492     It can be set directly in script, for example if a KeyProxy might
493     forward keys to it and you desire it to look active when this happens
494     (but without actually giving it active focus).
495
496     It should not be set directly on the element, like in the below QML,
497     as the specified value will be overridden an lost on focus changes.
498
499     \code
500     TextInput {
501         text: "Text"
502         cursorVisible: false
503     }
504     \endcode
505
506     In the above snippet the cursor will still become visible when the
507     TextInput gains active focus.
508 */
509 bool QQuickTextInput::isCursorVisible() const
510 {
511     Q_D(const QQuickTextInput);
512     return d->cursorVisible;
513 }
514
515 void QQuickTextInput::setCursorVisible(bool on)
516 {
517     Q_D(QQuickTextInput);
518     if (d->cursorVisible == on)
519         return;
520     d->cursorVisible = on;
521     d->control->setCursorBlinkPeriod(on ? qApp->styleHints()->cursorFlashTime() : 0);
522     QRect r = d->control->cursorRect();
523     if (d->control->inputMask().isEmpty())
524         updateRect(r);
525     else
526         updateRect();
527     emit cursorVisibleChanged(d->cursorVisible);
528 }
529
530 /*!
531     \qmlproperty int QtQuick2::TextInput::cursorPosition
532     The position of the cursor in the TextInput.
533 */
534 int QQuickTextInput::cursorPosition() const
535 {
536     Q_D(const QQuickTextInput);
537     return d->control->cursor();
538 }
539 void QQuickTextInput::setCursorPosition(int cp)
540 {
541     Q_D(QQuickTextInput);
542     if (cp < 0 || cp > d->control->text().length())
543         return;
544     d->control->moveCursor(cp);
545 }
546
547 /*!
548   Returns a Rect which encompasses the cursor, but which may be larger than is
549   required. Ignores custom cursor delegates.
550 */
551 QRect QQuickTextInput::cursorRectangle() const
552 {
553     Q_D(const QQuickTextInput);
554     QRect r = d->control->cursorRect();
555     // Scroll and make consistent with TextEdit
556     // QQuickLineControl inexplicably adds 1 to the height and horizontal padding
557     // for unicode direction markers.
558     r.adjust(5 - d->hscroll, 0, -4 - d->hscroll, -1);
559     return r;
560 }
561 /*!
562     \qmlproperty int QtQuick2::TextInput::selectionStart
563
564     The cursor position before the first character in the current selection.
565
566     This property is read-only. To change the selection, use select(start,end),
567     selectAll(), or selectWord().
568
569     \sa selectionEnd, cursorPosition, selectedText
570 */
571 int QQuickTextInput::selectionStart() const
572 {
573     Q_D(const QQuickTextInput);
574     return d->lastSelectionStart;
575 }
576 /*!
577     \qmlproperty int QtQuick2::TextInput::selectionEnd
578
579     The cursor position after the last character in the current selection.
580
581     This property is read-only. To change the selection, use select(start,end),
582     selectAll(), or selectWord().
583
584     \sa selectionStart, cursorPosition, selectedText
585 */
586 int QQuickTextInput::selectionEnd() const
587 {
588     Q_D(const QQuickTextInput);
589     return d->lastSelectionEnd;
590 }
591 /*!
592     \qmlmethod void QtQuick2::TextInput::select(int start, int end)
593
594     Causes the text from \a start to \a end to be selected.
595
596     If either start or end is out of range, the selection is not changed.
597
598     After calling this, selectionStart will become the lesser
599     and selectionEnd will become the greater (regardless of the order passed
600     to this method).
601
602     \sa selectionStart, selectionEnd
603 */
604 void QQuickTextInput::select(int start, int end)
605 {
606     Q_D(QQuickTextInput);
607     if (start < 0 || end < 0 || start > d->control->text().length() || end > d->control->text().length())
608         return;
609     d->control->setSelection(start, end-start);
610 }
611
612 /*!
613     \qmlproperty string QtQuick2::TextInput::selectedText
614
615     This read-only property provides the text currently selected in the
616     text input.
617
618     It is equivalent to the following snippet, but is faster and easier
619     to use.
620
621     \js
622     myTextInput.text.toString().substring(myTextInput.selectionStart,
623         myTextInput.selectionEnd);
624     \endjs
625 */
626 QString QQuickTextInput::selectedText() const
627 {
628     Q_D(const QQuickTextInput);
629     return d->control->selectedText();
630 }
631
632 /*!
633     \qmlproperty bool QtQuick2::TextInput::activeFocusOnPress
634
635     Whether the TextInput should gain active focus on a mouse press. By default this is
636     set to true.
637 */
638 bool QQuickTextInput::focusOnPress() const
639 {
640     Q_D(const QQuickTextInput);
641     return d->focusOnPress;
642 }
643
644 void QQuickTextInput::setFocusOnPress(bool b)
645 {
646     Q_D(QQuickTextInput);
647     if (d->focusOnPress == b)
648         return;
649
650     d->focusOnPress = b;
651
652     emit activeFocusOnPressChanged(d->focusOnPress);
653 }
654 /*!
655     \qmlproperty bool QtQuick2::TextInput::autoScroll
656
657     Whether the TextInput should scroll when the text is longer than the width. By default this is
658     set to true.
659 */
660 bool QQuickTextInput::autoScroll() const
661 {
662     Q_D(const QQuickTextInput);
663     return d->autoScroll;
664 }
665
666 void QQuickTextInput::setAutoScroll(bool b)
667 {
668     Q_D(QQuickTextInput);
669     if (d->autoScroll == b)
670         return;
671
672     d->autoScroll = b;
673     //We need to repaint so that the scrolling is taking into account.
674     updateSize(true);
675     updateCursorRectangle();
676     emit autoScrollChanged(d->autoScroll);
677 }
678
679 #ifndef QT_NO_VALIDATOR
680
681 /*!
682     \qmlclass IntValidator QIntValidator
683     \inqmlmodule QtQuick 2
684     \ingroup qml-basic-visual-elements
685
686     This element provides a validator for integer values.
687
688     IntValidator uses the \l {QLocale::setDefault()}{default locale} to interpret the number and
689     will accept locale specific digits, group separators, and positive and negative signs.  In
690     addition, IntValidator is always guaranteed to accept a number formatted according to the "C"
691     locale.
692 */
693 /*!
694     \qmlproperty int QtQuick2::IntValidator::top
695
696     This property holds the validator's highest acceptable value.
697     By default, this property's value is derived from the highest signed integer available (typically 2147483647).
698 */
699 /*!
700     \qmlproperty int QtQuick2::IntValidator::bottom
701
702     This property holds the validator's lowest acceptable value.
703     By default, this property's value is derived from the lowest signed integer available (typically -2147483647).
704 */
705
706 /*!
707     \qmlclass DoubleValidator QDoubleValidator
708     \inqmlmodule QtQuick 2
709     \ingroup qml-basic-visual-elements
710
711     This element provides a validator for non-integer numbers.
712 */
713
714 /*!
715     \qmlproperty real QtQuick2::DoubleValidator::top
716
717     This property holds the validator's maximum acceptable value.
718     By default, this property contains a value of infinity.
719 */
720 /*!
721     \qmlproperty real QtQuick2::DoubleValidator::bottom
722
723     This property holds the validator's minimum acceptable value.
724     By default, this property contains a value of -infinity.
725 */
726 /*!
727     \qmlproperty int QtQuick2::DoubleValidator::decimals
728
729     This property holds the validator's maximum number of digits after the decimal point.
730     By default, this property contains a value of 1000.
731 */
732 /*!
733     \qmlproperty enumeration QtQuick2::DoubleValidator::notation
734     This property holds the notation of how a string can describe a number.
735
736     The possible values for this property are:
737
738     \list
739     \o DoubleValidator.StandardNotation
740     \o DoubleValidator.ScientificNotation (default)
741     \endlist
742
743     If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part (e.g. 1.5E-2).
744 */
745
746 /*!
747     \qmlclass RegExpValidator QRegExpValidator
748     \inqmlmodule QtQuick 2
749     \ingroup qml-basic-visual-elements
750
751     This element provides a validator, which counts as valid any string which
752     matches a specified regular expression.
753 */
754 /*!
755    \qmlproperty regExp QtQuick2::RegExpValidator::regExp
756
757    This property holds the regular expression used for validation.
758
759    Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular expression
760    matching "a".
761
762    By default, this property contains a regular expression with the pattern .* that matches any string.
763 */
764
765 /*!
766     \qmlproperty Validator QtQuick2::TextInput::validator
767
768     Allows you to set a validator on the TextInput. When a validator is set
769     the TextInput will only accept input which leaves the text property in
770     an acceptable or intermediate state. The accepted signal will only be sent
771     if the text is in an acceptable state when enter is pressed.
772
773     Currently supported validators are IntValidator, DoubleValidator and
774     RegExpValidator. An example of using validators is shown below, which allows
775     input of integers between 11 and 31 into the text input:
776
777     \code
778     import QtQuick 1.0
779     TextInput{
780         validator: IntValidator{bottom: 11; top: 31;}
781         focus: true
782     }
783     \endcode
784
785     \sa acceptableInput, inputMask
786 */
787
788 QValidator* QQuickTextInput::validator() const
789 {
790     Q_D(const QQuickTextInput);
791     //###const cast isn't good, but needed for property system?
792     return const_cast<QValidator*>(d->control->validator());
793 }
794
795 void QQuickTextInput::setValidator(QValidator* v)
796 {
797     Q_D(QQuickTextInput);
798     if (d->control->validator() == v)
799         return;
800
801     d->control->setValidator(v);
802     if (!d->control->hasAcceptableInput()) {
803         d->oldValidity = false;
804         emit acceptableInputChanged();
805     }
806
807     emit validatorChanged();
808 }
809 #endif // QT_NO_VALIDATOR
810
811 /*!
812     \qmlproperty string QtQuick2::TextInput::inputMask
813
814     Allows you to set an input mask on the TextInput, restricting the allowable
815     text inputs. See QLineEdit::inputMask for further details, as the exact
816     same mask strings are used by TextInput.
817
818     \sa acceptableInput, validator
819 */
820 QString QQuickTextInput::inputMask() const
821 {
822     Q_D(const QQuickTextInput);
823     return d->control->inputMask();
824 }
825
826 void QQuickTextInput::setInputMask(const QString &im)
827 {
828     Q_D(QQuickTextInput);
829     if (d->control->inputMask() == im)
830         return;
831
832     d->control->setInputMask(im);
833     emit inputMaskChanged(d->control->inputMask());
834 }
835
836 /*!
837     \qmlproperty bool QtQuick2::TextInput::acceptableInput
838
839     This property is always true unless a validator or input mask has been set.
840     If a validator or input mask has been set, this property will only be true
841     if the current text is acceptable to the validator or input mask as a final
842     string (not as an intermediate string).
843 */
844 bool QQuickTextInput::hasAcceptableInput() const
845 {
846     Q_D(const QQuickTextInput);
847     return d->control->hasAcceptableInput();
848 }
849
850 /*!
851     \qmlsignal QtQuick2::TextInput::onAccepted()
852
853     This handler is called when the Return or Enter key is pressed.
854     Note that if there is a \l validator or \l inputMask set on the text
855     input, the handler will only be emitted if the input is in an acceptable
856     state.
857 */
858
859 void QQuickTextInputPrivate::updateInputMethodHints()
860 {
861     Q_Q(QQuickTextInput);
862     Qt::InputMethodHints hints = inputMethodHints;
863     uint echo = control->echoMode();
864     if (echo == QQuickTextInput::Password || echo == QQuickTextInput::NoEcho)
865         hints |= Qt::ImhHiddenText;
866     else if (echo == QQuickTextInput::PasswordEchoOnEdit)
867         hints &= ~Qt::ImhHiddenText;
868     if (echo != QQuickTextInput::Normal)
869         hints |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
870     q->setInputMethodHints(hints);
871 }
872 /*!
873     \qmlproperty enumeration QtQuick2::TextInput::echoMode
874
875     Specifies how the text should be displayed in the TextInput.
876     \list
877     \o TextInput.Normal - Displays the text as it is. (Default)
878     \o TextInput.Password - Displays asterisks instead of characters.
879     \o TextInput.NoEcho - Displays nothing.
880     \o TextInput.PasswordEchoOnEdit - Displays characters as they are entered
881     while editing, otherwise displays asterisks.
882     \endlist
883 */
884 QQuickTextInput::EchoMode QQuickTextInput::echoMode() const
885 {
886     Q_D(const QQuickTextInput);
887     return (QQuickTextInput::EchoMode)d->control->echoMode();
888 }
889
890 void QQuickTextInput::setEchoMode(QQuickTextInput::EchoMode echo)
891 {
892     Q_D(QQuickTextInput);
893     if (echoMode() == echo)
894         return;
895     d->control->setEchoMode((QQuickLineControl::EchoMode)echo);
896     d->updateInputMethodHints();
897     q_textChanged();
898     emit echoModeChanged(echoMode());
899 }
900
901 Qt::InputMethodHints QQuickTextInput::imHints() const
902 {
903     Q_D(const QQuickTextInput);
904     return d->inputMethodHints;
905 }
906
907 void QQuickTextInput::setIMHints(Qt::InputMethodHints hints)
908 {
909     Q_D(QQuickTextInput);
910     if (d->inputMethodHints == hints)
911         return;
912     d->inputMethodHints = hints;
913     d->updateInputMethodHints();
914 }
915
916 /*!
917     \qmlproperty Component QtQuick2::TextInput::cursorDelegate
918     The delegate for the cursor in the TextInput.
919
920     If you set a cursorDelegate for a TextInput, this delegate will be used for
921     drawing the cursor instead of the standard cursor. An instance of the
922     delegate will be created and managed by the TextInput when a cursor is
923     needed, and the x property of delegate instance will be set so as
924     to be one pixel before the top left of the current character.
925
926     Note that the root item of the delegate component must be a QDeclarativeItem or
927     QDeclarativeItem derived item.
928 */
929 QDeclarativeComponent* QQuickTextInput::cursorDelegate() const
930 {
931     Q_D(const QQuickTextInput);
932     return d->cursorComponent;
933 }
934
935 void QQuickTextInput::setCursorDelegate(QDeclarativeComponent* c)
936 {
937     Q_D(QQuickTextInput);
938     if (d->cursorComponent == c)
939         return;
940
941     d->cursorComponent = c;
942     if (!c) {
943         //note that the components are owned by something else
944         delete d->cursorItem;
945     } else {
946         d->startCreatingCursor();
947     }
948
949     emit cursorDelegateChanged();
950 }
951
952 void QQuickTextInputPrivate::startCreatingCursor()
953 {
954     Q_Q(QQuickTextInput);
955     if (cursorComponent->isReady()) {
956         q->createCursor();
957     } else if (cursorComponent->isLoading()) {
958         q->connect(cursorComponent, SIGNAL(statusChanged(int)),
959                 q, SLOT(createCursor()));
960     } else { // isError
961         qmlInfo(q, cursorComponent->errors()) << QQuickTextInput::tr("Could not load cursor delegate");
962     }
963 }
964
965 void QQuickTextInput::createCursor()
966 {
967     Q_D(QQuickTextInput);
968     if (d->cursorComponent->isError()) {
969         qmlInfo(this, d->cursorComponent->errors()) << tr("Could not load cursor delegate");
970         return;
971     }
972
973     if (!d->cursorComponent->isReady())
974         return;
975
976     if (d->cursorItem)
977         delete d->cursorItem;
978     QDeclarativeContext *creationContext = d->cursorComponent->creationContext();
979     QObject *object = d->cursorComponent->create(creationContext ? creationContext : qmlContext(this));
980     d->cursorItem = qobject_cast<QQuickItem*>(object);
981     if (!d->cursorItem) {
982         delete object;
983         qmlInfo(this, d->cursorComponent->errors()) << tr("Could not instantiate cursor delegate");
984         return;
985     }
986
987     QDeclarative_setParent_noEvent(d->cursorItem, this);
988     d->cursorItem->setParentItem(this);
989     d->cursorItem->setX(d->control->cursorToX());
990     d->cursorItem->setHeight(d->control->height()-1); // -1 to counter QQuickLineControl's +1 which is not consistent with Text.
991 }
992
993 /*!
994     \qmlmethod rect QtQuick2::TextInput::positionToRectangle(int pos)
995
996     This function takes a character position and returns the rectangle that the
997     cursor would occupy, if it was placed at that character position.
998
999     This is similar to setting the cursorPosition, and then querying the cursor
1000     rectangle, but the cursorPosition is not changed.
1001 */
1002 QRectF QQuickTextInput::positionToRectangle(int pos) const
1003 {
1004     Q_D(const QQuickTextInput);
1005     if (pos > d->control->cursorPosition())
1006         pos += d->control->preeditAreaText().length();
1007     return QRectF(d->control->cursorToX(pos)-d->hscroll,
1008         0.0,
1009         d->control->cursorWidth(),
1010         cursorRectangle().height());
1011 }
1012
1013 /*!
1014     \qmlmethod int QtQuick2::TextInput::positionAt(int x, CursorPosition position = CursorBetweenCharacters)
1015
1016     This function returns the character position at
1017     x pixels from the left of the textInput. Position 0 is before the
1018     first character, position 1 is after the first character but before the second,
1019     and so on until position text.length, which is after all characters.
1020
1021     This means that for all x values before the first character this function returns 0,
1022     and for all x values after the last character this function returns text.length.
1023
1024     The cursor position type specifies how the cursor position should be resolved.
1025
1026     \list
1027     \o TextInput.CursorBetweenCharacters - Returns the position between characters that is nearest x.
1028     \o TextInput.CursorOnCharacter - Returns the position before the character that is nearest x.
1029     \endlist
1030 */
1031 int QQuickTextInput::positionAt(int x) const
1032 {
1033     return positionAt(x, CursorBetweenCharacters);
1034 }
1035
1036 int QQuickTextInput::positionAt(int x, CursorPosition position) const
1037 {
1038     Q_D(const QQuickTextInput);
1039     int pos = d->control->xToPos(x + d->hscroll, QTextLine::CursorPosition(position));
1040     const int cursor = d->control->cursor();
1041     if (pos > cursor) {
1042         const int preeditLength = d->control->preeditAreaText().length();
1043         pos = pos > cursor + preeditLength
1044                 ? pos - preeditLength
1045                 : cursor;
1046     }
1047     return pos;
1048 }
1049
1050 void QQuickTextInput::keyPressEvent(QKeyEvent* ev)
1051 {
1052     Q_D(QQuickTextInput);
1053     // Don't allow MacOSX up/down support, and we don't allow a completer.
1054     bool ignore = (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) && ev->modifiers() == Qt::NoModifier;
1055     if (!ignore && (d->lastSelectionStart == d->lastSelectionEnd) && (ev->key() == Qt::Key_Right || ev->key() == Qt::Key_Left)) {
1056         // Ignore when moving off the end unless there is a selection,
1057         // because then moving will do something (deselect).
1058         int cursorPosition = d->control->cursor();
1059         if (cursorPosition == 0)
1060             ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Left : Qt::Key_Right);
1061         if (cursorPosition == d->control->text().length())
1062             ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Right : Qt::Key_Left);
1063     }
1064     if (ignore) {
1065         ev->ignore();
1066     } else {
1067         d->control->processKeyEvent(ev);
1068     }
1069     if (!ev->isAccepted())
1070         QQuickImplicitSizeItem::keyPressEvent(ev);
1071 }
1072
1073 void QQuickTextInput::inputMethodEvent(QInputMethodEvent *ev)
1074 {
1075     Q_D(QQuickTextInput);
1076     const bool wasComposing = d->control->preeditAreaText().length() > 0;
1077     if (d->control->isReadOnly()) {
1078         ev->ignore();
1079     } else {
1080         d->control->processInputMethodEvent(ev);
1081     }
1082     if (!ev->isAccepted())
1083         QQuickImplicitSizeItem::inputMethodEvent(ev);
1084
1085     if (wasComposing != (d->control->preeditAreaText().length() > 0))
1086         emit inputMethodComposingChanged();
1087 }
1088
1089 void QQuickTextInput::mouseDoubleClickEvent(QMouseEvent *event)
1090 {
1091     Q_D(QQuickTextInput);
1092
1093     if (d->selectByMouse && event->button() == Qt::LeftButton) {
1094         d->control->commitPreedit();
1095         int cursor = d->xToPos(event->localPos().x());
1096         d->control->selectWordAtPos(cursor);
1097         event->setAccepted(true);
1098         if (!d->hasPendingTripleClick()) {
1099             d->tripleClickStartPoint = event->localPos().toPoint();
1100             d->tripleClickTimer.start();
1101         }
1102     } else {
1103         if (d->sendMouseEventToInputContext(event))
1104             return;
1105         QQuickImplicitSizeItem::mouseDoubleClickEvent(event);
1106     }
1107 }
1108
1109 void QQuickTextInput::mousePressEvent(QMouseEvent *event)
1110 {
1111     Q_D(QQuickTextInput);
1112
1113     d->pressPos = event->localPos();
1114
1115     if (d->focusOnPress) {
1116         bool hadActiveFocus = hasActiveFocus();
1117         forceActiveFocus();
1118         // re-open input panel on press if already focused
1119         if (hasActiveFocus() && hadActiveFocus && !isReadOnly())
1120             openSoftwareInputPanel();
1121     }
1122     if (d->selectByMouse) {
1123         setKeepMouseGrab(false);
1124         d->selectPressed = true;
1125         QPoint distanceVector = d->pressPos.toPoint() - d->tripleClickStartPoint;
1126         if (d->hasPendingTripleClick()
1127             && distanceVector.manhattanLength() < qApp->styleHints()->startDragDistance()) {
1128             event->setAccepted(true);
1129             selectAll();
1130             return;
1131         }
1132     }
1133
1134     if (d->sendMouseEventToInputContext(event))
1135         return;
1136
1137     bool mark = (event->modifiers() & Qt::ShiftModifier) && d->selectByMouse;
1138     int cursor = d->xToPos(event->localPos().x());
1139     d->control->moveCursor(cursor, mark);
1140     event->setAccepted(true);
1141 }
1142
1143 void QQuickTextInput::mouseMoveEvent(QMouseEvent *event)
1144 {
1145     Q_D(QQuickTextInput);
1146
1147     if (d->selectPressed) {
1148         if (qAbs(int(event->localPos().x() - d->pressPos.x())) > qApp->styleHints()->startDragDistance())
1149             setKeepMouseGrab(true);
1150
1151         if (d->control->composeMode()) {
1152             // start selection
1153             int startPos = d->xToPos(d->pressPos.x());
1154             int currentPos = d->xToPos(event->localPos().x());
1155             if (startPos != currentPos)
1156                 d->control->setSelection(startPos, currentPos - startPos);
1157         } else {
1158             moveCursorSelection(d->xToPos(event->localPos().x()), d->mouseSelectionMode);
1159         }
1160         event->setAccepted(true);
1161     } else {
1162         QQuickImplicitSizeItem::mouseMoveEvent(event);
1163     }
1164 }
1165
1166 void QQuickTextInput::mouseReleaseEvent(QMouseEvent *event)
1167 {
1168     Q_D(QQuickTextInput);
1169     if (d->sendMouseEventToInputContext(event))
1170         return;
1171     if (d->selectPressed) {
1172         d->selectPressed = false;
1173         setKeepMouseGrab(false);
1174     }
1175 #ifndef QT_NO_CLIPBOARD
1176     if (QGuiApplication::clipboard()->supportsSelection()) {
1177         if (event->button() == Qt::LeftButton) {
1178             d->control->copy(QClipboard::Selection);
1179         } else if (!isReadOnly() && event->button() == Qt::MidButton) {
1180             d->control->deselect();
1181             d->control->insert(QGuiApplication::clipboard()->text(QClipboard::Selection));
1182         }
1183     }
1184 #endif
1185     if (!event->isAccepted())
1186         QQuickImplicitSizeItem::mouseReleaseEvent(event);
1187 }
1188
1189 bool QQuickTextInputPrivate::sendMouseEventToInputContext(QMouseEvent *event)
1190 {
1191 #if !defined QT_NO_IM
1192     if (control->composeMode()) {
1193         int tmp_cursor = xToPos(event->localPos().x());
1194         int mousePos = tmp_cursor - control->cursor();
1195         if (mousePos >= 0 && mousePos <= control->preeditAreaText().length()) {
1196             if (event->type() == QEvent::MouseButtonRelease) {
1197                 qApp->inputPanel()->invokeAction(QInputPanel::Click, mousePos);
1198             }
1199             return true;
1200         }
1201     }
1202 #else
1203     Q_UNUSED(event);
1204     Q_UNUSED(eventType)
1205 #endif
1206
1207     return false;
1208 }
1209
1210 void QQuickTextInput::mouseUngrabEvent()
1211 {
1212     Q_D(QQuickTextInput);
1213     d->selectPressed = false;
1214     setKeepMouseGrab(false);
1215 }
1216
1217 bool QQuickTextInput::event(QEvent* ev)
1218 {
1219 #ifndef QT_NO_SHORTCUT
1220     if (ev->type() == QEvent::ShortcutOverride) {
1221         if (isReadOnly())
1222             return false;
1223         QKeyEvent* ke = static_cast<QKeyEvent*>(ev);
1224         if (ke == QKeySequence::Copy
1225             || ke == QKeySequence::Paste
1226             || ke == QKeySequence::Cut
1227             || ke == QKeySequence::Redo
1228             || ke == QKeySequence::Undo
1229             || ke == QKeySequence::MoveToNextWord
1230             || ke == QKeySequence::MoveToPreviousWord
1231             || ke == QKeySequence::MoveToStartOfDocument
1232             || ke == QKeySequence::MoveToEndOfDocument
1233             || ke == QKeySequence::SelectNextWord
1234             || ke == QKeySequence::SelectPreviousWord
1235             || ke == QKeySequence::SelectStartOfLine
1236             || ke == QKeySequence::SelectEndOfLine
1237             || ke == QKeySequence::SelectStartOfBlock
1238             || ke == QKeySequence::SelectEndOfBlock
1239             || ke == QKeySequence::SelectStartOfDocument
1240             || ke == QKeySequence::SelectAll
1241             || ke == QKeySequence::SelectEndOfDocument) {
1242             ke->accept();
1243         } else if (ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier
1244                    || ke->modifiers() == Qt::KeypadModifier) {
1245             if (ke->key() < Qt::Key_Escape) {
1246                 ke->accept();
1247                 return true;
1248             } else {
1249                 switch (ke->key()) {
1250                 case Qt::Key_Delete:
1251                 case Qt::Key_Home:
1252                 case Qt::Key_End:
1253                 case Qt::Key_Backspace:
1254                 case Qt::Key_Left:
1255                 case Qt::Key_Right:
1256                     return true;
1257                 default:
1258                     break;
1259                 }
1260             }
1261         }
1262     }
1263 #endif
1264
1265     return QQuickImplicitSizeItem::event(ev);
1266 }
1267
1268 void QQuickTextInput::geometryChanged(const QRectF &newGeometry,
1269                                   const QRectF &oldGeometry)
1270 {
1271     if (newGeometry.width() != oldGeometry.width()) {
1272         updateSize();
1273         updateCursorRectangle();
1274     }
1275     QQuickImplicitSizeItem::geometryChanged(newGeometry, oldGeometry);
1276 }
1277
1278 int QQuickTextInputPrivate::calculateTextWidth()
1279 {
1280     return qRound(control->naturalTextWidth());
1281 }
1282
1283 void QQuickTextInputPrivate::updateHorizontalScroll()
1284 {
1285     Q_Q(QQuickTextInput);
1286     const int preeditLength = control->preeditAreaText().length();
1287     const int width = q->width();
1288     int widthUsed = calculateTextWidth();
1289
1290     if (!autoScroll || widthUsed <=  width) {
1291         QQuickTextInput::HAlignment effectiveHAlign = q->effectiveHAlign();
1292         // text fits in br; use hscroll for alignment
1293         switch (effectiveHAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) {
1294         case Qt::AlignRight:
1295             hscroll = widthUsed - width;
1296             break;
1297         case Qt::AlignHCenter:
1298             hscroll = (widthUsed - width) / 2;
1299             break;
1300         default:
1301             // Left
1302             hscroll = 0;
1303             break;
1304         }
1305     } else {
1306         int cix = qRound(control->cursorToX(control->cursor() + preeditLength));
1307         if (cix - hscroll >= width) {
1308             // text doesn't fit, cursor is to the right of br (scroll right)
1309             hscroll = cix - width;
1310         } else if (cix - hscroll < 0 && hscroll < widthUsed) {
1311             // text doesn't fit, cursor is to the left of br (scroll left)
1312             hscroll = cix;
1313         } else if (widthUsed - hscroll < width) {
1314             // text doesn't fit, text document is to the left of br; align
1315             // right
1316             hscroll = widthUsed - width;
1317         }
1318         if (preeditLength > 0) {
1319             // check to ensure long pre-edit text doesn't push the cursor
1320             // off to the left
1321              cix = qRound(control->cursorToX(
1322                      control->cursor() + qMax(0, control->preeditCursor() - 1)));
1323              if (cix < hscroll)
1324                  hscroll = cix;
1325         }
1326     }
1327 }
1328
1329 QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
1330 {
1331     Q_UNUSED(data);
1332     Q_D(QQuickTextInput);
1333
1334     QQuickTextNode *node = static_cast<QQuickTextNode *>(oldNode);
1335     if (node == 0)
1336         node = new QQuickTextNode(QQuickItemPrivate::get(this)->sceneGraphContext());
1337     d->textNode = node;
1338
1339     if (!d->textLayoutDirty) {
1340         QSGSimpleRectNode *cursorNode = node->cursorNode();
1341         if (cursorNode != 0 && !isReadOnly()) {
1342             cursorNode->setRect(cursorRectangle());
1343
1344             if (!d->cursorVisible
1345                     || (!d->control->cursorBlinkStatus() && d->control->cursorBlinkPeriod() > 0)) {
1346                 d->hideCursor();
1347             } else {
1348                 d->showCursor();
1349             }
1350         }
1351     } else {
1352         node->deleteContent();
1353         node->setMatrix(QMatrix4x4());
1354
1355         QPoint offset = QPoint(0,0);
1356         QFontMetrics fm = QFontMetrics(d->font);
1357         QRect br(boundingRect().toRect());
1358         if (d->autoScroll) {
1359             // the y offset is there to keep the baseline constant in case we have script changes in the text.
1360             offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent());
1361         } else {
1362             offset = QPoint(d->hscroll, 0);
1363         }
1364
1365         QTextLayout *textLayout = d->control->textLayout();
1366         if (!textLayout->text().isEmpty()) {
1367             node->addTextLayout(offset, textLayout, d->color,
1368                                 QQuickText::Normal, QColor(),
1369                                 d->selectionColor, d->selectedTextColor,
1370                                 d->control->selectionStart(),
1371                                 d->control->selectionEnd() - 1); // selectionEnd() returns first char after
1372                                                                  // selection
1373         }
1374
1375         if (!isReadOnly() && d->cursorItem == 0) {
1376             node->setCursor(cursorRectangle(), d->color);
1377             if (!d->cursorVisible
1378                     || (!d->control->cursorBlinkStatus() && d->control->cursorBlinkPeriod() > 0)) {
1379                 d->hideCursor();
1380             } else {
1381                 d->showCursor();
1382             }
1383         }
1384
1385         d->textLayoutDirty = false;
1386     }
1387
1388     return node;
1389 }
1390
1391 QVariant QQuickTextInput::inputMethodQuery(Qt::InputMethodQuery property) const
1392 {
1393     Q_D(const QQuickTextInput);
1394     switch (property) {
1395     case Qt::ImEnabled:
1396         return QVariant((bool)(flags() & ItemAcceptsInputMethod));
1397     case Qt::ImHints:
1398         return QVariant((int)inputMethodHints());
1399     case Qt::ImCursorRectangle:
1400         return cursorRectangle();
1401     case Qt::ImFont:
1402         return font();
1403     case Qt::ImCursorPosition:
1404         return QVariant(d->control->cursor());
1405     case Qt::ImSurroundingText:
1406         if (d->control->echoMode() == QQuickLineControl::PasswordEchoOnEdit
1407             && !d->control->passwordEchoEditing()) {
1408             return QVariant(displayText());
1409         } else {
1410             return QVariant(d->control->realText());
1411         }
1412     case Qt::ImCurrentSelection:
1413         return QVariant(selectedText());
1414     case Qt::ImMaximumTextLength:
1415         return QVariant(maxLength());
1416     case Qt::ImAnchorPosition:
1417         if (d->control->selectionStart() == d->control->selectionEnd())
1418             return QVariant(d->control->cursor());
1419         else if (d->control->selectionStart() == d->control->cursor())
1420             return QVariant(d->control->selectionEnd());
1421         else
1422             return QVariant(d->control->selectionStart());
1423     default:
1424         return QVariant();
1425     }
1426 }
1427
1428 /*!
1429     \qmlmethod void QtQuick2::TextInput::deselect()
1430
1431     Removes active text selection.
1432 */
1433 void QQuickTextInput::deselect()
1434 {
1435     Q_D(QQuickTextInput);
1436     d->control->deselect();
1437 }
1438
1439 /*!
1440     \qmlmethod void QtQuick2::TextInput::selectAll()
1441
1442     Causes all text to be selected.
1443 */
1444 void QQuickTextInput::selectAll()
1445 {
1446     Q_D(QQuickTextInput);
1447     d->control->setSelection(0, d->control->text().length());
1448 }
1449
1450 /*!
1451     \qmlmethod void QtQuick2::TextInput::isRightToLeft(int start, int end)
1452
1453     Returns true if the natural reading direction of the editor text
1454     found between positions \a start and \a end is right to left.
1455 */
1456 bool QQuickTextInput::isRightToLeft(int start, int end)
1457 {
1458     Q_D(QQuickTextInput);
1459     if (start > end) {
1460         qmlInfo(this) << "isRightToLeft(start, end) called with the end property being smaller than the start.";
1461         return false;
1462     } else {
1463         return d->control->text().mid(start, end - start).isRightToLeft();
1464     }
1465 }
1466
1467 #ifndef QT_NO_CLIPBOARD
1468 /*!
1469     \qmlmethod QtQuick2::TextInput::cut()
1470
1471     Moves the currently selected text to the system clipboard.
1472 */
1473 void QQuickTextInput::cut()
1474 {
1475     Q_D(QQuickTextInput);
1476     d->control->copy();
1477     d->control->del();
1478 }
1479
1480 /*!
1481     \qmlmethod QtQuick2::TextInput::copy()
1482
1483     Copies the currently selected text to the system clipboard.
1484 */
1485 void QQuickTextInput::copy()
1486 {
1487     Q_D(QQuickTextInput);
1488     d->control->copy();
1489 }
1490
1491 /*!
1492     \qmlmethod QtQuick2::TextInput::paste()
1493
1494     Replaces the currently selected text by the contents of the system clipboard.
1495 */
1496 void QQuickTextInput::paste()
1497 {
1498     Q_D(QQuickTextInput);
1499     if (!d->control->isReadOnly())
1500         d->control->paste();
1501 }
1502 #endif // QT_NO_CLIPBOARD
1503
1504 /*!
1505     \qmlmethod void QtQuick2::TextInput::selectWord()
1506
1507     Causes the word closest to the current cursor position to be selected.
1508 */
1509 void QQuickTextInput::selectWord()
1510 {
1511     Q_D(QQuickTextInput);
1512     d->control->selectWordAtPos(d->control->cursor());
1513 }
1514
1515 /*!
1516     \qmlproperty bool QtQuick2::TextInput::smooth
1517
1518     This property holds whether the text is smoothly scaled or transformed.
1519
1520     Smooth filtering gives better visual quality, but is slower.  If
1521     the item is displayed at its natural size, this property has no visual or
1522     performance effect.
1523
1524     \note Generally scaling artifacts are only visible if the item is stationary on
1525     the screen.  A common pattern when animating an item is to disable smooth
1526     filtering at the beginning of the animation and reenable it at the conclusion.
1527 */
1528
1529 /*!
1530    \qmlproperty string QtQuick2::TextInput::passwordCharacter
1531
1532    This is the character displayed when echoMode is set to Password or
1533    PasswordEchoOnEdit. By default it is an asterisk.
1534
1535    If this property is set to a string with more than one character,
1536    the first character is used. If the string is empty, the value
1537    is ignored and the property is not set.
1538 */
1539 QString QQuickTextInput::passwordCharacter() const
1540 {
1541     Q_D(const QQuickTextInput);
1542     return QString(d->control->passwordCharacter());
1543 }
1544
1545 void QQuickTextInput::setPasswordCharacter(const QString &str)
1546 {
1547     Q_D(QQuickTextInput);
1548     if (str.length() < 1)
1549         return;
1550     d->control->setPasswordCharacter(str.constData()[0]);
1551     EchoMode echoMode_ = echoMode();
1552     if (echoMode_ == Password || echoMode_ == PasswordEchoOnEdit) {
1553         updateSize();
1554     }
1555     emit passwordCharacterChanged();
1556 }
1557
1558 /*!
1559    \qmlproperty string QtQuick2::TextInput::displayText
1560
1561    This is the text displayed in the TextInput.
1562
1563    If \l echoMode is set to TextInput::Normal, this holds the
1564    same value as the TextInput::text property. Otherwise,
1565    this property holds the text visible to the user, while
1566    the \l text property holds the actual entered text.
1567 */
1568 QString QQuickTextInput::displayText() const
1569 {
1570     Q_D(const QQuickTextInput);
1571     return d->control->displayText();
1572 }
1573
1574 /*!
1575     \qmlproperty bool QtQuick2::TextInput::selectByMouse
1576
1577     Defaults to false.
1578
1579     If true, the user can use the mouse to select text in some
1580     platform-specific way. Note that for some platforms this may
1581     not be an appropriate interaction (eg. may conflict with how
1582     the text needs to behave inside a Flickable.
1583 */
1584 bool QQuickTextInput::selectByMouse() const
1585 {
1586     Q_D(const QQuickTextInput);
1587     return d->selectByMouse;
1588 }
1589
1590 void QQuickTextInput::setSelectByMouse(bool on)
1591 {
1592     Q_D(QQuickTextInput);
1593     if (d->selectByMouse != on) {
1594         d->selectByMouse = on;
1595         emit selectByMouseChanged(on);
1596     }
1597 }
1598
1599 /*!
1600     \qmlproperty enum QtQuick2::TextInput::mouseSelectionMode
1601
1602     Specifies how text should be selected using a mouse.
1603
1604     \list
1605     \o TextInput.SelectCharacters - The selection is updated with individual characters. (Default)
1606     \o TextInput.SelectWords - The selection is updated with whole words.
1607     \endlist
1608
1609     This property only applies when \l selectByMouse is true.
1610 */
1611
1612 QQuickTextInput::SelectionMode QQuickTextInput::mouseSelectionMode() const
1613 {
1614     Q_D(const QQuickTextInput);
1615     return d->mouseSelectionMode;
1616 }
1617
1618 void QQuickTextInput::setMouseSelectionMode(SelectionMode mode)
1619 {
1620     Q_D(QQuickTextInput);
1621     if (d->mouseSelectionMode != mode) {
1622         d->mouseSelectionMode = mode;
1623         emit mouseSelectionModeChanged(mode);
1624     }
1625 }
1626
1627 /*!
1628     \qmlproperty bool QtQuick2::TextInput::canPaste
1629
1630     Returns true if the TextInput is writable and the content of the clipboard is
1631     suitable for pasting into the TextEdit.
1632 */
1633 bool QQuickTextInput::canPaste() const
1634 {
1635     Q_D(const QQuickTextInput);
1636     return d->canPaste;
1637 }
1638
1639 void QQuickTextInput::moveCursorSelection(int position)
1640 {
1641     Q_D(QQuickTextInput);
1642     d->control->moveCursor(position, true);
1643 }
1644
1645 /*!
1646     \qmlmethod void QtQuick2::TextInput::moveCursorSelection(int position, SelectionMode mode = TextInput.SelectCharacters)
1647
1648     Moves the cursor to \a position and updates the selection according to the optional \a mode
1649     parameter.  (To only move the cursor, set the \l cursorPosition property.)
1650
1651     When this method is called it additionally sets either the
1652     selectionStart or the selectionEnd (whichever was at the previous cursor position)
1653     to the specified position. This allows you to easily extend and contract the selected
1654     text range.
1655
1656     The selection mode specifies whether the selection is updated on a per character or a per word
1657     basis.  If not specified the selection mode will default to TextInput.SelectCharacters.
1658
1659     \list
1660     \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
1661     the previous cursor position) to the specified position.
1662     \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all
1663     words between the specified position and the previous cursor position.  Words partially in the
1664     range are included.
1665     \endlist
1666
1667     For example, take this sequence of calls:
1668
1669     \code
1670         cursorPosition = 5
1671         moveCursorSelection(9, TextInput.SelectCharacters)
1672         moveCursorSelection(7, TextInput.SelectCharacters)
1673     \endcode
1674
1675     This moves the cursor to position 5, extend the selection end from 5 to 9
1676     and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
1677     selected (the 6th and 7th characters).
1678
1679     The same sequence with TextInput.SelectWords will extend the selection start to a word boundary
1680     before or on position 5 and extend the selection end to a word boundary on or past position 9.
1681 */
1682 void QQuickTextInput::moveCursorSelection(int pos, SelectionMode mode)
1683 {
1684     Q_D(QQuickTextInput);
1685
1686     if (mode == SelectCharacters) {
1687         d->control->moveCursor(pos, true);
1688     } else if (pos != d->control->cursor()){
1689         const int cursor = d->control->cursor();
1690         int anchor;
1691         if (!d->control->hasSelectedText())
1692             anchor = d->control->cursor();
1693         else if (d->control->selectionStart() == d->control->cursor())
1694             anchor = d->control->selectionEnd();
1695         else
1696             anchor = d->control->selectionStart();
1697
1698         if (anchor < pos || (anchor == pos && cursor < pos)) {
1699             const QString text = d->control->text();
1700             QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
1701             finder.setPosition(anchor);
1702
1703             const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
1704             if (anchor < text.length() && (!(reasons & QTextBoundaryFinder::StartWord)
1705                     || ((reasons & QTextBoundaryFinder::EndWord) && anchor > cursor))) {
1706                 finder.toPreviousBoundary();
1707             }
1708             anchor = finder.position() != -1 ? finder.position() : 0;
1709
1710             finder.setPosition(pos);
1711             if (pos > 0 && !finder.boundaryReasons())
1712                 finder.toNextBoundary();
1713             const int cursor = finder.position() != -1 ? finder.position() : text.length();
1714
1715             d->control->setSelection(anchor, cursor - anchor);
1716         } else if (anchor > pos || (anchor == pos && cursor > pos)) {
1717             const QString text = d->control->text();
1718             QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
1719             finder.setPosition(anchor);
1720
1721             const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
1722             if (anchor > 0 && (!(reasons & QTextBoundaryFinder::EndWord)
1723                     || ((reasons & QTextBoundaryFinder::StartWord) && anchor < cursor))) {
1724                 finder.toNextBoundary();
1725             }
1726
1727             anchor = finder.position() != -1 ? finder.position() : text.length();
1728
1729             finder.setPosition(pos);
1730             if (pos < text.length() && !finder.boundaryReasons())
1731                  finder.toPreviousBoundary();
1732             const int cursor = finder.position() != -1 ? finder.position() : 0;
1733
1734             d->control->setSelection(anchor, cursor - anchor);
1735         }
1736     }
1737 }
1738
1739 /*!
1740     \qmlmethod void QtQuick2::TextInput::openSoftwareInputPanel()
1741
1742     Opens software input panels like virtual keyboards for typing, useful for
1743     customizing when you want the input keyboard to be shown and hidden in
1744     your application.
1745
1746     By default the opening of input panels follows the platform style. Input panels are
1747     always closed if no editor has active focus.
1748
1749     You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1750     and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1751     the behavior you want.
1752
1753     Only relevant on platforms, which provide virtual keyboards.
1754
1755     \qml
1756         import QtQuick 1.0
1757         TextInput {
1758             id: textInput
1759             text: "Hello world!"
1760             activeFocusOnPress: false
1761             MouseArea {
1762                 anchors.fill: parent
1763                 onClicked: {
1764                     if (!textInput.activeFocus) {
1765                         textInput.forceActiveFocus()
1766                         textInput.openSoftwareInputPanel();
1767                     } else {
1768                         textInput.focus = false;
1769                     }
1770                 }
1771                 onPressAndHold: textInput.closeSoftwareInputPanel();
1772             }
1773         }
1774     \endqml
1775 */
1776 void QQuickTextInput::openSoftwareInputPanel()
1777 {
1778     if (qGuiApp)
1779         qGuiApp->inputPanel()->show();
1780 }
1781
1782 /*!
1783     \qmlmethod void QtQuick2::TextInput::closeSoftwareInputPanel()
1784
1785     Closes a software input panel like a virtual keyboard shown on the screen, useful
1786     for customizing when you want the input keyboard to be shown and hidden in
1787     your application.
1788
1789     By default the opening of input panels follows the platform style. Input panels are
1790     always closed if no editor has active focus.
1791
1792     You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1793     and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1794     the behavior you want.
1795
1796     Only relevant on platforms, which provide virtual keyboards.
1797
1798     \qml
1799         import QtQuick 1.0
1800         TextInput {
1801             id: textInput
1802             text: "Hello world!"
1803             activeFocusOnPress: false
1804             MouseArea {
1805                 anchors.fill: parent
1806                 onClicked: {
1807                     if (!textInput.activeFocus) {
1808                         textInput.forceActiveFocus();
1809                         textInput.openSoftwareInputPanel();
1810                     } else {
1811                         textInput.focus = false;
1812                     }
1813                 }
1814                 onPressAndHold: textInput.closeSoftwareInputPanel();
1815             }
1816         }
1817     \endqml
1818 */
1819 void QQuickTextInput::closeSoftwareInputPanel()
1820 {
1821     if (qGuiApp)
1822         qGuiApp->inputPanel()->hide();
1823 }
1824
1825 void QQuickTextInput::focusInEvent(QFocusEvent *event)
1826 {
1827     Q_D(const QQuickTextInput);
1828     if (d->focusOnPress && !isReadOnly())
1829         openSoftwareInputPanel();
1830     QQuickImplicitSizeItem::focusInEvent(event);
1831 }
1832
1833 void QQuickTextInput::itemChange(ItemChange change, const ItemChangeData &value)
1834 {
1835     Q_D(QQuickTextInput);
1836     if (change == ItemActiveFocusHasChanged) {
1837         bool hasFocus = value.boolValue;
1838         d->focused = hasFocus;
1839         setCursorVisible(hasFocus); // ### refactor:  && d->canvas && d->canvas->hasFocus()
1840         if (echoMode() == QQuickTextInput::PasswordEchoOnEdit && !hasFocus)
1841             d->control->updatePasswordEchoEditing(false);//QQuickLineControl sets it on key events, but doesn't deal with focus events
1842         if (!hasFocus)
1843             d->control->deselect();
1844     }
1845     QQuickItem::itemChange(change, value);
1846 }
1847
1848 /*!
1849     \qmlproperty bool QtQuick2::TextInput::inputMethodComposing
1850
1851
1852     This property holds whether the TextInput has partial text input from an
1853     input method.
1854
1855     While it is composing an input method may rely on mouse or key events from
1856     the TextInput to edit or commit the partial text.  This property can be
1857     used to determine when to disable events handlers that may interfere with
1858     the correct operation of an input method.
1859 */
1860 bool QQuickTextInput::isInputMethodComposing() const
1861 {
1862     Q_D(const QQuickTextInput);
1863     return d->control->preeditAreaText().length() > 0;
1864 }
1865
1866 void QQuickTextInputPrivate::init()
1867 {
1868     Q_Q(QQuickTextInput);
1869     control->setParent(q);//Now mandatory due to accessibility changes
1870     control->setCursorWidth(1);
1871     control->setPasswordCharacter(QLatin1Char('*'));
1872     q->setSmooth(smooth);
1873     q->setAcceptedMouseButtons(Qt::LeftButton);
1874     q->setFlag(QQuickItem::ItemAcceptsInputMethod);
1875     q->setFlag(QQuickItem::ItemHasContents);
1876     q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
1877                q, SLOT(cursorPosChanged()));
1878     q->connect(control, SIGNAL(selectionChanged()),
1879                q, SLOT(selectionChanged()));
1880     q->connect(control, SIGNAL(textChanged(QString)),
1881                q, SLOT(q_textChanged()));
1882     q->connect(control, SIGNAL(accepted()),
1883                q, SIGNAL(accepted()));
1884     q->connect(control, SIGNAL(updateNeeded(QRect)),
1885                q, SLOT(updateRect(QRect)));
1886 #ifndef QT_NO_CLIPBOARD
1887     q->connect(q, SIGNAL(readOnlyChanged(bool)),
1888             q, SLOT(q_canPasteChanged()));
1889     q->connect(QGuiApplication::clipboard(), SIGNAL(dataChanged()),
1890             q, SLOT(q_canPasteChanged()));
1891     canPaste = !control->isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
1892 #endif // QT_NO_CLIPBOARD
1893     q->connect(control, SIGNAL(updateMicroFocus()),
1894                q, SLOT(updateCursorRectangle()));
1895     q->connect(control, SIGNAL(displayTextChanged(QString)),
1896                q, SLOT(updateRect()));
1897     q->updateSize();
1898     imHints &= ~Qt::ImhMultiLine;
1899     oldValidity = control->hasAcceptableInput();
1900     lastSelectionStart = 0;
1901     lastSelectionEnd = 0;
1902     QPalette p = control->palette();
1903     selectedTextColor = p.color(QPalette::HighlightedText);
1904     selectionColor = p.color(QPalette::Highlight);
1905     determineHorizontalAlignment();
1906
1907     if (!qmlDisableDistanceField()) {
1908         QTextOption option = control->textLayout()->textOption();
1909         option.setUseDesignMetrics(true);
1910         control->textLayout()->setTextOption(option);
1911     }
1912 }
1913
1914 void QQuickTextInput::cursorPosChanged()
1915 {
1916     Q_D(QQuickTextInput);
1917     updateCursorRectangle();
1918     emit cursorPositionChanged();
1919     // XXX todo - not in 4.8?
1920 #if 0
1921     d->control->resetCursorBlinkTimer();
1922 #endif
1923
1924     if (!d->control->hasSelectedText()) {
1925         if (d->lastSelectionStart != d->control->cursor()) {
1926             d->lastSelectionStart = d->control->cursor();
1927             emit selectionStartChanged();
1928         }
1929         if (d->lastSelectionEnd != d->control->cursor()) {
1930             d->lastSelectionEnd = d->control->cursor();
1931             emit selectionEndChanged();
1932         }
1933     }
1934 }
1935
1936 void QQuickTextInput::updateCursorRectangle()
1937 {
1938     Q_D(QQuickTextInput);
1939     d->determineHorizontalAlignment();
1940     d->updateHorizontalScroll();
1941     updateRect();//TODO: Only update rect between pos's
1942     updateMicroFocus();
1943     emit cursorRectangleChanged();
1944     if (d->cursorItem)
1945         d->cursorItem->setX(d->control->cursorToX() - d->hscroll);
1946 }
1947
1948 void QQuickTextInput::selectionChanged()
1949 {
1950     Q_D(QQuickTextInput);
1951     updateRect();//TODO: Only update rect in selection
1952     emit selectedTextChanged();
1953
1954     if (d->lastSelectionStart != d->control->selectionStart()) {
1955         d->lastSelectionStart = d->control->selectionStart();
1956         if (d->lastSelectionStart == -1)
1957             d->lastSelectionStart = d->control->cursor();
1958         emit selectionStartChanged();
1959     }
1960     if (d->lastSelectionEnd != d->control->selectionEnd()) {
1961         d->lastSelectionEnd = d->control->selectionEnd();
1962         if (d->lastSelectionEnd == -1)
1963             d->lastSelectionEnd = d->control->cursor();
1964         emit selectionEndChanged();
1965     }
1966 }
1967
1968 void QQuickTextInput::q_textChanged()
1969 {
1970     Q_D(QQuickTextInput);
1971     emit textChanged();
1972     emit displayTextChanged();
1973     updateSize();
1974     d->determineHorizontalAlignment();
1975     d->updateHorizontalScroll();
1976     updateMicroFocus();
1977     if (hasAcceptableInput() != d->oldValidity) {
1978         d->oldValidity = hasAcceptableInput();
1979         emit acceptableInputChanged();
1980     }
1981 }
1982
1983 void QQuickTextInputPrivate::showCursor()
1984 {
1985     if (textNode != 0 && textNode->cursorNode() != 0)
1986         textNode->cursorNode()->setColor(color);
1987 }
1988
1989 void QQuickTextInputPrivate::hideCursor()
1990 {
1991     if (textNode != 0 && textNode->cursorNode() != 0)
1992         textNode->cursorNode()->setColor(QColor(0, 0, 0, 0));
1993 }
1994
1995 void QQuickTextInput::updateRect(const QRect &r)
1996 {
1997     Q_D(QQuickTextInput);
1998     if (!isComponentComplete())
1999         return;
2000
2001     if (r.isEmpty()) {
2002         d->textLayoutDirty = true;
2003     }
2004
2005     update();
2006 }
2007
2008 QRectF QQuickTextInput::boundingRect() const
2009 {
2010     Q_D(const QQuickTextInput);
2011     QRectF r = QQuickImplicitSizeItem::boundingRect();
2012
2013     int cursorWidth = d->cursorItem ? d->cursorItem->width() : d->control->cursorWidth();
2014
2015     // Could include font max left/right bearings to either side of rectangle.
2016
2017     r.setRight(r.right() + cursorWidth);
2018     return r;
2019 }
2020
2021 void QQuickTextInput::updateSize(bool needsRedraw)
2022 {
2023     Q_D(QQuickTextInput);
2024     int w = width();
2025     int h = height();
2026     setImplicitSize(d->calculateTextWidth(), d->control->height()-1); // -1 to counter QQuickLineControl's +1 which is not consistent with Text.
2027     if (w==width() && h==height() && needsRedraw)
2028         update();
2029 }
2030
2031 void QQuickTextInput::q_canPasteChanged()
2032 {
2033     Q_D(QQuickTextInput);
2034     bool old = d->canPaste;
2035 #ifndef QT_NO_CLIPBOARD
2036     d->canPaste = !d->control->isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
2037 #endif
2038     if (d->canPaste != old)
2039         emit canPasteChanged();
2040 }
2041
2042 QT_END_NAMESPACE
2043