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 cursorNode->setRect(cursorRectangle());
1301 if (!d->cursorVisible
1302 || (!d->control->cursorBlinkStatus() && d->control->cursorBlinkPeriod() > 0)) {
1309 node->deleteContent();
1310 node->setMatrix(QMatrix4x4());
1312 QPoint offset = QPoint(0,0);
1313 QFontMetrics fm = QFontMetrics(d->font);
1314 QRect br(boundingRect().toRect());
1315 if (d->autoScroll) {
1316 // the y offset is there to keep the baseline constant in case we have script changes in the text.
1317 offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent());
1319 offset = QPoint(d->hscroll, 0);
1322 QTextLayout *textLayout = d->control->textLayout();
1323 if (!textLayout->text().isEmpty()) {
1324 node->addTextLayout(offset, textLayout, d->color,
1325 QQuickText::Normal, QColor(),
1326 d->selectionColor, d->selectedTextColor,
1327 d->control->selectionStart(),
1328 d->control->selectionEnd() - 1); // selectionEnd() returns first char after
1332 if (!isReadOnly() && d->cursorItem == 0) {
1333 node->setCursor(cursorRectangle(), d->color);
1334 if (!d->cursorVisible
1335 || (!d->control->cursorBlinkStatus() && d->control->cursorBlinkPeriod() > 0)) {
1342 d->textLayoutDirty = false;
1348 QVariant QQuickTextInput::inputMethodQuery(Qt::InputMethodQuery property) const
1350 Q_D(const QQuickTextInput);
1353 return QVariant((bool)(flags() & ItemAcceptsInputMethod));
1355 return QVariant((int)inputMethodHints());
1356 case Qt::ImCursorRectangle:
1357 return cursorRectangle();
1360 case Qt::ImCursorPosition:
1361 return QVariant(d->control->cursor());
1362 case Qt::ImSurroundingText:
1363 if (d->control->echoMode() == QLineControl::PasswordEchoOnEdit
1364 && !d->control->passwordEchoEditing()) {
1365 return QVariant(displayText());
1367 return QVariant(d->control->realText());
1369 case Qt::ImCurrentSelection:
1370 return QVariant(selectedText());
1371 case Qt::ImMaximumTextLength:
1372 return QVariant(maxLength());
1373 case Qt::ImAnchorPosition:
1374 if (d->control->selectionStart() == d->control->selectionEnd())
1375 return QVariant(d->control->cursor());
1376 else if (d->control->selectionStart() == d->control->cursor())
1377 return QVariant(d->control->selectionEnd());
1379 return QVariant(d->control->selectionStart());
1386 \qmlmethod void QtQuick2::TextInput::deselect()
1388 Removes active text selection.
1390 void QQuickTextInput::deselect()
1392 Q_D(QQuickTextInput);
1393 d->control->deselect();
1397 \qmlmethod void QtQuick2::TextInput::selectAll()
1399 Causes all text to be selected.
1401 void QQuickTextInput::selectAll()
1403 Q_D(QQuickTextInput);
1404 d->control->setSelection(0, d->control->text().length());
1408 \qmlmethod void QtQuick2::TextInput::isRightToLeft(int start, int end)
1410 Returns true if the natural reading direction of the editor text
1411 found between positions \a start and \a end is right to left.
1413 bool QQuickTextInput::isRightToLeft(int start, int end)
1415 Q_D(QQuickTextInput);
1417 qmlInfo(this) << "isRightToLeft(start, end) called with the end property being smaller than the start.";
1420 return d->control->text().mid(start, end - start).isRightToLeft();
1424 #ifndef QT_NO_CLIPBOARD
1426 \qmlmethod QtQuick2::TextInput::cut()
1428 Moves the currently selected text to the system clipboard.
1430 void QQuickTextInput::cut()
1432 Q_D(QQuickTextInput);
1438 \qmlmethod QtQuick2::TextInput::copy()
1440 Copies the currently selected text to the system clipboard.
1442 void QQuickTextInput::copy()
1444 Q_D(QQuickTextInput);
1449 \qmlmethod QtQuick2::TextInput::paste()
1451 Replaces the currently selected text by the contents of the system clipboard.
1453 void QQuickTextInput::paste()
1455 Q_D(QQuickTextInput);
1456 if (!d->control->isReadOnly())
1457 d->control->paste();
1459 #endif // QT_NO_CLIPBOARD
1462 \qmlmethod void QtQuick2::TextInput::selectWord()
1464 Causes the word closest to the current cursor position to be selected.
1466 void QQuickTextInput::selectWord()
1468 Q_D(QQuickTextInput);
1469 d->control->selectWordAtPos(d->control->cursor());
1473 \qmlproperty bool QtQuick2::TextInput::smooth
1475 This property holds whether the text is smoothly scaled or transformed.
1477 Smooth filtering gives better visual quality, but is slower. If
1478 the item is displayed at its natural size, this property has no visual or
1481 \note Generally scaling artifacts are only visible if the item is stationary on
1482 the screen. A common pattern when animating an item is to disable smooth
1483 filtering at the beginning of the animation and reenable it at the conclusion.
1487 \qmlproperty string QtQuick2::TextInput::passwordCharacter
1489 This is the character displayed when echoMode is set to Password or
1490 PasswordEchoOnEdit. By default it is an asterisk.
1492 If this property is set to a string with more than one character,
1493 the first character is used. If the string is empty, the value
1494 is ignored and the property is not set.
1496 QString QQuickTextInput::passwordCharacter() const
1498 Q_D(const QQuickTextInput);
1499 return QString(d->control->passwordCharacter());
1502 void QQuickTextInput::setPasswordCharacter(const QString &str)
1504 Q_D(QQuickTextInput);
1505 if (str.length() < 1)
1507 d->control->setPasswordCharacter(str.constData()[0]);
1508 EchoMode echoMode_ = echoMode();
1509 if (echoMode_ == Password || echoMode_ == PasswordEchoOnEdit) {
1512 emit passwordCharacterChanged();
1516 \qmlproperty string QtQuick2::TextInput::displayText
1518 This is the text displayed in the TextInput.
1520 If \l echoMode is set to TextInput::Normal, this holds the
1521 same value as the TextInput::text property. Otherwise,
1522 this property holds the text visible to the user, while
1523 the \l text property holds the actual entered text.
1525 QString QQuickTextInput::displayText() const
1527 Q_D(const QQuickTextInput);
1528 return d->control->displayText();
1532 \qmlproperty bool QtQuick2::TextInput::selectByMouse
1536 If true, the user can use the mouse to select text in some
1537 platform-specific way. Note that for some platforms this may
1538 not be an appropriate interaction (eg. may conflict with how
1539 the text needs to behave inside a Flickable.
1541 bool QQuickTextInput::selectByMouse() const
1543 Q_D(const QQuickTextInput);
1544 return d->selectByMouse;
1547 void QQuickTextInput::setSelectByMouse(bool on)
1549 Q_D(QQuickTextInput);
1550 if (d->selectByMouse != on) {
1551 d->selectByMouse = on;
1552 emit selectByMouseChanged(on);
1557 \qmlproperty enum QtQuick2::TextInput::mouseSelectionMode
1559 Specifies how text should be selected using a mouse.
1562 \o TextInput.SelectCharacters - The selection is updated with individual characters. (Default)
1563 \o TextInput.SelectWords - The selection is updated with whole words.
1566 This property only applies when \l selectByMouse is true.
1569 QQuickTextInput::SelectionMode QQuickTextInput::mouseSelectionMode() const
1571 Q_D(const QQuickTextInput);
1572 return d->mouseSelectionMode;
1575 void QQuickTextInput::setMouseSelectionMode(SelectionMode mode)
1577 Q_D(QQuickTextInput);
1578 if (d->mouseSelectionMode != mode) {
1579 d->mouseSelectionMode = mode;
1580 emit mouseSelectionModeChanged(mode);
1585 \qmlproperty bool QtQuick2::TextInput::canPaste
1587 Returns true if the TextInput is writable and the content of the clipboard is
1588 suitable for pasting into the TextEdit.
1590 bool QQuickTextInput::canPaste() const
1592 Q_D(const QQuickTextInput);
1596 void QQuickTextInput::moveCursorSelection(int position)
1598 Q_D(QQuickTextInput);
1599 d->control->moveCursor(position, true);
1603 \qmlmethod void QtQuick2::TextInput::moveCursorSelection(int position, SelectionMode mode = TextInput.SelectCharacters)
1605 Moves the cursor to \a position and updates the selection according to the optional \a mode
1606 parameter. (To only move the cursor, set the \l cursorPosition property.)
1608 When this method is called it additionally sets either the
1609 selectionStart or the selectionEnd (whichever was at the previous cursor position)
1610 to the specified position. This allows you to easily extend and contract the selected
1613 The selection mode specifies whether the selection is updated on a per character or a per word
1614 basis. If not specified the selection mode will default to TextInput.SelectCharacters.
1617 \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
1618 the previous cursor position) to the specified position.
1619 \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all
1620 words between the specified position and the previous cursor position. Words partially in the
1624 For example, take this sequence of calls:
1628 moveCursorSelection(9, TextInput.SelectCharacters)
1629 moveCursorSelection(7, TextInput.SelectCharacters)
1632 This moves the cursor to position 5, extend the selection end from 5 to 9
1633 and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
1634 selected (the 6th and 7th characters).
1636 The same sequence with TextInput.SelectWords will extend the selection start to a word boundary
1637 before or on position 5 and extend the selection end to a word boundary on or past position 9.
1639 void QQuickTextInput::moveCursorSelection(int pos, SelectionMode mode)
1641 Q_D(QQuickTextInput);
1643 if (mode == SelectCharacters) {
1644 d->control->moveCursor(pos, true);
1645 } else if (pos != d->control->cursor()){
1646 const int cursor = d->control->cursor();
1648 if (!d->control->hasSelectedText())
1649 anchor = d->control->cursor();
1650 else if (d->control->selectionStart() == d->control->cursor())
1651 anchor = d->control->selectionEnd();
1653 anchor = d->control->selectionStart();
1655 if (anchor < pos || (anchor == pos && cursor < pos)) {
1656 const QString text = d->control->text();
1657 QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
1658 finder.setPosition(anchor);
1660 const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
1661 if (anchor < text.length() && (!(reasons & QTextBoundaryFinder::StartWord)
1662 || ((reasons & QTextBoundaryFinder::EndWord) && anchor > cursor))) {
1663 finder.toPreviousBoundary();
1665 anchor = finder.position() != -1 ? finder.position() : 0;
1667 finder.setPosition(pos);
1668 if (pos > 0 && !finder.boundaryReasons())
1669 finder.toNextBoundary();
1670 const int cursor = finder.position() != -1 ? finder.position() : text.length();
1672 d->control->setSelection(anchor, cursor - anchor);
1673 } else if (anchor > pos || (anchor == pos && cursor > pos)) {
1674 const QString text = d->control->text();
1675 QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
1676 finder.setPosition(anchor);
1678 const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
1679 if (anchor > 0 && (!(reasons & QTextBoundaryFinder::EndWord)
1680 || ((reasons & QTextBoundaryFinder::StartWord) && anchor < cursor))) {
1681 finder.toNextBoundary();
1684 anchor = finder.position() != -1 ? finder.position() : text.length();
1686 finder.setPosition(pos);
1687 if (pos < text.length() && !finder.boundaryReasons())
1688 finder.toPreviousBoundary();
1689 const int cursor = finder.position() != -1 ? finder.position() : 0;
1691 d->control->setSelection(anchor, cursor - anchor);
1697 \qmlmethod void QtQuick2::TextInput::openSoftwareInputPanel()
1699 Opens software input panels like virtual keyboards for typing, useful for
1700 customizing when you want the input keyboard to be shown and hidden in
1703 By default the opening of input panels follows the platform style. Input panels are
1704 always closed if no editor has active focus.
1706 You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1707 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1708 the behavior you want.
1710 Only relevant on platforms, which provide virtual keyboards.
1716 text: "Hello world!"
1717 activeFocusOnPress: false
1719 anchors.fill: parent
1721 if (!textInput.activeFocus) {
1722 textInput.forceActiveFocus()
1723 textInput.openSoftwareInputPanel();
1725 textInput.focus = false;
1728 onPressAndHold: textInput.closeSoftwareInputPanel();
1733 void QQuickTextInput::openSoftwareInputPanel()
1736 qGuiApp->inputPanel()->show();
1740 \qmlmethod void QtQuick2::TextInput::closeSoftwareInputPanel()
1742 Closes a software input panel like a virtual keyboard shown on the screen, useful
1743 for 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::closeSoftwareInputPanel()
1779 qGuiApp->inputPanel()->hide();
1782 void QQuickTextInput::focusInEvent(QFocusEvent *event)
1784 Q_D(const QQuickTextInput);
1785 if (d->focusOnPress && !isReadOnly())
1786 openSoftwareInputPanel();
1787 QQuickImplicitSizeItem::focusInEvent(event);
1790 void QQuickTextInput::itemChange(ItemChange change, const ItemChangeData &value)
1792 Q_D(QQuickTextInput);
1793 if (change == ItemActiveFocusHasChanged) {
1794 bool hasFocus = value.boolValue;
1795 d->focused = hasFocus;
1796 setCursorVisible(hasFocus); // ### refactor: && d->canvas && d->canvas->hasFocus()
1797 if (echoMode() == QQuickTextInput::PasswordEchoOnEdit && !hasFocus)
1798 d->control->updatePasswordEchoEditing(false);//QLineControl sets it on key events, but doesn't deal with focus events
1800 d->control->deselect();
1802 QQuickItem::itemChange(change, value);
1806 \qmlproperty bool QtQuick2::TextInput::inputMethodComposing
1809 This property holds whether the TextInput has partial text input from an
1812 While it is composing an input method may rely on mouse or key events from
1813 the TextInput to edit or commit the partial text. This property can be
1814 used to determine when to disable events handlers that may interfere with
1815 the correct operation of an input method.
1817 bool QQuickTextInput::isInputMethodComposing() const
1819 Q_D(const QQuickTextInput);
1820 return d->control->preeditAreaText().length() > 0;
1823 void QQuickTextInputPrivate::init()
1825 Q_Q(QQuickTextInput);
1826 control->setParent(q);//Now mandatory due to accessibility changes
1827 control->setCursorWidth(1);
1828 control->setPasswordCharacter(QLatin1Char('*'));
1829 q->setSmooth(smooth);
1830 q->setAcceptedMouseButtons(Qt::LeftButton);
1831 q->setFlag(QQuickItem::ItemAcceptsInputMethod);
1832 q->setFlag(QQuickItem::ItemHasContents);
1833 q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
1834 q, SLOT(cursorPosChanged()));
1835 q->connect(control, SIGNAL(selectionChanged()),
1836 q, SLOT(selectionChanged()));
1837 q->connect(control, SIGNAL(textChanged(QString)),
1838 q, SLOT(q_textChanged()));
1839 q->connect(control, SIGNAL(accepted()),
1840 q, SIGNAL(accepted()));
1841 q->connect(control, SIGNAL(updateNeeded(QRect)),
1842 q, SLOT(updateRect(QRect)));
1843 #ifndef QT_NO_CLIPBOARD
1844 q->connect(q, SIGNAL(readOnlyChanged(bool)),
1845 q, SLOT(q_canPasteChanged()));
1846 q->connect(QGuiApplication::clipboard(), SIGNAL(dataChanged()),
1847 q, SLOT(q_canPasteChanged()));
1848 canPaste = !control->isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
1849 #endif // QT_NO_CLIPBOARD
1850 q->connect(control, SIGNAL(updateMicroFocus()),
1851 q, SLOT(updateCursorRectangle()));
1852 q->connect(control, SIGNAL(displayTextChanged(QString)),
1853 q, SLOT(updateRect()));
1855 imHints &= ~Qt::ImhMultiLine;
1856 oldValidity = control->hasAcceptableInput();
1857 lastSelectionStart = 0;
1858 lastSelectionEnd = 0;
1859 QPalette p = control->palette();
1860 selectedTextColor = p.color(QPalette::HighlightedText);
1861 selectionColor = p.color(QPalette::Highlight);
1862 determineHorizontalAlignment();
1864 if (!qmlDisableDistanceField()) {
1865 QTextOption option = control->textLayout()->textOption();
1866 option.setUseDesignMetrics(true);
1867 control->textLayout()->setTextOption(option);
1871 void QQuickTextInput::cursorPosChanged()
1873 Q_D(QQuickTextInput);
1874 updateCursorRectangle();
1875 emit cursorPositionChanged();
1876 // XXX todo - not in 4.8?
1878 d->control->resetCursorBlinkTimer();
1881 if (!d->control->hasSelectedText()) {
1882 if (d->lastSelectionStart != d->control->cursor()) {
1883 d->lastSelectionStart = d->control->cursor();
1884 emit selectionStartChanged();
1886 if (d->lastSelectionEnd != d->control->cursor()) {
1887 d->lastSelectionEnd = d->control->cursor();
1888 emit selectionEndChanged();
1893 void QQuickTextInput::updateCursorRectangle()
1895 Q_D(QQuickTextInput);
1896 d->determineHorizontalAlignment();
1897 d->updateHorizontalScroll();
1898 updateRect();//TODO: Only update rect between pos's
1900 emit cursorRectangleChanged();
1902 d->cursorItem->setX(d->control->cursorToX() - d->hscroll);
1905 void QQuickTextInput::selectionChanged()
1907 Q_D(QQuickTextInput);
1908 updateRect();//TODO: Only update rect in selection
1909 emit selectedTextChanged();
1911 if (d->lastSelectionStart != d->control->selectionStart()) {
1912 d->lastSelectionStart = d->control->selectionStart();
1913 if (d->lastSelectionStart == -1)
1914 d->lastSelectionStart = d->control->cursor();
1915 emit selectionStartChanged();
1917 if (d->lastSelectionEnd != d->control->selectionEnd()) {
1918 d->lastSelectionEnd = d->control->selectionEnd();
1919 if (d->lastSelectionEnd == -1)
1920 d->lastSelectionEnd = d->control->cursor();
1921 emit selectionEndChanged();
1925 void QQuickTextInput::q_textChanged()
1927 Q_D(QQuickTextInput);
1929 emit displayTextChanged();
1931 d->determineHorizontalAlignment();
1932 d->updateHorizontalScroll();
1934 if (hasAcceptableInput() != d->oldValidity) {
1935 d->oldValidity = hasAcceptableInput();
1936 emit acceptableInputChanged();
1940 void QQuickTextInputPrivate::showCursor()
1942 if (textNode != 0 && textNode->cursorNode() != 0)
1943 textNode->cursorNode()->setColor(color);
1946 void QQuickTextInputPrivate::hideCursor()
1948 if (textNode != 0 && textNode->cursorNode() != 0)
1949 textNode->cursorNode()->setColor(QColor(0, 0, 0, 0));
1952 void QQuickTextInput::updateRect(const QRect &r)
1954 Q_D(QQuickTextInput);
1955 if (!isComponentComplete())
1959 d->textLayoutDirty = true;
1965 QRectF QQuickTextInput::boundingRect() const
1967 Q_D(const QQuickTextInput);
1968 QRectF r = QQuickImplicitSizeItem::boundingRect();
1970 int cursorWidth = d->cursorItem ? d->cursorItem->width() : d->control->cursorWidth();
1972 // Could include font max left/right bearings to either side of rectangle.
1974 r.setRight(r.right() + cursorWidth);
1978 void QQuickTextInput::updateSize(bool needsRedraw)
1980 Q_D(QQuickTextInput);
1983 setImplicitSize(d->calculateTextWidth(), d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
1984 if (w==width() && h==height() && needsRedraw)
1988 void QQuickTextInput::q_canPasteChanged()
1990 Q_D(QQuickTextInput);
1991 bool old = d->canPaste;
1992 #ifndef QT_NO_CLIPBOARD
1993 d->canPaste = !d->control->isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
1995 if (d->canPaste != old)
1996 emit canPasteChanged();