diff options
Diffstat (limited to 'src/declarative/items/qquicktextinput.cpp')
-rw-r--r-- | src/declarative/items/qquicktextinput.cpp | 2007 |
1 files changed, 0 insertions, 2007 deletions
diff --git a/src/declarative/items/qquicktextinput.cpp b/src/declarative/items/qquicktextinput.cpp deleted file mode 100644 index f3cdc8835a..0000000000 --- a/src/declarative/items/qquicktextinput.cpp +++ /dev/null @@ -1,2007 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qquicktextinput_p.h" -#include "qquicktextinput_p_p.h" -#include "qquickcanvas.h" - -#include <private/qdeclarativeglobal_p.h> - -#include <QtDeclarative/qdeclarativeinfo.h> -#include <QtGui/qevent.h> -#include <QTextBoundaryFinder> -#include "qquicktextnode_p.h" -#include <qsgsimplerectnode.h> - -#include <QtGui/qstylehints.h> -#include <QtGui/qinputpanel.h> - -QT_BEGIN_NAMESPACE - -DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD) - -/*! - \qmlclass TextInput QQuickTextInput - \inqmlmodule QtQuick 2 - \ingroup qml-basic-visual-elements - \brief The TextInput item displays an editable line of text. - \inherits Item - - The TextInput element displays a single line of editable plain text. - - TextInput is used to accept a line of text input. Input constraints - can be placed on a TextInput item (for example, through a \l validator or \l inputMask), - and setting \l echoMode to an appropriate value enables TextInput to be used for - a password input field. - - On Mac OS X, the Up/Down key bindings for Home/End are explicitly disabled. - If you want such bindings (on any platform), you will need to construct them in QML. - - \sa TextEdit, Text, {declarative/text/textselection}{Text Selection example} -*/ -QQuickTextInput::QQuickTextInput(QQuickItem* parent) -: QQuickImplicitSizeItem(*(new QQuickTextInputPrivate), parent) -{ - Q_D(QQuickTextInput); - d->init(); -} - -QQuickTextInput::~QQuickTextInput() -{ -} - -/*! - \qmlproperty string QtQuick2::TextInput::text - - The text in the TextInput. -*/ -QString QQuickTextInput::text() const -{ - Q_D(const QQuickTextInput); - return d->control->text(); -} - -void QQuickTextInput::setText(const QString &s) -{ - Q_D(QQuickTextInput); - if (s == text()) - return; - d->control->setText(s); -} - -/*! - \qmlproperty string QtQuick2::TextInput::font.family - - Sets the family name of the font. - - The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]". - If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen. - If the family isn't available a family will be set using the font matching algorithm. -*/ - -/*! - \qmlproperty bool QtQuick2::TextInput::font.bold - - Sets whether the font weight is bold. -*/ - -/*! - \qmlproperty enumeration QtQuick2::TextInput::font.weight - - Sets the font's weight. - - The weight can be one of: - \list - \o Font.Light - \o Font.Normal - the default - \o Font.DemiBold - \o Font.Bold - \o Font.Black - \endlist - - \qml - TextInput { text: "Hello"; font.weight: Font.DemiBold } - \endqml -*/ - -/*! - \qmlproperty bool QtQuick2::TextInput::font.italic - - Sets whether the font has an italic style. -*/ - -/*! - \qmlproperty bool QtQuick2::TextInput::font.underline - - Sets whether the text is underlined. -*/ - -/*! - \qmlproperty bool QtQuick2::TextInput::font.strikeout - - Sets whether the font has a strikeout style. -*/ - -/*! - \qmlproperty real QtQuick2::TextInput::font.pointSize - - Sets the font size in points. The point size must be greater than zero. -*/ - -/*! - \qmlproperty int QtQuick2::TextInput::font.pixelSize - - Sets the font size in pixels. - - Using this function makes the font device dependent. - Use \c pointSize to set the size of the font in a device independent manner. -*/ - -/*! - \qmlproperty real QtQuick2::TextInput::font.letterSpacing - - Sets the letter spacing for the font. - - Letter spacing changes the default spacing between individual letters in the font. - A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing. -*/ - -/*! - \qmlproperty real QtQuick2::TextInput::font.wordSpacing - - Sets the word spacing for the font. - - Word spacing changes the default spacing between individual words. - A positive value increases the word spacing by a corresponding amount of pixels, - while a negative value decreases the inter-word spacing accordingly. -*/ - -/*! - \qmlproperty enumeration QtQuick2::TextInput::font.capitalization - - Sets the capitalization for the text. - - \list - \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied. - \o Font.AllUppercase - This alters the text to be rendered in all uppercase type. - \o Font.AllLowercase - This alters the text to be rendered in all lowercase type. - \o Font.SmallCaps - This alters the text to be rendered in small-caps type. - \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character. - \endlist - - \qml - TextInput { text: "Hello"; font.capitalization: Font.AllLowercase } - \endqml -*/ - -QFont QQuickTextInput::font() const -{ - Q_D(const QQuickTextInput); - return d->sourceFont; -} - -void QQuickTextInput::setFont(const QFont &font) -{ - Q_D(QQuickTextInput); - if (d->sourceFont == font) - return; - - d->sourceFont = font; - QFont oldFont = d->font; - d->font = font; - if (d->font.pointSizeF() != -1) { - // 0.5pt resolution - qreal size = qRound(d->font.pointSizeF()*2.0); - d->font.setPointSizeF(size/2.0); - } - if (oldFont != d->font) { - d->control->setFont(d->font); - updateSize(); - updateCursorRectangle(); - if (d->cursorItem) { - d->cursorItem->setHeight(QFontMetrics(d->font).height()); - } - } - emit fontChanged(d->sourceFont); -} - -/*! - \qmlproperty color QtQuick2::TextInput::color - - The text color. -*/ -QColor QQuickTextInput::color() const -{ - Q_D(const QQuickTextInput); - return d->color; -} - -void QQuickTextInput::setColor(const QColor &c) -{ - Q_D(QQuickTextInput); - if (c != d->color) { - d->color = c; - update(); - emit colorChanged(c); - } -} - - -/*! - \qmlproperty color QtQuick2::TextInput::selectionColor - - The text highlight color, used behind selections. -*/ -QColor QQuickTextInput::selectionColor() const -{ - Q_D(const QQuickTextInput); - return d->selectionColor; -} - -void QQuickTextInput::setSelectionColor(const QColor &color) -{ - Q_D(QQuickTextInput); - if (d->selectionColor == color) - return; - - d->selectionColor = color; - QPalette p = d->control->palette(); - p.setColor(QPalette::Highlight, d->selectionColor); - d->control->setPalette(p); - if (d->control->hasSelectedText()) - update(); - emit selectionColorChanged(color); -} -/*! - \qmlproperty color QtQuick2::TextInput::selectedTextColor - - The highlighted text color, used in selections. -*/ -QColor QQuickTextInput::selectedTextColor() const -{ - Q_D(const QQuickTextInput); - return d->selectedTextColor; -} - -void QQuickTextInput::setSelectedTextColor(const QColor &color) -{ - Q_D(QQuickTextInput); - if (d->selectedTextColor == color) - return; - - d->selectedTextColor = color; - QPalette p = d->control->palette(); - p.setColor(QPalette::HighlightedText, d->selectedTextColor); - d->control->setPalette(p); - if (d->control->hasSelectedText()) - update(); - emit selectedTextColorChanged(color); -} - -/*! - \qmlproperty enumeration QtQuick2::TextInput::horizontalAlignment - \qmlproperty enumeration QtQuick2::TextInput::effectiveHorizontalAlignment - - Sets the horizontal alignment of the text within the TextInput item's - width and height. By default, the text alignment follows the natural alignment - of the text, for example text that is read from left to right will be aligned to - the left. - - TextInput does not have vertical alignment, as the natural height is - exactly the height of the single line of text. If you set the height - manually to something larger, TextInput will always be top aligned - vertically. You can use anchors to align it however you want within - another item. - - The valid values for \c horizontalAlignment are \c TextInput.AlignLeft, \c TextInput.AlignRight and - \c TextInput.AlignHCenter. - - When using the attached property LayoutMirroring::enabled to mirror application - layouts, the horizontal alignment of text will also be mirrored. However, the property - \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment - of TextInput, use the read-only property \c effectiveHorizontalAlignment. -*/ -QQuickTextInput::HAlignment QQuickTextInput::hAlign() const -{ - Q_D(const QQuickTextInput); - return d->hAlign; -} - -void QQuickTextInput::setHAlign(HAlignment align) -{ - Q_D(QQuickTextInput); - bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror; - d->hAlignImplicit = false; - if (d->setHAlign(align, forceAlign) && isComponentComplete()) { - updateCursorRectangle(); - } -} - -void QQuickTextInput::resetHAlign() -{ - Q_D(QQuickTextInput); - d->hAlignImplicit = true; - if (d->determineHorizontalAlignment() && isComponentComplete()) { - updateCursorRectangle(); - } -} - -QQuickTextInput::HAlignment QQuickTextInput::effectiveHAlign() const -{ - Q_D(const QQuickTextInput); - QQuickTextInput::HAlignment effectiveAlignment = d->hAlign; - if (!d->hAlignImplicit && d->effectiveLayoutMirror) { - switch (d->hAlign) { - case QQuickTextInput::AlignLeft: - effectiveAlignment = QQuickTextInput::AlignRight; - break; - case QQuickTextInput::AlignRight: - effectiveAlignment = QQuickTextInput::AlignLeft; - break; - default: - break; - } - } - return effectiveAlignment; -} - -bool QQuickTextInputPrivate::setHAlign(QQuickTextInput::HAlignment alignment, bool forceAlign) -{ - Q_Q(QQuickTextInput); - if ((hAlign != alignment || forceAlign) && alignment <= QQuickTextInput::AlignHCenter) { // justify not supported - QQuickTextInput::HAlignment oldEffectiveHAlign = q->effectiveHAlign(); - hAlign = alignment; - emit q->horizontalAlignmentChanged(alignment); - if (oldEffectiveHAlign != q->effectiveHAlign()) - emit q->effectiveHorizontalAlignmentChanged(); - return true; - } - return false; -} - -bool QQuickTextInputPrivate::determineHorizontalAlignment() -{ - if (hAlignImplicit) { - // if no explicit alignment has been set, follow the natural layout direction of the text - QString text = control->text(); - if (text.isEmpty()) - text = control->preeditAreaText(); - bool isRightToLeft = text.isEmpty() ? QGuiApplication::keyboardInputDirection() == Qt::RightToLeft : text.isRightToLeft(); - return setHAlign(isRightToLeft ? QQuickTextInput::AlignRight : QQuickTextInput::AlignLeft); - } - return false; -} - -void QQuickTextInputPrivate::mirrorChange() -{ - Q_Q(QQuickTextInput); - if (q->isComponentComplete()) { - if (!hAlignImplicit && (hAlign == QQuickTextInput::AlignRight || hAlign == QQuickTextInput::AlignLeft)) { - q->updateCursorRectangle(); - emit q->effectiveHorizontalAlignmentChanged(); - } - } -} - -/*! - \qmlproperty bool QtQuick2::TextInput::readOnly - - Sets whether user input can modify the contents of the TextInput. - - If readOnly is set to true, then user input will not affect the text - property. Any bindings or attempts to set the text property will still - work. -*/ -bool QQuickTextInput::isReadOnly() const -{ - Q_D(const QQuickTextInput); - return d->control->isReadOnly(); -} - -void QQuickTextInput::setReadOnly(bool ro) -{ - Q_D(QQuickTextInput); - if (d->control->isReadOnly() == ro) - return; - - setFlag(QQuickItem::ItemAcceptsInputMethod, !ro); - d->control->setReadOnly(ro); - if (!ro) - d->control->setCursorPosition(d->control->end()); - - emit readOnlyChanged(ro); -} - -/*! - \qmlproperty int QtQuick2::TextInput::maximumLength - The maximum permitted length of the text in the TextInput. - - If the text is too long, it is truncated at the limit. - - By default, this property contains a value of 32767. -*/ -int QQuickTextInput::maxLength() const -{ - Q_D(const QQuickTextInput); - return d->control->maxLength(); -} - -void QQuickTextInput::setMaxLength(int ml) -{ - Q_D(QQuickTextInput); - if (d->control->maxLength() == ml) - return; - - d->control->setMaxLength(ml); - - emit maximumLengthChanged(ml); -} - -/*! - \qmlproperty bool QtQuick2::TextInput::cursorVisible - Set to true when the TextInput shows a cursor. - - This property is set and unset when the TextInput gets active focus, so that other - properties can be bound to whether the cursor is currently showing. As it - gets set and unset automatically, when you set the value yourself you must - keep in mind that your value may be overwritten. - - It can be set directly in script, for example if a KeyProxy might - forward keys to it and you desire it to look active when this happens - (but without actually giving it active focus). - - It should not be set directly on the element, like in the below QML, - as the specified value will be overridden an lost on focus changes. - - \code - TextInput { - text: "Text" - cursorVisible: false - } - \endcode - - In the above snippet the cursor will still become visible when the - TextInput gains active focus. -*/ -bool QQuickTextInput::isCursorVisible() const -{ - Q_D(const QQuickTextInput); - return d->cursorVisible; -} - -void QQuickTextInput::setCursorVisible(bool on) -{ - Q_D(QQuickTextInput); - if (d->cursorVisible == on) - return; - d->cursorVisible = on; - d->control->setCursorBlinkPeriod(on ? qApp->styleHints()->cursorFlashTime() : 0); - QRect r = d->control->cursorRect(); - if (d->control->inputMask().isEmpty()) - updateRect(r); - else - updateRect(); - emit cursorVisibleChanged(d->cursorVisible); -} - -/*! - \qmlproperty int QtQuick2::TextInput::cursorPosition - The position of the cursor in the TextInput. -*/ -int QQuickTextInput::cursorPosition() const -{ - Q_D(const QQuickTextInput); - return d->control->cursor(); -} -void QQuickTextInput::setCursorPosition(int cp) -{ - Q_D(QQuickTextInput); - if (cp < 0 || cp > d->control->text().length()) - return; - d->control->moveCursor(cp); -} - -/*! - Returns a Rect which encompasses the cursor, but which may be larger than is - required. Ignores custom cursor delegates. -*/ -QRect QQuickTextInput::cursorRectangle() const -{ - Q_D(const QQuickTextInput); - QRect r = d->control->cursorRect(); - // Scroll and make consistent with TextEdit - // QLineControl inexplicably adds 1 to the height and horizontal padding - // for unicode direction markers. - r.adjust(5 - d->hscroll, 0, -4 - d->hscroll, -1); - return r; -} -/*! - \qmlproperty int QtQuick2::TextInput::selectionStart - - The cursor position before the first character in the current selection. - - This property is read-only. To change the selection, use select(start,end), - selectAll(), or selectWord(). - - \sa selectionEnd, cursorPosition, selectedText -*/ -int QQuickTextInput::selectionStart() const -{ - Q_D(const QQuickTextInput); - return d->lastSelectionStart; -} -/*! - \qmlproperty int QtQuick2::TextInput::selectionEnd - - The cursor position after the last character in the current selection. - - This property is read-only. To change the selection, use select(start,end), - selectAll(), or selectWord(). - - \sa selectionStart, cursorPosition, selectedText -*/ -int QQuickTextInput::selectionEnd() const -{ - Q_D(const QQuickTextInput); - return d->lastSelectionEnd; -} -/*! - \qmlmethod void QtQuick2::TextInput::select(int start, int end) - - Causes the text from \a start to \a end to be selected. - - If either start or end is out of range, the selection is not changed. - - After calling this, selectionStart will become the lesser - and selectionEnd will become the greater (regardless of the order passed - to this method). - - \sa selectionStart, selectionEnd -*/ -void QQuickTextInput::select(int start, int end) -{ - Q_D(QQuickTextInput); - if (start < 0 || end < 0 || start > d->control->text().length() || end > d->control->text().length()) - return; - d->control->setSelection(start, end-start); -} - -/*! - \qmlproperty string QtQuick2::TextInput::selectedText - - This read-only property provides the text currently selected in the - text input. - - It is equivalent to the following snippet, but is faster and easier - to use. - - \js - myTextInput.text.toString().substring(myTextInput.selectionStart, - myTextInput.selectionEnd); - \endjs -*/ -QString QQuickTextInput::selectedText() const -{ - Q_D(const QQuickTextInput); - return d->control->selectedText(); -} - -/*! - \qmlproperty bool QtQuick2::TextInput::activeFocusOnPress - - Whether the TextInput should gain active focus on a mouse press. By default this is - set to true. -*/ -bool QQuickTextInput::focusOnPress() const -{ - Q_D(const QQuickTextInput); - return d->focusOnPress; -} - -void QQuickTextInput::setFocusOnPress(bool b) -{ - Q_D(QQuickTextInput); - if (d->focusOnPress == b) - return; - - d->focusOnPress = b; - - emit activeFocusOnPressChanged(d->focusOnPress); -} -/*! - \qmlproperty bool QtQuick2::TextInput::autoScroll - - Whether the TextInput should scroll when the text is longer than the width. By default this is - set to true. -*/ -bool QQuickTextInput::autoScroll() const -{ - Q_D(const QQuickTextInput); - return d->autoScroll; -} - -void QQuickTextInput::setAutoScroll(bool b) -{ - Q_D(QQuickTextInput); - if (d->autoScroll == b) - return; - - d->autoScroll = b; - //We need to repaint so that the scrolling is taking into account. - updateSize(true); - updateCursorRectangle(); - emit autoScrollChanged(d->autoScroll); -} - -#ifndef QT_NO_VALIDATOR - -/*! - \qmlclass IntValidator QIntValidator - \inqmlmodule QtQuick 2 - \ingroup qml-basic-visual-elements - - This element provides a validator for integer values. - - IntValidator uses the \l {QLocale::setDefault()}{default locale} to interpret the number and - will accept locale specific digits, group separators, and positive and negative signs. In - addition, IntValidator is always guaranteed to accept a number formatted according to the "C" - locale. -*/ -/*! - \qmlproperty int QtQuick2::IntValidator::top - - This property holds the validator's highest acceptable value. - By default, this property's value is derived from the highest signed integer available (typically 2147483647). -*/ -/*! - \qmlproperty int QtQuick2::IntValidator::bottom - - This property holds the validator's lowest acceptable value. - By default, this property's value is derived from the lowest signed integer available (typically -2147483647). -*/ - -/*! - \qmlclass DoubleValidator QDoubleValidator - \inqmlmodule QtQuick 2 - \ingroup qml-basic-visual-elements - - This element provides a validator for non-integer numbers. -*/ - -/*! - \qmlproperty real QtQuick2::DoubleValidator::top - - This property holds the validator's maximum acceptable value. - By default, this property contains a value of infinity. -*/ -/*! - \qmlproperty real QtQuick2::DoubleValidator::bottom - - This property holds the validator's minimum acceptable value. - By default, this property contains a value of -infinity. -*/ -/*! - \qmlproperty int QtQuick2::DoubleValidator::decimals - - This property holds the validator's maximum number of digits after the decimal point. - By default, this property contains a value of 1000. -*/ -/*! - \qmlproperty enumeration QtQuick2::DoubleValidator::notation - This property holds the notation of how a string can describe a number. - - The possible values for this property are: - - \list - \o DoubleValidator.StandardNotation - \o DoubleValidator.ScientificNotation (default) - \endlist - - If this property is set to DoubleValidator.ScientificNotation, the written number may have an exponent part (e.g. 1.5E-2). -*/ - -/*! - \qmlclass RegExpValidator QRegExpValidator - \inqmlmodule QtQuick 2 - \ingroup qml-basic-visual-elements - - This element provides a validator, which counts as valid any string which - matches a specified regular expression. -*/ -/*! - \qmlproperty regExp QtQuick2::RegExpValidator::regExp - - This property holds the regular expression used for validation. - - Note that this property should be a regular expression in JS syntax, e.g /a/ for the regular expression - matching "a". - - By default, this property contains a regular expression with the pattern .* that matches any string. -*/ - -/*! - \qmlproperty Validator QtQuick2::TextInput::validator - - Allows you to set a validator on the TextInput. When a validator is set - the TextInput will only accept input which leaves the text property in - an acceptable or intermediate state. The accepted signal will only be sent - if the text is in an acceptable state when enter is pressed. - - Currently supported validators are IntValidator, DoubleValidator and - RegExpValidator. An example of using validators is shown below, which allows - input of integers between 11 and 31 into the text input: - - \code - import QtQuick 1.0 - TextInput{ - validator: IntValidator{bottom: 11; top: 31;} - focus: true - } - \endcode - - \sa acceptableInput, inputMask -*/ - -QValidator* QQuickTextInput::validator() const -{ - Q_D(const QQuickTextInput); - //###const cast isn't good, but needed for property system? - return const_cast<QValidator*>(d->control->validator()); -} - -void QQuickTextInput::setValidator(QValidator* v) -{ - Q_D(QQuickTextInput); - if (d->control->validator() == v) - return; - - d->control->setValidator(v); - if (!d->control->hasAcceptableInput()) { - d->oldValidity = false; - emit acceptableInputChanged(); - } - - emit validatorChanged(); -} -#endif // QT_NO_VALIDATOR - -/*! - \qmlproperty string QtQuick2::TextInput::inputMask - - Allows you to set an input mask on the TextInput, restricting the allowable - text inputs. See QLineEdit::inputMask for further details, as the exact - same mask strings are used by TextInput. - - \sa acceptableInput, validator -*/ -QString QQuickTextInput::inputMask() const -{ - Q_D(const QQuickTextInput); - return d->control->inputMask(); -} - -void QQuickTextInput::setInputMask(const QString &im) -{ - Q_D(QQuickTextInput); - if (d->control->inputMask() == im) - return; - - d->control->setInputMask(im); - emit inputMaskChanged(d->control->inputMask()); -} - -/*! - \qmlproperty bool QtQuick2::TextInput::acceptableInput - - This property is always true unless a validator or input mask has been set. - If a validator or input mask has been set, this property will only be true - if the current text is acceptable to the validator or input mask as a final - string (not as an intermediate string). -*/ -bool QQuickTextInput::hasAcceptableInput() const -{ - Q_D(const QQuickTextInput); - return d->control->hasAcceptableInput(); -} - -/*! - \qmlsignal QtQuick2::TextInput::onAccepted() - - This handler is called when the Return or Enter key is pressed. - Note that if there is a \l validator or \l inputMask set on the text - input, the handler will only be emitted if the input is in an acceptable - state. -*/ - -void QQuickTextInputPrivate::updateInputMethodHints() -{ - Q_Q(QQuickTextInput); - Qt::InputMethodHints hints = inputMethodHints; - uint echo = control->echoMode(); - if (echo == QQuickTextInput::Password || echo == QQuickTextInput::NoEcho) - hints |= Qt::ImhHiddenText; - else if (echo == QQuickTextInput::PasswordEchoOnEdit) - hints &= ~Qt::ImhHiddenText; - if (echo != QQuickTextInput::Normal) - hints |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText); - q->setInputMethodHints(hints); -} -/*! - \qmlproperty enumeration QtQuick2::TextInput::echoMode - - Specifies how the text should be displayed in the TextInput. - \list - \o TextInput.Normal - Displays the text as it is. (Default) - \o TextInput.Password - Displays asterisks instead of characters. - \o TextInput.NoEcho - Displays nothing. - \o TextInput.PasswordEchoOnEdit - Displays characters as they are entered - while editing, otherwise displays asterisks. - \endlist -*/ -QQuickTextInput::EchoMode QQuickTextInput::echoMode() const -{ - Q_D(const QQuickTextInput); - return (QQuickTextInput::EchoMode)d->control->echoMode(); -} - -void QQuickTextInput::setEchoMode(QQuickTextInput::EchoMode echo) -{ - Q_D(QQuickTextInput); - if (echoMode() == echo) - return; - d->control->setEchoMode((QLineControl::EchoMode)echo); - d->updateInputMethodHints(); - q_textChanged(); - emit echoModeChanged(echoMode()); -} - -Qt::InputMethodHints QQuickTextInput::imHints() const -{ - Q_D(const QQuickTextInput); - return d->inputMethodHints; -} - -void QQuickTextInput::setIMHints(Qt::InputMethodHints hints) -{ - Q_D(QQuickTextInput); - if (d->inputMethodHints == hints) - return; - d->inputMethodHints = hints; - d->updateInputMethodHints(); -} - -/*! - \qmlproperty Component QtQuick2::TextInput::cursorDelegate - The delegate for the cursor in the TextInput. - - If you set a cursorDelegate for a TextInput, this delegate will be used for - drawing the cursor instead of the standard cursor. An instance of the - delegate will be created and managed by the TextInput when a cursor is - needed, and the x property of delegate instance will be set so as - to be one pixel before the top left of the current character. - - Note that the root item of the delegate component must be a QDeclarativeItem or - QDeclarativeItem derived item. -*/ -QDeclarativeComponent* QQuickTextInput::cursorDelegate() const -{ - Q_D(const QQuickTextInput); - return d->cursorComponent; -} - -void QQuickTextInput::setCursorDelegate(QDeclarativeComponent* c) -{ - Q_D(QQuickTextInput); - if (d->cursorComponent == c) - return; - - d->cursorComponent = c; - if (!c) { - //note that the components are owned by something else - delete d->cursorItem; - } else { - d->startCreatingCursor(); - } - - emit cursorDelegateChanged(); -} - -void QQuickTextInputPrivate::startCreatingCursor() -{ - Q_Q(QQuickTextInput); - if (cursorComponent->isReady()) { - q->createCursor(); - } else if (cursorComponent->isLoading()) { - q->connect(cursorComponent, SIGNAL(statusChanged(int)), - q, SLOT(createCursor())); - } else { // isError - qmlInfo(q, cursorComponent->errors()) << QQuickTextInput::tr("Could not load cursor delegate"); - } -} - -void QQuickTextInput::createCursor() -{ - Q_D(QQuickTextInput); - if (d->cursorComponent->isError()) { - qmlInfo(this, d->cursorComponent->errors()) << tr("Could not load cursor delegate"); - return; - } - - if (!d->cursorComponent->isReady()) - return; - - if (d->cursorItem) - delete d->cursorItem; - QDeclarativeContext *creationContext = d->cursorComponent->creationContext(); - QObject *object = d->cursorComponent->create(creationContext ? creationContext : qmlContext(this)); - d->cursorItem = qobject_cast<QQuickItem*>(object); - if (!d->cursorItem) { - delete object; - qmlInfo(this, d->cursorComponent->errors()) << tr("Could not instantiate cursor delegate"); - return; - } - - QDeclarative_setParent_noEvent(d->cursorItem, this); - d->cursorItem->setParentItem(this); - d->cursorItem->setX(d->control->cursorToX()); - d->cursorItem->setHeight(d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text. -} - -/*! - \qmlmethod rect QtQuick2::TextInput::positionToRectangle(int pos) - - This function takes a character position and returns the rectangle that the - cursor would occupy, if it was placed at that character position. - - This is similar to setting the cursorPosition, and then querying the cursor - rectangle, but the cursorPosition is not changed. -*/ -QRectF QQuickTextInput::positionToRectangle(int pos) const -{ - Q_D(const QQuickTextInput); - if (pos > d->control->cursorPosition()) - pos += d->control->preeditAreaText().length(); - return QRectF(d->control->cursorToX(pos)-d->hscroll, - 0.0, - d->control->cursorWidth(), - cursorRectangle().height()); -} - -/*! - \qmlmethod int QtQuick2::TextInput::positionAt(int x, CursorPosition position = CursorBetweenCharacters) - - This function returns the character position at - x pixels from the left of the textInput. Position 0 is before the - first character, position 1 is after the first character but before the second, - and so on until position text.length, which is after all characters. - - This means that for all x values before the first character this function returns 0, - and for all x values after the last character this function returns text.length. - - The cursor position type specifies how the cursor position should be resolved. - - \list - \o TextInput.CursorBetweenCharacters - Returns the position between characters that is nearest x. - \o TextInput.CursorOnCharacter - Returns the position before the character that is nearest x. - \endlist -*/ -int QQuickTextInput::positionAt(int x) const -{ - return positionAt(x, CursorBetweenCharacters); -} - -int QQuickTextInput::positionAt(int x, CursorPosition position) const -{ - Q_D(const QQuickTextInput); - int pos = d->control->xToPos(x + d->hscroll, QTextLine::CursorPosition(position)); - const int cursor = d->control->cursor(); - if (pos > cursor) { - const int preeditLength = d->control->preeditAreaText().length(); - pos = pos > cursor + preeditLength - ? pos - preeditLength - : cursor; - } - return pos; -} - -void QQuickTextInput::keyPressEvent(QKeyEvent* ev) -{ - Q_D(QQuickTextInput); - // Don't allow MacOSX up/down support, and we don't allow a completer. - bool ignore = (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) && ev->modifiers() == Qt::NoModifier; - if (!ignore && (d->lastSelectionStart == d->lastSelectionEnd) && (ev->key() == Qt::Key_Right || ev->key() == Qt::Key_Left)) { - // Ignore when moving off the end unless there is a selection, - // because then moving will do something (deselect). - int cursorPosition = d->control->cursor(); - if (cursorPosition == 0) - ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Left : Qt::Key_Right); - if (cursorPosition == d->control->text().length()) - ignore = ev->key() == (d->control->layoutDirection() == Qt::LeftToRight ? Qt::Key_Right : Qt::Key_Left); - } - if (ignore) { - ev->ignore(); - } else { - d->control->processKeyEvent(ev); - } - if (!ev->isAccepted()) - QQuickImplicitSizeItem::keyPressEvent(ev); -} - -void QQuickTextInput::inputMethodEvent(QInputMethodEvent *ev) -{ - Q_D(QQuickTextInput); - const bool wasComposing = d->control->preeditAreaText().length() > 0; - if (d->control->isReadOnly()) { - ev->ignore(); - } else { - d->control->processInputMethodEvent(ev); - } - if (!ev->isAccepted()) - QQuickImplicitSizeItem::inputMethodEvent(ev); - - if (wasComposing != (d->control->preeditAreaText().length() > 0)) - emit inputMethodComposingChanged(); -} - -void QQuickTextInput::mouseDoubleClickEvent(QMouseEvent *event) -{ - Q_D(QQuickTextInput); - - if (d->selectByMouse && event->button() == Qt::LeftButton) { - d->control->commitPreedit(); - int cursor = d->xToPos(event->localPos().x()); - d->control->selectWordAtPos(cursor); - event->setAccepted(true); - if (!d->hasPendingTripleClick()) { - d->tripleClickStartPoint = event->localPos().toPoint(); - d->tripleClickTimer.start(); - } - } else { - if (d->sendMouseEventToInputContext(event)) - return; - QQuickImplicitSizeItem::mouseDoubleClickEvent(event); - } -} - -void QQuickTextInput::mousePressEvent(QMouseEvent *event) -{ - Q_D(QQuickTextInput); - - d->pressPos = event->localPos(); - - if (d->focusOnPress) { - bool hadActiveFocus = hasActiveFocus(); - forceActiveFocus(); - // re-open input panel on press if already focused - if (hasActiveFocus() && hadActiveFocus && !isReadOnly()) - openSoftwareInputPanel(); - } - if (d->selectByMouse) { - setKeepMouseGrab(false); - d->selectPressed = true; - QPoint distanceVector = d->pressPos.toPoint() - d->tripleClickStartPoint; - if (d->hasPendingTripleClick() - && distanceVector.manhattanLength() < qApp->styleHints()->startDragDistance()) { - event->setAccepted(true); - selectAll(); - return; - } - } - - if (d->sendMouseEventToInputContext(event)) - return; - - bool mark = (event->modifiers() & Qt::ShiftModifier) && d->selectByMouse; - int cursor = d->xToPos(event->localPos().x()); - d->control->moveCursor(cursor, mark); - event->setAccepted(true); -} - -void QQuickTextInput::mouseMoveEvent(QMouseEvent *event) -{ - Q_D(QQuickTextInput); - - if (d->selectPressed) { - if (qAbs(int(event->localPos().x() - d->pressPos.x())) > qApp->styleHints()->startDragDistance()) - setKeepMouseGrab(true); - - if (d->control->composeMode()) { - // start selection - int startPos = d->xToPos(d->pressPos.x()); - int currentPos = d->xToPos(event->localPos().x()); - if (startPos != currentPos) - d->control->setSelection(startPos, currentPos - startPos); - } else { - moveCursorSelection(d->xToPos(event->localPos().x()), d->mouseSelectionMode); - } - event->setAccepted(true); - } else { - QQuickImplicitSizeItem::mouseMoveEvent(event); - } -} - -void QQuickTextInput::mouseReleaseEvent(QMouseEvent *event) -{ - Q_D(QQuickTextInput); - if (d->sendMouseEventToInputContext(event)) - return; - if (d->selectPressed) { - d->selectPressed = false; - setKeepMouseGrab(false); - } - d->control->processEvent(event); - if (!event->isAccepted()) - QQuickImplicitSizeItem::mouseReleaseEvent(event); -} - -bool QQuickTextInputPrivate::sendMouseEventToInputContext(QMouseEvent *event) -{ -#if !defined QT_NO_IM - if (control->composeMode()) { - int tmp_cursor = xToPos(event->localPos().x()); - int mousePos = tmp_cursor - control->cursor(); - if (mousePos >= 0 && mousePos <= control->preeditAreaText().length()) { - if (event->type() == QEvent::MouseButtonRelease) { - qApp->inputPanel()->invokeAction(QInputPanel::Click, mousePos); - } - return true; - } - } -#else - Q_UNUSED(event); - Q_UNUSED(eventType) -#endif - - return false; -} - -void QQuickTextInput::mouseUngrabEvent() -{ - Q_D(QQuickTextInput); - d->selectPressed = false; - setKeepMouseGrab(false); -} - -bool QQuickTextInput::event(QEvent* ev) -{ - Q_D(QQuickTextInput); - //Anything we don't deal with ourselves, pass to the control - bool handled = false; - switch (ev->type()) { - case QEvent::KeyPress: - case QEvent::KeyRelease://###Should the control be doing anything with release? - case QEvent::InputMethod: - case QEvent::MouseButtonPress: - case QEvent::MouseMove: - case QEvent::MouseButtonRelease: - case QEvent::MouseButtonDblClick: - break; - default: - handled = d->control->processEvent(ev); - } - if (!handled) - handled = QQuickImplicitSizeItem::event(ev); - return handled; -} - -void QQuickTextInput::geometryChanged(const QRectF &newGeometry, - const QRectF &oldGeometry) -{ - if (newGeometry.width() != oldGeometry.width()) { - updateSize(); - updateCursorRectangle(); - } - QQuickImplicitSizeItem::geometryChanged(newGeometry, oldGeometry); -} - -int QQuickTextInputPrivate::calculateTextWidth() -{ - return qRound(control->naturalTextWidth()); -} - -void QQuickTextInputPrivate::updateHorizontalScroll() -{ - Q_Q(QQuickTextInput); - const int preeditLength = control->preeditAreaText().length(); - const int width = q->width(); - int widthUsed = calculateTextWidth(); - - if (!autoScroll || widthUsed <= width) { - QQuickTextInput::HAlignment effectiveHAlign = q->effectiveHAlign(); - // text fits in br; use hscroll for alignment - switch (effectiveHAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) { - case Qt::AlignRight: - hscroll = widthUsed - width; - break; - case Qt::AlignHCenter: - hscroll = (widthUsed - width) / 2; - break; - default: - // Left - hscroll = 0; - break; - } - } else { - int cix = qRound(control->cursorToX(control->cursor() + preeditLength)); - if (cix - hscroll >= width) { - // text doesn't fit, cursor is to the right of br (scroll right) - hscroll = cix - width; - } else if (cix - hscroll < 0 && hscroll < widthUsed) { - // text doesn't fit, cursor is to the left of br (scroll left) - hscroll = cix; - } else if (widthUsed - hscroll < width) { - // text doesn't fit, text document is to the left of br; align - // right - hscroll = widthUsed - width; - } - if (preeditLength > 0) { - // check to ensure long pre-edit text doesn't push the cursor - // off to the left - cix = qRound(control->cursorToX( - control->cursor() + qMax(0, control->preeditCursor() - 1))); - if (cix < hscroll) - hscroll = cix; - } - } -} - -QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data) -{ - Q_UNUSED(data); - Q_D(QQuickTextInput); - - QQuickTextNode *node = static_cast<QQuickTextNode *>(oldNode); - if (node == 0) - node = new QQuickTextNode(QQuickItemPrivate::get(this)->sceneGraphContext()); - d->textNode = node; - - if (!d->textLayoutDirty) { - QSGSimpleRectNode *cursorNode = node->cursorNode(); - if (cursorNode != 0 && !isReadOnly()) { - QFontMetrics fm = QFontMetrics(d->font); - // the y offset is there to keep the baseline constant in case we have script changes in the text. - QPoint offset(-d->hscroll, fm.ascent() - d->control->ascent()); - offset.rx() += d->control->cursorToX(); - - QRect br(boundingRect().toRect()); - cursorNode->setRect(QRectF(offset, QSizeF(d->control->cursorWidth(), br.height()))); - - if (!d->cursorVisible - || (!d->control->cursorBlinkStatus() && d->control->cursorBlinkPeriod() > 0)) { - d->hideCursor(); - } else { - d->showCursor(); - } - } - } else { - node->deleteContent(); - node->setMatrix(QMatrix4x4()); - - QPoint offset = QPoint(0,0); - QFontMetrics fm = QFontMetrics(d->font); - QRect br(boundingRect().toRect()); - if (d->autoScroll) { - // the y offset is there to keep the baseline constant in case we have script changes in the text. - offset = br.topLeft() - QPoint(d->hscroll, d->control->ascent() - fm.ascent()); - } else { - offset = QPoint(d->hscroll, 0); - } - - QTextLayout *textLayout = d->control->textLayout(); - if (!textLayout->text().isEmpty()) { - node->addTextLayout(offset, textLayout, d->color, - QQuickText::Normal, QColor(), - d->selectionColor, d->selectedTextColor, - d->control->selectionStart(), - d->control->selectionEnd() - 1); // selectionEnd() returns first char after - // selection - } - - if (!isReadOnly() && d->cursorItem == 0) { - offset.rx() += d->control->cursorToX(); - node->setCursor(QRectF(offset, QSizeF(d->control->cursorWidth(), br.height())), d->color); - if (!d->cursorVisible - || (!d->control->cursorBlinkStatus() && d->control->cursorBlinkPeriod() > 0)) { - d->hideCursor(); - } else { - d->showCursor(); - } - } - - d->textLayoutDirty = false; - } - - return node; -} - -QVariant QQuickTextInput::inputMethodQuery(Qt::InputMethodQuery property) const -{ - Q_D(const QQuickTextInput); - switch (property) { - case Qt::ImEnabled: - return QVariant((bool)(flags() & ItemAcceptsInputMethod)); - case Qt::ImHints: - return QVariant((int)inputMethodHints()); - case Qt::ImCursorRectangle: - return cursorRectangle(); - case Qt::ImFont: - return font(); - case Qt::ImCursorPosition: - return QVariant(d->control->cursor()); - case Qt::ImSurroundingText: - if (d->control->echoMode() == QLineControl::PasswordEchoOnEdit - && !d->control->passwordEchoEditing()) { - return QVariant(displayText()); - } else { - return QVariant(d->control->realText()); - } - case Qt::ImCurrentSelection: - return QVariant(selectedText()); - case Qt::ImMaximumTextLength: - return QVariant(maxLength()); - case Qt::ImAnchorPosition: - if (d->control->selectionStart() == d->control->selectionEnd()) - return QVariant(d->control->cursor()); - else if (d->control->selectionStart() == d->control->cursor()) - return QVariant(d->control->selectionEnd()); - else - return QVariant(d->control->selectionStart()); - default: - return QVariant(); - } -} - -/*! - \qmlmethod void QtQuick2::TextInput::deselect() - - Removes active text selection. -*/ -void QQuickTextInput::deselect() -{ - Q_D(QQuickTextInput); - d->control->deselect(); -} - -/*! - \qmlmethod void QtQuick2::TextInput::selectAll() - - Causes all text to be selected. -*/ -void QQuickTextInput::selectAll() -{ - Q_D(QQuickTextInput); - d->control->setSelection(0, d->control->text().length()); -} - -/*! - \qmlmethod void QtQuick2::TextInput::isRightToLeft(int start, int end) - - Returns true if the natural reading direction of the editor text - found between positions \a start and \a end is right to left. -*/ -bool QQuickTextInput::isRightToLeft(int start, int end) -{ - Q_D(QQuickTextInput); - if (start > end) { - qmlInfo(this) << "isRightToLeft(start, end) called with the end property being smaller than the start."; - return false; - } else { - return d->control->text().mid(start, end - start).isRightToLeft(); - } -} - -#ifndef QT_NO_CLIPBOARD -/*! - \qmlmethod QtQuick2::TextInput::cut() - - Moves the currently selected text to the system clipboard. -*/ -void QQuickTextInput::cut() -{ - Q_D(QQuickTextInput); - d->control->copy(); - d->control->del(); -} - -/*! - \qmlmethod QtQuick2::TextInput::copy() - - Copies the currently selected text to the system clipboard. -*/ -void QQuickTextInput::copy() -{ - Q_D(QQuickTextInput); - d->control->copy(); -} - -/*! - \qmlmethod QtQuick2::TextInput::paste() - - Replaces the currently selected text by the contents of the system clipboard. -*/ -void QQuickTextInput::paste() -{ - Q_D(QQuickTextInput); - if (!d->control->isReadOnly()) - d->control->paste(); -} -#endif // QT_NO_CLIPBOARD - -/*! - \qmlmethod void QtQuick2::TextInput::selectWord() - - Causes the word closest to the current cursor position to be selected. -*/ -void QQuickTextInput::selectWord() -{ - Q_D(QQuickTextInput); - d->control->selectWordAtPos(d->control->cursor()); -} - -/*! - \qmlproperty bool QtQuick2::TextInput::smooth - - This property holds whether the text is smoothly scaled or transformed. - - Smooth filtering gives better visual quality, but is slower. If - the item is displayed at its natural size, this property has no visual or - performance effect. - - \note Generally scaling artifacts are only visible if the item is stationary on - the screen. A common pattern when animating an item is to disable smooth - filtering at the beginning of the animation and reenable it at the conclusion. -*/ - -/*! - \qmlproperty string QtQuick2::TextInput::passwordCharacter - - This is the character displayed when echoMode is set to Password or - PasswordEchoOnEdit. By default it is an asterisk. - - If this property is set to a string with more than one character, - the first character is used. If the string is empty, the value - is ignored and the property is not set. -*/ -QString QQuickTextInput::passwordCharacter() const -{ - Q_D(const QQuickTextInput); - return QString(d->control->passwordCharacter()); -} - -void QQuickTextInput::setPasswordCharacter(const QString &str) -{ - Q_D(QQuickTextInput); - if (str.length() < 1) - return; - d->control->setPasswordCharacter(str.constData()[0]); - EchoMode echoMode_ = echoMode(); - if (echoMode_ == Password || echoMode_ == PasswordEchoOnEdit) { - updateSize(); - } - emit passwordCharacterChanged(); -} - -/*! - \qmlproperty string QtQuick2::TextInput::displayText - - This is the text displayed in the TextInput. - - If \l echoMode is set to TextInput::Normal, this holds the - same value as the TextInput::text property. Otherwise, - this property holds the text visible to the user, while - the \l text property holds the actual entered text. -*/ -QString QQuickTextInput::displayText() const -{ - Q_D(const QQuickTextInput); - return d->control->displayText(); -} - -/*! - \qmlproperty bool QtQuick2::TextInput::selectByMouse - - Defaults to false. - - If true, the user can use the mouse to select text in some - platform-specific way. Note that for some platforms this may - not be an appropriate interaction (eg. may conflict with how - the text needs to behave inside a Flickable. -*/ -bool QQuickTextInput::selectByMouse() const -{ - Q_D(const QQuickTextInput); - return d->selectByMouse; -} - -void QQuickTextInput::setSelectByMouse(bool on) -{ - Q_D(QQuickTextInput); - if (d->selectByMouse != on) { - d->selectByMouse = on; - emit selectByMouseChanged(on); - } -} - -/*! - \qmlproperty enum QtQuick2::TextInput::mouseSelectionMode - - Specifies how text should be selected using a mouse. - - \list - \o TextInput.SelectCharacters - The selection is updated with individual characters. (Default) - \o TextInput.SelectWords - The selection is updated with whole words. - \endlist - - This property only applies when \l selectByMouse is true. -*/ - -QQuickTextInput::SelectionMode QQuickTextInput::mouseSelectionMode() const -{ - Q_D(const QQuickTextInput); - return d->mouseSelectionMode; -} - -void QQuickTextInput::setMouseSelectionMode(SelectionMode mode) -{ - Q_D(QQuickTextInput); - if (d->mouseSelectionMode != mode) { - d->mouseSelectionMode = mode; - emit mouseSelectionModeChanged(mode); - } -} - -/*! - \qmlproperty bool QtQuick2::TextInput::canPaste - - Returns true if the TextInput is writable and the content of the clipboard is - suitable for pasting into the TextEdit. -*/ -bool QQuickTextInput::canPaste() const -{ - Q_D(const QQuickTextInput); - return d->canPaste; -} - -void QQuickTextInput::moveCursorSelection(int position) -{ - Q_D(QQuickTextInput); - d->control->moveCursor(position, true); -} - -/*! - \qmlmethod void QtQuick2::TextInput::moveCursorSelection(int position, SelectionMode mode = TextInput.SelectCharacters) - - Moves the cursor to \a position and updates the selection according to the optional \a mode - parameter. (To only move the cursor, set the \l cursorPosition property.) - - When this method is called it additionally sets either the - selectionStart or the selectionEnd (whichever was at the previous cursor position) - to the specified position. This allows you to easily extend and contract the selected - text range. - - The selection mode specifies whether the selection is updated on a per character or a per word - basis. If not specified the selection mode will default to TextInput.SelectCharacters. - - \list - \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at - the previous cursor position) to the specified position. - \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all - words between the specified position and the previous cursor position. Words partially in the - range are included. - \endlist - - For example, take this sequence of calls: - - \code - cursorPosition = 5 - moveCursorSelection(9, TextInput.SelectCharacters) - moveCursorSelection(7, TextInput.SelectCharacters) - \endcode - - This moves the cursor to position 5, extend the selection end from 5 to 9 - and then retract the selection end from 9 to 7, leaving the text from position 5 to 7 - selected (the 6th and 7th characters). - - The same sequence with TextInput.SelectWords will extend the selection start to a word boundary - before or on position 5 and extend the selection end to a word boundary on or past position 9. -*/ -void QQuickTextInput::moveCursorSelection(int pos, SelectionMode mode) -{ - Q_D(QQuickTextInput); - - if (mode == SelectCharacters) { - d->control->moveCursor(pos, true); - } else if (pos != d->control->cursor()){ - const int cursor = d->control->cursor(); - int anchor; - if (!d->control->hasSelectedText()) - anchor = d->control->cursor(); - else if (d->control->selectionStart() == d->control->cursor()) - anchor = d->control->selectionEnd(); - else - anchor = d->control->selectionStart(); - - if (anchor < pos || (anchor == pos && cursor < pos)) { - const QString text = d->control->text(); - QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text); - finder.setPosition(anchor); - - const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons(); - if (anchor < text.length() && (!(reasons & QTextBoundaryFinder::StartWord) - || ((reasons & QTextBoundaryFinder::EndWord) && anchor > cursor))) { - finder.toPreviousBoundary(); - } - anchor = finder.position() != -1 ? finder.position() : 0; - - finder.setPosition(pos); - if (pos > 0 && !finder.boundaryReasons()) - finder.toNextBoundary(); - const int cursor = finder.position() != -1 ? finder.position() : text.length(); - - d->control->setSelection(anchor, cursor - anchor); - } else if (anchor > pos || (anchor == pos && cursor > pos)) { - const QString text = d->control->text(); - QTextBoundaryFinder finder(QTextBoundaryFinder::Word, text); - finder.setPosition(anchor); - - const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons(); - if (anchor > 0 && (!(reasons & QTextBoundaryFinder::EndWord) - || ((reasons & QTextBoundaryFinder::StartWord) && anchor < cursor))) { - finder.toNextBoundary(); - } - - anchor = finder.position() != -1 ? finder.position() : text.length(); - - finder.setPosition(pos); - if (pos < text.length() && !finder.boundaryReasons()) - finder.toPreviousBoundary(); - const int cursor = finder.position() != -1 ? finder.position() : 0; - - d->control->setSelection(anchor, cursor - anchor); - } - } -} - -/*! - \qmlmethod void QtQuick2::TextInput::openSoftwareInputPanel() - - Opens software input panels like virtual keyboards for typing, useful for - customizing when you want the input keyboard to be shown and hidden in - your application. - - By default the opening of input panels follows the platform style. Input panels are - always closed if no editor has active focus. - - You can disable the automatic behavior by setting the property \c activeFocusOnPress to false - and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement - the behavior you want. - - Only relevant on platforms, which provide virtual keyboards. - - \qml - import QtQuick 1.0 - TextInput { - id: textInput - text: "Hello world!" - activeFocusOnPress: false - MouseArea { - anchors.fill: parent - onClicked: { - if (!textInput.activeFocus) { - textInput.forceActiveFocus() - textInput.openSoftwareInputPanel(); - } else { - textInput.focus = false; - } - } - onPressAndHold: textInput.closeSoftwareInputPanel(); - } - } - \endqml -*/ -void QQuickTextInput::openSoftwareInputPanel() -{ - if (qGuiApp) - qGuiApp->inputPanel()->show(); -} - -/*! - \qmlmethod void QtQuick2::TextInput::closeSoftwareInputPanel() - - Closes a software input panel like a virtual keyboard shown on the screen, useful - for customizing when you want the input keyboard to be shown and hidden in - your application. - - By default the opening of input panels follows the platform style. Input panels are - always closed if no editor has active focus. - - You can disable the automatic behavior by setting the property \c activeFocusOnPress to false - and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement - the behavior you want. - - Only relevant on platforms, which provide virtual keyboards. - - \qml - import QtQuick 1.0 - TextInput { - id: textInput - text: "Hello world!" - activeFocusOnPress: false - MouseArea { - anchors.fill: parent - onClicked: { - if (!textInput.activeFocus) { - textInput.forceActiveFocus(); - textInput.openSoftwareInputPanel(); - } else { - textInput.focus = false; - } - } - onPressAndHold: textInput.closeSoftwareInputPanel(); - } - } - \endqml -*/ -void QQuickTextInput::closeSoftwareInputPanel() -{ - if (qGuiApp) - qGuiApp->inputPanel()->hide(); -} - -void QQuickTextInput::focusInEvent(QFocusEvent *event) -{ - Q_D(const QQuickTextInput); - if (d->focusOnPress && !isReadOnly()) - openSoftwareInputPanel(); - QQuickImplicitSizeItem::focusInEvent(event); -} - -void QQuickTextInput::itemChange(ItemChange change, const ItemChangeData &value) -{ - Q_D(QQuickTextInput); - if (change == ItemActiveFocusHasChanged) { - bool hasFocus = value.boolValue; - d->focused = hasFocus; - setCursorVisible(hasFocus); // ### refactor: && d->canvas && d->canvas->hasFocus() - if (echoMode() == QQuickTextInput::PasswordEchoOnEdit && !hasFocus) - d->control->updatePasswordEchoEditing(false);//QLineControl sets it on key events, but doesn't deal with focus events - if (!hasFocus) - d->control->deselect(); - } - QQuickItem::itemChange(change, value); -} - -/*! - \qmlproperty bool QtQuick2::TextInput::inputMethodComposing - - - This property holds whether the TextInput has partial text input from an - input method. - - While it is composing an input method may rely on mouse or key events from - the TextInput to edit or commit the partial text. This property can be - used to determine when to disable events handlers that may interfere with - the correct operation of an input method. -*/ -bool QQuickTextInput::isInputMethodComposing() const -{ - Q_D(const QQuickTextInput); - return d->control->preeditAreaText().length() > 0; -} - -void QQuickTextInputPrivate::init() -{ - Q_Q(QQuickTextInput); - control->setParent(q);//Now mandatory due to accessibility changes - control->setCursorWidth(1); - control->setPasswordCharacter(QLatin1Char('*')); - q->setSmooth(smooth); - q->setAcceptedMouseButtons(Qt::LeftButton); - q->setFlag(QQuickItem::ItemAcceptsInputMethod); - q->setFlag(QQuickItem::ItemHasContents); - q->connect(control, SIGNAL(cursorPositionChanged(int,int)), - q, SLOT(cursorPosChanged())); - q->connect(control, SIGNAL(selectionChanged()), - q, SLOT(selectionChanged())); - q->connect(control, SIGNAL(textChanged(QString)), - q, SLOT(q_textChanged())); - q->connect(control, SIGNAL(accepted()), - q, SIGNAL(accepted())); - q->connect(control, SIGNAL(updateNeeded(QRect)), - q, SLOT(updateRect(QRect))); -#ifndef QT_NO_CLIPBOARD - q->connect(q, SIGNAL(readOnlyChanged(bool)), - q, SLOT(q_canPasteChanged())); - q->connect(QGuiApplication::clipboard(), SIGNAL(dataChanged()), - q, SLOT(q_canPasteChanged())); - canPaste = !control->isReadOnly() && QGuiApplication::clipboard()->text().length() != 0; -#endif // QT_NO_CLIPBOARD - q->connect(control, SIGNAL(updateMicroFocus()), - q, SLOT(updateCursorRectangle())); - q->connect(control, SIGNAL(displayTextChanged(QString)), - q, SLOT(updateRect())); - q->updateSize(); - imHints &= ~Qt::ImhMultiLine; - oldValidity = control->hasAcceptableInput(); - lastSelectionStart = 0; - lastSelectionEnd = 0; - QPalette p = control->palette(); - selectedTextColor = p.color(QPalette::HighlightedText); - selectionColor = p.color(QPalette::Highlight); - determineHorizontalAlignment(); - - if (!qmlDisableDistanceField()) { - QTextOption option = control->textLayout()->textOption(); - option.setUseDesignMetrics(true); - control->textLayout()->setTextOption(option); - } -} - -void QQuickTextInput::cursorPosChanged() -{ - Q_D(QQuickTextInput); - updateCursorRectangle(); - emit cursorPositionChanged(); - // XXX todo - not in 4.8? -#if 0 - d->control->resetCursorBlinkTimer(); -#endif - - if (!d->control->hasSelectedText()) { - if (d->lastSelectionStart != d->control->cursor()) { - d->lastSelectionStart = d->control->cursor(); - emit selectionStartChanged(); - } - if (d->lastSelectionEnd != d->control->cursor()) { - d->lastSelectionEnd = d->control->cursor(); - emit selectionEndChanged(); - } - } -} - -void QQuickTextInput::updateCursorRectangle() -{ - Q_D(QQuickTextInput); - d->determineHorizontalAlignment(); - d->updateHorizontalScroll(); - updateRect();//TODO: Only update rect between pos's - updateMicroFocus(); - emit cursorRectangleChanged(); - if (d->cursorItem) - d->cursorItem->setX(d->control->cursorToX() - d->hscroll); -} - -void QQuickTextInput::selectionChanged() -{ - Q_D(QQuickTextInput); - updateRect();//TODO: Only update rect in selection - emit selectedTextChanged(); - - if (d->lastSelectionStart != d->control->selectionStart()) { - d->lastSelectionStart = d->control->selectionStart(); - if (d->lastSelectionStart == -1) - d->lastSelectionStart = d->control->cursor(); - emit selectionStartChanged(); - } - if (d->lastSelectionEnd != d->control->selectionEnd()) { - d->lastSelectionEnd = d->control->selectionEnd(); - if (d->lastSelectionEnd == -1) - d->lastSelectionEnd = d->control->cursor(); - emit selectionEndChanged(); - } -} - -void QQuickTextInput::q_textChanged() -{ - Q_D(QQuickTextInput); - emit textChanged(); - emit displayTextChanged(); - updateSize(); - d->determineHorizontalAlignment(); - d->updateHorizontalScroll(); - updateMicroFocus(); - if (hasAcceptableInput() != d->oldValidity) { - d->oldValidity = hasAcceptableInput(); - emit acceptableInputChanged(); - } -} - -void QQuickTextInputPrivate::showCursor() -{ - if (textNode != 0 && textNode->cursorNode() != 0) - textNode->cursorNode()->setColor(color); -} - -void QQuickTextInputPrivate::hideCursor() -{ - if (textNode != 0 && textNode->cursorNode() != 0) - textNode->cursorNode()->setColor(QColor(0, 0, 0, 0)); -} - -void QQuickTextInput::updateRect(const QRect &r) -{ - Q_D(QQuickTextInput); - if (!isComponentComplete()) - return; - - if (r.isEmpty()) { - d->textLayoutDirty = true; - } - - update(); -} - -QRectF QQuickTextInput::boundingRect() const -{ - Q_D(const QQuickTextInput); - QRectF r = QQuickImplicitSizeItem::boundingRect(); - - int cursorWidth = d->cursorItem ? d->cursorItem->width() : d->control->cursorWidth(); - - // Could include font max left/right bearings to either side of rectangle. - - r.setRight(r.right() + cursorWidth); - return r; -} - -void QQuickTextInput::updateSize(bool needsRedraw) -{ - Q_D(QQuickTextInput); - int w = width(); - int h = height(); - setImplicitSize(d->calculateTextWidth(), d->control->height()-1); // -1 to counter QLineControl's +1 which is not consistent with Text. - if (w==width() && h==height() && needsRedraw) - update(); -} - -void QQuickTextInput::q_canPasteChanged() -{ - Q_D(QQuickTextInput); - bool old = d->canPaste; -#ifndef QT_NO_CLIPBOARD - d->canPaste = !d->control->isReadOnly() && QGuiApplication::clipboard()->text().length() != 0; -#endif - if (d->canPaste != old) - emit canPasteChanged(); -} - -QT_END_NAMESPACE - |