/**************************************************************************** | |
** | |
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). | |
** All rights reserved. | |
** Contact: Nokia Corporation (qt-info@nokia.com) | |
** | |
** This file is part of the QtGui module of the Qt Toolkit. | |
** | |
** $QT_BEGIN_LICENSE:LGPL$ | |
** GNU Lesser General Public License Usage | |
** This file may be used under the terms of the GNU Lesser General Public | |
** License version 2.1 as published by the Free Software Foundation and | |
** appearing in the file LICENSE.LGPL included in the packaging of this | |
** file. Please review the following information to ensure the GNU Lesser | |
** General Public License version 2.1 requirements will be met: | |
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | |
** | |
** In addition, as a special exception, Nokia gives you certain additional | |
** rights. These rights are described in the Nokia Qt LGPL Exception | |
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | |
** | |
** GNU General Public License Usage | |
** Alternatively, this file may be used under the terms of the GNU General | |
** Public License version 3.0 as published by the Free Software Foundation | |
** and appearing in the file LICENSE.GPL included in the packaging of this | |
** file. Please review the following information to ensure the GNU General | |
** Public License version 3.0 requirements will be met: | |
** http://www.gnu.org/copyleft/gpl.html. | |
** | |
** Other Usage | |
** Alternatively, this file may be used in accordance with the terms and | |
** conditions contained in a signed written agreement between you and Nokia. | |
** | |
** | |
** | |
** | |
** | |
** $QT_END_LICENSE$ | |
** | |
****************************************************************************/ | |
#include "qtextedit_p.h" | |
#include "qlineedit.h" | |
#include "qtextbrowser.h" | |
#ifndef QT_NO_TEXTEDIT | |
#include <qfont.h> | |
#include <qpainter.h> | |
#include <qevent.h> | |
#include <qdebug.h> | |
#include <qmime.h> | |
#include <qdrag.h> | |
#include <qclipboard.h> | |
#include <qmenu.h> | |
#include <qstyle.h> | |
#include <qtimer.h> | |
#include "private/qtextdocumentlayout_p.h" | |
#include "qtextdocument.h" | |
#include "private/qtextdocument_p.h" | |
#include "qtextlist.h" | |
#include "private/qtextcontrol_p.h" | |
#include <qtextformat.h> | |
#include <qdatetime.h> | |
#include <qapplication.h> | |
#include <limits.h> | |
#include <qtexttable.h> | |
#include <qvariant.h> | |
#include <qinputcontext.h> | |
#endif | |
QT_BEGIN_NAMESPACE | |
#ifndef QT_NO_TEXTEDIT | |
static inline bool shouldEnableInputMethod(QTextEdit *textedit) | |
{ | |
return !textedit->isReadOnly(); | |
} | |
class QTextEditControl : public QTextControl | |
{ | |
public: | |
inline QTextEditControl(QObject *parent) : QTextControl(parent) {} | |
virtual QMimeData *createMimeDataFromSelection() const { | |
QTextEdit *ed = qobject_cast<QTextEdit *>(parent()); | |
if (!ed) | |
return QTextControl::createMimeDataFromSelection(); | |
return ed->createMimeDataFromSelection(); | |
} | |
virtual bool canInsertFromMimeData(const QMimeData *source) const { | |
QTextEdit *ed = qobject_cast<QTextEdit *>(parent()); | |
if (!ed) | |
return QTextControl::canInsertFromMimeData(source); | |
return ed->canInsertFromMimeData(source); | |
} | |
virtual void insertFromMimeData(const QMimeData *source) { | |
QTextEdit *ed = qobject_cast<QTextEdit *>(parent()); | |
if (!ed) | |
QTextControl::insertFromMimeData(source); | |
else | |
ed->insertFromMimeData(source); | |
} | |
}; | |
QTextEditPrivate::QTextEditPrivate() | |
: control(0), | |
autoFormatting(QTextEdit::AutoNone), tabChangesFocus(false), | |
lineWrap(QTextEdit::WidgetWidth), lineWrapColumnOrWidth(0), | |
wordWrap(QTextOption::WrapAtWordBoundaryOrAnywhere), clickCausedFocus(0), | |
textFormat(Qt::AutoText) | |
{ | |
ignoreAutomaticScrollbarAdjustment = false; | |
preferRichText = false; | |
showCursorOnInitialShow = true; | |
inDrag = false; | |
} | |
void QTextEditPrivate::createAutoBulletList() | |
{ | |
QTextCursor cursor = control->textCursor(); | |
cursor.beginEditBlock(); | |
QTextBlockFormat blockFmt = cursor.blockFormat(); | |
QTextListFormat listFmt; | |
listFmt.setStyle(QTextListFormat::ListDisc); | |
listFmt.setIndent(blockFmt.indent() + 1); | |
blockFmt.setIndent(0); | |
cursor.setBlockFormat(blockFmt); | |
cursor.createList(listFmt); | |
cursor.endEditBlock(); | |
control->setTextCursor(cursor); | |
} | |
void QTextEditPrivate::init(const QString &html) | |
{ | |
Q_Q(QTextEdit); | |
control = new QTextEditControl(q); | |
control->setPalette(q->palette()); | |
QObject::connect(control, SIGNAL(microFocusChanged()), q, SLOT(updateMicroFocus())); | |
QObject::connect(control, SIGNAL(documentSizeChanged(QSizeF)), q, SLOT(_q_adjustScrollbars())); | |
QObject::connect(control, SIGNAL(updateRequest(QRectF)), q, SLOT(_q_repaintContents(QRectF))); | |
QObject::connect(control, SIGNAL(visibilityRequest(QRectF)), q, SLOT(_q_ensureVisible(QRectF))); | |
QObject::connect(control, SIGNAL(currentCharFormatChanged(QTextCharFormat)), | |
q, SLOT(_q_currentCharFormatChanged(QTextCharFormat))); | |
QObject::connect(control, SIGNAL(textChanged()), q, SIGNAL(textChanged())); | |
QObject::connect(control, SIGNAL(undoAvailable(bool)), q, SIGNAL(undoAvailable(bool))); | |
QObject::connect(control, SIGNAL(redoAvailable(bool)), q, SIGNAL(redoAvailable(bool))); | |
QObject::connect(control, SIGNAL(copyAvailable(bool)), q, SIGNAL(copyAvailable(bool))); | |
QObject::connect(control, SIGNAL(selectionChanged()), q, SIGNAL(selectionChanged())); | |
QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorPositionChanged())); | |
QObject::connect(control, SIGNAL(textChanged()), q, SLOT(updateMicroFocus())); | |
QTextDocument *doc = control->document(); | |
// set a null page size initially to avoid any relayouting until the textedit | |
// is shown. relayoutDocument() will take care of setting the page size to the | |
// viewport dimensions later. | |
doc->setPageSize(QSize(0, 0)); | |
doc->documentLayout()->setPaintDevice(viewport); | |
doc->setDefaultFont(q->font()); | |
doc->setUndoRedoEnabled(false); // flush undo buffer. | |
doc->setUndoRedoEnabled(true); | |
if (!html.isEmpty()) | |
control->setHtml(html); | |
hbar->setSingleStep(20); | |
vbar->setSingleStep(20); | |
viewport->setBackgroundRole(QPalette::Base); | |
q->setAcceptDrops(true); | |
q->setFocusPolicy(Qt::WheelFocus); | |
q->setAttribute(Qt::WA_KeyCompression); | |
q->setAttribute(Qt::WA_InputMethodEnabled); | |
#ifndef QT_NO_CURSOR | |
viewport->setCursor(Qt::IBeamCursor); | |
#endif | |
#ifdef Q_WS_WIN | |
setSingleFingerPanEnabled(true); | |
#endif | |
} | |
void QTextEditPrivate::_q_repaintContents(const QRectF &contentsRect) | |
{ | |
if (!contentsRect.isValid()) { | |
viewport->update(); | |
return; | |
} | |
const int xOffset = horizontalOffset(); | |
const int yOffset = verticalOffset(); | |
const QRectF visibleRect(xOffset, yOffset, viewport->width(), viewport->height()); | |
QRect r = contentsRect.intersected(visibleRect).toAlignedRect(); | |
if (r.isEmpty()) | |
return; | |
r.translate(-xOffset, -yOffset); | |
viewport->update(r); | |
} | |
void QTextEditPrivate::pageUpDown(QTextCursor::MoveOperation op, QTextCursor::MoveMode moveMode) | |
{ | |
QTextCursor cursor = control->textCursor(); | |
bool moved = false; | |
qreal lastY = control->cursorRect(cursor).top(); | |
qreal distance = 0; | |
// move using movePosition to keep the cursor's x | |
do { | |
qreal y = control->cursorRect(cursor).top(); | |
distance += qAbs(y - lastY); | |
lastY = y; | |
moved = cursor.movePosition(op, moveMode); | |
} while (moved && distance < viewport->height()); | |
if (moved) { | |
if (op == QTextCursor::Up) { | |
cursor.movePosition(QTextCursor::Down, moveMode); | |
vbar->triggerAction(QAbstractSlider::SliderPageStepSub); | |
} else { | |
cursor.movePosition(QTextCursor::Up, moveMode); | |
vbar->triggerAction(QAbstractSlider::SliderPageStepAdd); | |
} | |
} | |
control->setTextCursor(cursor); | |
} | |
#ifndef QT_NO_SCROLLBAR | |
static QSize documentSize(QTextControl *control) | |
{ | |
QTextDocument *doc = control->document(); | |
QAbstractTextDocumentLayout *layout = doc->documentLayout(); | |
QSize docSize; | |
if (QTextDocumentLayout *tlayout = qobject_cast<QTextDocumentLayout *>(layout)) { | |
docSize = tlayout->dynamicDocumentSize().toSize(); | |
int percentageDone = tlayout->layoutStatus(); | |
// extrapolate height | |
if (percentageDone > 0) | |
docSize.setHeight(docSize.height() * 100 / percentageDone); | |
} else { | |
docSize = layout->documentSize().toSize(); | |
} | |
return docSize; | |
} | |
void QTextEditPrivate::_q_adjustScrollbars() | |
{ | |
if (ignoreAutomaticScrollbarAdjustment) | |
return; | |
ignoreAutomaticScrollbarAdjustment = true; // avoid recursion, #106108 | |
QSize viewportSize = viewport->size(); | |
QSize docSize = documentSize(control); | |
// due to the recursion guard we have to repeat this step a few times, | |
// as adding/removing a scroll bar will cause the document or viewport | |
// size to change | |
// ideally we should loop until the viewport size and doc size stabilize, | |
// but in corner cases they might fluctuate, so we need to limit the | |
// number of iterations | |
for (int i = 0; i < 4; ++i) { | |
hbar->setRange(0, docSize.width() - viewportSize.width()); | |
hbar->setPageStep(viewportSize.width()); | |
vbar->setRange(0, docSize.height() - viewportSize.height()); | |
vbar->setPageStep(viewportSize.height()); | |
// if we are in left-to-right mode widening the document due to | |
// lazy layouting does not require a repaint. If in right-to-left | |
// the scroll bar has the value zero and it visually has the maximum | |
// value (it is visually at the right), then widening the document | |
// keeps it at value zero but visually adjusts it to the new maximum | |
// on the right, hence we need an update. | |
if (q_func()->isRightToLeft()) | |
viewport->update(); | |
_q_showOrHideScrollBars(); | |
const QSize oldViewportSize = viewportSize; | |
const QSize oldDocSize = docSize; | |
// make sure the document is layouted if the viewport width changes | |
viewportSize = viewport->size(); | |
if (viewportSize.width() != oldViewportSize.width()) | |
relayoutDocument(); | |
docSize = documentSize(control); | |
if (viewportSize == oldViewportSize && docSize == oldDocSize) | |
break; | |
} | |
ignoreAutomaticScrollbarAdjustment = false; | |
} | |
#endif | |
// rect is in content coordinates | |
void QTextEditPrivate::_q_ensureVisible(const QRectF &_rect) | |
{ | |
const QRect rect = _rect.toRect(); | |
if ((vbar->isVisible() && vbar->maximum() < rect.bottom()) | |
|| (hbar->isVisible() && hbar->maximum() < rect.right())) | |
_q_adjustScrollbars(); | |
const int visibleWidth = viewport->width(); | |
const int visibleHeight = viewport->height(); | |
const bool rtl = q_func()->isRightToLeft(); | |
if (rect.x() < horizontalOffset()) { | |
if (rtl) | |
hbar->setValue(hbar->maximum() - rect.x()); | |
else | |
hbar->setValue(rect.x()); | |
} else if (rect.x() + rect.width() > horizontalOffset() + visibleWidth) { | |
if (rtl) | |
hbar->setValue(hbar->maximum() - (rect.x() + rect.width() - visibleWidth)); | |
else | |
hbar->setValue(rect.x() + rect.width() - visibleWidth); | |
} | |
if (rect.y() < verticalOffset()) | |
vbar->setValue(rect.y()); | |
else if (rect.y() + rect.height() > verticalOffset() + visibleHeight) | |
vbar->setValue(rect.y() + rect.height() - visibleHeight); | |
} | |
/*! | |
\class QTextEdit | |
\brief The QTextEdit class provides a widget that is used to edit and display | |
both plain and rich text. | |
\ingroup richtext-processing | |
\tableofcontents | |
\section1 Introduction and Concepts | |
QTextEdit is an advanced WYSIWYG viewer/editor supporting rich | |
text formatting using HTML-style tags. It is optimized to handle | |
large documents and to respond quickly to user input. | |
QTextEdit works on paragraphs and characters. A paragraph is a | |
formatted string which is word-wrapped to fit into the width of | |
the widget. By default when reading plain text, one newline | |
signifies a paragraph. A document consists of zero or more | |
paragraphs. The words in the paragraph are aligned in accordance | |
with the paragraph's alignment. Paragraphs are separated by hard | |
line breaks. Each character within a paragraph has its own | |
attributes, for example, font and color. | |
QTextEdit can display images, lists and tables. If the text is | |
too large to view within the text edit's viewport, scroll bars will | |
appear. The text edit can load both plain text and HTML files (a | |
subset of HTML 3.2 and 4). | |
If you just need to display a small piece of rich text use QLabel. | |
The rich text support in Qt is designed to provide a fast, portable and | |
efficient way to add reasonable online help facilities to | |
applications, and to provide a basis for rich text editors. If | |
you find the HTML support insufficient for your needs you may consider | |
the use of QtWebKit, which provides a full-featured web browser | |
widget. | |
The shape of the mouse cursor on a QTextEdit is Qt::IBeamCursor by default. | |
It can be changed through the viewport()'s cursor property. | |
\section1 Using QTextEdit as a Display Widget | |
QTextEdit can display a large HTML subset, including tables and | |
images. | |
The text is set or replaced using setHtml() which deletes any | |
existing text and replaces it with the text passed in the | |
setHtml() call. If you call setHtml() with legacy HTML, and then | |
call toHtml(), the text that is returned may have different markup, | |
but will render the same. The entire text can be deleted with clear(). | |
Text itself can be inserted using the QTextCursor class or using the | |
convenience functions insertHtml(), insertPlainText(), append() or | |
paste(). QTextCursor is also able to insert complex objects like tables | |
or lists into the document, and it deals with creating selections | |
and applying changes to selected text. | |
By default the text edit wraps words at whitespace to fit within | |
the text edit widget. The setLineWrapMode() function is used to | |
specify the kind of line wrap you want, or \l NoWrap if you don't | |
want any wrapping. Call setLineWrapMode() to set a fixed pixel width | |
\l FixedPixelWidth, or character column (e.g. 80 column) \l | |
FixedColumnWidth with the pixels or columns specified with | |
setLineWrapColumnOrWidth(). If you use word wrap to the widget's width | |
\l WidgetWidth, you can specify whether to break on whitespace or | |
anywhere with setWordWrapMode(). | |
The find() function can be used to find and select a given string | |
within the text. | |
If you want to limit the total number of paragraphs in a QTextEdit, | |
as it is for example open useful in a log viewer, then you can use | |
QTextDocument's maximumBlockCount property for that. | |
\section2 Read-only Key Bindings | |
When QTextEdit is used read-only the key bindings are limited to | |
navigation, and text may only be selected with the mouse: | |
\table | |
\header \i Keypresses \i Action | |
\row \i Up \i Moves one line up. | |
\row \i Down \i Moves one line down. | |
\row \i Left \i Moves one character to the left. | |
\row \i Right \i Moves one character to the right. | |
\row \i PageUp \i Moves one (viewport) page up. | |
\row \i PageDown \i Moves one (viewport) page down. | |
\row \i Home \i Moves to the beginning of the text. | |
\row \i End \i Moves to the end of the text. | |
\row \i Alt+Wheel | |
\i Scrolls the page horizontally (the Wheel is the mouse wheel). | |
\row \i Ctrl+Wheel \i Zooms the text. | |
\row \i Ctrl+A \i Selects all text. | |
\endtable | |
The text edit may be able to provide some meta-information. For | |
example, the documentTitle() function will return the text from | |
within HTML \c{<title>} tags. | |
\section1 Using QTextEdit as an Editor | |
All the information about using QTextEdit as a display widget also | |
applies here. | |
The current char format's attributes are set with setFontItalic(), | |
setFontWeight(), setFontUnderline(), setFontFamily(), | |
setFontPointSize(), setTextColor() and setCurrentFont(). The current | |
paragraph's alignment is set with setAlignment(). | |
Selection of text is handled by the QTextCursor class, which provides | |
functionality for creating selections, retrieving the text contents or | |
deleting selections. You can retrieve the object that corresponds with | |
the user-visible cursor using the textCursor() method. If you want to set | |
a selection in QTextEdit just create one on a QTextCursor object and | |
then make that cursor the visible cursor using setTextCursor(). The selection | |
can be copied to the clipboard with copy(), or cut to the clipboard with | |
cut(). The entire text can be selected using selectAll(). | |
When the cursor is moved and the underlying formatting attributes change, | |
the currentCharFormatChanged() signal is emitted to reflect the new attributes | |
at the new cursor position. | |
QTextEdit holds a QTextDocument object which can be retrieved using the | |
document() method. You can also set your own document object using setDocument(). | |
QTextDocument emits a textChanged() signal if the text changes and it also | |
provides a isModified() function which will return true if the text has been | |
modified since it was either loaded or since the last call to setModified | |
with false as argument. In addition it provides methods for undo and redo. | |
\section2 Drag and Drop | |
QTextEdit also supports custom drag and drop behavior. By default, | |
QTextEdit will insert plain text, HTML and rich text when the user drops | |
data of these MIME types onto a document. Reimplement | |
canInsertFromMimeData() and insertFromMimeData() to add support for | |
additional MIME types. | |
For example, to allow the user to drag and drop an image onto a QTextEdit, | |
you could the implement these functions in the following way: | |
\snippet doc/src/snippets/textdocument-imagedrop/textedit.cpp 0 | |
We add support for image MIME types by returning true. For all other | |
MIME types, we use the default implementation. | |
\snippet doc/src/snippets/textdocument-imagedrop/textedit.cpp 1 | |
We unpack the image from the QVariant held by the MIME source and insert | |
it into the document as a resource. | |
\section2 Editing Key Bindings | |
The list of key bindings which are implemented for editing: | |
\table | |
\header \i Keypresses \i Action | |
\row \i Backspace \i Deletes the character to the left of the cursor. | |
\row \i Delete \i Deletes the character to the right of the cursor. | |
\row \i Ctrl+C \i Copy the selected text to the clipboard. | |
\row \i Ctrl+Insert \i Copy the selected text to the clipboard. | |
\row \i Ctrl+K \i Deletes to the end of the line. | |
\row \i Ctrl+V \i Pastes the clipboard text into text edit. | |
\row \i Shift+Insert \i Pastes the clipboard text into text edit. | |
\row \i Ctrl+X \i Deletes the selected text and copies it to the clipboard. | |
\row \i Shift+Delete \i Deletes the selected text and copies it to the clipboard. | |
\row \i Ctrl+Z \i Undoes the last operation. | |
\row \i Ctrl+Y \i Redoes the last operation. | |
\row \i Left \i Moves the cursor one character to the left. | |
\row \i Ctrl+Left \i Moves the cursor one word to the left. | |
\row \i Right \i Moves the cursor one character to the right. | |
\row \i Ctrl+Right \i Moves the cursor one word to the right. | |
\row \i Up \i Moves the cursor one line up. | |
\row \i Down \i Moves the cursor one line down. | |
\row \i PageUp \i Moves the cursor one page up. | |
\row \i PageDown \i Moves the cursor one page down. | |
\row \i Home \i Moves the cursor to the beginning of the line. | |
\row \i Ctrl+Home \i Moves the cursor to the beginning of the text. | |
\row \i End \i Moves the cursor to the end of the line. | |
\row \i Ctrl+End \i Moves the cursor to the end of the text. | |
\row \i Alt+Wheel \i Scrolls the page horizontally (the Wheel is the mouse wheel). | |
\endtable | |
To select (mark) text hold down the Shift key whilst pressing one | |
of the movement keystrokes, for example, \e{Shift+Right} | |
will select the character to the right, and \e{Shift+Ctrl+Right} will select the word to the right, etc. | |
\sa QTextDocument, QTextCursor, {Application Example}, | |
{Syntax Highlighter Example}, {Rich Text Processing} | |
*/ | |
/*! | |
\property QTextEdit::plainText | |
\since 4.3 | |
This property gets and sets the text editor's contents as plain | |
text. Previous contents are removed and undo/redo history is reset | |
when the property is set. | |
If the text edit has another content type, it will not be replaced | |
by plain text if you call toPlainText(). The only exception to this | |
is the non-break space, \e{nbsp;}, that will be converted into | |
standard space. | |
By default, for an editor with no contents, this property contains | |
an empty string. | |
\sa html | |
*/ | |
/*! | |
\property QTextEdit::undoRedoEnabled | |
\brief whether undo and redo are enabled | |
Users are only able to undo or redo actions if this property is | |
true, and if there is an action that can be undone (or redone). | |
*/ | |
/*! | |
\enum QTextEdit::LineWrapMode | |
\value NoWrap | |
\value WidgetWidth | |
\value FixedPixelWidth | |
\value FixedColumnWidth | |
*/ | |
/*! | |
\enum QTextEdit::AutoFormattingFlag | |
\value AutoNone Don't do any automatic formatting. | |
\value AutoBulletList Automatically create bullet lists (e.g. when | |
the user enters an asterisk ('*') in the left most column, or | |
presses Enter in an existing list item. | |
\value AutoAll Apply all automatic formatting. Currently only | |
automatic bullet lists are supported. | |
*/ | |
#ifdef QT3_SUPPORT | |
/*! | |
\enum QTextEdit::CursorAction | |
\compat | |
\value MoveBackward | |
\value MoveForward | |
\value MoveWordBackward | |
\value MoveWordForward | |
\value MoveUp | |
\value MoveDown | |
\value MoveLineStart | |
\value MoveLineEnd | |
\value MoveHome | |
\value MoveEnd | |
\value MovePageUp | |
\value MovePageDown | |
\omitvalue MovePgUp | |
\omitvalue MovePgDown | |
*/ | |
#endif | |
/*! | |
Constructs an empty QTextEdit with parent \a | |
parent. | |
*/ | |
QTextEdit::QTextEdit(QWidget *parent) | |
: QAbstractScrollArea(*new QTextEditPrivate, parent) | |
{ | |
Q_D(QTextEdit); | |
d->init(); | |
} | |
/*! | |
\internal | |
*/ | |
QTextEdit::QTextEdit(QTextEditPrivate &dd, QWidget *parent) | |
: QAbstractScrollArea(dd, parent) | |
{ | |
Q_D(QTextEdit); | |
d->init(); | |
} | |
/*! | |
Constructs a QTextEdit with parent \a parent. The text edit will display | |
the text \a text. The text is interpreted as html. | |
*/ | |
QTextEdit::QTextEdit(const QString &text, QWidget *parent) | |
: QAbstractScrollArea(*new QTextEditPrivate, parent) | |
{ | |
Q_D(QTextEdit); | |
d->init(text); | |
} | |
#ifdef QT3_SUPPORT | |
/*! | |
Use one of the constructors that doesn't take the \a name | |
argument and then use setObjectName() instead. | |
*/ | |
QTextEdit::QTextEdit(QWidget *parent, const char *name) | |
: QAbstractScrollArea(*new QTextEditPrivate, parent) | |
{ | |
Q_D(QTextEdit); | |
d->init(); | |
setObjectName(QString::fromAscii(name)); | |
} | |
#endif | |
/*! | |
Destructor. | |
*/ | |
QTextEdit::~QTextEdit() | |
{ | |
} | |
/*! | |
Returns the point size of the font of the current format. | |
\sa setFontFamily() setCurrentFont() setFontPointSize() | |
*/ | |
qreal QTextEdit::fontPointSize() const | |
{ | |
Q_D(const QTextEdit); | |
return d->control->textCursor().charFormat().fontPointSize(); | |
} | |
/*! | |
Returns the font family of the current format. | |
\sa setFontFamily() setCurrentFont() setFontPointSize() | |
*/ | |
QString QTextEdit::fontFamily() const | |
{ | |
Q_D(const QTextEdit); | |
return d->control->textCursor().charFormat().fontFamily(); | |
} | |
/*! | |
Returns the font weight of the current format. | |
\sa setFontWeight() setCurrentFont() setFontPointSize() QFont::Weight | |
*/ | |
int QTextEdit::fontWeight() const | |
{ | |
Q_D(const QTextEdit); | |
return d->control->textCursor().charFormat().fontWeight(); | |
} | |
/*! | |
Returns true if the font of the current format is underlined; otherwise returns | |
false. | |
\sa setFontUnderline() | |
*/ | |
bool QTextEdit::fontUnderline() const | |
{ | |
Q_D(const QTextEdit); | |
return d->control->textCursor().charFormat().fontUnderline(); | |
} | |
/*! | |
Returns true if the font of the current format is italic; otherwise returns | |
false. | |
\sa setFontItalic() | |
*/ | |
bool QTextEdit::fontItalic() const | |
{ | |
Q_D(const QTextEdit); | |
return d->control->textCursor().charFormat().fontItalic(); | |
} | |
/*! | |
Returns the text color of the current format. | |
\sa setTextColor() | |
*/ | |
QColor QTextEdit::textColor() const | |
{ | |
Q_D(const QTextEdit); | |
return d->control->textCursor().charFormat().foreground().color(); | |
} | |
/*! | |
\since 4.4 | |
Returns the text background color of the current format. | |
\sa setTextBackgroundColor() | |
*/ | |
QColor QTextEdit::textBackgroundColor() const | |
{ | |
Q_D(const QTextEdit); | |
return d->control->textCursor().charFormat().background().color(); | |
} | |
/*! | |
Returns the font of the current format. | |
\sa setCurrentFont() setFontFamily() setFontPointSize() | |
*/ | |
QFont QTextEdit::currentFont() const | |
{ | |
Q_D(const QTextEdit); | |
return d->control->textCursor().charFormat().font(); | |
} | |
/*! | |
Sets the alignment of the current paragraph to \a a. Valid | |
alignments are Qt::AlignLeft, Qt::AlignRight, | |
Qt::AlignJustify and Qt::AlignCenter (which centers | |
horizontally). | |
*/ | |
void QTextEdit::setAlignment(Qt::Alignment a) | |
{ | |
Q_D(QTextEdit); | |
QTextBlockFormat fmt; | |
fmt.setAlignment(a); | |
QTextCursor cursor = d->control->textCursor(); | |
cursor.mergeBlockFormat(fmt); | |
d->control->setTextCursor(cursor); | |
} | |
/*! | |
Returns the alignment of the current paragraph. | |
\sa setAlignment() | |
*/ | |
Qt::Alignment QTextEdit::alignment() const | |
{ | |
Q_D(const QTextEdit); | |
return d->control->textCursor().blockFormat().alignment(); | |
} | |
/*! | |
Makes \a document the new document of the text editor. | |
\note The editor \e{does not take ownership of the document} unless it | |
is the document's parent object. The parent object of the provided document | |
remains the owner of the object. | |
The editor does not delete the current document, even if it is a child of the editor. | |
\sa document() | |
*/ | |
void QTextEdit::setDocument(QTextDocument *document) | |
{ | |
Q_D(QTextEdit); | |
d->control->setDocument(document); | |
d->updateDefaultTextOption(); | |
d->relayoutDocument(); | |
} | |
/*! | |
Returns a pointer to the underlying document. | |
\sa setDocument() | |
*/ | |
QTextDocument *QTextEdit::document() const | |
{ | |
Q_D(const QTextEdit); | |
return d->control->document(); | |
} | |
/*! | |
Sets the visible \a cursor. | |
*/ | |
void QTextEdit::setTextCursor(const QTextCursor &cursor) | |
{ | |
Q_D(QTextEdit); | |
d->control->setTextCursor(cursor); | |
} | |
/*! | |
Returns a copy of the QTextCursor that represents the currently visible cursor. | |
Note that changes on the returned cursor do not affect QTextEdit's cursor; use | |
setTextCursor() to update the visible cursor. | |
*/ | |
QTextCursor QTextEdit::textCursor() const | |
{ | |
Q_D(const QTextEdit); | |
return d->control->textCursor(); | |
} | |
/*! | |
Sets the font family of the current format to \a fontFamily. | |
\sa fontFamily() setCurrentFont() | |
*/ | |
void QTextEdit::setFontFamily(const QString &fontFamily) | |
{ | |
QTextCharFormat fmt; | |
fmt.setFontFamily(fontFamily); | |
mergeCurrentCharFormat(fmt); | |
} | |
/*! | |
Sets the point size of the current format to \a s. | |
Note that if \a s is zero or negative, the behavior of this | |
function is not defined. | |
\sa fontPointSize() setCurrentFont() setFontFamily() | |
*/ | |
void QTextEdit::setFontPointSize(qreal s) | |
{ | |
QTextCharFormat fmt; | |
fmt.setFontPointSize(s); | |
mergeCurrentCharFormat(fmt); | |
} | |
/*! | |
\fn void QTextEdit::setFontWeight(int weight) | |
Sets the font weight of the current format to the given \a weight, | |
where the value used is in the range defined by the QFont::Weight | |
enum. | |
\sa fontWeight(), setCurrentFont(), setFontFamily() | |
*/ | |
void QTextEdit::setFontWeight(int w) | |
{ | |
QTextCharFormat fmt; | |
fmt.setFontWeight(w); | |
mergeCurrentCharFormat(fmt); | |
} | |
/*! | |
If \a underline is true, sets the current format to underline; | |
otherwise sets the current format to non-underline. | |
\sa fontUnderline() | |
*/ | |
void QTextEdit::setFontUnderline(bool underline) | |
{ | |
QTextCharFormat fmt; | |
fmt.setFontUnderline(underline); | |
mergeCurrentCharFormat(fmt); | |
} | |
/*! | |
If \a italic is true, sets the current format to italic; | |
otherwise sets the current format to non-italic. | |
\sa fontItalic() | |
*/ | |
void QTextEdit::setFontItalic(bool italic) | |
{ | |
QTextCharFormat fmt; | |
fmt.setFontItalic(italic); | |
mergeCurrentCharFormat(fmt); | |
} | |
/*! | |
Sets the text color of the current format to \a c. | |
\sa textColor() | |
*/ | |
void QTextEdit::setTextColor(const QColor &c) | |
{ | |
QTextCharFormat fmt; | |
fmt.setForeground(QBrush(c)); | |
mergeCurrentCharFormat(fmt); | |
} | |
/*! | |
\since 4.4 | |
Sets the text background color of the current format to \a c. | |
\sa textBackgroundColor() | |
*/ | |
void QTextEdit::setTextBackgroundColor(const QColor &c) | |
{ | |
QTextCharFormat fmt; | |
fmt.setBackground(QBrush(c)); | |
mergeCurrentCharFormat(fmt); | |
} | |
/*! | |
Sets the font of the current format to \a f. | |
\sa currentFont() setFontPointSize() setFontFamily() | |
*/ | |
void QTextEdit::setCurrentFont(const QFont &f) | |
{ | |
QTextCharFormat fmt; | |
fmt.setFont(f); | |
mergeCurrentCharFormat(fmt); | |
} | |
/*! | |
\since 4.2 | |
Undoes the last operation. | |
If there is no operation to undo, i.e. there is no undo step in | |
the undo/redo history, nothing happens. | |
\sa redo() | |
*/ | |
void QTextEdit::undo() | |
{ | |
Q_D(QTextEdit); | |
d->control->undo(); | |
} | |
void QTextEdit::redo() | |
{ | |
Q_D(QTextEdit); | |
d->control->redo(); | |
} | |
/*! | |
\fn void QTextEdit::undo() const | |
\fn void QTextEdit::redo() const | |
\overload | |
Use the non-const overload instead. | |
*/ | |
/*! | |
\fn void QTextEdit::redo() | |
\since 4.2 | |
Redoes the last operation. | |
If there is no operation to redo, i.e. there is no redo step in | |
the undo/redo history, nothing happens. | |
\sa undo() | |
*/ | |
#ifndef QT_NO_CLIPBOARD | |
/*! | |
Copies the selected text to the clipboard and deletes it from | |
the text edit. | |
If there is no selected text nothing happens. | |
\sa copy() paste() | |
*/ | |
void QTextEdit::cut() | |
{ | |
Q_D(QTextEdit); | |
d->control->cut(); | |
} | |
/*! | |
Copies any selected text to the clipboard. | |
\sa copyAvailable() | |
*/ | |
void QTextEdit::copy() | |
{ | |
Q_D(QTextEdit); | |
d->control->copy(); | |
} | |
/*! | |
Pastes the text from the clipboard into the text edit at the | |
current cursor position. | |
If there is no text in the clipboard nothing happens. | |
To change the behavior of this function, i.e. to modify what | |
QTextEdit can paste and how it is being pasted, reimplement the | |
virtual canInsertFromMimeData() and insertFromMimeData() | |
functions. | |
\sa cut() copy() | |
*/ | |
void QTextEdit::paste() | |
{ | |
Q_D(QTextEdit); | |
d->control->paste(); | |
} | |
#endif | |
/*! | |
Deletes all the text in the text edit. | |
Note that the undo/redo history is cleared by this function. | |
\sa cut() setPlainText() setHtml() | |
*/ | |
void QTextEdit::clear() | |
{ | |
Q_D(QTextEdit); | |
// clears and sets empty content | |
d->control->clear(); | |
} | |
/*! | |
Selects all text. | |
\sa copy() cut() textCursor() | |
*/ | |
void QTextEdit::selectAll() | |
{ | |
Q_D(QTextEdit); | |
d->control->selectAll(); | |
} | |
/*! \internal | |
*/ | |
bool QTextEdit::event(QEvent *e) | |
{ | |
Q_D(QTextEdit); | |
#ifndef QT_NO_CONTEXTMENU | |
if (e->type() == QEvent::ContextMenu | |
&& static_cast<QContextMenuEvent *>(e)->reason() == QContextMenuEvent::Keyboard) { | |
Q_D(QTextEdit); | |
ensureCursorVisible(); | |
const QPoint cursorPos = cursorRect().center(); | |
QContextMenuEvent ce(QContextMenuEvent::Keyboard, cursorPos, d->viewport->mapToGlobal(cursorPos)); | |
ce.setAccepted(e->isAccepted()); | |
const bool result = QAbstractScrollArea::event(&ce); | |
e->setAccepted(ce.isAccepted()); | |
return result; | |
} else if (e->type() == QEvent::ShortcutOverride | |
|| e->type() == QEvent::ToolTip) { | |
d->sendControlEvent(e); | |
} | |
#endif // QT_NO_CONTEXTMENU | |
#ifdef QT_KEYPAD_NAVIGATION | |
if (e->type() == QEvent::EnterEditFocus || e->type() == QEvent::LeaveEditFocus) { | |
if (QApplication::keypadNavigationEnabled()) | |
d->sendControlEvent(e); | |
} | |
#endif | |
return QAbstractScrollArea::event(e); | |
} | |
/*! \internal | |
*/ | |
void QTextEdit::timerEvent(QTimerEvent *e) | |
{ | |
Q_D(QTextEdit); | |
if (e->timerId() == d->autoScrollTimer.timerId()) { | |
QRect visible = d->viewport->rect(); | |
QPoint pos; | |
if (d->inDrag) { | |
pos = d->autoScrollDragPos; | |
visible.adjust(qMin(visible.width()/3,20), qMin(visible.height()/3,20), | |
-qMin(visible.width()/3,20), -qMin(visible.height()/3,20)); | |
} else { | |
const QPoint globalPos = QCursor::pos(); | |
pos = d->viewport->mapFromGlobal(globalPos); | |
QMouseEvent ev(QEvent::MouseMove, pos, globalPos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); | |
mouseMoveEvent(&ev); | |
} | |
int deltaY = qMax(pos.y() - visible.top(), visible.bottom() - pos.y()) - visible.height(); | |
int deltaX = qMax(pos.x() - visible.left(), visible.right() - pos.x()) - visible.width(); | |
int delta = qMax(deltaX, deltaY); | |
if (delta >= 0) { | |
if (delta < 7) | |
delta = 7; | |
int timeout = 4900 / (delta * delta); | |
d->autoScrollTimer.start(timeout, this); | |
if (deltaY > 0) | |
d->vbar->triggerAction(pos.y() < visible.center().y() ? | |
QAbstractSlider::SliderSingleStepSub | |
: QAbstractSlider::SliderSingleStepAdd); | |
if (deltaX > 0) | |
d->hbar->triggerAction(pos.x() < visible.center().x() ? | |
QAbstractSlider::SliderSingleStepSub | |
: QAbstractSlider::SliderSingleStepAdd); | |
} | |
} | |
#ifdef QT_KEYPAD_NAVIGATION | |
else if (e->timerId() == d->deleteAllTimer.timerId()) { | |
d->deleteAllTimer.stop(); | |
clear(); | |
} | |
#endif | |
} | |
/*! | |
Changes the text of the text edit to the string \a text. | |
Any previous text is removed. | |
\a text is interpreted as plain text. | |
Note that the undo/redo history is cleared by this function. | |
\sa toPlainText() | |
*/ | |
void QTextEdit::setPlainText(const QString &text) | |
{ | |
Q_D(QTextEdit); | |
d->control->setPlainText(text); | |
d->preferRichText = false; | |
} | |
/*! | |
\fn QString QTextEdit::toPlainText() const | |
Returns the text of the text edit as plain text. | |
\sa QTextEdit::setPlainText() | |
*/ | |
/*! | |
\property QTextEdit::html | |
This property provides an HTML interface to the text of the text edit. | |
toHtml() returns the text of the text edit as html. | |
setHtml() changes the text of the text edit. Any previous text is | |
removed and the undo/redo history is cleared. The input text is | |
interpreted as rich text in html format. | |
\note It is the responsibility of the caller to make sure that the | |
text is correctly decoded when a QString containing HTML is created | |
and passed to setHtml(). | |
By default, for a newly-created, empty document, this property contains | |
text to describe an HTML 4.0 document with no body text. | |
\sa {Supported HTML Subset}, plainText | |
*/ | |
#ifndef QT_NO_TEXTHTMLPARSER | |
void QTextEdit::setHtml(const QString &text) | |
{ | |
Q_D(QTextEdit); | |
d->control->setHtml(text); | |
d->preferRichText = true; | |
} | |
#endif | |
/*! \reimp | |
*/ | |
void QTextEdit::keyPressEvent(QKeyEvent *e) | |
{ | |
Q_D(QTextEdit); | |
#ifdef QT_KEYPAD_NAVIGATION | |
switch (e->key()) { | |
case Qt::Key_Select: | |
if (QApplication::keypadNavigationEnabled()) { | |
// code assumes linksaccessible + editable isn't meaningful | |
if (d->control->textInteractionFlags() & Qt::TextEditable) { | |
setEditFocus(!hasEditFocus()); | |
} else { | |
if (!hasEditFocus()) | |
setEditFocus(true); | |
else { | |
QTextCursor cursor = d->control->textCursor(); | |
QTextCharFormat charFmt = cursor.charFormat(); | |
if (!(d->control->textInteractionFlags() & Qt::LinksAccessibleByKeyboard) | |
|| !cursor.hasSelection() || charFmt.anchorHref().isEmpty()) { | |
e->accept(); | |
return; | |
} | |
} | |
} | |
} | |
break; | |
case Qt::Key_Back: | |
case Qt::Key_No: | |
if (!QApplication::keypadNavigationEnabled() | |
|| (QApplication::keypadNavigationEnabled() && !hasEditFocus())) { | |
e->ignore(); | |
return; | |
} | |
break; | |
default: | |
if (QApplication::keypadNavigationEnabled()) { | |
if (!hasEditFocus() && !(e->modifiers() & Qt::ControlModifier)) { | |
if (e->text()[0].isPrint()) | |
setEditFocus(true); | |
else { | |
e->ignore(); | |
return; | |
} | |
} | |
} | |
break; | |
} | |
#endif | |
#ifndef QT_NO_SHORTCUT | |
Qt::TextInteractionFlags tif = d->control->textInteractionFlags(); | |
if (tif & Qt::TextSelectableByKeyboard){ | |
if (e == QKeySequence::SelectPreviousPage) { | |
e->accept(); | |
d->pageUpDown(QTextCursor::Up, QTextCursor::KeepAnchor); | |
return; | |
} else if (e ==QKeySequence::SelectNextPage) { | |
e->accept(); | |
d->pageUpDown(QTextCursor::Down, QTextCursor::KeepAnchor); | |
return; | |
} | |
} | |
if (tif & (Qt::TextSelectableByKeyboard | Qt::TextEditable)) { | |
if (e == QKeySequence::MoveToPreviousPage) { | |
e->accept(); | |
d->pageUpDown(QTextCursor::Up, QTextCursor::MoveAnchor); | |
return; | |
} else if (e == QKeySequence::MoveToNextPage) { | |
e->accept(); | |
d->pageUpDown(QTextCursor::Down, QTextCursor::MoveAnchor); | |
return; | |
} | |
} | |
if (!(tif & Qt::TextEditable)) { | |
switch (e->key()) { | |
case Qt::Key_Space: | |
e->accept(); | |
if (e->modifiers() & Qt::ShiftModifier) | |
d->vbar->triggerAction(QAbstractSlider::SliderPageStepSub); | |
else | |
d->vbar->triggerAction(QAbstractSlider::SliderPageStepAdd); | |
break; | |
default: | |
d->sendControlEvent(e); | |
if (!e->isAccepted() && e->modifiers() == Qt::NoModifier) { | |
if (e->key() == Qt::Key_Home) { | |
d->vbar->triggerAction(QAbstractSlider::SliderToMinimum); | |
e->accept(); | |
} else if (e->key() == Qt::Key_End) { | |
d->vbar->triggerAction(QAbstractSlider::SliderToMaximum); | |
e->accept(); | |
} | |
} | |
if (!e->isAccepted()) { | |
QAbstractScrollArea::keyPressEvent(e); | |
} | |
} | |
return; | |
} | |
#endif // QT_NO_SHORTCUT | |
{ | |
QTextCursor cursor = d->control->textCursor(); | |
const QString text = e->text(); | |
if (cursor.atBlockStart() | |
&& (d->autoFormatting & AutoBulletList) | |
&& (text.length() == 1) | |
&& (text.at(0) == QLatin1Char('-') || text.at(0) == QLatin1Char('*')) | |
&& (!cursor.currentList())) { | |
d->createAutoBulletList(); | |
e->accept(); | |
return; | |
} | |
} | |
d->sendControlEvent(e); | |
#ifdef QT_KEYPAD_NAVIGATION | |
if (!e->isAccepted()) { | |
switch (e->key()) { | |
case Qt::Key_Up: | |
case Qt::Key_Down: | |
if (QApplication::keypadNavigationEnabled()) { | |
// Cursor position didn't change, so we want to leave | |
// these keys to change focus. | |
e->ignore(); | |
return; | |
} | |
break; | |
case Qt::Key_Back: | |
if (!e->isAutoRepeat()) { | |
if (QApplication::keypadNavigationEnabled()) { | |
if (document()->isEmpty() || !(d->control->textInteractionFlags() & Qt::TextEditable)) { | |
setEditFocus(false); | |
e->accept(); | |
} else if (!d->deleteAllTimer.isActive()) { | |
e->accept(); | |
d->deleteAllTimer.start(750, this); | |
} | |
} else { | |
e->ignore(); | |
return; | |
} | |
} | |
break; | |
default: break; | |
} | |
} | |
#endif | |
} | |
/*! \reimp | |
*/ | |
void QTextEdit::keyReleaseEvent(QKeyEvent *e) | |
{ | |
#ifdef QT_KEYPAD_NAVIGATION | |
Q_D(QTextEdit); | |
if (QApplication::keypadNavigationEnabled()) { | |
if (!e->isAutoRepeat() && e->key() == Qt::Key_Back | |
&& d->deleteAllTimer.isActive()) { | |
d->deleteAllTimer.stop(); | |
QTextCursor cursor = d->control->textCursor(); | |
QTextBlockFormat blockFmt = cursor.blockFormat(); | |
QTextList *list = cursor.currentList(); | |
if (list && cursor.atBlockStart()) { | |
list->remove(cursor.block()); | |
} else if (cursor.atBlockStart() && blockFmt.indent() > 0) { | |
blockFmt.setIndent(blockFmt.indent() - 1); | |
cursor.setBlockFormat(blockFmt); | |
} else { | |
cursor.deletePreviousChar(); | |
} | |
setTextCursor(cursor); | |
e->accept(); | |
return; | |
} | |
} | |
#endif | |
e->ignore(); | |
} | |
/*! | |
Loads the resource specified by the given \a type and \a name. | |
This function is an extension of QTextDocument::loadResource(). | |
\sa QTextDocument::loadResource() | |
*/ | |
QVariant QTextEdit::loadResource(int type, const QUrl &name) | |
{ | |
Q_UNUSED(type); | |
Q_UNUSED(name); | |
return QVariant(); | |
} | |
/*! \reimp | |
*/ | |
void QTextEdit::resizeEvent(QResizeEvent *e) | |
{ | |
Q_D(QTextEdit); | |
if (d->lineWrap == NoWrap) { | |
QTextDocument *doc = d->control->document(); | |
QVariant alignmentProperty = doc->documentLayout()->property("contentHasAlignment"); | |
if (!doc->pageSize().isNull() | |
&& alignmentProperty.type() == QVariant::Bool | |
&& !alignmentProperty.toBool()) { | |
d->_q_adjustScrollbars(); | |
return; | |
} | |
} | |
if (d->lineWrap != FixedPixelWidth | |
&& e->oldSize().width() != e->size().width()) | |
d->relayoutDocument(); | |
else | |
d->_q_adjustScrollbars(); | |
} | |
void QTextEditPrivate::relayoutDocument() | |
{ | |
QTextDocument *doc = control->document(); | |
QAbstractTextDocumentLayout *layout = doc->documentLayout(); | |
if (QTextDocumentLayout *tlayout = qobject_cast<QTextDocumentLayout *>(layout)) { | |
if (lineWrap == QTextEdit::FixedColumnWidth) | |
tlayout->setFixedColumnWidth(lineWrapColumnOrWidth); | |
else | |
tlayout->setFixedColumnWidth(-1); | |
} | |
QTextDocumentLayout *tlayout = qobject_cast<QTextDocumentLayout *>(layout); | |
QSize lastUsedSize; | |
if (tlayout) | |
lastUsedSize = tlayout->dynamicDocumentSize().toSize(); | |
else | |
lastUsedSize = layout->documentSize().toSize(); | |
// ignore calls to _q_adjustScrollbars caused by an emission of the | |
// usedSizeChanged() signal in the layout, as we're calling it | |
// later on our own anyway (or deliberately not) . | |
const bool oldIgnoreScrollbarAdjustment = ignoreAutomaticScrollbarAdjustment; | |
ignoreAutomaticScrollbarAdjustment = true; | |
int width = viewport->width(); | |
if (lineWrap == QTextEdit::FixedPixelWidth) | |
width = lineWrapColumnOrWidth; | |
else if (lineWrap == QTextEdit::NoWrap) { | |
QVariant alignmentProperty = doc->documentLayout()->property("contentHasAlignment"); | |
if (alignmentProperty.type() == QVariant::Bool && !alignmentProperty.toBool()) { | |
width = 0; | |
} | |
} | |
doc->setPageSize(QSize(width, -1)); | |
if (tlayout) | |
tlayout->ensureLayouted(verticalOffset() + viewport->height()); | |
ignoreAutomaticScrollbarAdjustment = oldIgnoreScrollbarAdjustment; | |
QSize usedSize; | |
if (tlayout) | |
usedSize = tlayout->dynamicDocumentSize().toSize(); | |
else | |
usedSize = layout->documentSize().toSize(); | |
// this is an obscure situation in the layout that can happen: | |
// if a character at the end of a line is the tallest one and therefore | |
// influencing the total height of the line and the line right below it | |
// is always taller though, then it can happen that if due to line breaking | |
// that tall character wraps into the lower line the document not only shrinks | |
// horizontally (causing the character to wrap in the first place) but also | |
// vertically, because the original line is now smaller and the one below kept | |
// its size. So a layout with less width _can_ take up less vertical space, too. | |
// If the wider case causes a vertical scroll bar to appear and the narrower one | |
// (narrower because the vertical scroll bar takes up horizontal space)) to disappear | |
// again then we have an endless loop, as _q_adjustScrollBars sets new ranges on the | |
// scroll bars, the QAbstractScrollArea will find out about it and try to show/hide | |
// the scroll bars again. That's why we try to detect this case here and break out. | |
// | |
// (if you change this please also check the layoutingLoop() testcase in | |
// QTextEdit's autotests) | |
if (lastUsedSize.isValid() | |
&& !vbar->isHidden() | |
&& viewport->width() < lastUsedSize.width() | |
&& usedSize.height() < lastUsedSize.height() | |
&& usedSize.height() <= viewport->height()) | |
return; | |
_q_adjustScrollbars(); | |
} | |
void QTextEditPrivate::paint(QPainter *p, QPaintEvent *e) | |
{ | |
const int xOffset = horizontalOffset(); | |
const int yOffset = verticalOffset(); | |
QRect r = e->rect(); | |
p->translate(-xOffset, -yOffset); | |
r.translate(xOffset, yOffset); | |
QTextDocument *doc = control->document(); | |
QTextDocumentLayout *layout = qobject_cast<QTextDocumentLayout *>(doc->documentLayout()); | |
// the layout might need to expand the root frame to | |
// the viewport if NoWrap is set | |
if (layout) | |
layout->setViewport(viewport->rect()); | |
control->drawContents(p, r, q_func()); | |
if (layout) | |
layout->setViewport(QRect()); | |
} | |
/*! \fn void QTextEdit::paintEvent(QPaintEvent *event) | |
This event handler can be reimplemented in a subclass to receive paint events passed in \a event. | |
It is usually unnecessary to reimplement this function in a subclass of QTextEdit. | |
\warning The underlying text document must not be modified from within a reimplementation | |
of this function. | |
*/ | |
void QTextEdit::paintEvent(QPaintEvent *e) | |
{ | |
Q_D(QTextEdit); | |
QPainter p(d->viewport); | |
d->paint(&p, e); | |
} | |
void QTextEditPrivate::_q_currentCharFormatChanged(const QTextCharFormat &fmt) | |
{ | |
Q_Q(QTextEdit); | |
emit q->currentCharFormatChanged(fmt); | |
#ifdef QT3_SUPPORT | |
// compat signals | |
emit q->currentFontChanged(fmt.font()); | |
emit q->currentColorChanged(fmt.foreground().color()); | |
#endif | |
} | |
void QTextEditPrivate::updateDefaultTextOption() | |
{ | |
QTextDocument *doc = control->document(); | |
QTextOption opt = doc->defaultTextOption(); | |
QTextOption::WrapMode oldWrapMode = opt.wrapMode(); | |
if (lineWrap == QTextEdit::NoWrap) | |
opt.setWrapMode(QTextOption::NoWrap); | |
else | |
opt.setWrapMode(wordWrap); | |
if (opt.wrapMode() != oldWrapMode) | |
doc->setDefaultTextOption(opt); | |
} | |
/*! \reimp | |
*/ | |
void QTextEdit::mousePressEvent(QMouseEvent *e) | |
{ | |
Q_D(QTextEdit); | |
#ifdef QT_KEYPAD_NAVIGATION | |
if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) | |
setEditFocus(true); | |
#endif | |
d->sendControlEvent(e); | |
} | |
/*! \reimp | |
*/ | |
void QTextEdit::mouseMoveEvent(QMouseEvent *e) | |
{ | |
Q_D(QTextEdit); | |
d->inDrag = false; // paranoia | |
const QPoint pos = e->pos(); | |
d->sendControlEvent(e); | |
if (!(e->buttons() & Qt::LeftButton)) | |
return; | |
QRect visible = d->viewport->rect(); | |
if (visible.contains(pos)) | |
d->autoScrollTimer.stop(); | |
else if (!d->autoScrollTimer.isActive()) | |
d->autoScrollTimer.start(100, this); | |
} | |
/*! \reimp | |
*/ | |
void QTextEdit::mouseReleaseEvent(QMouseEvent *e) | |
{ | |
Q_D(QTextEdit); | |
d->sendControlEvent(e); | |
if (d->autoScrollTimer.isActive()) { | |
d->autoScrollTimer.stop(); | |
ensureCursorVisible(); | |
} | |
if (!isReadOnly() && rect().contains(e->pos())) | |
d->handleSoftwareInputPanel(e->button(), d->clickCausedFocus); | |
d->clickCausedFocus = 0; | |
} | |
/*! \reimp | |
*/ | |
void QTextEdit::mouseDoubleClickEvent(QMouseEvent *e) | |
{ | |
Q_D(QTextEdit); | |
d->sendControlEvent(e); | |
} | |
/*! \reimp | |
*/ | |
bool QTextEdit::focusNextPrevChild(bool next) | |
{ | |
Q_D(const QTextEdit); | |
if (!d->tabChangesFocus && d->control->textInteractionFlags() & Qt::TextEditable) | |
return false; | |
return QAbstractScrollArea::focusNextPrevChild(next); | |
} | |
#ifndef QT_NO_CONTEXTMENU | |
/*! | |
\fn void QTextEdit::contextMenuEvent(QContextMenuEvent *event) | |
Shows the standard context menu created with createStandardContextMenu(). | |
If you do not want the text edit to have a context menu, you can set | |
its \l contextMenuPolicy to Qt::NoContextMenu. If you want to | |
customize the context menu, reimplement this function. If you want | |
to extend the standard context menu, reimplement this function, call | |
createStandardContextMenu() and extend the menu returned. | |
Information about the event is passed in the \a event object. | |
\snippet doc/src/snippets/code/src_gui_widgets_qtextedit.cpp 0 | |
*/ | |
void QTextEdit::contextMenuEvent(QContextMenuEvent *e) | |
{ | |
Q_D(QTextEdit); | |
d->sendControlEvent(e); | |
} | |
#endif // QT_NO_CONTEXTMENU | |
#ifndef QT_NO_DRAGANDDROP | |
/*! \reimp | |
*/ | |
void QTextEdit::dragEnterEvent(QDragEnterEvent *e) | |
{ | |
Q_D(QTextEdit); | |
d->inDrag = true; | |
d->sendControlEvent(e); | |
} | |
/*! \reimp | |
*/ | |
void QTextEdit::dragLeaveEvent(QDragLeaveEvent *e) | |
{ | |
Q_D(QTextEdit); | |
d->inDrag = false; | |
d->autoScrollTimer.stop(); | |
d->sendControlEvent(e); | |
} | |
/*! \reimp | |
*/ | |
void QTextEdit::dragMoveEvent(QDragMoveEvent *e) | |
{ | |
Q_D(QTextEdit); | |
d->autoScrollDragPos = e->pos(); | |
if (!d->autoScrollTimer.isActive()) | |
d->autoScrollTimer.start(100, this); | |
d->sendControlEvent(e); | |
} | |
/*! \reimp | |
*/ | |
void QTextEdit::dropEvent(QDropEvent *e) | |
{ | |
Q_D(QTextEdit); | |
d->inDrag = false; | |
d->autoScrollTimer.stop(); | |
d->sendControlEvent(e); | |
} | |
#endif // QT_NO_DRAGANDDROP | |
/*! \reimp | |
*/ | |
void QTextEdit::inputMethodEvent(QInputMethodEvent *e) | |
{ | |
Q_D(QTextEdit); | |
#ifdef QT_KEYPAD_NAVIGATION | |
if (d->control->textInteractionFlags() & Qt::TextEditable | |
&& QApplication::keypadNavigationEnabled() | |
&& !hasEditFocus()) | |
setEditFocus(true); | |
#endif | |
d->sendControlEvent(e); | |
ensureCursorVisible(); | |
} | |
/*!\reimp | |
*/ | |
void QTextEdit::scrollContentsBy(int dx, int dy) | |
{ | |
Q_D(QTextEdit); | |
if (isRightToLeft()) | |
dx = -dx; | |
d->viewport->scroll(dx, dy); | |
} | |
/*!\reimp | |
*/ | |
QVariant QTextEdit::inputMethodQuery(Qt::InputMethodQuery property) const | |
{ | |
Q_D(const QTextEdit); | |
QVariant v = d->control->inputMethodQuery(property); | |
const QPoint offset(-d->horizontalOffset(), -d->verticalOffset()); | |
if (v.type() == QVariant::RectF) | |
v = v.toRectF().toRect().translated(offset); | |
else if (v.type() == QVariant::PointF) | |
v = v.toPointF().toPoint() + offset; | |
else if (v.type() == QVariant::Rect) | |
v = v.toRect().translated(offset); | |
else if (v.type() == QVariant::Point) | |
v = v.toPoint() + offset; | |
return v; | |
} | |
/*! \reimp | |
*/ | |
void QTextEdit::focusInEvent(QFocusEvent *e) | |
{ | |
Q_D(QTextEdit); | |
if (e->reason() == Qt::MouseFocusReason) { | |
d->clickCausedFocus = 1; | |
} | |
QAbstractScrollArea::focusInEvent(e); | |
d->sendControlEvent(e); | |
} | |
/*! \reimp | |
*/ | |
void QTextEdit::focusOutEvent(QFocusEvent *e) | |
{ | |
Q_D(QTextEdit); | |
QAbstractScrollArea::focusOutEvent(e); | |
d->sendControlEvent(e); | |
} | |
/*! \reimp | |
*/ | |
void QTextEdit::showEvent(QShowEvent *) | |
{ | |
Q_D(QTextEdit); | |
if (!d->anchorToScrollToWhenVisible.isEmpty()) { | |
scrollToAnchor(d->anchorToScrollToWhenVisible); | |
d->anchorToScrollToWhenVisible.clear(); | |
d->showCursorOnInitialShow = false; | |
} else if (d->showCursorOnInitialShow) { | |
d->showCursorOnInitialShow = false; | |
ensureCursorVisible(); | |
} | |
} | |
/*! \reimp | |
*/ | |
void QTextEdit::changeEvent(QEvent *e) | |
{ | |
Q_D(QTextEdit); | |
QAbstractScrollArea::changeEvent(e); | |
if (e->type() == QEvent::ApplicationFontChange | |
|| e->type() == QEvent::FontChange) { | |
d->control->document()->setDefaultFont(font()); | |
} else if(e->type() == QEvent::ActivationChange) { | |
if (!isActiveWindow()) | |
d->autoScrollTimer.stop(); | |
} else if (e->type() == QEvent::EnabledChange) { | |
e->setAccepted(isEnabled()); | |
d->control->setPalette(palette()); | |
d->sendControlEvent(e); | |
} else if (e->type() == QEvent::PaletteChange) { | |
d->control->setPalette(palette()); | |
} else if (e->type() == QEvent::LayoutDirectionChange) { | |
d->sendControlEvent(e); | |
} | |
} | |
/*! \reimp | |
*/ | |
#ifndef QT_NO_WHEELEVENT | |
void QTextEdit::wheelEvent(QWheelEvent *e) | |
{ | |
Q_D(QTextEdit); | |
if (!(d->control->textInteractionFlags() & Qt::TextEditable)) { | |
if (e->modifiers() & Qt::ControlModifier) { | |
const int delta = e->delta(); | |
if (delta < 0) | |
zoomOut(); | |
else if (delta > 0) | |
zoomIn(); | |
return; | |
} | |
} | |
QAbstractScrollArea::wheelEvent(e); | |
updateMicroFocus(); | |
} | |
#endif | |
#ifndef QT_NO_CONTEXTMENU | |
/*! This function creates the standard context menu which is shown | |
when the user clicks on the text edit with the right mouse | |
button. It is called from the default contextMenuEvent() handler. | |
The popup menu's ownership is transferred to the caller. | |
We recommend that you use the createStandardContextMenu(QPoint) version instead | |
which will enable the actions that are sensitive to where the user clicked. | |
*/ | |
QMenu *QTextEdit::createStandardContextMenu() | |
{ | |
Q_D(QTextEdit); | |
return d->control->createStandardContextMenu(QPointF(), this); | |
} | |
/*! | |
\since 4.4 | |
This function creates the standard context menu which is shown | |
when the user clicks on the text edit with the right mouse | |
button. It is called from the default contextMenuEvent() handler | |
and it takes the \a position of where the mouse click was. | |
This can enable actions that are sensitive to the position where the user clicked. | |
The popup menu's ownership is transferred to the caller. | |
*/ | |
QMenu *QTextEdit::createStandardContextMenu(const QPoint &position) | |
{ | |
Q_D(QTextEdit); | |
return d->control->createStandardContextMenu(position, this); | |
} | |
#endif // QT_NO_CONTEXTMENU | |
/*! | |
returns a QTextCursor at position \a pos (in viewport coordinates). | |
*/ | |
QTextCursor QTextEdit::cursorForPosition(const QPoint &pos) const | |
{ | |
Q_D(const QTextEdit); | |
return d->control->cursorForPosition(d->mapToContents(pos)); | |
} | |
/*! | |
returns a rectangle (in viewport coordinates) that includes the | |
\a cursor. | |
*/ | |
QRect QTextEdit::cursorRect(const QTextCursor &cursor) const | |
{ | |
Q_D(const QTextEdit); | |
if (cursor.isNull()) | |
return QRect(); | |
QRect r = d->control->cursorRect(cursor).toRect(); | |
r.translate(-d->horizontalOffset(),-d->verticalOffset()); | |
return r; | |
} | |
/*! | |
returns a rectangle (in viewport coordinates) that includes the | |
cursor of the text edit. | |
*/ | |
QRect QTextEdit::cursorRect() const | |
{ | |
Q_D(const QTextEdit); | |
QRect r = d->control->cursorRect().toRect(); | |
r.translate(-d->horizontalOffset(),-d->verticalOffset()); | |
return r; | |
} | |
/*! | |
Returns the reference of the anchor at position \a pos, or an | |
empty string if no anchor exists at that point. | |
*/ | |
QString QTextEdit::anchorAt(const QPoint& pos) const | |
{ | |
Q_D(const QTextEdit); | |
return d->control->anchorAt(d->mapToContents(pos)); | |
} | |
/*! | |
\property QTextEdit::overwriteMode | |
\since 4.1 | |
\brief whether text entered by the user will overwrite existing text | |
As with many text editors, the text editor widget can be configured | |
to insert or overwrite existing text with new text entered by the user. | |
If this property is true, existing text is overwritten, character-for-character | |
by new text; otherwise, text is inserted at the cursor position, displacing | |
existing text. | |
By default, this property is false (new text does not overwrite existing text). | |
*/ | |
bool QTextEdit::overwriteMode() const | |
{ | |
Q_D(const QTextEdit); | |
return d->control->overwriteMode(); | |
} | |
void QTextEdit::setOverwriteMode(bool overwrite) | |
{ | |
Q_D(QTextEdit); | |
d->control->setOverwriteMode(overwrite); | |
} | |
/*! | |
\property QTextEdit::tabStopWidth | |
\brief the tab stop width in pixels | |
\since 4.1 | |
By default, this property contains a value of 80 pixels. | |
*/ | |
int QTextEdit::tabStopWidth() const | |
{ | |
Q_D(const QTextEdit); | |
return qRound(d->control->document()->defaultTextOption().tabStop()); | |
} | |
void QTextEdit::setTabStopWidth(int width) | |
{ | |
Q_D(QTextEdit); | |
QTextOption opt = d->control->document()->defaultTextOption(); | |
if (opt.tabStop() == width || width < 0) | |
return; | |
opt.setTabStop(width); | |
d->control->document()->setDefaultTextOption(opt); | |
} | |
/*! | |
\since 4.2 | |
\property QTextEdit::cursorWidth | |
This property specifies the width of the cursor in pixels. The default value is 1. | |
*/ | |
int QTextEdit::cursorWidth() const | |
{ | |
Q_D(const QTextEdit); | |
return d->control->cursorWidth(); | |
} | |
void QTextEdit::setCursorWidth(int width) | |
{ | |
Q_D(QTextEdit); | |
d->control->setCursorWidth(width); | |
} | |
/*! | |
\property QTextEdit::acceptRichText | |
\brief whether the text edit accepts rich text insertions by the user | |
\since 4.1 | |
When this propery is set to false text edit will accept only | |
plain text input from the user. For example through clipboard or drag and drop. | |
This property's default is true. | |
*/ | |
bool QTextEdit::acceptRichText() const | |
{ | |
Q_D(const QTextEdit); | |
return d->control->acceptRichText(); | |
} | |
void QTextEdit::setAcceptRichText(bool accept) | |
{ | |
Q_D(QTextEdit); | |
d->control->setAcceptRichText(accept); | |
} | |
/*! | |
\class QTextEdit::ExtraSelection | |
\since 4.2 | |
\brief The QTextEdit::ExtraSelection structure provides a way of specifying a | |
character format for a given selection in a document | |
*/ | |
/*! | |
\variable QTextEdit::ExtraSelection::cursor | |
A cursor that contains a selection in a QTextDocument | |
*/ | |
/*! | |
\variable QTextEdit::ExtraSelection::format | |
A format that is used to specify a foreground or background brush/color | |
for the selection. | |
*/ | |
/*! | |
\since 4.2 | |
This function allows temporarily marking certain regions in the document | |
with a given color, specified as \a selections. This can be useful for | |
example in a programming editor to mark a whole line of text with a given | |
background color to indicate the existence of a breakpoint. | |
\sa QTextEdit::ExtraSelection, extraSelections() | |
*/ | |
void QTextEdit::setExtraSelections(const QList<ExtraSelection> &selections) | |
{ | |
Q_D(QTextEdit); | |
d->control->setExtraSelections(selections); | |
} | |
/*! | |
\since 4.2 | |
Returns previously set extra selections. | |
\sa setExtraSelections() | |
*/ | |
QList<QTextEdit::ExtraSelection> QTextEdit::extraSelections() const | |
{ | |
Q_D(const QTextEdit); | |
return d->control->extraSelections(); | |
} | |
/*! | |
This function returns a new MIME data object to represent the contents | |
of the text edit's current selection. It is called when the selection needs | |
to be encapsulated into a new QMimeData object; for example, when a drag | |
and drop operation is started, or when data is copyied to the clipboard. | |
If you reimplement this function, note that the ownership of the returned | |
QMimeData object is passed to the caller. The selection can be retrieved | |
by using the textCursor() function. | |
*/ | |
QMimeData *QTextEdit::createMimeDataFromSelection() const | |
{ | |
Q_D(const QTextEdit); | |
return d->control->QTextControl::createMimeDataFromSelection(); | |
} | |
/*! | |
This function returns true if the contents of the MIME data object, specified | |
by \a source, can be decoded and inserted into the document. It is called | |
for example when during a drag operation the mouse enters this widget and it | |
is necessary to determine whether it is possible to accept the drag and drop | |
operation. | |
Reimplement this function to enable drag and drop support for additional MIME types. | |
*/ | |
bool QTextEdit::canInsertFromMimeData(const QMimeData *source) const | |
{ | |
Q_D(const QTextEdit); | |
return d->control->QTextControl::canInsertFromMimeData(source); | |
} | |
/*! | |
This function inserts the contents of the MIME data object, specified | |
by \a source, into the text edit at the current cursor position. It is | |
called whenever text is inserted as the result of a clipboard paste | |
operation, or when the text edit accepts data from a drag and drop | |
operation. | |
Reimplement this function to enable drag and drop support for additional MIME types. | |
*/ | |
void QTextEdit::insertFromMimeData(const QMimeData *source) | |
{ | |
Q_D(QTextEdit); | |
d->control->QTextControl::insertFromMimeData(source); | |
} | |
/*! | |
\property QTextEdit::readOnly | |
\brief whether the text edit is read-only | |
In a read-only text edit the user can only navigate through the | |
text and select text; modifying the text is not possible. | |
This property's default is false. | |
*/ | |
bool QTextEdit::isReadOnly() const | |
{ | |
Q_D(const QTextEdit); | |
return !(d->control->textInteractionFlags() & Qt::TextEditable); | |
} | |
void QTextEdit::setReadOnly(bool ro) | |
{ | |
Q_D(QTextEdit); | |
Qt::TextInteractionFlags flags = Qt::NoTextInteraction; | |
if (ro) { | |
flags = Qt::TextSelectableByMouse; | |
#ifndef QT_NO_TEXTBROWSER | |
if (qobject_cast<QTextBrowser *>(this)) | |
flags |= Qt::TextBrowserInteraction; | |
#endif | |
} else { | |
flags = Qt::TextEditorInteraction; | |
} | |
d->control->setTextInteractionFlags(flags); | |
setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this)); | |
} | |
/*! | |
\property QTextEdit::textInteractionFlags | |
\since 4.2 | |
Specifies how the widget should interact with user input. | |
The default value depends on whether the QTextEdit is read-only | |
or editable, and whether it is a QTextBrowser or not. | |
*/ | |
void QTextEdit::setTextInteractionFlags(Qt::TextInteractionFlags flags) | |
{ | |
Q_D(QTextEdit); | |
d->control->setTextInteractionFlags(flags); | |
} | |
Qt::TextInteractionFlags QTextEdit::textInteractionFlags() const | |
{ | |
Q_D(const QTextEdit); | |
return d->control->textInteractionFlags(); | |
} | |
/*! | |
Merges the properties specified in \a modifier into the current character | |
format by calling QTextCursor::mergeCharFormat on the editor's cursor. | |
If the editor has a selection then the properties of \a modifier are | |
directly applied to the selection. | |
\sa QTextCursor::mergeCharFormat() | |
*/ | |
void QTextEdit::mergeCurrentCharFormat(const QTextCharFormat &modifier) | |
{ | |
Q_D(QTextEdit); | |
d->control->mergeCurrentCharFormat(modifier); | |
} | |
/*! | |
Sets the char format that is be used when inserting new text to \a | |
format by calling QTextCursor::setCharFormat() on the editor's | |
cursor. If the editor has a selection then the char format is | |
directly applied to the selection. | |
*/ | |
void QTextEdit::setCurrentCharFormat(const QTextCharFormat &format) | |
{ | |
Q_D(QTextEdit); | |
d->control->setCurrentCharFormat(format); | |
} | |
/*! | |
Returns the char format that is used when inserting new text. | |
*/ | |
QTextCharFormat QTextEdit::currentCharFormat() const | |
{ | |
Q_D(const QTextEdit); | |
return d->control->currentCharFormat(); | |
} | |
/*! | |
\property QTextEdit::autoFormatting | |
\brief the enabled set of auto formatting features | |
The value can be any combination of the values in the | |
AutoFormattingFlag enum. The default is AutoNone. Choose | |
AutoAll to enable all automatic formatting. | |
Currently, the only automatic formatting feature provided is | |
AutoBulletList; future versions of Qt may offer more. | |
*/ | |
QTextEdit::AutoFormatting QTextEdit::autoFormatting() const | |
{ | |
Q_D(const QTextEdit); | |
return d->autoFormatting; | |
} | |
void QTextEdit::setAutoFormatting(AutoFormatting features) | |
{ | |
Q_D(QTextEdit); | |
d->autoFormatting = features; | |
} | |
/*! | |
Convenience slot that inserts \a text at the current | |
cursor position. | |
It is equivalent to | |
\snippet doc/src/snippets/code/src_gui_widgets_qtextedit.cpp 1 | |
*/ | |
void QTextEdit::insertPlainText(const QString &text) | |
{ | |
Q_D(QTextEdit); | |
d->control->insertPlainText(text); | |
} | |
/*! | |
Convenience slot that inserts \a text which is assumed to be of | |
html formatting at the current cursor position. | |
It is equivalent to: | |
\snippet doc/src/snippets/code/src_gui_widgets_qtextedit.cpp 2 | |
\note When using this function with a style sheet, the style sheet will | |
only apply to the current block in the document. In order to apply a style | |
sheet throughout a document, use QTextDocument::setDefaultStyleSheet() | |
instead. | |
*/ | |
#ifndef QT_NO_TEXTHTMLPARSER | |
void QTextEdit::insertHtml(const QString &text) | |
{ | |
Q_D(QTextEdit); | |
d->control->insertHtml(text); | |
} | |
#endif // QT_NO_TEXTHTMLPARSER | |
/*! | |
Scrolls the text edit so that the anchor with the given \a name is | |
visible; does nothing if the \a name is empty, or is already | |
visible, or isn't found. | |
*/ | |
void QTextEdit::scrollToAnchor(const QString &name) | |
{ | |
Q_D(QTextEdit); | |
if (name.isEmpty()) | |
return; | |
if (!isVisible()) { | |
d->anchorToScrollToWhenVisible = name; | |
return; | |
} | |
QPointF p = d->control->anchorPosition(name); | |
const int newPosition = qRound(p.y()); | |
if ( d->vbar->maximum() < newPosition ) | |
d->_q_adjustScrollbars(); | |
d->vbar->setValue(newPosition); | |
} | |
/*! | |
\fn QTextEdit::zoomIn(int range) | |
Zooms in on the text by making the base font size \a range | |
points larger and recalculating all font sizes to be the new size. | |
This does not change the size of any images. | |
\sa zoomOut() | |
*/ | |
void QTextEdit::zoomIn(int range) | |
{ | |
QFont f = font(); | |
const int newSize = f.pointSize() + range; | |
if (newSize <= 0) | |
return; | |
f.setPointSize(newSize); | |
setFont(f); | |
} | |
/*! | |
\fn QTextEdit::zoomOut(int range) | |
\overload | |
Zooms out on the text by making the base font size \a range points | |
smaller and recalculating all font sizes to be the new size. This | |
does not change the size of any images. | |
\sa zoomIn() | |
*/ | |
void QTextEdit::zoomOut(int range) | |
{ | |
zoomIn(-range); | |
} | |
/*! | |
\since 4.2 | |
Moves the cursor by performing the given \a operation. | |
If \a mode is QTextCursor::KeepAnchor, the cursor selects the text it moves over. | |
This is the same effect that the user achieves when they hold down the Shift key | |
and move the cursor with the cursor keys. | |
\sa QTextCursor::movePosition() | |
*/ | |
void QTextEdit::moveCursor(QTextCursor::MoveOperation operation, QTextCursor::MoveMode mode) | |
{ | |
Q_D(QTextEdit); | |
d->control->moveCursor(operation, mode); | |
} | |
/*! | |
\since 4.2 | |
Returns whether text can be pasted from the clipboard into the textedit. | |
*/ | |
bool QTextEdit::canPaste() const | |
{ | |
Q_D(const QTextEdit); | |
return d->control->canPaste(); | |
} | |
#ifndef QT_NO_PRINTER | |
/*! | |
\since 4.3 | |
Convenience function to print the text edit's document to the given \a printer. This | |
is equivalent to calling the print method on the document directly except that this | |
function also supports QPrinter::Selection as print range. | |
\sa QTextDocument::print() | |
*/ | |
void QTextEdit::print(QPrinter *printer) const | |
{ | |
Q_D(const QTextEdit); | |
d->control->print(printer); | |
} | |
#endif // QT _NO_PRINTER | |
/*! \property QTextEdit::tabChangesFocus | |
\brief whether \gui Tab changes focus or is accepted as input | |
In some occasions text edits should not allow the user to input | |
tabulators or change indentation using the \gui Tab key, as this breaks | |
the focus chain. The default is false. | |
*/ | |
bool QTextEdit::tabChangesFocus() const | |
{ | |
Q_D(const QTextEdit); | |
return d->tabChangesFocus; | |
} | |
void QTextEdit::setTabChangesFocus(bool b) | |
{ | |
Q_D(QTextEdit); | |
d->tabChangesFocus = b; | |
} | |
/*! | |
\property QTextEdit::documentTitle | |
\brief the title of the document parsed from the text. | |
By default, for a newly-created, empty document, this property contains | |
an empty string. | |
*/ | |
/*! | |
\property QTextEdit::lineWrapMode | |
\brief the line wrap mode | |
The default mode is WidgetWidth which causes words to be | |
wrapped at the right edge of the text edit. Wrapping occurs at | |
whitespace, keeping whole words intact. If you want wrapping to | |
occur within words use setWordWrapMode(). If you set a wrap mode of | |
FixedPixelWidth or FixedColumnWidth you should also call | |
setLineWrapColumnOrWidth() with the width you want. | |
\sa lineWrapColumnOrWidth | |
*/ | |
QTextEdit::LineWrapMode QTextEdit::lineWrapMode() const | |
{ | |
Q_D(const QTextEdit); | |
return d->lineWrap; | |
} | |
void QTextEdit::setLineWrapMode(LineWrapMode wrap) | |
{ | |
Q_D(QTextEdit); | |
if (d->lineWrap == wrap) | |
return; | |
d->lineWrap = wrap; | |
d->updateDefaultTextOption(); | |
d->relayoutDocument(); | |
} | |
/*! | |
\property QTextEdit::lineWrapColumnOrWidth | |
\brief the position (in pixels or columns depending on the wrap mode) where text will be wrapped | |
If the wrap mode is FixedPixelWidth, the value is the number of | |
pixels from the left edge of the text edit at which text should be | |
wrapped. If the wrap mode is FixedColumnWidth, the value is the | |
column number (in character columns) from the left edge of the | |
text edit at which text should be wrapped. | |
By default, this property contains a value of 0. | |
\sa lineWrapMode | |
*/ | |
int QTextEdit::lineWrapColumnOrWidth() const | |
{ | |
Q_D(const QTextEdit); | |
return d->lineWrapColumnOrWidth; | |
} | |
void QTextEdit::setLineWrapColumnOrWidth(int w) | |
{ | |
Q_D(QTextEdit); | |
d->lineWrapColumnOrWidth = w; | |
d->relayoutDocument(); | |
} | |
/*! | |
\property QTextEdit::wordWrapMode | |
\brief the mode QTextEdit will use when wrapping text by words | |
By default, this property is set to QTextOption::WrapAtWordBoundaryOrAnywhere. | |
\sa QTextOption::WrapMode | |
*/ | |
QTextOption::WrapMode QTextEdit::wordWrapMode() const | |
{ | |
Q_D(const QTextEdit); | |
return d->wordWrap; | |
} | |
void QTextEdit::setWordWrapMode(QTextOption::WrapMode mode) | |
{ | |
Q_D(QTextEdit); | |
if (mode == d->wordWrap) | |
return; | |
d->wordWrap = mode; | |
d->updateDefaultTextOption(); | |
} | |
/*! | |
Finds the next occurrence of the string, \a exp, using the given | |
\a options. Returns true if \a exp was found and changes the | |
cursor to select the match; otherwise returns false. | |
*/ | |
bool QTextEdit::find(const QString &exp, QTextDocument::FindFlags options) | |
{ | |
Q_D(QTextEdit); | |
return d->control->find(exp, options); | |
} | |
/*! | |
\fn void QTextEdit::copyAvailable(bool yes) | |
This signal is emitted when text is selected or de-selected in the | |
text edit. | |
When text is selected this signal will be emitted with \a yes set | |
to true. If no text has been selected or if the selected text is | |
de-selected this signal is emitted with \a yes set to false. | |
If \a yes is true then copy() can be used to copy the selection to | |
the clipboard. If \a yes is false then copy() does nothing. | |
\sa selectionChanged() | |
*/ | |
/*! | |
\fn void QTextEdit::currentCharFormatChanged(const QTextCharFormat &f) | |
This signal is emitted if the current character format has changed, for | |
example caused by a change of the cursor position. | |
The new format is \a f. | |
\sa setCurrentCharFormat() | |
*/ | |
/*! | |
\fn void QTextEdit::selectionChanged() | |
This signal is emitted whenever the selection changes. | |
\sa copyAvailable() | |
*/ | |
/*! | |
\fn void QTextEdit::cursorPositionChanged() | |
This signal is emitted whenever the position of the | |
cursor changed. | |
*/ | |
/*! | |
\since 4.2 | |
Sets the text edit's \a text. The text can be plain text or HTML | |
and the text edit will try to guess the right format. | |
Use setHtml() or setPlainText() directly to avoid text edit's guessing. | |
\sa toPlainText(), toHtml() | |
*/ | |
void QTextEdit::setText(const QString &text) | |
{ | |
Q_D(QTextEdit); | |
Qt::TextFormat format = d->textFormat; | |
if (d->textFormat == Qt::AutoText) | |
format = Qt::mightBeRichText(text) ? Qt::RichText : Qt::PlainText; | |
#ifndef QT_NO_TEXTHTMLPARSER | |
if (format == Qt::RichText || format == Qt::LogText) | |
setHtml(text); | |
else | |
#endif | |
setPlainText(text); | |
} | |
#ifdef QT3_SUPPORT | |
/*! | |
Use the QTextCursor class instead. | |
*/ | |
void QTextEdit::moveCursor(CursorAction action, QTextCursor::MoveMode mode) | |
{ | |
Q_D(QTextEdit); | |
if (action == MovePageUp) { | |
d->pageUpDown(QTextCursor::Up, mode); | |
return; | |
} else if (action == MovePageDown) { | |
d->pageUpDown(QTextCursor::Down, mode); | |
return; | |
} | |
QTextCursor cursor = d->control->textCursor(); | |
QTextCursor::MoveOperation op = QTextCursor::NoMove; | |
switch (action) { | |
case MoveBackward: op = QTextCursor::Left; break; | |
case MoveForward: op = QTextCursor::Right; break; | |
case MoveWordBackward: op = QTextCursor::WordLeft; break; | |
case MoveWordForward: op = QTextCursor::WordRight; break; | |
case MoveUp: op = QTextCursor::Up; break; | |
case MoveDown: op = QTextCursor::Down; break; | |
case MoveLineStart: op = QTextCursor::StartOfLine; break; | |
case MoveLineEnd: op = QTextCursor::EndOfLine; break; | |
case MoveHome: op = QTextCursor::Start; break; | |
case MoveEnd: op = QTextCursor::End; break; | |
default: return; | |
} | |
cursor.movePosition(op, mode); | |
d->control->setTextCursor(cursor); | |
} | |
/*! | |
Use the QTextCursor class instead. | |
*/ | |
void QTextEdit::moveCursor(CursorAction action, bool select) | |
{ | |
moveCursor(action, select ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor); | |
} | |
/*! | |
Executes keyboard action \a action. | |
Use the QTextCursor class instead. | |
\sa textCursor() | |
*/ | |
void QTextEdit::doKeyboardAction(KeyboardAction action) | |
{ | |
Q_D(QTextEdit); | |
QTextCursor cursor = d->control->textCursor(); | |
switch (action) { | |
case ActionBackspace: cursor.deletePreviousChar(); break; | |
case ActionDelete: cursor.deleteChar(); break; | |
case ActionReturn: cursor.insertBlock(); break; | |
case ActionKill: { | |
QTextBlock block = cursor.block(); | |
if (cursor.position() == block.position() + block.length() - 2) | |
cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor); | |
else | |
cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); | |
cursor.deleteChar(); | |
break; | |
} | |
case ActionWordBackspace: | |
cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor); | |
cursor.deletePreviousChar(); | |
break; | |
case ActionWordDelete: | |
cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); | |
cursor.deleteChar(); | |
break; | |
} | |
d->control->setTextCursor(cursor); | |
} | |
/*! | |
Returns all the text in the text edit as plain text. | |
*/ | |
QString QTextEdit::text() const | |
{ | |
Q_D(const QTextEdit); | |
if (d->textFormat == Qt::RichText || d->textFormat == Qt::LogText || (d->textFormat == Qt::AutoText && d->preferRichText)) | |
return d->control->toHtml(); | |
else | |
return d->control->toPlainText(); | |
} | |
/*! | |
Sets the text format to format \a f. | |
\sa textFormat() | |
*/ | |
void QTextEdit::setTextFormat(Qt::TextFormat f) | |
{ | |
Q_D(QTextEdit); | |
d->textFormat = f; | |
} | |
/*! | |
Returns the text format. | |
\sa setTextFormat() | |
*/ | |
Qt::TextFormat QTextEdit::textFormat() const | |
{ | |
Q_D(const QTextEdit); | |
return d->textFormat; | |
} | |
#endif // QT3_SUPPORT | |
/*! | |
Appends a new paragraph with \a text to the end of the text edit. | |
\note The new paragraph appended will have the same character format and | |
block format as the current paragraph, determined by the position of the cursor. | |
\sa currentCharFormat(), QTextCursor::blockFormat() | |
*/ | |
void QTextEdit::append(const QString &text) | |
{ | |
Q_D(QTextEdit); | |
QTextBlock lastBlock = d->control->document()->lastBlock(); | |
const bool atBottom = isReadOnly() ? d->verticalOffset() >= d->vbar->maximum() : | |
d->control->textCursor().atEnd(); | |
d->control->append(text); | |
if (atBottom) | |
d->vbar->setValue(d->vbar->maximum()); | |
} | |
/*! | |
Ensures that the cursor is visible by scrolling the text edit if | |
necessary. | |
*/ | |
void QTextEdit::ensureCursorVisible() | |
{ | |
Q_D(QTextEdit); | |
d->control->ensureCursorVisible(); | |
} | |
/*! | |
\enum QTextEdit::KeyboardAction | |
\compat | |
\value ActionBackspace | |
\value ActionDelete | |
\value ActionReturn | |
\value ActionKill | |
\value ActionWordBackspace | |
\value ActionWordDelete | |
*/ | |
/*! | |
\fn bool QTextEdit::find(const QString &exp, bool cs, bool wo) | |
Use the find() overload that takes a QTextDocument::FindFlags | |
argument. | |
*/ | |
/*! | |
\fn void QTextEdit::sync() | |
Does nothing. | |
*/ | |
/*! | |
\fn void QTextEdit::setBold(bool b) | |
Use setFontWeight() instead. | |
*/ | |
/*! | |
\fn void QTextEdit::setUnderline(bool b) | |
Use setFontUnderline() instead. | |
*/ | |
/*! | |
\fn void QTextEdit::setItalic(bool i) | |
Use setFontItalic() instead. | |
*/ | |
/*! | |
\fn void QTextEdit::setFamily(const QString &family) | |
Use setFontFamily() instead. | |
*/ | |
/*! | |
\fn void QTextEdit::setPointSize(int size) | |
Use setFontPointSize() instead. | |
*/ | |
/*! | |
\fn bool QTextEdit::italic() const | |
Use fontItalic() instead. | |
*/ | |
/*! | |
\fn bool QTextEdit::bold() const | |
Use fontWeight() >= QFont::Bold instead. | |
*/ | |
/*! | |
\fn bool QTextEdit::underline() const | |
Use fontUnderline() instead. | |
*/ | |
/*! | |
\fn QString QTextEdit::family() const | |
Use fontFamily() instead. | |
*/ | |
/*! | |
\fn int QTextEdit::pointSize() const | |
Use int(fontPointSize()+0.5) instead. | |
*/ | |
/*! | |
\fn bool QTextEdit::hasSelectedText() const | |
Use textCursor().hasSelection() instead. | |
*/ | |
/*! | |
\fn QString QTextEdit::selectedText() const | |
Use textCursor().selectedText() instead. | |
*/ | |
/*! | |
\fn bool QTextEdit::isUndoAvailable() const | |
Use document()->isUndoAvailable() instead. | |
*/ | |
/*! | |
\fn bool QTextEdit::isRedoAvailable() const | |
Use document()->isRedoAvailable() instead. | |
*/ | |
/*! | |
\fn void QTextEdit::insert(const QString &text) | |
Use insertPlainText() instead. | |
*/ | |
/*! | |
\fn bool QTextEdit::isModified() const | |
Use document()->isModified() instead. | |
*/ | |
/*! | |
\fn QColor QTextEdit::color() const | |
Use textColor() instead. | |
*/ | |
/*! | |
\fn void QTextEdit::textChanged() | |
This signal is emitted whenever the document's content changes; for | |
example, when text is inserted or deleted, or when formatting is applied. | |
*/ | |
/*! | |
\fn void QTextEdit::undoAvailable(bool available) | |
This signal is emitted whenever undo operations become available | |
(\a available is true) or unavailable (\a available is false). | |
*/ | |
/*! | |
\fn void QTextEdit::redoAvailable(bool available) | |
This signal is emitted whenever redo operations become available | |
(\a available is true) or unavailable (\a available is false). | |
*/ | |
/*! | |
\fn void QTextEdit::currentFontChanged(const QFont &font) | |
Use currentCharFormatChanged() instead. | |
*/ | |
/*! | |
\fn void QTextEdit::currentColorChanged(const QColor &color) | |
Use currentCharFormatChanged() instead. | |
*/ | |
/*! | |
\fn void QTextEdit::setModified(bool m) | |
Use document->setModified() instead. | |
*/ | |
/*! | |
\fn void QTextEdit::setColor(const QColor &color) | |
Use setTextColor() instead. | |
*/ | |
#endif // QT_NO_TEXTEDIT | |
QT_END_NAMESPACE | |
#include "moc_qtextedit.cpp" |