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