summaryrefslogtreecommitdiffstats
path: root/tests/auto/gui/util
diff options
context:
space:
mode:
authorMitch Curtis <mitch.curtis@qt.io>2020-03-10 15:40:56 +0100
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2020-03-30 12:36:29 +0200
commit3f73995a03c4b40e2648cb9af5d3e7ca393bf597 (patch)
treef7f9f4c63a5506287de4d44d4f01cdc57e093a27 /tests/auto/gui/util
parentadc1be3c33b4237a13e423c140bcb1c06aeb11d9 (diff)
Move undo framework out of Qt Widgets
- Moves QUndo* classes (except QUndoView) from src/widgets/utils to src/gui/utils - Moves related auto tests from widgets to gui - Replaces QUndoAction with lambdas that do text prefixing [ChangeLog][Undo Framework] QUndo* classes (except QUndoView) were moved from Qt Widgets to Qt GUI. Done-with: volker.hilsheimer@qt.io Fixes: QTBUG-40040 Change-Id: I3bd8d4d32c64f8dee548f62159a1df2126da89d8 Reviewed-by: Lars Knoll <lars.knoll@qt.io> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'tests/auto/gui/util')
-rw-r--r--tests/auto/gui/util/CMakeLists.txt2
-rw-r--r--tests/auto/gui/util/qundogroup/.gitignore1
-rw-r--r--tests/auto/gui/util/qundogroup/CMakeLists.txt12
-rw-r--r--tests/auto/gui/util/qundogroup/qundogroup.pro4
-rw-r--r--tests/auto/gui/util/qundogroup/testdata/qundogroup.ts25
-rw-r--r--tests/auto/gui/util/qundogroup/tst_qundogroup.cpp641
-rw-r--r--tests/auto/gui/util/qundostack/.gitignore1
-rw-r--r--tests/auto/gui/util/qundostack/CMakeLists.txt12
-rw-r--r--tests/auto/gui/util/qundostack/qundostack.pro4
-rw-r--r--tests/auto/gui/util/qundostack/testdata/qundostack.ts25
-rw-r--r--tests/auto/gui/util/qundostack/tst_qundostack.cpp3930
-rw-r--r--tests/auto/gui/util/util.pro4
12 files changed, 4660 insertions, 1 deletions
diff --git a/tests/auto/gui/util/CMakeLists.txt b/tests/auto/gui/util/CMakeLists.txt
index 1c4a53265d..4feae26818 100644
--- a/tests/auto/gui/util/CMakeLists.txt
+++ b/tests/auto/gui/util/CMakeLists.txt
@@ -10,3 +10,5 @@ add_subdirectory(qshadergraphloader)
add_subdirectory(qshadernodes)
add_subdirectory(qshadernodesloader)
add_subdirectory(qtexturefilereader)
+add_subdirectory(qundogroup)
+add_subdirectory(qundostack)
diff --git a/tests/auto/gui/util/qundogroup/.gitignore b/tests/auto/gui/util/qundogroup/.gitignore
new file mode 100644
index 0000000000..bc3e8c4691
--- /dev/null
+++ b/tests/auto/gui/util/qundogroup/.gitignore
@@ -0,0 +1 @@
+tst_qundogroup
diff --git a/tests/auto/gui/util/qundogroup/CMakeLists.txt b/tests/auto/gui/util/qundogroup/CMakeLists.txt
new file mode 100644
index 0000000000..3325556a3e
--- /dev/null
+++ b/tests/auto/gui/util/qundogroup/CMakeLists.txt
@@ -0,0 +1,12 @@
+# Generated from qundogroup.pro.
+
+#####################################################################
+## tst_qundogroup Test:
+#####################################################################
+
+add_qt_test(tst_qundogroup
+ SOURCES
+ tst_qundogroup.cpp
+ PUBLIC_LIBRARIES
+ Qt::Gui
+)
diff --git a/tests/auto/gui/util/qundogroup/qundogroup.pro b/tests/auto/gui/util/qundogroup/qundogroup.pro
new file mode 100644
index 0000000000..fbae557207
--- /dev/null
+++ b/tests/auto/gui/util/qundogroup/qundogroup.pro
@@ -0,0 +1,4 @@
+CONFIG += testcase
+QT += testlib
+SOURCES += tst_qundogroup.cpp
+TARGET = tst_qundogroup
diff --git a/tests/auto/gui/util/qundogroup/testdata/qundogroup.ts b/tests/auto/gui/util/qundogroup/testdata/qundogroup.ts
new file mode 100644
index 0000000000..a059bcb486
--- /dev/null
+++ b/tests/auto/gui/util/qundogroup/testdata/qundogroup.ts
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="en">
+<context>
+ <name>QUndoGroup</name>
+ <message>
+ <source>Undo %1</source>
+ <translation>undo-prefix %1 undo-suffix</translation>
+ </message>
+ <message>
+ <source>Undo</source>
+ <comment>Default text for undo action</comment>
+ <translation>Undo-default-text</translation>
+ </message>
+ <message>
+ <source>Redo %1</source>
+ <translation>redo-prefix %1 redo-suffix</translation>
+ </message>
+ <message>
+ <source>Redo</source>
+ <comment>Default text for redo action</comment>
+ <translation>Redo-default-text</translation>
+ </message>
+</context>
+</TS>
diff --git a/tests/auto/gui/util/qundogroup/tst_qundogroup.cpp b/tests/auto/gui/util/qundogroup/tst_qundogroup.cpp
new file mode 100644
index 0000000000..ba238105ec
--- /dev/null
+++ b/tests/auto/gui/util/qundogroup/tst_qundogroup.cpp
@@ -0,0 +1,641 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtTest/QtTest>
+#include <QUndoGroup>
+#include <QUndoStack>
+#include <QAction>
+
+/******************************************************************************
+** Commands
+*/
+
+class InsertCommand : public QUndoCommand
+{
+public:
+ InsertCommand(QString *str, int idx, const QString &text,
+ QUndoCommand *parent = 0);
+
+ virtual void undo();
+ virtual void redo();
+
+private:
+ QString *m_str;
+ int m_idx;
+ QString m_text;
+};
+
+class RemoveCommand : public QUndoCommand
+{
+public:
+ RemoveCommand(QString *str, int idx, int len, QUndoCommand *parent = 0);
+
+ virtual void undo();
+ virtual void redo();
+
+private:
+ QString *m_str;
+ int m_idx;
+ QString m_text;
+};
+
+class AppendCommand : public QUndoCommand
+{
+public:
+ AppendCommand(QString *str, const QString &text, QUndoCommand *parent = 0);
+
+ virtual void undo();
+ virtual void redo();
+ virtual int id() const;
+ virtual bool mergeWith(const QUndoCommand *other);
+
+ bool merged;
+
+private:
+ QString *m_str;
+ QString m_text;
+};
+
+InsertCommand::InsertCommand(QString *str, int idx, const QString &text,
+ QUndoCommand *parent)
+ : QUndoCommand(parent)
+{
+ QVERIFY(str->length() >= idx);
+
+ setText("insert");
+
+ m_str = str;
+ m_idx = idx;
+ m_text = text;
+}
+
+void InsertCommand::redo()
+{
+ QVERIFY(m_str->length() >= m_idx);
+
+ m_str->insert(m_idx, m_text);
+}
+
+void InsertCommand::undo()
+{
+ QCOMPARE(m_str->mid(m_idx, m_text.length()), m_text);
+
+ m_str->remove(m_idx, m_text.length());
+}
+
+RemoveCommand::RemoveCommand(QString *str, int idx, int len, QUndoCommand *parent)
+ : QUndoCommand(parent)
+{
+ QVERIFY(str->length() >= idx + len);
+
+ setText("remove");
+
+ m_str = str;
+ m_idx = idx;
+ m_text = m_str->mid(m_idx, len);
+}
+
+void RemoveCommand::redo()
+{
+ QCOMPARE(m_str->mid(m_idx, m_text.length()), m_text);
+
+ m_str->remove(m_idx, m_text.length());
+}
+
+void RemoveCommand::undo()
+{
+ QVERIFY(m_str->length() >= m_idx);
+
+ m_str->insert(m_idx, m_text);
+}
+
+AppendCommand::AppendCommand(QString *str, const QString &text, QUndoCommand *parent)
+ : QUndoCommand(parent)
+{
+ setText("append");
+
+ m_str = str;
+ m_text = text;
+ merged = false;
+}
+
+void AppendCommand::redo()
+{
+ m_str->append(m_text);
+}
+
+void AppendCommand::undo()
+{
+ QCOMPARE(m_str->mid(m_str->length() - m_text.length()), m_text);
+
+ m_str->truncate(m_str->length() - m_text.length());
+}
+
+int AppendCommand::id() const
+{
+ return 1;
+}
+
+bool AppendCommand::mergeWith(const QUndoCommand *other)
+{
+ if (other->id() != id())
+ return false;
+ m_text += static_cast<const AppendCommand*>(other)->m_text;
+ merged = true;
+ return true;
+}
+
+/******************************************************************************
+** tst_QUndoStack
+*/
+
+class tst_QUndoGroup : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QUndoGroup();
+
+private slots:
+ void setActive();
+ void addRemoveStack();
+ void deleteStack();
+ void checkSignals();
+ void addStackAndDie();
+ void commandTextFormat();
+};
+
+tst_QUndoGroup::tst_QUndoGroup()
+{
+}
+
+void tst_QUndoGroup::setActive()
+{
+ QUndoGroup group;
+ QUndoStack stack1(&group), stack2(&group);
+
+ QCOMPARE(group.activeStack(), nullptr);
+ QCOMPARE(stack1.isActive(), false);
+ QCOMPARE(stack2.isActive(), false);
+
+ QUndoStack stack3;
+ QCOMPARE(stack3.isActive(), true);
+
+ group.addStack(&stack3);
+ QCOMPARE(stack3.isActive(), false);
+
+ stack1.setActive();
+ QCOMPARE(group.activeStack(), &stack1);
+ QCOMPARE(stack1.isActive(), true);
+ QCOMPARE(stack2.isActive(), false);
+ QCOMPARE(stack3.isActive(), false);
+
+ group.setActiveStack(&stack2);
+ QCOMPARE(group.activeStack(), &stack2);
+ QCOMPARE(stack1.isActive(), false);
+ QCOMPARE(stack2.isActive(), true);
+ QCOMPARE(stack3.isActive(), false);
+
+ group.removeStack(&stack2);
+ QCOMPARE(group.activeStack(), nullptr);
+ QCOMPARE(stack1.isActive(), false);
+ QCOMPARE(stack2.isActive(), true);
+ QCOMPARE(stack3.isActive(), false);
+
+ group.removeStack(&stack2);
+ QCOMPARE(group.activeStack(), nullptr);
+ QCOMPARE(stack1.isActive(), false);
+ QCOMPARE(stack2.isActive(), true);
+ QCOMPARE(stack3.isActive(), false);
+}
+
+void tst_QUndoGroup::addRemoveStack()
+{
+ QUndoGroup group;
+
+ QUndoStack stack1(&group);
+ QCOMPARE(group.stacks(), QList<QUndoStack*>() << &stack1);
+
+ QUndoStack stack2;
+ group.addStack(&stack2);
+ QCOMPARE(group.stacks(), QList<QUndoStack*>() << &stack1 << &stack2);
+
+ group.addStack(&stack1);
+ QCOMPARE(group.stacks(), QList<QUndoStack*>() << &stack1 << &stack2);
+
+ group.removeStack(&stack1);
+ QCOMPARE(group.stacks(), QList<QUndoStack*>() << &stack2);
+
+ group.removeStack(&stack1);
+ QCOMPARE(group.stacks(), QList<QUndoStack*>() << &stack2);
+
+ group.removeStack(&stack2);
+ QCOMPARE(group.stacks(), QList<QUndoStack*>());
+}
+
+void tst_QUndoGroup::deleteStack()
+{
+ QUndoGroup group;
+
+ QUndoStack *stack1 = new QUndoStack(&group);
+ QCOMPARE(group.stacks(), QList<QUndoStack*>() << stack1);
+ QCOMPARE(group.activeStack(), nullptr);
+
+ stack1->setActive();
+ QCOMPARE(group.activeStack(), stack1);
+
+ QUndoStack *stack2 = new QUndoStack(&group);
+ QCOMPARE(group.stacks(), QList<QUndoStack*>() << stack1 << stack2);
+ QCOMPARE(group.activeStack(), stack1);
+
+ QUndoStack *stack3 = new QUndoStack(&group);
+ QCOMPARE(group.stacks(), QList<QUndoStack*>() << stack1 << stack2 << stack3);
+ QCOMPARE(group.activeStack(), stack1);
+
+ delete stack2;
+ QCOMPARE(group.stacks(), QList<QUndoStack*>() << stack1 << stack3);
+ QCOMPARE(group.activeStack(), stack1);
+
+ delete stack1;
+ QCOMPARE(group.stacks(), QList<QUndoStack*>() << stack3);
+ QCOMPARE(group.activeStack(), nullptr);
+
+ stack3->setActive(false);
+ QCOMPARE(group.activeStack(), nullptr);
+
+ stack3->setActive(true);
+ QCOMPARE(group.activeStack(), stack3);
+
+ group.removeStack(stack3);
+ QCOMPARE(group.stacks(), QList<QUndoStack*>());
+ QCOMPARE(group.activeStack(), nullptr);
+
+ delete stack3;
+}
+
+static QString glue(const QString &s1, const QString &s2)
+{
+ QString result;
+
+ result.append(s1);
+ if (!s1.isEmpty() && !s2.isEmpty())
+ result.append(' ');
+ result.append(s2);
+
+ return result;
+}
+
+#define CHECK_STATE(_activeStack, _clean, _canUndo, _undoText, _canRedo, _redoText, \
+ _cleanChanged, _indexChanged, _undoChanged, _redoChanged) \
+ QCOMPARE(group.activeStack(), (QUndoStack*)_activeStack); \
+ QCOMPARE(group.isClean(), _clean); \
+ QCOMPARE(group.canUndo(), _canUndo); \
+ QCOMPARE(group.undoText(), QString(_undoText)); \
+ QCOMPARE(group.canRedo(), _canRedo); \
+ QCOMPARE(group.redoText(), QString(_redoText)); \
+ if (_indexChanged) { \
+ QCOMPARE(indexChangedSpy.count(), 1); \
+ indexChangedSpy.clear(); \
+ } else { \
+ QCOMPARE(indexChangedSpy.count(), 0); \
+ } \
+ if (_cleanChanged) { \
+ QCOMPARE(cleanChangedSpy.count(), 1); \
+ QCOMPARE(cleanChangedSpy.at(0).at(0).toBool(), _clean); \
+ cleanChangedSpy.clear(); \
+ } else { \
+ QCOMPARE(cleanChangedSpy.count(), 0); \
+ } \
+ if (_undoChanged) { \
+ QCOMPARE(canUndoChangedSpy.count(), 1); \
+ QCOMPARE(canUndoChangedSpy.at(0).at(0).toBool(), _canUndo); \
+ QCOMPARE(undo_action->isEnabled(), _canUndo); \
+ QCOMPARE(undoTextChangedSpy.count(), 1); \
+ QCOMPARE(undoTextChangedSpy.at(0).at(0).toString(), QString(_undoText)); \
+ QCOMPARE(undo_action->text(), glue("foo", _undoText)); \
+ canUndoChangedSpy.clear(); \
+ undoTextChangedSpy.clear(); \
+ } else { \
+ QCOMPARE(canUndoChangedSpy.count(), 0); \
+ QCOMPARE(undoTextChangedSpy.count(), 0); \
+ } \
+ if (_redoChanged) { \
+ QCOMPARE(canRedoChangedSpy.count(), 1); \
+ QCOMPARE(canRedoChangedSpy.at(0).at(0).toBool(), _canRedo); \
+ QCOMPARE(redo_action->isEnabled(), _canRedo); \
+ QCOMPARE(redoTextChangedSpy.count(), 1); \
+ QCOMPARE(redoTextChangedSpy.at(0).at(0).toString(), QString(_redoText)); \
+ QCOMPARE(redo_action->text(), glue("bar", _redoText)); \
+ canRedoChangedSpy.clear(); \
+ redoTextChangedSpy.clear(); \
+ } else { \
+ QCOMPARE(canRedoChangedSpy.count(), 0); \
+ QCOMPARE(redoTextChangedSpy.count(), 0); \
+ }
+
+void tst_QUndoGroup::checkSignals()
+{
+ QUndoGroup group;
+ QScopedPointer<QAction> undo_action(group.createUndoAction(nullptr, QString("foo")));
+ QScopedPointer<QAction> redo_action(group.createRedoAction(nullptr, QString("bar")));
+ QSignalSpy indexChangedSpy(&group, &QUndoGroup::indexChanged);
+ QSignalSpy cleanChangedSpy(&group, &QUndoGroup::cleanChanged);
+ QSignalSpy canUndoChangedSpy(&group, &QUndoGroup::canUndoChanged);
+ QSignalSpy undoTextChangedSpy(&group, &QUndoGroup::undoTextChanged);
+ QSignalSpy canRedoChangedSpy(&group, &QUndoGroup::canRedoChanged);
+ QSignalSpy redoTextChangedSpy(&group, &QUndoGroup::redoTextChanged);
+
+ QString str;
+
+ CHECK_STATE(0, // activeStack
+ true, // clean
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false) // redoChanged
+
+ group.undo();
+ CHECK_STATE(0, // activeStack
+ true, // clean
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false) // redoChanged
+
+ group.redo();
+ CHECK_STATE(0, // activeStack
+ true, // clean
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false) // redoChanged
+
+ QUndoStack *stack1 = new QUndoStack(&group);
+ CHECK_STATE(0, // activeStack
+ true, // clean
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false) // redoChanged
+
+ stack1->push(new AppendCommand(&str, "foo"));
+ CHECK_STATE(0, // activeStack
+ true, // clean
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false) // redoChanged
+
+ stack1->setActive();
+ CHECK_STATE(stack1, // activeStack
+ false, // clean
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true) // redoChanged
+
+ stack1->push(new InsertCommand(&str, 0, "bar"));
+ CHECK_STATE(stack1, // activeStack
+ false, // clean
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true) // redoChanged
+
+ stack1->undo();
+ CHECK_STATE(stack1, // activeStack
+ false, // clean
+ true, // canUndo
+ "append", // undoText
+ true, // canRedo
+ "insert", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true) // redoChanged
+
+ stack1->undo();
+ CHECK_STATE(stack1, // activeStack
+ true, // clean
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "append", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true) // redoChanged
+
+ stack1->undo();
+ CHECK_STATE(stack1, // activeStack
+ true, // clean
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "append", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false) // redoChanged
+
+ group.undo();
+ CHECK_STATE(stack1, // activeStack
+ true, // clean
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "append", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false) // redoChanged
+
+ group.redo();
+ CHECK_STATE(stack1, // activeStack
+ false, // clean
+ true, // canUndo
+ "append", // undoText
+ true, // canRedo
+ "insert", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true) // redoChanged
+
+ stack1->setActive(false);
+ CHECK_STATE(0, // activeStack
+ true, // clean
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true) // redoChanged
+
+ QUndoStack *stack2 = new QUndoStack(&group);
+ CHECK_STATE(0, // activeStack
+ true, // clean
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false) // redoChanged
+
+ stack2->setActive();
+ CHECK_STATE(stack2, // activeStack
+ true, // clean
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true) // redoChanged
+
+ stack1->setActive();
+ CHECK_STATE(stack1, // activeStack
+ false, // clean
+ true, // canUndo
+ "append", // undoText
+ true, // canRedo
+ "insert", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true) // redoChanged
+
+ delete stack1;
+ CHECK_STATE(0, // activeStack
+ true, // clean
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true) // redoChanged
+}
+
+void tst_QUndoGroup::addStackAndDie()
+{
+ // Test that QUndoStack doesn't keep a reference to QUndoGroup after the
+ // group is deleted.
+ QUndoStack *stack = new QUndoStack;
+ QUndoGroup *group = new QUndoGroup;
+ group->addStack(stack);
+ delete group;
+ stack->setActive(true);
+ delete stack;
+}
+
+void tst_QUndoGroup::commandTextFormat()
+{
+#if !QT_CONFIG(process)
+ QSKIP("No QProcess available");
+#else
+ QString binDir = QLibraryInfo::location(QLibraryInfo::BinariesPath);
+
+ if (QProcess::execute(binDir + "/lrelease -version") != 0)
+ QSKIP("lrelease is missing or broken");
+
+ const QString tsFile = QFINDTESTDATA("testdata/qundogroup.ts");
+ QVERIFY(!tsFile.isEmpty());
+ QFile::remove("qundogroup.qm"); // Avoid confusion by strays.
+ QVERIFY(!QProcess::execute(binDir + "/lrelease -silent " + tsFile + " -qm qundogroup.qm"));
+
+ QTranslator translator;
+
+ QVERIFY(translator.load("qundogroup.qm"));
+ QFile::remove("qundogroup.qm");
+ qApp->installTranslator(&translator);
+
+ QUndoGroup group;
+ QScopedPointer<QAction> undo_action(group.createUndoAction(nullptr));
+ QScopedPointer<QAction> redo_action(group.createRedoAction(nullptr));
+
+ QCOMPARE(undo_action->text(), QString("Undo-default-text"));
+ QCOMPARE(redo_action->text(), QString("Redo-default-text"));
+
+ QUndoStack stack(&group);
+ stack.setActive();
+ QString str;
+
+ stack.push(new AppendCommand(&str, "foo"));
+ QCOMPARE(undo_action->text(), QString("undo-prefix append undo-suffix"));
+ QCOMPARE(redo_action->text(), QString("Redo-default-text"));
+
+ stack.push(new InsertCommand(&str, 0, "bar"));
+ stack.undo();
+ QCOMPARE(undo_action->text(), QString("undo-prefix append undo-suffix"));
+ QCOMPARE(redo_action->text(), QString("redo-prefix insert redo-suffix"));
+
+ stack.undo();
+ QCOMPARE(undo_action->text(), QString("Undo-default-text"));
+ QCOMPARE(redo_action->text(), QString("redo-prefix append redo-suffix"));
+
+ qApp->removeTranslator(&translator);
+#endif
+}
+
+QTEST_MAIN(tst_QUndoGroup)
+
+#include "tst_qundogroup.moc"
+
diff --git a/tests/auto/gui/util/qundostack/.gitignore b/tests/auto/gui/util/qundostack/.gitignore
new file mode 100644
index 0000000000..f8faf2771f
--- /dev/null
+++ b/tests/auto/gui/util/qundostack/.gitignore
@@ -0,0 +1 @@
+tst_qundostack
diff --git a/tests/auto/gui/util/qundostack/CMakeLists.txt b/tests/auto/gui/util/qundostack/CMakeLists.txt
new file mode 100644
index 0000000000..d6cf36187e
--- /dev/null
+++ b/tests/auto/gui/util/qundostack/CMakeLists.txt
@@ -0,0 +1,12 @@
+# Generated from qundostack.pro.
+
+#####################################################################
+## tst_qundostack Test:
+#####################################################################
+
+add_qt_test(tst_qundostack
+ SOURCES
+ tst_qundostack.cpp
+ PUBLIC_LIBRARIES
+ Qt::Gui
+)
diff --git a/tests/auto/gui/util/qundostack/qundostack.pro b/tests/auto/gui/util/qundostack/qundostack.pro
new file mode 100644
index 0000000000..bbade9635f
--- /dev/null
+++ b/tests/auto/gui/util/qundostack/qundostack.pro
@@ -0,0 +1,4 @@
+CONFIG += testcase
+QT += gui testlib
+SOURCES += tst_qundostack.cpp
+TARGET = tst_qundostack
diff --git a/tests/auto/gui/util/qundostack/testdata/qundostack.ts b/tests/auto/gui/util/qundostack/testdata/qundostack.ts
new file mode 100644
index 0000000000..4584036af2
--- /dev/null
+++ b/tests/auto/gui/util/qundostack/testdata/qundostack.ts
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="en">
+<context>
+ <name>QUndoStack</name>
+ <message>
+ <source>Undo %1</source>
+ <translation>undo-prefix %1 undo-suffix</translation>
+ </message>
+ <message>
+ <source>Undo</source>
+ <comment>Default text for undo action</comment>
+ <translation>Undo-default-text</translation>
+ </message>
+ <message>
+ <source>Redo %1</source>
+ <translation>redo-prefix %1 redo-suffix</translation>
+ </message>
+ <message>
+ <source>Redo</source>
+ <comment>Default text for redo action</comment>
+ <translation>Redo-default-text</translation>
+ </message>
+</context>
+</TS>
diff --git a/tests/auto/gui/util/qundostack/tst_qundostack.cpp b/tests/auto/gui/util/qundostack/tst_qundostack.cpp
new file mode 100644
index 0000000000..a24798cba7
--- /dev/null
+++ b/tests/auto/gui/util/qundostack/tst_qundostack.cpp
@@ -0,0 +1,3930 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QAction>
+#include <QUndoStack>
+
+/******************************************************************************
+** Commands
+*/
+
+class InsertCommand : public QUndoCommand
+{
+public:
+ InsertCommand(QString *str, int idx, const QString &text,
+ QUndoCommand *parent = 0);
+
+ virtual void undo();
+ virtual void redo();
+
+private:
+ QString *m_str;
+ int m_idx;
+ QString m_text;
+};
+
+class RemoveCommand : public QUndoCommand
+{
+public:
+ RemoveCommand(QString *str, int idx, int len, QUndoCommand *parent = 0);
+
+ virtual void undo();
+ virtual void redo();
+
+private:
+ QString *m_str;
+ int m_idx;
+ QString m_text;
+};
+
+class AppendCommand : public QUndoCommand
+{
+public:
+ AppendCommand(QString *str, const QString &text, bool _fail_merge = false,
+ QUndoCommand *parent = 0);
+ ~AppendCommand();
+
+ virtual void undo();
+ virtual void redo();
+ virtual int id() const;
+ virtual bool mergeWith(const QUndoCommand *other);
+
+ bool merged;
+ bool fail_merge;
+ static int delete_cnt;
+
+private:
+ QString *m_str;
+ QString m_text;
+};
+
+class IdleCommand : public QUndoCommand
+{
+public:
+ IdleCommand(QUndoCommand *parent = 0);
+ ~IdleCommand();
+
+ virtual void undo();
+ 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)
+{
+ QVERIFY(str->length() >= idx);
+
+ setText("insert");
+
+ m_str = str;
+ m_idx = idx;
+ m_text = text;
+}
+
+void InsertCommand::redo()
+{
+ QVERIFY(m_str->length() >= m_idx);
+
+ m_str->insert(m_idx, m_text);
+}
+
+void InsertCommand::undo()
+{
+ QCOMPARE(m_str->mid(m_idx, m_text.length()), m_text);
+
+ m_str->remove(m_idx, m_text.length());
+}
+
+RemoveCommand::RemoveCommand(QString *str, int idx, int len, QUndoCommand *parent)
+ : QUndoCommand(parent)
+{
+ QVERIFY(str->length() >= idx + len);
+
+ setText("remove");
+
+ m_str = str;
+ m_idx = idx;
+ m_text = m_str->mid(m_idx, len);
+}
+
+void RemoveCommand::redo()
+{
+ QCOMPARE(m_str->mid(m_idx, m_text.length()), m_text);
+
+ m_str->remove(m_idx, m_text.length());
+}
+
+void RemoveCommand::undo()
+{
+ QVERIFY(m_str->length() >= m_idx);
+
+ m_str->insert(m_idx, m_text);
+}
+
+int AppendCommand::delete_cnt = 0;
+
+AppendCommand::AppendCommand(QString *str, const QString &text, bool _fail_merge,
+ QUndoCommand *parent)
+ : QUndoCommand(parent)
+{
+ setText("append");
+
+ m_str = str;
+ m_text = text;
+ merged = false;
+ fail_merge = _fail_merge;
+}
+
+AppendCommand::~AppendCommand()
+{
+ ++delete_cnt;
+}
+
+void AppendCommand::redo()
+{
+ m_str->append(m_text);
+}
+
+void AppendCommand::undo()
+{
+ QCOMPARE(m_str->mid(m_str->length() - m_text.length()), m_text);
+
+ m_str->truncate(m_str->length() - m_text.length());
+}
+
+int AppendCommand::id() const
+{
+ return 1;
+}
+
+bool AppendCommand::mergeWith(const QUndoCommand *other)
+{
+ if (other->id() != id())
+ return false;
+ if (fail_merge)
+ return false;
+ m_text += static_cast<const AppendCommand*>(other)->m_text;
+ merged = true;
+ return true;
+}
+
+IdleCommand::IdleCommand(QUndoCommand *parent)
+ : QUndoCommand(parent)
+{
+ // "idle-item" goes to QUndoStack::{redo,undo}Text
+ // "idle-action" goes to all other places (e.g. QUndoView)
+ setText("idle-item\nidle-action");
+}
+
+IdleCommand::~IdleCommand()
+{
+}
+
+void IdleCommand::redo()
+{
+}
+
+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
+*/
+
+class tst_QUndoStack : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QUndoStack();
+
+private slots:
+ void undoRedo();
+ void setIndex();
+ void setClean();
+ void clear();
+ void childCommand();
+ void macroBeginEnd();
+ void compression();
+ void obsolete();
+ void undoLimit();
+ void commandTextFormat();
+ void separateUndoText();
+};
+
+tst_QUndoStack::tst_QUndoStack()
+{
+}
+
+static QString glue(const QString &s1, const QString &s2)
+{
+ QString result;
+
+ result.append(s1);
+ if (!s1.isEmpty() && !s2.isEmpty())
+ result.append(' ');
+ result.append(s2);
+
+ return result;
+}
+
+static void checkState(QSignalSpy &redoTextChangedSpy,
+ QSignalSpy &canRedoChangedSpy,
+ QSignalSpy &undoTextChangedSpy,
+ const QScopedPointer<QAction> &redoAction,
+ const QScopedPointer<QAction> &undoAction,
+ QSignalSpy &canUndoChangedSpy,
+ QSignalSpy &cleanChangedSpy,
+ QSignalSpy &indexChangedSpy,
+ QUndoStack &stack,
+ const bool _clean,
+ const int _count,
+ const int _index,
+ const bool _canUndo,
+ const QString &_undoText,
+ const bool _canRedo,
+ const QString &_redoText,
+ const bool _cleanChanged,
+ const bool _indexChanged,
+ const bool _undoChanged,
+ const bool _redoChanged)
+{
+ QCOMPARE(stack.count(), _count);
+ QCOMPARE(stack.isClean(), _clean);
+ QCOMPARE(stack.index(), _index);
+ QCOMPARE(stack.canUndo(), _canUndo);
+ QCOMPARE(stack.undoText(), QString(_undoText));
+ QCOMPARE(stack.canRedo(), _canRedo);
+ QCOMPARE(stack.redoText(), QString(_redoText));
+ if (_indexChanged) {
+ QCOMPARE(indexChangedSpy.count(), 1);
+ QCOMPARE(indexChangedSpy.at(0).at(0).toInt(), _index);
+ indexChangedSpy.clear();
+ } else {
+ QCOMPARE(indexChangedSpy.count(), 0);
+ }
+ if (_cleanChanged) {
+ QCOMPARE(cleanChangedSpy.count(), 1);
+ QCOMPARE(cleanChangedSpy.at(0).at(0).toBool(), _clean);
+ cleanChangedSpy.clear();
+ } else {
+ QCOMPARE(cleanChangedSpy.count(), 0);
+ }
+ if (_undoChanged) {
+ QCOMPARE(canUndoChangedSpy.count(), 1);
+ QCOMPARE(canUndoChangedSpy.at(0).at(0).toBool(), _canUndo);
+ QCOMPARE(undoAction->isEnabled(), _canUndo);
+ QCOMPARE(undoTextChangedSpy.count(), 1);
+ QCOMPARE(undoTextChangedSpy.at(0).at(0).toString(), QString(_undoText));
+ QCOMPARE(undoAction->text(), glue("foo", _undoText));
+ canUndoChangedSpy.clear();
+ undoTextChangedSpy.clear();
+ } else {
+ QCOMPARE(canUndoChangedSpy.count(), 0);
+ QCOMPARE(undoTextChangedSpy.count(), 0);
+ }
+ if (_redoChanged) {
+ QCOMPARE(canRedoChangedSpy.count(), 1);
+ QCOMPARE(canRedoChangedSpy.at(0).at(0).toBool(), _canRedo);
+ QCOMPARE(redoAction->isEnabled(), _canRedo);
+ QCOMPARE(redoTextChangedSpy.count(), 1);
+ QCOMPARE(redoTextChangedSpy.at(0).at(0).toString(), QString(_redoText));
+ QCOMPARE(redoAction->text(), glue("bar", _redoText));
+ canRedoChangedSpy.clear();
+ redoTextChangedSpy.clear();
+ } else {
+ QCOMPARE(canRedoChangedSpy.count(), 0);
+ QCOMPARE(redoTextChangedSpy.count(), 0);
+ }
+}
+
+void tst_QUndoStack::undoRedo()
+{
+ QUndoStack stack;
+ QScopedPointer<QAction> undoAction(stack.createUndoAction(nullptr, QString("foo")));
+ QScopedPointer<QAction> redoAction(stack.createRedoAction(nullptr, 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);
+ QString str;
+
+ // push, undo, redo
+
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 0, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.undo(); // nothing to undo
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 0, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.push(new InsertCommand(&str, 0, "hello"));
+ QCOMPARE(str, QString("hello"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new InsertCommand(&str, 2, "123"));
+ QCOMPARE(str, QString("he123llo"));
+ 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
+
+
+ stack.undo();
+ QCOMPARE(str, QString("hello"));
+ 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
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.redo();
+ QCOMPARE(str, QString("he123llo"));
+ 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
+
+ stack.redo(); // nothing to redo
+ QCOMPARE(str, QString("he123llo"));
+ 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
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("hello"));
+ 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
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 2, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "insert", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo(); // nothing to undo
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 2, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "insert", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ // push after undo - check that undone commands get deleted
+
+ 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
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new RemoveCommand(&str, 2, 2));
+ QCOMPARE(str, QString("heo"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count - still 2, last command got deleted
+ 2, // index
+ true, // canUndo
+ "remove", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("hello"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ true, // canRedo
+ "remove", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 2, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "insert", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new InsertCommand(&str, 0, "goodbye"));
+ QCOMPARE(str, QString("goodbye"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count - two commands got deleted
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+}
+
+void tst_QUndoStack::setIndex()
+{
+ QUndoStack stack;
+ QScopedPointer<QAction> undoAction(stack.createUndoAction(nullptr, QString("foo")));
+ QScopedPointer<QAction> redoAction(stack.createRedoAction(nullptr, 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);
+ QString str;
+
+ stack.setIndex(10); // should do nothing
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 0, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.setIndex(0); // should do nothing
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 0, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.setIndex(-10); // should do nothing
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 0, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.push(new InsertCommand(&str, 0, "hello"));
+ QCOMPARE(str, QString("hello"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new InsertCommand(&str, 2, "123"));
+ QCOMPARE(str, QString("he123llo"));
+ 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
+
+ stack.setIndex(2);
+ QCOMPARE(str, QString("he123llo"));
+ 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
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.setIndex(0);
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 2, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "insert", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.setIndex(10); // should set index to 2
+ QCOMPARE(str, QString("he123llo"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.setIndex(-10); // should set index to 0
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 2, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "insert", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.setIndex(1);
+ QCOMPARE(str, QString("hello"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ true, // canRedo
+ "insert", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.setIndex(2);
+ QCOMPARE(str, QString("he123llo"));
+ 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
+}
+
+void tst_QUndoStack::setClean()
+{
+ QUndoStack stack;
+ QScopedPointer<QAction> undoAction(stack.createUndoAction(nullptr, QString("foo")));
+ QScopedPointer<QAction> redoAction(stack.createRedoAction(nullptr, 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);
+ QString str;
+
+ QCOMPARE(stack.cleanIndex(), 0);
+ stack.setClean();
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 0, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+ QCOMPARE(stack.cleanIndex(), 0);
+
+ stack.push(new InsertCommand(&str, 0, "goodbye"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+ QCOMPARE(stack.cleanIndex(), 0);
+
+ stack.setClean();
+ QCOMPARE(str, QString("goodbye"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 1, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+ QCOMPARE(stack.cleanIndex(), 1);
+
+ stack.push(new AppendCommand(&str, " cowboy"));
+ QCOMPARE(str, QString("goodbye cowboy"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+ QCOMPARE(stack.cleanIndex(), 1);
+
+ stack.undo(); // reaching clean state from above
+ QCOMPARE(str, QString("goodbye"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 2, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ true, // canRedo
+ "append", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+ QCOMPARE(stack.cleanIndex(), 1);
+
+ stack.undo();
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "insert", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+ QCOMPARE(stack.cleanIndex(), 1);
+
+ stack.redo(); // reaching clean state from below
+ QCOMPARE(str, QString("goodbye"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 2, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ true, // canRedo
+ "append", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+ QCOMPARE(stack.cleanIndex(), 1);
+
+ stack.undo();
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "insert", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+ QCOMPARE(stack.cleanIndex(), 1);
+
+ stack.push(new InsertCommand(&str, 0, "foo")); // the clean state gets deleted!
+ QCOMPARE(str, QString("foo"));
+ 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
+ QCOMPARE(stack.cleanIndex(), -1);
+
+ stack.undo();
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "insert", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+ QCOMPARE(stack.cleanIndex(), -1);
+
+ stack.setClean();
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 1, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "insert", // redoText
+ true, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+ QCOMPARE(stack.cleanIndex(), 0);
+
+ stack.resetClean();
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "insert", // redoText
+ true, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+ QCOMPARE(stack.cleanIndex(), -1);
+
+ stack.redo();
+ QCOMPARE(str, QString("foo"));
+ 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
+ QCOMPARE(stack.cleanIndex(), -1);
+
+ stack.setClean();
+ QCOMPARE(str, QString("foo"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 1, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+ QCOMPARE(stack.cleanIndex(), 1);
+
+ stack.undo();
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "insert", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+ QCOMPARE(stack.cleanIndex(), 1);
+
+ stack.resetClean();
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "insert", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+ QCOMPARE(stack.cleanIndex(), -1);
+}
+
+void tst_QUndoStack::clear()
+{
+ QUndoStack stack;
+ QScopedPointer<QAction> undoAction(stack.createUndoAction(nullptr, QString("foo")));
+ QScopedPointer<QAction> redoAction(stack.createRedoAction(nullptr, 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);
+ QString str;
+
+ stack.clear();
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 0, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.push(new InsertCommand(&str, 0, "hello"));
+ QCOMPARE(str, QString("hello"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new InsertCommand(&str, 2, "123"));
+ QCOMPARE(str, QString("he123llo"));
+ 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
+
+ stack.clear();
+ QCOMPARE(str, QString("he123llo"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 0, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ str.clear();
+ stack.push(new InsertCommand(&str, 0, "hello"));
+ QCOMPARE(str, QString("hello"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new InsertCommand(&str, 2, "123"));
+ QCOMPARE(str, QString("he123llo"));
+ 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
+
+ stack.setIndex(0);
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 2, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "insert", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.clear();
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 0, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+}
+
+void tst_QUndoStack::childCommand()
+{
+ QUndoStack stack;
+ QScopedPointer<QAction> undoAction(stack.createUndoAction(nullptr, QString("foo")));
+ QScopedPointer<QAction> redoAction(stack.createRedoAction(nullptr, 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);
+ QString str;
+
+ stack.push(new InsertCommand(&str, 0, "hello"));
+ QCOMPARE(str, QString("hello"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ QUndoCommand *cmd = new QUndoCommand();
+ cmd->setText("ding");
+ new InsertCommand(&str, 5, "world", cmd);
+ new RemoveCommand(&str, 4, 1, cmd);
+ stack.push(cmd);
+ QCOMPARE(str, QString("hellworld"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "ding", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("hello"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ true, // canRedo
+ "ding", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.redo();
+ QCOMPARE(str, QString("hellworld"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "ding", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+}
+
+void tst_QUndoStack::macroBeginEnd()
+{
+ QUndoStack stack;
+ QScopedPointer<QAction> undoAction(stack.createUndoAction(nullptr, QString("foo")));
+ QScopedPointer<QAction> redoAction(stack.createRedoAction(nullptr, 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);
+ QString str;
+
+ stack.beginMacro("ding");
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.setClean(); // should do nothing
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.undo(); // should do nothing
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.redo(); // should do nothing
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.setIndex(0); // should do nothing
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 0, // 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
+ 1, // count
+ 1, // index - endMacro() increments index
+ true, // canUndo
+ "ding", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new InsertCommand(&str, 0, "h"));
+ QCOMPARE(str, QString("h"));
+ 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
+
+ stack.push(new InsertCommand(&str, 1, "owdy"));
+ QCOMPARE(str, QString("howdy"));
+ 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
+
+ stack.setIndex(2);
+ QCOMPARE(str, QString("h"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ true, // canUndo
+ "insert", // undoText
+ true, // canRedo
+ "insert", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.beginMacro("dong"); // the "owdy" command gets deleted
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new InsertCommand(&str, 1, "ello"));
+ QCOMPARE(str, QString("hello"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.push(new RemoveCommand(&str, 1, 2));
+ QCOMPARE(str, QString("hlo"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.beginMacro("dong2");
+ QCOMPARE(str, QString("hlo"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.push(new RemoveCommand(&str, 1, 1));
+ QCOMPARE(str, QString("ho"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.endMacro();
+ QCOMPARE(str, QString("ho"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.endMacro();
+ QCOMPARE(str, QString("ho"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 3, // index
+ true, // canUndo
+ "dong", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("h"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ true, // canUndo
+ "insert", // undoText
+ true, // canRedo
+ "dong", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString(""));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 1, // index
+ true, // canUndo
+ "ding", // undoText
+ true, // canRedo
+ "insert", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.setIndex(3);
+ QCOMPARE(str, QString("ho"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 3, // index
+ true, // canUndo
+ "dong", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.setIndex(1);
+ QCOMPARE(str, QString());
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 1, // index
+ true, // canUndo
+ "ding", // undoText
+ true, // canRedo
+ "insert", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+}
+
+void tst_QUndoStack::compression()
+{
+ QUndoStack stack;
+ QScopedPointer<QAction> undoAction(stack.createUndoAction(nullptr, QString("foo")));
+ QScopedPointer<QAction> redoAction(stack.createRedoAction(nullptr, 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);
+ QString str;
+
+ AppendCommand::delete_cnt = 0;
+
+ stack.push(new InsertCommand(&str, 0, "ene"));
+ 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
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new AppendCommand(&str, " due")); // #1
+ QCOMPARE(str, QString("ene due"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new AppendCommand(&str, " rike")); // #2 should merge
+ QCOMPARE(str, QString("ene due rike"));
+ QCOMPARE(AppendCommand::delete_cnt, 1); // #2 should be deleted
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "append", // 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
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.push(new AppendCommand(&str, " fake")); // #3 should NOT merge, since the stack was clean
+ QCOMPARE(str, QString("ene due rike fake")); // and we want to be able to return to this state
+ QCOMPARE(AppendCommand::delete_cnt, 1); // #3 should not be deleted
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 3, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("ene due rike"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 3, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ true, // canRedo
+ "append", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("ene"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 1, // index
+ true, // canUndo
+ "insert", // undoText
+ true, // canRedo
+ "append", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new AppendCommand(&str, "ma", true)); // #4 clean state gets deleted!
+ QCOMPARE(str, QString("enema"));
+ QCOMPARE(AppendCommand::delete_cnt, 3); // #1 got deleted
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new AppendCommand(&str, "trix")); // #5 should NOT merge
+ QCOMPARE(str, QString("enematrix"));
+ QCOMPARE(AppendCommand::delete_cnt, 3);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 3, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("enema"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ true, // canRedo
+ "append", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ // and now for command compression inside macros
+
+ stack.setClean();
+ QCOMPARE(str, QString("enema"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 3, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ true, // canRedo
+ "append", // redoText
+ true, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.beginMacro("ding");
+ QCOMPARE(str, QString("enema"));
+ QCOMPARE(AppendCommand::delete_cnt, 4); // #5 gets deleted
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ AppendCommand *merge_cmd = new AppendCommand(&str, "top");
+ stack.push(merge_cmd); // #6
+ QCOMPARE(merge_cmd->merged, false);
+ QCOMPARE(str, QString("enematop"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.push(new AppendCommand(&str, "eja")); // #7 should merge
+ QCOMPARE(str, QString("enematopeja"));
+ QCOMPARE(merge_cmd->merged, true);
+ QCOMPARE(AppendCommand::delete_cnt, 5); // #7 gets deleted
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+ merge_cmd->merged = false;
+
+ stack.push(new InsertCommand(&str, 2, "123")); // should not merge
+ QCOMPARE(str, QString("en123ematopeja"));
+ QCOMPARE(merge_cmd->merged, false);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.endMacro();
+ QCOMPARE(str, QString("en123ematopeja"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 3, // index
+ true, // canUndo
+ "ding", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("enema"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 3, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ true, // canRedo
+ "ding", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.redo();
+ QCOMPARE(str, QString("en123ematopeja"));
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 3, // index
+ true, // canUndo
+ "ding", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+}
+
+void tst_QUndoStack::obsolete()
+{
+ QUndoStack stack;
+ QScopedPointer<QAction> undoAction(stack.createUndoAction(nullptr, QString("foo")));
+ QScopedPointer<QAction> redoAction(stack.createRedoAction(nullptr, 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;
+ QScopedPointer<QAction> undoAction(stack.createUndoAction(nullptr, QString("foo")));
+ QScopedPointer<QAction> redoAction(stack.createRedoAction(nullptr, 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);
+ AppendCommand::delete_cnt = 0;
+ QString str;
+
+ QCOMPARE(stack.undoLimit(), 0);
+ stack.setUndoLimit(2);
+ QCOMPARE(stack.undoLimit(), 2);
+
+ stack.push(new AppendCommand(&str, "1", true));
+ QCOMPARE(str, QString("1"));
+ QCOMPARE(AppendCommand::delete_cnt, 0);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 1, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new AppendCommand(&str, "2", true));
+ QCOMPARE(str, QString("12"));
+ QCOMPARE(AppendCommand::delete_cnt, 0);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.setClean();
+ QCOMPARE(str, QString("12"));
+ QCOMPARE(AppendCommand::delete_cnt, 0);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.push(new AppendCommand(&str, "3", true));
+ QCOMPARE(str, QString("123"));
+ QCOMPARE(AppendCommand::delete_cnt, 1);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new AppendCommand(&str, "4", true));
+ QCOMPARE(str, QString("1234"));
+ QCOMPARE(AppendCommand::delete_cnt, 2);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("123"));
+ QCOMPARE(AppendCommand::delete_cnt, 2);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 1, // index
+ true, // canUndo
+ "append", // undoText
+ true, // canRedo
+ "append", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("12"));
+ QCOMPARE(AppendCommand::delete_cnt, 2);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ true, // clean
+ 2, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "append", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new AppendCommand(&str, "3", true));
+ QCOMPARE(str, QString("123"));
+ QCOMPARE(AppendCommand::delete_cnt, 4);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 1, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ true, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new AppendCommand(&str, "4", true));
+ QCOMPARE(str, QString("1234"));
+ QCOMPARE(AppendCommand::delete_cnt, 4);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new AppendCommand(&str, "5", true));
+ QCOMPARE(str, QString("12345"));
+ QCOMPARE(AppendCommand::delete_cnt, 5);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("1234"));
+ QCOMPARE(AppendCommand::delete_cnt, 5);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 1, // index
+ true, // canUndo
+ "append", // undoText
+ true, // canRedo
+ "append", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("123"));
+ QCOMPARE(AppendCommand::delete_cnt, 5);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "append", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new AppendCommand(&str, "4", true));
+ QCOMPARE(str, QString("1234"));
+ QCOMPARE(AppendCommand::delete_cnt, 7);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 1, // count
+ 1, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new AppendCommand(&str, "5"));
+ QCOMPARE(str, QString("12345"));
+ QCOMPARE(AppendCommand::delete_cnt, 7);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new AppendCommand(&str, "6", true)); // should be merged
+ QCOMPARE(str, QString("123456"));
+ QCOMPARE(AppendCommand::delete_cnt, 8);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "append", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.beginMacro("foo");
+ QCOMPARE(str, QString("123456"));
+ QCOMPARE(AppendCommand::delete_cnt, 8);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.push(new AppendCommand(&str, "7", true));
+ QCOMPARE(str, QString("1234567"));
+ QCOMPARE(AppendCommand::delete_cnt, 8);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.push(new AppendCommand(&str, "8"));
+ QCOMPARE(str, QString("12345678"));
+ QCOMPARE(AppendCommand::delete_cnt, 8);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 3, // count
+ 2, // index
+ false, // canUndo
+ "", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ false, // indexChanged
+ false, // undoChanged
+ false); // redoChanged
+
+ stack.endMacro();
+ QCOMPARE(str, QString("12345678"));
+ QCOMPARE(AppendCommand::delete_cnt, 9);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 2, // index
+ true, // canUndo
+ "foo", // undoText
+ false, // canRedo
+ "", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("123456"));
+ QCOMPARE(AppendCommand::delete_cnt, 9);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 1, // index
+ true, // canUndo
+ "append", // undoText
+ true, // canRedo
+ "foo", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+
+ stack.undo();
+ QCOMPARE(str, QString("1234"));
+ QCOMPARE(AppendCommand::delete_cnt, 9);
+ checkState(redoTextChangedSpy,
+ canRedoChangedSpy,
+ undoTextChangedSpy,
+ redoAction,
+ undoAction,
+ canUndoChangedSpy,
+ cleanChangedSpy,
+ indexChangedSpy,
+ stack,
+ false, // clean
+ 2, // count
+ 0, // index
+ false, // canUndo
+ "", // undoText
+ true, // canRedo
+ "append", // redoText
+ false, // cleanChanged
+ true, // indexChanged
+ true, // undoChanged
+ true); // redoChanged
+}
+
+void tst_QUndoStack::commandTextFormat()
+{
+#if !QT_CONFIG(process)
+ QSKIP("No QProcess available");
+#else
+ QString binDir = QLibraryInfo::location(QLibraryInfo::BinariesPath);
+
+ if (QProcess::execute(binDir + "/lrelease -version") != 0)
+ QSKIP("lrelease is missing or broken");
+
+ const QString tsFile = QFINDTESTDATA("testdata/qundostack.ts");
+ QVERIFY(!tsFile.isEmpty());
+ QFile::remove("qundostack.qm"); // Avoid confusion by strays.
+ QVERIFY(!QProcess::execute(binDir + "/lrelease -silent " + tsFile + " -qm qundostack.qm"));
+
+ QTranslator translator;
+ QVERIFY(translator.load("qundostack.qm"));
+ QFile::remove("qundostack.qm");
+ qApp->installTranslator(&translator);
+
+ QUndoStack stack;
+ QScopedPointer<QAction> undo_action(stack.createUndoAction(nullptr));
+ QScopedPointer<QAction> redo_action(stack.createRedoAction(nullptr));
+
+ QCOMPARE(undo_action->text(), QString("Undo-default-text"));
+ QCOMPARE(redo_action->text(), QString("Redo-default-text"));
+
+ QString str;
+
+ stack.push(new AppendCommand(&str, "foo"));
+ QCOMPARE(undo_action->text(), QString("undo-prefix append undo-suffix"));
+ QCOMPARE(redo_action->text(), QString("Redo-default-text"));
+
+ stack.push(new InsertCommand(&str, 0, "bar"));
+ stack.undo();
+ QCOMPARE(undo_action->text(), QString("undo-prefix append undo-suffix"));
+ QCOMPARE(redo_action->text(), QString("redo-prefix insert redo-suffix"));
+
+ stack.undo();
+ QCOMPARE(undo_action->text(), QString("Undo-default-text"));
+ QCOMPARE(redo_action->text(), QString("redo-prefix append redo-suffix"));
+
+ qApp->removeTranslator(&translator);
+#endif
+}
+
+void tst_QUndoStack::separateUndoText()
+{
+ QUndoStack stack;
+ QScopedPointer<QAction> undo_action(stack.createUndoAction(nullptr));
+ QScopedPointer<QAction> redo_action(stack.createRedoAction(nullptr));
+
+ QUndoCommand *command1 = new IdleCommand();
+ QUndoCommand *command2 = new IdleCommand();
+ stack.push(command1);
+ stack.push(command2);
+ stack.undo();
+
+ QCOMPARE(undo_action->text(), QString("Undo idle-action"));
+ QCOMPARE(redo_action->text(), QString("Redo idle-action"));
+ QCOMPARE(command1->actionText(), QString("idle-action"));
+
+ QCOMPARE(command1->text(), QString("idle-item"));
+ QCOMPARE(stack.text(0), QString("idle-item"));
+
+ command1->setText("idle");
+ QCOMPARE(command1->actionText(), QString("idle"));
+ QCOMPARE(command1->text(), QString("idle"));
+
+ command1->setText("idle-item\nidle-action");
+ QCOMPARE(command1->actionText(), QString("idle-action"));
+ QCOMPARE(command1->text(), QString("idle-item"));
+}
+
+QTEST_MAIN(tst_QUndoStack)
+
+#include "tst_qundostack.moc"
diff --git a/tests/auto/gui/util/util.pro b/tests/auto/gui/util/util.pro
index 961424cc35..7523e01ca4 100644
--- a/tests/auto/gui/util/util.pro
+++ b/tests/auto/gui/util/util.pro
@@ -9,4 +9,6 @@ SUBDIRS= \
qshadergraphloader \
qshadernodes \
qshadernodesloader \
- qtexturefilereader
+ qtexturefilereader \
+ qundogroup \
+ qundostack