src/gui/widgets/qplaintextedit.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qplaintextedit_p.h"
       
    43 
       
    44 
       
    45 #include <qfont.h>
       
    46 #include <qpainter.h>
       
    47 #include <qevent.h>
       
    48 #include <qdebug.h>
       
    49 #include <qmime.h>
       
    50 #include <qdrag.h>
       
    51 #include <qclipboard.h>
       
    52 #include <qmenu.h>
       
    53 #include <qstyle.h>
       
    54 #include <qtimer.h>
       
    55 #include "private/qtextdocumentlayout_p.h"
       
    56 #include "private/qabstracttextdocumentlayout_p.h"
       
    57 #include "qtextdocument.h"
       
    58 #include "private/qtextdocument_p.h"
       
    59 #include "qtextlist.h"
       
    60 #include "private/qtextcontrol_p.h"
       
    61 
       
    62 #include <qtextformat.h>
       
    63 #include <qdatetime.h>
       
    64 #include <qapplication.h>
       
    65 #include <limits.h>
       
    66 #include <qtexttable.h>
       
    67 #include <qvariant.h>
       
    68 #include <qinputcontext.h>
       
    69 
       
    70 #ifndef QT_NO_TEXTEDIT
       
    71 
       
    72 QT_BEGIN_NAMESPACE
       
    73 
       
    74 static inline bool shouldEnableInputMethod(QPlainTextEdit *plaintextedit)
       
    75 {
       
    76     return !plaintextedit->isReadOnly();
       
    77 }
       
    78 
       
    79 class QPlainTextDocumentLayoutPrivate : public QAbstractTextDocumentLayoutPrivate
       
    80 {
       
    81     Q_DECLARE_PUBLIC(QPlainTextDocumentLayout)
       
    82 public:
       
    83     QPlainTextDocumentLayoutPrivate() {
       
    84         mainViewPrivate = 0;
       
    85         width = 0;
       
    86         maximumWidth = 0;
       
    87         maximumWidthBlockNumber = 0;
       
    88         blockCount = 1;
       
    89         blockUpdate = blockDocumentSizeChanged = false;
       
    90         cursorWidth = 1;
       
    91         textLayoutFlags = 0;
       
    92     }
       
    93 
       
    94     qreal width;
       
    95     qreal maximumWidth;
       
    96     int maximumWidthBlockNumber;
       
    97     int blockCount;
       
    98     QPlainTextEditPrivate *mainViewPrivate;
       
    99     bool blockUpdate;
       
   100     bool blockDocumentSizeChanged;
       
   101     int cursorWidth;
       
   102     int textLayoutFlags;
       
   103 
       
   104     void layoutBlock(const QTextBlock &block);
       
   105     qreal blockWidth(const QTextBlock &block);
       
   106 
       
   107     void relayout();
       
   108 };
       
   109 
       
   110 
       
   111 
       
   112 /*! \class QPlainTextDocumentLayout
       
   113     \since 4.4
       
   114     \brief The QPlainTextDocumentLayout class implements a plain text layout for QTextDocument
       
   115 
       
   116     \ingroup richtext-processing
       
   117 
       
   118    A QPlainTextDocumentLayout is required for text documents that can
       
   119    be display or edited in a QPlainTextEdit. See
       
   120    QTextDocument::setDocumentLayout().
       
   121 
       
   122    QPlainTextDocumentLayout uses the QAbstractTextDocumentLayout API
       
   123    that QTextDocument requires, but redefines it partially in order to
       
   124    support plain text better. For instances, it does not operate on
       
   125    vertical pixels, but on paragraphs (called blocks) instead. The
       
   126    height of a document is identical to the number of paragraphs it
       
   127    contains. The layout also doesn't support tables or nested frames,
       
   128    or any sort of advanced text layout that goes beyond a list of
       
   129    paragraphs with syntax highlighting.
       
   130 
       
   131 */
       
   132 
       
   133 
       
   134 
       
   135 /*!
       
   136   Constructs a plain text document layout for the text \a document.
       
   137  */
       
   138 QPlainTextDocumentLayout::QPlainTextDocumentLayout(QTextDocument *document)
       
   139     :QAbstractTextDocumentLayout(* new QPlainTextDocumentLayoutPrivate, document) {
       
   140 }
       
   141 /*!
       
   142   Destructs a plain text document layout.
       
   143  */
       
   144 QPlainTextDocumentLayout::~QPlainTextDocumentLayout() {}
       
   145 
       
   146 
       
   147 /*!
       
   148   \reimp
       
   149  */
       
   150 void QPlainTextDocumentLayout::draw(QPainter *, const PaintContext &)
       
   151 {
       
   152 }
       
   153 
       
   154 /*!
       
   155   \reimp
       
   156  */
       
   157 int QPlainTextDocumentLayout::hitTest(const QPointF &, Qt::HitTestAccuracy ) const
       
   158 {
       
   159 //     this function is used from
       
   160 //     QAbstractTextDocumentLayout::anchorAt(), but is not
       
   161 //     implementable in a plain text document layout, because the
       
   162 //     layout depends on the top block and top line which depends on
       
   163 //     the view
       
   164     return -1;
       
   165 }
       
   166 
       
   167 /*!
       
   168   \reimp
       
   169  */
       
   170 int QPlainTextDocumentLayout::pageCount() const
       
   171 { return 1; }
       
   172 
       
   173 /*!
       
   174   \reimp
       
   175  */
       
   176 QSizeF QPlainTextDocumentLayout::documentSize() const
       
   177 {
       
   178     Q_D(const QPlainTextDocumentLayout);
       
   179     return QSizeF(d->maximumWidth, document()->lineCount());
       
   180 }
       
   181 
       
   182 /*!
       
   183   \reimp
       
   184  */
       
   185 QRectF QPlainTextDocumentLayout::frameBoundingRect(QTextFrame *) const
       
   186 {
       
   187     Q_D(const QPlainTextDocumentLayout);
       
   188     return QRectF(0, 0, qMax(d->width, d->maximumWidth), qreal(INT_MAX));
       
   189 }
       
   190 
       
   191 /*!
       
   192   \reimp
       
   193  */
       
   194 QRectF QPlainTextDocumentLayout::blockBoundingRect(const QTextBlock &block) const
       
   195 {
       
   196     if (!block.isValid()) { return QRectF(); }
       
   197     QTextLayout *tl = block.layout();
       
   198     if (!tl->lineCount())
       
   199         const_cast<QPlainTextDocumentLayout*>(this)->layoutBlock(block);
       
   200     QRectF br;
       
   201     if (block.isVisible()) {
       
   202         br = QRectF(QPointF(0, 0), tl->boundingRect().bottomRight());
       
   203         if (tl->lineCount() == 1)
       
   204             br.setWidth(qMax(br.width(), tl->lineAt(0).naturalTextWidth()));
       
   205         qreal margin = document()->documentMargin();
       
   206         br.adjust(0, 0, margin, 0);
       
   207         if (!block.next().isValid())
       
   208             br.adjust(0, 0, 0, margin);
       
   209     }
       
   210     return br;
       
   211 
       
   212 }
       
   213 
       
   214 /*!
       
   215   Ensures that \a block has a valid layout
       
   216  */
       
   217 void QPlainTextDocumentLayout::ensureBlockLayout(const QTextBlock &block) const
       
   218 {
       
   219     if (!block.isValid())
       
   220         return;
       
   221     QTextLayout *tl = block.layout();
       
   222     if (!tl->lineCount())
       
   223         const_cast<QPlainTextDocumentLayout*>(this)->layoutBlock(block);
       
   224 }
       
   225 
       
   226 
       
   227 /*! \property QPlainTextDocumentLayout::cursorWidth
       
   228 
       
   229     This property specifies the width of the cursor in pixels. The default value is 1.
       
   230 */
       
   231 void QPlainTextDocumentLayout::setCursorWidth(int width)
       
   232 {
       
   233     Q_D(QPlainTextDocumentLayout);
       
   234     d->cursorWidth = width;
       
   235 }
       
   236 
       
   237 int QPlainTextDocumentLayout::cursorWidth() const
       
   238 {
       
   239     Q_D(const QPlainTextDocumentLayout);
       
   240     return d->cursorWidth;
       
   241 }
       
   242 
       
   243 QPlainTextDocumentLayoutPrivate *QPlainTextDocumentLayout::priv() const
       
   244 {
       
   245     Q_D(const QPlainTextDocumentLayout);
       
   246     return const_cast<QPlainTextDocumentLayoutPrivate*>(d);
       
   247 }
       
   248 
       
   249 
       
   250 /*!
       
   251 
       
   252    Requests a complete update on all views.
       
   253  */
       
   254 void QPlainTextDocumentLayout::requestUpdate()
       
   255 {
       
   256     emit update(QRectF(0., -document()->documentMargin(), 1000000000., 1000000000.));
       
   257 }
       
   258 
       
   259 
       
   260 void QPlainTextDocumentLayout::setTextWidth(qreal newWidth)
       
   261 {
       
   262     Q_D(QPlainTextDocumentLayout);
       
   263     d->width = d->maximumWidth = newWidth;
       
   264     d->relayout();
       
   265 }
       
   266 
       
   267 qreal QPlainTextDocumentLayout::textWidth() const
       
   268 {
       
   269     Q_D(const QPlainTextDocumentLayout);
       
   270     return d->width;
       
   271 }
       
   272 
       
   273 void QPlainTextDocumentLayoutPrivate::relayout()
       
   274 {
       
   275     Q_Q(QPlainTextDocumentLayout);
       
   276     QTextBlock block = q->document()->firstBlock();
       
   277     while (block.isValid()) {
       
   278         block.layout()->clearLayout();
       
   279         block.setLineCount(block.isVisible() ? 1 : 0);
       
   280         block = block.next();
       
   281     }
       
   282     emit q->update();
       
   283 }
       
   284 
       
   285 
       
   286 /*! \reimp
       
   287  */
       
   288 void QPlainTextDocumentLayout::documentChanged(int from, int /*charsRemoved*/, int charsAdded)
       
   289 {
       
   290     Q_D(QPlainTextDocumentLayout);
       
   291     QTextDocument *doc = document();
       
   292     int newBlockCount = doc->blockCount();
       
   293 
       
   294     QTextBlock changeStartBlock = doc->findBlock(from);
       
   295     QTextBlock changeEndBlock = doc->findBlock(qMax(0, from + charsAdded - 1));
       
   296 
       
   297     if (changeStartBlock == changeEndBlock && newBlockCount == d->blockCount) {
       
   298         QTextBlock block = changeStartBlock;
       
   299         int blockLineCount = block.layout()->lineCount();
       
   300         if (block.isValid() && blockLineCount) {
       
   301             QRectF oldBr = blockBoundingRect(block);
       
   302             layoutBlock(block);
       
   303             QRectF newBr = blockBoundingRect(block);
       
   304             if (newBr.height() == oldBr.height()) {
       
   305                 if (!d->blockUpdate)
       
   306                     emit updateBlock(block);
       
   307                 return;
       
   308             }
       
   309         }
       
   310     } else {
       
   311         QTextBlock block = changeStartBlock;
       
   312         do {
       
   313             block.clearLayout();
       
   314             if (block == changeEndBlock)
       
   315                 break;
       
   316             block = block.next();
       
   317         } while(block.isValid());
       
   318     }
       
   319 
       
   320     if (newBlockCount != d->blockCount) {
       
   321 
       
   322         int changeEnd = changeEndBlock.blockNumber();
       
   323         int blockDiff = newBlockCount - d->blockCount;
       
   324         int oldChangeEnd = changeEnd - blockDiff;
       
   325 
       
   326         if (d->maximumWidthBlockNumber > oldChangeEnd)
       
   327             d->maximumWidthBlockNumber += blockDiff;
       
   328 
       
   329         d->blockCount = newBlockCount;
       
   330         if (d->blockCount == 1)
       
   331             d->maximumWidth = blockWidth(doc->firstBlock());
       
   332 
       
   333         if (!d->blockDocumentSizeChanged)
       
   334             emit documentSizeChanged(documentSize());
       
   335 
       
   336         if (blockDiff == 1 && changeEnd == newBlockCount -1 ) {
       
   337             if (!d->blockUpdate) {
       
   338                 QTextBlock b = changeStartBlock;
       
   339                 for(;;) {
       
   340                     emit updateBlock(b);
       
   341                     if (b == changeEndBlock)
       
   342                         break;
       
   343                     b = b.next();
       
   344                 }
       
   345             }
       
   346             return;
       
   347         }
       
   348     }
       
   349 
       
   350     if (!d->blockUpdate)
       
   351 	emit update(QRectF(0., -doc->documentMargin(), 1000000000., 1000000000.)); // optimization potential
       
   352 }
       
   353 
       
   354 
       
   355 void QPlainTextDocumentLayout::layoutBlock(const QTextBlock &block)
       
   356 {
       
   357     Q_D(QPlainTextDocumentLayout);
       
   358     QTextDocument *doc = document();
       
   359     qreal margin = doc->documentMargin();
       
   360     QFontMetrics fm(doc->defaultFont());
       
   361     qreal blockMaximumWidth = 0;
       
   362 
       
   363     int leading = qMax(0, fm.leading());
       
   364     qreal height = 0;
       
   365     QTextLayout *tl = block.layout();
       
   366     QTextOption option = doc->defaultTextOption();
       
   367     tl->setTextOption(option);
       
   368 
       
   369     int extraMargin = 0;
       
   370     if (option.flags() & QTextOption::AddSpaceForLineAndParagraphSeparators) {
       
   371         QFontMetrics fm(block.charFormat().font());
       
   372         extraMargin += fm.width(QChar(0x21B5));
       
   373     }
       
   374     tl->beginLayout();
       
   375     qreal availableWidth = d->width;
       
   376     if (availableWidth <= 0) {
       
   377         availableWidth = qreal(INT_MAX); // similar to text edit with pageSize.width == 0
       
   378     }
       
   379     availableWidth -= 2*margin + extraMargin;
       
   380     while (1) {
       
   381         QTextLine line = tl->createLine();
       
   382         if (!line.isValid())
       
   383             break;
       
   384         line.setLineWidth(availableWidth);
       
   385 
       
   386         height += leading;
       
   387         line.setPosition(QPointF(margin, height));
       
   388         height += line.height();
       
   389         blockMaximumWidth = qMax(blockMaximumWidth, line.naturalTextWidth() + 2*margin);
       
   390     }
       
   391     tl->endLayout();
       
   392 
       
   393     int previousLineCount = doc->lineCount();
       
   394     const_cast<QTextBlock&>(block).setLineCount(block.isVisible() ? tl->lineCount() : 0);
       
   395     int lineCount = doc->lineCount();
       
   396 
       
   397     bool emitDocumentSizeChanged = previousLineCount != lineCount;
       
   398     if (blockMaximumWidth > d->maximumWidth) {
       
   399         // new longest line
       
   400         d->maximumWidth = blockMaximumWidth;
       
   401         d->maximumWidthBlockNumber = block.blockNumber();
       
   402         emitDocumentSizeChanged = true;
       
   403     } else if (block.blockNumber() == d->maximumWidthBlockNumber && blockMaximumWidth < d->maximumWidth) {
       
   404         // longest line shrinking
       
   405         QTextBlock b = doc->firstBlock();
       
   406         d->maximumWidth = 0;
       
   407         QTextBlock maximumBlock;
       
   408         while (b.isValid()) {
       
   409             qreal blockMaximumWidth = blockWidth(b);
       
   410             if (blockMaximumWidth > d->maximumWidth) {
       
   411                 d->maximumWidth = blockMaximumWidth;
       
   412                 maximumBlock = b;
       
   413             }
       
   414             b = b.next();
       
   415         }
       
   416         if (maximumBlock.isValid()) {
       
   417             d->maximumWidthBlockNumber = maximumBlock.blockNumber();
       
   418             emitDocumentSizeChanged = true;
       
   419         }
       
   420     }
       
   421     if (emitDocumentSizeChanged && !d->blockDocumentSizeChanged)
       
   422         emit documentSizeChanged(documentSize());
       
   423 }
       
   424 
       
   425 qreal QPlainTextDocumentLayout::blockWidth(const QTextBlock &block)
       
   426 {
       
   427     QTextLayout *layout = block.layout();
       
   428     if (!layout->lineCount())
       
   429         return 0; // only for layouted blocks
       
   430     qreal blockWidth = 0;
       
   431     for (int i = 0; i < layout->lineCount(); ++i) {
       
   432         QTextLine line = layout->lineAt(i);
       
   433         blockWidth = qMax(line.naturalTextWidth() + 8, blockWidth);
       
   434     }
       
   435     return blockWidth;
       
   436 }
       
   437 
       
   438 
       
   439 QPlainTextEditControl::QPlainTextEditControl(QPlainTextEdit *parent)
       
   440     : QTextControl(parent), textEdit(parent),
       
   441       topBlock(0)
       
   442 {
       
   443     setAcceptRichText(false);
       
   444 }
       
   445 
       
   446 void QPlainTextEditPrivate::_q_cursorPositionChanged()
       
   447 {
       
   448     pageUpDownLastCursorYIsValid = false;
       
   449 }
       
   450 
       
   451 void QPlainTextEditPrivate::_q_verticalScrollbarActionTriggered(int action) {
       
   452     if (action == QAbstractSlider::SliderPageStepAdd) {
       
   453         pageUpDown(QTextCursor::Down, QTextCursor::MoveAnchor, false);
       
   454     } else if (action == QAbstractSlider::SliderPageStepSub) {
       
   455         pageUpDown(QTextCursor::Up, QTextCursor::MoveAnchor, false);
       
   456     }
       
   457 }
       
   458 
       
   459 QMimeData *QPlainTextEditControl::createMimeDataFromSelection() const {
       
   460         QPlainTextEdit *ed = qobject_cast<QPlainTextEdit *>(parent());
       
   461         if (!ed)
       
   462             return QTextControl::createMimeDataFromSelection();
       
   463         return ed->createMimeDataFromSelection();
       
   464     }
       
   465 bool QPlainTextEditControl::canInsertFromMimeData(const QMimeData *source) const {
       
   466     QPlainTextEdit *ed = qobject_cast<QPlainTextEdit *>(parent());
       
   467     if (!ed)
       
   468         return QTextControl::canInsertFromMimeData(source);
       
   469     return ed->canInsertFromMimeData(source);
       
   470 }
       
   471 void QPlainTextEditControl::insertFromMimeData(const QMimeData *source) {
       
   472     QPlainTextEdit *ed = qobject_cast<QPlainTextEdit *>(parent());
       
   473     if (!ed)
       
   474         QTextControl::insertFromMimeData(source);
       
   475     else
       
   476         ed->insertFromMimeData(source);
       
   477 }
       
   478 
       
   479 int QPlainTextEditPrivate::verticalOffset(int topBlock, int topLine) const
       
   480 {
       
   481     qreal offset = 0;
       
   482     QTextDocument *doc = control->document();
       
   483 
       
   484     if (topLine) {
       
   485         QTextBlock currentBlock = doc->findBlockByNumber(topBlock);
       
   486         QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(doc->documentLayout());
       
   487         Q_ASSERT(documentLayout);
       
   488         QRectF r = documentLayout->blockBoundingRect(currentBlock);
       
   489         QTextLayout *layout = currentBlock.layout();
       
   490         if (layout && topLine <= layout->lineCount()) {
       
   491             QTextLine line = layout->lineAt(topLine - 1);
       
   492             const QRectF lr = line.naturalTextRect();
       
   493             offset = lr.bottom();
       
   494         }
       
   495     }
       
   496     if (topBlock == 0 && topLine == 0)
       
   497         offset -= doc->documentMargin(); // top margin
       
   498     return (int)offset;
       
   499 }
       
   500 
       
   501 
       
   502 int QPlainTextEditPrivate::verticalOffset() const {
       
   503     return verticalOffset(control->topBlock, topLine);
       
   504 }
       
   505 
       
   506 
       
   507 QTextBlock QPlainTextEditControl::firstVisibleBlock() const
       
   508 {
       
   509     return document()->findBlockByNumber(topBlock);
       
   510 }
       
   511 
       
   512 
       
   513 
       
   514 int QPlainTextEditControl::hitTest(const QPointF &point, Qt::HitTestAccuracy ) const {
       
   515     int currentBlockNumber = topBlock;
       
   516     QTextBlock currentBlock = document()->findBlockByNumber(currentBlockNumber);
       
   517     if (!currentBlock.isValid())
       
   518         return -1;
       
   519 
       
   520     QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(document()->documentLayout());
       
   521     Q_ASSERT(documentLayout);
       
   522 
       
   523     QPointF offset;
       
   524     QRectF r = documentLayout->blockBoundingRect(currentBlock);
       
   525     while (currentBlock.next().isValid() && r.bottom() + offset.y() <= point.y()) {
       
   526         offset.ry() += r.height();
       
   527         currentBlock = currentBlock.next();
       
   528         ++currentBlockNumber;
       
   529         r = documentLayout->blockBoundingRect(currentBlock);
       
   530     }
       
   531     while (currentBlock.previous().isValid() && r.top() + offset.y() > point.y()) {
       
   532         offset.ry() -= r.height();
       
   533         currentBlock = currentBlock.previous();
       
   534         --currentBlockNumber;
       
   535         r = documentLayout->blockBoundingRect(currentBlock);
       
   536     }
       
   537 
       
   538 
       
   539     if (!currentBlock.isValid())
       
   540         return -1;
       
   541     QTextLayout *layout = currentBlock.layout();
       
   542     int off = 0;
       
   543     QPointF pos = point - offset;
       
   544     for (int i = 0; i < layout->lineCount(); ++i) {
       
   545         QTextLine line = layout->lineAt(i);
       
   546         const QRectF lr = line.naturalTextRect();
       
   547         if (lr.top() > pos.y()) {
       
   548             off = qMin(off, line.textStart());
       
   549         } else if (lr.bottom() <= pos.y()) {
       
   550             off = qMax(off, line.textStart() + line.textLength());
       
   551         } else {
       
   552             off = line.xToCursor(pos.x(), overwriteMode() ?
       
   553                                  QTextLine::CursorOnCharacter : QTextLine::CursorBetweenCharacters);
       
   554             break;
       
   555         }
       
   556     }
       
   557 
       
   558     return currentBlock.position() + off;
       
   559 }
       
   560 
       
   561 QRectF QPlainTextEditControl::blockBoundingRect(const QTextBlock &block) const {
       
   562     int currentBlockNumber = topBlock;
       
   563     int blockNumber = block.blockNumber();
       
   564     QTextBlock currentBlock = document()->findBlockByNumber(currentBlockNumber);
       
   565     if (!currentBlock.isValid())
       
   566         return QRectF();
       
   567     Q_ASSERT(currentBlock.blockNumber() == currentBlockNumber);
       
   568     QTextDocument *doc = document();
       
   569     QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(doc->documentLayout());
       
   570     Q_ASSERT(documentLayout);
       
   571 
       
   572     QPointF offset;
       
   573     if (!block.isValid())
       
   574         return QRectF();
       
   575     QRectF r = documentLayout->blockBoundingRect(currentBlock);
       
   576     int maxVerticalOffset = r.height();
       
   577     while (currentBlockNumber < blockNumber && offset.y() - maxVerticalOffset <= 2* textEdit->viewport()->height()) {
       
   578         offset.ry() += r.height();
       
   579         currentBlock = currentBlock.next();
       
   580         ++currentBlockNumber;
       
   581         if (!currentBlock.isVisible()) {
       
   582             currentBlock = doc->findBlockByLineNumber(currentBlock.firstLineNumber());
       
   583             currentBlockNumber = currentBlock.blockNumber();
       
   584         }
       
   585         r = documentLayout->blockBoundingRect(currentBlock);
       
   586     }
       
   587     while (currentBlockNumber > blockNumber && offset.y() + maxVerticalOffset >= -textEdit->viewport()->height()) {
       
   588         currentBlock = currentBlock.previous();
       
   589         --currentBlockNumber;
       
   590         while (!currentBlock.isVisible()) {
       
   591             currentBlock = currentBlock.previous();
       
   592             --currentBlockNumber;
       
   593         }
       
   594         if (!currentBlock.isValid())
       
   595             break;
       
   596 
       
   597         r = documentLayout->blockBoundingRect(currentBlock);
       
   598         offset.ry() -= r.height();
       
   599     }
       
   600 
       
   601     if (currentBlockNumber != blockNumber) {
       
   602         // fallback for blocks out of reach. Give it some geometry at
       
   603         // least, and ensure the layout is up to date.
       
   604         r = documentLayout->blockBoundingRect(block);
       
   605         if (currentBlockNumber > blockNumber)
       
   606             offset.ry() -= r.height();
       
   607     }
       
   608     r.translate(offset);
       
   609     return r;
       
   610 }
       
   611 
       
   612 
       
   613 void QPlainTextEditPrivate::setTopLine(int visualTopLine, int dx)
       
   614 {
       
   615     QTextDocument *doc = control->document();
       
   616     QTextBlock block = doc->findBlockByLineNumber(visualTopLine);
       
   617     int blockNumber = block.blockNumber();
       
   618     int lineNumber = visualTopLine - block.firstLineNumber();
       
   619     setTopBlock(blockNumber, lineNumber, dx);
       
   620 }
       
   621 
       
   622 void QPlainTextEditPrivate::setTopBlock(int blockNumber, int lineNumber, int dx)
       
   623 {
       
   624     Q_Q(QPlainTextEdit);
       
   625     blockNumber = qMax(0, blockNumber);
       
   626     lineNumber = qMax(0, lineNumber);
       
   627     QTextDocument *doc = control->document();
       
   628     QTextBlock block = doc->findBlockByNumber(blockNumber);
       
   629 
       
   630     int newTopLine = block.firstLineNumber() + lineNumber;
       
   631     int maxTopLine = vbar->maximum();
       
   632 
       
   633     if (newTopLine > maxTopLine) {
       
   634         block = doc->findBlockByLineNumber(maxTopLine);
       
   635         blockNumber = block.blockNumber();
       
   636         lineNumber = maxTopLine - block.firstLineNumber();
       
   637     }
       
   638 
       
   639     bool vbarSignalsBlocked = vbar->blockSignals(true);
       
   640     vbar->setValue(newTopLine);
       
   641     vbar->blockSignals(vbarSignalsBlocked);
       
   642 
       
   643     if (!dx && blockNumber == control->topBlock && lineNumber == topLine)
       
   644         return;
       
   645 
       
   646     if (viewport->updatesEnabled() && viewport->isVisible()) {
       
   647         int dy = 0;
       
   648         if (doc->findBlockByNumber(control->topBlock).isValid()) {
       
   649             dy = (int)(-q->blockBoundingGeometry(block).y())
       
   650                  + verticalOffset() - verticalOffset(blockNumber, lineNumber);
       
   651         }
       
   652         control->topBlock = blockNumber;
       
   653         topLine = lineNumber;
       
   654         if (dx || dy)
       
   655             viewport->scroll(q->isRightToLeft() ? -dx : dx, dy);
       
   656         else
       
   657             viewport->update();
       
   658         emit q->updateRequest(viewport->rect(), dy);
       
   659     } else {
       
   660         control->topBlock = blockNumber;
       
   661         topLine = lineNumber;
       
   662     }
       
   663 
       
   664 }
       
   665 
       
   666 
       
   667 
       
   668 void QPlainTextEditPrivate::ensureVisible(int position, bool center, bool forceCenter) {
       
   669     Q_Q(QPlainTextEdit);
       
   670     QRectF visible = QRectF(viewport->rect()).translated(-q->contentOffset());
       
   671     QTextBlock block = control->document()->findBlock(position);
       
   672     if (!block.isValid())
       
   673         return;
       
   674     QRectF br = control->blockBoundingRect(block);
       
   675     if (!br.isValid())
       
   676         return;
       
   677     QRectF lr = br;
       
   678     QTextLine line = block.layout()->lineForTextPosition(position - block.position());
       
   679     Q_ASSERT(line.isValid());
       
   680     lr = line.naturalTextRect().translated(br.topLeft());
       
   681 
       
   682     if (lr.bottom() >= visible.bottom() || (center && lr.top() < visible.top()) || forceCenter){
       
   683 
       
   684         qreal height = visible.height();
       
   685         if (center)
       
   686             height /= 2;
       
   687 
       
   688         qreal h = center ? line.naturalTextRect().center().y() : line.naturalTextRect().bottom();
       
   689 
       
   690         while (h < height && block.previous().isValid()) {
       
   691             block = block.previous();
       
   692             h += q->blockBoundingRect(block).height();
       
   693         }
       
   694 
       
   695         int l = 0;
       
   696         int lineCount = block.layout()->lineCount();
       
   697         int voffset = verticalOffset(block.blockNumber(), 0);
       
   698         while (l < lineCount) {
       
   699             QRectF lineRect = block.layout()->lineAt(l).naturalTextRect();
       
   700             if (h - voffset - lineRect.top() <= height)
       
   701                 break;
       
   702             ++l;
       
   703         }
       
   704 
       
   705         if (block.next().isValid() && l >= lineCount) {
       
   706             block = block.next();
       
   707             l = 0;
       
   708         }
       
   709         setTopBlock(block.blockNumber(), l);
       
   710     } else if (lr.top() < visible.top()) {
       
   711         setTopBlock(block.blockNumber(), line.lineNumber());
       
   712     }
       
   713 
       
   714 }
       
   715 
       
   716 
       
   717 void QPlainTextEditPrivate::updateViewport()
       
   718 {
       
   719     Q_Q(QPlainTextEdit);
       
   720     viewport->update();
       
   721     emit q->updateRequest(viewport->rect(), 0);
       
   722 }
       
   723 
       
   724 QPlainTextEditPrivate::QPlainTextEditPrivate()
       
   725     : control(0),
       
   726       tabChangesFocus(false),
       
   727       lineWrap(QPlainTextEdit::WidgetWidth),
       
   728       wordWrap(QTextOption::WrapAtWordBoundaryOrAnywhere),
       
   729       clickCausedFocus(0),topLine(0), 
       
   730       pageUpDownLastCursorYIsValid(false)
       
   731 {
       
   732     showCursorOnInitialShow = true;
       
   733     backgroundVisible = false;
       
   734     centerOnScroll = false;
       
   735     inDrag = false;
       
   736 #ifdef Q_WS_WIN
       
   737     singleFingerPanEnabled = true;
       
   738 #endif
       
   739 }
       
   740 
       
   741 
       
   742 void QPlainTextEditPrivate::init(const QString &txt)
       
   743 {
       
   744     Q_Q(QPlainTextEdit);
       
   745     control = new QPlainTextEditControl(q);
       
   746 
       
   747     QTextDocument *doc = new QTextDocument(control);
       
   748     QAbstractTextDocumentLayout *layout = new QPlainTextDocumentLayout(doc);
       
   749     doc->setDocumentLayout(layout);
       
   750     control->setDocument(doc);
       
   751 
       
   752     control->setPalette(q->palette());
       
   753 
       
   754     QObject::connect(vbar, SIGNAL(actionTriggered(int)), q, SLOT(_q_verticalScrollbarActionTriggered(int)));
       
   755 
       
   756     QObject::connect(control, SIGNAL(microFocusChanged()), q, SLOT(updateMicroFocus()));
       
   757     QObject::connect(control, SIGNAL(documentSizeChanged(QSizeF)), q, SLOT(_q_adjustScrollbars()));
       
   758     QObject::connect(control, SIGNAL(blockCountChanged(int)), q, SIGNAL(blockCountChanged(int)));
       
   759     QObject::connect(control, SIGNAL(updateRequest(QRectF)), q, SLOT(_q_repaintContents(QRectF)));
       
   760     QObject::connect(control, SIGNAL(modificationChanged(bool)), q, SIGNAL(modificationChanged(bool)));
       
   761 
       
   762     QObject::connect(control, SIGNAL(textChanged()), q, SIGNAL(textChanged()));
       
   763     QObject::connect(control, SIGNAL(undoAvailable(bool)), q, SIGNAL(undoAvailable(bool)));
       
   764     QObject::connect(control, SIGNAL(redoAvailable(bool)), q, SIGNAL(redoAvailable(bool)));
       
   765     QObject::connect(control, SIGNAL(copyAvailable(bool)), q, SIGNAL(copyAvailable(bool)));
       
   766     QObject::connect(control, SIGNAL(selectionChanged()), q, SIGNAL(selectionChanged()));
       
   767     QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SLOT(_q_cursorPositionChanged()));
       
   768     QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorPositionChanged()));
       
   769 
       
   770 
       
   771     // set a null page size initially to avoid any relayouting until the textedit
       
   772     // is shown. relayoutDocument() will take care of setting the page size to the
       
   773     // viewport dimensions later.
       
   774     doc->setTextWidth(-1);
       
   775     doc->documentLayout()->setPaintDevice(viewport);
       
   776     doc->setDefaultFont(q->font());
       
   777 
       
   778 
       
   779     if (!txt.isEmpty())
       
   780         control->setPlainText(txt);
       
   781 
       
   782     hbar->setSingleStep(20);
       
   783     vbar->setSingleStep(1);
       
   784 
       
   785     viewport->setBackgroundRole(QPalette::Base);
       
   786     q->setAcceptDrops(true);
       
   787     q->setFocusPolicy(Qt::WheelFocus);
       
   788     q->setAttribute(Qt::WA_KeyCompression);
       
   789     q->setAttribute(Qt::WA_InputMethodEnabled);
       
   790 
       
   791 #ifndef QT_NO_CURSOR
       
   792     viewport->setCursor(Qt::IBeamCursor);
       
   793 #endif
       
   794     originalOffsetY = 0;
       
   795 }
       
   796 
       
   797 void QPlainTextEditPrivate::_q_repaintContents(const QRectF &contentsRect)
       
   798 {
       
   799     Q_Q(QPlainTextEdit);
       
   800     if (!contentsRect.isValid()) {
       
   801         updateViewport();
       
   802         return;
       
   803     }
       
   804     const int xOffset = horizontalOffset();
       
   805     const int yOffset = verticalOffset();
       
   806     const QRect visibleRect(xOffset, yOffset, viewport->width(), viewport->height());
       
   807 
       
   808     QRect r = contentsRect.adjusted(-1, -1, 1, 1).intersected(visibleRect).toAlignedRect();
       
   809     if (r.isEmpty())
       
   810         return;
       
   811 
       
   812     r.translate(-xOffset, -yOffset);
       
   813     viewport->update(r);
       
   814     emit q->updateRequest(r, 0);
       
   815 }
       
   816 
       
   817 void QPlainTextEditPrivate::pageUpDown(QTextCursor::MoveOperation op, QTextCursor::MoveMode moveMode, bool moveCursor)
       
   818 {
       
   819 
       
   820     Q_Q(QPlainTextEdit);
       
   821 
       
   822     QTextCursor cursor = control->textCursor();
       
   823     if (moveCursor) {
       
   824         ensureCursorVisible();
       
   825         if (!pageUpDownLastCursorYIsValid)
       
   826             pageUpDownLastCursorY = control->cursorRect(cursor).top() - verticalOffset();
       
   827     }
       
   828 
       
   829     qreal lastY = pageUpDownLastCursorY;
       
   830 
       
   831 
       
   832     if (op == QTextCursor::Down) {
       
   833         QRectF visible = QRectF(viewport->rect()).translated(-q->contentOffset());
       
   834         QTextBlock firstVisibleBlock = q->firstVisibleBlock();
       
   835         QTextBlock block = firstVisibleBlock;
       
   836         QRectF br = q->blockBoundingRect(block);
       
   837         qreal h = 0;
       
   838         int atEnd = false;
       
   839         while (h + br.height() <= visible.bottom()) {
       
   840             if (!block.next().isValid()) {
       
   841                 atEnd = true;
       
   842                 lastY = visible.bottom(); // set cursor to last line
       
   843                 break;
       
   844             }
       
   845             h += br.height();
       
   846             block = block.next();
       
   847             br = q->blockBoundingRect(block);
       
   848         }
       
   849 
       
   850         if (!atEnd) {
       
   851             int line = 0;
       
   852             qreal diff = visible.bottom() - h;
       
   853             int lineCount = block.layout()->lineCount();
       
   854             while (line < lineCount - 1) {
       
   855                 if (block.layout()->lineAt(line).naturalTextRect().bottom() > diff) {
       
   856                     // the first line that did not completely fit the screen
       
   857                     break;
       
   858                 }
       
   859                 ++line;
       
   860             }
       
   861             setTopBlock(block.blockNumber(), line);
       
   862         }
       
   863 
       
   864         if (moveCursor) {
       
   865             // move using movePosition to keep the cursor's x
       
   866             lastY += verticalOffset();
       
   867             bool moved = false;
       
   868             do {
       
   869                 moved = cursor.movePosition(op, moveMode);
       
   870             } while (moved && control->cursorRect(cursor).top() < lastY);
       
   871         }
       
   872 
       
   873     } else if (op == QTextCursor::Up) {
       
   874 
       
   875         QRectF visible = QRectF(viewport->rect()).translated(-q->contentOffset());
       
   876         visible.translate(0, -visible.height()); // previous page
       
   877         QTextBlock block = q->firstVisibleBlock();
       
   878         qreal h = 0;
       
   879         while (h >= visible.top()) {
       
   880             if (!block.previous().isValid()) {
       
   881                 if (control->topBlock == 0 && topLine == 0) {
       
   882                     lastY = 0; // set cursor to first line
       
   883                 }
       
   884                 break;
       
   885             }
       
   886             block = block.previous();
       
   887             QRectF br = q->blockBoundingRect(block);
       
   888             h -= br.height();
       
   889         }
       
   890 
       
   891         int line = 0;
       
   892         if (block.isValid()) {
       
   893             qreal diff = visible.top() - h;
       
   894             int lineCount = block.layout()->lineCount();
       
   895             while (line < lineCount) {
       
   896                 if (block.layout()->lineAt(line).naturalTextRect().top() >= diff)
       
   897                     break;
       
   898                 ++line;
       
   899             }
       
   900             if (line == lineCount) {
       
   901                 if (block.next().isValid() && block.next() != q->firstVisibleBlock()) {
       
   902                     block = block.next();
       
   903                     line = 0;
       
   904                 } else {
       
   905                     --line;
       
   906                 }
       
   907             }
       
   908         }
       
   909         setTopBlock(block.blockNumber(), line);
       
   910 
       
   911         if (moveCursor) {
       
   912             // move using movePosition to keep the cursor's x
       
   913             lastY += verticalOffset();
       
   914             bool moved = false;
       
   915             do {
       
   916                 moved = cursor.movePosition(op, moveMode);
       
   917             } while (moved && control->cursorRect(cursor).top() > lastY);
       
   918         }
       
   919     }
       
   920 
       
   921     if (moveCursor) {
       
   922         control->setTextCursor(cursor);
       
   923         pageUpDownLastCursorYIsValid = true;
       
   924     }
       
   925 }
       
   926 
       
   927 #ifndef QT_NO_SCROLLBAR
       
   928 
       
   929 void QPlainTextEditPrivate::_q_adjustScrollbars()
       
   930 {
       
   931     Q_Q(QPlainTextEdit);
       
   932     QTextDocument *doc = control->document();
       
   933     QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(doc->documentLayout());
       
   934     Q_ASSERT(documentLayout);
       
   935     bool documentSizeChangedBlocked = documentLayout->priv()->blockDocumentSizeChanged;
       
   936     documentLayout->priv()->blockDocumentSizeChanged = true;
       
   937     qreal margin = doc->documentMargin();
       
   938 
       
   939     int vmax = 0;
       
   940 
       
   941     int vSliderLength = 0;
       
   942     if (!centerOnScroll && q->isVisible()) {
       
   943         QTextBlock block = doc->lastBlock();
       
   944         const int visible = static_cast<int>(viewport->rect().height() - margin - 1);
       
   945         int y = 0;
       
   946         int visibleFromBottom = 0;
       
   947 
       
   948         while (block.isValid()) {
       
   949             if (!block.isVisible()) {
       
   950                 block = block.previous();
       
   951                 continue;
       
   952             }
       
   953             y += int(documentLayout->blockBoundingRect(block).height());
       
   954 
       
   955             QTextLayout *layout = block.layout();
       
   956             int layoutLineCount = layout->lineCount();
       
   957             if (y > visible) {
       
   958                 int lineNumber = 0;
       
   959                 while (lineNumber < layoutLineCount) {
       
   960                     QTextLine line = layout->lineAt(lineNumber);
       
   961                     const QRectF lr = line.naturalTextRect();
       
   962                     if (int(lr.top()) >= y - visible)
       
   963                         break;
       
   964                     ++lineNumber;
       
   965                 }
       
   966                 if (lineNumber < layoutLineCount)
       
   967                     visibleFromBottom += (layoutLineCount - lineNumber - 1);
       
   968                 break;
       
   969 
       
   970             }
       
   971             visibleFromBottom += layoutLineCount;
       
   972             block = block.previous();
       
   973         }
       
   974         vmax = qMax(0, doc->lineCount() - visibleFromBottom);
       
   975         vSliderLength = visibleFromBottom;
       
   976 
       
   977     } else {
       
   978         vmax = qMax(0, doc->lineCount() - 1);
       
   979         vSliderLength = viewport->height() / q->fontMetrics().lineSpacing();
       
   980     }
       
   981 
       
   982 
       
   983 
       
   984     QSizeF documentSize = documentLayout->documentSize();
       
   985     vbar->setRange(0, qMax(0, vmax));
       
   986     vbar->setPageStep(vSliderLength);
       
   987     int visualTopLine = vmax;
       
   988     QTextBlock firstVisibleBlock = q->firstVisibleBlock();
       
   989     if (firstVisibleBlock.isValid())
       
   990         visualTopLine = firstVisibleBlock.firstLineNumber() + topLine;
       
   991     bool vbarSignalsBlocked = vbar->blockSignals(true);
       
   992     vbar->setValue(visualTopLine);
       
   993     vbar->blockSignals(vbarSignalsBlocked);
       
   994 
       
   995     hbar->setRange(0, (int)documentSize.width() - viewport->width());
       
   996     hbar->setPageStep(viewport->width());
       
   997     documentLayout->priv()->blockDocumentSizeChanged = documentSizeChangedBlocked;
       
   998     setTopLine(vbar->value());
       
   999 }
       
  1000 
       
  1001 #endif
       
  1002 
       
  1003 
       
  1004 void QPlainTextEditPrivate::ensureViewportLayouted()
       
  1005 {
       
  1006 }
       
  1007 
       
  1008 /*!
       
  1009     \class QPlainTextEdit
       
  1010     \since 4.4
       
  1011     \brief The QPlainTextEdit class provides a widget that is used to edit and display
       
  1012     plain text.
       
  1013 
       
  1014     \ingroup richtext-processing
       
  1015 
       
  1016 
       
  1017     \tableofcontents
       
  1018 
       
  1019     \section1 Introduction and Concepts
       
  1020 
       
  1021     QPlainTextEdit is an advanced viewer/editor supporting plain
       
  1022     text. It is optimized to handle large documents and to respond
       
  1023     quickly to user input.
       
  1024 
       
  1025     QPlainText uses very much the same technology and concepts as
       
  1026     QTextEdit, but is optimized for plain text handling.
       
  1027 
       
  1028     QPlainTextEdit works on paragraphs and characters. A paragraph is
       
  1029     a formatted string which is word-wrapped to fit into the width of
       
  1030     the widget. By default when reading plain text, one newline
       
  1031     signifies a paragraph. A document consists of zero or more
       
  1032     paragraphs. Paragraphs are separated by hard line breaks. Each
       
  1033     character within a paragraph has its own attributes, for example,
       
  1034     font and color.
       
  1035 
       
  1036     The shape of the mouse cursor on a QPlainTextEdit is
       
  1037     Qt::IBeamCursor by default.  It can be changed through the
       
  1038     viewport()'s cursor property.
       
  1039 
       
  1040     \section1 Using QPlainTextEdit as a Display Widget
       
  1041 
       
  1042     The text is set or replaced using setPlainText() which deletes the
       
  1043     existing text and replaces it with the text passed to setPlainText().
       
  1044 
       
  1045     Text can be inserted using the QTextCursor class or using the
       
  1046     convenience functions insertPlainText(), appendPlainText() or
       
  1047     paste().
       
  1048 
       
  1049     By default, the text edit wraps words at whitespace to fit within
       
  1050     the text edit widget. The setLineWrapMode() function is used to
       
  1051     specify the kind of line wrap you want, \l WidgetWidth or \l
       
  1052     NoWrap if you don't want any wrapping.  If you use word wrap to
       
  1053     the widget's width \l WidgetWidth, you can specify whether to
       
  1054     break on whitespace or anywhere with setWordWrapMode().
       
  1055 
       
  1056     The find() function can be used to find and select a given string
       
  1057     within the text.
       
  1058 
       
  1059     If you want to limit the total number of paragraphs in a
       
  1060     QPlainTextEdit, as it is for example useful in a log viewer, then
       
  1061     you can use the maximumBlockCount property. The combination of
       
  1062     setMaximumBlockCount() and appendPlainText() turns QPlainTextEdit
       
  1063     into an efficient viewer for log text. The scrolling can be
       
  1064     reduced with the centerOnScroll() property, making the log viewer
       
  1065     even faster. Text can be formatted in a limited way, either using
       
  1066     a syntax highlighter (see below), or by appending html-formatted
       
  1067     text with appendHtml(). While QPlainTextEdit does not support
       
  1068     complex rich text rendering with tables and floats, it does
       
  1069     support limited paragraph-based formatting that you may need in a
       
  1070     log viewer.
       
  1071 
       
  1072     \section2 Read-only Key Bindings
       
  1073 
       
  1074     When QPlainTextEdit is used read-only the key bindings are limited to
       
  1075     navigation, and text may only be selected with the mouse:
       
  1076     \table
       
  1077     \header \i Keypresses \i Action
       
  1078     \row \i Qt::UpArrow        \i Moves one line up.
       
  1079     \row \i Qt::DownArrow        \i Moves one line down.
       
  1080     \row \i Qt::LeftArrow        \i Moves one character to the left.
       
  1081     \row \i Qt::RightArrow        \i Moves one character to the right.
       
  1082     \row \i PageUp        \i Moves one (viewport) page up.
       
  1083     \row \i PageDown        \i Moves one (viewport) page down.
       
  1084     \row \i Home        \i Moves to the beginning of the text.
       
  1085     \row \i End                \i Moves to the end of the text.
       
  1086     \row \i Alt+Wheel
       
  1087          \i Scrolls the page horizontally (the Wheel is the mouse wheel).
       
  1088     \row \i Ctrl+Wheel        \i Zooms the text.
       
  1089     \row \i Ctrl+A            \i Selects all text.
       
  1090     \endtable
       
  1091 
       
  1092 
       
  1093     \section1 Using QPlainTextEdit as an Editor
       
  1094 
       
  1095     All the information about using QPlainTextEdit as a display widget also
       
  1096     applies here.
       
  1097 
       
  1098     Selection of text is handled by the QTextCursor class, which provides
       
  1099     functionality for creating selections, retrieving the text contents or
       
  1100     deleting selections. You can retrieve the object that corresponds with
       
  1101     the user-visible cursor using the textCursor() method. If you want to set
       
  1102     a selection in QPlainTextEdit just create one on a QTextCursor object and
       
  1103     then make that cursor the visible cursor using setCursor(). The selection
       
  1104     can be copied to the clipboard with copy(), or cut to the clipboard with
       
  1105     cut(). The entire text can be selected using selectAll().
       
  1106 
       
  1107     QPlainTextEdit holds a QTextDocument object which can be retrieved using the
       
  1108     document() method. You can also set your own document object using setDocument().
       
  1109     QTextDocument emits a textChanged() signal if the text changes and it also
       
  1110     provides a isModified() function which will return true if the text has been
       
  1111     modified since it was either loaded or since the last call to setModified
       
  1112     with false as argument. In addition it provides methods for undo and redo.
       
  1113 
       
  1114     \section2 Syntax Highlighting
       
  1115 
       
  1116     Just like QTextEdit, QPlainTextEdit works together with
       
  1117     QSyntaxHighlighter.
       
  1118 
       
  1119     \section2 Editing Key Bindings
       
  1120 
       
  1121     The list of key bindings which are implemented for editing:
       
  1122     \table
       
  1123     \header \i Keypresses \i Action
       
  1124     \row \i Backspace \i Deletes the character to the left of the cursor.
       
  1125     \row \i Delete \i Deletes the character to the right of the cursor.
       
  1126     \row \i Ctrl+C \i Copy the selected text to the clipboard.
       
  1127     \row \i Ctrl+Insert \i Copy the selected text to the clipboard.
       
  1128     \row \i Ctrl+K \i Deletes to the end of the line.
       
  1129     \row \i Ctrl+V \i Pastes the clipboard text into text edit.
       
  1130     \row \i Shift+Insert \i Pastes the clipboard text into text edit.
       
  1131     \row \i Ctrl+X \i Deletes the selected text and copies it to the clipboard.
       
  1132     \row \i Shift+Delete \i Deletes the selected text and copies it to the clipboard.
       
  1133     \row \i Ctrl+Z \i Undoes the last operation.
       
  1134     \row \i Ctrl+Y \i Redoes the last operation.
       
  1135     \row \i LeftArrow \i Moves the cursor one character to the left.
       
  1136     \row \i Ctrl+LeftArrow \i Moves the cursor one word to the left.
       
  1137     \row \i RightArrow \i Moves the cursor one character to the right.
       
  1138     \row \i Ctrl+RightArrow \i Moves the cursor one word to the right.
       
  1139     \row \i UpArrow \i Moves the cursor one line up.
       
  1140     \row \i Ctrl+UpArrow \i Moves the cursor one word up.
       
  1141     \row \i DownArrow \i Moves the cursor one line down.
       
  1142     \row \i Ctrl+Down Arrow \i Moves the cursor one word down.
       
  1143     \row \i PageUp \i Moves the cursor one page up.
       
  1144     \row \i PageDown \i Moves the cursor one page down.
       
  1145     \row \i Home \i Moves the cursor to the beginning of the line.
       
  1146     \row \i Ctrl+Home \i Moves the cursor to the beginning of the text.
       
  1147     \row \i End \i Moves the cursor to the end of the line.
       
  1148     \row \i Ctrl+End \i Moves the cursor to the end of the text.
       
  1149     \row \i Alt+Wheel \i Scrolls the page horizontally (the Wheel is the mouse wheel).
       
  1150     \row \i Ctrl+Wheel \i Zooms the text.
       
  1151     \endtable
       
  1152 
       
  1153     To select (mark) text hold down the Shift key whilst pressing one
       
  1154     of the movement keystrokes, for example, \e{Shift+Right Arrow}
       
  1155     will select the character to the right, and \e{Shift+Ctrl+Right
       
  1156     Arrow} will select the word to the right, etc.
       
  1157 
       
  1158    \section1 Differences to QTextEdit
       
  1159 
       
  1160    QPlainTextEdit is a thin class, implemented by using most of the
       
  1161    technology that is behind QTextEdit and QTextDocument. Its
       
  1162    performance benefits over QTextEdit stem mostly from using a
       
  1163    different and simplified text layout called
       
  1164    QPlainTextDocumentLayout on the text document (see
       
  1165    QTextDocument::setDocumentLayout()). The plain text document layout
       
  1166    does not support tables nor embedded frames, and \e{replaces a
       
  1167    pixel-exact height calculation with a line-by-line respectively
       
  1168    paragraph-by-paragraph scrolling approach}. This makes it possible
       
  1169    to handle significantly larger documents, and still resize the
       
  1170    editor with line wrap enabled in real time. It also makes for a
       
  1171    fast log viewer (see setMaximumBlockCount()).
       
  1172 
       
  1173 
       
  1174     \sa QTextDocument, QTextCursor, {Application Example},
       
  1175         {Code Editor Example}, {Syntax Highlighter Example},
       
  1176         {Rich Text Processing}
       
  1177 
       
  1178 */
       
  1179 
       
  1180 /*!
       
  1181     \property QPlainTextEdit::plainText
       
  1182 
       
  1183     This property gets and sets the plain text editor's contents. The previous
       
  1184     contents are removed and undo/redo history is reset when this property is set.
       
  1185 
       
  1186     By default, for an editor with no contents, this property contains an empty string.
       
  1187 */
       
  1188 
       
  1189 /*!
       
  1190     \property QPlainTextEdit::undoRedoEnabled
       
  1191     \brief whether undo and redo are enabled
       
  1192 
       
  1193     Users are only able to undo or redo actions if this property is
       
  1194     true, and if there is an action that can be undone (or redone).
       
  1195 
       
  1196     By default, this property is true.
       
  1197 */
       
  1198 
       
  1199 /*!
       
  1200     \enum QPlainTextEdit::LineWrapMode
       
  1201 
       
  1202     \value NoWrap
       
  1203     \value WidgetWidth
       
  1204 */
       
  1205 
       
  1206 
       
  1207 /*!
       
  1208     Constructs an empty QPlainTextEdit with parent \a
       
  1209     parent.
       
  1210 */
       
  1211 QPlainTextEdit::QPlainTextEdit(QWidget *parent)
       
  1212     : QAbstractScrollArea(*new QPlainTextEditPrivate, parent)
       
  1213 {
       
  1214     Q_D(QPlainTextEdit);
       
  1215     d->init();
       
  1216 }
       
  1217 
       
  1218 /*!
       
  1219     \internal
       
  1220 */
       
  1221 QPlainTextEdit::QPlainTextEdit(QPlainTextEditPrivate &dd, QWidget *parent)
       
  1222     : QAbstractScrollArea(dd, parent)
       
  1223 {
       
  1224     Q_D(QPlainTextEdit);
       
  1225     d->init();
       
  1226 }
       
  1227 
       
  1228 /*!
       
  1229     Constructs a QPlainTextEdit with parent \a parent. The text edit will display
       
  1230     the plain text \a text.
       
  1231 */
       
  1232 QPlainTextEdit::QPlainTextEdit(const QString &text, QWidget *parent)
       
  1233     : QAbstractScrollArea(*new QPlainTextEditPrivate, parent)
       
  1234 {
       
  1235     Q_D(QPlainTextEdit);
       
  1236     d->init(text);
       
  1237 }
       
  1238 
       
  1239 
       
  1240 /*!
       
  1241     Destructor.
       
  1242 */
       
  1243 QPlainTextEdit::~QPlainTextEdit()
       
  1244 {
       
  1245     Q_D(QPlainTextEdit);
       
  1246     if (d->documentLayoutPtr) {
       
  1247         if (d->documentLayoutPtr->priv()->mainViewPrivate == d)
       
  1248             d->documentLayoutPtr->priv()->mainViewPrivate = 0;
       
  1249     }
       
  1250 }
       
  1251 
       
  1252 /*!
       
  1253     Makes \a document the new document of the text editor.
       
  1254 
       
  1255     The parent QObject of the provided document remains the owner
       
  1256     of the object. If the current document is a child of the text
       
  1257     editor, then it is deleted.
       
  1258 
       
  1259     The document must have a document layout that inherits
       
  1260     QPlainTextDocumentLayout (see QTextDocument::setDocumentLayout()).
       
  1261 
       
  1262     \sa document()
       
  1263 */
       
  1264 void QPlainTextEdit::setDocument(QTextDocument *document)
       
  1265 {
       
  1266     Q_D(QPlainTextEdit);
       
  1267     QPlainTextDocumentLayout *documentLayout = 0;
       
  1268 
       
  1269     if (!document) {
       
  1270         document = new QTextDocument(d->control);
       
  1271         documentLayout = new QPlainTextDocumentLayout(document);
       
  1272         document->setDocumentLayout(documentLayout);
       
  1273     } else {
       
  1274         documentLayout = qobject_cast<QPlainTextDocumentLayout*>(document->documentLayout());
       
  1275         if (!documentLayout) {
       
  1276             qWarning("QPlainTextEdit::setDocument: Document set does not support QPlainTextDocumentLayout");
       
  1277             return;
       
  1278         }
       
  1279     }
       
  1280     d->control->setDocument(document);
       
  1281     if (!documentLayout->priv()->mainViewPrivate)
       
  1282         documentLayout->priv()->mainViewPrivate = d;
       
  1283     d->documentLayoutPtr = documentLayout;
       
  1284     d->updateDefaultTextOption();
       
  1285     d->relayoutDocument();
       
  1286     d->_q_adjustScrollbars();
       
  1287 }
       
  1288 
       
  1289 /*!
       
  1290     Returns a pointer to the underlying document.
       
  1291 
       
  1292     \sa setDocument()
       
  1293 */
       
  1294 QTextDocument *QPlainTextEdit::document() const
       
  1295 {
       
  1296     Q_D(const QPlainTextEdit);
       
  1297     return d->control->document();
       
  1298 }
       
  1299 
       
  1300 /*!
       
  1301     Sets the visible \a cursor.
       
  1302 */
       
  1303 void QPlainTextEdit::setTextCursor(const QTextCursor &cursor)
       
  1304 {
       
  1305     Q_D(QPlainTextEdit);
       
  1306     d->control->setTextCursor(cursor);
       
  1307 }
       
  1308 
       
  1309 /*!
       
  1310     Returns a copy of the QTextCursor that represents the currently visible cursor.
       
  1311     Note that changes on the returned cursor do not affect QPlainTextEdit's cursor; use
       
  1312     setTextCursor() to update the visible cursor.
       
  1313  */
       
  1314 QTextCursor QPlainTextEdit::textCursor() const
       
  1315 {
       
  1316     Q_D(const QPlainTextEdit);
       
  1317     return d->control->textCursor();
       
  1318 }
       
  1319 
       
  1320 
       
  1321 /*!
       
  1322     Undoes the last operation.
       
  1323 
       
  1324     If there is no operation to undo, i.e. there is no undo step in
       
  1325     the undo/redo history, nothing happens.
       
  1326 
       
  1327     \sa redo()
       
  1328 */
       
  1329 void QPlainTextEdit::undo()
       
  1330 {
       
  1331     Q_D(QPlainTextEdit);
       
  1332     d->control->undo();
       
  1333 }
       
  1334 
       
  1335 void QPlainTextEdit::redo()
       
  1336 {
       
  1337     Q_D(QPlainTextEdit);
       
  1338     d->control->redo();
       
  1339 }
       
  1340 
       
  1341 /*!
       
  1342     \fn void QPlainTextEdit::redo()
       
  1343 
       
  1344     Redoes the last operation.
       
  1345 
       
  1346     If there is no operation to redo, i.e. there is no redo step in
       
  1347     the undo/redo history, nothing happens.
       
  1348 
       
  1349     \sa undo()
       
  1350 */
       
  1351 
       
  1352 #ifndef QT_NO_CLIPBOARD
       
  1353 /*!
       
  1354     Copies the selected text to the clipboard and deletes it from
       
  1355     the text edit.
       
  1356 
       
  1357     If there is no selected text nothing happens.
       
  1358 
       
  1359     \sa copy() paste()
       
  1360 */
       
  1361 
       
  1362 void QPlainTextEdit::cut()
       
  1363 {
       
  1364     Q_D(QPlainTextEdit);
       
  1365     d->control->cut();
       
  1366 }
       
  1367 
       
  1368 /*!
       
  1369     Copies any selected text to the clipboard.
       
  1370 
       
  1371     \sa copyAvailable()
       
  1372 */
       
  1373 
       
  1374 void QPlainTextEdit::copy()
       
  1375 {
       
  1376     Q_D(QPlainTextEdit);
       
  1377     d->control->copy();
       
  1378 }
       
  1379 
       
  1380 /*!
       
  1381     Pastes the text from the clipboard into the text edit at the
       
  1382     current cursor position.
       
  1383 
       
  1384     If there is no text in the clipboard nothing happens.
       
  1385 
       
  1386     To change the behavior of this function, i.e. to modify what
       
  1387     QPlainTextEdit can paste and how it is being pasted, reimplement the
       
  1388     virtual canInsertFromMimeData() and insertFromMimeData()
       
  1389     functions.
       
  1390 
       
  1391     \sa cut() copy()
       
  1392 */
       
  1393 
       
  1394 void QPlainTextEdit::paste()
       
  1395 {
       
  1396     Q_D(QPlainTextEdit);
       
  1397     d->control->paste();
       
  1398 }
       
  1399 #endif
       
  1400 
       
  1401 /*!
       
  1402     Deletes all the text in the text edit.
       
  1403 
       
  1404     Note that the undo/redo history is cleared by this function.
       
  1405 
       
  1406     \sa cut() setPlainText()
       
  1407 */
       
  1408 void QPlainTextEdit::clear()
       
  1409 {
       
  1410     Q_D(QPlainTextEdit);
       
  1411     // clears and sets empty content
       
  1412     d->control->topBlock = d->topLine = 0;
       
  1413     d->control->clear();
       
  1414 }
       
  1415 
       
  1416 
       
  1417 /*!
       
  1418     Selects all text.
       
  1419 
       
  1420     \sa copy() cut() textCursor()
       
  1421  */
       
  1422 void QPlainTextEdit::selectAll()
       
  1423 {
       
  1424     Q_D(QPlainTextEdit);
       
  1425     d->control->selectAll();
       
  1426 }
       
  1427 
       
  1428 /*! \internal
       
  1429 */
       
  1430 bool QPlainTextEdit::event(QEvent *e)
       
  1431 {
       
  1432     Q_D(QPlainTextEdit);
       
  1433 
       
  1434 #ifndef QT_NO_CONTEXTMENU
       
  1435     if (e->type() == QEvent::ContextMenu
       
  1436         && static_cast<QContextMenuEvent *>(e)->reason() == QContextMenuEvent::Keyboard) {
       
  1437         ensureCursorVisible();
       
  1438         const QPoint cursorPos = cursorRect().center();
       
  1439         QContextMenuEvent ce(QContextMenuEvent::Keyboard, cursorPos, d->viewport->mapToGlobal(cursorPos));
       
  1440         ce.setAccepted(e->isAccepted());
       
  1441         const bool result = QAbstractScrollArea::event(&ce);
       
  1442         e->setAccepted(ce.isAccepted());
       
  1443         return result;
       
  1444     }
       
  1445 #endif // QT_NO_CONTEXTMENU
       
  1446     if (e->type() == QEvent::ShortcutOverride
       
  1447                || e->type() == QEvent::ToolTip) {
       
  1448         d->sendControlEvent(e);
       
  1449     }
       
  1450 #ifdef QT_KEYPAD_NAVIGATION
       
  1451     else if (e->type() == QEvent::EnterEditFocus || e->type() == QEvent::LeaveEditFocus) {
       
  1452         if (QApplication::keypadNavigationEnabled())
       
  1453             d->sendControlEvent(e);
       
  1454     }
       
  1455 #endif
       
  1456     return QAbstractScrollArea::event(e);
       
  1457 }
       
  1458 
       
  1459 /*! \internal
       
  1460 */
       
  1461 
       
  1462 void QPlainTextEdit::timerEvent(QTimerEvent *e)
       
  1463 {
       
  1464     Q_D(QPlainTextEdit);
       
  1465     if (e->timerId() == d->autoScrollTimer.timerId()) {
       
  1466         QRect visible = d->viewport->rect();
       
  1467         QPoint pos;
       
  1468         if (d->inDrag) {
       
  1469             pos = d->autoScrollDragPos;
       
  1470             visible.adjust(qMin(visible.width()/3,20), qMin(visible.height()/3,20),
       
  1471                            -qMin(visible.width()/3,20), -qMin(visible.height()/3,20));
       
  1472         } else {
       
  1473             const QPoint globalPos = QCursor::pos();
       
  1474             pos = d->viewport->mapFromGlobal(globalPos);
       
  1475             QMouseEvent ev(QEvent::MouseMove, pos, globalPos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
       
  1476             mouseMoveEvent(&ev);
       
  1477         }
       
  1478         int deltaY = qMax(pos.y() - visible.top(), visible.bottom() - pos.y()) - visible.height();
       
  1479         int deltaX = qMax(pos.x() - visible.left(), visible.right() - pos.x()) - visible.width();
       
  1480         int delta = qMax(deltaX, deltaY);
       
  1481         if (delta >= 0) {
       
  1482             if (delta < 7)
       
  1483                 delta = 7;
       
  1484             int timeout = 4900 / (delta * delta);
       
  1485             d->autoScrollTimer.start(timeout, this);
       
  1486 
       
  1487             if (deltaY > 0)
       
  1488                 d->vbar->triggerAction(pos.y() < visible.center().y() ?
       
  1489                                        QAbstractSlider::SliderSingleStepSub
       
  1490                                        : QAbstractSlider::SliderSingleStepAdd);
       
  1491             if (deltaX > 0)
       
  1492                 d->hbar->triggerAction(pos.x() < visible.center().x() ?
       
  1493                                        QAbstractSlider::SliderSingleStepSub
       
  1494                                        : QAbstractSlider::SliderSingleStepAdd);
       
  1495         }
       
  1496     }
       
  1497 #ifdef QT_KEYPAD_NAVIGATION
       
  1498     else if (e->timerId() == d->deleteAllTimer.timerId()) {
       
  1499         d->deleteAllTimer.stop();
       
  1500         clear();
       
  1501     }
       
  1502 #endif
       
  1503 }
       
  1504 
       
  1505 /*!
       
  1506     Changes the text of the text edit to the string \a text.
       
  1507     Any previous text is removed.
       
  1508 
       
  1509     \a text is interpreted as plain text.
       
  1510 
       
  1511     Note that the undo/redo history is cleared by this function.
       
  1512 
       
  1513     \sa toText()
       
  1514 */
       
  1515 
       
  1516 void QPlainTextEdit::setPlainText(const QString &text)
       
  1517 {
       
  1518     Q_D(QPlainTextEdit);
       
  1519     d->control->setPlainText(text);
       
  1520 }
       
  1521 
       
  1522 /*!
       
  1523     \fn QString QPlainTextEdit::toPlainText() const
       
  1524 
       
  1525     Returns the text of the text edit as plain text.
       
  1526 
       
  1527     \sa QPlainTextEdit::setPlainText()
       
  1528  */
       
  1529 
       
  1530 /*! \reimp
       
  1531 */
       
  1532 void QPlainTextEdit::keyPressEvent(QKeyEvent *e)
       
  1533 {
       
  1534     Q_D(QPlainTextEdit);
       
  1535 
       
  1536 #ifdef QT_KEYPAD_NAVIGATION
       
  1537     switch (e->key()) {
       
  1538         case Qt::Key_Select:
       
  1539             if (QApplication::keypadNavigationEnabled()) {
       
  1540                 if (!(d->control->textInteractionFlags() & Qt::LinksAccessibleByKeyboard))
       
  1541                     setEditFocus(!hasEditFocus());
       
  1542                 else {
       
  1543                     if (!hasEditFocus())
       
  1544                         setEditFocus(true);
       
  1545                     else {
       
  1546                         QTextCursor cursor = d->control->textCursor();
       
  1547                         QTextCharFormat charFmt = cursor.charFormat();
       
  1548                         if (!cursor.hasSelection() || charFmt.anchorHref().isEmpty()) {
       
  1549                             setEditFocus(false);
       
  1550                         }
       
  1551                     }
       
  1552                 }
       
  1553             }
       
  1554             break;
       
  1555         case Qt::Key_Back:
       
  1556         case Qt::Key_No:
       
  1557             if (!QApplication::keypadNavigationEnabled()
       
  1558                     || (QApplication::keypadNavigationEnabled() && !hasEditFocus())) {
       
  1559                 e->ignore();
       
  1560                 return;
       
  1561             }
       
  1562             break;
       
  1563         default:
       
  1564             if (QApplication::keypadNavigationEnabled()) {
       
  1565                 if (!hasEditFocus() && !(e->modifiers() & Qt::ControlModifier)) {
       
  1566                     if (e->text()[0].isPrint()) {
       
  1567                         setEditFocus(true);
       
  1568                         clear();
       
  1569                     } else {
       
  1570                         e->ignore();
       
  1571                         return;
       
  1572                     }
       
  1573                 }
       
  1574             }
       
  1575             break;
       
  1576     }
       
  1577 #endif
       
  1578 
       
  1579 #ifndef QT_NO_SHORTCUT
       
  1580 
       
  1581     Qt::TextInteractionFlags tif = d->control->textInteractionFlags();
       
  1582 
       
  1583     if (tif & Qt::TextSelectableByKeyboard){
       
  1584         if (e == QKeySequence::SelectPreviousPage) {
       
  1585             e->accept();
       
  1586             d->pageUpDown(QTextCursor::Up, QTextCursor::KeepAnchor);
       
  1587             return;
       
  1588         } else if (e ==QKeySequence::SelectNextPage) {
       
  1589             e->accept();
       
  1590             d->pageUpDown(QTextCursor::Down, QTextCursor::KeepAnchor);
       
  1591             return;
       
  1592         }
       
  1593     }
       
  1594     if (tif & (Qt::TextSelectableByKeyboard | Qt::TextEditable)) {
       
  1595         if (e == QKeySequence::MoveToPreviousPage) {
       
  1596             e->accept();
       
  1597             d->pageUpDown(QTextCursor::Up, QTextCursor::MoveAnchor);
       
  1598             return;
       
  1599         } else if (e == QKeySequence::MoveToNextPage) {
       
  1600             e->accept();
       
  1601             d->pageUpDown(QTextCursor::Down, QTextCursor::MoveAnchor);
       
  1602             return;
       
  1603         }
       
  1604     }
       
  1605 #endif // QT_NO_SHORTCUT
       
  1606 
       
  1607     if (!(tif & Qt::TextEditable)) {
       
  1608         switch (e->key()) {
       
  1609             case Qt::Key_Space:
       
  1610                 e->accept();
       
  1611                 if (e->modifiers() & Qt::ShiftModifier)
       
  1612                     d->vbar->triggerAction(QAbstractSlider::SliderPageStepSub);
       
  1613                 else
       
  1614                     d->vbar->triggerAction(QAbstractSlider::SliderPageStepAdd);
       
  1615                 break;
       
  1616             default:
       
  1617                 d->sendControlEvent(e);
       
  1618                 if (!e->isAccepted() && e->modifiers() == Qt::NoModifier) {
       
  1619                     if (e->key() == Qt::Key_Home) {
       
  1620                         d->vbar->triggerAction(QAbstractSlider::SliderToMinimum);
       
  1621                         e->accept();
       
  1622                     } else if (e->key() == Qt::Key_End) {
       
  1623                         d->vbar->triggerAction(QAbstractSlider::SliderToMaximum);
       
  1624                         e->accept();
       
  1625                     }
       
  1626                 }
       
  1627                 if (!e->isAccepted()) {
       
  1628                     QAbstractScrollArea::keyPressEvent(e);
       
  1629                 }
       
  1630         }
       
  1631         return;
       
  1632     }
       
  1633 
       
  1634     d->sendControlEvent(e);
       
  1635 #ifdef QT_KEYPAD_NAVIGATION
       
  1636     if (!e->isAccepted()) {
       
  1637         switch (e->key()) {
       
  1638             case Qt::Key_Up:
       
  1639             case Qt::Key_Down:
       
  1640                 if (QApplication::keypadNavigationEnabled()) {
       
  1641                     // Cursor position didn't change, so we want to leave
       
  1642                     // these keys to change focus.
       
  1643                     e->ignore();
       
  1644                     return;
       
  1645                 }
       
  1646                 break;
       
  1647             case Qt::Key_Left:
       
  1648             case Qt::Key_Right:
       
  1649                 if (QApplication::keypadNavigationEnabled()
       
  1650                         && QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
       
  1651                     // Same as for Key_Up and Key_Down.
       
  1652                     e->ignore();
       
  1653                     return;
       
  1654                 }
       
  1655                 break;
       
  1656             case Qt::Key_Back:
       
  1657                 if (!e->isAutoRepeat()) {
       
  1658                     if (QApplication::keypadNavigationEnabled()) {
       
  1659                         if (document()->isEmpty()) {
       
  1660                             setEditFocus(false);
       
  1661                             e->accept();
       
  1662                         } else if (!d->deleteAllTimer.isActive()) {
       
  1663                             e->accept();
       
  1664                             d->deleteAllTimer.start(750, this);
       
  1665                         }
       
  1666                     } else {
       
  1667                         e->ignore();
       
  1668                         return;
       
  1669                     }
       
  1670                 }
       
  1671                 break;
       
  1672             default: break;
       
  1673         }
       
  1674     }
       
  1675 #endif
       
  1676 }
       
  1677 
       
  1678 /*! \reimp
       
  1679 */
       
  1680 void QPlainTextEdit::keyReleaseEvent(QKeyEvent *e)
       
  1681 {
       
  1682 #ifdef QT_KEYPAD_NAVIGATION
       
  1683     Q_D(QPlainTextEdit);
       
  1684     if (QApplication::keypadNavigationEnabled()) {
       
  1685         if (!e->isAutoRepeat() && e->key() == Qt::Key_Back
       
  1686             && d->deleteAllTimer.isActive()) {
       
  1687             d->deleteAllTimer.stop();
       
  1688             QTextCursor cursor = d->control->textCursor();
       
  1689             QTextBlockFormat blockFmt = cursor.blockFormat();
       
  1690 
       
  1691             QTextList *list = cursor.currentList();
       
  1692             if (list && cursor.atBlockStart()) {
       
  1693                 list->remove(cursor.block());
       
  1694             } else if (cursor.atBlockStart() && blockFmt.indent() > 0) {
       
  1695                 blockFmt.setIndent(blockFmt.indent() - 1);
       
  1696                 cursor.setBlockFormat(blockFmt);
       
  1697             } else {
       
  1698                 cursor.deletePreviousChar();
       
  1699             }
       
  1700             setTextCursor(cursor);
       
  1701         }
       
  1702     }
       
  1703 #else
       
  1704     Q_UNUSED(e);
       
  1705 #endif
       
  1706 }
       
  1707 
       
  1708 /*!
       
  1709     Loads the resource specified by the given \a type and \a name.
       
  1710 
       
  1711     This function is an extension of QTextDocument::loadResource().
       
  1712 
       
  1713     \sa QTextDocument::loadResource()
       
  1714 */
       
  1715 QVariant QPlainTextEdit::loadResource(int type, const QUrl &name)
       
  1716 {
       
  1717     Q_UNUSED(type);
       
  1718     Q_UNUSED(name);
       
  1719     return QVariant();
       
  1720 }
       
  1721 
       
  1722 /*! \reimp
       
  1723 */
       
  1724 void QPlainTextEdit::resizeEvent(QResizeEvent *e)
       
  1725 {
       
  1726     Q_D(QPlainTextEdit);
       
  1727     if (e->oldSize().width() != e->size().width())
       
  1728         d->relayoutDocument();
       
  1729     d->_q_adjustScrollbars();
       
  1730 }
       
  1731 
       
  1732 void QPlainTextEditPrivate::relayoutDocument()
       
  1733 {
       
  1734     QTextDocument *doc = control->document();
       
  1735     QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(doc->documentLayout());
       
  1736     Q_ASSERT(documentLayout);
       
  1737     documentLayoutPtr = documentLayout;
       
  1738 
       
  1739     int width = viewport->width();
       
  1740 
       
  1741     if (documentLayout->priv()->mainViewPrivate == 0
       
  1742         || documentLayout->priv()->mainViewPrivate == this
       
  1743         || width > documentLayout->textWidth()) {
       
  1744         documentLayout->priv()->mainViewPrivate = this;
       
  1745         documentLayout->setTextWidth(width);
       
  1746     }
       
  1747 }
       
  1748 
       
  1749 static void fillBackground(QPainter *p, const QRectF &rect, QBrush brush, QRectF gradientRect = QRectF())
       
  1750 {
       
  1751     p->save();
       
  1752     if (brush.style() >= Qt::LinearGradientPattern && brush.style() <= Qt::ConicalGradientPattern) {
       
  1753         if (!gradientRect.isNull()) {
       
  1754             QTransform m = QTransform::fromTranslate(gradientRect.left(), gradientRect.top());
       
  1755             m.scale(gradientRect.width(), gradientRect.height());
       
  1756             brush.setTransform(m);
       
  1757             const_cast<QGradient *>(brush.gradient())->setCoordinateMode(QGradient::LogicalMode);
       
  1758         }
       
  1759     } else {
       
  1760         p->setBrushOrigin(rect.topLeft());
       
  1761     }
       
  1762     p->fillRect(rect, brush);
       
  1763     p->restore();
       
  1764 }
       
  1765 
       
  1766 
       
  1767 
       
  1768 /*! \reimp
       
  1769 */
       
  1770 void QPlainTextEdit::paintEvent(QPaintEvent *e)
       
  1771 {
       
  1772     QPainter painter(viewport());
       
  1773     Q_ASSERT(qobject_cast<QPlainTextDocumentLayout*>(document()->documentLayout()));
       
  1774 
       
  1775     QPointF offset(contentOffset());
       
  1776 
       
  1777     QRect er = e->rect();
       
  1778     QRect viewportRect = viewport()->rect();
       
  1779 
       
  1780     bool editable = !isReadOnly();
       
  1781 
       
  1782     QTextBlock block = firstVisibleBlock();
       
  1783     qreal maximumWidth = document()->documentLayout()->documentSize().width();
       
  1784 
       
  1785     // keep right margin clean from full-width selection
       
  1786     int maxX = offset.x() + qMax((qreal)viewportRect.width(), maximumWidth)
       
  1787                - document()->documentMargin();
       
  1788     er.setRight(qMin(er.right(), maxX));
       
  1789     painter.setClipRect(er);
       
  1790 
       
  1791 
       
  1792     QAbstractTextDocumentLayout::PaintContext context = getPaintContext();
       
  1793 
       
  1794     while (block.isValid()) {
       
  1795 
       
  1796         QRectF r = blockBoundingRect(block).translated(offset);
       
  1797         QTextLayout *layout = block.layout();
       
  1798 
       
  1799         if (!block.isVisible()) {
       
  1800             offset.ry() += r.height();
       
  1801             block = block.next();
       
  1802             continue;
       
  1803         }
       
  1804 
       
  1805         if (r.bottom() >= er.top() && r.top() <= er.bottom()) {
       
  1806 
       
  1807             QTextBlockFormat blockFormat = block.blockFormat();
       
  1808 
       
  1809             QBrush bg = blockFormat.background();
       
  1810             if (bg != Qt::NoBrush) {
       
  1811                 QRectF contentsRect = r;
       
  1812                 contentsRect.setWidth(qMax(r.width(), maximumWidth));
       
  1813                 fillBackground(&painter, contentsRect, bg);
       
  1814             }
       
  1815 
       
  1816 
       
  1817             QVector<QTextLayout::FormatRange> selections;
       
  1818             int blpos = block.position();
       
  1819             int bllen = block.length();
       
  1820             for (int i = 0; i < context.selections.size(); ++i) {
       
  1821                 const QAbstractTextDocumentLayout::Selection &range = context.selections.at(i);
       
  1822                 const int selStart = range.cursor.selectionStart() - blpos;
       
  1823                 const int selEnd = range.cursor.selectionEnd() - blpos;
       
  1824                 if (selStart < bllen && selEnd > 0
       
  1825                     && selEnd > selStart) {
       
  1826                     QTextLayout::FormatRange o;
       
  1827                     o.start = selStart;
       
  1828                     o.length = selEnd - selStart;
       
  1829                     o.format = range.format;
       
  1830                     selections.append(o);
       
  1831                 } else if (!range.cursor.hasSelection() && range.format.hasProperty(QTextFormat::FullWidthSelection)
       
  1832                            && block.contains(range.cursor.position())) {
       
  1833                     // for full width selections we don't require an actual selection, just
       
  1834                     // a position to specify the line. that's more convenience in usage.
       
  1835                     QTextLayout::FormatRange o;
       
  1836                     QTextLine l = layout->lineForTextPosition(range.cursor.position() - blpos);
       
  1837                     o.start = l.textStart();
       
  1838                     o.length = l.textLength();
       
  1839                     if (o.start + o.length == bllen - 1)
       
  1840                         ++o.length; // include newline
       
  1841                     o.format = range.format;
       
  1842                     selections.append(o);
       
  1843                 }
       
  1844             }
       
  1845 
       
  1846             bool drawCursor = (editable
       
  1847                                && context.cursorPosition >= blpos
       
  1848                                && context.cursorPosition < blpos + bllen);
       
  1849 
       
  1850             bool drawCursorAsBlock = drawCursor && overwriteMode() ;
       
  1851 
       
  1852             if (drawCursorAsBlock) {
       
  1853                 if (context.cursorPosition == blpos + bllen - 1) {
       
  1854                     drawCursorAsBlock = false;
       
  1855                 } else {
       
  1856                     QTextLayout::FormatRange o;
       
  1857                     o.start = context.cursorPosition - blpos;
       
  1858                     o.length = 1;
       
  1859                     o.format.setForeground(palette().base());
       
  1860                     o.format.setBackground(palette().text());
       
  1861                     selections.append(o);
       
  1862                 }
       
  1863             }
       
  1864 
       
  1865 
       
  1866             layout->draw(&painter, offset, selections, er);
       
  1867             if ((drawCursor && !drawCursorAsBlock)
       
  1868                 || (editable && context.cursorPosition < -1
       
  1869                     && !layout->preeditAreaText().isEmpty())) {
       
  1870                 int cpos = context.cursorPosition;
       
  1871                 if (cpos < -1)
       
  1872                     cpos = layout->preeditAreaPosition() - (cpos + 2);
       
  1873                 else
       
  1874                     cpos -= blpos;
       
  1875                 layout->drawCursor(&painter, offset, cpos, cursorWidth());
       
  1876             }
       
  1877         }
       
  1878 
       
  1879         offset.ry() += r.height();
       
  1880         if (offset.y() > viewportRect.height())
       
  1881             break;
       
  1882         block = block.next();
       
  1883     }
       
  1884 
       
  1885     if (backgroundVisible() && !block.isValid() && offset.y() <= er.bottom()
       
  1886         && (centerOnScroll() || verticalScrollBar()->maximum() == verticalScrollBar()->minimum())) {
       
  1887         painter.fillRect(QRect(QPoint((int)er.left(), (int)offset.y()), er.bottomRight()), palette().background());
       
  1888     }
       
  1889 }
       
  1890 
       
  1891 
       
  1892 void QPlainTextEditPrivate::updateDefaultTextOption()
       
  1893 {
       
  1894     QTextDocument *doc = control->document();
       
  1895 
       
  1896     QTextOption opt = doc->defaultTextOption();
       
  1897     QTextOption::WrapMode oldWrapMode = opt.wrapMode();
       
  1898 
       
  1899     if (lineWrap == QPlainTextEdit::NoWrap)
       
  1900         opt.setWrapMode(QTextOption::NoWrap);
       
  1901     else
       
  1902         opt.setWrapMode(wordWrap);
       
  1903 
       
  1904     if (opt.wrapMode() != oldWrapMode)
       
  1905         doc->setDefaultTextOption(opt);
       
  1906 }
       
  1907 
       
  1908 
       
  1909 /*! \reimp
       
  1910 */
       
  1911 void QPlainTextEdit::mousePressEvent(QMouseEvent *e)
       
  1912 {
       
  1913     Q_D(QPlainTextEdit);
       
  1914 #ifdef QT_KEYPAD_NAVIGATION
       
  1915     if (QApplication::keypadNavigationEnabled() && !hasEditFocus())
       
  1916         setEditFocus(true);
       
  1917 #endif
       
  1918     d->sendControlEvent(e);
       
  1919 }
       
  1920 
       
  1921 /*! \reimp
       
  1922 */
       
  1923 void QPlainTextEdit::mouseMoveEvent(QMouseEvent *e)
       
  1924 {
       
  1925     Q_D(QPlainTextEdit);
       
  1926     d->inDrag = false; // paranoia
       
  1927     const QPoint pos = e->pos();
       
  1928     d->sendControlEvent(e);
       
  1929     if (!(e->buttons() & Qt::LeftButton))
       
  1930         return;
       
  1931     QRect visible = d->viewport->rect();
       
  1932     if (visible.contains(pos))
       
  1933         d->autoScrollTimer.stop();
       
  1934     else if (!d->autoScrollTimer.isActive())
       
  1935         d->autoScrollTimer.start(100, this);
       
  1936 }
       
  1937 
       
  1938 /*! \reimp
       
  1939 */
       
  1940 void QPlainTextEdit::mouseReleaseEvent(QMouseEvent *e)
       
  1941 {
       
  1942     Q_D(QPlainTextEdit);
       
  1943     d->sendControlEvent(e);
       
  1944     if (d->autoScrollTimer.isActive()) {
       
  1945         d->autoScrollTimer.stop();
       
  1946         d->ensureCursorVisible();
       
  1947     }
       
  1948 
       
  1949     d->handleSoftwareInputPanel(e->button(), d->clickCausedFocus);
       
  1950     d->clickCausedFocus = 0;
       
  1951 }
       
  1952 
       
  1953 /*! \reimp
       
  1954 */
       
  1955 void QPlainTextEdit::mouseDoubleClickEvent(QMouseEvent *e)
       
  1956 {
       
  1957     Q_D(QPlainTextEdit);
       
  1958     d->sendControlEvent(e);
       
  1959 }
       
  1960 
       
  1961 /*! \reimp
       
  1962 */
       
  1963 bool QPlainTextEdit::focusNextPrevChild(bool next)
       
  1964 {
       
  1965     Q_D(const QPlainTextEdit);
       
  1966     if (!d->tabChangesFocus && d->control->textInteractionFlags() & Qt::TextEditable)
       
  1967         return false;
       
  1968     return QAbstractScrollArea::focusNextPrevChild(next);
       
  1969 }
       
  1970 
       
  1971 #ifndef QT_NO_CONTEXTMENU
       
  1972 /*!
       
  1973   \fn void QPlainTextEdit::contextMenuEvent(QContextMenuEvent *event)
       
  1974 
       
  1975   Shows the standard context menu created with createStandardContextMenu().
       
  1976 
       
  1977   If you do not want the text edit to have a context menu, you can set
       
  1978   its \l contextMenuPolicy to Qt::NoContextMenu. If you want to
       
  1979   customize the context menu, reimplement this function. If you want
       
  1980   to extend the standard context menu, reimplement this function, call
       
  1981   createStandardContextMenu() and extend the menu returned.
       
  1982 
       
  1983   Information about the event is passed in the \a event object.
       
  1984 
       
  1985   \snippet doc/src/snippets/code/src_gui_widgets_qplaintextedit.cpp 0
       
  1986 */
       
  1987 void QPlainTextEdit::contextMenuEvent(QContextMenuEvent *e)
       
  1988 {
       
  1989     Q_D(QPlainTextEdit);
       
  1990     d->sendControlEvent(e);
       
  1991 }
       
  1992 #endif // QT_NO_CONTEXTMENU
       
  1993 
       
  1994 #ifndef QT_NO_DRAGANDDROP
       
  1995 /*! \reimp
       
  1996 */
       
  1997 void QPlainTextEdit::dragEnterEvent(QDragEnterEvent *e)
       
  1998 {
       
  1999     Q_D(QPlainTextEdit);
       
  2000     d->inDrag = true;
       
  2001     d->sendControlEvent(e);
       
  2002 }
       
  2003 
       
  2004 /*! \reimp
       
  2005 */
       
  2006 void QPlainTextEdit::dragLeaveEvent(QDragLeaveEvent *e)
       
  2007 {
       
  2008     Q_D(QPlainTextEdit);
       
  2009     d->inDrag = false;
       
  2010     d->autoScrollTimer.stop();
       
  2011     d->sendControlEvent(e);
       
  2012 }
       
  2013 
       
  2014 /*! \reimp
       
  2015 */
       
  2016 void QPlainTextEdit::dragMoveEvent(QDragMoveEvent *e)
       
  2017 {
       
  2018     Q_D(QPlainTextEdit);
       
  2019     d->autoScrollDragPos = e->pos();
       
  2020     if (!d->autoScrollTimer.isActive())
       
  2021         d->autoScrollTimer.start(100, this);
       
  2022     d->sendControlEvent(e);
       
  2023 }
       
  2024 
       
  2025 /*! \reimp
       
  2026 */
       
  2027 void QPlainTextEdit::dropEvent(QDropEvent *e)
       
  2028 {
       
  2029     Q_D(QPlainTextEdit);
       
  2030     d->inDrag = false;
       
  2031     d->autoScrollTimer.stop();
       
  2032     d->sendControlEvent(e);
       
  2033 }
       
  2034 
       
  2035 #endif // QT_NO_DRAGANDDROP
       
  2036 
       
  2037 /*! \reimp
       
  2038  */
       
  2039 void QPlainTextEdit::inputMethodEvent(QInputMethodEvent *e)
       
  2040 {
       
  2041     Q_D(QPlainTextEdit);
       
  2042 #ifdef QT_KEYPAD_NAVIGATION
       
  2043     if (d->control->textInteractionFlags() & Qt::TextEditable
       
  2044         && QApplication::keypadNavigationEnabled()
       
  2045         && !hasEditFocus()) {
       
  2046         setEditFocus(true);
       
  2047         selectAll();    // so text is replaced rather than appended to
       
  2048     }
       
  2049 #endif
       
  2050     d->sendControlEvent(e);
       
  2051     ensureCursorVisible();
       
  2052 }
       
  2053 
       
  2054 /*!\reimp
       
  2055 */
       
  2056 void QPlainTextEdit::scrollContentsBy(int dx, int /*dy*/)
       
  2057 {
       
  2058     Q_D(QPlainTextEdit);
       
  2059     d->setTopLine(d->vbar->value(), dx);
       
  2060 }
       
  2061 
       
  2062 /*!\reimp
       
  2063 */
       
  2064 QVariant QPlainTextEdit::inputMethodQuery(Qt::InputMethodQuery property) const
       
  2065 {
       
  2066     Q_D(const QPlainTextEdit);
       
  2067     QVariant v = d->control->inputMethodQuery(property);
       
  2068     const QPoint offset(-d->horizontalOffset(), -0);
       
  2069     if (v.type() == QVariant::RectF)
       
  2070         v = v.toRectF().toRect().translated(offset);
       
  2071     else if (v.type() == QVariant::PointF)
       
  2072         v = v.toPointF().toPoint() + offset;
       
  2073     else if (v.type() == QVariant::Rect)
       
  2074         v = v.toRect().translated(offset);
       
  2075     else if (v.type() == QVariant::Point)
       
  2076         v = v.toPoint() + offset;
       
  2077     return v;
       
  2078 }
       
  2079 
       
  2080 /*! \reimp
       
  2081 */
       
  2082 void QPlainTextEdit::focusInEvent(QFocusEvent *e)
       
  2083 {
       
  2084     Q_D(QPlainTextEdit);
       
  2085     if (e->reason() == Qt::MouseFocusReason) {
       
  2086         d->clickCausedFocus = 1;
       
  2087     }
       
  2088     QAbstractScrollArea::focusInEvent(e);
       
  2089     d->sendControlEvent(e);
       
  2090 }
       
  2091 
       
  2092 /*! \reimp
       
  2093 */
       
  2094 void QPlainTextEdit::focusOutEvent(QFocusEvent *e)
       
  2095 {
       
  2096     Q_D(QPlainTextEdit);
       
  2097     QAbstractScrollArea::focusOutEvent(e);
       
  2098     d->sendControlEvent(e);
       
  2099 }
       
  2100 
       
  2101 /*! \reimp
       
  2102 */
       
  2103 void QPlainTextEdit::showEvent(QShowEvent *)
       
  2104 {
       
  2105     Q_D(QPlainTextEdit);
       
  2106     if (d->showCursorOnInitialShow) {
       
  2107         d->showCursorOnInitialShow = false;
       
  2108         ensureCursorVisible();
       
  2109     }
       
  2110 }
       
  2111 
       
  2112 /*! \reimp
       
  2113 */
       
  2114 void QPlainTextEdit::changeEvent(QEvent *e)
       
  2115 {
       
  2116     Q_D(QPlainTextEdit);
       
  2117     QAbstractScrollArea::changeEvent(e);
       
  2118     if (e->type() == QEvent::ApplicationFontChange
       
  2119         || e->type() == QEvent::FontChange) {
       
  2120         d->control->document()->setDefaultFont(font());
       
  2121     }  else if(e->type() == QEvent::ActivationChange) {
       
  2122         if (!isActiveWindow())
       
  2123             d->autoScrollTimer.stop();
       
  2124     } else if (e->type() == QEvent::EnabledChange) {
       
  2125         e->setAccepted(isEnabled());
       
  2126         d->sendControlEvent(e);
       
  2127     } else if (e->type() == QEvent::PaletteChange) {
       
  2128         d->control->setPalette(palette());
       
  2129     } else if (e->type() == QEvent::LayoutDirectionChange) {
       
  2130         d->sendControlEvent(e);
       
  2131     }
       
  2132 }
       
  2133 
       
  2134 /*! \reimp
       
  2135 */
       
  2136 #ifndef QT_NO_WHEELEVENT
       
  2137 void QPlainTextEdit::wheelEvent(QWheelEvent *e)
       
  2138 {
       
  2139     QAbstractScrollArea::wheelEvent(e);
       
  2140     updateMicroFocus();
       
  2141 }
       
  2142 #endif
       
  2143 
       
  2144 #ifndef QT_NO_CONTEXTMENU
       
  2145 /*!  This function creates the standard context menu which is shown
       
  2146   when the user clicks on the line edit with the right mouse
       
  2147   button. It is called from the default contextMenuEvent() handler.
       
  2148   The popup menu's ownership is transferred to the caller.
       
  2149 */
       
  2150 
       
  2151 QMenu *QPlainTextEdit::createStandardContextMenu()
       
  2152 {
       
  2153     Q_D(QPlainTextEdit);
       
  2154     return d->control->createStandardContextMenu(QPointF(), this);
       
  2155 }
       
  2156 #endif // QT_NO_CONTEXTMENU
       
  2157 
       
  2158 /*!
       
  2159   returns a QTextCursor at position \a pos (in viewport coordinates).
       
  2160 */
       
  2161 QTextCursor QPlainTextEdit::cursorForPosition(const QPoint &pos) const
       
  2162 {
       
  2163     Q_D(const QPlainTextEdit);
       
  2164     return d->control->cursorForPosition(d->mapToContents(pos));
       
  2165 }
       
  2166 
       
  2167 /*!
       
  2168   returns a rectangle (in viewport coordinates) that includes the
       
  2169   \a cursor.
       
  2170  */
       
  2171 QRect QPlainTextEdit::cursorRect(const QTextCursor &cursor) const
       
  2172 {
       
  2173     Q_D(const QPlainTextEdit);
       
  2174     if (cursor.isNull())
       
  2175         return QRect();
       
  2176 
       
  2177     QRect r = d->control->cursorRect(cursor).toRect();
       
  2178     r.translate(-d->horizontalOffset(),-d->verticalOffset());
       
  2179     return r;
       
  2180 }
       
  2181 
       
  2182 /*!
       
  2183   returns a rectangle (in viewport coordinates) that includes the
       
  2184   cursor of the text edit.
       
  2185  */
       
  2186 QRect QPlainTextEdit::cursorRect() const
       
  2187 {
       
  2188     Q_D(const QPlainTextEdit);
       
  2189     QRect r = d->control->cursorRect().toRect();
       
  2190     r.translate(-d->horizontalOffset(),-d->verticalOffset());
       
  2191     return r;
       
  2192 }
       
  2193 
       
  2194 
       
  2195 /*!
       
  2196    \property QPlainTextEdit::overwriteMode
       
  2197    \brief whether text entered by the user will overwrite existing text
       
  2198 
       
  2199    As with many text editors, the plain text editor widget can be configured
       
  2200    to insert or overwrite existing text with new text entered by the user.
       
  2201 
       
  2202    If this property is true, existing text is overwritten, character-for-character
       
  2203    by new text; otherwise, text is inserted at the cursor position, displacing
       
  2204    existing text.
       
  2205 
       
  2206    By default, this property is false (new text does not overwrite existing text).
       
  2207 */
       
  2208 
       
  2209 bool QPlainTextEdit::overwriteMode() const
       
  2210 {
       
  2211     Q_D(const QPlainTextEdit);
       
  2212     return d->control->overwriteMode();
       
  2213 }
       
  2214 
       
  2215 void QPlainTextEdit::setOverwriteMode(bool overwrite)
       
  2216 {
       
  2217     Q_D(QPlainTextEdit);
       
  2218     d->control->setOverwriteMode(overwrite);
       
  2219 }
       
  2220 
       
  2221 /*!
       
  2222     \property QPlainTextEdit::tabStopWidth
       
  2223     \brief the tab stop width in pixels
       
  2224 
       
  2225     By default, this property contains a value of 80.
       
  2226 */
       
  2227 
       
  2228 int QPlainTextEdit::tabStopWidth() const
       
  2229 {
       
  2230     Q_D(const QPlainTextEdit);
       
  2231     return qRound(d->control->document()->defaultTextOption().tabStop());
       
  2232 }
       
  2233 
       
  2234 void QPlainTextEdit::setTabStopWidth(int width)
       
  2235 {
       
  2236     Q_D(QPlainTextEdit);
       
  2237     QTextOption opt = d->control->document()->defaultTextOption();
       
  2238     if (opt.tabStop() == width || width < 0)
       
  2239         return;
       
  2240     opt.setTabStop(width);
       
  2241     d->control->document()->setDefaultTextOption(opt);
       
  2242 }
       
  2243 
       
  2244 /*!
       
  2245     \property QPlainTextEdit::cursorWidth
       
  2246 
       
  2247     This property specifies the width of the cursor in pixels. The default value is 1.
       
  2248 */
       
  2249 int QPlainTextEdit::cursorWidth() const
       
  2250 {
       
  2251     Q_D(const QPlainTextEdit);
       
  2252     return d->control->cursorWidth();
       
  2253 }
       
  2254 
       
  2255 void QPlainTextEdit::setCursorWidth(int width)
       
  2256 {
       
  2257     Q_D(QPlainTextEdit);
       
  2258     d->control->setCursorWidth(width);
       
  2259 }
       
  2260 
       
  2261 
       
  2262 
       
  2263 /*!
       
  2264     This function allows temporarily marking certain regions in the document
       
  2265     with a given color, specified as \a selections. This can be useful for
       
  2266     example in a programming editor to mark a whole line of text with a given
       
  2267     background color to indicate the existence of a breakpoint.
       
  2268 
       
  2269     \sa QTextEdit::ExtraSelection, extraSelections()
       
  2270 */
       
  2271 void QPlainTextEdit::setExtraSelections(const QList<QTextEdit::ExtraSelection> &selections)
       
  2272 {
       
  2273     Q_D(QPlainTextEdit);
       
  2274     d->control->setExtraSelections(selections);
       
  2275 }
       
  2276 
       
  2277 /*!
       
  2278     Returns previously set extra selections.
       
  2279 
       
  2280     \sa setExtraSelections()
       
  2281 */
       
  2282 QList<QTextEdit::ExtraSelection> QPlainTextEdit::extraSelections() const
       
  2283 {
       
  2284     Q_D(const QPlainTextEdit);
       
  2285     return d->control->extraSelections();
       
  2286 }
       
  2287 
       
  2288 /*!
       
  2289     This function returns a new MIME data object to represent the contents
       
  2290     of the text edit's current selection. It is called when the selection needs
       
  2291     to be encapsulated into a new QMimeData object; for example, when a drag
       
  2292     and drop operation is started, or when data is copied to the clipboard.
       
  2293 
       
  2294     If you reimplement this function, note that the ownership of the returned
       
  2295     QMimeData object is passed to the caller. The selection can be retrieved
       
  2296     by using the textCursor() function.
       
  2297 */
       
  2298 QMimeData *QPlainTextEdit::createMimeDataFromSelection() const
       
  2299 {
       
  2300     Q_D(const QPlainTextEdit);
       
  2301     return d->control->QTextControl::createMimeDataFromSelection();
       
  2302 }
       
  2303 
       
  2304 /*!
       
  2305     This function returns true if the contents of the MIME data object, specified
       
  2306     by \a source, can be decoded and inserted into the document. It is called
       
  2307     for example when during a drag operation the mouse enters this widget and it
       
  2308     is necessary to determine whether it is possible to accept the drag.
       
  2309  */
       
  2310 bool QPlainTextEdit::canInsertFromMimeData(const QMimeData *source) const
       
  2311 {
       
  2312     Q_D(const QPlainTextEdit);
       
  2313     return d->control->QTextControl::canInsertFromMimeData(source);
       
  2314 }
       
  2315 
       
  2316 /*!
       
  2317     This function inserts the contents of the MIME data object, specified
       
  2318     by \a source, into the text edit at the current cursor position. It is
       
  2319     called whenever text is inserted as the result of a clipboard paste
       
  2320     operation, or when the text edit accepts data from a drag and drop
       
  2321     operation.
       
  2322 */
       
  2323 void QPlainTextEdit::insertFromMimeData(const QMimeData *source)
       
  2324 {
       
  2325     Q_D(QPlainTextEdit);
       
  2326     d->control->QTextControl::insertFromMimeData(source);
       
  2327 }
       
  2328 
       
  2329 /*!
       
  2330     \property QPlainTextEdit::readOnly
       
  2331     \brief whether the text edit is read-only
       
  2332 
       
  2333     In a read-only text edit the user can only navigate through the
       
  2334     text and select text; modifying the text is not possible.
       
  2335 
       
  2336     This property's default is false.
       
  2337 */
       
  2338 
       
  2339 bool QPlainTextEdit::isReadOnly() const
       
  2340 {
       
  2341     Q_D(const QPlainTextEdit);
       
  2342     return !(d->control->textInteractionFlags() & Qt::TextEditable);
       
  2343 }
       
  2344 
       
  2345 void QPlainTextEdit::setReadOnly(bool ro)
       
  2346 {
       
  2347     Q_D(QPlainTextEdit);
       
  2348     Qt::TextInteractionFlags flags = Qt::NoTextInteraction;
       
  2349     if (ro) {
       
  2350         flags = Qt::TextSelectableByMouse;
       
  2351     } else {
       
  2352         flags = Qt::TextEditorInteraction;
       
  2353     }
       
  2354     setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this));
       
  2355     d->control->setTextInteractionFlags(flags);
       
  2356 }
       
  2357 
       
  2358 /*!
       
  2359     \property QPlainTextEdit::textInteractionFlags
       
  2360 
       
  2361     Specifies how the label should interact with user input if it displays text.
       
  2362 
       
  2363     If the flags contain either Qt::LinksAccessibleByKeyboard or Qt::TextSelectableByKeyboard
       
  2364     then the focus policy is also automatically set to Qt::ClickFocus.
       
  2365 
       
  2366     The default value depends on whether the QPlainTextEdit is read-only
       
  2367     or editable, and whether it is a QTextBrowser or not.
       
  2368 */
       
  2369 
       
  2370 void QPlainTextEdit::setTextInteractionFlags(Qt::TextInteractionFlags flags)
       
  2371 {
       
  2372     Q_D(QPlainTextEdit);
       
  2373     d->control->setTextInteractionFlags(flags);
       
  2374 }
       
  2375 
       
  2376 Qt::TextInteractionFlags QPlainTextEdit::textInteractionFlags() const
       
  2377 {
       
  2378     Q_D(const QPlainTextEdit);
       
  2379     return d->control->textInteractionFlags();
       
  2380 }
       
  2381 
       
  2382 /*!
       
  2383     Merges the properties specified in \a modifier into the current character
       
  2384     format by calling QTextCursor::mergeCharFormat on the editor's cursor.
       
  2385     If the editor has a selection then the properties of \a modifier are
       
  2386     directly applied to the selection.
       
  2387 
       
  2388     \sa QTextCursor::mergeCharFormat()
       
  2389  */
       
  2390 void QPlainTextEdit::mergeCurrentCharFormat(const QTextCharFormat &modifier)
       
  2391 {
       
  2392     Q_D(QPlainTextEdit);
       
  2393     d->control->mergeCurrentCharFormat(modifier);
       
  2394 }
       
  2395 
       
  2396 /*!
       
  2397     Sets the char format that is be used when inserting new text to \a
       
  2398     format by calling QTextCursor::setCharFormat() on the editor's
       
  2399     cursor.  If the editor has a selection then the char format is
       
  2400     directly applied to the selection.
       
  2401  */
       
  2402 void QPlainTextEdit::setCurrentCharFormat(const QTextCharFormat &format)
       
  2403 {
       
  2404     Q_D(QPlainTextEdit);
       
  2405     d->control->setCurrentCharFormat(format);
       
  2406 }
       
  2407 
       
  2408 /*!
       
  2409     Returns the char format that is used when inserting new text.
       
  2410  */
       
  2411 QTextCharFormat QPlainTextEdit::currentCharFormat() const
       
  2412 {
       
  2413     Q_D(const QPlainTextEdit);
       
  2414     return d->control->currentCharFormat();
       
  2415 }
       
  2416 
       
  2417 
       
  2418 
       
  2419 /*!
       
  2420     Convenience slot that inserts \a text at the current
       
  2421     cursor position.
       
  2422 
       
  2423     It is equivalent to
       
  2424 
       
  2425     \snippet doc/src/snippets/code/src_gui_widgets_qplaintextedit.cpp 1
       
  2426  */
       
  2427 void QPlainTextEdit::insertPlainText(const QString &text)
       
  2428 {
       
  2429     Q_D(QPlainTextEdit);
       
  2430     d->control->insertPlainText(text);
       
  2431 }
       
  2432 
       
  2433 
       
  2434 /*!
       
  2435     Moves the cursor by performing the given \a operation.
       
  2436 
       
  2437     If \a mode is QTextCursor::KeepAnchor, the cursor selects the text it moves over.
       
  2438     This is the same effect that the user achieves when they hold down the Shift key
       
  2439     and move the cursor with the cursor keys.
       
  2440 
       
  2441     \sa QTextCursor::movePosition()
       
  2442 */
       
  2443 void QPlainTextEdit::moveCursor(QTextCursor::MoveOperation operation, QTextCursor::MoveMode mode)
       
  2444 {
       
  2445     Q_D(QPlainTextEdit);
       
  2446     d->control->moveCursor(operation, mode);
       
  2447 }
       
  2448 
       
  2449 /*!
       
  2450     Returns whether text can be pasted from the clipboard into the textedit.
       
  2451 */
       
  2452 bool QPlainTextEdit::canPaste() const
       
  2453 {
       
  2454     Q_D(const QPlainTextEdit);
       
  2455     return d->control->canPaste();
       
  2456 }
       
  2457 
       
  2458 #ifndef QT_NO_PRINTER
       
  2459 /*!
       
  2460     Convenience function to print the text edit's document to the given \a printer. This
       
  2461     is equivalent to calling the print method on the document directly except that this
       
  2462     function also supports QPrinter::Selection as print range.
       
  2463 
       
  2464     \sa QTextDocument::print()
       
  2465 */
       
  2466 void QPlainTextEdit::print(QPrinter *printer) const
       
  2467 {
       
  2468     Q_D(const QPlainTextEdit);
       
  2469     d->control->print(printer);
       
  2470 }
       
  2471 #endif // QT _NO_PRINTER
       
  2472 
       
  2473 /*! \property QPlainTextEdit::tabChangesFocus
       
  2474   \brief whether \gui Tab changes focus or is accepted as input
       
  2475 
       
  2476   In some occasions text edits should not allow the user to input
       
  2477   tabulators or change indentation using the \gui Tab key, as this breaks
       
  2478   the focus chain. The default is false.
       
  2479 
       
  2480 */
       
  2481 
       
  2482 bool QPlainTextEdit::tabChangesFocus() const
       
  2483 {
       
  2484     Q_D(const QPlainTextEdit);
       
  2485     return d->tabChangesFocus;
       
  2486 }
       
  2487 
       
  2488 void QPlainTextEdit::setTabChangesFocus(bool b)
       
  2489 {
       
  2490     Q_D(QPlainTextEdit);
       
  2491     d->tabChangesFocus = b;
       
  2492 }
       
  2493 
       
  2494 /*!
       
  2495     \property QPlainTextEdit::documentTitle
       
  2496     \brief the title of the document parsed from the text.
       
  2497 
       
  2498     By default, this property contains an empty string.
       
  2499 */
       
  2500 
       
  2501 /*!
       
  2502     \property QPlainTextEdit::lineWrapMode
       
  2503     \brief the line wrap mode
       
  2504 
       
  2505     The default mode is WidgetWidth which causes words to be
       
  2506     wrapped at the right edge of the text edit. Wrapping occurs at
       
  2507     whitespace, keeping whole words intact. If you want wrapping to
       
  2508     occur within words use setWordWrapMode().
       
  2509 */
       
  2510 
       
  2511 QPlainTextEdit::LineWrapMode QPlainTextEdit::lineWrapMode() const
       
  2512 {
       
  2513     Q_D(const QPlainTextEdit);
       
  2514     return d->lineWrap;
       
  2515 }
       
  2516 
       
  2517 void QPlainTextEdit::setLineWrapMode(LineWrapMode wrap)
       
  2518 {
       
  2519     Q_D(QPlainTextEdit);
       
  2520     if (d->lineWrap == wrap)
       
  2521         return;
       
  2522     d->lineWrap = wrap;
       
  2523     d->updateDefaultTextOption();
       
  2524     d->relayoutDocument();
       
  2525     d->_q_adjustScrollbars();
       
  2526     ensureCursorVisible();
       
  2527 }
       
  2528 
       
  2529 /*!
       
  2530     \property QPlainTextEdit::wordWrapMode
       
  2531     \brief the mode QPlainTextEdit will use when wrapping text by words
       
  2532 
       
  2533     By default, this property is set to QTextOption::WrapAtWordBoundaryOrAnywhere.
       
  2534 
       
  2535     \sa QTextOption::WrapMode
       
  2536 */
       
  2537 
       
  2538 QTextOption::WrapMode QPlainTextEdit::wordWrapMode() const
       
  2539 {
       
  2540     Q_D(const QPlainTextEdit);
       
  2541     return d->wordWrap;
       
  2542 }
       
  2543 
       
  2544 void QPlainTextEdit::setWordWrapMode(QTextOption::WrapMode mode)
       
  2545 {
       
  2546     Q_D(QPlainTextEdit);
       
  2547     if (mode == d->wordWrap)
       
  2548         return;
       
  2549     d->wordWrap = mode;
       
  2550     d->updateDefaultTextOption();
       
  2551 }
       
  2552 
       
  2553 /*!
       
  2554     \property QPlainTextEdit::backgroundVisible
       
  2555     \brief whether the palette background is visible outside the document area
       
  2556 
       
  2557     If set to true, the plain text edit paints the palette background
       
  2558     on the viewport area not covered by the text document. Otherwise,
       
  2559     if set to false, it won't. The feature makes it possible for
       
  2560     the user to visually distinguish between the area of the document,
       
  2561     painted with the base color of the palette, and the empty
       
  2562     area not covered by any document.
       
  2563 
       
  2564     The default is false.
       
  2565 */
       
  2566 
       
  2567 bool QPlainTextEdit::backgroundVisible() const
       
  2568 {
       
  2569     Q_D(const QPlainTextEdit);
       
  2570     return d->backgroundVisible;
       
  2571 }
       
  2572 
       
  2573 void QPlainTextEdit::setBackgroundVisible(bool visible)
       
  2574 {
       
  2575     Q_D(QPlainTextEdit);
       
  2576     if (visible == d->backgroundVisible)
       
  2577         return;
       
  2578     d->backgroundVisible = visible;
       
  2579     d->updateViewport();
       
  2580 }
       
  2581 
       
  2582 /*!
       
  2583     \property QPlainTextEdit::centerOnScroll
       
  2584     \brief whether the cursor should be centered on screen
       
  2585 
       
  2586     If set to true, the plain text edit scrolls the document
       
  2587     vertically to make the cursor visible at the center of the
       
  2588     viewport. This also allows the text edit to scroll below the end
       
  2589     of the document. Otherwise, if set to false, the plain text edit
       
  2590     scrolls the smallest amount possible to ensure the cursor is
       
  2591     visible.  The same algorithm is applied to any new line appended
       
  2592     through appendPlainText().
       
  2593 
       
  2594     The default is false.
       
  2595 
       
  2596     \sa centerCursor(), ensureCursorVisible()
       
  2597 */
       
  2598 
       
  2599 bool QPlainTextEdit::centerOnScroll() const
       
  2600 {
       
  2601     Q_D(const QPlainTextEdit);
       
  2602     return d->centerOnScroll;
       
  2603 }
       
  2604 
       
  2605 void QPlainTextEdit::setCenterOnScroll(bool enabled)
       
  2606 {
       
  2607     Q_D(QPlainTextEdit);
       
  2608     if (enabled == d->centerOnScroll)
       
  2609         return;
       
  2610     d->centerOnScroll = enabled;
       
  2611 }
       
  2612 
       
  2613 
       
  2614 
       
  2615 /*!
       
  2616     Finds the next occurrence of the string, \a exp, using the given
       
  2617     \a options. Returns true if \a exp was found and changes the
       
  2618     cursor to select the match; otherwise returns false.
       
  2619 */
       
  2620 bool QPlainTextEdit::find(const QString &exp, QTextDocument::FindFlags options)
       
  2621 {
       
  2622     Q_D(QPlainTextEdit);
       
  2623     return d->control->find(exp, options);
       
  2624 }
       
  2625 
       
  2626 /*!
       
  2627     \fn void QPlainTextEdit::copyAvailable(bool yes)
       
  2628 
       
  2629     This signal is emitted when text is selected or de-selected in the
       
  2630     text edit.
       
  2631 
       
  2632     When text is selected this signal will be emitted with \a yes set
       
  2633     to true. If no text has been selected or if the selected text is
       
  2634     de-selected this signal is emitted with \a yes set to false.
       
  2635 
       
  2636     If \a yes is true then copy() can be used to copy the selection to
       
  2637     the clipboard. If \a yes is false then copy() does nothing.
       
  2638 
       
  2639     \sa selectionChanged()
       
  2640 */
       
  2641 
       
  2642 
       
  2643 /*!
       
  2644     \fn void QPlainTextEdit::selectionChanged()
       
  2645 
       
  2646     This signal is emitted whenever the selection changes.
       
  2647 
       
  2648     \sa copyAvailable()
       
  2649 */
       
  2650 
       
  2651 /*!
       
  2652     \fn void QPlainTextEdit::cursorPositionChanged()
       
  2653 
       
  2654     This signal is emitted whenever the position of the
       
  2655     cursor changed.
       
  2656 */
       
  2657 
       
  2658 
       
  2659 
       
  2660 /*!
       
  2661     \fn void QPlainTextEdit::updateRequest(const QRect &rect, int dy)
       
  2662 
       
  2663     This signal is emitted when the text document needs an update of
       
  2664     the specified \a rect. If the text is scrolled, \a rect will cover
       
  2665     the entire viewport area. If the text is scrolled vertically, \a
       
  2666     dy carries the amount of pixels the viewport was scrolled.
       
  2667 
       
  2668     The purpose of the signal is to support extra widgets in plain
       
  2669     text edit subclasses that e.g. show line numbers, breakpoints, or
       
  2670     other extra information.
       
  2671 */
       
  2672 
       
  2673 /*!  \fn void QPlainTextEdit::blockCountChanged(int newBlockCount);
       
  2674 
       
  2675     This signal is emitted whenever the block count changes. The new
       
  2676     block count is passed in \a newBlockCount.
       
  2677 */
       
  2678 
       
  2679 /*!  \fn void QPlainTextEdit::modificationChanged(bool changed);
       
  2680 
       
  2681     This signal is emitted whenever the content of the document
       
  2682     changes in a way that affects the modification state. If \a
       
  2683     changed is true, the document has been modified; otherwise it is
       
  2684     false.
       
  2685 
       
  2686     For example, calling setModified(false) on a document and then
       
  2687     inserting text causes the signal to get emitted. If you undo that
       
  2688     operation, causing the document to return to its original
       
  2689     unmodified state, the signal will get emitted again.
       
  2690 */
       
  2691 
       
  2692 
       
  2693 
       
  2694 
       
  2695 void QPlainTextEditPrivate::append(const QString &text, Qt::TextFormat format)
       
  2696 {
       
  2697     Q_Q(QPlainTextEdit);
       
  2698 
       
  2699     QTextDocument *document = control->document();
       
  2700     QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(document->documentLayout());
       
  2701     Q_ASSERT(documentLayout);
       
  2702 
       
  2703     int maximumBlockCount = document->maximumBlockCount();
       
  2704     if (maximumBlockCount)
       
  2705         document->setMaximumBlockCount(0);
       
  2706 
       
  2707     const bool atBottom =  q->isVisible()
       
  2708                            && (control->blockBoundingRect(document->lastBlock()).bottom() - verticalOffset()
       
  2709                                <= viewport->rect().bottom());
       
  2710 
       
  2711     if (!q->isVisible())
       
  2712         showCursorOnInitialShow = true;
       
  2713 
       
  2714     bool documentSizeChangedBlocked = documentLayout->priv()->blockDocumentSizeChanged;
       
  2715     documentLayout->priv()->blockDocumentSizeChanged = true;
       
  2716 
       
  2717     if (format == Qt::RichText)
       
  2718         control->appendHtml(text);
       
  2719     else if (format == Qt::PlainText)
       
  2720         control->appendPlainText(text);
       
  2721     else
       
  2722         control->append(text);
       
  2723 
       
  2724     if (maximumBlockCount > 0) {
       
  2725         if (document->blockCount() > maximumBlockCount) {
       
  2726             bool blockUpdate = false;
       
  2727             if (control->topBlock) {
       
  2728                 control->topBlock--;
       
  2729                 blockUpdate = true;
       
  2730                 emit q->updateRequest(viewport->rect(), 0);
       
  2731             }
       
  2732 
       
  2733             bool updatesBlocked = documentLayout->priv()->blockUpdate;
       
  2734             documentLayout->priv()->blockUpdate = blockUpdate;
       
  2735             QTextCursor cursor(document);
       
  2736             cursor.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor);
       
  2737             cursor.removeSelectedText();
       
  2738             documentLayout->priv()->blockUpdate = updatesBlocked;
       
  2739         }
       
  2740         document->setMaximumBlockCount(maximumBlockCount);
       
  2741     }
       
  2742 
       
  2743     documentLayout->priv()->blockDocumentSizeChanged = documentSizeChangedBlocked;
       
  2744     _q_adjustScrollbars();
       
  2745 
       
  2746 
       
  2747     if (atBottom) {
       
  2748         const bool needScroll =  !centerOnScroll
       
  2749                                  || control->blockBoundingRect(document->lastBlock()).bottom() - verticalOffset()
       
  2750                                  > viewport->rect().bottom();
       
  2751         if (needScroll)
       
  2752             vbar->setValue(vbar->maximum());
       
  2753     }
       
  2754 }
       
  2755 
       
  2756 
       
  2757 /*!
       
  2758     Appends a new paragraph with \a text to the end of the text edit.
       
  2759 
       
  2760     \sa appendHtml()
       
  2761 */
       
  2762 
       
  2763 void QPlainTextEdit::appendPlainText(const QString &text)
       
  2764 {
       
  2765     Q_D(QPlainTextEdit);
       
  2766     d->append(text, Qt::PlainText);
       
  2767 }
       
  2768 
       
  2769 /*!
       
  2770     Appends a new paragraph with \a html to the end of the text edit.
       
  2771 
       
  2772     appendPlainText()
       
  2773 */
       
  2774 
       
  2775 void QPlainTextEdit::appendHtml(const QString &html)
       
  2776 {
       
  2777     Q_D(QPlainTextEdit);
       
  2778     d->append(html, Qt::RichText);
       
  2779 }
       
  2780 
       
  2781 void QPlainTextEditPrivate::ensureCursorVisible(bool center)
       
  2782 {
       
  2783     Q_Q(QPlainTextEdit);
       
  2784     QRect visible = viewport->rect();
       
  2785     QRect cr = q->cursorRect();
       
  2786     if (cr.top() < visible.top() || cr.bottom() > visible.bottom()) {
       
  2787         ensureVisible(control->textCursor().position(), center);
       
  2788     }
       
  2789 
       
  2790     const bool rtl = q->isRightToLeft();
       
  2791     if (cr.left() < visible.left() || cr.right() > visible.right()) {
       
  2792         int x = cr.center().x() + horizontalOffset() - visible.width()/2;
       
  2793         hbar->setValue(rtl ? hbar->maximum() - x : x);
       
  2794     }
       
  2795 }
       
  2796 
       
  2797 /*!
       
  2798     Ensures that the cursor is visible by scrolling the text edit if
       
  2799     necessary.
       
  2800 
       
  2801     \sa centerCursor(), centerOnScroll
       
  2802 */
       
  2803 void QPlainTextEdit::ensureCursorVisible()
       
  2804 {
       
  2805     Q_D(QPlainTextEdit);
       
  2806     d->ensureCursorVisible(d->centerOnScroll);
       
  2807 }
       
  2808 
       
  2809 
       
  2810 /*!  Scrolls the document in order to center the cursor vertically.
       
  2811 
       
  2812 \sa ensureCursorVisible(), centerOnScroll
       
  2813  */
       
  2814 void QPlainTextEdit::centerCursor()
       
  2815 {
       
  2816     Q_D(QPlainTextEdit);
       
  2817     d->ensureVisible(textCursor().position(), true, true);
       
  2818 }
       
  2819 
       
  2820 /*!
       
  2821   Returns the first visible block.
       
  2822 
       
  2823   \sa blockBoundingRect()
       
  2824  */
       
  2825 QTextBlock QPlainTextEdit::firstVisibleBlock() const
       
  2826 {
       
  2827     Q_D(const QPlainTextEdit);
       
  2828     return d->control->firstVisibleBlock();
       
  2829 }
       
  2830 
       
  2831 /*!  Returns the content's origin in viewport coordinates.
       
  2832 
       
  2833      The origin of the content of a plain text edit is always the top
       
  2834      left corner of the first visible text block. The content offset
       
  2835      is different from (0,0) when the text has been scrolled
       
  2836      horizontally, or when the first visible block has been scrolled
       
  2837      partially off the screen, i.e. the visible text does not start
       
  2838      with the first line of the first visible block, or when the first
       
  2839      visible block is the very first block and the editor displays a
       
  2840      margin.
       
  2841 
       
  2842      \sa firstVisibleBlock(), horizontalScrollBar(), verticalScrollBar()
       
  2843  */
       
  2844 QPointF QPlainTextEdit::contentOffset() const
       
  2845 {
       
  2846     Q_D(const QPlainTextEdit);
       
  2847     return QPointF(-d->horizontalOffset(), -d->verticalOffset());
       
  2848 }
       
  2849 
       
  2850 
       
  2851 /*!  Returns the bounding rectangle of the text \a block in content
       
  2852   coordinates. Translate the rectangle with the contentOffset() to get
       
  2853   visual coordinates on the viewport.
       
  2854 
       
  2855   \sa firstVisibleBlock(), blockBoundingRect()
       
  2856  */
       
  2857 QRectF QPlainTextEdit::blockBoundingGeometry(const QTextBlock &block) const
       
  2858 {
       
  2859     Q_D(const QPlainTextEdit);
       
  2860     return d->control->blockBoundingRect(block);
       
  2861 }
       
  2862 
       
  2863 /*!
       
  2864   Returns the bounding rectangle of the text \a block in the block's own coordinates.
       
  2865 
       
  2866   \sa blockBoundingGeometry()
       
  2867  */
       
  2868 QRectF QPlainTextEdit::blockBoundingRect(const QTextBlock &block) const
       
  2869 {
       
  2870     QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(document()->documentLayout());
       
  2871     Q_ASSERT(documentLayout);
       
  2872     return documentLayout->blockBoundingRect(block);
       
  2873 }
       
  2874 
       
  2875 /*!
       
  2876     \property QPlainTextEdit::blockCount
       
  2877     \brief the number of text blocks in the document.
       
  2878 
       
  2879     By default, in an empty document, this property contains a value of 1.
       
  2880 */
       
  2881 int QPlainTextEdit::blockCount() const
       
  2882 {
       
  2883     return document()->blockCount();
       
  2884 }
       
  2885 
       
  2886 /*!  Returns the paint context for the viewport(), useful only when
       
  2887   reimplementing paintEvent().
       
  2888  */
       
  2889 QAbstractTextDocumentLayout::PaintContext QPlainTextEdit::getPaintContext() const
       
  2890 {
       
  2891     Q_D(const QPlainTextEdit);
       
  2892     return d->control->getPaintContext(d->viewport);
       
  2893 }
       
  2894 
       
  2895 /*!
       
  2896     \property QPlainTextEdit::maximumBlockCount
       
  2897     \brief the limit for blocks in the document.
       
  2898 
       
  2899     Specifies the maximum number of blocks the document may have. If there are
       
  2900     more blocks in the document that specified with this property blocks are removed
       
  2901     from the beginning of the document.
       
  2902 
       
  2903     A negative or zero value specifies that the document may contain an unlimited
       
  2904     amount of blocks.
       
  2905 
       
  2906     The default value is 0.
       
  2907 
       
  2908     Note that setting this property will apply the limit immediately to the document
       
  2909     contents. Setting this property also disables the undo redo history.
       
  2910 
       
  2911 */
       
  2912 
       
  2913 
       
  2914 /*!
       
  2915     \fn void QPlainTextEdit::textChanged()
       
  2916 
       
  2917     This signal is emitted whenever the document's content changes; for
       
  2918     example, when text is inserted or deleted, or when formatting is applied.
       
  2919 */
       
  2920 
       
  2921 /*!
       
  2922     \fn void QPlainTextEdit::undoAvailable(bool available)
       
  2923 
       
  2924     This signal is emitted whenever undo operations become available
       
  2925     (\a available is true) or unavailable (\a available is false).
       
  2926 */
       
  2927 
       
  2928 /*!
       
  2929     \fn void QPlainTextEdit::redoAvailable(bool available)
       
  2930 
       
  2931     This signal is emitted whenever redo operations become available
       
  2932     (\a available is true) or unavailable (\a available is false).
       
  2933 */
       
  2934 
       
  2935 //void QPlainTextEditPrivate::_q_gestureTriggered()
       
  2936 //{
       
  2937 //    Q_Q(QPlainTextEdit);
       
  2938 //    QPanGesture *g = qobject_cast<QPanGesture*>(q->sender());
       
  2939 //    if (!g)
       
  2940 //        return;
       
  2941 //    QScrollBar *hBar = q->horizontalScrollBar();
       
  2942 //    QScrollBar *vBar = q->verticalScrollBar();
       
  2943 //    if (g->state() == Qt::GestureStarted)
       
  2944 //        originalOffsetY = vBar->value();
       
  2945 //    QSizeF totalOffset = g->totalOffset();
       
  2946 //    if (!totalOffset.isNull()) {
       
  2947 //        if (QApplication::isRightToLeft())
       
  2948 //            totalOffset.rwidth() *= -1;
       
  2949 //        // QPlainTextEdit scrolls by lines only in vertical direction
       
  2950 //        QFontMetrics fm(q->document()->defaultFont());
       
  2951 //        int lineHeight = fm.height();
       
  2952 //        int newX = hBar->value() - g->lastOffset().width();
       
  2953 //        int newY = originalOffsetY - totalOffset.height()/lineHeight;
       
  2954 //        hbar->setValue(newX);
       
  2955 //        vbar->setValue(newY);
       
  2956 //    }
       
  2957 //}
       
  2958 
       
  2959 QT_END_NAMESPACE
       
  2960 
       
  2961 #include "moc_qplaintextedit.cpp"
       
  2962 #include "moc_qplaintextedit_p.cpp"
       
  2963 
       
  2964 #endif // QT_NO_TEXTEDIT