src/declarative/graphicsitems/qdeclarativetextedit.cpp
changeset 33 3e2da88830cd
parent 30 5dc02b23752f
child 37 758a864f9613
equal deleted inserted replaced
30:5dc02b23752f 33:3e2da88830cd
    59 
    59 
    60 QT_BEGIN_NAMESPACE
    60 QT_BEGIN_NAMESPACE
    61 
    61 
    62 /*!
    62 /*!
    63     \qmlclass TextEdit QDeclarativeTextEdit
    63     \qmlclass TextEdit QDeclarativeTextEdit
    64   \since 4.7
    64     \since 4.7
    65     \brief The TextEdit item allows you to add editable formatted text to a scene.
    65     \brief The TextEdit item displays multiple lines of editable formatted text.
       
    66     \inherits Item
       
    67 
       
    68     The TextEdit item displays a block of editable, formatted text.
    66 
    69 
    67     It can display both plain and rich text. For example:
    70     It can display both plain and rich text. For example:
    68 
    71 
    69     \qml
    72     \qml
    70 TextEdit {
    73 TextEdit {
    71     id: edit
    74     width: 240
    72     text: "<b>Hello</b> <i>World!</i>"
    75     text: "<b>Hello</b> <i>World!</i>"
    73     focus: true
       
    74     font.family: "Helvetica"
    76     font.family: "Helvetica"
    75     font.pointSize: 20
    77     font.pointSize: 20
    76     color: "blue"
    78     color: "blue"
    77     width: 240
    79     focus: true
    78 }
    80 }
    79     \endqml
    81     \endqml
    80 
    82 
    81     \image declarative-textedit.gif
    83     \image declarative-textedit.gif
    82 
    84 
    83     \sa Text
    85     Setting \l {Item::focus}{focus} to \c true enables the TextEdit item to receive keyboard focus.
       
    86 
       
    87     Note that the TextEdit does not implement scrolling, following the cursor, or other behaviors specific
       
    88     to a look-and-feel. For example, to add flickable scrolling that follows the cursor:
       
    89 
       
    90     \snippet snippets/declarative/texteditor.qml 0
       
    91 
       
    92     A particular look-and-feel might use smooth scrolling (eg. using SmoothedFollow), might have a visible
       
    93     scrollbar, or a scrollbar that fades in to show location, etc.
       
    94 
       
    95     Clipboard support is provided by the cut(), copy(), and paste() functions, and the selection can
       
    96     be handled in a traditional "mouse" mechanism by setting selectByMouse, or handled completely
       
    97     from QML by manipulating selectionStart and selectionEnd, or using selectAll() or selectWord().
       
    98 
       
    99     You can translate between cursor positions (characters from the start of the document) and pixel
       
   100     points using positionAt() and positionToRectangle().
       
   101 
       
   102     \sa Text, TextInput, {declarative/text/textselection}{Text Selection example}
    84 */
   103 */
    85 
   104 
    86 /*!
   105 /*!
    87     \internal
   106     \internal
    88     \class QDeclarativeTextEdit
   107     \class QDeclarativeTextEdit
    92 
   111 
    93     It can display both plain and rich text.
   112     It can display both plain and rich text.
    94 
   113 
    95     \image declarative-textedit.png
   114     \image declarative-textedit.png
    96 
   115 
    97     A QDeclarativeTextEdit object can be instantiated in Qml using the tag \c &lt;TextEdit&gt;.
   116     A QDeclarativeTextEdit object can be instantiated in QML using the tag \c &lt;TextEdit&gt;.
    98 */
   117 */
    99 
   118 
   100 /*!
   119 /*!
   101     Constructs a new QDeclarativeTextEdit.
   120     Constructs a new QDeclarativeTextEdit.
   102 */
   121 */
   109 
   128 
   110 QString QDeclarativeTextEdit::text() const
   129 QString QDeclarativeTextEdit::text() const
   111 {
   130 {
   112     Q_D(const QDeclarativeTextEdit);
   131     Q_D(const QDeclarativeTextEdit);
   113 
   132 
       
   133 #ifndef QT_NO_TEXTHTMLPARSER
   114     if (d->richText)
   134     if (d->richText)
   115         return d->document->toHtml();
   135         return d->document->toHtml();
   116     else
   136     else
       
   137 #endif
   117         return d->document->toPlainText();
   138         return d->document->toPlainText();
   118 }
   139 }
   119 
   140 
   120 /*!
   141 /*!
   121     \qmlproperty string TextEdit::font.family
   142     \qmlproperty string TextEdit::font.family
   163 
   184 
   164     Sets whether the text is underlined.
   185     Sets whether the text is underlined.
   165 */
   186 */
   166 
   187 
   167 /*!
   188 /*!
   168     \qmlproperty bool TextEdit::font.outline
       
   169 
       
   170     Sets whether the font has an outline style.
       
   171 */
       
   172 
       
   173 /*!
       
   174     \qmlproperty bool TextEdit::font.strikeout
   189     \qmlproperty bool TextEdit::font.strikeout
   175 
   190 
   176     Sets whether the font has a strikeout style.
   191     Sets whether the font has a strikeout style.
   177 */
   192 */
   178 
   193 
   185 /*!
   200 /*!
   186     \qmlproperty int TextEdit::font.pixelSize
   201     \qmlproperty int TextEdit::font.pixelSize
   187 
   202 
   188     Sets the font size in pixels.
   203     Sets the font size in pixels.
   189 
   204 
   190     Using this function makes the font device dependent.
   205     Using this function makes the font device dependent.  Use
   191     Use \c pointSize to set the size of the font in a device independent manner.
   206     \l{TextEdit::font.pointSize} to set the size of the font in a
       
   207     device independent manner.
   192 */
   208 */
   193 
   209 
   194 /*!
   210 /*!
   195     \qmlproperty real TextEdit::font.letterSpacing
   211     \qmlproperty real TextEdit::font.letterSpacing
   196 
   212 
   197     Sets the letter spacing for the font.
   213     Sets the letter spacing for the font.
   198 
   214 
   199     Letter spacing changes the default spacing between individual letters in the font.
   215     Letter spacing changes the default spacing between individual letters in the font.
   200     A value of 100 will keep the spacing unchanged; a value of 200 will enlarge the spacing after a character by
   216     A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing.
   201     the width of the character itself.
       
   202 */
   217 */
   203 
   218 
   204 /*!
   219 /*!
   205     \qmlproperty real TextEdit::font.wordSpacing
   220     \qmlproperty real TextEdit::font.wordSpacing
   206 
   221 
   239 void QDeclarativeTextEdit::setText(const QString &text)
   254 void QDeclarativeTextEdit::setText(const QString &text)
   240 {
   255 {
   241     Q_D(QDeclarativeTextEdit);
   256     Q_D(QDeclarativeTextEdit);
   242     if (QDeclarativeTextEdit::text() == text)
   257     if (QDeclarativeTextEdit::text() == text)
   243         return;
   258         return;
   244     d->text = text;
       
   245     d->richText = d->format == RichText || (d->format == AutoText && Qt::mightBeRichText(text));
   259     d->richText = d->format == RichText || (d->format == AutoText && Qt::mightBeRichText(text));
   246     if (d->richText) {
   260     if (d->richText) {
       
   261 #ifndef QT_NO_TEXTHTMLPARSER
   247         d->control->setHtml(text);
   262         d->control->setHtml(text);
       
   263 #else
       
   264         d->control->setPlainText(text);
       
   265 #endif
   248     } else {
   266     } else {
   249         d->control->setPlainText(text);
   267         d->control->setPlainText(text);
   250     }
   268     }
   251     q_textChanged();
   269     q_textChanged();
   252 }
   270 }
   307 
   325 
   308     if (wasRich && !d->richText) {
   326     if (wasRich && !d->richText) {
   309         d->control->setPlainText(d->text);
   327         d->control->setPlainText(d->text);
   310         updateSize();
   328         updateSize();
   311     } else if (!wasRich && d->richText) {
   329     } else if (!wasRich && d->richText) {
       
   330 #ifndef QT_NO_TEXTHTMLPARSER
   312         d->control->setHtml(d->text);
   331         d->control->setHtml(d->text);
       
   332 #else
       
   333         d->control->setPlainText(d->text);
       
   334 #endif
   313         updateSize();
   335         updateSize();
   314     }
   336     }
   315     d->format = format;
   337     d->format = format;
   316     emit textFormatChanged(d->format);
   338     emit textFormatChanged(d->format);
   317 }
   339 }
   425 
   447 
   426 /*!
   448 /*!
   427     \qmlproperty enumeration TextEdit::horizontalAlignment
   449     \qmlproperty enumeration TextEdit::horizontalAlignment
   428     \qmlproperty enumeration TextEdit::verticalAlignment
   450     \qmlproperty enumeration TextEdit::verticalAlignment
   429 
   451 
   430     Sets the horizontal and vertical alignment of the text within the TextEdit items
   452     Sets the horizontal and vertical alignment of the text within the TextEdit item's
   431     width and height.  By default, the text is top-left aligned.
   453     width and height.  By default, the text is top-left aligned.
   432 
   454 
   433     The valid values for \c horizontalAlignment are \c TextEdit.AlignLeft, \c TextEdit.AlignRight and
   455     Valid values for \c horizontalAlignment are:
   434     \c TextEdit.AlignHCenter.  The valid values for \c verticalAlignment are \c TextEdit.AlignTop, \c TextEdit.AlignBottom
   456     \list
   435     and \c TextEdit.AlignVCenter.
   457     \o TextEdit.AlignLeft (default)
       
   458     \o TextEdit.AlignRight 
       
   459     \o TextEdit.AlignHCenter
       
   460     \endlist
       
   461     
       
   462     Valid values for \c verticalAlignment are:
       
   463     \list
       
   464     \o TextEdit.AlignTop (default)
       
   465     \o TextEdit.AlignBottom
       
   466     \c TextEdit.AlignVCenter
       
   467     \endlist
   436 */
   468 */
   437 QDeclarativeTextEdit::HAlignment QDeclarativeTextEdit::hAlign() const
   469 QDeclarativeTextEdit::HAlignment QDeclarativeTextEdit::hAlign() const
   438 {
   470 {
   439     Q_D(const QDeclarativeTextEdit);
   471     Q_D(const QDeclarativeTextEdit);
   440     return d->hAlign;
   472     return d->hAlign;
   473 
   505 
   474     Set this property to wrap the text to the TextEdit item's width.
   506     Set this property to wrap the text to the TextEdit item's width.
   475     The text will only wrap if an explicit width has been set.
   507     The text will only wrap if an explicit width has been set.
   476 
   508 
   477     \list
   509     \list
   478     \o TextEdit.NoWrap - no wrapping will be performed.
   510     \o TextEdit.NoWrap - no wrapping will be performed. If the text contains insufficient newlines, then implicitWidth will exceed a set width.
   479     \o TextEdit.WordWrap - wrapping is done on word boundaries.
   511     \o TextEdit.WordWrap - wrapping is done on word boundaries only. If a word is too long, implicitWidth will exceed a set width.
   480     \o TextEdit.WrapAnywhere - Text can be wrapped at any point on a line, even if it occurs in the middle of a word.
   512     \o TextEdit.WrapAnywhere - wrapping is done at any point on a line, even if it occurs in the middle of a word.
   481     \o TextEdit.WrapAtWordBoundaryOrAnywhere - If possible, wrapping occurs at a word boundary; otherwise it
   513     \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.
   482        will occur at the appropriate point on the line, even in the middle of a word.
       
   483     \endlist
   514     \endlist
   484 
   515 
   485     The default is TextEdit.NoWrap.
   516     The default is TextEdit.NoWrap. If you set a width, consider using TextEdit.Wrap.
   486 */
   517 */
   487 QDeclarativeTextEdit::WrapMode QDeclarativeTextEdit::wrapMode() const
   518 QDeclarativeTextEdit::WrapMode QDeclarativeTextEdit::wrapMode() const
   488 {
   519 {
   489     Q_D(const QDeclarativeTextEdit);
   520     Q_D(const QDeclarativeTextEdit);
   490     return d->wrapMode;
   521     return d->wrapMode;
   500     updateSize();
   531     updateSize();
   501     emit wrapModeChanged();
   532     emit wrapModeChanged();
   502 }
   533 }
   503 
   534 
   504 /*!
   535 /*!
       
   536     \qmlproperty real TextEdit::paintedWidth
       
   537 
       
   538     Returns the width of the text, including the width past the width
       
   539     which is covered due to insufficient wrapping if \l wrapMode is set.
       
   540 */
       
   541 qreal QDeclarativeTextEdit::paintedWidth() const
       
   542 {
       
   543     return implicitWidth();
       
   544 }
       
   545 
       
   546 /*!
       
   547     \qmlproperty real TextEdit::paintedHeight
       
   548 
       
   549     Returns the height of the text, including the height past the height
       
   550     that is covered if the text does not fit within the set height.
       
   551 */
       
   552 qreal QDeclarativeTextEdit::paintedHeight() const
       
   553 {
       
   554     return implicitHeight();
       
   555 }
       
   556 
       
   557 /*!
       
   558     \qmlmethod rectangle TextEdit::positionToRectangle(position)
       
   559 
       
   560     Returns the rectangle at the given \a position in the text. The x, y,
       
   561     and height properties correspond to the cursor that would describe
       
   562     that position.
       
   563 */
       
   564 QRectF QDeclarativeTextEdit::positionToRectangle(int pos) const
       
   565 {
       
   566     Q_D(const QDeclarativeTextEdit);
       
   567     QTextCursor c(d->document);
       
   568     c.setPosition(pos);
       
   569     return d->control->cursorRect(c);
       
   570 
       
   571 }
       
   572 
       
   573 /*!
       
   574     \qmlmethod int TextEdit::positionAt(x,y)
       
   575 
       
   576     Returns the text position closest to pixel position (\a x, \a y).
       
   577 
       
   578     Position 0 is before the first character, position 1 is after the first character
       
   579     but before the second, and so on until position \l {text}.length, which is after all characters.
       
   580 */
       
   581 int QDeclarativeTextEdit::positionAt(int x, int y) const
       
   582 {
       
   583     Q_D(const QDeclarativeTextEdit);
       
   584     int r = d->document->documentLayout()->hitTest(QPoint(x,y-d->yoff), Qt::FuzzyHit);
       
   585     return r;
       
   586 }
       
   587 
       
   588 /*!
       
   589     \qmlmethod int TextEdit::moveCursorSelection(int pos)
       
   590 
       
   591     Moves the cursor to \a position and updates the selection accordingly.
       
   592     (To only move the cursor, set the \l cursorPosition property.)
       
   593 
       
   594     When this method is called it additionally sets either the
       
   595     selectionStart or the selectionEnd (whichever was at the previous cursor position)
       
   596     to the specified position. This allows you to easily extend and contract the selected
       
   597     text range.
       
   598 
       
   599     For example, take this sequence of calls:
       
   600 
       
   601     \code
       
   602         cursorPosition = 5
       
   603         moveCursorSelection(9)
       
   604         moveCursorSelection(7)
       
   605     \endcode
       
   606 
       
   607     This moves the cursor to position 5, extend the selection end from 5 to 9
       
   608     and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
       
   609     selected (the 6th and 7th characters).
       
   610 */
       
   611 void QDeclarativeTextEdit::moveCursorSelection(int pos)
       
   612 {
       
   613     //Note that this is the same as setCursorPosition but with the KeepAnchor flag set
       
   614     Q_D(QDeclarativeTextEdit);
       
   615     QTextCursor cursor = d->control->textCursor();
       
   616     if (cursor.position() == pos)
       
   617         return;
       
   618     cursor.setPosition(pos, QTextCursor::KeepAnchor);
       
   619     d->control->setTextCursor(cursor);
       
   620 }
       
   621 
       
   622 /*!
   505     \qmlproperty bool TextEdit::cursorVisible
   623     \qmlproperty bool TextEdit::cursorVisible
   506     If true the text edit shows a cursor.
   624     If true the text edit shows a cursor.
   507 
   625 
   508     This property is set and unset when the text edit gets focus, but it can also
   626     This property is set and unset when the text edit gets active focus, but it can also
   509     be set directly (useful, for example, if a KeyProxy might forward keys to it).
   627     be set directly (useful, for example, if a KeyProxy might forward keys to it).
   510 */
   628 */
   511 bool QDeclarativeTextEdit::isCursorVisible() const
   629 bool QDeclarativeTextEdit::isCursorVisible() const
   512 {
   630 {
   513     Q_D(const QDeclarativeTextEdit);
   631     Q_D(const QDeclarativeTextEdit);
   572     if(d->cursorComponent){
   690     if(d->cursorComponent){
   573         if(d->cursor){
   691         if(d->cursor){
   574             disconnect(d->control, SIGNAL(cursorPositionChanged()),
   692             disconnect(d->control, SIGNAL(cursorPositionChanged()),
   575                     this, SLOT(moveCursorDelegate()));
   693                     this, SLOT(moveCursorDelegate()));
   576             d->control->setCursorWidth(-1);
   694             d->control->setCursorWidth(-1);
   577             dirtyCache(cursorRect());
   695             dirtyCache(cursorRectangle());
   578             delete d->cursor;
   696             delete d->cursor;
   579             d->cursor = 0;
   697             d->cursor = 0;
   580         }
   698         }
   581     }
   699     }
   582     d->cursorComponent = c;
   700     d->cursorComponent = c;
   599     d->cursor = qobject_cast<QDeclarativeItem*>(d->cursorComponent->create(qmlContext(this)));
   717     d->cursor = qobject_cast<QDeclarativeItem*>(d->cursorComponent->create(qmlContext(this)));
   600     if(d->cursor){
   718     if(d->cursor){
   601         connect(d->control, SIGNAL(cursorPositionChanged()),
   719         connect(d->control, SIGNAL(cursorPositionChanged()),
   602                 this, SLOT(moveCursorDelegate()));
   720                 this, SLOT(moveCursorDelegate()));
   603         d->control->setCursorWidth(0);
   721         d->control->setCursorWidth(0);
   604         dirtyCache(cursorRect());
   722         dirtyCache(cursorRectangle());
   605         QDeclarative_setParent_noEvent(d->cursor, this);
   723         QDeclarative_setParent_noEvent(d->cursor, this);
   606         d->cursor->setParentItem(this);
   724         d->cursor->setParentItem(this);
   607         d->cursor->setHeight(QFontMetrics(d->font).height());
   725         d->cursor->setHeight(QFontMetrics(d->font).height());
   608         moveCursorDelegate();
   726         moveCursorDelegate();
   609     }else{
   727     }else{
   613 
   731 
   614 /*!
   732 /*!
   615     \qmlproperty int TextEdit::selectionStart
   733     \qmlproperty int TextEdit::selectionStart
   616 
   734 
   617     The cursor position before the first character in the current selection.
   735     The cursor position before the first character in the current selection.
   618     Setting this and selectionEnd allows you to specify a selection in the
   736 
   619     text edit.
   737     This property is read-only. To change the selection, use select(start,end),
   620 
   738     selectAll(), or selectWord().
   621     Note that if selectionStart == selectionEnd then there is no current
       
   622     selection. If you attempt to set selectionStart to a value outside of
       
   623     the current text, selectionStart will not be changed.
       
   624 
   739 
   625     \sa selectionEnd, cursorPosition, selectedText
   740     \sa selectionEnd, cursorPosition, selectedText
   626 */
   741 */
   627 int QDeclarativeTextEdit::selectionStart() const
   742 int QDeclarativeTextEdit::selectionStart() const
   628 {
   743 {
   629     Q_D(const QDeclarativeTextEdit);
   744     Q_D(const QDeclarativeTextEdit);
   630     return d->control->textCursor().selectionStart();
   745     return d->control->textCursor().selectionStart();
   631 }
   746 }
   632 
   747 
   633 void QDeclarativeTextEdit::setSelectionStart(int s)
       
   634 {
       
   635     Q_D(QDeclarativeTextEdit);
       
   636     if(d->lastSelectionStart == s || s < 0 || s > text().length())
       
   637         return;
       
   638     d->lastSelectionStart = s;
       
   639     d->updateSelection();// Will emit the relevant signals
       
   640 }
       
   641 
       
   642 /*!
   748 /*!
   643     \qmlproperty int TextEdit::selectionEnd
   749     \qmlproperty int TextEdit::selectionEnd
   644 
   750 
   645     The cursor position after the last character in the current selection.
   751     The cursor position after the last character in the current selection.
   646     Setting this and selectionStart allows you to specify a selection in the
   752 
   647     text edit.
   753     This property is read-only. To change the selection, use select(start,end),
   648 
   754     selectAll(), or selectWord().
   649     Note that if selectionStart == selectionEnd then there is no current
       
   650     selection. If you attempt to set selectionEnd to a value outside of
       
   651     the current text, selectionEnd will not be changed.
       
   652 
   755 
   653     \sa selectionStart, cursorPosition, selectedText
   756     \sa selectionStart, cursorPosition, selectedText
   654 */
   757 */
   655 int QDeclarativeTextEdit::selectionEnd() const
   758 int QDeclarativeTextEdit::selectionEnd() const
   656 {
   759 {
   657     Q_D(const QDeclarativeTextEdit);
   760     Q_D(const QDeclarativeTextEdit);
   658     return d->control->textCursor().selectionEnd();
   761     return d->control->textCursor().selectionEnd();
   659 }
       
   660 
       
   661 void QDeclarativeTextEdit::setSelectionEnd(int s)
       
   662 {
       
   663     Q_D(QDeclarativeTextEdit);
       
   664     if(d->lastSelectionEnd == s || s < 0 || s > text().length())
       
   665         return;
       
   666     d->lastSelectionEnd = s;
       
   667     d->updateSelection();// Will emit the relevant signals
       
   668 }
   762 }
   669 
   763 
   670 /*!
   764 /*!
   671     \qmlproperty string TextEdit::selectedText
   765     \qmlproperty string TextEdit::selectedText
   672 
   766 
   686     Q_D(const QDeclarativeTextEdit);
   780     Q_D(const QDeclarativeTextEdit);
   687     return d->control->textCursor().selectedText();
   781     return d->control->textCursor().selectedText();
   688 }
   782 }
   689 
   783 
   690 /*!
   784 /*!
   691     \qmlproperty bool TextEdit::focusOnPress
   785     \qmlproperty bool TextEdit::activeFocusOnPress
   692 
   786 
   693     Whether the TextEdit should gain focus on a mouse press. By default this is
   787     Whether the TextEdit should gain active focus on a mouse press. By default this is
   694     set to true.
   788     set to true.
   695 */
   789 */
   696 bool QDeclarativeTextEdit::focusOnPress() const
   790 bool QDeclarativeTextEdit::focusOnPress() const
   697 {
   791 {
   698     Q_D(const QDeclarativeTextEdit);
   792     Q_D(const QDeclarativeTextEdit);
   703 {
   797 {
   704     Q_D(QDeclarativeTextEdit);
   798     Q_D(QDeclarativeTextEdit);
   705     if (d->focusOnPress == on)
   799     if (d->focusOnPress == on)
   706         return;
   800         return;
   707     d->focusOnPress = on;
   801     d->focusOnPress = on;
   708     emit focusOnPressChanged(d->focusOnPress);
   802     emit activeFocusOnPressChanged(d->focusOnPress);
   709 }
   803 }
   710 
   804 
   711 /*!
   805 /*!
   712     \qmlproperty bool TextEdit::persistentSelection
   806     \qmlproperty bool TextEdit::persistentSelection
   713 
   807 
   714     Whether the TextEdit should keep the selection visible when it loses focus to another
   808     Whether the TextEdit should keep the selection visible when it loses active focus to another
   715     item in the scene. By default this is set to true;
   809     item in the scene. By default this is set to true;
   716 */
   810 */
   717 bool QDeclarativeTextEdit::persistentSelection() const
   811 bool QDeclarativeTextEdit::persistentSelection() const
   718 {
   812 {
   719     Q_D(const QDeclarativeTextEdit);
   813     Q_D(const QDeclarativeTextEdit);
   771         d->dirty = false;
   865         d->dirty = false;
   772     }
   866     }
   773 }
   867 }
   774 
   868 
   775 /*!
   869 /*!
   776     \qmlproperty string TextEdit::selectByMouse
   870     \qmlproperty bool TextEdit::selectByMouse
   777 
   871 
   778     Defaults to false.
   872     Defaults to false.
   779 
   873 
   780     If true, the user can use the mouse to select text in some
   874     If true, the user can use the mouse to select text in some
   781     platform-specific way. Note that for some platforms this may
   875     platform-specific way. Note that for some platforms this may
   852     Q_D(const QDeclarativeTextEdit);
   946     Q_D(const QDeclarativeTextEdit);
   853     return d->control->textInteractionFlags();
   947     return d->control->textInteractionFlags();
   854 }
   948 }
   855 
   949 
   856 /*!
   950 /*!
   857     Returns the rectangle where the text cursor is rendered
   951     \qmlproperty rectangle TextEdit::cursorRectangle
   858     within the text edit.
   952 
   859 */
   953     The rectangle where the text cursor is rendered
   860 QRect QDeclarativeTextEdit::cursorRect() const
   954     within the text edit. Read-only.
       
   955 */
       
   956 QRect QDeclarativeTextEdit::cursorRectangle() const
   861 {
   957 {
   862     Q_D(const QDeclarativeTextEdit);
   958     Q_D(const QDeclarativeTextEdit);
   863     return d->control->cursorRect().toRect().translated(0,-d->yoff);
   959     return d->control->cursorRect().toRect().translated(0,-d->yoff);
   864 }
   960 }
   865 
   961 
   912     q->setCursorVisible(hasFocus);
  1008     q->setCursorVisible(hasFocus);
   913     QDeclarativeItemPrivate::focusChanged(hasFocus);
  1009     QDeclarativeItemPrivate::focusChanged(hasFocus);
   914 }
  1010 }
   915 
  1011 
   916 /*!
  1012 /*!
       
  1013     \qmlmethod void TextEdit::selectAll()
       
  1014 
   917     Causes all text to be selected.
  1015     Causes all text to be selected.
   918 */
  1016 */
   919 void QDeclarativeTextEdit::selectAll()
  1017 void QDeclarativeTextEdit::selectAll()
   920 {
  1018 {
   921     Q_D(QDeclarativeTextEdit);
  1019     Q_D(QDeclarativeTextEdit);
   922     d->control->selectAll();
  1020     d->control->selectAll();
   923 }
  1021 }
       
  1022 
       
  1023 /*!
       
  1024     \qmlmethod void TextEdit::selectWord()
       
  1025 
       
  1026     Causes the word closest to the current cursor position to be selected.
       
  1027 */
       
  1028 void QDeclarativeTextEdit::selectWord()
       
  1029 {
       
  1030     Q_D(QDeclarativeTextEdit);
       
  1031     QTextCursor c = d->control->textCursor();
       
  1032     c.select(QTextCursor::WordUnderCursor);
       
  1033     d->control->setTextCursor(c);
       
  1034 }
       
  1035 
       
  1036 /*!
       
  1037     \qmlmethod void TextEdit::select(start,end)
       
  1038 
       
  1039     Causes the text from \a start to \a end to be selected.
       
  1040 
       
  1041     If either start or end is out of range, the selection is not changed.
       
  1042 
       
  1043     After calling this, selectionStart will become the lesser
       
  1044     and selectionEnd will become the greater (regardless of the order passed
       
  1045     to this method).
       
  1046 
       
  1047     \sa selectionStart, selectionEnd
       
  1048 */
       
  1049 void QDeclarativeTextEdit::select(int start, int end)
       
  1050 {
       
  1051     Q_D(QDeclarativeTextEdit);
       
  1052     if (start < 0 || end < 0 || start > d->text.length() || end > d->text.length())
       
  1053         return;
       
  1054     QTextCursor cursor = d->control->textCursor();
       
  1055     cursor.beginEditBlock();
       
  1056     cursor.setPosition(start, QTextCursor::MoveAnchor);
       
  1057     cursor.setPosition(end, QTextCursor::KeepAnchor);
       
  1058     cursor.endEditBlock();
       
  1059     d->control->setTextCursor(cursor);
       
  1060 
       
  1061     // QTBUG-11100
       
  1062     updateSelectionMarkers();
       
  1063 }
       
  1064 
       
  1065 #ifndef QT_NO_CLIPBOARD
       
  1066 /*!
       
  1067     \qmlmethod TextEdit::cut()
       
  1068 
       
  1069     Moves the currently selected text to the system clipboard.
       
  1070 */
       
  1071 void QDeclarativeTextEdit::cut()
       
  1072 {
       
  1073     Q_D(QDeclarativeTextEdit);
       
  1074     d->control->cut();
       
  1075 }
       
  1076 
       
  1077 /*!
       
  1078     \qmlmethod TextEdit::copy()
       
  1079 
       
  1080     Copies the currently selected text to the system clipboard.
       
  1081 */
       
  1082 void QDeclarativeTextEdit::copy()
       
  1083 {
       
  1084     Q_D(QDeclarativeTextEdit);
       
  1085     d->control->copy();
       
  1086 }
       
  1087 
       
  1088 /*!
       
  1089     \qmlmethod TextEdit::paste()
       
  1090 
       
  1091     Replaces the currently selected text by the contents of the system clipboard.
       
  1092 */
       
  1093 void QDeclarativeTextEdit::paste()
       
  1094 {
       
  1095     Q_D(QDeclarativeTextEdit);
       
  1096     d->control->paste();
       
  1097 }
       
  1098 #endif // QT_NO_CLIPBOARD
   924 
  1099 
   925 /*!
  1100 /*!
   926 \overload
  1101 \overload
   927 Handles the given mouse \a event.
  1102 Handles the given mouse \a event.
   928 */
  1103 */
   929 void QDeclarativeTextEdit::mousePressEvent(QGraphicsSceneMouseEvent *event)
  1104 void QDeclarativeTextEdit::mousePressEvent(QGraphicsSceneMouseEvent *event)
   930 {
  1105 {
   931     Q_D(QDeclarativeTextEdit);
  1106     Q_D(QDeclarativeTextEdit);
   932     bool hadFocus = hasFocus();
       
   933     if (d->focusOnPress){
  1107     if (d->focusOnPress){
   934         QGraphicsItem *p = parentItem();//###Is there a better way to find my focus scope?
  1108         bool hadActiveFocus = hasActiveFocus();
   935         while(p) {
  1109         forceActiveFocus();
   936             if (p->flags() & QGraphicsItem::ItemIsFocusScope)
  1110         if (d->showInputPanelOnFocus) {
   937                 p->setFocus();
  1111             if (hasActiveFocus() && hadActiveFocus && !isReadOnly()) {
   938             p = p->parentItem();
  1112                 // re-open input panel on press if already focused
       
  1113                 openSoftwareInputPanel();
       
  1114             }
       
  1115         } else { // show input panel on click
       
  1116             if (hasActiveFocus() && !hadActiveFocus) {
       
  1117                 d->clickCausedFocus = true;
       
  1118             }
   939         }
  1119         }
   940         setFocus(true);
  1120     }
   941     }
       
   942     if (!hadFocus && hasFocus())
       
   943         d->clickCausedFocus = true;
       
   944     if (event->type() != QEvent::GraphicsSceneMouseDoubleClick || d->selectByMouse)
  1121     if (event->type() != QEvent::GraphicsSceneMouseDoubleClick || d->selectByMouse)
   945         d->control->processEvent(event, QPointF(0, -d->yoff));
  1122         d->control->processEvent(event, QPointF(0, -d->yoff));
   946     if (!event->isAccepted())
  1123     if (!event->isAccepted())
   947         QDeclarativePaintedItem::mousePressEvent(event);
  1124         QDeclarativePaintedItem::mousePressEvent(event);
   948 }
  1125 }
   952 Handles the given mouse \a event.
  1129 Handles the given mouse \a event.
   953 */
  1130 */
   954 void QDeclarativeTextEdit::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
  1131 void QDeclarativeTextEdit::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
   955 {
  1132 {
   956     Q_D(QDeclarativeTextEdit);
  1133     Q_D(QDeclarativeTextEdit);
   957     QWidget *widget = event->widget();
  1134     d->control->processEvent(event, QPointF(0, -d->yoff));
   958     if (widget && (d->control->textInteractionFlags() & Qt::TextEditable) && boundingRect().contains(event->pos()))
  1135     if (!d->showInputPanelOnFocus) { // input panel on click
   959         qt_widget_private(widget)->handleSoftwareInputPanel(event->button(), d->clickCausedFocus);
  1136         if (d->focusOnPress && !isReadOnly() && boundingRect().contains(event->pos())) {
       
  1137             if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
       
  1138                 if (view->scene() && view->scene() == scene()) {
       
  1139                     qt_widget_private(view)->handleSoftwareInputPanel(event->button(), d->clickCausedFocus);
       
  1140                 }
       
  1141             }
       
  1142         }
       
  1143     }
   960     d->clickCausedFocus = false;
  1144     d->clickCausedFocus = false;
   961 
  1145 
   962     d->control->processEvent(event, QPointF(0, -d->yoff));
       
   963     if (!event->isAccepted())
  1146     if (!event->isAccepted())
   964         QDeclarativePaintedItem::mouseReleaseEvent(event);
  1147         QDeclarativePaintedItem::mouseReleaseEvent(event);
   965 }
  1148 }
   966 
  1149 
   967 /*!
  1150 /*!
  1034 }
  1217 }
  1035 
  1218 
  1036 void QDeclarativeTextEdit::updateImgCache(const QRectF &rf)
  1219 void QDeclarativeTextEdit::updateImgCache(const QRectF &rf)
  1037 {
  1220 {
  1038     Q_D(const QDeclarativeTextEdit);
  1221     Q_D(const QDeclarativeTextEdit);
  1039     QRect r = rf.toRect();
  1222     QRect r;
  1040     if (r != QRect(0,0,INT_MAX,INT_MAX)) // Don't translate "everything"
  1223     if (!rf.isValid()) {
  1041         r = r.translated(0,d->yoff);
  1224         r = QRect(0,0,INT_MAX,INT_MAX);
       
  1225     } else {
       
  1226         r = rf.toRect();
       
  1227         if (r.height() > INT_MAX/2) {
       
  1228             // Take care of overflow when translating "everything"
       
  1229             r.setTop(r.y() + d->yoff);
       
  1230             r.setBottom(INT_MAX/2);
       
  1231         } else {
       
  1232             r = r.translated(0,d->yoff);
       
  1233         }
       
  1234     }
  1042     dirtyCache(r);
  1235     dirtyCache(r);
  1043     emit update();
  1236     emit update();
  1044 }
  1237 }
  1045 
  1238 
  1046 /*!
  1239 /*!
  1066     q->setFlag(QGraphicsItem::ItemHasNoContents, false);
  1259     q->setFlag(QGraphicsItem::ItemHasNoContents, false);
  1067     q->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
  1260     q->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
  1068 
  1261 
  1069     control = new QTextControl(q);
  1262     control = new QTextControl(q);
  1070     control->setIgnoreUnusedNavigationEvents(true);
  1263     control->setIgnoreUnusedNavigationEvents(true);
       
  1264 
       
  1265     // QTextControl follows the default text color
       
  1266     // defined by the platform, declarative text
       
  1267     // should be black by default
       
  1268     QPalette pal = control->palette();
       
  1269     if (pal.color(QPalette::Text) != color) {
       
  1270         pal.setColor(QPalette::Text, color);
       
  1271         control->setPalette(pal);
       
  1272     }
  1071 
  1273 
  1072     QObject::connect(control, SIGNAL(updateRequest(QRectF)), q, SLOT(updateImgCache(QRectF)));
  1274     QObject::connect(control, SIGNAL(updateRequest(QRectF)), q, SLOT(updateImgCache(QRectF)));
  1073 
  1275 
  1074     QObject::connect(control, SIGNAL(textChanged()), q, SLOT(q_textChanged()));
  1276     QObject::connect(control, SIGNAL(textChanged()), q, SLOT(q_textChanged()));
  1075     QObject::connect(control, SIGNAL(selectionChanged()), q, SIGNAL(selectionChanged()));
  1277     QObject::connect(control, SIGNAL(selectionChanged()), q, SIGNAL(selectionChanged()));
  1076     QObject::connect(control, SIGNAL(selectionChanged()), q, SLOT(updateSelectionMarkers()));
  1278     QObject::connect(control, SIGNAL(selectionChanged()), q, SLOT(updateSelectionMarkers()));
  1077     QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SLOT(updateSelectionMarkers()));
  1279     QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SLOT(updateSelectionMarkers()));
  1078     QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorPositionChanged()));
  1280     QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorPositionChanged()));
       
  1281     QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorRectangleChanged()));
  1079 
  1282 
  1080     document = control->document();
  1283     document = control->document();
  1081     document->setDefaultFont(font);
  1284     document->setDefaultFont(font);
  1082     document->setDocumentMargin(textMargin);
  1285     document->setDocumentMargin(textMargin);
  1083     document->setUndoRedoEnabled(false); // flush undo buffer.
  1286     document->setUndoRedoEnabled(false); // flush undo buffer.
  1085     updateDefaultTextOption();
  1288     updateDefaultTextOption();
  1086 }
  1289 }
  1087 
  1290 
  1088 void QDeclarativeTextEdit::q_textChanged()
  1291 void QDeclarativeTextEdit::q_textChanged()
  1089 {
  1292 {
       
  1293     Q_D(QDeclarativeTextEdit);
       
  1294     d->text = text();
  1090     updateSize();
  1295     updateSize();
  1091     emit textChanged(text());
  1296     updateMicroFocus();
       
  1297     emit textChanged(d->text);
  1092 }
  1298 }
  1093 
  1299 
  1094 void QDeclarativeTextEdit::moveCursorDelegate()
  1300 void QDeclarativeTextEdit::moveCursorDelegate()
  1095 {
  1301 {
  1096     Q_D(QDeclarativeTextEdit);
  1302     Q_D(QDeclarativeTextEdit);
  1105 {
  1311 {
  1106     Q_Q(QDeclarativeTextEdit);
  1312     Q_Q(QDeclarativeTextEdit);
  1107     QTextCursor cursor = control->textCursor();
  1313     QTextCursor cursor = control->textCursor();
  1108     bool startChange = (lastSelectionStart != cursor.selectionStart());
  1314     bool startChange = (lastSelectionStart != cursor.selectionStart());
  1109     bool endChange = (lastSelectionEnd != cursor.selectionEnd());
  1315     bool endChange = (lastSelectionEnd != cursor.selectionEnd());
  1110     //### Is it worth calculating a more minimal set of movements?
       
  1111     cursor.beginEditBlock();
  1316     cursor.beginEditBlock();
  1112     cursor.setPosition(lastSelectionStart, QTextCursor::MoveAnchor);
  1317     cursor.setPosition(lastSelectionStart, QTextCursor::MoveAnchor);
  1113     cursor.setPosition(lastSelectionEnd, QTextCursor::KeepAnchor);
  1318     cursor.setPosition(lastSelectionEnd, QTextCursor::KeepAnchor);
  1114     cursor.endEditBlock();
  1319     cursor.endEditBlock();
  1115     control->setTextCursor(cursor);
  1320     control->setTextCursor(cursor);
  1116     if(startChange)
  1321     if(startChange)
  1117         q->selectionStartChanged();
  1322         q->selectionStartChanged();
  1118     if(endChange)
  1323     if(endChange)
  1119         q->selectionEndChanged();
  1324         q->selectionEndChanged();
  1120     startChange = (lastSelectionStart != control->textCursor().selectionStart());
       
  1121     endChange = (lastSelectionEnd != control->textCursor().selectionEnd());
       
  1122 }
  1325 }
  1123 
  1326 
  1124 void QDeclarativeTextEdit::updateSelectionMarkers()
  1327 void QDeclarativeTextEdit::updateSelectionMarkers()
  1125 {
  1328 {
  1126     Q_D(QDeclarativeTextEdit);
  1329     Q_D(QDeclarativeTextEdit);
  1130     }
  1333     }
  1131     if(d->lastSelectionEnd != d->control->textCursor().selectionEnd()){
  1334     if(d->lastSelectionEnd != d->control->textCursor().selectionEnd()){
  1132         d->lastSelectionEnd = d->control->textCursor().selectionEnd();
  1335         d->lastSelectionEnd = d->control->textCursor().selectionEnd();
  1133         emit selectionEndChanged();
  1336         emit selectionEndChanged();
  1134     }
  1337     }
  1135 }
  1338     updateMicroFocus();
       
  1339 }
       
  1340 
       
  1341 QRectF QDeclarativeTextEdit::boundingRect() const
       
  1342 {
       
  1343     Q_D(const QDeclarativeTextEdit);
       
  1344     QRectF r = QDeclarativePaintedItem::boundingRect();
       
  1345     int cursorWidth = 1;
       
  1346     if(d->cursor)
       
  1347         cursorWidth = d->cursor->width();
       
  1348     if(!d->document->isEmpty())
       
  1349         cursorWidth += 3;// ### Need a better way of accounting for space between char and cursor
       
  1350 
       
  1351     // Could include font max left/right bearings to either side of rectangle.
       
  1352 
       
  1353     r.setRight(r.right() + cursorWidth);
       
  1354     return r.translated(0,d->yoff);
       
  1355 }
       
  1356 
  1136 
  1357 
  1137 //### we should perhaps be a bit smarter here -- depending on what has changed, we shouldn't
  1358 //### we should perhaps be a bit smarter here -- depending on what has changed, we shouldn't
  1138 //    need to do all the calculations each time
  1359 //    need to do all the calculations each time
  1139 void QDeclarativeTextEdit::updateSize()
  1360 void QDeclarativeTextEdit::updateSize()
  1140 {
  1361 {
  1142     if (isComponentComplete()) {
  1363     if (isComponentComplete()) {
  1143         QFontMetrics fm = QFontMetrics(d->font);
  1364         QFontMetrics fm = QFontMetrics(d->font);
  1144         int dy = height();
  1365         int dy = height();
  1145         // ### assumes that if the width is set, the text will fill to edges
  1366         // ### assumes that if the width is set, the text will fill to edges
  1146         // ### (unless wrap is false, then clipping will occur)
  1367         // ### (unless wrap is false, then clipping will occur)
  1147         if (widthValid())
  1368         if (widthValid() && d->document->textWidth() != width())
  1148             d->document->setTextWidth(width());
  1369             d->document->setTextWidth(width());
  1149         dy -= (int)d->document->size().height();
  1370         dy -= (int)d->document->size().height();
  1150 
  1371 
       
  1372         int nyoff;
  1151         if (heightValid()) {
  1373         if (heightValid()) {
  1152             if (d->vAlign == AlignBottom)
  1374             if (d->vAlign == AlignBottom)
  1153                 d->yoff = dy;
  1375                 nyoff = dy;
  1154             else if (d->vAlign == AlignVCenter)
  1376             else if (d->vAlign == AlignVCenter)
  1155                 d->yoff = dy/2;
  1377                 nyoff = dy/2;
       
  1378             else
       
  1379                 nyoff = 0;
  1156         } else {
  1380         } else {
  1157             d->yoff = 0;
  1381             nyoff = 0;
       
  1382         }
       
  1383         if (nyoff != d->yoff) {
       
  1384             prepareGeometryChange();
       
  1385             d->yoff = nyoff;
  1158         }
  1386         }
  1159         setBaselineOffset(fm.ascent() + d->yoff + d->textMargin);
  1387         setBaselineOffset(fm.ascent() + d->yoff + d->textMargin);
  1160 
  1388 
  1161         //### need to comfirm cost of always setting these
  1389         //### need to comfirm cost of always setting these
  1162         int newWidth = qCeil(d->document->idealWidth());
  1390         int newWidth = qCeil(d->document->idealWidth());
  1163         if (!widthValid())
  1391         if (!widthValid() && d->document->textWidth() != newWidth)
  1164             d->document->setTextWidth(newWidth); // ### Text does not align if width is not set (QTextDoc bug)
  1392             d->document->setTextWidth(newWidth); // ### Text does not align if width is not set (QTextDoc bug)
  1165         int cursorWidth = 1;
       
  1166         if(d->cursor)
       
  1167             cursorWidth = d->cursor->width();
       
  1168         newWidth += cursorWidth;
       
  1169         if(!d->document->isEmpty())
       
  1170             newWidth += 3;// ### Need a better way of accounting for space between char and cursor
       
  1171         // ### Setting the implicitWidth triggers another updateSize(), and unless there are bindings nothing has changed.
  1393         // ### Setting the implicitWidth triggers another updateSize(), and unless there are bindings nothing has changed.
  1172         setImplicitWidth(newWidth);
  1394         setImplicitWidth(newWidth);
  1173         setImplicitHeight(d->text.isEmpty() ? fm.height() : (int)d->document->size().height());
  1395         qreal newHeight = d->document->isEmpty() ? fm.height() : (int)d->document->size().height();
  1174 
  1396         setImplicitHeight(newHeight);
  1175         setContentsSize(QSize(width(), height()));
  1397 
       
  1398         setContentsSize(QSize(newWidth, newHeight));
       
  1399 
       
  1400         emit paintedSizeChanged();
  1176     } else {
  1401     } else {
  1177         d->dirty = true;
  1402         d->dirty = true;
  1178     }
  1403     }
  1179     emit update();
  1404     emit update();
  1180 }
  1405 }
  1191     if (oldWrapMode == opt.wrapMode() && oldAlignment == opt.alignment())
  1416     if (oldWrapMode == opt.wrapMode() && oldAlignment == opt.alignment())
  1192         return;
  1417         return;
  1193     document->setDefaultTextOption(opt);
  1418     document->setDefaultTextOption(opt);
  1194 }
  1419 }
  1195 
  1420 
       
  1421 
       
  1422 /*!
       
  1423     \qmlmethod void TextEdit::openSoftwareInputPanel()
       
  1424 
       
  1425     Opens software input panels like virtual keyboards for typing, useful for
       
  1426     customizing when you want the input keyboard to be shown and hidden in
       
  1427     your application.
       
  1428 
       
  1429     By default the opening of input panels follows the platform style. On Symbian^1 and
       
  1430     Symbian^3 -based devices the panels are opened by clicking TextEdit. On other platforms
       
  1431     the panels are automatically opened when TextEdit element gains active focus. Input panels are
       
  1432     always closed if no editor has active focus.
       
  1433 
       
  1434     You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
       
  1435     and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
       
  1436     the behavior you want.
       
  1437 
       
  1438     Only relevant on platforms, which provide virtual keyboards.
       
  1439 
       
  1440     \code
       
  1441         import Qt 4.7
       
  1442         TextEdit {
       
  1443             id: textEdit
       
  1444             text: "Hello world!"
       
  1445             activeFocusOnPress: false
       
  1446             MouseArea {
       
  1447                 anchors.fill: parent
       
  1448                 onClicked: {
       
  1449                     if (!textEdit.activeFocus) {
       
  1450                         textEdit.forceActiveFocus();
       
  1451                         textEdit.openSoftwareInputPanel();
       
  1452                     } else {
       
  1453                         textEdit.focus = false;
       
  1454                     }
       
  1455                 }
       
  1456                 onPressAndHold: textEdit.closeSoftwareInputPanel();
       
  1457             }
       
  1458         }
       
  1459     \endcode
       
  1460 */
       
  1461 void QDeclarativeTextEdit::openSoftwareInputPanel()
       
  1462 {
       
  1463     QEvent event(QEvent::RequestSoftwareInputPanel);
       
  1464     if (qApp) {
       
  1465         if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
       
  1466             if (view->scene() && view->scene() == scene()) {
       
  1467                 QApplication::sendEvent(view, &event);
       
  1468             }
       
  1469         }
       
  1470     }
       
  1471 }
       
  1472 
       
  1473 /*!
       
  1474     \qmlmethod void TextEdit::closeSoftwareInputPanel()
       
  1475 
       
  1476     Closes a software input panel like a virtual keyboard shown on the screen, useful
       
  1477     for customizing when you want the input keyboard to be shown and hidden in
       
  1478     your application.
       
  1479 
       
  1480     By default the opening of input panels follows the platform style. On Symbian^1 and
       
  1481     Symbian^3 -based devices the panels are opened by clicking TextEdit. On other platforms
       
  1482     the panels are automatically opened when TextEdit element gains active focus. Input panels are
       
  1483     always closed if no editor has active focus.
       
  1484 
       
  1485     You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
       
  1486     and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
       
  1487     the behavior you want.
       
  1488 
       
  1489     Only relevant on platforms, which provide virtual keyboards.
       
  1490 
       
  1491     \code
       
  1492         import Qt 4.7
       
  1493         TextEdit {
       
  1494             id: textEdit
       
  1495             text: "Hello world!"
       
  1496             activeFocusOnPress: false
       
  1497             MouseArea {
       
  1498                 anchors.fill: parent
       
  1499                 onClicked: {
       
  1500                     if (!textEdit.activeFocus) {
       
  1501                         textEdit.forceActiveFocus();
       
  1502                         textEdit.openSoftwareInputPanel();
       
  1503                     } else {
       
  1504                         textEdit.focus = false;
       
  1505                     }
       
  1506                 }
       
  1507                 onPressAndHold: textEdit.closeSoftwareInputPanel();
       
  1508             }
       
  1509         }
       
  1510     \endcode
       
  1511 */
       
  1512 void QDeclarativeTextEdit::closeSoftwareInputPanel()
       
  1513 {
       
  1514     QEvent event(QEvent::CloseSoftwareInputPanel);
       
  1515     if (qApp) {
       
  1516         if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
       
  1517             if (view->scene() && view->scene() == scene()) {
       
  1518                 QApplication::sendEvent(view, &event);
       
  1519             }
       
  1520         }
       
  1521     }
       
  1522 }
       
  1523 
       
  1524 void QDeclarativeTextEdit::focusInEvent(QFocusEvent *event)
       
  1525 {
       
  1526     Q_D(const QDeclarativeTextEdit);
       
  1527     if (d->showInputPanelOnFocus) {
       
  1528         if (d->focusOnPress && !isReadOnly()) {
       
  1529             openSoftwareInputPanel();
       
  1530         }
       
  1531     }
       
  1532     QDeclarativePaintedItem::focusInEvent(event);
       
  1533 }
       
  1534 
  1196 QT_END_NAMESPACE
  1535 QT_END_NAMESPACE