diff options
-rw-r--r-- | src/widgets/util/qundostack.cpp | 156 | ||||
-rw-r--r-- | src/widgets/util/qundostack.h | 3 | ||||
-rw-r--r-- | src/widgets/util/qundostack_p.h | 3 | ||||
-rw-r--r-- | tests/auto/widgets/util/qundostack/tst_qundostack.cpp | 765 |
4 files changed, 912 insertions, 15 deletions
diff --git a/src/widgets/util/qundostack.cpp b/src/widgets/util/qundostack.cpp index 59d517e77b..cfca5787cb 100644 --- a/src/widgets/util/qundostack.cpp +++ b/src/widgets/util/qundostack.cpp @@ -145,6 +145,36 @@ QUndoCommand::~QUndoCommand() } /*! + \since 5.9 + + Returns whether the command is obsolete. + + The boolean is used for the automatic removal of commands that are not necessary in the + stack anymore. The isObsolete function is checked in the functions QUndoStack::push(), + QUndoStack::undo(), QUndoStack::redo(), and QUndoStack::setIndex(). + + \sa setObsolete(), mergeWith(), QUndoStack::push(), QUndoStack::undo(), QUndoStack::redo() +*/ + +bool QUndoCommand::isObsolete() const +{ + return d->obsolete; +} + +/*! + \since 5.9 + + Sets whether the command is obsolete. + + \sa isObsolete(), mergeWith(), QUndoStack::push(), QUndoStack::undo(), QUndoStack::redo() +*/ + +void QUndoCommand::setObsolete(bool obsolete) +{ + d->obsolete = obsolete; +} + +/*! Returns the ID of this command. A command ID is used in command compression. It must be an integer unique to @@ -390,6 +420,28 @@ const QUndoCommand *QUndoCommand::child(int index) const and to update the document's title to reflect that it contains unsaved changes. + \section1 Obsolete Commands + + QUndoStack is able to delete commands from the stack if the command is no + longer needed. One example may be to delete a command when two commands are + merged together in such a way that the merged command has no function. This + can be seen with move commands where the user moves their mouse to one part + of the screen and then moves it to the original position. The merged command + results in a mouse movement of 0. This command can be deleted since it serves + no purpose. Another example is with networking commands that fail due to connection + issues. In this case, the command is to be removed from the stack because the redo() + and undo() functions have no function since there was connection issues. + + A command can be marked obsolete with the QUndoCommand::setObsolete() function. + The QUndoCommand::isObsolete() flag is checked in QUndoStack::push(), + QUndoStack::undo(), QUndoStack::redo(), and QUndoStack::setIndex() after calling + QUndoCommand::undo(), QUndoCommand::redo() and QUndoCommand:mergeWith() where + applicable. + + If a command is set obsolete and the clean index is greater than or equal to the + current command index, then the clean index will be reset when the command is + deleted from the stack. + \sa QUndoCommand, QUndoView */ @@ -563,6 +615,11 @@ void QUndoStack::clear() commands by calling QUndoCommand::mergeWith() on the most recently executed command. If QUndoCommand::mergeWith() returns \c true, \a cmd is deleted. + After calling QUndoCommand::redo() and, if applicable, QUndoCommand::mergeWith(), + QUndoCommand::isObsolete() will be called for \a cmd or the merged command. + If QUndoCommand::isObsolete() returns \c true, then \a cmd or the merged command + will be deleted from the stack. + In all other cases \a cmd is simply pushed on the stack. If commands were undone before \a cmd was pushed, the current command and @@ -580,7 +637,8 @@ void QUndoStack::clear() void QUndoStack::push(QUndoCommand *cmd) { Q_D(QUndoStack); - cmd->redo(); + if (!cmd->isObsolete()) + cmd->redo(); bool macro = !d->macro_stack.isEmpty(); @@ -605,13 +663,25 @@ void QUndoStack::push(QUndoCommand *cmd) if (try_merge && cur->mergeWith(cmd)) { delete cmd; - if (!macro) { - emit indexChanged(d->index); - emit canUndoChanged(canUndo()); - emit undoTextChanged(undoText()); - emit canRedoChanged(canRedo()); - emit redoTextChanged(redoText()); + + if (macro) { + if (cur->isObsolete()) + delete d->macro_stack.constLast()->d->child_list.takeLast(); + } else { + if (cur->isObsolete()) { + delete d->command_list.takeLast(); + + d->setIndex(d->index - 1, false); + } else { + emit indexChanged(d->index); + emit canUndoChanged(canUndo()); + emit undoTextChanged(undoText()); + emit canRedoChanged(canRedo()); + emit redoTextChanged(redoText()); + } } + } else if (cmd->isObsolete()) { + delete cmd; // command should be deleted and NOT added to the stack } else { if (macro) { d->macro_stack.constLast()->d->child_list.append(cmd); @@ -710,6 +780,11 @@ int QUndoStack::cleanIndex() const If the stack is empty, or if the bottom command on the stack has already been undone, this function does nothing. + After the command is undone, if QUndoCommand::isObsolete() returns \c true, + then the command will be deleted from the stack. Additionally, if the clean + index is greater than or equal to the current command index, then the clean + index is reset. + \sa redo(), index() */ @@ -725,7 +800,18 @@ void QUndoStack::undo() } int idx = d->index - 1; - d->command_list.at(idx)->undo(); + QUndoCommand *cmd = d->command_list.at(idx); + + if (!cmd->isObsolete()) + cmd->undo(); + + if (cmd->isObsolete()) { // A separate check is done b/c the undo command may set obsolete flag + delete d->command_list.takeAt(idx); + + if (d->clean_index > idx) + resetClean(); + } + d->setIndex(idx, false); } @@ -736,6 +822,11 @@ void QUndoStack::undo() If the stack is empty, or if the top command on the stack has already been redone, this function does nothing. + If QUndoCommand::isObsolete() returns true for the current command, then + the command will be deleted from the stack. Additionally, if the clean + index is greater than or equal to the current command index, then the clean + index is reset. + \sa undo(), index() */ @@ -750,8 +841,20 @@ void QUndoStack::redo() return; } - d->command_list.at(d->index)->redo(); - d->setIndex(d->index + 1, false); + int idx = d->index; + QUndoCommand *cmd = d->command_list.at(idx); + + if (!cmd->isObsolete()) + cmd->redo(); // A separate check is done b/c the undo command may set obsolete flag + + if (cmd->isObsolete()) { + delete d->command_list.takeAt(idx); + + if (d->clean_index > idx) + resetClean(); + } else { + d->setIndex(d->index + 1, false); + } } /*! @@ -803,10 +906,35 @@ void QUndoStack::setIndex(int idx) idx = d->command_list.size(); int i = d->index; - while (i < idx) - d->command_list.at(i++)->redo(); - while (i > idx) - d->command_list.at(--i)->undo(); + while (i < idx) { + QUndoCommand *cmd = d->command_list.at(i); + + if (!cmd->isObsolete()) + cmd->redo(); // A separate check is done b/c the undo command may set obsolete flag + + if (cmd->isObsolete()) { + delete d->command_list.takeAt(i); + + if (d->clean_index > i) + resetClean(); + + idx--; // Subtract from idx because we removed a command + } else { + i++; + } + } + + while (i > idx) { + QUndoCommand *cmd = d->command_list.at(--i); + + cmd->undo(); + if (cmd->isObsolete()) { + delete d->command_list.takeAt(i); + + if (d->clean_index > i) + resetClean(); + } + } d->setIndex(idx, false); } diff --git a/src/widgets/util/qundostack.h b/src/widgets/util/qundostack.h index ca918b0618..2a8f4decb6 100644 --- a/src/widgets/util/qundostack.h +++ b/src/widgets/util/qundostack.h @@ -69,6 +69,9 @@ public: QString actionText() const; void setText(const QString &text); + bool isObsolete() const; + void setObsolete(bool obsolete); + virtual int id() const; virtual bool mergeWith(const QUndoCommand *other); diff --git a/src/widgets/util/qundostack_p.h b/src/widgets/util/qundostack_p.h index 1bfe992426..e92a1fe620 100644 --- a/src/widgets/util/qundostack_p.h +++ b/src/widgets/util/qundostack_p.h @@ -66,11 +66,12 @@ class QUndoGroup; class QUndoCommandPrivate { public: - QUndoCommandPrivate() : id(-1) {} + QUndoCommandPrivate() : id(-1), obsolete(false) {} QList<QUndoCommand*> child_list; QString text; QString actionText; int id; + bool obsolete; }; #ifndef QT_NO_UNDOSTACK diff --git a/tests/auto/widgets/util/qundostack/tst_qundostack.cpp b/tests/auto/widgets/util/qundostack/tst_qundostack.cpp index 8576e237ec..11a29b808c 100644 --- a/tests/auto/widgets/util/qundostack/tst_qundostack.cpp +++ b/tests/auto/widgets/util/qundostack/tst_qundostack.cpp @@ -95,6 +95,23 @@ public: virtual void redo(); }; +class MoveMouseCommand : public QUndoCommand +{ +public: + MoveMouseCommand(QPoint *mouse, QPoint oldPoint, QPoint newPoint, QUndoCommand *parent = 0); + ~MoveMouseCommand(); + + virtual void undo(); + virtual void redo(); + virtual int id() const; + virtual bool mergeWith(const QUndoCommand *other); + +private: + QPoint *m_mouse; + QPoint m_oldPoint; + QPoint m_newPoint; +}; + InsertCommand::InsertCommand(QString *str, int idx, const QString &text, QUndoCommand *parent) : QUndoCommand(parent) @@ -215,6 +232,48 @@ void IdleCommand::undo() { } +MoveMouseCommand::MoveMouseCommand(QPoint *mouse, QPoint oldPoint, QPoint newPoint, QUndoCommand *parent) + : QUndoCommand(parent) +{ + setText("move mouse"); + + m_mouse = mouse; + m_oldPoint = oldPoint; + m_newPoint = newPoint; + + if (m_oldPoint == m_newPoint) + setObsolete(true); +} + +MoveMouseCommand::~MoveMouseCommand() +{ +} + +void MoveMouseCommand::redo() +{ + *m_mouse = m_newPoint; +} + +void MoveMouseCommand::undo() +{ + *m_mouse = m_oldPoint; +} + +int MoveMouseCommand::id() const +{ + return 2; +} + +bool MoveMouseCommand::mergeWith(const QUndoCommand *other) +{ + m_newPoint = static_cast<const MoveMouseCommand*>(other)->m_newPoint; + + if (m_newPoint == m_oldPoint) + setObsolete(true); + + return true; +} + /****************************************************************************** ** tst_QUndoStack */ @@ -233,6 +292,7 @@ private slots: void childCommand(); void macroBeginEnd(); void compression(); + void obsolete(); void undoLimit(); void commandTextFormat(); void separateUndoText(); @@ -2563,6 +2623,711 @@ void tst_QUndoStack::compression() true); // redoChanged } +void tst_QUndoStack::obsolete() +{ + QUndoStack stack; + const QScopedPointer<QAction> undoAction(stack.createUndoAction(0, QString("foo"))); + const QScopedPointer<QAction> redoAction(stack.createRedoAction(0, QString("bar"))); + QSignalSpy indexChangedSpy(&stack, &QUndoStack::indexChanged); + QSignalSpy cleanChangedSpy(&stack, &QUndoStack::cleanChanged); + QSignalSpy canUndoChangedSpy(&stack, &QUndoStack::canUndoChanged); + QSignalSpy undoTextChangedSpy(&stack, &QUndoStack::undoTextChanged); + QSignalSpy canRedoChangedSpy(&stack, &QUndoStack::canRedoChanged); + QSignalSpy redoTextChangedSpy(&stack, &QUndoStack::redoTextChanged); + QPoint mouse(0, 0); + QString str; + MoveMouseCommand *cmd1 = 0; + MoveMouseCommand *cmd2 = 0; + + stack.resetClean(); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + false, // clean + 0, // count + 0, // index + false, // canUndo + "", // undoText + false, // canRedo + "", // redoText + true, // cleanChanged + false, // indexChanged + false, // undoChanged + false); // redoChanged + + stack.push(new MoveMouseCommand(&mouse, mouse, QPoint(0, 0))); // #1 should not merge but will be deleted (b/c oldPoint == newPoint) + QCOMPARE(mouse, QPoint(0, 0)); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + false, // clean + 0, // count + 0, // index + false, // canUndo + "", // undoText + false, // canRedo + "", // redoText + false, // cleanChanged + false, // indexChanged + false, // undoChanged + false); // redoChanged + + stack.push(new MoveMouseCommand(&mouse, mouse, QPoint(12, 0))); // #2 should not merge or be deleted (b/c oldPoint != newPoint) + QCOMPARE(mouse, QPoint(12, 0)); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + false, // clean + 1, // count + 1, // index + true, // canUndo + "move mouse", // undoText + false, // canRedo + "", // redoText + false, // cleanChanged + true, // indexChanged + true, // undoChanged + true); // redoChanged + + stack.push(new MoveMouseCommand(&mouse, mouse, QPoint(8, 2))); // #3 should merge and not be deleted (b/c oldPoint != newPoint) + QCOMPARE(mouse, QPoint(8, 2)); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + false, // clean + 1, // count + 1, // index + true, // canUndo + "move mouse", // undoText + false, // canRedo + "", // redoText + false, // cleanChanged + true, // indexChanged + true, // undoChanged + true); // redoChanged + + stack.push(new MoveMouseCommand(&mouse, mouse, QPoint(0, 0))); // #4 should merge and be deleted (b/c oldPoint == newPoint) + QCOMPARE(mouse, QPoint(0, 0)); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + false, // clean + 0, // count + 0, // index + false, // canUndo + "", // undoText + false, // canRedo + "", // redoText + false, // cleanChanged + true, // indexChanged + true, // undoChanged + true); // redoChanged + + + + + stack.push(new InsertCommand(&str, 0, "ene")); // #5 should not merge or be deleted + QCOMPARE(str, QString("ene")); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + false, // clean + 1, // count + 1, // index + true, // canUndo + "insert", // undoText + false, // canRedo + "", // redoText + false, // cleanChanged + true, // indexChanged + true, // undoChanged + true); // redoChanged + + cmd1 = new MoveMouseCommand(&mouse, mouse, QPoint(6, 5)); + stack.push(cmd1); // #6 should not merge or be deleted (b/c oldPoint != newPoint) + QCOMPARE(mouse, QPoint(6, 5)); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + false, // clean + 2, // count + 2, // index + true, // canUndo + "move mouse", // undoText + false, // canRedo + "", // redoText + false, // cleanChanged + true, // indexChanged + true, // undoChanged + true); // redoChanged + + stack.push(new InsertCommand(&str, 3, "ma")); // #7 should not merge or be deleted + QCOMPARE(str, QString("enema")); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + false, // clean + 3, // count + 3, // index + true, // canUndo + "insert", // undoText + false, // canRedo + "", // redoText + false, // cleanChanged + true, // indexChanged + true, // undoChanged + true); // redoChanged + + cmd2 = new MoveMouseCommand(&mouse, mouse, QPoint(12, 4)); + stack.push(cmd2); // #8 should not merge or be deleted (b/c oldPoint != newPoint) + QCOMPARE(mouse, QPoint(12, 4)); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + false, // clean + 4, // count + 4, // index + true, // canUndo + "move mouse", // undoText + false, // canRedo + "", // redoText + false, // cleanChanged + true, // indexChanged + true, // undoChanged + true); // redoChanged + + stack.setClean(); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + true, // clean + 4, // count + 4, // index + true, // canUndo + "move mouse", // undoText + false, // canRedo + "", // redoText + true, // cleanChanged + false, // indexChanged + false, // undoChanged + false); // redoChanged + QCOMPARE(stack.cleanIndex(), 4); + + cmd2->setObsolete(true); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + true, // clean + 4, // count + 4, // index + true, // canUndo + "move mouse", // undoText + false, // canRedo + "", // redoText + false, // cleanChanged + false, // indexChanged + false, // undoChanged + false); // redoChanged + + stack.undo(); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + false, // clean + 3, // count + 3, // index + true, // canUndo + "insert", // undoText + false, // canRedo + "", // redoText + true, // cleanChanged + true, // indexChanged + true, // undoChanged + true); // redoChanged + QCOMPARE(stack.cleanIndex(), -1); + + stack.undo(); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + false, // clean + 3, // count + 2, // index + true, // canUndo + "move mouse", // undoText + true, // canRedo + "insert", // redoText + false, // cleanChanged + true, // indexChanged + true, // undoChanged + true); // redoChanged + + stack.setClean(); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + true, // clean + 3, // count + 2, // index + true, // canUndo + "move mouse", // undoText + true, // canRedo + "insert", // redoText + true, // cleanChanged + false, // indexChanged + false, // undoChanged + false); // redoChanged + QCOMPARE(stack.cleanIndex(), 2); + + stack.undo(); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + false, // clean + 3, // count + 1, // index + true, // canUndo + "insert", // undoText + true, // canRedo + "move mouse", // redoText + true, // cleanChanged + true, // indexChanged + true, // undoChanged + true); // redoChanged + + cmd1->setObsolete(true); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + false, // clean + 3, // count + 1, // index + true, // canUndo + "insert", // undoText + true, // canRedo + "move mouse", // redoText + false, // cleanChanged + false, // indexChanged + false, // undoChanged + false); // redoChanged + + stack.redo(); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + false, // clean + 2, // count + 1, // index + true, // canUndo + "insert", // undoText + true, // canRedo + "insert", // redoText + false, // cleanChanged + false, // indexChanged + false, // undoChanged + false); // redoChanged + QCOMPARE(stack.cleanIndex(), -1); + + stack.redo(); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + false, // clean + 2, // count + 2, // index + true, // canUndo + "insert", // undoText + false, // canRedo + "", // redoText + false, // cleanChanged + true, // indexChanged + true, // undoChanged + true); // redoChanged + QCOMPARE(stack.cleanIndex(), -1); + + cmd1 = new MoveMouseCommand(&mouse, mouse, QPoint(13, 2)); + stack.push(cmd1); // #9 should not merge or be deleted (b/c oldPoint != newPoint) + QCOMPARE(mouse, QPoint(13, 2)); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + false, // clean + 3, // count + 3, // index + true, // canUndo + "move mouse", // undoText + false, // canRedo + "", // redoText + false, // cleanChanged + true, // indexChanged + true, // undoChanged + true); // redoChanged + + stack.push(new InsertCommand(&str, 3, "ma")); // #10 should not merge or be deleted + QCOMPARE(str, QString("enemama")); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + false, // clean + 4, // count + 4, // index + true, // canUndo + "insert", // undoText + false, // canRedo + "", // redoText + false, // cleanChanged + true, // indexChanged + true, // undoChanged + true); // redoChanged + + cmd2 = new MoveMouseCommand(&mouse, mouse, QPoint(6, 20)); + stack.push(cmd2); // #11 should not merge or be deleted (b/c oldPoint != newPoint) + QCOMPARE(mouse, QPoint(6, 20)); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + false, // clean + 5, // count + 5, // index + true, // canUndo + "move mouse", // undoText + false, // canRedo + "", // redoText + false, // cleanChanged + true, // indexChanged + true, // undoChanged + true); // redoChanged + + cmd1->setObsolete(true); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + false, // clean + 5, // count + 5, // index + true, // canUndo + "move mouse", // undoText + false, // canRedo + "", // redoText + false, // cleanChanged + false, // indexChanged + false, // undoChanged + false); // redoChanged + + stack.setClean(); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + true, // clean + 5, // count + 5, // index + true, // canUndo + "move mouse", // undoText + false, // canRedo + "", // redoText + true, // cleanChanged + false, // indexChanged + false, // undoChanged + false); // redoChanged + QCOMPARE(stack.cleanIndex(), 5); + + stack.setIndex(0); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + false, // clean + 4, // count + 0, // index + false, // canUndo + "", // undoText + true, // canRedo + "insert", // redoText + true, // cleanChanged + true, // indexChanged + true, // undoChanged + true); // redoChanged + QCOMPARE(stack.cleanIndex(), -1); + + cmd2->setObsolete(true); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + false, // clean + 4, // count + 0, // index + false, // canUndo + "", // undoText + true, // canRedo + "insert", // redoText + false, // cleanChanged + false, // indexChanged + false, // undoChanged + false); // redoChanged + + stack.setIndex(stack.count()); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + false, // clean + 3, // count + 3, // index + true, // canUndo + "insert", // undoText + false, // canRedo + "", // redoText + false, // cleanChanged + true, // indexChanged + true, // undoChanged + true); // redoChanged + + mouse = QPoint(0, 0); // Reset mouse position + stack.beginMacro("ding"); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + false, // clean + 4, // count + 3, // index + false, // canUndo + "", // undoText + false, // canRedo + "", // redoText + false, // cleanChanged + false, // indexChanged + true, // undoChanged + true); // redoChanged + + stack.push(new MoveMouseCommand(&mouse, mouse, QPoint(7, 7))); // #12 should not merge or be deleted (b/c oldPoint != newPoint & in macro) + QCOMPARE(mouse, QPoint(7, 7)); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + false, // clean + 4, // count + 3, // index + false, // canUndo + "", // undoText + false, // canRedo + "", // redoText + false, // cleanChanged + false, // indexChanged + false, // undoChanged + false); // redoChanged + + stack.push(new MoveMouseCommand(&mouse, mouse, QPoint(0, 0))); // #13 should merge and be deleted (b/c oldPoint = newPoint) + QCOMPARE(mouse, QPoint(0, 0)); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + false, // clean + 4, // count + 3, // index + false, // canUndo + "", // undoText + false, // canRedo + "", // redoText + false, // cleanChanged + false, // indexChanged + false, // undoChanged + false); // redoChanged + + stack.endMacro(); + checkState(redoTextChangedSpy, + canRedoChangedSpy, + undoTextChangedSpy, + redoAction, + undoAction, + canUndoChangedSpy, + cleanChangedSpy, + indexChangedSpy, + stack, + false, // clean + 4, // count + 4, // index + true, // canUndo + "ding", // undoText + false, // canRedo + "", // redoText + false, // cleanChanged + true, // indexChanged + true, // undoChanged + true); // redoChanged +} + void tst_QUndoStack::undoLimit() { QUndoStack stack; |