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);
263 emit colorChanged(c);
269 \qmlproperty color QtQuick2::TextInput::selectionColor
271 The text highlight color, used behind selections.
273 QColor QQuickTextInput::selectionColor() const
275 Q_D(const QQuickTextInput);
276 return d->selectionColor;
279 void QQuickTextInput::setSelectionColor(const QColor &color)
281 Q_D(QQuickTextInput);
282 if (d->selectionColor == color)
285 d->selectionColor = color;
286 QPalette p = d->control->palette();
287 p.setColor(QPalette::Highlight, d->selectionColor);
288 d->control->setPalette(p);
289 if (d->control->hasSelectedText())
291 emit selectionColorChanged(color);
294 \qmlproperty color QtQuick2::TextInput::selectedTextColor
296 The highlighted text color, used in selections.
298 QColor QQuickTextInput::selectedTextColor() const
300 Q_D(const QQuickTextInput);
301 return d->selectedTextColor;
304 void QQuickTextInput::setSelectedTextColor(const QColor &color)
306 Q_D(QQuickTextInput);
307 if (d->selectedTextColor == color)
310 d->selectedTextColor = color;
311 QPalette p = d->control->palette();
312 p.setColor(QPalette::HighlightedText, d->selectedTextColor);
313 d->control->setPalette(p);
314 if (d->control->hasSelectedText())
316 emit selectedTextColorChanged(color);
320 \qmlproperty enumeration QtQuick2::TextInput::horizontalAlignment
321 \qmlproperty enumeration QtQuick2::TextInput::effectiveHorizontalAlignment
323 Sets the horizontal alignment of the text within the TextInput item's
324 width and height. By default, the text alignment follows the natural alignment
325 of the text, for example text that is read from left to right will be aligned to
328 TextInput does not have vertical alignment, as the natural height is
329 exactly the height of the single line of text. If you set the height
330 manually to something larger, TextInput will always be top aligned
331 vertically. You can use anchors to align it however you want within
334 The valid values for \c horizontalAlignment are \c TextInput.AlignLeft, \c TextInput.AlignRight and
335 \c TextInput.AlignHCenter.
337 When using the attached property LayoutMirroring::enabled to mirror application
338 layouts, the horizontal alignment of text will also be mirrored. However, the property
339 \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
340 of TextInput, use the read-only property \c effectiveHorizontalAlignment.
342 QQuickTextInput::HAlignment QQuickTextInput::hAlign() const
344 Q_D(const QQuickTextInput);
348 void QQuickTextInput::setHAlign(HAlignment align)
350 Q_D(QQuickTextInput);
351 bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror;
352 d->hAlignImplicit = false;
353 if (d->setHAlign(align, forceAlign) && isComponentComplete()) {
354 updateCursorRectangle();
358 void QQuickTextInput::resetHAlign()
360 Q_D(QQuickTextInput);
361 d->hAlignImplicit = true;
362 if (d->determineHorizontalAlignment() && isComponentComplete()) {
363 updateCursorRectangle();
367 QQuickTextInput::HAlignment QQuickTextInput::effectiveHAlign() const
369 Q_D(const QQuickTextInput);
370 QQuickTextInput::HAlignment effectiveAlignment = d->hAlign;
371 if (!d->hAlignImplicit && d->effectiveLayoutMirror) {
373 case QQuickTextInput::AlignLeft:
374 effectiveAlignment = QQuickTextInput::AlignRight;
376 case QQuickTextInput::AlignRight:
377 effectiveAlignment = QQuickTextInput::AlignLeft;
383 return effectiveAlignment;
386 bool QQuickTextInputPrivate::setHAlign(QQuickTextInput::HAlignment alignment, bool forceAlign)
388 Q_Q(QQuickTextInput);
389 if ((hAlign != alignment || forceAlign) && alignment <= QQuickTextInput::AlignHCenter) { // justify not supported
390 QQuickTextInput::HAlignment oldEffectiveHAlign = q->effectiveHAlign();
392 emit q->horizontalAlignmentChanged(alignment);
393 if (oldEffectiveHAlign != q->effectiveHAlign())
394 emit q->effectiveHorizontalAlignmentChanged();
400 bool QQuickTextInputPrivate::determineHorizontalAlignment()
402 if (hAlignImplicit) {
403 // if no explicit alignment has been set, follow the natural layout direction of the text
404 QString text = control->text();
406 text = control->preeditAreaText();
407 bool isRightToLeft = text.isEmpty() ? QGuiApplication::keyboardInputDirection() == Qt::RightToLeft : text.isRightToLeft();
408 return setHAlign(isRightToLeft ? QQuickTextInput::AlignRight : QQuickTextInput::AlignLeft);
413 void QQuickTextInputPrivate::mirrorChange()
415 Q_Q(QQuickTextInput);
416 if (q->isComponentComplete()) {
417 if (!hAlignImplicit && (hAlign == QQuickTextInput::AlignRight || hAlign == QQuickTextInput::AlignLeft)) {
418 q->updateCursorRectangle();
419 emit q->effectiveHorizontalAlignmentChanged();
425 \qmlproperty bool QtQuick2::TextInput::readOnly
427 Sets whether user input can modify the contents of the TextInput.
429 If readOnly is set to true, then user input will not affect the text
430 property. Any bindings or attempts to set the text property will still
433 bool QQuickTextInput::isReadOnly() const
435 Q_D(const QQuickTextInput);
436 return d->control->isReadOnly();
439 void QQuickTextInput::setReadOnly(bool ro)
441 Q_D(QQuickTextInput);
442 if (d->control->isReadOnly() == ro)
445 setFlag(QQuickItem::ItemAcceptsInputMethod, !ro);
446 d->control->setReadOnly(ro);
448 d->control->setCursorPosition(d->control->end());
450 emit readOnlyChanged(ro);
454 \qmlproperty int QtQuick2::TextInput::maximumLength
455 The maximum permitted length of the text in the TextInput.
457 If the text is too long, it is truncated at the limit.
459 By default, this property contains a value of 32767.
461 int QQuickTextInput::maxLength() const
463 Q_D(const QQuickTextInput);
464 return d->control->maxLength();
467 void QQuickTextInput::setMaxLength(int ml)
469 Q_D(QQuickTextInput);
470 if (d->control->maxLength() == ml)
473 d->control->setMaxLength(ml);
475 emit maximumLengthChanged(ml);
479 \qmlproperty bool QtQuick2::TextInput::cursorVisible
480 Set to true when the TextInput shows a cursor.
482 This property is set and unset when the TextInput gets active focus, so that other
483 properties can be bound to whether the cursor is currently showing. As it
484 gets set and unset automatically, when you set the value yourself you must
485 keep in mind that your value may be overwritten.
487 It can be set directly in script, for example if a KeyProxy might
488 forward keys to it and you desire it to look active when this happens
489 (but without actually giving it active focus).
491 It should not be set directly on the element, like in the below QML,
492 as the specified value will be overridden an lost on focus changes.
501 In the above snippet the cursor will still become visible when the
502 TextInput gains active focus.
504 bool QQuickTextInput::isCursorVisible() const
506 Q_D(const QQuickTextInput);
507 return d->cursorVisible;
510 void QQuickTextInput::setCursorVisible(bool on)
512 Q_D(QQuickTextInput);
513 if (d->cursorVisible == on)
515 d->cursorVisible = on;
516 d->control->setCursorBlinkPeriod(on ? qApp->styleHints()->cursorFlashTime() : 0);
517 QRect r = d->control->cursorRect();
518 if (d->control->inputMask().isEmpty())
522 emit cursorVisibleChanged(d->cursorVisible);
526 \qmlproperty int QtQuick2::TextInput::cursorPosition
527 The position of the cursor in the TextInput.
529 int QQuickTextInput::cursorPosition() const
531 Q_D(const QQuickTextInput);
532 return d->control->cursor();
534 void QQuickTextInput::setCursorPosition(int cp)
536 Q_D(QQuickTextInput);
537 if (cp < 0 || cp > d->control->text().length())
539 d->control->moveCursor(cp);
543 Returns a Rect which encompasses the cursor, but which may be larger than is
544 required. Ignores custom cursor delegates.
546 QRect QQuickTextInput::cursorRectangle() const
548 Q_D(const QQuickTextInput);
549 QRect r = d->control->cursorRect();
550 // Scroll and make consistent with TextEdit
551 // QLineControl inexplicably adds 1 to the height and horizontal padding
552 // for unicode direction markers.
553 r.adjust(5 - d->hscroll, 0, -4 - d->hscroll, -1);
557 \qmlproperty int QtQuick2::TextInput::selectionStart
559 The cursor position before the first character in the current selection.
561 This property is read-only. To change the selection, use select(start,end),
562 selectAll(), or selectWord().
564 \sa selectionEnd, cursorPosition, selectedText
566 int QQuickTextInput::selectionStart() const
568 Q_D(const QQuickTextInput);
569 return d->lastSelectionStart;
572 \qmlproperty int QtQuick2::TextInput::selectionEnd
574 The cursor position after the last character in the current selection.
576 This property is read-only. To change the selection, use select(start,end),
577 selectAll(), or selectWord().
579 \sa selectionStart, cursorPosition, selectedText
581 int QQuickTextInput::selectionEnd() const
583 Q_D(const QQuickTextInput);
584 return d->lastSelectionEnd;
587 \qmlmethod void QtQuick2::TextInput::select(int start, int end)
589 Causes the text from \a start to \a end to be selected.
591 If either start or end is out of range, the selection is not changed.
593 After calling this, selectionStart will become the lesser
594 and selectionEnd will become the greater (regardless of the order passed
597 \sa selectionStart, selectionEnd
599 void QQuickTextInput::select(int start, int end)
601 Q_D(QQuickTextInput);
602 if (start < 0 || end < 0 || start > d->control->text().length() || end > d->control->text().length())
604 d->control->setSelection(start, end-start);
608 \qmlproperty string QtQuick2::TextInput::selectedText
610 This read-only property provides the text currently selected in the
613 It is equivalent to the following snippet, but is faster and easier
617 myTextInput.text.toString().substring(myTextInput.selectionStart,
618 myTextInput.selectionEnd);
621 QString QQuickTextInput::selectedText() const
623 Q_D(const QQuickTextInput);
624 return d->control->selectedText();
628 \qmlproperty bool QtQuick2::TextInput::activeFocusOnPress
630 Whether the TextInput should gain active focus on a mouse press. By default this is
633 bool QQuickTextInput::focusOnPress() const
635 Q_D(const QQuickTextInput);
636 return d->focusOnPress;
639 void QQuickTextInput::setFocusOnPress(bool b)
641 Q_D(QQuickTextInput);
642 if (d->focusOnPress == b)
647 emit activeFocusOnPressChanged(d->focusOnPress);
650 \qmlproperty bool QtQuick2::TextInput::autoScroll
652 Whether the TextInput should scroll when the text is longer than the width. By default this is
655 bool QQuickTextInput::autoScroll() const
657 Q_D(const QQuickTextInput);
658 return d->autoScroll;
661 void QQuickTextInput::setAutoScroll(bool b)
663 Q_D(QQuickTextInput);
664 if (d->autoScroll == b)
668 //We need to repaint so that the scrolling is taking into account.
670 updateCursorRectangle();
671 emit autoScrollChanged(d->autoScroll);
674 #ifndef QT_NO_VALIDATOR
677 \qmlclass IntValidator QIntValidator
678 \inqmlmodule QtQuick 2
679 \ingroup qml-basic-visual-elements
681 This element provides a validator for integer values.
683 IntValidator uses the \l {QLocale::setDefault()}{default locale} to interpret the number and
684 will accept locale specific digits, group separators, and positive and negative signs. In
685 addition, IntValidator is always guaranteed to accept a number formatted according to the "C"
689 \qmlproperty int QtQuick2::IntValidator::top
691 This property holds the validator's highest acceptable value.
692 By default, this property's value is derived from the highest signed integer available (typically 2147483647).
695 \qmlproperty int QtQuick2::IntValidator::bottom
697 This property holds the validator's lowest acceptable value.
698 By default, this property's value is derived from the lowest signed integer available (typically -2147483647).
702 \qmlclass DoubleValidator QDoubleValidator
703 \inqmlmodule QtQuick 2
704 \ingroup qml-basic-visual-elements
706 This element provides a validator for non-integer numbers.
710 \qmlproperty real QtQuick2::DoubleValidator::top
712 This property holds the validator's maximum acceptable value.
713 By default, this property contains a value of infinity.
716 \qmlproperty real QtQuick2::DoubleValidator::bottom
718 This property holds the validator's minimum acceptable value.
719 By default, this property contains a value of -infinity.
722 \qmlproperty int QtQuick2::DoubleValidator::decimals
724 This property holds the validator's maximum number of digits after the decimal point.
725 By default, this property contains a value of 1000.
728 \qmlproperty enumeration QtQuick2::DoubleValidator::notation
729 This property holds the notation of how a string can describe a number.
731 The possible values for this property are:
734 \o DoubleValidator.StandardNotation
735 \o DoubleValidator.ScientificNotation (default)
738 If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part (e.g. 1.5E-2).
742 \qmlclass RegExpValidator QRegExpValidator
743 \inqmlmodule QtQuick 2
744 \ingroup qml-basic-visual-elements
746 This element provides a validator, which counts as valid any string which
747 matches a specified regular expression.
750 \qmlproperty regExp QtQuick2::RegExpValidator::regExp
752 This property holds the regular expression used for validation.
754 Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular expression
757 By default, this property contains a regular expression with the pattern .* that matches any string.
761 \qmlproperty Validator QtQuick2::TextInput::validator
763 Allows you to set a validator on the TextInput. When a validator is set
764 the TextInput will only accept input which leaves the text property in
765 an acceptable or intermediate state. The accepted signal will only be sent
766 if the text is in an acceptable state when enter is pressed.
768 Currently supported validators are IntValidator, DoubleValidator and
769 RegExpValidator. An example of using validators is shown below, which allows
770 input of integers between 11 and 31 into the text input:
775 validator: IntValidator{bottom: 11; top: 31;}
780 \sa acceptableInput, inputMask
783 QValidator* QQuickTextInput::validator() const
785 Q_D(const QQuickTextInput);
786 //###const cast isn't good, but needed for property system?
787 return const_cast<QValidator*>(d->control->validator());
790 void QQuickTextInput::setValidator(QValidator* v)
792 Q_D(QQuickTextInput);
793 if (d->control->validator() == v)
796 d->control->setValidator(v);
797 if (!d->control->hasAcceptableInput()) {
798 d->oldValidity = false;
799 emit acceptableInputChanged();
802 emit validatorChanged();
804 #endif // QT_NO_VALIDATOR
807 \qmlproperty string QtQuick2::TextInput::inputMask
809 Allows you to set an input mask on the TextInput, restricting the allowable
810 text inputs. See QLineEdit::inputMask for further details, as the exact
811 same mask strings are used by TextInput.
813 \sa acceptableInput, validator
815 QString QQuickTextInput::inputMask() const
817 Q_D(const QQuickTextInput);
818 return d->control->inputMask();
821 void QQuickTextInput::setInputMask(const QString &im)
823 Q_D(QQuickTextInput);
824 if (d->control->inputMask() == im)
827 d->control->setInputMask(im);
828 emit inputMaskChanged(d->control->inputMask());
832 \qmlproperty bool QtQuick2::TextInput::acceptableInput
834 This property is always true unless a validator or input mask has been set.
835 If a validator or input mask has been set, this property will only be true
836 if the current text is acceptable to the validator or input mask as a final
837 string (not as an intermediate string).
839 bool QQuickTextInput::hasAcceptableInput() const
841 Q_D(const QQuickTextInput);
842 return d->control->hasAcceptableInput();
846 \qmlsignal QtQuick2::TextInput::onAccepted()
848 This handler is called when the Return or Enter key is pressed.
849 Note that if there is a \l validator or \l inputMask set on the text
850 input, the handler will only be emitted if the input is in an acceptable
854 void QQuickTextInputPrivate::updateInputMethodHints()
856 Q_Q(QQuickTextInput);
857 Qt::InputMethodHints hints = inputMethodHints;
858 uint echo = control->echoMode();
859 if (echo == QQuickTextInput::Password || echo == QQuickTextInput::NoEcho)
860 hints |= Qt::ImhHiddenText;
861 else if (echo == QQuickTextInput::PasswordEchoOnEdit)
862 hints &= ~Qt::ImhHiddenText;
863 if (echo != QQuickTextInput::Normal)
864 hints |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
865 q->setInputMethodHints(hints);
868 \qmlproperty enumeration QtQuick2::TextInput::echoMode
870 Specifies how the text should be displayed in the TextInput.
872 \o TextInput.Normal - Displays the text as it is. (Default)
873 \o TextInput.Password - Displays asterisks instead of characters.
874 \o TextInput.NoEcho - Displays nothing.
875 \o TextInput.PasswordEchoOnEdit - Displays characters as they are entered
876 while editing, otherwise displays asterisks.
879 QQuickTextInput::EchoMode QQuickTextInput::echoMode() const
881 Q_D(const QQuickTextInput);
882 return (QQuickTextInput::EchoMode)d->control->echoMode();
885 void QQuickTextInput::setEchoMode(QQuickTextInput::EchoMode echo)
887 Q_D(QQuickTextInput);
888 if (echoMode() == echo)
890 d->control->setEchoMode((QLineControl::EchoMode)echo);
891 d->updateInputMethodHints();
893 emit echoModeChanged(echoMode());
896 Qt::InputMethodHints QQuickTextInput::imHints() const
898 Q_D(const QQuickTextInput);
899 return d->inputMethodHints;
902 void QQuickTextInput::setIMHints(Qt::InputMethodHints hints)
904 Q_D(QQuickTextInput);
905 if (d->inputMethodHints == hints)
907 d->inputMethodHints = hints;
908 d->updateInputMethodHints();
912 \qmlproperty Component QtQuick2::TextInput::cursorDelegate
913 The delegate for the cursor in the TextInput.
915 If you set a cursorDelegate for a TextInput, this delegate will be used for
916 drawing the cursor instead of the standard cursor. An instance of the
917 delegate will be created and managed by the TextInput when a cursor is
918 needed, and the x property of delegate instance will be set so as
919 to be one pixel before the top left of the current character.
921 Note that the root item of the delegate component must be a QDeclarativeItem or
922 QDeclarativeItem derived item.
924 QDeclarativeComponent* QQuickTextInput::cursorDelegate() const
926 Q_D(const QQuickTextInput);
927 return d->cursorComponent;
930 void QQuickTextInput::setCursorDelegate(QDeclarativeComponent* c)
932 Q_D(QQuickTextInput);
933 if (d->cursorComponent == c)
936 d->cursorComponent = c;
938 //note that the components are owned by something else
939 delete d->cursorItem;
941 d->startCreatingCursor();
944 emit cursorDelegateChanged();
947 void QQuickTextInputPrivate::startCreatingCursor()
949 Q_Q(QQuickTextInput);
950 if (cursorComponent->isReady()) {
952 } else if (cursorComponent->isLoading()) {
953 q->connect(cursorComponent, SIGNAL(statusChanged(int)),
954 q, SLOT(createCursor()));
956 qmlInfo(q, cursorComponent->errors()) << QQuickTextInput::tr("Could not load cursor delegate");
960 void QQuickTextInput::createCursor()
962 Q_D(QQuickTextInput);
963 if (d->cursorComponent->isError()) {
964 qmlInfo(this, d->cursorComponent->errors()) << tr("Could not load cursor delegate");
968 if (!d->cursorComponent->isReady())
972 delete d->cursorItem;
973 QDeclarativeContext *creationContext = d->cursorComponent->creationContext();
974 QObject *object = d->cursorComponent->create(creationContext ? creationContext : qmlContext(this));
975 d->cursorItem = qobject_cast<QQuickItem*>(object);
976 if (!d->cursorItem) {
978 qmlInfo(this, d->cursorComponent->errors()) << tr("Could not instantiate cursor delegate");
982 QDeclarative_setParent_noEvent(d->cursorItem, this);
983 d->cursorItem->setParentItem(this);
984 d->cursorItem->setX(d->control->cursorToX());
985 d->cursorItem->setHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
989 \qmlmethod rect QtQuick2::TextInput::positionToRectangle(int pos)
991 This function takes a character position and returns the rectangle that the
992 cursor would occupy, if it was placed at that character position.
994 This is similar to setting the cursorPosition, and then querying the cursor
995 rectangle, but the cursorPosition is not changed.
997 QRectF QQuickTextInput::positionToRectangle(int pos) const
999 Q_D(const QQuickTextInput);
1000 if (pos > d->control->cursorPosition())
1001 pos += d->control->preeditAreaText().length();
1002 return QRectF(d->control->cursorToX(pos)-d->hscroll,
1004 d->control->cursorWidth(),
1005 cursorRectangle().height());
1009 \qmlmethod int QtQuick2::TextInput::positionAt(int x, CursorPosition position = CursorBetweenCharacters)
1011 This function returns the character position at
1012 x pixels from the left of the textInput. Position 0 is before the
1013 first character, position 1 is after the first character but before the second,
1014 and so on until position text.length, which is after all characters.
1016 This means that for all x values before the first character this function returns 0,
1017 and for all x values after the last character this function returns text.length.
1019 The cursor position type specifies how the cursor position should be resolved.
1022 \o TextInput.CursorBetweenCharacters - Returns the position between characters that is nearest x.
1023 \o TextInput.CursorOnCharacter - Returns the position before the character that is nearest x.
1026 int QQuickTextInput::positionAt(int x) const
1028 return positionAt(x, CursorBetweenCharacters);
1031 int QQuickTextInput::positionAt(int x, CursorPosition position) const
1033 Q_D(const QQuickTextInput);
1034 int pos = d->control->xToPos(x + d->hscroll, QTextLine::CursorPosition(position));
1035 const int cursor = d->control->cursor();
1037 const int preeditLength = d->control->preeditAreaText().length();
1038 pos = pos > cursor + preeditLength
1039 ? pos - preeditLength
1045 void QQuickTextInput::keyPressEvent(QKeyEvent* ev)
1047 Q_D(QQuickTextInput);
1048 // Don't allow MacOSX up/down support, and we don't allow a completer.
1049 bool ignore = (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) && ev->modifiers() == Qt::NoModifier;
1050 if (!ignore && (d->lastSelectionStart == d->lastSelectionEnd) && (ev->key() == Qt::Key_Right || ev->key() == Qt::Key_Left)) {
1051 // Ignore when moving off the end unless there is a selection,
1052 // because then moving will do something (deselect).
1053 int cursorPosition = d->control->cursor();
1054 if (cursorPosition == 0)
1055 ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Left : Qt::Key_Right);
1056 if (cursorPosition == d->control->text().length())
1057 ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Right : Qt::Key_Left);
1062 d->control->processKeyEvent(ev);
1064 if (!ev->isAccepted())
1065 QQuickImplicitSizeItem::keyPressEvent(ev);
1068 void QQuickTextInput::inputMethodEvent(QInputMethodEvent *ev)
1070 Q_D(QQuickTextInput);
1071 const bool wasComposing = d->control->preeditAreaText().length() > 0;
1072 if (d->control->isReadOnly()) {
1075 d->control->processInputMethodEvent(ev);
1077 if (!ev->isAccepted())
1078 QQuickImplicitSizeItem::inputMethodEvent(ev);
1080 if (wasComposing != (d->control->preeditAreaText().length() > 0))
1081 emit inputMethodComposingChanged();
1084 void QQuickTextInput::mouseDoubleClickEvent(QMouseEvent *event)
1086 Q_D(QQuickTextInput);
1088 if (d->selectByMouse && event->button() == Qt::LeftButton) {
1089 d->control->commitPreedit();
1090 int cursor = d->xToPos(event->localPos().x());
1091 d->control->selectWordAtPos(cursor);
1092 event->setAccepted(true);
1093 if (!d->hasPendingTripleClick()) {
1094 d->tripleClickStartPoint = event->localPos().toPoint();
1095 d->tripleClickTimer.start();
1098 if (d->sendMouseEventToInputContext(event))
1100 QQuickImplicitSizeItem::mouseDoubleClickEvent(event);
1104 void QQuickTextInput::mousePressEvent(QMouseEvent *event)
1106 Q_D(QQuickTextInput);
1108 d->pressPos = event->localPos();
1110 if (d->focusOnPress) {
1111 bool hadActiveFocus = hasActiveFocus();
1113 // re-open input panel on press if already focused
1114 if (hasActiveFocus() && hadActiveFocus && !isReadOnly())
1115 openSoftwareInputPanel();
1117 if (d->selectByMouse) {
1118 setKeepMouseGrab(false);
1119 d->selectPressed = true;
1120 QPoint distanceVector = d->pressPos.toPoint() - d->tripleClickStartPoint;
1121 if (d->hasPendingTripleClick()
1122 && distanceVector.manhattanLength() < qApp->styleHints()->startDragDistance()) {
1123 event->setAccepted(true);
1129 if (d->sendMouseEventToInputContext(event))
1132 bool mark = (event->modifiers() & Qt::ShiftModifier) && d->selectByMouse;
1133 int cursor = d->xToPos(event->localPos().x());
1134 d->control->moveCursor(cursor, mark);
1135 event->setAccepted(true);
1138 void QQuickTextInput::mouseMoveEvent(QMouseEvent *event)
1140 Q_D(QQuickTextInput);
1142 if (d->selectPressed) {
1143 if (qAbs(int(event->localPos().x() - d->pressPos.x())) > qApp->styleHints()->startDragDistance())
1144 setKeepMouseGrab(true);
1146 if (d->control->composeMode()) {
1148 int startPos = d->xToPos(d->pressPos.x());
1149 int currentPos = d->xToPos(event->localPos().x());
1150 if (startPos != currentPos)
1151 d->control->setSelection(startPos, currentPos - startPos);
1153 moveCursorSelection(d->xToPos(event->localPos().x()), d->mouseSelectionMode);
1155 event->setAccepted(true);
1157 QQuickImplicitSizeItem::mouseMoveEvent(event);
1161 void QQuickTextInput::mouseReleaseEvent(QMouseEvent *event)
1163 Q_D(QQuickTextInput);
1164 if (d->sendMouseEventToInputContext(event))
1166 if (d->selectPressed) {
1167 d->selectPressed = false;
1168 setKeepMouseGrab(false);
1170 d->control->processEvent(event);
1171 if (!event->isAccepted())
1172 QQuickImplicitSizeItem::mouseReleaseEvent(event);
1175 bool QQuickTextInputPrivate::sendMouseEventToInputContext(QMouseEvent *event)
1177 #if !defined QT_NO_IM
1178 if (control->composeMode()) {
1179 int tmp_cursor = xToPos(event->localPos().x());
1180 int mousePos = tmp_cursor - control->cursor();
1181 if (mousePos >= 0 && mousePos <= control->preeditAreaText().length()) {
1182 if (event->type() == QEvent::MouseButtonRelease) {
1183 qApp->inputPanel()->invokeAction(QInputPanel::Click, mousePos);
1196 void QQuickTextInput::mouseUngrabEvent()
1198 Q_D(QQuickTextInput);
1199 d->selectPressed = false;
1200 setKeepMouseGrab(false);
1203 bool QQuickTextInput::event(QEvent* ev)
1205 Q_D(QQuickTextInput);
1206 //Anything we don't deal with ourselves, pass to the control
1207 bool handled = false;
1208 switch (ev->type()) {
1209 case QEvent::KeyPress:
1210 case QEvent::KeyRelease://###Should the control be doing anything with release?
1211 case QEvent::InputMethod:
1212 case QEvent::MouseButtonPress:
1213 case QEvent::MouseMove:
1214 case QEvent::MouseButtonRelease:
1215 case QEvent::MouseButtonDblClick:
1218 handled = d->control->processEvent(ev);
1221 handled = QQuickImplicitSizeItem::event(ev);
1225 void QQuickTextInput::geometryChanged(const QRectF &newGeometry,
1226 const QRectF &oldGeometry)
1228 if (newGeometry.width() != oldGeometry.width()) {
1230 updateCursorRectangle();
1232 QQuickImplicitSizeItem::geometryChanged(newGeometry, oldGeometry);
1235 int QQuickTextInputPrivate::calculateTextWidth()
1237 return qRound(control->naturalTextWidth());
1240 void QQuickTextInputPrivate::updateHorizontalScroll()
1242 Q_Q(QQuickTextInput);
1243 const int preeditLength = control->preeditAreaText().length();
1244 const int width = q->width();
1245 int widthUsed = calculateTextWidth();
1247 if (!autoScroll || widthUsed <= width) {
1248 QQuickTextInput::HAlignment effectiveHAlign = q->effectiveHAlign();
1249 // text fits in br; use hscroll for alignment
1250 switch (effectiveHAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) {
1251 case Qt::AlignRight:
1252 hscroll = widthUsed - width;
1254 case Qt::AlignHCenter:
1255 hscroll = (widthUsed - width) / 2;
1263 int cix = qRound(control->cursorToX(control->cursor() + preeditLength));
1264 if (cix - hscroll >= width) {
1265 // text doesn't fit, cursor is to the right of br (scroll right)
1266 hscroll = cix - width;
1267 } else if (cix - hscroll < 0 && hscroll < widthUsed) {
1268 // text doesn't fit, cursor is to the left of br (scroll left)
1270 } else if (widthUsed - hscroll < width) {
1271 // text doesn't fit, text document is to the left of br; align
1273 hscroll = widthUsed - width;
1275 if (preeditLength > 0) {
1276 // check to ensure long pre-edit text doesn't push the cursor
1278 cix = qRound(control->cursorToX(
1279 control->cursor() + qMax(0, control->preeditCursor() - 1)));
1286 QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
1289 Q_D(QQuickTextInput);
1291 QQuickTextNode *node = static_cast<QQuickTextNode *>(oldNode);
1293 node = new QQuickTextNode(QQuickItemPrivate::get(this)->sceneGraphContext());
1296 if (!d->textLayoutDirty) {
1297 QSGSimpleRectNode *cursorNode = node->cursorNode();
1298 if (cursorNode != 0 && !isReadOnly()) {
1299 QFontMetrics fm = QFontMetrics(d->font);
1300 // the y offset is there to keep the baseline constant in case we have script changes in the text.
1301 QPoint offset(-d->hscroll, fm.ascent() - d->control->ascent());
1302 offset.rx() += d->control->cursorToX();
1304 QRect br(boundingRect().toRect());
1305 cursorNode->setRect(QRectF(offset, QSizeF(d->control->cursorWidth(), br.height())));
1307 if (!d->cursorVisible
1308 || (!d->control->cursorBlinkStatus() && d->control->cursorBlinkPeriod() > 0)) {
1315 node->deleteContent();
1316 node->setMatrix(QMatrix4x4());
1318 QPoint offset = QPoint(0,0);
1319 QFontMetrics fm = QFontMetrics(d->font);
1320 QRect br(boundingRect().toRect());
1321 if (d->autoScroll) {
1322 // the y offset is there to keep the baseline constant in case we have script changes in the text.
1323 offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent());
1325 offset = QPoint(d->hscroll, 0);
1328 QTextLayout *textLayout = d->control->textLayout();
1329 if (!textLayout->text().isEmpty()) {
1330 node->addTextLayout(offset, textLayout, d->color,
1331 QQuickText::Normal, QColor(),
1332 d->selectionColor, d->selectedTextColor,
1333 d->control->selectionStart(),
1334 d->control->selectionEnd() - 1); // selectionEnd() returns first char after
1338 if (!isReadOnly() && d->cursorItem == 0) {
1339 offset.rx() += d->control->cursorToX();
1340 node->setCursor(QRectF(offset, QSizeF(d->control->cursorWidth(), br.height())), d->color);
1341 if (!d->cursorVisible
1342 || (!d->control->cursorBlinkStatus() && d->control->cursorBlinkPeriod() > 0)) {
1349 d->textLayoutDirty = false;
1355 QVariant QQuickTextInput::inputMethodQuery(Qt::InputMethodQuery property) const
1357 Q_D(const QQuickTextInput);
1360 return QVariant((bool)(flags() & ItemAcceptsInputMethod));
1362 return QVariant((int)inputMethodHints());
1363 case Qt::ImCursorRectangle:
1364 return cursorRectangle();
1367 case Qt::ImCursorPosition:
1368 return QVariant(d->control->cursor());
1369 case Qt::ImSurroundingText:
1370 if (d->control->echoMode() == QLineControl::PasswordEchoOnEdit
1371 && !d->control->passwordEchoEditing()) {
1372 return QVariant(displayText());
1374 return QVariant(d->control->realText());
1376 case Qt::ImCurrentSelection:
1377 return QVariant(selectedText());
1378 case Qt::ImMaximumTextLength:
1379 return QVariant(maxLength());
1380 case Qt::ImAnchorPosition:
1381 if (d->control->selectionStart() == d->control->selectionEnd())
1382 return QVariant(d->control->cursor());
1383 else if (d->control->selectionStart() == d->control->cursor())
1384 return QVariant(d->control->selectionEnd());
1386 return QVariant(d->control->selectionStart());
1393 \qmlmethod void QtQuick2::TextInput::deselect()
1395 Removes active text selection.
1397 void QQuickTextInput::deselect()
1399 Q_D(QQuickTextInput);
1400 d->control->deselect();
1404 \qmlmethod void QtQuick2::TextInput::selectAll()
1406 Causes all text to be selected.
1408 void QQuickTextInput::selectAll()
1410 Q_D(QQuickTextInput);
1411 d->control->setSelection(0, d->control->text().length());
1415 \qmlmethod void QtQuick2::TextInput::isRightToLeft(int start, int end)
1417 Returns true if the natural reading direction of the editor text
1418 found between positions \a start and \a end is right to left.
1420 bool QQuickTextInput::isRightToLeft(int start, int end)
1422 Q_D(QQuickTextInput);
1424 qmlInfo(this) << "isRightToLeft(start, end) called with the end property being smaller than the start.";
1427 return d->control->text().mid(start, end - start).isRightToLeft();
1431 #ifndef QT_NO_CLIPBOARD
1433 \qmlmethod QtQuick2::TextInput::cut()
1435 Moves the currently selected text to the system clipboard.
1437 void QQuickTextInput::cut()
1439 Q_D(QQuickTextInput);
1445 \qmlmethod QtQuick2::TextInput::copy()
1447 Copies the currently selected text to the system clipboard.
1449 void QQuickTextInput::copy()
1451 Q_D(QQuickTextInput);
1456 \qmlmethod QtQuick2::TextInput::paste()
1458 Replaces the currently selected text by the contents of the system clipboard.
1460 void QQuickTextInput::paste()
1462 Q_D(QQuickTextInput);
1463 if (!d->control->isReadOnly())
1464 d->control->paste();
1466 #endif // QT_NO_CLIPBOARD
1469 \qmlmethod void QtQuick2::TextInput::selectWord()
1471 Causes the word closest to the current cursor position to be selected.
1473 void QQuickTextInput::selectWord()
1475 Q_D(QQuickTextInput);
1476 d->control->selectWordAtPos(d->control->cursor());
1480 \qmlproperty bool QtQuick2::TextInput::smooth
1482 This property holds whether the text is smoothly scaled or transformed.
1484 Smooth filtering gives better visual quality, but is slower. If
1485 the item is displayed at its natural size, this property has no visual or
1488 \note Generally scaling artifacts are only visible if the item is stationary on
1489 the screen. A common pattern when animating an item is to disable smooth
1490 filtering at the beginning of the animation and reenable it at the conclusion.
1494 \qmlproperty string QtQuick2::TextInput::passwordCharacter
1496 This is the character displayed when echoMode is set to Password or
1497 PasswordEchoOnEdit. By default it is an asterisk.
1499 If this property is set to a string with more than one character,
1500 the first character is used. If the string is empty, the value
1501 is ignored and the property is not set.
1503 QString QQuickTextInput::passwordCharacter() const
1505 Q_D(const QQuickTextInput);
1506 return QString(d->control->passwordCharacter());
1509 void QQuickTextInput::setPasswordCharacter(const QString &str)
1511 Q_D(QQuickTextInput);
1512 if (str.length() < 1)
1514 d->control->setPasswordCharacter(str.constData()[0]);
1515 EchoMode echoMode_ = echoMode();
1516 if (echoMode_ == Password || echoMode_ == PasswordEchoOnEdit) {
1519 emit passwordCharacterChanged();
1523 \qmlproperty string QtQuick2::TextInput::displayText
1525 This is the text displayed in the TextInput.
1527 If \l echoMode is set to TextInput::Normal, this holds the
1528 same value as the TextInput::text property. Otherwise,
1529 this property holds the text visible to the user, while
1530 the \l text property holds the actual entered text.
1532 QString QQuickTextInput::displayText() const
1534 Q_D(const QQuickTextInput);
1535 return d->control->displayText();
1539 \qmlproperty bool QtQuick2::TextInput::selectByMouse
1543 If true, the user can use the mouse to select text in some
1544 platform-specific way. Note that for some platforms this may
1545 not be an appropriate interaction (eg. may conflict with how
1546 the text needs to behave inside a Flickable.
1548 bool QQuickTextInput::selectByMouse() const
1550 Q_D(const QQuickTextInput);
1551 return d->selectByMouse;
1554 void QQuickTextInput::setSelectByMouse(bool on)
1556 Q_D(QQuickTextInput);
1557 if (d->selectByMouse != on) {
1558 d->selectByMouse = on;
1559 emit selectByMouseChanged(on);
1564 \qmlproperty enum QtQuick2::TextInput::mouseSelectionMode
1566 Specifies how text should be selected using a mouse.
1569 \o TextInput.SelectCharacters - The selection is updated with individual characters. (Default)
1570 \o TextInput.SelectWords - The selection is updated with whole words.
1573 This property only applies when \l selectByMouse is true.
1576 QQuickTextInput::SelectionMode QQuickTextInput::mouseSelectionMode() const
1578 Q_D(const QQuickTextInput);
1579 return d->mouseSelectionMode;
1582 void QQuickTextInput::setMouseSelectionMode(SelectionMode mode)
1584 Q_D(QQuickTextInput);
1585 if (d->mouseSelectionMode != mode) {
1586 d->mouseSelectionMode = mode;
1587 emit mouseSelectionModeChanged(mode);
1592 \qmlproperty bool QtQuick2::TextInput::canPaste
1594 Returns true if the TextInput is writable and the content of the clipboard is
1595 suitable for pasting into the TextEdit.
1597 bool QQuickTextInput::canPaste() const
1599 Q_D(const QQuickTextInput);
1603 void QQuickTextInput::moveCursorSelection(int position)
1605 Q_D(QQuickTextInput);
1606 d->control->moveCursor(position, true);
1610 \qmlmethod void QtQuick2::TextInput::moveCursorSelection(int position, SelectionMode mode = TextInput.SelectCharacters)
1612 Moves the cursor to \a position and updates the selection according to the optional \a mode
1613 parameter. (To only move the cursor, set the \l cursorPosition property.)
1615 When this method is called it additionally sets either the
1616 selectionStart or the selectionEnd (whichever was at the previous cursor position)
1617 to the specified position. This allows you to easily extend and contract the selected
1620 The selection mode specifies whether the selection is updated on a per character or a per word
1621 basis. If not specified the selection mode will default to TextInput.SelectCharacters.
1624 \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
1625 the previous cursor position) to the specified position.
1626 \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all
1627 words between the specified position and the previous cursor position. Words partially in the
1631 For example, take this sequence of calls:
1635 moveCursorSelection(9, TextInput.SelectCharacters)
1636 moveCursorSelection(7, TextInput.SelectCharacters)
1639 This moves the cursor to position 5, extend the selection end from 5 to 9
1640 and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
1641 selected (the 6th and 7th characters).
1643 The same sequence with TextInput.SelectWords will extend the selection start to a word boundary
1644 before or on position 5 and extend the selection end to a word boundary on or past position 9.
1646 void QQuickTextInput::moveCursorSelection(int pos, SelectionMode mode)
1648 Q_D(QQuickTextInput);
1650 if (mode == SelectCharacters) {
1651 d->control->moveCursor(pos, true);
1652 } else if (pos != d->control->cursor()){
1653 const int cursor = d->control->cursor();
1655 if (!d->control->hasSelectedText())
1656 anchor = d->control->cursor();
1657 else if (d->control->selectionStart() == d->control->cursor())
1658 anchor = d->control->selectionEnd();
1660 anchor = d->control->selectionStart();
1662 if (anchor < pos || (anchor == pos && cursor < pos)) {
1663 const QString text = d->control->text();
1664 QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
1665 finder.setPosition(anchor);
1667 const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
1668 if (anchor < text.length() && (!(reasons & QTextBoundaryFinder::StartWord)
1669 || ((reasons & QTextBoundaryFinder::EndWord) && anchor > cursor))) {
1670 finder.toPreviousBoundary();
1672 anchor = finder.position() != -1 ? finder.position() : 0;
1674 finder.setPosition(pos);
1675 if (pos > 0 && !finder.boundaryReasons())
1676 finder.toNextBoundary();
1677 const int cursor = finder.position() != -1 ? finder.position() : text.length();
1679 d->control->setSelection(anchor, cursor - anchor);
1680 } else if (anchor > pos || (anchor == pos && cursor > pos)) {
1681 const QString text = d->control->text();
1682 QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
1683 finder.setPosition(anchor);
1685 const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
1686 if (anchor > 0 && (!(reasons & QTextBoundaryFinder::EndWord)
1687 || ((reasons & QTextBoundaryFinder::StartWord) && anchor < cursor))) {
1688 finder.toNextBoundary();
1691 anchor = finder.position() != -1 ? finder.position() : text.length();
1693 finder.setPosition(pos);
1694 if (pos < text.length() && !finder.boundaryReasons())
1695 finder.toPreviousBoundary();
1696 const int cursor = finder.position() != -1 ? finder.position() : 0;
1698 d->control->setSelection(anchor, cursor - anchor);
1704 \qmlmethod void QtQuick2::TextInput::openSoftwareInputPanel()
1706 Opens software input panels like virtual keyboards for typing, useful for
1707 customizing when you want the input keyboard to be shown and hidden in
1710 By default the opening of input panels follows the platform style. Input panels are
1711 always closed if no editor has active focus.
1713 You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1714 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1715 the behavior you want.
1717 Only relevant on platforms, which provide virtual keyboards.
1723 text: "Hello world!"
1724 activeFocusOnPress: false
1726 anchors.fill: parent
1728 if (!textInput.activeFocus) {
1729 textInput.forceActiveFocus()
1730 textInput.openSoftwareInputPanel();
1732 textInput.focus = false;
1735 onPressAndHold: textInput.closeSoftwareInputPanel();
1740 void QQuickTextInput::openSoftwareInputPanel()
1743 qGuiApp->inputPanel()->show();
1747 \qmlmethod void QtQuick2::TextInput::closeSoftwareInputPanel()
1749 Closes a software input panel like a virtual keyboard shown on the screen, useful
1750 for customizing when you want the input keyboard to be shown and hidden in
1753 By default the opening of input panels follows the platform style. Input panels are
1754 always closed if no editor has active focus.
1756 You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1757 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1758 the behavior you want.
1760 Only relevant on platforms, which provide virtual keyboards.
1766 text: "Hello world!"
1767 activeFocusOnPress: false
1769 anchors.fill: parent
1771 if (!textInput.activeFocus) {
1772 textInput.forceActiveFocus();
1773 textInput.openSoftwareInputPanel();
1775 textInput.focus = false;
1778 onPressAndHold: textInput.closeSoftwareInputPanel();
1783 void QQuickTextInput::closeSoftwareInputPanel()
1786 qGuiApp->inputPanel()->hide();
1789 void QQuickTextInput::focusInEvent(QFocusEvent *event)
1791 Q_D(const QQuickTextInput);
1792 if (d->focusOnPress && !isReadOnly())
1793 openSoftwareInputPanel();
1794 QQuickImplicitSizeItem::focusInEvent(event);
1797 void QQuickTextInput::itemChange(ItemChange change, const ItemChangeData &value)
1799 Q_D(QQuickTextInput);
1800 if (change == ItemActiveFocusHasChanged) {
1801 bool hasFocus = value.boolValue;
1802 d->focused = hasFocus;
1803 setCursorVisible(hasFocus); // ### refactor: && d->canvas && d->canvas->hasFocus()
1804 if (echoMode() == QQuickTextInput::PasswordEchoOnEdit && !hasFocus)
1805 d->control->updatePasswordEchoEditing(false);//QLineControl sets it on key events, but doesn't deal with focus events
1807 d->control->deselect();
1809 QQuickItem::itemChange(change, value);
1813 \qmlproperty bool QtQuick2::TextInput::inputMethodComposing
1816 This property holds whether the TextInput has partial text input from an
1819 While it is composing an input method may rely on mouse or key events from
1820 the TextInput to edit or commit the partial text. This property can be
1821 used to determine when to disable events handlers that may interfere with
1822 the correct operation of an input method.
1824 bool QQuickTextInput::isInputMethodComposing() const
1826 Q_D(const QQuickTextInput);
1827 return d->control->preeditAreaText().length() > 0;
1830 void QQuickTextInputPrivate::init()
1832 Q_Q(QQuickTextInput);
1833 control->setParent(q);//Now mandatory due to accessibility changes
1834 control->setCursorWidth(1);
1835 control->setPasswordCharacter(QLatin1Char('*'));
1836 q->setSmooth(smooth);
1837 q->setAcceptedMouseButtons(Qt::LeftButton);
1838 q->setFlag(QQuickItem::ItemAcceptsInputMethod);
1839 q->setFlag(QQuickItem::ItemHasContents);
1840 q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
1841 q, SLOT(cursorPosChanged()));
1842 q->connect(control, SIGNAL(selectionChanged()),
1843 q, SLOT(selectionChanged()));
1844 q->connect(control, SIGNAL(textChanged(QString)),
1845 q, SLOT(q_textChanged()));
1846 q->connect(control, SIGNAL(accepted()),
1847 q, SIGNAL(accepted()));
1848 q->connect(control, SIGNAL(updateNeeded(QRect)),
1849 q, SLOT(updateRect(QRect)));
1850 #ifndef QT_NO_CLIPBOARD
1851 q->connect(q, SIGNAL(readOnlyChanged(bool)),
1852 q, SLOT(q_canPasteChanged()));
1853 q->connect(QGuiApplication::clipboard(), SIGNAL(dataChanged()),
1854 q, SLOT(q_canPasteChanged()));
1855 canPaste = !control->isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
1856 #endif // QT_NO_CLIPBOARD
1857 q->connect(control, SIGNAL(updateMicroFocus()),
1858 q, SLOT(updateCursorRectangle()));
1859 q->connect(control, SIGNAL(displayTextChanged(QString)),
1860 q, SLOT(updateRect()));
1862 imHints &= ~Qt::ImhMultiLine;
1863 oldValidity = control->hasAcceptableInput();
1864 lastSelectionStart = 0;
1865 lastSelectionEnd = 0;
1866 QPalette p = control->palette();
1867 selectedTextColor = p.color(QPalette::HighlightedText);
1868 selectionColor = p.color(QPalette::Highlight);
1869 determineHorizontalAlignment();
1871 if (!qmlDisableDistanceField()) {
1872 QTextOption option = control->textLayout()->textOption();
1873 option.setUseDesignMetrics(true);
1874 control->textLayout()->setTextOption(option);
1878 void QQuickTextInput::cursorPosChanged()
1880 Q_D(QQuickTextInput);
1881 updateCursorRectangle();
1882 emit cursorPositionChanged();
1883 // XXX todo - not in 4.8?
1885 d->control->resetCursorBlinkTimer();
1888 if (!d->control->hasSelectedText()) {
1889 if (d->lastSelectionStart != d->control->cursor()) {
1890 d->lastSelectionStart = d->control->cursor();
1891 emit selectionStartChanged();
1893 if (d->lastSelectionEnd != d->control->cursor()) {
1894 d->lastSelectionEnd = d->control->cursor();
1895 emit selectionEndChanged();
1900 void QQuickTextInput::updateCursorRectangle()
1902 Q_D(QQuickTextInput);
1903 d->determineHorizontalAlignment();
1904 d->updateHorizontalScroll();
1905 updateRect();//TODO: Only update rect between pos's
1907 emit cursorRectangleChanged();
1909 d->cursorItem->setX(d->control->cursorToX() - d->hscroll);
1912 void QQuickTextInput::selectionChanged()
1914 Q_D(QQuickTextInput);
1915 updateRect();//TODO: Only update rect in selection
1916 emit selectedTextChanged();
1918 if (d->lastSelectionStart != d->control->selectionStart()) {
1919 d->lastSelectionStart = d->control->selectionStart();
1920 if (d->lastSelectionStart == -1)
1921 d->lastSelectionStart = d->control->cursor();
1922 emit selectionStartChanged();
1924 if (d->lastSelectionEnd != d->control->selectionEnd()) {
1925 d->lastSelectionEnd = d->control->selectionEnd();
1926 if (d->lastSelectionEnd == -1)
1927 d->lastSelectionEnd = d->control->cursor();
1928 emit selectionEndChanged();
1932 void QQuickTextInput::q_textChanged()
1934 Q_D(QQuickTextInput);
1936 emit displayTextChanged();
1938 d->determineHorizontalAlignment();
1939 d->updateHorizontalScroll();
1941 if (hasAcceptableInput() != d->oldValidity) {
1942 d->oldValidity = hasAcceptableInput();
1943 emit acceptableInputChanged();
1947 void QQuickTextInputPrivate::showCursor()
1949 if (textNode != 0 && textNode->cursorNode() != 0)
1950 textNode->cursorNode()->setColor(color);
1953 void QQuickTextInputPrivate::hideCursor()
1955 if (textNode != 0 && textNode->cursorNode() != 0)
1956 textNode->cursorNode()->setColor(QColor(0, 0, 0, 0));
1959 void QQuickTextInput::updateRect(const QRect &r)
1961 Q_D(QQuickTextInput);
1962 if (!isComponentComplete())
1966 d->textLayoutDirty = true;
1972 QRectF QQuickTextInput::boundingRect() const
1974 Q_D(const QQuickTextInput);
1975 QRectF r = QQuickImplicitSizeItem::boundingRect();
1977 int cursorWidth = d->cursorItem ? d->cursorItem->width() : d->control->cursorWidth();
1979 // Could include font max left/right bearings to either side of rectangle.
1981 r.setRight(r.right() + cursorWidth);
1985 void QQuickTextInput::updateSize(bool needsRedraw)
1987 Q_D(QQuickTextInput);
1990 setImplicitSize(d->calculateTextWidth(), d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
1991 if (w==width() && h==height() && needsRedraw)
1995 void QQuickTextInput::q_canPasteChanged()
1997 Q_D(QQuickTextInput);
1998 bool old = d->canPaste;
1999 #ifndef QT_NO_CLIPBOARD
2000 d->canPaste = !d->control->isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
2002 if (d->canPaste != old)
2003 emit canPasteChanged();