Build against refactor.
[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 <QFontMetrics>
52 #include <QPainter>
53 #include <QTextBoundaryFinder>
54 #include <QInputContext>
55 #include <qstyle.h>
56
57 #ifndef QT_NO_LINEEDIT
58
59 QT_BEGIN_NAMESPACE
60
61
62
63 /*!
64     \qmlclass TextInput QDeclarative1TextInput
65     \inqmlmodule QtQuick 1
66     \ingroup qml-basic-visual-elements
67     \since QtQuick 1.0
68     \brief The TextInput item displays an editable line of text.
69     \inherits Item
70
71     The TextInput element displays a single line of editable plain text.
72
73     TextInput is used to accept a line of text input. Input constraints
74     can be placed on a TextInput item (for example, through a \l validator or \l inputMask),
75     and setting \l echoMode to an appropriate value enables TextInput to be used for
76     a password input field.
77
78     On Mac OS X, the Up/Down key bindings for Home/End are explicitly disabled.
79     If you want such bindings (on any platform), you will need to construct them in QML.
80     
81     \sa TextEdit, Text, {declarative/text/textselection}{Text Selection example}
82 */
83 QDeclarative1TextInput::QDeclarative1TextInput(QDeclarativeItem* parent)
84     : QDeclarative1ImplicitSizePaintedItem(*(new QDeclarative1TextInputPrivate), parent)
85 {
86     Q_D(QDeclarative1TextInput);
87     d->init();
88 }
89
90 QDeclarative1TextInput::~QDeclarative1TextInput()
91 {
92 }
93
94 /*!
95     \qmlproperty string QtQuick1::TextInput::text
96
97     The text in the TextInput.
98 */
99
100 QString QDeclarative1TextInput::text() const
101 {
102     Q_D(const QDeclarative1TextInput);
103     return d->control->text();
104 }
105
106 void QDeclarative1TextInput::setText(const QString &s)
107 {
108     Q_D(QDeclarative1TextInput);
109     if(s == text())
110         return;
111     d->control->setText(s);
112 }
113
114 /*!
115     \qmlproperty string QtQuick1::TextInput::font.family
116
117     Sets the family name of the font.
118
119     The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]".
120     If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen.
121     If the family isn't available a family will be set using the font matching algorithm.
122 */
123
124 /*!
125     \qmlproperty bool QtQuick1::TextInput::font.bold
126
127     Sets whether the font weight is bold.
128 */
129
130 /*!
131     \qmlproperty enumeration QtQuick1::TextInput::font.weight
132
133     Sets the font's weight.
134
135     The weight can be one of:
136     \list
137     \o Font.Light
138     \o Font.Normal - the default
139     \o Font.DemiBold
140     \o Font.Bold
141     \o Font.Black
142     \endlist
143
144     \qml
145     TextInput { text: "Hello"; font.weight: Font.DemiBold }
146     \endqml
147 */
148
149 /*!
150     \qmlproperty bool QtQuick1::TextInput::font.italic
151
152     Sets whether the font has an italic style.
153 */
154
155 /*!
156     \qmlproperty bool QtQuick1::TextInput::font.underline
157
158     Sets whether the text is underlined.
159 */
160
161 /*!
162     \qmlproperty bool QtQuick1::TextInput::font.strikeout
163
164     Sets whether the font has a strikeout style.
165 */
166
167 /*!
168     \qmlproperty real QtQuick1::TextInput::font.pointSize
169
170     Sets the font size in points. The point size must be greater than zero.
171 */
172
173 /*!
174     \qmlproperty int QtQuick1::TextInput::font.pixelSize
175
176     Sets the font size in pixels.
177
178     Using this function makes the font device dependent.
179     Use \c pointSize to set the size of the font in a device independent manner.
180 */
181
182 /*!
183     \qmlproperty real QtQuick1::TextInput::font.letterSpacing
184
185     Sets the letter spacing for the font.
186
187     Letter spacing changes the default spacing between individual letters in the font.
188     A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing.
189 */
190
191 /*!
192     \qmlproperty real QtQuick1::TextInput::font.wordSpacing
193
194     Sets the word spacing for the font.
195
196     Word spacing changes the default spacing between individual words.
197     A positive value increases the word spacing by a corresponding amount of pixels,
198     while a negative value decreases the inter-word spacing accordingly.
199 */
200
201 /*!
202     \qmlproperty enumeration QtQuick1::TextInput::font.capitalization
203
204     Sets the capitalization for the text.
205
206     \list
207     \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied.
208     \o Font.AllUppercase - This alters the text to be rendered in all uppercase type.
209     \o Font.AllLowercase         - This alters the text to be rendered in all lowercase type.
210     \o Font.SmallCaps - This alters the text to be rendered in small-caps type.
211     \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character.
212     \endlist
213
214     \qml
215     TextInput { text: "Hello"; font.capitalization: Font.AllLowercase }
216     \endqml
217 */
218
219 QFont QDeclarative1TextInput::font() const
220 {
221     Q_D(const QDeclarative1TextInput);
222     return d->sourceFont;
223 }
224
225 void QDeclarative1TextInput::setFont(const QFont &font)
226 {
227     Q_D(QDeclarative1TextInput);
228     if (d->sourceFont == font)
229         return;
230
231     d->sourceFont = font;
232     QFont oldFont = d->font;
233     d->font = font;
234     if (d->font.pointSizeF() != -1) {
235         // 0.5pt resolution
236         qreal size = qRound(d->font.pointSizeF()*2.0);
237         d->font.setPointSizeF(size/2.0);
238     }
239
240     if (oldFont != d->font) {
241         d->control->setFont(d->font);
242         updateSize();
243         updateCursorRectangle();
244         if(d->cursorItem){
245             d->cursorItem->setHeight(QFontMetrics(d->font).height());
246         }
247     }
248     emit fontChanged(d->sourceFont);
249 }
250
251 /*!
252     \qmlproperty color QtQuick1::TextInput::color
253
254     The text color.
255 */
256 QColor QDeclarative1TextInput::color() const
257 {
258     Q_D(const QDeclarative1TextInput);
259     return d->color;
260 }
261
262 void QDeclarative1TextInput::setColor(const QColor &c)
263 {
264     Q_D(QDeclarative1TextInput);
265     if (c != d->color) {
266         d->color = c;
267         clearCache();
268         update();
269         emit colorChanged(c);
270     }
271 }
272
273
274 /*!
275     \qmlproperty color QtQuick1::TextInput::selectionColor
276
277     The text highlight color, used behind selections.
278 */
279 QColor QDeclarative1TextInput::selectionColor() const
280 {
281     Q_D(const QDeclarative1TextInput);
282     return d->selectionColor;
283 }
284
285 void QDeclarative1TextInput::setSelectionColor(const QColor &color)
286 {
287     Q_D(QDeclarative1TextInput);
288     if (d->selectionColor == color)
289         return;
290
291     d->selectionColor = color;
292     QPalette p = d->control->palette();
293     p.setColor(QPalette::Highlight, d->selectionColor);
294     d->control->setPalette(p);
295     if (d->control->hasSelectedText()) {
296         clearCache();
297         update();
298     }
299     emit selectionColorChanged(color);
300 }
301
302 /*!
303     \qmlproperty color QtQuick1::TextInput::selectedTextColor
304
305     The highlighted text color, used in selections.
306 */
307 QColor QDeclarative1TextInput::selectedTextColor() const
308 {
309     Q_D(const QDeclarative1TextInput);
310     return d->selectedTextColor;
311 }
312
313 void QDeclarative1TextInput::setSelectedTextColor(const QColor &color)
314 {
315     Q_D(QDeclarative1TextInput);
316     if (d->selectedTextColor == color)
317         return;
318
319     d->selectedTextColor = color;
320     QPalette p = d->control->palette();
321     p.setColor(QPalette::HighlightedText, d->selectedTextColor);
322     d->control->setPalette(p);
323     if (d->control->hasSelectedText()) {
324         clearCache();
325         update();
326     }
327     emit selectedTextColorChanged(color);
328 }
329
330 /*!
331     \qmlproperty enumeration QtQuick1::TextInput::horizontalAlignment
332     \qmlproperty enumeration QtQuick1::TextInput::effectiveHorizontalAlignment
333
334     Sets the horizontal alignment of the text within the TextInput item's
335     width and height. By default, the text alignment follows the natural alignment
336     of the text, for example text that is read from left to right will be aligned to
337     the left.
338
339     TextInput does not have vertical alignment, as the natural height is
340     exactly the height of the single line of text. If you set the height
341     manually to something larger, TextInput will always be top aligned
342     vertically. You can use anchors to align it however you want within
343     another item.
344
345     The valid values for \c horizontalAlignment are \c TextInput.AlignLeft, \c TextInput.AlignRight and
346     \c TextInput.AlignHCenter.
347
348     When using the attached property LayoutMirroring::enabled to mirror application
349     layouts, the horizontal alignment of text will also be mirrored. However, the property
350     \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
351     of TextInput, use the read-only property \c effectiveHorizontalAlignment.
352 */
353 QDeclarative1TextInput::HAlignment QDeclarative1TextInput::hAlign() const
354 {
355     Q_D(const QDeclarative1TextInput);
356     return d->hAlign;
357 }
358
359 void QDeclarative1TextInput::setHAlign(HAlignment align)
360 {
361     Q_D(QDeclarative1TextInput);
362     bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror;
363     d->hAlignImplicit = false;
364     if (d->setHAlign(align, forceAlign) && isComponentComplete()) {
365         updateCursorRectangle();
366     }
367 }
368
369 void QDeclarative1TextInput::resetHAlign()
370 {
371     Q_D(QDeclarative1TextInput);
372     d->hAlignImplicit = true;
373     if (d->determineHorizontalAlignment() && isComponentComplete()) {
374         updateCursorRectangle();
375     }
376 }
377
378 QDeclarative1TextInput::HAlignment QDeclarative1TextInput::effectiveHAlign() const
379 {
380     Q_D(const QDeclarative1TextInput);
381     QDeclarative1TextInput::HAlignment effectiveAlignment = d->hAlign;
382     if (!d->hAlignImplicit && d->effectiveLayoutMirror) {
383         switch (d->hAlign) {
384         case QDeclarative1TextInput::AlignLeft:
385             effectiveAlignment = QDeclarative1TextInput::AlignRight;
386             break;
387         case QDeclarative1TextInput::AlignRight:
388             effectiveAlignment = QDeclarative1TextInput::AlignLeft;
389             break;
390         default:
391             break;
392         }
393     }
394     return effectiveAlignment;
395 }
396
397 bool QDeclarative1TextInputPrivate::setHAlign(QDeclarative1TextInput::HAlignment alignment, bool forceAlign)
398 {
399     Q_Q(QDeclarative1TextInput);
400     if ((hAlign != alignment || forceAlign) && alignment <= QDeclarative1TextInput::AlignHCenter) { // justify not supported
401         QDeclarative1TextInput::HAlignment oldEffectiveHAlign = q->effectiveHAlign();
402         hAlign = alignment;
403         emit q->horizontalAlignmentChanged(alignment);
404         if (oldEffectiveHAlign != q->effectiveHAlign())
405             emit q->effectiveHorizontalAlignmentChanged();
406         return true;
407     }
408     return false;
409 }
410
411 bool QDeclarative1TextInputPrivate::determineHorizontalAlignment()
412 {
413     if (hAlignImplicit) {
414         // if no explicit alignment has been set, follow the natural layout direction of the text
415         QString text = control->text();
416         bool isRightToLeft = text.isEmpty() ? QApplication::keyboardInputDirection() == Qt::RightToLeft : text.isRightToLeft();
417         return setHAlign(isRightToLeft ? QDeclarative1TextInput::AlignRight : QDeclarative1TextInput::AlignLeft);
418     }
419     return false;
420 }
421
422 void QDeclarative1TextInputPrivate::mirrorChange()
423 {
424     Q_Q(QDeclarative1TextInput);
425     if (q->isComponentComplete()) {
426         if (!hAlignImplicit && (hAlign == QDeclarative1TextInput::AlignRight || hAlign == QDeclarative1TextInput::AlignLeft)) {
427             q->updateCursorRectangle();
428             emit q->effectiveHorizontalAlignmentChanged();
429         }
430     }
431 }
432
433 /*!
434     \qmlproperty bool QtQuick1::TextInput::readOnly
435
436     Sets whether user input can modify the contents of the TextInput.
437
438     If readOnly is set to true, then user input will not affect the text
439     property. Any bindings or attempts to set the text property will still
440     work.
441 */
442
443 bool QDeclarative1TextInput::isReadOnly() const
444 {
445     Q_D(const QDeclarative1TextInput);
446     return d->control->isReadOnly();
447 }
448
449 void QDeclarative1TextInput::setReadOnly(bool ro)
450 {
451     Q_D(QDeclarative1TextInput);
452     if (d->control->isReadOnly() == ro)
453         return;
454
455     setFlag(QGraphicsItem::ItemAcceptsInputMethod, !ro);
456     d->control->setReadOnly(ro);
457
458     emit readOnlyChanged(ro);
459 }
460
461 /*!
462     \qmlproperty int QtQuick1::TextInput::maximumLength
463     The maximum permitted length of the text in the TextInput.
464
465     If the text is too long, it is truncated at the limit.
466
467     By default, this property contains a value of 32767.
468 */
469 int QDeclarative1TextInput::maxLength() const
470 {
471     Q_D(const QDeclarative1TextInput);
472     return d->control->maxLength();
473 }
474
475 void QDeclarative1TextInput::setMaxLength(int ml)
476 {
477     Q_D(QDeclarative1TextInput);
478     if (d->control->maxLength() == ml)
479         return;
480
481     d->control->setMaxLength(ml);
482
483     emit maximumLengthChanged(ml);
484 }
485
486 /*!
487     \qmlproperty bool QtQuick1::TextInput::cursorVisible
488     Set to true when the TextInput shows a cursor.
489
490     This property is set and unset when the TextInput gets active focus, so that other
491     properties can be bound to whether the cursor is currently showing. As it
492     gets set and unset automatically, when you set the value yourself you must
493     keep in mind that your value may be overwritten.
494
495     It can be set directly in script, for example if a KeyProxy might
496     forward keys to it and you desire it to look active when this happens
497     (but without actually giving it active focus).
498
499     It should not be set directly on the element, like in the below QML,
500     as the specified value will be overridden an lost on focus changes.
501
502     \code
503     TextInput {
504         text: "Text"
505         cursorVisible: false
506     }
507     \endcode
508
509     In the above snippet the cursor will still become visible when the
510     TextInput gains active focus.
511 */
512 bool QDeclarative1TextInput::isCursorVisible() const
513 {
514     Q_D(const QDeclarative1TextInput);
515     return d->cursorVisible;
516 }
517
518 void QDeclarative1TextInput::setCursorVisible(bool on)
519 {
520     Q_D(QDeclarative1TextInput);
521     if (d->cursorVisible == on)
522         return;
523     d->cursorVisible = on;
524     d->control->setCursorBlinkPeriod(on?QApplication::cursorFlashTime():0);
525     QRect r = d->control->cursorRect();
526     if (d->control->inputMask().isEmpty())
527         updateRect(r);
528     else
529         updateRect();
530     emit cursorVisibleChanged(d->cursorVisible);
531 }
532
533 /*!
534     \qmlproperty int QtQuick1::TextInput::cursorPosition
535     The position of the cursor in the TextInput.
536 */
537 int QDeclarative1TextInput::cursorPosition() const
538 {
539     Q_D(const QDeclarative1TextInput);
540     return d->control->cursor();
541 }
542 void QDeclarative1TextInput::setCursorPosition(int cp)
543 {
544     Q_D(QDeclarative1TextInput);
545     if (cp < 0 || cp > d->control->text().length())
546         return;
547     d->control->moveCursor(cp);
548 }
549
550 /*!
551   Returns a Rect which encompasses the cursor, but which may be larger than is
552   required. Ignores custom cursor delegates.
553 */
554 QRect QDeclarative1TextInput::cursorRectangle() const
555 {
556     Q_D(const QDeclarative1TextInput);
557     QRect r = d->control->cursorRect();
558     // Scroll and make consistent with TextEdit
559     // QLineControl inexplicably adds 1 to the height and horizontal padding
560     // for unicode direction markers.
561     r.adjust(5 - d->hscroll, 0, -4 - d->hscroll, -1);
562     return r;
563 }
564
565 /*!
566     \qmlproperty int QtQuick1::TextInput::selectionStart
567
568     The cursor position before the first character in the current selection.
569
570     This property is read-only. To change the selection, use select(start,end),
571     selectAll(), or selectWord().
572
573     \sa selectionEnd, cursorPosition, selectedText
574 */
575 int QDeclarative1TextInput::selectionStart() const
576 {
577     Q_D(const QDeclarative1TextInput);
578     return d->lastSelectionStart;
579 }
580
581 /*!
582     \qmlproperty int QtQuick1::TextInput::selectionEnd
583
584     The cursor position after the last character in the current selection.
585
586     This property is read-only. To change the selection, use select(start,end),
587     selectAll(), or selectWord().
588
589     \sa selectionStart, cursorPosition, selectedText
590 */
591 int QDeclarative1TextInput::selectionEnd() const
592 {
593     Q_D(const QDeclarative1TextInput);
594     return d->lastSelectionEnd;
595 }
596
597 /*!
598     \qmlmethod void QtQuick1::TextInput::select(int start, int end)
599
600     Causes the text from \a start to \a end to be selected.
601
602     If either start or end is out of range, the selection is not changed.
603
604     After calling this, selectionStart will become the lesser
605     and selectionEnd will become the greater (regardless of the order passed
606     to this method).
607
608     \sa selectionStart, selectionEnd
609 */
610 void QDeclarative1TextInput::select(int start, int end)
611 {
612     Q_D(QDeclarative1TextInput);
613     if (start < 0 || end < 0 || start > d->control->text().length() || end > d->control->text().length())
614         return;
615     d->control->setSelection(start, end-start);
616 }
617
618 /*!
619     \qmlproperty string QtQuick1::TextInput::selectedText
620
621     This read-only property provides the text currently selected in the
622     text input.
623
624     It is equivalent to the following snippet, but is faster and easier
625     to use.
626
627     \js
628     myTextInput.text.toString().substring(myTextInput.selectionStart,
629         myTextInput.selectionEnd);
630     \endjs
631 */
632 QString QDeclarative1TextInput::selectedText() const
633 {
634     Q_D(const QDeclarative1TextInput);
635     return d->control->selectedText();
636 }
637
638 /*!
639     \qmlproperty bool QtQuick1::TextInput::activeFocusOnPress
640
641     Whether the TextInput should gain active focus on a mouse press. By default this is
642     set to true.
643 */
644 bool QDeclarative1TextInput::focusOnPress() const
645 {
646     Q_D(const QDeclarative1TextInput);
647     return d->focusOnPress;
648 }
649
650 void QDeclarative1TextInput::setFocusOnPress(bool b)
651 {
652     Q_D(QDeclarative1TextInput);
653     if (d->focusOnPress == b)
654         return;
655
656     d->focusOnPress = b;
657
658     emit activeFocusOnPressChanged(d->focusOnPress);
659 }
660
661 /*!
662     \qmlproperty bool QtQuick1::TextInput::autoScroll
663
664     Whether the TextInput should scroll when the text is longer than the width. By default this is
665     set to true.
666 */
667 bool QDeclarative1TextInput::autoScroll() const
668 {
669     Q_D(const QDeclarative1TextInput);
670     return d->autoScroll;
671 }
672
673 void QDeclarative1TextInput::setAutoScroll(bool b)
674 {
675     Q_D(QDeclarative1TextInput);
676     if (d->autoScroll == b)
677         return;
678
679     d->autoScroll = b;
680     //We need to repaint so that the scrolling is taking into account.
681     updateSize(true);
682     updateCursorRectangle();
683     emit autoScrollChanged(d->autoScroll);
684 }
685
686 /*!
687     \qmlclass IntValidator QIntValidator
688     \inqmlmodule QtQuick 1
689     \ingroup qml-basic-visual-elements
690
691     This element provides a validator for integer values.
692
693     IntValidator uses the \l {QLocale::setDefault()}{default locale} to interpret the number and
694     will accept locale specific digits, group separators, and positive and negative signs.  In
695     addition, IntValidator is always guaranteed to accept a number formatted according to the "C"
696     locale.
697 */
698 /*!
699     \qmlproperty int QtQuick1::IntValidator::top
700
701     This property holds the validator's highest acceptable value.
702     By default, this property's value is derived from the highest signed integer available (typically 2147483647).
703 */
704 /*!
705     \qmlproperty int QtQuick1::IntValidator::bottom
706
707     This property holds the validator's lowest acceptable value.
708     By default, this property's value is derived from the lowest signed integer available (typically -2147483647).
709 */
710
711 /*!
712     \qmlclass DoubleValidator QDoubleValidator
713     \inqmlmodule QtQuick 1
714     \ingroup qml-basic-visual-elements
715
716     This element provides a validator for non-integer numbers.
717 */
718
719 /*!
720     \qmlproperty real QtQuick1::DoubleValidator::top
721
722     This property holds the validator's maximum acceptable value.
723     By default, this property contains a value of infinity.
724 */
725 /*!
726     \qmlproperty real QtQuick1::DoubleValidator::bottom
727
728     This property holds the validator's minimum acceptable value.
729     By default, this property contains a value of -infinity.
730 */
731 /*!
732     \qmlproperty int QtQuick1::DoubleValidator::decimals
733
734     This property holds the validator's maximum number of digits after the decimal point.
735     By default, this property contains a value of 1000.
736 */
737 /*!
738     \qmlproperty enumeration QtQuick1::DoubleValidator::notation
739     This property holds the notation of how a string can describe a number.
740
741     The possible values for this property are:
742     
743     \list
744     \o DoubleValidator.StandardNotation 
745     \o DoubleValidator.ScientificNotation (default)
746     \endlist
747
748     If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part (e.g. 1.5E-2).
749 */
750
751 /*!
752     \qmlclass RegExpValidator QRegExpValidator
753     \inqmlmodule QtQuick 1
754     \ingroup qml-basic-visual-elements
755
756     This element provides a validator, which counts as valid any string which
757     matches a specified regular expression.
758 */
759 /*!
760    \qmlproperty regExp QtQuick1::RegExpValidator::regExp
761
762    This property holds the regular expression used for validation.
763
764    Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular expression
765    matching "a".
766
767    By default, this property contains a regular expression with the pattern .* that matches any string.
768 */
769
770 /*!
771     \qmlproperty Validator QtQuick1::TextInput::validator
772
773     Allows you to set a validator on the TextInput. When a validator is set
774     the TextInput will only accept input which leaves the text property in
775     an acceptable or intermediate state. The accepted signal will only be sent
776     if the text is in an acceptable state when enter is pressed.
777
778     Currently supported validators are IntValidator, DoubleValidator and
779     RegExpValidator. An example of using validators is shown below, which allows
780     input of integers between 11 and 31 into the text input:
781
782     \code
783     import QtQuick 1.0
784     TextInput{
785         validator: IntValidator{bottom: 11; top: 31;}
786         focus: true
787     }
788     \endcode
789
790     \sa acceptableInput, inputMask
791 */
792 #ifndef QT_NO_VALIDATOR
793 QValidator* QDeclarative1TextInput::validator() const
794 {
795     Q_D(const QDeclarative1TextInput);
796     //###const cast isn't good, but needed for property system?
797     return const_cast<QValidator*>(d->control->validator());
798 }
799
800 void QDeclarative1TextInput::setValidator(QValidator* v)
801 {
802     Q_D(QDeclarative1TextInput);
803     if (d->control->validator() == v)
804         return;
805
806     d->control->setValidator(v);
807     if(!d->control->hasAcceptableInput()){
808         d->oldValidity = false;
809         emit acceptableInputChanged();
810     }
811
812     emit validatorChanged();
813 }
814 #endif // QT_NO_VALIDATOR
815
816 /*!
817     \qmlproperty string QtQuick1::TextInput::inputMask
818
819     Allows you to set an input mask on the TextInput, restricting the allowable
820     text inputs. See QLineEdit::inputMask for further details, as the exact
821     same mask strings are used by TextInput.
822
823     \sa acceptableInput, validator
824 */
825 QString QDeclarative1TextInput::inputMask() const
826 {
827     Q_D(const QDeclarative1TextInput);
828     return d->control->inputMask();
829 }
830
831 void QDeclarative1TextInput::setInputMask(const QString &im)
832 {
833     Q_D(QDeclarative1TextInput);
834     if (d->control->inputMask() == im)
835         return;
836
837     d->control->setInputMask(im);
838     emit inputMaskChanged(d->control->inputMask());
839 }
840
841 /*!
842     \qmlproperty bool QtQuick1::TextInput::acceptableInput
843
844     This property is always true unless a validator or input mask has been set.
845     If a validator or input mask has been set, this property will only be true
846     if the current text is acceptable to the validator or input mask as a final
847     string (not as an intermediate string).
848 */
849 bool QDeclarative1TextInput::hasAcceptableInput() const
850 {
851     Q_D(const QDeclarative1TextInput);
852     return d->control->hasAcceptableInput();
853 }
854
855 /*!
856     \qmlsignal QtQuick1::TextInput::onAccepted()
857
858     This handler is called when the Return or Enter key is pressed.
859     Note that if there is a \l validator or \l inputMask set on the text
860     input, the handler will only be emitted if the input is in an acceptable
861     state.
862 */
863
864 void QDeclarative1TextInputPrivate::updateInputMethodHints()
865 {
866     Q_Q(QDeclarative1TextInput);
867     Qt::InputMethodHints hints = inputMethodHints;
868     uint echo = control->echoMode();
869     if (echo == QDeclarative1TextInput::Password || echo == QDeclarative1TextInput::NoEcho)
870         hints |= Qt::ImhHiddenText;
871     else if (echo == QDeclarative1TextInput::PasswordEchoOnEdit)
872         hints &= ~Qt::ImhHiddenText;
873     if (echo != QDeclarative1TextInput::Normal) {
874         hints |= Qt::ImhNoAutoUppercase;
875         hints |= Qt::ImhNoPredictiveText;
876     }
877     q->setInputMethodHints(hints);
878 }
879
880 /*!
881     \qmlproperty enumeration QtQuick1::TextInput::echoMode
882
883     Specifies how the text should be displayed in the TextInput.
884     \list
885     \o TextInput.Normal - Displays the text as it is. (Default)
886     \o TextInput.Password - Displays asterixes instead of characters.
887     \o TextInput.NoEcho - Displays nothing.
888     \o TextInput.PasswordEchoOnEdit - Displays characters as they are entered
889     while editing, otherwise displays asterisks.
890     \endlist
891 */
892 QDeclarative1TextInput::EchoMode QDeclarative1TextInput::echoMode() const
893 {
894     Q_D(const QDeclarative1TextInput);
895     return (QDeclarative1TextInput::EchoMode)d->control->echoMode();
896 }
897
898 void QDeclarative1TextInput::setEchoMode(QDeclarative1TextInput::EchoMode echo)
899 {
900     Q_D(QDeclarative1TextInput);
901     if (echoMode() == echo)
902         return;
903     d->control->setEchoMode((QLineControl::EchoMode)echo);
904     d->updateInputMethodHints();
905     q_textChanged();
906     emit echoModeChanged(echoMode());
907 }
908
909 Qt::InputMethodHints QDeclarative1TextInput::imHints() const
910 {
911     Q_D(const QDeclarative1TextInput);
912     return d->inputMethodHints;
913 }
914
915 void QDeclarative1TextInput::setIMHints(Qt::InputMethodHints hints)
916 {
917     Q_D(QDeclarative1TextInput);
918     if (d->inputMethodHints == hints)
919         return;
920     d->inputMethodHints = hints;
921     d->updateInputMethodHints();
922 }
923
924 /*!
925     \qmlproperty Component QtQuick1::TextInput::cursorDelegate
926     The delegate for the cursor in the TextInput.
927
928     If you set a cursorDelegate for a TextInput, this delegate will be used for
929     drawing the cursor instead of the standard cursor. An instance of the
930     delegate will be created and managed by the TextInput when a cursor is
931     needed, and the x property of delegate instance will be set so as
932     to be one pixel before the top left of the current character.
933
934     Note that the root item of the delegate component must be a QDeclarativeItem or
935     QDeclarativeItem derived item.
936 */
937 QDeclarativeComponent* QDeclarative1TextInput::cursorDelegate() const
938 {
939     Q_D(const QDeclarative1TextInput);
940     return d->cursorComponent;
941 }
942
943 void QDeclarative1TextInput::setCursorDelegate(QDeclarativeComponent* c)
944 {
945     Q_D(QDeclarative1TextInput);
946     if (d->cursorComponent == c)
947         return;
948
949     d->cursorComponent = c;
950     if(!c){
951         //note that the components are owned by something else
952         delete d->cursorItem;
953     }else{
954         d->startCreatingCursor();
955     }
956
957     emit cursorDelegateChanged();
958 }
959
960 void QDeclarative1TextInputPrivate::startCreatingCursor()
961 {
962     Q_Q(QDeclarative1TextInput);
963     if(cursorComponent->isReady()){
964         q->createCursor();
965     }else if(cursorComponent->isLoading()){
966         q->connect(cursorComponent, SIGNAL(statusChanged(int)),
967                 q, SLOT(createCursor()));
968     }else {//isError
969         qmlInfo(q, cursorComponent->errors()) << QDeclarative1TextInput::tr("Could not load cursor delegate");
970     }
971 }
972
973 void QDeclarative1TextInput::createCursor()
974 {
975     Q_D(QDeclarative1TextInput);
976     if(d->cursorComponent->isError()){
977         qmlInfo(this, d->cursorComponent->errors()) << tr("Could not load cursor delegate");
978         return;
979     }
980
981     if(!d->cursorComponent->isReady())
982         return;
983
984     if(d->cursorItem)
985         delete d->cursorItem;
986     d->cursorItem = qobject_cast<QDeclarativeItem*>(d->cursorComponent->create());
987     if(!d->cursorItem){
988         qmlInfo(this, d->cursorComponent->errors()) << tr("Could not instantiate cursor delegate");
989         return;
990     }
991
992     QDeclarative_setParent_noEvent(d->cursorItem, this);
993     d->cursorItem->setParentItem(this);
994     d->cursorItem->setX(d->control->cursorToX());
995     d->cursorItem->setHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
996 }
997
998 /*!
999     \qmlmethod rect QtQuick1::TextInput::positionToRectangle(int pos)
1000
1001     This function takes a character position and returns the rectangle that the
1002     cursor would occupy, if it was placed at that character position.
1003
1004     This is similar to setting the cursorPosition, and then querying the cursor
1005     rectangle, but the cursorPosition is not changed.
1006 */
1007 QRectF QDeclarative1TextInput::positionToRectangle(int pos) const
1008 {
1009     Q_D(const QDeclarative1TextInput);
1010     if (pos > d->control->cursorPosition())
1011         pos += d->control->preeditAreaText().length();
1012     return QRectF(d->control->cursorToX(pos)-d->hscroll,
1013         0.0,
1014         d->control->cursorWidth(),
1015         cursorRectangle().height());
1016 }
1017
1018 int QDeclarative1TextInput::positionAt(int x) const
1019 {
1020     return positionAt(x, CursorBetweenCharacters);
1021 }
1022
1023 /*!
1024     \qmlmethod int QtQuick1::TextInput::positionAt(int x, CursorPosition position = CursorBetweenCharacters)
1025     \since Quick 1.1
1026
1027     This function returns the character position at
1028     x pixels from the left of the textInput. Position 0 is before the
1029     first character, position 1 is after the first character but before the second,
1030     and so on until position text.length, which is after all characters.
1031
1032     This means that for all x values before the first character this function returns 0,
1033     and for all x values after the last character this function returns text.length.
1034
1035     The cursor position type specifies how the cursor position should be resolved.
1036
1037     \list
1038     \o TextInput.CursorBetweenCharacters - Returns the position between characters that is nearest x.
1039     \o TextInput.CursorOnCharacter - Returns the position before the character that is nearest x.
1040     \endlist
1041 */
1042 int QDeclarative1TextInput::positionAt(int x, CursorPosition position) const
1043 {
1044     Q_D(const QDeclarative1TextInput);
1045     int pos = d->control->xToPos(x + d->hscroll, QTextLine::CursorPosition(position));
1046     const int cursor = d->control->cursor();
1047     if (pos > cursor) {
1048         const int preeditLength = d->control->preeditAreaText().length();
1049         pos = pos > cursor + preeditLength
1050                 ? pos - preeditLength
1051                 : cursor;
1052     }
1053     return pos;
1054 }
1055
1056 void QDeclarative1TextInputPrivate::focusChanged(bool hasFocus)
1057 {
1058     Q_Q(QDeclarative1TextInput);
1059     focused = hasFocus;
1060     q->setCursorVisible(hasFocus && scene && scene->hasFocus());
1061     if(q->echoMode() == QDeclarative1TextInput::PasswordEchoOnEdit && !hasFocus)
1062         control->updatePasswordEchoEditing(false);//QLineControl sets it on key events, but doesn't deal with focus events
1063     if (!hasFocus)
1064         control->deselect();
1065     QDeclarativeItemPrivate::focusChanged(hasFocus);
1066 }
1067
1068 void QDeclarative1TextInput::keyPressEvent(QKeyEvent* ev)
1069 {
1070     Q_D(QDeclarative1TextInput);
1071     keyPressPreHandler(ev);
1072     if (ev->isAccepted())
1073         return;
1074
1075     // Don't allow MacOSX up/down support, and we don't allow a completer.
1076     bool ignore = (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) && ev->modifiers() == Qt::NoModifier;
1077     if (!ignore && (d->lastSelectionStart == d->lastSelectionEnd) && (ev->key() == Qt::Key_Right || ev->key() == Qt::Key_Left)) {
1078         // Ignore when moving off the end unless there is a selection,
1079         // because then moving will do something (deselect).
1080         int cursorPosition = d->control->cursor();
1081         if (cursorPosition == 0)
1082             ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Left : Qt::Key_Right);
1083         if (cursorPosition == d->control->text().length())
1084             ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Right : Qt::Key_Left);
1085     }
1086     if (ignore) {
1087         ev->ignore();
1088     } else {
1089         d->control->processKeyEvent(ev);
1090     }
1091     if (!ev->isAccepted())
1092         QDeclarative1PaintedItem::keyPressEvent(ev);
1093 }
1094
1095 void QDeclarative1TextInput::inputMethodEvent(QInputMethodEvent *ev)
1096 {
1097     Q_D(QDeclarative1TextInput);
1098     ev->ignore();
1099     const bool wasComposing = d->control->preeditAreaText().length() > 0;
1100     inputMethodPreHandler(ev);
1101     if (!ev->isAccepted()) {
1102         if (d->control->isReadOnly()) {
1103             ev->ignore();
1104         } else {
1105             d->control->processInputMethodEvent(ev);
1106         }
1107     }
1108     if (!ev->isAccepted())
1109         QDeclarative1PaintedItem::inputMethodEvent(ev);
1110
1111     if (wasComposing != (d->control->preeditAreaText().length() > 0))
1112         emit inputMethodComposingChanged();
1113 }
1114
1115 /*!
1116 \overload
1117 Handles the given mouse \a event.
1118 */
1119 void QDeclarative1TextInput::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
1120 {
1121     Q_D(QDeclarative1TextInput);
1122     if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonDblClick))
1123         return;
1124     if (d->selectByMouse) {
1125         int cursor = d->xToPos(event->pos().x());
1126         d->control->selectWordAtPos(cursor);
1127         event->setAccepted(true);
1128     } else {
1129         QDeclarative1PaintedItem::mouseDoubleClickEvent(event);
1130     }
1131 }
1132
1133 void QDeclarative1TextInput::mousePressEvent(QGraphicsSceneMouseEvent *event)
1134 {
1135     Q_D(QDeclarative1TextInput);
1136     if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonPress))
1137         return;
1138     if(d->focusOnPress){
1139         bool hadActiveFocus = hasActiveFocus();
1140         forceActiveFocus();
1141         if (d->showInputPanelOnFocus) {
1142             if (hasActiveFocus() && hadActiveFocus && !isReadOnly()) {
1143                 // re-open input panel on press if already focused
1144                 openSoftwareInputPanel();
1145             }
1146         } else { // show input panel on click
1147             if (hasActiveFocus() && !hadActiveFocus) {
1148                 d->clickCausedFocus = true;
1149             }
1150         }
1151     }
1152     if (d->selectByMouse) {
1153         setKeepMouseGrab(false);
1154         d->selectPressed = true;
1155         d->pressPos = event->pos();
1156     }
1157     bool mark = (event->modifiers() & Qt::ShiftModifier) && d->selectByMouse;
1158     int cursor = d->xToPos(event->pos().x());
1159     d->control->moveCursor(cursor, mark);
1160     event->setAccepted(true);
1161 }
1162
1163 void QDeclarative1TextInput::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
1164 {
1165     Q_D(QDeclarative1TextInput);
1166     if (d->sendMouseEventToInputContext(event, QEvent::MouseMove))
1167         return;
1168     if (d->selectPressed) {
1169         if (qAbs(int(event->pos().x() - d->pressPos.x())) > QApplication::startDragDistance())
1170             setKeepMouseGrab(true);
1171         moveCursorSelection(d->xToPos(event->pos().x()), d->mouseSelectionMode);
1172         event->setAccepted(true);
1173     } else {
1174         QDeclarative1PaintedItem::mouseMoveEvent(event);
1175     }
1176 }
1177
1178 /*!
1179 \overload
1180 Handles the given mouse \a event.
1181 */
1182 void QDeclarative1TextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
1183 {
1184     Q_D(QDeclarative1TextInput);
1185     if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonRelease))
1186         return;
1187     if (d->selectPressed) {
1188         d->selectPressed = false;
1189         setKeepMouseGrab(false);
1190     }
1191     if (!d->showInputPanelOnFocus) { // input panel on click
1192         if (d->focusOnPress && !isReadOnly() && boundingRect().contains(event->pos())) {
1193             if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1194                 if (view->scene() && view->scene() == scene()) {
1195                     qt_widget_private(view)->handleSoftwareInputPanel(event->button(), d->clickCausedFocus);
1196                 }
1197             }
1198         }
1199     }
1200     d->clickCausedFocus = false;
1201     d->control->processEvent(event);
1202     if (!event->isAccepted())
1203         QDeclarative1PaintedItem::mouseReleaseEvent(event);
1204 }
1205
1206 bool QDeclarative1TextInputPrivate::sendMouseEventToInputContext(
1207         QGraphicsSceneMouseEvent *event, QEvent::Type eventType)
1208 {
1209 #if !defined QT_NO_IM
1210     if (event->widget() && control->composeMode()) {
1211         int tmp_cursor = xToPos(event->pos().x());
1212         int mousePos = tmp_cursor - control->cursor();
1213         if (mousePos < 0 || mousePos > control->preeditAreaText().length()) {
1214             mousePos = -1;
1215             // don't send move events outside the preedit area
1216             if (eventType == QEvent::MouseMove)
1217                 return true;
1218         }
1219
1220         QInputContext *qic = event->widget()->inputContext();
1221         if (qic) {
1222             QMouseEvent mouseEvent(
1223                     eventType,
1224                     event->widget()->mapFromGlobal(event->screenPos()),
1225                     event->screenPos(),
1226                     event->button(),
1227                     event->buttons(),
1228                     event->modifiers());
1229             // may be causing reset() in some input methods
1230             qic->mouseHandler(mousePos, &mouseEvent);
1231             event->setAccepted(mouseEvent.isAccepted());
1232         }
1233         if (!control->preeditAreaText().isEmpty())
1234             return true;
1235     }
1236 #else
1237     Q_UNUSED(event);
1238     Q_UNUSED(eventType)
1239 #endif
1240
1241     return false;
1242 }
1243
1244 bool QDeclarative1TextInput::sceneEvent(QEvent *event)
1245 {
1246     Q_D(QDeclarative1TextInput);
1247     bool rv = QDeclarativeItem::sceneEvent(event);
1248     if (event->type() == QEvent::UngrabMouse) {
1249         d->selectPressed = false;
1250         setKeepMouseGrab(false);
1251     }
1252     return rv;
1253 }
1254
1255 bool QDeclarative1TextInput::event(QEvent* ev)
1256 {
1257     Q_D(QDeclarative1TextInput);
1258     //Anything we don't deal with ourselves, pass to the control
1259     bool handled = false;
1260     switch(ev->type()){
1261         case QEvent::KeyPress:
1262         case QEvent::KeyRelease://###Should the control be doing anything with release?
1263         case QEvent::InputMethod:
1264         case QEvent::GraphicsSceneMousePress:
1265         case QEvent::GraphicsSceneMouseMove:
1266         case QEvent::GraphicsSceneMouseRelease:
1267         case QEvent::GraphicsSceneMouseDoubleClick:
1268             break;
1269         default:
1270             handled = d->control->processEvent(ev);
1271     }
1272     if(!handled)
1273         handled = QDeclarative1PaintedItem::event(ev);
1274     return handled;
1275 }
1276
1277 void QDeclarative1TextInput::geometryChanged(const QRectF &newGeometry,
1278                                   const QRectF &oldGeometry)
1279 {
1280     Q_D(QDeclarative1TextInput);
1281     if (newGeometry.width() != oldGeometry.width()) {
1282         updateSize();
1283         updateCursorRectangle();
1284     }
1285     QDeclarative1PaintedItem::geometryChanged(newGeometry, oldGeometry);
1286 }
1287
1288 int QDeclarative1TextInputPrivate::calculateTextWidth()
1289 {
1290     return qRound(control->naturalTextWidth());
1291 }
1292
1293 void QDeclarative1TextInputPrivate::updateHorizontalScroll()
1294 {
1295     Q_Q(QDeclarative1TextInput);
1296     const int preeditLength = control->preeditAreaText().length();
1297     int cix = qRound(control->cursorToX(control->cursor() + preeditLength));
1298     QRect br(q->boundingRect().toRect());
1299     int widthUsed = calculateTextWidth();
1300
1301     QDeclarative1TextInput::HAlignment effectiveHAlign = q->effectiveHAlign();
1302     if (autoScroll) {
1303         if (widthUsed <=  br.width()) {
1304             // text fits in br; use hscroll for alignment
1305             switch (effectiveHAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) {
1306             case Qt::AlignRight:
1307                 hscroll = widthUsed - br.width() - 1;
1308                 break;
1309             case Qt::AlignHCenter:
1310                 hscroll = (widthUsed - br.width()) / 2;
1311                 break;
1312             default:
1313                 // Left
1314                 hscroll = 0;
1315                 break;
1316             }
1317         } else if (cix - hscroll >= br.width()) {
1318             // text doesn't fit, cursor is to the right of br (scroll right)
1319             hscroll = cix - br.width() + 1;
1320         } else if (cix - hscroll < 0 && hscroll < widthUsed) {
1321             // text doesn't fit, cursor is to the left of br (scroll left)
1322             hscroll = cix;
1323         } else if (widthUsed - hscroll < br.width()) {
1324             // text doesn't fit, text document is to the left of br; align
1325             // right
1326             hscroll = widthUsed - br.width() + 1;
1327         }
1328         if (preeditLength > 0) {
1329             // check to ensure long pre-edit text doesn't push the cursor
1330             // off to the left
1331              cix = qRound(control->cursorToX(
1332                      control->cursor() + qMax(0, control->preeditCursor() - 1)));
1333              if (cix < hscroll)
1334                  hscroll = cix;
1335         }
1336     } else {
1337         switch (effectiveHAlign) {
1338         case QDeclarative1TextInput::AlignRight:
1339             hscroll = q->width() - widthUsed;
1340             break;
1341         case QDeclarative1TextInput::AlignHCenter:
1342             hscroll = (q->width() - widthUsed) / 2;
1343             break;
1344         default:
1345             // Left
1346             hscroll = 0;
1347             break;
1348         }
1349     }
1350 }
1351
1352 void QDeclarative1TextInput::drawContents(QPainter *p, const QRect &r)
1353 {
1354     Q_D(QDeclarative1TextInput);
1355     p->setRenderHint(QPainter::TextAntialiasing, true);
1356     p->save();
1357     p->setPen(QPen(d->color));
1358     int flags = QLineControl::DrawText;
1359     if(!isReadOnly() && d->cursorVisible && !d->cursorItem)
1360         flags |= QLineControl::DrawCursor;
1361     if (d->control->hasSelectedText())
1362             flags |= QLineControl::DrawSelections;
1363     QPoint offset = QPoint(0,0);
1364     QFontMetrics fm = QFontMetrics(d->font);
1365     QRect br(boundingRect().toRect());
1366     if (d->autoScroll) {
1367         // the y offset is there to keep the baseline constant in case we have script changes in the text.
1368         offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent());
1369     } else {
1370         offset = QPoint(d->hscroll, 0);
1371     }
1372     d->control->draw(p, offset, r, flags);
1373     p->restore();
1374 }
1375
1376 /*!
1377 \overload
1378 Returns the value of the given \a property.
1379 */
1380 QVariant QDeclarative1TextInput::inputMethodQuery(Qt::InputMethodQuery property) const
1381 {
1382     Q_D(const QDeclarative1TextInput);
1383     switch(property) {
1384     case Qt::ImMicroFocus:
1385         return cursorRectangle();
1386     case Qt::ImFont:
1387         return font();
1388     case Qt::ImCursorPosition:
1389         return QVariant(d->control->cursor());
1390     case Qt::ImSurroundingText:
1391         if (d->control->echoMode() == PasswordEchoOnEdit && !d->control->passwordEchoEditing())
1392             return QVariant(displayText());
1393         else
1394             return QVariant(text());
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     QEvent event(QEvent::RequestSoftwareInputPanel);
1767     if (qApp) {
1768         if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1769             if (view->scene() && view->scene() == scene()) {
1770                 QApplication::sendEvent(view, &event);
1771             }
1772         }
1773     }
1774 }
1775
1776 /*!
1777     \qmlmethod void QtQuick1::TextInput::closeSoftwareInputPanel()
1778
1779     Closes a software input panel like a virtual keyboard shown on the screen, useful
1780     for customizing when you want the input keyboard to be shown and hidden in
1781     your application.
1782
1783     By default the opening of input panels follows the platform style. On Symbian^1 and
1784     Symbian^3 -based devices the panels are opened by clicking TextInput. On other platforms
1785     the panels are automatically opened when TextInput element gains active focus. Input panels are
1786     always closed if no editor has active focus.
1787
1788   . You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1789     and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1790     the behavior you want.
1791
1792     Only relevant on platforms, which provide virtual keyboards.
1793
1794     \qml
1795         import QtQuick 1.0
1796         TextInput {
1797             id: textInput
1798             text: "Hello world!"
1799             activeFocusOnPress: false
1800             MouseArea {
1801                 anchors.fill: parent
1802                 onClicked: {
1803                     if (!textInput.activeFocus) {
1804                         textInput.forceActiveFocus();
1805                         textInput.openSoftwareInputPanel();
1806                     } else {
1807                         textInput.focus = false;
1808                     }
1809                 }
1810                 onPressAndHold: textInput.closeSoftwareInputPanel();
1811             }
1812         }
1813     \endqml
1814 */
1815 void QDeclarative1TextInput::closeSoftwareInputPanel()
1816 {
1817     QEvent event(QEvent::CloseSoftwareInputPanel);
1818     if (qApp) {
1819         QEvent event(QEvent::CloseSoftwareInputPanel);
1820         if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1821             if (view->scene() && view->scene() == scene()) {
1822                 QApplication::sendEvent(view, &event);
1823             }
1824         }
1825     }
1826 }
1827
1828 void QDeclarative1TextInput::focusInEvent(QFocusEvent *event)
1829 {
1830     Q_D(const QDeclarative1TextInput);
1831     if (d->showInputPanelOnFocus) {
1832         if (d->focusOnPress && !isReadOnly()) {
1833             openSoftwareInputPanel();
1834         }
1835     }
1836     QDeclarative1PaintedItem::focusInEvent(event);
1837 }
1838
1839 /*!
1840     \qmlproperty bool QtQuick1::TextInput::inputMethodComposing
1841
1842     \since QtQuick 1.1
1843
1844     This property holds whether the TextInput has partial text input from an
1845     input method.
1846
1847     While it is composing an input method may rely on mouse or key events from
1848     the TextInput to edit or commit the partial text.  This property can be
1849     used to determine when to disable events handlers that may interfere with
1850     the correct operation of an input method.
1851 */
1852 bool QDeclarative1TextInput::isInputMethodComposing() const
1853 {
1854     Q_D(const QDeclarative1TextInput);
1855     return d->control->preeditAreaText().length() > 0;
1856 }
1857
1858 void QDeclarative1TextInputPrivate::init()
1859 {
1860     Q_Q(QDeclarative1TextInput);
1861     control->setParent(q);//Now mandatory due to accessibility changes
1862     control->setCursorWidth(1);
1863     control->setPasswordCharacter(QLatin1Char('*'));
1864     q->setSmooth(smooth);
1865     q->setAcceptedMouseButtons(Qt::LeftButton);
1866     q->setFlag(QGraphicsItem::ItemHasNoContents, false);
1867     q->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
1868     q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
1869                q, SLOT(cursorPosChanged()));
1870     q->connect(control, SIGNAL(selectionChanged()),
1871                q, SLOT(selectionChanged()));
1872     q->connect(control, SIGNAL(textChanged(QString)),
1873                q, SLOT(q_textChanged()));
1874     q->connect(control, SIGNAL(accepted()),
1875                q, SIGNAL(accepted()));
1876     q->connect(control, SIGNAL(updateNeeded(QRect)),
1877                q, SLOT(updateRect(QRect)));
1878 #ifndef QT_NO_CLIPBOARD
1879     q->connect(q, SIGNAL(readOnlyChanged(bool)),
1880             q, SLOT(q_canPasteChanged()));
1881     q->connect(QApplication::clipboard(), SIGNAL(dataChanged()),
1882             q, SLOT(q_canPasteChanged()));
1883     canPaste = !control->isReadOnly() && QApplication::clipboard()->text().length() != 0;
1884 #endif // QT_NO_CLIPBOARD
1885     q->connect(control, SIGNAL(updateMicroFocus()),
1886                q, SLOT(updateCursorRectangle()));
1887     q->connect(control, SIGNAL(displayTextChanged(QString)),
1888                q, SLOT(updateRect()));
1889     q->updateSize();
1890     oldValidity = control->hasAcceptableInput();
1891     lastSelectionStart = 0;
1892     lastSelectionEnd = 0;
1893     QPalette p = control->palette();
1894     selectedTextColor = p.color(QPalette::HighlightedText);
1895     selectionColor = p.color(QPalette::Highlight);
1896     determineHorizontalAlignment();
1897 }
1898
1899 void QDeclarative1TextInput::cursorPosChanged()
1900 {
1901     Q_D(QDeclarative1TextInput);
1902     updateCursorRectangle();
1903     emit cursorPositionChanged();
1904     d->control->resetCursorBlinkTimer();
1905
1906     if(!d->control->hasSelectedText()){
1907         if(d->lastSelectionStart != d->control->cursor()){
1908             d->lastSelectionStart = d->control->cursor();
1909             emit selectionStartChanged();
1910         }
1911         if(d->lastSelectionEnd != d->control->cursor()){
1912             d->lastSelectionEnd = d->control->cursor();
1913             emit selectionEndChanged();
1914         }
1915     }
1916 }
1917
1918 void QDeclarative1TextInput::updateCursorRectangle()
1919 {
1920     Q_D(QDeclarative1TextInput);
1921     d->updateHorizontalScroll();
1922     updateRect();//TODO: Only update rect between pos's
1923     updateMicroFocus();
1924     emit cursorRectangleChanged();
1925     if (d->cursorItem)
1926         d->cursorItem->setX(d->control->cursorToX() - d->hscroll);
1927 }
1928
1929 void QDeclarative1TextInput::selectionChanged()
1930 {
1931     Q_D(QDeclarative1TextInput);
1932     updateRect();//TODO: Only update rect in selection
1933     emit selectedTextChanged();
1934
1935     if(d->lastSelectionStart != d->control->selectionStart()){
1936         d->lastSelectionStart = d->control->selectionStart();
1937         if(d->lastSelectionStart == -1)
1938             d->lastSelectionStart = d->control->cursor();
1939         emit selectionStartChanged();
1940     }
1941     if(d->lastSelectionEnd != d->control->selectionEnd()){
1942         d->lastSelectionEnd = d->control->selectionEnd();
1943         if(d->lastSelectionEnd == -1)
1944             d->lastSelectionEnd = d->control->cursor();
1945         emit selectionEndChanged();
1946     }
1947 }
1948
1949 void QDeclarative1TextInput::q_textChanged()
1950 {
1951     Q_D(QDeclarative1TextInput);
1952     emit textChanged();
1953     emit displayTextChanged();
1954     updateSize();
1955     d->determineHorizontalAlignment();
1956     d->updateHorizontalScroll();
1957     updateMicroFocus();
1958     if(hasAcceptableInput() != d->oldValidity){
1959         d->oldValidity = hasAcceptableInput();
1960         emit acceptableInputChanged();
1961     }
1962 }
1963
1964 void QDeclarative1TextInput::updateRect(const QRect &r)
1965 {
1966     Q_D(QDeclarative1TextInput);
1967     if(r == QRect())
1968         clearCache();
1969     else
1970         dirtyCache(QRect(r.x() - d->hscroll, r.y(), r.width(), r.height()));
1971     update();
1972 }
1973
1974 QRectF QDeclarative1TextInput::boundingRect() const
1975 {
1976     Q_D(const QDeclarative1TextInput);
1977     QRectF r = QDeclarative1PaintedItem::boundingRect();
1978
1979     int cursorWidth = d->cursorItem ? d->cursorItem->width() : d->control->cursorWidth();
1980
1981     // Could include font max left/right bearings to either side of rectangle.
1982
1983     r.setRight(r.right() + cursorWidth);
1984     return r;
1985 }
1986
1987 void QDeclarative1TextInput::updateSize(bool needsRedraw)
1988 {
1989     Q_D(QDeclarative1TextInput);
1990     int w = width();
1991     int h = height();
1992     setImplicitHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
1993     setImplicitWidth(d->calculateTextWidth());
1994     setContentsSize(QSize(width(), height()));//Repaints if changed
1995     if(w==width() && h==height() && needsRedraw){
1996         clearCache();
1997         update();
1998     }
1999 }
2000
2001 void QDeclarative1TextInput::q_canPasteChanged()
2002 {
2003     Q_D(QDeclarative1TextInput);
2004     bool old = d->canPaste;
2005 #ifndef QT_NO_CLIPBOARD
2006     d->canPaste = !d->control->isReadOnly() && QApplication::clipboard()->text().length() != 0;
2007 #endif
2008     if(d->canPaste != old)
2009         emit canPasteChanged();
2010 }
2011
2012
2013
2014 QT_END_NAMESPACE
2015
2016 #endif // QT_NO_LINEEDIT
2017