1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "private/qdeclarativetextedit_p.h"
43 #include "private/qdeclarativetextedit_p_p.h"
45 #include "private/qdeclarativeevents_p_p.h"
46 #include <private/qdeclarativeglobal_p.h>
47 #include <qdeclarativeinfo.h>
49 #include <QtCore/qmath.h>
51 #include <private/qtextengine_p.h>
52 #include <QTextLayout>
54 #include <QTextDocument>
55 #include <QTextObject>
56 #include <QGraphicsSceneMouseEvent>
59 #include <QtGui/QInputPanel>
61 #include <private/qwidgettextcontrol_p.h>
68 \qmlclass TextEdit QDeclarative1TextEdit
69 \inqmlmodule QtQuick 1
70 \ingroup qml-basic-visual-elements
72 \brief The TextEdit item displays multiple lines of editable formatted text.
75 The TextEdit item displays a block of editable, formatted text.
77 It can display both plain and rich text. For example:
82 text: "<b>Hello</b> <i>World!</i>"
83 font.family: "Helvetica"
90 \image declarative-textedit.gif
92 Setting \l {Item::focus}{focus} to \c true enables the TextEdit item to receive keyboard focus.
94 Note that the TextEdit does not implement scrolling, following the cursor, or other behaviors specific
95 to a look-and-feel. For example, to add flickable scrolling that follows the cursor:
97 \snippet snippets/declarative/texteditor.qml 0
99 A particular look-and-feel might use smooth scrolling (eg. using SmoothedFollow), might have a visible
100 scrollbar, or a scrollbar that fades in to show location, etc.
102 Clipboard support is provided by the cut(), copy(), and paste() functions, and the selection can
103 be handled in a traditional "mouse" mechanism by setting selectByMouse, or handled completely
104 from QML by manipulating selectionStart and selectionEnd, or using selectAll() or selectWord().
106 You can translate between cursor positions (characters from the start of the document) and pixel
107 points using positionAt() and positionToRectangle().
109 \sa Text, TextInput, {declarative/text/textselection}{Text Selection example}
113 \qmlsignal QtQuick1::TextEdit::onLinkActivated(string link)
116 This handler is called when the user clicks on a link embedded in the text.
117 The link must be in rich text or HTML format and the
118 \a link string provides access to the particular link.
120 QDeclarative1TextEdit::QDeclarative1TextEdit(QDeclarativeItem *parent)
121 : QDeclarative1ImplicitSizePaintedItem(*(new QDeclarative1TextEditPrivate), parent)
123 Q_D(QDeclarative1TextEdit);
127 QString QDeclarative1TextEdit::text() const
129 Q_D(const QDeclarative1TextEdit);
131 #ifndef QT_NO_TEXTHTMLPARSER
133 return d->control->toHtml();
136 return d->control->toPlainText();
140 \qmlproperty string QtQuick1::TextEdit::font.family
142 Sets the family name of the font.
144 The family name is case insensitive and may optionally include a foundry name, e.g. "Helvetica [Cronyx]".
145 If the family is available from more than one foundry and the foundry isn't specified, an arbitrary foundry is chosen.
146 If the family isn't available a family will be set using the font matching algorithm.
150 \qmlproperty bool QtQuick1::TextEdit::font.bold
152 Sets whether the font weight is bold.
156 \qmlproperty enumeration QtQuick1::TextEdit::font.weight
158 Sets the font's weight.
160 The weight can be one of:
163 \o Font.Normal - the default
170 TextEdit { text: "Hello"; font.weight: Font.DemiBold }
175 \qmlproperty bool QtQuick1::TextEdit::font.italic
177 Sets whether the font has an italic style.
181 \qmlproperty bool QtQuick1::TextEdit::font.underline
183 Sets whether the text is underlined.
187 \qmlproperty bool QtQuick1::TextEdit::font.strikeout
189 Sets whether the font has a strikeout style.
193 \qmlproperty real QtQuick1::TextEdit::font.pointSize
195 Sets the font size in points. The point size must be greater than zero.
199 \qmlproperty int QtQuick1::TextEdit::font.pixelSize
201 Sets the font size in pixels.
203 Using this function makes the font device dependent. Use
204 \l{TextEdit::font.pointSize} to set the size of the font in a
205 device independent manner.
209 \qmlproperty real QtQuick1::TextEdit::font.letterSpacing
211 Sets the letter spacing for the font.
213 Letter spacing changes the default spacing between individual letters in the font.
214 A positive value increases the letter spacing by the corresponding pixels; a negative value decreases the spacing.
218 \qmlproperty real QtQuick1::TextEdit::font.wordSpacing
220 Sets the word spacing for the font.
222 Word spacing changes the default spacing between individual words.
223 A positive value increases the word spacing by a corresponding amount of pixels,
224 while a negative value decreases the inter-word spacing accordingly.
228 \qmlproperty enumeration QtQuick1::TextEdit::font.capitalization
230 Sets the capitalization for the text.
233 \o Font.MixedCase - This is the normal text rendering option where no capitalization change is applied.
234 \o Font.AllUppercase - This alters the text to be rendered in all uppercase type.
235 \o Font.AllLowercase - This alters the text to be rendered in all lowercase type.
236 \o Font.SmallCaps - This alters the text to be rendered in small-caps type.
237 \o Font.Capitalize - This alters the text to be rendered with the first character of each word as an uppercase character.
241 TextEdit { text: "Hello"; font.capitalization: Font.AllLowercase }
246 \qmlproperty string QtQuick1::TextEdit::text
248 The text to display. If the text format is AutoText the text edit will
249 automatically determine whether the text should be treated as
250 rich text. This determination is made using Qt::mightBeRichText().
252 void QDeclarative1TextEdit::setText(const QString &text)
254 Q_D(QDeclarative1TextEdit);
255 if (QDeclarative1TextEdit::text() == text)
258 d->richText = d->format == RichText || (d->format == AutoText && Qt::mightBeRichText(text));
260 #ifndef QT_NO_TEXTHTMLPARSER
261 d->control->setHtml(text);
263 d->control->setPlainText(text);
266 d->control->setPlainText(text);
272 \qmlproperty enumeration QtQuick1::TextEdit::textFormat
274 The way the text property should be displayed.
278 \o TextEdit.PlainText
282 The default is TextEdit.AutoText. If the text format is TextEdit.AutoText the text edit
283 will automatically determine whether the text should be treated as
284 rich text. This determination is made using Qt::mightBeRichText().
293 text: "<b>Hello</b> <i>World!</i>"
297 textFormat: TextEdit.RichText
298 text: "<b>Hello</b> <i>World!</i>"
302 textFormat: TextEdit.PlainText
303 text: "<b>Hello</b> <i>World!</i>"
307 \o \image declarative-textformat.png
310 QDeclarative1TextEdit::TextFormat QDeclarative1TextEdit::textFormat() const
312 Q_D(const QDeclarative1TextEdit);
316 void QDeclarative1TextEdit::setTextFormat(TextFormat format)
318 Q_D(QDeclarative1TextEdit);
319 if (format == d->format)
321 bool wasRich = d->richText;
322 d->richText = format == RichText || (format == AutoText && Qt::mightBeRichText(d->text));
324 if (wasRich && !d->richText) {
325 d->control->setPlainText(d->text);
327 } else if (!wasRich && d->richText) {
328 #ifndef QT_NO_TEXTHTMLPARSER
329 d->control->setHtml(d->text);
331 d->control->setPlainText(d->text);
336 d->control->setAcceptRichText(d->format != PlainText);
337 emit textFormatChanged(d->format);
340 QFont QDeclarative1TextEdit::font() const
342 Q_D(const QDeclarative1TextEdit);
343 return d->sourceFont;
346 void QDeclarative1TextEdit::setFont(const QFont &font)
348 Q_D(QDeclarative1TextEdit);
349 if (d->sourceFont == font)
352 d->sourceFont = font;
353 QFont oldFont = d->font;
355 if (d->font.pointSizeF() != -1) {
357 qreal size = qRound(d->font.pointSizeF()*2.0);
358 d->font.setPointSizeF(size/2.0);
361 if (oldFont != d->font) {
363 d->document->setDefaultFont(d->font);
365 d->cursor->setHeight(QFontMetrics(d->font).height());
366 moveCursorDelegate();
371 emit fontChanged(d->sourceFont);
375 \qmlproperty color QtQuick1::TextEdit::color
380 // green text using hexadecimal notation
381 TextEdit { color: "#00FF00" }
385 // steelblue text using SVG color name
386 TextEdit { color: "steelblue" }
389 QColor QDeclarative1TextEdit::color() const
391 Q_D(const QDeclarative1TextEdit);
395 void QDeclarative1TextEdit::setColor(const QColor &color)
397 Q_D(QDeclarative1TextEdit);
398 if (d->color == color)
403 QPalette pal = d->control->palette();
404 pal.setColor(QPalette::Text, color);
405 d->control->setPalette(pal);
407 emit colorChanged(d->color);
411 \qmlproperty color QtQuick1::TextEdit::selectionColor
413 The text highlight color, used behind selections.
415 QColor QDeclarative1TextEdit::selectionColor() const
417 Q_D(const QDeclarative1TextEdit);
418 return d->selectionColor;
421 void QDeclarative1TextEdit::setSelectionColor(const QColor &color)
423 Q_D(QDeclarative1TextEdit);
424 if (d->selectionColor == color)
428 d->selectionColor = color;
429 QPalette pal = d->control->palette();
430 pal.setColor(QPalette::Highlight, color);
431 d->control->setPalette(pal);
433 emit selectionColorChanged(d->selectionColor);
437 \qmlproperty color QtQuick1::TextEdit::selectedTextColor
439 The selected text color, used in selections.
441 QColor QDeclarative1TextEdit::selectedTextColor() const
443 Q_D(const QDeclarative1TextEdit);
444 return d->selectedTextColor;
447 void QDeclarative1TextEdit::setSelectedTextColor(const QColor &color)
449 Q_D(QDeclarative1TextEdit);
450 if (d->selectedTextColor == color)
454 d->selectedTextColor = color;
455 QPalette pal = d->control->palette();
456 pal.setColor(QPalette::HighlightedText, color);
457 d->control->setPalette(pal);
459 emit selectedTextColorChanged(d->selectedTextColor);
463 \qmlproperty enumeration QtQuick1::TextEdit::horizontalAlignment
464 \qmlproperty enumeration QtQuick1::TextEdit::verticalAlignment
465 \qmlproperty enumeration QtQuick1::TextEdit::effectiveHorizontalAlignment
467 Sets the horizontal and vertical alignment of the text within the TextEdit item's
468 width and height. By default, the text alignment follows the natural alignment
469 of the text, for example text that is read from left to right will be aligned to
472 Valid values for \c horizontalAlignment are:
474 \o TextEdit.AlignLeft (default)
475 \o TextEdit.AlignRight
476 \o TextEdit.AlignHCenter
477 \o TextEdit.AlignJustify
480 Valid values for \c verticalAlignment are:
482 \o TextEdit.AlignTop (default)
483 \o TextEdit.AlignBottom
484 \o TextEdit.AlignVCenter
487 When using the attached property LayoutMirroring::enabled to mirror application
488 layouts, the horizontal alignment of text will also be mirrored. However, the property
489 \c horizontalAlignment will remain unchanged. To query the effective horizontal alignment
490 of TextEdit, use the read-only property \c effectiveHorizontalAlignment.
492 QDeclarative1TextEdit::HAlignment QDeclarative1TextEdit::hAlign() const
494 Q_D(const QDeclarative1TextEdit);
498 void QDeclarative1TextEdit::setHAlign(HAlignment align)
500 Q_D(QDeclarative1TextEdit);
501 bool forceAlign = d->hAlignImplicit && d->effectiveLayoutMirror;
502 d->hAlignImplicit = false;
503 if (d->setHAlign(align, forceAlign) && isComponentComplete()) {
504 d->updateDefaultTextOption();
509 void QDeclarative1TextEdit::resetHAlign()
511 Q_D(QDeclarative1TextEdit);
512 d->hAlignImplicit = true;
513 if (d->determineHorizontalAlignment() && isComponentComplete()) {
514 d->updateDefaultTextOption();
519 QDeclarative1TextEdit::HAlignment QDeclarative1TextEdit::effectiveHAlign() const
521 Q_D(const QDeclarative1TextEdit);
522 QDeclarative1TextEdit::HAlignment effectiveAlignment = d->hAlign;
523 if (!d->hAlignImplicit && d->effectiveLayoutMirror) {
525 case QDeclarative1TextEdit::AlignLeft:
526 effectiveAlignment = QDeclarative1TextEdit::AlignRight;
528 case QDeclarative1TextEdit::AlignRight:
529 effectiveAlignment = QDeclarative1TextEdit::AlignLeft;
535 return effectiveAlignment;
538 bool QDeclarative1TextEditPrivate::setHAlign(QDeclarative1TextEdit::HAlignment alignment, bool forceAlign)
540 Q_Q(QDeclarative1TextEdit);
541 if (hAlign != alignment || forceAlign) {
542 QDeclarative1TextEdit::HAlignment oldEffectiveHAlign = q->effectiveHAlign();
544 emit q->horizontalAlignmentChanged(alignment);
545 if (oldEffectiveHAlign != q->effectiveHAlign())
546 emit q->effectiveHorizontalAlignmentChanged();
552 bool QDeclarative1TextEditPrivate::determineHorizontalAlignment()
554 Q_Q(QDeclarative1TextEdit);
555 if (hAlignImplicit && q->isComponentComplete()) {
557 if (text.isEmpty()) {
558 QTextCursor cursor = control->textCursor();
559 const QString preeditText = cursor.block().isValid()
560 ? control->textCursor().block().layout()->preeditAreaText()
562 alignToRight = preeditText.isEmpty()
563 ? qApp->inputPanel()->inputDirection() == Qt::RightToLeft
564 : preeditText.isRightToLeft();
566 alignToRight = rightToLeftText;
568 return setHAlign(alignToRight ? QDeclarative1TextEdit::AlignRight : QDeclarative1TextEdit::AlignLeft);
573 void QDeclarative1TextEditPrivate::mirrorChange()
575 Q_Q(QDeclarative1TextEdit);
576 if (q->isComponentComplete()) {
577 if (!hAlignImplicit && (hAlign == QDeclarative1TextEdit::AlignRight || hAlign == QDeclarative1TextEdit::AlignLeft)) {
578 updateDefaultTextOption();
580 emit q->effectiveHorizontalAlignmentChanged();
585 QDeclarative1TextEdit::VAlignment QDeclarative1TextEdit::vAlign() const
587 Q_D(const QDeclarative1TextEdit);
591 void QDeclarative1TextEdit::setVAlign(QDeclarative1TextEdit::VAlignment alignment)
593 Q_D(QDeclarative1TextEdit);
594 if (alignment == d->vAlign)
596 d->vAlign = alignment;
597 d->updateDefaultTextOption();
599 moveCursorDelegate();
600 emit verticalAlignmentChanged(d->vAlign);
604 \qmlproperty enumeration QtQuick1::TextEdit::wrapMode
606 Set this property to wrap the text to the TextEdit item's width.
607 The text will only wrap if an explicit width has been set.
610 \o TextEdit.NoWrap - no wrapping will be performed. If the text contains insufficient newlines, then implicitWidth will exceed a set width.
611 \o TextEdit.WordWrap - wrapping is done on word boundaries only. If a word is too long, implicitWidth will exceed a set width.
612 \o TextEdit.WrapAnywhere - wrapping is done at any point on a line, even if it occurs in the middle of a word.
613 \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.
616 The default is TextEdit.NoWrap. If you set a width, consider using TextEdit.Wrap.
618 QDeclarative1TextEdit::WrapMode QDeclarative1TextEdit::wrapMode() const
620 Q_D(const QDeclarative1TextEdit);
624 void QDeclarative1TextEdit::setWrapMode(WrapMode mode)
626 Q_D(QDeclarative1TextEdit);
627 if (mode == d->wrapMode)
630 d->updateDefaultTextOption();
632 emit wrapModeChanged();
636 \qmlproperty int QtQuick1::TextEdit::lineCount
639 Returns the total number of lines in the textEdit item.
641 int QDeclarative1TextEdit::lineCount() const
643 Q_D(const QDeclarative1TextEdit);
648 \qmlproperty real QtQuick1::TextEdit::paintedWidth
650 Returns the width of the text, including the width past the width
651 which is covered due to insufficient wrapping if \l wrapMode is set.
653 qreal QDeclarative1TextEdit::paintedWidth() const
655 Q_D(const QDeclarative1TextEdit);
656 return d->paintedSize.width();
660 \qmlproperty real QtQuick1::TextEdit::paintedHeight
662 Returns the height of the text, including the height past the height
663 that is covered if the text does not fit within the set height.
665 qreal QDeclarative1TextEdit::paintedHeight() const
667 Q_D(const QDeclarative1TextEdit);
668 return d->paintedSize.height();
672 \qmlmethod rectangle QtQuick1::TextEdit::positionToRectangle(position)
674 Returns the rectangle at the given \a position in the text. The x, y,
675 and height properties correspond to the cursor that would describe
678 QRectF QDeclarative1TextEdit::positionToRectangle(int pos) const
680 Q_D(const QDeclarative1TextEdit);
681 QTextCursor c(d->document);
683 return d->control->cursorRect(c);
688 \qmlmethod int QtQuick1::TextEdit::positionAt(int x, int y)
690 Returns the text position closest to pixel position (\a x, \a y).
692 Position 0 is before the first character, position 1 is after the first character
693 but before the second, and so on until position \l {text}.length, which is after all characters.
695 int QDeclarative1TextEdit::positionAt(int x, int y) const
697 Q_D(const QDeclarative1TextEdit);
698 int r = d->document->documentLayout()->hitTest(QPoint(x,y-d->yoff), Qt::FuzzyHit);
699 QTextCursor cursor = d->control->textCursor();
700 if (r > cursor.position()) {
701 // The cursor position includes positions within the preedit text, but only positions in the
702 // same text block are offset so it is possible to get a position that is either part of the
703 // preedit or the next text block.
704 QTextLayout *layout = cursor.block().layout();
705 const int preeditLength = layout
706 ? layout->preeditAreaText().length()
708 if (preeditLength > 0
709 && d->document->documentLayout()->blockBoundingRect(cursor.block()).contains(x,y-d->yoff)) {
710 r = r > cursor.position() + preeditLength
718 void QDeclarative1TextEdit::moveCursorSelection(int pos)
720 //Note that this is the same as setCursorPosition but with the KeepAnchor flag set
721 Q_D(QDeclarative1TextEdit);
722 QTextCursor cursor = d->control->textCursor();
723 if (cursor.position() == pos)
725 cursor.setPosition(pos, QTextCursor::KeepAnchor);
726 d->control->setTextCursor(cursor);
730 \qmlmethod void QtQuick1::TextEdit::moveCursorSelection(int position, SelectionMode mode = TextEdit.SelectCharacters)
733 Moves the cursor to \a position and updates the selection according to the optional \a mode
734 parameter. (To only move the cursor, set the \l cursorPosition property.)
736 When this method is called it additionally sets either the
737 selectionStart or the selectionEnd (whichever was at the previous cursor position)
738 to the specified position. This allows you to easily extend and contract the selected
741 The selection mode specifies whether the selection is updated on a per character or a per word
742 basis. If not specified the selection mode will default to TextEdit.SelectCharacters.
745 \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at
746 the previous cursor position) to the specified position.
747 \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all
748 words between the specified postion and the previous cursor position. Words partially in the
752 For example, take this sequence of calls:
756 moveCursorSelection(9, TextEdit.SelectCharacters)
757 moveCursorSelection(7, TextEdit.SelectCharacters)
760 This moves the cursor to position 5, extend the selection end from 5 to 9
761 and then retract the selection end from 9 to 7, leaving the text from position 5 to 7
762 selected (the 6th and 7th characters).
764 The same sequence with TextEdit.SelectWords will extend the selection start to a word boundary
765 before or on position 5 and extend the selection end to a word boundary on or past position 9.
767 void QDeclarative1TextEdit::moveCursorSelection(int pos, SelectionMode mode)
769 Q_D(QDeclarative1TextEdit);
770 QTextCursor cursor = d->control->textCursor();
771 if (cursor.position() == pos)
773 if (mode == SelectCharacters) {
774 cursor.setPosition(pos, QTextCursor::KeepAnchor);
775 } else if (cursor.anchor() < pos || (cursor.anchor() == pos && cursor.position() < pos)) {
776 if (cursor.anchor() > cursor.position()) {
777 cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
778 cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor);
779 if (cursor.position() == cursor.anchor())
780 cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::MoveAnchor);
782 cursor.setPosition(cursor.position(), QTextCursor::MoveAnchor);
784 cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
785 cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::MoveAnchor);
788 cursor.setPosition(pos, QTextCursor::KeepAnchor);
789 cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor);
790 if (cursor.position() != pos)
791 cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
792 } else if (cursor.anchor() > pos || (cursor.anchor() == pos && cursor.position() > pos)) {
793 if (cursor.anchor() < cursor.position()) {
794 cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
795 cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::MoveAnchor);
797 cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
798 cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor);
799 cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
800 if (cursor.position() != cursor.anchor()) {
801 cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
802 cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::MoveAnchor);
806 cursor.setPosition(pos, QTextCursor::KeepAnchor);
807 cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
808 if (cursor.position() != pos) {
809 cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor);
810 cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor);
813 d->control->setTextCursor(cursor);
817 \qmlproperty bool QtQuick1::TextEdit::cursorVisible
818 If true the text edit shows a cursor.
820 This property is set and unset when the text edit gets active focus, but it can also
821 be set directly (useful, for example, if a KeyProxy might forward keys to it).
823 bool QDeclarative1TextEdit::isCursorVisible() const
825 Q_D(const QDeclarative1TextEdit);
826 return d->cursorVisible;
829 void QDeclarative1TextEdit::setCursorVisible(bool on)
831 Q_D(QDeclarative1TextEdit);
832 if (d->cursorVisible == on)
834 d->cursorVisible = on;
835 QFocusEvent focusEvent(on ? QEvent::FocusIn : QEvent::FocusOut);
836 if (!on && !d->persistentSelection)
837 d->control->setCursorIsFocusIndicator(true);
838 d->control->processEvent(&focusEvent, QPointF(0, -d->yoff));
839 emit cursorVisibleChanged(d->cursorVisible);
843 \qmlproperty int QtQuick1::TextEdit::cursorPosition
844 The position of the cursor in the TextEdit.
846 int QDeclarative1TextEdit::cursorPosition() const
848 Q_D(const QDeclarative1TextEdit);
849 return d->control->textCursor().position();
852 void QDeclarative1TextEdit::setCursorPosition(int pos)
854 Q_D(QDeclarative1TextEdit);
855 if (pos < 0 || pos > d->text.length())
857 QTextCursor cursor = d->control->textCursor();
858 if (cursor.position() == pos && cursor.anchor() == pos)
860 cursor.setPosition(pos);
861 d->control->setTextCursor(cursor);
865 \qmlproperty Component QtQuick1::TextEdit::cursorDelegate
866 The delegate for the cursor in the TextEdit.
868 If you set a cursorDelegate for a TextEdit, this delegate will be used for
869 drawing the cursor instead of the standard cursor. An instance of the
870 delegate will be created and managed by the text edit when a cursor is
871 needed, and the x and y properties of delegate instance will be set so as
872 to be one pixel before the top left of the current character.
874 Note that the root item of the delegate component must be a QDeclarativeItem or
875 QDeclarativeItem derived item.
877 QDeclarativeComponent* QDeclarative1TextEdit::cursorDelegate() const
879 Q_D(const QDeclarative1TextEdit);
880 return d->cursorComponent;
883 void QDeclarative1TextEdit::setCursorDelegate(QDeclarativeComponent* c)
885 Q_D(QDeclarative1TextEdit);
886 if(d->cursorComponent){
888 d->control->setCursorWidth(-1);
889 dirtyCache(cursorRectangle());
894 d->cursorComponent = c;
895 if(c && c->isReady()){
896 loadCursorDelegate();
899 connect(c, SIGNAL(statusChanged()),
900 this, SLOT(loadCursorDelegate()));
903 emit cursorDelegateChanged();
906 void QDeclarative1TextEdit::loadCursorDelegate()
908 Q_D(QDeclarative1TextEdit);
909 if(d->cursorComponent->isLoading())
911 d->cursor = qobject_cast<QDeclarativeItem*>(d->cursorComponent->create(qmlContext(this)));
913 d->control->setCursorWidth(0);
914 dirtyCache(cursorRectangle());
915 QDeclarative_setParent_noEvent(d->cursor, this);
916 d->cursor->setParentItem(this);
917 d->cursor->setHeight(QFontMetrics(d->font).height());
918 moveCursorDelegate();
920 qmlInfo(this) << "Error loading cursor delegate.";
925 \qmlproperty int QtQuick1::TextEdit::selectionStart
927 The cursor position before the first character in the current selection.
929 This property is read-only. To change the selection, use select(start,end),
930 selectAll(), or selectWord().
932 \sa selectionEnd, cursorPosition, selectedText
934 int QDeclarative1TextEdit::selectionStart() const
936 Q_D(const QDeclarative1TextEdit);
937 return d->control->textCursor().selectionStart();
941 \qmlproperty int QtQuick1::TextEdit::selectionEnd
943 The cursor position after the last character in the current selection.
945 This property is read-only. To change the selection, use select(start,end),
946 selectAll(), or selectWord().
948 \sa selectionStart, cursorPosition, selectedText
950 int QDeclarative1TextEdit::selectionEnd() const
952 Q_D(const QDeclarative1TextEdit);
953 return d->control->textCursor().selectionEnd();
957 \qmlproperty string QtQuick1::TextEdit::selectedText
959 This read-only property provides the text currently selected in the
962 It is equivalent to the following snippet, but is faster and easier
965 //myTextEdit is the id of the TextEdit
966 myTextEdit.text.toString().substring(myTextEdit.selectionStart,
967 myTextEdit.selectionEnd);
970 QString QDeclarative1TextEdit::selectedText() const
972 Q_D(const QDeclarative1TextEdit);
973 return d->control->textCursor().selectedText();
977 \qmlproperty bool QtQuick1::TextEdit::activeFocusOnPress
979 Whether the TextEdit should gain active focus on a mouse press. By default this is
982 bool QDeclarative1TextEdit::focusOnPress() const
984 Q_D(const QDeclarative1TextEdit);
985 return d->focusOnPress;
988 void QDeclarative1TextEdit::setFocusOnPress(bool on)
990 Q_D(QDeclarative1TextEdit);
991 if (d->focusOnPress == on)
993 d->focusOnPress = on;
994 emit activeFocusOnPressChanged(d->focusOnPress);
998 \qmlproperty bool QtQuick1::TextEdit::persistentSelection
1000 Whether the TextEdit should keep the selection visible when it loses active focus to another
1001 item in the scene. By default this is set to true;
1003 bool QDeclarative1TextEdit::persistentSelection() const
1005 Q_D(const QDeclarative1TextEdit);
1006 return d->persistentSelection;
1009 void QDeclarative1TextEdit::setPersistentSelection(bool on)
1011 Q_D(QDeclarative1TextEdit);
1012 if (d->persistentSelection == on)
1014 d->persistentSelection = on;
1015 emit persistentSelectionChanged(d->persistentSelection);
1019 \qmlproperty real QtQuick1::TextEdit::textMargin
1021 The margin, in pixels, around the text in the TextEdit.
1023 qreal QDeclarative1TextEdit::textMargin() const
1025 Q_D(const QDeclarative1TextEdit);
1026 return d->textMargin;
1029 void QDeclarative1TextEdit::setTextMargin(qreal margin)
1031 Q_D(QDeclarative1TextEdit);
1032 if (d->textMargin == margin)
1034 d->textMargin = margin;
1035 d->document->setDocumentMargin(d->textMargin);
1036 emit textMarginChanged(d->textMargin);
1039 void QDeclarative1TextEdit::geometryChanged(const QRectF &newGeometry,
1040 const QRectF &oldGeometry)
1042 if (newGeometry.width() != oldGeometry.width())
1044 QDeclarative1PaintedItem::geometryChanged(newGeometry, oldGeometry);
1048 Ensures any delayed caching or data loading the class
1049 needs to performed is complete.
1051 void QDeclarative1TextEdit::componentComplete()
1053 Q_D(QDeclarative1TextEdit);
1054 QDeclarative1PaintedItem::componentComplete();
1056 d->determineHorizontalAlignment();
1057 d->updateDefaultTextOption();
1064 \qmlproperty bool QtQuick1::TextEdit::selectByMouse
1068 If true, the user can use the mouse to select text in some
1069 platform-specific way. Note that for some platforms this may
1070 not be an appropriate interaction (eg. may conflict with how
1071 the text needs to behave inside a Flickable.
1073 bool QDeclarative1TextEdit::selectByMouse() const
1075 Q_D(const QDeclarative1TextEdit);
1076 return d->selectByMouse;
1079 void QDeclarative1TextEdit::setSelectByMouse(bool on)
1081 Q_D(QDeclarative1TextEdit);
1082 if (d->selectByMouse != on) {
1083 d->selectByMouse = on;
1084 setKeepMouseGrab(on);
1086 setTextInteractionFlags(d->control->textInteractionFlags() | Qt::TextSelectableByMouse);
1088 setTextInteractionFlags(d->control->textInteractionFlags() & ~Qt::TextSelectableByMouse);
1089 emit selectByMouseChanged(on);
1095 \qmlproperty enum QtQuick1::TextEdit::mouseSelectionMode
1098 Specifies how text should be selected using a mouse.
1101 \o TextEdit.SelectCharacters - The selection is updated with individual characters. (Default)
1102 \o TextEdit.SelectWords - The selection is updated with whole words.
1105 This property only applies when \l selectByMouse is true.
1108 QDeclarative1TextEdit::SelectionMode QDeclarative1TextEdit::mouseSelectionMode() const
1110 Q_D(const QDeclarative1TextEdit);
1111 return d->mouseSelectionMode;
1114 void QDeclarative1TextEdit::setMouseSelectionMode(SelectionMode mode)
1116 Q_D(QDeclarative1TextEdit);
1117 if (d->mouseSelectionMode != mode) {
1118 d->mouseSelectionMode = mode;
1119 d->control->setWordSelectionEnabled(mode == SelectWords);
1120 emit mouseSelectionModeChanged(mode);
1125 \qmlproperty bool QtQuick1::TextEdit::readOnly
1127 Whether the user can interact with the TextEdit item. If this
1128 property is set to true the text cannot be edited by user interaction.
1130 By default this property is false.
1132 void QDeclarative1TextEdit::setReadOnly(bool r)
1134 Q_D(QDeclarative1TextEdit);
1135 if (r == isReadOnly())
1138 setFlag(QGraphicsItem::ItemAcceptsInputMethod, !r);
1140 Qt::TextInteractionFlags flags = Qt::LinksAccessibleByMouse;
1141 if (d->selectByMouse)
1142 flags = flags | Qt::TextSelectableByMouse;
1144 flags = flags | Qt::TextSelectableByKeyboard | Qt::TextEditable;
1145 d->control->setTextInteractionFlags(flags);
1147 d->control->moveCursor(QTextCursor::End);
1149 emit readOnlyChanged(r);
1152 bool QDeclarative1TextEdit::isReadOnly() const
1154 Q_D(const QDeclarative1TextEdit);
1155 return !(d->control->textInteractionFlags() & Qt::TextEditable);
1159 Sets how the text edit should interact with user input to the given
1162 void QDeclarative1TextEdit::setTextInteractionFlags(Qt::TextInteractionFlags flags)
1164 Q_D(QDeclarative1TextEdit);
1165 d->control->setTextInteractionFlags(flags);
1169 Returns the flags specifying how the text edit should interact
1172 Qt::TextInteractionFlags QDeclarative1TextEdit::textInteractionFlags() const
1174 Q_D(const QDeclarative1TextEdit);
1175 return d->control->textInteractionFlags();
1179 \qmlproperty rectangle QtQuick1::TextEdit::cursorRectangle
1181 The rectangle where the text cursor is rendered
1182 within the text edit. Read-only.
1184 QRect QDeclarative1TextEdit::cursorRectangle() const
1186 Q_D(const QDeclarative1TextEdit);
1187 return d->control->cursorRect().toRect().translated(0,d->yoff);
1193 Handles the given \a event.
1195 bool QDeclarative1TextEdit::event(QEvent *event)
1197 Q_D(QDeclarative1TextEdit);
1198 if (event->type() == QEvent::ShortcutOverride) {
1199 d->control->processEvent(event, QPointF(0, -d->yoff));
1200 return event->isAccepted();
1202 return QDeclarative1PaintedItem::event(event);
1207 Handles the given key \a event.
1209 void QDeclarative1TextEdit::keyPressEvent(QKeyEvent *event)
1211 Q_D(QDeclarative1TextEdit);
1212 keyPressPreHandler(event);
1213 if (!event->isAccepted())
1214 d->control->processEvent(event, QPointF(0, -d->yoff));
1215 if (!event->isAccepted())
1216 QDeclarative1PaintedItem::keyPressEvent(event);
1221 Handles the given key \a event.
1223 void QDeclarative1TextEdit::keyReleaseEvent(QKeyEvent *event)
1225 Q_D(QDeclarative1TextEdit);
1226 keyReleasePreHandler(event);
1227 if (!event->isAccepted())
1228 d->control->processEvent(event, QPointF(0, -d->yoff));
1229 if (!event->isAccepted())
1230 QDeclarative1PaintedItem::keyReleaseEvent(event);
1233 void QDeclarative1TextEditPrivate::focusChanged(bool hasFocus)
1235 Q_Q(QDeclarative1TextEdit);
1236 q->setCursorVisible(hasFocus && scene && scene->hasFocus());
1237 QDeclarativeItemPrivate::focusChanged(hasFocus);
1241 \qmlmethod void QtQuick1::TextEdit::deselect()
1244 Removes active text selection.
1246 void QDeclarative1TextEdit::deselect()
1248 Q_D(QDeclarative1TextEdit);
1249 QTextCursor c = d->control->textCursor();
1251 d->control->setTextCursor(c);
1255 \qmlmethod void QtQuick1::TextEdit::selectAll()
1257 Causes all text to be selected.
1259 void QDeclarative1TextEdit::selectAll()
1261 Q_D(QDeclarative1TextEdit);
1262 d->control->selectAll();
1266 \qmlmethod void QtQuick1::TextEdit::selectWord()
1268 Causes the word closest to the current cursor position to be selected.
1270 void QDeclarative1TextEdit::selectWord()
1272 Q_D(QDeclarative1TextEdit);
1273 QTextCursor c = d->control->textCursor();
1274 c.select(QTextCursor::WordUnderCursor);
1275 d->control->setTextCursor(c);
1279 \qmlmethod void QtQuick1::TextEdit::select(int start, int end)
1281 Causes the text from \a start to \a end to be selected.
1283 If either start or end is out of range, the selection is not changed.
1285 After calling this, selectionStart will become the lesser
1286 and selectionEnd will become the greater (regardless of the order passed
1289 \sa selectionStart, selectionEnd
1291 void QDeclarative1TextEdit::select(int start, int end)
1293 Q_D(QDeclarative1TextEdit);
1294 if (start < 0 || end < 0 || start > d->text.length() || end > d->text.length())
1296 QTextCursor cursor = d->control->textCursor();
1297 cursor.beginEditBlock();
1298 cursor.setPosition(start, QTextCursor::MoveAnchor);
1299 cursor.setPosition(end, QTextCursor::KeepAnchor);
1300 cursor.endEditBlock();
1301 d->control->setTextCursor(cursor);
1304 updateSelectionMarkers();
1308 \qmlmethod void QtQuick1::TextEdit::isRightToLeft(int start, int end)
1310 Returns true if the natural reading direction of the editor text
1311 found between positions \a start and \a end is right to left.
1313 bool QDeclarative1TextEdit::isRightToLeft(int start, int end)
1315 Q_D(QDeclarative1TextEdit);
1317 qmlInfo(this) << "isRightToLeft(start, end) called with the end property being smaller than the start.";
1320 return d->text.mid(start, end - start).isRightToLeft();
1324 #ifndef QT_NO_CLIPBOARD
1326 \qmlmethod QtQuick1::TextEdit::cut()
1328 Moves the currently selected text to the system clipboard.
1330 void QDeclarative1TextEdit::cut()
1332 Q_D(QDeclarative1TextEdit);
1337 \qmlmethod QtQuick1::TextEdit::copy()
1339 Copies the currently selected text to the system clipboard.
1341 void QDeclarative1TextEdit::copy()
1343 Q_D(QDeclarative1TextEdit);
1348 \qmlmethod QtQuick1::TextEdit::paste()
1350 Replaces the currently selected text by the contents of the system clipboard.
1352 void QDeclarative1TextEdit::paste()
1354 Q_D(QDeclarative1TextEdit);
1355 d->control->paste();
1357 #endif // QT_NO_CLIPBOARD
1361 Handles the given mouse \a event.
1363 void QDeclarative1TextEdit::mousePressEvent(QGraphicsSceneMouseEvent *event)
1365 Q_D(QDeclarative1TextEdit);
1366 if (d->focusOnPress){
1367 bool hadActiveFocus = hasActiveFocus();
1369 if (d->showInputPanelOnFocus) {
1370 if (hasActiveFocus() && hadActiveFocus && !isReadOnly()) {
1371 // re-open input panel on press if already focused
1372 openSoftwareInputPanel();
1374 } else { // show input panel on click
1375 if (hasActiveFocus() && !hadActiveFocus) {
1376 d->clickCausedFocus = true;
1381 d->control->processEvent(event, QPointF(0, -d->yoff));
1382 if (!event->isAccepted())
1383 QDeclarative1PaintedItem::mousePressEvent(event);
1388 Handles the given mouse \a event.
1390 void QDeclarative1TextEdit::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
1392 Q_D(QDeclarative1TextEdit);
1393 d->control->processEvent(event, QPointF(0, -d->yoff));
1394 if (!d->showInputPanelOnFocus) { // input panel on click
1395 if (d->focusOnPress && !isReadOnly() && boundingRect().contains(event->pos())) {
1396 if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1397 if (view->scene() && view->scene() == scene()) {
1398 qt_widget_private(view)->handleSoftwareInputPanel(event->button(), d->clickCausedFocus);
1403 d->clickCausedFocus = false;
1405 if (!event->isAccepted())
1406 QDeclarative1PaintedItem::mouseReleaseEvent(event);
1411 Handles the given mouse \a event.
1413 void QDeclarative1TextEdit::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
1415 Q_D(QDeclarative1TextEdit);
1417 d->control->processEvent(event, QPointF(0, -d->yoff));
1418 if (!event->isAccepted())
1419 QDeclarative1PaintedItem::mouseDoubleClickEvent(event);
1425 Handles the given mouse \a event.
1427 void QDeclarative1TextEdit::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
1429 Q_D(QDeclarative1TextEdit);
1430 d->control->processEvent(event, QPointF(0, -d->yoff));
1431 if (!event->isAccepted())
1432 QDeclarative1PaintedItem::mouseMoveEvent(event);
1437 Handles the given input method \a event.
1439 void QDeclarative1TextEdit::inputMethodEvent(QInputMethodEvent *event)
1441 Q_D(QDeclarative1TextEdit);
1442 const bool wasComposing = isInputMethodComposing();
1443 d->control->processEvent(event, QPointF(0, -d->yoff));
1444 if (wasComposing != isInputMethodComposing())
1445 emit inputMethodComposingChanged();
1450 Returns the value of the given \a property.
1452 QVariant QDeclarative1TextEdit::inputMethodQuery(Qt::InputMethodQuery property) const
1454 Q_D(const QDeclarative1TextEdit);
1455 return d->control->inputMethodQuery(property);
1459 Draws the contents of the text edit using the given \a painter within
1460 the given \a bounds.
1462 void QDeclarative1TextEdit::drawContents(QPainter *painter, const QRect &bounds)
1464 Q_D(QDeclarative1TextEdit);
1466 painter->setRenderHint(QPainter::TextAntialiasing, true);
1467 painter->translate(0,d->yoff);
1469 d->control->drawContents(painter, bounds.translated(0,-d->yoff));
1471 painter->translate(0,-d->yoff);
1474 void QDeclarative1TextEdit::updateImgCache(const QRectF &rf)
1476 Q_D(const QDeclarative1TextEdit);
1478 if (!rf.isValid()) {
1479 r = QRect(0,0,INT_MAX,INT_MAX);
1482 if (r.height() > INT_MAX/2) {
1483 // Take care of overflow when translating "everything"
1484 r.setTop(r.y() + d->yoff);
1485 r.setBottom(INT_MAX/2);
1487 r = r.translated(0,d->yoff);
1495 \qmlproperty bool QtQuick1::TextEdit::smooth
1497 This property holds whether the text is smoothly scaled or transformed.
1499 Smooth filtering gives better visual quality, but is slower. If
1500 the item is displayed at its natural size, this property has no visual or
1503 \note Generally scaling artifacts are only visible if the item is stationary on
1504 the screen. A common pattern when animating an item is to disable smooth
1505 filtering at the beginning of the animation and reenable it at the conclusion.
1509 \qmlproperty bool QtQuick1::TextEdit::canPaste
1512 Returns true if the TextEdit is writable and the content of the clipboard is
1513 suitable for pasting into the TextEdit.
1515 bool QDeclarative1TextEdit::canPaste() const
1517 Q_D(const QDeclarative1TextEdit);
1522 \qmlproperty bool QtQuick1::TextEdit::inputMethodComposing
1526 This property holds whether the TextEdit has partial text input from an
1529 While it is composing an input method may rely on mouse or key events from
1530 the TextEdit to edit or commit the partial text. This property can be used
1531 to determine when to disable events handlers that may interfere with the
1532 correct operation of an input method.
1534 bool QDeclarative1TextEdit::isInputMethodComposing() const
1536 Q_D(const QDeclarative1TextEdit);
1537 if (QTextLayout *layout = d->control->textCursor().block().layout())
1538 return layout->preeditAreaText().length() > 0;
1542 void QDeclarative1TextEditPrivate::init()
1544 Q_Q(QDeclarative1TextEdit);
1546 q->setSmooth(smooth);
1547 q->setAcceptedMouseButtons(Qt::LeftButton);
1548 q->setFlag(QGraphicsItem::ItemHasNoContents, false);
1549 q->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
1551 control = new QWidgetTextControl(q);
1552 control->setIgnoreUnusedNavigationEvents(true);
1553 control->setTextInteractionFlags(Qt::TextInteractionFlags(Qt::LinksAccessibleByMouse | Qt::TextSelectableByKeyboard | Qt::TextEditable));
1554 control->setDragEnabled(false);
1556 // QWidgetTextControl follows the default text color
1557 // defined by the platform, declarative text
1558 // should be black by default
1559 QPalette pal = control->palette();
1560 if (pal.color(QPalette::Text) != color) {
1561 pal.setColor(QPalette::Text, color);
1562 control->setPalette(pal);
1565 QObject::connect(control, SIGNAL(updateRequest(QRectF)), q, SLOT(updateImgCache(QRectF)));
1567 QObject::connect(control, SIGNAL(textChanged()), q, SLOT(q_textChanged()));
1568 QObject::connect(control, SIGNAL(selectionChanged()), q, SIGNAL(selectionChanged()));
1569 QObject::connect(control, SIGNAL(selectionChanged()), q, SLOT(updateSelectionMarkers()));
1570 QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SLOT(updateSelectionMarkers()));
1571 QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorPositionChanged()));
1572 QObject::connect(control, SIGNAL(microFocusChanged()), q, SLOT(moveCursorDelegate()));
1573 QObject::connect(control, SIGNAL(linkActivated(QString)), q, SIGNAL(linkActivated(QString)));
1574 #ifndef QT_NO_CLIPBOARD
1575 QObject::connect(q, SIGNAL(readOnlyChanged(bool)), q, SLOT(q_canPasteChanged()));
1576 QObject::connect(QApplication::clipboard(), SIGNAL(dataChanged()), q, SLOT(q_canPasteChanged()));
1577 canPaste = control->canPaste();
1580 document = control->document();
1581 document->setDefaultFont(font);
1582 document->setDocumentMargin(textMargin);
1583 document->setUndoRedoEnabled(false); // flush undo buffer.
1584 document->setUndoRedoEnabled(true);
1585 updateDefaultTextOption();
1588 void QDeclarative1TextEdit::q_textChanged()
1590 Q_D(QDeclarative1TextEdit);
1592 d->rightToLeftText = d->document->begin().layout()->engine()->isRightToLeft();
1593 d->determineHorizontalAlignment();
1594 d->updateDefaultTextOption();
1597 emit textChanged(d->text);
1600 void QDeclarative1TextEdit::moveCursorDelegate()
1602 Q_D(QDeclarative1TextEdit);
1603 d->determineHorizontalAlignment();
1605 emit cursorRectangleChanged();
1608 QRectF cursorRect = cursorRectangle();
1609 d->cursor->setX(cursorRect.x());
1610 d->cursor->setY(cursorRect.y());
1613 void QDeclarative1TextEdit::updateSelectionMarkers()
1615 Q_D(QDeclarative1TextEdit);
1616 if(d->lastSelectionStart != d->control->textCursor().selectionStart()){
1617 d->lastSelectionStart = d->control->textCursor().selectionStart();
1618 emit selectionStartChanged();
1620 if(d->lastSelectionEnd != d->control->textCursor().selectionEnd()){
1621 d->lastSelectionEnd = d->control->textCursor().selectionEnd();
1622 emit selectionEndChanged();
1626 QRectF QDeclarative1TextEdit::boundingRect() const
1628 Q_D(const QDeclarative1TextEdit);
1629 QRectF r = QDeclarative1PaintedItem::boundingRect();
1630 int cursorWidth = 1;
1632 cursorWidth = d->cursor->width();
1633 if(!d->document->isEmpty())
1634 cursorWidth += 3;// ### Need a better way of accounting for space between char and cursor
1636 // Could include font max left/right bearings to either side of rectangle.
1638 r.setRight(r.right() + cursorWidth);
1639 return r.translated(0,d->yoff);
1642 qreal QDeclarative1TextEditPrivate::implicitWidth() const
1644 Q_Q(const QDeclarative1TextEdit);
1645 if (!requireImplicitWidth) {
1646 // We don't calculate implicitWidth unless it is required.
1647 // We need to force a size update now to ensure implicitWidth is calculated
1648 const_cast<QDeclarative1TextEditPrivate*>(this)->requireImplicitWidth = true;
1649 const_cast<QDeclarative1TextEdit*>(q)->updateSize();
1651 return mImplicitWidth;
1654 //### we should perhaps be a bit smarter here -- depending on what has changed, we shouldn't
1655 // need to do all the calculations each time
1656 void QDeclarative1TextEdit::updateSize()
1658 Q_D(QDeclarative1TextEdit);
1659 if (isComponentComplete()) {
1660 qreal naturalWidth = d->mImplicitWidth;
1661 // ### assumes that if the width is set, the text will fill to edges
1662 // ### (unless wrap is false, then clipping will occur)
1664 if (!d->requireImplicitWidth) {
1665 emit implicitWidthChanged();
1666 // if the implicitWidth is used, then updateSize() has already been called (recursively)
1667 if (d->requireImplicitWidth)
1670 if (d->requireImplicitWidth) {
1671 d->document->setTextWidth(-1);
1672 naturalWidth = d->document->idealWidth();
1674 if (d->document->textWidth() != width())
1675 d->document->setTextWidth(width());
1677 d->document->setTextWidth(-1);
1679 QFontMetrics fm = QFontMetrics(d->font);
1681 dy -= (int)d->document->size().height();
1684 if (heightValid()) {
1685 if (d->vAlign == AlignBottom)
1687 else if (d->vAlign == AlignVCenter)
1694 if (nyoff != d->yoff) {
1695 prepareGeometryChange();
1698 setBaselineOffset(fm.ascent() + d->yoff + d->textMargin);
1700 //### need to comfirm cost of always setting these
1701 int newWidth = qCeil(d->document->idealWidth());
1702 if (!widthValid() && d->document->textWidth() != newWidth)
1703 d->document->setTextWidth(newWidth); // ### Text does not align if width is not set (QTextDoc bug)
1704 // ### Setting the implicitWidth triggers another updateSize(), and unless there are bindings nothing has changed.
1706 setImplicitWidth(newWidth);
1707 else if (d->requireImplicitWidth)
1708 setImplicitWidth(naturalWidth);
1709 qreal newHeight = d->document->isEmpty() ? fm.height() : (int)d->document->size().height();
1710 setImplicitHeight(newHeight);
1712 d->paintedSize = QSize(newWidth, newHeight);
1713 setContentsSize(d->paintedSize);
1714 emit paintedSizeChanged();
1721 void QDeclarative1TextEdit::updateTotalLines()
1723 Q_D(QDeclarative1TextEdit);
1727 for (QTextBlock it = d->document->begin(); it != d->document->end(); it = it.next()) {
1728 QTextLayout *layout = it.layout();
1731 subLines += layout->lineCount()-1;
1734 int newTotalLines = d->document->lineCount() + subLines;
1735 if (d->lineCount != newTotalLines) {
1736 d->lineCount = newTotalLines;
1737 emit lineCountChanged();
1741 void QDeclarative1TextEditPrivate::updateDefaultTextOption()
1743 Q_Q(QDeclarative1TextEdit);
1744 QTextOption opt = document->defaultTextOption();
1745 int oldAlignment = opt.alignment();
1747 QDeclarative1TextEdit::HAlignment horizontalAlignment = q->effectiveHAlign();
1748 if (rightToLeftText) {
1749 if (horizontalAlignment == QDeclarative1TextEdit::AlignLeft)
1750 horizontalAlignment = QDeclarative1TextEdit::AlignRight;
1751 else if (horizontalAlignment == QDeclarative1TextEdit::AlignRight)
1752 horizontalAlignment = QDeclarative1TextEdit::AlignLeft;
1754 opt.setAlignment((Qt::Alignment)(int)(horizontalAlignment | vAlign));
1756 QTextOption::WrapMode oldWrapMode = opt.wrapMode();
1757 opt.setWrapMode(QTextOption::WrapMode(wrapMode));
1759 if (oldWrapMode == opt.wrapMode() && oldAlignment == opt.alignment())
1761 document->setDefaultTextOption(opt);
1766 \qmlmethod void QtQuick1::TextEdit::openSoftwareInputPanel()
1768 Opens software input panels like virtual keyboards for typing, useful for
1769 customizing when you want the input keyboard to be shown and hidden in
1772 By default the opening of input panels follows the platform style.
1773 The panels are automatically opened when TextEdit element gains active focus. Input panels are
1774 always closed if no editor has active focus.
1776 You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1777 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1778 the behavior you want.
1780 Only relevant on platforms, which provide virtual keyboards.
1786 text: "Hello world!"
1787 activeFocusOnPress: false
1789 anchors.fill: parent
1791 if (!textEdit.activeFocus) {
1792 textEdit.forceActiveFocus();
1793 textEdit.openSoftwareInputPanel();
1795 textEdit.focus = false;
1798 onPressAndHold: textEdit.closeSoftwareInputPanel();
1803 void QDeclarative1TextEdit::openSoftwareInputPanel()
1806 if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1807 if (view->scene() && view->scene() == scene()) {
1808 qApp->inputPanel()->show();
1815 \qmlmethod void QtQuick1::TextEdit::closeSoftwareInputPanel()
1817 Closes a software input panel like a virtual keyboard shown on the screen, useful
1818 for customizing when you want the input keyboard to be shown and hidden in
1821 By default the opening of input panels follows the platform style.
1822 The panels are automatically opened when TextEdit element gains active focus. Input panels are
1823 always closed if no editor has active focus.
1825 You can disable the automatic behavior by setting the property \c activeFocusOnPress to false
1826 and use functions openSoftwareInputPanel() and closeSoftwareInputPanel() to implement
1827 the behavior you want.
1829 Only relevant on platforms, which provide virtual keyboards.
1835 text: "Hello world!"
1836 activeFocusOnPress: false
1838 anchors.fill: parent
1840 if (!textEdit.activeFocus) {
1841 textEdit.forceActiveFocus();
1842 textEdit.openSoftwareInputPanel();
1844 textEdit.focus = false;
1847 onPressAndHold: textEdit.closeSoftwareInputPanel();
1852 void QDeclarative1TextEdit::closeSoftwareInputPanel()
1855 if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) {
1856 if (view->scene() && view->scene() == scene()) {
1857 qApp->inputPanel()->hide();
1863 void QDeclarative1TextEdit::focusInEvent(QFocusEvent *event)
1865 Q_D(const QDeclarative1TextEdit);
1866 if (d->showInputPanelOnFocus) {
1867 if (d->focusOnPress && !isReadOnly()) {
1868 openSoftwareInputPanel();
1871 QDeclarative1PaintedItem::focusInEvent(event);
1874 void QDeclarative1TextEdit::q_canPasteChanged()
1876 Q_D(QDeclarative1TextEdit);
1877 bool old = d->canPaste;
1878 d->canPaste = d->control->canPaste();
1879 if(old!=d->canPaste)
1880 emit canPasteChanged();