⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qtextcursor.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the QtGui module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file.  Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qtextcursor.h"#include "qtextcursor_p.h"#include "qglobal.h"#include "qtextdocumentfragment.h"#include "qtextdocumentfragment_p.h"#include "qtextlist.h"#include "qtexttable.h"#include "qtexttable_p.h"#include "qtextengine_p.h"#include <qtextlayout.h>#include <qdebug.h>enum {    AdjustPrev = 0x1,    AdjustUp = 0x3,    AdjustNext = 0x4,    AdjustDown = 0x12};QTextCursorPrivate::QTextCursorPrivate(QTextDocumentPrivate *p)    : priv(p), x(0), position(0), anchor(0), adjusted_anchor(0),      currentCharFormat(-1){    priv->addCursor(this);}QTextCursorPrivate::QTextCursorPrivate(const QTextCursorPrivate &rhs)    : QSharedData(rhs){    position = rhs.position;    anchor = rhs.anchor;    adjusted_anchor = rhs.adjusted_anchor;    priv = rhs.priv;    x = rhs.x;    currentCharFormat = rhs.currentCharFormat;    priv->addCursor(this);}QTextCursorPrivate::~QTextCursorPrivate(){    if (priv)        priv->removeCursor(this);}QTextCursorPrivate::AdjustResult QTextCursorPrivate::adjustPosition(int positionOfChange, int charsAddedOrRemoved, QTextUndoCommand::Operation op){    QTextCursorPrivate::AdjustResult result = QTextCursorPrivate::CursorMoved;    // not(!) <= , so that inserting text adjusts the cursor correctly    if (position < positionOfChange ||        (position == positionOfChange && op == QTextUndoCommand::KeepCursor)) {        result = CursorUnchanged;    } else {        if (charsAddedOrRemoved < 0 && position < positionOfChange - charsAddedOrRemoved)            position = positionOfChange;        else            position += charsAddedOrRemoved;        currentCharFormat = -1;    }    if (anchor >= positionOfChange        && (anchor != positionOfChange || op != QTextUndoCommand::KeepCursor)) {        if (charsAddedOrRemoved < 0 && anchor < positionOfChange - charsAddedOrRemoved)            anchor = positionOfChange;        else            anchor += charsAddedOrRemoved;    }    if (adjusted_anchor >= positionOfChange        && (adjusted_anchor != positionOfChange || op != QTextUndoCommand::KeepCursor)) {        if (charsAddedOrRemoved < 0 && adjusted_anchor < positionOfChange - charsAddedOrRemoved)            adjusted_anchor = positionOfChange;        else            adjusted_anchor += charsAddedOrRemoved;    }    return result;}void QTextCursorPrivate::setX(){    QTextBlock block = priv->blocksFind(position);    const QTextLayout *layout = block.layout();    int pos = position - block.position();    QTextLine line = layout->lineForTextPosition(pos);    if (line.isValid())        x = line.cursorToX(pos);}void QTextCursorPrivate::remove(){    if (anchor == position)        return;    priv->beginEditBlock();    currentCharFormat = -1;    int pos1 = position;    int pos2 = adjusted_anchor;    QTextUndoCommand::Operation op = QTextUndoCommand::KeepCursor;    if (pos1 > pos2) {        pos1 = adjusted_anchor;        pos2 = position;        op = QTextUndoCommand::MoveCursor;    }    // deleting inside table? -> delete only content    QTextTable *table = complexSelectionTable();    if (table) {        int startRow, startCol, numRows, numCols;        selectedTableCells(&startRow, &numRows, &startCol, &numCols);        clearCells(table, startRow, startCol, numRows, numCols, op);    } else {        priv->remove(pos1, pos2-pos1, op);    }    adjusted_anchor = anchor = position;    priv->endEditBlock();}void QTextCursorPrivate::clearCells(QTextTable *table, int startRow, int startCol, int numRows, int numCols, QTextUndoCommand::Operation op){    priv->beginEditBlock();    for (int row = startRow; row < startRow + numRows; ++row)        for (int col = startCol; col < startCol + numCols; ++col) {            QTextTableCell cell = table->cellAt(row, col);            const int startPos = cell.firstPosition();            const int endPos = cell.lastPosition();            Q_ASSERT(startPos <= endPos);            priv->remove(startPos, endPos - startPos, op);        }    priv->endEditBlock();}bool QTextCursorPrivate::canDelete(int pos) const{    QTextDocumentPrivate::FragmentIterator fit = priv->find(pos);    QTextCharFormat fmt = priv->formatCollection()->charFormat((*fit)->format);    return (fmt.objectIndex() == -1 || fmt.objectType() == QTextFormat::ImageObject);}void QTextCursorPrivate::insertBlock(const QTextBlockFormat &format, const QTextCharFormat &charFormat){    QTextFormatCollection *formats = priv->formatCollection();    int idx = formats->indexForFormat(format);    Q_ASSERT(formats->format(idx).isBlockFormat());    priv->insertBlock(position, idx, formats->indexForFormat(charFormat));    currentCharFormat = -1;}void QTextCursorPrivate::adjustCursor(QTextCursor::MoveOperation m){    adjusted_anchor = anchor;    if (position == anchor)        return;    QTextFrame *f_position = priv->frameAt(position);    QTextFrame *f_anchor = priv->frameAt(adjusted_anchor);    if (f_position != f_anchor) {        // find common parent frame        QList<QTextFrame *> positionChain;        QList<QTextFrame *> anchorChain;        QTextFrame *f = f_position;        while (f) {            positionChain.prepend(f);            f = f->parentFrame();        }        f = f_anchor;        while (f) {            anchorChain.prepend(f);            f = f->parentFrame();        }        Q_ASSERT(positionChain.at(0) == anchorChain.at(0));        int i = 1;        int l = qMin(positionChain.size(), anchorChain.size());        for (; i < l; ++i) {            if (positionChain.at(i) != anchorChain.at(i))                break;        }        if (m <= QTextCursor::WordLeft) {            if (i < positionChain.size())                position = positionChain.at(i)->firstPosition() - 1;        } else {            if (i < positionChain.size())                position = positionChain.at(i)->lastPosition() + 1;        }        if (position < adjusted_anchor) {            if (i < anchorChain.size())                adjusted_anchor = anchorChain.at(i)->lastPosition() + 1;        } else {            if (i < anchorChain.size())                adjusted_anchor = anchorChain.at(i)->firstPosition() - 1;        }        f_position = positionChain.at(i-1);    }    // same frame, either need to adjust to cell boundaries or return    QTextTable *table = qobject_cast<QTextTable *>(f_position);    if (!table)        return;    QTextTableCell c_position = table->cellAt(position);    QTextTableCell c_anchor = table->cellAt(adjusted_anchor);    if (c_position != c_anchor) {        bool before;        int col_position = c_position.column();        int col_anchor = c_anchor.column();        if (col_position == col_anchor) {            before = c_position.row() < c_anchor.row();        } else {            before = col_position < col_anchor;        }        // adjust to cell boundaries        if (m <= QTextCursor::WordLeft) {            position = c_position.firstPosition();            if (!before)                --position;        } else {            position = c_position.lastPosition();            if (before)                ++position;        }        if (position < adjusted_anchor)            adjusted_anchor = c_anchor.lastPosition();        else            adjusted_anchor = c_anchor.firstPosition();    }    currentCharFormat = -1;}bool QTextCursorPrivate::movePosition(QTextCursor::MoveOperation op, QTextCursor::MoveMode mode){    currentCharFormat = -1;    bool adjustX = true;    QTextBlock blockIt = block();    if (op >= QTextCursor::Left && op <= QTextCursor::WordRight        && blockIt.blockFormat().layoutDirection() == Qt::RightToLeft) {        if (op == QTextCursor::Left)            op = QTextCursor::NextCharacter;        else if (op == QTextCursor::Right)            op = QTextCursor::PreviousCharacter;        else if (op == QTextCursor::WordLeft)            op = QTextCursor::NextWord;        else if (op == QTextCursor::WordRight)            op = QTextCursor::PreviousWord;    }    const QTextLayout *layout = blockIt.layout();    int relativePos = position - blockIt.position();    QTextLine line = layout->lineForTextPosition(relativePos);    Q_ASSERT(priv->frameAt(position) == priv->frameAt(adjusted_anchor));    int newPosition = position;    switch(op) {    case QTextCursor::NoMove:        return true;    case QTextCursor::Start:        newPosition = 0;        break;    case QTextCursor::StartOfLine: {        if (!line.isValid())            break;        newPosition = blockIt.position() + line.textStart();        break;    }    case QTextCursor::StartOfBlock: {        newPosition = blockIt.position();        break;    }    case QTextCursor::PreviousBlock: {        if (blockIt == priv->blocksBegin())            return false;        blockIt = blockIt.previous();        newPosition = blockIt.position();        break;    }    case QTextCursor::PreviousCharacter:    case QTextCursor::Left:        newPosition = priv->previousCursorPosition(position, QTextLayout::SkipCharacters);        break;    case QTextCursor::StartOfWord: {        QTextEngine *engine = layout->engine();        const QCharAttributes *attributes = engine->attributes();        if (relativePos == 0)            return false;        // skip if already at word start        if (attributes[relativePos - 1].whiteSpace            && !attributes[relativePos].whiteSpace)            return false;        // FALL THROUGH!    }    case QTextCursor::PreviousWord:    case QTextCursor::WordLeft:        newPosition = priv->previousCursorPosition(position, QTextLayout::SkipWords);        break;    case QTextCursor::Up: {        int i = line.lineNumber() - 1;        if (i == -1) {            if (blockIt == priv->blocksBegin())                return false;            int blockPosition = blockIt.position();            QTextTable *table = qobject_cast<QTextTable *>(priv->frameAt(blockPosition));            if (table) {                QTextTableCell cell = table->cellAt(blockPosition);                if (cell.firstPosition() == blockPosition) {                    int row = cell.row() - 1;                    if (row >= 0) {                        blockPosition = table->cellAt(row, cell.column()).lastPosition();                    } else {                        // move to line above the table                        blockPosition = table->firstPosition() - 1;                    }                    blockIt = priv->blocksFind(blockPosition);                } else {                    blockIt = blockIt.previous();                }            } else {                blockIt = blockIt.previous();            }            layout = blockIt.layout();            i = layout->lineCount()-1;        }        if (layout->lineCount()) {            QTextLine line = layout->lineAt(i);            newPosition = line.xToCursor(x) + blockIt.position();        } else {            newPosition = blockIt.position();        }        adjustX = false;        break;    }    case QTextCursor::End:        newPosition = priv->length() - 1;        break;    case QTextCursor::EndOfLine: {        if (!line.isValid() || line.textLength() == 0)            break;        newPosition = blockIt.position() + line.textStart() + line.textLength();        if (line.lineNumber() < layout->lineCount() - 1) {            const QString text = blockIt.text();            // ###### this relies on spaces being the cause for linebreaks.            // this doesn't work with japanese            if (text.at(line.textStart() + line.textLength() - 1).isSpace())                --newPosition;        }        break;    }    case QTextCursor::EndOfWord: {        QTextEngine *engine = layout->engine();        const QCharAttributes *attributes = engine->attributes();        const QString string = engine->layoutData->string;        const int len = layout->engine()->layoutData->string.length();        if (relativePos >= len)            return false;        relativePos++;        while (relativePos < len               && !attributes[relativePos].whiteSpace               && !engine->atWordSeparator(relativePos))            relativePos++;        newPosition = blockIt.position() + relativePos;        break;    }    case QTextCursor::EndOfBlock:        if (blockIt.length() >= 1)            // position right before the block separator            newPosition = blockIt.position() + blockIt.length() - 1;        break;    case QTextCursor::NextBlock: {        blockIt = blockIt.next();        if (!blockIt.isValid())            return false;        newPosition = blockIt.position();        break;    }    case QTextCursor::NextCharacter:    case QTextCursor::Right:        newPosition = priv->nextCursorPosition(position, QTextLayout::SkipCharacters);        break;    case QTextCursor::NextWord:    case QTextCursor::WordRight:        newPosition = priv->nextCursorPosition(position, QTextLayout::SkipWords);        break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -