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

Last change on this file since 138 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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