📄 qtextdocument_p.cpp
字号:
QTextUndoCommand c = { QTextUndoCommand::BlockInserted, true, op, charFormat, strPos, pos, { blockFormat } }; appendUndoItem(c); Q_ASSERT(undoState == undoStack.size()); if (formats.charFormat(charFormat).objectIndex() == -1) ensureMaximumBlockCount(); endEditBlock(); return fragment;}int QTextDocumentPrivate::insertBlock(int pos, int blockFormat, int charFormat, QTextUndoCommand::Operation op){ return insertBlock(QChar::ParagraphSeparator, pos, blockFormat, charFormat, op);}void QTextDocumentPrivate::insert(int pos, int strPos, int strLength, int format){ if (strLength <= 0) return; Q_ASSERT(pos >= 0 && pos < fragments.length()); Q_ASSERT(formats.format(format).isCharFormat()); insert_string(pos, strPos, strLength, format, QTextUndoCommand::MoveCursor); beginEditBlock(); QTextUndoCommand c = { QTextUndoCommand::Inserted, true, QTextUndoCommand::MoveCursor, format, strPos, pos, { strLength } }; appendUndoItem(c); Q_ASSERT(undoState == undoStack.size()); endEditBlock();}void QTextDocumentPrivate::insert(int pos, const QString &str, int format){ if (str.size() == 0) return; Q_ASSERT(noBlockInString(str)); int strPos = text.length(); text.append(str); insert(pos, strPos, str.length(), format);}int QTextDocumentPrivate::remove_string(int pos, uint length, QTextUndoCommand::Operation op){ Q_ASSERT(pos >= 0); Q_ASSERT(blocks.length() == fragments.length()); Q_ASSERT(blocks.length() >= pos+(int)length); int b = blocks.findNode(pos); uint x = fragments.findNode(pos); Q_ASSERT(blocks.size(b) > length); Q_ASSERT(x && fragments.position(x) == (uint)pos && fragments.size(x) == length); Q_ASSERT(noBlockInString(text.mid(fragments.fragment(x)->stringPosition, length))); blocks.setSize(b, blocks.size(b)-length); QTextFrame *frame = qobject_cast<QTextFrame *>(objectForFormat(fragments.fragment(x)->format)); if (frame) { frame->d_func()->fragmentRemoved(text.at(fragments.fragment(x)->stringPosition), x); framesDirty = true; } const int w = fragments.erase_single(x); if (!undoEnabled) unreachableCharacterCount += length; adjustDocumentChangesAndCursors(pos, -int(length), op); return w;}int QTextDocumentPrivate::remove_block(int pos, int *blockFormat, int command, QTextUndoCommand::Operation op){ Q_ASSERT(pos >= 0); Q_ASSERT(blocks.length() == fragments.length()); Q_ASSERT(blocks.length() > pos); int b = blocks.findNode(pos); uint x = fragments.findNode(pos); Q_ASSERT(x && (int)fragments.position(x) == pos); Q_ASSERT(fragments.size(x) == 1); Q_ASSERT(isValidBlockSeparator(text.at(fragments.fragment(x)->stringPosition))); Q_ASSERT(b); if (blocks.size(b) == 1 && command == QTextUndoCommand::BlockAdded) { Q_ASSERT((int)blocks.position(b) == pos);// qDebug("removing empty block"); // empty block remove the block itself } else { // non empty block, merge with next one into this block// qDebug("merging block with next"); int n = blocks.next(b); Q_ASSERT((int)blocks.position(n) == pos + 1); blocks.setSize(b, blocks.size(b) + blocks.size(n) - 1); b = n; } *blockFormat = blocks.fragment(b)->format; QTextBlockGroup *group = qobject_cast<QTextBlockGroup *>(objectForFormat(blocks.fragment(b)->format)); if (group) group->blockRemoved(QTextBlock(this, b)); QTextFrame *frame = qobject_cast<QTextFrame *>(objectForFormat(fragments.fragment(x)->format)); if (frame) { frame->d_func()->fragmentRemoved(text.at(fragments.fragment(x)->stringPosition), x); framesDirty = true; } blocks.erase_single(b); const int w = fragments.erase_single(x); adjustDocumentChangesAndCursors(pos, -1, op); return w;}#if !defined(QT_NO_DEBUG)static bool isAncestorFrame(QTextFrame *possibleAncestor, QTextFrame *child){ while (child) { if (child == possibleAncestor) return true; child = child->parentFrame(); } return false;}#endifvoid QTextDocumentPrivate::move(int pos, int to, int length, QTextUndoCommand::Operation op){ Q_ASSERT(to <= fragments.length() && to <= pos); Q_ASSERT(pos >= 0 && pos+length <= fragments.length()); Q_ASSERT(blocks.length() == fragments.length()); if (pos == to) return; bool needsInsert = to != -1;#if !defined(QT_NO_DEBUG) const bool startAndEndInSameFrame = (frameAt(pos) == frameAt(pos + length - 1)); const bool endIsEndOfChildFrame = (isAncestorFrame(frameAt(pos), frameAt(pos + length - 1)) && text.at(find(pos + length - 1)->stringPosition) == QTextEndOfFrame); const bool startIsStartOfFrameAndEndIsEndOfFrameWithCommonParent = (text.at(find(pos)->stringPosition) == QTextBeginningOfFrame && text.at(find(pos + length - 1)->stringPosition) == QTextEndOfFrame && frameAt(pos)->parentFrame() == frameAt(pos + length - 1)->parentFrame()); const bool isFirstTableCell = (qobject_cast<QTextTable *>(frameAt(pos + length - 1)) && frameAt(pos + length - 1)->parentFrame() == frameAt(pos)); Q_ASSERT(startAndEndInSameFrame || endIsEndOfChildFrame || startIsStartOfFrameAndEndIsEndOfFrameWithCommonParent || isFirstTableCell);#endif beginEditBlock(); split(pos); split(pos+length); uint dst = needsInsert ? fragments.findNode(to) : 0; uint dstKey = needsInsert ? fragments.position(dst) : 0; uint x = fragments.findNode(pos); uint end = fragments.findNode(pos+length); uint w = 0; while (x != end) { uint n = fragments.next(x); uint key = fragments.position(x); uint b = blocks.findNode(key+1); QTextFragmentData *X = fragments.fragment(x); QTextUndoCommand c = { QTextUndoCommand::Removed, true, op, X->format, X->stringPosition, key, { X->size } }; QTextUndoCommand cInsert = { QTextUndoCommand::Inserted, true, op, X->format, X->stringPosition, dstKey, { X->size } }; if (key+1 != blocks.position(b)) {// qDebug("remove_string from %d length %d", key, X->size); Q_ASSERT(noBlockInString(text.mid(X->stringPosition, X->size))); w = remove_string(key, X->size, op); if (needsInsert) { insert_string(dstKey, X->stringPosition, X->size, X->format, op); dstKey += X->size; } } else {// qDebug("remove_block at %d", key); Q_ASSERT(X->size == 1 && isValidBlockSeparator(text.at(X->stringPosition))); b = blocks.previous(b); c.command = blocks.size(b) == 1 ? QTextUndoCommand::BlockDeleted : QTextUndoCommand::BlockRemoved; w = remove_block(key, &c.blockFormat, QTextUndoCommand::BlockAdded, op); if (needsInsert) { insert_block(dstKey++, X->stringPosition, X->format, c.blockFormat, op, QTextUndoCommand::BlockRemoved); cInsert.command = blocks.size(b) == 1 ? QTextUndoCommand::BlockAdded : QTextUndoCommand::BlockInserted; cInsert.blockFormat = c.blockFormat; } } appendUndoItem(c); x = n; if (needsInsert) appendUndoItem(cInsert); } if (w) unite(w); Q_ASSERT(blocks.length() == fragments.length()); endEditBlock();}void QTextDocumentPrivate::remove(int pos, int length, QTextUndoCommand::Operation op){ move(pos, -1, length, op);}void QTextDocumentPrivate::setCharFormat(int pos, int length, const QTextCharFormat &newFormat, FormatChangeMode mode){ beginEditBlock(); Q_ASSERT(newFormat.isValid()); int newFormatIdx = -1; if (mode == SetFormatAndPreserveObjectIndices) { QTextCharFormat cleanFormat = newFormat; cleanFormat.clearProperty(QTextFormat::ObjectIndex); newFormatIdx = formats.indexForFormat(cleanFormat); } else if (mode == SetFormat) { newFormatIdx = formats.indexForFormat(newFormat); } if (pos == -1) { if (mode == MergeFormat) { QTextFormat format = formats.format(initialBlockCharFormatIndex); format.merge(newFormat); initialBlockCharFormatIndex = formats.indexForFormat(format); } else if (mode == SetFormatAndPreserveObjectIndices && formats.format(initialBlockCharFormatIndex).objectIndex() != -1) { QTextCharFormat f = newFormat; f.setObjectIndex(formats.format(initialBlockCharFormatIndex).objectIndex()); initialBlockCharFormatIndex = formats.indexForFormat(f); } else { initialBlockCharFormatIndex = newFormatIdx; } ++pos; --length; } const int startPos = pos; const int endPos = pos + length; split(startPos); split(endPos); while (pos < endPos) { FragmentMap::Iterator it = fragments.find(pos); Q_ASSERT(!it.atEnd()); QTextFragmentData *fragment = it.value(); Q_ASSERT(formats.format(fragment->format).type() == QTextFormat::CharFormat); int offset = pos - it.position(); int length = qMin(endPos - pos, int(fragment->size - offset)); int oldFormat = fragment->format; if (mode == MergeFormat) { QTextFormat format = formats.format(fragment->format); format.merge(newFormat); fragment->format = formats.indexForFormat(format); } else if (mode == SetFormatAndPreserveObjectIndices && formats.format(oldFormat).objectIndex() != -1) { QTextCharFormat f = newFormat; f.setObjectIndex(formats.format(oldFormat).objectIndex()); fragment->format = formats.indexForFormat(f); } else { fragment->format = newFormatIdx; } QTextUndoCommand c = { QTextUndoCommand::CharFormatChanged, true, QTextUndoCommand::MoveCursor, oldFormat, 0, pos, { length } }; appendUndoItem(c); pos += length; Q_ASSERT(pos == (int)(it.position() + fragment->size) || pos >= endPos); } int n = fragments.findNode(startPos - 1); if (n) unite(n); n = fragments.findNode(endPos); if (n) unite(n); QTextBlock blockIt = blocksFind(startPos); QTextBlock endIt = blocksFind(endPos); if (endIt.isValid()) endIt = endIt.next(); for (; blockIt.isValid() && blockIt != endIt; blockIt = blockIt.next()) QTextDocumentPrivate::block(blockIt)->invalidate(); documentChange(startPos, length); endEditBlock();}void QTextDocumentPrivate::setBlockFormat(const QTextBlock &from, const QTextBlock &to, const QTextBlockFormat &newFormat, FormatChangeMode mode){ beginEditBlock(); Q_ASSERT(mode != SetFormatAndPreserveObjectIndices); // only implemented for setCharFormat Q_ASSERT(newFormat.isValid()); int newFormatIdx = -1; if (mode == SetFormat) newFormatIdx = formats.indexForFormat(newFormat); QTextBlockGroup *group = qobject_cast<QTextBlockGroup *>(objectForFormat(newFormat)); QTextBlock it = from; QTextBlock end = to; if (end.isValid()) end = end.next(); for (; it != end; it = it.next()) { int oldFormat = block(it)->format; QTextBlockFormat format = formats.blockFormat(oldFormat); QTextBlockGroup *oldGroup = qobject_cast<QTextBlockGroup *>(objectForFormat(format)); if (mode == MergeFormat) { format.merge(newFormat); newFormatIdx = formats.indexForFormat(format); group = qobject_cast<QTextBlockGroup *>(objectForFormat(format)); } block(it)->format = newFormatIdx; block(it)->invalidate(); QTextUndoCommand c = { QTextUndoCommand::BlockFormatChanged, true, QTextUndoCommand::MoveCursor, oldFormat, 0, it.position(), { 1 } }; appendUndoItem(c); if (group != oldGroup) { if (oldGroup) oldGroup->blockRemoved(it); if (group) group->blockInserted(it); } else if (group) { group->blockFormatChanged(it); } } documentChange(from.position(), to.position() + to.length() - from.position()); endEditBlock();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -