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>
47 #include <private/qsgdistancefieldglyphcache_p.h>
49 #include <QtDeclarative/qdeclarativeinfo.h>
50 #include <QtGui/qevent.h>
51 #include <QTextBoundaryFinder>
52 #include "qquicktextnode_p.h"
53 #include <qsgsimplerectnode.h>
55 #include <QtGui/qstylehints.h>
56 #include <QtGui/qinputpanel.h>
60 DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
63 \qmlclass TextInput QQuickTextInput
64 \inqmlmodule QtQuick 2
65 \ingroup qml-basic-visual-elements
66 \brief The TextInput item displays an editable line of text.
69 The TextInput element displays a single line of editable plain text.
71 TextInput is used to accept a line of text input. Input constraints
72 can be placed on a TextInput item (for example, through a \l validator or \l inputMask),
73 and setting \l echoMode to an appropriate value enables TextInput to be used for
74 a password input field.
76 On Mac OS X, the Up/Down key bindings for Home/End are explicitly disabled.
77 If you want such bindings (on any platform), you will need to construct them in QML.
79 \sa TextEdit, Text, {declarative/text/textselection}{Text Selection example}
81 QQuickTextInput::QQuickTextInput(QQuickItem* parent)
82 : QQuickImplicitSizeItem(*(new QQuickTextInputPrivate), parent)
88 QQuickTextInput::~QQuickTextInput()
93 \qmlproperty string QtQuick2::TextInput::text
95 The text in the TextInput.
97 QString QQuickTextInput::text() const
99 Q_D(const QQuickTextInput);
100 return d->control->text();
103 void QQuickTextInput::setText(const QString &s)
105 Q_D(QQuickTextInput);
108 d->control->setText(s);
112 \qmlproperty string QtQuick2::TextInput::font.family
114 Sets the family name of the font.
116 The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]".
117 If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen.
118 If the family isn't available a family will be set using the font matching algorithm.
122 \qmlproperty bool QtQuick2::TextInput::font.bold
124 Sets whether the font weight is bold.
128 \qmlproperty enumeration QtQuick2::TextInput::font.weight
130 Sets the font's weight.
132 The weight can be one of:
135 \o Font.Normal - the default
142 TextInput { text: "Hello"; font.weight: Font.DemiBold }
147 \qmlproperty bool QtQuick2::TextInput::font.italic
149 Sets whether the font has an italic style.
153 \qmlproperty bool QtQuick2::TextInput::font.underline
155 Sets whether the text is underlined.
159 \qmlproperty bool QtQuick2::TextInput::font.strikeout
161 Sets whether the font has a strikeout style.
165 \qmlproperty real QtQuick2::TextInput::font.pointSize
167 Sets the font size in points. The point size must be greater than zero.
171 \qmlproperty int QtQuick2::TextInput::font.pixelSize
173 Sets the font size in pixels.
175 Using this function makes the font device dependent.
176 Use \c pointSize to set the size of the font in a device independent manner.
180 \qmlproperty real QtQuick2::TextInput::font.letterSpacing
182 Sets the letter spacing for the font.
184 Letter spacing changes the default spacing between individual letters in the font.
185 A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing.
189 \qmlproperty real QtQuick2::TextInput::font.wordSpacing
191 Sets the word spacing for the font.
193 Word spacing changes the default spacing between individual words.
194 A positive value increases the word spacing by a corresponding amount of pixels,
195 while a negative value decreases the inter-word spacing accordingly.
199 \qmlproperty enumeration QtQuick2::TextInput::font.capitalization
201 Sets the capitalization for the text.
204 \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied.
205 \o Font.AllUppercase - This alters the text to be rendered in all uppercase type.
206 \o Font.AllLowercase - This alters the text to be rendered in all lowercase type.
207 \o Font.SmallCaps - This alters the text to be rendered in small-caps type.
208 \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character.
212 TextInput { text: "Hello"; font.capitalization: Font.AllLowercase }
216 QFont QQuickTextInput::font() const
218 Q_D(const QQuickTextInput);
219 return d->sourceFont;
222 void QQuickTextInput::setFont(const QFont &font)
224 Q_D(QQuickTextInput);
225 if (d->sourceFont == font)
228 d->sourceFont = font;
229 QFont oldFont = d->font;
231 if (d->font.pointSizeF() != -1) {
233 qreal size = qRound(d->font.pointSizeF()*2.0);
234 d->font.setPointSizeF(size/2.0);
236 if (oldFont != d->font) {
237 d->control->setFont(d->font);
239 updateCursorRectangle();
241 d->cursorItem->setHeight(QFontMetrics(d->font).height());
244 emit fontChanged(d->sourceFont);
248 \qmlproperty color QtQuick2::TextInput::color
252 QColor QQuickTextInput::color() const
254 Q_D(const QQuickTextInput);
258 void QQuickTextInput::setColor(const QColor &c)
260 Q_D(QQuickTextInput);
264 emit colorChanged(c);
270 \qmlproperty color QtQuick2::TextInput::selectionColor
272 The text highlight color, used behind selections.
274 QColor QQuickTextInput::selectionColor() const
276 Q_D(const QQuickTextInput);
277 return d->selectionColor;
280 void QQuickTextInput::setSelectionColor(const QColor &color)
282 Q_D(QQuickTextInput);
283 if (d->selectionColor == color)
286 d->selectionColor = color;
287 QPalette p = d->control->palette();
288 p.setColor(QPalette::Highlight, d->selectionColor);
289 d->control->setPalette(p);
290 if (d->control->hasSelectedText())
292 emit selectionColorChanged(color);
295 \qmlproperty color QtQuick2::TextInput::selectedTextColor
297 The highlighted text color, used in selections.
299 QColor QQuickTextInput::selectedTextColor() const
301 Q_D(const QQuickTextInput);
302 return d->selectedTextColor;
305 void QQuickTextInput::setSelectedTextColor(const QColor &color)
307 Q_D(QQuickTextInput);
308 if (d->selectedTextColor == color)
311 d->selectedTextColor = color;
312 QPalette p = d->control->palette();
313 p.setColor(QPalette::HighlightedText, d->selectedTextColor);
314 d->control->setPalette(p);
315 if (d->control->hasSelectedText())
317 emit selectedTextColorChanged(color);
321 \qmlproperty enumeration QtQuick2::TextInput::horizontalAlignment
322 \qmlproperty enumeration QtQuick2::TextInput::effectiveHorizontalAlignment
324 Sets the horizontal alignment of the text within the TextInput item's
325 width and height. By default, the text alignment follows the natural alignment
326 of the text, for example text that is read from left to right will be aligned to
329 TextInput does not have vertical alignment, as the natural height is
330 exactly the height of the single line of text. If you set the height
331 manually to something larger, TextInput will always be top aligned
332 vertically. You can use anchors to align it however you want within
335 The valid values for \c horizontalAlignment are \c TextInput.AlignLeft, \c TextInput.AlignRight and
336 \c TextInput.AlignHCenter.
338 When using the attached property LayoutMirroring::enabled to mirror application
339 layouts, the horizontal alignment of text will also be mirrored. However, the property
340 \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
341 of TextInput, use the read-only property \c effectiveHorizontalAlignment.
343 QQuickTextInput::HAlignment QQuickTextInput::hAlign() const
345 Q_D(const QQuickTextInput);
349 void QQuickTextInput::setHAlign(HAlignment align)
351 Q_D(QQuickTextInput);
352 bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror;
353 d->hAlignImplicit = false;
354 if (d->setHAlign(align, forceAlign) && isComponentComplete()) {
355 updateCursorRectangle();
359 void QQuickTextInput::resetHAlign()
361 Q_D(QQuickTextInput);
362 d->hAlignImplicit = true;
363 if (d->determineHorizontalAlignment() && isComponentComplete()) {
364 updateCursorRectangle();
368 QQuickTextInput::HAlignment QQuickTextInput::effectiveHAlign() const
370 Q_D(const QQuickTextInput);
371 QQuickTextInput::HAlignment effectiveAlignment = d->hAlign;
372 if (!d->hAlignImplicit && d->effectiveLayoutMirror) {
374 case QQuickTextInput::AlignLeft:
375 effectiveAlignment = QQuickTextInput::AlignRight;
377 case QQuickTextInput::AlignRight:
378 effectiveAlignment = QQuickTextInput::AlignLeft;
384 return effectiveAlignment;
387 bool QQuickTextInputPrivate::setHAlign(QQuickTextInput::HAlignment alignment, bool forceAlign)
389 Q_Q(QQuickTextInput);
390 if ((hAlign != alignment || forceAlign) && alignment <= QQuickTextInput::AlignHCenter) { // justify not supported
391 QQuickTextInput::HAlignment oldEffectiveHAlign = q->effectiveHAlign();
393 emit q->horizontalAlignmentChanged(alignment);
394 if (oldEffectiveHAlign != q->effectiveHAlign())
395 emit q->effectiveHorizontalAlignmentChanged();
401 bool QQuickTextInputPrivate::determineHorizontalAlignment()
403 if (hAlignImplicit) {
404 // if no explicit alignment has been set, follow the natural layout direction of the text
405 QString text = control->text();
407 text = control->preeditAreaText();
408 bool isRightToLeft = text.isEmpty() ? QGuiApplication::keyboardInputDirection() == Qt::RightToLeft : text.isRightToLeft();
409 return setHAlign(isRightToLeft ? QQuickTextInput::AlignRight : QQuickTextInput::AlignLeft);
414 void QQuickTextInputPrivate::mirrorChange()
416 Q_Q(QQuickTextInput);
417 if (q->isComponentComplete()) {
418 if (!hAlignImplicit && (hAlign == QQuickTextInput::AlignRight || hAlign == QQuickTextInput::AlignLeft)) {
419 q->updateCursorRectangle();
420 emit q->effectiveHorizontalAlignmentChanged();
426 \qmlproperty bool QtQuick2::TextInput::readOnly
428 Sets whether user input can modify the contents of the TextInput.
430 If readOnly is set to true, then user input will not affect the text
431 property. Any bindings or attempts to set the text property will still
434 bool QQuickTextInput::isReadOnly() const
436 Q_D(const QQuickTextInput);
437 return d->control->isReadOnly();
440 void QQuickTextInput::setReadOnly(bool ro)
442 Q_D(QQuickTextInput);
443 if (d->control->isReadOnly() == ro)
446 setFlag(QQuickItem::ItemAcceptsInputMethod, !ro);
447 d->control->setReadOnly(ro);
449 d->control->setCursorPosition(d->control->end());
451 emit readOnlyChanged(ro);
455 \qmlproperty int QtQuick2::TextInput::maximumLength
456 The maximum permitted length of the text in the TextInput.
458 If the text is too long, it is truncated at the limit.
460 By default, this property contains a value of 32767.
462 int QQuickTextInput::maxLength() const
464 Q_D(const QQuickTextInput);
465 return d->control->maxLength();
468 void QQuickTextInput::setMaxLength(int ml)
470 Q_D(QQuickTextInput);
471 if (d->control->maxLength() == ml)
474 d->control->setMaxLength(ml);
476 emit maximumLengthChanged(ml);
480 \qmlproperty bool QtQuick2::TextInput::cursorVisible
481 Set to true when the TextInput shows a cursor.
483 This property is set and unset when the TextInput gets active focus, so that other
484 properties can be bound to whether the cursor is currently showing. As it
485 gets set and unset automatically, when you set the value yourself you must
486 keep in mind that your value may be overwritten.
488 It can be set directly in script, for example if a KeyProxy might
489 forward keys to it and you desire it to look active when this happens
490 (but without actually giving it active focus).
492 It should not be set directly on the element, like in the below QML,
493 as the specified value will be overridden an lost on focus changes.
502 In the above snippet the cursor will still become visible when the
503 TextInput gains active focus.
505 bool QQuickTextInput::isCursorVisible() const
507 Q_D(const QQuickTextInput);
508 return d->cursorVisible;
511 void QQuickTextInput::setCursorVisible(bool on)
513 Q_D(QQuickTextInput);
514 if (d->cursorVisible == on)
516 d->cursorVisible = on;
517 d->control->setCursorBlinkPeriod(on ? qApp->styleHints()->cursorFlashTime() : 0);
518 QRect r = d->control->cursorRect();
519 if (d->control->inputMask().isEmpty())
523 emit cursorVisibleChanged(d->cursorVisible);
527 \qmlproperty int QtQuick2::TextInput::cursorPosition
528 The position of the cursor in the TextInput.
530 int QQuickTextInput::cursorPosition() const
532 Q_D(const QQuickTextInput);
533 return d->control->cursor();
535 void QQuickTextInput::setCursorPosition(int cp)
537 Q_D(QQuickTextInput);
538 if (cp < 0 || cp > d->control->text().length())
540 d->control->moveCursor(cp);
544 Returns a Rect which encompasses the cursor, but which may be larger than is
545 required. Ignores custom cursor delegates.
547 QRect QQuickTextInput::cursorRectangle() const
549 Q_D(const QQuickTextInput);
550 QRect r = d->control->cursorRect();
551 // Scroll and make consistent with TextEdit
552 // QLineControl inexplicably adds 1 to the height and horizontal padding
553 // for unicode direction markers.
554 r.adjust(5 - d->hscroll, 0, -4 - d->hscroll, -1);
558 \qmlproperty int QtQuick2::TextInput::selectionStart
560 The cursor position before the first character in the current selection.
562 This property is read-only. To change the selection, use select(start,end),
563 selectAll(), or selectWord().
565 \sa selectionEnd, cursorPosition, selectedText
567 int QQuickTextInput::selectionStart() const
569 Q_D(const QQuickTextInput);
570 return d->lastSelectionStart;
573 \qmlproperty int QtQuick2::TextInput::selectionEnd
575 The cursor position after the last character in the current selection.
577 This property is read-only. To change the selection, use select(start,end),
578 selectAll(), or selectWord().
580 \sa selectionStart, cursorPosition, selectedText
582 int QQuickTextInput::selectionEnd() const
584 Q_D(const QQuickTextInput);
585 return d->lastSelectionEnd;
588 \qmlmethod void QtQuick2::TextInput::select(int start, int end)
590 Causes the text from \a start to \a end to be selected.
592 If either start or end is out of range, the selection is not changed.
594 After calling this, selectionStart will become the lesser
595 and selectionEnd will become the greater (regardless of the order passed
598 \sa selectionStart, selectionEnd
600 void QQuickTextInput::select(int start, int end)
602 Q_D(QQuickTextInput);
603 if (start < 0 || end < 0 || start > d->control->text().length() || end > d->control->text().length())
605 d->control->setSelection(start, end-start);
609 \qmlproperty string QtQuick2::TextInput::selectedText
611 This read-only property provides the text currently selected in the
614 It is equivalent to the following snippet, but is faster and easier
618 myTextInput.text.toString().substring(myTextInput.selectionStart,
619 myTextInput.selectionEnd);
622 QString QQuickTextInput::selectedText() const
624 Q_D(const QQuickTextInput);
625 return d->control->selectedText();
629 \qmlproperty bool QtQuick2::TextInput::activeFocusOnPress
631 Whether the TextInput should gain active focus on a mouse press. By default this is
634 bool QQuickTextInput::focusOnPress() const
636 Q_D(const QQuickTextInput);
637 return d->focusOnPress;
640 void QQuickTextInput::setFocusOnPress(bool b)
642 Q_D(QQuickTextInput);
643 if (d->focusOnPress == b)
648 emit activeFocusOnPressChanged(d->focusOnPress);
651 \qmlproperty bool QtQuick2::TextInput::autoScroll
653 Whether the TextInput should scroll when the text is longer than the width. By default this is
656 bool QQuickTextInput::autoScroll() const
658 Q_D(const QQuickTextInput);
659 return d->autoScroll;
662 void QQuickTextInput::setAutoScroll(bool b)
664 Q_D(QQuickTextInput);
665 if (d->autoScroll == b)
669 //We need to repaint so that the scrolling is taking into account.
671 updateCursorRectangle();
672 emit autoScrollChanged(d->autoScroll);
675 #ifndef QT_NO_VALIDATOR
678 \qmlclass IntValidator QIntValidator
679 \inqmlmodule QtQuick 2
680 \ingroup qml-basic-visual-elements
682 This element provides a validator for integer values.
684 IntValidator uses the \l {QLocale::setDefault()}{default locale} to interpret the number and
685 will accept locale specific digits, group separators, and positive and negative signs. In
686 addition, IntValidator is always guaranteed to accept a number formatted according to the "C"
690 \qmlproperty int QtQuick2::IntValidator::top
692 This property holds the validator's highest acceptable value.
693 By default, this property's value is derived from the highest signed integer available (typically 2147483647).
696 \qmlproperty int QtQuick2::IntValidator::bottom
698 This property holds the validator's lowest acceptable value.
699 By default, this property's value is derived from the lowest signed integer available (typically -2147483647).
703 \qmlclass DoubleValidator QDoubleValidator
704 \inqmlmodule QtQuick 2
705 \ingroup qml-basic-visual-elements
707 This element provides a validator for non-integer numbers.
711 \qmlproperty real QtQuick2::DoubleValidator::top
713 This property holds the validator's maximum acceptable value.
714 By default, this property contains a value of infinity.
717 \qmlproperty real QtQuick2::DoubleValidator::bottom
719 This property holds the validator's minimum acceptable value.
720 By default, this property contains a value of -infinity.
723 \qmlproperty int QtQuick2::DoubleValidator::decimals
725 This property holds the validator's maximum number of digits after the decimal point.
726 By default, this property contains a value of 1000.
729 \qmlproperty enumeration QtQuick2::DoubleValidator::notation
730 This property holds the notation of how a string can describe a number.
732 The possible values for this property are:
735 \o DoubleValidator.StandardNotation
736 \o DoubleValidator.ScientificNotation (default)
739 If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part (e.g. 1.5E-2).
743 \qmlclass RegExpValidator QRegExpValidator
744 \inqmlmodule QtQuick 2
745 \ingroup qml-basic-visual-elements
747 This element provides a validator, which counts as valid any string which
748 matches a specified regular expression.
751 \qmlproperty regExp QtQuick2::RegExpValidator::regExp
753 This property holds the regular expression used for validation.
755 Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular expression
758 By default, this property contains a regular expression with the pattern .* that matches any string.
762 \qmlproperty Validator QtQuick2::TextInput::validator
764 Allows you to set a validator on the TextInput. When a validator is set
765 the TextInput will only accept input which leaves the text property in
766 an acceptable or intermediate state. The accepted signal will only be sent
767 if the text is in an acceptable state when enter is pressed.
769 Currently supported validators are IntValidator, DoubleValidator and
770 RegExpValidator. An example of using validators is shown below, which allows
771 input of integers between 11 and 31 into the text input:
776 validator: IntValidator{bottom: 11; top: 31;}
781 \sa acceptableInput, inputMask
784 QValidator* QQuickTextInput::validator() const
786 Q_D(const QQuickTextInput);
787 //###const cast isn't good, but needed for property system?
788 return const_cast<QValidator*>(d->control->validator());
791 void QQuickTextInput::setValidator(QValidator* v)
793 Q_D(QQuickTextInput);
794 if (d->control->validator() == v)
797 d->control->setValidator(v);
798 if (!d->control->hasAcceptableInput()) {
799 d->oldValidity = false;
800 emit acceptableInputChanged();
803 emit validatorChanged();
805 #endif // QT_NO_VALIDATOR
808 \qmlproperty string QtQuick2::TextInput::inputMask
810 Allows you to set an input mask on the TextInput, restricting the allowable
811 text inputs. See QLineEdit::inputMask for further details, as the exact
812 same mask strings are used by TextInput.
814 \sa acceptableInput, validator
816 QString QQuickTextInput::inputMask() const
818 Q_D(const QQuickTextInput);
819 return d->control->inputMask();
822 void QQuickTextInput::setInputMask(const QString &im)
824 Q_D(QQuickTextInput);
825 if (d->control->inputMask() == im)
828 d->control->setInputMask(im);
829 emit inputMaskChanged(d->control->inputMask());
833 \qmlproperty bool QtQuick2::TextInput::acceptableInput
835 This property is always true unless a validator or input mask has been set.
836 If a validator or input mask has been set, this property will only be true
837 if the current text is acceptable to the validator or input mask as a final
838 string (not as an intermediate string).
840 bool QQuickTextInput::hasAcceptableInput() const
842 Q_D(const QQuickTextInput);
843 return d->control->hasAcceptableInput();
847 \qmlsignal QtQuick2::TextInput::onAccepted()
849 This handler is called when the Return or Enter key is pressed.
850 Note that if there is a \l validator or \l inputMask set on the text
851 input, the handler will only be emitted if the input is in an acceptable
855 void QQuickTextInputPrivate::updateInputMethodHints()
857 Q_Q(QQuickTextInput);
858 Qt::InputMethodHints hints = inputMethodHints;
859 uint echo = control->echoMode();
860 if (echo == QQuickTextInput::Password || echo == QQuickTextInput::NoEcho)
861 hints |= Qt::ImhHiddenText;
862 else if (echo == QQuickTextInput::PasswordEchoOnEdit)
863 hints &= ~Qt::ImhHiddenText;
864 if (echo != QQuickTextInput::Normal)
865 hints |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
866 q->setInputMethodHints(hints);
869 \qmlproperty enumeration QtQuick2::TextInput::echoMode
871 Specifies how the text should be displayed in the TextInput.
873 \o TextInput.Normal - Displays the text as it is. (Default)
874 \o TextInput.Password - Displays asterisks instead of characters.
875 \o TextInput.NoEcho - Displays nothing.
876 \o TextInput.PasswordEchoOnEdit - Displays characters as they are entered
877 while editing, otherwise displays asterisks.
880 QQuickTextInput::EchoMode QQuickTextInput::echoMode() const
882 Q_D(const QQuickTextInput);
883 return (QQuickTextInput::EchoMode)d->control->echoMode();
886 void QQuickTextInput::setEchoMode(QQuickTextInput::EchoMode echo)
888 Q_D(QQuickTextInput);
889 if (echoMode() == echo)
891 d->control->setEchoMode((QLineControl::EchoMode)echo);
892 d->updateInputMethodHints();
894 emit echoModeChanged(echoMode());
897 Qt::InputMethodHints QQuickTextInput::imHints() const
899 Q_D(const QQuickTextInput);
900 return d->inputMethodHints;
903 void QQuickTextInput::setIMHints(Qt::InputMethodHints hints)
905 Q_D(QQuickTextInput);
906 if (d->inputMethodHints == hints)
908 d->inputMethodHints = hints;
909 d->updateInputMethodHints();
913 \qmlproperty Component QtQuick2::TextInput::cursorDelegate
914 The delegate for the cursor in the TextInput.
916 If you set a cursorDelegate for a TextInput, this delegate will be used for
917 drawing the cursor instead of the standard cursor. An instance of the
918 delegate will be created and managed by the TextInput when a cursor is
919 needed, and the x property of delegate instance will be set so as
920 to be one pixel before the top left of the current character.
922 Note that the root item of the delegate component must be a QDeclarativeItem or
923 QDeclarativeItem derived item.
925 QDeclarativeComponent* QQuickTextInput::cursorDelegate() const
927 Q_D(const QQuickTextInput);
928 return d->cursorComponent;
931 void QQuickTextInput::setCursorDelegate(QDeclarativeComponent* c)
933 Q_D(QQuickTextInput);
934 if (d->cursorComponent == c)
937 d->cursorComponent = c;
939 //note that the components are owned by something else
940 delete d->cursorItem;
942 d->startCreatingCursor();
945 emit cursorDelegateChanged();
948 void QQuickTextInputPrivate::startCreatingCursor()
950 Q_Q(QQuickTextInput);
951 if (cursorComponent->isReady()) {
953 } else if (cursorComponent->isLoading()) {
954 q->connect(cursorComponent, SIGNAL(statusChanged(int)),
955 q, SLOT(createCursor()));
957 qmlInfo(q, cursorComponent->errors()) << QQuickTextInput::tr("Could not load cursor delegate");
961 void QQuickTextInput::createCursor()
963 Q_D(QQuickTextInput);
964 if (d->cursorComponent->isError()) {
965 qmlInfo(this, d->cursorComponent->errors()) << tr("Could not load cursor delegate");
969 if (!d->cursorComponent->isReady())
973 delete d->cursorItem;
974 QDeclarativeContext *creationContext = d->cursorComponent->creationContext();
975 QObject *object = d->cursorComponent->create(creationContext ? creationContext : qmlContext(this));
976 d->cursorItem = qobject_cast<QQuickItem*>(object);
977 if (!d->cursorItem) {
979 qmlInfo(this, d->cursorComponent->errors()) << tr("Could not instantiate cursor delegate");
983 QDeclarative_setParent_noEvent(d->cursorItem, this);
984 d->cursorItem->setParentItem(this);
985 d->cursorItem->setX(d->control->cursorToX());
986 d->cursorItem->setHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
990 \qmlmethod rect QtQuick2::TextInput::positionToRectangle(int pos)
992 This function takes a character position and returns the rectangle that the
993 cursor would occupy, if it was placed at that character position.
995 This is similar to setting the cursorPosition, and then querying the cursor
996 rectangle, but the cursorPosition is not changed.
998 QRectF QQuickTextInput::positionToRectangle(int pos) const
1000 Q_D(const QQuickTextInput);
1001 if (pos > d->control->cursorPosition())
1002 pos += d->control->preeditAreaText().length();
1003 return QRectF(d->control->cursorToX(pos)-d->hscroll,
1005 d->control->cursorWidth(),
1006 cursorRectangle().height());
1010 \qmlmethod int QtQuick2::TextInput::positionAt(int x, CursorPosition position = CursorBetweenCharacters)
1012 This function returns the character position at
1013 x pixels from the left of the textInput. Position 0 is before the
1014 first character, position 1 is after the first character but before the second,
1015 and so on until position text.length, which is after all characters.
1017 This means that for all x values before the first character this function returns 0,
1018 and for all x values after the last character this function returns text.length.
1020 The cursor position type specifies how the cursor position should be resolved.
1023 \o TextInput.CursorBetweenCharacters - Returns the position between characters that is nearest x.
1024 \o TextInput.CursorOnCharacter - Returns the position before the character that is nearest x.
1027 int QQuickTextInput::positionAt(int x) const
1029 return positionAt(x, CursorBetweenCharacters);
1032 int QQuickTextInput::positionAt(int x, CursorPosition position) const
1034 Q_D(const QQuickTextInput);
1035 int pos = d->control->xToPos(x + d->hscroll, QTextLine::CursorPosition(position));
1036 const int cursor = d->control->cursor();
1038 const int preeditLength = d->control->preeditAreaText().length();
1039 pos = pos > cursor + preeditLength
1040 ? pos - preeditLength
1046 void QQuickTextInput::keyPressEvent(QKeyEvent* ev)
1048 Q_D(QQuickTextInput);
1049 // Don't allow MacOSX up/down support, and we don't allow a completer.
1050 bool ignore = (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) && ev->modifiers() == Qt::NoModifier;
1051 if (!ignore && (d->lastSelectionStart == d->lastSelectionEnd) && (ev->key() == Qt::Key_Right || ev->key() == Qt::Key_Left)) {
1052 // Ignore when moving off the end unless there is a selection,
1053 // because then moving will do something (deselect).
1054 int cursorPosition = d->control->cursor();
1055 if (cursorPosition == 0)
1056 ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Left : Qt::Key_Right);
1057 if (cursorPosition == d->control->text().length())
1058 ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Right : Qt::Key_Left);
1063 d->control->processKeyEvent(ev);
1065 if (!ev->isAccepted())
1066 QQuickImplicitSizeItem::keyPressEvent(ev);
1069 void QQuickTextInput::inputMethodEvent(QInputMethodEvent *ev)
1071 Q_D(QQuickTextInput);
1072 const bool wasComposing = d->control->preeditAreaText().length() > 0;
1073 if (d->control->isReadOnly()) {
1076 d->control->processInputMethodEvent(ev);
1078 if (!ev->isAccepted())
1079 QQuickImplicitSizeItem::inputMethodEvent(ev);
1081 if (wasComposing != (d->control->preeditAreaText().length() > 0))
1082 emit inputMethodComposingChanged();
1085 void QQuickTextInput::mouseDoubleClickEvent(QMouseEvent *event)
1087 Q_D(QQuickTextInput);
1088 if (d->sendMouseEventToInputContext(event))
1090 if (d->selectByMouse) {
1091 int cursor = d->xToPos(event->localPos().x());
1092 d->control->selectWordAtPos(cursor);
1093 event->setAccepted(true);
1094 if (!d->hasPendingTripleClick()) {
1095 d->tripleClickStartPoint = event->localPos().toPoint();
1096 d->tripleClickTimer.start();
1099 QQuickImplicitSizeItem::mouseDoubleClickEvent(event);
1103 void QQuickTextInput::mousePressEvent(QMouseEvent *event)
1105 Q_D(QQuickTextInput);
1106 if (d->sendMouseEventToInputContext(event))
1108 if (d->focusOnPress) {
1109 bool hadActiveFocus = hasActiveFocus();
1111 // re-open input panel on press if already focused
1112 if (hasActiveFocus() && hadActiveFocus && !isReadOnly())
1113 openSoftwareInputPanel();
1115 if (d->selectByMouse) {
1116 setKeepMouseGrab(false);
1117 d->selectPressed = true;
1118 d->pressPos = event->localPos();
1119 QPoint distanceVector = d->pressPos.toPoint() - d->tripleClickStartPoint;
1120 if (d->hasPendingTripleClick()
1121 && distanceVector.manhattanLength() < qApp->styleHints()->startDragDistance()) {
1122 event->setAccepted(true);
1127 bool mark = (event->modifiers() & Qt::ShiftModifier) && d->selectByMouse;
1128 int cursor = d->xToPos(event->localPos().x());
1129 d->control->moveCursor(cursor, mark);
1130 event->setAccepted(true);
1133 void QQuickTextInput::mouseMoveEvent(QMouseEvent *event)
1135 Q_D(QQuickTextInput);
1136 if (d->sendMouseEventToInputContext(event))
1138 if (d->selectPressed) {
1139 if (qAbs(int(event->localPos().x() - d->pressPos.x())) > qApp->styleHints()->startDragDistance())
1140 setKeepMouseGrab(true);
1141 moveCursorSelection(d->xToPos(event->localPos().x()), d->mouseSelectionMode);
1142 event->setAccepted(true);
1144 QQuickImplicitSizeItem::mouseMoveEvent(event);
1148 void QQuickTextInput::mouseReleaseEvent(QMouseEvent *event)
1150 Q_D(QQuickTextInput);
1151 if (d->sendMouseEventToInputContext(event))
1153 if (d->selectPressed) {
1154 d->selectPressed = false;
1155 setKeepMouseGrab(false);
1157 d->control->processEvent(event);
1158 if (!event->isAccepted())
1159 QQuickImplicitSizeItem::mouseReleaseEvent(event);
1162 bool QQuickTextInputPrivate::sendMouseEventToInputContext(QMouseEvent *event)
1164 #if !defined QT_NO_IM
1165 if (control->composeMode() && event->type() == QEvent::MouseButtonRelease) {
1166 int tmp_cursor = xToPos(event->localPos().x());
1167 int mousePos = tmp_cursor - control->cursor();
1168 // may be causing reset() in some input methods
1169 qApp->inputPanel()->invokeAction(QInputPanel::Click, mousePos);
1170 if (!control->preeditAreaText().isEmpty())
1181 void QQuickTextInput::mouseUngrabEvent()
1183 Q_D(QQuickTextInput);
1184 d->selectPressed = false;
1185 setKeepMouseGrab(false);
1188 bool QQuickTextInput::event(QEvent* ev)
1190 Q_D(QQuickTextInput);
1191 //Anything we don't deal with ourselves, pass to the control
1192 bool handled = false;
1193 switch (ev->type()) {
1194 case QEvent::KeyPress:
1195 case QEvent::KeyRelease://###Should the control be doing anything with release?
1196 case QEvent::InputMethod:
1197 case QEvent::MouseButtonPress:
1198 case QEvent::MouseMove:
1199 case QEvent::MouseButtonRelease:
1200 case QEvent::MouseButtonDblClick:
1203 handled = d->control->processEvent(ev);
1206 handled = QQuickImplicitSizeItem::event(ev);
1210 void QQuickTextInput::geometryChanged(const QRectF &newGeometry,
1211 const QRectF &oldGeometry)
1213 if (newGeometry.width() != oldGeometry.width()) {
1215 updateCursorRectangle();
1217 QQuickImplicitSizeItem::geometryChanged(newGeometry, oldGeometry);
1220 int QQuickTextInputPrivate::calculateTextWidth()
1222 return qRound(control->naturalTextWidth());
1225 void QQuickTextInputPrivate::updateHorizontalScroll()
1227 Q_Q(QQuickTextInput);
1228 const int preeditLength = control->preeditAreaText().length();
1229 const int width = q->width();
1230 int widthUsed = calculateTextWidth();
1232 if (!autoScroll || widthUsed <= width) {
1233 QQuickTextInput::HAlignment effectiveHAlign = q->effectiveHAlign();
1234 // text fits in br; use hscroll for alignment
1235 switch (effectiveHAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) {
1236 case Qt::AlignRight:
1237 hscroll = widthUsed - width;
1239 case Qt::AlignHCenter:
1240 hscroll = (widthUsed - width) / 2;
1248 int cix = qRound(control->cursorToX(control->cursor() + preeditLength));
1249 if (cix - hscroll >= width) {
1250 // text doesn't fit, cursor is to the right of br (scroll right)
1251 hscroll = cix - width;
1252 } else if (cix - hscroll < 0 && hscroll < widthUsed) {
1253 // text doesn't fit, cursor is to the left of br (scroll left)
1255 } else if (widthUsed - hscroll < width) {
1256 // text doesn't fit, text document is to the left of br; align
1258 hscroll = widthUsed - width;
1260 if (preeditLength > 0) {
1261 // check to ensure long pre-edit text doesn't push the cursor
1263 cix = qRound(control->cursorToX(
1264 control->cursor() + qMax(0, control->preeditCursor() - 1)));
1271 QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
1274 Q_D(QQuickTextInput);
1276 QQuickTextNode *node = static_cast<QQuickTextNode *>(oldNode);
1278 node = new QQuickTextNode(QQuickItemPrivate::get(this)->sceneGraphContext());
1281 if (!d->textLayoutDirty) {
1282 QSGSimpleRectNode *cursorNode = node->cursorNode();
1283 if (cursorNode != 0 && !isReadOnly()) {
1284 QFontMetrics fm = QFontMetrics(d->font);
1285 // the y offset is there to keep the baseline constant in case we have script changes in the text.
1286 QPoint offset(-d->hscroll, fm.ascent() - d->control->ascent());
1287 offset.rx() += d->control->cursorToX();
1289 QRect br(boundingRect().toRect());
1290 cursorNode->setRect(QRectF(offset, QSizeF(d->control->cursorWidth(), br.height())));
1292 if (!d->cursorVisible
1293 || (!d->control->cursorBlinkStatus() && d->control->cursorBlinkPeriod() > 0)) {
1300 node->deleteContent();
1301 node->setMatrix(QMatrix4x4());
1303 QPoint offset = QPoint(0,0);
1304 QFontMetrics fm = QFontMetrics(d->font);
1305 QRect br(boundingRect().toRect());
1306 if (d->autoScroll) {
1307 // the y offset is there to keep the baseline constant in case we have script changes in the text.
1308 offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent());
1310 offset = QPoint(d->hscroll, 0);
1313 QTextLayout *textLayout = d->control->textLayout();
1314 if (!textLayout->text().isEmpty()) {
1315 node->addTextLayout(offset, textLayout, d->color,
1316 QQuickText::Normal, QColor(),
1317 d->selectionColor, d->selectedTextColor,
1318 d->control->selectionStart(),
1319 d->control->selectionEnd() - 1); // selectionEnd() returns first char after
1323 if (!isReadOnly() && d->cursorItem == 0) {
1324 offset.rx() += d->control->cursorToX();
1325 node->setCursor(QRectF(offset, QSizeF(d->control->cursorWidth(), br.height())), d->color);
1326 if (!d->cursorVisible
1327 || (!d->control->cursorBlinkStatus() && d->control->cursorBlinkPeriod() > 0)) {
1334 d->textLayoutDirty = false;
1340 QVariant QQuickTextInput::inputMethodQuery(Qt::InputMethodQuery property) const
1342 Q_D(const QQuickTextInput);
1345 return QVariant((bool)(flags() & ItemAcceptsInputMethod));
1347 return QVariant((int)inputMethodHints());
1348 case Qt::ImCursorRectangle:
1349 return cursorRectangle();
1352 case Qt::ImCursorPosition:
1353 return QVariant(d->control->cursor());
1354 case Qt::ImSurroundingText:
1355 if (d->control->echoMode() == QLineControl::PasswordEchoOnEdit
1356 && !d->control->passwordEchoEditing()) {
1357 return QVariant(displayText());
1359 return QVariant(text());
1361 case Qt::ImCurrentSelection:
1362 return QVariant(selectedText());
1363 case Qt::ImMaximumTextLength:
1364 return QVariant(maxLength());
1365 case Qt::ImAnchorPosition:
1366 if (d->control->selectionStart() == d->control->selectionEnd())
1367 return QVariant(d->control->cursor());
1368 else if (d->control->selectionStart() == d->control->cursor())
1369 return QVariant(d->control->selectionEnd());
1371 return QVariant(d->control->selectionStart());
1378 \qmlmethod void QtQuick2::TextInput::deselect()
1380 Removes active text selection.
1382 void QQuickTextInput::deselect()
1384 Q_D(QQuickTextInput);
1385 d->control->deselect();
1389 \qmlmethod void QtQuick2::TextInput::selectAll()
1391 Causes all text to be selected.
1393 void QQuickTextInput::selectAll()
1395 Q_D(QQuickTextInput);
1396 d->control->setSelection(0, d->control->text().length());
1400 \qmlmethod void QtQuick2::TextInput::isRightToLeft(int start, int end)
1402 Returns true if the natural reading direction of the editor text
1403 found between positions \a start and \a end is right to left.
1405 bool QQuickTextInput::isRightToLeft(int start, int end)
1407 Q_D(QQuickTextInput);
1409 qmlInfo(this) << "isRightToLeft(start, end) called with the end property being smaller than the start.";
1412 return d->control->text().mid(start, end - start).isRightToLeft();
1416 #ifndef QT_NO_CLIPBOARD
1418 \qmlmethod QtQuick2::TextInput::cut()
1420 Moves the currently selected text to the system clipboard.
1422 void QQuickTextInput::cut()
1424 Q_D(QQuickTextInput);
1430 \qmlmethod QtQuick2::TextInput::copy()
1432 Copies the currently selected text to the system clipboard.
1434 void QQuickTextInput::copy()
1436 Q_D(QQuickTextInput);
1441 \qmlmethod QtQuick2::TextInput::paste()
1443 Replaces the currently selected text by the contents of the system clipboard.
1445 void QQuickTextInput::paste()
1447 Q_D(QQuickTextInput);
1448 if (!d->control->isReadOnly())
1449 d->control->paste();
1451 #endif // QT_NO_CLIPBOARD
1454 \qmlmethod void QtQuick2::TextInput::selectWord()
1456 Causes the word closest to the current cursor position to be selected.
1458 void QQuickTextInput::selectWord()
1460 Q_D(QQuickTextInput);
1461 d->control->selectWordAtPos(d->control->cursor());
1465 \qmlproperty bool QtQuick2::TextInput::smooth
1467 This property holds whether the text is smoothly scaled or transformed.
1469 Smooth filtering gives better visual quality, but is slower. If
1470 the item is displayed at its natural size, this property has no visual or
1473 \note Generally scaling artifacts are only visible if the item is stationary on
1474 the screen. A common pattern when animating an item is to disable smooth
1475 filtering at the beginning of the animation and reenable it at the conclusion.
1479 \qmlproperty string QtQuick2::TextInput::passwordCharacter
1481 This is the character displayed when echoMode is set to Password or
1482 PasswordEchoOnEdit. By default it is an asterisk.
1484 If this property is set to a string with more than one character,
1485 the first character is used. If the string is empty, the value
1486 is ignored and the property is not set.
1488 QString QQuickTextInput::passwordCharacter() const
1490 Q_D(const QQuickTextInput);
1491 return QString(d->control->passwordCharacter());
1494 void QQuickTextInput::setPasswordCharacter(const QString &str)
1496 Q_D(QQuickTextInput);
1497 if (str.length() < 1)
1499 d->control->setPasswordCharacter(str.constData()[0]);
1500 EchoMode echoMode_ = echoMode();
1501 if (echoMode_ == Password || echoMode_ == PasswordEchoOnEdit) {
1504 emit passwordCharacterChanged();
1508 \qmlproperty string QtQuick2::TextInput::displayText
1510 This is the text displayed in the TextInput.
1512 If \l echoMode is set to TextInput::Normal, this holds the
1513 same value as the TextInput::text property. Otherwise,
1514 this property holds the text visible to the user, while
1515 the \l text property holds the actual entered text.
1517 QString QQuickTextInput::displayText() const
1519 Q_D(const QQuickTextInput);
1520 return d->control->displayText();
1524 \qmlproperty bool QtQuick2::TextInput::selectByMouse
1528 If true, the user can use the mouse to select text in some
1529 platform-specific way. Note that for some platforms this may
1530 not be an appropriate interaction (eg. may conflict with how
1531 the text needs to behave inside a Flickable.
1533 bool QQuickTextInput::selectByMouse() const
1535 Q_D(const QQuickTextInput);
1536 return d->selectByMouse;
1539 void QQuickTextInput::setSelectByMouse(bool on)
1541 Q_D(QQuickTextInput);
1542 if (d->selectByMouse != on) {
1543 d->selectByMouse = on;
1544 emit selectByMouseChanged(on);
1549 \qmlproperty enum QtQuick2::TextInput::mouseSelectionMode
1551 Specifies how text should be selected using a mouse.
1554 \o TextInput.SelectCharacters - The selection is updated with individual characters. (Default)
1555 \o TextInput.SelectWords - The selection is updated with whole words.
1558 This property only applies when \l selectByMouse is true.
1561 QQuickTextInput::SelectionMode QQuickTextInput::mouseSelectionMode() const
1563 Q_D(const QQuickTextInput);
1564 return d->mouseSelectionMode;
1567 void QQuickTextInput::setMouseSelectionMode(SelectionMode mode)
1569 Q_D(QQuickTextInput);
1570 if (d->mouseSelectionMode != mode) {
1571 d->mouseSelectionMode = mode;
1572 emit mouseSelectionModeChanged(mode);
1577 \qmlproperty bool QtQuick2::TextInput::canPaste
1579 Returns true if the TextInput is writable and the content of the clipboard is
1580 suitable for pasting into the TextEdit.
1582 bool QQuickTextInput::canPaste() const
1584 Q_D(const QQuickTextInput);
1588 void QQuickTextInput::moveCursorSelection(int position)
1590 Q_D(QQuickTextInput);
1591 d->control->moveCursor(position, true);
1595 \qmlmethod void QtQuick2::TextInput::moveCursorSelection(int position, SelectionMode mode = TextInput.SelectCharacters)
1597 Moves the cursor to \a position and updates the selection according to the optional \a mode
1598 parameter. (To only move the cursor, set the \l cursorPosition property.)
1600 When this method is called it additionally sets either the
1601 selectionStart or the selectionEnd (whichever was at the previous cursor position)
1602 to the specified position. This allows you to easily extend and contract the selected
1605 The selection mode specifies whether the selection is updated on a per character or a per word
1606 basis. If not specified the selection mode will default to TextInput.SelectCharacters.
1609 \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
1610 the previous cursor position) to the specified position.
1611 \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all
1612 words between the specified position and the previous cursor position. Words partially in the
1616 For example, take this sequence of calls:
1620 moveCursorSelection(9, TextInput.SelectCharacters)
1621 moveCursorSelection(7, TextInput.SelectCharacters)
1624 This moves the cursor to position 5, extend the selection end from 5 to 9
1625 and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
1626 selected (the 6th and 7th characters).
1628 The same sequence with TextInput.SelectWords will extend the selection start to a word boundary
1629 before or on position 5 and extend the selection end to a word boundary on or past position 9.
1631 void QQuickTextInput::moveCursorSelection(int pos, SelectionMode mode)
1633 Q_D(QQuickTextInput);
1635 if (mode == SelectCharacters) {
1636 d->control->moveCursor(pos, true);
1637 } else if (pos != d->control->cursor()){
1638 const int cursor = d->control->cursor();
1640 if (!d->control->hasSelectedText())
1641 anchor = d->control->cursor();
1642 else if (d->control->selectionStart() == d->control->cursor())
1643 anchor = d->control->selectionEnd();
1645 anchor = d->control->selectionStart();
1647 if (anchor < pos || (anchor == pos && cursor < pos)) {
1648 const QString text = d->control->text();
1649 QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
1650 finder.setPosition(anchor);
1652 const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
1653 if (anchor < text.length() && (!(reasons & QTextBoundaryFinder::StartWord)
1654 || ((reasons & QTextBoundaryFinder::EndWord) && anchor > cursor))) {
1655 finder.toPreviousBoundary();
1657 anchor = finder.position() != -1 ? finder.position() : 0;
1659 finder.setPosition(pos);
1660 if (pos > 0 && !finder.boundaryReasons())
1661 finder.toNextBoundary();
1662 const int cursor = finder.position() != -1 ? finder.position() : text.length();
1664 d->control->setSelection(anchor, cursor - anchor);
1665 } else if (anchor > pos || (anchor == pos && cursor > pos)) {
1666 const QString text = d->control->text();
1667 QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
1668 finder.setPosition(anchor);
1670 const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
1671 if (anchor > 0 && (!(reasons & QTextBoundaryFinder::EndWord)
1672 || ((reasons & QTextBoundaryFinder::StartWord) && anchor < cursor))) {
1673 finder.toNextBoundary();
1676 anchor = finder.position() != -1 ? finder.position() : text.length();
1678 finder.setPosition(pos);
1679 if (pos < text.length() && !finder.boundaryReasons())
1680 finder.toPreviousBoundary();
1681 const int cursor = finder.position() != -1 ? finder.position() : 0;
1683 d->control->setSelection(anchor, cursor - anchor);
1689 \qmlmethod void QtQuick2::TextInput::openSoftwareInputPanel()
1691 Opens software input panels like virtual keyboards for typing, useful for
1692 customizing when you want the input keyboard to be shown and hidden in
1695 By default the opening of input panels follows the platform style. Input panels are
1696 always closed if no editor has active focus.
1698 You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1699 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1700 the behavior you want.
1702 Only relevant on platforms, which provide virtual keyboards.
1708 text: "Hello world!"
1709 activeFocusOnPress: false
1711 anchors.fill: parent
1713 if (!textInput.activeFocus) {
1714 textInput.forceActiveFocus()
1715 textInput.openSoftwareInputPanel();
1717 textInput.focus = false;
1720 onPressAndHold: textInput.closeSoftwareInputPanel();
1725 void QQuickTextInput::openSoftwareInputPanel()
1728 qGuiApp->inputPanel()->show();
1732 \qmlmethod void QtQuick2::TextInput::closeSoftwareInputPanel()
1734 Closes a software input panel like a virtual keyboard shown on the screen, useful
1735 for customizing when you want the input keyboard to be shown and hidden in
1738 By default the opening of input panels follows the platform style. Input panels are
1739 always closed if no editor has active focus.
1741 You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1742 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1743 the behavior you want.
1745 Only relevant on platforms, which provide virtual keyboards.
1751 text: "Hello world!"
1752 activeFocusOnPress: false
1754 anchors.fill: parent
1756 if (!textInput.activeFocus) {
1757 textInput.forceActiveFocus();
1758 textInput.openSoftwareInputPanel();
1760 textInput.focus = false;
1763 onPressAndHold: textInput.closeSoftwareInputPanel();
1768 void QQuickTextInput::closeSoftwareInputPanel()
1771 qGuiApp->inputPanel()->hide();
1774 void QQuickTextInput::focusInEvent(QFocusEvent *event)
1776 Q_D(const QQuickTextInput);
1777 if (d->focusOnPress && !isReadOnly())
1778 openSoftwareInputPanel();
1779 QQuickImplicitSizeItem::focusInEvent(event);
1782 void QQuickTextInput::itemChange(ItemChange change, const ItemChangeData &value)
1784 Q_D(QQuickTextInput);
1785 if (change == ItemActiveFocusHasChanged) {
1786 bool hasFocus = value.boolValue;
1787 d->focused = hasFocus;
1788 setCursorVisible(hasFocus); // ### refactor: && d->canvas && d->canvas->hasFocus()
1789 if (echoMode() == QQuickTextInput::PasswordEchoOnEdit && !hasFocus)
1790 d->control->updatePasswordEchoEditing(false);//QLineControl sets it on key events, but doesn't deal with focus events
1792 d->control->deselect();
1794 QQuickItem::itemChange(change, value);
1798 \qmlproperty bool QtQuick2::TextInput::inputMethodComposing
1801 This property holds whether the TextInput has partial text input from an
1804 While it is composing an input method may rely on mouse or key events from
1805 the TextInput to edit or commit the partial text. This property can be
1806 used to determine when to disable events handlers that may interfere with
1807 the correct operation of an input method.
1809 bool QQuickTextInput::isInputMethodComposing() const
1811 Q_D(const QQuickTextInput);
1812 return d->control->preeditAreaText().length() > 0;
1815 void QQuickTextInputPrivate::init()
1817 Q_Q(QQuickTextInput);
1818 control->setParent(q);//Now mandatory due to accessibility changes
1819 control->setCursorWidth(1);
1820 control->setPasswordCharacter(QLatin1Char('*'));
1821 q->setSmooth(smooth);
1822 q->setAcceptedMouseButtons(Qt::LeftButton);
1823 q->setFlag(QQuickItem::ItemAcceptsInputMethod);
1824 q->setFlag(QQuickItem::ItemHasContents);
1825 q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
1826 q, SLOT(cursorPosChanged()));
1827 q->connect(control, SIGNAL(selectionChanged()),
1828 q, SLOT(selectionChanged()));
1829 q->connect(control, SIGNAL(textChanged(QString)),
1830 q, SLOT(q_textChanged()));
1831 q->connect(control, SIGNAL(accepted()),
1832 q, SIGNAL(accepted()));
1833 q->connect(control, SIGNAL(updateNeeded(QRect)),
1834 q, SLOT(updateRect(QRect)));
1835 #ifndef QT_NO_CLIPBOARD
1836 q->connect(q, SIGNAL(readOnlyChanged(bool)),
1837 q, SLOT(q_canPasteChanged()));
1838 q->connect(QGuiApplication::clipboard(), SIGNAL(dataChanged()),
1839 q, SLOT(q_canPasteChanged()));
1840 canPaste = !control->isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
1841 #endif // QT_NO_CLIPBOARD
1842 q->connect(control, SIGNAL(updateMicroFocus()),
1843 q, SLOT(updateCursorRectangle()));
1844 q->connect(control, SIGNAL(displayTextChanged(QString)),
1845 q, SLOT(updateRect()));
1847 imHints &= ~Qt::ImhMultiLine;
1848 oldValidity = control->hasAcceptableInput();
1849 lastSelectionStart = 0;
1850 lastSelectionEnd = 0;
1851 QPalette p = control->palette();
1852 selectedTextColor = p.color(QPalette::HighlightedText);
1853 selectionColor = p.color(QPalette::Highlight);
1854 determineHorizontalAlignment();
1856 if (!qmlDisableDistanceField()) {
1857 QTextOption option = control->textLayout()->textOption();
1858 option.setUseDesignMetrics(true);
1859 control->textLayout()->setTextOption(option);
1863 void QQuickTextInput::cursorPosChanged()
1865 Q_D(QQuickTextInput);
1866 updateCursorRectangle();
1867 emit cursorPositionChanged();
1868 // XXX todo - not in 4.8?
1870 d->control->resetCursorBlinkTimer();
1873 if (!d->control->hasSelectedText()) {
1874 if (d->lastSelectionStart != d->control->cursor()) {
1875 d->lastSelectionStart = d->control->cursor();
1876 emit selectionStartChanged();
1878 if (d->lastSelectionEnd != d->control->cursor()) {
1879 d->lastSelectionEnd = d->control->cursor();
1880 emit selectionEndChanged();
1885 void QQuickTextInput::updateCursorRectangle()
1887 Q_D(QQuickTextInput);
1888 d->determineHorizontalAlignment();
1889 d->updateHorizontalScroll();
1890 updateRect();//TODO: Only update rect between pos's
1892 emit cursorRectangleChanged();
1894 d->cursorItem->setX(d->control->cursorToX() - d->hscroll);
1897 void QQuickTextInput::selectionChanged()
1899 Q_D(QQuickTextInput);
1900 updateRect();//TODO: Only update rect in selection
1901 emit selectedTextChanged();
1903 if (d->lastSelectionStart != d->control->selectionStart()) {
1904 d->lastSelectionStart = d->control->selectionStart();
1905 if (d->lastSelectionStart == -1)
1906 d->lastSelectionStart = d->control->cursor();
1907 emit selectionStartChanged();
1909 if (d->lastSelectionEnd != d->control->selectionEnd()) {
1910 d->lastSelectionEnd = d->control->selectionEnd();
1911 if (d->lastSelectionEnd == -1)
1912 d->lastSelectionEnd = d->control->cursor();
1913 emit selectionEndChanged();
1917 void QQuickTextInput::q_textChanged()
1919 Q_D(QQuickTextInput);
1921 emit displayTextChanged();
1923 d->determineHorizontalAlignment();
1924 d->updateHorizontalScroll();
1926 if (hasAcceptableInput() != d->oldValidity) {
1927 d->oldValidity = hasAcceptableInput();
1928 emit acceptableInputChanged();
1932 void QQuickTextInputPrivate::showCursor()
1934 if (textNode != 0 && textNode->cursorNode() != 0)
1935 textNode->cursorNode()->setColor(color);
1938 void QQuickTextInputPrivate::hideCursor()
1940 if (textNode != 0 && textNode->cursorNode() != 0)
1941 textNode->cursorNode()->setColor(QColor(0, 0, 0, 0));
1944 void QQuickTextInput::updateRect(const QRect &r)
1946 Q_D(QQuickTextInput);
1947 if (!isComponentComplete())
1951 d->textLayoutDirty = true;
1957 QRectF QQuickTextInput::boundingRect() const
1959 Q_D(const QQuickTextInput);
1960 QRectF r = QQuickImplicitSizeItem::boundingRect();
1962 int cursorWidth = d->cursorItem ? d->cursorItem->width() : d->control->cursorWidth();
1964 // Could include font max left/right bearings to either side of rectangle.
1966 r.setRight(r.right() + cursorWidth);
1970 void QQuickTextInput::updateSize(bool needsRedraw)
1972 Q_D(QQuickTextInput);
1975 setImplicitHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
1976 setImplicitWidth(d->calculateTextWidth());
1977 if (w==width() && h==height() && needsRedraw)
1981 void QQuickTextInput::q_canPasteChanged()
1983 Q_D(QQuickTextInput);
1984 bool old = d->canPaste;
1985 #ifndef QT_NO_CLIPBOARD
1986 d->canPaste = !d->control->isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
1988 if (d->canPaste != old)
1989 emit canPasteChanged();