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