From 4af30f47c37fd0e6826aca2984dd0f567dc7e465 Mon Sep 17 00:00:00 2001 From: mae Date: Fri, 8 May 2009 16:39:42 +0200 Subject: Fixed unwanted merging of undo commands from different edit blocks With this patch, commands no longer merge across block bounderies. In order to have merging still work for the normal insertion and deletion case, the unnecessary beginEditBlock()/endEditBlock() calls where cleaned up. Reviewed-by: Simon Hausmann --- src/gui/text/qtextcursor.cpp | 25 +++++++++++++++++++------ src/gui/text/qtextdocument_p.cpp | 39 ++++++++++++++++++++++++++------------- src/gui/text/qtextdocument_p.h | 3 ++- 3 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src/gui/text/qtextcursor.cpp b/src/gui/text/qtextcursor.cpp index 48963bb..d12e3fe 100644 --- a/src/gui/text/qtextcursor.cpp +++ b/src/gui/text/qtextcursor.cpp @@ -145,7 +145,6 @@ void QTextCursorPrivate::remove() { if (anchor == position) return; - priv->beginEditBlock(); currentCharFormat = -1; int pos1 = position; int pos2 = adjusted_anchor; @@ -159,15 +158,18 @@ void QTextCursorPrivate::remove() // deleting inside table? -> delete only content QTextTable *table = complexSelectionTable(); if (table) { + priv->beginEditBlock(); int startRow, startCol, numRows, numCols; selectedTableCells(&startRow, &numRows, &startCol, &numCols); clearCells(table, startRow, startCol, numRows, numCols, op); + adjusted_anchor = anchor = position; + priv->endEditBlock(); } else { priv->remove(pos1, pos2-pos1, op); + adjusted_anchor = anchor = position; + priv->finishEdit(); } - adjusted_anchor = anchor = position; - priv->endEditBlock(); } void QTextCursorPrivate::clearCells(QTextTable *table, int startRow, int startCol, int numRows, int numCols, QTextUndoCommand::Operation op) @@ -1291,9 +1293,14 @@ void QTextCursor::insertText(const QString &text, const QTextCharFormat &_format QTextCharFormat format = _format; format.clearProperty(QTextFormat::ObjectIndex); - d->priv->beginEditBlock(); + bool hasEditBlock = false; + + if (d->anchor != d->position) { + hasEditBlock = true; + d->priv->beginEditBlock(); + d->remove(); + } - d->remove(); if (!text.isEmpty()) { QTextFormatCollection *formats = d->priv->formatCollection(); int formatIdx = formats->indexForFormat(format); @@ -1323,6 +1330,11 @@ void QTextCursor::insertText(const QString &text, const QTextCharFormat &_format || ch == QChar::ParagraphSeparator || ch == QLatin1Char('\r')) { + if (!hasEditBlock) { + hasEditBlock = true; + d->priv->beginEditBlock(); + } + if (blockEnd > blockStart) d->priv->insert(d->position, textStart + blockStart, blockEnd - blockStart, formatIdx); @@ -1333,7 +1345,8 @@ void QTextCursor::insertText(const QString &text, const QTextCharFormat &_format if (textStart + blockStart < textEnd) d->priv->insert(d->position, textStart + blockStart, textEnd - textStart - blockStart, formatIdx); } - d->priv->endEditBlock(); + if (hasEditBlock) + d->priv->endEditBlock(); d->setX(); } diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp index 05ddf47..e1da4be 100644 --- a/src/gui/text/qtextdocument_p.cpp +++ b/src/gui/text/qtextdocument_p.cpp @@ -404,7 +404,7 @@ int QTextDocumentPrivate::insertBlock(const QChar &blockSeparator, int b = blocks.findNode(pos); QTextBlockData *B = blocks.fragment(b); - QTextUndoCommand c = { QTextUndoCommand::BlockInserted, true, + QTextUndoCommand c = { QTextUndoCommand::BlockInserted, editBlock != 0, op, charFormat, strPos, pos, { blockFormat }, B->revision }; @@ -439,20 +439,19 @@ void QTextDocumentPrivate::insert(int pos, int strPos, int strLength, int format Q_ASSERT(pos >= 0 && pos < fragments.length()); Q_ASSERT(formats.format(format).isCharFormat()); - beginEditBlock(); insert_string(pos, strPos, strLength, format, QTextUndoCommand::MoveCursor); if (undoEnabled) { int b = blocks.findNode(pos); QTextBlockData *B = blocks.fragment(b); - QTextUndoCommand c = { QTextUndoCommand::Inserted, true, + QTextUndoCommand c = { QTextUndoCommand::Inserted, editBlock != 0, QTextUndoCommand::MoveCursor, format, strPos, pos, { strLength }, B->revision }; appendUndoItem(c); B->revision = undoState; Q_ASSERT(undoState == undoStack.size()); } - endEditBlock(); + finishEdit(); } void QTextDocumentPrivate::insert(int pos, const QString &str, int format) @@ -584,8 +583,6 @@ void QTextDocumentPrivate::move(int pos, int to, int length, QTextUndoCommand::O Q_ASSERT(startAndEndInSameFrame || endIsEndOfChildFrame || startIsStartOfFrameAndEndIsEndOfFrameWithCommonParent || isFirstTableCell); #endif - beginEditBlock(); - split(pos); split(pos+length); @@ -605,10 +602,10 @@ void QTextDocumentPrivate::move(int pos, int to, int length, QTextUndoCommand::O int blockRevision = B->revision; QTextFragmentData *X = fragments.fragment(x); - QTextUndoCommand c = { QTextUndoCommand::Removed, true, + QTextUndoCommand c = { QTextUndoCommand::Removed, editBlock != 0, op, X->format, X->stringPosition, key, { X->size_array[0] }, blockRevision }; - QTextUndoCommand cInsert = { QTextUndoCommand::Inserted, true, + QTextUndoCommand cInsert = { QTextUndoCommand::Inserted, editBlock != 0, op, X->format, X->stringPosition, dstKey, { X->size_array[0] }, blockRevision }; @@ -648,7 +645,7 @@ void QTextDocumentPrivate::move(int pos, int to, int length, QTextUndoCommand::O Q_ASSERT(blocks.length() == fragments.length()); - endEditBlock(); + finishEdit(); } void QTextDocumentPrivate::remove(int pos, int length, QTextUndoCommand::Operation op) @@ -1004,8 +1001,12 @@ void QTextDocumentPrivate::appendUndoItem(const QTextUndoCommand &c) if (!undoStack.isEmpty() && modified) { QTextUndoCommand &last = undoStack[undoState - 1]; - if (last.tryMerge(c)) - return; + if ( (last.block && c.block) // part of the same block => can merge + || (!c.block && !last.block // two single undo items => can merge + && (undoState < 2 || !undoStack[undoState-2].block))) { + if (last.tryMerge(c)) + return; + } } if (modifiedState > undoState) modifiedState = -1; @@ -1013,6 +1014,9 @@ void QTextDocumentPrivate::appendUndoItem(const QTextUndoCommand &c) undoState++; emitUndoAvailable(true); emitRedoAvailable(false); + + if (!c.block) + emit document()->undoCommandAdded(); } void QTextDocumentPrivate::truncateUndoStack() @@ -1082,7 +1086,6 @@ void QTextDocumentPrivate::joinPreviousEditBlock() void QTextDocumentPrivate::endEditBlock() { - Q_Q(QTextDocument); if (--editBlock) return; @@ -1093,6 +1096,16 @@ void QTextDocumentPrivate::endEditBlock() emit document()->undoCommandAdded(); } + finishEdit(); +} + +void QTextDocumentPrivate::finishEdit() +{ + Q_Q(QTextDocument); + + if (editBlock) + return; + if (framesDirty) scan_frames(docChangeFrom, docChangeOldLength, docChangeLength); @@ -1279,7 +1292,7 @@ void QTextDocumentPrivate::changeObjectFormat(QTextObject *obj, int format) if (f) documentChange(f->firstPosition(), f->lastPosition() - f->firstPosition()); - QTextUndoCommand c = { QTextUndoCommand::GroupFormatChange, true, QTextUndoCommand::MoveCursor, oldFormatIndex, + QTextUndoCommand c = { QTextUndoCommand::GroupFormatChange, editBlock != 0, QTextUndoCommand::MoveCursor, oldFormatIndex, 0, 0, { obj->d_func()->objectIndex }, 0 }; appendUndoItem(c); diff --git a/src/gui/text/qtextdocument_p.h b/src/gui/text/qtextdocument_p.h index 25763e1..d754ff0 100644 --- a/src/gui/text/qtextdocument_p.h +++ b/src/gui/text/qtextdocument_p.h @@ -139,7 +139,7 @@ public: MoveCursor = 1 }; quint16 command; - quint8 block; ///< All undo commands that have this set to zero/false are combined with the preceding command on undo/redo. + quint8 block; ///< All undo commands that have this set to true are combined with the preceding command on undo/redo. quint8 operation; int format; quint32 strPos; @@ -202,6 +202,7 @@ public: inline void beginEditBlock() { editBlock++; } void joinPreviousEditBlock(); void endEditBlock(); + void finishEdit(); inline bool isInEditBlock() const { return editBlock; } void enableUndoRedo(bool enable); inline bool isUndoRedoEnabled() const { return undoEnabled; } -- cgit v0.12