1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
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 <QtGui/QInputPanel>
52 #include <QFontMetrics>
54 #include <QTextBoundaryFinder>
55 #include <QInputContext>
58 #ifndef QT_NO_LINEEDIT
65 \qmlclass TextInput QDeclarative1TextInput
66 \inqmlmodule QtQuick 1
67 \ingroup qml-basic-visual-elements
69 \brief The TextInput item displays an editable line of text.
72 The TextInput element displays a single line of editable plain text.
74 TextInput is used to accept a line of text input. Input constraints
75 can be placed on a TextInput item (for example, through a \l validator or \l inputMask),
76 and setting \l echoMode to an appropriate value enables TextInput to be used for
77 a password input field.
79 On Mac OS X, the Up/Down key bindings for Home/End are explicitly disabled.
80 If you want such bindings (on any platform), you will need to construct them in QML.
82 \sa TextEdit, Text, {declarative/text/textselection}{Text Selection example}
84 QDeclarative1TextInput::QDeclarative1TextInput(QDeclarativeItem* parent)
85 : QDeclarative1ImplicitSizePaintedItem(*(new QDeclarative1TextInputPrivate), parent)
87 Q_D(QDeclarative1TextInput);
91 QDeclarative1TextInput::~QDeclarative1TextInput()
96 \qmlproperty string QtQuick1::TextInput::text
98 The text in the TextInput.
101 QString QDeclarative1TextInput::text() const
103 Q_D(const QDeclarative1TextInput);
104 return d->control->text();
107 void QDeclarative1TextInput::setText(const QString &s)
109 Q_D(QDeclarative1TextInput);
112 d->control->setText(s);
116 \qmlproperty string QtQuick1::TextInput::font.family
118 Sets the family name of the font.
120 The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]".
121 If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen.
122 If the family isn't available a family will be set using the font matching algorithm.
126 \qmlproperty bool QtQuick1::TextInput::font.bold
128 Sets whether the font weight is bold.
132 \qmlproperty enumeration QtQuick1::TextInput::font.weight
134 Sets the font's weight.
136 The weight can be one of:
139 \o Font.Normal - the default
146 TextInput { text: "Hello"; font.weight: Font.DemiBold }
151 \qmlproperty bool QtQuick1::TextInput::font.italic
153 Sets whether the font has an italic style.
157 \qmlproperty bool QtQuick1::TextInput::font.underline
159 Sets whether the text is underlined.
163 \qmlproperty bool QtQuick1::TextInput::font.strikeout
165 Sets whether the font has a strikeout style.
169 \qmlproperty real QtQuick1::TextInput::font.pointSize
171 Sets the font size in points. The point size must be greater than zero.
175 \qmlproperty int QtQuick1::TextInput::font.pixelSize
177 Sets the font size in pixels.
179 Using this function makes the font device dependent.
180 Use \c pointSize to set the size of the font in a device independent manner.
184 \qmlproperty real QtQuick1::TextInput::font.letterSpacing
186 Sets the letter spacing for the font.
188 Letter spacing changes the default spacing between individual letters in the font.
189 A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing.
193 \qmlproperty real QtQuick1::TextInput::font.wordSpacing
195 Sets the word spacing for the font.
197 Word spacing changes the default spacing between individual words.
198 A positive value increases the word spacing by a corresponding amount of pixels,
199 while a negative value decreases the inter-word spacing accordingly.
203 \qmlproperty enumeration QtQuick1::TextInput::font.capitalization
205 Sets the capitalization for the text.
208 \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied.
209 \o Font.AllUppercase - This alters the text to be rendered in all uppercase type.
210 \o Font.AllLowercase - This alters the text to be rendered in all lowercase type.
211 \o Font.SmallCaps - This alters the text to be rendered in small-caps type.
212 \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character.
216 TextInput { text: "Hello"; font.capitalization: Font.AllLowercase }
220 QFont QDeclarative1TextInput::font() const
222 Q_D(const QDeclarative1TextInput);
223 return d->sourceFont;
226 void QDeclarative1TextInput::setFont(const QFont &font)
228 Q_D(QDeclarative1TextInput);
229 if (d->sourceFont == font)
232 d->sourceFont = font;
233 QFont oldFont = d->font;
235 if (d->font.pointSizeF() != -1) {
237 qreal size = qRound(d->font.pointSizeF()*2.0);
238 d->font.setPointSizeF(size/2.0);
241 if (oldFont != d->font) {
242 d->control->setFont(d->font);
244 updateCursorRectangle();
246 d->cursorItem->setHeight(QFontMetrics(d->font).height());
249 emit fontChanged(d->sourceFont);
253 \qmlproperty color QtQuick1::TextInput::color
257 QColor QDeclarative1TextInput::color() const
259 Q_D(const QDeclarative1TextInput);
263 void QDeclarative1TextInput::setColor(const QColor &c)
265 Q_D(QDeclarative1TextInput);
270 emit colorChanged(c);
276 \qmlproperty color QtQuick1::TextInput::selectionColor
278 The text highlight color, used behind selections.
280 QColor QDeclarative1TextInput::selectionColor() const
282 Q_D(const QDeclarative1TextInput);
283 return d->selectionColor;
286 void QDeclarative1TextInput::setSelectionColor(const QColor &color)
288 Q_D(QDeclarative1TextInput);
289 if (d->selectionColor == color)
292 d->selectionColor = color;
293 QPalette p = d->control->palette();
294 p.setColor(QPalette::Highlight, d->selectionColor);
295 d->control->setPalette(p);
296 if (d->control->hasSelectedText()) {
300 emit selectionColorChanged(color);
304 \qmlproperty color QtQuick1::TextInput::selectedTextColor
306 The highlighted text color, used in selections.
308 QColor QDeclarative1TextInput::selectedTextColor() const
310 Q_D(const QDeclarative1TextInput);
311 return d->selectedTextColor;
314 void QDeclarative1TextInput::setSelectedTextColor(const QColor &color)
316 Q_D(QDeclarative1TextInput);
317 if (d->selectedTextColor == color)
320 d->selectedTextColor = color;
321 QPalette p = d->control->palette();
322 p.setColor(QPalette::HighlightedText, d->selectedTextColor);
323 d->control->setPalette(p);
324 if (d->control->hasSelectedText()) {
328 emit selectedTextColorChanged(color);
332 \qmlproperty enumeration QtQuick1::TextInput::horizontalAlignment
333 \qmlproperty enumeration QtQuick1::TextInput::effectiveHorizontalAlignment
335 Sets the horizontal alignment of the text within the TextInput item's
336 width and height. By default, the text alignment follows the natural alignment
337 of the text, for example text that is read from left to right will be aligned to
340 TextInput does not have vertical alignment, as the natural height is
341 exactly the height of the single line of text. If you set the height
342 manually to something larger, TextInput will always be top aligned
343 vertically. You can use anchors to align it however you want within
346 The valid values for \c horizontalAlignment are \c TextInput.AlignLeft, \c TextInput.AlignRight and
347 \c TextInput.AlignHCenter.
349 When using the attached property LayoutMirroring::enabled to mirror application
350 layouts, the horizontal alignment of text will also be mirrored. However, the property
351 \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
352 of TextInput, use the read-only property \c effectiveHorizontalAlignment.
354 QDeclarative1TextInput::HAlignment QDeclarative1TextInput::hAlign() const
356 Q_D(const QDeclarative1TextInput);
360 void QDeclarative1TextInput::setHAlign(HAlignment align)
362 Q_D(QDeclarative1TextInput);
363 bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror;
364 d->hAlignImplicit = false;
365 if (d->setHAlign(align, forceAlign) && isComponentComplete()) {
366 updateCursorRectangle();
370 void QDeclarative1TextInput::resetHAlign()
372 Q_D(QDeclarative1TextInput);
373 d->hAlignImplicit = true;
374 if (d->determineHorizontalAlignment() && isComponentComplete()) {
375 updateCursorRectangle();
379 QDeclarative1TextInput::HAlignment QDeclarative1TextInput::effectiveHAlign() const
381 Q_D(const QDeclarative1TextInput);
382 QDeclarative1TextInput::HAlignment effectiveAlignment = d->hAlign;
383 if (!d->hAlignImplicit && d->effectiveLayoutMirror) {
385 case QDeclarative1TextInput::AlignLeft:
386 effectiveAlignment = QDeclarative1TextInput::AlignRight;
388 case QDeclarative1TextInput::AlignRight:
389 effectiveAlignment = QDeclarative1TextInput::AlignLeft;
395 return effectiveAlignment;
398 bool QDeclarative1TextInputPrivate::setHAlign(QDeclarative1TextInput::HAlignment alignment, bool forceAlign)
400 Q_Q(QDeclarative1TextInput);
401 if ((hAlign != alignment || forceAlign) && alignment <= QDeclarative1TextInput::AlignHCenter) { // justify not supported
402 QDeclarative1TextInput::HAlignment oldEffectiveHAlign = q->effectiveHAlign();
404 emit q->horizontalAlignmentChanged(alignment);
405 if (oldEffectiveHAlign != q->effectiveHAlign())
406 emit q->effectiveHorizontalAlignmentChanged();
412 bool QDeclarative1TextInputPrivate::determineHorizontalAlignment()
414 if (hAlignImplicit) {
415 // if no explicit alignment has been set, follow the natural layout direction of the text
416 QString text = control->text();
418 text = control->preeditAreaText();
419 bool isRightToLeft = text.isEmpty()
420 ? qApp->inputPanel()->inputDirection() == Qt::RightToLeft
421 : text.isRightToLeft();
422 return setHAlign(isRightToLeft ? QDeclarative1TextInput::AlignRight : QDeclarative1TextInput::AlignLeft);
427 void QDeclarative1TextInputPrivate::mirrorChange()
429 Q_Q(QDeclarative1TextInput);
430 if (q->isComponentComplete()) {
431 if (!hAlignImplicit && (hAlign == QDeclarative1TextInput::AlignRight || hAlign == QDeclarative1TextInput::AlignLeft)) {
432 q->updateCursorRectangle();
433 emit q->effectiveHorizontalAlignmentChanged();
439 \qmlproperty bool QtQuick1::TextInput::readOnly
441 Sets whether user input can modify the contents of the TextInput.
443 If readOnly is set to true, then user input will not affect the text
444 property. Any bindings or attempts to set the text property will still
448 bool QDeclarative1TextInput::isReadOnly() const
450 Q_D(const QDeclarative1TextInput);
451 return d->control->isReadOnly();
454 void QDeclarative1TextInput::setReadOnly(bool ro)
456 Q_D(QDeclarative1TextInput);
457 if (d->control->isReadOnly() == ro)
460 setFlag(QGraphicsItem::ItemAcceptsInputMethod, !ro);
461 d->control->setReadOnly(ro);
463 emit readOnlyChanged(ro);
467 \qmlproperty int QtQuick1::TextInput::maximumLength
468 The maximum permitted length of the text in the TextInput.
470 If the text is too long, it is truncated at the limit.
472 By default, this property contains a value of 32767.
474 int QDeclarative1TextInput::maxLength() const
476 Q_D(const QDeclarative1TextInput);
477 return d->control->maxLength();
480 void QDeclarative1TextInput::setMaxLength(int ml)
482 Q_D(QDeclarative1TextInput);
483 if (d->control->maxLength() == ml)
486 d->control->setMaxLength(ml);
488 emit maximumLengthChanged(ml);
492 \qmlproperty bool QtQuick1::TextInput::cursorVisible
493 Set to true when the TextInput shows a cursor.
495 This property is set and unset when the TextInput gets active focus, so that other
496 properties can be bound to whether the cursor is currently showing. As it
497 gets set and unset automatically, when you set the value yourself you must
498 keep in mind that your value may be overwritten.
500 It can be set directly in script, for example if a KeyProxy might
501 forward keys to it and you desire it to look active when this happens
502 (but without actually giving it active focus).
504 It should not be set directly on the element, like in the below QML,
505 as the specified value will be overridden an lost on focus changes.
514 In the above snippet the cursor will still become visible when the
515 TextInput gains active focus.
517 bool QDeclarative1TextInput::isCursorVisible() const
519 Q_D(const QDeclarative1TextInput);
520 return d->cursorVisible;
523 void QDeclarative1TextInput::setCursorVisible(bool on)
525 Q_D(QDeclarative1TextInput);
526 if (d->cursorVisible == on)
528 d->cursorVisible = on;
529 d->control->setCursorBlinkPeriod(on?QApplication::cursorFlashTime():0);
530 QRect r = d->control->cursorRect();
531 if (d->control->inputMask().isEmpty())
535 emit cursorVisibleChanged(d->cursorVisible);
539 \qmlproperty int QtQuick1::TextInput::cursorPosition
540 The position of the cursor in the TextInput.
542 int QDeclarative1TextInput::cursorPosition() const
544 Q_D(const QDeclarative1TextInput);
545 return d->control->cursor();
547 void QDeclarative1TextInput::setCursorPosition(int cp)
549 Q_D(QDeclarative1TextInput);
550 if (cp < 0 || cp > d->control->text().length())
552 d->control->moveCursor(cp);
556 Returns a Rect which encompasses the cursor, but which may be larger than is
557 required. Ignores custom cursor delegates.
559 QRect QDeclarative1TextInput::cursorRectangle() const
561 Q_D(const QDeclarative1TextInput);
562 QRect r = d->control->cursorRect();
563 // Scroll and make consistent with TextEdit
564 // QWidgetLineControl inexplicably adds 1 to the height and horizontal padding
565 // for unicode direction markers.
566 r.adjust(5 - d->hscroll, 0, -4 - d->hscroll, -1);
571 \qmlproperty int QtQuick1::TextInput::selectionStart
573 The cursor position before the first character in the current selection.
575 This property is read-only. To change the selection, use select(start,end),
576 selectAll(), or selectWord().
578 \sa selectionEnd, cursorPosition, selectedText
580 int QDeclarative1TextInput::selectionStart() const
582 Q_D(const QDeclarative1TextInput);
583 return d->lastSelectionStart;
587 \qmlproperty int QtQuick1::TextInput::selectionEnd
589 The cursor position after the last character in the current selection.
591 This property is read-only. To change the selection, use select(start,end),
592 selectAll(), or selectWord().
594 \sa selectionStart, cursorPosition, selectedText
596 int QDeclarative1TextInput::selectionEnd() const
598 Q_D(const QDeclarative1TextInput);
599 return d->lastSelectionEnd;
603 \qmlmethod void QtQuick1::TextInput::select(int start, int end)
605 Causes the text from \a start to \a end to be selected.
607 If either start or end is out of range, the selection is not changed.
609 After calling this, selectionStart will become the lesser
610 and selectionEnd will become the greater (regardless of the order passed
613 \sa selectionStart, selectionEnd
615 void QDeclarative1TextInput::select(int start, int end)
617 Q_D(QDeclarative1TextInput);
618 if (start < 0 || end < 0 || start > d->control->text().length() || end > d->control->text().length())
620 d->control->setSelection(start, end-start);
624 \qmlproperty string QtQuick1::TextInput::selectedText
626 This read-only property provides the text currently selected in the
629 It is equivalent to the following snippet, but is faster and easier
633 myTextInput.text.toString().substring(myTextInput.selectionStart,
634 myTextInput.selectionEnd);
637 QString QDeclarative1TextInput::selectedText() const
639 Q_D(const QDeclarative1TextInput);
640 return d->control->selectedText();
644 \qmlproperty bool QtQuick1::TextInput::activeFocusOnPress
646 Whether the TextInput should gain active focus on a mouse press. By default this is
649 bool QDeclarative1TextInput::focusOnPress() const
651 Q_D(const QDeclarative1TextInput);
652 return d->focusOnPress;
655 void QDeclarative1TextInput::setFocusOnPress(bool b)
657 Q_D(QDeclarative1TextInput);
658 if (d->focusOnPress == b)
663 emit activeFocusOnPressChanged(d->focusOnPress);
667 \qmlproperty bool QtQuick1::TextInput::autoScroll
669 Whether the TextInput should scroll when the text is longer than the width. By default this is
672 bool QDeclarative1TextInput::autoScroll() const
674 Q_D(const QDeclarative1TextInput);
675 return d->autoScroll;
678 void QDeclarative1TextInput::setAutoScroll(bool b)
680 Q_D(QDeclarative1TextInput);
681 if (d->autoScroll == b)
685 //We need to repaint so that the scrolling is taking into account.
687 updateCursorRectangle();
688 emit autoScrollChanged(d->autoScroll);
692 \qmlclass IntValidator QIntValidator
693 \inqmlmodule QtQuick 1
694 \ingroup qml-basic-visual-elements
696 This element provides a validator for integer values.
698 IntValidator uses the \l {QLocale::setDefault()}{default locale} to interpret the number and
699 will accept locale specific digits, group separators, and positive and negative signs. In
700 addition, IntValidator is always guaranteed to accept a number formatted according to the "C"
704 \qmlproperty int QtQuick1::IntValidator::top
706 This property holds the validator's highest acceptable value.
707 By default, this property's value is derived from the highest signed integer available (typically 2147483647).
710 \qmlproperty int QtQuick1::IntValidator::bottom
712 This property holds the validator's lowest acceptable value.
713 By default, this property's value is derived from the lowest signed integer available (typically -2147483647).
717 \qmlclass DoubleValidator QDoubleValidator
718 \inqmlmodule QtQuick 1
719 \ingroup qml-basic-visual-elements
721 This element provides a validator for non-integer numbers.
725 \qmlproperty real QtQuick1::DoubleValidator::top
727 This property holds the validator's maximum acceptable value.
728 By default, this property contains a value of infinity.
731 \qmlproperty real QtQuick1::DoubleValidator::bottom
733 This property holds the validator's minimum acceptable value.
734 By default, this property contains a value of -infinity.
737 \qmlproperty int QtQuick1::DoubleValidator::decimals
739 This property holds the validator's maximum number of digits after the decimal point.
740 By default, this property contains a value of 1000.
743 \qmlproperty enumeration QtQuick1::DoubleValidator::notation
744 This property holds the notation of how a string can describe a number.
746 The possible values for this property are:
749 \o DoubleValidator.StandardNotation
750 \o DoubleValidator.ScientificNotation (default)
753 If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part (e.g. 1.5E-2).
757 \qmlclass RegExpValidator QRegExpValidator
758 \inqmlmodule QtQuick 1
759 \ingroup qml-basic-visual-elements
761 This element provides a validator, which counts as valid any string which
762 matches a specified regular expression.
765 \qmlproperty regExp QtQuick1::RegExpValidator::regExp
767 This property holds the regular expression used for validation.
769 Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular expression
772 By default, this property contains a regular expression with the pattern .* that matches any string.
776 \qmlproperty Validator QtQuick1::TextInput::validator
778 Allows you to set a validator on the TextInput. When a validator is set
779 the TextInput will only accept input which leaves the text property in
780 an acceptable or intermediate state. The accepted signal will only be sent
781 if the text is in an acceptable state when enter is pressed.
783 Currently supported validators are IntValidator, DoubleValidator and
784 RegExpValidator. An example of using validators is shown below, which allows
785 input of integers between 11 and 31 into the text input:
790 validator: IntValidator{bottom: 11; top: 31;}
795 \sa acceptableInput, inputMask
797 #ifndef QT_NO_VALIDATOR
798 QValidator* QDeclarative1TextInput::validator() const
800 Q_D(const QDeclarative1TextInput);
801 //###const cast isn't good, but needed for property system?
802 return const_cast<QValidator*>(d->control->validator());
805 void QDeclarative1TextInput::setValidator(QValidator* v)
807 Q_D(QDeclarative1TextInput);
808 if (d->control->validator() == v)
811 d->control->setValidator(v);
812 if(!d->control->hasAcceptableInput()){
813 d->oldValidity = false;
814 emit acceptableInputChanged();
817 emit validatorChanged();
819 #endif // QT_NO_VALIDATOR
822 \qmlproperty string QtQuick1::TextInput::inputMask
824 Allows you to set an input mask on the TextInput, restricting the allowable
825 text inputs. See QLineEdit::inputMask for further details, as the exact
826 same mask strings are used by TextInput.
828 \sa acceptableInput, validator
830 QString QDeclarative1TextInput::inputMask() const
832 Q_D(const QDeclarative1TextInput);
833 return d->control->inputMask();
836 void QDeclarative1TextInput::setInputMask(const QString &im)
838 Q_D(QDeclarative1TextInput);
839 if (d->control->inputMask() == im)
842 d->control->setInputMask(im);
843 emit inputMaskChanged(d->control->inputMask());
847 \qmlproperty bool QtQuick1::TextInput::acceptableInput
849 This property is always true unless a validator or input mask has been set.
850 If a validator or input mask has been set, this property will only be true
851 if the current text is acceptable to the validator or input mask as a final
852 string (not as an intermediate string).
854 bool QDeclarative1TextInput::hasAcceptableInput() const
856 Q_D(const QDeclarative1TextInput);
857 return d->control->hasAcceptableInput();
861 \qmlsignal QtQuick1::TextInput::onAccepted()
863 This handler is called when the Return or Enter key is pressed.
864 Note that if there is a \l validator or \l inputMask set on the text
865 input, the handler will only be emitted if the input is in an acceptable
869 void QDeclarative1TextInputPrivate::updateInputMethodHints()
871 Q_Q(QDeclarative1TextInput);
872 Qt::InputMethodHints hints = inputMethodHints;
873 uint echo = control->echoMode();
874 if (echo == QDeclarative1TextInput::Password || echo == QDeclarative1TextInput::NoEcho)
875 hints |= Qt::ImhHiddenText;
876 else if (echo == QDeclarative1TextInput::PasswordEchoOnEdit)
877 hints &= ~Qt::ImhHiddenText;
878 if (echo != QDeclarative1TextInput::Normal) {
879 hints |= Qt::ImhNoAutoUppercase;
880 hints |= Qt::ImhNoPredictiveText;
882 q->setInputMethodHints(hints);
886 \qmlproperty enumeration QtQuick1::TextInput::echoMode
888 Specifies how the text should be displayed in the TextInput.
890 \o TextInput.Normal - Displays the text as it is. (Default)
891 \o TextInput.Password - Displays asterixes instead of characters.
892 \o TextInput.NoEcho - Displays nothing.
893 \o TextInput.PasswordEchoOnEdit - Displays characters as they are entered
894 while editing, otherwise displays asterisks.
897 QDeclarative1TextInput::EchoMode QDeclarative1TextInput::echoMode() const
899 Q_D(const QDeclarative1TextInput);
900 return (QDeclarative1TextInput::EchoMode)d->control->echoMode();
903 void QDeclarative1TextInput::setEchoMode(QDeclarative1TextInput::EchoMode echo)
905 Q_D(QDeclarative1TextInput);
906 if (echoMode() == echo)
908 d->control->setEchoMode(echo);
909 d->updateInputMethodHints();
911 emit echoModeChanged(echoMode());
914 Qt::InputMethodHints QDeclarative1TextInput::imHints() const
916 Q_D(const QDeclarative1TextInput);
917 return d->inputMethodHints;
920 void QDeclarative1TextInput::setIMHints(Qt::InputMethodHints hints)
922 Q_D(QDeclarative1TextInput);
923 if (d->inputMethodHints == hints)
925 d->inputMethodHints = hints;
926 d->updateInputMethodHints();
930 \qmlproperty Component QtQuick1::TextInput::cursorDelegate
931 The delegate for the cursor in the TextInput.
933 If you set a cursorDelegate for a TextInput, this delegate will be used for
934 drawing the cursor instead of the standard cursor. An instance of the
935 delegate will be created and managed by the TextInput when a cursor is
936 needed, and the x property of delegate instance will be set so as
937 to be one pixel before the top left of the current character.
939 Note that the root item of the delegate component must be a QDeclarativeItem or
940 QDeclarativeItem derived item.
942 QDeclarativeComponent* QDeclarative1TextInput::cursorDelegate() const
944 Q_D(const QDeclarative1TextInput);
945 return d->cursorComponent;
948 void QDeclarative1TextInput::setCursorDelegate(QDeclarativeComponent* c)
950 Q_D(QDeclarative1TextInput);
951 if (d->cursorComponent == c)
954 d->cursorComponent = c;
956 //note that the components are owned by something else
957 delete d->cursorItem;
959 d->startCreatingCursor();
962 emit cursorDelegateChanged();
965 void QDeclarative1TextInputPrivate::startCreatingCursor()
967 Q_Q(QDeclarative1TextInput);
968 if(cursorComponent->isReady()){
970 }else if(cursorComponent->isLoading()){
971 q->connect(cursorComponent, SIGNAL(statusChanged(int)),
972 q, SLOT(createCursor()));
974 qmlInfo(q, cursorComponent->errors()) << QDeclarative1TextInput::tr("Could not load cursor delegate");
978 void QDeclarative1TextInput::createCursor()
980 Q_D(QDeclarative1TextInput);
981 if(d->cursorComponent->isError()){
982 qmlInfo(this, d->cursorComponent->errors()) << tr("Could not load cursor delegate");
986 if(!d->cursorComponent->isReady())
990 delete d->cursorItem;
991 d->cursorItem = qobject_cast<QDeclarativeItem*>(d->cursorComponent->create());
993 qmlInfo(this, d->cursorComponent->errors()) << tr("Could not instantiate cursor delegate");
997 QDeclarative_setParent_noEvent(d->cursorItem, this);
998 d->cursorItem->setParentItem(this);
999 d->cursorItem->setX(d->control->cursorToX());
1000 d->cursorItem->setHeight(d->control->height()-1); // -1 to counter QWidgetLineControl's +1 which is not consistent with Text.
1004 \qmlmethod rect QtQuick1::TextInput::positionToRectangle(int pos)
1006 This function takes a character position and returns the rectangle that the
1007 cursor would occupy, if it was placed at that character position.
1009 This is similar to setting the cursorPosition, and then querying the cursor
1010 rectangle, but the cursorPosition is not changed.
1012 QRectF QDeclarative1TextInput::positionToRectangle(int pos) const
1014 Q_D(const QDeclarative1TextInput);
1015 if (pos > d->control->cursorPosition())
1016 pos += d->control->preeditAreaText().length();
1017 return QRectF(d->control->cursorToX(pos)-d->hscroll,
1019 d->control->cursorWidth(),
1020 cursorRectangle().height());
1023 int QDeclarative1TextInput::positionAt(int x) const
1025 return positionAt(x, CursorBetweenCharacters);
1029 \qmlmethod int QtQuick1::TextInput::positionAt(int x, CursorPosition position = CursorBetweenCharacters)
1032 This function returns the character position at
1033 x pixels from the left of the textInput. Position 0 is before the
1034 first character, position 1 is after the first character but before the second,
1035 and so on until position text.length, which is after all characters.
1037 This means that for all x values before the first character this function returns 0,
1038 and for all x values after the last character this function returns text.length.
1040 The cursor position type specifies how the cursor position should be resolved.
1043 \o TextInput.CursorBetweenCharacters - Returns the position between characters that is nearest x.
1044 \o TextInput.CursorOnCharacter - Returns the position before the character that is nearest x.
1047 int QDeclarative1TextInput::positionAt(int x, CursorPosition position) const
1049 Q_D(const QDeclarative1TextInput);
1050 int pos = d->control->xToPos(x + d->hscroll, QTextLine::CursorPosition(position));
1051 const int cursor = d->control->cursor();
1053 const int preeditLength = d->control->preeditAreaText().length();
1054 pos = pos > cursor + preeditLength
1055 ? pos - preeditLength
1061 void QDeclarative1TextInputPrivate::focusChanged(bool hasFocus)
1063 Q_Q(QDeclarative1TextInput);
1065 q->setCursorVisible(hasFocus && scene && scene->hasFocus());
1066 if(!hasFocus && control->passwordEchoEditing())
1067 control->updatePasswordEchoEditing(false);//QWidgetLineControl sets it on key events, but doesn't deal with focus events
1069 control->commitPreedit();
1070 control->deselect();
1072 QDeclarativeItemPrivate::focusChanged(hasFocus);
1075 void QDeclarative1TextInput::keyPressEvent(QKeyEvent* ev)
1077 Q_D(QDeclarative1TextInput);
1078 keyPressPreHandler(ev);
1079 if (ev->isAccepted())
1082 // Don't allow MacOSX up/down support, and we don't allow a completer.
1083 bool ignore = (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) && ev->modifiers() == Qt::NoModifier;
1084 if (!ignore && (d->lastSelectionStart == d->lastSelectionEnd) && (ev->key() == Qt::Key_Right || ev->key() == Qt::Key_Left)) {
1085 // Ignore when moving off the end unless there is a selection,
1086 // because then moving will do something (deselect).
1087 int cursorPosition = d->control->cursor();
1088 if (cursorPosition == 0)
1089 ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Left : Qt::Key_Right);
1090 if (cursorPosition == d->control->text().length())
1091 ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Right : Qt::Key_Left);
1096 d->control->processKeyEvent(ev);
1098 if (!ev->isAccepted())
1099 QDeclarative1PaintedItem::keyPressEvent(ev);
1102 void QDeclarative1TextInput::inputMethodEvent(QInputMethodEvent *ev)
1104 Q_D(QDeclarative1TextInput);
1106 const bool wasComposing = d->control->preeditAreaText().length() > 0;
1107 inputMethodPreHandler(ev);
1108 if (!ev->isAccepted()) {
1109 if (d->control->isReadOnly()) {
1112 d->control->processInputMethodEvent(ev);
1115 if (!ev->isAccepted())
1116 QDeclarative1PaintedItem::inputMethodEvent(ev);
1118 if (wasComposing != (d->control->preeditAreaText().length() > 0))
1119 emit inputMethodComposingChanged();
1124 Handles the given mouse \a event.
1126 void QDeclarative1TextInput::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
1128 Q_D(QDeclarative1TextInput);
1129 if (d->selectByMouse && event->button() == Qt::LeftButton) {
1130 int cursor = d->xToPos(event->pos().x());
1131 d->control->selectWordAtPos(cursor);
1132 event->setAccepted(true);
1134 if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonDblClick))
1136 QDeclarative1PaintedItem::mouseDoubleClickEvent(event);
1140 void QDeclarative1TextInput::mousePressEvent(QGraphicsSceneMouseEvent *event)
1142 Q_D(QDeclarative1TextInput);
1144 d->pressPos = event->pos();
1146 if(d->focusOnPress){
1147 bool hadActiveFocus = hasActiveFocus();
1149 if (d->showInputPanelOnFocus) {
1150 if (hasActiveFocus() && hadActiveFocus && !isReadOnly()) {
1151 // re-open input panel on press if already focused
1152 openSoftwareInputPanel();
1154 } else { // show input panel on click
1155 if (hasActiveFocus() && !hadActiveFocus) {
1156 d->clickCausedFocus = true;
1160 if (d->selectByMouse) {
1161 setKeepMouseGrab(false);
1162 d->selectPressed = true;
1164 if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonPress))
1167 bool mark = (event->modifiers() & Qt::ShiftModifier) && d->selectByMouse;
1168 int cursor = d->xToPos(event->pos().x());
1169 d->control->moveCursor(cursor, mark);
1170 event->setAccepted(true);
1173 void QDeclarative1TextInput::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
1175 Q_D(QDeclarative1TextInput);
1177 if (d->selectPressed) {
1178 if (qAbs(int(event->pos().x() - d->pressPos.x())) > QApplication::startDragDistance())
1179 setKeepMouseGrab(true);
1181 if (d->control->composeMode()) {
1183 int startPos = d->xToPos(d->pressPos.x());
1184 int currentPos = d->xToPos(event->pos().x());
1185 if (startPos != currentPos)
1186 d->control->setSelection(startPos, currentPos - startPos);
1188 moveCursorSelection(d->xToPos(event->pos().x()), d->mouseSelectionMode);
1190 event->setAccepted(true);
1192 QDeclarative1PaintedItem::mouseMoveEvent(event);
1198 Handles the given mouse \a event.
1200 void QDeclarative1TextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
1202 Q_D(QDeclarative1TextInput);
1203 if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonRelease))
1205 if (d->selectPressed) {
1206 d->selectPressed = false;
1207 setKeepMouseGrab(false);
1209 if (!d->showInputPanelOnFocus) { // input panel on click
1210 if (d->focusOnPress && !isReadOnly() && boundingRect().contains(event->pos())) {
1211 if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1212 if (view->scene() && view->scene() == scene()) {
1213 qt_widget_private(view)->handleSoftwareInputPanel(event->button(), d->clickCausedFocus);
1218 d->clickCausedFocus = false;
1219 #ifndef QT_NO_CLIPBOARD
1220 if (QGuiApplication::clipboard()->supportsSelection()) {
1221 if (event->button() == Qt::LeftButton) {
1222 d->control->copy(QClipboard::Selection);
1223 } else if (!isReadOnly() && event->button() == Qt::MidButton) {
1224 d->control->deselect();
1225 d->control->insert(QGuiApplication::clipboard()->text(QClipboard::Selection));
1229 if (!event->isAccepted())
1230 QDeclarative1PaintedItem::mouseReleaseEvent(event);
1233 bool QDeclarative1TextInputPrivate::sendMouseEventToInputContext(
1234 QGraphicsSceneMouseEvent *event, QEvent::Type eventType)
1236 #if !defined QT_NO_IM
1237 if (event->widget() && control->composeMode()) {
1238 int tmp_cursor = xToPos(event->pos().x());
1239 int mousePos = tmp_cursor - control->cursor();
1240 if (mousePos >= 0 && mousePos <= control->preeditAreaText().length()) {
1241 if (eventType == QEvent::MouseButtonRelease) {
1242 qApp->inputPanel()->invokeAction(QInputPanel::Click, mousePos);
1255 bool QDeclarative1TextInput::sceneEvent(QEvent *event)
1257 Q_D(QDeclarative1TextInput);
1258 bool rv = QDeclarativeItem::sceneEvent(event);
1259 if (event->type() == QEvent::UngrabMouse) {
1260 d->selectPressed = false;
1261 setKeepMouseGrab(false);
1266 bool QDeclarative1TextInput::event(QEvent* ev)
1268 #ifndef QT_NO_SHORTCUT
1269 Q_D(QDeclarative1TextInput);
1271 if (ev->type() == QEvent::ShortcutOverride) {
1272 d->control->processShortcutOverrideEvent(static_cast<QKeyEvent *>(ev));
1273 return ev->isAccepted();
1276 return QDeclarative1PaintedItem::event(ev);
1279 void QDeclarative1TextInput::geometryChanged(const QRectF &newGeometry,
1280 const QRectF &oldGeometry)
1282 if (newGeometry.width() != oldGeometry.width()) {
1284 updateCursorRectangle();
1286 QDeclarative1PaintedItem::geometryChanged(newGeometry, oldGeometry);
1289 int QDeclarative1TextInputPrivate::calculateTextWidth()
1291 return qRound(control->naturalTextWidth());
1294 void QDeclarative1TextInputPrivate::updateHorizontalScroll()
1296 Q_Q(QDeclarative1TextInput);
1297 const int preeditLength = control->preeditAreaText().length();
1298 int cix = qRound(control->cursorToX(control->cursor() + preeditLength));
1299 QRect br(q->boundingRect().toRect());
1300 int widthUsed = calculateTextWidth();
1302 QDeclarative1TextInput::HAlignment effectiveHAlign = q->effectiveHAlign();
1304 if (widthUsed <= br.width()) {
1305 // text fits in br; use hscroll for alignment
1306 switch (effectiveHAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) {
1307 case Qt::AlignRight:
1308 hscroll = widthUsed - br.width() - 1;
1310 case Qt::AlignHCenter:
1311 hscroll = (widthUsed - br.width()) / 2;
1318 } else if (cix - hscroll >= br.width()) {
1319 // text doesn't fit, cursor is to the right of br (scroll right)
1320 hscroll = cix - br.width() + 1;
1321 } else if (cix - hscroll < 0 && hscroll < widthUsed) {
1322 // text doesn't fit, cursor is to the left of br (scroll left)
1324 } else if (widthUsed - hscroll < br.width()) {
1325 // text doesn't fit, text document is to the left of br; align
1327 hscroll = widthUsed - br.width() + 1;
1329 if (preeditLength > 0) {
1330 // check to ensure long pre-edit text doesn't push the cursor
1332 cix = qRound(control->cursorToX(
1333 control->cursor() + qMax(0, control->preeditCursor() - 1)));
1338 switch (effectiveHAlign) {
1339 case QDeclarative1TextInput::AlignRight:
1340 hscroll = q->width() - widthUsed;
1342 case QDeclarative1TextInput::AlignHCenter:
1343 hscroll = (q->width() - widthUsed) / 2;
1353 void QDeclarative1TextInput::drawContents(QPainter *p, const QRect &r)
1355 Q_D(QDeclarative1TextInput);
1356 p->setRenderHint(QPainter::TextAntialiasing, true);
1358 p->setPen(QPen(d->color));
1359 int flags = QWidgetLineControl::DrawText;
1360 if(!isReadOnly() && d->cursorVisible && !d->cursorItem)
1361 flags |= QWidgetLineControl::DrawCursor;
1362 if (d->control->hasSelectedText())
1363 flags |= QWidgetLineControl::DrawSelections;
1364 QPoint offset = QPoint(0,0);
1365 QFontMetrics fm = QFontMetrics(d->font);
1366 QRect br(boundingRect().toRect());
1367 if (d->autoScroll) {
1368 // the y offset is there to keep the baseline constant in case we have script changes in the text.
1369 offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent());
1371 offset = QPoint(d->hscroll, 0);
1373 d->control->draw(p, offset, r, flags);
1379 Returns the value of the given \a property.
1381 QVariant QDeclarative1TextInput::inputMethodQuery(Qt::InputMethodQuery property) const
1383 Q_D(const QDeclarative1TextInput);
1385 case Qt::ImMicroFocus:
1386 return cursorRectangle();
1389 case Qt::ImCursorPosition:
1390 return QVariant(d->control->cursor());
1391 case Qt::ImSurroundingText:
1392 if (d->control->echoMode() == PasswordEchoOnEdit
1393 && !d->control->passwordEchoEditing())
1394 return QVariant(displayText());
1396 return QVariant(d->control->realText());
1397 case Qt::ImCurrentSelection:
1398 return QVariant(selectedText());
1399 case Qt::ImMaximumTextLength:
1400 return QVariant(maxLength());
1401 case Qt::ImAnchorPosition:
1402 if (d->control->selectionStart() == d->control->selectionEnd())
1403 return QVariant(d->control->cursor());
1404 else if (d->control->selectionStart() == d->control->cursor())
1405 return QVariant(d->control->selectionEnd());
1407 return QVariant(d->control->selectionStart());
1414 \qmlmethod void QtQuick1::TextInput::deselect()
1417 Removes active text selection.
1419 void QDeclarative1TextInput::deselect()
1421 Q_D(QDeclarative1TextInput);
1422 d->control->deselect();
1426 \qmlmethod void QtQuick1::TextInput::selectAll()
1428 Causes all text to be selected.
1430 void QDeclarative1TextInput::selectAll()
1432 Q_D(QDeclarative1TextInput);
1433 d->control->setSelection(0, d->control->text().length());
1437 \qmlmethod void QtQuick1::TextInput::isRightToLeft(int start, int end)
1439 Returns true if the natural reading direction of the editor text
1440 found between positions \a start and \a end is right to left.
1442 bool QDeclarative1TextInput::isRightToLeft(int start, int end)
1444 Q_D(QDeclarative1TextInput);
1446 qmlInfo(this) << "isRightToLeft(start, end) called with the end property being smaller than the start.";
1449 return d->control->text().mid(start, end - start).isRightToLeft();
1453 #ifndef QT_NO_CLIPBOARD
1455 \qmlmethod QtQuick1::TextInput::cut()
1457 Moves the currently selected text to the system clipboard.
1459 void QDeclarative1TextInput::cut()
1461 Q_D(QDeclarative1TextInput);
1467 \qmlmethod QtQuick1::TextInput::copy()
1469 Copies the currently selected text to the system clipboard.
1471 void QDeclarative1TextInput::copy()
1473 Q_D(QDeclarative1TextInput);
1478 \qmlmethod QtQuick1::TextInput::paste()
1480 Replaces the currently selected text by the contents of the system clipboard.
1482 void QDeclarative1TextInput::paste()
1484 Q_D(QDeclarative1TextInput);
1485 if(!d->control->isReadOnly())
1486 d->control->paste();
1488 #endif // QT_NO_CLIPBOARD
1491 \qmlmethod void QtQuick1::TextInput::selectWord()
1493 Causes the word closest to the current cursor position to be selected.
1495 void QDeclarative1TextInput::selectWord()
1497 Q_D(QDeclarative1TextInput);
1498 d->control->selectWordAtPos(d->control->cursor());
1502 \qmlproperty bool QtQuick1::TextInput::smooth
1504 This property holds whether the text is smoothly scaled or transformed.
1506 Smooth filtering gives better visual quality, but is slower. If
1507 the item is displayed at its natural size, this property has no visual or
1510 \note Generally scaling artifacts are only visible if the item is stationary on
1511 the screen. A common pattern when animating an item is to disable smooth
1512 filtering at the beginning of the animation and reenable it at the conclusion.
1516 \qmlproperty string QtQuick1::TextInput::passwordCharacter
1518 This is the character displayed when echoMode is set to Password or
1519 PasswordEchoOnEdit. By default it is an asterisk.
1521 If this property is set to a string with more than one character,
1522 the first character is used. If the string is empty, the value
1523 is ignored and the property is not set.
1525 QString QDeclarative1TextInput::passwordCharacter() const
1527 Q_D(const QDeclarative1TextInput);
1528 return QString(d->control->passwordCharacter());
1531 void QDeclarative1TextInput::setPasswordCharacter(const QString &str)
1533 Q_D(QDeclarative1TextInput);
1534 if(str.length() < 1)
1536 d->control->setPasswordCharacter(str.constData()[0]);
1537 EchoMode echoMode_ = echoMode();
1538 if (echoMode_ == Password || echoMode_ == PasswordEchoOnEdit) {
1541 emit passwordCharacterChanged();
1545 \qmlproperty string QtQuick1::TextInput::displayText
1547 This is the text displayed in the TextInput.
1549 If \l echoMode is set to TextInput::Normal, this holds the
1550 same value as the TextInput::text property. Otherwise,
1551 this property holds the text visible to the user, while
1552 the \l text property holds the actual entered text.
1554 QString QDeclarative1TextInput::displayText() const
1556 Q_D(const QDeclarative1TextInput);
1557 return d->control->displayText();
1561 \qmlproperty bool QtQuick1::TextInput::selectByMouse
1565 If true, the user can use the mouse to select text in some
1566 platform-specific way. Note that for some platforms this may
1567 not be an appropriate interaction (eg. may conflict with how
1568 the text needs to behave inside a Flickable.
1570 bool QDeclarative1TextInput::selectByMouse() const
1572 Q_D(const QDeclarative1TextInput);
1573 return d->selectByMouse;
1576 void QDeclarative1TextInput::setSelectByMouse(bool on)
1578 Q_D(QDeclarative1TextInput);
1579 if (d->selectByMouse != on) {
1580 d->selectByMouse = on;
1581 emit selectByMouseChanged(on);
1586 \qmlproperty enum QtQuick1::TextInput::mouseSelectionMode
1589 Specifies how text should be selected using a mouse.
1592 \o TextInput.SelectCharacters - The selection is updated with individual characters. (Default)
1593 \o TextInput.SelectWords - The selection is updated with whole words.
1596 This property only applies when \l selectByMouse is true.
1599 QDeclarative1TextInput::SelectionMode QDeclarative1TextInput::mouseSelectionMode() const
1601 Q_D(const QDeclarative1TextInput);
1602 return d->mouseSelectionMode;
1605 void QDeclarative1TextInput::setMouseSelectionMode(SelectionMode mode)
1607 Q_D(QDeclarative1TextInput);
1608 if (d->mouseSelectionMode != mode) {
1609 d->mouseSelectionMode = mode;
1610 emit mouseSelectionModeChanged(mode);
1615 \qmlproperty bool QtQuick1::TextInput::canPaste
1618 Returns true if the TextInput is writable and the content of the clipboard is
1619 suitable for pasting into the TextEdit.
1621 bool QDeclarative1TextInput::canPaste() const
1623 Q_D(const QDeclarative1TextInput);
1627 void QDeclarative1TextInput::moveCursorSelection(int position)
1629 Q_D(QDeclarative1TextInput);
1630 d->control->moveCursor(position, true);
1634 \qmlmethod void QtQuick1::TextInput::moveCursorSelection(int position, SelectionMode mode = TextInput.SelectCharacters)
1637 Moves the cursor to \a position and updates the selection according to the optional \a mode
1638 parameter. (To only move the cursor, set the \l cursorPosition property.)
1640 When this method is called it additionally sets either the
1641 selectionStart or the selectionEnd (whichever was at the previous cursor position)
1642 to the specified position. This allows you to easily extend and contract the selected
1645 The selection mode specifies whether the selection is updated on a per character or a per word
1646 basis. If not specified the selection mode will default to TextInput.SelectCharacters.
1649 \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
1650 the previous cursor position) to the specified position.
1651 \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all
1652 words between the specified postion and the previous cursor position. Words partially in the
1656 For example, take this sequence of calls:
1660 moveCursorSelection(9, TextInput.SelectCharacters)
1661 moveCursorSelection(7, TextInput.SelectCharacters)
1664 This moves the cursor to position 5, extend the selection end from 5 to 9
1665 and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
1666 selected (the 6th and 7th characters).
1668 The same sequence with TextInput.SelectWords will extend the selection start to a word boundary
1669 before or on position 5 and extend the selection end to a word boundary on or past position 9.
1671 void QDeclarative1TextInput::moveCursorSelection(int pos, SelectionMode mode)
1673 Q_D(QDeclarative1TextInput);
1675 if (mode == SelectCharacters) {
1676 d->control->moveCursor(pos, true);
1677 } else if (pos != d->control->cursor()){
1678 const int cursor = d->control->cursor();
1680 if (!d->control->hasSelectedText())
1681 anchor = d->control->cursor();
1682 else if (d->control->selectionStart() == d->control->cursor())
1683 anchor = d->control->selectionEnd();
1685 anchor = d->control->selectionStart();
1687 if (anchor < pos || (anchor == pos && cursor < pos)) {
1688 const QString text = d->control->text();
1689 QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
1690 finder.setPosition(anchor);
1692 const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
1693 if (anchor < text.length() && (!(reasons & QTextBoundaryFinder::StartWord)
1694 || ((reasons & QTextBoundaryFinder::EndWord) && anchor > cursor))) {
1695 finder.toPreviousBoundary();
1697 anchor = finder.position() != -1 ? finder.position() : 0;
1699 finder.setPosition(pos);
1700 if (pos > 0 && !finder.boundaryReasons())
1701 finder.toNextBoundary();
1702 const int cursor = finder.position() != -1 ? finder.position() : text.length();
1704 d->control->setSelection(anchor, cursor - anchor);
1705 } else if (anchor > pos || (anchor == pos && cursor > pos)) {
1706 const QString text = d->control->text();
1707 QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
1708 finder.setPosition(anchor);
1710 const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
1711 if (anchor > 0 && (!(reasons & QTextBoundaryFinder::EndWord)
1712 || ((reasons & QTextBoundaryFinder::StartWord) && anchor < cursor))) {
1713 finder.toNextBoundary();
1715 anchor = finder.position() != -1 ? finder.position() : text.length();
1717 finder.setPosition(pos);
1718 if (pos < text.length() && !finder.boundaryReasons())
1719 finder.toPreviousBoundary();
1720 const int cursor = finder.position() != -1 ? finder.position() : 0;
1722 d->control->setSelection(anchor, cursor - anchor);
1728 \qmlmethod void QtQuick1::TextInput::openSoftwareInputPanel()
1730 Opens software input panels like virtual keyboards for typing, useful for
1731 customizing when you want the input keyboard to be shown and hidden in
1734 By default the opening of input panels follows the platform style. On Symbian^1 and
1735 Symbian^3 -based devices the panels are opened by clicking TextInput. On other platforms
1736 the panels are automatically opened when TextInput element gains active focus. Input panels are
1737 always closed if no editor has active focus.
1739 . You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1740 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1741 the behavior you want.
1743 Only relevant on platforms, which provide virtual keyboards.
1749 text: "Hello world!"
1750 activeFocusOnPress: false
1752 anchors.fill: parent
1754 if (!textInput.activeFocus) {
1755 textInput.forceActiveFocus()
1756 textInput.openSoftwareInputPanel();
1758 textInput.focus = false;
1761 onPressAndHold: textInput.closeSoftwareInputPanel();
1766 void QDeclarative1TextInput::openSoftwareInputPanel()
1769 if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1770 if (view->scene() && view->scene() == scene()) {
1771 qApp->inputPanel()->show();
1778 \qmlmethod void QtQuick1::TextInput::closeSoftwareInputPanel()
1780 Closes a software input panel like a virtual keyboard shown on the screen, useful
1781 for customizing when you want the input keyboard to be shown and hidden in
1784 By default the opening of input panels follows the platform style. On Symbian^1 and
1785 Symbian^3 -based devices the panels are opened by clicking TextInput. On other platforms
1786 the panels are automatically opened when TextInput element gains active focus. Input panels are
1787 always closed if no editor has active focus.
1789 . You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1790 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1791 the behavior you want.
1793 Only relevant on platforms, which provide virtual keyboards.
1799 text: "Hello world!"
1800 activeFocusOnPress: false
1802 anchors.fill: parent
1804 if (!textInput.activeFocus) {
1805 textInput.forceActiveFocus();
1806 textInput.openSoftwareInputPanel();
1808 textInput.focus = false;
1811 onPressAndHold: textInput.closeSoftwareInputPanel();
1816 void QDeclarative1TextInput::closeSoftwareInputPanel()
1819 if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1820 if (view->scene() && view->scene() == scene()) {
1821 qApp->inputPanel()->hide();
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->determineHorizontalAlignment();
1921 d->updateHorizontalScroll();
1922 updateRect();//TODO: Only update rect between pos's
1924 emit cursorRectangleChanged();
1926 d->cursorItem->setX(d->control->cursorToX() - d->hscroll);
1929 void QDeclarative1TextInput::selectionChanged()
1931 Q_D(QDeclarative1TextInput);
1932 updateRect();//TODO: Only update rect in selection
1933 emit selectedTextChanged();
1935 if(d->lastSelectionStart != d->control->selectionStart()){
1936 d->lastSelectionStart = d->control->selectionStart();
1937 if(d->lastSelectionStart == -1)
1938 d->lastSelectionStart = d->control->cursor();
1939 emit selectionStartChanged();
1941 if(d->lastSelectionEnd != d->control->selectionEnd()){
1942 d->lastSelectionEnd = d->control->selectionEnd();
1943 if(d->lastSelectionEnd == -1)
1944 d->lastSelectionEnd = d->control->cursor();
1945 emit selectionEndChanged();
1949 void QDeclarative1TextInput::q_textChanged()
1951 Q_D(QDeclarative1TextInput);
1953 emit displayTextChanged();
1955 d->determineHorizontalAlignment();
1956 d->updateHorizontalScroll();
1958 if(hasAcceptableInput() != d->oldValidity){
1959 d->oldValidity = hasAcceptableInput();
1960 emit acceptableInputChanged();
1964 void QDeclarative1TextInput::updateRect(const QRect &r)
1966 Q_D(QDeclarative1TextInput);
1970 dirtyCache(QRect(r.x() - d->hscroll, r.y(), r.width(), r.height()));
1974 QRectF QDeclarative1TextInput::boundingRect() const
1976 Q_D(const QDeclarative1TextInput);
1977 QRectF r = QDeclarative1PaintedItem::boundingRect();
1979 int cursorWidth = d->cursorItem ? d->cursorItem->width() : d->control->cursorWidth();
1981 // Could include font max left/right bearings to either side of rectangle.
1983 r.setRight(r.right() + cursorWidth);
1987 void QDeclarative1TextInput::updateSize(bool needsRedraw)
1989 Q_D(QDeclarative1TextInput);
1992 setImplicitHeight(d->control->height()-1); // -1 to counter QWidgetLineControl's +1 which is not consistent with Text.
1993 setImplicitWidth(d->calculateTextWidth());
1994 setContentsSize(QSize(width(), height()));//Repaints if changed
1995 if(w==width() && h==height() && needsRedraw){
2001 void QDeclarative1TextInput::q_canPasteChanged()
2003 Q_D(QDeclarative1TextInput);
2004 bool old = d->canPaste;
2005 #ifndef QT_NO_CLIPBOARD
2006 d->canPaste = !d->control->isReadOnly() && QApplication::clipboard()->text().length() != 0;
2008 if(d->canPaste != old)
2009 emit canPasteChanged();
2016 #endif // QT_NO_LINEEDIT