5273e16ab58f4eec11535d69f1da8e38c9c0439c
[profile/ivi/qtbase.git] / src / widgets / widgets / qtextedit.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qtextedit_p.h"
43 #include "qlineedit.h"
44 #include "qtextbrowser.h"
45
46 #ifndef QT_NO_TEXTEDIT
47 #include <qfont.h>
48 #include <qpainter.h>
49 #include <qevent.h>
50 #include <qdebug.h>
51 #include <qdrag.h>
52 #include <qclipboard.h>
53 #include <qmenu.h>
54 #include <qstyle.h>
55 #include <qtimer.h>
56 #include "private/qtextdocumentlayout_p.h"
57 #include "qtextdocument.h"
58 #include "private/qtextdocument_p.h"
59 #include "qtextlist.h"
60 #include "private/qwidgettextcontrol_p.h"
61
62 #include <qtextformat.h>
63 #include <qdatetime.h>
64 #include <qapplication.h>
65 #include <limits.h>
66 #include <qtexttable.h>
67 #include <qvariant.h>
68
69 #endif
70
71 QT_BEGIN_NAMESPACE
72
73
74 #ifndef QT_NO_TEXTEDIT
75 static inline bool shouldEnableInputMethod(QTextEdit *textedit)
76 {
77     return !textedit->isReadOnly();
78 }
79
80 class QTextEditControl : public QWidgetTextControl
81 {
82 public:
83     inline QTextEditControl(QObject *parent) : QWidgetTextControl(parent) {}
84
85     virtual QMimeData *createMimeDataFromSelection() const {
86         QTextEdit *ed = qobject_cast<QTextEdit *>(parent());
87         if (!ed)
88             return QWidgetTextControl::createMimeDataFromSelection();
89         return ed->createMimeDataFromSelection();
90     }
91     virtual bool canInsertFromMimeData(const QMimeData *source) const {
92         QTextEdit *ed = qobject_cast<QTextEdit *>(parent());
93         if (!ed)
94             return QWidgetTextControl::canInsertFromMimeData(source);
95         return ed->canInsertFromMimeData(source);
96     }
97     virtual void insertFromMimeData(const QMimeData *source) {
98         QTextEdit *ed = qobject_cast<QTextEdit *>(parent());
99         if (!ed)
100             QWidgetTextControl::insertFromMimeData(source);
101         else
102             ed->insertFromMimeData(source);
103     }
104 };
105
106 QTextEditPrivate::QTextEditPrivate()
107     : control(0),
108       autoFormatting(QTextEdit::AutoNone), tabChangesFocus(false),
109       lineWrap(QTextEdit::WidgetWidth), lineWrapColumnOrWidth(0),
110       wordWrap(QTextOption::WrapAtWordBoundaryOrAnywhere), clickCausedFocus(0),
111       textFormat(Qt::AutoText)
112 {
113     ignoreAutomaticScrollbarAdjustment = false;
114     preferRichText = false;
115     showCursorOnInitialShow = true;
116     inDrag = false;
117 }
118
119 void QTextEditPrivate::createAutoBulletList()
120 {
121     QTextCursor cursor = control->textCursor();
122     cursor.beginEditBlock();
123
124     QTextBlockFormat blockFmt = cursor.blockFormat();
125
126     QTextListFormat listFmt;
127     listFmt.setStyle(QTextListFormat::ListDisc);
128     listFmt.setIndent(blockFmt.indent() + 1);
129
130     blockFmt.setIndent(0);
131     cursor.setBlockFormat(blockFmt);
132
133     cursor.createList(listFmt);
134
135     cursor.endEditBlock();
136     control->setTextCursor(cursor);
137 }
138
139 void QTextEditPrivate::init(const QString &html)
140 {
141     Q_Q(QTextEdit);
142     control = new QTextEditControl(q);
143     control->setPalette(q->palette());
144
145     QObject::connect(control, SIGNAL(microFocusChanged()), q, SLOT(updateMicroFocus()));
146     QObject::connect(control, SIGNAL(documentSizeChanged(QSizeF)), q, SLOT(_q_adjustScrollbars()));
147     QObject::connect(control, SIGNAL(updateRequest(QRectF)), q, SLOT(_q_repaintContents(QRectF)));
148     QObject::connect(control, SIGNAL(visibilityRequest(QRectF)), q, SLOT(_q_ensureVisible(QRectF)));
149     QObject::connect(control, SIGNAL(currentCharFormatChanged(QTextCharFormat)),
150                      q, SLOT(_q_currentCharFormatChanged(QTextCharFormat)));
151
152     QObject::connect(control, SIGNAL(textChanged()), q, SIGNAL(textChanged()));
153     QObject::connect(control, SIGNAL(undoAvailable(bool)), q, SIGNAL(undoAvailable(bool)));
154     QObject::connect(control, SIGNAL(redoAvailable(bool)), q, SIGNAL(redoAvailable(bool)));
155     QObject::connect(control, SIGNAL(copyAvailable(bool)), q, SIGNAL(copyAvailable(bool)));
156     QObject::connect(control, SIGNAL(selectionChanged()), q, SIGNAL(selectionChanged()));
157     QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorPositionChanged()));
158
159     QObject::connect(control, SIGNAL(textChanged()), q, SLOT(updateMicroFocus()));
160
161     QTextDocument *doc = control->document();
162     // set a null page size initially to avoid any relayouting until the textedit
163     // is shown. relayoutDocument() will take care of setting the page size to the
164     // viewport dimensions later.
165     doc->setPageSize(QSize(0, 0));
166     doc->documentLayout()->setPaintDevice(viewport);
167     doc->setDefaultFont(q->font());
168     doc->setUndoRedoEnabled(false); // flush undo buffer.
169     doc->setUndoRedoEnabled(true);
170
171     if (!html.isEmpty())
172         control->setHtml(html);
173
174     hbar->setSingleStep(20);
175     vbar->setSingleStep(20);
176
177     viewport->setBackgroundRole(QPalette::Base);
178     q->setAcceptDrops(true);
179     q->setFocusPolicy(Qt::WheelFocus);
180     q->setAttribute(Qt::WA_KeyCompression);
181     q->setAttribute(Qt::WA_InputMethodEnabled);
182
183 #ifndef QT_NO_CURSOR
184     viewport->setCursor(Qt::IBeamCursor);
185 #endif
186 #ifdef Q_WS_WIN
187     setSingleFingerPanEnabled(true);
188 #endif
189 }
190
191 void QTextEditPrivate::_q_repaintContents(const QRectF &contentsRect)
192 {
193     if (!contentsRect.isValid()) {
194         viewport->update();
195         return;
196     }
197     const int xOffset = horizontalOffset();
198     const int yOffset = verticalOffset();
199     const QRectF visibleRect(xOffset, yOffset, viewport->width(), viewport->height());
200
201     QRect r = contentsRect.intersected(visibleRect).toAlignedRect();
202     if (r.isEmpty())
203         return;
204
205     r.translate(-xOffset, -yOffset);
206     viewport->update(r);
207 }
208
209 void QTextEditPrivate::pageUpDown(QTextCursor::MoveOperation op, QTextCursor::MoveMode moveMode)
210 {
211     QTextCursor cursor = control->textCursor();
212     bool moved = false;
213     qreal lastY = control->cursorRect(cursor).top();
214     qreal distance = 0;
215     // move using movePosition to keep the cursor's x
216     do {
217         qreal y = control->cursorRect(cursor).top();
218         distance += qAbs(y - lastY);
219         lastY = y;
220         moved = cursor.movePosition(op, moveMode);
221     } while (moved && distance < viewport->height());
222
223     if (moved) {
224         if (op == QTextCursor::Up) {
225             cursor.movePosition(QTextCursor::Down, moveMode);
226             vbar->triggerAction(QAbstractSlider::SliderPageStepSub);
227         } else {
228             cursor.movePosition(QTextCursor::Up, moveMode);
229             vbar->triggerAction(QAbstractSlider::SliderPageStepAdd);
230         }
231     }
232     control->setTextCursor(cursor);
233 }
234
235 #ifndef QT_NO_SCROLLBAR
236 static QSize documentSize(QWidgetTextControl *control)
237 {
238     QTextDocument *doc = control->document();
239     QAbstractTextDocumentLayout *layout = doc->documentLayout();
240
241     QSize docSize;
242
243     if (QTextDocumentLayout *tlayout = qobject_cast<QTextDocumentLayout *>(layout)) {
244         docSize = tlayout->dynamicDocumentSize().toSize();
245         int percentageDone = tlayout->layoutStatus();
246         // extrapolate height
247         if (percentageDone > 0)
248             docSize.setHeight(docSize.height() * 100 / percentageDone);
249     } else {
250         docSize = layout->documentSize().toSize();
251     }
252
253     return docSize;
254 }
255
256 void QTextEditPrivate::_q_adjustScrollbars()
257 {
258     if (ignoreAutomaticScrollbarAdjustment)
259         return;
260     ignoreAutomaticScrollbarAdjustment = true; // avoid recursion, #106108
261
262     QSize viewportSize = viewport->size();
263     QSize docSize = documentSize(control);
264
265     // due to the recursion guard we have to repeat this step a few times,
266     // as adding/removing a scroll bar will cause the document or viewport
267     // size to change
268     // ideally we should loop until the viewport size and doc size stabilize,
269     // but in corner cases they might fluctuate, so we need to limit the
270     // number of iterations
271     for (int i = 0; i < 4; ++i) {
272         hbar->setRange(0, docSize.width() - viewportSize.width());
273         hbar->setPageStep(viewportSize.width());
274
275         vbar->setRange(0, docSize.height() - viewportSize.height());
276         vbar->setPageStep(viewportSize.height());
277
278         // if we are in left-to-right mode widening the document due to
279         // lazy layouting does not require a repaint. If in right-to-left
280         // the scroll bar has the value zero and it visually has the maximum
281         // value (it is visually at the right), then widening the document
282         // keeps it at value zero but visually adjusts it to the new maximum
283         // on the right, hence we need an update.
284         if (q_func()->isRightToLeft())
285             viewport->update();
286
287         _q_showOrHideScrollBars();
288
289         const QSize oldViewportSize = viewportSize;
290         const QSize oldDocSize = docSize;
291
292         // make sure the document is layouted if the viewport width changes
293         viewportSize = viewport->size();
294         if (viewportSize.width() != oldViewportSize.width())
295             relayoutDocument();
296
297         docSize = documentSize(control);
298         if (viewportSize == oldViewportSize && docSize == oldDocSize)
299             break;
300     }
301     ignoreAutomaticScrollbarAdjustment = false;
302 }
303 #endif
304
305 // rect is in content coordinates
306 void QTextEditPrivate::_q_ensureVisible(const QRectF &_rect)
307 {
308     const QRect rect = _rect.toRect();
309     if ((vbar->isVisible() && vbar->maximum() < rect.bottom())
310         || (hbar->isVisible() && hbar->maximum() < rect.right()))
311         _q_adjustScrollbars();
312     const int visibleWidth = viewport->width();
313     const int visibleHeight = viewport->height();
314     const bool rtl = q_func()->isRightToLeft();
315
316     if (rect.x() < horizontalOffset()) {
317         if (rtl)
318             hbar->setValue(hbar->maximum() - rect.x());
319         else
320             hbar->setValue(rect.x());
321     } else if (rect.x() + rect.width() > horizontalOffset() + visibleWidth) {
322         if (rtl)
323             hbar->setValue(hbar->maximum() - (rect.x() + rect.width() - visibleWidth));
324         else
325             hbar->setValue(rect.x() + rect.width() - visibleWidth);
326     }
327
328     if (rect.y() < verticalOffset())
329         vbar->setValue(rect.y());
330     else if (rect.y() + rect.height() > verticalOffset() + visibleHeight)
331         vbar->setValue(rect.y() + rect.height() - visibleHeight);
332 }
333
334 /*!
335     \class QTextEdit
336     \brief The QTextEdit class provides a widget that is used to edit and display
337     both plain and rich text.
338
339     \ingroup richtext-processing
340     \inmodule QtWidgets
341
342     \tableofcontents
343
344     \section1 Introduction and Concepts
345
346     QTextEdit is an advanced WYSIWYG viewer/editor supporting rich
347     text formatting using HTML-style tags. It is optimized to handle
348     large documents and to respond quickly to user input.
349
350     QTextEdit works on paragraphs and characters. A paragraph is a
351     formatted string which is word-wrapped to fit into the width of
352     the widget. By default when reading plain text, one newline
353     signifies a paragraph. A document consists of zero or more
354     paragraphs. The words in the paragraph are aligned in accordance
355     with the paragraph's alignment. Paragraphs are separated by hard
356     line breaks. Each character within a paragraph has its own
357     attributes, for example, font and color.
358
359     QTextEdit can display images, lists and tables. If the text is
360     too large to view within the text edit's viewport, scroll bars will
361     appear. The text edit can load both plain text and HTML files (a
362     subset of HTML 3.2 and 4).
363
364     If you just need to display a small piece of rich text use QLabel.
365
366     The rich text support in Qt is designed to provide a fast, portable and
367     efficient way to add reasonable online help facilities to
368     applications, and to provide a basis for rich text editors. If
369     you find the HTML support insufficient for your needs you may consider
370     the use of QtWebKit, which provides a full-featured web browser
371     widget.
372
373     The shape of the mouse cursor on a QTextEdit is Qt::IBeamCursor by default.
374     It can be changed through the viewport()'s cursor property.
375
376     \section1 Using QTextEdit as a Display Widget
377
378     QTextEdit can display a large HTML subset, including tables and
379     images.
380
381     The text is set or replaced using setHtml() which deletes any
382     existing text and replaces it with the text passed in the
383     setHtml() call. If you call setHtml() with legacy HTML, and then
384     call toHtml(), the text that is returned may have different markup,
385     but will render the same. The entire text can be deleted with clear().
386
387     Text itself can be inserted using the QTextCursor class or using the
388     convenience functions insertHtml(), insertPlainText(), append() or
389     paste(). QTextCursor is also able to insert complex objects like tables
390     or lists into the document, and it deals with creating selections
391     and applying changes to selected text.
392
393     By default the text edit wraps words at whitespace to fit within
394     the text edit widget. The setLineWrapMode() function is used to
395     specify the kind of line wrap you want, or \l NoWrap if you don't
396     want any wrapping. Call setLineWrapMode() to set a fixed pixel width
397     \l FixedPixelWidth, or character column (e.g. 80 column) \l
398     FixedColumnWidth with the pixels or columns specified with
399     setLineWrapColumnOrWidth(). If you use word wrap to the widget's width
400     \l WidgetWidth, you can specify whether to break on whitespace or
401     anywhere with setWordWrapMode().
402
403     The find() function can be used to find and select a given string
404     within the text.
405
406     If you want to limit the total number of paragraphs in a QTextEdit,
407     as it is for example open useful in a log viewer, then you can use
408     QTextDocument's maximumBlockCount property for that.
409
410     \section2 Read-only Key Bindings
411
412     When QTextEdit is used read-only the key bindings are limited to
413     navigation, and text may only be selected with the mouse:
414     \table
415     \header \i Keypresses \i Action
416     \row \i Up        \i Moves one line up.
417     \row \i Down        \i Moves one line down.
418     \row \i Left        \i Moves one character to the left.
419     \row \i Right        \i Moves one character to the right.
420     \row \i PageUp        \i Moves one (viewport) page up.
421     \row \i PageDown        \i Moves one (viewport) page down.
422     \row \i Home        \i Moves to the beginning of the text.
423     \row \i End                \i Moves to the end of the text.
424     \row \i Alt+Wheel
425          \i Scrolls the page horizontally (the Wheel is the mouse wheel).
426     \row \i Ctrl+Wheel        \i Zooms the text.
427     \row \i Ctrl+A            \i Selects all text.
428     \endtable
429
430     The text edit may be able to provide some meta-information. For
431     example, the documentTitle() function will return the text from
432     within HTML \c{<title>} tags.
433
434     \section1 Using QTextEdit as an Editor
435
436     All the information about using QTextEdit as a display widget also
437     applies here.
438
439     The current char format's attributes are set with setFontItalic(),
440     setFontWeight(), setFontUnderline(), setFontFamily(),
441     setFontPointSize(), setTextColor() and setCurrentFont(). The current
442     paragraph's alignment is set with setAlignment().
443
444     Selection of text is handled by the QTextCursor class, which provides
445     functionality for creating selections, retrieving the text contents or
446     deleting selections. You can retrieve the object that corresponds with
447     the user-visible cursor using the textCursor() method. If you want to set
448     a selection in QTextEdit just create one on a QTextCursor object and
449     then make that cursor the visible cursor using setTextCursor(). The selection
450     can be copied to the clipboard with copy(), or cut to the clipboard with
451     cut(). The entire text can be selected using selectAll().
452
453     When the cursor is moved and the underlying formatting attributes change,
454     the currentCharFormatChanged() signal is emitted to reflect the new attributes
455     at the new cursor position.
456
457     QTextEdit holds a QTextDocument object which can be retrieved using the
458     document() method. You can also set your own document object using setDocument().
459     QTextDocument emits a textChanged() signal if the text changes and it also
460     provides a isModified() function which will return true if the text has been
461     modified since it was either loaded or since the last call to setModified
462     with false as argument. In addition it provides methods for undo and redo.
463
464     \section2 Drag and Drop
465
466     QTextEdit also supports custom drag and drop behavior. By default,
467     QTextEdit will insert plain text, HTML and rich text when the user drops
468     data of these MIME types onto a document. Reimplement
469     canInsertFromMimeData() and insertFromMimeData() to add support for
470     additional MIME types.
471
472     For example, to allow the user to drag and drop an image onto a QTextEdit,
473     you could the implement these functions in the following way:
474
475     \snippet doc/src/snippets/textdocument-imagedrop/textedit.cpp 0
476
477     We add support for image MIME types by returning true. For all other
478     MIME types, we use the default implementation.
479
480     \snippet doc/src/snippets/textdocument-imagedrop/textedit.cpp 1
481
482     We unpack the image from the QVariant held by the MIME source and insert
483     it into the document as a resource.
484
485     \section2 Editing Key Bindings
486
487     The list of key bindings which are implemented for editing:
488     \table
489     \header \i Keypresses \i Action
490     \row \i Backspace \i Deletes the character to the left of the cursor.
491     \row \i Delete \i Deletes the character to the right of the cursor.
492     \row \i Ctrl+C \i Copy the selected text to the clipboard.
493     \row \i Ctrl+Insert \i Copy the selected text to the clipboard.
494     \row \i Ctrl+K \i Deletes to the end of the line.
495     \row \i Ctrl+V \i Pastes the clipboard text into text edit.
496     \row \i Shift+Insert \i Pastes the clipboard text into text edit.
497     \row \i Ctrl+X \i Deletes the selected text and copies it to the clipboard.
498     \row \i Shift+Delete \i Deletes the selected text and copies it to the clipboard.
499     \row \i Ctrl+Z \i Undoes the last operation.
500     \row \i Ctrl+Y \i Redoes the last operation.
501     \row \i Left \i Moves the cursor one character to the left.
502     \row \i Ctrl+Left \i Moves the cursor one word to the left.
503     \row \i Right \i Moves the cursor one character to the right.
504     \row \i Ctrl+Right \i Moves the cursor one word to the right.
505     \row \i Up \i Moves the cursor one line up.
506     \row \i Down \i Moves the cursor one line down.
507     \row \i PageUp \i Moves the cursor one page up.
508     \row \i PageDown \i Moves the cursor one page down.
509     \row \i Home \i Moves the cursor to the beginning of the line.
510     \row \i Ctrl+Home \i Moves the cursor to the beginning of the text.
511     \row \i End \i Moves the cursor to the end of the line.
512     \row \i Ctrl+End \i Moves the cursor to the end of the text.
513     \row \i Alt+Wheel \i Scrolls the page horizontally (the Wheel is the mouse wheel).
514     \endtable
515
516     To select (mark) text hold down the Shift key whilst pressing one
517     of the movement keystrokes, for example, \e{Shift+Right}
518     will select the character to the right, and \e{Shift+Ctrl+Right} will select the word to the right, etc.
519
520     \sa QTextDocument, QTextCursor, {Application Example},
521         {Syntax Highlighter Example}, {Rich Text Processing}
522 */
523
524 /*!
525     \property QTextEdit::plainText
526     \since 4.3
527
528     This property gets and sets the text editor's contents as plain
529     text. Previous contents are removed and undo/redo history is reset
530     when the property is set.
531
532     If the text edit has another content type, it will not be replaced
533     by plain text if you call toPlainText(). The only exception to this
534     is the non-break space, \e{nbsp;}, that will be converted into
535     standard space.
536
537     By default, for an editor with no contents, this property contains
538     an empty string.
539
540     \sa html
541 */
542
543 /*!
544     \property QTextEdit::undoRedoEnabled
545     \brief whether undo and redo are enabled
546
547     Users are only able to undo or redo actions if this property is
548     true, and if there is an action that can be undone (or redone).
549 */
550
551 /*!
552     \enum QTextEdit::LineWrapMode
553
554     \value NoWrap
555     \value WidgetWidth
556     \value FixedPixelWidth
557     \value FixedColumnWidth
558 */
559
560 /*!
561     \enum QTextEdit::AutoFormattingFlag
562
563     \value AutoNone Don't do any automatic formatting.
564     \value AutoBulletList Automatically create bullet lists (e.g. when
565     the user enters an asterisk ('*') in the left most column, or
566     presses Enter in an existing list item.
567     \value AutoAll Apply all automatic formatting. Currently only
568     automatic bullet lists are supported.
569 */
570
571
572 /*!
573     Constructs an empty QTextEdit with parent \a
574     parent.
575 */
576 QTextEdit::QTextEdit(QWidget *parent)
577     : QAbstractScrollArea(*new QTextEditPrivate, parent)
578 {
579     Q_D(QTextEdit);
580     d->init();
581 }
582
583 /*!
584     \internal
585 */
586 QTextEdit::QTextEdit(QTextEditPrivate &dd, QWidget *parent)
587     : QAbstractScrollArea(dd, parent)
588 {
589     Q_D(QTextEdit);
590     d->init();
591 }
592
593 /*!
594     Constructs a QTextEdit with parent \a parent. The text edit will display
595     the text \a text. The text is interpreted as html.
596 */
597 QTextEdit::QTextEdit(const QString &text, QWidget *parent)
598     : QAbstractScrollArea(*new QTextEditPrivate, parent)
599 {
600     Q_D(QTextEdit);
601     d->init(text);
602 }
603
604
605
606 /*!
607     Destructor.
608 */
609 QTextEdit::~QTextEdit()
610 {
611 }
612
613 /*!
614     Returns the point size of the font of the current format.
615
616     \sa setFontFamily() setCurrentFont() setFontPointSize()
617 */
618 qreal QTextEdit::fontPointSize() const
619 {
620     Q_D(const QTextEdit);
621     return d->control->textCursor().charFormat().fontPointSize();
622 }
623
624 /*!
625     Returns the font family of the current format.
626
627     \sa setFontFamily() setCurrentFont() setFontPointSize()
628 */
629 QString QTextEdit::fontFamily() const
630 {
631     Q_D(const QTextEdit);
632     return d->control->textCursor().charFormat().fontFamily();
633 }
634
635 /*!
636     Returns the font weight of the current format.
637
638     \sa setFontWeight() setCurrentFont() setFontPointSize() QFont::Weight
639 */
640 int QTextEdit::fontWeight() const
641 {
642     Q_D(const QTextEdit);
643     return d->control->textCursor().charFormat().fontWeight();
644 }
645
646 /*!
647     Returns true if the font of the current format is underlined; otherwise returns
648     false.
649
650     \sa setFontUnderline()
651 */
652 bool QTextEdit::fontUnderline() const
653 {
654     Q_D(const QTextEdit);
655     return d->control->textCursor().charFormat().fontUnderline();
656 }
657
658 /*!
659     Returns true if the font of the current format is italic; otherwise returns
660     false.
661
662     \sa setFontItalic()
663 */
664 bool QTextEdit::fontItalic() const
665 {
666     Q_D(const QTextEdit);
667     return d->control->textCursor().charFormat().fontItalic();
668 }
669
670 /*!
671     Returns the text color of the current format.
672
673     \sa setTextColor()
674 */
675 QColor QTextEdit::textColor() const
676 {
677     Q_D(const QTextEdit);
678     return d->control->textCursor().charFormat().foreground().color();
679 }
680
681 /*!
682     \since 4.4
683
684     Returns the text background color of the current format.
685
686     \sa setTextBackgroundColor()
687 */
688 QColor QTextEdit::textBackgroundColor() const
689 {
690     Q_D(const QTextEdit);
691     return d->control->textCursor().charFormat().background().color();
692 }
693
694 /*!
695     Returns the font of the current format.
696
697     \sa setCurrentFont() setFontFamily() setFontPointSize()
698 */
699 QFont QTextEdit::currentFont() const
700 {
701     Q_D(const QTextEdit);
702     return d->control->textCursor().charFormat().font();
703 }
704
705 /*!
706     Sets the alignment of the current paragraph to \a a. Valid
707     alignments are Qt::AlignLeft, Qt::AlignRight,
708     Qt::AlignJustify and Qt::AlignCenter (which centers
709     horizontally).
710 */
711 void QTextEdit::setAlignment(Qt::Alignment a)
712 {
713     Q_D(QTextEdit);
714     QTextBlockFormat fmt;
715     fmt.setAlignment(a);
716     QTextCursor cursor = d->control->textCursor();
717     cursor.mergeBlockFormat(fmt);
718     d->control->setTextCursor(cursor);
719 }
720
721 /*!
722     Returns the alignment of the current paragraph.
723
724     \sa setAlignment()
725 */
726 Qt::Alignment QTextEdit::alignment() const
727 {
728     Q_D(const QTextEdit);
729     return d->control->textCursor().blockFormat().alignment();
730 }
731
732 /*!
733     Makes \a document the new document of the text editor.
734
735     \note The editor \e{does not take ownership of the document} unless it
736     is the document's parent object. The parent object of the provided document
737     remains the owner of the object.
738
739     The editor does not delete the current document, even if it is a child of the editor.
740
741     \sa document()
742 */
743 void QTextEdit::setDocument(QTextDocument *document)
744 {
745     Q_D(QTextEdit);
746     d->control->setDocument(document);
747     d->updateDefaultTextOption();
748     d->relayoutDocument();
749 }
750
751 /*!
752     Returns a pointer to the underlying document.
753
754     \sa setDocument()
755 */
756 QTextDocument *QTextEdit::document() const
757 {
758     Q_D(const QTextEdit);
759     return d->control->document();
760 }
761
762 /*!
763     Sets the visible \a cursor.
764 */
765 void QTextEdit::setTextCursor(const QTextCursor &cursor)
766 {
767     Q_D(QTextEdit);
768     d->control->setTextCursor(cursor);
769 }
770
771 /*!
772     Returns a copy of the QTextCursor that represents the currently visible cursor.
773     Note that changes on the returned cursor do not affect QTextEdit's cursor; use
774     setTextCursor() to update the visible cursor.
775  */
776 QTextCursor QTextEdit::textCursor() const
777 {
778     Q_D(const QTextEdit);
779     return d->control->textCursor();
780 }
781
782 /*!
783     Sets the font family of the current format to \a fontFamily.
784
785     \sa fontFamily() setCurrentFont()
786 */
787 void QTextEdit::setFontFamily(const QString &fontFamily)
788 {
789     QTextCharFormat fmt;
790     fmt.setFontFamily(fontFamily);
791     mergeCurrentCharFormat(fmt);
792 }
793
794 /*!
795     Sets the point size of the current format to \a s.
796
797     Note that if \a s is zero or negative, the behavior of this
798     function is not defined.
799
800     \sa fontPointSize() setCurrentFont() setFontFamily()
801 */
802 void QTextEdit::setFontPointSize(qreal s)
803 {
804     QTextCharFormat fmt;
805     fmt.setFontPointSize(s);
806     mergeCurrentCharFormat(fmt);
807 }
808
809 /*!
810     \fn void QTextEdit::setFontWeight(int weight)
811
812     Sets the font weight of the current format to the given \a weight,
813     where the value used is in the range defined by the QFont::Weight
814     enum.
815
816     \sa fontWeight(), setCurrentFont(), setFontFamily()
817 */
818 void QTextEdit::setFontWeight(int w)
819 {
820     QTextCharFormat fmt;
821     fmt.setFontWeight(w);
822     mergeCurrentCharFormat(fmt);
823 }
824
825 /*!
826     If \a underline is true, sets the current format to underline;
827     otherwise sets the current format to non-underline.
828
829     \sa fontUnderline()
830 */
831 void QTextEdit::setFontUnderline(bool underline)
832 {
833     QTextCharFormat fmt;
834     fmt.setFontUnderline(underline);
835     mergeCurrentCharFormat(fmt);
836 }
837
838 /*!
839     If \a italic is true, sets the current format to italic;
840     otherwise sets the current format to non-italic.
841
842     \sa fontItalic()
843 */
844 void QTextEdit::setFontItalic(bool italic)
845 {
846     QTextCharFormat fmt;
847     fmt.setFontItalic(italic);
848     mergeCurrentCharFormat(fmt);
849 }
850
851 /*!
852     Sets the text color of the current format to \a c.
853
854     \sa textColor()
855 */
856 void QTextEdit::setTextColor(const QColor &c)
857 {
858     QTextCharFormat fmt;
859     fmt.setForeground(QBrush(c));
860     mergeCurrentCharFormat(fmt);
861 }
862
863 /*!
864     \since 4.4
865
866     Sets the text background color of the current format to \a c.
867
868     \sa textBackgroundColor()
869 */
870 void QTextEdit::setTextBackgroundColor(const QColor &c)
871 {
872     QTextCharFormat fmt;
873     fmt.setBackground(QBrush(c));
874     mergeCurrentCharFormat(fmt);
875 }
876
877 /*!
878     Sets the font of the current format to \a f.
879
880     \sa currentFont() setFontPointSize() setFontFamily()
881 */
882 void QTextEdit::setCurrentFont(const QFont &f)
883 {
884     QTextCharFormat fmt;
885     fmt.setFont(f);
886     mergeCurrentCharFormat(fmt);
887 }
888
889 /*!
890     \since 4.2
891
892     Undoes the last operation.
893
894     If there is no operation to undo, i.e. there is no undo step in
895     the undo/redo history, nothing happens.
896
897     \sa redo()
898 */
899 void QTextEdit::undo()
900 {
901     Q_D(QTextEdit);
902     d->control->undo();
903 }
904
905 void QTextEdit::redo()
906 {
907     Q_D(QTextEdit);
908     d->control->redo();
909 }
910
911 /*!
912     \fn void QTextEdit::undo() const
913     \fn void QTextEdit::redo() const
914     \overload
915
916     Use the non-const overload instead.
917 */
918
919 /*!
920     \fn void QTextEdit::redo()
921     \since 4.2
922
923     Redoes the last operation.
924
925     If there is no operation to redo, i.e. there is no redo step in
926     the undo/redo history, nothing happens.
927
928     \sa undo()
929 */
930
931 #ifndef QT_NO_CLIPBOARD
932 /*!
933     Copies the selected text to the clipboard and deletes it from
934     the text edit.
935
936     If there is no selected text nothing happens.
937
938     \sa copy() paste()
939 */
940
941 void QTextEdit::cut()
942 {
943     Q_D(QTextEdit);
944     d->control->cut();
945 }
946
947 /*!
948     Copies any selected text to the clipboard.
949
950     \sa copyAvailable()
951 */
952
953 void QTextEdit::copy()
954 {
955     Q_D(QTextEdit);
956     d->control->copy();
957 }
958
959 /*!
960     Pastes the text from the clipboard into the text edit at the
961     current cursor position.
962
963     If there is no text in the clipboard nothing happens.
964
965     To change the behavior of this function, i.e. to modify what
966     QTextEdit can paste and how it is being pasted, reimplement the
967     virtual canInsertFromMimeData() and insertFromMimeData()
968     functions.
969
970     \sa cut() copy()
971 */
972
973 void QTextEdit::paste()
974 {
975     Q_D(QTextEdit);
976     d->control->paste();
977 }
978 #endif
979
980 /*!
981     Deletes all the text in the text edit.
982
983     Note that the undo/redo history is cleared by this function.
984
985     \sa cut() setPlainText() setHtml()
986 */
987 void QTextEdit::clear()
988 {
989     Q_D(QTextEdit);
990     // clears and sets empty content
991     d->control->clear();
992 }
993
994
995 /*!
996     Selects all text.
997
998     \sa copy() cut() textCursor()
999  */
1000 void QTextEdit::selectAll()
1001 {
1002     Q_D(QTextEdit);
1003     d->control->selectAll();
1004 }
1005
1006 /*! \internal
1007 */
1008 bool QTextEdit::event(QEvent *e)
1009 {
1010     Q_D(QTextEdit);
1011 #ifndef QT_NO_CONTEXTMENU
1012     if (e->type() == QEvent::ContextMenu
1013         && static_cast<QContextMenuEvent *>(e)->reason() == QContextMenuEvent::Keyboard) {
1014         Q_D(QTextEdit);
1015         ensureCursorVisible();
1016         const QPoint cursorPos = cursorRect().center();
1017         QContextMenuEvent ce(QContextMenuEvent::Keyboard, cursorPos, d->viewport->mapToGlobal(cursorPos));
1018         ce.setAccepted(e->isAccepted());
1019         const bool result = QAbstractScrollArea::event(&ce);
1020         e->setAccepted(ce.isAccepted());
1021         return result;
1022     } else if (e->type() == QEvent::ShortcutOverride
1023                || e->type() == QEvent::ToolTip) {
1024         d->sendControlEvent(e);
1025     }
1026 #endif // QT_NO_CONTEXTMENU
1027 #ifdef QT_KEYPAD_NAVIGATION
1028     if (e->type() == QEvent::EnterEditFocus || e->type() == QEvent::LeaveEditFocus) {
1029         if (QApplication::keypadNavigationEnabled())
1030             d->sendControlEvent(e);
1031     }
1032 #endif
1033     return QAbstractScrollArea::event(e);
1034 }
1035
1036 /*! \internal
1037 */
1038
1039 void QTextEdit::timerEvent(QTimerEvent *e)
1040 {
1041     Q_D(QTextEdit);
1042     if (e->timerId() == d->autoScrollTimer.timerId()) {
1043         QRect visible = d->viewport->rect();
1044         QPoint pos;
1045         if (d->inDrag) {
1046             pos = d->autoScrollDragPos;
1047             visible.adjust(qMin(visible.width()/3,20), qMin(visible.height()/3,20),
1048                            -qMin(visible.width()/3,20), -qMin(visible.height()/3,20));
1049         } else {
1050             const QPoint globalPos = QCursor::pos();
1051             pos = d->viewport->mapFromGlobal(globalPos);
1052             QMouseEvent ev(QEvent::MouseMove, pos, mapTo(topLevelWidget(), pos), globalPos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
1053             mouseMoveEvent(&ev);
1054         }
1055         int deltaY = qMax(pos.y() - visible.top(), visible.bottom() - pos.y()) - visible.height();
1056         int deltaX = qMax(pos.x() - visible.left(), visible.right() - pos.x()) - visible.width();
1057         int delta = qMax(deltaX, deltaY);
1058         if (delta >= 0) {
1059             if (delta < 7)
1060                 delta = 7;
1061             int timeout = 4900 / (delta * delta);
1062             d->autoScrollTimer.start(timeout, this);
1063
1064             if (deltaY > 0)
1065                 d->vbar->triggerAction(pos.y() < visible.center().y() ?
1066                                        QAbstractSlider::SliderSingleStepSub
1067                                        : QAbstractSlider::SliderSingleStepAdd);
1068             if (deltaX > 0)
1069                 d->hbar->triggerAction(pos.x() < visible.center().x() ?
1070                                        QAbstractSlider::SliderSingleStepSub
1071                                        : QAbstractSlider::SliderSingleStepAdd);
1072         }
1073     }
1074 #ifdef QT_KEYPAD_NAVIGATION
1075     else if (e->timerId() == d->deleteAllTimer.timerId()) {
1076         d->deleteAllTimer.stop();
1077         clear();
1078     }
1079 #endif
1080 }
1081
1082 /*!
1083     Changes the text of the text edit to the string \a text.
1084     Any previous text is removed.
1085
1086     \a text is interpreted as plain text.
1087
1088     Note that the undo/redo history is cleared by this function.
1089
1090     \sa toPlainText()
1091 */
1092
1093 void QTextEdit::setPlainText(const QString &text)
1094 {
1095     Q_D(QTextEdit);
1096     d->control->setPlainText(text);
1097     d->preferRichText = false;
1098 }
1099
1100 /*!
1101     QString QTextEdit::toPlainText() const
1102
1103     Returns the text of the text edit as plain text.
1104
1105     \sa QTextEdit::setPlainText()
1106  */
1107 QString QTextEdit::toPlainText() const
1108 {
1109     Q_D(const QTextEdit);
1110     return d->control->toPlainText();
1111 }
1112
1113 /*!
1114     \property QTextEdit::html
1115
1116     This property provides an HTML interface to the text of the text edit.
1117
1118     toHtml() returns the text of the text edit as html.
1119
1120     setHtml() changes the text of the text edit.  Any previous text is
1121     removed and the undo/redo history is cleared. The input text is
1122     interpreted as rich text in html format.
1123
1124     \note It is the responsibility of the caller to make sure that the
1125     text is correctly decoded when a QString containing HTML is created
1126     and passed to setHtml().
1127
1128     By default, for a newly-created, empty document, this property contains
1129     text to describe an HTML 4.0 document with no body text.
1130
1131     \sa {Supported HTML Subset}, plainText
1132 */
1133
1134 #ifndef QT_NO_TEXTHTMLPARSER
1135 void QTextEdit::setHtml(const QString &text)
1136 {
1137     Q_D(QTextEdit);
1138     d->control->setHtml(text);
1139     d->preferRichText = true;
1140 }
1141
1142 QString QTextEdit::toHtml() const
1143 {
1144     Q_D(const QTextEdit);
1145     return d->control->toHtml();
1146 }
1147 #endif
1148
1149
1150 /*! \reimp
1151 */
1152 void QTextEdit::keyPressEvent(QKeyEvent *e)
1153 {
1154     Q_D(QTextEdit);
1155
1156 #ifdef QT_KEYPAD_NAVIGATION
1157     switch (e->key()) {
1158         case Qt::Key_Select:
1159             if (QApplication::keypadNavigationEnabled()) {
1160                 // code assumes linksaccessible + editable isn't meaningful
1161                 if (d->control->textInteractionFlags() & Qt::TextEditable) {
1162                     setEditFocus(!hasEditFocus());
1163                 } else {
1164                     if (!hasEditFocus())
1165                         setEditFocus(true);
1166                     else {
1167                         QTextCursor cursor = d->control->textCursor();
1168                         QTextCharFormat charFmt = cursor.charFormat();
1169                         if (!(d->control->textInteractionFlags() & Qt::LinksAccessibleByKeyboard)
1170                             || !cursor.hasSelection() || charFmt.anchorHref().isEmpty()) {
1171                             e->accept();
1172                             return;
1173                         }
1174                     }
1175                 }
1176             }
1177             break;
1178         case Qt::Key_Back:
1179         case Qt::Key_No:
1180             if (!QApplication::keypadNavigationEnabled()
1181                     || (QApplication::keypadNavigationEnabled() && !hasEditFocus())) {
1182                 e->ignore();
1183                 return;
1184             }
1185             break;
1186         default:
1187             if (QApplication::keypadNavigationEnabled()) {
1188                 if (!hasEditFocus() && !(e->modifiers() & Qt::ControlModifier)) {
1189                     if (e->text()[0].isPrint())
1190                         setEditFocus(true);
1191                     else {
1192                         e->ignore();
1193                         return;
1194                     }
1195                 }
1196             }
1197             break;
1198     }
1199 #endif
1200 #ifndef QT_NO_SHORTCUT
1201
1202     Qt::TextInteractionFlags tif = d->control->textInteractionFlags();
1203
1204     if (tif & Qt::TextSelectableByKeyboard){
1205         if (e == QKeySequence::SelectPreviousPage) {
1206             e->accept();
1207             d->pageUpDown(QTextCursor::Up, QTextCursor::KeepAnchor);
1208             return;
1209         } else if (e ==QKeySequence::SelectNextPage) {
1210             e->accept();
1211             d->pageUpDown(QTextCursor::Down, QTextCursor::KeepAnchor);
1212             return;
1213         }
1214     }
1215     if (tif & (Qt::TextSelectableByKeyboard | Qt::TextEditable)) {
1216         if (e == QKeySequence::MoveToPreviousPage) {
1217             e->accept();
1218             d->pageUpDown(QTextCursor::Up, QTextCursor::MoveAnchor);
1219             return;
1220         } else if (e == QKeySequence::MoveToNextPage) {
1221             e->accept();
1222             d->pageUpDown(QTextCursor::Down, QTextCursor::MoveAnchor);
1223             return;
1224         }
1225     }
1226
1227     if (!(tif & Qt::TextEditable)) {
1228         switch (e->key()) {
1229             case Qt::Key_Space:
1230                 e->accept();
1231                 if (e->modifiers() & Qt::ShiftModifier)
1232                     d->vbar->triggerAction(QAbstractSlider::SliderPageStepSub);
1233                 else
1234                     d->vbar->triggerAction(QAbstractSlider::SliderPageStepAdd);
1235                 break;
1236             default:
1237                 d->sendControlEvent(e);
1238                 if (!e->isAccepted() && e->modifiers() == Qt::NoModifier) {
1239                     if (e->key() == Qt::Key_Home) {
1240                         d->vbar->triggerAction(QAbstractSlider::SliderToMinimum);
1241                         e->accept();
1242                     } else if (e->key() == Qt::Key_End) {
1243                         d->vbar->triggerAction(QAbstractSlider::SliderToMaximum);
1244                         e->accept();
1245                     }
1246                 }
1247                 if (!e->isAccepted()) {
1248                     QAbstractScrollArea::keyPressEvent(e);
1249                 }
1250         }
1251         return;
1252     }
1253 #endif // QT_NO_SHORTCUT
1254
1255     {
1256         QTextCursor cursor = d->control->textCursor();
1257         const QString text = e->text();
1258         if (cursor.atBlockStart()
1259             && (d->autoFormatting & AutoBulletList)
1260             && (text.length() == 1)
1261             && (text.at(0) == QLatin1Char('-') || text.at(0) == QLatin1Char('*'))
1262             && (!cursor.currentList())) {
1263
1264             d->createAutoBulletList();
1265             e->accept();
1266             return;
1267         }
1268     }
1269
1270     d->sendControlEvent(e);
1271 #ifdef QT_KEYPAD_NAVIGATION
1272     if (!e->isAccepted()) {
1273         switch (e->key()) {
1274             case Qt::Key_Up:
1275             case Qt::Key_Down:
1276                 if (QApplication::keypadNavigationEnabled()) {
1277                     // Cursor position didn't change, so we want to leave
1278                     // these keys to change focus.
1279                     e->ignore();
1280                     return;
1281                 }
1282                 break;
1283             case Qt::Key_Back:
1284                 if (!e->isAutoRepeat()) {
1285                     if (QApplication::keypadNavigationEnabled()) {
1286                         if (document()->isEmpty() || !(d->control->textInteractionFlags() & Qt::TextEditable)) {
1287                             setEditFocus(false);
1288                             e->accept();
1289                         } else if (!d->deleteAllTimer.isActive()) {
1290                             e->accept();
1291                             d->deleteAllTimer.start(750, this);
1292                         }
1293                     } else {
1294                         e->ignore();
1295                         return;
1296                     }
1297                 }
1298                 break;
1299             default: break;
1300         }
1301     }
1302 #endif
1303 }
1304
1305 /*! \reimp
1306 */
1307 void QTextEdit::keyReleaseEvent(QKeyEvent *e)
1308 {
1309 #ifdef QT_KEYPAD_NAVIGATION
1310     Q_D(QTextEdit);
1311     if (QApplication::keypadNavigationEnabled()) {
1312         if (!e->isAutoRepeat() && e->key() == Qt::Key_Back
1313             && d->deleteAllTimer.isActive()) {
1314             d->deleteAllTimer.stop();
1315             QTextCursor cursor = d->control->textCursor();
1316             QTextBlockFormat blockFmt = cursor.blockFormat();
1317
1318             QTextList *list = cursor.currentList();
1319             if (list && cursor.atBlockStart()) {
1320                 list->remove(cursor.block());
1321             } else if (cursor.atBlockStart() && blockFmt.indent() > 0) {
1322                 blockFmt.setIndent(blockFmt.indent() - 1);
1323                 cursor.setBlockFormat(blockFmt);
1324             } else {
1325                 cursor.deletePreviousChar();
1326             }
1327             setTextCursor(cursor);
1328             e->accept();
1329             return;
1330         }
1331     }
1332 #endif
1333     e->ignore();
1334 }
1335
1336 /*!
1337     Loads the resource specified by the given \a type and \a name.
1338
1339     This function is an extension of QTextDocument::loadResource().
1340
1341     \sa QTextDocument::loadResource()
1342 */
1343 QVariant QTextEdit::loadResource(int type, const QUrl &name)
1344 {
1345     Q_UNUSED(type);
1346     Q_UNUSED(name);
1347     return QVariant();
1348 }
1349
1350 /*! \reimp
1351 */
1352 void QTextEdit::resizeEvent(QResizeEvent *e)
1353 {
1354     Q_D(QTextEdit);
1355
1356     if (d->lineWrap == NoWrap) {
1357         QTextDocument *doc = d->control->document();
1358         QVariant alignmentProperty = doc->documentLayout()->property("contentHasAlignment");
1359
1360         if (!doc->pageSize().isNull()
1361             && alignmentProperty.type() == QVariant::Bool
1362             && !alignmentProperty.toBool()) {
1363
1364             d->_q_adjustScrollbars();
1365             return;
1366         }
1367     }
1368
1369     if (d->lineWrap != FixedPixelWidth
1370         && e->oldSize().width() != e->size().width())
1371         d->relayoutDocument();
1372     else
1373         d->_q_adjustScrollbars();
1374 }
1375
1376 void QTextEditPrivate::relayoutDocument()
1377 {
1378     QTextDocument *doc = control->document();
1379     QAbstractTextDocumentLayout *layout = doc->documentLayout();
1380
1381     if (QTextDocumentLayout *tlayout = qobject_cast<QTextDocumentLayout *>(layout)) {
1382         if (lineWrap == QTextEdit::FixedColumnWidth)
1383             tlayout->setFixedColumnWidth(lineWrapColumnOrWidth);
1384         else
1385             tlayout->setFixedColumnWidth(-1);
1386     }
1387
1388     QTextDocumentLayout *tlayout = qobject_cast<QTextDocumentLayout *>(layout);
1389     QSize lastUsedSize;
1390     if (tlayout)
1391         lastUsedSize = tlayout->dynamicDocumentSize().toSize();
1392     else
1393         lastUsedSize = layout->documentSize().toSize();
1394
1395     // ignore calls to _q_adjustScrollbars caused by an emission of the
1396     // usedSizeChanged() signal in the layout, as we're calling it
1397     // later on our own anyway (or deliberately not) .
1398     const bool oldIgnoreScrollbarAdjustment = ignoreAutomaticScrollbarAdjustment;
1399     ignoreAutomaticScrollbarAdjustment = true;
1400
1401     int width = viewport->width();
1402     if (lineWrap == QTextEdit::FixedPixelWidth)
1403         width = lineWrapColumnOrWidth;
1404     else if (lineWrap == QTextEdit::NoWrap) {
1405         QVariant alignmentProperty = doc->documentLayout()->property("contentHasAlignment");
1406         if (alignmentProperty.type() == QVariant::Bool && !alignmentProperty.toBool()) {
1407
1408             width = 0;
1409         }
1410     }
1411
1412     doc->setPageSize(QSize(width, -1));
1413     if (tlayout)
1414         tlayout->ensureLayouted(verticalOffset() + viewport->height());
1415
1416     ignoreAutomaticScrollbarAdjustment = oldIgnoreScrollbarAdjustment;
1417
1418     QSize usedSize;
1419     if (tlayout)
1420         usedSize = tlayout->dynamicDocumentSize().toSize();
1421     else
1422         usedSize = layout->documentSize().toSize();
1423
1424     // this is an obscure situation in the layout that can happen:
1425     // if a character at the end of a line is the tallest one and therefore
1426     // influencing the total height of the line and the line right below it
1427     // is always taller though, then it can happen that if due to line breaking
1428     // that tall character wraps into the lower line the document not only shrinks
1429     // horizontally (causing the character to wrap in the first place) but also
1430     // vertically, because the original line is now smaller and the one below kept
1431     // its size. So a layout with less width _can_ take up less vertical space, too.
1432     // If the wider case causes a vertical scroll bar to appear and the narrower one
1433     // (narrower because the vertical scroll bar takes up horizontal space)) to disappear
1434     // again then we have an endless loop, as _q_adjustScrollBars sets new ranges on the
1435     // scroll bars, the QAbstractScrollArea will find out about it and try to show/hide
1436     // the scroll bars again. That's why we try to detect this case here and break out.
1437     //
1438     // (if you change this please also check the layoutingLoop() testcase in
1439     // QTextEdit's autotests)
1440     if (lastUsedSize.isValid()
1441         && !vbar->isHidden()
1442         && viewport->width() < lastUsedSize.width()
1443         && usedSize.height() < lastUsedSize.height()
1444         && usedSize.height() <= viewport->height())
1445         return;
1446
1447     _q_adjustScrollbars();
1448 }
1449
1450 void QTextEditPrivate::paint(QPainter *p, QPaintEvent *e)
1451 {
1452     const int xOffset = horizontalOffset();
1453     const int yOffset = verticalOffset();
1454
1455     QRect r = e->rect();
1456     p->translate(-xOffset, -yOffset);
1457     r.translate(xOffset, yOffset);
1458
1459     QTextDocument *doc = control->document();
1460     QTextDocumentLayout *layout = qobject_cast<QTextDocumentLayout *>(doc->documentLayout());
1461
1462     // the layout might need to expand the root frame to
1463     // the viewport if NoWrap is set
1464     if (layout)
1465         layout->setViewport(viewport->rect());
1466
1467     control->drawContents(p, r, q_func());
1468
1469     if (layout)
1470         layout->setViewport(QRect());
1471 }
1472
1473 /*! \fn void QTextEdit::paintEvent(QPaintEvent *event)
1474
1475 This event handler can be reimplemented in a subclass to receive paint events passed in \a event.
1476 It is usually unnecessary to reimplement this function in a subclass of QTextEdit.
1477
1478 \warning The underlying text document must not be modified from within a reimplementation
1479 of this function.
1480 */
1481 void QTextEdit::paintEvent(QPaintEvent *e)
1482 {
1483     Q_D(QTextEdit);
1484     QPainter p(d->viewport);
1485     d->paint(&p, e);
1486 }
1487
1488 void QTextEditPrivate::_q_currentCharFormatChanged(const QTextCharFormat &fmt)
1489 {
1490     Q_Q(QTextEdit);
1491     emit q->currentCharFormatChanged(fmt);
1492 }
1493
1494 void QTextEditPrivate::updateDefaultTextOption()
1495 {
1496     QTextDocument *doc = control->document();
1497
1498     QTextOption opt = doc->defaultTextOption();
1499     QTextOption::WrapMode oldWrapMode = opt.wrapMode();
1500
1501     if (lineWrap == QTextEdit::NoWrap)
1502         opt.setWrapMode(QTextOption::NoWrap);
1503     else
1504         opt.setWrapMode(wordWrap);
1505
1506     if (opt.wrapMode() != oldWrapMode)
1507         doc->setDefaultTextOption(opt);
1508 }
1509
1510 /*! \reimp
1511 */
1512 void QTextEdit::mousePressEvent(QMouseEvent *e)
1513 {
1514     Q_D(QTextEdit);
1515 #ifdef QT_KEYPAD_NAVIGATION
1516     if (QApplication::keypadNavigationEnabled() && !hasEditFocus())
1517         setEditFocus(true);
1518 #endif
1519     d->sendControlEvent(e);
1520 }
1521
1522 /*! \reimp
1523 */
1524 void QTextEdit::mouseMoveEvent(QMouseEvent *e)
1525 {
1526     Q_D(QTextEdit);
1527     d->inDrag = false; // paranoia
1528     const QPoint pos = e->pos();
1529     d->sendControlEvent(e);
1530     if (!(e->buttons() & Qt::LeftButton))
1531         return;
1532     QRect visible = d->viewport->rect();
1533     if (visible.contains(pos))
1534         d->autoScrollTimer.stop();
1535     else if (!d->autoScrollTimer.isActive())
1536         d->autoScrollTimer.start(100, this);
1537 }
1538
1539 /*! \reimp
1540 */
1541 void QTextEdit::mouseReleaseEvent(QMouseEvent *e)
1542 {
1543     Q_D(QTextEdit);
1544     d->sendControlEvent(e);
1545     if (d->autoScrollTimer.isActive()) {
1546         d->autoScrollTimer.stop();
1547         ensureCursorVisible();
1548     }
1549     if (!isReadOnly() && rect().contains(e->pos()))
1550         d->handleSoftwareInputPanel(e->button(), d->clickCausedFocus);
1551     d->clickCausedFocus = 0;
1552 }
1553
1554 /*! \reimp
1555 */
1556 void QTextEdit::mouseDoubleClickEvent(QMouseEvent *e)
1557 {
1558     Q_D(QTextEdit);
1559     d->sendControlEvent(e);
1560 }
1561
1562 /*! \reimp
1563 */
1564 bool QTextEdit::focusNextPrevChild(bool next)
1565 {
1566     Q_D(const QTextEdit);
1567     if (!d->tabChangesFocus && d->control->textInteractionFlags() & Qt::TextEditable)
1568         return false;
1569     return QAbstractScrollArea::focusNextPrevChild(next);
1570 }
1571
1572 #ifndef QT_NO_CONTEXTMENU
1573 /*!
1574   \fn void QTextEdit::contextMenuEvent(QContextMenuEvent *event)
1575
1576   Shows the standard context menu created with createStandardContextMenu().
1577
1578   If you do not want the text edit to have a context menu, you can set
1579   its \l contextMenuPolicy to Qt::NoContextMenu. If you want to
1580   customize the context menu, reimplement this function. If you want
1581   to extend the standard context menu, reimplement this function, call
1582   createStandardContextMenu() and extend the menu returned.
1583
1584   Information about the event is passed in the \a event object.
1585
1586   \snippet doc/src/snippets/code/src_gui_widgets_qtextedit.cpp 0
1587 */
1588 void QTextEdit::contextMenuEvent(QContextMenuEvent *e)
1589 {
1590     Q_D(QTextEdit);
1591     d->sendControlEvent(e);
1592 }
1593 #endif // QT_NO_CONTEXTMENU
1594
1595 #ifndef QT_NO_DRAGANDDROP
1596 /*! \reimp
1597 */
1598 void QTextEdit::dragEnterEvent(QDragEnterEvent *e)
1599 {
1600     Q_D(QTextEdit);
1601     d->inDrag = true;
1602     d->sendControlEvent(e);
1603 }
1604
1605 /*! \reimp
1606 */
1607 void QTextEdit::dragLeaveEvent(QDragLeaveEvent *e)
1608 {
1609     Q_D(QTextEdit);
1610     d->inDrag = false;
1611     d->autoScrollTimer.stop();
1612     d->sendControlEvent(e);
1613 }
1614
1615 /*! \reimp
1616 */
1617 void QTextEdit::dragMoveEvent(QDragMoveEvent *e)
1618 {
1619     Q_D(QTextEdit);
1620     d->autoScrollDragPos = e->pos();
1621     if (!d->autoScrollTimer.isActive())
1622         d->autoScrollTimer.start(100, this);
1623     d->sendControlEvent(e);
1624 }
1625
1626 /*! \reimp
1627 */
1628 void QTextEdit::dropEvent(QDropEvent *e)
1629 {
1630     Q_D(QTextEdit);
1631     d->inDrag = false;
1632     d->autoScrollTimer.stop();
1633     d->sendControlEvent(e);
1634 }
1635
1636 #endif // QT_NO_DRAGANDDROP
1637
1638 /*! \reimp
1639  */
1640 void QTextEdit::inputMethodEvent(QInputMethodEvent *e)
1641 {
1642     Q_D(QTextEdit);
1643 #ifdef QT_KEYPAD_NAVIGATION
1644     if (d->control->textInteractionFlags() & Qt::TextEditable
1645         && QApplication::keypadNavigationEnabled()
1646         && !hasEditFocus())
1647         setEditFocus(true);
1648 #endif
1649     d->sendControlEvent(e);
1650     ensureCursorVisible();
1651 }
1652
1653 /*!\reimp
1654 */
1655 void QTextEdit::scrollContentsBy(int dx, int dy)
1656 {
1657     Q_D(QTextEdit);
1658     if (isRightToLeft())
1659         dx = -dx;
1660     d->viewport->scroll(dx, dy);
1661 }
1662
1663 /*!\reimp
1664 */
1665 QVariant QTextEdit::inputMethodQuery(Qt::InputMethodQuery property) const
1666 {
1667     Q_D(const QTextEdit);
1668     QVariant v = d->control->inputMethodQuery(property);
1669     const QPoint offset(-d->horizontalOffset(), -d->verticalOffset());
1670     if (v.type() == QVariant::RectF)
1671         v = v.toRectF().toRect().translated(offset);
1672     else if (v.type() == QVariant::PointF)
1673         v = v.toPointF().toPoint() + offset;
1674     else if (v.type() == QVariant::Rect)
1675         v = v.toRect().translated(offset);
1676     else if (v.type() == QVariant::Point)
1677         v = v.toPoint() + offset;
1678     return v;
1679 }
1680
1681 /*! \reimp
1682 */
1683 void QTextEdit::focusInEvent(QFocusEvent *e)
1684 {
1685     Q_D(QTextEdit);
1686     if (e->reason() == Qt::MouseFocusReason) {
1687         d->clickCausedFocus = 1;
1688     }
1689     QAbstractScrollArea::focusInEvent(e);
1690     d->sendControlEvent(e);
1691 }
1692
1693 /*! \reimp
1694 */
1695 void QTextEdit::focusOutEvent(QFocusEvent *e)
1696 {
1697     Q_D(QTextEdit);
1698     QAbstractScrollArea::focusOutEvent(e);
1699     d->sendControlEvent(e);
1700 }
1701
1702 /*! \reimp
1703 */
1704 void QTextEdit::showEvent(QShowEvent *)
1705 {
1706     Q_D(QTextEdit);
1707     if (!d->anchorToScrollToWhenVisible.isEmpty()) {
1708         scrollToAnchor(d->anchorToScrollToWhenVisible);
1709         d->anchorToScrollToWhenVisible.clear();
1710         d->showCursorOnInitialShow = false;
1711     } else if (d->showCursorOnInitialShow) {
1712         d->showCursorOnInitialShow = false;
1713         ensureCursorVisible();
1714     }
1715 }
1716
1717 /*! \reimp
1718 */
1719 void QTextEdit::changeEvent(QEvent *e)
1720 {
1721     Q_D(QTextEdit);
1722     QAbstractScrollArea::changeEvent(e);
1723     if (e->type() == QEvent::ApplicationFontChange
1724         || e->type() == QEvent::FontChange) {
1725         d->control->document()->setDefaultFont(font());
1726     }  else if(e->type() == QEvent::ActivationChange) {
1727         if (!isActiveWindow())
1728             d->autoScrollTimer.stop();
1729     } else if (e->type() == QEvent::EnabledChange) {
1730         e->setAccepted(isEnabled());
1731         d->control->setPalette(palette());
1732         d->sendControlEvent(e);
1733     } else if (e->type() == QEvent::PaletteChange) {
1734         d->control->setPalette(palette());
1735     } else if (e->type() == QEvent::LayoutDirectionChange) {
1736         d->sendControlEvent(e);
1737     }
1738 }
1739
1740 /*! \reimp
1741 */
1742 #ifndef QT_NO_WHEELEVENT
1743 void QTextEdit::wheelEvent(QWheelEvent *e)
1744 {
1745     Q_D(QTextEdit);
1746     if (!(d->control->textInteractionFlags() & Qt::TextEditable)) {
1747         if (e->modifiers() & Qt::ControlModifier) {
1748             const int delta = e->delta();
1749             if (delta < 0)
1750                 zoomOut();
1751             else if (delta > 0)
1752                 zoomIn();
1753             return;
1754         }
1755     }
1756     QAbstractScrollArea::wheelEvent(e);
1757     updateMicroFocus();
1758 }
1759 #endif
1760
1761 #ifndef QT_NO_CONTEXTMENU
1762 /*!  This function creates the standard context menu which is shown
1763   when the user clicks on the text edit with the right mouse
1764   button. It is called from the default contextMenuEvent() handler.
1765   The popup menu's ownership is transferred to the caller.
1766
1767   We recommend that you use the createStandardContextMenu(QPoint) version instead
1768   which will enable the actions that are sensitive to where the user clicked.
1769 */
1770
1771 QMenu *QTextEdit::createStandardContextMenu()
1772 {
1773     Q_D(QTextEdit);
1774     return d->control->createStandardContextMenu(QPointF(), this);
1775 }
1776
1777 /*!
1778   \since 4.4
1779   This function creates the standard context menu which is shown
1780   when the user clicks on the text edit with the right mouse
1781   button. It is called from the default contextMenuEvent() handler
1782   and it takes the \a position of where the mouse click was.
1783   This can enable actions that are sensitive to the position where the user clicked.
1784   The popup menu's ownership is transferred to the caller.
1785 */
1786
1787 QMenu *QTextEdit::createStandardContextMenu(const QPoint &position)
1788 {
1789     Q_D(QTextEdit);
1790     return d->control->createStandardContextMenu(position, this);
1791 }
1792 #endif // QT_NO_CONTEXTMENU
1793
1794 /*!
1795   returns a QTextCursor at position \a pos (in viewport coordinates).
1796 */
1797 QTextCursor QTextEdit::cursorForPosition(const QPoint &pos) const
1798 {
1799     Q_D(const QTextEdit);
1800     return d->control->cursorForPosition(d->mapToContents(pos));
1801 }
1802
1803 /*!
1804   returns a rectangle (in viewport coordinates) that includes the
1805   \a cursor.
1806  */
1807 QRect QTextEdit::cursorRect(const QTextCursor &cursor) const
1808 {
1809     Q_D(const QTextEdit);
1810     if (cursor.isNull())
1811         return QRect();
1812
1813     QRect r = d->control->cursorRect(cursor).toRect();
1814     r.translate(-d->horizontalOffset(),-d->verticalOffset());
1815     return r;
1816 }
1817
1818 /*!
1819   returns a rectangle (in viewport coordinates) that includes the
1820   cursor of the text edit.
1821  */
1822 QRect QTextEdit::cursorRect() const
1823 {
1824     Q_D(const QTextEdit);
1825     QRect r = d->control->cursorRect().toRect();
1826     r.translate(-d->horizontalOffset(),-d->verticalOffset());
1827     return r;
1828 }
1829
1830
1831 /*!
1832     Returns the reference of the anchor at position \a pos, or an
1833     empty string if no anchor exists at that point.
1834 */
1835 QString QTextEdit::anchorAt(const QPoint& pos) const
1836 {
1837     Q_D(const QTextEdit);
1838     return d->control->anchorAt(d->mapToContents(pos));
1839 }
1840
1841 /*!
1842    \property QTextEdit::overwriteMode
1843    \since 4.1
1844    \brief whether text entered by the user will overwrite existing text
1845
1846    As with many text editors, the text editor widget can be configured
1847    to insert or overwrite existing text with new text entered by the user.
1848
1849    If this property is true, existing text is overwritten, character-for-character
1850    by new text; otherwise, text is inserted at the cursor position, displacing
1851    existing text.
1852
1853    By default, this property is false (new text does not overwrite existing text).
1854 */
1855
1856 bool QTextEdit::overwriteMode() const
1857 {
1858     Q_D(const QTextEdit);
1859     return d->control->overwriteMode();
1860 }
1861
1862 void QTextEdit::setOverwriteMode(bool overwrite)
1863 {
1864     Q_D(QTextEdit);
1865     d->control->setOverwriteMode(overwrite);
1866 }
1867
1868 /*!
1869     \property QTextEdit::tabStopWidth
1870     \brief the tab stop width in pixels
1871     \since 4.1
1872
1873     By default, this property contains a value of 80 pixels.
1874 */
1875
1876 int QTextEdit::tabStopWidth() const
1877 {
1878     Q_D(const QTextEdit);
1879     return qRound(d->control->document()->defaultTextOption().tabStop());
1880 }
1881
1882 void QTextEdit::setTabStopWidth(int width)
1883 {
1884     Q_D(QTextEdit);
1885     QTextOption opt = d->control->document()->defaultTextOption();
1886     if (opt.tabStop() == width || width < 0)
1887         return;
1888     opt.setTabStop(width);
1889     d->control->document()->setDefaultTextOption(opt);
1890 }
1891
1892 /*!
1893     \since 4.2
1894     \property QTextEdit::cursorWidth
1895
1896     This property specifies the width of the cursor in pixels. The default value is 1.
1897 */
1898 int QTextEdit::cursorWidth() const
1899 {
1900     Q_D(const QTextEdit);
1901     return d->control->cursorWidth();
1902 }
1903
1904 void QTextEdit::setCursorWidth(int width)
1905 {
1906     Q_D(QTextEdit);
1907     d->control->setCursorWidth(width);
1908 }
1909
1910 /*!
1911     \property QTextEdit::acceptRichText
1912     \brief whether the text edit accepts rich text insertions by the user
1913     \since 4.1
1914
1915     When this propery is set to false text edit will accept only
1916     plain text input from the user. For example through clipboard or drag and drop.
1917
1918     This property's default is true.
1919 */
1920
1921 bool QTextEdit::acceptRichText() const
1922 {
1923     Q_D(const QTextEdit);
1924     return d->control->acceptRichText();
1925 }
1926
1927 void QTextEdit::setAcceptRichText(bool accept)
1928 {
1929     Q_D(QTextEdit);
1930     d->control->setAcceptRichText(accept);
1931 }
1932
1933 /*!
1934     \class QTextEdit::ExtraSelection
1935     \since 4.2
1936     \inmodule QtWidgets
1937
1938     \brief The QTextEdit::ExtraSelection structure provides a way of specifying a
1939            character format for a given selection in a document
1940 */
1941
1942 /*!
1943     \variable QTextEdit::ExtraSelection::cursor
1944     A cursor that contains a selection in a QTextDocument
1945 */
1946
1947 /*!
1948     \variable QTextEdit::ExtraSelection::format
1949     A format that is used to specify a foreground or background brush/color
1950     for the selection.
1951 */
1952
1953 /*!
1954     \since 4.2
1955     This function allows temporarily marking certain regions in the document
1956     with a given color, specified as \a selections. This can be useful for
1957     example in a programming editor to mark a whole line of text with a given
1958     background color to indicate the existence of a breakpoint.
1959
1960     \sa QTextEdit::ExtraSelection, extraSelections()
1961 */
1962 void QTextEdit::setExtraSelections(const QList<ExtraSelection> &selections)
1963 {
1964     Q_D(QTextEdit);
1965     d->control->setExtraSelections(selections);
1966 }
1967
1968 /*!
1969     \since 4.2
1970     Returns previously set extra selections.
1971
1972     \sa setExtraSelections()
1973 */
1974 QList<QTextEdit::ExtraSelection> QTextEdit::extraSelections() const
1975 {
1976     Q_D(const QTextEdit);
1977     return d->control->extraSelections();
1978 }
1979
1980 /*!
1981     This function returns a new MIME data object to represent the contents
1982     of the text edit's current selection. It is called when the selection needs
1983     to be encapsulated into a new QMimeData object; for example, when a drag
1984     and drop operation is started, or when data is copyied to the clipboard.
1985
1986     If you reimplement this function, note that the ownership of the returned
1987     QMimeData object is passed to the caller. The selection can be retrieved
1988     by using the textCursor() function.
1989 */
1990 QMimeData *QTextEdit::createMimeDataFromSelection() const
1991 {
1992     Q_D(const QTextEdit);
1993     return d->control->QWidgetTextControl::createMimeDataFromSelection();
1994 }
1995
1996 /*!
1997     This function returns true if the contents of the MIME data object, specified
1998     by \a source, can be decoded and inserted into the document. It is called
1999     for example when during a drag operation the mouse enters this widget and it
2000     is necessary to determine whether it is possible to accept the drag and drop
2001     operation.
2002
2003     Reimplement this function to enable drag and drop support for additional MIME types.
2004  */
2005 bool QTextEdit::canInsertFromMimeData(const QMimeData *source) const
2006 {
2007     Q_D(const QTextEdit);
2008     return d->control->QWidgetTextControl::canInsertFromMimeData(source);
2009 }
2010
2011 /*!
2012     This function inserts the contents of the MIME data object, specified
2013     by \a source, into the text edit at the current cursor position. It is
2014     called whenever text is inserted as the result of a clipboard paste
2015     operation, or when the text edit accepts data from a drag and drop
2016     operation.
2017
2018     Reimplement this function to enable drag and drop support for additional MIME types.
2019  */
2020 void QTextEdit::insertFromMimeData(const QMimeData *source)
2021 {
2022     Q_D(QTextEdit);
2023     d->control->QWidgetTextControl::insertFromMimeData(source);
2024 }
2025
2026 /*!
2027     \property QTextEdit::readOnly
2028     \brief whether the text edit is read-only
2029
2030     In a read-only text edit the user can only navigate through the
2031     text and select text; modifying the text is not possible.
2032
2033     This property's default is false.
2034 */
2035
2036 bool QTextEdit::isReadOnly() const
2037 {
2038     Q_D(const QTextEdit);
2039     return !(d->control->textInteractionFlags() & Qt::TextEditable);
2040 }
2041
2042 void QTextEdit::setReadOnly(bool ro)
2043 {
2044     Q_D(QTextEdit);
2045     Qt::TextInteractionFlags flags = Qt::NoTextInteraction;
2046     if (ro) {
2047         flags = Qt::TextSelectableByMouse;
2048 #ifndef QT_NO_TEXTBROWSER
2049         if (qobject_cast<QTextBrowser *>(this))
2050             flags |= Qt::TextBrowserInteraction;
2051 #endif
2052     } else {
2053         flags = Qt::TextEditorInteraction;
2054     }
2055     d->control->setTextInteractionFlags(flags);
2056     setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this));
2057 }
2058
2059 /*!
2060     \property QTextEdit::textInteractionFlags
2061     \since 4.2
2062
2063     Specifies how the widget should interact with user input.
2064
2065     The default value depends on whether the QTextEdit is read-only
2066     or editable, and whether it is a QTextBrowser or not.
2067 */
2068
2069 void QTextEdit::setTextInteractionFlags(Qt::TextInteractionFlags flags)
2070 {
2071     Q_D(QTextEdit);
2072     d->control->setTextInteractionFlags(flags);
2073 }
2074
2075 Qt::TextInteractionFlags QTextEdit::textInteractionFlags() const
2076 {
2077     Q_D(const QTextEdit);
2078     return d->control->textInteractionFlags();
2079 }
2080
2081 /*!
2082     Merges the properties specified in \a modifier into the current character
2083     format by calling QTextCursor::mergeCharFormat on the editor's cursor.
2084     If the editor has a selection then the properties of \a modifier are
2085     directly applied to the selection.
2086
2087     \sa QTextCursor::mergeCharFormat()
2088  */
2089 void QTextEdit::mergeCurrentCharFormat(const QTextCharFormat &modifier)
2090 {
2091     Q_D(QTextEdit);
2092     d->control->mergeCurrentCharFormat(modifier);
2093 }
2094
2095 /*!
2096     Sets the char format that is be used when inserting new text to \a
2097     format by calling QTextCursor::setCharFormat() on the editor's
2098     cursor.  If the editor has a selection then the char format is
2099     directly applied to the selection.
2100  */
2101 void QTextEdit::setCurrentCharFormat(const QTextCharFormat &format)
2102 {
2103     Q_D(QTextEdit);
2104     d->control->setCurrentCharFormat(format);
2105 }
2106
2107 /*!
2108     Returns the char format that is used when inserting new text.
2109  */
2110 QTextCharFormat QTextEdit::currentCharFormat() const
2111 {
2112     Q_D(const QTextEdit);
2113     return d->control->currentCharFormat();
2114 }
2115
2116 /*!
2117     \property QTextEdit::autoFormatting
2118     \brief the enabled set of auto formatting features
2119
2120     The value can be any combination of the values in the
2121     AutoFormattingFlag enum.  The default is AutoNone. Choose
2122     AutoAll to enable all automatic formatting.
2123
2124     Currently, the only automatic formatting feature provided is
2125     AutoBulletList; future versions of Qt may offer more.
2126 */
2127
2128 QTextEdit::AutoFormatting QTextEdit::autoFormatting() const
2129 {
2130     Q_D(const QTextEdit);
2131     return d->autoFormatting;
2132 }
2133
2134 void QTextEdit::setAutoFormatting(AutoFormatting features)
2135 {
2136     Q_D(QTextEdit);
2137     d->autoFormatting = features;
2138 }
2139
2140 /*!
2141     Convenience slot that inserts \a text at the current
2142     cursor position.
2143
2144     It is equivalent to
2145
2146     \snippet doc/src/snippets/code/src_gui_widgets_qtextedit.cpp 1
2147  */
2148 void QTextEdit::insertPlainText(const QString &text)
2149 {
2150     Q_D(QTextEdit);
2151     d->control->insertPlainText(text);
2152 }
2153
2154 /*!
2155     Convenience slot that inserts \a text which is assumed to be of
2156     html formatting at the current cursor position.
2157
2158     It is equivalent to:
2159
2160     \snippet doc/src/snippets/code/src_gui_widgets_qtextedit.cpp 2
2161
2162     \note When using this function with a style sheet, the style sheet will
2163     only apply to the current block in the document. In order to apply a style
2164     sheet throughout a document, use QTextDocument::setDefaultStyleSheet()
2165     instead.
2166  */
2167 #ifndef QT_NO_TEXTHTMLPARSER
2168 void QTextEdit::insertHtml(const QString &text)
2169 {
2170     Q_D(QTextEdit);
2171     d->control->insertHtml(text);
2172 }
2173 #endif // QT_NO_TEXTHTMLPARSER
2174
2175 /*!
2176     Scrolls the text edit so that the anchor with the given \a name is
2177     visible; does nothing if the \a name is empty, or is already
2178     visible, or isn't found.
2179 */
2180 void QTextEdit::scrollToAnchor(const QString &name)
2181 {
2182     Q_D(QTextEdit);
2183     if (name.isEmpty())
2184         return;
2185
2186     if (!isVisible()) {
2187         d->anchorToScrollToWhenVisible = name;
2188         return;
2189     }
2190
2191     QPointF p = d->control->anchorPosition(name);
2192     const int newPosition = qRound(p.y());
2193     if ( d->vbar->maximum() < newPosition )
2194         d->_q_adjustScrollbars();
2195     d->vbar->setValue(newPosition);
2196 }
2197
2198 /*!
2199     \fn QTextEdit::zoomIn(int range)
2200
2201     Zooms in on the text by making the base font size \a range
2202     points larger and recalculating all font sizes to be the new size.
2203     This does not change the size of any images.
2204
2205     \sa zoomOut()
2206 */
2207 void QTextEdit::zoomIn(int range)
2208 {
2209     QFont f = font();
2210     const int newSize = f.pointSize() + range;
2211     if (newSize <= 0)
2212         return;
2213     f.setPointSize(newSize);
2214     setFont(f);
2215 }
2216
2217 /*!
2218     \fn QTextEdit::zoomOut(int range)
2219
2220     \overload
2221
2222     Zooms out on the text by making the base font size \a range points
2223     smaller and recalculating all font sizes to be the new size. This
2224     does not change the size of any images.
2225
2226     \sa zoomIn()
2227 */
2228 void QTextEdit::zoomOut(int range)
2229 {
2230     zoomIn(-range);
2231 }
2232
2233 /*!
2234     \since 4.2
2235     Moves the cursor by performing the given \a operation.
2236
2237     If \a mode is QTextCursor::KeepAnchor, the cursor selects the text it moves over.
2238     This is the same effect that the user achieves when they hold down the Shift key
2239     and move the cursor with the cursor keys.
2240
2241     \sa QTextCursor::movePosition()
2242 */
2243 void QTextEdit::moveCursor(QTextCursor::MoveOperation operation, QTextCursor::MoveMode mode)
2244 {
2245     Q_D(QTextEdit);
2246     d->control->moveCursor(operation, mode);
2247 }
2248
2249 /*!
2250     \since 4.2
2251     Returns whether text can be pasted from the clipboard into the textedit.
2252 */
2253 bool QTextEdit::canPaste() const
2254 {
2255     Q_D(const QTextEdit);
2256     return d->control->canPaste();
2257 }
2258
2259 /*!
2260     \since 4.3
2261     Convenience function to print the text edit's document to the given \a printer. This
2262     is equivalent to calling the print method on the document directly except that this
2263     function also supports QPrinter::Selection as print range.
2264
2265     \sa QTextDocument::print()
2266 */
2267 #ifndef QT_NO_PRINTER
2268 void QTextEdit::print(QPagedPaintDevice *printer) const
2269 {
2270     Q_D(const QTextEdit);
2271     d->control->print(printer);
2272 }
2273 #endif
2274
2275 /*! \property QTextEdit::tabChangesFocus
2276   \brief whether \gui Tab changes focus or is accepted as input
2277
2278   In some occasions text edits should not allow the user to input
2279   tabulators or change indentation using the \gui Tab key, as this breaks
2280   the focus chain. The default is false.
2281
2282 */
2283
2284 bool QTextEdit::tabChangesFocus() const
2285 {
2286     Q_D(const QTextEdit);
2287     return d->tabChangesFocus;
2288 }
2289
2290 void QTextEdit::setTabChangesFocus(bool b)
2291 {
2292     Q_D(QTextEdit);
2293     d->tabChangesFocus = b;
2294 }
2295
2296 /*!
2297     \property QTextEdit::documentTitle
2298     \brief the title of the document parsed from the text.
2299
2300     By default, for a newly-created, empty document, this property contains
2301     an empty string.
2302 */
2303
2304 /*!
2305     \property QTextEdit::lineWrapMode
2306     \brief the line wrap mode
2307
2308     The default mode is WidgetWidth which causes words to be
2309     wrapped at the right edge of the text edit. Wrapping occurs at
2310     whitespace, keeping whole words intact. If you want wrapping to
2311     occur within words use setWordWrapMode(). If you set a wrap mode of
2312     FixedPixelWidth or FixedColumnWidth you should also call
2313     setLineWrapColumnOrWidth() with the width you want.
2314
2315     \sa lineWrapColumnOrWidth
2316 */
2317
2318 QTextEdit::LineWrapMode QTextEdit::lineWrapMode() const
2319 {
2320     Q_D(const QTextEdit);
2321     return d->lineWrap;
2322 }
2323
2324 void QTextEdit::setLineWrapMode(LineWrapMode wrap)
2325 {
2326     Q_D(QTextEdit);
2327     if (d->lineWrap == wrap)
2328         return;
2329     d->lineWrap = wrap;
2330     d->updateDefaultTextOption();
2331     d->relayoutDocument();
2332 }
2333
2334 /*!
2335     \property QTextEdit::lineWrapColumnOrWidth
2336     \brief the position (in pixels or columns depending on the wrap mode) where text will be wrapped
2337
2338     If the wrap mode is FixedPixelWidth, the value is the number of
2339     pixels from the left edge of the text edit at which text should be
2340     wrapped. If the wrap mode is FixedColumnWidth, the value is the
2341     column number (in character columns) from the left edge of the
2342     text edit at which text should be wrapped.
2343
2344     By default, this property contains a value of 0.
2345
2346     \sa lineWrapMode
2347 */
2348
2349 int QTextEdit::lineWrapColumnOrWidth() const
2350 {
2351     Q_D(const QTextEdit);
2352     return d->lineWrapColumnOrWidth;
2353 }
2354
2355 void QTextEdit::setLineWrapColumnOrWidth(int w)
2356 {
2357     Q_D(QTextEdit);
2358     d->lineWrapColumnOrWidth = w;
2359     d->relayoutDocument();
2360 }
2361
2362 /*!
2363     \property QTextEdit::wordWrapMode
2364     \brief the mode QTextEdit will use when wrapping text by words
2365
2366     By default, this property is set to QTextOption::WrapAtWordBoundaryOrAnywhere.
2367
2368     \sa QTextOption::WrapMode
2369 */
2370
2371 QTextOption::WrapMode QTextEdit::wordWrapMode() const
2372 {
2373     Q_D(const QTextEdit);
2374     return d->wordWrap;
2375 }
2376
2377 void QTextEdit::setWordWrapMode(QTextOption::WrapMode mode)
2378 {
2379     Q_D(QTextEdit);
2380     if (mode == d->wordWrap)
2381         return;
2382     d->wordWrap = mode;
2383     d->updateDefaultTextOption();
2384 }
2385
2386 /*!
2387     Finds the next occurrence of the string, \a exp, using the given
2388     \a options. Returns true if \a exp was found and changes the
2389     cursor to select the match; otherwise returns false.
2390 */
2391 bool QTextEdit::find(const QString &exp, QTextDocument::FindFlags options)
2392 {
2393     Q_D(QTextEdit);
2394     return d->control->find(exp, options);
2395 }
2396
2397 /*!
2398     \fn void QTextEdit::copyAvailable(bool yes)
2399
2400     This signal is emitted when text is selected or de-selected in the
2401     text edit.
2402
2403     When text is selected this signal will be emitted with \a yes set
2404     to true. If no text has been selected or if the selected text is
2405     de-selected this signal is emitted with \a yes set to false.
2406
2407     If \a yes is true then copy() can be used to copy the selection to
2408     the clipboard. If \a yes is false then copy() does nothing.
2409
2410     \sa selectionChanged()
2411 */
2412
2413 /*!
2414     \fn void QTextEdit::currentCharFormatChanged(const QTextCharFormat &f)
2415
2416     This signal is emitted if the current character format has changed, for
2417     example caused by a change of the cursor position.
2418
2419     The new format is \a f.
2420
2421     \sa setCurrentCharFormat()
2422 */
2423
2424 /*!
2425     \fn void QTextEdit::selectionChanged()
2426
2427     This signal is emitted whenever the selection changes.
2428
2429     \sa copyAvailable()
2430 */
2431
2432 /*!
2433     \fn void QTextEdit::cursorPositionChanged()
2434
2435     This signal is emitted whenever the position of the
2436     cursor changed.
2437 */
2438
2439 /*!
2440     \since 4.2
2441
2442     Sets the text edit's \a text. The text can be plain text or HTML
2443     and the text edit will try to guess the right format.
2444
2445     Use setHtml() or setPlainText() directly to avoid text edit's guessing.
2446
2447     \sa toPlainText(), toHtml()
2448 */
2449 void QTextEdit::setText(const QString &text)
2450 {
2451     Q_D(QTextEdit);
2452     Qt::TextFormat format = d->textFormat;
2453     if (d->textFormat == Qt::AutoText)
2454         format = Qt::mightBeRichText(text) ? Qt::RichText : Qt::PlainText;
2455 #ifndef QT_NO_TEXTHTMLPARSER
2456     if (format == Qt::RichText || format == Qt::LogText)
2457         setHtml(text);
2458     else
2459 #endif
2460         setPlainText(text);
2461 }
2462
2463
2464 /*!
2465     Appends a new paragraph with \a text to the end of the text edit.
2466
2467     \note The new paragraph appended will have the same character format and
2468     block format as the current paragraph, determined by the position of the cursor.
2469
2470     \sa currentCharFormat(), QTextCursor::blockFormat()
2471 */
2472
2473 void QTextEdit::append(const QString &text)
2474 {
2475     Q_D(QTextEdit);
2476     const bool atBottom = isReadOnly() ?  d->verticalOffset() >= d->vbar->maximum() :
2477             d->control->textCursor().atEnd();
2478     d->control->append(text);
2479     if (atBottom)
2480         d->vbar->setValue(d->vbar->maximum());
2481 }
2482
2483 /*!
2484     Ensures that the cursor is visible by scrolling the text edit if
2485     necessary.
2486 */
2487 void QTextEdit::ensureCursorVisible()
2488 {
2489     Q_D(QTextEdit);
2490     d->control->ensureCursorVisible();
2491 }
2492
2493 /*!
2494     \enum QTextEdit::KeyboardAction
2495
2496     \compat
2497
2498     \value ActionBackspace
2499     \value ActionDelete
2500     \value ActionReturn
2501     \value ActionKill
2502     \value ActionWordBackspace
2503     \value ActionWordDelete
2504 */
2505
2506 /*!
2507     \fn bool QTextEdit::find(const QString &exp, bool cs, bool wo)
2508
2509     Use the find() overload that takes a QTextDocument::FindFlags
2510     argument.
2511 */
2512
2513 /*!
2514     \fn void QTextEdit::sync()
2515
2516     Does nothing.
2517 */
2518
2519 /*!
2520     \fn void QTextEdit::setBold(bool b)
2521
2522     Use setFontWeight() instead.
2523 */
2524
2525 /*!
2526     \fn void QTextEdit::setUnderline(bool b)
2527
2528     Use setFontUnderline() instead.
2529 */
2530
2531 /*!
2532     \fn void QTextEdit::setItalic(bool i)
2533
2534     Use setFontItalic() instead.
2535 */
2536
2537 /*!
2538     \fn void QTextEdit::setFamily(const QString &family)
2539
2540     Use setFontFamily() instead.
2541 */
2542
2543 /*!
2544     \fn void QTextEdit::setPointSize(int size)
2545
2546     Use setFontPointSize() instead.
2547 */
2548
2549 /*!
2550     \fn bool QTextEdit::italic() const
2551
2552     Use fontItalic() instead.
2553 */
2554
2555 /*!
2556     \fn bool QTextEdit::bold() const
2557
2558     Use fontWeight() >= QFont::Bold instead.
2559 */
2560
2561 /*!
2562     \fn bool QTextEdit::underline() const
2563
2564     Use fontUnderline() instead.
2565 */
2566
2567 /*!
2568     \fn QString QTextEdit::family() const
2569
2570     Use fontFamily() instead.
2571 */
2572
2573 /*!
2574     \fn int QTextEdit::pointSize() const
2575
2576     Use int(fontPointSize()+0.5) instead.
2577 */
2578
2579 /*!
2580     \fn bool QTextEdit::hasSelectedText() const
2581
2582     Use textCursor().hasSelection() instead.
2583 */
2584
2585 /*!
2586     \fn QString QTextEdit::selectedText() const
2587
2588     Use textCursor().selectedText() instead.
2589 */
2590
2591 /*!
2592     \fn bool QTextEdit::isUndoAvailable() const
2593
2594     Use document()->isUndoAvailable() instead.
2595 */
2596
2597 /*!
2598     \fn bool QTextEdit::isRedoAvailable() const
2599
2600     Use document()->isRedoAvailable() instead.
2601 */
2602
2603 /*!
2604     \fn void QTextEdit::insert(const QString &text)
2605
2606     Use insertPlainText() instead.
2607 */
2608
2609 /*!
2610     \fn bool QTextEdit::isModified() const
2611
2612     Use document()->isModified() instead.
2613 */
2614
2615 /*!
2616     \fn QColor QTextEdit::color() const
2617
2618     Use textColor() instead.
2619 */
2620
2621 /*!
2622     \fn void QTextEdit::textChanged()
2623
2624     This signal is emitted whenever the document's content changes; for
2625     example, when text is inserted or deleted, or when formatting is applied.
2626 */
2627
2628 /*!
2629     \fn void QTextEdit::undoAvailable(bool available)
2630
2631     This signal is emitted whenever undo operations become available
2632     (\a available is true) or unavailable (\a available is false).
2633 */
2634
2635 /*!
2636     \fn void QTextEdit::redoAvailable(bool available)
2637
2638     This signal is emitted whenever redo operations become available
2639     (\a available is true) or unavailable (\a available is false).
2640 */
2641
2642 /*!
2643     \fn void QTextEdit::currentFontChanged(const QFont &font)
2644
2645     Use currentCharFormatChanged() instead.
2646 */
2647
2648 /*!
2649     \fn void QTextEdit::currentColorChanged(const QColor &color)
2650
2651     Use currentCharFormatChanged() instead.
2652 */
2653
2654 /*!
2655     \fn void QTextEdit::setModified(bool m)
2656
2657     Use document->setModified() instead.
2658 */
2659
2660 /*!
2661     \fn void QTextEdit::setColor(const QColor &color)
2662
2663     Use setTextColor() instead.
2664 */
2665 #endif // QT_NO_TEXTEDIT
2666
2667 QT_END_NAMESPACE
2668
2669 #include "moc_qtextedit.cpp"