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 "qsgtextedit_p.h"
43 #include "qsgtextedit_p_p.h"
44 #include "qsgevents_p_p.h"
45 #include "qsgcanvas.h"
47 #include <QtDeclarative/qdeclarativeinfo.h>
48 #include <QtGui/qapplication.h>
49 #include <QtGui/qgraphicssceneevent.h>
50 #include <QtGui/qpainter.h>
51 #include <QtGui/qtextobject.h>
52 #include <QtCore/qmath.h>
54 #include <private/qdeclarativeglobal_p.h>
55 #include <private/qtextcontrol_p.h>
56 #include <private/qtextengine_p.h>
57 #include <private/qwidget_p.h>
61 QWidgetPrivate *qt_widget_private(QWidget *widget);
63 \qmlclass TextEdit QSGTextEdit
64 \inqmlmodule QtQuick 2
65 \ingroup qml-basic-visual-elements
66 \brief The TextEdit item displays multiple lines of editable formatted text.
69 The TextEdit item displays a block of editable, formatted text.
71 It can display both plain and rich text. For example:
76 text: "<b>Hello</b> <i>World!</i>"
77 font.family: "Helvetica"
84 \image declarative-textedit.gif
86 Setting \l {Item::focus}{focus} to \c true enables the TextEdit item to receive keyboard focus.
88 Note that the TextEdit does not implement scrolling, following the cursor, or other behaviors specific
89 to a look-and-feel. For example, to add flickable scrolling that follows the cursor:
91 \snippet snippets/declarative/texteditor.qml 0
93 A particular look-and-feel might use smooth scrolling (eg. using SmoothedFollow), might have a visible
94 scrollbar, or a scrollbar that fades in to show location, etc.
96 Clipboard support is provided by the cut(), copy(), and paste() functions, and the selection can
97 be handled in a traditional "mouse" mechanism by setting selectByMouse, or handled completely
98 from QML by manipulating selectionStart and selectionEnd, or using selectAll() or selectWord().
100 You can translate between cursor positions (characters from the start of the document) and pixel
101 points using positionAt() and positionToRectangle().
103 \sa Text, TextInput, {declarative/text/textselection}{Text Selection example}
107 \qmlsignal QtQuick2::TextEdit::onLinkActivated(string link)
109 This handler is called when the user clicks on a link embedded in the text.
110 The link must be in rich text or HTML format and the
111 \a link string provides access to the particular link.
113 QSGTextEdit::QSGTextEdit(QSGItem *parent)
114 : QSGImplicitSizePaintedItem(*(new QSGTextEditPrivate), parent)
120 QString QSGTextEdit::text() const
122 Q_D(const QSGTextEdit);
124 #ifndef QT_NO_TEXTHTMLPARSER
126 return d->document->toHtml();
129 return d->document->toPlainText();
133 \qmlproperty string QtQuick2::TextEdit::font.family
135 Sets the family name of the font.
137 The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]".
138 If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen.
139 If the family isn't available a family will be set using the font matching algorithm.
143 \qmlproperty bool QtQuick2::TextEdit::font.bold
145 Sets whether the font weight is bold.
149 \qmlproperty enumeration QtQuick2::TextEdit::font.weight
151 Sets the font's weight.
153 The weight can be one of:
156 \o Font.Normal - the default
163 TextEdit { text: "Hello"; font.weight: Font.DemiBold }
168 \qmlproperty bool QtQuick2::TextEdit::font.italic
170 Sets whether the font has an italic style.
174 \qmlproperty bool QtQuick2::TextEdit::font.underline
176 Sets whether the text is underlined.
180 \qmlproperty bool QtQuick2::TextEdit::font.strikeout
182 Sets whether the font has a strikeout style.
186 \qmlproperty real QtQuick2::TextEdit::font.pointSize
188 Sets the font size in points. The point size must be greater than zero.
192 \qmlproperty int QtQuick2::TextEdit::font.pixelSize
194 Sets the font size in pixels.
196 Using this function makes the font device dependent. Use
197 \l{TextEdit::font.pointSize} to set the size of the font in a
198 device independent manner.
202 \qmlproperty real QtQuick2::TextEdit::font.letterSpacing
204 Sets the letter spacing for the font.
206 Letter spacing changes the default spacing between individual letters in the font.
207 A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing.
211 \qmlproperty real QtQuick2::TextEdit::font.wordSpacing
213 Sets the word spacing for the font.
215 Word spacing changes the default spacing between individual words.
216 A positive value increases the word spacing by a corresponding amount of pixels,
217 while a negative value decreases the inter-word spacing accordingly.
221 \qmlproperty enumeration QtQuick2::TextEdit::font.capitalization
223 Sets the capitalization for the text.
226 \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied.
227 \o Font.AllUppercase - This alters the text to be rendered in all uppercase type.
228 \o Font.AllLowercase - This alters the text to be rendered in all lowercase type.
229 \o Font.SmallCaps - This alters the text to be rendered in small-caps type.
230 \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character.
234 TextEdit { text: "Hello"; font.capitalization: Font.AllLowercase }
239 \qmlproperty string QtQuick2::TextEdit::text
241 The text to display. If the text format is AutoText the text edit will
242 automatically determine whether the text should be treated as
243 rich text. This determination is made using Qt::mightBeRichText().
245 void QSGTextEdit::setText(const QString &text)
248 if (QSGTextEdit::text() == text)
251 d->richText = d->format == RichText || (d->format == AutoText && Qt::mightBeRichText(text));
253 #ifndef QT_NO_TEXTHTMLPARSER
254 d->control->setHtml(text);
256 d->control->setPlainText(text);
259 d->control->setPlainText(text);
265 \qmlproperty enumeration QtQuick2::TextEdit::textFormat
267 The way the text property should be displayed.
271 \o TextEdit.PlainText
275 The default is TextEdit.AutoText. If the text format is TextEdit.AutoText the text edit
276 will automatically determine whether the text should be treated as
277 rich text. This determination is made using Qt::mightBeRichText().
286 text: "<b>Hello</b> <i>World!</i>"
290 textFormat: TextEdit.RichText
291 text: "<b>Hello</b> <i>World!</i>"
295 textFormat: TextEdit.PlainText
296 text: "<b>Hello</b> <i>World!</i>"
300 \o \image declarative-textformat.png
303 QSGTextEdit::TextFormat QSGTextEdit::textFormat() const
305 Q_D(const QSGTextEdit);
309 void QSGTextEdit::setTextFormat(TextFormat format)
312 if (format == d->format)
314 bool wasRich = d->richText;
315 d->richText = format == RichText || (format == AutoText && Qt::mightBeRichText(d->text));
317 if (wasRich && !d->richText) {
318 d->control->setPlainText(d->text);
320 } else if (!wasRich && d->richText) {
321 #ifndef QT_NO_TEXTHTMLPARSER
322 d->control->setHtml(d->text);
324 d->control->setPlainText(d->text);
329 d->control->setAcceptRichText(d->format != PlainText);
330 emit textFormatChanged(d->format);
333 QFont QSGTextEdit::font() const
335 Q_D(const QSGTextEdit);
336 return d->sourceFont;
339 void QSGTextEdit::setFont(const QFont &font)
342 if (d->sourceFont == font)
345 d->sourceFont = font;
346 QFont oldFont = d->font;
348 if (d->font.pointSizeF() != -1) {
350 qreal size = qRound(d->font.pointSizeF()*2.0);
351 d->font.setPointSizeF(size/2.0);
354 if (oldFont != d->font) {
355 d->document->setDefaultFont(d->font);
357 d->cursor->setHeight(QFontMetrics(d->font).height());
358 moveCursorDelegate();
363 emit fontChanged(d->sourceFont);
367 \qmlproperty color QtQuick2::TextEdit::color
372 // green text using hexadecimal notation
373 TextEdit { color: "#00FF00" }
377 // steelblue text using SVG color name
378 TextEdit { color: "steelblue" }
381 QColor QSGTextEdit::color() const
383 Q_D(const QSGTextEdit);
387 void QSGTextEdit::setColor(const QColor &color)
390 if (d->color == color)
394 QPalette pal = d->control->palette();
395 pal.setColor(QPalette::Text, color);
396 d->control->setPalette(pal);
398 emit colorChanged(d->color);
402 \qmlproperty color QtQuick2::TextEdit::selectionColor
404 The text highlight color, used behind selections.
406 QColor QSGTextEdit::selectionColor() const
408 Q_D(const QSGTextEdit);
409 return d->selectionColor;
412 void QSGTextEdit::setSelectionColor(const QColor &color)
415 if (d->selectionColor == color)
418 d->selectionColor = color;
419 QPalette pal = d->control->palette();
420 pal.setColor(QPalette::Highlight, color);
421 d->control->setPalette(pal);
423 emit selectionColorChanged(d->selectionColor);
427 \qmlproperty color QtQuick2::TextEdit::selectedTextColor
429 The selected text color, used in selections.
431 QColor QSGTextEdit::selectedTextColor() const
433 Q_D(const QSGTextEdit);
434 return d->selectedTextColor;
437 void QSGTextEdit::setSelectedTextColor(const QColor &color)
440 if (d->selectedTextColor == color)
443 d->selectedTextColor = color;
444 QPalette pal = d->control->palette();
445 pal.setColor(QPalette::HighlightedText, color);
446 d->control->setPalette(pal);
448 emit selectedTextColorChanged(d->selectedTextColor);
452 \qmlproperty enumeration QtQuick2::TextEdit::horizontalAlignment
453 \qmlproperty enumeration QtQuick2::TextEdit::verticalAlignment
454 \qmlproperty enumeration QtQuick2::TextEdit::effectiveHorizontalAlignment
456 Sets the horizontal and vertical alignment of the text within the TextEdit item's
457 width and height. By default, the text alignment follows the natural alignment
458 of the text, for example text that is read from left to right will be aligned to
461 Valid values for \c horizontalAlignment are:
463 \o TextEdit.AlignLeft (default)
464 \o TextEdit.AlignRight
465 \o TextEdit.AlignHCenter
466 \o TextEdit.AlignJustify
469 Valid values for \c verticalAlignment are:
471 \o TextEdit.AlignTop (default)
472 \o TextEdit.AlignBottom
473 \o TextEdit.AlignVCenter
476 When using the attached property LayoutMirroring::enabled to mirror application
477 layouts, the horizontal alignment of text will also be mirrored. However, the property
478 \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
479 of TextEdit, use the read-only property \c effectiveHorizontalAlignment.
481 QSGTextEdit::HAlignment QSGTextEdit::hAlign() const
483 Q_D(const QSGTextEdit);
487 void QSGTextEdit::setHAlign(HAlignment align)
490 bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror;
491 d->hAlignImplicit = false;
492 if (d->setHAlign(align, forceAlign) && isComponentComplete()) {
493 d->updateDefaultTextOption();
498 void QSGTextEdit::resetHAlign()
501 d->hAlignImplicit = true;
502 if (d->determineHorizontalAlignment() && isComponentComplete()) {
503 d->updateDefaultTextOption();
508 QSGTextEdit::HAlignment QSGTextEdit::effectiveHAlign() const
510 Q_D(const QSGTextEdit);
511 QSGTextEdit::HAlignment effectiveAlignment = d->hAlign;
512 if (!d->hAlignImplicit && d->effectiveLayoutMirror) {
514 case QSGTextEdit::AlignLeft:
515 effectiveAlignment = QSGTextEdit::AlignRight;
517 case QSGTextEdit::AlignRight:
518 effectiveAlignment = QSGTextEdit::AlignLeft;
524 return effectiveAlignment;
527 bool QSGTextEditPrivate::setHAlign(QSGTextEdit::HAlignment alignment, bool forceAlign)
530 if (hAlign != alignment || forceAlign) {
531 QSGTextEdit::HAlignment oldEffectiveHAlign = q->effectiveHAlign();
533 emit q->horizontalAlignmentChanged(alignment);
534 if (oldEffectiveHAlign != q->effectiveHAlign())
535 emit q->effectiveHorizontalAlignmentChanged();
541 bool QSGTextEditPrivate::determineHorizontalAlignment()
544 if (hAlignImplicit && q->isComponentComplete()) {
545 bool alignToRight = text.isEmpty() ? QApplication::keyboardInputDirection() == Qt::RightToLeft : rightToLeftText;
546 return setHAlign(alignToRight ? QSGTextEdit::AlignRight : QSGTextEdit::AlignLeft);
551 void QSGTextEditPrivate::mirrorChange()
554 if (q->isComponentComplete()) {
555 if (!hAlignImplicit && (hAlign == QSGTextEdit::AlignRight || hAlign == QSGTextEdit::AlignLeft)) {
556 updateDefaultTextOption();
558 emit q->effectiveHorizontalAlignmentChanged();
563 QSGTextEdit::VAlignment QSGTextEdit::vAlign() const
565 Q_D(const QSGTextEdit);
569 void QSGTextEdit::setVAlign(QSGTextEdit::VAlignment alignment)
572 if (alignment == d->vAlign)
574 d->vAlign = alignment;
575 d->updateDefaultTextOption();
577 moveCursorDelegate();
578 emit verticalAlignmentChanged(d->vAlign);
581 \qmlproperty enumeration QtQuick2::TextEdit::wrapMode
583 Set this property to wrap the text to the TextEdit item's width.
584 The text will only wrap if an explicit width has been set.
587 \o TextEdit.NoWrap - no wrapping will be performed. If the text contains insufficient newlines, then implicitWidth will exceed a set width.
588 \o TextEdit.WordWrap - wrapping is done on word boundaries only. If a word is too long, implicitWidth will exceed a set width.
589 \o TextEdit.WrapAnywhere - wrapping is done at any point on a line, even if it occurs in the middle of a word.
590 \o TextEdit.Wrap - if possible, wrapping occurs at a word boundary; otherwise it will occur at the appropriate point on the line, even in the middle of a word.
593 The default is TextEdit.NoWrap. If you set a width, consider using TextEdit.Wrap.
595 QSGTextEdit::WrapMode QSGTextEdit::wrapMode() const
597 Q_D(const QSGTextEdit);
601 void QSGTextEdit::setWrapMode(WrapMode mode)
604 if (mode == d->wrapMode)
607 d->updateDefaultTextOption();
609 emit wrapModeChanged();
613 \qmlproperty int QtQuick2::TextEdit::lineCount
615 Returns the total number of lines in the textEdit item.
617 int QSGTextEdit::lineCount() const
619 Q_D(const QSGTextEdit);
624 \qmlproperty real QtQuick2::TextEdit::paintedWidth
626 Returns the width of the text, including the width past the width
627 which is covered due to insufficient wrapping if \l wrapMode is set.
629 qreal QSGTextEdit::paintedWidth() const
631 Q_D(const QSGTextEdit);
632 return d->paintedSize.width();
636 \qmlproperty real QtQuick2::TextEdit::paintedHeight
638 Returns the height of the text, including the height past the height
639 that is covered if the text does not fit within the set height.
641 qreal QSGTextEdit::paintedHeight() const
643 Q_D(const QSGTextEdit);
644 return d->paintedSize.height();
648 \qmlmethod rectangle QtQuick2::TextEdit::positionToRectangle(position)
650 Returns the rectangle at the given \a position in the text. The x, y,
651 and height properties correspond to the cursor that would describe
654 QRectF QSGTextEdit::positionToRectangle(int pos) const
656 Q_D(const QSGTextEdit);
657 QTextCursor c(d->document);
659 return d->control->cursorRect(c);
664 \qmlmethod int QtQuick2::TextEdit::positionAt(int x, int y)
666 Returns the text position closest to pixel position (\a x, \a y).
668 Position 0 is before the first character, position 1 is after the first character
669 but before the second, and so on until position \l {text}.length, which is after all characters.
671 int QSGTextEdit::positionAt(int x, int y) const
673 Q_D(const QSGTextEdit);
674 int r = d->document->documentLayout()->hitTest(QPoint(x,y-d->yoff), Qt::FuzzyHit);
675 QTextCursor cursor = d->control->textCursor();
676 if (r > cursor.position()) {
677 // The cursor position includes positions within the preedit text, but only positions in the
678 // same text block are offset so it is possible to get a position that is either part of the
679 // preedit or the next text block.
680 QTextLayout *layout = cursor.block().layout();
681 const int preeditLength = layout
682 ? layout->preeditAreaText().length()
684 if (preeditLength > 0
685 && d->document->documentLayout()->blockBoundingRect(cursor.block()).contains(x,y-d->yoff)) {
686 r = r > cursor.position() + preeditLength
695 \qmlmethod void QtQuick2::TextEdit::moveCursorSelection(int position, SelectionMode mode = TextEdit.SelectCharacters)
697 Moves the cursor to \a position and updates the selection according to the optional \a mode
698 parameter. (To only move the cursor, set the \l cursorPosition property.)
700 When this method is called it additionally sets either the
701 selectionStart or the selectionEnd (whichever was at the previous cursor position)
702 to the specified position. This allows you to easily extend and contract the selected
705 The selection mode specifies whether the selection is updated on a per character or a per word
706 basis. If not specified the selection mode will default to TextEdit.SelectCharacters.
709 \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
710 the previous cursor position) to the specified position.
711 \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all
712 words between the specified postion and the previous cursor position. Words partially in the
716 For example, take this sequence of calls:
720 moveCursorSelection(9, TextEdit.SelectCharacters)
721 moveCursorSelection(7, TextEdit.SelectCharacters)
724 This moves the cursor to position 5, extend the selection end from 5 to 9
725 and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
726 selected (the 6th and 7th characters).
728 The same sequence with TextEdit.SelectWords will extend the selection start to a word boundary
729 before or on position 5 and extend the selection end to a word boundary on or past position 9.
731 void QSGTextEdit::moveCursorSelection(int pos)
733 //Note that this is the same as setCursorPosition but with the KeepAnchor flag set
735 QTextCursor cursor = d->control->textCursor();
736 if (cursor.position() == pos)
738 cursor.setPosition(pos, QTextCursor::KeepAnchor);
739 d->control->setTextCursor(cursor);
742 void QSGTextEdit::moveCursorSelection(int pos, SelectionMode mode)
745 QTextCursor cursor = d->control->textCursor();
746 if (cursor.position() == pos)
748 if (mode == SelectCharacters) {
749 cursor.setPosition(pos, QTextCursor::KeepAnchor);
750 } else if (cursor.anchor() < pos || (cursor.anchor() == pos && cursor.position() < pos)) {
751 if (cursor.anchor() > cursor.position()) {
752 cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
753 cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor);
754 if (cursor.position() == cursor.anchor())
755 cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::MoveAnchor);
757 cursor.setPosition(cursor.position(), QTextCursor::MoveAnchor);
759 cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
760 cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::MoveAnchor);
763 cursor.setPosition(pos, QTextCursor::KeepAnchor);
764 cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor);
765 if (cursor.position() != pos)
766 cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
767 } else if (cursor.anchor() > pos || (cursor.anchor() == pos && cursor.position() > pos)) {
768 if (cursor.anchor() < cursor.position()) {
769 cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
770 cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::MoveAnchor);
772 cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
773 cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor);
774 cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
775 if (cursor.position() != cursor.anchor()) {
776 cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
777 cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::MoveAnchor);
781 cursor.setPosition(pos, QTextCursor::KeepAnchor);
782 cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
783 if (cursor.position() != pos) {
784 cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor);
785 cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor);
788 d->control->setTextCursor(cursor);
792 \qmlproperty bool QtQuick2::TextEdit::cursorVisible
793 If true the text edit shows a cursor.
795 This property is set and unset when the text edit gets active focus, but it can also
796 be set directly (useful, for example, if a KeyProxy might forward keys to it).
798 bool QSGTextEdit::isCursorVisible() const
800 Q_D(const QSGTextEdit);
801 return d->cursorVisible;
804 void QSGTextEdit::setCursorVisible(bool on)
807 if (d->cursorVisible == on)
809 d->cursorVisible = on;
810 QFocusEvent focusEvent(on ? QEvent::FocusIn : QEvent::FocusOut);
811 if (!on && !d->persistentSelection)
812 d->control->setCursorIsFocusIndicator(true);
813 d->control->processEvent(&focusEvent, QPointF(0, -d->yoff));
814 emit cursorVisibleChanged(d->cursorVisible);
818 \qmlproperty int QtQuick2::TextEdit::cursorPosition
819 The position of the cursor in the TextEdit.
821 int QSGTextEdit::cursorPosition() const
823 Q_D(const QSGTextEdit);
824 return d->control->textCursor().position();
827 void QSGTextEdit::setCursorPosition(int pos)
830 if (pos < 0 || pos > d->text.length())
832 QTextCursor cursor = d->control->textCursor();
833 if (cursor.position() == pos && cursor.anchor() == pos)
835 cursor.setPosition(pos);
836 d->control->setTextCursor(cursor);
840 \qmlproperty Component QtQuick2::TextEdit::cursorDelegate
841 The delegate for the cursor in the TextEdit.
843 If you set a cursorDelegate for a TextEdit, this delegate will be used for
844 drawing the cursor instead of the standard cursor. An instance of the
845 delegate will be created and managed by the text edit when a cursor is
846 needed, and the x and y properties of delegate instance will be set so as
847 to be one pixel before the top left of the current character.
849 Note that the root item of the delegate component must be a QDeclarativeItem or
850 QDeclarativeItem derived item.
852 QDeclarativeComponent* QSGTextEdit::cursorDelegate() const
854 Q_D(const QSGTextEdit);
855 return d->cursorComponent;
858 void QSGTextEdit::setCursorDelegate(QDeclarativeComponent* c)
861 if(d->cursorComponent){
863 d->control->setCursorWidth(-1);
864 update(cursorRectangle());
869 d->cursorComponent = c;
870 if(c && c->isReady()){
871 loadCursorDelegate();
874 connect(c, SIGNAL(statusChanged()),
875 this, SLOT(loadCursorDelegate()));
878 emit cursorDelegateChanged();
881 void QSGTextEdit::loadCursorDelegate()
884 if(d->cursorComponent->isLoading())
886 d->cursor = qobject_cast<QSGItem*>(d->cursorComponent->create(qmlContext(this)));
888 d->control->setCursorWidth(0);
889 update(cursorRectangle());
890 QDeclarative_setParent_noEvent(d->cursor, this);
891 d->cursor->setParentItem(this);
892 d->cursor->setHeight(QFontMetrics(d->font).height());
893 moveCursorDelegate();
895 qmlInfo(this) << "Error loading cursor delegate.";
900 \qmlproperty int QtQuick2::TextEdit::selectionStart
902 The cursor position before the first character in the current selection.
904 This property is read-only. To change the selection, use select(start,end),
905 selectAll(), or selectWord().
907 \sa selectionEnd, cursorPosition, selectedText
909 int QSGTextEdit::selectionStart() const
911 Q_D(const QSGTextEdit);
912 return d->control->textCursor().selectionStart();
916 \qmlproperty int QtQuick2::TextEdit::selectionEnd
918 The cursor position after the last character in the current selection.
920 This property is read-only. To change the selection, use select(start,end),
921 selectAll(), or selectWord().
923 \sa selectionStart, cursorPosition, selectedText
925 int QSGTextEdit::selectionEnd() const
927 Q_D(const QSGTextEdit);
928 return d->control->textCursor().selectionEnd();
932 \qmlproperty string QtQuick2::TextEdit::selectedText
934 This read-only property provides the text currently selected in the
937 It is equivalent to the following snippet, but is faster and easier
940 //myTextEdit is the id of the TextEdit
941 myTextEdit.text.toString().substring(myTextEdit.selectionStart,
942 myTextEdit.selectionEnd);
945 QString QSGTextEdit::selectedText() const
947 Q_D(const QSGTextEdit);
948 return d->control->textCursor().selectedText();
952 \qmlproperty bool QtQuick2::TextEdit::activeFocusOnPress
954 Whether the TextEdit should gain active focus on a mouse press. By default this is
957 bool QSGTextEdit::focusOnPress() const
959 Q_D(const QSGTextEdit);
960 return d->focusOnPress;
963 void QSGTextEdit::setFocusOnPress(bool on)
966 if (d->focusOnPress == on)
968 d->focusOnPress = on;
969 emit activeFocusOnPressChanged(d->focusOnPress);
973 \qmlproperty bool QtQuick2::TextEdit::persistentSelection
975 Whether the TextEdit should keep the selection visible when it loses active focus to another
976 item in the scene. By default this is set to true;
978 bool QSGTextEdit::persistentSelection() const
980 Q_D(const QSGTextEdit);
981 return d->persistentSelection;
984 void QSGTextEdit::setPersistentSelection(bool on)
987 if (d->persistentSelection == on)
989 d->persistentSelection = on;
990 emit persistentSelectionChanged(d->persistentSelection);
994 \qmlproperty real QtQuick2::TextEdit::textMargin
996 The margin, in pixels, around the text in the TextEdit.
998 qreal QSGTextEdit::textMargin() const
1000 Q_D(const QSGTextEdit);
1001 return d->textMargin;
1004 void QSGTextEdit::setTextMargin(qreal margin)
1007 if (d->textMargin == margin)
1009 d->textMargin = margin;
1010 d->document->setDocumentMargin(d->textMargin);
1011 emit textMarginChanged(d->textMargin);
1014 void QSGTextEdit::geometryChanged(const QRectF &newGeometry,
1015 const QRectF &oldGeometry)
1017 if (newGeometry.width() != oldGeometry.width())
1019 QSGPaintedItem::geometryChanged(newGeometry, oldGeometry);
1023 Ensures any delayed caching or data loading the class
1024 needs to performed is complete.
1026 void QSGTextEdit::componentComplete()
1029 QSGPaintedItem::componentComplete();
1031 d->determineHorizontalAlignment();
1032 d->updateDefaultTextOption();
1038 \qmlproperty bool QtQuick2::TextEdit::selectByMouse
1042 If true, the user can use the mouse to select text in some
1043 platform-specific way. Note that for some platforms this may
1044 not be an appropriate interaction (eg. may conflict with how
1045 the text needs to behave inside a Flickable.
1047 bool QSGTextEdit::selectByMouse() const
1049 Q_D(const QSGTextEdit);
1050 return d->selectByMouse;
1053 void QSGTextEdit::setSelectByMouse(bool on)
1056 if (d->selectByMouse != on) {
1057 d->selectByMouse = on;
1058 setKeepMouseGrab(on);
1060 setTextInteractionFlags(d->control->textInteractionFlags() | Qt::TextSelectableByMouse);
1062 setTextInteractionFlags(d->control->textInteractionFlags() & ~Qt::TextSelectableByMouse);
1063 emit selectByMouseChanged(on);
1068 \qmlproperty enum QtQuick2::TextEdit::mouseSelectionMode
1070 Specifies how text should be selected using a mouse.
1073 \o TextEdit.SelectCharacters - The selection is updated with individual characters. (Default)
1074 \o TextEdit.SelectWords - The selection is updated with whole words.
1077 This property only applies when \l selectByMouse is true.
1079 QSGTextEdit::SelectionMode QSGTextEdit::mouseSelectionMode() const
1081 Q_D(const QSGTextEdit);
1082 return d->mouseSelectionMode;
1085 void QSGTextEdit::setMouseSelectionMode(SelectionMode mode)
1088 if (d->mouseSelectionMode != mode) {
1089 d->mouseSelectionMode = mode;
1090 d->control->setWordSelectionEnabled(mode == SelectWords);
1091 emit mouseSelectionModeChanged(mode);
1096 \qmlproperty bool QtQuick2::TextEdit::readOnly
1098 Whether the user can interact with the TextEdit item. If this
1099 property is set to true the text cannot be edited by user interaction.
1101 By default this property is false.
1103 void QSGTextEdit::setReadOnly(bool r)
1106 if (r == isReadOnly())
1109 setFlag(QSGItem::ItemAcceptsInputMethod, !r);
1110 Qt::TextInteractionFlags flags = Qt::LinksAccessibleByMouse;
1111 if (d->selectByMouse)
1112 flags = flags | Qt::TextSelectableByMouse;
1114 flags = flags | Qt::TextSelectableByKeyboard | Qt::TextEditable;
1115 d->control->setTextInteractionFlags(flags);
1117 d->control->moveCursor(QTextCursor::End);
1119 emit readOnlyChanged(r);
1122 bool QSGTextEdit::isReadOnly() const
1124 Q_D(const QSGTextEdit);
1125 return !(d->control->textInteractionFlags() & Qt::TextEditable);
1129 Sets how the text edit should interact with user input to the given
1132 void QSGTextEdit::setTextInteractionFlags(Qt::TextInteractionFlags flags)
1135 d->control->setTextInteractionFlags(flags);
1139 Returns the flags specifying how the text edit should interact
1142 Qt::TextInteractionFlags QSGTextEdit::textInteractionFlags() const
1144 Q_D(const QSGTextEdit);
1145 return d->control->textInteractionFlags();
1149 \qmlproperty rectangle QtQuick2::TextEdit::cursorRectangle
1151 The rectangle where the text cursor is rendered
1152 within the text edit. Read-only.
1154 QRect QSGTextEdit::cursorRectangle() const
1156 Q_D(const QSGTextEdit);
1157 return d->control->cursorRect().toRect().translated(0,d->yoff);
1160 bool QSGTextEdit::event(QEvent *event)
1163 if (event->type() == QEvent::ShortcutOverride) {
1164 d->control->processEvent(event, QPointF(0, -d->yoff));
1165 return event->isAccepted();
1167 return QSGPaintedItem::event(event);
1172 Handles the given key \a event.
1174 void QSGTextEdit::keyPressEvent(QKeyEvent *event)
1177 d->control->processEvent(event, QPointF(0, -d->yoff));
1178 if (!event->isAccepted())
1179 QSGPaintedItem::keyPressEvent(event);
1184 Handles the given key \a event.
1186 void QSGTextEdit::keyReleaseEvent(QKeyEvent *event)
1189 d->control->processEvent(event, QPointF(0, -d->yoff));
1190 if (!event->isAccepted())
1191 QSGPaintedItem::keyReleaseEvent(event);
1195 \qmlmethod void QtQuick2::TextEdit::deselect()
1197 Removes active text selection.
1199 void QSGTextEdit::deselect()
1202 QTextCursor c = d->control->textCursor();
1204 d->control->setTextCursor(c);
1208 \qmlmethod void QtQuick2::TextEdit::selectAll()
1210 Causes all text to be selected.
1212 void QSGTextEdit::selectAll()
1215 d->control->selectAll();
1219 \qmlmethod void QtQuick2::TextEdit::selectWord()
1221 Causes the word closest to the current cursor position to be selected.
1223 void QSGTextEdit::selectWord()
1226 QTextCursor c = d->control->textCursor();
1227 c.select(QTextCursor::WordUnderCursor);
1228 d->control->setTextCursor(c);
1232 \qmlmethod void QtQuick2::TextEdit::select(int start, int end)
1234 Causes the text from \a start to \a end to be selected.
1236 If either start or end is out of range, the selection is not changed.
1238 After calling this, selectionStart will become the lesser
1239 and selectionEnd will become the greater (regardless of the order passed
1242 \sa selectionStart, selectionEnd
1244 void QSGTextEdit::select(int start, int end)
1247 if (start < 0 || end < 0 || start > d->text.length() || end > d->text.length())
1249 QTextCursor cursor = d->control->textCursor();
1250 cursor.beginEditBlock();
1251 cursor.setPosition(start, QTextCursor::MoveAnchor);
1252 cursor.setPosition(end, QTextCursor::KeepAnchor);
1253 cursor.endEditBlock();
1254 d->control->setTextCursor(cursor);
1257 updateSelectionMarkers();
1261 \qmlmethod void QtQuick2::TextEdit::isRightToLeft(int start, int end)
1263 Returns true if the natural reading direction of the editor text
1264 found between positions \a start and \a end is right to left.
1266 bool QSGTextEdit::isRightToLeft(int start, int end)
1270 qmlInfo(this) << "isRightToLeft(start, end) called with the end property being smaller than the start.";
1273 return d->text.mid(start, end - start).isRightToLeft();
1277 #ifndef QT_NO_CLIPBOARD
1279 \qmlmethod QtQuick2::TextEdit::cut()
1281 Moves the currently selected text to the system clipboard.
1283 void QSGTextEdit::cut()
1290 \qmlmethod QtQuick2::TextEdit::copy()
1292 Copies the currently selected text to the system clipboard.
1294 void QSGTextEdit::copy()
1301 \qmlmethod QtQuick2::TextEdit::paste()
1303 Replaces the currently selected text by the contents of the system clipboard.
1305 void QSGTextEdit::paste()
1308 d->control->paste();
1310 #endif // QT_NO_CLIPBOARD
1314 Handles the given mouse \a event.
1316 void QSGTextEdit::mousePressEvent(QGraphicsSceneMouseEvent *event)
1319 if (d->focusOnPress){
1320 bool hadActiveFocus = hasActiveFocus();
1322 if (d->showInputPanelOnFocus) {
1323 if (hasActiveFocus() && hadActiveFocus && !isReadOnly()) {
1324 // re-open input panel on press if already focused
1325 openSoftwareInputPanel();
1327 } else { // show input panel on click
1328 if (hasActiveFocus() && !hadActiveFocus) {
1329 d->clickCausedFocus = true;
1333 d->control->processEvent(event, QPointF(0, -d->yoff));
1334 if (!event->isAccepted())
1335 QSGPaintedItem::mousePressEvent(event);
1340 Handles the given mouse \a event.
1342 void QSGTextEdit::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
1345 d->control->processEvent(event, QPointF(0, -d->yoff));
1346 if (!d->showInputPanelOnFocus) { // input panel on click
1347 if (d->focusOnPress && !isReadOnly() && boundingRect().contains(event->pos())) {
1348 if (canvas() && canvas() == qApp->focusWidget()) {
1349 qt_widget_private(canvas())->handleSoftwareInputPanel(event->button(), d->clickCausedFocus);
1353 d->clickCausedFocus = false;
1355 if (!event->isAccepted())
1356 QSGPaintedItem::mouseReleaseEvent(event);
1361 Handles the given mouse \a event.
1363 void QSGTextEdit::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
1366 d->control->processEvent(event, QPointF(0, -d->yoff));
1367 if (!event->isAccepted())
1368 QSGPaintedItem::mouseDoubleClickEvent(event);
1373 Handles the given mouse \a event.
1375 void QSGTextEdit::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
1378 d->control->processEvent(event, QPointF(0, -d->yoff));
1379 if (!event->isAccepted())
1380 QSGPaintedItem::mouseMoveEvent(event);
1385 Handles the given input method \a event.
1387 void QSGTextEdit::inputMethodEvent(QInputMethodEvent *event)
1390 const bool wasComposing = isInputMethodComposing();
1391 d->control->processEvent(event, QPointF(0, -d->yoff));
1392 if (wasComposing != isInputMethodComposing())
1393 emit inputMethodComposingChanged();
1396 void QSGTextEdit::itemChange(ItemChange change, const ItemChangeData &value)
1399 if (change == ItemActiveFocusHasChanged) {
1400 setCursorVisible(value.boolValue && d->canvas && d->canvas->hasFocus());
1402 QSGItem::itemChange(change, value);
1407 Returns the value of the given \a property.
1409 QVariant QSGTextEdit::inputMethodQuery(Qt::InputMethodQuery property) const
1411 Q_D(const QSGTextEdit);
1412 return d->control->inputMethodQuery(property);
1416 Draws the contents of the text edit using the given \a painter within
1417 the given \a bounds.
1419 void QSGTextEdit::paint(QPainter *painter)
1422 QRect bounds(0, 0, width(), height());
1425 painter->setRenderHint(QPainter::TextAntialiasing, true);
1426 painter->translate(0,d->yoff);
1428 d->control->drawContents(painter, bounds.translated(0,-d->yoff));
1430 painter->translate(0,-d->yoff);
1433 void QSGTextEdit::updateImgCache(const QRectF &rf)
1435 Q_D(const QSGTextEdit);
1437 if (!rf.isValid()) {
1438 r = QRect(0,0,INT_MAX,INT_MAX);
1441 if (r.height() > INT_MAX/2) {
1442 // Take care of overflow when translating "everything"
1443 r.setTop(r.y() + d->yoff);
1444 r.setBottom(INT_MAX/2);
1446 r = r.translated(0,d->yoff);
1453 \qmlproperty bool QtQuick2::TextEdit::smooth
1455 This property holds whether the text is smoothly scaled or transformed.
1457 Smooth filtering gives better visual quality, but is slower. If
1458 the item is displayed at its natural size, this property has no visual or
1461 \note Generally scaling artifacts are only visible if the item is stationary on
1462 the screen. A common pattern when animating an item is to disable smooth
1463 filtering at the beginning of the animation and reenable it at the conclusion.
1467 \qmlproperty bool QtQuick2::TextEdit::canPaste
1469 Returns true if the TextEdit is writable and the content of the clipboard is
1470 suitable for pasting into the TextEdit.
1472 bool QSGTextEdit::canPaste() const
1474 Q_D(const QSGTextEdit);
1479 \qmlproperty bool QtQuick2::TextEdit::inputMethodComposing
1482 This property holds whether the TextEdit has partial text input from an
1485 While it is composing an input method may rely on mouse or key events from
1486 the TextEdit to edit or commit the partial text. This property can be used
1487 to determine when to disable events handlers that may interfere with the
1488 correct operation of an input method.
1490 bool QSGTextEdit::isInputMethodComposing() const
1492 Q_D(const QSGTextEdit);
1493 if (QTextLayout *layout = d->control->textCursor().block().layout())
1494 return layout->preeditAreaText().length() > 0;
1498 void QSGTextEditPrivate::init()
1502 q->setSmooth(smooth);
1503 q->setAcceptedMouseButtons(Qt::LeftButton);
1504 q->setFlag(QSGItem::ItemAcceptsInputMethod);
1506 control = new QTextControl(q);
1507 control->setIgnoreUnusedNavigationEvents(true);
1508 control->setTextInteractionFlags(Qt::LinksAccessibleByMouse | Qt::TextSelectableByKeyboard | Qt::TextEditable);
1509 control->setDragEnabled(false);
1511 // QTextControl follows the default text color
1512 // defined by the platform, declarative text
1513 // should be black by default
1514 QPalette pal = control->palette();
1515 if (pal.color(QPalette::Text) != color) {
1516 pal.setColor(QPalette::Text, color);
1517 control->setPalette(pal);
1520 QObject::connect(control, SIGNAL(updateRequest(QRectF)), q, SLOT(updateImgCache(QRectF)));
1522 QObject::connect(control, SIGNAL(textChanged()), q, SLOT(q_textChanged()));
1523 QObject::connect(control, SIGNAL(selectionChanged()), q, SIGNAL(selectionChanged()));
1524 QObject::connect(control, SIGNAL(selectionChanged()), q, SLOT(updateSelectionMarkers()));
1525 QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SLOT(updateSelectionMarkers()));
1526 QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorPositionChanged()));
1527 QObject::connect(control, SIGNAL(microFocusChanged()), q, SLOT(moveCursorDelegate()));
1528 QObject::connect(control, SIGNAL(linkActivated(QString)), q, SIGNAL(linkActivated(QString)));
1529 #ifndef QT_NO_CLIPBOARD
1530 QObject::connect(q, SIGNAL(readOnlyChanged(bool)), q, SLOT(q_canPasteChanged()));
1531 QObject::connect(QApplication::clipboard(), SIGNAL(dataChanged()), q, SLOT(q_canPasteChanged()));
1532 canPaste = control->canPaste();
1535 document = control->document();
1536 document->setDefaultFont(font);
1537 document->setDocumentMargin(textMargin);
1538 document->setUndoRedoEnabled(false); // flush undo buffer.
1539 document->setUndoRedoEnabled(true);
1540 updateDefaultTextOption();
1543 void QSGTextEdit::q_textChanged()
1547 d->rightToLeftText = d->document->begin().layout()->engine()->isRightToLeft();
1548 d->determineHorizontalAlignment();
1549 d->updateDefaultTextOption();
1552 emit textChanged(d->text);
1555 void QSGTextEdit::moveCursorDelegate()
1559 emit cursorRectangleChanged();
1562 QRectF cursorRect = cursorRectangle();
1563 d->cursor->setX(cursorRect.x());
1564 d->cursor->setY(cursorRect.y());
1567 void QSGTextEditPrivate::updateSelection()
1570 QTextCursor cursor = control->textCursor();
1571 bool startChange = (lastSelectionStart != cursor.selectionStart());
1572 bool endChange = (lastSelectionEnd != cursor.selectionEnd());
1573 cursor.beginEditBlock();
1574 cursor.setPosition(lastSelectionStart, QTextCursor::MoveAnchor);
1575 cursor.setPosition(lastSelectionEnd, QTextCursor::KeepAnchor);
1576 cursor.endEditBlock();
1577 control->setTextCursor(cursor);
1579 q->selectionStartChanged();
1581 q->selectionEndChanged();
1584 void QSGTextEdit::updateSelectionMarkers()
1587 if(d->lastSelectionStart != d->control->textCursor().selectionStart()){
1588 d->lastSelectionStart = d->control->textCursor().selectionStart();
1589 emit selectionStartChanged();
1591 if(d->lastSelectionEnd != d->control->textCursor().selectionEnd()){
1592 d->lastSelectionEnd = d->control->textCursor().selectionEnd();
1593 emit selectionEndChanged();
1597 QRectF QSGTextEdit::boundingRect() const
1599 Q_D(const QSGTextEdit);
1600 QRectF r = QSGPaintedItem::boundingRect();
1601 int cursorWidth = 1;
1603 cursorWidth = d->cursor->width();
1604 if(!d->document->isEmpty())
1605 cursorWidth += 3;// ### Need a better way of accounting for space between char and cursor
1607 // Could include font max left/right bearings to either side of rectangle.
1609 r.setRight(r.right() + cursorWidth);
1610 return r.translated(0,d->yoff);
1613 qreal QSGTextEditPrivate::getImplicitWidth() const
1615 Q_Q(const QSGTextEdit);
1616 if (!requireImplicitWidth) {
1617 // We don't calculate implicitWidth unless it is required.
1618 // We need to force a size update now to ensure implicitWidth is calculated
1619 const_cast<QSGTextEditPrivate*>(this)->requireImplicitWidth = true;
1620 const_cast<QSGTextEdit*>(q)->updateSize();
1622 return implicitWidth;
1625 //### we should perhaps be a bit smarter here -- depending on what has changed, we shouldn't
1626 // need to do all the calculations each time
1627 void QSGTextEdit::updateSize()
1630 if (isComponentComplete()) {
1631 qreal naturalWidth = d->implicitWidth;
1632 // ### assumes that if the width is set, the text will fill to edges
1633 // ### (unless wrap is false, then clipping will occur)
1635 if (!d->requireImplicitWidth) {
1636 emit implicitWidthChanged();
1637 // if the implicitWidth is used, then updateSize() has already been called (recursively)
1638 if (d->requireImplicitWidth)
1641 if (d->requireImplicitWidth) {
1642 d->document->setTextWidth(-1);
1643 naturalWidth = d->document->idealWidth();
1645 if (d->document->textWidth() != width())
1646 d->document->setTextWidth(width());
1648 d->document->setTextWidth(-1);
1650 QFontMetrics fm = QFontMetrics(d->font);
1652 dy -= (int)d->document->size().height();
1655 if (heightValid()) {
1656 if (d->vAlign == AlignBottom)
1658 else if (d->vAlign == AlignVCenter)
1665 if (nyoff != d->yoff)
1667 setBaselineOffset(fm.ascent() + d->yoff + d->textMargin);
1669 //### need to comfirm cost of always setting these
1670 int newWidth = qCeil(d->document->idealWidth());
1671 if (!widthValid() && d->document->textWidth() != newWidth)
1672 d->document->setTextWidth(newWidth); // ### Text does not align if width is not set (QTextDoc bug)
1673 // ### Setting the implicitWidth triggers another updateSize(), and unless there are bindings nothing has changed.
1675 setImplicitWidth(newWidth);
1676 else if (d->requireImplicitWidth)
1677 setImplicitWidth(naturalWidth);
1678 qreal newHeight = d->document->isEmpty() ? fm.height() : (int)d->document->size().height();
1679 setImplicitHeight(newHeight);
1681 d->paintedSize = QSize(newWidth, newHeight);
1682 setContentsSize(d->paintedSize);
1683 emit paintedSizeChanged();
1690 void QSGTextEdit::updateTotalLines()
1696 for (QTextBlock it = d->document->begin(); it != d->document->end(); it = it.next()) {
1697 QTextLayout *layout = it.layout();
1700 subLines += layout->lineCount()-1;
1703 int newTotalLines = d->document->lineCount() + subLines;
1704 if (d->lineCount != newTotalLines) {
1705 d->lineCount = newTotalLines;
1706 emit lineCountChanged();
1710 void QSGTextEditPrivate::updateDefaultTextOption()
1713 QTextOption opt = document->defaultTextOption();
1714 int oldAlignment = opt.alignment();
1716 QSGTextEdit::HAlignment horizontalAlignment = q->effectiveHAlign();
1717 if (rightToLeftText) {
1718 if (horizontalAlignment == QSGTextEdit::AlignLeft)
1719 horizontalAlignment = QSGTextEdit::AlignRight;
1720 else if (horizontalAlignment == QSGTextEdit::AlignRight)
1721 horizontalAlignment = QSGTextEdit::AlignLeft;
1723 opt.setAlignment((Qt::Alignment)(int)(horizontalAlignment | vAlign));
1725 QTextOption::WrapMode oldWrapMode = opt.wrapMode();
1726 opt.setWrapMode(QTextOption::WrapMode(wrapMode));
1728 if (oldWrapMode == opt.wrapMode() && oldAlignment == opt.alignment())
1730 document->setDefaultTextOption(opt);
1736 \qmlmethod void QtQuick2::TextEdit::openSoftwareInputPanel()
1738 Opens software input panels like virtual keyboards for typing, useful for
1739 customizing when you want the input keyboard to be shown and hidden in
1742 By default the opening of input panels follows the platform style. On Symbian^1 and
1743 Symbian^3 -based devices the panels are opened by clicking TextEdit. On other platforms
1744 the panels are automatically opened when TextEdit element gains active focus. Input panels are
1745 always closed if no editor has active focus.
1747 You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1748 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1749 the behavior you want.
1751 Only relevant on platforms, which provide virtual keyboards.
1757 text: "Hello world!"
1758 activeFocusOnPress: false
1760 anchors.fill: parent
1762 if (!textEdit.activeFocus) {
1763 textEdit.forceActiveFocus();
1764 textEdit.openSoftwareInputPanel();
1766 textEdit.focus = false;
1769 onPressAndHold: textEdit.closeSoftwareInputPanel();
1774 void QSGTextEdit::openSoftwareInputPanel()
1777 if (canvas() && canvas() == qApp->focusWidget()) {
1778 QEvent event(QEvent::RequestSoftwareInputPanel);
1779 QApplication::sendEvent(canvas(), &event);
1785 \qmlmethod void QtQuick2::TextEdit::closeSoftwareInputPanel()
1787 Closes a software input panel like a virtual keyboard shown on the screen, useful
1788 for customizing when you want the input keyboard to be shown and hidden in
1791 By default the opening of input panels follows the platform style. On Symbian^1 and
1792 Symbian^3 -based devices the panels are opened by clicking TextEdit. On other platforms
1793 the panels are automatically opened when TextEdit element gains active focus. Input panels are
1794 always closed if no editor has active focus.
1796 You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1797 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1798 the behavior you want.
1800 Only relevant on platforms, which provide virtual keyboards.
1806 text: "Hello world!"
1807 activeFocusOnPress: false
1809 anchors.fill: parent
1811 if (!textEdit.activeFocus) {
1812 textEdit.forceActiveFocus();
1813 textEdit.openSoftwareInputPanel();
1815 textEdit.focus = false;
1818 onPressAndHold: textEdit.closeSoftwareInputPanel();
1823 void QSGTextEdit::closeSoftwareInputPanel()
1826 if (canvas() && canvas() == qApp->focusWidget()) {
1827 QEvent event(QEvent::CloseSoftwareInputPanel);
1828 QApplication::sendEvent(canvas(), &event);
1833 void QSGTextEdit::focusInEvent(QFocusEvent *event)
1835 Q_D(const QSGTextEdit);
1836 if (d->showInputPanelOnFocus) {
1837 if (d->focusOnPress && !isReadOnly()) {
1838 openSoftwareInputPanel();
1841 QSGPaintedItem::focusInEvent(event);
1844 void QSGTextEdit::q_canPasteChanged()
1847 bool old = d->canPaste;
1848 d->canPaste = d->control->canPaste();
1849 if(old!=d->canPaste)
1850 emit canPasteChanged();