Ignore:
Timestamp:
Feb 11, 2010, 11:19:06 PM (15 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.6.1 sources.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/gui/widgets/qplaintextedit.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtGui module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     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.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    6666#include <qtexttable.h>
    6767#include <qvariant.h>
    68 
    6968#include <qinputcontext.h>
    7069
     
    7271
    7372QT_BEGIN_NAMESPACE
     73
     74static inline bool shouldEnableInputMethod(QPlainTextEdit *plaintextedit)
     75{
     76    return !plaintextedit->isReadOnly();
     77}
    7478
    7579class QPlainTextDocumentLayoutPrivate : public QAbstractTextDocumentLayoutPrivate
     
    110114    \brief The QPlainTextDocumentLayout class implements a plain text layout for QTextDocument
    111115
    112     \ingroup text
    113 
     116    \ingroup richtext-processing
    114117
    115118   A QPlainTextDocumentLayout is required for text documents that can
     
    251254void QPlainTextDocumentLayout::requestUpdate()
    252255{
    253     emit update(QRectF(0., -4., 1000000000., 1000000000.));
     256    emit update(QRectF(0., -document()->documentMargin(), 1000000000., 1000000000.));
    254257}
    255258
     
    346349
    347350    if (!d->blockUpdate)
    348         emit update(); // optimization potential
    349 
     351        emit update(QRectF(0., -doc->documentMargin(), 1000000000., 1000000000.)); // optimization potential
    350352}
    351353
     
    356358    QTextDocument *doc = document();
    357359    qreal margin = doc->documentMargin();
    358     QFontMetrics fm(doc->defaultFont());
    359360    qreal blockMaximumWidth = 0;
    360361
    361     int leading = qMax(0, fm.leading());
    362362    qreal height = 0;
    363363    QTextLayout *tl = block.layout();
     
    371371    }
    372372    tl->beginLayout();
     373    qreal availableWidth = d->width;
     374    if (availableWidth <= 0) {
     375        availableWidth = qreal(INT_MAX); // similar to text edit with pageSize.width == 0
     376    }
     377    availableWidth -= 2*margin + extraMargin;
    373378    while (1) {
    374379        QTextLine line = tl->createLine();
    375380        if (!line.isValid())
    376381            break;
    377         line.setLineWidth(d->width - 2*margin - extraMargin);
    378 
    379         height += leading;
     382        line.setLeadingIncluded(true);
     383        line.setLineWidth(availableWidth);
    380384        line.setPosition(QPointF(margin, height));
    381385        height += line.height();
     
    440444{
    441445    pageUpDownLastCursorYIsValid = false;
    442 };
     446}
    443447
    444448void QPlainTextEditPrivate::_q_verticalScrollbarActionTriggered(int action) {
     
    508512    int currentBlockNumber = topBlock;
    509513    QTextBlock currentBlock = document()->findBlockByNumber(currentBlockNumber);
     514    if (!currentBlock.isValid())
     515        return -1;
     516
    510517    QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(document()->documentLayout());
    511518    Q_ASSERT(documentLayout);
     
    556563        return QRectF();
    557564    Q_ASSERT(currentBlock.blockNumber() == currentBlockNumber);
    558     QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(document()->documentLayout());
     565    QTextDocument *doc = document();
     566    QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(doc->documentLayout());
    559567    Q_ASSERT(documentLayout);
    560568
     
    563571        return QRectF();
    564572    QRectF r = documentLayout->blockBoundingRect(currentBlock);
    565     while (currentBlockNumber < blockNumber && offset.y() <= 2* textEdit->viewport()->height()) {
     573    int maxVerticalOffset = r.height();
     574    while (currentBlockNumber < blockNumber && offset.y() - maxVerticalOffset <= 2* textEdit->viewport()->height()) {
    566575        offset.ry() += r.height();
    567576        currentBlock = currentBlock.next();
    568577        ++currentBlockNumber;
     578        if (!currentBlock.isVisible()) {
     579            currentBlock = doc->findBlockByLineNumber(currentBlock.firstLineNumber());
     580            currentBlockNumber = currentBlock.blockNumber();
     581        }
    569582        r = documentLayout->blockBoundingRect(currentBlock);
    570583    }
    571     while (currentBlockNumber > blockNumber && offset.y() >= -textEdit->viewport()->height()) {
     584    while (currentBlockNumber > blockNumber && offset.y() + maxVerticalOffset >= -textEdit->viewport()->height()) {
    572585        currentBlock = currentBlock.previous();
     586        --currentBlockNumber;
     587        while (!currentBlock.isVisible()) {
     588            currentBlock = currentBlock.previous();
     589            --currentBlockNumber;
     590        }
    573591        if (!currentBlock.isValid())
    574592            break;
    575         --currentBlockNumber;
     593
    576594        r = documentLayout->blockBoundingRect(currentBlock);
    577595        offset.ry() -= r.height();
     
    625643    if (viewport->updatesEnabled() && viewport->isVisible()) {
    626644        int dy = 0;
    627         if (doc->findBlockByLineNumber(control->topBlock).isValid()) {
     645        if (doc->findBlockByNumber(control->topBlock).isValid()) {
    628646            dy = (int)(-q->blockBoundingGeometry(block).y())
    629647                 + verticalOffset() - verticalOffset(blockNumber, lineNumber);
     
    667685        qreal h = center ? line.naturalTextRect().center().y() : line.naturalTextRect().bottom();
    668686
     687        QTextBlock previousVisibleBlock = block;
    669688        while (h < height && block.previous().isValid()) {
    670             block = block.previous();
     689            previousVisibleBlock = block;
     690            do {
     691                block = block.previous();
     692            } while (!block.isVisible() && block.previous().isValid());
    671693            h += q->blockBoundingRect(block).height();
    672694        }
     
    682704        }
    683705
    684         if (block.next().isValid() && l >= lineCount) {
    685             block = block.next();
     706        if (l >= lineCount) {
     707            block = previousVisibleBlock;
    686708            l = 0;
    687709        }
     
    706728      lineWrap(QPlainTextEdit::WidgetWidth),
    707729      wordWrap(QTextOption::WrapAtWordBoundaryOrAnywhere),
    708       topLine(0), pageUpDownLastCursorYIsValid(false)
     730      clickCausedFocus(0),topLine(0),
     731      pageUpDownLastCursorYIsValid(false)
    709732{
    710733    showCursorOnInitialShow = true;
     
    743766    QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorPositionChanged()));
    744767
     768    QObject::connect(control, SIGNAL(textChanged()), q, SLOT(updateMicroFocus()));
    745769
    746770    // set a null page size initially to avoid any relayouting until the textedit
    747771    // is shown. relayoutDocument() will take care of setting the page size to the
    748772    // viewport dimensions later.
    749     doc->setTextWidth(0);
     773    doc->setTextWidth(-1);
    750774    doc->documentLayout()->setPaintDevice(viewport);
    751775    doc->setDefaultFont(q->font());
     
    766790#ifndef QT_NO_CURSOR
    767791    viewport->setCursor(Qt::IBeamCursor);
     792#endif
     793    originalOffsetY = 0;
     794#ifdef Q_WS_WIN
     795    setSingleFingerPanEnabled(true);
    768796#endif
    769797}
     
    9861014    plain text.
    9871015
    988     \ingroup text
    989     \mainclass
     1016    \ingroup richtext-processing
     1017
    9901018
    9911019    \tableofcontents
     
    10001028    QTextEdit, but is optimized for plain text handling.
    10011029
    1002     QPlainTextEdit works on paragraphs and characters. A paragraph is a
    1003     formatted string which is word-wrapped to fit into the width of
     1030    QPlainTextEdit works on paragraphs and characters. A paragraph is
     1031    a formatted string which is word-wrapped to fit into the width of
    10041032    the widget. By default when reading plain text, one newline
    10051033    signifies a paragraph. A document consists of zero or more
    1006     paragraphs. The words in the paragraph are aligned in accordance
    1007     with the paragraph's alignment. Paragraphs are separated by hard
    1008     line breaks. Each character within a paragraph has its own
    1009     attributes, for example, font and color.
     1034    paragraphs. Paragraphs are separated by hard line breaks. Each
     1035    character within a paragraph has its own attributes, for example,
     1036    font and color.
    10101037
    10111038    The shape of the mouse cursor on a QPlainTextEdit is
     
    10151042    \section1 Using QPlainTextEdit as a Display Widget
    10161043
    1017     The text is set or replaced using setPlainText() which deletes any
    1018     existing text and replaces it with the text passed in the
    1019     setPlainText() call.
    1020 
    1021     Text itself can be inserted using the QTextCursor class or using
    1022     the convenience functins insertPlainText(), appendPlainText() or
     1044    The text is set or replaced using setPlainText() which deletes the
     1045    existing text and replaces it with the text passed to setPlainText().
     1046
     1047    Text can be inserted using the QTextCursor class or using the
     1048    convenience functions insertPlainText(), appendPlainText() or
    10231049    paste().
    10241050
    1025     By default the text edit wraps words at whitespace to fit within
     1051    By default, the text edit wraps words at whitespace to fit within
    10261052    the text edit widget. The setLineWrapMode() function is used to
    10271053    specify the kind of line wrap you want, \l WidgetWidth or \l
     
    11491175
    11501176    \sa QTextDocument, QTextCursor, {Application Example},
    1151         {Syntax Highlighter Example}, {Rich Text Processing}
     1177        {Code Editor Example}, {Syntax Highlighter Example},
     1178        {Rich Text Processing}
    11521179
    11531180*/
     
    14291456    }
    14301457#endif
     1458    else if (e->type() == QEvent::Gesture) {
     1459        QGestureEvent *ge = static_cast<QGestureEvent *>(e);
     1460        QPanGesture *g = static_cast<QPanGesture *>(ge->gesture(Qt::PanGesture));
     1461        if (g) {
     1462            QScrollBar *hBar = horizontalScrollBar();
     1463            QScrollBar *vBar = verticalScrollBar();
     1464            if (g->state() == Qt::GestureStarted)
     1465                d->originalOffsetY = vBar->value();
     1466            QPointF offset = g->offset();
     1467            if (!offset.isNull()) {
     1468                if (QApplication::isRightToLeft())
     1469                    offset.rx() *= -1;
     1470                // QPlainTextEdit scrolls by lines only in vertical direction
     1471                QFontMetrics fm(document()->defaultFont());
     1472                int lineHeight = fm.height();
     1473                int newX = hBar->value() - g->delta().x();
     1474                int newY = d->originalOffsetY - offset.y()/lineHeight;
     1475                hBar->setValue(newX);
     1476                vBar->setValue(newY);
     1477            }
     1478        }
     1479        return true;
     1480    }
    14311481    return QAbstractScrollArea::event(e);
    14321482}
     
    15521602#endif
    15531603
    1554     if (!(d->control->textInteractionFlags() & Qt::TextEditable)) {
     1604#ifndef QT_NO_SHORTCUT
     1605
     1606    Qt::TextInteractionFlags tif = d->control->textInteractionFlags();
     1607
     1608    if (tif & Qt::TextSelectableByKeyboard){
     1609        if (e == QKeySequence::SelectPreviousPage) {
     1610            e->accept();
     1611            d->pageUpDown(QTextCursor::Up, QTextCursor::KeepAnchor);
     1612            return;
     1613        } else if (e ==QKeySequence::SelectNextPage) {
     1614            e->accept();
     1615            d->pageUpDown(QTextCursor::Down, QTextCursor::KeepAnchor);
     1616            return;
     1617        }
     1618    }
     1619    if (tif & (Qt::TextSelectableByKeyboard | Qt::TextEditable)) {
     1620        if (e == QKeySequence::MoveToPreviousPage) {
     1621            e->accept();
     1622            d->pageUpDown(QTextCursor::Up, QTextCursor::MoveAnchor);
     1623            return;
     1624        } else if (e == QKeySequence::MoveToNextPage) {
     1625            e->accept();
     1626            d->pageUpDown(QTextCursor::Down, QTextCursor::MoveAnchor);
     1627            return;
     1628        }
     1629    }
     1630
     1631    if (!(tif & Qt::TextEditable)) {
    15551632        switch (e->key()) {
    15561633            case Qt::Key_Space:
     
    15781655        return;
    15791656    }
    1580 
    1581 #ifndef QT_NO_SHORTCUT
    1582     if (e == QKeySequence::MoveToPreviousPage) {
    1583             e->accept();
    1584             d->pageUpDown(QTextCursor::Up, QTextCursor::MoveAnchor);
    1585             return;
    1586     } else if (e == QKeySequence::MoveToNextPage) {
    1587             e->accept();
    1588             d->pageUpDown(QTextCursor::Down, QTextCursor::MoveAnchor);
    1589             return;
    1590     } else if (e == QKeySequence::SelectPreviousPage) {
    1591             e->accept();
    1592             d->pageUpDown(QTextCursor::Up, QTextCursor::KeepAnchor);
    1593             return;
    1594     } else if (e ==QKeySequence::SelectNextPage) {
    1595             e->accept();
    1596             d->pageUpDown(QTextCursor::Down, QTextCursor::KeepAnchor);
    1597             return;
    1598     }
    15991657#endif // QT_NO_SHORTCUT
    1600 
    16011658
    16021659    d->sendControlEvent(e);
     
    16091666                    // Cursor position didn't change, so we want to leave
    16101667                    // these keys to change focus.
     1668                    e->ignore();
     1669                    return;
     1670                }
     1671                break;
     1672            case Qt::Key_Left:
     1673            case Qt::Key_Right:
     1674                if (QApplication::keypadNavigationEnabled()
     1675                        && QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) {
     1676                    // Same as for Key_Up and Key_Down.
    16111677                    e->ignore();
    16121678                    return;
     
    17111777    if (brush.style() >= Qt::LinearGradientPattern && brush.style() <= Qt::ConicalGradientPattern) {
    17121778        if (!gradientRect.isNull()) {
    1713             QTransform m;
    1714             m.translate(gradientRect.left(), gradientRect.top());
     1779            QTransform m = QTransform::fromTranslate(gradientRect.left(), gradientRect.top());
    17151780            m.scale(gradientRect.width(), gradientRect.height());
    17161781            brush.setTransform(m);
     
    17421807    QTextBlock block = firstVisibleBlock();
    17431808    qreal maximumWidth = document()->documentLayout()->documentSize().width();
    1744    
     1809
     1810    // Set a brush origin so that the WaveUnderline knows where the wave started
     1811    painter.setBrushOrigin(offset);
     1812
    17451813    // keep right margin clean from full-width selection
    17461814    int maxX = offset.x() + qMax((qreal)viewportRect.width(), maximumWidth)
     
    19061974        d->ensureCursorVisible();
    19071975    }
     1976
     1977    if (!isReadOnly() && rect().contains(e->pos()))
     1978        d->handleSoftwareInputPanel(e->button(), d->clickCausedFocus);
     1979    d->clickCausedFocus = 0;
    19081980}
    19091981
     
    20062078#endif
    20072079    d->sendControlEvent(e);
     2080    ensureCursorVisible();
    20082081}
    20092082
     
    20392112{
    20402113    Q_D(QPlainTextEdit);
     2114    if (e->reason() == Qt::MouseFocusReason) {
     2115        d->clickCausedFocus = 1;
     2116    }
    20412117    QAbstractScrollArea::focusInEvent(e);
    20422118    d->sendControlEvent(e);
     
    23052381        flags = Qt::TextEditorInteraction;
    23062382    }
    2307     setAttribute(Qt::WA_InputMethodEnabled, !ro);
     2383    setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this));
    23082384    d->control->setTextInteractionFlags(flags);
    23092385}
Note: See TracChangeset for help on using the changeset viewer.