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 "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
64 \qmlclass TextInput QDeclarative1TextInput
65 \inqmlmodule QtQuick 1
66 \ingroup qml-basic-visual-elements
68 \brief The TextInput item displays an editable line of text.
71 The TextInput element displays a single line of editable plain text.
73 TextInput is used to accept a line of text input. Input constraints
74 can be placed on a TextInput item (for example, through a \l validator or \l inputMask),
75 and setting \l echoMode to an appropriate value enables TextInput to be used for
76 a password input field.
78 On Mac OS X, the Up/Down key bindings for Home/End are explicitly disabled.
79 If you want such bindings (on any platform), you will need to construct them in QML.
81 \sa TextEdit, Text, {declarative/text/textselection}{Text Selection example}
83 QDeclarative1TextInput::QDeclarative1TextInput(QDeclarativeItem* parent)
84 : QDeclarative1ImplicitSizePaintedItem(*(new QDeclarative1TextInputPrivate), parent)
86 Q_D(QDeclarative1TextInput);
90 QDeclarative1TextInput::~QDeclarative1TextInput()
95 \qmlproperty string QtQuick1::TextInput::text
97 The text in the TextInput.
100 QString QDeclarative1TextInput::text() const
102 Q_D(const QDeclarative1TextInput);
103 return d->control->text();
106 void QDeclarative1TextInput::setText(const QString &s)
108 Q_D(QDeclarative1TextInput);
111 d->control->setText(s);
115 \qmlproperty string QtQuick1::TextInput::font.family
117 Sets the family name of the font.
119 The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]".
120 If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen.
121 If the family isn't available a family will be set using the font matching algorithm.
125 \qmlproperty bool QtQuick1::TextInput::font.bold
127 Sets whether the font weight is bold.
131 \qmlproperty enumeration QtQuick1::TextInput::font.weight
133 Sets the font's weight.
135 The weight can be one of:
138 \o Font.Normal - the default
145 TextInput { text: "Hello"; font.weight: Font.DemiBold }
150 \qmlproperty bool QtQuick1::TextInput::font.italic
152 Sets whether the font has an italic style.
156 \qmlproperty bool QtQuick1::TextInput::font.underline
158 Sets whether the text is underlined.
162 \qmlproperty bool QtQuick1::TextInput::font.strikeout
164 Sets whether the font has a strikeout style.
168 \qmlproperty real QtQuick1::TextInput::font.pointSize
170 Sets the font size in points. The point size must be greater than zero.
174 \qmlproperty int QtQuick1::TextInput::font.pixelSize
176 Sets the font size in pixels.
178 Using this function makes the font device dependent.
179 Use \c pointSize to set the size of the font in a device independent manner.
183 \qmlproperty real QtQuick1::TextInput::font.letterSpacing
185 Sets the letter spacing for the font.
187 Letter spacing changes the default spacing between individual letters in the font.
188 A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing.
192 \qmlproperty real QtQuick1::TextInput::font.wordSpacing
194 Sets the word spacing for the font.
196 Word spacing changes the default spacing between individual words.
197 A positive value increases the word spacing by a corresponding amount of pixels,
198 while a negative value decreases the inter-word spacing accordingly.
202 \qmlproperty enumeration QtQuick1::TextInput::font.capitalization
204 Sets the capitalization for the text.
207 \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied.
208 \o Font.AllUppercase - This alters the text to be rendered in all uppercase type.
209 \o Font.AllLowercase - This alters the text to be rendered in all lowercase type.
210 \o Font.SmallCaps - This alters the text to be rendered in small-caps type.
211 \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character.
215 TextInput { text: "Hello"; font.capitalization: Font.AllLowercase }
219 QFont QDeclarative1TextInput::font() const
221 Q_D(const QDeclarative1TextInput);
222 return d->sourceFont;
225 void QDeclarative1TextInput::setFont(const QFont &font)
227 Q_D(QDeclarative1TextInput);
228 if (d->sourceFont == font)
231 d->sourceFont = font;
232 QFont oldFont = d->font;
234 if (d->font.pointSizeF() != -1) {
236 qreal size = qRound(d->font.pointSizeF()*2.0);
237 d->font.setPointSizeF(size/2.0);
240 if (oldFont != d->font) {
241 d->control->setFont(d->font);
243 updateCursorRectangle();
245 d->cursorItem->setHeight(QFontMetrics(d->font).height());
248 emit fontChanged(d->sourceFont);
252 \qmlproperty color QtQuick1::TextInput::color
256 QColor QDeclarative1TextInput::color() const
258 Q_D(const QDeclarative1TextInput);
262 void QDeclarative1TextInput::setColor(const QColor &c)
264 Q_D(QDeclarative1TextInput);
269 emit colorChanged(c);
275 \qmlproperty color QtQuick1::TextInput::selectionColor
277 The text highlight color, used behind selections.
279 QColor QDeclarative1TextInput::selectionColor() const
281 Q_D(const QDeclarative1TextInput);
282 return d->selectionColor;
285 void QDeclarative1TextInput::setSelectionColor(const QColor &color)
287 Q_D(QDeclarative1TextInput);
288 if (d->selectionColor == color)
291 d->selectionColor = color;
292 QPalette p = d->control->palette();
293 p.setColor(QPalette::Highlight, d->selectionColor);
294 d->control->setPalette(p);
295 if (d->control->hasSelectedText()) {
299 emit selectionColorChanged(color);
303 \qmlproperty color QtQuick1::TextInput::selectedTextColor
305 The highlighted text color, used in selections.
307 QColor QDeclarative1TextInput::selectedTextColor() const
309 Q_D(const QDeclarative1TextInput);
310 return d->selectedTextColor;
313 void QDeclarative1TextInput::setSelectedTextColor(const QColor &color)
315 Q_D(QDeclarative1TextInput);
316 if (d->selectedTextColor == color)
319 d->selectedTextColor = color;
320 QPalette p = d->control->palette();
321 p.setColor(QPalette::HighlightedText, d->selectedTextColor);
322 d->control->setPalette(p);
323 if (d->control->hasSelectedText()) {
327 emit selectedTextColorChanged(color);
331 \qmlproperty enumeration QtQuick1::TextInput::horizontalAlignment
332 \qmlproperty enumeration QtQuick1::TextInput::effectiveHorizontalAlignment
334 Sets the horizontal alignment of the text within the TextInput item's
335 width and height. By default, the text alignment follows the natural alignment
336 of the text, for example text that is read from left to right will be aligned to
339 TextInput does not have vertical alignment, as the natural height is
340 exactly the height of the single line of text. If you set the height
341 manually to something larger, TextInput will always be top aligned
342 vertically. You can use anchors to align it however you want within
345 The valid values for \c horizontalAlignment are \c TextInput.AlignLeft, \c TextInput.AlignRight and
346 \c TextInput.AlignHCenter.
348 When using the attached property LayoutMirroring::enabled to mirror application
349 layouts, the horizontal alignment of text will also be mirrored. However, the property
350 \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
351 of TextInput, use the read-only property \c effectiveHorizontalAlignment.
353 QDeclarative1TextInput::HAlignment QDeclarative1TextInput::hAlign() const
355 Q_D(const QDeclarative1TextInput);
359 void QDeclarative1TextInput::setHAlign(HAlignment align)
361 Q_D(QDeclarative1TextInput);
362 bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror;
363 d->hAlignImplicit = false;
364 if (d->setHAlign(align, forceAlign) && isComponentComplete()) {
365 updateCursorRectangle();
369 void QDeclarative1TextInput::resetHAlign()
371 Q_D(QDeclarative1TextInput);
372 d->hAlignImplicit = true;
373 if (d->determineHorizontalAlignment() && isComponentComplete()) {
374 updateCursorRectangle();
378 QDeclarative1TextInput::HAlignment QDeclarative1TextInput::effectiveHAlign() const
380 Q_D(const QDeclarative1TextInput);
381 QDeclarative1TextInput::HAlignment effectiveAlignment = d->hAlign;
382 if (!d->hAlignImplicit && d->effectiveLayoutMirror) {
384 case QDeclarative1TextInput::AlignLeft:
385 effectiveAlignment = QDeclarative1TextInput::AlignRight;
387 case QDeclarative1TextInput::AlignRight:
388 effectiveAlignment = QDeclarative1TextInput::AlignLeft;
394 return effectiveAlignment;
397 bool QDeclarative1TextInputPrivate::setHAlign(QDeclarative1TextInput::HAlignment alignment, bool forceAlign)
399 Q_Q(QDeclarative1TextInput);
400 if ((hAlign != alignment || forceAlign) && alignment <= QDeclarative1TextInput::AlignHCenter) { // justify not supported
401 QDeclarative1TextInput::HAlignment oldEffectiveHAlign = q->effectiveHAlign();
403 emit q->horizontalAlignmentChanged(alignment);
404 if (oldEffectiveHAlign != q->effectiveHAlign())
405 emit q->effectiveHorizontalAlignmentChanged();
411 bool QDeclarative1TextInputPrivate::determineHorizontalAlignment()
413 if (hAlignImplicit) {
414 // if no explicit alignment has been set, follow the natural layout direction of the text
415 QString text = control->text();
416 bool isRightToLeft = text.isEmpty() ? QApplication::keyboardInputDirection() == Qt::RightToLeft : text.isRightToLeft();
417 return setHAlign(isRightToLeft ? QDeclarative1TextInput::AlignRight : QDeclarative1TextInput::AlignLeft);
422 void QDeclarative1TextInputPrivate::mirrorChange()
424 Q_Q(QDeclarative1TextInput);
425 if (q->isComponentComplete()) {
426 if (!hAlignImplicit && (hAlign == QDeclarative1TextInput::AlignRight || hAlign == QDeclarative1TextInput::AlignLeft)) {
427 q->updateCursorRectangle();
428 emit q->effectiveHorizontalAlignmentChanged();
434 \qmlproperty bool QtQuick1::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 QDeclarative1TextInput::isReadOnly() const
445 Q_D(const QDeclarative1TextInput);
446 return d->control->isReadOnly();
449 void QDeclarative1TextInput::setReadOnly(bool ro)
451 Q_D(QDeclarative1TextInput);
452 if (d->control->isReadOnly() == ro)
455 setFlag(QGraphicsItem::ItemAcceptsInputMethod, !ro);
456 d->control->setReadOnly(ro);
458 emit readOnlyChanged(ro);
462 \qmlproperty int QtQuick1::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 QDeclarative1TextInput::maxLength() const
471 Q_D(const QDeclarative1TextInput);
472 return d->control->maxLength();
475 void QDeclarative1TextInput::setMaxLength(int ml)
477 Q_D(QDeclarative1TextInput);
478 if (d->control->maxLength() == ml)
481 d->control->setMaxLength(ml);
483 emit maximumLengthChanged(ml);
487 \qmlproperty bool QtQuick1::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 QDeclarative1TextInput::isCursorVisible() const
514 Q_D(const QDeclarative1TextInput);
515 return d->cursorVisible;
518 void QDeclarative1TextInput::setCursorVisible(bool on)
520 Q_D(QDeclarative1TextInput);
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 QtQuick1::TextInput::cursorPosition
535 The position of the cursor in the TextInput.
537 int QDeclarative1TextInput::cursorPosition() const
539 Q_D(const QDeclarative1TextInput);
540 return d->control->cursor();
542 void QDeclarative1TextInput::setCursorPosition(int cp)
544 Q_D(QDeclarative1TextInput);
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 QDeclarative1TextInput::cursorRectangle() const
556 Q_D(const QDeclarative1TextInput);
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 QtQuick1::TextInput::selectionStart
568 The cursor position before the first character in the current selection.
570 This property is read-only. To change the selection, use select(start,end),
571 selectAll(), or selectWord().
573 \sa selectionEnd, cursorPosition, selectedText
575 int QDeclarative1TextInput::selectionStart() const
577 Q_D(const QDeclarative1TextInput);
578 return d->lastSelectionStart;
582 \qmlproperty int QtQuick1::TextInput::selectionEnd
584 The cursor position after the last character in the current selection.
586 This property is read-only. To change the selection, use select(start,end),
587 selectAll(), or selectWord().
589 \sa selectionStart, cursorPosition, selectedText
591 int QDeclarative1TextInput::selectionEnd() const
593 Q_D(const QDeclarative1TextInput);
594 return d->lastSelectionEnd;
598 \qmlmethod void QtQuick1::TextInput::select(int start, int end)
600 Causes the text from \a start to \a end to be selected.
602 If either start or end is out of range, the selection is not changed.
604 After calling this, selectionStart will become the lesser
605 and selectionEnd will become the greater (regardless of the order passed
608 \sa selectionStart, selectionEnd
610 void QDeclarative1TextInput::select(int start, int end)
612 Q_D(QDeclarative1TextInput);
613 if (start < 0 || end < 0 || start > d->control->text().length() || end > d->control->text().length())
615 d->control->setSelection(start, end-start);
619 \qmlproperty string QtQuick1::TextInput::selectedText
621 This read-only property provides the text currently selected in the
624 It is equivalent to the following snippet, but is faster and easier
628 myTextInput.text.toString().substring(myTextInput.selectionStart,
629 myTextInput.selectionEnd);
632 QString QDeclarative1TextInput::selectedText() const
634 Q_D(const QDeclarative1TextInput);
635 return d->control->selectedText();
639 \qmlproperty bool QtQuick1::TextInput::activeFocusOnPress
641 Whether the TextInput should gain active focus on a mouse press. By default this is
644 bool QDeclarative1TextInput::focusOnPress() const
646 Q_D(const QDeclarative1TextInput);
647 return d->focusOnPress;
650 void QDeclarative1TextInput::setFocusOnPress(bool b)
652 Q_D(QDeclarative1TextInput);
653 if (d->focusOnPress == b)
658 emit activeFocusOnPressChanged(d->focusOnPress);
662 \qmlproperty bool QtQuick1::TextInput::autoScroll
664 Whether the TextInput should scroll when the text is longer than the width. By default this is
667 bool QDeclarative1TextInput::autoScroll() const
669 Q_D(const QDeclarative1TextInput);
670 return d->autoScroll;
673 void QDeclarative1TextInput::setAutoScroll(bool b)
675 Q_D(QDeclarative1TextInput);
676 if (d->autoScroll == b)
680 //We need to repaint so that the scrolling is taking into account.
682 updateCursorRectangle();
683 emit autoScrollChanged(d->autoScroll);
687 \qmlclass IntValidator QIntValidator
688 \inqmlmodule QtQuick 1
689 \ingroup qml-basic-visual-elements
691 This element provides a validator for integer values.
693 IntValidator uses the \l {QLocale::setDefault()}{default locale} to interpret the number and
694 will accept locale specific digits, group separators, and positive and negative signs. In
695 addition, IntValidator is always guaranteed to accept a number formatted according to the "C"
699 \qmlproperty int QtQuick1::IntValidator::top
701 This property holds the validator's highest acceptable value.
702 By default, this property's value is derived from the highest signed integer available (typically 2147483647).
705 \qmlproperty int QtQuick1::IntValidator::bottom
707 This property holds the validator's lowest acceptable value.
708 By default, this property's value is derived from the lowest signed integer available (typically -2147483647).
712 \qmlclass DoubleValidator QDoubleValidator
713 \inqmlmodule QtQuick 1
714 \ingroup qml-basic-visual-elements
716 This element provides a validator for non-integer numbers.
720 \qmlproperty real QtQuick1::DoubleValidator::top
722 This property holds the validator's maximum acceptable value.
723 By default, this property contains a value of infinity.
726 \qmlproperty real QtQuick1::DoubleValidator::bottom
728 This property holds the validator's minimum acceptable value.
729 By default, this property contains a value of -infinity.
732 \qmlproperty int QtQuick1::DoubleValidator::decimals
734 This property holds the validator's maximum number of digits after the decimal point.
735 By default, this property contains a value of 1000.
738 \qmlproperty enumeration QtQuick1::DoubleValidator::notation
739 This property holds the notation of how a string can describe a number.
741 The possible values for this property are:
744 \o DoubleValidator.StandardNotation
745 \o DoubleValidator.ScientificNotation (default)
748 If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part (e.g. 1.5E-2).
752 \qmlclass RegExpValidator QRegExpValidator
753 \inqmlmodule QtQuick 1
754 \ingroup qml-basic-visual-elements
756 This element provides a validator, which counts as valid any string which
757 matches a specified regular expression.
760 \qmlproperty regExp QtQuick1::RegExpValidator::regExp
762 This property holds the regular expression used for validation.
764 Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular expression
767 By default, this property contains a regular expression with the pattern .* that matches any string.
771 \qmlproperty Validator QtQuick1::TextInput::validator
773 Allows you to set a validator on the TextInput. When a validator is set
774 the TextInput will only accept input which leaves the text property in
775 an acceptable or intermediate state. The accepted signal will only be sent
776 if the text is in an acceptable state when enter is pressed.
778 Currently supported validators are IntValidator, DoubleValidator and
779 RegExpValidator. An example of using validators is shown below, which allows
780 input of integers between 11 and 31 into the text input:
785 validator: IntValidator{bottom: 11; top: 31;}
790 \sa acceptableInput, inputMask
792 #ifndef QT_NO_VALIDATOR
793 QValidator* QDeclarative1TextInput::validator() const
795 Q_D(const QDeclarative1TextInput);
796 //###const cast isn't good, but needed for property system?
797 return const_cast<QValidator*>(d->control->validator());
800 void QDeclarative1TextInput::setValidator(QValidator* v)
802 Q_D(QDeclarative1TextInput);
803 if (d->control->validator() == v)
806 d->control->setValidator(v);
807 if(!d->control->hasAcceptableInput()){
808 d->oldValidity = false;
809 emit acceptableInputChanged();
812 emit validatorChanged();
814 #endif // QT_NO_VALIDATOR
817 \qmlproperty string QtQuick1::TextInput::inputMask
819 Allows you to set an input mask on the TextInput, restricting the allowable
820 text inputs. See QLineEdit::inputMask for further details, as the exact
821 same mask strings are used by TextInput.
823 \sa acceptableInput, validator
825 QString QDeclarative1TextInput::inputMask() const
827 Q_D(const QDeclarative1TextInput);
828 return d->control->inputMask();
831 void QDeclarative1TextInput::setInputMask(const QString &im)
833 Q_D(QDeclarative1TextInput);
834 if (d->control->inputMask() == im)
837 d->control->setInputMask(im);
838 emit inputMaskChanged(d->control->inputMask());
842 \qmlproperty bool QtQuick1::TextInput::acceptableInput
844 This property is always true unless a validator or input mask has been set.
845 If a validator or input mask has been set, this property will only be true
846 if the current text is acceptable to the validator or input mask as a final
847 string (not as an intermediate string).
849 bool QDeclarative1TextInput::hasAcceptableInput() const
851 Q_D(const QDeclarative1TextInput);
852 return d->control->hasAcceptableInput();
856 \qmlsignal QtQuick1::TextInput::onAccepted()
858 This handler is called when the Return or Enter key is pressed.
859 Note that if there is a \l validator or \l inputMask set on the text
860 input, the handler will only be emitted if the input is in an acceptable
864 void QDeclarative1TextInputPrivate::updateInputMethodHints()
866 Q_Q(QDeclarative1TextInput);
867 Qt::InputMethodHints hints = inputMethodHints;
868 uint echo = control->echoMode();
869 if (echo == QDeclarative1TextInput::Password || echo == QDeclarative1TextInput::NoEcho)
870 hints |= Qt::ImhHiddenText;
871 else if (echo == QDeclarative1TextInput::PasswordEchoOnEdit)
872 hints &= ~Qt::ImhHiddenText;
873 if (echo != QDeclarative1TextInput::Normal) {
874 hints |= Qt::ImhNoAutoUppercase;
875 hints |= Qt::ImhNoPredictiveText;
877 q->setInputMethodHints(hints);
881 \qmlproperty enumeration QtQuick1::TextInput::echoMode
883 Specifies how the text should be displayed in the TextInput.
885 \o TextInput.Normal - Displays the text as it is. (Default)
886 \o TextInput.Password - Displays asterixes instead of characters.
887 \o TextInput.NoEcho - Displays nothing.
888 \o TextInput.PasswordEchoOnEdit - Displays all but the current character as asterixes.
891 QDeclarative1TextInput::EchoMode QDeclarative1TextInput::echoMode() const
893 Q_D(const QDeclarative1TextInput);
894 return (QDeclarative1TextInput::EchoMode)d->control->echoMode();
897 void QDeclarative1TextInput::setEchoMode(QDeclarative1TextInput::EchoMode echo)
899 Q_D(QDeclarative1TextInput);
900 if (echoMode() == echo)
902 d->control->setEchoMode((uint)echo);
903 d->updateInputMethodHints();
905 emit echoModeChanged(echoMode());
908 Qt::InputMethodHints QDeclarative1TextInput::imHints() const
910 Q_D(const QDeclarative1TextInput);
911 return d->inputMethodHints;
914 void QDeclarative1TextInput::setIMHints(Qt::InputMethodHints hints)
916 Q_D(QDeclarative1TextInput);
917 if (d->inputMethodHints == hints)
919 d->inputMethodHints = hints;
920 d->updateInputMethodHints();
924 \qmlproperty Component QtQuick1::TextInput::cursorDelegate
925 The delegate for the cursor in the TextInput.
927 If you set a cursorDelegate for a TextInput, this delegate will be used for
928 drawing the cursor instead of the standard cursor. An instance of the
929 delegate will be created and managed by the TextInput when a cursor is
930 needed, and the x property of delegate instance will be set so as
931 to be one pixel before the top left of the current character.
933 Note that the root item of the delegate component must be a QDeclarativeItem or
934 QDeclarativeItem derived item.
936 QDeclarativeComponent* QDeclarative1TextInput::cursorDelegate() const
938 Q_D(const QDeclarative1TextInput);
939 return d->cursorComponent;
942 void QDeclarative1TextInput::setCursorDelegate(QDeclarativeComponent* c)
944 Q_D(QDeclarative1TextInput);
945 if (d->cursorComponent == c)
948 d->cursorComponent = c;
950 //note that the components are owned by something else
951 delete d->cursorItem;
953 d->startCreatingCursor();
956 emit cursorDelegateChanged();
959 void QDeclarative1TextInputPrivate::startCreatingCursor()
961 Q_Q(QDeclarative1TextInput);
962 if(cursorComponent->isReady()){
964 }else if(cursorComponent->isLoading()){
965 q->connect(cursorComponent, SIGNAL(statusChanged(int)),
966 q, SLOT(createCursor()));
968 qmlInfo(q, cursorComponent->errors()) << QDeclarative1TextInput::tr("Could not load cursor delegate");
972 void QDeclarative1TextInput::createCursor()
974 Q_D(QDeclarative1TextInput);
975 if(d->cursorComponent->isError()){
976 qmlInfo(this, d->cursorComponent->errors()) << tr("Could not load cursor delegate");
980 if(!d->cursorComponent->isReady())
984 delete d->cursorItem;
985 d->cursorItem = qobject_cast<QDeclarativeItem*>(d->cursorComponent->create());
987 qmlInfo(this, d->cursorComponent->errors()) << tr("Could not instantiate cursor delegate");
991 QDeclarative_setParent_noEvent(d->cursorItem, this);
992 d->cursorItem->setParentItem(this);
993 d->cursorItem->setX(d->control->cursorToX());
994 d->cursorItem->setHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
998 \qmlmethod rect QtQuick1::TextInput::positionToRectangle(int pos)
1000 This function takes a character position and returns the rectangle that the
1001 cursor would occupy, if it was placed at that character position.
1003 This is similar to setting the cursorPosition, and then querying the cursor
1004 rectangle, but the cursorPosition is not changed.
1006 QRectF QDeclarative1TextInput::positionToRectangle(int pos) const
1008 Q_D(const QDeclarative1TextInput);
1009 if (pos > d->control->cursorPosition())
1010 pos += d->control->preeditAreaText().length();
1011 return QRectF(d->control->cursorToX(pos)-d->hscroll,
1013 d->control->cursorWidth(),
1014 cursorRectangle().height());
1017 int QDeclarative1TextInput::positionAt(int x) const
1019 return positionAt(x, CursorBetweenCharacters);
1023 \qmlmethod int QtQuick1::TextInput::positionAt(int x, CursorPosition position = CursorBetweenCharacters)
1026 This function returns the character position at
1027 x pixels from the left of the textInput. Position 0 is before the
1028 first character, position 1 is after the first character but before the second,
1029 and so on until position text.length, which is after all characters.
1031 This means that for all x values before the first character this function returns 0,
1032 and for all x values after the last character this function returns text.length.
1034 The cursor position type specifies how the cursor position should be resolved.
1037 \o TextInput.CursorBetweenCharacters - Returns the position between characters that is nearest x.
1038 \o TextInput.CursorOnCharacter - Returns the position before the character that is nearest x.
1041 int QDeclarative1TextInput::positionAt(int x, CursorPosition position) const
1043 Q_D(const QDeclarative1TextInput);
1044 int pos = d->control->xToPos(x + d->hscroll, QTextLine::CursorPosition(position));
1045 const int cursor = d->control->cursor();
1047 const int preeditLength = d->control->preeditAreaText().length();
1048 pos = pos > cursor + preeditLength
1049 ? pos - preeditLength
1055 void QDeclarative1TextInputPrivate::focusChanged(bool hasFocus)
1057 Q_Q(QDeclarative1TextInput);
1059 q->setCursorVisible(hasFocus && scene && scene->hasFocus());
1060 if(q->echoMode() == QDeclarative1TextInput::PasswordEchoOnEdit && !hasFocus)
1061 control->updatePasswordEchoEditing(false);//QLineControl sets it on key events, but doesn't deal with focus events
1063 control->deselect();
1064 QDeclarativeItemPrivate::focusChanged(hasFocus);
1067 void QDeclarative1TextInput::keyPressEvent(QKeyEvent* ev)
1069 Q_D(QDeclarative1TextInput);
1070 keyPressPreHandler(ev);
1071 if (ev->isAccepted())
1074 // Don't allow MacOSX up/down support, and we don't allow a completer.
1075 bool ignore = (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) && ev->modifiers() == Qt::NoModifier;
1076 if (!ignore && (d->lastSelectionStart == d->lastSelectionEnd) && (ev->key() == Qt::Key_Right || ev->key() == Qt::Key_Left)) {
1077 // Ignore when moving off the end unless there is a selection,
1078 // because then moving will do something (deselect).
1079 int cursorPosition = d->control->cursor();
1080 if (cursorPosition == 0)
1081 ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Left : Qt::Key_Right);
1082 if (cursorPosition == d->control->text().length())
1083 ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Right : Qt::Key_Left);
1088 d->control->processKeyEvent(ev);
1090 if (!ev->isAccepted())
1091 QDeclarative1PaintedItem::keyPressEvent(ev);
1094 void QDeclarative1TextInput::inputMethodEvent(QInputMethodEvent *ev)
1096 Q_D(QDeclarative1TextInput);
1098 const bool wasComposing = d->control->preeditAreaText().length() > 0;
1099 inputMethodPreHandler(ev);
1100 if (!ev->isAccepted()) {
1101 if (d->control->isReadOnly()) {
1104 d->control->processInputMethodEvent(ev);
1107 if (!ev->isAccepted())
1108 QDeclarative1PaintedItem::inputMethodEvent(ev);
1110 if (wasComposing != (d->control->preeditAreaText().length() > 0))
1111 emit inputMethodComposingChanged();
1116 Handles the given mouse \a event.
1118 void QDeclarative1TextInput::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
1120 Q_D(QDeclarative1TextInput);
1121 if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonDblClick))
1123 if (d->selectByMouse) {
1124 int cursor = d->xToPos(event->pos().x());
1125 d->control->selectWordAtPos(cursor);
1126 event->setAccepted(true);
1128 QDeclarative1PaintedItem::mouseDoubleClickEvent(event);
1132 void QDeclarative1TextInput::mousePressEvent(QGraphicsSceneMouseEvent *event)
1134 Q_D(QDeclarative1TextInput);
1135 if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonPress))
1137 if(d->focusOnPress){
1138 bool hadActiveFocus = hasActiveFocus();
1140 if (d->showInputPanelOnFocus) {
1141 if (hasActiveFocus() && hadActiveFocus && !isReadOnly()) {
1142 // re-open input panel on press if already focused
1143 openSoftwareInputPanel();
1145 } else { // show input panel on click
1146 if (hasActiveFocus() && !hadActiveFocus) {
1147 d->clickCausedFocus = true;
1151 if (d->selectByMouse) {
1152 setKeepMouseGrab(false);
1153 d->selectPressed = true;
1154 d->pressPos = event->pos();
1156 bool mark = (event->modifiers() & Qt::ShiftModifier) && d->selectByMouse;
1157 int cursor = d->xToPos(event->pos().x());
1158 d->control->moveCursor(cursor, mark);
1159 event->setAccepted(true);
1162 void QDeclarative1TextInput::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
1164 Q_D(QDeclarative1TextInput);
1165 if (d->sendMouseEventToInputContext(event, QEvent::MouseMove))
1167 if (d->selectPressed) {
1168 if (qAbs(int(event->pos().x() - d->pressPos.x())) > QApplication::startDragDistance())
1169 setKeepMouseGrab(true);
1170 moveCursorSelection(d->xToPos(event->pos().x()), d->mouseSelectionMode);
1171 event->setAccepted(true);
1173 QDeclarative1PaintedItem::mouseMoveEvent(event);
1179 Handles the given mouse \a event.
1181 void QDeclarative1TextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
1183 Q_D(QDeclarative1TextInput);
1184 if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonRelease))
1186 if (d->selectPressed) {
1187 d->selectPressed = false;
1188 setKeepMouseGrab(false);
1190 if (!d->showInputPanelOnFocus) { // input panel on click
1191 if (d->focusOnPress && !isReadOnly() && boundingRect().contains(event->pos())) {
1192 if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1193 if (view->scene() && view->scene() == scene()) {
1194 qt_widget_private(view)->handleSoftwareInputPanel(event->button(), d->clickCausedFocus);
1199 d->clickCausedFocus = false;
1200 d->control->processEvent(event);
1201 if (!event->isAccepted())
1202 QDeclarative1PaintedItem::mouseReleaseEvent(event);
1205 bool QDeclarative1TextInputPrivate::sendMouseEventToInputContext(
1206 QGraphicsSceneMouseEvent *event, QEvent::Type eventType)
1208 #if !defined QT_NO_IM
1209 if (event->widget() && control->composeMode()) {
1210 int tmp_cursor = xToPos(event->pos().x());
1211 int mousePos = tmp_cursor - control->cursor();
1212 if (mousePos < 0 || mousePos > control->preeditAreaText().length()) {
1214 // don't send move events outside the preedit area
1215 if (eventType == QEvent::MouseMove)
1219 QInputContext *qic = event->widget()->inputContext();
1221 QMouseEvent mouseEvent(
1223 event->widget()->mapFromGlobal(event->screenPos()),
1227 event->modifiers());
1228 // may be causing reset() in some input methods
1229 qic->mouseHandler(mousePos, &mouseEvent);
1230 event->setAccepted(mouseEvent.isAccepted());
1232 if (!control->preeditAreaText().isEmpty())
1243 bool QDeclarative1TextInput::sceneEvent(QEvent *event)
1245 Q_D(QDeclarative1TextInput);
1246 bool rv = QDeclarativeItem::sceneEvent(event);
1247 if (event->type() == QEvent::UngrabMouse) {
1248 d->selectPressed = false;
1249 setKeepMouseGrab(false);
1254 bool QDeclarative1TextInput::event(QEvent* ev)
1256 Q_D(QDeclarative1TextInput);
1257 //Anything we don't deal with ourselves, pass to the control
1258 bool handled = false;
1260 case QEvent::KeyPress:
1261 case QEvent::KeyRelease://###Should the control be doing anything with release?
1262 case QEvent::InputMethod:
1263 case QEvent::GraphicsSceneMousePress:
1264 case QEvent::GraphicsSceneMouseMove:
1265 case QEvent::GraphicsSceneMouseRelease:
1266 case QEvent::GraphicsSceneMouseDoubleClick:
1269 handled = d->control->processEvent(ev);
1272 handled = QDeclarative1PaintedItem::event(ev);
1276 void QDeclarative1TextInput::geometryChanged(const QRectF &newGeometry,
1277 const QRectF &oldGeometry)
1279 Q_D(QDeclarative1TextInput);
1280 if (newGeometry.width() != oldGeometry.width()) {
1282 updateCursorRectangle();
1284 QDeclarative1PaintedItem::geometryChanged(newGeometry, oldGeometry);
1287 int QDeclarative1TextInputPrivate::calculateTextWidth()
1289 return qRound(control->naturalTextWidth());
1292 void QDeclarative1TextInputPrivate::updateHorizontalScroll()
1294 Q_Q(QDeclarative1TextInput);
1295 const int preeditLength = control->preeditAreaText().length();
1296 int cix = qRound(control->cursorToX(control->cursor() + preeditLength));
1297 QRect br(q->boundingRect().toRect());
1298 int widthUsed = calculateTextWidth();
1300 QDeclarative1TextInput::HAlignment effectiveHAlign = q->effectiveHAlign();
1302 if (widthUsed <= br.width()) {
1303 // text fits in br; use hscroll for alignment
1304 switch (effectiveHAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) {
1305 case Qt::AlignRight:
1306 hscroll = widthUsed - br.width() - 1;
1308 case Qt::AlignHCenter:
1309 hscroll = (widthUsed - br.width()) / 2;
1316 } else if (cix - hscroll >= br.width()) {
1317 // text doesn't fit, cursor is to the right of br (scroll right)
1318 hscroll = cix - br.width() + 1;
1319 } else if (cix - hscroll < 0 && hscroll < widthUsed) {
1320 // text doesn't fit, cursor is to the left of br (scroll left)
1322 } else if (widthUsed - hscroll < br.width()) {
1323 // text doesn't fit, text document is to the left of br; align
1325 hscroll = widthUsed - br.width() + 1;
1327 if (preeditLength > 0) {
1328 // check to ensure long pre-edit text doesn't push the cursor
1330 cix = qRound(control->cursorToX(
1331 control->cursor() + qMax(0, control->preeditCursor() - 1)));
1336 switch (effectiveHAlign) {
1337 case QDeclarative1TextInput::AlignRight:
1338 hscroll = q->width() - widthUsed;
1340 case QDeclarative1TextInput::AlignHCenter:
1341 hscroll = (q->width() - widthUsed) / 2;
1351 void QDeclarative1TextInput::drawContents(QPainter *p, const QRect &r)
1353 Q_D(QDeclarative1TextInput);
1354 p->setRenderHint(QPainter::TextAntialiasing, true);
1356 p->setPen(QPen(d->color));
1357 int flags = QLineControl::DrawText;
1358 if(!isReadOnly() && d->cursorVisible && !d->cursorItem)
1359 flags |= QLineControl::DrawCursor;
1360 if (d->control->hasSelectedText())
1361 flags |= QLineControl::DrawSelections;
1362 QPoint offset = QPoint(0,0);
1363 QFontMetrics fm = QFontMetrics(d->font);
1364 QRect br(boundingRect().toRect());
1365 if (d->autoScroll) {
1366 // the y offset is there to keep the baseline constant in case we have script changes in the text.
1367 offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent());
1369 offset = QPoint(d->hscroll, 0);
1371 d->control->draw(p, offset, r, flags);
1377 Returns the value of the given \a property.
1379 QVariant QDeclarative1TextInput::inputMethodQuery(Qt::InputMethodQuery property) const
1381 Q_D(const QDeclarative1TextInput);
1383 case Qt::ImMicroFocus:
1384 return cursorRectangle();
1387 case Qt::ImCursorPosition:
1388 return QVariant(d->control->cursor());
1389 case Qt::ImSurroundingText:
1390 if (d->control->echoMode() == PasswordEchoOnEdit && !d->control->passwordEchoEditing())
1391 return QVariant(displayText());
1393 return QVariant(text());
1394 case Qt::ImCurrentSelection:
1395 return QVariant(selectedText());
1396 case Qt::ImMaximumTextLength:
1397 return QVariant(maxLength());
1398 case Qt::ImAnchorPosition:
1399 if (d->control->selectionStart() == d->control->selectionEnd())
1400 return QVariant(d->control->cursor());
1401 else if (d->control->selectionStart() == d->control->cursor())
1402 return QVariant(d->control->selectionEnd());
1404 return QVariant(d->control->selectionStart());
1411 \qmlmethod void QtQuick1::TextInput::deselect()
1414 Removes active text selection.
1416 void QDeclarative1TextInput::deselect()
1418 Q_D(QDeclarative1TextInput);
1419 d->control->deselect();
1423 \qmlmethod void QtQuick1::TextInput::selectAll()
1425 Causes all text to be selected.
1427 void QDeclarative1TextInput::selectAll()
1429 Q_D(QDeclarative1TextInput);
1430 d->control->setSelection(0, d->control->text().length());
1434 \qmlmethod void QtQuick1::TextInput::isRightToLeft(int start, int end)
1436 Returns true if the natural reading direction of the editor text
1437 found between positions \a start and \a end is right to left.
1439 bool QDeclarative1TextInput::isRightToLeft(int start, int end)
1441 Q_D(QDeclarative1TextInput);
1443 qmlInfo(this) << "isRightToLeft(start, end) called with the end property being smaller than the start.";
1446 return d->control->text().mid(start, end - start).isRightToLeft();
1450 #ifndef QT_NO_CLIPBOARD
1452 \qmlmethod QtQuick1::TextInput::cut()
1454 Moves the currently selected text to the system clipboard.
1456 void QDeclarative1TextInput::cut()
1458 Q_D(QDeclarative1TextInput);
1464 \qmlmethod QtQuick1::TextInput::copy()
1466 Copies the currently selected text to the system clipboard.
1468 void QDeclarative1TextInput::copy()
1470 Q_D(QDeclarative1TextInput);
1475 \qmlmethod QtQuick1::TextInput::paste()
1477 Replaces the currently selected text by the contents of the system clipboard.
1479 void QDeclarative1TextInput::paste()
1481 Q_D(QDeclarative1TextInput);
1482 if(!d->control->isReadOnly())
1483 d->control->paste();
1485 #endif // QT_NO_CLIPBOARD
1488 \qmlmethod void QtQuick1::TextInput::selectWord()
1490 Causes the word closest to the current cursor position to be selected.
1492 void QDeclarative1TextInput::selectWord()
1494 Q_D(QDeclarative1TextInput);
1495 d->control->selectWordAtPos(d->control->cursor());
1499 \qmlproperty bool QtQuick1::TextInput::smooth
1501 This property holds whether the text is smoothly scaled or transformed.
1503 Smooth filtering gives better visual quality, but is slower. If
1504 the item is displayed at its natural size, this property has no visual or
1507 \note Generally scaling artifacts are only visible if the item is stationary on
1508 the screen. A common pattern when animating an item is to disable smooth
1509 filtering at the beginning of the animation and reenable it at the conclusion.
1513 \qmlproperty string QtQuick1::TextInput::passwordCharacter
1515 This is the character displayed when echoMode is set to Password or
1516 PasswordEchoOnEdit. By default it is an asterisk.
1518 If this property is set to a string with more than one character,
1519 the first character is used. If the string is empty, the value
1520 is ignored and the property is not set.
1522 QString QDeclarative1TextInput::passwordCharacter() const
1524 Q_D(const QDeclarative1TextInput);
1525 return QString(d->control->passwordCharacter());
1528 void QDeclarative1TextInput::setPasswordCharacter(const QString &str)
1530 Q_D(QDeclarative1TextInput);
1531 if(str.length() < 1)
1533 d->control->setPasswordCharacter(str.constData()[0]);
1534 EchoMode echoMode_ = echoMode();
1535 if (echoMode_ == Password || echoMode_ == PasswordEchoOnEdit) {
1538 emit passwordCharacterChanged();
1542 \qmlproperty string QtQuick1::TextInput::displayText
1544 This is the text displayed in the TextInput.
1546 If \l echoMode is set to TextInput::Normal, this holds the
1547 same value as the TextInput::text property. Otherwise,
1548 this property holds the text visible to the user, while
1549 the \l text property holds the actual entered text.
1551 QString QDeclarative1TextInput::displayText() const
1553 Q_D(const QDeclarative1TextInput);
1554 return d->control->displayText();
1558 \qmlproperty bool QtQuick1::TextInput::selectByMouse
1562 If true, the user can use the mouse to select text in some
1563 platform-specific way. Note that for some platforms this may
1564 not be an appropriate interaction (eg. may conflict with how
1565 the text needs to behave inside a Flickable.
1567 bool QDeclarative1TextInput::selectByMouse() const
1569 Q_D(const QDeclarative1TextInput);
1570 return d->selectByMouse;
1573 void QDeclarative1TextInput::setSelectByMouse(bool on)
1575 Q_D(QDeclarative1TextInput);
1576 if (d->selectByMouse != on) {
1577 d->selectByMouse = on;
1578 emit selectByMouseChanged(on);
1583 \qmlproperty enum QtQuick1::TextInput::mouseSelectionMode
1586 Specifies how text should be selected using a mouse.
1589 \o TextInput.SelectCharacters - The selection is updated with individual characters. (Default)
1590 \o TextInput.SelectWords - The selection is updated with whole words.
1593 This property only applies when \l selectByMouse is true.
1596 QDeclarative1TextInput::SelectionMode QDeclarative1TextInput::mouseSelectionMode() const
1598 Q_D(const QDeclarative1TextInput);
1599 return d->mouseSelectionMode;
1602 void QDeclarative1TextInput::setMouseSelectionMode(SelectionMode mode)
1604 Q_D(QDeclarative1TextInput);
1605 if (d->mouseSelectionMode != mode) {
1606 d->mouseSelectionMode = mode;
1607 emit mouseSelectionModeChanged(mode);
1612 \qmlproperty bool QtQuick1::TextInput::canPaste
1615 Returns true if the TextInput is writable and the content of the clipboard is
1616 suitable for pasting into the TextEdit.
1618 bool QDeclarative1TextInput::canPaste() const
1620 Q_D(const QDeclarative1TextInput);
1624 void QDeclarative1TextInput::moveCursorSelection(int position)
1626 Q_D(QDeclarative1TextInput);
1627 d->control->moveCursor(position, true);
1631 \qmlmethod void QtQuick1::TextInput::moveCursorSelection(int position, SelectionMode mode = TextInput.SelectCharacters)
1634 Moves the cursor to \a position and updates the selection according to the optional \a mode
1635 parameter. (To only move the cursor, set the \l cursorPosition property.)
1637 When this method is called it additionally sets either the
1638 selectionStart or the selectionEnd (whichever was at the previous cursor position)
1639 to the specified position. This allows you to easily extend and contract the selected
1642 The selection mode specifies whether the selection is updated on a per character or a per word
1643 basis. If not specified the selection mode will default to TextInput.SelectCharacters.
1646 \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
1647 the previous cursor position) to the specified position.
1648 \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all
1649 words between the specified postion and the previous cursor position. Words partially in the
1653 For example, take this sequence of calls:
1657 moveCursorSelection(9, TextInput.SelectCharacters)
1658 moveCursorSelection(7, TextInput.SelectCharacters)
1661 This moves the cursor to position 5, extend the selection end from 5 to 9
1662 and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
1663 selected (the 6th and 7th characters).
1665 The same sequence with TextInput.SelectWords will extend the selection start to a word boundary
1666 before or on position 5 and extend the selection end to a word boundary on or past position 9.
1668 void QDeclarative1TextInput::moveCursorSelection(int pos, SelectionMode mode)
1670 Q_D(QDeclarative1TextInput);
1672 if (mode == SelectCharacters) {
1673 d->control->moveCursor(pos, true);
1674 } else if (pos != d->control->cursor()){
1675 const int cursor = d->control->cursor();
1677 if (!d->control->hasSelectedText())
1678 anchor = d->control->cursor();
1679 else if (d->control->selectionStart() == d->control->cursor())
1680 anchor = d->control->selectionEnd();
1682 anchor = d->control->selectionStart();
1684 if (anchor < pos || (anchor == pos && cursor < pos)) {
1685 const QString text = d->control->text();
1686 QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
1687 finder.setPosition(anchor);
1689 const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
1690 if (anchor < text.length() && (!(reasons & QTextBoundaryFinder::StartWord)
1691 || ((reasons & QTextBoundaryFinder::EndWord) && anchor > cursor))) {
1692 finder.toPreviousBoundary();
1694 anchor = finder.position() != -1 ? finder.position() : 0;
1696 finder.setPosition(pos);
1697 if (pos > 0 && !finder.boundaryReasons())
1698 finder.toNextBoundary();
1699 const int cursor = finder.position() != -1 ? finder.position() : text.length();
1701 d->control->setSelection(anchor, cursor - anchor);
1702 } else if (anchor > pos || (anchor == pos && cursor > pos)) {
1703 const QString text = d->control->text();
1704 QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
1705 finder.setPosition(anchor);
1707 const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
1708 if (anchor > 0 && (!(reasons & QTextBoundaryFinder::EndWord)
1709 || ((reasons & QTextBoundaryFinder::StartWord) && anchor < cursor))) {
1710 finder.toNextBoundary();
1712 anchor = finder.position() != -1 ? finder.position() : text.length();
1714 finder.setPosition(pos);
1715 if (pos < text.length() && !finder.boundaryReasons())
1716 finder.toPreviousBoundary();
1717 const int cursor = finder.position() != -1 ? finder.position() : 0;
1719 d->control->setSelection(anchor, cursor - anchor);
1725 \qmlmethod void QtQuick1::TextInput::openSoftwareInputPanel()
1727 Opens software input panels like virtual keyboards for typing, useful for
1728 customizing when you want the input keyboard to be shown and hidden in
1731 By default the opening of input panels follows the platform style. On Symbian^1 and
1732 Symbian^3 -based devices the panels are opened by clicking TextInput. On other platforms
1733 the panels are automatically opened when TextInput element gains active focus. Input panels are
1734 always closed if no editor has active focus.
1736 . You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1737 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1738 the behavior you want.
1740 Only relevant on platforms, which provide virtual keyboards.
1746 text: "Hello world!"
1747 activeFocusOnPress: false
1749 anchors.fill: parent
1751 if (!textInput.activeFocus) {
1752 textInput.forceActiveFocus()
1753 textInput.openSoftwareInputPanel();
1755 textInput.focus = false;
1758 onPressAndHold: textInput.closeSoftwareInputPanel();
1763 void QDeclarative1TextInput::openSoftwareInputPanel()
1765 QEvent event(QEvent::RequestSoftwareInputPanel);
1767 if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1768 if (view->scene() && view->scene() == scene()) {
1769 QApplication::sendEvent(view, &event);
1776 \qmlmethod void QtQuick1::TextInput::closeSoftwareInputPanel()
1778 Closes a software input panel like a virtual keyboard shown on the screen, useful
1779 for customizing when you want the input keyboard to be shown and hidden in
1782 By default the opening of input panels follows the platform style. On Symbian^1 and
1783 Symbian^3 -based devices the panels are opened by clicking TextInput. On other platforms
1784 the panels are automatically opened when TextInput element gains active focus. Input panels are
1785 always closed if no editor has active focus.
1787 . You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1788 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1789 the behavior you want.
1791 Only relevant on platforms, which provide virtual keyboards.
1797 text: "Hello world!"
1798 activeFocusOnPress: false
1800 anchors.fill: parent
1802 if (!textInput.activeFocus) {
1803 textInput.forceActiveFocus();
1804 textInput.openSoftwareInputPanel();
1806 textInput.focus = false;
1809 onPressAndHold: textInput.closeSoftwareInputPanel();
1814 void QDeclarative1TextInput::closeSoftwareInputPanel()
1816 QEvent event(QEvent::CloseSoftwareInputPanel);
1818 QEvent event(QEvent::CloseSoftwareInputPanel);
1819 if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1820 if (view->scene() && view->scene() == scene()) {
1821 QApplication::sendEvent(view, &event);
1827 void QDeclarative1TextInput::focusInEvent(QFocusEvent *event)
1829 Q_D(const QDeclarative1TextInput);
1830 if (d->showInputPanelOnFocus) {
1831 if (d->focusOnPress && !isReadOnly()) {
1832 openSoftwareInputPanel();
1835 QDeclarative1PaintedItem::focusInEvent(event);
1839 \qmlproperty bool QtQuick1::TextInput::inputMethodComposing
1843 This property holds whether the TextInput has partial text input from an
1846 While it is composing an input method may rely on mouse or key events from
1847 the TextInput to edit or commit the partial text. This property can be
1848 used to determine when to disable events handlers that may interfere with
1849 the correct operation of an input method.
1851 bool QDeclarative1TextInput::isInputMethodComposing() const
1853 Q_D(const QDeclarative1TextInput);
1854 return d->control->preeditAreaText().length() > 0;
1857 void QDeclarative1TextInputPrivate::init()
1859 Q_Q(QDeclarative1TextInput);
1860 control->setParent(q);//Now mandatory due to accessibility changes
1861 control->setCursorWidth(1);
1862 control->setPasswordCharacter(QLatin1Char('*'));
1863 q->setSmooth(smooth);
1864 q->setAcceptedMouseButtons(Qt::LeftButton);
1865 q->setFlag(QGraphicsItem::ItemHasNoContents, false);
1866 q->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
1867 q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
1868 q, SLOT(cursorPosChanged()));
1869 q->connect(control, SIGNAL(selectionChanged()),
1870 q, SLOT(selectionChanged()));
1871 q->connect(control, SIGNAL(textChanged(QString)),
1872 q, SLOT(q_textChanged()));
1873 q->connect(control, SIGNAL(accepted()),
1874 q, SIGNAL(accepted()));
1875 q->connect(control, SIGNAL(updateNeeded(QRect)),
1876 q, SLOT(updateRect(QRect)));
1877 #ifndef QT_NO_CLIPBOARD
1878 q->connect(q, SIGNAL(readOnlyChanged(bool)),
1879 q, SLOT(q_canPasteChanged()));
1880 q->connect(QApplication::clipboard(), SIGNAL(dataChanged()),
1881 q, SLOT(q_canPasteChanged()));
1882 canPaste = !control->isReadOnly() && QApplication::clipboard()->text().length() != 0;
1883 #endif // QT_NO_CLIPBOARD
1884 q->connect(control, SIGNAL(updateMicroFocus()),
1885 q, SLOT(updateCursorRectangle()));
1886 q->connect(control, SIGNAL(displayTextChanged(QString)),
1887 q, SLOT(updateRect()));
1889 oldValidity = control->hasAcceptableInput();
1890 lastSelectionStart = 0;
1891 lastSelectionEnd = 0;
1892 QPalette p = control->palette();
1893 selectedTextColor = p.color(QPalette::HighlightedText);
1894 selectionColor = p.color(QPalette::Highlight);
1895 determineHorizontalAlignment();
1898 void QDeclarative1TextInput::cursorPosChanged()
1900 Q_D(QDeclarative1TextInput);
1901 updateCursorRectangle();
1902 emit cursorPositionChanged();
1903 d->control->resetCursorBlinkTimer();
1905 if(!d->control->hasSelectedText()){
1906 if(d->lastSelectionStart != d->control->cursor()){
1907 d->lastSelectionStart = d->control->cursor();
1908 emit selectionStartChanged();
1910 if(d->lastSelectionEnd != d->control->cursor()){
1911 d->lastSelectionEnd = d->control->cursor();
1912 emit selectionEndChanged();
1917 void QDeclarative1TextInput::updateCursorRectangle()
1919 Q_D(QDeclarative1TextInput);
1920 d->updateHorizontalScroll();
1921 updateRect();//TODO: Only update rect between pos's
1923 emit cursorRectangleChanged();
1925 d->cursorItem->setX(d->control->cursorToX() - d->hscroll);
1928 void QDeclarative1TextInput::selectionChanged()
1930 Q_D(QDeclarative1TextInput);
1931 updateRect();//TODO: Only update rect in selection
1932 emit selectedTextChanged();
1934 if(d->lastSelectionStart != d->control->selectionStart()){
1935 d->lastSelectionStart = d->control->selectionStart();
1936 if(d->lastSelectionStart == -1)
1937 d->lastSelectionStart = d->control->cursor();
1938 emit selectionStartChanged();
1940 if(d->lastSelectionEnd != d->control->selectionEnd()){
1941 d->lastSelectionEnd = d->control->selectionEnd();
1942 if(d->lastSelectionEnd == -1)
1943 d->lastSelectionEnd = d->control->cursor();
1944 emit selectionEndChanged();
1948 void QDeclarative1TextInput::q_textChanged()
1950 Q_D(QDeclarative1TextInput);
1952 emit displayTextChanged();
1954 d->determineHorizontalAlignment();
1955 d->updateHorizontalScroll();
1957 if(hasAcceptableInput() != d->oldValidity){
1958 d->oldValidity = hasAcceptableInput();
1959 emit acceptableInputChanged();
1963 void QDeclarative1TextInput::updateRect(const QRect &r)
1965 Q_D(QDeclarative1TextInput);
1969 dirtyCache(QRect(r.x() - d->hscroll, r.y(), r.width(), r.height()));
1973 QRectF QDeclarative1TextInput::boundingRect() const
1975 Q_D(const QDeclarative1TextInput);
1976 QRectF r = QDeclarative1PaintedItem::boundingRect();
1978 int cursorWidth = d->cursorItem ? d->cursorItem->width() : d->control->cursorWidth();
1980 // Could include font max left/right bearings to either side of rectangle.
1982 r.setRight(r.right() + cursorWidth);
1986 void QDeclarative1TextInput::updateSize(bool needsRedraw)
1988 Q_D(QDeclarative1TextInput);
1991 setImplicitHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
1992 setImplicitWidth(d->calculateTextWidth());
1993 setContentsSize(QSize(width(), height()));//Repaints if changed
1994 if(w==width() && h==height() && needsRedraw){
2000 void QDeclarative1TextInput::q_canPasteChanged()
2002 Q_D(QDeclarative1TextInput);
2003 bool old = d->canPaste;
2004 #ifndef QT_NO_CLIPBOARD
2005 d->canPaste = !d->control->isReadOnly() && QApplication::clipboard()->text().length() != 0;
2007 if(d->canPaste != old)
2008 emit canPasteChanged();
2015 #endif // QT_NO_LINEEDIT