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 // 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->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->selectByMouse && event->button() == Qt::LeftButton) {
1128 int cursor = d->xToPos(event->pos().x());
1129 d->control->selectWordAtPos(cursor);
1130 event->setAccepted(true);
1132 if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonDblClick))
1134 QDeclarative1PaintedItem::mouseDoubleClickEvent(event);
1138 void QDeclarative1TextInput::mousePressEvent(QGraphicsSceneMouseEvent *event)
1140 Q_D(QDeclarative1TextInput);
1142 d->pressPos = event->pos();
1144 if(d->focusOnPress){
1145 bool hadActiveFocus = hasActiveFocus();
1147 if (d->showInputPanelOnFocus) {
1148 if (hasActiveFocus() && hadActiveFocus && !isReadOnly()) {
1149 // re-open input panel on press if already focused
1150 openSoftwareInputPanel();
1152 } else { // show input panel on click
1153 if (hasActiveFocus() && !hadActiveFocus) {
1154 d->clickCausedFocus = true;
1158 if (d->selectByMouse) {
1159 setKeepMouseGrab(false);
1160 d->selectPressed = true;
1162 if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonPress))
1165 bool mark = (event->modifiers() & Qt::ShiftModifier) && d->selectByMouse;
1166 int cursor = d->xToPos(event->pos().x());
1167 d->control->moveCursor(cursor, mark);
1168 event->setAccepted(true);
1171 void QDeclarative1TextInput::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
1173 Q_D(QDeclarative1TextInput);
1175 if (d->selectPressed) {
1176 if (qAbs(int(event->pos().x() - d->pressPos.x())) > QApplication::startDragDistance())
1177 setKeepMouseGrab(true);
1179 if (d->control->composeMode()) {
1181 int startPos = d->xToPos(d->pressPos.x());
1182 int currentPos = d->xToPos(event->pos().x());
1183 if (startPos != currentPos)
1184 d->control->setSelection(startPos, currentPos - startPos);
1186 moveCursorSelection(d->xToPos(event->pos().x()), d->mouseSelectionMode);
1188 event->setAccepted(true);
1190 QDeclarative1PaintedItem::mouseMoveEvent(event);
1196 Handles the given mouse \a event.
1198 void QDeclarative1TextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
1200 Q_D(QDeclarative1TextInput);
1201 if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonRelease))
1203 if (d->selectPressed) {
1204 d->selectPressed = false;
1205 setKeepMouseGrab(false);
1207 if (!d->showInputPanelOnFocus) { // input panel on click
1208 if (d->focusOnPress && !isReadOnly() && boundingRect().contains(event->pos())) {
1209 if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1210 if (view->scene() && view->scene() == scene()) {
1211 qt_widget_private(view)->handleSoftwareInputPanel(event->button(), d->clickCausedFocus);
1216 d->clickCausedFocus = false;
1217 #ifndef QT_NO_CLIPBOARD
1218 if (QGuiApplication::clipboard()->supportsSelection()) {
1219 if (event->button() == Qt::LeftButton) {
1220 d->control->copy(QClipboard::Selection);
1221 } else if (!isReadOnly() && event->button() == Qt::MidButton) {
1222 d->control->deselect();
1223 d->control->insert(QGuiApplication::clipboard()->text(QClipboard::Selection));
1227 if (!event->isAccepted())
1228 QDeclarative1PaintedItem::mouseReleaseEvent(event);
1231 bool QDeclarative1TextInputPrivate::sendMouseEventToInputContext(
1232 QGraphicsSceneMouseEvent *event, QEvent::Type eventType)
1234 #if !defined QT_NO_IM
1235 if (event->widget() && control->composeMode()) {
1236 int tmp_cursor = xToPos(event->pos().x());
1237 int mousePos = tmp_cursor - control->cursor();
1238 if (mousePos >= 0 && mousePos <= control->preeditAreaText().length()) {
1239 if (eventType == QEvent::MouseButtonRelease) {
1240 qApp->inputPanel()->invokeAction(QInputPanel::Click, mousePos);
1253 bool QDeclarative1TextInput::sceneEvent(QEvent *event)
1255 Q_D(QDeclarative1TextInput);
1256 bool rv = QDeclarativeItem::sceneEvent(event);
1257 if (event->type() == QEvent::UngrabMouse) {
1258 d->selectPressed = false;
1259 setKeepMouseGrab(false);
1264 bool QDeclarative1TextInput::event(QEvent* ev)
1266 #ifndef QT_NO_SHORTCUT
1267 Q_D(QDeclarative1TextInput);
1269 if (ev->type() == QEvent::ShortcutOverride) {
1270 d->control->processShortcutOverrideEvent(static_cast<QKeyEvent *>(ev));
1271 return ev->isAccepted();
1274 return QDeclarative1PaintedItem::event(ev);
1277 void QDeclarative1TextInput::geometryChanged(const QRectF &newGeometry,
1278 const QRectF &oldGeometry)
1280 if (newGeometry.width() != oldGeometry.width()) {
1282 updateCursorRectangle();
1284 QDeclarative1PaintedItem::geometryChanged(newGeometry, oldGeometry);
1287 int QDeclarative1TextInputPrivate::calculateTextWidth()
1289 return qRound(control->naturalTextWidth());
1292 void QDeclarative1TextInputPrivate::updateHorizontalScroll()
1294 Q_Q(QDeclarative1TextInput);
1295 const int preeditLength = control->preeditAreaText().length();
1296 int cix = qRound(control->cursorToX(control->cursor() + preeditLength));
1297 QRect br(q->boundingRect().toRect());
1298 int widthUsed = calculateTextWidth();
1300 QDeclarative1TextInput::HAlignment effectiveHAlign = q->effectiveHAlign();
1302 if (widthUsed <= br.width()) {
1303 // text fits in br; use hscroll for alignment
1304 switch (effectiveHAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) {
1305 case Qt::AlignRight:
1306 hscroll = widthUsed - br.width() - 1;
1308 case Qt::AlignHCenter:
1309 hscroll = (widthUsed - br.width()) / 2;
1316 } else if (cix - hscroll >= br.width()) {
1317 // text doesn't fit, cursor is to the right of br (scroll right)
1318 hscroll = cix - br.width() + 1;
1319 } else if (cix - hscroll < 0 && hscroll < widthUsed) {
1320 // text doesn't fit, cursor is to the left of br (scroll left)
1322 } else if (widthUsed - hscroll < br.width()) {
1323 // text doesn't fit, text document is to the left of br; align
1325 hscroll = widthUsed - br.width() + 1;
1327 if (preeditLength > 0) {
1328 // check to ensure long pre-edit text doesn't push the cursor
1330 cix = qRound(control->cursorToX(
1331 control->cursor() + qMax(0, control->preeditCursor() - 1)));
1336 switch (effectiveHAlign) {
1337 case QDeclarative1TextInput::AlignRight:
1338 hscroll = q->width() - widthUsed;
1340 case QDeclarative1TextInput::AlignHCenter:
1341 hscroll = (q->width() - widthUsed) / 2;
1351 void QDeclarative1TextInput::drawContents(QPainter *p, const QRect &r)
1353 Q_D(QDeclarative1TextInput);
1354 p->setRenderHint(QPainter::TextAntialiasing, true);
1356 p->setPen(QPen(d->color));
1357 int flags = QWidgetLineControl::DrawText;
1358 if(!isReadOnly() && d->cursorVisible && !d->cursorItem)
1359 flags |= QWidgetLineControl::DrawCursor;
1360 if (d->control->hasSelectedText())
1361 flags |= QWidgetLineControl::DrawSelections;
1362 QPoint offset = QPoint(0,0);
1363 QFontMetrics fm = QFontMetrics(d->font);
1364 QRect br(boundingRect().toRect());
1365 if (d->autoScroll) {
1366 // the y offset is there to keep the baseline constant in case we have script changes in the text.
1367 offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent());
1369 offset = QPoint(d->hscroll, 0);
1371 d->control->draw(p, offset, r, flags);
1377 Returns the value of the given \a property.
1379 QVariant QDeclarative1TextInput::inputMethodQuery(Qt::InputMethodQuery property) const
1381 Q_D(const QDeclarative1TextInput);
1383 case Qt::ImMicroFocus:
1384 return cursorRectangle();
1387 case Qt::ImCursorPosition:
1388 return QVariant(d->control->cursor());
1389 case Qt::ImSurroundingText:
1390 if (d->control->echoMode() == PasswordEchoOnEdit
1391 && !d->control->passwordEchoEditing())
1392 return QVariant(displayText());
1394 return QVariant(d->control->realText());
1395 case Qt::ImCurrentSelection:
1396 return QVariant(selectedText());
1397 case Qt::ImMaximumTextLength:
1398 return QVariant(maxLength());
1399 case Qt::ImAnchorPosition:
1400 if (d->control->selectionStart() == d->control->selectionEnd())
1401 return QVariant(d->control->cursor());
1402 else if (d->control->selectionStart() == d->control->cursor())
1403 return QVariant(d->control->selectionEnd());
1405 return QVariant(d->control->selectionStart());
1412 \qmlmethod void QtQuick1::TextInput::deselect()
1415 Removes active text selection.
1417 void QDeclarative1TextInput::deselect()
1419 Q_D(QDeclarative1TextInput);
1420 d->control->deselect();
1424 \qmlmethod void QtQuick1::TextInput::selectAll()
1426 Causes all text to be selected.
1428 void QDeclarative1TextInput::selectAll()
1430 Q_D(QDeclarative1TextInput);
1431 d->control->setSelection(0, d->control->text().length());
1435 \qmlmethod void QtQuick1::TextInput::isRightToLeft(int start, int end)
1437 Returns true if the natural reading direction of the editor text
1438 found between positions \a start and \a end is right to left.
1440 bool QDeclarative1TextInput::isRightToLeft(int start, int end)
1442 Q_D(QDeclarative1TextInput);
1444 qmlInfo(this) << "isRightToLeft(start, end) called with the end property being smaller than the start.";
1447 return d->control->text().mid(start, end - start).isRightToLeft();
1451 #ifndef QT_NO_CLIPBOARD
1453 \qmlmethod QtQuick1::TextInput::cut()
1455 Moves the currently selected text to the system clipboard.
1457 void QDeclarative1TextInput::cut()
1459 Q_D(QDeclarative1TextInput);
1465 \qmlmethod QtQuick1::TextInput::copy()
1467 Copies the currently selected text to the system clipboard.
1469 void QDeclarative1TextInput::copy()
1471 Q_D(QDeclarative1TextInput);
1476 \qmlmethod QtQuick1::TextInput::paste()
1478 Replaces the currently selected text by the contents of the system clipboard.
1480 void QDeclarative1TextInput::paste()
1482 Q_D(QDeclarative1TextInput);
1483 if(!d->control->isReadOnly())
1484 d->control->paste();
1486 #endif // QT_NO_CLIPBOARD
1489 \qmlmethod void QtQuick1::TextInput::selectWord()
1491 Causes the word closest to the current cursor position to be selected.
1493 void QDeclarative1TextInput::selectWord()
1495 Q_D(QDeclarative1TextInput);
1496 d->control->selectWordAtPos(d->control->cursor());
1500 \qmlproperty bool QtQuick1::TextInput::smooth
1502 This property holds whether the text is smoothly scaled or transformed.
1504 Smooth filtering gives better visual quality, but is slower. If
1505 the item is displayed at its natural size, this property has no visual or
1508 \note Generally scaling artifacts are only visible if the item is stationary on
1509 the screen. A common pattern when animating an item is to disable smooth
1510 filtering at the beginning of the animation and reenable it at the conclusion.
1514 \qmlproperty string QtQuick1::TextInput::passwordCharacter
1516 This is the character displayed when echoMode is set to Password or
1517 PasswordEchoOnEdit. By default it is an asterisk.
1519 If this property is set to a string with more than one character,
1520 the first character is used. If the string is empty, the value
1521 is ignored and the property is not set.
1523 QString QDeclarative1TextInput::passwordCharacter() const
1525 Q_D(const QDeclarative1TextInput);
1526 return QString(d->control->passwordCharacter());
1529 void QDeclarative1TextInput::setPasswordCharacter(const QString &str)
1531 Q_D(QDeclarative1TextInput);
1532 if(str.length() < 1)
1534 d->control->setPasswordCharacter(str.constData()[0]);
1535 EchoMode echoMode_ = echoMode();
1536 if (echoMode_ == Password || echoMode_ == PasswordEchoOnEdit) {
1539 emit passwordCharacterChanged();
1543 \qmlproperty string QtQuick1::TextInput::displayText
1545 This is the text displayed in the TextInput.
1547 If \l echoMode is set to TextInput::Normal, this holds the
1548 same value as the TextInput::text property. Otherwise,
1549 this property holds the text visible to the user, while
1550 the \l text property holds the actual entered text.
1552 QString QDeclarative1TextInput::displayText() const
1554 Q_D(const QDeclarative1TextInput);
1555 return d->control->displayText();
1559 \qmlproperty bool QtQuick1::TextInput::selectByMouse
1563 If true, the user can use the mouse to select text in some
1564 platform-specific way. Note that for some platforms this may
1565 not be an appropriate interaction (eg. may conflict with how
1566 the text needs to behave inside a Flickable.
1568 bool QDeclarative1TextInput::selectByMouse() const
1570 Q_D(const QDeclarative1TextInput);
1571 return d->selectByMouse;
1574 void QDeclarative1TextInput::setSelectByMouse(bool on)
1576 Q_D(QDeclarative1TextInput);
1577 if (d->selectByMouse != on) {
1578 d->selectByMouse = on;
1579 emit selectByMouseChanged(on);
1584 \qmlproperty enum QtQuick1::TextInput::mouseSelectionMode
1587 Specifies how text should be selected using a mouse.
1590 \o TextInput.SelectCharacters - The selection is updated with individual characters. (Default)
1591 \o TextInput.SelectWords - The selection is updated with whole words.
1594 This property only applies when \l selectByMouse is true.
1597 QDeclarative1TextInput::SelectionMode QDeclarative1TextInput::mouseSelectionMode() const
1599 Q_D(const QDeclarative1TextInput);
1600 return d->mouseSelectionMode;
1603 void QDeclarative1TextInput::setMouseSelectionMode(SelectionMode mode)
1605 Q_D(QDeclarative1TextInput);
1606 if (d->mouseSelectionMode != mode) {
1607 d->mouseSelectionMode = mode;
1608 emit mouseSelectionModeChanged(mode);
1613 \qmlproperty bool QtQuick1::TextInput::canPaste
1616 Returns true if the TextInput is writable and the content of the clipboard is
1617 suitable for pasting into the TextEdit.
1619 bool QDeclarative1TextInput::canPaste() const
1621 Q_D(const QDeclarative1TextInput);
1625 void QDeclarative1TextInput::moveCursorSelection(int position)
1627 Q_D(QDeclarative1TextInput);
1628 d->control->moveCursor(position, true);
1632 \qmlmethod void QtQuick1::TextInput::moveCursorSelection(int position, SelectionMode mode = TextInput.SelectCharacters)
1635 Moves the cursor to \a position and updates the selection according to the optional \a mode
1636 parameter. (To only move the cursor, set the \l cursorPosition property.)
1638 When this method is called it additionally sets either the
1639 selectionStart or the selectionEnd (whichever was at the previous cursor position)
1640 to the specified position. This allows you to easily extend and contract the selected
1643 The selection mode specifies whether the selection is updated on a per character or a per word
1644 basis. If not specified the selection mode will default to TextInput.SelectCharacters.
1647 \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
1648 the previous cursor position) to the specified position.
1649 \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all
1650 words between the specified postion and the previous cursor position. Words partially in the
1654 For example, take this sequence of calls:
1658 moveCursorSelection(9, TextInput.SelectCharacters)
1659 moveCursorSelection(7, TextInput.SelectCharacters)
1662 This moves the cursor to position 5, extend the selection end from 5 to 9
1663 and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
1664 selected (the 6th and 7th characters).
1666 The same sequence with TextInput.SelectWords will extend the selection start to a word boundary
1667 before or on position 5 and extend the selection end to a word boundary on or past position 9.
1669 void QDeclarative1TextInput::moveCursorSelection(int pos, SelectionMode mode)
1671 Q_D(QDeclarative1TextInput);
1673 if (mode == SelectCharacters) {
1674 d->control->moveCursor(pos, true);
1675 } else if (pos != d->control->cursor()){
1676 const int cursor = d->control->cursor();
1678 if (!d->control->hasSelectedText())
1679 anchor = d->control->cursor();
1680 else if (d->control->selectionStart() == d->control->cursor())
1681 anchor = d->control->selectionEnd();
1683 anchor = d->control->selectionStart();
1685 if (anchor < pos || (anchor == pos && cursor < pos)) {
1686 const QString text = d->control->text();
1687 QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
1688 finder.setPosition(anchor);
1690 const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
1691 if (anchor < text.length() && (!(reasons & QTextBoundaryFinder::StartWord)
1692 || ((reasons & QTextBoundaryFinder::EndWord) && anchor > cursor))) {
1693 finder.toPreviousBoundary();
1695 anchor = finder.position() != -1 ? finder.position() : 0;
1697 finder.setPosition(pos);
1698 if (pos > 0 && !finder.boundaryReasons())
1699 finder.toNextBoundary();
1700 const int cursor = finder.position() != -1 ? finder.position() : text.length();
1702 d->control->setSelection(anchor, cursor - anchor);
1703 } else if (anchor > pos || (anchor == pos && cursor > pos)) {
1704 const QString text = d->control->text();
1705 QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
1706 finder.setPosition(anchor);
1708 const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
1709 if (anchor > 0 && (!(reasons & QTextBoundaryFinder::EndWord)
1710 || ((reasons & QTextBoundaryFinder::StartWord) && anchor < cursor))) {
1711 finder.toNextBoundary();
1713 anchor = finder.position() != -1 ? finder.position() : text.length();
1715 finder.setPosition(pos);
1716 if (pos < text.length() && !finder.boundaryReasons())
1717 finder.toPreviousBoundary();
1718 const int cursor = finder.position() != -1 ? finder.position() : 0;
1720 d->control->setSelection(anchor, cursor - anchor);
1726 \qmlmethod void QtQuick1::TextInput::openSoftwareInputPanel()
1728 Opens software input panels like virtual keyboards for typing, useful for
1729 customizing when you want the input keyboard to be shown and hidden in
1732 By default the opening of input panels follows the platform style. On Symbian^1 and
1733 Symbian^3 -based devices the panels are opened by clicking TextInput. On other platforms
1734 the panels are automatically opened when TextInput element gains active focus. Input panels are
1735 always closed if no editor has active focus.
1737 . You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1738 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1739 the behavior you want.
1741 Only relevant on platforms, which provide virtual keyboards.
1747 text: "Hello world!"
1748 activeFocusOnPress: false
1750 anchors.fill: parent
1752 if (!textInput.activeFocus) {
1753 textInput.forceActiveFocus()
1754 textInput.openSoftwareInputPanel();
1756 textInput.focus = false;
1759 onPressAndHold: textInput.closeSoftwareInputPanel();
1764 void QDeclarative1TextInput::openSoftwareInputPanel()
1767 if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1768 if (view->scene() && view->scene() == scene()) {
1769 qApp->inputPanel()->show();
1776 \qmlmethod void QtQuick1::TextInput::closeSoftwareInputPanel()
1778 Closes a software input panel like a virtual keyboard shown on the screen, useful
1779 for customizing when you want the input keyboard to be shown and hidden in
1782 By default the opening of input panels follows the platform style. On Symbian^1 and
1783 Symbian^3 -based devices the panels are opened by clicking TextInput. On other platforms
1784 the panels are automatically opened when TextInput element gains active focus. Input panels are
1785 always closed if no editor has active focus.
1787 . You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1788 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1789 the behavior you want.
1791 Only relevant on platforms, which provide virtual keyboards.
1797 text: "Hello world!"
1798 activeFocusOnPress: false
1800 anchors.fill: parent
1802 if (!textInput.activeFocus) {
1803 textInput.forceActiveFocus();
1804 textInput.openSoftwareInputPanel();
1806 textInput.focus = false;
1809 onPressAndHold: textInput.closeSoftwareInputPanel();
1814 void QDeclarative1TextInput::closeSoftwareInputPanel()
1817 if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1818 if (view->scene() && view->scene() == scene()) {
1819 qApp->inputPanel()->hide();
1825 void QDeclarative1TextInput::focusInEvent(QFocusEvent *event)
1827 Q_D(const QDeclarative1TextInput);
1828 if (d->showInputPanelOnFocus) {
1829 if (d->focusOnPress && !isReadOnly()) {
1830 openSoftwareInputPanel();
1833 QDeclarative1PaintedItem::focusInEvent(event);
1837 \qmlproperty bool QtQuick1::TextInput::inputMethodComposing
1841 This property holds whether the TextInput has partial text input from an
1844 While it is composing an input method may rely on mouse or key events from
1845 the TextInput to edit or commit the partial text. This property can be
1846 used to determine when to disable events handlers that may interfere with
1847 the correct operation of an input method.
1849 bool QDeclarative1TextInput::isInputMethodComposing() const
1851 Q_D(const QDeclarative1TextInput);
1852 return d->control->preeditAreaText().length() > 0;
1855 void QDeclarative1TextInputPrivate::init()
1857 Q_Q(QDeclarative1TextInput);
1858 control->setParent(q);//Now mandatory due to accessibility changes
1859 control->setCursorWidth(1);
1860 control->setPasswordCharacter(QLatin1Char('*'));
1861 q->setSmooth(smooth);
1862 q->setAcceptedMouseButtons(Qt::LeftButton);
1863 q->setFlag(QGraphicsItem::ItemHasNoContents, false);
1864 q->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
1865 q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
1866 q, SLOT(cursorPosChanged()));
1867 q->connect(control, SIGNAL(selectionChanged()),
1868 q, SLOT(selectionChanged()));
1869 q->connect(control, SIGNAL(textChanged(QString)),
1870 q, SLOT(q_textChanged()));
1871 q->connect(control, SIGNAL(accepted()),
1872 q, SIGNAL(accepted()));
1873 q->connect(control, SIGNAL(updateNeeded(QRect)),
1874 q, SLOT(updateRect(QRect)));
1875 #ifndef QT_NO_CLIPBOARD
1876 q->connect(q, SIGNAL(readOnlyChanged(bool)),
1877 q, SLOT(q_canPasteChanged()));
1878 q->connect(QApplication::clipboard(), SIGNAL(dataChanged()),
1879 q, SLOT(q_canPasteChanged()));
1880 canPaste = !control->isReadOnly() && QApplication::clipboard()->text().length() != 0;
1881 #endif // QT_NO_CLIPBOARD
1882 q->connect(control, SIGNAL(updateMicroFocus()),
1883 q, SLOT(updateCursorRectangle()));
1884 q->connect(control, SIGNAL(displayTextChanged(QString)),
1885 q, SLOT(updateRect()));
1887 oldValidity = control->hasAcceptableInput();
1888 lastSelectionStart = 0;
1889 lastSelectionEnd = 0;
1890 QPalette p = control->palette();
1891 selectedTextColor = p.color(QPalette::HighlightedText);
1892 selectionColor = p.color(QPalette::Highlight);
1893 determineHorizontalAlignment();
1896 void QDeclarative1TextInput::cursorPosChanged()
1898 Q_D(QDeclarative1TextInput);
1899 updateCursorRectangle();
1900 emit cursorPositionChanged();
1901 d->control->resetCursorBlinkTimer();
1903 if(!d->control->hasSelectedText()){
1904 if(d->lastSelectionStart != d->control->cursor()){
1905 d->lastSelectionStart = d->control->cursor();
1906 emit selectionStartChanged();
1908 if(d->lastSelectionEnd != d->control->cursor()){
1909 d->lastSelectionEnd = d->control->cursor();
1910 emit selectionEndChanged();
1915 void QDeclarative1TextInput::updateCursorRectangle()
1917 Q_D(QDeclarative1TextInput);
1918 d->determineHorizontalAlignment();
1919 d->updateHorizontalScroll();
1920 updateRect();//TODO: Only update rect between pos's
1922 emit cursorRectangleChanged();
1924 d->cursorItem->setX(d->control->cursorToX() - d->hscroll);
1927 void QDeclarative1TextInput::selectionChanged()
1929 Q_D(QDeclarative1TextInput);
1930 updateRect();//TODO: Only update rect in selection
1931 emit selectedTextChanged();
1933 if(d->lastSelectionStart != d->control->selectionStart()){
1934 d->lastSelectionStart = d->control->selectionStart();
1935 if(d->lastSelectionStart == -1)
1936 d->lastSelectionStart = d->control->cursor();
1937 emit selectionStartChanged();
1939 if(d->lastSelectionEnd != d->control->selectionEnd()){
1940 d->lastSelectionEnd = d->control->selectionEnd();
1941 if(d->lastSelectionEnd == -1)
1942 d->lastSelectionEnd = d->control->cursor();
1943 emit selectionEndChanged();
1947 void QDeclarative1TextInput::q_textChanged()
1949 Q_D(QDeclarative1TextInput);
1951 emit displayTextChanged();
1953 d->determineHorizontalAlignment();
1954 d->updateHorizontalScroll();
1956 if(hasAcceptableInput() != d->oldValidity){
1957 d->oldValidity = hasAcceptableInput();
1958 emit acceptableInputChanged();
1962 void QDeclarative1TextInput::updateRect(const QRect &r)
1964 Q_D(QDeclarative1TextInput);
1968 dirtyCache(QRect(r.x() - d->hscroll, r.y(), r.width(), r.height()));
1972 QRectF QDeclarative1TextInput::boundingRect() const
1974 Q_D(const QDeclarative1TextInput);
1975 QRectF r = QDeclarative1PaintedItem::boundingRect();
1977 int cursorWidth = d->cursorItem ? d->cursorItem->width() : d->control->cursorWidth();
1979 // Could include font max left/right bearings to either side of rectangle.
1981 r.setRight(r.right() + cursorWidth);
1985 void QDeclarative1TextInput::updateSize(bool needsRedraw)
1987 Q_D(QDeclarative1TextInput);
1990 setImplicitHeight(d->control->height()-1); // -1 to counter QWidgetLineControl's +1 which is not consistent with Text.
1991 setImplicitWidth(d->calculateTextWidth());
1992 setContentsSize(QSize(width(), height()));//Repaints if changed
1993 if(w==width() && h==height() && needsRedraw){
1999 void QDeclarative1TextInput::q_canPasteChanged()
2001 Q_D(QDeclarative1TextInput);
2002 bool old = d->canPaste;
2003 #ifndef QT_NO_CLIPBOARD
2004 d->canPaste = !d->control->isReadOnly() && QApplication::clipboard()->text().length() != 0;
2006 if(d->canPaste != old)
2007 emit canPasteChanged();
2014 #endif // QT_NO_LINEEDIT