TextInput to use password mask delay if platform style defines one
[profile/ivi/qtdeclarative.git] / src / quick / items / qquicktextinput.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
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/qqmlglobal_p.h>
47
48 #include <QtQml/qqmlinfo.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/qinputmethod.h>
56
57 #ifndef QT_NO_ACCESSIBILITY
58 #include "qaccessible.h"
59 #endif
60
61 QT_BEGIN_NAMESPACE
62
63 DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
64
65 /*!
66     \qmlclass TextInput QQuickTextInput
67     \inqmlmodule QtQuick 2
68     \ingroup qml-basic-visual-elements
69     \brief The TextInput item displays an editable line of text.
70     \inherits Item
71
72     The TextInput element displays a single line of editable plain text.
73
74     TextInput is used to accept a line of text input. Input constraints
75     can be placed on a TextInput item (for example, through a \l validator or \l inputMask),
76     and setting \l echoMode to an appropriate value enables TextInput to be used for
77     a password input field.
78
79     On Mac OS X, the Up/Down key bindings for Home/End are explicitly disabled.
80     If you want such bindings (on any platform), you will need to construct them in QML.
81
82     \sa TextEdit, Text, {declarative/text/textselection}{Text Selection example}
83 */
84 QQuickTextInput::QQuickTextInput(QQuickItem* parent)
85 : QQuickImplicitSizeItem(*(new QQuickTextInputPrivate), parent)
86 {
87     Q_D(QQuickTextInput);
88     d->init();
89 }
90
91 QQuickTextInput::~QQuickTextInput()
92 {
93 }
94
95 void QQuickTextInput::componentComplete()
96 {
97     Q_D(QQuickTextInput);
98
99     QQuickImplicitSizeItem::componentComplete();
100
101     d->checkIsValid();
102     d->updateLayout();
103     updateCursorRectangle();
104     if (d->cursorComponent && d->cursorComponent->isReady())
105         createCursor();
106 }
107
108 /*!
109     \qmlproperty string QtQuick2::TextInput::text
110
111     The text in the TextInput.
112 */
113 QString QQuickTextInput::text() const
114 {
115     Q_D(const QQuickTextInput);
116
117     QString content = d->m_text;
118     QString res = d->m_maskData ? d->stripString(content) : content;
119     return (res.isNull() ? QString::fromLatin1("") : res);
120 }
121
122 void QQuickTextInput::setText(const QString &s)
123 {
124     Q_D(QQuickTextInput);
125     if (s == text())
126         return;
127     if (d->composeMode())
128         qApp->inputMethod()->reset();
129     d->internalSetText(s, -1, false);
130 }
131
132 /*!
133     \qmlproperty int QtQuick2::TextInput::length
134
135     Returns the total number of characters in the TextInput item.
136
137     If the TextInput has an inputMask the length will include mask characters and may differ
138     from the length of the string returned by the \l text property.
139
140     This property can be faster than querying the length the \l text property as it doesn't
141     require any copying or conversion of the TextInput's internal string data.
142 */
143
144 int QQuickTextInput::length() const
145 {
146     Q_D(const QQuickTextInput);
147     return d->m_text.length();
148 }
149
150 /*!
151     \qmlmethod string QtQuick2::TextInput::getText(int start, int end)
152
153     Returns the section of text that is between the \a start and \a end positions.
154
155     If the TextInput has an inputMask the length will include mask characters.
156 */
157
158 QString QQuickTextInput::getText(int start, int end) const
159 {
160     Q_D(const QQuickTextInput);
161
162     if (start > end)
163         qSwap(start, end);
164
165     return d->m_text.mid(start, end - start);
166 }
167
168 QString QQuickTextInputPrivate::realText() const
169 {
170     QString res = m_maskData ? stripString(m_text) : m_text;
171     return (res.isNull() ? QString::fromLatin1("") : res);
172 }
173
174 /*!
175     \qmlproperty string QtQuick2::TextInput::font.family
176
177     Sets the family name of the font.
178
179     The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]".
180     If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen.
181     If the family isn't available a family will be set using the font matching algorithm.
182 */
183
184 /*!
185     \qmlproperty bool QtQuick2::TextInput::font.bold
186
187     Sets whether the font weight is bold.
188 */
189
190 /*!
191     \qmlproperty enumeration QtQuick2::TextInput::font.weight
192
193     Sets the font's weight.
194
195     The weight can be one of:
196     \list
197     \li Font.Light
198     \li Font.Normal - the default
199     \li Font.DemiBold
200     \li Font.Bold
201     \li Font.Black
202     \endlist
203
204     \qml
205     TextInput { text: "Hello"; font.weight: Font.DemiBold }
206     \endqml
207 */
208
209 /*!
210     \qmlproperty bool QtQuick2::TextInput::font.italic
211
212     Sets whether the font has an italic style.
213 */
214
215 /*!
216     \qmlproperty bool QtQuick2::TextInput::font.underline
217
218     Sets whether the text is underlined.
219 */
220
221 /*!
222     \qmlproperty bool QtQuick2::TextInput::font.strikeout
223
224     Sets whether the font has a strikeout style.
225 */
226
227 /*!
228     \qmlproperty real QtQuick2::TextInput::font.pointSize
229
230     Sets the font size in points. The point size must be greater than zero.
231 */
232
233 /*!
234     \qmlproperty int QtQuick2::TextInput::font.pixelSize
235
236     Sets the font size in pixels.
237
238     Using this function makes the font device dependent.
239     Use \c pointSize to set the size of the font in a device independent manner.
240 */
241
242 /*!
243     \qmlproperty real QtQuick2::TextInput::font.letterSpacing
244
245     Sets the letter spacing for the font.
246
247     Letter spacing changes the default spacing between individual letters in the font.
248     A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing.
249 */
250
251 /*!
252     \qmlproperty real QtQuick2::TextInput::font.wordSpacing
253
254     Sets the word spacing for the font.
255
256     Word spacing changes the default spacing between individual words.
257     A positive value increases the word spacing by a corresponding amount of pixels,
258     while a negative value decreases the inter-word spacing accordingly.
259 */
260
261 /*!
262     \qmlproperty enumeration QtQuick2::TextInput::font.capitalization
263
264     Sets the capitalization for the text.
265
266     \list
267     \li Font.MixedCase - This is the normal text rendering option where no capitalization change is applied.
268     \li Font.AllUppercase - This alters the text to be rendered in all uppercase type.
269     \li Font.AllLowercase - This alters the text to be rendered in all lowercase type.
270     \li Font.SmallCaps - This alters the text to be rendered in small-caps type.
271     \li Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character.
272     \endlist
273
274     \qml
275     TextInput { text: "Hello"; font.capitalization: Font.AllLowercase }
276     \endqml
277 */
278
279 QFont QQuickTextInput::font() const
280 {
281     Q_D(const QQuickTextInput);
282     return d->sourceFont;
283 }
284
285 void QQuickTextInput::setFont(const QFont &font)
286 {
287     Q_D(QQuickTextInput);
288     if (d->sourceFont == font)
289         return;
290
291     d->sourceFont = font;
292     QFont oldFont = d->font;
293     d->font = font;
294     if (d->font.pointSizeF() != -1) {
295         // 0.5pt resolution
296         qreal size = qRound(d->font.pointSizeF()*2.0);
297         d->font.setPointSizeF(size/2.0);
298     }
299     if (oldFont != d->font) {
300         d->updateLayout();
301         updateCursorRectangle();
302         updateInputMethod(Qt::ImCursorRectangle | Qt::ImFont);
303     }
304     emit fontChanged(d->sourceFont);
305 }
306
307 /*!
308     \qmlproperty color QtQuick2::TextInput::color
309
310     The text color.
311 */
312 QColor QQuickTextInput::color() const
313 {
314     Q_D(const QQuickTextInput);
315     return d->color;
316 }
317
318 void QQuickTextInput::setColor(const QColor &c)
319 {
320     Q_D(QQuickTextInput);
321     if (c != d->color) {
322         d->color = c;
323         d->textLayoutDirty = true;
324         d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
325         update();
326         emit colorChanged();
327     }
328 }
329
330
331 /*!
332     \qmlproperty color QtQuick2::TextInput::selectionColor
333
334     The text highlight color, used behind selections.
335 */
336 QColor QQuickTextInput::selectionColor() const
337 {
338     Q_D(const QQuickTextInput);
339     return d->selectionColor;
340 }
341
342 void QQuickTextInput::setSelectionColor(const QColor &color)
343 {
344     Q_D(QQuickTextInput);
345     if (d->selectionColor == color)
346         return;
347
348     d->selectionColor = color;
349     if (d->hasSelectedText()) {
350         d->textLayoutDirty = true;
351         d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
352         update();
353     }
354     emit selectionColorChanged();
355 }
356 /*!
357     \qmlproperty color QtQuick2::TextInput::selectedTextColor
358
359     The highlighted text color, used in selections.
360 */
361 QColor QQuickTextInput::selectedTextColor() const
362 {
363     Q_D(const QQuickTextInput);
364     return d->selectedTextColor;
365 }
366
367 void QQuickTextInput::setSelectedTextColor(const QColor &color)
368 {
369     Q_D(QQuickTextInput);
370     if (d->selectedTextColor == color)
371         return;
372
373     d->selectedTextColor = color;
374     if (d->hasSelectedText()) {
375         d->textLayoutDirty = true;
376         d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
377         update();
378     }
379     emit selectedTextColorChanged();
380 }
381
382 /*!
383     \qmlproperty enumeration QtQuick2::TextInput::horizontalAlignment
384     \qmlproperty enumeration QtQuick2::TextInput::effectiveHorizontalAlignment
385     \qmlproperty enumeration QtQuick2::TextInput::verticalAlignment
386
387     Sets the horizontal alignment of the text within the TextInput item's
388     width and height. By default, the text alignment follows the natural alignment
389     of the text, for example text that is read from left to right will be aligned to
390     the left.
391
392     TextInput does not have vertical alignment, as the natural height is
393     exactly the height of the single line of text. If you set the height
394     manually to something larger, TextInput will always be top aligned
395     vertically. You can use anchors to align it however you want within
396     another item.
397
398     The valid values for \c horizontalAlignment are \c TextInput.AlignLeft, \c TextInput.AlignRight and
399     \c TextInput.AlignHCenter.
400
401     Valid values for \c verticalAlignment are \c TextInput.AlignTop (default),
402     \c TextInput.AlignBottom \c TextInput.AlignVCenter.
403
404     When using the attached property LayoutMirroring::enabled to mirror application
405     layouts, the horizontal alignment of text will also be mirrored. However, the property
406     \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
407     of TextInput, use the read-only property \c effectiveHorizontalAlignment.
408 */
409 QQuickTextInput::HAlignment QQuickTextInput::hAlign() const
410 {
411     Q_D(const QQuickTextInput);
412     return d->hAlign;
413 }
414
415 void QQuickTextInput::setHAlign(HAlignment align)
416 {
417     Q_D(QQuickTextInput);
418     bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror;
419     d->hAlignImplicit = false;
420     if (d->setHAlign(align, forceAlign) && isComponentComplete()) {
421         d->updateLayout();
422         updateCursorRectangle();
423     }
424 }
425
426 void QQuickTextInput::resetHAlign()
427 {
428     Q_D(QQuickTextInput);
429     d->hAlignImplicit = true;
430     if (d->determineHorizontalAlignment() && isComponentComplete()) {
431         d->updateLayout();
432         updateCursorRectangle();
433     }
434 }
435
436 QQuickTextInput::HAlignment QQuickTextInput::effectiveHAlign() const
437 {
438     Q_D(const QQuickTextInput);
439     QQuickTextInput::HAlignment effectiveAlignment = d->hAlign;
440     if (!d->hAlignImplicit && d->effectiveLayoutMirror) {
441         switch (d->hAlign) {
442         case QQuickTextInput::AlignLeft:
443             effectiveAlignment = QQuickTextInput::AlignRight;
444             break;
445         case QQuickTextInput::AlignRight:
446             effectiveAlignment = QQuickTextInput::AlignLeft;
447             break;
448         default:
449             break;
450         }
451     }
452     return effectiveAlignment;
453 }
454
455 bool QQuickTextInputPrivate::setHAlign(QQuickTextInput::HAlignment alignment, bool forceAlign)
456 {
457     Q_Q(QQuickTextInput);
458     if ((hAlign != alignment || forceAlign) && alignment <= QQuickTextInput::AlignHCenter) { // justify not supported
459         QQuickTextInput::HAlignment oldEffectiveHAlign = q->effectiveHAlign();
460         hAlign = alignment;
461         emit q->horizontalAlignmentChanged(alignment);
462         if (oldEffectiveHAlign != q->effectiveHAlign())
463             emit q->effectiveHorizontalAlignmentChanged();
464         return true;
465     }
466     return false;
467 }
468
469 bool QQuickTextInputPrivate::determineHorizontalAlignment()
470 {
471     if (hAlignImplicit) {
472         // if no explicit alignment has been set, follow the natural layout direction of the text
473         QString text = q_func()->text();
474         if (text.isEmpty())
475             text = m_textLayout.preeditAreaText();
476         bool isRightToLeft = text.isEmpty() ? qApp->inputMethod()->inputDirection() == Qt::RightToLeft
477                                             : text.isRightToLeft();
478         return setHAlign(isRightToLeft ? QQuickTextInput::AlignRight : QQuickTextInput::AlignLeft);
479     }
480     return false;
481 }
482
483 QQuickTextInput::VAlignment QQuickTextInput::vAlign() const
484 {
485     Q_D(const QQuickTextInput);
486     return d->vAlign;
487 }
488
489 void QQuickTextInput::setVAlign(QQuickTextInput::VAlignment alignment)
490 {
491     Q_D(QQuickTextInput);
492     if (alignment == d->vAlign)
493         return;
494     d->vAlign = alignment;
495     emit verticalAlignmentChanged(d->vAlign);
496     if (isComponentComplete()) {
497         updateCursorRectangle();
498     }
499 }
500
501 /*!
502     \qmlproperty enumeration QtQuick2::TextInput::wrapMode
503
504     Set this property to wrap the text to the TextInput item's width.
505     The text will only wrap if an explicit width has been set.
506
507     \list
508     \li TextInput.NoWrap - no wrapping will be performed. If the text contains insufficient newlines, then implicitWidth will exceed a set width.
509     \li TextInput.WordWrap - wrapping is done on word boundaries only. If a word is too long, implicitWidth will exceed a set width.
510     \li TextInput.WrapAnywhere - wrapping is done at any point on a line, even if it occurs in the middle of a word.
511     \li TextInput.Wrap - if possible, wrapping occurs at a word boundary; otherwise it will occur at the appropriate point on the line, even in the middle of a word.
512     \endlist
513
514     The default is TextInput.NoWrap. If you set a width, consider using TextInput.Wrap.
515 */
516 QQuickTextInput::WrapMode QQuickTextInput::wrapMode() const
517 {
518     Q_D(const QQuickTextInput);
519     return d->wrapMode;
520 }
521
522 void QQuickTextInput::setWrapMode(WrapMode mode)
523 {
524     Q_D(QQuickTextInput);
525     if (mode == d->wrapMode)
526         return;
527     d->wrapMode = mode;
528     d->updateLayout();
529     updateCursorRectangle();
530     emit wrapModeChanged();
531 }
532
533 void QQuickTextInputPrivate::mirrorChange()
534 {
535     Q_Q(QQuickTextInput);
536     if (q->isComponentComplete()) {
537         if (!hAlignImplicit && (hAlign == QQuickTextInput::AlignRight || hAlign == QQuickTextInput::AlignLeft)) {
538             q->updateCursorRectangle();
539             emit q->effectiveHorizontalAlignmentChanged();
540         }
541     }
542 }
543
544 /*!
545     \qmlproperty bool QtQuick2::TextInput::readOnly
546
547     Sets whether user input can modify the contents of the TextInput.
548
549     If readOnly is set to true, then user input will not affect the text
550     property. Any bindings or attempts to set the text property will still
551     work.
552 */
553 bool QQuickTextInput::isReadOnly() const
554 {
555     Q_D(const QQuickTextInput);
556     return d->m_readOnly;
557 }
558
559 void QQuickTextInput::setReadOnly(bool ro)
560 {
561     Q_D(QQuickTextInput);
562     if (d->m_readOnly == ro)
563         return;
564
565     setFlag(QQuickItem::ItemAcceptsInputMethod, !ro);
566     d->m_readOnly = ro;
567     if (!ro)
568         d->setCursorPosition(d->end());
569     updateInputMethod(Qt::ImEnabled);
570     q_canPasteChanged();
571     d->emitUndoRedoChanged();
572     emit readOnlyChanged(ro);
573 }
574
575 /*!
576     \qmlproperty int QtQuick2::TextInput::maximumLength
577     The maximum permitted length of the text in the TextInput.
578
579     If the text is too long, it is truncated at the limit.
580
581     By default, this property contains a value of 32767.
582 */
583 int QQuickTextInput::maxLength() const
584 {
585     Q_D(const QQuickTextInput);
586     return d->m_maxLength;
587 }
588
589 void QQuickTextInput::setMaxLength(int ml)
590 {
591     Q_D(QQuickTextInput);
592     if (d->m_maxLength == ml || d->m_maskData)
593         return;
594
595     d->m_maxLength = ml;
596     d->internalSetText(d->m_text, -1, false);
597
598     emit maximumLengthChanged(ml);
599 }
600
601 /*!
602     \qmlproperty bool QtQuick2::TextInput::cursorVisible
603     Set to true when the TextInput shows a cursor.
604
605     This property is set and unset when the TextInput gets active focus, so that other
606     properties can be bound to whether the cursor is currently showing. As it
607     gets set and unset automatically, when you set the value yourself you must
608     keep in mind that your value may be overwritten.
609
610     It can be set directly in script, for example if a KeyProxy might
611     forward keys to it and you desire it to look active when this happens
612     (but without actually giving it active focus).
613
614     It should not be set directly on the element, like in the below QML,
615     as the specified value will be overridden an lost on focus changes.
616
617     \code
618     TextInput {
619         text: "Text"
620         cursorVisible: false
621     }
622     \endcode
623
624     In the above snippet the cursor will still become visible when the
625     TextInput gains active focus.
626 */
627 bool QQuickTextInput::isCursorVisible() const
628 {
629     Q_D(const QQuickTextInput);
630     return d->cursorVisible;
631 }
632
633 void QQuickTextInput::setCursorVisible(bool on)
634 {
635     Q_D(QQuickTextInput);
636     if (d->cursorVisible == on)
637         return;
638     d->cursorVisible = on;
639     d->setCursorBlinkPeriod(on ? qApp->styleHints()->cursorFlashTime() : 0);
640     d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
641     update();
642     emit cursorVisibleChanged(d->cursorVisible);
643 }
644
645 /*!
646     \qmlproperty int QtQuick2::TextInput::cursorPosition
647     The position of the cursor in the TextInput.
648 */
649 int QQuickTextInput::cursorPosition() const
650 {
651     Q_D(const QQuickTextInput);
652     return d->m_cursor;
653 }
654
655 void QQuickTextInput::setCursorPosition(int cp)
656 {
657     Q_D(QQuickTextInput);
658     if (cp < 0 || cp > text().length())
659         return;
660     d->moveCursor(cp);
661 }
662
663 /*!
664     \qmlproperty rectangle QtQuick2::TextInput::cursorRectangle
665
666     The rectangle where the standard text cursor is rendered within the text input.  Read only.
667
668     The position and height of a custom cursorDelegate are updated to follow the cursorRectangle
669     automatically when it changes.  The width of the delegate is unaffected by changes in the
670     cursor rectangle.
671 */
672
673 QRectF QQuickTextInput::cursorRectangle() const
674 {
675     Q_D(const QQuickTextInput);
676
677     int c = d->m_cursor;
678     if (d->m_preeditCursor != -1)
679         c += d->m_preeditCursor;
680     if (d->m_echoMode == NoEcho)
681         c = 0;
682     QTextLine l = d->m_textLayout.lineForTextPosition(c);
683     if (!l.isValid())
684         return QRectF();
685     return QRectF(l.cursorToX(c) - d->hscroll, l.y() - d->vscroll, 1, l.height());
686 }
687
688 /*!
689     \qmlproperty int QtQuick2::TextInput::selectionStart
690
691     The cursor position before the first character in the current selection.
692
693     This property is read-only. To change the selection, use select(start,end),
694     selectAll(), or selectWord().
695
696     \sa selectionEnd, cursorPosition, selectedText
697 */
698 int QQuickTextInput::selectionStart() const
699 {
700     Q_D(const QQuickTextInput);
701     return d->lastSelectionStart;
702 }
703 /*!
704     \qmlproperty int QtQuick2::TextInput::selectionEnd
705
706     The cursor position after the last character in the current selection.
707
708     This property is read-only. To change the selection, use select(start,end),
709     selectAll(), or selectWord().
710
711     \sa selectionStart, cursorPosition, selectedText
712 */
713 int QQuickTextInput::selectionEnd() const
714 {
715     Q_D(const QQuickTextInput);
716     return d->lastSelectionEnd;
717 }
718 /*!
719     \qmlmethod void QtQuick2::TextInput::select(int start, int end)
720
721     Causes the text from \a start to \a end to be selected.
722
723     If either start or end is out of range, the selection is not changed.
724
725     After calling this, selectionStart will become the lesser
726     and selectionEnd will become the greater (regardless of the order passed
727     to this method).
728
729     \sa selectionStart, selectionEnd
730 */
731 void QQuickTextInput::select(int start, int end)
732 {
733     Q_D(QQuickTextInput);
734     if (start < 0 || end < 0 || start > d->m_text.length() || end > d->m_text.length())
735         return;
736     d->setSelection(start, end-start);
737 }
738
739 /*!
740     \qmlproperty string QtQuick2::TextInput::selectedText
741
742     This read-only property provides the text currently selected in the
743     text input.
744
745     It is equivalent to the following snippet, but is faster and easier
746     to use.
747
748     \js
749     myTextInput.text.toString().substring(myTextInput.selectionStart,
750         myTextInput.selectionEnd);
751     \endjs
752 */
753 QString QQuickTextInput::selectedText() const
754 {
755     Q_D(const QQuickTextInput);
756     return d->selectedText();
757 }
758
759 /*!
760     \qmlproperty bool QtQuick2::TextInput::activeFocusOnPress
761
762     Whether the TextInput should gain active focus on a mouse press. By default this is
763     set to true.
764 */
765 bool QQuickTextInput::focusOnPress() const
766 {
767     Q_D(const QQuickTextInput);
768     return d->focusOnPress;
769 }
770
771 void QQuickTextInput::setFocusOnPress(bool b)
772 {
773     Q_D(QQuickTextInput);
774     if (d->focusOnPress == b)
775         return;
776
777     d->focusOnPress = b;
778
779     emit activeFocusOnPressChanged(d->focusOnPress);
780 }
781 /*!
782     \qmlproperty bool QtQuick2::TextInput::autoScroll
783
784     Whether the TextInput should scroll when the text is longer than the width. By default this is
785     set to true.
786 */
787 bool QQuickTextInput::autoScroll() const
788 {
789     Q_D(const QQuickTextInput);
790     return d->autoScroll;
791 }
792
793 void QQuickTextInput::setAutoScroll(bool b)
794 {
795     Q_D(QQuickTextInput);
796     if (d->autoScroll == b)
797         return;
798
799     d->autoScroll = b;
800     //We need to repaint so that the scrolling is taking into account.
801     updateCursorRectangle();
802     emit autoScrollChanged(d->autoScroll);
803 }
804
805 #ifndef QT_NO_VALIDATOR
806
807 /*!
808     \qmlclass IntValidator QIntValidator
809     \inqmlmodule QtQuick 2
810     \ingroup qml-basic-visual-elements
811
812     This element provides a validator for integer values.
813
814     If no \l locale is set IntValidator uses the \l {QLocale::setDefault()}{default locale} to
815     interpret the number and will accept locale specific digits, group separators, and positive
816     and negative signs.  In addition, IntValidator is always guaranteed to accept a number
817     formatted according to the "C" locale.
818 */
819
820
821 QQuickIntValidator::QQuickIntValidator(QObject *parent)
822     : QIntValidator(parent)
823 {
824 }
825
826 /*!
827     \qmlproperty string QtQuick2::IntValidator::locale
828
829     This property holds the name of the locale used to interpret the number.
830
831     \sa QML:Qt::locale()
832 */
833
834 QString QQuickIntValidator::localeName() const
835 {
836     return locale().name();
837 }
838
839 void QQuickIntValidator::setLocaleName(const QString &name)
840 {
841     if (locale().name() != name) {
842         setLocale(QLocale(name));
843         emit localeNameChanged();
844     }
845 }
846
847 void QQuickIntValidator::resetLocaleName()
848 {
849     QLocale defaultLocale;
850     if (locale() != defaultLocale) {
851         setLocale(defaultLocale);
852         emit localeNameChanged();
853     }
854 }
855
856 /*!
857     \qmlproperty int QtQuick2::IntValidator::top
858
859     This property holds the validator's highest acceptable value.
860     By default, this property's value is derived from the highest signed integer available (typically 2147483647).
861 */
862 /*!
863     \qmlproperty int QtQuick2::IntValidator::bottom
864
865     This property holds the validator's lowest acceptable value.
866     By default, this property's value is derived from the lowest signed integer available (typically -2147483647).
867 */
868
869 /*!
870     \qmlclass DoubleValidator QDoubleValidator
871     \inqmlmodule QtQuick 2
872     \ingroup qml-basic-visual-elements
873
874     This element provides a validator for non-integer numbers.
875
876     Input is accepted if it contains a double that is within the valid range
877     and is in the  correct format.
878
879     Input is accepected but invalid if it contains a double that is outside
880     the range or is in the wrong format; e.g. with too many digits after the
881     decimal point or is empty.
882
883     Input is rejected if it is not a double.
884
885     Note: If the valid range consists of just positive doubles (e.g. 0.0 to
886     100.0) and input is a negative double then it is rejected. If \l notation
887     is set to DoubleValidator.StandardNotation, and  the input contains more
888     digits before the decimal point than a double in the valid range may have,
889     it is also rejected. If \l notation is DoubleValidator.ScientificNotation,
890     and the input is not in the valid range, it is accecpted but invalid. The
891     value may yet become valid by changing the exponent.
892 */
893
894 QQuickDoubleValidator::QQuickDoubleValidator(QObject *parent)
895     : QDoubleValidator(parent)
896 {
897 }
898
899 /*!
900     \qmlproperty string QtQuick2::DoubleValidator::locale
901
902     This property holds the name of the locale used to interpret the number.
903
904     \sa QML:Qt::locale()
905 */
906
907 QString QQuickDoubleValidator::localeName() const
908 {
909     return locale().name();
910 }
911
912 void QQuickDoubleValidator::setLocaleName(const QString &name)
913 {
914     if (locale().name() != name) {
915         setLocale(QLocale(name));
916         emit localeNameChanged();
917     }
918 }
919
920 void QQuickDoubleValidator::resetLocaleName()
921 {
922     QLocale defaultLocale;
923     if (locale() != defaultLocale) {
924         setLocale(defaultLocale);
925         emit localeNameChanged();
926     }
927 }
928
929 /*!
930     \qmlproperty real QtQuick2::DoubleValidator::top
931
932     This property holds the validator's maximum acceptable value.
933     By default, this property contains a value of infinity.
934 */
935 /*!
936     \qmlproperty real QtQuick2::DoubleValidator::bottom
937
938     This property holds the validator's minimum acceptable value.
939     By default, this property contains a value of -infinity.
940 */
941 /*!
942     \qmlproperty int QtQuick2::DoubleValidator::decimals
943
944     This property holds the validator's maximum number of digits after the decimal point.
945     By default, this property contains a value of 1000.
946 */
947 /*!
948     \qmlproperty enumeration QtQuick2::DoubleValidator::notation
949     This property holds the notation of how a string can describe a number.
950
951     The possible values for this property are:
952
953     \list
954     \li DoubleValidator.StandardNotation
955     \li DoubleValidator.ScientificNotation (default)
956     \endlist
957
958     If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part (e.g. 1.5E-2).
959 */
960
961 /*!
962     \qmlclass RegExpValidator QRegExpValidator
963     \inqmlmodule QtQuick 2
964     \ingroup qml-basic-visual-elements
965
966     This element provides a validator, which counts as valid any string which
967     matches a specified regular expression.
968 */
969 /*!
970    \qmlproperty regExp QtQuick2::RegExpValidator::regExp
971
972    This property holds the regular expression used for validation.
973
974    Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular expression
975    matching "a".
976
977    By default, this property contains a regular expression with the pattern .* that matches any string.
978 */
979
980 /*!
981     \qmlproperty Validator QtQuick2::TextInput::validator
982
983     Allows you to set a validator on the TextInput. When a validator is set
984     the TextInput will only accept input which leaves the text property in
985     an acceptable or intermediate state. The accepted signal will only be sent
986     if the text is in an acceptable state when enter is pressed.
987
988     Currently supported validators are IntValidator, DoubleValidator and
989     RegExpValidator. An example of using validators is shown below, which allows
990     input of integers between 11 and 31 into the text input:
991
992     \code
993     import QtQuick 2.0
994     TextInput{
995         validator: IntValidator{bottom: 11; top: 31;}
996         focus: true
997     }
998     \endcode
999
1000     \sa acceptableInput, inputMask
1001 */
1002
1003 QValidator* QQuickTextInput::validator() const
1004 {
1005     Q_D(const QQuickTextInput);
1006     return d->m_validator;
1007 }
1008
1009 void QQuickTextInput::setValidator(QValidator* v)
1010 {
1011     Q_D(QQuickTextInput);
1012     if (d->m_validator == v)
1013         return;
1014
1015     d->m_validator = v;
1016
1017     if (isComponentComplete())
1018         d->checkIsValid();
1019
1020     emit validatorChanged();
1021 }
1022
1023 #endif // QT_NO_VALIDATOR
1024
1025 void QQuickTextInputPrivate::checkIsValid()
1026 {
1027     Q_Q(QQuickTextInput);
1028
1029     ValidatorState state = hasAcceptableInput(m_text);
1030     m_validInput = state != InvalidInput;
1031     if (state != AcceptableInput) {
1032         if (m_acceptableInput) {
1033             m_acceptableInput = false;
1034             emit q->acceptableInputChanged();
1035         }
1036     } else if (!m_acceptableInput) {
1037         m_acceptableInput = true;
1038         emit q->acceptableInputChanged();
1039     }
1040 }
1041
1042 /*!
1043     \qmlproperty string QtQuick2::TextInput::inputMask
1044
1045     Allows you to set an input mask on the TextInput, restricting the allowable
1046     text inputs. See QLineEdit::inputMask for further details, as the exact
1047     same mask strings are used by TextInput.
1048
1049     \sa acceptableInput, validator
1050 */
1051 QString QQuickTextInput::inputMask() const
1052 {
1053     Q_D(const QQuickTextInput);
1054     return d->inputMask();
1055 }
1056
1057 void QQuickTextInput::setInputMask(const QString &im)
1058 {
1059     Q_D(QQuickTextInput);
1060     if (d->inputMask() == im)
1061         return;
1062
1063     d->setInputMask(im);
1064     emit inputMaskChanged(d->inputMask());
1065 }
1066
1067 /*!
1068     \qmlproperty bool QtQuick2::TextInput::acceptableInput
1069
1070     This property is always true unless a validator or input mask has been set.
1071     If a validator or input mask has been set, this property will only be true
1072     if the current text is acceptable to the validator or input mask as a final
1073     string (not as an intermediate string).
1074 */
1075 bool QQuickTextInput::hasAcceptableInput() const
1076 {
1077     Q_D(const QQuickTextInput);
1078     return d->hasAcceptableInput(d->m_text) == QQuickTextInputPrivate::AcceptableInput;
1079 }
1080
1081 /*!
1082     \qmlsignal QtQuick2::TextInput::onAccepted()
1083
1084     This handler is called when the Return or Enter key is pressed.
1085     Note that if there is a \l validator or \l inputMask set on the text
1086     input, the handler will only be emitted if the input is in an acceptable
1087     state.
1088 */
1089
1090 Qt::InputMethodHints QQuickTextInputPrivate::effectiveInputMethodHints() const
1091 {
1092     Qt::InputMethodHints hints = inputMethodHints;
1093     if (m_echoMode == QQuickTextInput::Password || m_echoMode == QQuickTextInput::NoEcho)
1094         hints |= Qt::ImhHiddenText;
1095     else if (m_echoMode == QQuickTextInput::PasswordEchoOnEdit)
1096         hints &= ~Qt::ImhHiddenText;
1097     if (m_echoMode != QQuickTextInput::Normal)
1098         hints |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText | Qt::ImhSensitiveData);
1099     return hints;
1100 }
1101 /*!
1102     \qmlproperty enumeration QtQuick2::TextInput::echoMode
1103
1104     Specifies how the text should be displayed in the TextInput.
1105     \list
1106     \li TextInput.Normal - Displays the text as it is. (Default)
1107     \li TextInput.Password - Displays asterisks instead of characters.
1108     \li TextInput.NoEcho - Displays nothing.
1109     \li TextInput.PasswordEchoOnEdit - Displays characters as they are entered
1110     while editing, otherwise displays asterisks.
1111     \endlist
1112 */
1113 QQuickTextInput::EchoMode QQuickTextInput::echoMode() const
1114 {
1115     Q_D(const QQuickTextInput);
1116     return QQuickTextInput::EchoMode(d->m_echoMode);
1117 }
1118
1119 void QQuickTextInput::setEchoMode(QQuickTextInput::EchoMode echo)
1120 {
1121     Q_D(QQuickTextInput);
1122     if (echoMode() == echo)
1123         return;
1124     d->cancelPasswordEchoTimer();
1125     d->m_echoMode = echo;
1126     d->m_passwordEchoEditing = false;
1127     updateInputMethod(Qt::ImHints);
1128     d->updateDisplayText();
1129     updateCursorRectangle();
1130
1131     emit echoModeChanged(echoMode());
1132 }
1133
1134 /*!
1135     \qmlproperty enumeration QtQuick2::TextInput::inputMethodHints
1136
1137     Provides hints to the input method about the expected content of the text input and how it
1138     should operate.
1139
1140     The value is a bit-wise combination of flags, or Qt.ImhNone if no hints are set.
1141
1142     Flags that alter behaviour are:
1143
1144     \list
1145     \li Qt.ImhHiddenText - Characters should be hidden, as is typically used when entering passwords.
1146             This is automatically set when setting echoMode to \c TextInput.Password.
1147     \li Qt.ImhSensitiveData - Typed text should not be stored by the active input method
1148             in any persistent storage like predictive user dictionary.
1149     \li Qt.ImhNoAutoUppercase - The input method should not try to automatically switch to upper case
1150             when a sentence ends.
1151     \li Qt.ImhPreferNumbers - Numbers are preferred (but not required).
1152     \li Qt.ImhPreferUppercase - Upper case letters are preferred (but not required).
1153     \li Qt.ImhPreferLowercase - Lower case letters are preferred (but not required).
1154     \li Qt.ImhNoPredictiveText - Do not use predictive text (i.e. dictionary lookup) while typing.
1155
1156     \li Qt.ImhDate - The text editor functions as a date field.
1157     \li Qt.ImhTime - The text editor functions as a time field.
1158     \endlist
1159
1160     Flags that restrict input (exclusive flags) are:
1161
1162     \list
1163     \li Qt.ImhDigitsOnly - Only digits are allowed.
1164     \li Qt.ImhFormattedNumbersOnly - Only number input is allowed. This includes decimal point and minus sign.
1165     \li Qt.ImhUppercaseOnly - Only upper case letter input is allowed.
1166     \li Qt.ImhLowercaseOnly - Only lower case letter input is allowed.
1167     \li Qt.ImhDialableCharactersOnly - Only characters suitable for phone dialing are allowed.
1168     \li Qt.ImhEmailCharactersOnly - Only characters suitable for email addresses are allowed.
1169     \li Qt.ImhUrlCharactersOnly - Only characters suitable for URLs are allowed.
1170     \endlist
1171
1172     Masks:
1173
1174     \list
1175     \li Qt.ImhExclusiveInputMask - This mask yields nonzero if any of the exclusive flags are used.
1176     \endlist
1177 */
1178
1179 Qt::InputMethodHints QQuickTextInput::inputMethodHints() const
1180 {
1181     Q_D(const QQuickTextInput);
1182     return d->inputMethodHints;
1183 }
1184
1185 void QQuickTextInput::setInputMethodHints(Qt::InputMethodHints hints)
1186 {
1187     Q_D(QQuickTextInput);
1188
1189     if (hints == d->inputMethodHints)
1190         return;
1191
1192     d->inputMethodHints = hints;
1193     updateInputMethod(Qt::ImHints);
1194     emit inputMethodHintsChanged();
1195 }
1196
1197 /*!
1198     \qmlproperty Component QtQuick2::TextInput::cursorDelegate
1199     The delegate for the cursor in the TextInput.
1200
1201     If you set a cursorDelegate for a TextInput, this delegate will be used for
1202     drawing the cursor instead of the standard cursor. An instance of the
1203     delegate will be created and managed by the TextInput when a cursor is
1204     needed, and the x property of delegate instance will be set so as
1205     to be one pixel before the top left of the current character.
1206
1207     Note that the root item of the delegate component must be a QQuickItem or
1208     QQuickItem derived item.
1209 */
1210 QQmlComponent* QQuickTextInput::cursorDelegate() const
1211 {
1212     Q_D(const QQuickTextInput);
1213     return d->cursorComponent;
1214 }
1215
1216 void QQuickTextInput::setCursorDelegate(QQmlComponent* c)
1217 {
1218     Q_D(QQuickTextInput);
1219     if (d->cursorComponent == c)
1220         return;
1221
1222     d->cursorComponent = c;
1223     if (!c) {
1224         //note that the components are owned by something else
1225         delete d->cursorItem;
1226         d->cursorItem = 0;
1227     } else {
1228         d->startCreatingCursor();
1229     }
1230
1231     emit cursorDelegateChanged();
1232 }
1233
1234 void QQuickTextInputPrivate::startCreatingCursor()
1235 {
1236     Q_Q(QQuickTextInput);
1237     if (cursorComponent->isReady()) {
1238         q->createCursor();
1239     } else if (cursorComponent->isLoading()) {
1240         q->connect(cursorComponent, SIGNAL(statusChanged(int)),
1241                 q, SLOT(createCursor()));
1242     } else { // isError
1243         qmlInfo(q, cursorComponent->errors()) << QQuickTextInput::tr("Could not load cursor delegate");
1244     }
1245 }
1246
1247 void QQuickTextInput::createCursor()
1248 {
1249     Q_D(QQuickTextInput);
1250     if (!isComponentComplete())
1251         return;
1252
1253     if (d->cursorComponent->isError()) {
1254         qmlInfo(this, d->cursorComponent->errors()) << tr("Could not load cursor delegate");
1255         return;
1256     }
1257
1258     if (!d->cursorComponent->isReady())
1259         return;
1260
1261     if (d->cursorItem)
1262         delete d->cursorItem;
1263     QQmlContext *creationContext = d->cursorComponent->creationContext();
1264     QObject *object = d->cursorComponent->create(creationContext ? creationContext : qmlContext(this));
1265     d->cursorItem = qobject_cast<QQuickItem*>(object);
1266     if (!d->cursorItem) {
1267         delete object;
1268         qmlInfo(this, d->cursorComponent->errors()) << tr("Could not instantiate cursor delegate");
1269         return;
1270     }
1271
1272     QRectF r = cursorRectangle();
1273
1274     QQml_setParent_noEvent(d->cursorItem, this);
1275     d->cursorItem->setParentItem(this);
1276     d->cursorItem->setPos(r.topLeft());
1277     d->cursorItem->setHeight(r.height());
1278 }
1279
1280 /*!
1281     \qmlmethod rect QtQuick2::TextInput::positionToRectangle(int pos)
1282
1283     This function takes a character position and returns the rectangle that the
1284     cursor would occupy, if it was placed at that character position.
1285
1286     This is similar to setting the cursorPosition, and then querying the cursor
1287     rectangle, but the cursorPosition is not changed.
1288 */
1289 QRectF QQuickTextInput::positionToRectangle(int pos) const
1290 {
1291     Q_D(const QQuickTextInput);
1292     if (d->m_echoMode == NoEcho)
1293         pos = 0;
1294     else if (pos > d->m_cursor)
1295         pos += d->preeditAreaText().length();
1296     QTextLine l = d->m_textLayout.lineForTextPosition(pos);
1297     return l.isValid()
1298             ? QRectF(l.cursorToX(pos) - d->hscroll, l.y() - d->vscroll, 1, l.height())
1299             : QRectF();
1300 }
1301
1302 /*!
1303     \qmlmethod int QtQuick2::TextInput::positionAt(real x, real y, CursorPosition position = CursorBetweenCharacters)
1304
1305     This function returns the character position at
1306     x and y pixels from the top left  of the textInput. Position 0 is before the
1307     first character, position 1 is after the first character but before the second,
1308     and so on until position text.length, which is after all characters.
1309
1310     This means that for all x values before the first character this function returns 0,
1311     and for all x values after the last character this function returns text.length.  If
1312     the y value is above the text the position will be that of the nearest character on
1313     the first line line and if it is below the text the position of the nearest character
1314     on the last line will be returned.
1315
1316     The cursor position type specifies how the cursor position should be resolved.
1317
1318     \list
1319     \li TextInput.CursorBetweenCharacters - Returns the position between characters that is nearest x.
1320     \li TextInput.CursorOnCharacter - Returns the position before the character that is nearest x.
1321     \endlist
1322 */
1323
1324 void QQuickTextInput::positionAt(QQmlV8Function *args) const
1325 {
1326     Q_D(const QQuickTextInput);
1327
1328     qreal x = 0;
1329     qreal y = 0;
1330     QTextLine::CursorPosition position = QTextLine::CursorBetweenCharacters;
1331
1332     if (args->Length() < 1)
1333         return;
1334
1335     int i = 0;
1336     v8::Local<v8::Value> arg = (*args)[i];
1337     x = arg->NumberValue();
1338
1339     if (++i < args->Length()) {
1340         arg = (*args)[i];
1341         y = arg->NumberValue();
1342     }
1343
1344     if (++i < args->Length()) {
1345         arg = (*args)[i];
1346         position = QTextLine::CursorPosition(arg->Int32Value());
1347     }
1348
1349     int pos = d->positionAt(x, y, position);
1350     const int cursor = d->m_cursor;
1351     if (pos > cursor) {
1352         const int preeditLength = d->preeditAreaText().length();
1353         pos = pos > cursor + preeditLength
1354                 ? pos - preeditLength
1355                 : cursor;
1356     }
1357     args->returnValue(v8::Int32::New(pos));
1358 }
1359
1360 int QQuickTextInputPrivate::positionAt(qreal x, qreal y, QTextLine::CursorPosition position) const
1361 {
1362     x += hscroll;
1363     y += vscroll;
1364     QTextLine line = m_textLayout.lineAt(0);
1365     for (int i = 1; i < m_textLayout.lineCount(); ++i) {
1366         QTextLine nextLine = m_textLayout.lineAt(i);
1367
1368         if (y < (line.rect().bottom() + nextLine.y()) / 2)
1369             break;
1370         line = nextLine;
1371     }
1372     return line.isValid() ? line.xToCursor(x, position) : 0;
1373 }
1374
1375 void QQuickTextInput::keyPressEvent(QKeyEvent* ev)
1376 {
1377     Q_D(QQuickTextInput);
1378     // Don't allow MacOSX up/down support, and we don't allow a completer.
1379     bool ignore = (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) && ev->modifiers() == Qt::NoModifier;
1380     if (!ignore && (d->lastSelectionStart == d->lastSelectionEnd) && (ev->key() == Qt::Key_Right || ev->key() == Qt::Key_Left)) {
1381         // Ignore when moving off the end unless there is a selection,
1382         // because then moving will do something (deselect).
1383         int cursorPosition = d->m_cursor;
1384         if (cursorPosition == 0)
1385             ignore = ev->key() == (d->layoutDirection() == Qt::LeftToRight ? Qt::Key_Left : Qt::Key_Right);
1386         if (cursorPosition == text().length())
1387             ignore = ev->key() == (d->layoutDirection() == Qt::LeftToRight ? Qt::Key_Right : Qt::Key_Left);
1388     }
1389     if (ignore) {
1390         ev->ignore();
1391     } else {
1392         d->processKeyEvent(ev);
1393     }
1394     if (!ev->isAccepted())
1395         QQuickImplicitSizeItem::keyPressEvent(ev);
1396 }
1397
1398 void QQuickTextInput::inputMethodEvent(QInputMethodEvent *ev)
1399 {
1400     Q_D(QQuickTextInput);
1401     const bool wasComposing = d->preeditAreaText().length() > 0;
1402     if (d->m_readOnly) {
1403         ev->ignore();
1404     } else {
1405         d->processInputMethodEvent(ev);
1406     }
1407     if (!ev->isAccepted())
1408         QQuickImplicitSizeItem::inputMethodEvent(ev);
1409
1410     if (wasComposing != (d->m_textLayout.preeditAreaText().length() > 0))
1411         emit inputMethodComposingChanged();
1412 }
1413
1414 void QQuickTextInput::mouseDoubleClickEvent(QMouseEvent *event)
1415 {
1416     Q_D(QQuickTextInput);
1417
1418     if (d->selectByMouse && event->button() == Qt::LeftButton) {
1419         d->commitPreedit();
1420         int cursor = d->positionAt(event->localPos());
1421         d->selectWordAtPos(cursor);
1422         event->setAccepted(true);
1423         if (!d->hasPendingTripleClick()) {
1424             d->tripleClickStartPoint = event->localPos();
1425             d->tripleClickTimer.start();
1426         }
1427     } else {
1428         if (d->sendMouseEventToInputContext(event))
1429             return;
1430         QQuickImplicitSizeItem::mouseDoubleClickEvent(event);
1431     }
1432 }
1433
1434 void QQuickTextInput::mousePressEvent(QMouseEvent *event)
1435 {
1436     Q_D(QQuickTextInput);
1437
1438     d->pressPos = event->localPos();
1439
1440     if (d->sendMouseEventToInputContext(event))
1441         return;
1442
1443     if (d->selectByMouse) {
1444         setKeepMouseGrab(false);
1445         d->selectPressed = true;
1446         QPointF distanceVector = d->pressPos - d->tripleClickStartPoint;
1447         if (d->hasPendingTripleClick()
1448             && distanceVector.manhattanLength() < qApp->styleHints()->startDragDistance()) {
1449             event->setAccepted(true);
1450             selectAll();
1451             return;
1452         }
1453     }
1454
1455     bool mark = (event->modifiers() & Qt::ShiftModifier) && d->selectByMouse;
1456     int cursor = d->positionAt(event->localPos());
1457     d->moveCursor(cursor, mark);
1458
1459     if (d->focusOnPress) {
1460         bool hadActiveFocus = hasActiveFocus();
1461         forceActiveFocus();
1462         // re-open input panel on press if already focused
1463         if (hasActiveFocus() && hadActiveFocus && !d->m_readOnly)
1464             openSoftwareInputPanel();
1465     }
1466
1467     event->setAccepted(true);
1468 }
1469
1470 void QQuickTextInput::mouseMoveEvent(QMouseEvent *event)
1471 {
1472     Q_D(QQuickTextInput);
1473
1474     if (d->selectPressed) {
1475         if (qAbs(int(event->localPos().x() - d->pressPos.x())) > qApp->styleHints()->startDragDistance())
1476             setKeepMouseGrab(true);
1477
1478         if (d->composeMode()) {
1479             // start selection
1480             int startPos = d->positionAt(d->pressPos);
1481             int currentPos = d->positionAt(event->localPos());
1482             if (startPos != currentPos)
1483                 d->setSelection(startPos, currentPos - startPos);
1484         } else {
1485             moveCursorSelection(d->positionAt(event->localPos()), d->mouseSelectionMode);
1486         }
1487         event->setAccepted(true);
1488     } else {
1489         QQuickImplicitSizeItem::mouseMoveEvent(event);
1490     }
1491 }
1492
1493 void QQuickTextInput::mouseReleaseEvent(QMouseEvent *event)
1494 {
1495     Q_D(QQuickTextInput);
1496     if (d->sendMouseEventToInputContext(event))
1497         return;
1498     if (d->selectPressed) {
1499         d->selectPressed = false;
1500         setKeepMouseGrab(false);
1501     }
1502 #ifndef QT_NO_CLIPBOARD
1503     if (QGuiApplication::clipboard()->supportsSelection()) {
1504         if (event->button() == Qt::LeftButton) {
1505             d->copy(QClipboard::Selection);
1506         } else if (!d->m_readOnly && event->button() == Qt::MidButton) {
1507             d->deselect();
1508             d->insert(QGuiApplication::clipboard()->text(QClipboard::Selection));
1509         }
1510     }
1511 #endif
1512     if (!event->isAccepted())
1513         QQuickImplicitSizeItem::mouseReleaseEvent(event);
1514 }
1515
1516 bool QQuickTextInputPrivate::sendMouseEventToInputContext(QMouseEvent *event)
1517 {
1518 #if !defined QT_NO_IM
1519     if (composeMode()) {
1520         int tmp_cursor = positionAt(event->localPos());
1521         int mousePos = tmp_cursor - m_cursor;
1522         if (mousePos >= 0 && mousePos <= m_textLayout.preeditAreaText().length()) {
1523             if (event->type() == QEvent::MouseButtonRelease) {
1524                 qApp->inputMethod()->invokeAction(QInputMethod::Click, mousePos);
1525             }
1526             return true;
1527         }
1528     }
1529 #else
1530     Q_UNUSED(event);
1531     Q_UNUSED(eventType)
1532 #endif
1533
1534     return false;
1535 }
1536
1537 void QQuickTextInput::mouseUngrabEvent()
1538 {
1539     Q_D(QQuickTextInput);
1540     d->selectPressed = false;
1541     setKeepMouseGrab(false);
1542 }
1543
1544 bool QQuickTextInput::event(QEvent* ev)
1545 {
1546 #ifndef QT_NO_SHORTCUT
1547     Q_D(QQuickTextInput);
1548     if (ev->type() == QEvent::ShortcutOverride) {
1549         if (d->m_readOnly)
1550             return false;
1551         QKeyEvent* ke = static_cast<QKeyEvent*>(ev);
1552         if (ke == QKeySequence::Copy
1553             || ke == QKeySequence::Paste
1554             || ke == QKeySequence::Cut
1555             || ke == QKeySequence::Redo
1556             || ke == QKeySequence::Undo
1557             || ke == QKeySequence::MoveToNextWord
1558             || ke == QKeySequence::MoveToPreviousWord
1559             || ke == QKeySequence::MoveToStartOfDocument
1560             || ke == QKeySequence::MoveToEndOfDocument
1561             || ke == QKeySequence::SelectNextWord
1562             || ke == QKeySequence::SelectPreviousWord
1563             || ke == QKeySequence::SelectStartOfLine
1564             || ke == QKeySequence::SelectEndOfLine
1565             || ke == QKeySequence::SelectStartOfBlock
1566             || ke == QKeySequence::SelectEndOfBlock
1567             || ke == QKeySequence::SelectStartOfDocument
1568             || ke == QKeySequence::SelectAll
1569             || ke == QKeySequence::SelectEndOfDocument) {
1570             ke->accept();
1571         } else if (ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier
1572                    || ke->modifiers() == Qt::KeypadModifier) {
1573             if (ke->key() < Qt::Key_Escape) {
1574                 ke->accept();
1575                 return true;
1576             } else {
1577                 switch (ke->key()) {
1578                 case Qt::Key_Delete:
1579                 case Qt::Key_Home:
1580                 case Qt::Key_End:
1581                 case Qt::Key_Backspace:
1582                 case Qt::Key_Left:
1583                 case Qt::Key_Right:
1584                     return true;
1585                 default:
1586                     break;
1587                 }
1588             }
1589         }
1590     }
1591 #endif
1592
1593     return QQuickImplicitSizeItem::event(ev);
1594 }
1595
1596 void QQuickTextInput::geometryChanged(const QRectF &newGeometry,
1597                                   const QRectF &oldGeometry)
1598 {
1599     Q_D(QQuickTextInput);
1600     if (!d->inLayout) {
1601         if (newGeometry.width() != oldGeometry.width() && d->wrapMode != NoWrap)
1602             d->updateLayout();
1603         updateCursorRectangle();
1604     }
1605     QQuickImplicitSizeItem::geometryChanged(newGeometry, oldGeometry);
1606 }
1607
1608 void QQuickTextInputPrivate::updateHorizontalScroll()
1609 {
1610     Q_Q(QQuickTextInput);
1611     QTextLine currentLine = m_textLayout.lineForTextPosition(m_cursor + m_preeditCursor);
1612     const int preeditLength = m_textLayout.preeditAreaText().length();
1613     const qreal width = qMax<qreal>(0, q->width());
1614     qreal cix = 0;
1615     qreal widthUsed = 0;
1616     if (currentLine.isValid()) {
1617         cix = currentLine.cursorToX(m_cursor + preeditLength);
1618         const qreal cursorWidth = cix >= 0 ? cix : width - cix;
1619         widthUsed = qMax(currentLine.naturalTextWidth(), cursorWidth);
1620     }
1621     int previousScroll = hscroll;
1622
1623     if (!autoScroll || widthUsed <=  width || m_echoMode == QQuickTextInput::NoEcho) {
1624         hscroll = 0;
1625     } else {
1626         Q_ASSERT(currentLine.isValid());
1627         if (cix - hscroll >= width) {
1628             // text doesn't fit, cursor is to the right of br (scroll right)
1629             hscroll = cix - width;
1630         } else if (cix - hscroll < 0 && hscroll < widthUsed) {
1631             // text doesn't fit, cursor is to the left of br (scroll left)
1632             hscroll = cix;
1633         } else if (widthUsed - hscroll < width) {
1634             // text doesn't fit, text document is to the left of br; align
1635             // right
1636             hscroll = widthUsed - width;
1637         } else if (width - hscroll > widthUsed) {
1638             // text doesn't fit, text document is to the right of br; align
1639             // left
1640             hscroll = width - widthUsed;
1641         }
1642         if (preeditLength > 0) {
1643             // check to ensure long pre-edit text doesn't push the cursor
1644             // off to the left
1645              cix = currentLine.cursorToX(m_cursor + qMax(0, m_preeditCursor - 1));
1646              if (cix < hscroll)
1647                  hscroll = cix;
1648         }
1649     }
1650     if (previousScroll != hscroll)
1651         textLayoutDirty = true;
1652 }
1653
1654 void QQuickTextInputPrivate::updateVerticalScroll()
1655 {
1656     Q_Q(QQuickTextInput);
1657     const int preeditLength = m_textLayout.preeditAreaText().length();
1658     const qreal height = qMax<qreal>(0, q->height());
1659     qreal heightUsed = boundingRect.height();
1660     qreal previousScroll = vscroll;
1661
1662     if (!autoScroll || heightUsed <=  height) {
1663         // text fits in br; use vscroll for alignment
1664         switch (vAlign & ~(Qt::AlignAbsolute|Qt::AlignHorizontal_Mask)) {
1665         case Qt::AlignBottom:
1666             vscroll = heightUsed - height;
1667             break;
1668         case Qt::AlignVCenter:
1669             vscroll = (heightUsed - height) / 2;
1670             break;
1671         default:
1672             // Top
1673             vscroll = 0;
1674             break;
1675         }
1676     } else {
1677         QTextLine currentLine = m_textLayout.lineForTextPosition(m_cursor + preeditLength);
1678         QRectF r = currentLine.isValid() ? currentLine.rect() : QRectF();
1679         qreal top = r.top();
1680         int bottom = r.bottom();
1681
1682         if (bottom - vscroll >= height) {
1683             // text doesn't fit, cursor is to the below the br (scroll down)
1684             vscroll = bottom - height;
1685         } else if (top - vscroll < 0 && vscroll < heightUsed) {
1686             // text doesn't fit, cursor is above br (scroll up)
1687             vscroll = top;
1688         } else if (heightUsed - vscroll < height) {
1689             // text doesn't fit, text document is to the left of br; align
1690             // right
1691             vscroll = heightUsed - height;
1692         }
1693         if (preeditLength > 0) {
1694             // check to ensure long pre-edit text doesn't push the cursor
1695             // off the top
1696             currentLine = m_textLayout.lineForTextPosition(m_cursor + qMax(0, m_preeditCursor - 1));
1697             top = currentLine.isValid() ? currentLine.rect().top() : 0;
1698             if (top < vscroll)
1699                 vscroll = top;
1700         }
1701     }
1702     if (previousScroll != vscroll)
1703         textLayoutDirty = true;
1704 }
1705
1706 void QQuickTextInput::triggerPreprocess()
1707 {
1708     Q_D(QQuickTextInput);
1709     if (d->updateType == QQuickTextInputPrivate::UpdateNone)
1710         d->updateType = QQuickTextInputPrivate::UpdateOnlyPreprocess;
1711     update();
1712 }
1713
1714 QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
1715 {
1716     Q_UNUSED(data);
1717     Q_D(QQuickTextInput);
1718
1719     if (d->updateType != QQuickTextInputPrivate::UpdatePaintNode && oldNode != 0) {
1720         // Update done in preprocess() in the nodes
1721         d->updateType = QQuickTextInputPrivate::UpdateNone;
1722         return oldNode;
1723     }
1724
1725     d->updateType = QQuickTextInputPrivate::UpdateNone;
1726
1727     QQuickTextNode *node = static_cast<QQuickTextNode *>(oldNode);
1728     if (node == 0)
1729         node = new QQuickTextNode(QQuickItemPrivate::get(this)->sceneGraphContext(), this);
1730     d->textNode = node;
1731
1732     if (!d->textLayoutDirty) {
1733         QSGSimpleRectNode *cursorNode = node->cursorNode();
1734         if (cursorNode != 0 && !isReadOnly()) {
1735             cursorNode->setRect(cursorRectangle());
1736
1737             if (!d->cursorVisible || (!d->m_blinkStatus && d->m_blinkPeriod > 0)) {
1738                 d->hideCursor();
1739             } else {
1740                 d->showCursor();
1741             }
1742         }
1743     } else {
1744         node->deleteContent();
1745         node->setMatrix(QMatrix4x4());
1746
1747         QPointF offset(0, 0);
1748         if (d->autoScroll && d->m_textLayout.lineCount() > 0) {
1749             QFontMetricsF fm(d->font);
1750             // the y offset is there to keep the baseline constant in case we have script changes in the text.
1751             offset = -QPoint(d->hscroll, d->vscroll + d->m_textLayout.lineAt(0).ascent() - fm.ascent());
1752         } else {
1753             offset = -QPoint(d->hscroll, d->vscroll);
1754         }
1755
1756         if (!d->m_textLayout.text().isEmpty() || !d->m_textLayout.preeditAreaText().isEmpty()) {
1757             node->addTextLayout(offset, &d->m_textLayout, d->color,
1758                                 QQuickText::Normal, QColor(), QColor(),
1759                                 d->selectionColor, d->selectedTextColor,
1760                                 d->selectionStart(),
1761                                 d->selectionEnd() - 1); // selectionEnd() returns first char after
1762                                                                  // selection
1763         }
1764
1765         if (!isReadOnly() && d->cursorItem == 0) {
1766             node->setCursor(cursorRectangle(), d->color);
1767             if (!d->cursorVisible || (!d->m_blinkStatus && d->m_blinkPeriod > 0)) {
1768                 d->hideCursor();
1769             } else {
1770                 d->showCursor();
1771             }
1772         }
1773
1774         d->textLayoutDirty = false;
1775     }
1776
1777     return node;
1778 }
1779
1780 QVariant QQuickTextInput::inputMethodQuery(Qt::InputMethodQuery property) const
1781 {
1782     Q_D(const QQuickTextInput);
1783     switch (property) {
1784     case Qt::ImEnabled:
1785         return QVariant((bool)(flags() & ItemAcceptsInputMethod));
1786     case Qt::ImHints:
1787         return QVariant((int) d->effectiveInputMethodHints());
1788     case Qt::ImCursorRectangle:
1789         return cursorRectangle();
1790     case Qt::ImFont:
1791         return font();
1792     case Qt::ImCursorPosition:
1793         return QVariant(d->m_cursor);
1794     case Qt::ImSurroundingText:
1795         if (d->m_echoMode == PasswordEchoOnEdit && !d->m_passwordEchoEditing) {
1796             return QVariant(displayText());
1797         } else {
1798             return QVariant(d->realText());
1799         }
1800     case Qt::ImCurrentSelection:
1801         return QVariant(selectedText());
1802     case Qt::ImMaximumTextLength:
1803         return QVariant(maxLength());
1804     case Qt::ImAnchorPosition:
1805         if (d->selectionStart() == d->selectionEnd())
1806             return QVariant(d->m_cursor);
1807         else if (d->selectionStart() == d->m_cursor)
1808             return QVariant(d->selectionEnd());
1809         else
1810             return QVariant(d->selectionStart());
1811     default:
1812         return QVariant();
1813     }
1814 }
1815
1816 /*!
1817     \qmlmethod void QtQuick2::TextInput::deselect()
1818
1819     Removes active text selection.
1820 */
1821 void QQuickTextInput::deselect()
1822 {
1823     Q_D(QQuickTextInput);
1824     d->deselect();
1825 }
1826
1827 /*!
1828     \qmlmethod void QtQuick2::TextInput::selectAll()
1829
1830     Causes all text to be selected.
1831 */
1832 void QQuickTextInput::selectAll()
1833 {
1834     Q_D(QQuickTextInput);
1835     d->setSelection(0, text().length());
1836 }
1837
1838 /*!
1839     \qmlmethod void QtQuick2::TextInput::isRightToLeft(int start, int end)
1840
1841     Returns true if the natural reading direction of the editor text
1842     found between positions \a start and \a end is right to left.
1843 */
1844 bool QQuickTextInput::isRightToLeft(int start, int end)
1845 {
1846     if (start > end) {
1847         qmlInfo(this) << "isRightToLeft(start, end) called with the end property being smaller than the start.";
1848         return false;
1849     } else {
1850         return text().mid(start, end - start).isRightToLeft();
1851     }
1852 }
1853
1854 #ifndef QT_NO_CLIPBOARD
1855 /*!
1856     \qmlmethod QtQuick2::TextInput::cut()
1857
1858     Moves the currently selected text to the system clipboard.
1859 */
1860 void QQuickTextInput::cut()
1861 {
1862     Q_D(QQuickTextInput);
1863     d->copy();
1864     d->del();
1865 }
1866
1867 /*!
1868     \qmlmethod QtQuick2::TextInput::copy()
1869
1870     Copies the currently selected text to the system clipboard.
1871 */
1872 void QQuickTextInput::copy()
1873 {
1874     Q_D(QQuickTextInput);
1875     d->copy();
1876 }
1877
1878 /*!
1879     \qmlmethod QtQuick2::TextInput::paste()
1880
1881     Replaces the currently selected text by the contents of the system clipboard.
1882 */
1883 void QQuickTextInput::paste()
1884 {
1885     Q_D(QQuickTextInput);
1886     if (!d->m_readOnly)
1887         d->paste();
1888 }
1889 #endif // QT_NO_CLIPBOARD
1890
1891 /*!
1892     Undoes the last operation if undo is \l {canUndo}{available}. Deselects any
1893     current selection, and updates the selection start to the current cursor
1894     position.
1895 */
1896
1897 void QQuickTextInput::undo()
1898 {
1899     Q_D(QQuickTextInput);
1900     if (!d->m_readOnly) {
1901         d->internalUndo();
1902         d->finishChange(-1, true);
1903     }
1904 }
1905
1906 /*!
1907     Redoes the last operation if redo is \l {canRedo}{available}.
1908 */
1909
1910 void QQuickTextInput::redo()
1911 {
1912     Q_D(QQuickTextInput);
1913     if (!d->m_readOnly) {
1914         d->internalRedo();
1915         d->finishChange();
1916     }
1917 }
1918
1919 /*!
1920     \qmlmethod void QtQuick2::TextInput::insert(int position, string text)
1921
1922     Inserts \a text into the TextInput at position.
1923 */
1924
1925 void QQuickTextInput::insert(int position, const QString &text)
1926 {
1927     Q_D(QQuickTextInput);
1928     if (d->m_echoMode == QQuickTextInput::Password) {
1929         int delay = qGuiApp->styleHints()->passwordMaskDelay();
1930         if (delay > 0)
1931             d->m_passwordEchoTimer.start(delay, this);
1932     }
1933     if (position < 0 || position > d->m_text.length())
1934         return;
1935
1936     const int priorState = d->m_undoState;
1937
1938     QString insertText = text;
1939
1940     if (d->hasSelectedText()) {
1941         d->addCommand(QQuickTextInputPrivate::Command(
1942                 QQuickTextInputPrivate::SetSelection, d->m_cursor, 0, d->m_selstart, d->m_selend));
1943     }
1944     if (d->m_maskData) {
1945         insertText = d->maskString(position, insertText);
1946         for (int i = 0; i < insertText.length(); ++i) {
1947             d->addCommand(QQuickTextInputPrivate::Command(
1948                     QQuickTextInputPrivate::DeleteSelection, position + i, d->m_text.at(position + i), -1, -1));
1949             d->addCommand(QQuickTextInputPrivate::Command(
1950                     QQuickTextInputPrivate::Insert, position + i, insertText.at(i), -1, -1));
1951         }
1952         d->m_text.replace(position, insertText.length(), insertText);
1953         if (!insertText.isEmpty())
1954             d->m_textDirty = true;
1955         if (position < d->m_selend && position + insertText.length() > d->m_selstart)
1956             d->m_selDirty = true;
1957     } else {
1958         int remaining = d->m_maxLength - d->m_text.length();
1959         if (remaining != 0) {
1960             insertText = insertText.left(remaining);
1961             d->m_text.insert(position, insertText);
1962             for (int i = 0; i < insertText.length(); ++i)
1963                d->addCommand(QQuickTextInputPrivate::Command(
1964                     QQuickTextInputPrivate::Insert, position + i, insertText.at(i), -1, -1));
1965             if (d->m_cursor >= position)
1966                 d->m_cursor += insertText.length();
1967             if (d->m_selstart >= position)
1968                 d->m_selstart += insertText.length();
1969             if (d->m_selend >= position)
1970                 d->m_selend += insertText.length();
1971             d->m_textDirty = true;
1972             if (position >= d->m_selstart && position <= d->m_selend)
1973                 d->m_selDirty = true;
1974         }
1975     }
1976
1977     d->addCommand(QQuickTextInputPrivate::Command(
1978             QQuickTextInputPrivate::SetSelection, d->m_cursor, 0, d->m_selstart, d->m_selend));
1979     d->finishChange(priorState);
1980
1981     if (d->lastSelectionStart != d->lastSelectionEnd) {
1982         if (d->m_selstart != d->lastSelectionStart) {
1983             d->lastSelectionStart = d->m_selstart;
1984             emit selectionStartChanged();
1985         }
1986         if (d->m_selend != d->lastSelectionEnd) {
1987             d->lastSelectionEnd = d->m_selend;
1988             emit selectionEndChanged();
1989         }
1990     }
1991 }
1992
1993 /*!
1994     \qmlmethod string QtQuick2::TextInput::getText(int start, int end)
1995
1996     Removes the section of text that is between the \a start and \a end positions from the TextInput.
1997 */
1998
1999 void QQuickTextInput::remove(int start, int end)
2000 {
2001     Q_D(QQuickTextInput);
2002
2003     start = qBound(0, start, d->m_text.length());
2004     end = qBound(0, end, d->m_text.length());
2005
2006     if (start > end)
2007         qSwap(start, end);
2008     else if (start == end)
2009         return;
2010
2011     if (start < d->m_selend && end > d->m_selstart)
2012         d->m_selDirty = true;
2013
2014     const int priorState = d->m_undoState;
2015
2016     d->addCommand(QQuickTextInputPrivate::Command(
2017             QQuickTextInputPrivate::SetSelection, d->m_cursor, 0, d->m_selstart, d->m_selend));
2018
2019     if (start <= d->m_cursor && d->m_cursor < end) {
2020         // cursor is within the selection. Split up the commands
2021         // to be able to restore the correct cursor position
2022         for (int i = d->m_cursor; i >= start; --i) {
2023             d->addCommand(QQuickTextInputPrivate::Command(
2024                     QQuickTextInputPrivate::DeleteSelection, i, d->m_text.at(i), -1, 1));
2025         }
2026         for (int i = end - 1; i > d->m_cursor; --i) {
2027             d->addCommand(QQuickTextInputPrivate::Command(
2028                     QQuickTextInputPrivate::DeleteSelection, i - d->m_cursor + start - 1, d->m_text.at(i), -1, -1));
2029         }
2030     } else {
2031         for (int i = end - 1; i >= start; --i) {
2032             d->addCommand(QQuickTextInputPrivate::Command(
2033                     QQuickTextInputPrivate::RemoveSelection, i, d->m_text.at(i), -1, -1));
2034         }
2035     }
2036     if (d->m_maskData) {
2037         d->m_text.replace(start, end - start,  d->clearString(start, end - start));
2038         for (int i = 0; i < end - start; ++i) {
2039             d->addCommand(QQuickTextInputPrivate::Command(
2040                     QQuickTextInputPrivate::Insert, start + i, d->m_text.at(start + i), -1, -1));
2041         }
2042     } else {
2043         d->m_text.remove(start, end - start);
2044
2045         if (d->m_cursor > start)
2046             d->m_cursor -= qMin(d->m_cursor, end) - start;
2047         if (d->m_selstart > start)
2048             d->m_selstart -= qMin(d->m_selstart, end) - start;
2049         if (d->m_selend > end)
2050             d->m_selend -= qMin(d->m_selend, end) - start;
2051     }
2052     d->addCommand(QQuickTextInputPrivate::Command(
2053             QQuickTextInputPrivate::SetSelection, d->m_cursor, 0, d->m_selstart, d->m_selend));
2054
2055     d->m_textDirty = true;
2056     d->finishChange(priorState);
2057
2058     if (d->lastSelectionStart != d->lastSelectionEnd) {
2059         if (d->m_selstart != d->lastSelectionStart) {
2060             d->lastSelectionStart = d->m_selstart;
2061             emit selectionStartChanged();
2062         }
2063         if (d->m_selend != d->lastSelectionEnd) {
2064             d->lastSelectionEnd = d->m_selend;
2065             emit selectionEndChanged();
2066         }
2067     }
2068 }
2069
2070
2071 /*!
2072     \qmlmethod void QtQuick2::TextInput::selectWord()
2073
2074     Causes the word closest to the current cursor position to be selected.
2075 */
2076 void QQuickTextInput::selectWord()
2077 {
2078     Q_D(QQuickTextInput);
2079     d->selectWordAtPos(d->m_cursor);
2080 }
2081
2082 /*!
2083     \qmlproperty bool QtQuick2::TextInput::smooth
2084
2085     This property holds whether the text is smoothly scaled or transformed.
2086
2087     Smooth filtering gives better visual quality, but is slower.  If
2088     the item is displayed at its natural size, this property has no visual or
2089     performance effect.
2090
2091     \note Generally scaling artifacts are only visible if the item is stationary on
2092     the screen.  A common pattern when animating an item is to disable smooth
2093     filtering at the beginning of the animation and reenable it at the conclusion.
2094 */
2095
2096 /*!
2097    \qmlproperty string QtQuick2::TextInput::passwordCharacter
2098
2099    This is the character displayed when echoMode is set to Password or
2100    PasswordEchoOnEdit. By default it is an asterisk.
2101
2102    If this property is set to a string with more than one character,
2103    the first character is used. If the string is empty, the value
2104    is ignored and the property is not set.
2105 */
2106 QString QQuickTextInput::passwordCharacter() const
2107 {
2108     Q_D(const QQuickTextInput);
2109     return QString(d->m_passwordCharacter);
2110 }
2111
2112 void QQuickTextInput::setPasswordCharacter(const QString &str)
2113 {
2114     Q_D(QQuickTextInput);
2115     if (str.length() < 1)
2116         return;
2117     d->m_passwordCharacter = str.constData()[0];
2118     if (d->m_echoMode == Password || d->m_echoMode == PasswordEchoOnEdit)
2119         d->updateDisplayText();
2120     emit passwordCharacterChanged();
2121 }
2122
2123 /*!
2124    \qmlproperty string QtQuick2::TextInput::displayText
2125
2126    This is the text displayed in the TextInput.
2127
2128    If \l echoMode is set to TextInput::Normal, this holds the
2129    same value as the TextInput::text property. Otherwise,
2130    this property holds the text visible to the user, while
2131    the \l text property holds the actual entered text.
2132 */
2133 QString QQuickTextInput::displayText() const
2134 {
2135     Q_D(const QQuickTextInput);
2136     return d->m_textLayout.text();
2137 }
2138
2139 /*!
2140     \qmlproperty bool QtQuick2::TextInput::selectByMouse
2141
2142     Defaults to false.
2143
2144     If true, the user can use the mouse to select text in some
2145     platform-specific way. Note that for some platforms this may
2146     not be an appropriate interaction (eg. may conflict with how
2147     the text needs to behave inside a Flickable.
2148 */
2149 bool QQuickTextInput::selectByMouse() const
2150 {
2151     Q_D(const QQuickTextInput);
2152     return d->selectByMouse;
2153 }
2154
2155 void QQuickTextInput::setSelectByMouse(bool on)
2156 {
2157     Q_D(QQuickTextInput);
2158     if (d->selectByMouse != on) {
2159         d->selectByMouse = on;
2160         emit selectByMouseChanged(on);
2161     }
2162 }
2163
2164 /*!
2165     \qmlproperty enum QtQuick2::TextInput::mouseSelectionMode
2166
2167     Specifies how text should be selected using a mouse.
2168
2169     \list
2170     \li TextInput.SelectCharacters - The selection is updated with individual characters. (Default)
2171     \li TextInput.SelectWords - The selection is updated with whole words.
2172     \endlist
2173
2174     This property only applies when \l selectByMouse is true.
2175 */
2176
2177 QQuickTextInput::SelectionMode QQuickTextInput::mouseSelectionMode() const
2178 {
2179     Q_D(const QQuickTextInput);
2180     return d->mouseSelectionMode;
2181 }
2182
2183 void QQuickTextInput::setMouseSelectionMode(SelectionMode mode)
2184 {
2185     Q_D(QQuickTextInput);
2186     if (d->mouseSelectionMode != mode) {
2187         d->mouseSelectionMode = mode;
2188         emit mouseSelectionModeChanged(mode);
2189     }
2190 }
2191
2192 /*!
2193     \qmlproperty bool QtQuick2::TextInput::persistentSelection
2194
2195     Whether the TextInput should keep its selection when it loses active focus to another
2196     item in the scene. By default this is set to false;
2197 */
2198
2199 bool QQuickTextInput::persistentSelection() const
2200 {
2201     Q_D(const QQuickTextInput);
2202     return d->persistentSelection;
2203 }
2204
2205 void QQuickTextInput::setPersistentSelection(bool on)
2206 {
2207     Q_D(QQuickTextInput);
2208     if (d->persistentSelection == on)
2209         return;
2210     d->persistentSelection = on;
2211     emit persistentSelectionChanged();
2212 }
2213
2214 /*!
2215     \qmlproperty bool QtQuick2::TextInput::canPaste
2216
2217     Returns true if the TextInput is writable and the content of the clipboard is
2218     suitable for pasting into the TextInput.
2219 */
2220 bool QQuickTextInput::canPaste() const
2221 {
2222     Q_D(const QQuickTextInput);
2223     if (!d->canPasteValid) {
2224         if (const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData())
2225             const_cast<QQuickTextInputPrivate *>(d)->canPaste = !d->m_readOnly && mimeData->hasText();
2226         const_cast<QQuickTextInputPrivate *>(d)->canPasteValid = true;
2227     }
2228     return d->canPaste;
2229 }
2230
2231 /*!
2232     \qmlproperty bool QtQuick2::TextInput::canUndo
2233
2234     Returns true if the TextInput is writable and there are previous operations
2235     that can be undone.
2236 */
2237
2238 bool QQuickTextInput::canUndo() const
2239 {
2240     Q_D(const QQuickTextInput);
2241     return d->canUndo;
2242 }
2243
2244 /*!
2245     \qmlproperty bool QtQuick2::TextInput::canRedo
2246
2247     Returns true if the TextInput is writable and there are \l {undo}{undone}
2248     operations that can be redone.
2249 */
2250
2251 bool QQuickTextInput::canRedo() const
2252 {
2253     Q_D(const QQuickTextInput);
2254     return d->canRedo;
2255 }
2256
2257 /*!
2258     \qmlproperty real QtQuick2::TextInput::contentWidth
2259
2260     Returns the width of the text, including the width past the width
2261     which is covered due to insufficient wrapping if \l wrapMode is set.
2262 */
2263
2264 qreal QQuickTextInput::contentWidth() const
2265 {
2266     Q_D(const QQuickTextInput);
2267     return d->boundingRect.width();
2268 }
2269
2270 /*!
2271     \qmlproperty real QtQuick2::TextInput::contentHeight
2272
2273     Returns the height of the text, including the height past the height
2274     that is covered if the text does not fit within the set height.
2275 */
2276
2277 qreal QQuickTextInput::contentHeight() const
2278 {
2279     Q_D(const QQuickTextInput);
2280     return d->boundingRect.height();
2281 }
2282
2283 void QQuickTextInput::moveCursorSelection(int position)
2284 {
2285     Q_D(QQuickTextInput);
2286     d->moveCursor(position, true);
2287 }
2288
2289 /*!
2290     \qmlmethod void QtQuick2::TextInput::moveCursorSelection(int position, SelectionMode mode = TextInput.SelectCharacters)
2291
2292     Moves the cursor to \a position and updates the selection according to the optional \a mode
2293     parameter.  (To only move the cursor, set the \l cursorPosition property.)
2294
2295     When this method is called it additionally sets either the
2296     selectionStart or the selectionEnd (whichever was at the previous cursor position)
2297     to the specified position. This allows you to easily extend and contract the selected
2298     text range.
2299
2300     The selection mode specifies whether the selection is updated on a per character or a per word
2301     basis.  If not specified the selection mode will default to TextInput.SelectCharacters.
2302
2303     \list
2304     \li TextInput.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
2305     the previous cursor position) to the specified position.
2306     \li TextInput.SelectWords - Sets the selectionStart and selectionEnd to include all
2307     words between the specified position and the previous cursor position.  Words partially in the
2308     range are included.
2309     \endlist
2310
2311     For example, take this sequence of calls:
2312
2313     \code
2314         cursorPosition = 5
2315         moveCursorSelection(9, TextInput.SelectCharacters)
2316         moveCursorSelection(7, TextInput.SelectCharacters)
2317     \endcode
2318
2319     This moves the cursor to position 5, extend the selection end from 5 to 9
2320     and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
2321     selected (the 6th and 7th characters).
2322
2323     The same sequence with TextInput.SelectWords will extend the selection start to a word boundary
2324     before or on position 5 and extend the selection end to a word boundary on or past position 9.
2325 */
2326 void QQuickTextInput::moveCursorSelection(int pos, SelectionMode mode)
2327 {
2328     Q_D(QQuickTextInput);
2329
2330     if (mode == SelectCharacters) {
2331         d->moveCursor(pos, true);
2332     } else if (pos != d->m_cursor){
2333         const int cursor = d->m_cursor;
2334         int anchor;
2335         if (!d->hasSelectedText())
2336             anchor = d->m_cursor;
2337         else if (d->selectionStart() == d->m_cursor)
2338             anchor = d->selectionEnd();
2339         else
2340             anchor = d->selectionStart();
2341
2342         if (anchor < pos || (anchor == pos && cursor < pos)) {
2343             const QString text = this->text();
2344             QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
2345             finder.setPosition(anchor);
2346
2347             const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
2348             if (anchor < text.length() && (!(reasons & QTextBoundaryFinder::StartWord)
2349                     || ((reasons & QTextBoundaryFinder::EndWord) && anchor > cursor))) {
2350                 finder.toPreviousBoundary();
2351             }
2352             anchor = finder.position() != -1 ? finder.position() : 0;
2353
2354             finder.setPosition(pos);
2355             if (pos > 0 && !finder.boundaryReasons())
2356                 finder.toNextBoundary();
2357             const int cursor = finder.position() != -1 ? finder.position() : text.length();
2358
2359             d->setSelection(anchor, cursor - anchor);
2360         } else if (anchor > pos || (anchor == pos && cursor > pos)) {
2361             const QString text = this->text();
2362             QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
2363             finder.setPosition(anchor);
2364
2365             const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
2366             if (anchor > 0 && (!(reasons & QTextBoundaryFinder::EndWord)
2367                     || ((reasons & QTextBoundaryFinder::StartWord) && anchor < cursor))) {
2368                 finder.toNextBoundary();
2369             }
2370
2371             anchor = finder.position() != -1 ? finder.position() : text.length();
2372
2373             finder.setPosition(pos);
2374             if (pos < text.length() && !finder.boundaryReasons())
2375                  finder.toPreviousBoundary();
2376             const int cursor = finder.position() != -1 ? finder.position() : 0;
2377
2378             d->setSelection(anchor, cursor - anchor);
2379         }
2380     }
2381 }
2382
2383 /*!
2384     \qmlmethod void QtQuick2::TextInput::openSoftwareInputPanel()
2385
2386     Opens software input panels like virtual keyboards for typing, useful for
2387     customizing when you want the input keyboard to be shown and hidden in
2388     your application.
2389
2390     By default the opening of input panels follows the platform style. Input panels are
2391     always closed if no editor has active focus.
2392
2393     You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
2394     and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
2395     the behavior you want.
2396
2397     Only relevant on platforms, which provide virtual keyboards.
2398
2399     \qml
2400         import QtQuick 2.0
2401         TextInput {
2402             id: textInput
2403             text: "Hello world!"
2404             activeFocusOnPress: false
2405             MouseArea {
2406                 anchors.fill: parent
2407                 onClicked: {
2408                     if (!textInput.activeFocus) {
2409                         textInput.forceActiveFocus()
2410                         textInput.openSoftwareInputPanel();
2411                     } else {
2412                         textInput.focus = false;
2413                     }
2414                 }
2415                 onPressAndHold: textInput.closeSoftwareInputPanel();
2416             }
2417         }
2418     \endqml
2419 */
2420 void QQuickTextInput::openSoftwareInputPanel()
2421 {
2422     if (qGuiApp)
2423         qGuiApp->inputMethod()->show();
2424 }
2425
2426 /*!
2427     \qmlmethod void QtQuick2::TextInput::closeSoftwareInputPanel()
2428
2429     Closes a software input panel like a virtual keyboard shown on the screen, useful
2430     for customizing when you want the input keyboard to be shown and hidden in
2431     your application.
2432
2433     By default the opening of input panels follows the platform style. Input panels are
2434     always closed if no editor has active focus.
2435
2436     You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
2437     and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
2438     the behavior you want.
2439
2440     Only relevant on platforms, which provide virtual keyboards.
2441
2442     \qml
2443         import QtQuick 2.0
2444         TextInput {
2445             id: textInput
2446             text: "Hello world!"
2447             activeFocusOnPress: false
2448             MouseArea {
2449                 anchors.fill: parent
2450                 onClicked: {
2451                     if (!textInput.activeFocus) {
2452                         textInput.forceActiveFocus();
2453                         textInput.openSoftwareInputPanel();
2454                     } else {
2455                         textInput.focus = false;
2456                     }
2457                 }
2458                 onPressAndHold: textInput.closeSoftwareInputPanel();
2459             }
2460         }
2461     \endqml
2462 */
2463 void QQuickTextInput::closeSoftwareInputPanel()
2464 {
2465     if (qGuiApp)
2466         qGuiApp->inputMethod()->hide();
2467 }
2468
2469 void QQuickTextInput::focusInEvent(QFocusEvent *event)
2470 {
2471     Q_D(const QQuickTextInput);
2472     if (d->focusOnPress && !d->m_readOnly)
2473         openSoftwareInputPanel();
2474     QQuickImplicitSizeItem::focusInEvent(event);
2475 }
2476
2477 void QQuickTextInput::itemChange(ItemChange change, const ItemChangeData &value)
2478 {
2479     Q_D(QQuickTextInput);
2480     if (change == ItemActiveFocusHasChanged) {
2481         bool hasFocus = value.boolValue;
2482         setCursorVisible(hasFocus); // ### refactor:  && d->canvas && d->canvas->hasFocus()
2483         if (!hasFocus && (d->m_passwordEchoEditing || d->m_passwordEchoTimer.isActive())) {
2484             d->updatePasswordEchoEditing(false);//QQuickTextInputPrivate sets it on key events, but doesn't deal with focus events
2485         }
2486
2487         if (!hasFocus) {
2488             if (!d->persistentSelection)
2489                 d->deselect();
2490             disconnect(qApp->inputMethod(), SIGNAL(inputDirectionChanged(Qt::LayoutDirection)),
2491                        this, SLOT(q_updateAlignment()));
2492         } else {
2493             q_updateAlignment();
2494             connect(qApp->inputMethod(), SIGNAL(inputDirectionChanged(Qt::LayoutDirection)),
2495                     this, SLOT(q_updateAlignment()));
2496         }
2497     }
2498     QQuickItem::itemChange(change, value);
2499 }
2500
2501 /*!
2502     \qmlproperty bool QtQuick2::TextInput::inputMethodComposing
2503
2504
2505     This property holds whether the TextInput has partial text input from an
2506     input method.
2507
2508     While it is composing an input method may rely on mouse or key events from
2509     the TextInput to edit or commit the partial text.  This property can be
2510     used to determine when to disable events handlers that may interfere with
2511     the correct operation of an input method.
2512 */
2513 bool QQuickTextInput::isInputMethodComposing() const
2514 {
2515     Q_D(const QQuickTextInput);
2516     return d->preeditAreaText().length() > 0;
2517 }
2518
2519 void QQuickTextInputPrivate::init()
2520 {
2521     Q_Q(QQuickTextInput);
2522     q->setSmooth(smooth);
2523     q->setAcceptedMouseButtons(Qt::LeftButton);
2524     q->setFlag(QQuickItem::ItemAcceptsInputMethod);
2525     q->setFlag(QQuickItem::ItemHasContents);
2526 #ifndef QT_NO_CLIPBOARD
2527     q->connect(QGuiApplication::clipboard(), SIGNAL(dataChanged()),
2528             q, SLOT(q_canPasteChanged()));
2529 #endif // QT_NO_CLIPBOARD
2530
2531     lastSelectionStart = 0;
2532     lastSelectionEnd = 0;
2533     determineHorizontalAlignment();
2534
2535     if (!qmlDisableDistanceField()) {
2536         QTextOption option = m_textLayout.textOption();
2537         option.setUseDesignMetrics(true);
2538         m_textLayout.setTextOption(option);
2539     }
2540 }
2541
2542 void QQuickTextInput::updateCursorRectangle()
2543 {
2544     Q_D(QQuickTextInput);
2545     if (!isComponentComplete())
2546         return;
2547
2548     d->updateHorizontalScroll();
2549     d->updateVerticalScroll();
2550     d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
2551     update();
2552     emit cursorRectangleChanged();
2553     if (d->cursorItem) {
2554         QRectF r = cursorRectangle();
2555         d->cursorItem->setPos(r.topLeft());
2556         d->cursorItem->setHeight(r.height());
2557     }
2558     updateInputMethod(Qt::ImCursorRectangle);
2559 }
2560
2561 void QQuickTextInput::selectionChanged()
2562 {
2563     Q_D(QQuickTextInput);
2564     d->textLayoutDirty = true; //TODO: Only update rect in selection
2565     d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
2566     update();
2567     emit selectedTextChanged();
2568
2569     if (d->lastSelectionStart != d->selectionStart()) {
2570         d->lastSelectionStart = d->selectionStart();
2571         if (d->lastSelectionStart == -1)
2572             d->lastSelectionStart = d->m_cursor;
2573         emit selectionStartChanged();
2574     }
2575     if (d->lastSelectionEnd != d->selectionEnd()) {
2576         d->lastSelectionEnd = d->selectionEnd();
2577         if (d->lastSelectionEnd == -1)
2578             d->lastSelectionEnd = d->m_cursor;
2579         emit selectionEndChanged();
2580     }
2581 }
2582
2583 void QQuickTextInputPrivate::showCursor()
2584 {
2585     if (textNode != 0 && textNode->cursorNode() != 0)
2586         textNode->cursorNode()->setColor(color);
2587 }
2588
2589 void QQuickTextInputPrivate::hideCursor()
2590 {
2591     if (textNode != 0 && textNode->cursorNode() != 0)
2592         textNode->cursorNode()->setColor(QColor(0, 0, 0, 0));
2593 }
2594
2595 QRectF QQuickTextInput::boundingRect() const
2596 {
2597     Q_D(const QQuickTextInput);
2598
2599     int cursorWidth = d->cursorItem ? d->cursorItem->width() : 1;
2600
2601     // Could include font max left/right bearings to either side of rectangle.
2602     QRectF r = QQuickImplicitSizeItem::boundingRect();
2603     r.setRight(r.right() + cursorWidth);
2604     return r;
2605 }
2606
2607 void QQuickTextInput::q_canPasteChanged()
2608 {
2609     Q_D(QQuickTextInput);
2610     bool old = d->canPaste;
2611 #ifndef QT_NO_CLIPBOARD
2612     if (const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData())
2613         d->canPaste = !d->m_readOnly && mimeData->hasText();
2614     else
2615         d->canPaste = false;
2616 #endif
2617
2618     bool changed = d->canPaste != old || !d->canPasteValid;
2619     d->canPasteValid = true;
2620     if (changed)
2621         emit canPasteChanged();
2622
2623 }
2624
2625 void QQuickTextInput::q_updateAlignment()
2626 {
2627     Q_D(QQuickTextInput);
2628     if (d->determineHorizontalAlignment()) {
2629         d->updateLayout();
2630         updateCursorRectangle();
2631     }
2632 }
2633
2634 // ### these should come from QStyleHints
2635 const int textCursorWidth = 1;
2636 const bool fullWidthSelection = true;
2637
2638 /*!
2639     \internal
2640
2641     Updates the display text based of the current edit text
2642     If the text has changed will emit displayTextChanged()
2643 */
2644 void QQuickTextInputPrivate::updateDisplayText(bool forceUpdate)
2645 {
2646     QString orig = m_textLayout.text();
2647     QString str;
2648     if (m_echoMode == QQuickTextInput::NoEcho)
2649         str = QString::fromLatin1("");
2650     else
2651         str = m_text;
2652
2653     if (m_echoMode == QQuickTextInput::Password) {
2654          str.fill(m_passwordCharacter);
2655         if (m_passwordEchoTimer.isActive() && m_cursor > 0 && m_cursor <= m_text.length()) {
2656             int cursor = m_cursor - 1;
2657             QChar uc = m_text.at(cursor);
2658             str[cursor] = uc;
2659             if (cursor > 0 && uc.unicode() >= 0xdc00 && uc.unicode() < 0xe000) {
2660                 // second half of a surrogate, check if we have the first half as well,
2661                 // if yes restore both at once
2662                 uc = m_text.at(cursor - 1);
2663                 if (uc.unicode() >= 0xd800 && uc.unicode() < 0xdc00)
2664                     str[cursor - 1] = uc;
2665             }
2666         }
2667     } else if (m_echoMode == QQuickTextInput::PasswordEchoOnEdit && !m_passwordEchoEditing) {
2668         str.fill(m_passwordCharacter);
2669     }
2670
2671     // replace certain non-printable characters with spaces (to avoid
2672     // drawing boxes when using fonts that don't have glyphs for such
2673     // characters)
2674     QChar* uc = str.data();
2675     for (int i = 0; i < (int)str.length(); ++i) {
2676         if ((uc[i] < 0x20 && uc[i] != 0x09)
2677             || uc[i] == QChar::LineSeparator
2678             || uc[i] == QChar::ParagraphSeparator
2679             || uc[i] == QChar::ObjectReplacementCharacter)
2680             uc[i] = QChar(0x0020);
2681     }
2682
2683     if (str != orig || forceUpdate) {
2684         m_textLayout.setText(str);
2685         updateLayout(); // polish?
2686         emit q_func()->displayTextChanged();
2687     }
2688 }
2689
2690 qreal QQuickTextInputPrivate::getImplicitWidth() const
2691 {
2692     Q_Q(const QQuickTextInput);
2693     if (!requireImplicitWidth) {
2694         QQuickTextInputPrivate *d = const_cast<QQuickTextInputPrivate *>(this);
2695         d->requireImplicitWidth = true;
2696
2697         if (q->isComponentComplete()) {
2698             // One time cost, only incurred if implicitWidth is first requested after
2699             // componentComplete.
2700             QTextLayout layout(m_text);
2701
2702             QTextOption option = m_textLayout.textOption();
2703             option.setTextDirection(m_layoutDirection);
2704             option.setFlags(QTextOption::IncludeTrailingSpaces);
2705             option.setWrapMode(QTextOption::WrapMode(wrapMode));
2706             option.setAlignment(Qt::Alignment(q->effectiveHAlign()));
2707             layout.setTextOption(option);
2708             layout.setFont(font);
2709             layout.setPreeditArea(m_textLayout.preeditAreaPosition(), m_textLayout.preeditAreaText());
2710             layout.beginLayout();
2711
2712             QTextLine line = layout.createLine();
2713             line.setLineWidth(INT_MAX);
2714             d->implicitWidth = qCeil(line.naturalTextWidth());
2715
2716             layout.endLayout();
2717         }
2718     }
2719     return implicitWidth;
2720 }
2721
2722 void QQuickTextInputPrivate::updateLayout()
2723 {
2724     Q_Q(QQuickTextInput);
2725
2726     if (!q->isComponentComplete())
2727         return;
2728
2729     const QRectF previousRect = boundingRect;
2730
2731     QTextOption option = m_textLayout.textOption();
2732     option.setTextDirection(layoutDirection());
2733     option.setWrapMode(QTextOption::WrapMode(wrapMode));
2734     option.setAlignment(Qt::Alignment(q->effectiveHAlign()));
2735     m_textLayout.setTextOption(option);
2736     m_textLayout.setFont(font);
2737
2738     boundingRect = QRectF();
2739     m_textLayout.beginLayout();
2740     QTextLine line = m_textLayout.createLine();
2741     if (requireImplicitWidth) {
2742         line.setLineWidth(INT_MAX);
2743         const bool wasInLayout = inLayout;
2744         inLayout = true;
2745         q->setImplicitWidth(qCeil(line.naturalTextWidth()));
2746         inLayout = wasInLayout;
2747         if (inLayout)       // probably the result of a binding loop, but by letting it
2748             return;         // get this far we'll get a warning to that effect.
2749     }
2750     qreal lineWidth = q->widthValid() ? q->width() : INT_MAX;
2751     qreal height = 0;
2752     do {
2753         line.setLineWidth(lineWidth);
2754         line.setPosition(QPointF(line.position().x(), height));
2755         boundingRect = boundingRect.united(line.naturalTextRect());
2756
2757         height += line.height();
2758         line = m_textLayout.createLine();
2759     } while (line.isValid());
2760     m_textLayout.endLayout();
2761
2762     option.setWrapMode(QTextOption::NoWrap);
2763     m_textLayout.setTextOption(option);
2764
2765     textLayoutDirty = true;
2766
2767     updateType = UpdatePaintNode;
2768     q->update();
2769
2770     if (!requireImplicitWidth && !q->widthValid())
2771         q->setImplicitSize(qCeil(boundingRect.width()), qCeil(boundingRect.height()));
2772     else
2773         q->setImplicitHeight(qCeil(boundingRect.height()));
2774
2775     if (previousRect != boundingRect)
2776         emit q->contentSizeChanged();
2777 }
2778
2779 #ifndef QT_NO_CLIPBOARD
2780 /*!
2781     \internal
2782
2783     Copies the currently selected text into the clipboard using the given
2784     \a mode.
2785
2786     \note If the echo mode is set to a mode other than Normal then copy
2787     will not work.  This is to prevent using copy as a method of bypassing
2788     password features of the line control.
2789 */
2790 void QQuickTextInputPrivate::copy(QClipboard::Mode mode) const
2791 {
2792     QString t = selectedText();
2793     if (!t.isEmpty() && m_echoMode == QQuickTextInput::Normal) {
2794         QGuiApplication::clipboard()->setText(t, mode);
2795     }
2796 }
2797
2798 /*!
2799     \internal
2800
2801     Inserts the text stored in the application clipboard into the line
2802     control.
2803
2804     \sa insert()
2805 */
2806 void QQuickTextInputPrivate::paste(QClipboard::Mode clipboardMode)
2807 {
2808     QString clip = QGuiApplication::clipboard()->text(clipboardMode);
2809     if (!clip.isEmpty() || hasSelectedText()) {
2810         separate(); //make it a separate undo/redo command
2811         insert(clip);
2812         separate();
2813     }
2814 }
2815
2816 #endif // !QT_NO_CLIPBOARD
2817
2818 /*!
2819     \internal
2820 */
2821 void QQuickTextInputPrivate::commitPreedit()
2822 {
2823     if (!composeMode())
2824         return;
2825
2826     qApp->inputMethod()->commit();
2827
2828     if (!composeMode())
2829         return;
2830
2831     m_preeditCursor = 0;
2832     m_textLayout.setPreeditArea(-1, QString());
2833     m_textLayout.clearAdditionalFormats();
2834     updateLayout();
2835 }
2836
2837 /*!
2838     \internal
2839
2840     Handles the behavior for the backspace key or function.
2841     Removes the current selection if there is a selection, otherwise
2842     removes the character prior to the cursor position.
2843
2844     \sa del()
2845 */
2846 void QQuickTextInputPrivate::backspace()
2847 {
2848     int priorState = m_undoState;
2849     if (hasSelectedText()) {
2850         removeSelectedText();
2851     } else if (m_cursor) {
2852             --m_cursor;
2853             if (m_maskData)
2854                 m_cursor = prevMaskBlank(m_cursor);
2855             QChar uc = m_text.at(m_cursor);
2856             if (m_cursor > 0 && uc.unicode() >= 0xdc00 && uc.unicode() < 0xe000) {
2857                 // second half of a surrogate, check if we have the first half as well,
2858                 // if yes delete both at once
2859                 uc = m_text.at(m_cursor - 1);
2860                 if (uc.unicode() >= 0xd800 && uc.unicode() < 0xdc00) {
2861                     internalDelete(true);
2862                     --m_cursor;
2863                 }
2864             }
2865             internalDelete(true);
2866     }
2867     finishChange(priorState);
2868 }
2869
2870 /*!
2871     \internal
2872
2873     Handles the behavior for the delete key or function.
2874     Removes the current selection if there is a selection, otherwise
2875     removes the character after the cursor position.
2876
2877     \sa del()
2878 */
2879 void QQuickTextInputPrivate::del()
2880 {
2881     int priorState = m_undoState;
2882     if (hasSelectedText()) {
2883         removeSelectedText();
2884     } else {
2885         int n = m_textLayout.nextCursorPosition(m_cursor) - m_cursor;
2886         while (n--)
2887             internalDelete();
2888     }
2889     finishChange(priorState);
2890 }
2891
2892 /*!
2893     \internal
2894
2895     Inserts the given \a newText at the current cursor position.
2896     If there is any selected text it is removed prior to insertion of
2897     the new text.
2898 */
2899 void QQuickTextInputPrivate::insert(const QString &newText)
2900 {
2901     int priorState = m_undoState;
2902     removeSelectedText();
2903     internalInsert(newText);
2904     finishChange(priorState);
2905 }
2906
2907 /*!
2908     \internal
2909
2910     Clears the line control text.
2911 */
2912 void QQuickTextInputPrivate::clear()
2913 {
2914     int priorState = m_undoState;
2915     m_selstart = 0;
2916     m_selend = m_text.length();
2917     removeSelectedText();
2918     separate();
2919     finishChange(priorState, /*update*/false, /*edited*/false);
2920 }
2921
2922 /*!
2923     \internal
2924
2925     Sets \a length characters from the given \a start position as selected.
2926     The given \a start position must be within the current text for
2927     the line control.  If \a length characters cannot be selected, then
2928     the selection will extend to the end of the current text.
2929 */
2930 void QQuickTextInputPrivate::setSelection(int start, int length)
2931 {
2932     Q_Q(QQuickTextInput);
2933     commitPreedit();
2934
2935     if (start < 0 || start > (int)m_text.length()){
2936         qWarning("QQuickTextInputPrivate::setSelection: Invalid start position");
2937         return;
2938     }
2939
2940     if (length > 0) {
2941         if (start == m_selstart && start + length == m_selend && m_cursor == m_selend)
2942             return;
2943         m_selstart = start;
2944         m_selend = qMin(start + length, (int)m_text.length());
2945         m_cursor = m_selend;
2946     } else if (length < 0){
2947         if (start == m_selend && start + length == m_selstart && m_cursor == m_selstart)
2948             return;
2949         m_selstart = qMax(start + length, 0);
2950         m_selend = start;
2951         m_cursor = m_selstart;
2952     } else if (m_selstart != m_selend) {
2953         m_selstart = 0;
2954         m_selend = 0;
2955         m_cursor = start;
2956     } else {
2957         m_cursor = start;
2958         emitCursorPositionChanged();
2959         return;
2960     }
2961     emit q->selectionChanged();
2962     emitCursorPositionChanged();
2963     q->updateInputMethod(Qt::ImCursorRectangle | Qt::ImAnchorPosition
2964                         | Qt::ImCursorPosition | Qt::ImCurrentSelection);
2965 }
2966
2967 /*!
2968     \internal
2969
2970     Sets the password echo editing to \a editing.  If password echo editing
2971     is true, then the text of the password is displayed even if the echo
2972     mode is set to QLineEdit::PasswordEchoOnEdit.  Password echoing editing
2973     does not affect other echo modes.
2974 */
2975 void QQuickTextInputPrivate::updatePasswordEchoEditing(bool editing)
2976 {
2977     cancelPasswordEchoTimer();
2978     m_passwordEchoEditing = editing;
2979     updateDisplayText();
2980 }
2981
2982 /*!
2983     \internal
2984
2985     Fixes the current text so that it is valid given any set validators.
2986
2987     Returns true if the text was changed.  Otherwise returns false.
2988 */
2989 bool QQuickTextInputPrivate::fixup() // this function assumes that validate currently returns != Acceptable
2990 {
2991 #ifndef QT_NO_VALIDATOR
2992     if (m_validator) {
2993         QString textCopy = m_text;
2994         int cursorCopy = m_cursor;
2995         m_validator->fixup(textCopy);
2996         if (m_validator->validate(textCopy, cursorCopy) == QValidator::Acceptable) {
2997             if (textCopy != m_text || cursorCopy != m_cursor)
2998                 internalSetText(textCopy, cursorCopy);
2999             return true;
3000         }
3001     }
3002 #endif
3003     return false;
3004 }
3005
3006 /*!
3007     \internal
3008
3009     Moves the cursor to the given position \a pos.   If \a mark is true will
3010     adjust the currently selected text.
3011 */
3012 void QQuickTextInputPrivate::moveCursor(int pos, bool mark)
3013 {
3014     Q_Q(QQuickTextInput);
3015     commitPreedit();
3016
3017     if (pos != m_cursor) {
3018         separate();
3019         if (m_maskData)
3020             pos = pos > m_cursor ? nextMaskBlank(pos) : prevMaskBlank(pos);
3021     }
3022     if (mark) {
3023         int anchor;
3024         if (m_selend > m_selstart && m_cursor == m_selstart)
3025             anchor = m_selend;
3026         else if (m_selend > m_selstart && m_cursor == m_selend)
3027             anchor = m_selstart;
3028         else
3029             anchor = m_cursor;
3030         m_selstart = qMin(anchor, pos);
3031         m_selend = qMax(anchor, pos);
3032     } else {
3033         internalDeselect();
3034     }
3035     m_cursor = pos;
3036     if (mark || m_selDirty) {
3037         m_selDirty = false;
3038         emit q->selectionChanged();
3039     }
3040     emitCursorPositionChanged();
3041     q->updateInputMethod();
3042 }
3043
3044 /*!
3045     \internal
3046
3047     Applies the given input method event \a event to the text of the line
3048     control
3049 */
3050 void QQuickTextInputPrivate::processInputMethodEvent(QInputMethodEvent *event)
3051 {
3052     Q_Q(QQuickTextInput);
3053
3054     int priorState = -1;
3055     bool isGettingInput = !event->commitString().isEmpty()
3056             || event->preeditString() != preeditAreaText()
3057             || event->replacementLength() > 0;
3058     bool cursorPositionChanged = false;
3059     bool selectionChange = false;
3060     m_preeditDirty = event->preeditString() != preeditAreaText();
3061
3062     if (isGettingInput) {
3063         // If any text is being input, remove selected text.
3064         priorState = m_undoState;
3065         if (m_echoMode == QQuickTextInput::PasswordEchoOnEdit && !m_passwordEchoEditing) {
3066             updatePasswordEchoEditing(true);
3067             m_selstart = 0;
3068             m_selend = m_text.length();
3069         }
3070         removeSelectedText();
3071     }
3072
3073     int c = m_cursor; // cursor position after insertion of commit string
3074     if (event->replacementStart() <= 0)
3075         c += event->commitString().length() - qMin(-event->replacementStart(), event->replacementLength());
3076
3077     m_cursor += event->replacementStart();
3078     if (m_cursor < 0)
3079         m_cursor = 0;
3080
3081     // insert commit string
3082     if (event->replacementLength()) {
3083         m_selstart = m_cursor;
3084         m_selend = m_selstart + event->replacementLength();
3085         m_selend = qMin(m_selend, m_text.length());
3086         removeSelectedText();
3087     }
3088     if (!event->commitString().isEmpty()) {
3089         internalInsert(event->commitString());
3090         cursorPositionChanged = true;
3091     }
3092
3093     m_cursor = qBound(0, c, m_text.length());
3094
3095     for (int i = 0; i < event->attributes().size(); ++i) {
3096         const QInputMethodEvent::Attribute &a = event->attributes().at(i);
3097         if (a.type == QInputMethodEvent::Selection) {
3098             m_cursor = qBound(0, a.start + a.length, m_text.length());
3099             if (a.length) {
3100                 m_selstart = qMax(0, qMin(a.start, m_text.length()));
3101                 m_selend = m_cursor;
3102                 if (m_selend < m_selstart) {
3103                     qSwap(m_selstart, m_selend);
3104                 }
3105                 selectionChange = true;
3106             } else {
3107                 m_selstart = m_selend = 0;
3108             }
3109             cursorPositionChanged = true;
3110         }
3111     }
3112 #ifndef QT_NO_IM
3113     m_textLayout.setPreeditArea(m_cursor, event->preeditString());
3114 #endif //QT_NO_IM
3115     const int oldPreeditCursor = m_preeditCursor;
3116     m_preeditCursor = event->preeditString().length();
3117     m_hideCursor = false;
3118     QList<QTextLayout::FormatRange> formats;
3119     for (int i = 0; i < event->attributes().size(); ++i) {
3120         const QInputMethodEvent::Attribute &a = event->attributes().at(i);
3121         if (a.type == QInputMethodEvent::Cursor) {
3122             m_preeditCursor = a.start;
3123             m_hideCursor = !a.length;
3124         } else if (a.type == QInputMethodEvent::TextFormat) {
3125             QTextCharFormat f = qvariant_cast<QTextFormat>(a.value).toCharFormat();
3126             if (f.isValid()) {
3127                 QTextLayout::FormatRange o;
3128                 o.start = a.start + m_cursor;
3129                 o.length = a.length;
3130                 o.format = f;
3131                 formats.append(o);
3132             }
3133         }
3134     }
3135     m_textLayout.setAdditionalFormats(formats);
3136
3137     updateDisplayText(/*force*/ true);
3138     if (cursorPositionChanged) {
3139         emitCursorPositionChanged();
3140     } else if (m_preeditCursor != oldPreeditCursor) {
3141         q->updateCursorRectangle();
3142     }
3143
3144     if (isGettingInput)
3145         finishChange(priorState);
3146
3147     if (selectionChange) {
3148         emit q->selectionChanged();
3149         q->updateInputMethod(Qt::ImCursorRectangle | Qt::ImAnchorPosition
3150                             | Qt::ImCursorPosition | Qt::ImCurrentSelection);
3151     }
3152 }
3153
3154 /*!
3155     \internal
3156
3157     Sets the selection to cover the word at the given cursor position.
3158     The word boundaries are defined by the behavior of QTextLayout::SkipWords
3159     cursor mode.
3160 */
3161 void QQuickTextInputPrivate::selectWordAtPos(int cursor)
3162 {
3163     int next = cursor + 1;
3164     if (next > end())
3165         --next;
3166     int c = m_textLayout.previousCursorPosition(next, QTextLayout::SkipWords);
3167     moveCursor(c, false);
3168     // ## text layout should support end of words.
3169     int end = m_textLayout.nextCursorPosition(c, QTextLayout::SkipWords);
3170     while (end > cursor && m_text[end-1].isSpace())
3171         --end;
3172     moveCursor(end, true);
3173 }
3174
3175 /*!
3176     \internal
3177
3178     Completes a change to the line control text.  If the change is not valid
3179     will undo the line control state back to the given \a validateFromState.
3180
3181     If \a edited is true and the change is valid, will emit textEdited() in
3182     addition to textChanged().  Otherwise only emits textChanged() on a valid
3183     change.
3184
3185     The \a update value is currently unused.
3186 */
3187 bool QQuickTextInputPrivate::finishChange(int validateFromState, bool update, bool /*edited*/)
3188 {
3189     Q_Q(QQuickTextInput);
3190
3191     Q_UNUSED(update)
3192     bool inputMethodAttributesChanged = m_textDirty || m_selDirty;
3193     bool alignmentChanged = false;
3194
3195     if (m_textDirty) {
3196         // do validation
3197         bool wasValidInput = m_validInput;
3198         bool wasAcceptable = m_acceptableInput;
3199         m_validInput = true;
3200         m_acceptableInput = true;
3201 #ifndef QT_NO_VALIDATOR
3202         if (m_validator) {
3203             QString textCopy = m_text;
3204             int cursorCopy = m_cursor;
3205             QValidator::State state = m_validator->validate(textCopy, cursorCopy);
3206             m_validInput = state != QValidator::Invalid;
3207             m_acceptableInput = state == QValidator::Acceptable;
3208             if (m_validInput) {
3209                 if (m_text != textCopy) {
3210                     internalSetText(textCopy, cursorCopy);
3211                     return true;
3212                 }
3213                 m_cursor = cursorCopy;
3214             }
3215         }
3216 #endif
3217         if (validateFromState >= 0 && wasValidInput && !m_validInput) {
3218             if (m_transactions.count())
3219                 return false;
3220             internalUndo(validateFromState);
3221             m_history.resize(m_undoState);
3222             m_validInput = true;
3223             m_acceptableInput = wasAcceptable;
3224             m_textDirty = false;
3225         }
3226
3227         if (m_textDirty) {
3228             m_textDirty = false;
3229             m_preeditDirty = false;
3230             alignmentChanged = determineHorizontalAlignment();
3231             emit q->textChanged();
3232         }
3233
3234         updateDisplayText(alignmentChanged);
3235
3236         if (m_acceptableInput != wasAcceptable)
3237             emit q->acceptableInputChanged();
3238     }
3239     if (m_preeditDirty) {
3240         m_preeditDirty = false;
3241         if (determineHorizontalAlignment()) {
3242             alignmentChanged = true;
3243             updateLayout();
3244         }
3245     }
3246
3247     if (m_selDirty) {
3248         m_selDirty = false;
3249         emit q->selectionChanged();
3250     }
3251
3252     inputMethodAttributesChanged |= (m_cursor == m_lastCursorPos);
3253     if (inputMethodAttributesChanged)
3254         q->updateInputMethod();
3255     emitUndoRedoChanged();
3256
3257     if (!emitCursorPositionChanged() && alignmentChanged)
3258         q->updateCursorRectangle();
3259
3260     return true;
3261 }
3262
3263 /*!
3264     \internal
3265
3266     An internal function for setting the text of the line control.
3267 */
3268 void QQuickTextInputPrivate::internalSetText(const QString &txt, int pos, bool edited)
3269 {
3270     Q_Q(QQuickTextInput);
3271     internalDeselect();
3272     QString oldText = m_text;
3273     if (m_maskData) {
3274         m_text = maskString(0, txt, true);
3275         m_text += clearString(m_text.length(), m_maxLength - m_text.length());
3276     } else {
3277         m_text = txt.isEmpty() ? txt : txt.left(m_maxLength);
3278     }
3279     m_history.clear();
3280     m_undoState = 0;
3281     m_cursor = (pos < 0 || pos > m_text.length()) ? m_text.length() : pos;
3282     m_textDirty = (oldText != m_text);
3283
3284     bool changed = finishChange(-1, true, edited);
3285 #ifdef QT_NO_ACCESSIBILITY
3286     Q_UNUSED(changed)
3287 #else
3288     if (changed) {
3289         QAccessibleTextUpdateEvent ev(q, 0, oldText, m_text);
3290         QAccessible::updateAccessibility(&ev);
3291     }
3292 #endif
3293 }
3294
3295
3296 /*!
3297     \internal
3298
3299     Adds the given \a command to the undo history
3300     of the line control.  Does not apply the command.
3301 */
3302 void QQuickTextInputPrivate::addCommand(const Command &cmd)
3303 {
3304     if (m_separator && m_undoState && m_history[m_undoState - 1].type != Separator) {
3305         m_history.resize(m_undoState + 2);
3306         m_history[m_undoState++] = Command(Separator, m_cursor, 0, m_selstart, m_selend);
3307     } else {
3308         m_history.resize(m_undoState + 1);
3309     }
3310     m_separator = false;
3311     m_history[m_undoState++] = cmd;
3312 }
3313
3314 /*!
3315     \internal
3316
3317     Inserts the given string \a s into the line
3318     control.
3319
3320     Also adds the appropriate commands into the undo history.
3321     This function does not call finishChange(), and may leave the text
3322     in an invalid state.
3323 */
3324 void QQuickTextInputPrivate::internalInsert(const QString &s)
3325 {
3326     Q_Q(QQuickTextInput);
3327     if (m_echoMode == QQuickTextInput::Password) {
3328         int delay = qGuiApp->styleHints()->passwordMaskDelay();
3329         if (delay > 0)
3330             m_passwordEchoTimer.start(delay, q);
3331     }
3332     if (hasSelectedText())
3333         addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend));
3334     if (m_maskData) {
3335         QString ms = maskString(m_cursor, s);
3336         for (int i = 0; i < (int) ms.length(); ++i) {
3337             addCommand (Command(DeleteSelection, m_cursor + i, m_text.at(m_cursor + i), -1, -1));
3338             addCommand(Command(Insert, m_cursor + i, ms.at(i), -1, -1));
3339         }
3340         m_text.replace(m_cursor, ms.length(), ms);
3341         m_cursor += ms.length();
3342         m_cursor = nextMaskBlank(m_cursor);
3343         m_textDirty = true;
3344     } else {
3345         int remaining = m_maxLength - m_text.length();
3346         if (remaining != 0) {
3347             m_text.insert(m_cursor, s.left(remaining));
3348             for (int i = 0; i < (int) s.left(remaining).length(); ++i)
3349                addCommand(Command(Insert, m_cursor++, s.at(i), -1, -1));
3350             m_textDirty = true;
3351         }
3352     }
3353 }
3354
3355 /*!
3356     \internal
3357
3358     deletes a single character from the current text.  If \a wasBackspace,
3359     the character prior to the cursor is removed.  Otherwise the character
3360     after the cursor is removed.
3361
3362     Also adds the appropriate commands into the undo history.
3363     This function does not call finishChange(), and may leave the text
3364     in an invalid state.
3365 */
3366 void QQuickTextInputPrivate::internalDelete(bool wasBackspace)
3367 {
3368     if (m_cursor < (int) m_text.length()) {
3369         cancelPasswordEchoTimer();
3370         if (hasSelectedText())
3371             addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend));
3372         addCommand(Command((CommandType)((m_maskData ? 2 : 0) + (wasBackspace ? Remove : Delete)),
3373                    m_cursor, m_text.at(m_cursor), -1, -1));
3374         if (m_maskData) {
3375             m_text.replace(m_cursor, 1, clearString(m_cursor, 1));
3376             addCommand(Command(Insert, m_cursor, m_text.at(m_cursor), -1, -1));
3377         } else {
3378             m_text.remove(m_cursor, 1);
3379         }
3380         m_textDirty = true;
3381     }
3382 }
3383
3384 /*!
3385     \internal
3386
3387     removes the currently selected text from the line control.
3388
3389     Also adds the appropriate commands into the undo history.
3390     This function does not call finishChange(), and may leave the text
3391     in an invalid state.
3392 */
3393 void QQuickTextInputPrivate::removeSelectedText()
3394 {
3395     if (m_selstart < m_selend && m_selend <= (int) m_text.length()) {
3396         cancelPasswordEchoTimer();
3397         separate();
3398         int i ;
3399         addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend));
3400         if (m_selstart <= m_cursor && m_cursor < m_selend) {
3401             // cursor is within the selection. Split up the commands
3402             // to be able to restore the correct cursor position
3403             for (i = m_cursor; i >= m_selstart; --i)
3404                 addCommand (Command(DeleteSelection, i, m_text.at(i), -1, 1));
3405             for (i = m_selend - 1; i > m_cursor; --i)
3406                 addCommand (Command(DeleteSelection, i - m_cursor + m_selstart - 1, m_text.at(i), -1, -1));
3407         } else {
3408             for (i = m_selend-1; i >= m_selstart; --i)
3409                 addCommand (Command(RemoveSelection, i, m_text.at(i), -1, -1));
3410         }
3411         if (m_maskData) {
3412             m_text.replace(m_selstart, m_selend - m_selstart,  clearString(m_selstart, m_selend - m_selstart));
3413             for (int i = 0; i < m_selend - m_selstart; ++i)
3414                 addCommand(Command(Insert, m_selstart + i, m_text.at(m_selstart + i), -1, -1));
3415         } else {
3416             m_text.remove(m_selstart, m_selend - m_selstart);
3417         }
3418         if (m_cursor > m_selstart)
3419             m_cursor -= qMin(m_cursor, m_selend) - m_selstart;
3420         internalDeselect();
3421         m_textDirty = true;
3422     }
3423 }
3424
3425 /*!
3426     \internal
3427
3428     Parses the input mask specified by \a maskFields to generate
3429     the mask data used to handle input masks.
3430 */
3431 void QQuickTextInputPrivate::parseInputMask(const QString &maskFields)
3432 {
3433     int delimiter = maskFields.indexOf(QLatin1Char(';'));
3434     if (maskFields.isEmpty() || delimiter == 0) {
3435         if (m_maskData) {
3436             delete [] m_maskData;
3437             m_maskData = 0;
3438             m_maxLength = 32767;
3439             internalSetText(QString());
3440         }
3441         return;
3442     }
3443
3444     if (delimiter == -1) {
3445         m_blank = QLatin1Char(' ');
3446         m_inputMask = maskFields;
3447     } else {
3448         m_inputMask = maskFields.left(delimiter);
3449         m_blank = (delimiter + 1 < maskFields.length()) ? maskFields[delimiter + 1] : QLatin1Char(' ');
3450     }
3451
3452     // calculate m_maxLength / m_maskData length
3453     m_maxLength = 0;
3454     QChar c = 0;
3455     for (int i=0; i<m_inputMask.length(); i++) {
3456         c = m_inputMask.at(i);
3457         if (i > 0 && m_inputMask.at(i-1) == QLatin1Char('\\')) {
3458             m_maxLength++;
3459             continue;
3460         }
3461         if (c != QLatin1Char('\\') && c != QLatin1Char('!') &&
3462              c != QLatin1Char('<') && c != QLatin1Char('>') &&
3463              c != QLatin1Char('{') && c != QLatin1Char('}') &&
3464              c != QLatin1Char('[') && c != QLatin1Char(']'))
3465             m_maxLength++;
3466     }
3467
3468     delete [] m_maskData;
3469     m_maskData = new MaskInputData[m_maxLength];
3470
3471     MaskInputData::Casemode m = MaskInputData::NoCaseMode;
3472     c = 0;
3473     bool s;
3474     bool escape = false;
3475     int index = 0;
3476     for (int i = 0; i < m_inputMask.length(); i++) {
3477         c = m_inputMask.at(i);
3478         if (escape) {
3479             s = true;
3480             m_maskData[index].maskChar = c;
3481             m_maskData[index].separator = s;
3482             m_maskData[index].caseMode = m;
3483             index++;
3484             escape = false;
3485         } else if (c == QLatin1Char('<')) {
3486                 m = MaskInputData::Lower;
3487         } else if (c == QLatin1Char('>')) {
3488             m = MaskInputData::Upper;
3489         } else if (c == QLatin1Char('!')) {
3490             m = MaskInputData::NoCaseMode;
3491         } else if (c != QLatin1Char('{') && c != QLatin1Char('}') && c != QLatin1Char('[') && c != QLatin1Char(']')) {
3492             switch (c.unicode()) {
3493             case 'A':
3494             case 'a':
3495             case 'N':
3496             case 'n':
3497             case 'X':
3498             case 'x':
3499             case '9':
3500             case '0':
3501             case 'D':
3502             case 'd':
3503             case '#':
3504             case 'H':
3505             case 'h':
3506             case 'B':
3507             case 'b':
3508                 s = false;
3509                 break;
3510             case '\\':
3511                 escape = true;
3512             default:
3513                 s = true;
3514                 break;
3515             }
3516
3517             if (!escape) {
3518                 m_maskData[index].maskChar = c;
3519                 m_maskData[index].separator = s;
3520                 m_maskData[index].caseMode = m;
3521                 index++;
3522             }
3523         }
3524     }
3525     internalSetText(m_text);
3526 }
3527
3528
3529 /*!
3530     \internal
3531
3532     checks if the key is valid compared to the inputMask
3533 */
3534 bool QQuickTextInputPrivate::isValidInput(QChar key, QChar mask) const
3535 {
3536     switch (mask.unicode()) {
3537     case 'A':
3538         if (key.isLetter())
3539             return true;
3540         break;
3541     case 'a':
3542         if (key.isLetter() || key == m_blank)
3543             return true;
3544         break;
3545     case 'N':
3546         if (key.isLetterOrNumber())
3547             return true;
3548         break;
3549     case 'n':
3550         if (key.isLetterOrNumber() || key == m_blank)
3551             return true;
3552         break;
3553     case 'X':
3554         if (key.isPrint())
3555             return true;
3556         break;
3557     case 'x':
3558         if (key.isPrint() || key == m_blank)
3559             return true;
3560         break;
3561     case '9':
3562         if (key.isNumber())
3563             return true;
3564         break;
3565     case '0':
3566         if (key.isNumber() || key == m_blank)
3567             return true;
3568         break;
3569     case 'D':
3570         if (key.isNumber() && key.digitValue() > 0)
3571             return true;
3572         break;
3573     case 'd':
3574         if ((key.isNumber() && key.digitValue() > 0) || key == m_blank)
3575             return true;
3576         break;
3577     case '#':
3578         if (key.isNumber() || key == QLatin1Char('+') || key == QLatin1Char('-') || key == m_blank)
3579             return true;
3580         break;
3581     case 'B':
3582         if (key == QLatin1Char('0') || key == QLatin1Char('1'))
3583             return true;
3584         break;
3585     case 'b':
3586         if (key == QLatin1Char('0') || key == QLatin1Char('1') || key == m_blank)
3587             return true;
3588         break;
3589     case 'H':
3590         if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')))
3591             return true;
3592         break;
3593     case 'h':
3594         if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')) || key == m_blank)
3595             return true;
3596         break;
3597     default:
3598         break;
3599     }
3600     return false;
3601 }
3602
3603 /*!
3604     \internal
3605
3606     Returns true if the given text \a str is valid for any
3607     validator or input mask set for the line control.
3608
3609     Otherwise returns false
3610 */
3611 QQuickTextInputPrivate::ValidatorState QQuickTextInputPrivate::hasAcceptableInput(const QString &str) const
3612 {
3613 #ifndef QT_NO_VALIDATOR
3614     QString textCopy = str;
3615     int cursorCopy = m_cursor;
3616     if (m_validator) {
3617         QValidator::State state = m_validator->validate(textCopy, cursorCopy);
3618         if (state != QValidator::Acceptable)
3619             return ValidatorState(state);
3620     }
3621 #endif
3622
3623     if (!m_maskData)
3624         return AcceptableInput;
3625
3626     if (str.length() != m_maxLength)
3627         return InvalidInput;
3628
3629     for (int i=0; i < m_maxLength; ++i) {
3630         if (m_maskData[i].separator) {
3631             if (str.at(i) != m_maskData[i].maskChar)
3632                 return InvalidInput;
3633         } else {
3634             if (!isValidInput(str.at(i), m_maskData[i].maskChar))
3635                 return InvalidInput;
3636         }
3637     }
3638     return AcceptableInput;
3639 }
3640
3641 /*!
3642     \internal
3643
3644     Applies the inputMask on \a str starting from position \a pos in the mask. \a clear
3645     specifies from where characters should be gotten when a separator is met in \a str - true means
3646     that blanks will be used, false that previous input is used.
3647     Calling this when no inputMask is set is undefined.
3648 */
3649 QString QQuickTextInputPrivate::maskString(uint pos, const QString &str, bool clear) const
3650 {
3651     if (pos >= (uint)m_maxLength)
3652         return QString::fromLatin1("");
3653
3654     QString fill;
3655     fill = clear ? clearString(0, m_maxLength) : m_text;
3656
3657     int strIndex = 0;
3658     QString s = QString::fromLatin1("");
3659     int i = pos;
3660     while (i < m_maxLength) {
3661         if (strIndex < str.length()) {
3662             if (m_maskData[i].separator) {
3663                 s += m_maskData[i].maskChar;
3664                 if (str[(int)strIndex] == m_maskData[i].maskChar)
3665                     strIndex++;
3666                 ++i;
3667             } else {
3668                 if (isValidInput(str[(int)strIndex], m_maskData[i].maskChar)) {
3669                     switch (m_maskData[i].caseMode) {
3670                     case MaskInputData::Upper:
3671                         s += str[(int)strIndex].toUpper();
3672                         break;
3673                     case MaskInputData::Lower:
3674                         s += str[(int)strIndex].toLower();
3675                         break;
3676                     default:
3677                         s += str[(int)strIndex];
3678                     }
3679                     ++i;
3680                 } else {
3681                     // search for separator first
3682                     int n = findInMask(i, true, true, str[(int)strIndex]);
3683                     if (n != -1) {
3684                         if (str.length() != 1 || i == 0 || (i > 0 && (!m_maskData[i-1].separator || m_maskData[i-1].maskChar != str[(int)strIndex]))) {
3685                             s += fill.mid(i, n-i+1);
3686                             i = n + 1; // update i to find + 1
3687                         }
3688                     } else {
3689                         // search for valid m_blank if not
3690                         n = findInMask(i, true, false, str[(int)strIndex]);
3691                         if (n != -1) {
3692                             s += fill.mid(i, n-i);
3693                             switch (m_maskData[n].caseMode) {
3694                             case MaskInputData::Upper:
3695                                 s += str[(int)strIndex].toUpper();
3696                                 break;
3697                             case MaskInputData::Lower:
3698                                 s += str[(int)strIndex].toLower();
3699                                 break;
3700                             default:
3701                                 s += str[(int)strIndex];
3702                             }
3703                             i = n + 1; // updates i to find + 1
3704                         }
3705                     }
3706                 }
3707                 ++strIndex;
3708             }
3709         } else
3710             break;
3711     }
3712
3713     return s;
3714 }
3715
3716
3717
3718 /*!
3719     \internal
3720
3721     Returns a "cleared" string with only separators and blank chars.
3722     Calling this when no inputMask is set is undefined.
3723 */
3724 QString QQuickTextInputPrivate::clearString(uint pos, uint len) const
3725 {
3726     if (pos >= (uint)m_maxLength)
3727         return QString();
3728
3729     QString s;
3730     int end = qMin((uint)m_maxLength, pos + len);
3731     for (int i = pos; i < end; ++i)
3732         if (m_maskData[i].separator)
3733             s += m_maskData[i].maskChar;
3734         else
3735             s += m_blank;
3736
3737     return s;
3738 }
3739
3740 /*!
3741     \internal
3742
3743     Strips blank parts of the input in a QQuickTextInputPrivate when an inputMask is set,
3744     separators are still included. Typically "127.0__.0__.1__" becomes "127.0.0.1".
3745 */
3746 QString QQuickTextInputPrivate::stripString(const QString &str) const
3747 {
3748     if (!m_maskData)
3749         return str;
3750
3751     QString s;
3752     int end = qMin(m_maxLength, (int)str.length());
3753     for (int i = 0; i < end; ++i) {
3754         if (m_maskData[i].separator)
3755             s += m_maskData[i].maskChar;
3756         else if (str[i] != m_blank)
3757             s += str[i];
3758     }
3759
3760     return s;
3761 }
3762
3763 /*!
3764     \internal
3765     searches forward/backward in m_maskData for either a separator or a m_blank
3766 */
3767 int QQuickTextInputPrivate::findInMask(int pos, bool forward, bool findSeparator, QChar searchChar) const
3768 {
3769     if (pos >= m_maxLength || pos < 0)
3770         return -1;
3771
3772     int end = forward ? m_maxLength : -1;
3773     int step = forward ? 1 : -1;
3774     int i = pos;
3775
3776     while (i != end) {
3777         if (findSeparator) {
3778             if (m_maskData[i].separator && m_maskData[i].maskChar == searchChar)
3779                 return i;
3780         } else {
3781             if (!m_maskData[i].separator) {
3782                 if (searchChar.isNull())
3783                     return i;
3784                 else if (isValidInput(searchChar, m_maskData[i].maskChar))
3785                     return i;
3786             }
3787         }
3788         i += step;
3789     }
3790     return -1;
3791 }
3792
3793 void QQuickTextInputPrivate::internalUndo(int until)
3794 {
3795     if (!isUndoAvailable())
3796         return;
3797     cancelPasswordEchoTimer();
3798     internalDeselect();
3799     while (m_undoState && m_undoState > until) {
3800         Command& cmd = m_history[--m_undoState];
3801         switch (cmd.type) {
3802         case Insert:
3803             m_text.remove(cmd.pos, 1);
3804             m_cursor = cmd.pos;
3805             break;
3806         case SetSelection:
3807             m_selstart = cmd.selStart;
3808             m_selend = cmd.selEnd;
3809             m_cursor = cmd.pos;
3810             break;
3811         case Remove:
3812         case RemoveSelection:
3813             m_text.insert(cmd.pos, cmd.uc);
3814             m_cursor = cmd.pos + 1;
3815             break;
3816         case Delete:
3817         case DeleteSelection:
3818             m_text.insert(cmd.pos, cmd.uc);
3819             m_cursor = cmd.pos;
3820             break;
3821         case Separator:
3822             continue;
3823         }
3824         if (until < 0 && m_undoState) {
3825             Command& next = m_history[m_undoState-1];
3826             if (next.type != cmd.type && next.type < RemoveSelection
3827                  && (cmd.type < RemoveSelection || next.type == Separator))
3828                 break;
3829         }
3830     }
3831     m_textDirty = true;
3832 }
3833
3834 void QQuickTextInputPrivate::internalRedo()
3835 {
3836     if (!isRedoAvailable())
3837         return;
3838     internalDeselect();
3839     while (m_undoState < (int)m_history.size()) {
3840         Command& cmd = m_history[m_undoState++];
3841         switch (cmd.type) {
3842         case Insert:
3843             m_text.insert(cmd.pos, cmd.uc);
3844             m_cursor = cmd.pos + 1;
3845             break;
3846         case SetSelection:
3847             m_selstart = cmd.selStart;
3848             m_selend = cmd.selEnd;
3849             m_cursor = cmd.pos;
3850             break;
3851         case Remove:
3852         case Delete:
3853         case RemoveSelection:
3854         case DeleteSelection:
3855             m_text.remove(cmd.pos, 1);
3856             m_selstart = cmd.selStart;
3857             m_selend = cmd.selEnd;
3858             m_cursor = cmd.pos;
3859             break;
3860         case Separator:
3861             m_selstart = cmd.selStart;
3862             m_selend = cmd.selEnd;
3863             m_cursor = cmd.pos;
3864             break;
3865         }
3866         if (m_undoState < (int)m_history.size()) {
3867             Command& next = m_history[m_undoState];
3868             if (next.type != cmd.type && cmd.type < RemoveSelection && next.type != Separator
3869                  && (next.type < RemoveSelection || cmd.type == Separator))
3870                 break;
3871         }
3872     }
3873     m_textDirty = true;
3874 }
3875
3876 void QQuickTextInputPrivate::emitUndoRedoChanged()
3877 {
3878     Q_Q(QQuickTextInput);
3879     const bool previousUndo = canUndo;
3880     const bool previousRedo = canRedo;
3881
3882     canUndo = isUndoAvailable();
3883     canRedo = isRedoAvailable();
3884
3885     if (previousUndo != canUndo)
3886         emit q->canUndoChanged();
3887     if (previousRedo != canRedo)
3888         emit q->canRedoChanged();
3889 }
3890
3891 /*!
3892     \internal
3893
3894     If the current cursor position differs from the last emitted cursor
3895     position, emits cursorPositionChanged().
3896 */
3897 bool QQuickTextInputPrivate::emitCursorPositionChanged()
3898 {
3899     Q_Q(QQuickTextInput);
3900     if (m_cursor != m_lastCursorPos) {
3901         m_lastCursorPos = m_cursor;
3902
3903         q->updateCursorRectangle();
3904         emit q->cursorPositionChanged();
3905
3906         if (!hasSelectedText()) {
3907             if (lastSelectionStart != m_cursor) {
3908                 lastSelectionStart = m_cursor;
3909                 emit q->selectionStartChanged();
3910             }
3911             if (lastSelectionEnd != m_cursor) {
3912                 lastSelectionEnd = m_cursor;
3913                 emit q->selectionEndChanged();
3914             }
3915         }
3916
3917 #ifndef QT_NO_ACCESSIBILITY
3918         QAccessibleTextCursorEvent ev(q, m_cursor);
3919         QAccessible::updateAccessibility(&ev);
3920 #endif
3921
3922         return true;
3923     }
3924     return false;
3925 }
3926
3927
3928 void QQuickTextInputPrivate::setCursorBlinkPeriod(int msec)
3929 {
3930     Q_Q(QQuickTextInput);
3931     if (msec == m_blinkPeriod)
3932         return;
3933     if (m_blinkTimer) {
3934         q->killTimer(m_blinkTimer);
3935     }
3936     if (msec) {
3937         m_blinkTimer = q->startTimer(msec / 2);
3938         m_blinkStatus = 1;
3939     } else {
3940         m_blinkTimer = 0;
3941         if (m_blinkStatus == 1) {
3942             updateType = UpdatePaintNode;
3943             q->update();
3944         }
3945     }
3946     m_blinkPeriod = msec;
3947 }
3948
3949 void QQuickTextInput::timerEvent(QTimerEvent *event)
3950 {
3951     Q_D(QQuickTextInput);
3952     if (event->timerId() == d->m_blinkTimer) {
3953         d->m_blinkStatus = !d->m_blinkStatus;
3954         d->updateType = QQuickTextInputPrivate::UpdatePaintNode;
3955         update();
3956     } else if (event->timerId() == d->m_passwordEchoTimer.timerId()) {
3957         d->m_passwordEchoTimer.stop();
3958         d->updateDisplayText();
3959     }
3960 }
3961
3962 void QQuickTextInputPrivate::processKeyEvent(QKeyEvent* event)
3963 {
3964     Q_Q(QQuickTextInput);
3965     bool inlineCompletionAccepted = false;
3966
3967     if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
3968         if (hasAcceptableInput(m_text) || fixup()) {
3969             emit q->accepted();
3970         }
3971         if (inlineCompletionAccepted)
3972             event->accept();
3973         else
3974             event->ignore();
3975         return;
3976     }
3977
3978     if (m_echoMode == QQuickTextInput::PasswordEchoOnEdit
3979         && !m_passwordEchoEditing
3980         && !m_readOnly
3981         && !event->text().isEmpty()
3982         && !(event->modifiers() & Qt::ControlModifier)) {
3983         // Clear the edit and reset to normal echo mode while editing; the
3984         // echo mode switches back when the edit loses focus
3985         // ### resets current content.  dubious code; you can
3986         // navigate with keys up, down, back, and select(?), but if you press
3987         // "left" or "right" it clears?
3988         updatePasswordEchoEditing(true);
3989         clear();
3990     }
3991
3992     bool unknown = false;
3993     bool visual = cursorMoveStyle() == Qt::VisualMoveStyle;
3994
3995     if (false) {
3996     }
3997 #ifndef QT_NO_SHORTCUT
3998     else if (event == QKeySequence::Undo) {
3999         q->undo();
4000     }
4001     else if (event == QKeySequence::Redo) {
4002         q->redo();
4003     }
4004     else if (event == QKeySequence::SelectAll) {
4005         selectAll();
4006     }
4007 #ifndef QT_NO_CLIPBOARD
4008     else if (event == QKeySequence::Copy) {
4009         copy();
4010     }
4011     else if (event == QKeySequence::Paste) {
4012         if (!m_readOnly) {
4013             QClipboard::Mode mode = QClipboard::Clipboard;
4014             paste(mode);
4015         }
4016     }
4017     else if (event == QKeySequence::Cut) {
4018         if (!m_readOnly) {
4019             copy();
4020             del();
4021         }
4022     }
4023     else if (event == QKeySequence::DeleteEndOfLine) {
4024         if (!m_readOnly) {
4025             setSelection(m_cursor, end());
4026             copy();
4027             del();
4028         }
4029     }
4030 #endif //QT_NO_CLIPBOARD
4031     else if (event == QKeySequence::MoveToStartOfLine || event == QKeySequence::MoveToStartOfBlock) {
4032         home(0);
4033     }
4034     else if (event == QKeySequence::MoveToEndOfLine || event == QKeySequence::MoveToEndOfBlock) {
4035         end(0);
4036     }
4037     else if (event == QKeySequence::SelectStartOfLine || event == QKeySequence::SelectStartOfBlock) {
4038         home(1);
4039     }
4040     else if (event == QKeySequence::SelectEndOfLine || event == QKeySequence::SelectEndOfBlock) {
4041         end(1);
4042     }
4043     else if (event == QKeySequence::MoveToNextChar) {
4044         if (hasSelectedText()) {
4045             moveCursor(selectionEnd(), false);
4046         } else {
4047             cursorForward(0, visual ? 1 : (layoutDirection() == Qt::LeftToRight ? 1 : -1));
4048         }
4049     }
4050     else if (event == QKeySequence::SelectNextChar) {
4051         cursorForward(1, visual ? 1 : (layoutDirection() == Qt::LeftToRight ? 1 : -1));
4052     }
4053     else if (event == QKeySequence::MoveToPreviousChar) {
4054         if (hasSelectedText()) {
4055             moveCursor(selectionStart(), false);
4056         } else {
4057             cursorForward(0, visual ? -1 : (layoutDirection() == Qt::LeftToRight ? -1 : 1));
4058         }
4059     }
4060     else if (event == QKeySequence::SelectPreviousChar) {
4061         cursorForward(1, visual ? -1 : (layoutDirection() == Qt::LeftToRight ? -1 : 1));
4062     }
4063     else if (event == QKeySequence::MoveToNextWord) {
4064         if (m_echoMode == QQuickTextInput::Normal)
4065             layoutDirection() == Qt::LeftToRight ? cursorWordForward(0) : cursorWordBackward(0);
4066         else
4067             layoutDirection() == Qt::LeftToRight ? end(0) : home(0);
4068     }
4069     else if (event == QKeySequence::MoveToPreviousWord) {
4070         if (m_echoMode == QQuickTextInput::Normal)
4071             layoutDirection() == Qt::LeftToRight ? cursorWordBackward(0) : cursorWordForward(0);
4072         else if (!m_readOnly) {
4073             layoutDirection() == Qt::LeftToRight ? home(0) : end(0);
4074         }
4075     }
4076     else if (event == QKeySequence::SelectNextWord) {
4077         if (m_echoMode == QQuickTextInput::Normal)
4078             layoutDirection() == Qt::LeftToRight ? cursorWordForward(1) : cursorWordBackward(1);
4079         else
4080             layoutDirection() == Qt::LeftToRight ? end(1) : home(1);
4081     }
4082     else if (event == QKeySequence::SelectPreviousWord) {
4083         if (m_echoMode == QQuickTextInput::Normal)
4084             layoutDirection() == Qt::LeftToRight ? cursorWordBackward(1) : cursorWordForward(1);
4085         else
4086             layoutDirection() == Qt::LeftToRight ? home(1) : end(1);
4087     }
4088     else if (event == QKeySequence::Delete) {
4089         if (!m_readOnly)
4090             del();
4091     }
4092     else if (event == QKeySequence::DeleteEndOfWord) {
4093         if (!m_readOnly) {
4094             cursorWordForward(true);
4095             del();
4096         }
4097     }
4098     else if (event == QKeySequence::DeleteStartOfWord) {
4099         if (!m_readOnly) {
4100             cursorWordBackward(true);
4101             del();
4102         }
4103     }
4104 #endif // QT_NO_SHORTCUT
4105     else {
4106         bool handled = false;
4107         if (event->modifiers() & Qt::ControlModifier) {
4108             switch (event->key()) {
4109             case Qt::Key_Backspace:
4110                 if (!m_readOnly) {
4111                     cursorWordBackward(true);
4112                     del();
4113                 }
4114                 break;
4115             default:
4116                 if (!handled)
4117                     unknown = true;
4118             }
4119         } else { // ### check for *no* modifier
4120             switch (event->key()) {
4121             case Qt::Key_Backspace:
4122                 if (!m_readOnly) {
4123                     backspace();
4124                 }
4125                 break;
4126             default:
4127                 if (!handled)
4128                     unknown = true;
4129             }
4130         }
4131     }
4132
4133     if (event->key() == Qt::Key_Direction_L || event->key() == Qt::Key_Direction_R) {
4134         setLayoutDirection((event->key() == Qt::Key_Direction_L) ? Qt::LeftToRight : Qt::RightToLeft);
4135         unknown = false;
4136     }
4137
4138     if (unknown && !m_readOnly) {
4139         QString t = event->text();
4140         if (!t.isEmpty() && t.at(0).isPrint()) {
4141             insert(t);
4142             event->accept();
4143             return;
4144         }
4145     }
4146
4147     if (unknown)
4148         event->ignore();
4149     else
4150         event->accept();
4151 }
4152
4153
4154 QT_END_NAMESPACE
4155