source: trunk/src/gui/widgets/qtextedit.cpp@ 769

Last change on this file since 769 was 651, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.2 sources.

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