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 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include "private/qdeclarativetextinput_p.h"
43 #include "private/qdeclarativetextinput_p_p.h"
45 #include <private/qdeclarativeglobal_p.h>
46 #include <qdeclarativeinfo.h>
49 #include <QTextCursor>
50 #include <QApplication>
51 #include <QFontMetrics>
53 #include <QTextBoundaryFinder>
54 #include <QInputContext>
57 #ifndef QT_NO_LINEEDIT
62 \qmlclass TextInput QDeclarativeTextInput
63 \ingroup qml-basic-visual-elements
65 \brief The TextInput item displays an editable line of text.
68 The TextInput element displays a single line of editable plain text.
70 TextInput is used to accept a line of text input. Input constraints
71 can be placed on a TextInput item (for example, through a \l validator or \l inputMask),
72 and setting \l echoMode to an appropriate value enables TextInput to be used for
73 a password input field.
75 On Mac OS X, the Up/Down key bindings for Home/End are explicitly disabled.
76 If you want such bindings (on any platform), you will need to construct them in QML.
78 \sa TextEdit, Text, {declarative/text/textselection}{Text Selection example}
80 QDeclarativeTextInput::QDeclarativeTextInput(QDeclarativeItem* parent)
81 : QDeclarativeImplicitSizePaintedItem(*(new QDeclarativeTextInputPrivate), parent)
83 Q_D(QDeclarativeTextInput);
87 QDeclarativeTextInput::~QDeclarativeTextInput()
92 \qmlproperty string TextInput::text
94 The text in the TextInput.
97 QString QDeclarativeTextInput::text() const
99 Q_D(const QDeclarativeTextInput);
100 return d->control->text();
103 void QDeclarativeTextInput::setText(const QString &s)
105 Q_D(QDeclarativeTextInput);
108 d->control->setText(s);
112 \qmlproperty string 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 TextInput::font.bold
124 Sets whether the font weight is bold.
128 \qmlproperty enumeration 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 TextInput::font.italic
149 Sets whether the font has an italic style.
153 \qmlproperty bool TextInput::font.underline
155 Sets whether the text is underlined.
159 \qmlproperty bool TextInput::font.strikeout
161 Sets whether the font has a strikeout style.
165 \qmlproperty real TextInput::font.pointSize
167 Sets the font size in points. The point size must be greater than zero.
171 \qmlproperty int 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 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 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 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 QDeclarativeTextInput::font() const
218 Q_D(const QDeclarativeTextInput);
219 return d->sourceFont;
222 void QDeclarativeTextInput::setFont(const QFont &font)
224 Q_D(QDeclarativeTextInput);
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);
237 if (oldFont != d->font) {
238 d->control->setFont(d->font);
240 d->cursorItem->setHeight(QFontMetrics(d->font).height());
245 emit fontChanged(d->sourceFont);
249 \qmlproperty color TextInput::color
253 QColor QDeclarativeTextInput::color() const
255 Q_D(const QDeclarativeTextInput);
259 void QDeclarativeTextInput::setColor(const QColor &c)
261 Q_D(QDeclarativeTextInput);
266 emit colorChanged(c);
272 \qmlproperty color TextInput::selectionColor
274 The text highlight color, used behind selections.
276 QColor QDeclarativeTextInput::selectionColor() const
278 Q_D(const QDeclarativeTextInput);
279 return d->selectionColor;
282 void QDeclarativeTextInput::setSelectionColor(const QColor &color)
284 Q_D(QDeclarativeTextInput);
285 if (d->selectionColor == color)
288 d->selectionColor = color;
289 QPalette p = d->control->palette();
290 p.setColor(QPalette::Highlight, d->selectionColor);
291 d->control->setPalette(p);
292 if (d->control->hasSelectedText()) {
296 emit selectionColorChanged(color);
300 \qmlproperty color TextInput::selectedTextColor
302 The highlighted text color, used in selections.
304 QColor QDeclarativeTextInput::selectedTextColor() const
306 Q_D(const QDeclarativeTextInput);
307 return d->selectedTextColor;
310 void QDeclarativeTextInput::setSelectedTextColor(const QColor &color)
312 Q_D(QDeclarativeTextInput);
313 if (d->selectedTextColor == color)
316 d->selectedTextColor = color;
317 QPalette p = d->control->palette();
318 p.setColor(QPalette::HighlightedText, d->selectedTextColor);
319 d->control->setPalette(p);
320 if (d->control->hasSelectedText()) {
324 emit selectedTextColorChanged(color);
328 \qmlproperty enumeration TextInput::horizontalAlignment
329 \qmlproperty enumeration TextInput::effectiveHorizontalAlignment
331 Sets the horizontal alignment of the text within the TextInput item's
332 width and height. By default, the text alignment follows the natural alignment
333 of the text, for example text that is read from left to right will be aligned to
336 TextInput does not have vertical alignment, as the natural height is
337 exactly the height of the single line of text. If you set the height
338 manually to something larger, TextInput will always be top aligned
339 vertically. You can use anchors to align it however you want within
342 The valid values for \c horizontalAlignment are \c TextInput.AlignLeft, \c TextInput.AlignRight and
343 \c TextInput.AlignHCenter.
345 When using the attached property LayoutMirroring::enabled to mirror application
346 layouts, the horizontal alignment of text will also be mirrored. However, the property
347 \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
348 of TextInput, use the read-only property \c effectiveHorizontalAlignment.
350 QDeclarativeTextInput::HAlignment QDeclarativeTextInput::hAlign() const
352 Q_D(const QDeclarativeTextInput);
356 void QDeclarativeTextInput::setHAlign(HAlignment align)
358 Q_D(QDeclarativeTextInput);
359 bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror;
360 d->hAlignImplicit = false;
361 if (d->setHAlign(align, forceAlign) && isComponentComplete()) {
363 d->updateHorizontalScroll();
367 void QDeclarativeTextInput::resetHAlign()
369 Q_D(QDeclarativeTextInput);
370 d->hAlignImplicit = true;
371 if (d->determineHorizontalAlignment() && isComponentComplete()) {
373 d->updateHorizontalScroll();
377 QDeclarativeTextInput::HAlignment QDeclarativeTextInput::effectiveHAlign() const
379 Q_D(const QDeclarativeTextInput);
380 QDeclarativeTextInput::HAlignment effectiveAlignment = d->hAlign;
381 if (!d->hAlignImplicit && d->effectiveLayoutMirror) {
383 case QDeclarativeTextInput::AlignLeft:
384 effectiveAlignment = QDeclarativeTextInput::AlignRight;
386 case QDeclarativeTextInput::AlignRight:
387 effectiveAlignment = QDeclarativeTextInput::AlignLeft;
393 return effectiveAlignment;
396 bool QDeclarativeTextInputPrivate::setHAlign(QDeclarativeTextInput::HAlignment alignment, bool forceAlign)
398 Q_Q(QDeclarativeTextInput);
399 if ((hAlign != alignment || forceAlign) && alignment <= QDeclarativeTextInput::AlignHCenter) { // justify not supported
400 QDeclarativeTextInput::HAlignment oldEffectiveHAlign = q->effectiveHAlign();
402 emit q->horizontalAlignmentChanged(alignment);
403 if (oldEffectiveHAlign != q->effectiveHAlign())
404 emit q->effectiveHorizontalAlignmentChanged();
410 bool QDeclarativeTextInputPrivate::determineHorizontalAlignment()
412 if (hAlignImplicit) {
413 // if no explicit alignment has been set, follow the natural layout direction of the text
414 QString text = control->text();
415 bool isRightToLeft = text.isEmpty() ? QApplication::keyboardInputDirection() == Qt::RightToLeft : text.isRightToLeft();
416 return setHAlign(isRightToLeft ? QDeclarativeTextInput::AlignRight : QDeclarativeTextInput::AlignLeft);
421 void QDeclarativeTextInputPrivate::mirrorChange()
423 Q_Q(QDeclarativeTextInput);
424 if (q->isComponentComplete()) {
425 if (!hAlignImplicit && (hAlign == QDeclarativeTextInput::AlignRight || hAlign == QDeclarativeTextInput::AlignLeft)) {
427 updateHorizontalScroll();
428 emit q->effectiveHorizontalAlignmentChanged();
434 \qmlproperty bool TextInput::readOnly
436 Sets whether user input can modify the contents of the TextInput.
438 If readOnly is set to true, then user input will not affect the text
439 property. Any bindings or attempts to set the text property will still
443 bool QDeclarativeTextInput::isReadOnly() const
445 Q_D(const QDeclarativeTextInput);
446 return d->control->isReadOnly();
449 void QDeclarativeTextInput::setReadOnly(bool ro)
451 Q_D(QDeclarativeTextInput);
452 if (d->control->isReadOnly() == ro)
455 setFlag(QGraphicsItem::ItemAcceptsInputMethod, !ro);
456 d->control->setReadOnly(ro);
458 emit readOnlyChanged(ro);
462 \qmlproperty int TextInput::maximumLength
463 The maximum permitted length of the text in the TextInput.
465 If the text is too long, it is truncated at the limit.
467 By default, this property contains a value of 32767.
469 int QDeclarativeTextInput::maxLength() const
471 Q_D(const QDeclarativeTextInput);
472 return d->control->maxLength();
475 void QDeclarativeTextInput::setMaxLength(int ml)
477 Q_D(QDeclarativeTextInput);
478 if (d->control->maxLength() == ml)
481 d->control->setMaxLength(ml);
483 emit maximumLengthChanged(ml);
487 \qmlproperty bool TextInput::cursorVisible
488 Set to true when the TextInput shows a cursor.
490 This property is set and unset when the TextInput gets active focus, so that other
491 properties can be bound to whether the cursor is currently showing. As it
492 gets set and unset automatically, when you set the value yourself you must
493 keep in mind that your value may be overwritten.
495 It can be set directly in script, for example if a KeyProxy might
496 forward keys to it and you desire it to look active when this happens
497 (but without actually giving it active focus).
499 It should not be set directly on the element, like in the below QML,
500 as the specified value will be overridden an lost on focus changes.
509 In the above snippet the cursor will still become visible when the
510 TextInput gains active focus.
512 bool QDeclarativeTextInput::isCursorVisible() const
514 Q_D(const QDeclarativeTextInput);
515 return d->cursorVisible;
518 void QDeclarativeTextInput::setCursorVisible(bool on)
520 Q_D(QDeclarativeTextInput);
521 if (d->cursorVisible == on)
523 d->cursorVisible = on;
524 d->control->setCursorBlinkPeriod(on?QApplication::cursorFlashTime():0);
525 QRect r = d->control->cursorRect();
526 if (d->control->inputMask().isEmpty())
530 emit cursorVisibleChanged(d->cursorVisible);
534 \qmlproperty int TextInput::cursorPosition
535 The position of the cursor in the TextInput.
537 int QDeclarativeTextInput::cursorPosition() const
539 Q_D(const QDeclarativeTextInput);
540 return d->control->cursor();
542 void QDeclarativeTextInput::setCursorPosition(int cp)
544 Q_D(QDeclarativeTextInput);
545 if (cp < 0 || cp > d->control->text().length())
547 d->control->moveCursor(cp);
551 Returns a Rect which encompasses the cursor, but which may be larger than is
552 required. Ignores custom cursor delegates.
554 QRect QDeclarativeTextInput::cursorRectangle() const
556 Q_D(const QDeclarativeTextInput);
557 QRect r = d->control->cursorRect();
558 // Scroll and make consistent with TextEdit
559 // QLineControl inexplicably adds 1 to the height and horizontal padding
560 // for unicode direction markers.
561 r.adjust(5 - d->hscroll, 0, -4 - d->hscroll, -1);
566 \qmlproperty int TextInput::selectionStart
568 The cursor position before the first character in the current selection.
569 Setting this and selectionEnd allows you to specify a selection in the
572 Note that if selectionStart == selectionEnd then there is no current
575 \sa selectionEnd, cursorPosition, selectedText, select()
577 int QDeclarativeTextInput::selectionStart() const
579 Q_D(const QDeclarativeTextInput);
580 return d->lastSelectionStart;
584 \qmlproperty int TextInput::selectionEnd
586 The cursor position after the last character in the current selection.
587 Setting this and selectionStart allows you to specify a selection in the
590 Note that if selectionStart == selectionEnd then there is no current
593 \sa selectionStart, cursorPosition, selectedText, select()
595 int QDeclarativeTextInput::selectionEnd() const
597 Q_D(const QDeclarativeTextInput);
598 return d->lastSelectionEnd;
602 \qmlmethod void TextInput::select(int start, int end)
604 Causes the text from \a start to \a end to be selected.
606 If either start or end is out of range, the selection is not changed.
608 After calling this, selectionStart will become the lesser
609 and selectionEnd will become the greater (regardless of the order passed
612 \sa selectionStart, selectionEnd
614 void QDeclarativeTextInput::select(int start, int end)
616 Q_D(QDeclarativeTextInput);
617 if (start < 0 || end < 0 || start > d->control->text().length() || end > d->control->text().length())
619 d->control->setSelection(start, end-start);
623 \qmlproperty string TextInput::selectedText
625 This read-only property provides the text currently selected in the
628 It is equivalent to the following snippet, but is faster and easier
632 myTextInput.text.toString().substring(myTextInput.selectionStart,
633 myTextInput.selectionEnd);
636 QString QDeclarativeTextInput::selectedText() const
638 Q_D(const QDeclarativeTextInput);
639 return d->control->selectedText();
643 \qmlproperty bool TextInput::activeFocusOnPress
645 Whether the TextInput should gain active focus on a mouse press. By default this is
648 bool QDeclarativeTextInput::focusOnPress() const
650 Q_D(const QDeclarativeTextInput);
651 return d->focusOnPress;
654 void QDeclarativeTextInput::setFocusOnPress(bool b)
656 Q_D(QDeclarativeTextInput);
657 if (d->focusOnPress == b)
662 emit activeFocusOnPressChanged(d->focusOnPress);
666 \qmlproperty bool TextInput::autoScroll
668 Whether the TextInput should scroll when the text is longer than the width. By default this is
671 bool QDeclarativeTextInput::autoScroll() const
673 Q_D(const QDeclarativeTextInput);
674 return d->autoScroll;
677 void QDeclarativeTextInput::setAutoScroll(bool b)
679 Q_D(QDeclarativeTextInput);
680 if (d->autoScroll == b)
684 //We need to repaint so that the scrolling is taking into account.
686 d->updateHorizontalScroll();
687 emit autoScrollChanged(d->autoScroll);
691 \qmlclass IntValidator QIntValidator
692 \ingroup qml-basic-visual-elements
694 This element provides a validator for integer values.
696 IntValidator uses the \l {QLocale::setDefault()}{default locale} to interpret the number and
697 will accept locale specific digits, group separators, and positive and negative signs. In
698 addition, IntValidator is always guaranteed to accept a number formatted according to the "C"
702 \qmlproperty int IntValidator::top
704 This property holds the validator's highest acceptable value.
705 By default, this property's value is derived from the highest signed integer available (typically 2147483647).
708 \qmlproperty int IntValidator::bottom
710 This property holds the validator's lowest acceptable value.
711 By default, this property's value is derived from the lowest signed integer available (typically -2147483647).
715 \qmlclass DoubleValidator QDoubleValidator
716 \ingroup qml-basic-visual-elements
718 This element provides a validator for non-integer numbers.
722 \qmlproperty real DoubleValidator::top
724 This property holds the validator's maximum acceptable value.
725 By default, this property contains a value of infinity.
728 \qmlproperty real DoubleValidator::bottom
730 This property holds the validator's minimum acceptable value.
731 By default, this property contains a value of -infinity.
734 \qmlproperty int DoubleValidator::decimals
736 This property holds the validator's maximum number of digits after the decimal point.
737 By default, this property contains a value of 1000.
740 \qmlproperty enumeration DoubleValidator::notation
741 This property holds the notation of how a string can describe a number.
743 The possible values for this property are:
746 \o DoubleValidator.StandardNotation
747 \o DoubleValidator.ScientificNotation (default)
750 If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part (e.g. 1.5E-2).
754 \qmlclass RegExpValidator QRegExpValidator
755 \ingroup qml-basic-visual-elements
757 This element provides a validator, which counts as valid any string which
758 matches a specified regular expression.
761 \qmlproperty regExp RegExpValidator::regExp
763 This property holds the regular expression used for validation.
765 Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular expression
768 By default, this property contains a regular expression with the pattern .* that matches any string.
772 \qmlproperty Validator TextInput::validator
774 Allows you to set a validator on the TextInput. When a validator is set
775 the TextInput will only accept input which leaves the text property in
776 an acceptable or intermediate state. The accepted signal will only be sent
777 if the text is in an acceptable state when enter is pressed.
779 Currently supported validators are IntValidator, DoubleValidator and
780 RegExpValidator. An example of using validators is shown below, which allows
781 input of integers between 11 and 31 into the text input:
786 validator: IntValidator{bottom: 11; top: 31;}
791 \sa acceptableInput, inputMask
793 #ifndef QT_NO_VALIDATOR
794 QValidator* QDeclarativeTextInput::validator() const
796 Q_D(const QDeclarativeTextInput);
797 //###const cast isn't good, but needed for property system?
798 return const_cast<QValidator*>(d->control->validator());
801 void QDeclarativeTextInput::setValidator(QValidator* v)
803 Q_D(QDeclarativeTextInput);
804 if (d->control->validator() == v)
807 d->control->setValidator(v);
808 if(!d->control->hasAcceptableInput()){
809 d->oldValidity = false;
810 emit acceptableInputChanged();
813 emit validatorChanged();
815 #endif // QT_NO_VALIDATOR
818 \qmlproperty string TextInput::inputMask
820 Allows you to set an input mask on the TextInput, restricting the allowable
821 text inputs. See QLineEdit::inputMask for further details, as the exact
822 same mask strings are used by TextInput.
824 \sa acceptableInput, validator
826 QString QDeclarativeTextInput::inputMask() const
828 Q_D(const QDeclarativeTextInput);
829 return d->control->inputMask();
832 void QDeclarativeTextInput::setInputMask(const QString &im)
834 Q_D(QDeclarativeTextInput);
835 if (d->control->inputMask() == im)
838 d->control->setInputMask(im);
839 emit inputMaskChanged(d->control->inputMask());
843 \qmlproperty bool TextInput::acceptableInput
845 This property is always true unless a validator or input mask has been set.
846 If a validator or input mask has been set, this property will only be true
847 if the current text is acceptable to the validator or input mask as a final
848 string (not as an intermediate string).
850 bool QDeclarativeTextInput::hasAcceptableInput() const
852 Q_D(const QDeclarativeTextInput);
853 return d->control->hasAcceptableInput();
857 \qmlsignal TextInput::onAccepted()
859 This handler is called when the Return or Enter key is pressed.
860 Note that if there is a \l validator or \l inputMask set on the text
861 input, the handler will only be emitted if the input is in an acceptable
865 void QDeclarativeTextInputPrivate::updateInputMethodHints()
867 Q_Q(QDeclarativeTextInput);
868 Qt::InputMethodHints hints = inputMethodHints;
869 uint echo = control->echoMode();
870 if (echo == QDeclarativeTextInput::Password || echo == QDeclarativeTextInput::NoEcho)
871 hints |= Qt::ImhHiddenText;
872 else if (echo == QDeclarativeTextInput::PasswordEchoOnEdit)
873 hints &= ~Qt::ImhHiddenText;
874 if (echo != QDeclarativeTextInput::Normal)
875 hints |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
876 q->setInputMethodHints(hints);
880 \qmlproperty enumeration TextInput::echoMode
882 Specifies how the text should be displayed in the TextInput.
884 \o TextInput.Normal - Displays the text as it is. (Default)
885 \o TextInput.Password - Displays asterixes instead of characters.
886 \o TextInput.NoEcho - Displays nothing.
887 \o TextInput.PasswordEchoOnEdit - Displays all but the current character as asterixes.
890 QDeclarativeTextInput::EchoMode QDeclarativeTextInput::echoMode() const
892 Q_D(const QDeclarativeTextInput);
893 return (QDeclarativeTextInput::EchoMode)d->control->echoMode();
896 void QDeclarativeTextInput::setEchoMode(QDeclarativeTextInput::EchoMode echo)
898 Q_D(QDeclarativeTextInput);
899 if (echoMode() == echo)
901 d->control->setEchoMode((uint)echo);
902 d->updateInputMethodHints();
904 emit echoModeChanged(echoMode());
907 Qt::InputMethodHints QDeclarativeTextInput::imHints() const
909 Q_D(const QDeclarativeTextInput);
910 return d->inputMethodHints;
913 void QDeclarativeTextInput::setIMHints(Qt::InputMethodHints hints)
915 Q_D(QDeclarativeTextInput);
916 if (d->inputMethodHints == hints)
918 d->inputMethodHints = hints;
919 d->updateInputMethodHints();
923 \qmlproperty Component TextInput::cursorDelegate
924 The delegate for the cursor in the TextInput.
926 If you set a cursorDelegate for a TextInput, this delegate will be used for
927 drawing the cursor instead of the standard cursor. An instance of the
928 delegate will be created and managed by the TextInput when a cursor is
929 needed, and the x property of delegate instance will be set so as
930 to be one pixel before the top left of the current character.
932 Note that the root item of the delegate component must be a QDeclarativeItem or
933 QDeclarativeItem derived item.
935 QDeclarativeComponent* QDeclarativeTextInput::cursorDelegate() const
937 Q_D(const QDeclarativeTextInput);
938 return d->cursorComponent;
941 void QDeclarativeTextInput::setCursorDelegate(QDeclarativeComponent* c)
943 Q_D(QDeclarativeTextInput);
944 if (d->cursorComponent == c)
947 d->cursorComponent = c;
949 //note that the components are owned by something else
950 disconnect(d->control, SIGNAL(cursorPositionChanged(int,int)),
951 this, SLOT(moveCursor()));
952 disconnect(d->control, SIGNAL(updateMicroFocus()),
953 this, SLOT(moveCursor()));
954 delete d->cursorItem;
956 d->startCreatingCursor();
959 emit cursorDelegateChanged();
962 void QDeclarativeTextInputPrivate::startCreatingCursor()
964 Q_Q(QDeclarativeTextInput);
965 q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
966 q, SLOT(moveCursor()), Qt::UniqueConnection);
967 q->connect(control, SIGNAL(updateMicroFocus()),
968 q, SLOT(moveCursor()), Qt::UniqueConnection);
969 if(cursorComponent->isReady()){
971 }else if(cursorComponent->isLoading()){
972 q->connect(cursorComponent, SIGNAL(statusChanged(int)),
973 q, SLOT(createCursor()));
975 qmlInfo(q, cursorComponent->errors()) << QDeclarativeTextInput::tr("Could not load cursor delegate");
979 void QDeclarativeTextInput::createCursor()
981 Q_D(QDeclarativeTextInput);
982 if(d->cursorComponent->isError()){
983 qmlInfo(this, d->cursorComponent->errors()) << tr("Could not load cursor delegate");
987 if(!d->cursorComponent->isReady())
991 delete d->cursorItem;
992 d->cursorItem = qobject_cast<QDeclarativeItem*>(d->cursorComponent->create());
994 qmlInfo(this, d->cursorComponent->errors()) << tr("Could not instantiate cursor delegate");
998 QDeclarative_setParent_noEvent(d->cursorItem, this);
999 d->cursorItem->setParentItem(this);
1000 d->cursorItem->setX(d->control->cursorToX());
1001 d->cursorItem->setHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
1004 void QDeclarativeTextInput::moveCursor()
1006 Q_D(QDeclarativeTextInput);
1009 d->updateHorizontalScroll();
1010 d->cursorItem->setX(d->control->cursorToX() - d->hscroll);
1014 \qmlmethod rect TextInput::positionToRectangle(int pos)
1016 This function takes a character position and returns the rectangle that the
1017 cursor would occupy, if it was placed at that character position.
1019 This is similar to setting the cursorPosition, and then querying the cursor
1020 rectangle, but the cursorPosition is not changed.
1022 QRectF QDeclarativeTextInput::positionToRectangle(int pos) const
1024 Q_D(const QDeclarativeTextInput);
1025 if (pos > d->control->cursorPosition())
1026 pos += d->control->preeditAreaText().length();
1027 return QRectF(d->control->cursorToX(pos)-d->hscroll,
1029 d->control->cursorWidth(),
1030 cursorRectangle().height());
1033 int QDeclarativeTextInput::positionAt(int x) const
1035 return positionAt(x, CursorBetweenCharacters);
1039 \qmlmethod int TextInput::positionAt(int x, CursorPosition position = CursorBetweenCharacters)
1042 This function returns the character position at
1043 x pixels from the left of the textInput. Position 0 is before the
1044 first character, position 1 is after the first character but before the second,
1045 and so on until position text.length, which is after all characters.
1047 This means that for all x values before the first character this function returns 0,
1048 and for all x values after the last character this function returns text.length.
1050 The cursor position type specifies how the cursor position should be resolved.
1053 \o TextInput.CursorBetweenCharacters - Returns the position between characters that is nearest x.
1054 \o TextInput.CursorOnCharacter - Returns the position before the character that is nearest x.
1057 int QDeclarativeTextInput::positionAt(int x, CursorPosition position) const
1059 Q_D(const QDeclarativeTextInput);
1060 int pos = d->control->xToPos(x + d->hscroll, QTextLine::CursorPosition(position));
1061 const int cursor = d->control->cursor();
1063 const int preeditLength = d->control->preeditAreaText().length();
1064 pos = pos > cursor + preeditLength
1065 ? pos - preeditLength
1071 void QDeclarativeTextInputPrivate::focusChanged(bool hasFocus)
1073 Q_Q(QDeclarativeTextInput);
1075 q->setCursorVisible(hasFocus && scene && scene->hasFocus());
1076 if(q->echoMode() == QDeclarativeTextInput::PasswordEchoOnEdit && !hasFocus)
1077 control->updatePasswordEchoEditing(false);//QLineControl sets it on key events, but doesn't deal with focus events
1079 control->deselect();
1080 QDeclarativeItemPrivate::focusChanged(hasFocus);
1083 void QDeclarativeTextInput::keyPressEvent(QKeyEvent* ev)
1085 Q_D(QDeclarativeTextInput);
1086 keyPressPreHandler(ev);
1087 if (ev->isAccepted())
1090 // Don't allow MacOSX up/down support, and we don't allow a completer.
1091 bool ignore = (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) && ev->modifiers() == Qt::NoModifier;
1092 if (!ignore && (d->lastSelectionStart == d->lastSelectionEnd) && (ev->key() == Qt::Key_Right || ev->key() == Qt::Key_Left)) {
1093 // Ignore when moving off the end unless there is a selection,
1094 // because then moving will do something (deselect).
1095 int cursorPosition = d->control->cursor();
1096 if (cursorPosition == 0)
1097 ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Left : Qt::Key_Right);
1098 if (cursorPosition == d->control->text().length())
1099 ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Right : Qt::Key_Left);
1104 d->control->processKeyEvent(ev);
1106 if (!ev->isAccepted())
1107 QDeclarativePaintedItem::keyPressEvent(ev);
1110 void QDeclarativeTextInput::inputMethodEvent(QInputMethodEvent *ev)
1112 Q_D(QDeclarativeTextInput);
1114 const bool wasComposing = d->control->preeditAreaText().length() > 0;
1115 inputMethodPreHandler(ev);
1116 if (!ev->isAccepted()) {
1117 if (d->control->isReadOnly()) {
1120 d->control->processInputMethodEvent(ev);
1122 d->updateHorizontalScroll();
1125 if (!ev->isAccepted())
1126 QDeclarativePaintedItem::inputMethodEvent(ev);
1128 if (wasComposing != (d->control->preeditAreaText().length() > 0))
1129 emit inputMethodComposingChanged();
1134 Handles the given mouse \a event.
1136 void QDeclarativeTextInput::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
1138 Q_D(QDeclarativeTextInput);
1139 if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonDblClick))
1141 if (d->selectByMouse) {
1142 int cursor = d->xToPos(event->pos().x());
1143 d->control->selectWordAtPos(cursor);
1144 event->setAccepted(true);
1146 QDeclarativePaintedItem::mouseDoubleClickEvent(event);
1150 void QDeclarativeTextInput::mousePressEvent(QGraphicsSceneMouseEvent *event)
1152 Q_D(QDeclarativeTextInput);
1153 if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonPress))
1155 if(d->focusOnPress){
1156 bool hadActiveFocus = hasActiveFocus();
1158 if (d->showInputPanelOnFocus) {
1159 if (hasActiveFocus() && hadActiveFocus && !isReadOnly()) {
1160 // re-open input panel on press if already focused
1161 openSoftwareInputPanel();
1163 } else { // show input panel on click
1164 if (hasActiveFocus() && !hadActiveFocus) {
1165 d->clickCausedFocus = true;
1169 if (d->selectByMouse) {
1170 setKeepMouseGrab(false);
1171 d->selectPressed = true;
1172 d->pressPos = event->pos();
1174 bool mark = (event->modifiers() & Qt::ShiftModifier) && d->selectByMouse;
1175 int cursor = d->xToPos(event->pos().x());
1176 d->control->moveCursor(cursor, mark);
1177 event->setAccepted(true);
1180 void QDeclarativeTextInput::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
1182 Q_D(QDeclarativeTextInput);
1183 if (d->sendMouseEventToInputContext(event, QEvent::MouseMove))
1185 if (d->selectPressed) {
1186 if (qAbs(int(event->pos().x() - d->pressPos.x())) > QApplication::startDragDistance())
1187 setKeepMouseGrab(true);
1188 moveCursorSelection(d->xToPos(event->pos().x()), d->mouseSelectionMode);
1189 event->setAccepted(true);
1191 QDeclarativePaintedItem::mouseMoveEvent(event);
1197 Handles the given mouse \a event.
1199 void QDeclarativeTextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
1201 Q_D(QDeclarativeTextInput);
1202 if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonRelease))
1204 if (d->selectPressed) {
1205 d->selectPressed = false;
1206 setKeepMouseGrab(false);
1208 if (!d->showInputPanelOnFocus) { // input panel on click
1209 if (d->focusOnPress && !isReadOnly() && boundingRect().contains(event->pos())) {
1210 if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1211 if (view->scene() && view->scene() == scene()) {
1212 qt_widget_private(view)->handleSoftwareInputPanel(event->button(), d->clickCausedFocus);
1217 d->clickCausedFocus = false;
1218 d->control->processEvent(event);
1219 if (!event->isAccepted())
1220 QDeclarativePaintedItem::mouseReleaseEvent(event);
1223 bool QDeclarativeTextInputPrivate::sendMouseEventToInputContext(
1224 QGraphicsSceneMouseEvent *event, QEvent::Type eventType)
1226 #if !defined QT_NO_IM
1227 if (event->widget() && control->composeMode()) {
1228 int tmp_cursor = xToPos(event->pos().x());
1229 int mousePos = tmp_cursor - control->cursor();
1230 if (mousePos < 0 || mousePos > control->preeditAreaText().length()) {
1232 // don't send move events outside the preedit area
1233 if (eventType == QEvent::MouseMove)
1237 QInputContext *qic = event->widget()->inputContext();
1239 QMouseEvent mouseEvent(
1241 event->widget()->mapFromGlobal(event->screenPos()),
1245 event->modifiers());
1246 // may be causing reset() in some input methods
1247 qic->mouseHandler(mousePos, &mouseEvent);
1248 event->setAccepted(mouseEvent.isAccepted());
1250 if (!control->preeditAreaText().isEmpty())
1261 bool QDeclarativeTextInput::sceneEvent(QEvent *event)
1263 Q_D(QDeclarativeTextInput);
1264 bool rv = QDeclarativeItem::sceneEvent(event);
1265 if (event->type() == QEvent::UngrabMouse) {
1266 d->selectPressed = false;
1267 setKeepMouseGrab(false);
1272 bool QDeclarativeTextInput::event(QEvent* ev)
1274 Q_D(QDeclarativeTextInput);
1275 //Anything we don't deal with ourselves, pass to the control
1276 bool handled = false;
1278 case QEvent::KeyPress:
1279 case QEvent::KeyRelease://###Should the control be doing anything with release?
1280 case QEvent::InputMethod:
1281 case QEvent::GraphicsSceneMousePress:
1282 case QEvent::GraphicsSceneMouseMove:
1283 case QEvent::GraphicsSceneMouseRelease:
1284 case QEvent::GraphicsSceneMouseDoubleClick:
1287 handled = d->control->processEvent(ev);
1290 handled = QDeclarativePaintedItem::event(ev);
1294 void QDeclarativeTextInput::geometryChanged(const QRectF &newGeometry,
1295 const QRectF &oldGeometry)
1297 Q_D(QDeclarativeTextInput);
1298 if (newGeometry.width() != oldGeometry.width()) {
1300 d->updateHorizontalScroll();
1302 QDeclarativePaintedItem::geometryChanged(newGeometry, oldGeometry);
1305 int QDeclarativeTextInputPrivate::calculateTextWidth()
1307 return qRound(control->naturalTextWidth());
1310 void QDeclarativeTextInputPrivate::updateHorizontalScroll()
1312 Q_Q(QDeclarativeTextInput);
1313 const int preeditLength = control->preeditAreaText().length();
1314 int cix = qRound(control->cursorToX(control->cursor() + preeditLength));
1315 QRect br(q->boundingRect().toRect());
1316 int widthUsed = calculateTextWidth();
1318 QDeclarativeTextInput::HAlignment effectiveHAlign = q->effectiveHAlign();
1320 if (widthUsed <= br.width()) {
1321 // text fits in br; use hscroll for alignment
1322 switch (effectiveHAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) {
1323 case Qt::AlignRight:
1324 hscroll = widthUsed - br.width() - 1;
1326 case Qt::AlignHCenter:
1327 hscroll = (widthUsed - br.width()) / 2;
1334 } else if (cix - hscroll >= br.width()) {
1335 // text doesn't fit, cursor is to the right of br (scroll right)
1336 hscroll = cix - br.width() + 1;
1337 } else if (cix - hscroll < 0 && hscroll < widthUsed) {
1338 // text doesn't fit, cursor is to the left of br (scroll left)
1340 } else if (widthUsed - hscroll < br.width()) {
1341 // text doesn't fit, text document is to the left of br; align
1343 hscroll = widthUsed - br.width() + 1;
1345 if (preeditLength > 0) {
1346 // check to ensure long pre-edit text doesn't push the cursor
1348 cix = qRound(control->cursorToX(
1349 control->cursor() + qMax(0, control->preeditCursor() - 1)));
1354 switch (effectiveHAlign) {
1355 case QDeclarativeTextInput::AlignRight:
1356 hscroll = q->width() - widthUsed;
1358 case QDeclarativeTextInput::AlignHCenter:
1359 hscroll = (q->width() - widthUsed) / 2;
1369 void QDeclarativeTextInput::drawContents(QPainter *p, const QRect &r)
1371 Q_D(QDeclarativeTextInput);
1372 p->setRenderHint(QPainter::TextAntialiasing, true);
1374 p->setPen(QPen(d->color));
1375 int flags = QLineControl::DrawText;
1376 if(!isReadOnly() && d->cursorVisible && !d->cursorItem)
1377 flags |= QLineControl::DrawCursor;
1378 if (d->control->hasSelectedText())
1379 flags |= QLineControl::DrawSelections;
1380 QPoint offset = QPoint(0,0);
1381 QFontMetrics fm = QFontMetrics(d->font);
1382 QRect br(boundingRect().toRect());
1383 if (d->autoScroll) {
1384 // the y offset is there to keep the baseline constant in case we have script changes in the text.
1385 offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent());
1387 offset = QPoint(d->hscroll, 0);
1389 d->control->draw(p, offset, r, flags);
1395 Returns the value of the given \a property.
1397 QVariant QDeclarativeTextInput::inputMethodQuery(Qt::InputMethodQuery property) const
1399 Q_D(const QDeclarativeTextInput);
1401 case Qt::ImMicroFocus:
1402 return cursorRectangle();
1405 case Qt::ImCursorPosition:
1406 return QVariant(d->control->cursor());
1407 case Qt::ImSurroundingText:
1408 if (d->control->echoMode() == PasswordEchoOnEdit && !d->control->passwordEchoEditing())
1409 return QVariant(displayText());
1411 return QVariant(text());
1412 case Qt::ImCurrentSelection:
1413 return QVariant(selectedText());
1414 case Qt::ImMaximumTextLength:
1415 return QVariant(maxLength());
1416 case Qt::ImAnchorPosition:
1417 if (d->control->selectionStart() == d->control->selectionEnd())
1418 return QVariant(d->control->cursor());
1419 else if (d->control->selectionStart() == d->control->cursor())
1420 return QVariant(d->control->selectionEnd());
1422 return QVariant(d->control->selectionStart());
1429 \qmlmethod void TextInput::deselect()
1432 Removes active text selection.
1434 void QDeclarativeTextInput::deselect()
1436 Q_D(QDeclarativeTextInput);
1437 d->control->deselect();
1441 \qmlmethod void TextInput::selectAll()
1443 Causes all text to be selected.
1445 void QDeclarativeTextInput::selectAll()
1447 Q_D(QDeclarativeTextInput);
1448 d->control->setSelection(0, d->control->text().length());
1452 \qmlmethod void TextInput::isRightToLeft(int start, int end)
1454 Returns true if the natural reading direction of the editor text
1455 found between positions \a start and \a end is right to left.
1457 bool QDeclarativeTextInput::isRightToLeft(int start, int end)
1459 Q_D(QDeclarativeTextInput);
1461 qmlInfo(this) << "isRightToLeft(start, end) called with the end property being smaller than the start.";
1464 return d->control->text().mid(start, end - start).isRightToLeft();
1468 #ifndef QT_NO_CLIPBOARD
1470 \qmlmethod TextInput::cut()
1472 Moves the currently selected text to the system clipboard.
1474 void QDeclarativeTextInput::cut()
1476 Q_D(QDeclarativeTextInput);
1482 \qmlmethod TextInput::copy()
1484 Copies the currently selected text to the system clipboard.
1486 void QDeclarativeTextInput::copy()
1488 Q_D(QDeclarativeTextInput);
1493 \qmlmethod TextInput::paste()
1495 Replaces the currently selected text by the contents of the system clipboard.
1497 void QDeclarativeTextInput::paste()
1499 Q_D(QDeclarativeTextInput);
1500 if(!d->control->isReadOnly())
1501 d->control->paste();
1503 #endif // QT_NO_CLIPBOARD
1506 \qmlmethod void TextInput::selectWord()
1508 Causes the word closest to the current cursor position to be selected.
1510 void QDeclarativeTextInput::selectWord()
1512 Q_D(QDeclarativeTextInput);
1513 d->control->selectWordAtPos(d->control->cursor());
1517 \qmlproperty bool TextInput::smooth
1519 This property holds whether the text is smoothly scaled or transformed.
1521 Smooth filtering gives better visual quality, but is slower. If
1522 the item is displayed at its natural size, this property has no visual or
1525 \note Generally scaling artifacts are only visible if the item is stationary on
1526 the screen. A common pattern when animating an item is to disable smooth
1527 filtering at the beginning of the animation and reenable it at the conclusion.
1531 \qmlproperty string TextInput::passwordCharacter
1533 This is the character displayed when echoMode is set to Password or
1534 PasswordEchoOnEdit. By default it is an asterisk.
1536 If this property is set to a string with more than one character,
1537 the first character is used. If the string is empty, the value
1538 is ignored and the property is not set.
1540 QString QDeclarativeTextInput::passwordCharacter() const
1542 Q_D(const QDeclarativeTextInput);
1543 return QString(d->control->passwordCharacter());
1546 void QDeclarativeTextInput::setPasswordCharacter(const QString &str)
1548 Q_D(QDeclarativeTextInput);
1549 if(str.length() < 1)
1551 d->control->setPasswordCharacter(str.constData()[0]);
1552 EchoMode echoMode_ = echoMode();
1553 if (echoMode_ == Password || echoMode_ == PasswordEchoOnEdit) {
1556 emit passwordCharacterChanged();
1560 \qmlproperty string TextInput::displayText
1562 This is the text displayed in the TextInput.
1564 If \l echoMode is set to TextInput::Normal, this holds the
1565 same value as the TextInput::text property. Otherwise,
1566 this property holds the text visible to the user, while
1567 the \l text property holds the actual entered text.
1569 QString QDeclarativeTextInput::displayText() const
1571 Q_D(const QDeclarativeTextInput);
1572 return d->control->displayText();
1576 \qmlproperty bool TextInput::selectByMouse
1580 If true, the user can use the mouse to select text in some
1581 platform-specific way. Note that for some platforms this may
1582 not be an appropriate interaction (eg. may conflict with how
1583 the text needs to behave inside a Flickable.
1585 bool QDeclarativeTextInput::selectByMouse() const
1587 Q_D(const QDeclarativeTextInput);
1588 return d->selectByMouse;
1591 void QDeclarativeTextInput::setSelectByMouse(bool on)
1593 Q_D(QDeclarativeTextInput);
1594 if (d->selectByMouse != on) {
1595 d->selectByMouse = on;
1596 emit selectByMouseChanged(on);
1601 \qmlproperty enum TextInput::mouseSelectionMode
1604 Specifies how text should be selected using a mouse.
1607 \o TextInput.SelectCharacters - The selection is updated with individual characters. (Default)
1608 \o TextInput.SelectWords - The selection is updated with whole words.
1611 This property only applies when \l selectByMouse is true.
1614 QDeclarativeTextInput::SelectionMode QDeclarativeTextInput::mouseSelectionMode() const
1616 Q_D(const QDeclarativeTextInput);
1617 return d->mouseSelectionMode;
1620 void QDeclarativeTextInput::setMouseSelectionMode(SelectionMode mode)
1622 Q_D(QDeclarativeTextInput);
1623 if (d->mouseSelectionMode != mode) {
1624 d->mouseSelectionMode = mode;
1625 emit mouseSelectionModeChanged(mode);
1630 \qmlproperty bool TextInput::canPaste
1633 Returns true if the TextInput is writable and the content of the clipboard is
1634 suitable for pasting into the TextEdit.
1636 bool QDeclarativeTextInput::canPaste() const
1638 Q_D(const QDeclarativeTextInput);
1642 void QDeclarativeTextInput::moveCursorSelection(int position)
1644 Q_D(QDeclarativeTextInput);
1645 d->control->moveCursor(position, true);
1646 d->updateHorizontalScroll();
1650 \qmlmethod void TextInput::moveCursorSelection(int position, SelectionMode mode = TextInput.SelectCharacters)
1653 Moves the cursor to \a position and updates the selection according to the optional \a mode
1654 parameter. (To only move the cursor, set the \l cursorPosition property.)
1656 When this method is called it additionally sets either the
1657 selectionStart or the selectionEnd (whichever was at the previous cursor position)
1658 to the specified position. This allows you to easily extend and contract the selected
1661 The selection mode specifies whether the selection is updated on a per character or a per word
1662 basis. If not specified the selection mode will default to TextInput.SelectCharacters.
1665 \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
1666 the previous cursor position) to the specified position.
1667 \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all
1668 words between the specified postion and the previous cursor position. Words partially in the
1672 For example, take this sequence of calls:
1676 moveCursorSelection(9, TextInput.SelectCharacters)
1677 moveCursorSelection(7, TextInput.SelectCharacters)
1680 This moves the cursor to position 5, extend the selection end from 5 to 9
1681 and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
1682 selected (the 6th and 7th characters).
1684 The same sequence with TextInput.SelectWords will extend the selection start to a word boundary
1685 before or on position 5 and extend the selection end to a word boundary on or past position 9.
1687 void QDeclarativeTextInput::moveCursorSelection(int pos, SelectionMode mode)
1689 Q_D(QDeclarativeTextInput);
1691 if (mode == SelectCharacters) {
1692 d->control->moveCursor(pos, true);
1693 } else if (pos != d->control->cursor()){
1694 const int cursor = d->control->cursor();
1696 if (!d->control->hasSelectedText())
1697 anchor = d->control->cursor();
1698 else if (d->control->selectionStart() == d->control->cursor())
1699 anchor = d->control->selectionEnd();
1701 anchor = d->control->selectionStart();
1703 if (anchor < pos || (anchor == pos && cursor < pos)) {
1704 const QString text = d->control->text();
1705 QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
1706 finder.setPosition(anchor);
1708 const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
1709 if (anchor < text.length() && (!(reasons & QTextBoundaryFinder::StartWord)
1710 || ((reasons & QTextBoundaryFinder::EndWord) && anchor > cursor))) {
1711 finder.toPreviousBoundary();
1713 anchor = finder.position() != -1 ? finder.position() : 0;
1715 finder.setPosition(pos);
1716 if (pos > 0 && !finder.boundaryReasons())
1717 finder.toNextBoundary();
1718 const int cursor = finder.position() != -1 ? finder.position() : text.length();
1720 d->control->setSelection(anchor, cursor - anchor);
1721 } else if (anchor > pos || (anchor == pos && cursor > pos)) {
1722 const QString text = d->control->text();
1723 QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
1724 finder.setPosition(anchor);
1726 const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
1727 if (anchor > 0 && (!(reasons & QTextBoundaryFinder::EndWord)
1728 || ((reasons & QTextBoundaryFinder::StartWord) && anchor < cursor))) {
1729 finder.toNextBoundary();
1731 anchor = finder.position() != -1 ? finder.position() : text.length();
1733 finder.setPosition(pos);
1734 if (pos < text.length() && !finder.boundaryReasons())
1735 finder.toPreviousBoundary();
1736 const int cursor = finder.position() != -1 ? finder.position() : 0;
1738 d->control->setSelection(anchor, cursor - anchor);
1744 \qmlmethod void TextInput::openSoftwareInputPanel()
1746 Opens software input panels like virtual keyboards for typing, useful for
1747 customizing when you want the input keyboard to be shown and hidden in
1750 By default the opening of input panels follows the platform style. On Symbian^1 and
1751 Symbian^3 -based devices the panels are opened by clicking TextInput. On other platforms
1752 the panels are automatically opened when TextInput element gains active focus. Input panels are
1753 always closed if no editor has active focus.
1755 . You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1756 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1757 the behavior you want.
1759 Only relevant on platforms, which provide virtual keyboards.
1765 text: "Hello world!"
1766 activeFocusOnPress: false
1768 anchors.fill: parent
1770 if (!textInput.activeFocus) {
1771 textInput.forceActiveFocus()
1772 textInput.openSoftwareInputPanel();
1774 textInput.focus = false;
1777 onPressAndHold: textInput.closeSoftwareInputPanel();
1782 void QDeclarativeTextInput::openSoftwareInputPanel()
1784 QEvent event(QEvent::RequestSoftwareInputPanel);
1786 if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1787 if (view->scene() && view->scene() == scene()) {
1788 QApplication::sendEvent(view, &event);
1795 \qmlmethod void TextInput::closeSoftwareInputPanel()
1797 Closes a software input panel like a virtual keyboard shown on the screen, useful
1798 for customizing when you want the input keyboard to be shown and hidden in
1801 By default the opening of input panels follows the platform style. On Symbian^1 and
1802 Symbian^3 -based devices the panels are opened by clicking TextInput. On other platforms
1803 the panels are automatically opened when TextInput element gains active focus. Input panels are
1804 always closed if no editor has active focus.
1806 . You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1807 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1808 the behavior you want.
1810 Only relevant on platforms, which provide virtual keyboards.
1816 text: "Hello world!"
1817 activeFocusOnPress: false
1819 anchors.fill: parent
1821 if (!textInput.activeFocus) {
1822 textInput.forceActiveFocus();
1823 textInput.openSoftwareInputPanel();
1825 textInput.focus = false;
1828 onPressAndHold: textInput.closeSoftwareInputPanel();
1833 void QDeclarativeTextInput::closeSoftwareInputPanel()
1835 QEvent event(QEvent::CloseSoftwareInputPanel);
1837 QEvent event(QEvent::CloseSoftwareInputPanel);
1838 if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1839 if (view->scene() && view->scene() == scene()) {
1840 QApplication::sendEvent(view, &event);
1846 void QDeclarativeTextInput::focusInEvent(QFocusEvent *event)
1848 Q_D(const QDeclarativeTextInput);
1849 if (d->showInputPanelOnFocus) {
1850 if (d->focusOnPress && !isReadOnly()) {
1851 openSoftwareInputPanel();
1854 QDeclarativePaintedItem::focusInEvent(event);
1858 \qmlproperty bool TextInput::inputMethodComposing
1862 This property holds whether the TextInput has partial text input from an
1865 While it is composing an input method may rely on mouse or key events from
1866 the TextInput to edit or commit the partial text. This property can be
1867 used to determine when to disable events handlers that may interfere with
1868 the correct operation of an input method.
1870 bool QDeclarativeTextInput::isInputMethodComposing() const
1872 Q_D(const QDeclarativeTextInput);
1873 return d->control->preeditAreaText().length() > 0;
1876 void QDeclarativeTextInputPrivate::init()
1878 Q_Q(QDeclarativeTextInput);
1879 control->setCursorWidth(1);
1880 control->setPasswordCharacter(QLatin1Char('*'));
1881 q->setSmooth(smooth);
1882 q->setAcceptedMouseButtons(Qt::LeftButton);
1883 q->setFlag(QGraphicsItem::ItemHasNoContents, false);
1884 q->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
1885 q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
1886 q, SLOT(cursorPosChanged()));
1887 q->connect(control, SIGNAL(selectionChanged()),
1888 q, SLOT(selectionChanged()));
1889 q->connect(control, SIGNAL(textChanged(QString)),
1890 q, SLOT(q_textChanged()));
1891 q->connect(control, SIGNAL(accepted()),
1892 q, SIGNAL(accepted()));
1893 q->connect(control, SIGNAL(updateNeeded(QRect)),
1894 q, SLOT(updateRect(QRect)));
1895 #ifndef QT_NO_CLIPBOARD
1896 q->connect(q, SIGNAL(readOnlyChanged(bool)),
1897 q, SLOT(q_canPasteChanged()));
1898 q->connect(QApplication::clipboard(), SIGNAL(dataChanged()),
1899 q, SLOT(q_canPasteChanged()));
1900 canPaste = !control->isReadOnly() && QApplication::clipboard()->text().length() != 0;
1901 #endif // QT_NO_CLIPBOARD
1902 q->connect(control, SIGNAL(updateMicroFocus()),
1903 q, SLOT(updateMicroFocus()));
1904 q->connect(control, SIGNAL(displayTextChanged(QString)),
1905 q, SLOT(updateRect()));
1907 oldValidity = control->hasAcceptableInput();
1908 lastSelectionStart = 0;
1909 lastSelectionEnd = 0;
1910 QPalette p = control->palette();
1911 selectedTextColor = p.color(QPalette::HighlightedText);
1912 selectionColor = p.color(QPalette::Highlight);
1913 determineHorizontalAlignment();
1916 void QDeclarativeTextInput::cursorPosChanged()
1918 Q_D(QDeclarativeTextInput);
1919 d->updateHorizontalScroll();
1920 updateRect();//TODO: Only update rect between pos's
1922 emit cursorPositionChanged();
1923 d->control->resetCursorBlinkTimer();
1925 if(!d->control->hasSelectedText()){
1926 if(d->lastSelectionStart != d->control->cursor()){
1927 d->lastSelectionStart = d->control->cursor();
1928 emit selectionStartChanged();
1930 if(d->lastSelectionEnd != d->control->cursor()){
1931 d->lastSelectionEnd = d->control->cursor();
1932 emit selectionEndChanged();
1937 void QDeclarativeTextInput::selectionChanged()
1939 Q_D(QDeclarativeTextInput);
1940 updateRect();//TODO: Only update rect in selection
1941 emit selectedTextChanged();
1943 if(d->lastSelectionStart != d->control->selectionStart()){
1944 d->lastSelectionStart = d->control->selectionStart();
1945 if(d->lastSelectionStart == -1)
1946 d->lastSelectionStart = d->control->cursor();
1947 emit selectionStartChanged();
1949 if(d->lastSelectionEnd != d->control->selectionEnd()){
1950 d->lastSelectionEnd = d->control->selectionEnd();
1951 if(d->lastSelectionEnd == -1)
1952 d->lastSelectionEnd = d->control->cursor();
1953 emit selectionEndChanged();
1957 void QDeclarativeTextInput::q_textChanged()
1959 Q_D(QDeclarativeTextInput);
1961 d->determineHorizontalAlignment();
1962 d->updateHorizontalScroll();
1965 emit displayTextChanged();
1966 if(hasAcceptableInput() != d->oldValidity){
1967 d->oldValidity = hasAcceptableInput();
1968 emit acceptableInputChanged();
1972 void QDeclarativeTextInput::updateRect(const QRect &r)
1974 Q_D(QDeclarativeTextInput);
1978 dirtyCache(QRect(r.x() - d->hscroll, r.y(), r.width(), r.height()));
1982 QRectF QDeclarativeTextInput::boundingRect() const
1984 Q_D(const QDeclarativeTextInput);
1985 QRectF r = QDeclarativePaintedItem::boundingRect();
1987 int cursorWidth = d->cursorItem ? d->cursorItem->width() : d->control->cursorWidth();
1989 // Could include font max left/right bearings to either side of rectangle.
1991 r.setRight(r.right() + cursorWidth);
1995 void QDeclarativeTextInput::updateSize(bool needsRedraw)
1997 Q_D(QDeclarativeTextInput);
2000 setImplicitHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
2001 setImplicitWidth(d->calculateTextWidth());
2002 setContentsSize(QSize(width(), height()));//Repaints if changed
2003 if(w==width() && h==height() && needsRedraw){
2009 void QDeclarativeTextInput::q_canPasteChanged()
2011 Q_D(QDeclarativeTextInput);
2012 bool old = d->canPaste;
2013 #ifndef QT_NO_CLIPBOARD
2014 d->canPaste = !d->control->isReadOnly() && QApplication::clipboard()->text().length() != 0;
2016 if(d->canPaste != old)
2017 emit canPasteChanged();
2022 #endif // QT_NO_LINEEDIT