1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
42 #include "qquicktextinput_p.h"
43 #include "qquicktextinput_p_p.h"
44 #include "qquickcanvas.h"
46 #include <private/qdeclarativeglobal_p.h>
48 #include <QtDeclarative/qdeclarativeinfo.h>
49 #include <QtGui/qevent.h>
50 #include <QTextBoundaryFinder>
51 #include "qquicktextnode_p.h"
52 #include <QtQuick/qsgsimplerectnode.h>
54 #include <QtGui/qstylehints.h>
55 #include <QtGui/qinputpanel.h>
59 DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
62 \qmlclass TextInput QQuickTextInput
63 \inqmlmodule QtQuick 2
64 \ingroup qml-basic-visual-elements
65 \brief The TextInput item displays an editable line of text.
68 The TextInput element displays a single line of editable plain text.
70 TextInput is used to accept a line of text input. Input constraints
71 can be placed on a TextInput item (for example, through a \l validator or \l inputMask),
72 and setting \l echoMode to an appropriate value enables TextInput to be used for
73 a password input field.
75 On Mac OS X, the Up/Down key bindings for Home/End are explicitly disabled.
76 If you want such bindings (on any platform), you will need to construct them in QML.
78 \sa TextEdit, Text, {declarative/text/textselection}{Text Selection example}
80 QQuickTextInput::QQuickTextInput(QQuickItem* parent)
81 : QQuickImplicitSizeItem(*(new QQuickTextInputPrivate), parent)
87 QQuickTextInput::~QQuickTextInput()
92 \qmlproperty string QtQuick2::TextInput::text
94 The text in the TextInput.
96 QString QQuickTextInput::text() const
98 Q_D(const QQuickTextInput);
99 return d->control->text();
102 void QQuickTextInput::setText(const QString &s)
104 Q_D(QQuickTextInput);
107 d->control->setText(s);
111 \qmlproperty string QtQuick2::TextInput::font.family
113 Sets the family name of the font.
115 The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]".
116 If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen.
117 If the family isn't available a family will be set using the font matching algorithm.
121 \qmlproperty bool QtQuick2::TextInput::font.bold
123 Sets whether the font weight is bold.
127 \qmlproperty enumeration QtQuick2::TextInput::font.weight
129 Sets the font's weight.
131 The weight can be one of:
134 \o Font.Normal - the default
141 TextInput { text: "Hello"; font.weight: Font.DemiBold }
146 \qmlproperty bool QtQuick2::TextInput::font.italic
148 Sets whether the font has an italic style.
152 \qmlproperty bool QtQuick2::TextInput::font.underline
154 Sets whether the text is underlined.
158 \qmlproperty bool QtQuick2::TextInput::font.strikeout
160 Sets whether the font has a strikeout style.
164 \qmlproperty real QtQuick2::TextInput::font.pointSize
166 Sets the font size in points. The point size must be greater than zero.
170 \qmlproperty int QtQuick2::TextInput::font.pixelSize
172 Sets the font size in pixels.
174 Using this function makes the font device dependent.
175 Use \c pointSize to set the size of the font in a device independent manner.
179 \qmlproperty real QtQuick2::TextInput::font.letterSpacing
181 Sets the letter spacing for the font.
183 Letter spacing changes the default spacing between individual letters in the font.
184 A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing.
188 \qmlproperty real QtQuick2::TextInput::font.wordSpacing
190 Sets the word spacing for the font.
192 Word spacing changes the default spacing between individual words.
193 A positive value increases the word spacing by a corresponding amount of pixels,
194 while a negative value decreases the inter-word spacing accordingly.
198 \qmlproperty enumeration QtQuick2::TextInput::font.capitalization
200 Sets the capitalization for the text.
203 \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied.
204 \o Font.AllUppercase - This alters the text to be rendered in all uppercase type.
205 \o Font.AllLowercase - This alters the text to be rendered in all lowercase type.
206 \o Font.SmallCaps - This alters the text to be rendered in small-caps type.
207 \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character.
211 TextInput { text: "Hello"; font.capitalization: Font.AllLowercase }
215 QFont QQuickTextInput::font() const
217 Q_D(const QQuickTextInput);
218 return d->sourceFont;
221 void QQuickTextInput::setFont(const QFont &font)
223 Q_D(QQuickTextInput);
224 if (d->sourceFont == font)
227 d->sourceFont = font;
228 QFont oldFont = d->font;
230 if (d->font.pointSizeF() != -1) {
232 qreal size = qRound(d->font.pointSizeF()*2.0);
233 d->font.setPointSizeF(size/2.0);
235 if (oldFont != d->font) {
236 d->control->setFont(d->font);
238 updateCursorRectangle();
240 d->cursorItem->setHeight(QFontMetrics(d->font).height());
243 emit fontChanged(d->sourceFont);
247 \qmlproperty color QtQuick2::TextInput::color
251 QColor QQuickTextInput::color() const
253 Q_D(const QQuickTextInput);
257 void QQuickTextInput::setColor(const QColor &c)
259 Q_D(QQuickTextInput);
262 d->textLayoutDirty = true;
264 emit colorChanged(c);
270 \qmlproperty color QtQuick2::TextInput::selectionColor
272 The text highlight color, used behind selections.
274 QColor QQuickTextInput::selectionColor() const
276 Q_D(const QQuickTextInput);
277 return d->selectionColor;
280 void QQuickTextInput::setSelectionColor(const QColor &color)
282 Q_D(QQuickTextInput);
283 if (d->selectionColor == color)
286 d->selectionColor = color;
287 QPalette p = d->control->palette();
288 p.setColor(QPalette::Highlight, d->selectionColor);
289 d->control->setPalette(p);
290 if (d->control->hasSelectedText()) {
291 d->textLayoutDirty = true;
294 emit selectionColorChanged(color);
297 \qmlproperty color QtQuick2::TextInput::selectedTextColor
299 The highlighted text color, used in selections.
301 QColor QQuickTextInput::selectedTextColor() const
303 Q_D(const QQuickTextInput);
304 return d->selectedTextColor;
307 void QQuickTextInput::setSelectedTextColor(const QColor &color)
309 Q_D(QQuickTextInput);
310 if (d->selectedTextColor == color)
313 d->selectedTextColor = color;
314 QPalette p = d->control->palette();
315 p.setColor(QPalette::HighlightedText, d->selectedTextColor);
316 d->control->setPalette(p);
317 if (d->control->hasSelectedText()) {
318 d->textLayoutDirty = true;
321 emit selectedTextColorChanged(color);
325 \qmlproperty enumeration QtQuick2::TextInput::horizontalAlignment
326 \qmlproperty enumeration QtQuick2::TextInput::effectiveHorizontalAlignment
328 Sets the horizontal alignment of the text within the TextInput item's
329 width and height. By default, the text alignment follows the natural alignment
330 of the text, for example text that is read from left to right will be aligned to
333 TextInput does not have vertical alignment, as the natural height is
334 exactly the height of the single line of text. If you set the height
335 manually to something larger, TextInput will always be top aligned
336 vertically. You can use anchors to align it however you want within
339 The valid values for \c horizontalAlignment are \c TextInput.AlignLeft, \c TextInput.AlignRight and
340 \c TextInput.AlignHCenter.
342 When using the attached property LayoutMirroring::enabled to mirror application
343 layouts, the horizontal alignment of text will also be mirrored. However, the property
344 \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
345 of TextInput, use the read-only property \c effectiveHorizontalAlignment.
347 QQuickTextInput::HAlignment QQuickTextInput::hAlign() const
349 Q_D(const QQuickTextInput);
353 void QQuickTextInput::setHAlign(HAlignment align)
355 Q_D(QQuickTextInput);
356 bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror;
357 d->hAlignImplicit = false;
358 if (d->setHAlign(align, forceAlign) && isComponentComplete()) {
359 updateCursorRectangle();
363 void QQuickTextInput::resetHAlign()
365 Q_D(QQuickTextInput);
366 d->hAlignImplicit = true;
367 if (d->determineHorizontalAlignment() && isComponentComplete()) {
368 updateCursorRectangle();
372 QQuickTextInput::HAlignment QQuickTextInput::effectiveHAlign() const
374 Q_D(const QQuickTextInput);
375 QQuickTextInput::HAlignment effectiveAlignment = d->hAlign;
376 if (!d->hAlignImplicit && d->effectiveLayoutMirror) {
378 case QQuickTextInput::AlignLeft:
379 effectiveAlignment = QQuickTextInput::AlignRight;
381 case QQuickTextInput::AlignRight:
382 effectiveAlignment = QQuickTextInput::AlignLeft;
388 return effectiveAlignment;
391 bool QQuickTextInputPrivate::setHAlign(QQuickTextInput::HAlignment alignment, bool forceAlign)
393 Q_Q(QQuickTextInput);
394 if ((hAlign != alignment || forceAlign) && alignment <= QQuickTextInput::AlignHCenter) { // justify not supported
395 QQuickTextInput::HAlignment oldEffectiveHAlign = q->effectiveHAlign();
397 emit q->horizontalAlignmentChanged(alignment);
398 if (oldEffectiveHAlign != q->effectiveHAlign())
399 emit q->effectiveHorizontalAlignmentChanged();
405 bool QQuickTextInputPrivate::determineHorizontalAlignment()
407 if (hAlignImplicit) {
408 // if no explicit alignment has been set, follow the natural layout direction of the text
409 QString text = control->text();
411 text = control->preeditAreaText();
412 bool isRightToLeft = text.isEmpty() ? QGuiApplication::keyboardInputDirection() == Qt::RightToLeft : text.isRightToLeft();
413 return setHAlign(isRightToLeft ? QQuickTextInput::AlignRight : QQuickTextInput::AlignLeft);
418 void QQuickTextInputPrivate::mirrorChange()
420 Q_Q(QQuickTextInput);
421 if (q->isComponentComplete()) {
422 if (!hAlignImplicit && (hAlign == QQuickTextInput::AlignRight || hAlign == QQuickTextInput::AlignLeft)) {
423 q->updateCursorRectangle();
424 emit q->effectiveHorizontalAlignmentChanged();
430 \qmlproperty bool QtQuick2::TextInput::readOnly
432 Sets whether user input can modify the contents of the TextInput.
434 If readOnly is set to true, then user input will not affect the text
435 property. Any bindings or attempts to set the text property will still
438 bool QQuickTextInput::isReadOnly() const
440 Q_D(const QQuickTextInput);
441 return d->control->isReadOnly();
444 void QQuickTextInput::setReadOnly(bool ro)
446 Q_D(QQuickTextInput);
447 if (d->control->isReadOnly() == ro)
450 setFlag(QQuickItem::ItemAcceptsInputMethod, !ro);
451 d->control->setReadOnly(ro);
453 d->control->setCursorPosition(d->control->end());
455 emit readOnlyChanged(ro);
459 \qmlproperty int QtQuick2::TextInput::maximumLength
460 The maximum permitted length of the text in the TextInput.
462 If the text is too long, it is truncated at the limit.
464 By default, this property contains a value of 32767.
466 int QQuickTextInput::maxLength() const
468 Q_D(const QQuickTextInput);
469 return d->control->maxLength();
472 void QQuickTextInput::setMaxLength(int ml)
474 Q_D(QQuickTextInput);
475 if (d->control->maxLength() == ml)
478 d->control->setMaxLength(ml);
480 emit maximumLengthChanged(ml);
484 \qmlproperty bool QtQuick2::TextInput::cursorVisible
485 Set to true when the TextInput shows a cursor.
487 This property is set and unset when the TextInput gets active focus, so that other
488 properties can be bound to whether the cursor is currently showing. As it
489 gets set and unset automatically, when you set the value yourself you must
490 keep in mind that your value may be overwritten.
492 It can be set directly in script, for example if a KeyProxy might
493 forward keys to it and you desire it to look active when this happens
494 (but without actually giving it active focus).
496 It should not be set directly on the element, like in the below QML,
497 as the specified value will be overridden an lost on focus changes.
506 In the above snippet the cursor will still become visible when the
507 TextInput gains active focus.
509 bool QQuickTextInput::isCursorVisible() const
511 Q_D(const QQuickTextInput);
512 return d->cursorVisible;
515 void QQuickTextInput::setCursorVisible(bool on)
517 Q_D(QQuickTextInput);
518 if (d->cursorVisible == on)
520 d->cursorVisible = on;
521 d->control->setCursorBlinkPeriod(on ? qApp->styleHints()->cursorFlashTime() : 0);
522 QRect r = d->control->cursorRect();
523 if (d->control->inputMask().isEmpty())
527 emit cursorVisibleChanged(d->cursorVisible);
531 \qmlproperty int QtQuick2::TextInput::cursorPosition
532 The position of the cursor in the TextInput.
534 int QQuickTextInput::cursorPosition() const
536 Q_D(const QQuickTextInput);
537 return d->control->cursor();
539 void QQuickTextInput::setCursorPosition(int cp)
541 Q_D(QQuickTextInput);
542 if (cp < 0 || cp > d->control->text().length())
544 d->control->moveCursor(cp);
548 Returns a Rect which encompasses the cursor, but which may be larger than is
549 required. Ignores custom cursor delegates.
551 QRect QQuickTextInput::cursorRectangle() const
553 Q_D(const QQuickTextInput);
554 QRect r = d->control->cursorRect();
555 // Scroll and make consistent with TextEdit
556 // QQuickLineControl inexplicably adds 1 to the height and horizontal padding
557 // for unicode direction markers.
558 r.adjust(5 - d->hscroll, 0, -4 - d->hscroll, -1);
562 \qmlproperty int QtQuick2::TextInput::selectionStart
564 The cursor position before the first character in the current selection.
566 This property is read-only. To change the selection, use select(start,end),
567 selectAll(), or selectWord().
569 \sa selectionEnd, cursorPosition, selectedText
571 int QQuickTextInput::selectionStart() const
573 Q_D(const QQuickTextInput);
574 return d->lastSelectionStart;
577 \qmlproperty int QtQuick2::TextInput::selectionEnd
579 The cursor position after the last character in the current selection.
581 This property is read-only. To change the selection, use select(start,end),
582 selectAll(), or selectWord().
584 \sa selectionStart, cursorPosition, selectedText
586 int QQuickTextInput::selectionEnd() const
588 Q_D(const QQuickTextInput);
589 return d->lastSelectionEnd;
592 \qmlmethod void QtQuick2::TextInput::select(int start, int end)
594 Causes the text from \a start to \a end to be selected.
596 If either start or end is out of range, the selection is not changed.
598 After calling this, selectionStart will become the lesser
599 and selectionEnd will become the greater (regardless of the order passed
602 \sa selectionStart, selectionEnd
604 void QQuickTextInput::select(int start, int end)
606 Q_D(QQuickTextInput);
607 if (start < 0 || end < 0 || start > d->control->text().length() || end > d->control->text().length())
609 d->control->setSelection(start, end-start);
613 \qmlproperty string QtQuick2::TextInput::selectedText
615 This read-only property provides the text currently selected in the
618 It is equivalent to the following snippet, but is faster and easier
622 myTextInput.text.toString().substring(myTextInput.selectionStart,
623 myTextInput.selectionEnd);
626 QString QQuickTextInput::selectedText() const
628 Q_D(const QQuickTextInput);
629 return d->control->selectedText();
633 \qmlproperty bool QtQuick2::TextInput::activeFocusOnPress
635 Whether the TextInput should gain active focus on a mouse press. By default this is
638 bool QQuickTextInput::focusOnPress() const
640 Q_D(const QQuickTextInput);
641 return d->focusOnPress;
644 void QQuickTextInput::setFocusOnPress(bool b)
646 Q_D(QQuickTextInput);
647 if (d->focusOnPress == b)
652 emit activeFocusOnPressChanged(d->focusOnPress);
655 \qmlproperty bool QtQuick2::TextInput::autoScroll
657 Whether the TextInput should scroll when the text is longer than the width. By default this is
660 bool QQuickTextInput::autoScroll() const
662 Q_D(const QQuickTextInput);
663 return d->autoScroll;
666 void QQuickTextInput::setAutoScroll(bool b)
668 Q_D(QQuickTextInput);
669 if (d->autoScroll == b)
673 //We need to repaint so that the scrolling is taking into account.
675 updateCursorRectangle();
676 emit autoScrollChanged(d->autoScroll);
679 #ifndef QT_NO_VALIDATOR
682 \qmlclass IntValidator QIntValidator
683 \inqmlmodule QtQuick 2
684 \ingroup qml-basic-visual-elements
686 This element provides a validator for integer values.
688 IntValidator uses the \l {QLocale::setDefault()}{default locale} to interpret the number and
689 will accept locale specific digits, group separators, and positive and negative signs. In
690 addition, IntValidator is always guaranteed to accept a number formatted according to the "C"
694 \qmlproperty int QtQuick2::IntValidator::top
696 This property holds the validator's highest acceptable value.
697 By default, this property's value is derived from the highest signed integer available (typically 2147483647).
700 \qmlproperty int QtQuick2::IntValidator::bottom
702 This property holds the validator's lowest acceptable value.
703 By default, this property's value is derived from the lowest signed integer available (typically -2147483647).
707 \qmlclass DoubleValidator QDoubleValidator
708 \inqmlmodule QtQuick 2
709 \ingroup qml-basic-visual-elements
711 This element provides a validator for non-integer numbers.
715 \qmlproperty real QtQuick2::DoubleValidator::top
717 This property holds the validator's maximum acceptable value.
718 By default, this property contains a value of infinity.
721 \qmlproperty real QtQuick2::DoubleValidator::bottom
723 This property holds the validator's minimum acceptable value.
724 By default, this property contains a value of -infinity.
727 \qmlproperty int QtQuick2::DoubleValidator::decimals
729 This property holds the validator's maximum number of digits after the decimal point.
730 By default, this property contains a value of 1000.
733 \qmlproperty enumeration QtQuick2::DoubleValidator::notation
734 This property holds the notation of how a string can describe a number.
736 The possible values for this property are:
739 \o DoubleValidator.StandardNotation
740 \o DoubleValidator.ScientificNotation (default)
743 If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part (e.g. 1.5E-2).
747 \qmlclass RegExpValidator QRegExpValidator
748 \inqmlmodule QtQuick 2
749 \ingroup qml-basic-visual-elements
751 This element provides a validator, which counts as valid any string which
752 matches a specified regular expression.
755 \qmlproperty regExp QtQuick2::RegExpValidator::regExp
757 This property holds the regular expression used for validation.
759 Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular expression
762 By default, this property contains a regular expression with the pattern .* that matches any string.
766 \qmlproperty Validator QtQuick2::TextInput::validator
768 Allows you to set a validator on the TextInput. When a validator is set
769 the TextInput will only accept input which leaves the text property in
770 an acceptable or intermediate state. The accepted signal will only be sent
771 if the text is in an acceptable state when enter is pressed.
773 Currently supported validators are IntValidator, DoubleValidator and
774 RegExpValidator. An example of using validators is shown below, which allows
775 input of integers between 11 and 31 into the text input:
780 validator: IntValidator{bottom: 11; top: 31;}
785 \sa acceptableInput, inputMask
788 QValidator* QQuickTextInput::validator() const
790 Q_D(const QQuickTextInput);
791 //###const cast isn't good, but needed for property system?
792 return const_cast<QValidator*>(d->control->validator());
795 void QQuickTextInput::setValidator(QValidator* v)
797 Q_D(QQuickTextInput);
798 if (d->control->validator() == v)
801 d->control->setValidator(v);
802 if (!d->control->hasAcceptableInput()) {
803 d->oldValidity = false;
804 emit acceptableInputChanged();
807 emit validatorChanged();
809 #endif // QT_NO_VALIDATOR
812 \qmlproperty string QtQuick2::TextInput::inputMask
814 Allows you to set an input mask on the TextInput, restricting the allowable
815 text inputs. See QLineEdit::inputMask for further details, as the exact
816 same mask strings are used by TextInput.
818 \sa acceptableInput, validator
820 QString QQuickTextInput::inputMask() const
822 Q_D(const QQuickTextInput);
823 return d->control->inputMask();
826 void QQuickTextInput::setInputMask(const QString &im)
828 Q_D(QQuickTextInput);
829 if (d->control->inputMask() == im)
832 d->control->setInputMask(im);
833 emit inputMaskChanged(d->control->inputMask());
837 \qmlproperty bool QtQuick2::TextInput::acceptableInput
839 This property is always true unless a validator or input mask has been set.
840 If a validator or input mask has been set, this property will only be true
841 if the current text is acceptable to the validator or input mask as a final
842 string (not as an intermediate string).
844 bool QQuickTextInput::hasAcceptableInput() const
846 Q_D(const QQuickTextInput);
847 return d->control->hasAcceptableInput();
851 \qmlsignal QtQuick2::TextInput::onAccepted()
853 This handler is called when the Return or Enter key is pressed.
854 Note that if there is a \l validator or \l inputMask set on the text
855 input, the handler will only be emitted if the input is in an acceptable
859 void QQuickTextInputPrivate::updateInputMethodHints()
861 Q_Q(QQuickTextInput);
862 Qt::InputMethodHints hints = inputMethodHints;
863 uint echo = control->echoMode();
864 if (echo == QQuickTextInput::Password || echo == QQuickTextInput::NoEcho)
865 hints |= Qt::ImhHiddenText;
866 else if (echo == QQuickTextInput::PasswordEchoOnEdit)
867 hints &= ~Qt::ImhHiddenText;
868 if (echo != QQuickTextInput::Normal)
869 hints |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
870 q->setInputMethodHints(hints);
873 \qmlproperty enumeration QtQuick2::TextInput::echoMode
875 Specifies how the text should be displayed in the TextInput.
877 \o TextInput.Normal - Displays the text as it is. (Default)
878 \o TextInput.Password - Displays asterisks instead of characters.
879 \o TextInput.NoEcho - Displays nothing.
880 \o TextInput.PasswordEchoOnEdit - Displays characters as they are entered
881 while editing, otherwise displays asterisks.
884 QQuickTextInput::EchoMode QQuickTextInput::echoMode() const
886 Q_D(const QQuickTextInput);
887 return (QQuickTextInput::EchoMode)d->control->echoMode();
890 void QQuickTextInput::setEchoMode(QQuickTextInput::EchoMode echo)
892 Q_D(QQuickTextInput);
893 if (echoMode() == echo)
895 d->control->setEchoMode((QQuickLineControl::EchoMode)echo);
896 d->updateInputMethodHints();
898 emit echoModeChanged(echoMode());
901 Qt::InputMethodHints QQuickTextInput::imHints() const
903 Q_D(const QQuickTextInput);
904 return d->inputMethodHints;
907 void QQuickTextInput::setIMHints(Qt::InputMethodHints hints)
909 Q_D(QQuickTextInput);
910 if (d->inputMethodHints == hints)
912 d->inputMethodHints = hints;
913 d->updateInputMethodHints();
917 \qmlproperty Component QtQuick2::TextInput::cursorDelegate
918 The delegate for the cursor in the TextInput.
920 If you set a cursorDelegate for a TextInput, this delegate will be used for
921 drawing the cursor instead of the standard cursor. An instance of the
922 delegate will be created and managed by the TextInput when a cursor is
923 needed, and the x property of delegate instance will be set so as
924 to be one pixel before the top left of the current character.
926 Note that the root item of the delegate component must be a QDeclarativeItem or
927 QDeclarativeItem derived item.
929 QDeclarativeComponent* QQuickTextInput::cursorDelegate() const
931 Q_D(const QQuickTextInput);
932 return d->cursorComponent;
935 void QQuickTextInput::setCursorDelegate(QDeclarativeComponent* c)
937 Q_D(QQuickTextInput);
938 if (d->cursorComponent == c)
941 d->cursorComponent = c;
943 //note that the components are owned by something else
944 delete d->cursorItem;
946 d->startCreatingCursor();
949 emit cursorDelegateChanged();
952 void QQuickTextInputPrivate::startCreatingCursor()
954 Q_Q(QQuickTextInput);
955 if (cursorComponent->isReady()) {
957 } else if (cursorComponent->isLoading()) {
958 q->connect(cursorComponent, SIGNAL(statusChanged(int)),
959 q, SLOT(createCursor()));
961 qmlInfo(q, cursorComponent->errors()) << QQuickTextInput::tr("Could not load cursor delegate");
965 void QQuickTextInput::createCursor()
967 Q_D(QQuickTextInput);
968 if (d->cursorComponent->isError()) {
969 qmlInfo(this, d->cursorComponent->errors()) << tr("Could not load cursor delegate");
973 if (!d->cursorComponent->isReady())
977 delete d->cursorItem;
978 QDeclarativeContext *creationContext = d->cursorComponent->creationContext();
979 QObject *object = d->cursorComponent->create(creationContext ? creationContext : qmlContext(this));
980 d->cursorItem = qobject_cast<QQuickItem*>(object);
981 if (!d->cursorItem) {
983 qmlInfo(this, d->cursorComponent->errors()) << tr("Could not instantiate cursor delegate");
987 QDeclarative_setParent_noEvent(d->cursorItem, this);
988 d->cursorItem->setParentItem(this);
989 d->cursorItem->setX(d->control->cursorToX());
990 d->cursorItem->setHeight(d->control->height()-1); // -1 to counter QQuickLineControl's +1 which is not consistent with Text.
994 \qmlmethod rect QtQuick2::TextInput::positionToRectangle(int pos)
996 This function takes a character position and returns the rectangle that the
997 cursor would occupy, if it was placed at that character position.
999 This is similar to setting the cursorPosition, and then querying the cursor
1000 rectangle, but the cursorPosition is not changed.
1002 QRectF QQuickTextInput::positionToRectangle(int pos) const
1004 Q_D(const QQuickTextInput);
1005 if (pos > d->control->cursorPosition())
1006 pos += d->control->preeditAreaText().length();
1007 return QRectF(d->control->cursorToX(pos)-d->hscroll,
1009 d->control->cursorWidth(),
1010 cursorRectangle().height());
1014 \qmlmethod int QtQuick2::TextInput::positionAt(int x, CursorPosition position = CursorBetweenCharacters)
1016 This function returns the character position at
1017 x pixels from the left of the textInput. Position 0 is before the
1018 first character, position 1 is after the first character but before the second,
1019 and so on until position text.length, which is after all characters.
1021 This means that for all x values before the first character this function returns 0,
1022 and for all x values after the last character this function returns text.length.
1024 The cursor position type specifies how the cursor position should be resolved.
1027 \o TextInput.CursorBetweenCharacters - Returns the position between characters that is nearest x.
1028 \o TextInput.CursorOnCharacter - Returns the position before the character that is nearest x.
1031 int QQuickTextInput::positionAt(int x) const
1033 return positionAt(x, CursorBetweenCharacters);
1036 int QQuickTextInput::positionAt(int x, CursorPosition position) const
1038 Q_D(const QQuickTextInput);
1039 int pos = d->control->xToPos(x + d->hscroll, QTextLine::CursorPosition(position));
1040 const int cursor = d->control->cursor();
1042 const int preeditLength = d->control->preeditAreaText().length();
1043 pos = pos > cursor + preeditLength
1044 ? pos - preeditLength
1050 void QQuickTextInput::keyPressEvent(QKeyEvent* ev)
1052 Q_D(QQuickTextInput);
1053 // Don't allow MacOSX up/down support, and we don't allow a completer.
1054 bool ignore = (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) && ev->modifiers() == Qt::NoModifier;
1055 if (!ignore && (d->lastSelectionStart == d->lastSelectionEnd) && (ev->key() == Qt::Key_Right || ev->key() == Qt::Key_Left)) {
1056 // Ignore when moving off the end unless there is a selection,
1057 // because then moving will do something (deselect).
1058 int cursorPosition = d->control->cursor();
1059 if (cursorPosition == 0)
1060 ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Left : Qt::Key_Right);
1061 if (cursorPosition == d->control->text().length())
1062 ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Right : Qt::Key_Left);
1067 d->control->processKeyEvent(ev);
1069 if (!ev->isAccepted())
1070 QQuickImplicitSizeItem::keyPressEvent(ev);
1073 void QQuickTextInput::inputMethodEvent(QInputMethodEvent *ev)
1075 Q_D(QQuickTextInput);
1076 const bool wasComposing = d->control->preeditAreaText().length() > 0;
1077 if (d->control->isReadOnly()) {
1080 d->control->processInputMethodEvent(ev);
1082 if (!ev->isAccepted())
1083 QQuickImplicitSizeItem::inputMethodEvent(ev);
1085 if (wasComposing != (d->control->preeditAreaText().length() > 0))
1086 emit inputMethodComposingChanged();
1089 void QQuickTextInput::mouseDoubleClickEvent(QMouseEvent *event)
1091 Q_D(QQuickTextInput);
1093 if (d->selectByMouse && event->button() == Qt::LeftButton) {
1094 d->control->commitPreedit();
1095 int cursor = d->xToPos(event->localPos().x());
1096 d->control->selectWordAtPos(cursor);
1097 event->setAccepted(true);
1098 if (!d->hasPendingTripleClick()) {
1099 d->tripleClickStartPoint = event->localPos().toPoint();
1100 d->tripleClickTimer.start();
1103 if (d->sendMouseEventToInputContext(event))
1105 QQuickImplicitSizeItem::mouseDoubleClickEvent(event);
1109 void QQuickTextInput::mousePressEvent(QMouseEvent *event)
1111 Q_D(QQuickTextInput);
1113 d->pressPos = event->localPos();
1115 if (d->focusOnPress) {
1116 bool hadActiveFocus = hasActiveFocus();
1118 // re-open input panel on press if already focused
1119 if (hasActiveFocus() && hadActiveFocus && !isReadOnly())
1120 openSoftwareInputPanel();
1122 if (d->selectByMouse) {
1123 setKeepMouseGrab(false);
1124 d->selectPressed = true;
1125 QPoint distanceVector = d->pressPos.toPoint() - d->tripleClickStartPoint;
1126 if (d->hasPendingTripleClick()
1127 && distanceVector.manhattanLength() < qApp->styleHints()->startDragDistance()) {
1128 event->setAccepted(true);
1134 if (d->sendMouseEventToInputContext(event))
1137 bool mark = (event->modifiers() & Qt::ShiftModifier) && d->selectByMouse;
1138 int cursor = d->xToPos(event->localPos().x());
1139 d->control->moveCursor(cursor, mark);
1140 event->setAccepted(true);
1143 void QQuickTextInput::mouseMoveEvent(QMouseEvent *event)
1145 Q_D(QQuickTextInput);
1147 if (d->selectPressed) {
1148 if (qAbs(int(event->localPos().x() - d->pressPos.x())) > qApp->styleHints()->startDragDistance())
1149 setKeepMouseGrab(true);
1151 if (d->control->composeMode()) {
1153 int startPos = d->xToPos(d->pressPos.x());
1154 int currentPos = d->xToPos(event->localPos().x());
1155 if (startPos != currentPos)
1156 d->control->setSelection(startPos, currentPos - startPos);
1158 moveCursorSelection(d->xToPos(event->localPos().x()), d->mouseSelectionMode);
1160 event->setAccepted(true);
1162 QQuickImplicitSizeItem::mouseMoveEvent(event);
1166 void QQuickTextInput::mouseReleaseEvent(QMouseEvent *event)
1168 Q_D(QQuickTextInput);
1169 if (d->sendMouseEventToInputContext(event))
1171 if (d->selectPressed) {
1172 d->selectPressed = false;
1173 setKeepMouseGrab(false);
1175 d->control->processEvent(event);
1176 if (!event->isAccepted())
1177 QQuickImplicitSizeItem::mouseReleaseEvent(event);
1180 bool QQuickTextInputPrivate::sendMouseEventToInputContext(QMouseEvent *event)
1182 #if !defined QT_NO_IM
1183 if (control->composeMode()) {
1184 int tmp_cursor = xToPos(event->localPos().x());
1185 int mousePos = tmp_cursor - control->cursor();
1186 if (mousePos >= 0 && mousePos <= control->preeditAreaText().length()) {
1187 if (event->type() == QEvent::MouseButtonRelease) {
1188 qApp->inputPanel()->invokeAction(QInputPanel::Click, mousePos);
1201 void QQuickTextInput::mouseUngrabEvent()
1203 Q_D(QQuickTextInput);
1204 d->selectPressed = false;
1205 setKeepMouseGrab(false);
1208 bool QQuickTextInput::event(QEvent* ev)
1210 Q_D(QQuickTextInput);
1211 //Anything we don't deal with ourselves, pass to the control
1212 bool handled = false;
1213 switch (ev->type()) {
1214 case QEvent::KeyPress:
1215 case QEvent::KeyRelease://###Should the control be doing anything with release?
1216 case QEvent::InputMethod:
1217 case QEvent::MouseButtonPress:
1218 case QEvent::MouseMove:
1219 case QEvent::MouseButtonRelease:
1220 case QEvent::MouseButtonDblClick:
1223 handled = d->control->processEvent(ev);
1226 handled = QQuickImplicitSizeItem::event(ev);
1230 void QQuickTextInput::geometryChanged(const QRectF &newGeometry,
1231 const QRectF &oldGeometry)
1233 if (newGeometry.width() != oldGeometry.width()) {
1235 updateCursorRectangle();
1237 QQuickImplicitSizeItem::geometryChanged(newGeometry, oldGeometry);
1240 int QQuickTextInputPrivate::calculateTextWidth()
1242 return qRound(control->naturalTextWidth());
1245 void QQuickTextInputPrivate::updateHorizontalScroll()
1247 Q_Q(QQuickTextInput);
1248 const int preeditLength = control->preeditAreaText().length();
1249 const int width = q->width();
1250 int widthUsed = calculateTextWidth();
1252 if (!autoScroll || widthUsed <= width) {
1253 QQuickTextInput::HAlignment effectiveHAlign = q->effectiveHAlign();
1254 // text fits in br; use hscroll for alignment
1255 switch (effectiveHAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) {
1256 case Qt::AlignRight:
1257 hscroll = widthUsed - width;
1259 case Qt::AlignHCenter:
1260 hscroll = (widthUsed - width) / 2;
1268 int cix = qRound(control->cursorToX(control->cursor() + preeditLength));
1269 if (cix - hscroll >= width) {
1270 // text doesn't fit, cursor is to the right of br (scroll right)
1271 hscroll = cix - width;
1272 } else if (cix - hscroll < 0 && hscroll < widthUsed) {
1273 // text doesn't fit, cursor is to the left of br (scroll left)
1275 } else if (widthUsed - hscroll < width) {
1276 // text doesn't fit, text document is to the left of br; align
1278 hscroll = widthUsed - width;
1280 if (preeditLength > 0) {
1281 // check to ensure long pre-edit text doesn't push the cursor
1283 cix = qRound(control->cursorToX(
1284 control->cursor() + qMax(0, control->preeditCursor() - 1)));
1291 QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
1294 Q_D(QQuickTextInput);
1296 QQuickTextNode *node = static_cast<QQuickTextNode *>(oldNode);
1298 node = new QQuickTextNode(QQuickItemPrivate::get(this)->sceneGraphContext());
1301 if (!d->textLayoutDirty) {
1302 QSGSimpleRectNode *cursorNode = node->cursorNode();
1303 if (cursorNode != 0 && !isReadOnly()) {
1304 cursorNode->setRect(cursorRectangle());
1306 if (!d->cursorVisible
1307 || (!d->control->cursorBlinkStatus() && d->control->cursorBlinkPeriod() > 0)) {
1314 node->deleteContent();
1315 node->setMatrix(QMatrix4x4());
1317 QPoint offset = QPoint(0,0);
1318 QFontMetrics fm = QFontMetrics(d->font);
1319 QRect br(boundingRect().toRect());
1320 if (d->autoScroll) {
1321 // the y offset is there to keep the baseline constant in case we have script changes in the text.
1322 offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent());
1324 offset = QPoint(d->hscroll, 0);
1327 QTextLayout *textLayout = d->control->textLayout();
1328 if (!textLayout->text().isEmpty()) {
1329 node->addTextLayout(offset, textLayout, d->color,
1330 QQuickText::Normal, QColor(),
1331 d->selectionColor, d->selectedTextColor,
1332 d->control->selectionStart(),
1333 d->control->selectionEnd() - 1); // selectionEnd() returns first char after
1337 if (!isReadOnly() && d->cursorItem == 0) {
1338 node->setCursor(cursorRectangle(), d->color);
1339 if (!d->cursorVisible
1340 || (!d->control->cursorBlinkStatus() && d->control->cursorBlinkPeriod() > 0)) {
1347 d->textLayoutDirty = false;
1353 QVariant QQuickTextInput::inputMethodQuery(Qt::InputMethodQuery property) const
1355 Q_D(const QQuickTextInput);
1358 return QVariant((bool)(flags() & ItemAcceptsInputMethod));
1360 return QVariant((int)inputMethodHints());
1361 case Qt::ImCursorRectangle:
1362 return cursorRectangle();
1365 case Qt::ImCursorPosition:
1366 return QVariant(d->control->cursor());
1367 case Qt::ImSurroundingText:
1368 if (d->control->echoMode() == QQuickLineControl::PasswordEchoOnEdit
1369 && !d->control->passwordEchoEditing()) {
1370 return QVariant(displayText());
1372 return QVariant(d->control->realText());
1374 case Qt::ImCurrentSelection:
1375 return QVariant(selectedText());
1376 case Qt::ImMaximumTextLength:
1377 return QVariant(maxLength());
1378 case Qt::ImAnchorPosition:
1379 if (d->control->selectionStart() == d->control->selectionEnd())
1380 return QVariant(d->control->cursor());
1381 else if (d->control->selectionStart() == d->control->cursor())
1382 return QVariant(d->control->selectionEnd());
1384 return QVariant(d->control->selectionStart());
1391 \qmlmethod void QtQuick2::TextInput::deselect()
1393 Removes active text selection.
1395 void QQuickTextInput::deselect()
1397 Q_D(QQuickTextInput);
1398 d->control->deselect();
1402 \qmlmethod void QtQuick2::TextInput::selectAll()
1404 Causes all text to be selected.
1406 void QQuickTextInput::selectAll()
1408 Q_D(QQuickTextInput);
1409 d->control->setSelection(0, d->control->text().length());
1413 \qmlmethod void QtQuick2::TextInput::isRightToLeft(int start, int end)
1415 Returns true if the natural reading direction of the editor text
1416 found between positions \a start and \a end is right to left.
1418 bool QQuickTextInput::isRightToLeft(int start, int end)
1420 Q_D(QQuickTextInput);
1422 qmlInfo(this) << "isRightToLeft(start, end) called with the end property being smaller than the start.";
1425 return d->control->text().mid(start, end - start).isRightToLeft();
1429 #ifndef QT_NO_CLIPBOARD
1431 \qmlmethod QtQuick2::TextInput::cut()
1433 Moves the currently selected text to the system clipboard.
1435 void QQuickTextInput::cut()
1437 Q_D(QQuickTextInput);
1443 \qmlmethod QtQuick2::TextInput::copy()
1445 Copies the currently selected text to the system clipboard.
1447 void QQuickTextInput::copy()
1449 Q_D(QQuickTextInput);
1454 \qmlmethod QtQuick2::TextInput::paste()
1456 Replaces the currently selected text by the contents of the system clipboard.
1458 void QQuickTextInput::paste()
1460 Q_D(QQuickTextInput);
1461 if (!d->control->isReadOnly())
1462 d->control->paste();
1464 #endif // QT_NO_CLIPBOARD
1467 \qmlmethod void QtQuick2::TextInput::selectWord()
1469 Causes the word closest to the current cursor position to be selected.
1471 void QQuickTextInput::selectWord()
1473 Q_D(QQuickTextInput);
1474 d->control->selectWordAtPos(d->control->cursor());
1478 \qmlproperty bool QtQuick2::TextInput::smooth
1480 This property holds whether the text is smoothly scaled or transformed.
1482 Smooth filtering gives better visual quality, but is slower. If
1483 the item is displayed at its natural size, this property has no visual or
1486 \note Generally scaling artifacts are only visible if the item is stationary on
1487 the screen. A common pattern when animating an item is to disable smooth
1488 filtering at the beginning of the animation and reenable it at the conclusion.
1492 \qmlproperty string QtQuick2::TextInput::passwordCharacter
1494 This is the character displayed when echoMode is set to Password or
1495 PasswordEchoOnEdit. By default it is an asterisk.
1497 If this property is set to a string with more than one character,
1498 the first character is used. If the string is empty, the value
1499 is ignored and the property is not set.
1501 QString QQuickTextInput::passwordCharacter() const
1503 Q_D(const QQuickTextInput);
1504 return QString(d->control->passwordCharacter());
1507 void QQuickTextInput::setPasswordCharacter(const QString &str)
1509 Q_D(QQuickTextInput);
1510 if (str.length() < 1)
1512 d->control->setPasswordCharacter(str.constData()[0]);
1513 EchoMode echoMode_ = echoMode();
1514 if (echoMode_ == Password || echoMode_ == PasswordEchoOnEdit) {
1517 emit passwordCharacterChanged();
1521 \qmlproperty string QtQuick2::TextInput::displayText
1523 This is the text displayed in the TextInput.
1525 If \l echoMode is set to TextInput::Normal, this holds the
1526 same value as the TextInput::text property. Otherwise,
1527 this property holds the text visible to the user, while
1528 the \l text property holds the actual entered text.
1530 QString QQuickTextInput::displayText() const
1532 Q_D(const QQuickTextInput);
1533 return d->control->displayText();
1537 \qmlproperty bool QtQuick2::TextInput::selectByMouse
1541 If true, the user can use the mouse to select text in some
1542 platform-specific way. Note that for some platforms this may
1543 not be an appropriate interaction (eg. may conflict with how
1544 the text needs to behave inside a Flickable.
1546 bool QQuickTextInput::selectByMouse() const
1548 Q_D(const QQuickTextInput);
1549 return d->selectByMouse;
1552 void QQuickTextInput::setSelectByMouse(bool on)
1554 Q_D(QQuickTextInput);
1555 if (d->selectByMouse != on) {
1556 d->selectByMouse = on;
1557 emit selectByMouseChanged(on);
1562 \qmlproperty enum QtQuick2::TextInput::mouseSelectionMode
1564 Specifies how text should be selected using a mouse.
1567 \o TextInput.SelectCharacters - The selection is updated with individual characters. (Default)
1568 \o TextInput.SelectWords - The selection is updated with whole words.
1571 This property only applies when \l selectByMouse is true.
1574 QQuickTextInput::SelectionMode QQuickTextInput::mouseSelectionMode() const
1576 Q_D(const QQuickTextInput);
1577 return d->mouseSelectionMode;
1580 void QQuickTextInput::setMouseSelectionMode(SelectionMode mode)
1582 Q_D(QQuickTextInput);
1583 if (d->mouseSelectionMode != mode) {
1584 d->mouseSelectionMode = mode;
1585 emit mouseSelectionModeChanged(mode);
1590 \qmlproperty bool QtQuick2::TextInput::canPaste
1592 Returns true if the TextInput is writable and the content of the clipboard is
1593 suitable for pasting into the TextEdit.
1595 bool QQuickTextInput::canPaste() const
1597 Q_D(const QQuickTextInput);
1601 void QQuickTextInput::moveCursorSelection(int position)
1603 Q_D(QQuickTextInput);
1604 d->control->moveCursor(position, true);
1608 \qmlmethod void QtQuick2::TextInput::moveCursorSelection(int position, SelectionMode mode = TextInput.SelectCharacters)
1610 Moves the cursor to \a position and updates the selection according to the optional \a mode
1611 parameter. (To only move the cursor, set the \l cursorPosition property.)
1613 When this method is called it additionally sets either the
1614 selectionStart or the selectionEnd (whichever was at the previous cursor position)
1615 to the specified position. This allows you to easily extend and contract the selected
1618 The selection mode specifies whether the selection is updated on a per character or a per word
1619 basis. If not specified the selection mode will default to TextInput.SelectCharacters.
1622 \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
1623 the previous cursor position) to the specified position.
1624 \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all
1625 words between the specified position and the previous cursor position. Words partially in the
1629 For example, take this sequence of calls:
1633 moveCursorSelection(9, TextInput.SelectCharacters)
1634 moveCursorSelection(7, TextInput.SelectCharacters)
1637 This moves the cursor to position 5, extend the selection end from 5 to 9
1638 and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
1639 selected (the 6th and 7th characters).
1641 The same sequence with TextInput.SelectWords will extend the selection start to a word boundary
1642 before or on position 5 and extend the selection end to a word boundary on or past position 9.
1644 void QQuickTextInput::moveCursorSelection(int pos, SelectionMode mode)
1646 Q_D(QQuickTextInput);
1648 if (mode == SelectCharacters) {
1649 d->control->moveCursor(pos, true);
1650 } else if (pos != d->control->cursor()){
1651 const int cursor = d->control->cursor();
1653 if (!d->control->hasSelectedText())
1654 anchor = d->control->cursor();
1655 else if (d->control->selectionStart() == d->control->cursor())
1656 anchor = d->control->selectionEnd();
1658 anchor = d->control->selectionStart();
1660 if (anchor < pos || (anchor == pos && cursor < pos)) {
1661 const QString text = d->control->text();
1662 QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
1663 finder.setPosition(anchor);
1665 const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
1666 if (anchor < text.length() && (!(reasons & QTextBoundaryFinder::StartWord)
1667 || ((reasons & QTextBoundaryFinder::EndWord) && anchor > cursor))) {
1668 finder.toPreviousBoundary();
1670 anchor = finder.position() != -1 ? finder.position() : 0;
1672 finder.setPosition(pos);
1673 if (pos > 0 && !finder.boundaryReasons())
1674 finder.toNextBoundary();
1675 const int cursor = finder.position() != -1 ? finder.position() : text.length();
1677 d->control->setSelection(anchor, cursor - anchor);
1678 } else if (anchor > pos || (anchor == pos && cursor > pos)) {
1679 const QString text = d->control->text();
1680 QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
1681 finder.setPosition(anchor);
1683 const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
1684 if (anchor > 0 && (!(reasons & QTextBoundaryFinder::EndWord)
1685 || ((reasons & QTextBoundaryFinder::StartWord) && anchor < cursor))) {
1686 finder.toNextBoundary();
1689 anchor = finder.position() != -1 ? finder.position() : text.length();
1691 finder.setPosition(pos);
1692 if (pos < text.length() && !finder.boundaryReasons())
1693 finder.toPreviousBoundary();
1694 const int cursor = finder.position() != -1 ? finder.position() : 0;
1696 d->control->setSelection(anchor, cursor - anchor);
1702 \qmlmethod void QtQuick2::TextInput::openSoftwareInputPanel()
1704 Opens software input panels like virtual keyboards for typing, useful for
1705 customizing when you want the input keyboard to be shown and hidden in
1708 By default the opening of input panels follows the platform style. Input panels are
1709 always closed if no editor has active focus.
1711 You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1712 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1713 the behavior you want.
1715 Only relevant on platforms, which provide virtual keyboards.
1721 text: "Hello world!"
1722 activeFocusOnPress: false
1724 anchors.fill: parent
1726 if (!textInput.activeFocus) {
1727 textInput.forceActiveFocus()
1728 textInput.openSoftwareInputPanel();
1730 textInput.focus = false;
1733 onPressAndHold: textInput.closeSoftwareInputPanel();
1738 void QQuickTextInput::openSoftwareInputPanel()
1741 qGuiApp->inputPanel()->show();
1745 \qmlmethod void QtQuick2::TextInput::closeSoftwareInputPanel()
1747 Closes a software input panel like a virtual keyboard shown on the screen, useful
1748 for customizing when you want the input keyboard to be shown and hidden in
1751 By default the opening of input panels follows the platform style. Input panels are
1752 always closed if no editor has active focus.
1754 You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1755 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1756 the behavior you want.
1758 Only relevant on platforms, which provide virtual keyboards.
1764 text: "Hello world!"
1765 activeFocusOnPress: false
1767 anchors.fill: parent
1769 if (!textInput.activeFocus) {
1770 textInput.forceActiveFocus();
1771 textInput.openSoftwareInputPanel();
1773 textInput.focus = false;
1776 onPressAndHold: textInput.closeSoftwareInputPanel();
1781 void QQuickTextInput::closeSoftwareInputPanel()
1784 qGuiApp->inputPanel()->hide();
1787 void QQuickTextInput::focusInEvent(QFocusEvent *event)
1789 Q_D(const QQuickTextInput);
1790 if (d->focusOnPress && !isReadOnly())
1791 openSoftwareInputPanel();
1792 QQuickImplicitSizeItem::focusInEvent(event);
1795 void QQuickTextInput::itemChange(ItemChange change, const ItemChangeData &value)
1797 Q_D(QQuickTextInput);
1798 if (change == ItemActiveFocusHasChanged) {
1799 bool hasFocus = value.boolValue;
1800 d->focused = hasFocus;
1801 setCursorVisible(hasFocus); // ### refactor: && d->canvas && d->canvas->hasFocus()
1802 if (echoMode() == QQuickTextInput::PasswordEchoOnEdit && !hasFocus)
1803 d->control->updatePasswordEchoEditing(false);//QQuickLineControl sets it on key events, but doesn't deal with focus events
1805 d->control->deselect();
1807 QQuickItem::itemChange(change, value);
1811 \qmlproperty bool QtQuick2::TextInput::inputMethodComposing
1814 This property holds whether the TextInput has partial text input from an
1817 While it is composing an input method may rely on mouse or key events from
1818 the TextInput to edit or commit the partial text. This property can be
1819 used to determine when to disable events handlers that may interfere with
1820 the correct operation of an input method.
1822 bool QQuickTextInput::isInputMethodComposing() const
1824 Q_D(const QQuickTextInput);
1825 return d->control->preeditAreaText().length() > 0;
1828 void QQuickTextInputPrivate::init()
1830 Q_Q(QQuickTextInput);
1831 control->setParent(q);//Now mandatory due to accessibility changes
1832 control->setCursorWidth(1);
1833 control->setPasswordCharacter(QLatin1Char('*'));
1834 q->setSmooth(smooth);
1835 q->setAcceptedMouseButtons(Qt::LeftButton);
1836 q->setFlag(QQuickItem::ItemAcceptsInputMethod);
1837 q->setFlag(QQuickItem::ItemHasContents);
1838 q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
1839 q, SLOT(cursorPosChanged()));
1840 q->connect(control, SIGNAL(selectionChanged()),
1841 q, SLOT(selectionChanged()));
1842 q->connect(control, SIGNAL(textChanged(QString)),
1843 q, SLOT(q_textChanged()));
1844 q->connect(control, SIGNAL(accepted()),
1845 q, SIGNAL(accepted()));
1846 q->connect(control, SIGNAL(updateNeeded(QRect)),
1847 q, SLOT(updateRect(QRect)));
1848 #ifndef QT_NO_CLIPBOARD
1849 q->connect(q, SIGNAL(readOnlyChanged(bool)),
1850 q, SLOT(q_canPasteChanged()));
1851 q->connect(QGuiApplication::clipboard(), SIGNAL(dataChanged()),
1852 q, SLOT(q_canPasteChanged()));
1853 canPaste = !control->isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
1854 #endif // QT_NO_CLIPBOARD
1855 q->connect(control, SIGNAL(updateMicroFocus()),
1856 q, SLOT(updateCursorRectangle()));
1857 q->connect(control, SIGNAL(displayTextChanged(QString)),
1858 q, SLOT(updateRect()));
1860 imHints &= ~Qt::ImhMultiLine;
1861 oldValidity = control->hasAcceptableInput();
1862 lastSelectionStart = 0;
1863 lastSelectionEnd = 0;
1864 QPalette p = control->palette();
1865 selectedTextColor = p.color(QPalette::HighlightedText);
1866 selectionColor = p.color(QPalette::Highlight);
1867 determineHorizontalAlignment();
1869 if (!qmlDisableDistanceField()) {
1870 QTextOption option = control->textLayout()->textOption();
1871 option.setUseDesignMetrics(true);
1872 control->textLayout()->setTextOption(option);
1876 void QQuickTextInput::cursorPosChanged()
1878 Q_D(QQuickTextInput);
1879 updateCursorRectangle();
1880 emit cursorPositionChanged();
1881 // XXX todo - not in 4.8?
1883 d->control->resetCursorBlinkTimer();
1886 if (!d->control->hasSelectedText()) {
1887 if (d->lastSelectionStart != d->control->cursor()) {
1888 d->lastSelectionStart = d->control->cursor();
1889 emit selectionStartChanged();
1891 if (d->lastSelectionEnd != d->control->cursor()) {
1892 d->lastSelectionEnd = d->control->cursor();
1893 emit selectionEndChanged();
1898 void QQuickTextInput::updateCursorRectangle()
1900 Q_D(QQuickTextInput);
1901 d->determineHorizontalAlignment();
1902 d->updateHorizontalScroll();
1903 updateRect();//TODO: Only update rect between pos's
1905 emit cursorRectangleChanged();
1907 d->cursorItem->setX(d->control->cursorToX() - d->hscroll);
1910 void QQuickTextInput::selectionChanged()
1912 Q_D(QQuickTextInput);
1913 updateRect();//TODO: Only update rect in selection
1914 emit selectedTextChanged();
1916 if (d->lastSelectionStart != d->control->selectionStart()) {
1917 d->lastSelectionStart = d->control->selectionStart();
1918 if (d->lastSelectionStart == -1)
1919 d->lastSelectionStart = d->control->cursor();
1920 emit selectionStartChanged();
1922 if (d->lastSelectionEnd != d->control->selectionEnd()) {
1923 d->lastSelectionEnd = d->control->selectionEnd();
1924 if (d->lastSelectionEnd == -1)
1925 d->lastSelectionEnd = d->control->cursor();
1926 emit selectionEndChanged();
1930 void QQuickTextInput::q_textChanged()
1932 Q_D(QQuickTextInput);
1934 emit displayTextChanged();
1936 d->determineHorizontalAlignment();
1937 d->updateHorizontalScroll();
1939 if (hasAcceptableInput() != d->oldValidity) {
1940 d->oldValidity = hasAcceptableInput();
1941 emit acceptableInputChanged();
1945 void QQuickTextInputPrivate::showCursor()
1947 if (textNode != 0 && textNode->cursorNode() != 0)
1948 textNode->cursorNode()->setColor(color);
1951 void QQuickTextInputPrivate::hideCursor()
1953 if (textNode != 0 && textNode->cursorNode() != 0)
1954 textNode->cursorNode()->setColor(QColor(0, 0, 0, 0));
1957 void QQuickTextInput::updateRect(const QRect &r)
1959 Q_D(QQuickTextInput);
1960 if (!isComponentComplete())
1964 d->textLayoutDirty = true;
1970 QRectF QQuickTextInput::boundingRect() const
1972 Q_D(const QQuickTextInput);
1973 QRectF r = QQuickImplicitSizeItem::boundingRect();
1975 int cursorWidth = d->cursorItem ? d->cursorItem->width() : d->control->cursorWidth();
1977 // Could include font max left/right bearings to either side of rectangle.
1979 r.setRight(r.right() + cursorWidth);
1983 void QQuickTextInput::updateSize(bool needsRedraw)
1985 Q_D(QQuickTextInput);
1988 setImplicitSize(d->calculateTextWidth(), d->control->height()-1); // -1 to counter QQuickLineControl's +1 which is not consistent with Text.
1989 if (w==width() && h==height() && needsRedraw)
1993 void QQuickTextInput::q_canPasteChanged()
1995 Q_D(QQuickTextInput);
1996 bool old = d->canPaste;
1997 #ifndef QT_NO_CLIPBOARD
1998 d->canPaste = !d->control->isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
2000 if (d->canPaste != old)
2001 emit canPasteChanged();