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 <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 ? QApplication::keyboardInputDirection() == 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 // QLineControl 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((QLineControl::EchoMode)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 QLineControl'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);//QLineControl sets it on key events, but doesn't deal with focus events
1069 control->deselect();
1070 QDeclarativeItemPrivate::focusChanged(hasFocus);
1073 void QDeclarative1TextInput::keyPressEvent(QKeyEvent* ev)
1075 Q_D(QDeclarative1TextInput);
1076 keyPressPreHandler(ev);
1077 if (ev->isAccepted())
1080 // Don't allow MacOSX up/down support, and we don't allow a completer.
1081 bool ignore = (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) && ev->modifiers() == Qt::NoModifier;
1082 if (!ignore && (d->lastSelectionStart == d->lastSelectionEnd) && (ev->key() == Qt::Key_Right || ev->key() == Qt::Key_Left)) {
1083 // Ignore when moving off the end unless there is a selection,
1084 // because then moving will do something (deselect).
1085 int cursorPosition = d->control->cursor();
1086 if (cursorPosition == 0)
1087 ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Left : Qt::Key_Right);
1088 if (cursorPosition == d->control->text().length())
1089 ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Right : Qt::Key_Left);
1094 d->control->processKeyEvent(ev);
1096 if (!ev->isAccepted())
1097 QDeclarative1PaintedItem::keyPressEvent(ev);
1100 void QDeclarative1TextInput::inputMethodEvent(QInputMethodEvent *ev)
1102 Q_D(QDeclarative1TextInput);
1104 const bool wasComposing = d->control->preeditAreaText().length() > 0;
1105 inputMethodPreHandler(ev);
1106 if (!ev->isAccepted()) {
1107 if (d->control->isReadOnly()) {
1110 d->control->processInputMethodEvent(ev);
1113 if (!ev->isAccepted())
1114 QDeclarative1PaintedItem::inputMethodEvent(ev);
1116 if (wasComposing != (d->control->preeditAreaText().length() > 0))
1117 emit inputMethodComposingChanged();
1122 Handles the given mouse \a event.
1124 void QDeclarative1TextInput::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
1126 Q_D(QDeclarative1TextInput);
1127 if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonDblClick))
1129 if (d->selectByMouse) {
1130 int cursor = d->xToPos(event->pos().x());
1131 d->control->selectWordAtPos(cursor);
1132 event->setAccepted(true);
1134 QDeclarative1PaintedItem::mouseDoubleClickEvent(event);
1138 void QDeclarative1TextInput::mousePressEvent(QGraphicsSceneMouseEvent *event)
1140 Q_D(QDeclarative1TextInput);
1141 if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonPress))
1143 if(d->focusOnPress){
1144 bool hadActiveFocus = hasActiveFocus();
1146 if (d->showInputPanelOnFocus) {
1147 if (hasActiveFocus() && hadActiveFocus && !isReadOnly()) {
1148 // re-open input panel on press if already focused
1149 openSoftwareInputPanel();
1151 } else { // show input panel on click
1152 if (hasActiveFocus() && !hadActiveFocus) {
1153 d->clickCausedFocus = true;
1157 if (d->selectByMouse) {
1158 setKeepMouseGrab(false);
1159 d->selectPressed = true;
1160 d->pressPos = event->pos();
1162 bool mark = (event->modifiers() & Qt::ShiftModifier) && d->selectByMouse;
1163 int cursor = d->xToPos(event->pos().x());
1164 d->control->moveCursor(cursor, mark);
1165 event->setAccepted(true);
1168 void QDeclarative1TextInput::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
1170 Q_D(QDeclarative1TextInput);
1171 if (d->sendMouseEventToInputContext(event, QEvent::MouseMove))
1173 if (d->selectPressed) {
1174 if (qAbs(int(event->pos().x() - d->pressPos.x())) > QApplication::startDragDistance())
1175 setKeepMouseGrab(true);
1176 moveCursorSelection(d->xToPos(event->pos().x()), d->mouseSelectionMode);
1177 event->setAccepted(true);
1179 QDeclarative1PaintedItem::mouseMoveEvent(event);
1185 Handles the given mouse \a event.
1187 void QDeclarative1TextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
1189 Q_D(QDeclarative1TextInput);
1190 if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonRelease))
1192 if (d->selectPressed) {
1193 d->selectPressed = false;
1194 setKeepMouseGrab(false);
1196 if (!d->showInputPanelOnFocus) { // input panel on click
1197 if (d->focusOnPress && !isReadOnly() && boundingRect().contains(event->pos())) {
1198 if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1199 if (view->scene() && view->scene() == scene()) {
1200 qt_widget_private(view)->handleSoftwareInputPanel(event->button(), d->clickCausedFocus);
1205 d->clickCausedFocus = false;
1206 d->control->processEvent(event);
1207 if (!event->isAccepted())
1208 QDeclarative1PaintedItem::mouseReleaseEvent(event);
1211 bool QDeclarative1TextInputPrivate::sendMouseEventToInputContext(
1212 QGraphicsSceneMouseEvent *event, QEvent::Type eventType)
1214 #if !defined QT_NO_IM
1215 if (event->widget() && control->composeMode()) {
1216 int tmp_cursor = xToPos(event->pos().x());
1217 int mousePos = tmp_cursor - control->cursor();
1218 if (mousePos < 0 || mousePos > control->preeditAreaText().length()) {
1220 // don't send move events outside the preedit area
1221 if (eventType == QEvent::MouseMove)
1225 QInputContext *qic = event->widget()->inputContext();
1227 QMouseEvent mouseEvent(
1229 event->widget()->mapFromGlobal(event->screenPos()),
1233 event->modifiers());
1234 // may be causing reset() in some input methods
1235 qic->mouseHandler(mousePos, &mouseEvent);
1236 event->setAccepted(mouseEvent.isAccepted());
1238 if (!control->preeditAreaText().isEmpty())
1249 bool QDeclarative1TextInput::sceneEvent(QEvent *event)
1251 Q_D(QDeclarative1TextInput);
1252 bool rv = QDeclarativeItem::sceneEvent(event);
1253 if (event->type() == QEvent::UngrabMouse) {
1254 d->selectPressed = false;
1255 setKeepMouseGrab(false);
1260 bool QDeclarative1TextInput::event(QEvent* ev)
1262 Q_D(QDeclarative1TextInput);
1263 //Anything we don't deal with ourselves, pass to the control
1264 bool handled = false;
1266 case QEvent::KeyPress:
1267 case QEvent::KeyRelease://###Should the control be doing anything with release?
1268 case QEvent::InputMethod:
1269 case QEvent::GraphicsSceneMousePress:
1270 case QEvent::GraphicsSceneMouseMove:
1271 case QEvent::GraphicsSceneMouseRelease:
1272 case QEvent::GraphicsSceneMouseDoubleClick:
1275 handled = d->control->processEvent(ev);
1278 handled = QDeclarative1PaintedItem::event(ev);
1282 void QDeclarative1TextInput::geometryChanged(const QRectF &newGeometry,
1283 const QRectF &oldGeometry)
1285 if (newGeometry.width() != oldGeometry.width()) {
1287 updateCursorRectangle();
1289 QDeclarative1PaintedItem::geometryChanged(newGeometry, oldGeometry);
1292 int QDeclarative1TextInputPrivate::calculateTextWidth()
1294 return qRound(control->naturalTextWidth());
1297 void QDeclarative1TextInputPrivate::updateHorizontalScroll()
1299 Q_Q(QDeclarative1TextInput);
1300 const int preeditLength = control->preeditAreaText().length();
1301 int cix = qRound(control->cursorToX(control->cursor() + preeditLength));
1302 QRect br(q->boundingRect().toRect());
1303 int widthUsed = calculateTextWidth();
1305 QDeclarative1TextInput::HAlignment effectiveHAlign = q->effectiveHAlign();
1307 if (widthUsed <= br.width()) {
1308 // text fits in br; use hscroll for alignment
1309 switch (effectiveHAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) {
1310 case Qt::AlignRight:
1311 hscroll = widthUsed - br.width() - 1;
1313 case Qt::AlignHCenter:
1314 hscroll = (widthUsed - br.width()) / 2;
1321 } else if (cix - hscroll >= br.width()) {
1322 // text doesn't fit, cursor is to the right of br (scroll right)
1323 hscroll = cix - br.width() + 1;
1324 } else if (cix - hscroll < 0 && hscroll < widthUsed) {
1325 // text doesn't fit, cursor is to the left of br (scroll left)
1327 } else if (widthUsed - hscroll < br.width()) {
1328 // text doesn't fit, text document is to the left of br; align
1330 hscroll = widthUsed - br.width() + 1;
1332 if (preeditLength > 0) {
1333 // check to ensure long pre-edit text doesn't push the cursor
1335 cix = qRound(control->cursorToX(
1336 control->cursor() + qMax(0, control->preeditCursor() - 1)));
1341 switch (effectiveHAlign) {
1342 case QDeclarative1TextInput::AlignRight:
1343 hscroll = q->width() - widthUsed;
1345 case QDeclarative1TextInput::AlignHCenter:
1346 hscroll = (q->width() - widthUsed) / 2;
1356 void QDeclarative1TextInput::drawContents(QPainter *p, const QRect &r)
1358 Q_D(QDeclarative1TextInput);
1359 p->setRenderHint(QPainter::TextAntialiasing, true);
1361 p->setPen(QPen(d->color));
1362 int flags = QLineControl::DrawText;
1363 if(!isReadOnly() && d->cursorVisible && !d->cursorItem)
1364 flags |= QLineControl::DrawCursor;
1365 if (d->control->hasSelectedText())
1366 flags |= QLineControl::DrawSelections;
1367 QPoint offset = QPoint(0,0);
1368 QFontMetrics fm = QFontMetrics(d->font);
1369 QRect br(boundingRect().toRect());
1370 if (d->autoScroll) {
1371 // the y offset is there to keep the baseline constant in case we have script changes in the text.
1372 offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent());
1374 offset = QPoint(d->hscroll, 0);
1376 d->control->draw(p, offset, r, flags);
1382 Returns the value of the given \a property.
1384 QVariant QDeclarative1TextInput::inputMethodQuery(Qt::InputMethodQuery property) const
1386 Q_D(const QDeclarative1TextInput);
1388 case Qt::ImMicroFocus:
1389 return cursorRectangle();
1392 case Qt::ImCursorPosition:
1393 return QVariant(d->control->cursor());
1394 case Qt::ImSurroundingText:
1395 if (d->control->echoMode() == PasswordEchoOnEdit && !d->control->passwordEchoEditing())
1396 return QVariant(displayText());
1398 return QVariant(text());
1399 case Qt::ImCurrentSelection:
1400 return QVariant(selectedText());
1401 case Qt::ImMaximumTextLength:
1402 return QVariant(maxLength());
1403 case Qt::ImAnchorPosition:
1404 if (d->control->selectionStart() == d->control->selectionEnd())
1405 return QVariant(d->control->cursor());
1406 else if (d->control->selectionStart() == d->control->cursor())
1407 return QVariant(d->control->selectionEnd());
1409 return QVariant(d->control->selectionStart());
1416 \qmlmethod void QtQuick1::TextInput::deselect()
1419 Removes active text selection.
1421 void QDeclarative1TextInput::deselect()
1423 Q_D(QDeclarative1TextInput);
1424 d->control->deselect();
1428 \qmlmethod void QtQuick1::TextInput::selectAll()
1430 Causes all text to be selected.
1432 void QDeclarative1TextInput::selectAll()
1434 Q_D(QDeclarative1TextInput);
1435 d->control->setSelection(0, d->control->text().length());
1439 \qmlmethod void QtQuick1::TextInput::isRightToLeft(int start, int end)
1441 Returns true if the natural reading direction of the editor text
1442 found between positions \a start and \a end is right to left.
1444 bool QDeclarative1TextInput::isRightToLeft(int start, int end)
1446 Q_D(QDeclarative1TextInput);
1448 qmlInfo(this) << "isRightToLeft(start, end) called with the end property being smaller than the start.";
1451 return d->control->text().mid(start, end - start).isRightToLeft();
1455 #ifndef QT_NO_CLIPBOARD
1457 \qmlmethod QtQuick1::TextInput::cut()
1459 Moves the currently selected text to the system clipboard.
1461 void QDeclarative1TextInput::cut()
1463 Q_D(QDeclarative1TextInput);
1469 \qmlmethod QtQuick1::TextInput::copy()
1471 Copies the currently selected text to the system clipboard.
1473 void QDeclarative1TextInput::copy()
1475 Q_D(QDeclarative1TextInput);
1480 \qmlmethod QtQuick1::TextInput::paste()
1482 Replaces the currently selected text by the contents of the system clipboard.
1484 void QDeclarative1TextInput::paste()
1486 Q_D(QDeclarative1TextInput);
1487 if(!d->control->isReadOnly())
1488 d->control->paste();
1490 #endif // QT_NO_CLIPBOARD
1493 \qmlmethod void QtQuick1::TextInput::selectWord()
1495 Causes the word closest to the current cursor position to be selected.
1497 void QDeclarative1TextInput::selectWord()
1499 Q_D(QDeclarative1TextInput);
1500 d->control->selectWordAtPos(d->control->cursor());
1504 \qmlproperty bool QtQuick1::TextInput::smooth
1506 This property holds whether the text is smoothly scaled or transformed.
1508 Smooth filtering gives better visual quality, but is slower. If
1509 the item is displayed at its natural size, this property has no visual or
1512 \note Generally scaling artifacts are only visible if the item is stationary on
1513 the screen. A common pattern when animating an item is to disable smooth
1514 filtering at the beginning of the animation and reenable it at the conclusion.
1518 \qmlproperty string QtQuick1::TextInput::passwordCharacter
1520 This is the character displayed when echoMode is set to Password or
1521 PasswordEchoOnEdit. By default it is an asterisk.
1523 If this property is set to a string with more than one character,
1524 the first character is used. If the string is empty, the value
1525 is ignored and the property is not set.
1527 QString QDeclarative1TextInput::passwordCharacter() const
1529 Q_D(const QDeclarative1TextInput);
1530 return QString(d->control->passwordCharacter());
1533 void QDeclarative1TextInput::setPasswordCharacter(const QString &str)
1535 Q_D(QDeclarative1TextInput);
1536 if(str.length() < 1)
1538 d->control->setPasswordCharacter(str.constData()[0]);
1539 EchoMode echoMode_ = echoMode();
1540 if (echoMode_ == Password || echoMode_ == PasswordEchoOnEdit) {
1543 emit passwordCharacterChanged();
1547 \qmlproperty string QtQuick1::TextInput::displayText
1549 This is the text displayed in the TextInput.
1551 If \l echoMode is set to TextInput::Normal, this holds the
1552 same value as the TextInput::text property. Otherwise,
1553 this property holds the text visible to the user, while
1554 the \l text property holds the actual entered text.
1556 QString QDeclarative1TextInput::displayText() const
1558 Q_D(const QDeclarative1TextInput);
1559 return d->control->displayText();
1563 \qmlproperty bool QtQuick1::TextInput::selectByMouse
1567 If true, the user can use the mouse to select text in some
1568 platform-specific way. Note that for some platforms this may
1569 not be an appropriate interaction (eg. may conflict with how
1570 the text needs to behave inside a Flickable.
1572 bool QDeclarative1TextInput::selectByMouse() const
1574 Q_D(const QDeclarative1TextInput);
1575 return d->selectByMouse;
1578 void QDeclarative1TextInput::setSelectByMouse(bool on)
1580 Q_D(QDeclarative1TextInput);
1581 if (d->selectByMouse != on) {
1582 d->selectByMouse = on;
1583 emit selectByMouseChanged(on);
1588 \qmlproperty enum QtQuick1::TextInput::mouseSelectionMode
1591 Specifies how text should be selected using a mouse.
1594 \o TextInput.SelectCharacters - The selection is updated with individual characters. (Default)
1595 \o TextInput.SelectWords - The selection is updated with whole words.
1598 This property only applies when \l selectByMouse is true.
1601 QDeclarative1TextInput::SelectionMode QDeclarative1TextInput::mouseSelectionMode() const
1603 Q_D(const QDeclarative1TextInput);
1604 return d->mouseSelectionMode;
1607 void QDeclarative1TextInput::setMouseSelectionMode(SelectionMode mode)
1609 Q_D(QDeclarative1TextInput);
1610 if (d->mouseSelectionMode != mode) {
1611 d->mouseSelectionMode = mode;
1612 emit mouseSelectionModeChanged(mode);
1617 \qmlproperty bool QtQuick1::TextInput::canPaste
1620 Returns true if the TextInput is writable and the content of the clipboard is
1621 suitable for pasting into the TextEdit.
1623 bool QDeclarative1TextInput::canPaste() const
1625 Q_D(const QDeclarative1TextInput);
1629 void QDeclarative1TextInput::moveCursorSelection(int position)
1631 Q_D(QDeclarative1TextInput);
1632 d->control->moveCursor(position, true);
1636 \qmlmethod void QtQuick1::TextInput::moveCursorSelection(int position, SelectionMode mode = TextInput.SelectCharacters)
1639 Moves the cursor to \a position and updates the selection according to the optional \a mode
1640 parameter. (To only move the cursor, set the \l cursorPosition property.)
1642 When this method is called it additionally sets either the
1643 selectionStart or the selectionEnd (whichever was at the previous cursor position)
1644 to the specified position. This allows you to easily extend and contract the selected
1647 The selection mode specifies whether the selection is updated on a per character or a per word
1648 basis. If not specified the selection mode will default to TextInput.SelectCharacters.
1651 \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
1652 the previous cursor position) to the specified position.
1653 \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all
1654 words between the specified postion and the previous cursor position. Words partially in the
1658 For example, take this sequence of calls:
1662 moveCursorSelection(9, TextInput.SelectCharacters)
1663 moveCursorSelection(7, TextInput.SelectCharacters)
1666 This moves the cursor to position 5, extend the selection end from 5 to 9
1667 and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
1668 selected (the 6th and 7th characters).
1670 The same sequence with TextInput.SelectWords will extend the selection start to a word boundary
1671 before or on position 5 and extend the selection end to a word boundary on or past position 9.
1673 void QDeclarative1TextInput::moveCursorSelection(int pos, SelectionMode mode)
1675 Q_D(QDeclarative1TextInput);
1677 if (mode == SelectCharacters) {
1678 d->control->moveCursor(pos, true);
1679 } else if (pos != d->control->cursor()){
1680 const int cursor = d->control->cursor();
1682 if (!d->control->hasSelectedText())
1683 anchor = d->control->cursor();
1684 else if (d->control->selectionStart() == d->control->cursor())
1685 anchor = d->control->selectionEnd();
1687 anchor = d->control->selectionStart();
1689 if (anchor < pos || (anchor == pos && cursor < pos)) {
1690 const QString text = d->control->text();
1691 QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
1692 finder.setPosition(anchor);
1694 const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
1695 if (anchor < text.length() && (!(reasons & QTextBoundaryFinder::StartWord)
1696 || ((reasons & QTextBoundaryFinder::EndWord) && anchor > cursor))) {
1697 finder.toPreviousBoundary();
1699 anchor = finder.position() != -1 ? finder.position() : 0;
1701 finder.setPosition(pos);
1702 if (pos > 0 && !finder.boundaryReasons())
1703 finder.toNextBoundary();
1704 const int cursor = finder.position() != -1 ? finder.position() : text.length();
1706 d->control->setSelection(anchor, cursor - anchor);
1707 } else if (anchor > pos || (anchor == pos && cursor > pos)) {
1708 const QString text = d->control->text();
1709 QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
1710 finder.setPosition(anchor);
1712 const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
1713 if (anchor > 0 && (!(reasons & QTextBoundaryFinder::EndWord)
1714 || ((reasons & QTextBoundaryFinder::StartWord) && anchor < cursor))) {
1715 finder.toNextBoundary();
1717 anchor = finder.position() != -1 ? finder.position() : text.length();
1719 finder.setPosition(pos);
1720 if (pos < text.length() && !finder.boundaryReasons())
1721 finder.toPreviousBoundary();
1722 const int cursor = finder.position() != -1 ? finder.position() : 0;
1724 d->control->setSelection(anchor, cursor - anchor);
1730 \qmlmethod void QtQuick1::TextInput::openSoftwareInputPanel()
1732 Opens software input panels like virtual keyboards for typing, useful for
1733 customizing when you want the input keyboard to be shown and hidden in
1736 By default the opening of input panels follows the platform style. On Symbian^1 and
1737 Symbian^3 -based devices the panels are opened by clicking TextInput. On other platforms
1738 the panels are automatically opened when TextInput element gains active focus. Input panels are
1739 always closed if no editor has active focus.
1741 . You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1742 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1743 the behavior you want.
1745 Only relevant on platforms, which provide virtual keyboards.
1751 text: "Hello world!"
1752 activeFocusOnPress: false
1754 anchors.fill: parent
1756 if (!textInput.activeFocus) {
1757 textInput.forceActiveFocus()
1758 textInput.openSoftwareInputPanel();
1760 textInput.focus = false;
1763 onPressAndHold: textInput.closeSoftwareInputPanel();
1768 void QDeclarative1TextInput::openSoftwareInputPanel()
1771 if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1772 if (view->scene() && view->scene() == scene()) {
1773 qApp->inputPanel()->show();
1780 \qmlmethod void QtQuick1::TextInput::closeSoftwareInputPanel()
1782 Closes a software input panel like a virtual keyboard shown on the screen, useful
1783 for customizing when you want the input keyboard to be shown and hidden in
1786 By default the opening of input panels follows the platform style. On Symbian^1 and
1787 Symbian^3 -based devices the panels are opened by clicking TextInput. On other platforms
1788 the panels are automatically opened when TextInput element gains active focus. Input panels are
1789 always closed if no editor has active focus.
1791 . You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1792 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1793 the behavior you want.
1795 Only relevant on platforms, which provide virtual keyboards.
1801 text: "Hello world!"
1802 activeFocusOnPress: false
1804 anchors.fill: parent
1806 if (!textInput.activeFocus) {
1807 textInput.forceActiveFocus();
1808 textInput.openSoftwareInputPanel();
1810 textInput.focus = false;
1813 onPressAndHold: textInput.closeSoftwareInputPanel();
1818 void QDeclarative1TextInput::closeSoftwareInputPanel()
1821 if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1822 if (view->scene() && view->scene() == scene()) {
1823 qApp->inputPanel()->hide();
1829 void QDeclarative1TextInput::focusInEvent(QFocusEvent *event)
1831 Q_D(const QDeclarative1TextInput);
1832 if (d->showInputPanelOnFocus) {
1833 if (d->focusOnPress && !isReadOnly()) {
1834 openSoftwareInputPanel();
1837 QDeclarative1PaintedItem::focusInEvent(event);
1841 \qmlproperty bool QtQuick1::TextInput::inputMethodComposing
1845 This property holds whether the TextInput has partial text input from an
1848 While it is composing an input method may rely on mouse or key events from
1849 the TextInput to edit or commit the partial text. This property can be
1850 used to determine when to disable events handlers that may interfere with
1851 the correct operation of an input method.
1853 bool QDeclarative1TextInput::isInputMethodComposing() const
1855 Q_D(const QDeclarative1TextInput);
1856 return d->control->preeditAreaText().length() > 0;
1859 void QDeclarative1TextInputPrivate::init()
1861 Q_Q(QDeclarative1TextInput);
1862 control->setParent(q);//Now mandatory due to accessibility changes
1863 control->setCursorWidth(1);
1864 control->setPasswordCharacter(QLatin1Char('*'));
1865 q->setSmooth(smooth);
1866 q->setAcceptedMouseButtons(Qt::LeftButton);
1867 q->setFlag(QGraphicsItem::ItemHasNoContents, false);
1868 q->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
1869 q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
1870 q, SLOT(cursorPosChanged()));
1871 q->connect(control, SIGNAL(selectionChanged()),
1872 q, SLOT(selectionChanged()));
1873 q->connect(control, SIGNAL(textChanged(QString)),
1874 q, SLOT(q_textChanged()));
1875 q->connect(control, SIGNAL(accepted()),
1876 q, SIGNAL(accepted()));
1877 q->connect(control, SIGNAL(updateNeeded(QRect)),
1878 q, SLOT(updateRect(QRect)));
1879 #ifndef QT_NO_CLIPBOARD
1880 q->connect(q, SIGNAL(readOnlyChanged(bool)),
1881 q, SLOT(q_canPasteChanged()));
1882 q->connect(QApplication::clipboard(), SIGNAL(dataChanged()),
1883 q, SLOT(q_canPasteChanged()));
1884 canPaste = !control->isReadOnly() && QApplication::clipboard()->text().length() != 0;
1885 #endif // QT_NO_CLIPBOARD
1886 q->connect(control, SIGNAL(updateMicroFocus()),
1887 q, SLOT(updateCursorRectangle()));
1888 q->connect(control, SIGNAL(displayTextChanged(QString)),
1889 q, SLOT(updateRect()));
1891 oldValidity = control->hasAcceptableInput();
1892 lastSelectionStart = 0;
1893 lastSelectionEnd = 0;
1894 QPalette p = control->palette();
1895 selectedTextColor = p.color(QPalette::HighlightedText);
1896 selectionColor = p.color(QPalette::Highlight);
1897 determineHorizontalAlignment();
1900 void QDeclarative1TextInput::cursorPosChanged()
1902 Q_D(QDeclarative1TextInput);
1903 updateCursorRectangle();
1904 emit cursorPositionChanged();
1905 d->control->resetCursorBlinkTimer();
1907 if(!d->control->hasSelectedText()){
1908 if(d->lastSelectionStart != d->control->cursor()){
1909 d->lastSelectionStart = d->control->cursor();
1910 emit selectionStartChanged();
1912 if(d->lastSelectionEnd != d->control->cursor()){
1913 d->lastSelectionEnd = d->control->cursor();
1914 emit selectionEndChanged();
1919 void QDeclarative1TextInput::updateCursorRectangle()
1921 Q_D(QDeclarative1TextInput);
1922 d->determineHorizontalAlignment();
1923 d->updateHorizontalScroll();
1924 updateRect();//TODO: Only update rect between pos's
1926 emit cursorRectangleChanged();
1928 d->cursorItem->setX(d->control->cursorToX() - d->hscroll);
1931 void QDeclarative1TextInput::selectionChanged()
1933 Q_D(QDeclarative1TextInput);
1934 updateRect();//TODO: Only update rect in selection
1935 emit selectedTextChanged();
1937 if(d->lastSelectionStart != d->control->selectionStart()){
1938 d->lastSelectionStart = d->control->selectionStart();
1939 if(d->lastSelectionStart == -1)
1940 d->lastSelectionStart = d->control->cursor();
1941 emit selectionStartChanged();
1943 if(d->lastSelectionEnd != d->control->selectionEnd()){
1944 d->lastSelectionEnd = d->control->selectionEnd();
1945 if(d->lastSelectionEnd == -1)
1946 d->lastSelectionEnd = d->control->cursor();
1947 emit selectionEndChanged();
1951 void QDeclarative1TextInput::q_textChanged()
1953 Q_D(QDeclarative1TextInput);
1955 emit displayTextChanged();
1957 d->determineHorizontalAlignment();
1958 d->updateHorizontalScroll();
1960 if(hasAcceptableInput() != d->oldValidity){
1961 d->oldValidity = hasAcceptableInput();
1962 emit acceptableInputChanged();
1966 void QDeclarative1TextInput::updateRect(const QRect &r)
1968 Q_D(QDeclarative1TextInput);
1972 dirtyCache(QRect(r.x() - d->hscroll, r.y(), r.width(), r.height()));
1976 QRectF QDeclarative1TextInput::boundingRect() const
1978 Q_D(const QDeclarative1TextInput);
1979 QRectF r = QDeclarative1PaintedItem::boundingRect();
1981 int cursorWidth = d->cursorItem ? d->cursorItem->width() : d->control->cursorWidth();
1983 // Could include font max left/right bearings to either side of rectangle.
1985 r.setRight(r.right() + cursorWidth);
1989 void QDeclarative1TextInput::updateSize(bool needsRedraw)
1991 Q_D(QDeclarative1TextInput);
1994 setImplicitHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
1995 setImplicitWidth(d->calculateTextWidth());
1996 setContentsSize(QSize(width(), height()));//Repaints if changed
1997 if(w==width() && h==height() && needsRedraw){
2003 void QDeclarative1TextInput::q_canPasteChanged()
2005 Q_D(QDeclarative1TextInput);
2006 bool old = d->canPaste;
2007 #ifndef QT_NO_CLIPBOARD
2008 d->canPaste = !d->control->isReadOnly() && QApplication::clipboard()->text().length() != 0;
2010 if(d->canPaste != old)
2011 emit canPasteChanged();
2018 #endif // QT_NO_LINEEDIT