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 #ifndef QT_NO_CLIPBOARD
1176 if (QGuiApplication::clipboard()->supportsSelection()) {
1177 if (event->button() == Qt::LeftButton) {
1178 d->control->copy(QClipboard::Selection);
1179 } else if (!isReadOnly() && event->button() == Qt::MidButton) {
1180 d->control->deselect();
1181 d->control->insert(QGuiApplication::clipboard()->text(QClipboard::Selection));
1185 if (!event->isAccepted())
1186 QQuickImplicitSizeItem::mouseReleaseEvent(event);
1189 bool QQuickTextInputPrivate::sendMouseEventToInputContext(QMouseEvent *event)
1191 #if !defined QT_NO_IM
1192 if (control->composeMode()) {
1193 int tmp_cursor = xToPos(event->localPos().x());
1194 int mousePos = tmp_cursor - control->cursor();
1195 if (mousePos >= 0 && mousePos <= control->preeditAreaText().length()) {
1196 if (event->type() == QEvent::MouseButtonRelease) {
1197 qApp->inputPanel()->invokeAction(QInputPanel::Click, mousePos);
1210 void QQuickTextInput::mouseUngrabEvent()
1212 Q_D(QQuickTextInput);
1213 d->selectPressed = false;
1214 setKeepMouseGrab(false);
1217 bool QQuickTextInput::event(QEvent* ev)
1219 #ifndef QT_NO_SHORTCUT
1220 if (ev->type() == QEvent::ShortcutOverride) {
1223 QKeyEvent* ke = static_cast<QKeyEvent*>(ev);
1224 if (ke == QKeySequence::Copy
1225 || ke == QKeySequence::Paste
1226 || ke == QKeySequence::Cut
1227 || ke == QKeySequence::Redo
1228 || ke == QKeySequence::Undo
1229 || ke == QKeySequence::MoveToNextWord
1230 || ke == QKeySequence::MoveToPreviousWord
1231 || ke == QKeySequence::MoveToStartOfDocument
1232 || ke == QKeySequence::MoveToEndOfDocument
1233 || ke == QKeySequence::SelectNextWord
1234 || ke == QKeySequence::SelectPreviousWord
1235 || ke == QKeySequence::SelectStartOfLine
1236 || ke == QKeySequence::SelectEndOfLine
1237 || ke == QKeySequence::SelectStartOfBlock
1238 || ke == QKeySequence::SelectEndOfBlock
1239 || ke == QKeySequence::SelectStartOfDocument
1240 || ke == QKeySequence::SelectAll
1241 || ke == QKeySequence::SelectEndOfDocument) {
1243 } else if (ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier
1244 || ke->modifiers() == Qt::KeypadModifier) {
1245 if (ke->key() < Qt::Key_Escape) {
1249 switch (ke->key()) {
1250 case Qt::Key_Delete:
1253 case Qt::Key_Backspace:
1265 return QQuickImplicitSizeItem::event(ev);
1268 void QQuickTextInput::geometryChanged(const QRectF &newGeometry,
1269 const QRectF &oldGeometry)
1271 if (newGeometry.width() != oldGeometry.width()) {
1273 updateCursorRectangle();
1275 QQuickImplicitSizeItem::geometryChanged(newGeometry, oldGeometry);
1278 int QQuickTextInputPrivate::calculateTextWidth()
1280 return qRound(control->naturalTextWidth());
1283 void QQuickTextInputPrivate::updateHorizontalScroll()
1285 Q_Q(QQuickTextInput);
1286 const int preeditLength = control->preeditAreaText().length();
1287 const int width = q->width();
1288 int widthUsed = calculateTextWidth();
1290 if (!autoScroll || widthUsed <= width) {
1291 QQuickTextInput::HAlignment effectiveHAlign = q->effectiveHAlign();
1292 // text fits in br; use hscroll for alignment
1293 switch (effectiveHAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) {
1294 case Qt::AlignRight:
1295 hscroll = widthUsed - width;
1297 case Qt::AlignHCenter:
1298 hscroll = (widthUsed - width) / 2;
1306 int cix = qRound(control->cursorToX(control->cursor() + preeditLength));
1307 if (cix - hscroll >= width) {
1308 // text doesn't fit, cursor is to the right of br (scroll right)
1309 hscroll = cix - width;
1310 } else if (cix - hscroll < 0 && hscroll < widthUsed) {
1311 // text doesn't fit, cursor is to the left of br (scroll left)
1313 } else if (widthUsed - hscroll < width) {
1314 // text doesn't fit, text document is to the left of br; align
1316 hscroll = widthUsed - width;
1318 if (preeditLength > 0) {
1319 // check to ensure long pre-edit text doesn't push the cursor
1321 cix = qRound(control->cursorToX(
1322 control->cursor() + qMax(0, control->preeditCursor() - 1)));
1329 QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
1332 Q_D(QQuickTextInput);
1334 QQuickTextNode *node = static_cast<QQuickTextNode *>(oldNode);
1336 node = new QQuickTextNode(QQuickItemPrivate::get(this)->sceneGraphContext());
1339 if (!d->textLayoutDirty) {
1340 QSGSimpleRectNode *cursorNode = node->cursorNode();
1341 if (cursorNode != 0 && !isReadOnly()) {
1342 cursorNode->setRect(cursorRectangle());
1344 if (!d->cursorVisible
1345 || (!d->control->cursorBlinkStatus() && d->control->cursorBlinkPeriod() > 0)) {
1352 node->deleteContent();
1353 node->setMatrix(QMatrix4x4());
1355 QPoint offset = QPoint(0,0);
1356 QFontMetrics fm = QFontMetrics(d->font);
1357 QRect br(boundingRect().toRect());
1358 if (d->autoScroll) {
1359 // the y offset is there to keep the baseline constant in case we have script changes in the text.
1360 offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent());
1362 offset = QPoint(d->hscroll, 0);
1365 QTextLayout *textLayout = d->control->textLayout();
1366 if (!textLayout->text().isEmpty()) {
1367 node->addTextLayout(offset, textLayout, d->color,
1368 QQuickText::Normal, QColor(),
1369 d->selectionColor, d->selectedTextColor,
1370 d->control->selectionStart(),
1371 d->control->selectionEnd() - 1); // selectionEnd() returns first char after
1375 if (!isReadOnly() && d->cursorItem == 0) {
1376 node->setCursor(cursorRectangle(), d->color);
1377 if (!d->cursorVisible
1378 || (!d->control->cursorBlinkStatus() && d->control->cursorBlinkPeriod() > 0)) {
1385 d->textLayoutDirty = false;
1391 QVariant QQuickTextInput::inputMethodQuery(Qt::InputMethodQuery property) const
1393 Q_D(const QQuickTextInput);
1396 return QVariant((bool)(flags() & ItemAcceptsInputMethod));
1398 return QVariant((int)inputMethodHints());
1399 case Qt::ImCursorRectangle:
1400 return cursorRectangle();
1403 case Qt::ImCursorPosition:
1404 return QVariant(d->control->cursor());
1405 case Qt::ImSurroundingText:
1406 if (d->control->echoMode() == QQuickLineControl::PasswordEchoOnEdit
1407 && !d->control->passwordEchoEditing()) {
1408 return QVariant(displayText());
1410 return QVariant(d->control->realText());
1412 case Qt::ImCurrentSelection:
1413 return QVariant(selectedText());
1414 case Qt::ImMaximumTextLength:
1415 return QVariant(maxLength());
1416 case Qt::ImAnchorPosition:
1417 if (d->control->selectionStart() == d->control->selectionEnd())
1418 return QVariant(d->control->cursor());
1419 else if (d->control->selectionStart() == d->control->cursor())
1420 return QVariant(d->control->selectionEnd());
1422 return QVariant(d->control->selectionStart());
1429 \qmlmethod void QtQuick2::TextInput::deselect()
1431 Removes active text selection.
1433 void QQuickTextInput::deselect()
1435 Q_D(QQuickTextInput);
1436 d->control->deselect();
1440 \qmlmethod void QtQuick2::TextInput::selectAll()
1442 Causes all text to be selected.
1444 void QQuickTextInput::selectAll()
1446 Q_D(QQuickTextInput);
1447 d->control->setSelection(0, d->control->text().length());
1451 \qmlmethod void QtQuick2::TextInput::isRightToLeft(int start, int end)
1453 Returns true if the natural reading direction of the editor text
1454 found between positions \a start and \a end is right to left.
1456 bool QQuickTextInput::isRightToLeft(int start, int end)
1458 Q_D(QQuickTextInput);
1460 qmlInfo(this) << "isRightToLeft(start, end) called with the end property being smaller than the start.";
1463 return d->control->text().mid(start, end - start).isRightToLeft();
1467 #ifndef QT_NO_CLIPBOARD
1469 \qmlmethod QtQuick2::TextInput::cut()
1471 Moves the currently selected text to the system clipboard.
1473 void QQuickTextInput::cut()
1475 Q_D(QQuickTextInput);
1481 \qmlmethod QtQuick2::TextInput::copy()
1483 Copies the currently selected text to the system clipboard.
1485 void QQuickTextInput::copy()
1487 Q_D(QQuickTextInput);
1492 \qmlmethod QtQuick2::TextInput::paste()
1494 Replaces the currently selected text by the contents of the system clipboard.
1496 void QQuickTextInput::paste()
1498 Q_D(QQuickTextInput);
1499 if (!d->control->isReadOnly())
1500 d->control->paste();
1502 #endif // QT_NO_CLIPBOARD
1505 \qmlmethod void QtQuick2::TextInput::selectWord()
1507 Causes the word closest to the current cursor position to be selected.
1509 void QQuickTextInput::selectWord()
1511 Q_D(QQuickTextInput);
1512 d->control->selectWordAtPos(d->control->cursor());
1516 \qmlproperty bool QtQuick2::TextInput::smooth
1518 This property holds whether the text is smoothly scaled or transformed.
1520 Smooth filtering gives better visual quality, but is slower. If
1521 the item is displayed at its natural size, this property has no visual or
1524 \note Generally scaling artifacts are only visible if the item is stationary on
1525 the screen. A common pattern when animating an item is to disable smooth
1526 filtering at the beginning of the animation and reenable it at the conclusion.
1530 \qmlproperty string QtQuick2::TextInput::passwordCharacter
1532 This is the character displayed when echoMode is set to Password or
1533 PasswordEchoOnEdit. By default it is an asterisk.
1535 If this property is set to a string with more than one character,
1536 the first character is used. If the string is empty, the value
1537 is ignored and the property is not set.
1539 QString QQuickTextInput::passwordCharacter() const
1541 Q_D(const QQuickTextInput);
1542 return QString(d->control->passwordCharacter());
1545 void QQuickTextInput::setPasswordCharacter(const QString &str)
1547 Q_D(QQuickTextInput);
1548 if (str.length() < 1)
1550 d->control->setPasswordCharacter(str.constData()[0]);
1551 EchoMode echoMode_ = echoMode();
1552 if (echoMode_ == Password || echoMode_ == PasswordEchoOnEdit) {
1555 emit passwordCharacterChanged();
1559 \qmlproperty string QtQuick2::TextInput::displayText
1561 This is the text displayed in the TextInput.
1563 If \l echoMode is set to TextInput::Normal, this holds the
1564 same value as the TextInput::text property. Otherwise,
1565 this property holds the text visible to the user, while
1566 the \l text property holds the actual entered text.
1568 QString QQuickTextInput::displayText() const
1570 Q_D(const QQuickTextInput);
1571 return d->control->displayText();
1575 \qmlproperty bool QtQuick2::TextInput::selectByMouse
1579 If true, the user can use the mouse to select text in some
1580 platform-specific way. Note that for some platforms this may
1581 not be an appropriate interaction (eg. may conflict with how
1582 the text needs to behave inside a Flickable.
1584 bool QQuickTextInput::selectByMouse() const
1586 Q_D(const QQuickTextInput);
1587 return d->selectByMouse;
1590 void QQuickTextInput::setSelectByMouse(bool on)
1592 Q_D(QQuickTextInput);
1593 if (d->selectByMouse != on) {
1594 d->selectByMouse = on;
1595 emit selectByMouseChanged(on);
1600 \qmlproperty enum QtQuick2::TextInput::mouseSelectionMode
1602 Specifies how text should be selected using a mouse.
1605 \o TextInput.SelectCharacters - The selection is updated with individual characters. (Default)
1606 \o TextInput.SelectWords - The selection is updated with whole words.
1609 This property only applies when \l selectByMouse is true.
1612 QQuickTextInput::SelectionMode QQuickTextInput::mouseSelectionMode() const
1614 Q_D(const QQuickTextInput);
1615 return d->mouseSelectionMode;
1618 void QQuickTextInput::setMouseSelectionMode(SelectionMode mode)
1620 Q_D(QQuickTextInput);
1621 if (d->mouseSelectionMode != mode) {
1622 d->mouseSelectionMode = mode;
1623 emit mouseSelectionModeChanged(mode);
1628 \qmlproperty bool QtQuick2::TextInput::canPaste
1630 Returns true if the TextInput is writable and the content of the clipboard is
1631 suitable for pasting into the TextEdit.
1633 bool QQuickTextInput::canPaste() const
1635 Q_D(const QQuickTextInput);
1639 void QQuickTextInput::moveCursorSelection(int position)
1641 Q_D(QQuickTextInput);
1642 d->control->moveCursor(position, true);
1646 \qmlmethod void QtQuick2::TextInput::moveCursorSelection(int position, SelectionMode mode = TextInput.SelectCharacters)
1648 Moves the cursor to \a position and updates the selection according to the optional \a mode
1649 parameter. (To only move the cursor, set the \l cursorPosition property.)
1651 When this method is called it additionally sets either the
1652 selectionStart or the selectionEnd (whichever was at the previous cursor position)
1653 to the specified position. This allows you to easily extend and contract the selected
1656 The selection mode specifies whether the selection is updated on a per character or a per word
1657 basis. If not specified the selection mode will default to TextInput.SelectCharacters.
1660 \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
1661 the previous cursor position) to the specified position.
1662 \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all
1663 words between the specified position and the previous cursor position. Words partially in the
1667 For example, take this sequence of calls:
1671 moveCursorSelection(9, TextInput.SelectCharacters)
1672 moveCursorSelection(7, TextInput.SelectCharacters)
1675 This moves the cursor to position 5, extend the selection end from 5 to 9
1676 and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
1677 selected (the 6th and 7th characters).
1679 The same sequence with TextInput.SelectWords will extend the selection start to a word boundary
1680 before or on position 5 and extend the selection end to a word boundary on or past position 9.
1682 void QQuickTextInput::moveCursorSelection(int pos, SelectionMode mode)
1684 Q_D(QQuickTextInput);
1686 if (mode == SelectCharacters) {
1687 d->control->moveCursor(pos, true);
1688 } else if (pos != d->control->cursor()){
1689 const int cursor = d->control->cursor();
1691 if (!d->control->hasSelectedText())
1692 anchor = d->control->cursor();
1693 else if (d->control->selectionStart() == d->control->cursor())
1694 anchor = d->control->selectionEnd();
1696 anchor = d->control->selectionStart();
1698 if (anchor < pos || (anchor == pos && cursor < pos)) {
1699 const QString text = d->control->text();
1700 QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
1701 finder.setPosition(anchor);
1703 const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
1704 if (anchor < text.length() && (!(reasons & QTextBoundaryFinder::StartWord)
1705 || ((reasons & QTextBoundaryFinder::EndWord) && anchor > cursor))) {
1706 finder.toPreviousBoundary();
1708 anchor = finder.position() != -1 ? finder.position() : 0;
1710 finder.setPosition(pos);
1711 if (pos > 0 && !finder.boundaryReasons())
1712 finder.toNextBoundary();
1713 const int cursor = finder.position() != -1 ? finder.position() : text.length();
1715 d->control->setSelection(anchor, cursor - anchor);
1716 } else if (anchor > pos || (anchor == pos && cursor > pos)) {
1717 const QString text = d->control->text();
1718 QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
1719 finder.setPosition(anchor);
1721 const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
1722 if (anchor > 0 && (!(reasons & QTextBoundaryFinder::EndWord)
1723 || ((reasons & QTextBoundaryFinder::StartWord) && anchor < cursor))) {
1724 finder.toNextBoundary();
1727 anchor = finder.position() != -1 ? finder.position() : text.length();
1729 finder.setPosition(pos);
1730 if (pos < text.length() && !finder.boundaryReasons())
1731 finder.toPreviousBoundary();
1732 const int cursor = finder.position() != -1 ? finder.position() : 0;
1734 d->control->setSelection(anchor, cursor - anchor);
1740 \qmlmethod void QtQuick2::TextInput::openSoftwareInputPanel()
1742 Opens software input panels like virtual keyboards for typing, useful for
1743 customizing when you want the input keyboard to be shown and hidden in
1746 By default the opening of input panels follows the platform style. Input panels are
1747 always closed if no editor has active focus.
1749 You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1750 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1751 the behavior you want.
1753 Only relevant on platforms, which provide virtual keyboards.
1759 text: "Hello world!"
1760 activeFocusOnPress: false
1762 anchors.fill: parent
1764 if (!textInput.activeFocus) {
1765 textInput.forceActiveFocus()
1766 textInput.openSoftwareInputPanel();
1768 textInput.focus = false;
1771 onPressAndHold: textInput.closeSoftwareInputPanel();
1776 void QQuickTextInput::openSoftwareInputPanel()
1779 qGuiApp->inputPanel()->show();
1783 \qmlmethod void QtQuick2::TextInput::closeSoftwareInputPanel()
1785 Closes a software input panel like a virtual keyboard shown on the screen, useful
1786 for customizing when you want the input keyboard to be shown and hidden in
1789 By default the opening of input panels follows the platform style. Input panels are
1790 always closed if no editor has active focus.
1792 You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1793 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1794 the behavior you want.
1796 Only relevant on platforms, which provide virtual keyboards.
1802 text: "Hello world!"
1803 activeFocusOnPress: false
1805 anchors.fill: parent
1807 if (!textInput.activeFocus) {
1808 textInput.forceActiveFocus();
1809 textInput.openSoftwareInputPanel();
1811 textInput.focus = false;
1814 onPressAndHold: textInput.closeSoftwareInputPanel();
1819 void QQuickTextInput::closeSoftwareInputPanel()
1822 qGuiApp->inputPanel()->hide();
1825 void QQuickTextInput::focusInEvent(QFocusEvent *event)
1827 Q_D(const QQuickTextInput);
1828 if (d->focusOnPress && !isReadOnly())
1829 openSoftwareInputPanel();
1830 QQuickImplicitSizeItem::focusInEvent(event);
1833 void QQuickTextInput::itemChange(ItemChange change, const ItemChangeData &value)
1835 Q_D(QQuickTextInput);
1836 if (change == ItemActiveFocusHasChanged) {
1837 bool hasFocus = value.boolValue;
1838 d->focused = hasFocus;
1839 setCursorVisible(hasFocus); // ### refactor: && d->canvas && d->canvas->hasFocus()
1840 if (echoMode() == QQuickTextInput::PasswordEchoOnEdit && !hasFocus)
1841 d->control->updatePasswordEchoEditing(false);//QQuickLineControl sets it on key events, but doesn't deal with focus events
1843 d->control->deselect();
1845 QQuickItem::itemChange(change, value);
1849 \qmlproperty bool QtQuick2::TextInput::inputMethodComposing
1852 This property holds whether the TextInput has partial text input from an
1855 While it is composing an input method may rely on mouse or key events from
1856 the TextInput to edit or commit the partial text. This property can be
1857 used to determine when to disable events handlers that may interfere with
1858 the correct operation of an input method.
1860 bool QQuickTextInput::isInputMethodComposing() const
1862 Q_D(const QQuickTextInput);
1863 return d->control->preeditAreaText().length() > 0;
1866 void QQuickTextInputPrivate::init()
1868 Q_Q(QQuickTextInput);
1869 control->setParent(q);//Now mandatory due to accessibility changes
1870 control->setCursorWidth(1);
1871 control->setPasswordCharacter(QLatin1Char('*'));
1872 q->setSmooth(smooth);
1873 q->setAcceptedMouseButtons(Qt::LeftButton);
1874 q->setFlag(QQuickItem::ItemAcceptsInputMethod);
1875 q->setFlag(QQuickItem::ItemHasContents);
1876 q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
1877 q, SLOT(cursorPosChanged()));
1878 q->connect(control, SIGNAL(selectionChanged()),
1879 q, SLOT(selectionChanged()));
1880 q->connect(control, SIGNAL(textChanged(QString)),
1881 q, SLOT(q_textChanged()));
1882 q->connect(control, SIGNAL(accepted()),
1883 q, SIGNAL(accepted()));
1884 q->connect(control, SIGNAL(updateNeeded(QRect)),
1885 q, SLOT(updateRect(QRect)));
1886 #ifndef QT_NO_CLIPBOARD
1887 q->connect(q, SIGNAL(readOnlyChanged(bool)),
1888 q, SLOT(q_canPasteChanged()));
1889 q->connect(QGuiApplication::clipboard(), SIGNAL(dataChanged()),
1890 q, SLOT(q_canPasteChanged()));
1891 canPaste = !control->isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
1892 #endif // QT_NO_CLIPBOARD
1893 q->connect(control, SIGNAL(updateMicroFocus()),
1894 q, SLOT(updateCursorRectangle()));
1895 q->connect(control, SIGNAL(displayTextChanged(QString)),
1896 q, SLOT(updateRect()));
1898 imHints &= ~Qt::ImhMultiLine;
1899 oldValidity = control->hasAcceptableInput();
1900 lastSelectionStart = 0;
1901 lastSelectionEnd = 0;
1902 QPalette p = control->palette();
1903 selectedTextColor = p.color(QPalette::HighlightedText);
1904 selectionColor = p.color(QPalette::Highlight);
1905 determineHorizontalAlignment();
1907 if (!qmlDisableDistanceField()) {
1908 QTextOption option = control->textLayout()->textOption();
1909 option.setUseDesignMetrics(true);
1910 control->textLayout()->setTextOption(option);
1914 void QQuickTextInput::cursorPosChanged()
1916 Q_D(QQuickTextInput);
1917 updateCursorRectangle();
1918 emit cursorPositionChanged();
1919 // XXX todo - not in 4.8?
1921 d->control->resetCursorBlinkTimer();
1924 if (!d->control->hasSelectedText()) {
1925 if (d->lastSelectionStart != d->control->cursor()) {
1926 d->lastSelectionStart = d->control->cursor();
1927 emit selectionStartChanged();
1929 if (d->lastSelectionEnd != d->control->cursor()) {
1930 d->lastSelectionEnd = d->control->cursor();
1931 emit selectionEndChanged();
1936 void QQuickTextInput::updateCursorRectangle()
1938 Q_D(QQuickTextInput);
1939 d->determineHorizontalAlignment();
1940 d->updateHorizontalScroll();
1941 updateRect();//TODO: Only update rect between pos's
1943 emit cursorRectangleChanged();
1945 d->cursorItem->setX(d->control->cursorToX() - d->hscroll);
1948 void QQuickTextInput::selectionChanged()
1950 Q_D(QQuickTextInput);
1951 updateRect();//TODO: Only update rect in selection
1952 emit selectedTextChanged();
1954 if (d->lastSelectionStart != d->control->selectionStart()) {
1955 d->lastSelectionStart = d->control->selectionStart();
1956 if (d->lastSelectionStart == -1)
1957 d->lastSelectionStart = d->control->cursor();
1958 emit selectionStartChanged();
1960 if (d->lastSelectionEnd != d->control->selectionEnd()) {
1961 d->lastSelectionEnd = d->control->selectionEnd();
1962 if (d->lastSelectionEnd == -1)
1963 d->lastSelectionEnd = d->control->cursor();
1964 emit selectionEndChanged();
1968 void QQuickTextInput::q_textChanged()
1970 Q_D(QQuickTextInput);
1972 emit displayTextChanged();
1974 d->determineHorizontalAlignment();
1975 d->updateHorizontalScroll();
1977 if (hasAcceptableInput() != d->oldValidity) {
1978 d->oldValidity = hasAcceptableInput();
1979 emit acceptableInputChanged();
1983 void QQuickTextInputPrivate::showCursor()
1985 if (textNode != 0 && textNode->cursorNode() != 0)
1986 textNode->cursorNode()->setColor(color);
1989 void QQuickTextInputPrivate::hideCursor()
1991 if (textNode != 0 && textNode->cursorNode() != 0)
1992 textNode->cursorNode()->setColor(QColor(0, 0, 0, 0));
1995 void QQuickTextInput::updateRect(const QRect &r)
1997 Q_D(QQuickTextInput);
1998 if (!isComponentComplete())
2002 d->textLayoutDirty = true;
2008 QRectF QQuickTextInput::boundingRect() const
2010 Q_D(const QQuickTextInput);
2011 QRectF r = QQuickImplicitSizeItem::boundingRect();
2013 int cursorWidth = d->cursorItem ? d->cursorItem->width() : d->control->cursorWidth();
2015 // Could include font max left/right bearings to either side of rectangle.
2017 r.setRight(r.right() + cursorWidth);
2021 void QQuickTextInput::updateSize(bool needsRedraw)
2023 Q_D(QQuickTextInput);
2026 setImplicitSize(d->calculateTextWidth(), d->control->height()-1); // -1 to counter QQuickLineControl's +1 which is not consistent with Text.
2027 if (w==width() && h==height() && needsRedraw)
2031 void QQuickTextInput::q_canPasteChanged()
2033 Q_D(QQuickTextInput);
2034 bool old = d->canPaste;
2035 #ifndef QT_NO_CLIPBOARD
2036 d->canPaste = !d->control->isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
2038 if (d->canPaste != old)
2039 emit canPasteChanged();