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