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 asterixes 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::KeyRelease) {
1166 int tmp_cursor = xToPos(event->localPos().x());
1167 int mousePos = tmp_cursor - control->cursor();
1168 if (mousePos < 0 || mousePos > control->preeditAreaText().length()) {
1170 // don't send move events outside the preedit area
1171 if (event->type() == QEvent::MouseMove)
1175 // may be causing reset() in some input methods
1176 qApp->inputPanel()->invokeAction(QInputPanel::Click, mousePos);
1177 if (!control->preeditAreaText().isEmpty())
1188 void QQuickTextInput::mouseUngrabEvent()
1190 Q_D(QQuickTextInput);
1191 d->selectPressed = false;
1192 setKeepMouseGrab(false);
1195 bool QQuickTextInput::event(QEvent* ev)
1197 Q_D(QQuickTextInput);
1198 //Anything we don't deal with ourselves, pass to the control
1199 bool handled = false;
1200 switch (ev->type()) {
1201 case QEvent::KeyPress:
1202 case QEvent::KeyRelease://###Should the control be doing anything with release?
1203 case QEvent::InputMethod:
1204 case QEvent::MouseButtonPress:
1205 case QEvent::MouseMove:
1206 case QEvent::MouseButtonRelease:
1207 case QEvent::MouseButtonDblClick:
1210 handled = d->control->processEvent(ev);
1213 handled = QQuickImplicitSizeItem::event(ev);
1217 void QQuickTextInput::geometryChanged(const QRectF &newGeometry,
1218 const QRectF &oldGeometry)
1220 if (newGeometry.width() != oldGeometry.width()) {
1222 updateCursorRectangle();
1224 QQuickImplicitSizeItem::geometryChanged(newGeometry, oldGeometry);
1227 int QQuickTextInputPrivate::calculateTextWidth()
1229 return qRound(control->naturalTextWidth());
1232 void QQuickTextInputPrivate::updateHorizontalScroll()
1234 Q_Q(QQuickTextInput);
1235 const int preeditLength = control->preeditAreaText().length();
1236 const int width = q->width();
1237 int widthUsed = calculateTextWidth();
1239 if (!autoScroll || widthUsed <= width) {
1240 QQuickTextInput::HAlignment effectiveHAlign = q->effectiveHAlign();
1241 // text fits in br; use hscroll for alignment
1242 switch (effectiveHAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) {
1243 case Qt::AlignRight:
1244 hscroll = widthUsed - width;
1246 case Qt::AlignHCenter:
1247 hscroll = (widthUsed - width) / 2;
1255 int cix = qRound(control->cursorToX(control->cursor() + preeditLength));
1256 if (cix - hscroll >= width) {
1257 // text doesn't fit, cursor is to the right of br (scroll right)
1258 hscroll = cix - width;
1259 } else if (cix - hscroll < 0 && hscroll < widthUsed) {
1260 // text doesn't fit, cursor is to the left of br (scroll left)
1262 } else if (widthUsed - hscroll < width) {
1263 // text doesn't fit, text document is to the left of br; align
1265 hscroll = widthUsed - width;
1267 if (preeditLength > 0) {
1268 // check to ensure long pre-edit text doesn't push the cursor
1270 cix = qRound(control->cursorToX(
1271 control->cursor() + qMax(0, control->preeditCursor() - 1)));
1278 QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
1281 Q_D(QQuickTextInput);
1283 QQuickTextNode *node = static_cast<QQuickTextNode *>(oldNode);
1285 node = new QQuickTextNode(QQuickItemPrivate::get(this)->sceneGraphContext());
1288 if (!d->textLayoutDirty) {
1289 QSGSimpleRectNode *cursorNode = node->cursorNode();
1290 if (cursorNode != 0 && !isReadOnly()) {
1291 QFontMetrics fm = QFontMetrics(d->font);
1292 // the y offset is there to keep the baseline constant in case we have script changes in the text.
1293 QPoint offset(-d->hscroll, fm.ascent() - d->control->ascent());
1294 offset.rx() += d->control->cursorToX();
1296 QRect br(boundingRect().toRect());
1297 cursorNode->setRect(QRectF(offset, QSizeF(d->control->cursorWidth(), br.height())));
1299 if (!d->cursorVisible
1300 || (!d->control->cursorBlinkStatus() && d->control->cursorBlinkPeriod() > 0)) {
1307 node->deleteContent();
1308 node->setMatrix(QMatrix4x4());
1310 QPoint offset = QPoint(0,0);
1311 QFontMetrics fm = QFontMetrics(d->font);
1312 QRect br(boundingRect().toRect());
1313 if (d->autoScroll) {
1314 // the y offset is there to keep the baseline constant in case we have script changes in the text.
1315 offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent());
1317 offset = QPoint(d->hscroll, 0);
1320 QTextLayout *textLayout = d->control->textLayout();
1321 if (!textLayout->text().isEmpty()) {
1322 node->addTextLayout(offset, textLayout, d->color,
1323 QQuickText::Normal, QColor(),
1324 d->selectionColor, d->selectedTextColor,
1325 d->control->selectionStart(),
1326 d->control->selectionEnd() - 1); // selectionEnd() returns first char after
1330 if (!isReadOnly() && d->cursorItem == 0) {
1331 offset.rx() += d->control->cursorToX();
1332 node->setCursor(QRectF(offset, QSizeF(d->control->cursorWidth(), br.height())), d->color);
1333 if (!d->cursorVisible
1334 || (!d->control->cursorBlinkStatus() && d->control->cursorBlinkPeriod() > 0)) {
1341 d->textLayoutDirty = false;
1347 QVariant QQuickTextInput::inputMethodQuery(Qt::InputMethodQuery property) const
1349 Q_D(const QQuickTextInput);
1352 return QVariant((bool)(flags() & ItemAcceptsInputMethod));
1354 return QVariant((int)inputMethodHints());
1355 case Qt::ImCursorRectangle:
1356 return cursorRectangle();
1359 case Qt::ImCursorPosition:
1360 return QVariant(d->control->cursor());
1361 case Qt::ImSurroundingText:
1362 if (d->control->echoMode() == QLineControl::PasswordEchoOnEdit
1363 && !d->control->passwordEchoEditing()) {
1364 return QVariant(displayText());
1366 return QVariant(text());
1368 case Qt::ImCurrentSelection:
1369 return QVariant(selectedText());
1370 case Qt::ImMaximumTextLength:
1371 return QVariant(maxLength());
1372 case Qt::ImAnchorPosition:
1373 if (d->control->selectionStart() == d->control->selectionEnd())
1374 return QVariant(d->control->cursor());
1375 else if (d->control->selectionStart() == d->control->cursor())
1376 return QVariant(d->control->selectionEnd());
1378 return QVariant(d->control->selectionStart());
1385 \qmlmethod void QtQuick2::TextInput::deselect()
1387 Removes active text selection.
1389 void QQuickTextInput::deselect()
1391 Q_D(QQuickTextInput);
1392 d->control->deselect();
1396 \qmlmethod void QtQuick2::TextInput::selectAll()
1398 Causes all text to be selected.
1400 void QQuickTextInput::selectAll()
1402 Q_D(QQuickTextInput);
1403 d->control->setSelection(0, d->control->text().length());
1407 \qmlmethod void QtQuick2::TextInput::isRightToLeft(int start, int end)
1409 Returns true if the natural reading direction of the editor text
1410 found between positions \a start and \a end is right to left.
1412 bool QQuickTextInput::isRightToLeft(int start, int end)
1414 Q_D(QQuickTextInput);
1416 qmlInfo(this) << "isRightToLeft(start, end) called with the end property being smaller than the start.";
1419 return d->control->text().mid(start, end - start).isRightToLeft();
1423 #ifndef QT_NO_CLIPBOARD
1425 \qmlmethod QtQuick2::TextInput::cut()
1427 Moves the currently selected text to the system clipboard.
1429 void QQuickTextInput::cut()
1431 Q_D(QQuickTextInput);
1437 \qmlmethod QtQuick2::TextInput::copy()
1439 Copies the currently selected text to the system clipboard.
1441 void QQuickTextInput::copy()
1443 Q_D(QQuickTextInput);
1448 \qmlmethod QtQuick2::TextInput::paste()
1450 Replaces the currently selected text by the contents of the system clipboard.
1452 void QQuickTextInput::paste()
1454 Q_D(QQuickTextInput);
1455 if (!d->control->isReadOnly())
1456 d->control->paste();
1458 #endif // QT_NO_CLIPBOARD
1461 \qmlmethod void QtQuick2::TextInput::selectWord()
1463 Causes the word closest to the current cursor position to be selected.
1465 void QQuickTextInput::selectWord()
1467 Q_D(QQuickTextInput);
1468 d->control->selectWordAtPos(d->control->cursor());
1472 \qmlproperty bool QtQuick2::TextInput::smooth
1474 This property holds whether the text is smoothly scaled or transformed.
1476 Smooth filtering gives better visual quality, but is slower. If
1477 the item is displayed at its natural size, this property has no visual or
1480 \note Generally scaling artifacts are only visible if the item is stationary on
1481 the screen. A common pattern when animating an item is to disable smooth
1482 filtering at the beginning of the animation and reenable it at the conclusion.
1486 \qmlproperty string QtQuick2::TextInput::passwordCharacter
1488 This is the character displayed when echoMode is set to Password or
1489 PasswordEchoOnEdit. By default it is an asterisk.
1491 If this property is set to a string with more than one character,
1492 the first character is used. If the string is empty, the value
1493 is ignored and the property is not set.
1495 QString QQuickTextInput::passwordCharacter() const
1497 Q_D(const QQuickTextInput);
1498 return QString(d->control->passwordCharacter());
1501 void QQuickTextInput::setPasswordCharacter(const QString &str)
1503 Q_D(QQuickTextInput);
1504 if (str.length() < 1)
1506 d->control->setPasswordCharacter(str.constData()[0]);
1507 EchoMode echoMode_ = echoMode();
1508 if (echoMode_ == Password || echoMode_ == PasswordEchoOnEdit) {
1511 emit passwordCharacterChanged();
1515 \qmlproperty string QtQuick2::TextInput::displayText
1517 This is the text displayed in the TextInput.
1519 If \l echoMode is set to TextInput::Normal, this holds the
1520 same value as the TextInput::text property. Otherwise,
1521 this property holds the text visible to the user, while
1522 the \l text property holds the actual entered text.
1524 QString QQuickTextInput::displayText() const
1526 Q_D(const QQuickTextInput);
1527 return d->control->displayText();
1531 \qmlproperty bool QtQuick2::TextInput::selectByMouse
1535 If true, the user can use the mouse to select text in some
1536 platform-specific way. Note that for some platforms this may
1537 not be an appropriate interaction (eg. may conflict with how
1538 the text needs to behave inside a Flickable.
1540 bool QQuickTextInput::selectByMouse() const
1542 Q_D(const QQuickTextInput);
1543 return d->selectByMouse;
1546 void QQuickTextInput::setSelectByMouse(bool on)
1548 Q_D(QQuickTextInput);
1549 if (d->selectByMouse != on) {
1550 d->selectByMouse = on;
1551 emit selectByMouseChanged(on);
1556 \qmlproperty enum QtQuick2::TextInput::mouseSelectionMode
1558 Specifies how text should be selected using a mouse.
1561 \o TextInput.SelectCharacters - The selection is updated with individual characters. (Default)
1562 \o TextInput.SelectWords - The selection is updated with whole words.
1565 This property only applies when \l selectByMouse is true.
1568 QQuickTextInput::SelectionMode QQuickTextInput::mouseSelectionMode() const
1570 Q_D(const QQuickTextInput);
1571 return d->mouseSelectionMode;
1574 void QQuickTextInput::setMouseSelectionMode(SelectionMode mode)
1576 Q_D(QQuickTextInput);
1577 if (d->mouseSelectionMode != mode) {
1578 d->mouseSelectionMode = mode;
1579 emit mouseSelectionModeChanged(mode);
1584 \qmlproperty bool QtQuick2::TextInput::canPaste
1586 Returns true if the TextInput is writable and the content of the clipboard is
1587 suitable for pasting into the TextEdit.
1589 bool QQuickTextInput::canPaste() const
1591 Q_D(const QQuickTextInput);
1595 void QQuickTextInput::moveCursorSelection(int position)
1597 Q_D(QQuickTextInput);
1598 d->control->moveCursor(position, true);
1602 \qmlmethod void QtQuick2::TextInput::moveCursorSelection(int position, SelectionMode mode = TextInput.SelectCharacters)
1604 Moves the cursor to \a position and updates the selection according to the optional \a mode
1605 parameter. (To only move the cursor, set the \l cursorPosition property.)
1607 When this method is called it additionally sets either the
1608 selectionStart or the selectionEnd (whichever was at the previous cursor position)
1609 to the specified position. This allows you to easily extend and contract the selected
1612 The selection mode specifies whether the selection is updated on a per character or a per word
1613 basis. If not specified the selection mode will default to TextInput.SelectCharacters.
1616 \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
1617 the previous cursor position) to the specified position.
1618 \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all
1619 words between the specified postion and the previous cursor position. Words partially in the
1623 For example, take this sequence of calls:
1627 moveCursorSelection(9, TextInput.SelectCharacters)
1628 moveCursorSelection(7, TextInput.SelectCharacters)
1631 This moves the cursor to position 5, extend the selection end from 5 to 9
1632 and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
1633 selected (the 6th and 7th characters).
1635 The same sequence with TextInput.SelectWords will extend the selection start to a word boundary
1636 before or on position 5 and extend the selection end to a word boundary on or past position 9.
1638 void QQuickTextInput::moveCursorSelection(int pos, SelectionMode mode)
1640 Q_D(QQuickTextInput);
1642 if (mode == SelectCharacters) {
1643 d->control->moveCursor(pos, true);
1644 } else if (pos != d->control->cursor()){
1645 const int cursor = d->control->cursor();
1647 if (!d->control->hasSelectedText())
1648 anchor = d->control->cursor();
1649 else if (d->control->selectionStart() == d->control->cursor())
1650 anchor = d->control->selectionEnd();
1652 anchor = d->control->selectionStart();
1654 if (anchor < pos || (anchor == pos && cursor < pos)) {
1655 const QString text = d->control->text();
1656 QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
1657 finder.setPosition(anchor);
1659 const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
1660 if (anchor < text.length() && (!(reasons & QTextBoundaryFinder::StartWord)
1661 || ((reasons & QTextBoundaryFinder::EndWord) && anchor > cursor))) {
1662 finder.toPreviousBoundary();
1664 anchor = finder.position() != -1 ? finder.position() : 0;
1666 finder.setPosition(pos);
1667 if (pos > 0 && !finder.boundaryReasons())
1668 finder.toNextBoundary();
1669 const int cursor = finder.position() != -1 ? finder.position() : text.length();
1671 d->control->setSelection(anchor, cursor - anchor);
1672 } else if (anchor > pos || (anchor == pos && cursor > pos)) {
1673 const QString text = d->control->text();
1674 QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
1675 finder.setPosition(anchor);
1677 const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
1678 if (anchor > 0 && (!(reasons & QTextBoundaryFinder::EndWord)
1679 || ((reasons & QTextBoundaryFinder::StartWord) && anchor < cursor))) {
1680 finder.toNextBoundary();
1683 anchor = finder.position() != -1 ? finder.position() : text.length();
1685 finder.setPosition(pos);
1686 if (pos < text.length() && !finder.boundaryReasons())
1687 finder.toPreviousBoundary();
1688 const int cursor = finder.position() != -1 ? finder.position() : 0;
1690 d->control->setSelection(anchor, cursor - anchor);
1696 \qmlmethod void QtQuick2::TextInput::openSoftwareInputPanel()
1698 Opens software input panels like virtual keyboards for typing, useful for
1699 customizing when you want the input keyboard to be shown and hidden in
1702 By default the opening of input panels follows the platform style. On Symbian^1 and
1703 Symbian^3 -based devices the panels are opened by clicking TextInput. On other platforms
1704 the panels are automatically opened when TextInput element gains active focus. Input panels are
1705 always closed if no editor has active focus.
1707 . You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1708 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1709 the behavior you want.
1711 Only relevant on platforms, which provide virtual keyboards.
1717 text: "Hello world!"
1718 activeFocusOnPress: false
1720 anchors.fill: parent
1722 if (!textInput.activeFocus) {
1723 textInput.forceActiveFocus()
1724 textInput.openSoftwareInputPanel();
1726 textInput.focus = false;
1729 onPressAndHold: textInput.closeSoftwareInputPanel();
1734 void QQuickTextInput::openSoftwareInputPanel()
1737 qGuiApp->inputPanel()->show();
1741 \qmlmethod void QtQuick2::TextInput::closeSoftwareInputPanel()
1743 Closes a software input panel like a virtual keyboard shown on the screen, useful
1744 for customizing when you want the input keyboard to be shown and hidden in
1747 By default the opening of input panels follows the platform style. On Symbian^1 and
1748 Symbian^3 -based devices the panels are opened by clicking TextInput. On other platforms
1749 the panels are automatically opened when TextInput element gains active focus. Input panels are
1750 always closed if no editor has active focus.
1752 . You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1753 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1754 the behavior you want.
1756 Only relevant on platforms, which provide virtual keyboards.
1762 text: "Hello world!"
1763 activeFocusOnPress: false
1765 anchors.fill: parent
1767 if (!textInput.activeFocus) {
1768 textInput.forceActiveFocus();
1769 textInput.openSoftwareInputPanel();
1771 textInput.focus = false;
1774 onPressAndHold: textInput.closeSoftwareInputPanel();
1779 void QQuickTextInput::closeSoftwareInputPanel()
1782 qGuiApp->inputPanel()->hide();
1785 void QQuickTextInput::focusInEvent(QFocusEvent *event)
1787 Q_D(const QQuickTextInput);
1788 if (d->focusOnPress && !isReadOnly())
1789 openSoftwareInputPanel();
1790 QQuickImplicitSizeItem::focusInEvent(event);
1793 void QQuickTextInput::itemChange(ItemChange change, const ItemChangeData &value)
1795 Q_D(QQuickTextInput);
1796 if (change == ItemActiveFocusHasChanged) {
1797 bool hasFocus = value.boolValue;
1798 d->focused = hasFocus;
1799 setCursorVisible(hasFocus); // ### refactor: && d->canvas && d->canvas->hasFocus()
1800 if (echoMode() == QQuickTextInput::PasswordEchoOnEdit && !hasFocus)
1801 d->control->updatePasswordEchoEditing(false);//QLineControl sets it on key events, but doesn't deal with focus events
1803 d->control->deselect();
1805 QQuickItem::itemChange(change, value);
1809 \qmlproperty bool QtQuick2::TextInput::inputMethodComposing
1812 This property holds whether the TextInput has partial text input from an
1815 While it is composing an input method may rely on mouse or key events from
1816 the TextInput to edit or commit the partial text. This property can be
1817 used to determine when to disable events handlers that may interfere with
1818 the correct operation of an input method.
1820 bool QQuickTextInput::isInputMethodComposing() const
1822 Q_D(const QQuickTextInput);
1823 return d->control->preeditAreaText().length() > 0;
1826 void QQuickTextInputPrivate::init()
1828 Q_Q(QQuickTextInput);
1829 #if defined(Q_WS_MAC)
1830 control->setThreadChecks(true);
1832 control->setParent(q);//Now mandatory due to accessibility changes
1833 control->setCursorWidth(1);
1834 control->setPasswordCharacter(QLatin1Char('*'));
1835 q->setSmooth(smooth);
1836 q->setAcceptedMouseButtons(Qt::LeftButton);
1837 q->setFlag(QQuickItem::ItemAcceptsInputMethod);
1838 q->setFlag(QQuickItem::ItemHasContents);
1839 q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
1840 q, SLOT(cursorPosChanged()));
1841 q->connect(control, SIGNAL(selectionChanged()),
1842 q, SLOT(selectionChanged()));
1843 q->connect(control, SIGNAL(textChanged(QString)),
1844 q, SLOT(q_textChanged()));
1845 q->connect(control, SIGNAL(accepted()),
1846 q, SIGNAL(accepted()));
1847 q->connect(control, SIGNAL(updateNeeded(QRect)),
1848 q, SLOT(updateRect(QRect)));
1849 #ifndef QT_NO_CLIPBOARD
1850 q->connect(q, SIGNAL(readOnlyChanged(bool)),
1851 q, SLOT(q_canPasteChanged()));
1852 q->connect(QGuiApplication::clipboard(), SIGNAL(dataChanged()),
1853 q, SLOT(q_canPasteChanged()));
1854 canPaste = !control->isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
1855 #endif // QT_NO_CLIPBOARD
1856 q->connect(control, SIGNAL(updateMicroFocus()),
1857 q, SLOT(updateCursorRectangle()));
1858 q->connect(control, SIGNAL(displayTextChanged(QString)),
1859 q, SLOT(updateRect()));
1861 imHints &= ~Qt::ImhMultiLine;
1862 oldValidity = control->hasAcceptableInput();
1863 lastSelectionStart = 0;
1864 lastSelectionEnd = 0;
1865 QPalette p = control->palette();
1866 selectedTextColor = p.color(QPalette::HighlightedText);
1867 selectionColor = p.color(QPalette::Highlight);
1868 determineHorizontalAlignment();
1870 if (!qmlDisableDistanceField()) {
1871 QTextOption option = control->textLayout()->textOption();
1872 option.setUseDesignMetrics(true);
1873 control->textLayout()->setTextOption(option);
1877 void QQuickTextInput::cursorPosChanged()
1879 Q_D(QQuickTextInput);
1880 updateCursorRectangle();
1881 emit cursorPositionChanged();
1882 // XXX todo - not in 4.8?
1884 d->control->resetCursorBlinkTimer();
1887 if (!d->control->hasSelectedText()) {
1888 if (d->lastSelectionStart != d->control->cursor()) {
1889 d->lastSelectionStart = d->control->cursor();
1890 emit selectionStartChanged();
1892 if (d->lastSelectionEnd != d->control->cursor()) {
1893 d->lastSelectionEnd = d->control->cursor();
1894 emit selectionEndChanged();
1899 void QQuickTextInput::updateCursorRectangle()
1901 Q_D(QQuickTextInput);
1902 d->determineHorizontalAlignment();
1903 d->updateHorizontalScroll();
1904 updateRect();//TODO: Only update rect between pos's
1906 emit cursorRectangleChanged();
1908 d->cursorItem->setX(d->control->cursorToX() - d->hscroll);
1911 void QQuickTextInput::selectionChanged()
1913 Q_D(QQuickTextInput);
1914 updateRect();//TODO: Only update rect in selection
1915 emit selectedTextChanged();
1917 if (d->lastSelectionStart != d->control->selectionStart()) {
1918 d->lastSelectionStart = d->control->selectionStart();
1919 if (d->lastSelectionStart == -1)
1920 d->lastSelectionStart = d->control->cursor();
1921 emit selectionStartChanged();
1923 if (d->lastSelectionEnd != d->control->selectionEnd()) {
1924 d->lastSelectionEnd = d->control->selectionEnd();
1925 if (d->lastSelectionEnd == -1)
1926 d->lastSelectionEnd = d->control->cursor();
1927 emit selectionEndChanged();
1931 void QQuickTextInput::q_textChanged()
1933 Q_D(QQuickTextInput);
1935 emit displayTextChanged();
1937 d->determineHorizontalAlignment();
1938 d->updateHorizontalScroll();
1940 if (hasAcceptableInput() != d->oldValidity) {
1941 d->oldValidity = hasAcceptableInput();
1942 emit acceptableInputChanged();
1946 void QQuickTextInputPrivate::showCursor()
1948 if (textNode != 0 && textNode->cursorNode() != 0)
1949 textNode->cursorNode()->setColor(color);
1952 void QQuickTextInputPrivate::hideCursor()
1954 if (textNode != 0 && textNode->cursorNode() != 0)
1955 textNode->cursorNode()->setColor(QColor(0, 0, 0, 0));
1958 void QQuickTextInput::updateRect(const QRect &r)
1960 Q_D(QQuickTextInput);
1961 if (!isComponentComplete())
1965 d->textLayoutDirty = true;
1971 QRectF QQuickTextInput::boundingRect() const
1973 Q_D(const QQuickTextInput);
1974 QRectF r = QQuickImplicitSizeItem::boundingRect();
1976 int cursorWidth = d->cursorItem ? d->cursorItem->width() : d->control->cursorWidth();
1978 // Could include font max left/right bearings to either side of rectangle.
1980 r.setRight(r.right() + cursorWidth);
1984 void QQuickTextInput::updateSize(bool needsRedraw)
1986 Q_D(QQuickTextInput);
1989 setImplicitHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
1990 setImplicitWidth(d->calculateTextWidth());
1991 if (w==width() && h==height() && needsRedraw)
1995 void QQuickTextInput::q_canPasteChanged()
1997 Q_D(QQuickTextInput);
1998 bool old = d->canPaste;
1999 #ifndef QT_NO_CLIPBOARD
2000 d->canPaste = !d->control->isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
2002 if (d->canPaste != old)
2003 emit canPasteChanged();