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

📄 qtextdocument_p.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/******************************************************************************** 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 <private/qtools_p.h>#include <qdebug.h>#include "qtextdocument_p.h"#include "qtextdocument.h"#include <qtextformat.h>#include "qtextformat_p.h"#include "qtextobject_p.h"#include "qtextcursor.h"#include "qtextimagehandler_p.h"#include "qtextcursor_p.h"#include "qtextdocumentlayout_p.h"#include "qtexttable.h"#include "qtextengine_p.h"#include <stdlib.h>#define PMDEBUG if(0) qDebug/*  Structure of a document:  DOCUMENT :== FRAME_CONTENTS  FRAME :== START_OF_FRAME  FRAME_CONTENTS END_OF_FRAME  FRAME_CONTENTS = LIST_OF_BLOCKS ((FRAME | TABLE) LIST_OF_BLOCKS)*  TABLE :== (START_OF_FRAME TABLE_CELL)+ END_OF_FRAME  TABLE_CELL = FRAME_CONTENTS  LIST_OF_BLOCKS :== (BLOCK END_OF_PARA)* BLOCK  BLOCK :== (FRAGMENT)*  FRAGMENT :== String of characters  END_OF_PARA :== 0x2029 # Paragraph separator in Unicode  START_OF_FRAME :== 0xfdd0  END_OF_FRAME := 0xfdd1  Note also that LIST_OF_BLOCKS can be empty. Nevertheless, there is  at least one valid cursor position there where you could start  typing. The block format is in this case determined by the last  END_OF_PARA/START_OF_FRAME/END_OF_FRAME (see below).  Lists are not in here, as they are treated specially. A list is just  a collection of (not neccessarily connected) blocks, that share the  same objectIndex() in the format that refers to the list format and  object.  The above does not clearly note where formats are. Here's  how it looks currently:  FRAGMENT: one charFormat associated  END_OF_PARA: one charFormat, and a blockFormat for the _next_ block.  START_OF_FRAME: one char format, and a blockFormat (for the next  block). The format associated with the objectIndex() of the  charFormat decides whether this is a frame or table and it's  properties  END_OF_FRAME: one charFormat and a blockFormat (for the next  block). The object() of the charFormat is the same as for the  corresponding START_OF_BLOCK.  The document is independent of the layout with certain restrictions:  * Cursor movement (esp. up and down) depend on the layout.  * You cannot have more than one layout, as the layout data of QTextObjects    is stored in the text object itself.*/void QTextBlockData::invalidate() const{    if (layout)        layout->engine()->invalidate();}static bool isValidBlockSeparator(const QChar &ch){    return ch == QChar::ParagraphSeparator        || ch == QTextBeginningOfFrame        || ch == QTextEndOfFrame;}#ifndef QT_NO_DEBUGstatic bool noBlockInString(const QString &str){    return !str.contains(QChar::ParagraphSeparator)        && !str.contains(QTextBeginningOfFrame)        && !str.contains(QTextEndOfFrame);}#endifbool QTextUndoCommand::tryMerge(const QTextUndoCommand &other){    if (command != other.command)        return false;    if (command == Inserted        && (pos + length == other.pos)        && (strPos + length == other.strPos)        && format == other.format) {        length += other.length;        return true;    }    // removal to the 'right' using 'Delete' key    if (command == Removed        && pos == other.pos        && (strPos + length == other.strPos)        && format == other.format) {        length += other.length;        return true;    }    // removal to the 'left' using 'Backspace'    if (command == Removed        && (other.pos + other.length == pos)        && (other.strPos + other.length == strPos)        && (format == other.format)) {        int l = length;        (*this) = other;        length += l;        return true;    }    return false;}QTextDocumentPrivate::QTextDocumentPrivate()    : wasUndoAvailable(false)    , wasRedoAvailable(false){    editBlock = 0;    docChangeFrom = -1;    undoState = 0;    lout = 0;    modified = false;    modifiedState = 0;    undoEnabled = true;    inContentsChange = false;    defaultTextOption.setTabStop(80); // same as in qtextengine.cpp    defaultTextOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);    maximumBlockCount = 0;    unreachableCharacterCount = 0;    lastBlockCount = 0;}void QTextDocumentPrivate::init(){    rtFrame = 0;    framesDirty = false;    bool undoState = undoEnabled;    undoEnabled = false;    initialBlockCharFormatIndex = formats.indexForFormat(QTextCharFormat());    insertBlock(0, formats.indexForFormat(QTextBlockFormat()), formats.indexForFormat(QTextCharFormat()));    undoEnabled = undoState;    modified = false;    modifiedState = 0;    lastBlockCount = blocks.numNodes();}void QTextDocumentPrivate::clear(){    Q_Q(QTextDocument);    for (int i = 0; i < cursors.count(); ++i) {        cursors.at(i)->setPosition(0);        cursors.at(i)->anchor = 0;    }    QList<QTextCursorPrivate *>oldCursors = cursors;    cursors.clear();    changedCursors.clear();    QMap<int, QTextObject *>::Iterator objectIt = objects.begin();    while (objectIt != objects.end()) {        if (*objectIt != rtFrame) {            delete *objectIt;            objectIt = objects.erase(objectIt);        } else {            ++objectIt;        }    }    // also clear out the remaining root frame pointer    // (we're going to delete the object further down)    objects.clear();    title.clear();    undoState = 0;    truncateUndoStack();    text = QString();    unreachableCharacterCount = 0;    modifiedState = 0;    modified = false;    formats = QTextFormatCollection();    int len = fragments.length();    fragments.clear();    blocks.clear();    cachedResources.clear();    delete rtFrame;    init();    cursors = oldCursors;    inContentsChange = true;    q->contentsChange(0, len, 0);    inContentsChange = false;    if (lout)        lout->documentChanged(0, len, 0);}QTextDocumentPrivate::~QTextDocumentPrivate(){    for (int i = 0; i < cursors.count(); ++i)        cursors.at(i)->priv = 0;    cursors.clear();    undoState = 0;    undoEnabled = true;    truncateUndoStack();}void QTextDocumentPrivate::setLayout(QAbstractTextDocumentLayout *layout){    Q_Q(QTextDocument);    if (lout == layout)        return;    const bool firstLayout = !lout;    delete lout;    lout = layout;    if (!firstLayout)        for (BlockMap::Iterator it = blocks.begin(); !it.atEnd(); ++it)            it->free();    inContentsChange = true;    emit q->contentsChange(0, 0, length());    inContentsChange = false;    if (lout)        lout->documentChanged(0, 0, length());}void QTextDocumentPrivate::insert_string(int pos, uint strPos, uint length, int format, QTextUndoCommand::Operation op){    // ##### optimise when only appending to the fragment!    Q_ASSERT(noBlockInString(text.mid(strPos, length)));    split(pos);    uint x = fragments.insert_single(pos, length);    QTextFragmentData *X = fragments.fragment(x);    X->format = format;    X->stringPosition = strPos;    uint w = fragments.previous(x);    if (w)        unite(w);    int b = blocks.findNode(pos);    blocks.setSize(b, blocks.size(b)+length);    Q_ASSERT(blocks.length() == fragments.length());    QTextFrame *frame = qobject_cast<QTextFrame *>(objectForFormat(format));    if (frame) {        frame->d_func()->fragmentAdded(text.at(strPos), x);        framesDirty = true;    }    adjustDocumentChangesAndCursors(pos, length, op);}int QTextDocumentPrivate::insert_block(int pos, uint strPos, int format, int blockFormat, QTextUndoCommand::Operation op, int command){    split(pos);    uint x = fragments.insert_single(pos, 1);    QTextFragmentData *X = fragments.fragment(x);    X->format = format;    X->stringPosition = strPos;    // no need trying to unite, since paragraph separators are always in a fragment of their own    Q_ASSERT(isValidBlockSeparator(text.at(strPos)));    Q_ASSERT(blocks.length()+1 == fragments.length());    int block_pos = pos;    if (blocks.length() && command == QTextUndoCommand::BlockRemoved)        ++block_pos;    int size = 1;    int n = blocks.findNode(block_pos);    int key = n ? blocks.position(n) : blocks.length();    Q_ASSERT(n || (!n && block_pos == blocks.length()));    if (key != block_pos) {        Q_ASSERT(key < block_pos);        int oldSize = blocks.size(n);        blocks.setSize(n, block_pos-key);        size += oldSize - (block_pos-key);    }    int b = blocks.insert_single(block_pos, size);    QTextBlockData *B = blocks.fragment(b);    B->format = blockFormat;    Q_ASSERT(blocks.length() == fragments.length());    QTextBlockGroup *group = qobject_cast<QTextBlockGroup *>(objectForFormat(blockFormat));    if (group)        group->blockInserted(QTextBlock(this, b));    QTextFrame *frame = qobject_cast<QTextFrame *>(objectForFormat(formats.format(format)));    if (frame) {        frame->d_func()->fragmentAdded(text.at(strPos), x);        framesDirty = true;    }    adjustDocumentChangesAndCursors(pos, 1, op);    return x;}int QTextDocumentPrivate::insertBlock(const QChar &blockSeparator,                                  int pos, int blockFormat, int charFormat, QTextUndoCommand::Operation op){    Q_ASSERT(formats.format(blockFormat).isBlockFormat());    Q_ASSERT(formats.format(charFormat).isCharFormat());    Q_ASSERT(pos >= 0 && (pos < fragments.length() || (pos == 0 && fragments.length() == 0)));    Q_ASSERT(isValidBlockSeparator(blockSeparator));    beginEditBlock();    int strPos = text.length();    text.append(blockSeparator);    const int fragment = insert_block(pos, strPos, charFormat, blockFormat, op, QTextUndoCommand::BlockRemoved);    Q_ASSERT(blocks.length() == fragments.length());

⌨️ 快捷键说明

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