📄 qtextdocument_p.cpp
字号:
QString QTextDocumentPrivate::plainText() const{ QString result; result.reserve(length()); for (QTextDocumentPrivate::FragmentIterator it = begin(); it != end(); ++it) { const QTextFragmentData *f = *it; result += QString::fromRawData(text.unicode() + f->stringPosition, f->size); } // remove trailing block separator result.chop(1); return result;}int QTextDocumentPrivate::blockCharFormatIndex(int node) const{ int pos = blocks.position(node); if (pos == 0) return initialBlockCharFormatIndex; return fragments.find(pos - 1)->format;}int QTextDocumentPrivate::nextCursorPosition(int position, QTextLayout::CursorMode mode) const{ if (position == length()-1) return position; QTextBlock it = blocksFind(position); int start = it.position(); int end = start + it.length() - 1; if (position == end) return end + 1; return it.layout()->nextCursorPosition(position-start, mode) + start;}int QTextDocumentPrivate::previousCursorPosition(int position, QTextLayout::CursorMode mode) const{ if (position == 0) return position; QTextBlock it = blocksFind(position); int start = it.position(); if (position == start) return start - 1; return it.layout()->previousCursorPosition(position-start, mode) + start;}void QTextDocumentPrivate::changeObjectFormat(QTextObject *obj, int format){ beginEditBlock(); int objectIndex = obj->objectIndex(); int oldFormatIndex = formats.objectFormatIndex(objectIndex); formats.setObjectFormatIndex(objectIndex, format); QTextBlockGroup *b = qobject_cast<QTextBlockGroup *>(obj); if (b) { b->d_func()->markBlocksDirty(); } QTextFrame *f = qobject_cast<QTextFrame *>(obj); if (f) documentChange(f->firstPosition(), f->lastPosition() - f->firstPosition()); QTextUndoCommand c = { QTextUndoCommand::GroupFormatChange, true, QTextUndoCommand::MoveCursor, oldFormatIndex, 0, 0, { obj->d_func()->objectIndex } }; appendUndoItem(c); endEditBlock();}static QTextFrame *findChildFrame(QTextFrame *f, int pos){ // ##### use binary search QList<QTextFrame *> children = f->childFrames(); for (int i = 0; i < children.size(); ++i) { QTextFrame *c = children.at(i); if (pos >= c->firstPosition() && pos <= c->lastPosition()) return c; } return 0;}QTextFrame *QTextDocumentPrivate::rootFrame() const{ if (!rtFrame) { QTextFrameFormat defaultRootFrameFormat; defaultRootFrameFormat.setMargin(DefaultRootFrameMargin); rtFrame = qobject_cast<QTextFrame *>(const_cast<QTextDocumentPrivate *>(this)->createObject(defaultRootFrameFormat)); } return rtFrame;}QTextFrame *QTextDocumentPrivate::frameAt(int pos) const{ QTextFrame *f = rootFrame(); while (1) { QTextFrame *c = findChildFrame(f, pos); if (!c) return f; f = c; }}void QTextDocumentPrivate::clearFrame(QTextFrame *f){ for (int i = 0; i < f->d_func()->childFrames.count(); ++i) clearFrame(f->d_func()->childFrames.at(i)); f->d_func()->childFrames.clear(); f->d_func()->parentFrame = 0;}void QTextDocumentPrivate::scan_frames(int pos, int charsRemoved, int charsAdded){ // ###### optimise Q_UNUSED(pos); Q_UNUSED(charsRemoved); Q_UNUSED(charsAdded); QTextFrame *f = rootFrame(); clearFrame(f); for (FragmentIterator it = begin(); it != end(); ++it) { // QTextFormat fmt = formats.format(it->format); QTextFrame *frame = qobject_cast<QTextFrame *>(objectForFormat(it->format)); if (!frame) continue; Q_ASSERT(it.size() == 1); QChar ch = text.at(it->stringPosition); if (ch == QTextBeginningOfFrame) { if (f != frame) { // f == frame happens for tables Q_ASSERT(frame->d_func()->fragment_start == it.n || frame->d_func()->fragment_start == 0); frame->d_func()->parentFrame = f; f->d_func()->childFrames.append(frame); f = frame; } } else if (ch == QTextEndOfFrame) { Q_ASSERT(f == frame); Q_ASSERT(frame->d_func()->fragment_end == it.n || frame->d_func()->fragment_end == 0); f = frame->d_func()->parentFrame; } else if (ch == QChar::ObjectReplacementCharacter) { Q_ASSERT(f != frame); Q_ASSERT(frame->d_func()->fragment_start == it.n || frame->d_func()->fragment_start == 0); Q_ASSERT(frame->d_func()->fragment_end == it.n || frame->d_func()->fragment_end == 0); frame->d_func()->parentFrame = f; f->d_func()->childFrames.append(frame); } else { Q_ASSERT(false); } } Q_ASSERT(f == rtFrame); framesDirty = false;}void QTextDocumentPrivate::insert_frame(QTextFrame *f){ int start = f->firstPosition(); int end = f->lastPosition(); QTextFrame *parent = frameAt(start-1); Q_ASSERT(parent == frameAt(end+1)); if (start != end) { // iterator over the parent and move all children contained in my frame to myself for (int i = 0; i < parent->d_func()->childFrames.size(); ++i) { QTextFrame *c = parent->d_func()->childFrames.at(i); if (start < c->firstPosition() && end > c->lastPosition()) { parent->d_func()->childFrames.removeAt(i); f->d_func()->childFrames.append(c); c->d_func()->parentFrame = f; } } } // insert at the correct position int i = 0; for (; i < parent->d_func()->childFrames.size(); ++i) { QTextFrame *c = parent->d_func()->childFrames.at(i); if (c->firstPosition() > end) break; } parent->d_func()->childFrames.insert(i, f); f->d_func()->parentFrame = parent;}QTextFrame *QTextDocumentPrivate::insertFrame(int start, int end, const QTextFrameFormat &format){ Q_ASSERT(start >= 0 && start < length()); Q_ASSERT(end >= 0 && end < length()); Q_ASSERT(start <= end || end == -1); if (start != end && frameAt(start) != frameAt(end)) return 0; beginEditBlock(); QTextFrame *frame = qobject_cast<QTextFrame *>(createObject(format)); Q_ASSERT(frame); // #### using the default block and char format below might be wrong int idx = formats.indexForFormat(QTextBlockFormat()); QTextCharFormat cfmt; cfmt.setObjectIndex(frame->objectIndex()); int charIdx = formats.indexForFormat(cfmt); insertBlock(QTextBeginningOfFrame, start, idx, charIdx, QTextUndoCommand::MoveCursor); insertBlock(QTextEndOfFrame, ++end, idx, charIdx, QTextUndoCommand::KeepCursor); frame->d_func()->fragment_start = find(start).n; frame->d_func()->fragment_end = find(end).n; insert_frame(frame); endEditBlock(); return frame;}void QTextDocumentPrivate::removeFrame(QTextFrame *frame){ QTextFrame *parent = frame->d_func()->parentFrame; if (!parent) return; int start = frame->firstPosition(); int end = frame->lastPosition(); Q_ASSERT(end >= start); beginEditBlock(); // remove already removes the frames from the tree remove(end, 1); remove(start-1, 1); endEditBlock();}QTextObject *QTextDocumentPrivate::objectForIndex(int objectIndex) const{ if (objectIndex < 0) return 0; QTextObject *object = objects.value(objectIndex, 0); if (!object) { QTextDocumentPrivate *that = const_cast<QTextDocumentPrivate *>(this); QTextFormat fmt = formats.objectFormat(objectIndex); object = that->createObject(fmt, objectIndex); } return object;}QTextObject *QTextDocumentPrivate::objectForFormat(int formatIndex) const{ int objectIndex = formats.format(formatIndex).objectIndex(); return objectForIndex(objectIndex);}QTextObject *QTextDocumentPrivate::objectForFormat(const QTextFormat &f) const{ return objectForIndex(f.objectIndex());}QTextObject *QTextDocumentPrivate::createObject(const QTextFormat &f, int objectIndex){ QTextObject *obj = document()->createObject(f); if (obj) { obj->d_func()->pieceTable = this; obj->d_func()->objectIndex = objectIndex == -1 ? formats.createObjectIndex(f) : objectIndex; objects[obj->d_func()->objectIndex] = obj; } return obj;}void QTextDocumentPrivate::deleteObject(QTextObject *object){ const int objIdx = object->d_func()->objectIndex; objects.remove(objIdx); delete object;}void QTextDocumentPrivate::contentsChanged(){ Q_Q(QTextDocument); if (editBlock) return; bool m = undoEnabled ? (modifiedState != undoState) : true; if (modified != m) { modified = m; emit q->modificationChanged(modified); } emit q->contentsChanged();}void QTextDocumentPrivate::compressPieceTable(){ if (undoEnabled) return; const uint garbageCollectionThreshold = 96 * 1024; // bytes //qDebug() << "unreachable bytes:" << unreachableCharacterCount * sizeof(QChar) << " -- limit" << garbageCollectionThreshold << "text size =" << text.size() << "capacity:" << text.capacity(); bool compressTable = unreachableCharacterCount * sizeof(QChar) > garbageCollectionThreshold && text.size() >= text.capacity() * 0.9; if (!compressTable) return; QString newText; newText.resize(text.size()); QChar *newTextPtr = newText.data(); int newLen = 0; for (FragmentMap::Iterator it = fragments.begin(); !it.atEnd(); ++it) { qMemCopy(newTextPtr, text.constData() + it->stringPosition, it->size * sizeof(QChar)); it->stringPosition = newLen; newTextPtr += it->size; newLen += it->size; } newText.resize(newLen); newText.squeeze(); //qDebug() << "removed" << text.size() - newText.size() << "characters"; text = newText; unreachableCharacterCount = 0;}void QTextDocumentPrivate::setModified(bool m){ Q_Q(QTextDocument); if (m == modified) return; modified = m; if (!modified) modifiedState = undoState; else modifiedState = -1; emit q->modificationChanged(modified);}void QTextDocumentPrivate::ensureMaximumBlockCount(){ if (maximumBlockCount <= 0) return; if (blocks.numNodes() <= maximumBlockCount) return; beginEditBlock(); const int blocksToRemove = blocks.numNodes() - maximumBlockCount; QTextCursor cursor(this, 0); cursor.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor, blocksToRemove); unreachableCharacterCount += cursor.selectionEnd() - cursor.selectionStart(); // preserve the char format of the paragraph that is to become the new first one QTextCharFormat charFmt = cursor.blockCharFormat(); cursor.removeSelectedText(); cursor.setBlockCharFormat(charFmt); endEditBlock(); compressPieceTable();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -