📄 qtextdocumentfragment.cpp
字号:
/******************************************************************************** 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 "qtextdocumentfragment.h"#include "qtextdocumentfragment_p.h"#include "qtextcursor_p.h"#include "qtextlist.h"#include "private/qunicodetables_p.h"#include <qdebug.h>#include <qtextcodec.h>#include <qbytearray.h>#include <qdatastream.h>#include <qdatetime.h>QTextCopyHelper::QTextCopyHelper(const QTextCursor &_source, const QTextCursor &_destination, bool forceCharFormat, const QTextCharFormat &fmt) : formatCollection(*_destination.d->priv->formatCollection()), originalText(_source.d->priv->buffer()){ src = _source.d->priv; dst = _destination.d->priv; insertPos = _destination.position(); this->forceCharFormat = forceCharFormat; primaryCharFormatIndex = convertFormatIndex(fmt); cursor = _source;}int QTextCopyHelper::convertFormatIndex(const QTextFormat &oldFormat, int objectIndexToSet){ QTextFormat fmt = oldFormat; if (objectIndexToSet != -1) { fmt.setObjectIndex(objectIndexToSet); } else if (fmt.objectIndex() != -1) { int newObjectIndex = objectIndexMap.value(fmt.objectIndex(), -1); if (newObjectIndex == -1) { QTextFormat objFormat = src->formatCollection()->objectFormat(fmt.objectIndex()); Q_ASSERT(objFormat.objectIndex() == -1); newObjectIndex = formatCollection.createObjectIndex(objFormat); objectIndexMap.insert(fmt.objectIndex(), newObjectIndex); } fmt.setObjectIndex(newObjectIndex); } int idx = formatCollection.indexForFormat(fmt); Q_ASSERT(formatCollection.format(idx).type() == oldFormat.type()); return idx;}int QTextCopyHelper::appendFragment(int pos, int endPos, int objectIndex){ QTextDocumentPrivate::FragmentIterator fragIt = src->find(pos); const QTextFragmentData * const frag = fragIt.value(); Q_ASSERT(objectIndex == -1 || (frag->size == 1 && src->formatCollection()->format(frag->format).objectIndex() != -1)); int charFormatIndex; if (forceCharFormat) charFormatIndex = primaryCharFormatIndex; else charFormatIndex = convertFormatIndex(frag->format, objectIndex); const int inFragmentOffset = qMax(0, pos - fragIt.position()); int charsToCopy = qMin(int(frag->size - inFragmentOffset), endPos - pos); QTextBlock nextBlock = src->blocksFind(pos + 1); int blockIdx = -2; if (nextBlock.position() == pos + 1) { blockIdx = convertFormatIndex(nextBlock.blockFormat()); } else if (pos == 0 && insertPos == 0) { dst->setBlockFormat(dst->blocksBegin(), dst->blocksBegin(), convertFormat(src->blocksBegin().blockFormat()).toBlockFormat()); dst->setCharFormat(-1, 1, convertFormat(src->blocksBegin().charFormat()).toCharFormat()); } QString txtToInsert(originalText.constData() + frag->stringPosition + inFragmentOffset, charsToCopy); if (txtToInsert.length() == 1 && (txtToInsert.at(0) == QChar::ParagraphSeparator || txtToInsert.at(0) == QTextBeginningOfFrame || txtToInsert.at(0) == QTextEndOfFrame ) ) { dst->insertBlock(txtToInsert.at(0), insertPos, blockIdx, charFormatIndex); ++insertPos; } else { if (nextBlock.textList()) { QTextBlock dstBlock = dst->blocksFind(insertPos); if (!dstBlock.textList()) { blockIdx = convertFormatIndex(nextBlock.blockFormat()); dst->insertBlock(insertPos, blockIdx, charFormatIndex); ++insertPos; } } dst->insert(insertPos, txtToInsert, charFormatIndex); const int userState = nextBlock.userState(); if (userState != -1) dst->blocksFind(insertPos).setUserState(userState); insertPos += txtToInsert.length(); } return charsToCopy;}void QTextCopyHelper::appendFragments(int pos, int endPos){ Q_ASSERT(pos < endPos); while (pos < endPos) pos += appendFragment(pos, endPos);}void QTextCopyHelper::copy(){ if (cursor.hasComplexSelection()) { QTextTable *table = cursor.currentTable(); int row_start, col_start, num_rows, num_cols; cursor.selectedTableCells(&row_start, &num_rows, &col_start, &num_cols); QTextTableFormat tableFormat = table->format(); tableFormat.setColumns(num_cols); tableFormat.clearColumnWidthConstraints(); const int objectIndex = dst->formatCollection()->createObjectIndex(tableFormat); Q_ASSERT(row_start != -1); for (int r = row_start; r < row_start + num_rows; ++r) { for (int c = col_start; c < col_start + num_cols; ++c) { QTextTableCell cell = table->cellAt(r, c); const int rspan = cell.rowSpan(); const int cspan = cell.columnSpan(); if (rspan != 1) { int cr = cell.row(); if (cr != r) continue; } if (cspan != 1) { int cc = cell.column(); if (cc != c) continue; } // add the QTextBeginningOfFrame QTextCharFormat cellFormat = cell.format(); if (r + rspan >= row_start + num_rows) { cellFormat.setTableCellRowSpan(row_start + num_rows - r); } if (c + cspan >= col_start + num_cols) { cellFormat.setTableCellColumnSpan(col_start + num_cols - c); } const int charFormatIndex = convertFormatIndex(cellFormat, objectIndex); int blockIdx = -2; const int cellPos = cell.firstPosition(); QTextBlock block = src->blocksFind(cellPos); if (block.position() == cellPos) { blockIdx = convertFormatIndex(block.blockFormat()); } dst->insertBlock(QTextBeginningOfFrame, insertPos, blockIdx, charFormatIndex); ++insertPos; // nothing to add for empty cells if (cell.lastPosition() > cellPos) { // add the contents appendFragments(cellPos, cell.lastPosition()); } } } // add end of table int end = table->lastPosition(); appendFragment(end, end+1, objectIndex); } else { appendFragments(cursor.selectionStart(), cursor.selectionEnd()); }}QTextDocumentFragmentPrivate::QTextDocumentFragmentPrivate(const QTextCursor &_cursor) : ref(1), doc(new QTextDocument), importedFromPlainText(false){ doc->setUndoRedoEnabled(false); if (!_cursor.hasSelection()) return; doc->docHandle()->beginEditBlock(); QTextCursor destCursor(doc); QTextCopyHelper(_cursor, destCursor).copy(); doc->docHandle()->endEditBlock();}void QTextDocumentFragmentPrivate::insert(QTextCursor &_cursor) const{ if (_cursor.isNull()) return; QTextDocumentPrivate *destPieceTable = _cursor.d->priv; destPieceTable->beginEditBlock(); QTextCursor sourceCursor(doc); sourceCursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor); QTextCopyHelper(sourceCursor, _cursor, importedFromPlainText, _cursor.charFormat()).copy(); destPieceTable->endEditBlock();}/*! \class QTextDocumentFragment \brief The QTextDocumentFragment class represents a piece of formatted text from a QTextDocument. \ingroup text \ingroup shared A QTextDocumentFragment is a fragment of rich text, that can be inserted into a QTextDocument. A document fragment can be created from a QTextDocument, from a QTextCursor's selection, or from another document fragment. Document fragments can also be created by the static functions, fromPlainText() and fromHtml(). The contents of a document fragment can be obtained as plain text by using the toPlainText() function, or it can be obtained as HTML with toHtml().*//*! Constructs an empty QTextDocumentFragment. \sa isEmpty()*/QTextDocumentFragment::QTextDocumentFragment() : d(0){}/*! Converts the given \a document into a QTextDocumentFragment. Note that the QTextDocumentFragment only stores the document contents, not meta information like the document's title.*/QTextDocumentFragment::QTextDocumentFragment(const QTextDocument *document) : d(0){ if (!document) return; QTextCursor cursor(const_cast<QTextDocument *>(document)); cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor); d = new QTextDocumentFragmentPrivate(cursor);}/*! Creates a QTextDocumentFragment from the \a{cursor}'s selection. If the cursor doesn't have a selection, the created fragment is empty. \sa isEmpty() QTextCursor::selection()*/QTextDocumentFragment::QTextDocumentFragment(const QTextCursor &cursor) : d(0){ if (!cursor.hasSelection()) return; d = new QTextDocumentFragmentPrivate(cursor);}/*! \fn QTextDocumentFragment::QTextDocumentFragment(const QTextDocumentFragment &other) Copy constructor. Creates a copy of the \a other fragment.*/QTextDocumentFragment::QTextDocumentFragment(const QTextDocumentFragment &rhs) : d(rhs.d){ if (d) d->ref.ref();}/*! \fn QTextDocumentFragment &QTextDocumentFragment::operator=(const QTextDocumentFragment &other) Assigns the \a other fragment to this fragment.*/QTextDocumentFragment &QTextDocumentFragment::operator=(const QTextDocumentFragment &rhs){ QTextDocumentFragmentPrivate *x = rhs.d; if (x) x->ref.ref(); x = qAtomicSetPtr(&d, x); if (x && !x->ref.deref()) delete x; return *this;}/*! Destroys the document fragment.*/QTextDocumentFragment::~QTextDocumentFragment(){ if (d && !d->ref.deref()) delete d;}/*! Returns true if the fragment is empty; otherwise returns false.*/bool QTextDocumentFragment::isEmpty() const{ return !d || !d->doc || d->doc->docHandle()->length() <= 1;}/*! Returns the document fragment's text as plain text (i.e. with no formatting information). \sa toHtml()*/QString QTextDocumentFragment::toPlainText() const{ if (!d) return QString(); return d->doc->toPlainText();}// #### Qt 5: merge with other overload/*! \overload*/QString QTextDocumentFragment::toHtml() const{ return toHtml(QByteArray());}/*! \since 4.2 Returns the contents of the document fragment as HTML, using the specified \a encoding (e.g., "UTF-8", "ISO 8859-1"). \sa toPlainText(), QTextDocument::toHtml(), QTextCodec*/QString QTextDocumentFragment::toHtml(const QByteArray &encoding) const{ if (!d) return QString(); return QTextHtmlExporter(d->doc).toHtml(encoding, QTextHtmlExporter::ExportFragment);}/*! Returns a document fragment that contains the given \a plainText.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -