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() == QLineControl::PasswordEchoOnEdit
1396 && !d->control->passwordEchoEditing())
1397 return QVariant(displayText());
1399 return QVariant(d->control->realText());
1400 case Qt::ImCurrentSelection:
1401 return QVariant(selectedText());
1402 case Qt::ImMaximumTextLength:
1403 return QVariant(maxLength());
1404 case Qt::ImAnchorPosition:
1405 if (d->control->selectionStart() == d->control->selectionEnd())
1406 return QVariant(d->control->cursor());
1407 else if (d->control->selectionStart() == d->control->cursor())
1408 return QVariant(d->control->selectionEnd());
1410 return QVariant(d->control->selectionStart());
1417 \qmlmethod void QtQuick1::TextInput::deselect()
1420 Removes active text selection.
1422 void QDeclarative1TextInput::deselect()
1424 Q_D(QDeclarative1TextInput);
1425 d->control->deselect();
1429 \qmlmethod void QtQuick1::TextInput::selectAll()
1431 Causes all text to be selected.
1433 void QDeclarative1TextInput::selectAll()
1435 Q_D(QDeclarative1TextInput);
1436 d->control->setSelection(0, d->control->text().length());
1440 \qmlmethod void QtQuick1::TextInput::isRightToLeft(int start, int end)
1442 Returns true if the natural reading direction of the editor text
1443 found between positions \a start and \a end is right to left.
1445 bool QDeclarative1TextInput::isRightToLeft(int start, int end)
1447 Q_D(QDeclarative1TextInput);
1449 qmlInfo(this) << "isRightToLeft(start, end) called with the end property being smaller than the start.";
1452 return d->control->text().mid(start, end - start).isRightToLeft();
1456 #ifndef QT_NO_CLIPBOARD
1458 \qmlmethod QtQuick1::TextInput::cut()
1460 Moves the currently selected text to the system clipboard.
1462 void QDeclarative1TextInput::cut()
1464 Q_D(QDeclarative1TextInput);
1470 \qmlmethod QtQuick1::TextInput::copy()
1472 Copies the currently selected text to the system clipboard.
1474 void QDeclarative1TextInput::copy()
1476 Q_D(QDeclarative1TextInput);
1481 \qmlmethod QtQuick1::TextInput::paste()
1483 Replaces the currently selected text by the contents of the system clipboard.
1485 void QDeclarative1TextInput::paste()
1487 Q_D(QDeclarative1TextInput);
1488 if(!d->control->isReadOnly())
1489 d->control->paste();
1491 #endif // QT_NO_CLIPBOARD
1494 \qmlmethod void QtQuick1::TextInput::selectWord()
1496 Causes the word closest to the current cursor position to be selected.
1498 void QDeclarative1TextInput::selectWord()
1500 Q_D(QDeclarative1TextInput);
1501 d->control->selectWordAtPos(d->control->cursor());
1505 \qmlproperty bool QtQuick1::TextInput::smooth
1507 This property holds whether the text is smoothly scaled or transformed.
1509 Smooth filtering gives better visual quality, but is slower. If
1510 the item is displayed at its natural size, this property has no visual or
1513 \note Generally scaling artifacts are only visible if the item is stationary on
1514 the screen. A common pattern when animating an item is to disable smooth
1515 filtering at the beginning of the animation and reenable it at the conclusion.
1519 \qmlproperty string QtQuick1::TextInput::passwordCharacter
1521 This is the character displayed when echoMode is set to Password or
1522 PasswordEchoOnEdit. By default it is an asterisk.
1524 If this property is set to a string with more than one character,
1525 the first character is used. If the string is empty, the value
1526 is ignored and the property is not set.
1528 QString QDeclarative1TextInput::passwordCharacter() const
1530 Q_D(const QDeclarative1TextInput);
1531 return QString(d->control->passwordCharacter());
1534 void QDeclarative1TextInput::setPasswordCharacter(const QString &str)
1536 Q_D(QDeclarative1TextInput);
1537 if(str.length() < 1)
1539 d->control->setPasswordCharacter(str.constData()[0]);
1540 EchoMode echoMode_ = echoMode();
1541 if (echoMode_ == Password || echoMode_ == PasswordEchoOnEdit) {
1544 emit passwordCharacterChanged();
1548 \qmlproperty string QtQuick1::TextInput::displayText
1550 This is the text displayed in the TextInput.
1552 If \l echoMode is set to TextInput::Normal, this holds the
1553 same value as the TextInput::text property. Otherwise,
1554 this property holds the text visible to the user, while
1555 the \l text property holds the actual entered text.
1557 QString QDeclarative1TextInput::displayText() const
1559 Q_D(const QDeclarative1TextInput);
1560 return d->control->displayText();
1564 \qmlproperty bool QtQuick1::TextInput::selectByMouse
1568 If true, the user can use the mouse to select text in some
1569 platform-specific way. Note that for some platforms this may
1570 not be an appropriate interaction (eg. may conflict with how
1571 the text needs to behave inside a Flickable.
1573 bool QDeclarative1TextInput::selectByMouse() const
1575 Q_D(const QDeclarative1TextInput);
1576 return d->selectByMouse;
1579 void QDeclarative1TextInput::setSelectByMouse(bool on)
1581 Q_D(QDeclarative1TextInput);
1582 if (d->selectByMouse != on) {
1583 d->selectByMouse = on;
1584 emit selectByMouseChanged(on);
1589 \qmlproperty enum QtQuick1::TextInput::mouseSelectionMode
1592 Specifies how text should be selected using a mouse.
1595 \o TextInput.SelectCharacters - The selection is updated with individual characters. (Default)
1596 \o TextInput.SelectWords - The selection is updated with whole words.
1599 This property only applies when \l selectByMouse is true.
1602 QDeclarative1TextInput::SelectionMode QDeclarative1TextInput::mouseSelectionMode() const
1604 Q_D(const QDeclarative1TextInput);
1605 return d->mouseSelectionMode;
1608 void QDeclarative1TextInput::setMouseSelectionMode(SelectionMode mode)
1610 Q_D(QDeclarative1TextInput);
1611 if (d->mouseSelectionMode != mode) {
1612 d->mouseSelectionMode = mode;
1613 emit mouseSelectionModeChanged(mode);
1618 \qmlproperty bool QtQuick1::TextInput::canPaste
1621 Returns true if the TextInput is writable and the content of the clipboard is
1622 suitable for pasting into the TextEdit.
1624 bool QDeclarative1TextInput::canPaste() const
1626 Q_D(const QDeclarative1TextInput);
1630 void QDeclarative1TextInput::moveCursorSelection(int position)
1632 Q_D(QDeclarative1TextInput);
1633 d->control->moveCursor(position, true);
1637 \qmlmethod void QtQuick1::TextInput::moveCursorSelection(int position, SelectionMode mode = TextInput.SelectCharacters)
1640 Moves the cursor to \a position and updates the selection according to the optional \a mode
1641 parameter. (To only move the cursor, set the \l cursorPosition property.)
1643 When this method is called it additionally sets either the
1644 selectionStart or the selectionEnd (whichever was at the previous cursor position)
1645 to the specified position. This allows you to easily extend and contract the selected
1648 The selection mode specifies whether the selection is updated on a per character or a per word
1649 basis. If not specified the selection mode will default to TextInput.SelectCharacters.
1652 \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
1653 the previous cursor position) to the specified position.
1654 \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all
1655 words between the specified postion and the previous cursor position. Words partially in the
1659 For example, take this sequence of calls:
1663 moveCursorSelection(9, TextInput.SelectCharacters)
1664 moveCursorSelection(7, TextInput.SelectCharacters)
1667 This moves the cursor to position 5, extend the selection end from 5 to 9
1668 and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
1669 selected (the 6th and 7th characters).
1671 The same sequence with TextInput.SelectWords will extend the selection start to a word boundary
1672 before or on position 5 and extend the selection end to a word boundary on or past position 9.
1674 void QDeclarative1TextInput::moveCursorSelection(int pos, SelectionMode mode)
1676 Q_D(QDeclarative1TextInput);
1678 if (mode == SelectCharacters) {
1679 d->control->moveCursor(pos, true);
1680 } else if (pos != d->control->cursor()){
1681 const int cursor = d->control->cursor();
1683 if (!d->control->hasSelectedText())
1684 anchor = d->control->cursor();
1685 else if (d->control->selectionStart() == d->control->cursor())
1686 anchor = d->control->selectionEnd();
1688 anchor = d->control->selectionStart();
1690 if (anchor < pos || (anchor == pos && cursor < pos)) {
1691 const QString text = d->control->text();
1692 QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
1693 finder.setPosition(anchor);
1695 const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
1696 if (anchor < text.length() && (!(reasons & QTextBoundaryFinder::StartWord)
1697 || ((reasons & QTextBoundaryFinder::EndWord) && anchor > cursor))) {
1698 finder.toPreviousBoundary();
1700 anchor = finder.position() != -1 ? finder.position() : 0;
1702 finder.setPosition(pos);
1703 if (pos > 0 && !finder.boundaryReasons())
1704 finder.toNextBoundary();
1705 const int cursor = finder.position() != -1 ? finder.position() : text.length();
1707 d->control->setSelection(anchor, cursor - anchor);
1708 } else if (anchor > pos || (anchor == pos && cursor > pos)) {
1709 const QString text = d->control->text();
1710 QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text);
1711 finder.setPosition(anchor);
1713 const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons();
1714 if (anchor > 0 && (!(reasons & QTextBoundaryFinder::EndWord)
1715 || ((reasons & QTextBoundaryFinder::StartWord) && anchor < cursor))) {
1716 finder.toNextBoundary();
1718 anchor = finder.position() != -1 ? finder.position() : text.length();
1720 finder.setPosition(pos);
1721 if (pos < text.length() && !finder.boundaryReasons())
1722 finder.toPreviousBoundary();
1723 const int cursor = finder.position() != -1 ? finder.position() : 0;
1725 d->control->setSelection(anchor, cursor - anchor);
1731 \qmlmethod void QtQuick1::TextInput::openSoftwareInputPanel()
1733 Opens software input panels like virtual keyboards for typing, useful for
1734 customizing when you want the input keyboard to be shown and hidden in
1737 By default the opening of input panels follows the platform style. On Symbian^1 and
1738 Symbian^3 -based devices the panels are opened by clicking TextInput. On other platforms
1739 the panels are automatically opened when TextInput element gains active focus. Input panels are
1740 always closed if no editor has active focus.
1742 . You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1743 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1744 the behavior you want.
1746 Only relevant on platforms, which provide virtual keyboards.
1752 text: "Hello world!"
1753 activeFocusOnPress: false
1755 anchors.fill: parent
1757 if (!textInput.activeFocus) {
1758 textInput.forceActiveFocus()
1759 textInput.openSoftwareInputPanel();
1761 textInput.focus = false;
1764 onPressAndHold: textInput.closeSoftwareInputPanel();
1769 void QDeclarative1TextInput::openSoftwareInputPanel()
1772 if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1773 if (view->scene() && view->scene() == scene()) {
1774 qApp->inputPanel()->show();
1781 \qmlmethod void QtQuick1::TextInput::closeSoftwareInputPanel()
1783 Closes a software input panel like a virtual keyboard shown on the screen, useful
1784 for customizing when you want the input keyboard to be shown and hidden in
1787 By default the opening of input panels follows the platform style. On Symbian^1 and
1788 Symbian^3 -based devices the panels are opened by clicking TextInput. On other platforms
1789 the panels are automatically opened when TextInput element gains active focus. Input panels are
1790 always closed if no editor has active focus.
1792 . You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1793 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1794 the behavior you want.
1796 Only relevant on platforms, which provide virtual keyboards.
1802 text: "Hello world!"
1803 activeFocusOnPress: false
1805 anchors.fill: parent
1807 if (!textInput.activeFocus) {
1808 textInput.forceActiveFocus();
1809 textInput.openSoftwareInputPanel();
1811 textInput.focus = false;
1814 onPressAndHold: textInput.closeSoftwareInputPanel();
1819 void QDeclarative1TextInput::closeSoftwareInputPanel()
1822 if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1823 if (view->scene() && view->scene() == scene()) {
1824 qApp->inputPanel()->hide();
1830 void QDeclarative1TextInput::focusInEvent(QFocusEvent *event)
1832 Q_D(const QDeclarative1TextInput);
1833 if (d->showInputPanelOnFocus) {
1834 if (d->focusOnPress && !isReadOnly()) {
1835 openSoftwareInputPanel();
1838 QDeclarative1PaintedItem::focusInEvent(event);
1842 \qmlproperty bool QtQuick1::TextInput::inputMethodComposing
1846 This property holds whether the TextInput has partial text input from an
1849 While it is composing an input method may rely on mouse or key events from
1850 the TextInput to edit or commit the partial text. This property can be
1851 used to determine when to disable events handlers that may interfere with
1852 the correct operation of an input method.
1854 bool QDeclarative1TextInput::isInputMethodComposing() const
1856 Q_D(const QDeclarative1TextInput);
1857 return d->control->preeditAreaText().length() > 0;
1860 void QDeclarative1TextInputPrivate::init()
1862 Q_Q(QDeclarative1TextInput);
1863 control->setParent(q);//Now mandatory due to accessibility changes
1864 control->setCursorWidth(1);
1865 control->setPasswordCharacter(QLatin1Char('*'));
1866 q->setSmooth(smooth);
1867 q->setAcceptedMouseButtons(Qt::LeftButton);
1868 q->setFlag(QGraphicsItem::ItemHasNoContents, false);
1869 q->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
1870 q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
1871 q, SLOT(cursorPosChanged()));
1872 q->connect(control, SIGNAL(selectionChanged()),
1873 q, SLOT(selectionChanged()));
1874 q->connect(control, SIGNAL(textChanged(QString)),
1875 q, SLOT(q_textChanged()));
1876 q->connect(control, SIGNAL(accepted()),
1877 q, SIGNAL(accepted()));
1878 q->connect(control, SIGNAL(updateNeeded(QRect)),
1879 q, SLOT(updateRect(QRect)));
1880 #ifndef QT_NO_CLIPBOARD
1881 q->connect(q, SIGNAL(readOnlyChanged(bool)),
1882 q, SLOT(q_canPasteChanged()));
1883 q->connect(QApplication::clipboard(), SIGNAL(dataChanged()),
1884 q, SLOT(q_canPasteChanged()));
1885 canPaste = !control->isReadOnly() && QApplication::clipboard()->text().length() != 0;
1886 #endif // QT_NO_CLIPBOARD
1887 q->connect(control, SIGNAL(updateMicroFocus()),
1888 q, SLOT(updateCursorRectangle()));
1889 q->connect(control, SIGNAL(displayTextChanged(QString)),
1890 q, SLOT(updateRect()));
1892 oldValidity = control->hasAcceptableInput();
1893 lastSelectionStart = 0;
1894 lastSelectionEnd = 0;
1895 QPalette p = control->palette();
1896 selectedTextColor = p.color(QPalette::HighlightedText);
1897 selectionColor = p.color(QPalette::Highlight);
1898 determineHorizontalAlignment();
1901 void QDeclarative1TextInput::cursorPosChanged()
1903 Q_D(QDeclarative1TextInput);
1904 updateCursorRectangle();
1905 emit cursorPositionChanged();
1906 d->control->resetCursorBlinkTimer();
1908 if(!d->control->hasSelectedText()){
1909 if(d->lastSelectionStart != d->control->cursor()){
1910 d->lastSelectionStart = d->control->cursor();
1911 emit selectionStartChanged();
1913 if(d->lastSelectionEnd != d->control->cursor()){
1914 d->lastSelectionEnd = d->control->cursor();
1915 emit selectionEndChanged();
1920 void QDeclarative1TextInput::updateCursorRectangle()
1922 Q_D(QDeclarative1TextInput);
1923 d->determineHorizontalAlignment();
1924 d->updateHorizontalScroll();
1925 updateRect();//TODO: Only update rect between pos's
1927 emit cursorRectangleChanged();
1929 d->cursorItem->setX(d->control->cursorToX() - d->hscroll);
1932 void QDeclarative1TextInput::selectionChanged()
1934 Q_D(QDeclarative1TextInput);
1935 updateRect();//TODO: Only update rect in selection
1936 emit selectedTextChanged();
1938 if(d->lastSelectionStart != d->control->selectionStart()){
1939 d->lastSelectionStart = d->control->selectionStart();
1940 if(d->lastSelectionStart == -1)
1941 d->lastSelectionStart = d->control->cursor();
1942 emit selectionStartChanged();
1944 if(d->lastSelectionEnd != d->control->selectionEnd()){
1945 d->lastSelectionEnd = d->control->selectionEnd();
1946 if(d->lastSelectionEnd == -1)
1947 d->lastSelectionEnd = d->control->cursor();
1948 emit selectionEndChanged();
1952 void QDeclarative1TextInput::q_textChanged()
1954 Q_D(QDeclarative1TextInput);
1956 emit displayTextChanged();
1958 d->determineHorizontalAlignment();
1959 d->updateHorizontalScroll();
1961 if(hasAcceptableInput() != d->oldValidity){
1962 d->oldValidity = hasAcceptableInput();
1963 emit acceptableInputChanged();
1967 void QDeclarative1TextInput::updateRect(const QRect &r)
1969 Q_D(QDeclarative1TextInput);
1973 dirtyCache(QRect(r.x() - d->hscroll, r.y(), r.width(), r.height()));
1977 QRectF QDeclarative1TextInput::boundingRect() const
1979 Q_D(const QDeclarative1TextInput);
1980 QRectF r = QDeclarative1PaintedItem::boundingRect();
1982 int cursorWidth = d->cursorItem ? d->cursorItem->width() : d->control->cursorWidth();
1984 // Could include font max left/right bearings to either side of rectangle.
1986 r.setRight(r.right() + cursorWidth);
1990 void QDeclarative1TextInput::updateSize(bool needsRedraw)
1992 Q_D(QDeclarative1TextInput);
1995 setImplicitHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
1996 setImplicitWidth(d->calculateTextWidth());
1997 setContentsSize(QSize(width(), height()));//Repaints if changed
1998 if(w==width() && h==height() && needsRedraw){
2004 void QDeclarative1TextInput::q_canPasteChanged()
2006 Q_D(QDeclarative1TextInput);
2007 bool old = d->canPaste;
2008 #ifndef QT_NO_CLIPBOARD
2009 d->canPaste = !d->control->isReadOnly() && QApplication::clipboard()->text().length() != 0;
2011 if(d->canPaste != old)
2012 emit canPasteChanged();
2019 #endif // QT_NO_LINEEDIT