1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "private/qdeclarativetextinput_p.h"
43 #include "private/qdeclarativetextinput_p_p.h"
45 #include <private/qdeclarativeglobal_p.h>
46 #include <qdeclarativeinfo.h>
49 #include <QTextCursor>
50 #include <QApplication>
51 #include <QFontMetrics>
53 #include <QTextBoundaryFinder>
54 #include <QInputContext>
57 #ifndef QT_NO_LINEEDIT
64 \qmlclass TextInput QDeclarative1TextInput
65 \inqmlmodule QtQuick 1
66 \ingroup qml-basic-visual-elements
68 \brief The TextInput item displays an editable line of text.
71 The TextInput element displays a single line of editable plain text.
73 TextInput is used to accept a line of text input. Input constraints
74 can be placed on a TextInput item (for example, through a \l validator or \l inputMask),
75 and setting \l echoMode to an appropriate value enables TextInput to be used for
76 a password input field.
78 On Mac OS X, the Up/Down key bindings for Home/End are explicitly disabled.
79 If you want such bindings (on any platform), you will need to construct them in QML.
81 \sa TextEdit, Text, {declarative/text/textselection}{Text Selection example}
83 QDeclarative1TextInput::QDeclarative1TextInput(QDeclarativeItem* parent)
84 : QDeclarative1ImplicitSizePaintedItem(*(new QDeclarative1TextInputPrivate), parent)
86 Q_D(QDeclarative1TextInput);
90 QDeclarative1TextInput::~QDeclarative1TextInput()
95 \qmlproperty string QtQuick1::TextInput::text
97 The text in the TextInput.
100 QString QDeclarative1TextInput::text() const
102 Q_D(const QDeclarative1TextInput);
103 return d->control->text();
106 void QDeclarative1TextInput::setText(const QString &s)
108 Q_D(QDeclarative1TextInput);
111 d->control->setText(s);
115 \qmlproperty string QtQuick1::TextInput::font.family
117 Sets the family name of the font.
119 The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]".
120 If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen.
121 If the family isn't available a family will be set using the font matching algorithm.
125 \qmlproperty bool QtQuick1::TextInput::font.bold
127 Sets whether the font weight is bold.
131 \qmlproperty enumeration QtQuick1::TextInput::font.weight
133 Sets the font's weight.
135 The weight can be one of:
138 \o Font.Normal - the default
145 TextInput { text: "Hello"; font.weight: Font.DemiBold }
150 \qmlproperty bool QtQuick1::TextInput::font.italic
152 Sets whether the font has an italic style.
156 \qmlproperty bool QtQuick1::TextInput::font.underline
158 Sets whether the text is underlined.
162 \qmlproperty bool QtQuick1::TextInput::font.strikeout
164 Sets whether the font has a strikeout style.
168 \qmlproperty real QtQuick1::TextInput::font.pointSize
170 Sets the font size in points. The point size must be greater than zero.
174 \qmlproperty int QtQuick1::TextInput::font.pixelSize
176 Sets the font size in pixels.
178 Using this function makes the font device dependent.
179 Use \c pointSize to set the size of the font in a device independent manner.
183 \qmlproperty real QtQuick1::TextInput::font.letterSpacing
185 Sets the letter spacing for the font.
187 Letter spacing changes the default spacing between individual letters in the font.
188 A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing.
192 \qmlproperty real QtQuick1::TextInput::font.wordSpacing
194 Sets the word spacing for the font.
196 Word spacing changes the default spacing between individual words.
197 A positive value increases the word spacing by a corresponding amount of pixels,
198 while a negative value decreases the inter-word spacing accordingly.
202 \qmlproperty enumeration QtQuick1::TextInput::font.capitalization
204 Sets the capitalization for the text.
207 \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied.
208 \o Font.AllUppercase - This alters the text to be rendered in all uppercase type.
209 \o Font.AllLowercase - This alters the text to be rendered in all lowercase type.
210 \o Font.SmallCaps - This alters the text to be rendered in small-caps type.
211 \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character.
215 TextInput { text: "Hello"; font.capitalization: Font.AllLowercase }
219 QFont QDeclarative1TextInput::font() const
221 Q_D(const QDeclarative1TextInput);
222 return d->sourceFont;
225 void QDeclarative1TextInput::setFont(const QFont &font)
227 Q_D(QDeclarative1TextInput);
228 if (d->sourceFont == font)
231 d->sourceFont = font;
232 QFont oldFont = d->font;
234 if (d->font.pointSizeF() != -1) {
236 qreal size = qRound(d->font.pointSizeF()*2.0);
237 d->font.setPointSizeF(size/2.0);
240 if (oldFont != d->font) {
241 d->control->setFont(d->font);
243 updateCursorRectangle();
245 d->cursorItem->setHeight(QFontMetrics(d->font).height());
248 emit fontChanged(d->sourceFont);
252 \qmlproperty color QtQuick1::TextInput::color
256 QColor QDeclarative1TextInput::color() const
258 Q_D(const QDeclarative1TextInput);
262 void QDeclarative1TextInput::setColor(const QColor &c)
264 Q_D(QDeclarative1TextInput);
269 emit colorChanged(c);
275 \qmlproperty color QtQuick1::TextInput::selectionColor
277 The text highlight color, used behind selections.
279 QColor QDeclarative1TextInput::selectionColor() const
281 Q_D(const QDeclarative1TextInput);
282 return d->selectionColor;
285 void QDeclarative1TextInput::setSelectionColor(const QColor &color)
287 Q_D(QDeclarative1TextInput);
288 if (d->selectionColor == color)
291 d->selectionColor = color;
292 QPalette p = d->control->palette();
293 p.setColor(QPalette::Highlight, d->selectionColor);
294 d->control->setPalette(p);
295 if (d->control->hasSelectedText()) {
299 emit selectionColorChanged(color);
303 \qmlproperty color QtQuick1::TextInput::selectedTextColor
305 The highlighted text color, used in selections.
307 QColor QDeclarative1TextInput::selectedTextColor() const
309 Q_D(const QDeclarative1TextInput);
310 return d->selectedTextColor;
313 void QDeclarative1TextInput::setSelectedTextColor(const QColor &color)
315 Q_D(QDeclarative1TextInput);
316 if (d->selectedTextColor == color)
319 d->selectedTextColor = color;
320 QPalette p = d->control->palette();
321 p.setColor(QPalette::HighlightedText, d->selectedTextColor);
322 d->control->setPalette(p);
323 if (d->control->hasSelectedText()) {
327 emit selectedTextColorChanged(color);
331 \qmlproperty enumeration QtQuick1::TextInput::horizontalAlignment
332 \qmlproperty enumeration QtQuick1::TextInput::effectiveHorizontalAlignment
334 Sets the horizontal alignment of the text within the TextInput item's
335 width and height. By default, the text alignment follows the natural alignment
336 of the text, for example text that is read from left to right will be aligned to
339 TextInput does not have vertical alignment, as the natural height is
340 exactly the height of the single line of text. If you set the height
341 manually to something larger, TextInput will always be top aligned
342 vertically. You can use anchors to align it however you want within
345 The valid values for \c horizontalAlignment are \c TextInput.AlignLeft, \c TextInput.AlignRight and
346 \c TextInput.AlignHCenter.
348 When using the attached property LayoutMirroring::enabled to mirror application
349 layouts, the horizontal alignment of text will also be mirrored. However, the property
350 \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
351 of TextInput, use the read-only property \c effectiveHorizontalAlignment.
353 QDeclarative1TextInput::HAlignment QDeclarative1TextInput::hAlign() const
355 Q_D(const QDeclarative1TextInput);
359 void QDeclarative1TextInput::setHAlign(HAlignment align)
361 Q_D(QDeclarative1TextInput);
362 bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror;
363 d->hAlignImplicit = false;
364 if (d->setHAlign(align, forceAlign) && isComponentComplete()) {
365 updateCursorRectangle();
369 void QDeclarative1TextInput::resetHAlign()
371 Q_D(QDeclarative1TextInput);
372 d->hAlignImplicit = true;
373 if (d->determineHorizontalAlignment() && isComponentComplete()) {
374 updateCursorRectangle();
378 QDeclarative1TextInput::HAlignment QDeclarative1TextInput::effectiveHAlign() const
380 Q_D(const QDeclarative1TextInput);
381 QDeclarative1TextInput::HAlignment effectiveAlignment = d->hAlign;
382 if (!d->hAlignImplicit && d->effectiveLayoutMirror) {
384 case QDeclarative1TextInput::AlignLeft:
385 effectiveAlignment = QDeclarative1TextInput::AlignRight;
387 case QDeclarative1TextInput::AlignRight:
388 effectiveAlignment = QDeclarative1TextInput::AlignLeft;
394 return effectiveAlignment;
397 bool QDeclarative1TextInputPrivate::setHAlign(QDeclarative1TextInput::HAlignment alignment, bool forceAlign)
399 Q_Q(QDeclarative1TextInput);
400 if ((hAlign != alignment || forceAlign) && alignment <= QDeclarative1TextInput::AlignHCenter) { // justify not supported
401 QDeclarative1TextInput::HAlignment oldEffectiveHAlign = q->effectiveHAlign();
403 emit q->horizontalAlignmentChanged(alignment);
404 if (oldEffectiveHAlign != q->effectiveHAlign())
405 emit q->effectiveHorizontalAlignmentChanged();
411 bool QDeclarative1TextInputPrivate::determineHorizontalAlignment()
413 if (hAlignImplicit) {
414 // if no explicit alignment has been set, follow the natural layout direction of the text
415 QString text = control->text();
416 bool isRightToLeft = text.isEmpty() ? QApplication::keyboardInputDirection() == Qt::RightToLeft : text.isRightToLeft();
417 return setHAlign(isRightToLeft ? QDeclarative1TextInput::AlignRight : QDeclarative1TextInput::AlignLeft);
422 void QDeclarative1TextInputPrivate::mirrorChange()
424 Q_Q(QDeclarative1TextInput);
425 if (q->isComponentComplete()) {
426 if (!hAlignImplicit && (hAlign == QDeclarative1TextInput::AlignRight || hAlign == QDeclarative1TextInput::AlignLeft)) {
427 q->updateCursorRectangle();
428 emit q->effectiveHorizontalAlignmentChanged();
434 \qmlproperty bool QtQuick1::TextInput::readOnly
436 Sets whether user input can modify the contents of the TextInput.
438 If readOnly is set to true, then user input will not affect the text
439 property. Any bindings or attempts to set the text property will still
443 bool QDeclarative1TextInput::isReadOnly() const
445 Q_D(const QDeclarative1TextInput);
446 return d->control->isReadOnly();
449 void QDeclarative1TextInput::setReadOnly(bool ro)
451 Q_D(QDeclarative1TextInput);
452 if (d->control->isReadOnly() == ro)
455 setFlag(QGraphicsItem::ItemAcceptsInputMethod, !ro);
456 d->control->setReadOnly(ro);
458 emit readOnlyChanged(ro);
462 \qmlproperty int QtQuick1::TextInput::maximumLength
463 The maximum permitted length of the text in the TextInput.
465 If the text is too long, it is truncated at the limit.
467 By default, this property contains a value of 32767.
469 int QDeclarative1TextInput::maxLength() const
471 Q_D(const QDeclarative1TextInput);
472 return d->control->maxLength();
475 void QDeclarative1TextInput::setMaxLength(int ml)
477 Q_D(QDeclarative1TextInput);
478 if (d->control->maxLength() == ml)
481 d->control->setMaxLength(ml);
483 emit maximumLengthChanged(ml);
487 \qmlproperty bool QtQuick1::TextInput::cursorVisible
488 Set to true when the TextInput shows a cursor.
490 This property is set and unset when the TextInput gets active focus, so that other
491 properties can be bound to whether the cursor is currently showing. As it
492 gets set and unset automatically, when you set the value yourself you must
493 keep in mind that your value may be overwritten.
495 It can be set directly in script, for example if a KeyProxy might
496 forward keys to it and you desire it to look active when this happens
497 (but without actually giving it active focus).
499 It should not be set directly on the element, like in the below QML,
500 as the specified value will be overridden an lost on focus changes.
509 In the above snippet the cursor will still become visible when the
510 TextInput gains active focus.
512 bool QDeclarative1TextInput::isCursorVisible() const
514 Q_D(const QDeclarative1TextInput);
515 return d->cursorVisible;
518 void QDeclarative1TextInput::setCursorVisible(bool on)
520 Q_D(QDeclarative1TextInput);
521 if (d->cursorVisible == on)
523 d->cursorVisible = on;
524 d->control->setCursorBlinkPeriod(on?QApplication::cursorFlashTime():0);
525 QRect r = d->control->cursorRect();
526 if (d->control->inputMask().isEmpty())
530 emit cursorVisibleChanged(d->cursorVisible);
534 \qmlproperty int QtQuick1::TextInput::cursorPosition
535 The position of the cursor in the TextInput.
537 int QDeclarative1TextInput::cursorPosition() const
539 Q_D(const QDeclarative1TextInput);
540 return d->control->cursor();
542 void QDeclarative1TextInput::setCursorPosition(int cp)
544 Q_D(QDeclarative1TextInput);
545 if (cp < 0 || cp > d->control->text().length())
547 d->control->moveCursor(cp);
551 Returns a Rect which encompasses the cursor, but which may be larger than is
552 required. Ignores custom cursor delegates.
554 QRect QDeclarative1TextInput::cursorRectangle() const
556 Q_D(const QDeclarative1TextInput);
557 QRect r = d->control->cursorRect();
558 // Scroll and make consistent with TextEdit
559 // QLineControl inexplicably adds 1 to the height and horizontal padding
560 // for unicode direction markers.
561 r.adjust(5 - d->hscroll, 0, -4 - d->hscroll, -1);
566 \qmlproperty int QtQuick1::TextInput::selectionStart
568 The cursor position before the first character in the current selection.
570 This property is read-only. To change the selection, use select(start,end),
571 selectAll(), or selectWord().
573 \sa selectionEnd, cursorPosition, selectedText
575 int QDeclarative1TextInput::selectionStart() const
577 Q_D(const QDeclarative1TextInput);
578 return d->lastSelectionStart;
582 \qmlproperty int QtQuick1::TextInput::selectionEnd
584 The cursor position after the last character in the current selection.
586 This property is read-only. To change the selection, use select(start,end),
587 selectAll(), or selectWord().
589 \sa selectionStart, cursorPosition, selectedText
591 int QDeclarative1TextInput::selectionEnd() const
593 Q_D(const QDeclarative1TextInput);
594 return d->lastSelectionEnd;
598 \qmlmethod void QtQuick1::TextInput::select(int start, int end)
600 Causes the text from \a start to \a end to be selected.
602 If either start or end is out of range, the selection is not changed.
604 After calling this, selectionStart will become the lesser
605 and selectionEnd will become the greater (regardless of the order passed
608 \sa selectionStart, selectionEnd
610 void QDeclarative1TextInput::select(int start, int end)
612 Q_D(QDeclarative1TextInput);
613 if (start < 0 || end < 0 || start > d->control->text().length() || end > d->control->text().length())
615 d->control->setSelection(start, end-start);
619 \qmlproperty string QtQuick1::TextInput::selectedText
621 This read-only property provides the text currently selected in the
624 It is equivalent to the following snippet, but is faster and easier
628 myTextInput.text.toString().substring(myTextInput.selectionStart,
629 myTextInput.selectionEnd);
632 QString QDeclarative1TextInput::selectedText() const
634 Q_D(const QDeclarative1TextInput);
635 return d->control->selectedText();
639 \qmlproperty bool QtQuick1::TextInput::activeFocusOnPress
641 Whether the TextInput should gain active focus on a mouse press. By default this is
644 bool QDeclarative1TextInput::focusOnPress() const
646 Q_D(const QDeclarative1TextInput);
647 return d->focusOnPress;
650 void QDeclarative1TextInput::setFocusOnPress(bool b)
652 Q_D(QDeclarative1TextInput);
653 if (d->focusOnPress == b)
658 emit activeFocusOnPressChanged(d->focusOnPress);
662 \qmlproperty bool QtQuick1::TextInput::autoScroll
664 Whether the TextInput should scroll when the text is longer than the width. By default this is
667 bool QDeclarative1TextInput::autoScroll() const
669 Q_D(const QDeclarative1TextInput);
670 return d->autoScroll;
673 void QDeclarative1TextInput::setAutoScroll(bool b)
675 Q_D(QDeclarative1TextInput);
676 if (d->autoScroll == b)
680 //We need to repaint so that the scrolling is taking into account.
682 updateCursorRectangle();
683 emit autoScrollChanged(d->autoScroll);
687 \qmlclass IntValidator QIntValidator
688 \inqmlmodule QtQuick 1
689 \ingroup qml-basic-visual-elements
691 This element provides a validator for integer values.
693 IntValidator uses the \l {QLocale::setDefault()}{default locale} to interpret the number and
694 will accept locale specific digits, group separators, and positive and negative signs. In
695 addition, IntValidator is always guaranteed to accept a number formatted according to the "C"
699 \qmlproperty int QtQuick1::IntValidator::top
701 This property holds the validator's highest acceptable value.
702 By default, this property's value is derived from the highest signed integer available (typically 2147483647).
705 \qmlproperty int QtQuick1::IntValidator::bottom
707 This property holds the validator's lowest acceptable value.
708 By default, this property's value is derived from the lowest signed integer available (typically -2147483647).
712 \qmlclass DoubleValidator QDoubleValidator
713 \inqmlmodule QtQuick 1
714 \ingroup qml-basic-visual-elements
716 This element provides a validator for non-integer numbers.
720 \qmlproperty real QtQuick1::DoubleValidator::top
722 This property holds the validator's maximum acceptable value.
723 By default, this property contains a value of infinity.
726 \qmlproperty real QtQuick1::DoubleValidator::bottom
728 This property holds the validator's minimum acceptable value.
729 By default, this property contains a value of -infinity.
732 \qmlproperty int QtQuick1::DoubleValidator::decimals
734 This property holds the validator's maximum number of digits after the decimal point.
735 By default, this property contains a value of 1000.
738 \qmlproperty enumeration QtQuick1::DoubleValidator::notation
739 This property holds the notation of how a string can describe a number.
741 The possible values for this property are:
744 \o DoubleValidator.StandardNotation
745 \o DoubleValidator.ScientificNotation (default)
748 If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part (e.g. 1.5E-2).
752 \qmlclass RegExpValidator QRegExpValidator
753 \inqmlmodule QtQuick 1
754 \ingroup qml-basic-visual-elements
756 This element provides a validator, which counts as valid any string which
757 matches a specified regular expression.
760 \qmlproperty regExp QtQuick1::RegExpValidator::regExp
762 This property holds the regular expression used for validation.
764 Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular expression
767 By default, this property contains a regular expression with the pattern .* that matches any string.
771 \qmlproperty Validator QtQuick1::TextInput::validator
773 Allows you to set a validator on the TextInput. When a validator is set
774 the TextInput will only accept input which leaves the text property in
775 an acceptable or intermediate state. The accepted signal will only be sent
776 if the text is in an acceptable state when enter is pressed.
778 Currently supported validators are IntValidator, DoubleValidator and
779 RegExpValidator. An example of using validators is shown below, which allows
780 input of integers between 11 and 31 into the text input:
785 validator: IntValidator{bottom: 11; top: 31;}
790 \sa acceptableInput, inputMask
792 #ifndef QT_NO_VALIDATOR
793 QValidator* QDeclarative1TextInput::validator() const
795 Q_D(const QDeclarative1TextInput);
796 //###const cast isn't good, but needed for property system?
797 return const_cast<QValidator*>(d->control->validator());
800 void QDeclarative1TextInput::setValidator(QValidator* v)
802 Q_D(QDeclarative1TextInput);
803 if (d->control->validator() == v)
806 d->control->setValidator(v);
807 if(!d->control->hasAcceptableInput()){
808 d->oldValidity = false;
809 emit acceptableInputChanged();
812 emit validatorChanged();
814 #endif // QT_NO_VALIDATOR
817 \qmlproperty string QtQuick1::TextInput::inputMask
819 Allows you to set an input mask on the TextInput, restricting the allowable
820 text inputs. See QLineEdit::inputMask for further details, as the exact
821 same mask strings are used by TextInput.
823 \sa acceptableInput, validator
825 QString QDeclarative1TextInput::inputMask() const
827 Q_D(const QDeclarative1TextInput);
828 return d->control->inputMask();
831 void QDeclarative1TextInput::setInputMask(const QString &im)
833 Q_D(QDeclarative1TextInput);
834 if (d->control->inputMask() == im)
837 d->control->setInputMask(im);
838 emit inputMaskChanged(d->control->inputMask());
842 \qmlproperty bool QtQuick1::TextInput::acceptableInput
844 This property is always true unless a validator or input mask has been set.
845 If a validator or input mask has been set, this property will only be true
846 if the current text is acceptable to the validator or input mask as a final
847 string (not as an intermediate string).
849 bool QDeclarative1TextInput::hasAcceptableInput() const
851 Q_D(const QDeclarative1TextInput);
852 return d->control->hasAcceptableInput();
856 \qmlsignal QtQuick1::TextInput::onAccepted()
858 This handler is called when the Return or Enter key is pressed.
859 Note that if there is a \l validator or \l inputMask set on the text
860 input, the handler will only be emitted if the input is in an acceptable
864 void QDeclarative1TextInputPrivate::updateInputMethodHints()
866 Q_Q(QDeclarative1TextInput);
867 Qt::InputMethodHints hints = inputMethodHints;
868 uint echo = control->echoMode();
869 if (echo == QDeclarative1TextInput::Password || echo == QDeclarative1TextInput::NoEcho)
870 hints |= Qt::ImhHiddenText;
871 else if (echo == QDeclarative1TextInput::PasswordEchoOnEdit)
872 hints &= ~Qt::ImhHiddenText;
873 if (echo != QDeclarative1TextInput::Normal) {
874 hints |= Qt::ImhNoAutoUppercase;
875 hints |= Qt::ImhNoPredictiveText;
877 q->setInputMethodHints(hints);
881 \qmlproperty enumeration QtQuick1::TextInput::echoMode
883 Specifies how the text should be displayed in the TextInput.
885 \o TextInput.Normal - Displays the text as it is. (Default)
886 \o TextInput.Password - Displays asterixes instead of characters.
887 \o TextInput.NoEcho - Displays nothing.
888 \o TextInput.PasswordEchoOnEdit - Displays characters as they are entered
889 while editing, otherwise displays asterisks.
892 QDeclarative1TextInput::EchoMode QDeclarative1TextInput::echoMode() const
894 Q_D(const QDeclarative1TextInput);
895 return (QDeclarative1TextInput::EchoMode)d->control->echoMode();
898 void QDeclarative1TextInput::setEchoMode(QDeclarative1TextInput::EchoMode echo)
900 Q_D(QDeclarative1TextInput);
901 if (echoMode() == echo)
903 d->control->setEchoMode((uint)echo);
904 d->updateInputMethodHints();
906 emit echoModeChanged(echoMode());
909 Qt::InputMethodHints QDeclarative1TextInput::imHints() const
911 Q_D(const QDeclarative1TextInput);
912 return d->inputMethodHints;
915 void QDeclarative1TextInput::setIMHints(Qt::InputMethodHints hints)
917 Q_D(QDeclarative1TextInput);
918 if (d->inputMethodHints == hints)
920 d->inputMethodHints = hints;
921 d->updateInputMethodHints();
925 \qmlproperty Component QtQuick1::TextInput::cursorDelegate
926 The delegate for the cursor in the TextInput.
928 If you set a cursorDelegate for a TextInput, this delegate will be used for
929 drawing the cursor instead of the standard cursor. An instance of the
930 delegate will be created and managed by the TextInput when a cursor is
931 needed, and the x property of delegate instance will be set so as
932 to be one pixel before the top left of the current character.
934 Note that the root item of the delegate component must be a QDeclarativeItem or
935 QDeclarativeItem derived item.
937 QDeclarativeComponent* QDeclarative1TextInput::cursorDelegate() const
939 Q_D(const QDeclarative1TextInput);
940 return d->cursorComponent;
943 void QDeclarative1TextInput::setCursorDelegate(QDeclarativeComponent* c)
945 Q_D(QDeclarative1TextInput);
946 if (d->cursorComponent == c)
949 d->cursorComponent = c;
951 //note that the components are owned by something else
952 delete d->cursorItem;
954 d->startCreatingCursor();
957 emit cursorDelegateChanged();
960 void QDeclarative1TextInputPrivate::startCreatingCursor()
962 Q_Q(QDeclarative1TextInput);
963 if(cursorComponent->isReady()){
965 }else if(cursorComponent->isLoading()){
966 q->connect(cursorComponent, SIGNAL(statusChanged(int)),
967 q, SLOT(createCursor()));
969 qmlInfo(q, cursorComponent->errors()) << QDeclarative1TextInput::tr("Could not load cursor delegate");
973 void QDeclarative1TextInput::createCursor()
975 Q_D(QDeclarative1TextInput);
976 if(d->cursorComponent->isError()){
977 qmlInfo(this, d->cursorComponent->errors()) << tr("Could not load cursor delegate");
981 if(!d->cursorComponent->isReady())
985 delete d->cursorItem;
986 d->cursorItem = qobject_cast<QDeclarativeItem*>(d->cursorComponent->create());
988 qmlInfo(this, d->cursorComponent->errors()) << tr("Could not instantiate cursor delegate");
992 QDeclarative_setParent_noEvent(d->cursorItem, this);
993 d->cursorItem->setParentItem(this);
994 d->cursorItem->setX(d->control->cursorToX());
995 d->cursorItem->setHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
999 \qmlmethod rect QtQuick1::TextInput::positionToRectangle(int pos)
1001 This function takes a character position and returns the rectangle that the
1002 cursor would occupy, if it was placed at that character position.
1004 This is similar to setting the cursorPosition, and then querying the cursor
1005 rectangle, but the cursorPosition is not changed.
1007 QRectF QDeclarative1TextInput::positionToRectangle(int pos) const
1009 Q_D(const QDeclarative1TextInput);
1010 if (pos > d->control->cursorPosition())
1011 pos += d->control->preeditAreaText().length();
1012 return QRectF(d->control->cursorToX(pos)-d->hscroll,
1014 d->control->cursorWidth(),
1015 cursorRectangle().height());
1018 int QDeclarative1TextInput::positionAt(int x) const
1020 return positionAt(x, CursorBetweenCharacters);
1024 \qmlmethod int QtQuick1::TextInput::positionAt(int x, CursorPosition position = CursorBetweenCharacters)
1027 This function returns the character position at
1028 x pixels from the left of the textInput. Position 0 is before the
1029 first character, position 1 is after the first character but before the second,
1030 and so on until position text.length, which is after all characters.
1032 This means that for all x values before the first character this function returns 0,
1033 and for all x values after the last character this function returns text.length.
1035 The cursor position type specifies how the cursor position should be resolved.
1038 \o TextInput.CursorBetweenCharacters - Returns the position between characters that is nearest x.
1039 \o TextInput.CursorOnCharacter - Returns the position before the character that is nearest x.
1042 int QDeclarative1TextInput::positionAt(int x, CursorPosition position) const
1044 Q_D(const QDeclarative1TextInput);
1045 int pos = d->control->xToPos(x + d->hscroll, QTextLine::CursorPosition(position));
1046 const int cursor = d->control->cursor();
1048 const int preeditLength = d->control->preeditAreaText().length();
1049 pos = pos > cursor + preeditLength
1050 ? pos - preeditLength
1056 void QDeclarative1TextInputPrivate::focusChanged(bool hasFocus)
1058 Q_Q(QDeclarative1TextInput);
1060 q->setCursorVisible(hasFocus && scene && scene->hasFocus());
1061 if(q->echoMode() == QDeclarative1TextInput::PasswordEchoOnEdit && !hasFocus)
1062 control->updatePasswordEchoEditing(false);//QLineControl sets it on key events, but doesn't deal with focus events
1064 control->deselect();
1065 QDeclarativeItemPrivate::focusChanged(hasFocus);
1068 void QDeclarative1TextInput::keyPressEvent(QKeyEvent* ev)
1070 Q_D(QDeclarative1TextInput);
1071 keyPressPreHandler(ev);
1072 if (ev->isAccepted())
1075 // Don't allow MacOSX up/down support, and we don't allow a completer.
1076 bool ignore = (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) && ev->modifiers() == Qt::NoModifier;
1077 if (!ignore && (d->lastSelectionStart == d->lastSelectionEnd) && (ev->key() == Qt::Key_Right || ev->key() == Qt::Key_Left)) {
1078 // Ignore when moving off the end unless there is a selection,
1079 // because then moving will do something (deselect).
1080 int cursorPosition = d->control->cursor();
1081 if (cursorPosition == 0)
1082 ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Left : Qt::Key_Right);
1083 if (cursorPosition == d->control->text().length())
1084 ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Right : Qt::Key_Left);
1089 d->control->processKeyEvent(ev);
1091 if (!ev->isAccepted())
1092 QDeclarative1PaintedItem::keyPressEvent(ev);
1095 void QDeclarative1TextInput::inputMethodEvent(QInputMethodEvent *ev)
1097 Q_D(QDeclarative1TextInput);
1099 const bool wasComposing = d->control->preeditAreaText().length() > 0;
1100 inputMethodPreHandler(ev);
1101 if (!ev->isAccepted()) {
1102 if (d->control->isReadOnly()) {
1105 d->control->processInputMethodEvent(ev);
1108 if (!ev->isAccepted())
1109 QDeclarative1PaintedItem::inputMethodEvent(ev);
1111 if (wasComposing != (d->control->preeditAreaText().length() > 0))
1112 emit inputMethodComposingChanged();
1117 Handles the given mouse \a event.
1119 void QDeclarative1TextInput::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
1121 Q_D(QDeclarative1TextInput);
1122 if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonDblClick))
1124 if (d->selectByMouse) {
1125 int cursor = d->xToPos(event->pos().x());
1126 d->control->selectWordAtPos(cursor);
1127 event->setAccepted(true);
1129 QDeclarative1PaintedItem::mouseDoubleClickEvent(event);
1133 void QDeclarative1TextInput::mousePressEvent(QGraphicsSceneMouseEvent *event)
1135 Q_D(QDeclarative1TextInput);
1136 if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonPress))
1138 if(d->focusOnPress){
1139 bool hadActiveFocus = hasActiveFocus();
1141 if (d->showInputPanelOnFocus) {
1142 if (hasActiveFocus() && hadActiveFocus && !isReadOnly()) {
1143 // re-open input panel on press if already focused
1144 openSoftwareInputPanel();
1146 } else { // show input panel on click
1147 if (hasActiveFocus() && !hadActiveFocus) {
1148 d->clickCausedFocus = true;
1152 if (d->selectByMouse) {
1153 setKeepMouseGrab(false);
1154 d->selectPressed = true;
1155 d->pressPos = event->pos();
1157 bool mark = (event->modifiers() & Qt::ShiftModifier) && d->selectByMouse;
1158 int cursor = d->xToPos(event->pos().x());
1159 d->control->moveCursor(cursor, mark);
1160 event->setAccepted(true);
1163 void QDeclarative1TextInput::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
1165 Q_D(QDeclarative1TextInput);
1166 if (d->sendMouseEventToInputContext(event, QEvent::MouseMove))
1168 if (d->selectPressed) {
1169 if (qAbs(int(event->pos().x() - d->pressPos.x())) > QApplication::startDragDistance())
1170 setKeepMouseGrab(true);
1171 moveCursorSelection(d->xToPos(event->pos().x()), d->mouseSelectionMode);
1172 event->setAccepted(true);
1174 QDeclarative1PaintedItem::mouseMoveEvent(event);
1180 Handles the given mouse \a event.
1182 void QDeclarative1TextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
1184 Q_D(QDeclarative1TextInput);
1185 if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonRelease))
1187 if (d->selectPressed) {
1188 d->selectPressed = false;
1189 setKeepMouseGrab(false);
1191 if (!d->showInputPanelOnFocus) { // input panel on click
1192 if (d->focusOnPress && !isReadOnly() && boundingRect().contains(event->pos())) {
1193 if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1194 if (view->scene() && view->scene() == scene()) {
1195 qt_widget_private(view)->handleSoftwareInputPanel(event->button(), d->clickCausedFocus);
1200 d->clickCausedFocus = false;
1201 d->control->processEvent(event);
1202 if (!event->isAccepted())
1203 QDeclarative1PaintedItem::mouseReleaseEvent(event);
1206 bool QDeclarative1TextInputPrivate::sendMouseEventToInputContext(
1207 QGraphicsSceneMouseEvent *event, QEvent::Type eventType)
1209 #if !defined QT_NO_IM
1210 if (event->widget() && control->composeMode()) {
1211 int tmp_cursor = xToPos(event->pos().x());
1212 int mousePos = tmp_cursor - control->cursor();
1213 if (mousePos < 0 || mousePos > control->preeditAreaText().length()) {
1215 // don't send move events outside the preedit area
1216 if (eventType == QEvent::MouseMove)
1220 QInputContext *qic = event->widget()->inputContext();
1222 QMouseEvent mouseEvent(
1224 event->widget()->mapFromGlobal(event->screenPos()),
1228 event->modifiers());
1229 // may be causing reset() in some input methods
1230 qic->mouseHandler(mousePos, &mouseEvent);
1231 event->setAccepted(mouseEvent.isAccepted());
1233 if (!control->preeditAreaText().isEmpty())
1244 bool QDeclarative1TextInput::sceneEvent(QEvent *event)
1246 Q_D(QDeclarative1TextInput);
1247 bool rv = QDeclarativeItem::sceneEvent(event);
1248 if (event->type() == QEvent::UngrabMouse) {
1249 d->selectPressed = false;
1250 setKeepMouseGrab(false);
1255 bool QDeclarative1TextInput::event(QEvent* ev)
1257 Q_D(QDeclarative1TextInput);
1258 //Anything we don't deal with ourselves, pass to the control
1259 bool handled = false;
1261 case QEvent::KeyPress:
1262 case QEvent::KeyRelease://###Should the control be doing anything with release?
1263 case QEvent::InputMethod:
1264 case QEvent::GraphicsSceneMousePress:
1265 case QEvent::GraphicsSceneMouseMove:
1266 case QEvent::GraphicsSceneMouseRelease:
1267 case QEvent::GraphicsSceneMouseDoubleClick:
1270 handled = d->control->processEvent(ev);
1273 handled = QDeclarative1PaintedItem::event(ev);
1277 void QDeclarative1TextInput::geometryChanged(const QRectF &newGeometry,
1278 const QRectF &oldGeometry)
1280 Q_D(QDeclarative1TextInput);
1281 if (newGeometry.width() != oldGeometry.width()) {
1283 updateCursorRectangle();
1285 QDeclarative1PaintedItem::geometryChanged(newGeometry, oldGeometry);
1288 int QDeclarative1TextInputPrivate::calculateTextWidth()
1290 return qRound(control->naturalTextWidth());
1293 void QDeclarative1TextInputPrivate::updateHorizontalScroll()
1295 Q_Q(QDeclarative1TextInput);
1296 const int preeditLength = control->preeditAreaText().length();
1297 int cix = qRound(control->cursorToX(control->cursor() + preeditLength));
1298 QRect br(q->boundingRect().toRect());
1299 int widthUsed = calculateTextWidth();
1301 QDeclarative1TextInput::HAlignment effectiveHAlign = q->effectiveHAlign();
1303 if (widthUsed <= br.width()) {
1304 // text fits in br; use hscroll for alignment
1305 switch (effectiveHAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) {
1306 case Qt::AlignRight:
1307 hscroll = widthUsed - br.width() - 1;
1309 case Qt::AlignHCenter:
1310 hscroll = (widthUsed - br.width()) / 2;
1317 } else if (cix - hscroll >= br.width()) {
1318 // text doesn't fit, cursor is to the right of br (scroll right)
1319 hscroll = cix - br.width() + 1;
1320 } else if (cix - hscroll < 0 && hscroll < widthUsed) {
1321 // text doesn't fit, cursor is to the left of br (scroll left)
1323 } else if (widthUsed - hscroll < br.width()) {
1324 // text doesn't fit, text document is to the left of br; align
1326 hscroll = widthUsed - br.width() + 1;
1328 if (preeditLength > 0) {
1329 // check to ensure long pre-edit text doesn't push the cursor
1331 cix = qRound(control->cursorToX(
1332 control->cursor() + qMax(0, control->preeditCursor() - 1)));
1337 switch (effectiveHAlign) {
1338 case QDeclarative1TextInput::AlignRight:
1339 hscroll = q->width() - widthUsed;
1341 case QDeclarative1TextInput::AlignHCenter:
1342 hscroll = (q->width() - widthUsed) / 2;
1352 void QDeclarative1TextInput::drawContents(QPainter *p, const QRect &r)
1354 Q_D(QDeclarative1TextInput);
1355 p->setRenderHint(QPainter::TextAntialiasing, true);
1357 p->setPen(QPen(d->color));
1358 int flags = QLineControl::DrawText;
1359 if(!isReadOnly() && d->cursorVisible && !d->cursorItem)
1360 flags |= QLineControl::DrawCursor;
1361 if (d->control->hasSelectedText())
1362 flags |= QLineControl::DrawSelections;
1363 QPoint offset = QPoint(0,0);
1364 QFontMetrics fm = QFontMetrics(d->font);
1365 QRect br(boundingRect().toRect());
1366 if (d->autoScroll) {
1367 // the y offset is there to keep the baseline constant in case we have script changes in the text.
1368 offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent());
1370 offset = QPoint(d->hscroll, 0);
1372 d->control->draw(p, offset, r, flags);
1378 Returns the value of the given \a property.
1380 QVariant QDeclarative1TextInput::inputMethodQuery(Qt::InputMethodQuery property) const
1382 Q_D(const QDeclarative1TextInput);
1384 case Qt::ImMicroFocus:
1385 return cursorRectangle();
1388 case Qt::ImCursorPosition:
1389 return QVariant(d->control->cursor());
1390 case Qt::ImSurroundingText:
1391 if (d->control->echoMode() == PasswordEchoOnEdit && !d->control->passwordEchoEditing())
1392 return QVariant(displayText());
1394 return QVariant(text());
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()
1766 QEvent event(QEvent::RequestSoftwareInputPanel);
1768 if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1769 if (view->scene() && view->scene() == scene()) {
1770 QApplication::sendEvent(view, &event);
1777 \qmlmethod void QtQuick1::TextInput::closeSoftwareInputPanel()
1779 Closes a software input panel like a virtual keyboard shown on the screen, useful
1780 for customizing when you want the input keyboard to be shown and hidden in
1783 By default the opening of input panels follows the platform style. On Symbian^1 and
1784 Symbian^3 -based devices the panels are opened by clicking TextInput. On other platforms
1785 the panels are automatically opened when TextInput element gains active focus. Input panels are
1786 always closed if no editor has active focus.
1788 . You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1789 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1790 the behavior you want.
1792 Only relevant on platforms, which provide virtual keyboards.
1798 text: "Hello world!"
1799 activeFocusOnPress: false
1801 anchors.fill: parent
1803 if (!textInput.activeFocus) {
1804 textInput.forceActiveFocus();
1805 textInput.openSoftwareInputPanel();
1807 textInput.focus = false;
1810 onPressAndHold: textInput.closeSoftwareInputPanel();
1815 void QDeclarative1TextInput::closeSoftwareInputPanel()
1817 QEvent event(QEvent::CloseSoftwareInputPanel);
1819 QEvent event(QEvent::CloseSoftwareInputPanel);
1820 if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1821 if (view->scene() && view->scene() == scene()) {
1822 QApplication::sendEvent(view, &event);
1828 void QDeclarative1TextInput::focusInEvent(QFocusEvent *event)
1830 Q_D(const QDeclarative1TextInput);
1831 if (d->showInputPanelOnFocus) {
1832 if (d->focusOnPress && !isReadOnly()) {
1833 openSoftwareInputPanel();
1836 QDeclarative1PaintedItem::focusInEvent(event);
1840 \qmlproperty bool QtQuick1::TextInput::inputMethodComposing
1844 This property holds whether the TextInput has partial text input from an
1847 While it is composing an input method may rely on mouse or key events from
1848 the TextInput to edit or commit the partial text. This property can be
1849 used to determine when to disable events handlers that may interfere with
1850 the correct operation of an input method.
1852 bool QDeclarative1TextInput::isInputMethodComposing() const
1854 Q_D(const QDeclarative1TextInput);
1855 return d->control->preeditAreaText().length() > 0;
1858 void QDeclarative1TextInputPrivate::init()
1860 Q_Q(QDeclarative1TextInput);
1861 control->setParent(q);//Now mandatory due to accessibility changes
1862 control->setCursorWidth(1);
1863 control->setPasswordCharacter(QLatin1Char('*'));
1864 q->setSmooth(smooth);
1865 q->setAcceptedMouseButtons(Qt::LeftButton);
1866 q->setFlag(QGraphicsItem::ItemHasNoContents, false);
1867 q->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
1868 q->connect(control, SIGNAL(cursorPositionChanged(int,int)),
1869 q, SLOT(cursorPosChanged()));
1870 q->connect(control, SIGNAL(selectionChanged()),
1871 q, SLOT(selectionChanged()));
1872 q->connect(control, SIGNAL(textChanged(QString)),
1873 q, SLOT(q_textChanged()));
1874 q->connect(control, SIGNAL(accepted()),
1875 q, SIGNAL(accepted()));
1876 q->connect(control, SIGNAL(updateNeeded(QRect)),
1877 q, SLOT(updateRect(QRect)));
1878 #ifndef QT_NO_CLIPBOARD
1879 q->connect(q, SIGNAL(readOnlyChanged(bool)),
1880 q, SLOT(q_canPasteChanged()));
1881 q->connect(QApplication::clipboard(), SIGNAL(dataChanged()),
1882 q, SLOT(q_canPasteChanged()));
1883 canPaste = !control->isReadOnly() && QApplication::clipboard()->text().length() != 0;
1884 #endif // QT_NO_CLIPBOARD
1885 q->connect(control, SIGNAL(updateMicroFocus()),
1886 q, SLOT(updateCursorRectangle()));
1887 q->connect(control, SIGNAL(displayTextChanged(QString)),
1888 q, SLOT(updateRect()));
1890 oldValidity = control->hasAcceptableInput();
1891 lastSelectionStart = 0;
1892 lastSelectionEnd = 0;
1893 QPalette p = control->palette();
1894 selectedTextColor = p.color(QPalette::HighlightedText);
1895 selectionColor = p.color(QPalette::Highlight);
1896 determineHorizontalAlignment();
1899 void QDeclarative1TextInput::cursorPosChanged()
1901 Q_D(QDeclarative1TextInput);
1902 updateCursorRectangle();
1903 emit cursorPositionChanged();
1904 d->control->resetCursorBlinkTimer();
1906 if(!d->control->hasSelectedText()){
1907 if(d->lastSelectionStart != d->control->cursor()){
1908 d->lastSelectionStart = d->control->cursor();
1909 emit selectionStartChanged();
1911 if(d->lastSelectionEnd != d->control->cursor()){
1912 d->lastSelectionEnd = d->control->cursor();
1913 emit selectionEndChanged();
1918 void QDeclarative1TextInput::updateCursorRectangle()
1920 Q_D(QDeclarative1TextInput);
1921 d->updateHorizontalScroll();
1922 updateRect();//TODO: Only update rect between pos's
1924 emit cursorRectangleChanged();
1926 d->cursorItem->setX(d->control->cursorToX() - d->hscroll);
1929 void QDeclarative1TextInput::selectionChanged()
1931 Q_D(QDeclarative1TextInput);
1932 updateRect();//TODO: Only update rect in selection
1933 emit selectedTextChanged();
1935 if(d->lastSelectionStart != d->control->selectionStart()){
1936 d->lastSelectionStart = d->control->selectionStart();
1937 if(d->lastSelectionStart == -1)
1938 d->lastSelectionStart = d->control->cursor();
1939 emit selectionStartChanged();
1941 if(d->lastSelectionEnd != d->control->selectionEnd()){
1942 d->lastSelectionEnd = d->control->selectionEnd();
1943 if(d->lastSelectionEnd == -1)
1944 d->lastSelectionEnd = d->control->cursor();
1945 emit selectionEndChanged();
1949 void QDeclarative1TextInput::q_textChanged()
1951 Q_D(QDeclarative1TextInput);
1953 emit displayTextChanged();
1955 d->determineHorizontalAlignment();
1956 d->updateHorizontalScroll();
1958 if(hasAcceptableInput() != d->oldValidity){
1959 d->oldValidity = hasAcceptableInput();
1960 emit acceptableInputChanged();
1964 void QDeclarative1TextInput::updateRect(const QRect &r)
1966 Q_D(QDeclarative1TextInput);
1970 dirtyCache(QRect(r.x() - d->hscroll, r.y(), r.width(), r.height()));
1974 QRectF QDeclarative1TextInput::boundingRect() const
1976 Q_D(const QDeclarative1TextInput);
1977 QRectF r = QDeclarative1PaintedItem::boundingRect();
1979 int cursorWidth = d->cursorItem ? d->cursorItem->width() : d->control->cursorWidth();
1981 // Could include font max left/right bearings to either side of rectangle.
1983 r.setRight(r.right() + cursorWidth);
1987 void QDeclarative1TextInput::updateSize(bool needsRedraw)
1989 Q_D(QDeclarative1TextInput);
1992 setImplicitHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text.
1993 setImplicitWidth(d->calculateTextWidth());
1994 setContentsSize(QSize(width(), height()));//Repaints if changed
1995 if(w==width() && h==height() && needsRedraw){
2001 void QDeclarative1TextInput::q_canPasteChanged()
2003 Q_D(QDeclarative1TextInput);
2004 bool old = d->canPaste;
2005 #ifndef QT_NO_CLIPBOARD
2006 d->canPaste = !d->control->isReadOnly() && QApplication::clipboard()->text().length() != 0;
2008 if(d->canPaste != old)
2009 emit canPasteChanged();
2016 #endif // QT_NO_LINEEDIT