summaryrefslogtreecommitdiffstats
path: root/tests/auto/widgets/util
diff options
context:
space:
mode:
authorJo Asplin <jo.asplin@nokia.com>2011-10-20 13:17:26 +0200
committerQt by Nokia <qt-info@nokia.com>2011-10-20 19:45:41 +0200
commit9f1aa866bda7678261f2f441d4cfd5bb524c2411 (patch)
tree5028f578122e7feb9200d571405494c73d96db89 /tests/auto/widgets/util
parent78d02e93aca5325fc5be9bfd275862795207abaa (diff)
Moved tests into integrationtests/ and widgets/
Task-number: QTBUG-19013 Change-Id: Ibb776f5967c0645ce6d22ef7afdc40657c575461 Reviewed-by: Holger Ihrig <holger.ihrig@nokia.com>
Diffstat (limited to 'tests/auto/widgets/util')
-rw-r--r--tests/auto/widgets/util/qcompleter/.gitignore1
-rw-r--r--tests/auto/widgets/util/qcompleter/qcompleter.pro11
-rw-r--r--tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp1519
-rw-r--r--tests/auto/widgets/util/qscroller/qscroller.pro4
-rw-r--r--tests/auto/widgets/util/qscroller/tst_qscroller.cpp530
-rw-r--r--tests/auto/widgets/util/qsystemtrayicon/.gitignore1
-rw-r--r--tests/auto/widgets/util/qsystemtrayicon/icons/icon.pngbin0 -> 1086 bytes
-rw-r--r--tests/auto/widgets/util/qsystemtrayicon/qsystemtrayicon.pro9
-rw-r--r--tests/auto/widgets/util/qsystemtrayicon/tst_qsystemtrayicon.cpp152
-rw-r--r--tests/auto/widgets/util/qundogroup/.gitignore1
-rw-r--r--tests/auto/widgets/util/qundogroup/qundogroup.pro4
-rw-r--r--tests/auto/widgets/util/qundogroup/testdata/qundogroup.ts25
-rw-r--r--tests/auto/widgets/util/qundogroup/tst_qundogroup.cpp668
-rw-r--r--tests/auto/widgets/util/qundostack/.gitignore1
-rw-r--r--tests/auto/widgets/util/qundostack/qundostack.pro4
-rw-r--r--tests/auto/widgets/util/qundostack/testdata/qundostack.ts25
-rw-r--r--tests/auto/widgets/util/qundostack/tst_qundostack.cpp3039
-rw-r--r--tests/auto/widgets/util/util.pro11
18 files changed, 6005 insertions, 0 deletions
diff --git a/tests/auto/widgets/util/qcompleter/.gitignore b/tests/auto/widgets/util/qcompleter/.gitignore
new file mode 100644
index 0000000000..4db1c0d5c2
--- /dev/null
+++ b/tests/auto/widgets/util/qcompleter/.gitignore
@@ -0,0 +1 @@
+tst_qcompleter
diff --git a/tests/auto/widgets/util/qcompleter/qcompleter.pro b/tests/auto/widgets/util/qcompleter/qcompleter.pro
new file mode 100644
index 0000000000..4d58e6b813
--- /dev/null
+++ b/tests/auto/widgets/util/qcompleter/qcompleter.pro
@@ -0,0 +1,11 @@
+load(qttest_p4)
+TEMPLATE = app
+TARGET = tst_qcompleter
+QT += widgets
+DEPENDPATH += .
+INCLUDEPATH += . ..
+
+# Input
+SOURCES += tst_qcompleter.cpp
+
+CONFIG += insignificant_test # QTBUG-21424
diff --git a/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp b/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp
new file mode 100644
index 0000000000..ccf3c449b3
--- /dev/null
+++ b/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp
@@ -0,0 +1,1519 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtGui>
+#include <QtWidgets>
+#include <QtDebug>
+#include <QPair>
+#include <QList>
+#include <QPointer>
+
+#include "../../../../shared/filesystem.h"
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class CsvCompleter : public QCompleter
+{
+ Q_OBJECT
+public:
+ CsvCompleter(QObject *parent = 0) : QCompleter(parent), csv(true) { }
+
+ QString pathFromIndex(const QModelIndex& sourceIndex) const;
+
+ void setCsvCompletion(bool set) { csv = set; }
+
+protected:
+ QStringList splitPath(const QString &path) const {
+ return csv ? path.split(",") : QCompleter::splitPath(path);
+ }
+
+private:
+ bool csv;
+};
+
+QString CsvCompleter::pathFromIndex(const QModelIndex& si) const
+{
+ if (!csv)
+ return QCompleter::pathFromIndex(si);
+
+ if (!si.isValid())
+ return QString();
+
+ QModelIndex idx = si;
+ QStringList list;
+ do {
+ QString t = model()->data(idx, completionRole()).toString();
+ list.prepend(t);
+ QModelIndex parent = idx.parent();
+ idx = parent.sibling(parent.row(), si.column());
+ } while (idx.isValid());
+
+ if (list.count() == 1)
+ return list[0];
+ return list.join(",");
+}
+
+class tst_QCompleter : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QCompleter();
+ ~tst_QCompleter();
+
+private slots:
+ void getSetCheck();
+
+ void multipleWidgets();
+ void focusIn();
+
+ void csMatchingOnCsSortedModel_data();
+ void csMatchingOnCsSortedModel();
+ void ciMatchingOnCiSortedModel_data();
+ void ciMatchingOnCiSortedModel();
+
+ void ciMatchingOnCsSortedModel_data();
+ void ciMatchingOnCsSortedModel();
+ void csMatchingOnCiSortedModel_data();
+ void csMatchingOnCiSortedModel();
+
+ void directoryModel_data();
+ void directoryModel();
+ void fileSystemModel_data();
+ void fileSystemModel();
+
+ void changingModel_data();
+ void changingModel();
+
+ void sortedEngineRowCount_data();
+ void sortedEngineRowCount();
+ void unsortedEngineRowCount_data();
+ void unsortedEngineRowCount();
+
+ void currentRow();
+ void sortedEngineMapFromSource();
+ void unsortedEngineMapFromSource();
+
+ void historySearch();
+
+ void modelDeletion();
+ void setters();
+
+ void dynamicSortOrder();
+ void disabledItems();
+
+ // task-specific tests below me
+ void task178797_activatedOnReturn();
+ void task189564_omitNonSelectableItems();
+ void task246056_setCompletionPrefix();
+ void task250064_lostFocus();
+
+ void task253125_lineEditCompletion_data();
+ void task253125_lineEditCompletion();
+ void task247560_keyboardNavigation();
+ void QTBUG_14292_filesystem();
+
+private:
+ void filter(bool assync = false);
+ void testRowCount();
+ enum ModelType {
+ CASE_SENSITIVELY_SORTED_MODEL,
+ CASE_INSENSITIVELY_SORTED_MODEL,
+ DIRECTORY_MODEL,
+ HISTORY_MODEL,
+ FILESYSTEM_MODEL
+ };
+ void setSourceModel(ModelType);
+
+ CsvCompleter *completer;
+ QTreeWidget *treeWidget;
+ const int completionColumn;
+ const int columnCount;
+};
+
+tst_QCompleter::tst_QCompleter() : completer(0), completionColumn(0), columnCount(3)
+{
+ treeWidget = new QTreeWidget;
+ treeWidget->setColumnCount(columnCount);
+}
+
+tst_QCompleter::~tst_QCompleter()
+{
+ delete treeWidget;
+ delete completer;
+}
+
+void tst_QCompleter::setSourceModel(ModelType type)
+{
+ QString text;
+ QTreeWidgetItem *parent, *child;
+ treeWidget->clear();
+ switch(type) {
+ case CASE_SENSITIVELY_SORTED_MODEL:
+ // Creates a tree model with top level items P0, P1, .., p0, p1,..
+ // Each of these items parents have children (for P0 - c0P0, c1P0,...)
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < 5; j++) {
+ parent = new QTreeWidgetItem(treeWidget);
+ text.sprintf("%c%i", i == 0 ? 'P' : 'p', j);
+ parent->setText(completionColumn, text);
+ for (int k = 0; k < 5; k++) {
+ child = new QTreeWidgetItem(parent);
+ QString t = QString().sprintf("c%i", k) + text;
+ child->setText(completionColumn, t);
+ }
+ }
+ }
+ completer->setModel(treeWidget->model());
+ completer->setCompletionColumn(completionColumn);
+ break;
+ case CASE_INSENSITIVELY_SORTED_MODEL:
+ case HISTORY_MODEL:
+ // Creates a tree model with top level items P0, p0, P1, p1,...
+ // Each of these items have children c0p0, c1p0,..
+ for (int i = 0; i < 5; i++) {
+ for (int j = 0; j < 2; j++) {
+ parent = new QTreeWidgetItem(treeWidget);
+ text.sprintf("%c%i", j == 0 ? 'P' : 'p', i);
+ parent->setText(completionColumn, text);
+ for (int k = 0; k < 5; k++) {
+ child = new QTreeWidgetItem(parent);
+ QString t = QString().sprintf("c%i", k) + text;
+ child->setText(completionColumn, t);
+ }
+ }
+ }
+ completer->setModel(treeWidget->model());
+ completer->setCompletionColumn(completionColumn);
+ if (type == CASE_INSENSITIVELY_SORTED_MODEL)
+ break;
+ parent = new QTreeWidgetItem(treeWidget);
+ parent->setText(completionColumn, QLatin1String("p3,c3p3"));
+ parent = new QTreeWidgetItem(treeWidget);
+ parent->setText(completionColumn, QLatin1String("p2,c4p2"));
+ break;
+ case DIRECTORY_MODEL:
+ completer->setCsvCompletion(false);
+ completer->setModel(new QDirModel(completer));
+ completer->setCompletionColumn(0);
+ break;
+ case FILESYSTEM_MODEL:
+ completer->setCsvCompletion(false);
+ {
+ QFileSystemModel *m = new QFileSystemModel(completer);
+ m->setRootPath("/");
+ completer->setModel(m);
+ }
+ completer->setCompletionColumn(0);
+ break;
+ default:
+ qDebug() << "Invalid type";
+ }
+}
+
+void tst_QCompleter::filter(bool assync)
+{
+ QFETCH(QString, filterText);
+ QFETCH(QString, step);
+ QFETCH(QString, completion);
+ QFETCH(QString, completionText);
+
+ if (filterText.compare("FILTERING_OFF", Qt::CaseInsensitive) == 0) {
+ completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
+ return;
+ }
+
+ int times = 0;
+retry:
+
+ completer->setCompletionPrefix(filterText);
+
+ for (int i = 0; i < step.length(); i++) {
+ int row = completer->currentRow();
+ switch (step[i].toUpper().toAscii()) {
+ case 'P': --row; break;
+ case 'N': ++row; break;
+ case 'L': row = completer->completionCount() - 1; break;
+ case 'F': row = 0; break;
+ default:
+ QFAIL(qPrintable(QString(
+ "Problem with 'step' value in test data: %1 (only P, N, L and F are allowed)."
+ ).arg(step[i])));
+ }
+ completer->setCurrentRow(row);
+ }
+
+ int r = QString::compare(completer->currentCompletion(), completionText, completer->caseSensitivity());
+ if (assync && r && times < 10) {
+ times++;
+ QTest::qWait(50*times);
+ goto retry;
+ }
+ QVERIFY(!r);
+}
+
+// Testing get/set functions
+void tst_QCompleter::getSetCheck()
+{
+ QStandardItemModel model(3,3);
+ QCompleter completer(&model);
+
+ // QString QCompleter::completionPrefix()
+ // void QCompleter::setCompletionPrefix(QString)
+ completer.setCompletionPrefix(QString("te"));
+ QCOMPARE(completer.completionPrefix(), QString("te"));
+ completer.setCompletionPrefix(QString());
+ QCOMPARE(completer.completionPrefix(), QString());
+
+ // ModelSorting QCompleter::modelSorting()
+ // void QCompleter::setModelSorting(ModelSorting)
+ completer.setModelSorting(QCompleter::CaseSensitivelySortedModel);
+ QCOMPARE(completer.modelSorting(), QCompleter::CaseSensitivelySortedModel);
+ completer.setModelSorting(QCompleter::CaseInsensitivelySortedModel);
+ QCOMPARE(completer.modelSorting(), QCompleter::CaseInsensitivelySortedModel);
+ completer.setModelSorting(QCompleter::UnsortedModel);
+ QCOMPARE(completer.modelSorting(), QCompleter::UnsortedModel);
+
+ // CompletionMode QCompleter::completionMode()
+ // void QCompleter::setCompletionMode(CompletionMode)
+ QCOMPARE(completer.completionMode(), QCompleter::PopupCompletion); // default value
+ completer.setCompletionMode(QCompleter::UnfilteredPopupCompletion);
+ QCOMPARE(completer.completionMode(), QCompleter::UnfilteredPopupCompletion);
+ completer.setCompletionMode(QCompleter::InlineCompletion);
+ QCOMPARE(completer.completionMode(), QCompleter::InlineCompletion);
+
+ // int QCompleter::completionColumn()
+ // void QCompleter::setCompletionColumn(int)
+ completer.setCompletionColumn(2);
+ QCOMPARE(completer.completionColumn(), 2);
+ completer.setCompletionColumn(1);
+ QCOMPARE(completer.completionColumn(), 1);
+
+ // int QCompleter::completionRole()
+ // void QCompleter::setCompletionRole(int)
+ QCOMPARE(completer.completionRole(), static_cast<int>(Qt::EditRole)); // default value
+ completer.setCompletionRole(Qt::DisplayRole);
+ QCOMPARE(completer.completionRole(), static_cast<int>(Qt::DisplayRole));
+
+ // int QCompleter::maxVisibleItems()
+ // void QCompleter::setMaxVisibleItems(int)
+ QCOMPARE(completer.maxVisibleItems(), 7); // default value
+ completer.setMaxVisibleItems(10);
+ QCOMPARE(completer.maxVisibleItems(), 10);
+ QTest::ignoreMessage(QtWarningMsg, "QCompleter::setMaxVisibleItems: "
+ "Invalid max visible items (-2147483648) must be >= 0");
+ completer.setMaxVisibleItems(INT_MIN);
+ QCOMPARE(completer.maxVisibleItems(), 10); // Cannot be set to something negative => old value
+
+ // Qt::CaseSensitivity QCompleter::caseSensitivity()
+ // void QCompleter::setCaseSensitivity(Qt::CaseSensitivity)
+ QCOMPARE(completer.caseSensitivity(), Qt::CaseSensitive); // default value
+ completer.setCaseSensitivity(Qt::CaseInsensitive);
+ QCOMPARE(completer.caseSensitivity(), Qt::CaseInsensitive);
+
+ // bool QCompleter::wrapAround()
+ // void QCompleter::setWrapAround(bool)
+ QCOMPARE(completer.wrapAround(), true); // default value
+ completer.setWrapAround(false);
+ QCOMPARE(completer.wrapAround(), false);
+}
+
+void tst_QCompleter::csMatchingOnCsSortedModel_data()
+{
+ delete completer;
+ completer = new CsvCompleter;
+ completer->setModelSorting(QCompleter::CaseSensitivelySortedModel);
+ completer->setCaseSensitivity(Qt::CaseSensitive);
+ setSourceModel(CASE_SENSITIVELY_SORTED_MODEL);
+
+ QTest::addColumn<QString>("filterText");
+ QTest::addColumn<QString>("step");
+ QTest::addColumn<QString>("completion");
+ QTest::addColumn<QString>("completionText");
+
+ for (int i = 0; i < 2; i++) {
+ if (i == 1)
+ QTest::newRow("FILTERING_OFF") << "FILTERING_OFF" << "" << "" << "";
+
+ // Plain text filter
+ QTest::newRow("()") << "" << "" << "P0" << "P0";
+ QTest::newRow("()F") << "" << "F" << "P0" << "P0";
+ QTest::newRow("()L") << "" << "L" << "p4" << "p4";
+ QTest::newRow("()L") << "" << "L" << "p4" << "p4";
+ QTest::newRow("()N") << "" << "N" << "P1" << "P1";
+ QTest::newRow("(P)") << "P" << "" << "P0" << "P0";
+ QTest::newRow("(P)F") << "P" << "" << "P0" << "P0";
+ QTest::newRow("(P)L") << "P" << "L" << "P4" << "P4";
+ QTest::newRow("(p)") << "p" << "" << "p0" << "p0";
+ QTest::newRow("(p)N") << "p" << "N" << "p1" << "p1";
+ QTest::newRow("(p)NN") << "p" << "NN" << "p2" << "p2";
+ QTest::newRow("(p)NNN") << "p" << "NNN" << "p3" << "p3";
+ QTest::newRow("(p)NNNN") << "p" << "NNNN" << "p4" << "p4";
+ QTest::newRow("(p1)") << "p1" << "" << "p1" << "p1";
+ QTest::newRow("(p11)") << "p11" << "" << "" << "";
+
+ // Tree filter
+ QTest::newRow("(P0,)") << "P0," << "" << "c0P0" << "P0,c0P0";
+ QTest::newRow("(P0,c)") << "P0,c" << "" << "c0P0" << "P0,c0P0";
+ QTest::newRow("(P0,c1)") << "P0,c1" << "" << "c1P0" << "P0,c1P0";
+ QTest::newRow("(P0,c3P0)") << "P0,c3P0" << "" << "c3P0" << "P0,c3P0";
+ QTest::newRow("(P3,c)F") << "P3,c" << "F" << "c0P3" << "P3,c0P3";
+ QTest::newRow("(P3,c)L") << "P3,c" << "L" << "c4P3" << "P3,c4P3";
+ QTest::newRow("(P3,c)N") << "P3,c" << "N" << "c1P3" << "P3,c1P3";
+ QTest::newRow("(P3,c)NN") << "P3,c" << "NN" << "c2P3" << "P3,c2P3";
+ QTest::newRow("(P3,,c)") << "P3,,c" << "" << "" << "";
+ QTest::newRow("(P3,c0P3,)") << "P3,c0P3," << "" << "" << "";
+ QTest::newRow("(P,)") << "P," << "" << "" << "";
+ }
+}
+
+void tst_QCompleter::csMatchingOnCsSortedModel()
+{
+ filter();
+}
+
+void tst_QCompleter::ciMatchingOnCiSortedModel_data()
+{
+ delete completer;
+ completer = new CsvCompleter;
+ completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
+ completer->setCaseSensitivity(Qt::CaseInsensitive);
+ setSourceModel(CASE_INSENSITIVELY_SORTED_MODEL);
+
+ QTest::addColumn<QString>("filterText");
+ QTest::addColumn<QString>("step");
+ QTest::addColumn<QString>("completion");
+ QTest::addColumn<QString>("completionText");
+
+ for (int i = 0; i < 2; i++) {
+ if (i == 1)
+ QTest::newRow("FILTERING_OFF") << "FILTERING_OFF" << "" << "" << "";
+
+ // Plain text filter
+ QTest::newRow("()") << "" << "" << "P0" << "P0";
+ QTest::newRow("()F") << "" << "F" << "P0" << "P0";
+ QTest::newRow("()L") << "" << "L" << "p4" << "p4";
+ QTest::newRow("()N") << "" << "N" << "p0" << "p0";
+ QTest::newRow("(P)") << "P" << "" << "P0" << "P0";
+ QTest::newRow("(P)F") << "P" << "" << "P0" << "P0";
+ QTest::newRow("(P)L") << "P" << "L" << "p4" << "p4";
+ QTest::newRow("(p)") << "p" << "" << "P0" << "P0";
+ QTest::newRow("(p)N") << "p" << "N" << "p0" << "p0";
+ QTest::newRow("(p)NN") << "p" << "NN" << "P1" << "P1";
+ QTest::newRow("(p)NNN") << "p" << "NNN" << "p1" << "p1";
+ QTest::newRow("(p1)") << "p1" << "" << "P1" << "P1";
+ QTest::newRow("(p1)N") << "p1" << "N" << "p1" << "p1";
+ QTest::newRow("(p11)") << "p11" << "" << "" << "";
+
+ //// Tree filter
+ QTest::newRow("(p0,)") << "p0," << "" << "c0P0" << "P0,c0P0";
+ QTest::newRow("(p0,c)") << "p0,c" << "" << "c0P0" << "P0,c0P0";
+ QTest::newRow("(p0,c1)") << "p0,c1" << "" << "c1P0" << "P0,c1P0";
+ QTest::newRow("(p0,c3P0)") << "p0,c3P0" << "" << "c3P0" << "P0,c3P0";
+ QTest::newRow("(p3,c)F") << "p3,c" << "F" << "c0P3" << "P3,c0P3";
+ QTest::newRow("(p3,c)L") << "p3,c" << "L" << "c4P3" << "P3,c4P3";
+ QTest::newRow("(p3,c)N") << "p3,c" << "N" << "c1P3" << "P3,c1P3";
+ QTest::newRow("(p3,c)NN") << "p3,c" << "NN" << "c2P3" << "P3,c2P3";
+ QTest::newRow("(p3,,c)") << "p3,,c" << "" << "" << "";
+ QTest::newRow("(p3,c0P3,)") << "p3,c0P3," << "" << "" << "";
+ QTest::newRow("(p,)") << "p," << "" << "" << "";
+ }
+}
+
+void tst_QCompleter::ciMatchingOnCiSortedModel()
+{
+ filter();
+}
+
+void tst_QCompleter::ciMatchingOnCsSortedModel_data()
+{
+ delete completer;
+ completer = new CsvCompleter;
+ completer->setModelSorting(QCompleter::CaseSensitivelySortedModel);
+ setSourceModel(CASE_SENSITIVELY_SORTED_MODEL);
+ completer->setCaseSensitivity(Qt::CaseInsensitive);
+
+ QTest::addColumn<QString>("filterText");
+ QTest::addColumn<QString>("step");
+ QTest::addColumn<QString>("completion");
+ QTest::addColumn<QString>("completionText");
+
+ for (int i = 0; i < 2; i++) {
+ if (i == 1)
+ QTest::newRow("FILTERING_OFF") << "FILTERING_OFF" << "" << "" << "";
+
+ // Plain text filter
+ QTest::newRow("()") << "" << "" << "P0" << "P0";
+ QTest::newRow("()F") << "" << "F" << "P0" << "P0";
+ QTest::newRow("()L") << "" << "L" << "p4" << "p4";
+ QTest::newRow("(P)") << "P" << "" << "P0" << "P0";
+ QTest::newRow("(P)F") << "P" << "" << "P0" << "P0";
+ QTest::newRow("(P)L") << "P" << "L" << "p4" << "p4";
+ QTest::newRow("(p)") << "p" << "" << "P0" << "P0";
+ QTest::newRow("(p)N") << "p" << "N" << "P1" << "P1";
+ QTest::newRow("(p)NN") << "p" << "NN" << "P2" << "P2";
+ QTest::newRow("(p)NNN") << "p" << "NNN" << "P3" << "P3";
+ QTest::newRow("(p1)") << "p1" << "" << "P1" << "P1";
+ QTest::newRow("(p1)N") << "p1" << "N" << "p1" << "p1";
+ QTest::newRow("(p11)") << "p11" << "" << "" << "";
+
+ // Tree filter
+ QTest::newRow("(p0,)") << "p0," << "" << "c0P0" << "P0,c0P0";
+ QTest::newRow("(p0,c)") << "p0,c" << "" << "c0P0" << "P0,c0P0";
+ QTest::newRow("(p0,c1)") << "p0,c1" << "" << "c1P0" << "P0,c1P0";
+ QTest::newRow("(p0,c3P0)") << "p0,c3P0" << "" << "c3P0" << "P0,c3P0";
+ QTest::newRow("(p3,c)F") << "p3,c" << "F" << "c0P3" << "P3,c0P3";
+ QTest::newRow("(p3,c)L") << "p3,c" << "L" << "c4P3" << "P3,c4P3";
+ QTest::newRow("(p3,c)N") << "p3,c" << "N" << "c1P3" << "P3,c1P3";
+ QTest::newRow("(p3,c)NN") << "p3,c" << "NN" << "c2P3" << "P3,c2P3";
+ QTest::newRow("(p3,,c)") << "p3,,c" << "" << "" << "";
+ QTest::newRow("(p3,c0P3,)") << "p3,c0P3," << "" << "" << "";
+ QTest::newRow("(p,)") << "p," << "" << "" << "";
+ }
+}
+
+void tst_QCompleter::ciMatchingOnCsSortedModel()
+{
+ filter();
+}
+
+void tst_QCompleter::csMatchingOnCiSortedModel_data()
+{
+ delete completer;
+ completer = new CsvCompleter;
+ completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
+ setSourceModel(CASE_INSENSITIVELY_SORTED_MODEL);
+ completer->setCaseSensitivity(Qt::CaseSensitive);
+
+ QTest::addColumn<QString>("filterText");
+ QTest::addColumn<QString>("step");
+ QTest::addColumn<QString>("completion");
+ QTest::addColumn<QString>("completionText");
+
+ for (int i = 0; i < 2; i++) {
+ if (i == 1)
+ QTest::newRow("FILTERING_OFF") << "FILTERING_OFF" << "" << "" << "";
+
+ // Plain text filter
+ QTest::newRow("()") << "" << "" << "P0" << "P0";
+ QTest::newRow("()F") << "" << "F" << "P0" << "P0";
+ QTest::newRow("()L") << "" << "L" << "p4" << "p4";
+ QTest::newRow("()N") << "" << "N" << "p0" << "p0";
+ QTest::newRow("(P)") << "P" << "" << "P0" << "P0";
+ QTest::newRow("(P)F") << "P" << "" << "P0" << "P0";
+ QTest::newRow("(P)L") << "P" << "L" << "P4" << "P4";
+ QTest::newRow("(p)") << "p" << "" << "p0" << "p0";
+ QTest::newRow("(p)N") << "p" << "N" << "p1" << "p1";
+ QTest::newRow("(p)NN") << "p" << "NN" << "p2" << "p2";
+ QTest::newRow("(p)NNN") << "p" << "NNN" << "p3" << "p3";
+ QTest::newRow("(p1)") << "p1" << "" << "p1" << "p1";
+ QTest::newRow("(p11)") << "p11" << "" << "" << "";
+
+ //// Tree filter
+ QTest::newRow("(p0,)") << "p0," << "" << "c0p0" << "p0,c0p0";
+ QTest::newRow("(p0,c)") << "p0,c" << "" << "c0p0" << "p0,c0p0";
+ QTest::newRow("(p0,c1)") << "p0,c1" << "" << "c1p0" << "p0,c1p0";
+ QTest::newRow("(p0,c3P0)") << "p0,c3p0" << "" << "c3p0" << "p0,c3p0";
+ QTest::newRow("(p3,c)F") << "p3,c" << "F" << "c0p3" << "p3,c0p3";
+ QTest::newRow("(p3,c)L") << "p3,c" << "L" << "c4p3" << "p3,c4p3";
+ QTest::newRow("(p3,c)N") << "p3,c" << "N" << "c1p3" << "p3,c1p3";
+ QTest::newRow("(p3,c)NN") << "p3,c" << "NN" << "c2p3" << "p3,c2p3";
+ QTest::newRow("(p3,,c)") << "p3,,c" << "" << "" << "";
+ QTest::newRow("(p3,c0P3,)") << "p3,c0P3," << "" << "" << "";
+ QTest::newRow("(p,)") << "p," << "" << "" << "";
+
+ QTest::newRow("FILTERING_OFF") << "FILTERING_OFF" << "" << "" << "";
+ }
+}
+
+void tst_QCompleter::csMatchingOnCiSortedModel()
+{
+ filter();
+}
+
+void tst_QCompleter::directoryModel_data()
+{
+ delete completer;
+
+ completer = new CsvCompleter;
+ completer->setModelSorting(QCompleter::CaseSensitivelySortedModel);
+ setSourceModel(DIRECTORY_MODEL);
+ completer->setCaseSensitivity(Qt::CaseInsensitive);
+
+ QTest::addColumn<QString>("filterText");
+ QTest::addColumn<QString>("step");
+ QTest::addColumn<QString>("completion");
+ QTest::addColumn<QString>("completionText");
+
+ // NOTE: Add tests carefully, ensurely the paths exist on all systems
+ // Output is the sourceText; currentCompletionText()
+
+ for (int i = 0; i < 2; i++) {
+ if (i == 1)
+ QTest::newRow("FILTERING_OFF") << "FILTERING_OFF" << "" << "" << "";
+
+#if defined(Q_OS_WINCE)
+ QTest::newRow("()") << "" << "" << "/" << "/";
+ QTest::newRow("()") << "\\Program" << "" << "Program Files" << "\\Program Files";
+#elif defined(Q_OS_WIN)
+ QTest::newRow("()") << "C" << "" << "C:" << "C:";
+ QTest::newRow("()") << "C:\\Program" << "" << "Program Files" << "C:\\Program Files";
+#elif defined (Q_OS_MAC)
+ QTest::newRow("()") << "" << "" << "/" << "/";
+ QTest::newRow("(/a)") << "/a" << "" << "Applications" << "/Applications";
+ QTest::newRow("(/d)") << "/d" << "" << "Developer" << "/Developer";
+#else
+ QTest::newRow("()") << "" << "" << "/" << "/";
+#if !defined(Q_OS_IRIX) && !defined(Q_OS_AIX) && !defined(Q_OS_HPUX)
+ QTest::newRow("(/h)") << "/h" << "" << "home" << "/home";
+#endif
+ QTest::newRow("(/et)") << "/et" << "" << "etc" << "/etc";
+ QTest::newRow("(/etc/passw)") << "/etc/passw" << "" << "passwd" << "/etc/passwd";
+#endif
+ }
+}
+
+void tst_QCompleter::directoryModel()
+{
+ filter();
+}
+
+void tst_QCompleter::fileSystemModel_data()
+{
+ delete completer;
+ completer = new CsvCompleter;
+ completer->setModelSorting(QCompleter::CaseSensitivelySortedModel);
+ setSourceModel(FILESYSTEM_MODEL);
+ completer->setCaseSensitivity(Qt::CaseInsensitive);
+
+ QTest::addColumn<QString>("filterText");
+ QTest::addColumn<QString>("step");
+ QTest::addColumn<QString>("completion");
+ QTest::addColumn<QString>("completionText");
+
+ // NOTE: Add tests carefully, ensurely the paths exist on all systems
+ // Output is the sourceText; currentCompletionText()
+
+ for (int i = 0; i < 2; i++) {
+ if (i == 1)
+ QTest::newRow("FILTERING_OFF") << "FILTERING_OFF" << "" << "" << "";
+
+#if defined(Q_OS_WINCE)
+ QTest::newRow("()") << "" << "" << "/" << "/";
+ QTest::newRow("()") << "\\Program" << "" << "Program Files" << "\\Program Files";
+#elif defined(Q_OS_WIN)
+ QTest::newRow("()") << "C" << "" << "C:" << "C:";
+ QTest::newRow("()") << "C:\\Program" << "" << "Program Files" << "C:\\Program Files";
+#elif defined (Q_OS_MAC)
+ QTest::newRow("()") << "" << "" << "/" << "/";
+ QTest::newRow("(/a)") << "/a" << "" << "Applications" << "/Applications";
+// QTest::newRow("(/d)") << "/d" << "" << "Developer" << "/Developer";
+#else
+ QTest::newRow("()") << "" << "" << "/" << "/";
+#if !defined(Q_OS_IRIX) && !defined(Q_OS_AIX) && !defined(Q_OS_HPUX)
+ QTest::newRow("(/h)") << "/h" << "" << "home" << "/home";
+#endif
+ QTest::newRow("(/et)") << "/et" << "" << "etc" << "/etc";
+ QTest::newRow("(/etc/passw)") << "/etc/passw" << "" << "passwd" << "/etc/passwd";
+#endif
+ }
+}
+
+void tst_QCompleter::fileSystemModel()
+{
+ //QFileSystemModel is assync.
+ filter(true);
+}
+
+
+void tst_QCompleter::changingModel_data()
+{
+}
+
+void tst_QCompleter::changingModel()
+{
+ for (int i = 0; i < 2; i++) {
+ delete completer;
+ completer = new CsvCompleter;
+ completer->setModelSorting(QCompleter::CaseSensitivelySortedModel);
+ completer->setCaseSensitivity(Qt::CaseSensitive);
+ setSourceModel(CASE_SENSITIVELY_SORTED_MODEL);
+
+ if (i == 1) {
+ completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
+ }
+
+ completer->setCompletionPrefix("p");
+ completer->setCurrentRow(completer->completionCount() - 1);
+ QCOMPARE(completer->currentCompletion(), QString("p4"));
+
+ // Test addition of data
+ QTreeWidgetItem p5item;
+ p5item.setText(completionColumn, "p5");
+ treeWidget->addTopLevelItem(&p5item);
+ completer->setCompletionPrefix("p5");
+ QCOMPARE(completer->currentCompletion(), QString("p5"));
+
+ // Test removal of data
+ int p5index = treeWidget->indexOfTopLevelItem(&p5item);
+ treeWidget->takeTopLevelItem(p5index);
+ QCOMPARE(completer->currentCompletion(), QString(""));
+
+ // Test clear
+ treeWidget->clear();
+ QCOMPARE(completer->currentIndex(), QModelIndex());
+ }
+}
+
+void tst_QCompleter::testRowCount()
+{
+ QFETCH(QString, filterText);
+ QFETCH(bool, hasChildren);
+ QFETCH(int, rowCount);
+ QFETCH(int, completionCount);
+
+ if (filterText.compare("FILTERING_OFF", Qt::CaseInsensitive) == 0) {
+ completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
+ return;
+ }
+
+ completer->setCompletionPrefix(filterText);
+ const QAbstractItemModel *completionModel = completer->completionModel();
+ QCOMPARE(completionModel->rowCount(), rowCount);
+ QCOMPARE(completionCount, completionCount);
+ QCOMPARE(completionModel->hasChildren(), hasChildren);
+ QCOMPARE(completionModel->columnCount(), columnCount);
+}
+
+void tst_QCompleter::sortedEngineRowCount_data()
+{
+ delete completer;
+ completer = new CsvCompleter;
+ completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
+ completer->setCaseSensitivity(Qt::CaseInsensitive);
+ setSourceModel(CASE_INSENSITIVELY_SORTED_MODEL);
+
+ QTest::addColumn<QString>("filterText");
+ QTest::addColumn<bool>("hasChildren");
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("completionCount");
+
+ QTest::newRow("whatever") << "whatever" << false << 0 << 0;
+ QTest::newRow("p") << "p" << true << 10 << 10;
+ QTest::newRow("p1") << "p1" << true << 2 << 2;
+ QTest::newRow("P1,") << "P1," << true << 5 << 5;
+ QTest::newRow("P1,c") << "P1,c" << true << 5 << 5;
+ QTest::newRow("P1,cc") << "P1,cc" << false << 0 << 0;
+
+ QTest::newRow("FILTERING_OFF") << "FILTERING_OFF" << false << 0 << 0;
+
+ QTest::newRow("whatever(filter off)") << "whatever" << true << 10 << 0;
+ QTest::newRow("p1(filter off)") << "p1" << true << 10 << 2;
+ QTest::newRow("p1,(filter off)") << "p1," << true << 5 << 5;
+ QTest::newRow("p1,c(filter off)") << "p1,c" << true << 5 << 5;
+ QTest::newRow("P1,cc(filter off)") << "P1,cc" << true << 5 << 0;
+}
+
+void tst_QCompleter::sortedEngineRowCount()
+{
+ testRowCount();
+}
+
+void tst_QCompleter::unsortedEngineRowCount_data()
+{
+ delete completer;
+ completer = new CsvCompleter;
+ completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
+ completer->setCaseSensitivity(Qt::CaseSensitive);
+ setSourceModel(CASE_INSENSITIVELY_SORTED_MODEL);
+
+ QTest::addColumn<QString>("filterText");
+ QTest::addColumn<bool>("hasChildren");
+ QTest::addColumn<int>("rowCount");
+ QTest::addColumn<int>("completionCount");
+
+ QTest::newRow("whatever") << "whatever" << false << 0 << 0;
+ QTest::newRow("p") << "p" << true << 5 << 5;
+ QTest::newRow("p1") << "p1" << true << 1 << 1;
+ QTest::newRow("P1,") << "P1," << true << 5 << 5;
+ QTest::newRow("P1,c") << "P1,c" << true << 5 << 5;
+ QTest::newRow("P1,cc") << "P1,cc" << false << 0 << 0;
+
+ QTest::newRow("FILTERING_OFF") << "FILTERING_OFF" << false << 0 << 0;
+
+ QTest::newRow("whatever(filter off)") << "whatever" << true << 10 << 0;
+ QTest::newRow("p1(filter off)") << "p1" << true << 10 << 1;
+ QTest::newRow("p1,(filter off)") << "p1," << true << 5 << 5;
+ QTest::newRow("p1,c(filter off)") << "p1,c" << true << 5 << 5;
+ QTest::newRow("P1,cc(filter off)") << "P1,cc" << true << 5 << 0;
+}
+
+void tst_QCompleter::unsortedEngineRowCount()
+{
+ testRowCount();
+}
+
+void tst_QCompleter::currentRow()
+{
+ delete completer;
+ completer = new CsvCompleter;
+ completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
+ completer->setCaseSensitivity(Qt::CaseInsensitive);
+ setSourceModel(CASE_INSENSITIVELY_SORTED_MODEL);
+
+ // blank text
+ completer->setCompletionPrefix("");
+ QCOMPARE(completer->currentRow(), 0);
+ QVERIFY(completer->setCurrentRow(4));
+ QCOMPARE(completer->currentRow(), 4);
+ QVERIFY(!completer->setCurrentRow(13));
+ QVERIFY(completer->setCurrentRow(4));
+
+ // some text
+ completer->setCompletionPrefix("p1");
+ QCOMPARE(completer->currentRow(), 0);
+ QVERIFY(completer->setCurrentRow(1));
+ QCOMPARE(completer->currentRow(), 1);
+ QVERIFY(!completer->setCurrentRow(2));
+ QCOMPARE(completer->currentRow(), 1);
+
+ // invalid text
+ completer->setCompletionPrefix("well");
+ QCOMPARE(completer->currentRow(), -1);
+}
+
+void tst_QCompleter::sortedEngineMapFromSource()
+{
+ delete completer;
+ completer = new CsvCompleter;
+ completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
+ completer->setCaseSensitivity(Qt::CaseInsensitive);
+ setSourceModel(CASE_INSENSITIVELY_SORTED_MODEL);
+
+ QModelIndex si1, si2, pi;
+ QAbstractItemModel *sourceModel = completer->model();
+ const QAbstractProxyModel *completionModel =
+ qobject_cast<const QAbstractProxyModel *>(completer->completionModel());
+
+ // Fitering ON
+ // empty
+ si1 = sourceModel->index(4, completionColumn); // "P2"
+ si2 = sourceModel->index(2, 0, si1); // "P2,c0P2"
+ pi = completionModel->mapFromSource(si1);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P2"));
+ pi = completionModel->mapFromSource(si2);
+ QCOMPARE(pi.isValid(), false);
+
+ // some text
+ completer->setCompletionPrefix("p");
+ pi = completionModel->mapFromSource(si1);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P2"));
+ pi = completionModel->mapFromSource(si2);
+ QCOMPARE(pi.isValid(), false);
+
+ // more text
+ completer->setCompletionPrefix("p2");
+ pi = completionModel->mapFromSource(si1);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P2"));
+ pi = completionModel->mapFromSource(si2);
+ QCOMPARE(pi.isValid(), false);
+
+ // invalid text
+ completer->setCompletionPrefix("whatever");
+ pi = completionModel->mapFromSource(si1);
+ QVERIFY(!pi.isValid());
+
+ // Fitering OFF
+ completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
+ // empty
+ si1 = sourceModel->index(4, completionColumn); // "P2"
+ si2 = sourceModel->index(2, 0, si1); // "P2,c0P2"
+ pi = completionModel->mapFromSource(si1);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P2"));
+ pi = completionModel->mapFromSource(si2);
+ QCOMPARE(pi.isValid(), false);
+
+ // some text
+ completer->setCompletionPrefix("p");
+ pi = completionModel->mapFromSource(si1);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P2"));
+ pi = completionModel->mapFromSource(si2);
+ QCOMPARE(pi.isValid(), false);
+
+ // more text
+ completer->setCompletionPrefix("p2");
+ pi = completionModel->mapFromSource(si1);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P2"));
+ pi = completionModel->mapFromSource(si2);
+ QCOMPARE(pi.isValid(), false);
+
+ // invalid text
+ completer->setCompletionPrefix("whatever");
+ pi = completionModel->mapFromSource(si1);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P2"));
+}
+
+void tst_QCompleter::unsortedEngineMapFromSource()
+{
+ delete completer;
+ completer = new CsvCompleter;
+ completer->setCaseSensitivity(Qt::CaseInsensitive);
+ setSourceModel(HISTORY_MODEL); // case insensitively sorted model
+ completer->setModelSorting(QCompleter::UnsortedModel);
+
+ QModelIndex si, si2, si3, pi;
+ QAbstractItemModel *sourceModel = completer->model();
+ const QAbstractProxyModel *completionModel =
+ qobject_cast<const QAbstractProxyModel *>(completer->completionModel());
+
+ si = sourceModel->index(6, completionColumn); // "P3"
+ QCOMPARE(si.data().toString(), QLatin1String("P3"));
+ si2 = sourceModel->index(3, completionColumn, sourceModel->index(0, completionColumn)); // "P0,c3P0"
+ QCOMPARE(si2.data().toString(), QLatin1String("c3P0"));
+ si3 = sourceModel->index(10, completionColumn); // "p3,c3p3" (history)
+ QCOMPARE(si3.data().toString(), QLatin1String("p3,c3p3"));
+
+ // FILTERING ON
+ // empty
+ pi = completionModel->mapFromSource(si);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P3"));
+ pi = completionModel->mapFromSource(si2);
+ QCOMPARE(pi.isValid(), false);
+ pi = completionModel->mapFromSource(si3);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("p3,c3p3"));
+
+ // some text
+ completer->setCompletionPrefix("P");
+ pi = completionModel->mapFromSource(si);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P3"));
+ pi = completionModel->mapFromSource(si2);
+ QCOMPARE(pi.isValid(), false);
+ pi = completionModel->mapFromSource(si3);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("p3,c3p3"));
+
+ // invalid text
+ completer->setCompletionPrefix("whatever");
+ pi = completionModel->mapFromSource(si);
+ QVERIFY(!pi.isValid());
+ pi = completionModel->mapFromSource(si2);
+ QVERIFY(!pi.isValid());
+
+ // tree matching
+ completer->setCompletionPrefix("P0,c");
+ pi = completionModel->mapFromSource(si);
+ QVERIFY(!pi.isValid());
+ pi = completionModel->mapFromSource(si2);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("c3P0"));
+ pi = completionModel->mapFromSource(si3);
+ QCOMPARE(pi.isValid(), false);
+
+ // more tree matching
+ completer->setCompletionPrefix("p3,");
+ pi = completionModel->mapFromSource(si2);
+ QVERIFY(!pi.isValid());
+ pi = completionModel->mapFromSource(si3);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("p3,c3p3"));
+
+ // FILTERING OFF
+ // empty
+ completer->setCompletionPrefix("");
+ completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
+ pi = completionModel->mapFromSource(si);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P3"));
+
+ // some text
+ completer->setCompletionPrefix("P");
+ pi = completionModel->mapFromSource(si);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P3"));
+
+ // more text
+ completer->setCompletionPrefix("P3");
+ pi = completionModel->mapFromSource(si);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P3"));
+
+ // invalid text
+ completer->setCompletionPrefix("whatever");
+ pi = completionModel->mapFromSource(si);
+ QCOMPARE(completionModel->data(pi).toString(), QLatin1String("P3"));
+}
+
+void tst_QCompleter::historySearch()
+{
+ delete completer;
+ completer = new CsvCompleter;
+ completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
+ completer->setCaseSensitivity(Qt::CaseSensitive);
+ setSourceModel(HISTORY_MODEL);
+
+ const QAbstractProxyModel *completionModel =
+ qobject_cast<const QAbstractProxyModel *>(completer->completionModel());
+
+ // "p3,c3p3" and "p2,c4p2" are added in the tree root
+
+ // FILTERING ON
+ // empty
+ completer->setCurrentRow(10);
+ QCOMPARE(completer->currentCompletion(), QLatin1String("p3,c3p3"));
+
+ // more text
+ completer->setCompletionPrefix("p2");
+ completer->setCurrentRow(1);
+ QCOMPARE(completer->currentCompletion(), QLatin1String("p2,c4p2"));
+
+ // comma separated text
+ completer->setCompletionPrefix("p2,c4");
+ completer->setCurrentRow(1);
+ QCOMPARE(completionModel->rowCount(), 2);
+ QCOMPARE(completer->currentCompletion(), QLatin1String("p2,c4p2"));
+
+ // invalid text
+ completer->setCompletionPrefix("whatever");
+ QCOMPARE(completer->currentCompletion(), QString());
+
+ // FILTERING OFF
+ completer->setCompletionPrefix("");
+ completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
+ completer->setCurrentRow(10);
+ QCOMPARE(completer->currentCompletion(), QLatin1String("p3,c3p3"));
+
+ // more text
+ completer->setCompletionPrefix("p2");
+ completer->setCurrentRow(1);
+ QCOMPARE(completer->currentCompletion(), QLatin1String("p2,c4p2"));
+
+ // comma separated text
+ completer->setCompletionPrefix("p2,c4");
+ QCOMPARE(completionModel->rowCount(), 5);
+
+ // invalid text
+ completer->setCompletionPrefix("whatever");
+ QCOMPARE(completer->currentCompletion(), QString());
+}
+
+void tst_QCompleter::setters()
+{
+ delete completer;
+ completer = new CsvCompleter;
+ QVERIFY(completer->popup() != 0);
+ QPointer<QDirModel> dirModel = new QDirModel(completer);
+ QAbstractItemModel *oldModel = completer->model();
+ completer->setModel(dirModel);
+ QVERIFY(completer->popup()->model() != oldModel);
+ QVERIFY(completer->popup()->model() == completer->completionModel());
+ completer->setPopup(new QListView);
+ QVERIFY(completer->popup()->model() == completer->completionModel());
+ completer->setModel(new QStringListModel(completer));
+ QVERIFY(dirModel == 0); // must have been deleted
+
+ completer->setModel(0);
+ completer->setWidget(0);
+}
+
+void tst_QCompleter::modelDeletion()
+{
+ delete completer;
+ completer = new CsvCompleter;
+ QStringList list;
+ list << "item1" << "item2" << "item3";
+ QStringListModel *listModel = new QStringListModel(list);
+ completer->setCompletionPrefix("i");
+ completer->setModel(listModel);
+ QVERIFY(completer->completionCount() == 3);
+ QListView *view = new QListView;
+ view->setModel(completer->completionModel());
+ delete listModel;
+ view->show();
+ qApp->processEvents();
+ delete view;
+ QVERIFY(completer->completionCount() == 0);
+ QVERIFY(completer->currentRow() == -1);
+}
+
+void tst_QCompleter::multipleWidgets()
+{
+ QStringList list;
+ list << "item1" << "item2" << "item2";
+ QCompleter completer(list);
+ completer.setCompletionMode(QCompleter::InlineCompletion);
+
+ QWidget window;
+ window.show();
+ QApplication::setActiveWindow(&window);
+ QTest::qWaitForWindowShown(&window);
+ QTRY_VERIFY(qApp->activeWindow() == &window);
+
+ QFocusEvent focusIn(QEvent::FocusIn);
+ QFocusEvent focusOut(QEvent::FocusOut);
+
+ QComboBox *comboBox = new QComboBox(&window);
+ comboBox->setEditable(true);
+ comboBox->setCompleter(&completer);
+ comboBox->setFocus();
+ comboBox->show();
+ window.activateWindow();
+ QApplication::setActiveWindow(&window);
+ QTest::qWait(50);
+ QTRY_VERIFY(qApp->focusWidget() == comboBox);
+ comboBox->lineEdit()->setText("it");
+ QCOMPARE(comboBox->currentText(), QString("it")); // should not complete with setText
+ QTest::keyPress(comboBox, 'e');
+ QCOMPARE(comboBox->currentText(), QString("item1"));
+ comboBox->clearEditText();
+ QCOMPARE(comboBox->currentText(), QString("")); // combo box text must not change!
+
+ QLineEdit *lineEdit = new QLineEdit(&window);
+ lineEdit->setCompleter(&completer);
+ lineEdit->show();
+ lineEdit->setFocus();
+ QTest::qWait(50);
+ QTRY_VERIFY(qApp->focusWidget() == lineEdit);
+ lineEdit->setText("it");
+ QCOMPARE(lineEdit->text(), QString("it")); // should not completer with setText
+ QCOMPARE(comboBox->currentText(), QString("")); // combo box text must not change!
+ QTest::keyPress(lineEdit, 'e');
+ QCOMPARE(lineEdit->text(), QString("item1"));
+ QCOMPARE(comboBox->currentText(), QString("")); // combo box text must not change!
+}
+
+void tst_QCompleter::focusIn()
+{
+ QStringList list;
+ list << "item1" << "item2" << "item2";
+ QCompleter completer(list);
+
+ QWidget window;
+ window.show();
+ QTest::qWait(100);
+ window.activateWindow();
+ QApplication::setActiveWindow(&window);
+ QTest::qWait(100);
+
+ QTRY_COMPARE(qApp->activeWindow(), &window);
+
+ QComboBox *comboBox = new QComboBox(&window);
+ comboBox->setEditable(true);
+ comboBox->setCompleter(&completer);
+ comboBox->show();
+ comboBox->lineEdit()->setText("it");
+
+ QLineEdit *lineEdit = new QLineEdit(&window);
+ lineEdit->setCompleter(&completer);
+ lineEdit->setText("it");
+ lineEdit->show();
+
+ QLineEdit *lineEdit2 = new QLineEdit(&window); // has no completer!
+ lineEdit2->show();
+
+ comboBox->setFocus();
+ QTRY_VERIFY(completer.widget() == comboBox);
+ lineEdit->setFocus();
+ QTRY_VERIFY(completer.widget() == lineEdit);
+ comboBox->setFocus();
+ QTRY_VERIFY(completer.widget() == comboBox);
+ lineEdit2->setFocus();
+ QTRY_VERIFY(completer.widget() == comboBox);
+}
+
+void tst_QCompleter::dynamicSortOrder()
+{
+ QStandardItemModel model;
+ QCompleter completer(&model);
+ completer.setModelSorting(QCompleter::CaseSensitivelySortedModel);
+ QStandardItem *root = model.invisibleRootItem();
+ for (int i = 0; i < 20; i++) {
+ root->appendRow(new QStandardItem(QString("%1").arg(i)));
+ }
+ root->appendRow(new QStandardItem("13"));
+ root->sortChildren(0, Qt::AscendingOrder);
+ completer.setCompletionPrefix("1");
+ QCOMPARE(completer.completionCount(), 12);
+ completer.setCompletionPrefix("13");
+ QCOMPARE(completer.completionCount(), 2);
+
+ root->sortChildren(0, Qt::DescendingOrder);
+ completer.setCompletionPrefix("13");
+ QCOMPARE(completer.completionCount(), 2);
+ completer.setCompletionPrefix("1");
+ QCOMPARE(completer.completionCount(), 12);
+}
+
+void tst_QCompleter::disabledItems()
+{
+ QLineEdit lineEdit;
+ QStandardItemModel *model = new QStandardItemModel(&lineEdit);
+ QStandardItem *suggestions = new QStandardItem("suggestions");
+ suggestions->setEnabled(false);
+ model->appendRow(suggestions);
+ model->appendRow(new QStandardItem("suggestions Enabled"));
+ QCompleter *completer = new QCompleter(model, &lineEdit);
+ QSignalSpy spy(completer, SIGNAL(activated(const QString &)));
+ lineEdit.setCompleter(completer);
+ lineEdit.show();
+
+ QTest::keyPress(&lineEdit, Qt::Key_S);
+ QTest::keyPress(&lineEdit, Qt::Key_U);
+ QAbstractItemView *view = lineEdit.completer()->popup();
+ QVERIFY(view->isVisible());
+ QTest::mouseClick(view->viewport(), Qt::LeftButton, 0, view->visualRect(view->model()->index(0, 0)).center());
+ QCOMPARE(spy.count(), 0);
+ QVERIFY(view->isVisible());
+ QTest::mouseClick(view->viewport(), Qt::LeftButton, 0, view->visualRect(view->model()->index(1, 0)).center());
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(!view->isVisible());
+}
+
+void tst_QCompleter::task178797_activatedOnReturn()
+{
+ QStringList words;
+ words << "foobar1" << "foobar2";
+ QLineEdit *ledit = new QLineEdit;
+ QCompleter *completer = new QCompleter(words);
+ ledit->setCompleter(completer);
+ QSignalSpy spy(completer, SIGNAL(activated(const QString)));
+ QCOMPARE(spy.count(), 0);
+ ledit->show();
+ QTest::keyClick(ledit, Qt::Key_F);
+ qApp->processEvents();
+ QVERIFY(qApp->activePopupWidget());
+ QTest::keyClick(qApp->activePopupWidget(), Qt::Key_Down);
+ qApp->processEvents();
+ QTest::keyClick(qApp->activePopupWidget(), Qt::Key_Return);
+ qApp->processEvents();
+ QCOMPARE(spy.count(), 1);
+}
+
+class task189564_StringListModel : public QStringListModel
+{
+ const QString omitString;
+ Qt::ItemFlags flags(const QModelIndex &index) const
+ {
+ Qt::ItemFlags flags = Qt::ItemIsEnabled;
+ if (data(index, Qt::DisplayRole).toString() != omitString)
+ flags |= Qt::ItemIsSelectable;
+ return flags;
+ }
+public:
+ task189564_StringListModel(const QString &omitString, QObject *parent = 0)
+ : QStringListModel(parent)
+ , omitString(omitString)
+ {
+ }
+};
+
+void tst_QCompleter::task189564_omitNonSelectableItems()
+{
+ const QString prefix("a");
+ const int n = 5;
+
+ QStringList strings;
+ for (int i = 0; i < n; ++i)
+ strings << QString("%1%2").arg(prefix).arg(i);
+ const QString omitString(strings.at(n / 2));
+ task189564_StringListModel model(omitString);
+ model.setStringList(strings);
+ QCompleter completer_(&model);
+ completer_.setCompletionPrefix(prefix);
+
+ QAbstractItemModel *completionModel = completer_.completionModel();
+ QModelIndexList matches1 =
+ completionModel->match(completionModel->index(0, 0), Qt::DisplayRole, prefix, -1);
+ QCOMPARE(matches1.size(), n - 1);
+ QModelIndexList matches2 =
+ completionModel->match(completionModel->index(0, 0), Qt::DisplayRole, omitString);
+ QVERIFY(matches2.isEmpty());
+}
+
+class task246056_ComboBox : public QComboBox
+{
+ Q_OBJECT
+public:
+ task246056_ComboBox()
+ {
+ setEditable(true);
+ setInsertPolicy(NoInsert);
+ if (completer()) {
+ completer()->setCompletionMode(QCompleter::PopupCompletion);
+ completer()->setCompletionRole(Qt::DisplayRole);
+ connect(lineEdit(), SIGNAL(editingFinished()), SLOT(setCompletionPrefix()));
+ }
+ }
+private slots:
+ void setCompletionPrefix() { completer()->setCompletionPrefix(lineEdit()->text()); }
+};
+
+void tst_QCompleter::task246056_setCompletionPrefix()
+{
+ task246056_ComboBox *comboBox = new task246056_ComboBox;
+ QVERIFY(comboBox->completer());
+ comboBox->addItem("");
+ comboBox->addItem("a1");
+ comboBox->addItem("a2");
+ comboBox->show();
+ comboBox->setFocus();
+ QTest::qWait(100);
+ QTest::keyPress(comboBox, 'a');
+ QTest::keyPress(comboBox->completer()->popup(), Qt::Key_Down);
+ QTest::keyPress(comboBox->completer()->popup(), Qt::Key_Down);
+ QTest::keyPress(comboBox->completer()->popup(), Qt::Key_Enter); // don't crash!
+}
+
+class task250064_TextEdit : public QTextEdit
+{
+public:
+ QCompleter *completer;
+
+ task250064_TextEdit()
+ {
+ completer = new QCompleter;
+ completer->setWidget(this);
+ }
+
+ void keyPressEvent (QKeyEvent *e)
+ {
+ completer->popup();
+ QTextEdit::keyPressEvent(e);
+ }
+};
+
+class task250064_Widget : public QWidget
+{
+ Q_OBJECT
+public:
+ task250064_TextEdit *textEdit;
+
+ task250064_Widget(task250064_TextEdit *textEdit)
+ : textEdit(textEdit)
+ {
+ QTabWidget *tabWidget = new QTabWidget;
+ tabWidget->setFocusPolicy(Qt::ClickFocus);
+ tabWidget->addTab(textEdit, "untitled");
+
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ layout->addWidget(tabWidget);
+
+ textEdit->setPlainText("bla bla bla");
+ textEdit->setFocus();
+ }
+
+ void setCompletionModel()
+ {
+ textEdit->completer->setModel(0);
+ }
+};
+
+void tst_QCompleter::task250064_lostFocus()
+{
+ task250064_TextEdit *textEdit = new task250064_TextEdit;
+ task250064_Widget *widget = new task250064_Widget(textEdit);
+ widget->show();
+ QTest::qWait(100);
+ QTest::keyPress(textEdit, 'a');
+ Qt::FocusPolicy origPolicy = textEdit->focusPolicy();
+ QVERIFY(origPolicy != Qt::NoFocus);
+ widget->setCompletionModel();
+ QCOMPARE(textEdit->focusPolicy(), origPolicy);
+}
+
+void tst_QCompleter::task253125_lineEditCompletion_data()
+{
+ QTest::addColumn<QStringList>("list");
+ QTest::addColumn<int>("completionMode");
+
+ QStringList list = QStringList()
+ << "alpha" << "beta" << "gamma" << "delta" << "epsilon" << "zeta"
+ << "eta" << "theta" << "iota" << "kappa" << "lambda" << "mu"
+ << "nu" << "xi" << "omicron" << "pi" << "rho" << "sigma"
+ << "tau" << "upsilon" << "phi" << "chi" << "psi" << "omega";
+
+ QTest::newRow("Inline") << list << (int)QCompleter::InlineCompletion;
+ QTest::newRow("Filtered") << list << (int)QCompleter::PopupCompletion;
+ QTest::newRow("Unfiltered") << list << (int)QCompleter::UnfilteredPopupCompletion;
+}
+
+void tst_QCompleter::task253125_lineEditCompletion()
+{
+ QFETCH(QStringList, list);
+ QFETCH(int, completionMode);
+
+ QStringListModel *model = new QStringListModel;
+ model->setStringList(list);
+
+ QCompleter *completer = new QCompleter(list);
+ completer->setModel(model);
+ completer->setCompletionMode((QCompleter::CompletionMode)completionMode);
+
+ QLineEdit edit;
+ edit.setCompleter(completer);
+ edit.show();
+ edit.setFocus();
+
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&edit);
+#endif
+ QTest::qWait(10);
+ QApplication::setActiveWindow(&edit);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&edit));
+
+ QTest::keyClick(&edit, 'i');
+ QCOMPARE(edit.completer()->currentCompletion(), QString("iota"));
+ QTest::keyClick(edit.completer()->popup(), Qt::Key_Down);
+ QTest::keyClick(edit.completer()->popup(), Qt::Key_Enter);
+
+ QCOMPARE(edit.text(), QString("iota"));
+
+ delete completer;
+ delete model;
+}
+
+void tst_QCompleter::task247560_keyboardNavigation()
+{
+ QStandardItemModel model;
+
+ for (int i = 0; i < 5; i++) {
+ for (int j = 0; j < 5; j++) {
+ model.setItem(i, j, new QStandardItem(QString("row %1 column %2").arg(i).arg(j)));
+ }
+ }
+
+
+ QCompleter completer(&model);
+ completer.setCompletionColumn(1);
+
+ QLineEdit edit;
+ edit.setCompleter(&completer);
+ edit.show();
+ edit.setFocus();
+
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&edit);
+#endif
+
+ QTest::qWait(10);
+ QApplication::setActiveWindow(&edit);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&edit));
+
+ QTest::keyClick(&edit, 'r');
+ QTest::keyClick(edit.completer()->popup(), Qt::Key_Down);
+ QTest::keyClick(edit.completer()->popup(), Qt::Key_Down);
+ QTest::keyClick(edit.completer()->popup(), Qt::Key_Enter);
+
+ QCOMPARE(edit.text(), QString("row 1 column 1"));
+
+ edit.clear();
+
+ QTest::keyClick(&edit, 'r');
+ QTest::keyClick(edit.completer()->popup(), Qt::Key_Up);
+ QTest::keyClick(edit.completer()->popup(), Qt::Key_Up);
+ QTest::keyClick(edit.completer()->popup(), Qt::Key_Enter);
+
+ QCOMPARE(edit.text(), QString("row 3 column 1"));
+}
+
+void tst_QCompleter::QTBUG_14292_filesystem()
+{
+ FileSystem fs;
+ QDir tmpDir = QDir::currentPath();
+
+ qsrand(QTime::currentTime().msec());
+ QString d = "tst_QCompleter_" + QString::number(qrand());
+ QVERIFY(fs.createDirectory(tmpDir.filePath(d)));
+
+ QVERIFY(tmpDir.cd(d));
+ QVERIFY(fs.createDirectory(tmpDir.filePath("hello")));
+ QVERIFY(fs.createDirectory(tmpDir.filePath("holla")));
+
+ QLineEdit edit;
+ QCompleter comp;
+ QFileSystemModel model;
+ model.setRootPath(tmpDir.path());
+ comp.setModel(&model);
+ edit.setCompleter(&comp);
+
+ edit.show();
+ QApplication::setActiveWindow(&edit);
+ QTest::qWaitForWindowShown(&edit);
+ QTRY_VERIFY(QApplication::activeWindow() == &edit);
+ edit.setFocus();
+ QTRY_VERIFY(edit.hasFocus());
+
+ QVERIFY(!comp.popup()->isVisible());
+ edit.setText(tmpDir.path());
+ QTest::keyClick(&edit, '/');
+ QTRY_VERIFY(comp.popup()->isVisible());
+ QCOMPARE(comp.popup()->model()->rowCount(), 2);
+ QApplication::processEvents();
+ QTest::keyClick(&edit, 'h');
+ QCOMPARE(comp.popup()->model()->rowCount(), 2);
+ QTest::keyClick(&edit, 'e');
+ QCOMPARE(comp.popup()->model()->rowCount(), 1);
+ QTest::keyClick(&edit, 'r');
+ QTRY_VERIFY(!comp.popup()->isVisible());
+ QVERIFY(fs.createDirectory(tmpDir.filePath("hero")));
+ QTRY_VERIFY(comp.popup()->isVisible());
+ QCOMPARE(comp.popup()->model()->rowCount(), 1);
+ QTest::keyClick(comp.popup(), Qt::Key_Escape);
+ QTRY_VERIFY(!comp.popup()->isVisible());
+ QVERIFY(fs.createDirectory(tmpDir.filePath("nothingThere")));
+ //there is no reason creating a file should open a popup, it did in Qt 4.7.0
+ QTest::qWait(60);
+ QVERIFY(!comp.popup()->isVisible());
+
+ QTest::keyClick(&edit, Qt::Key_Backspace);
+ QTRY_VERIFY(comp.popup()->isVisible());
+ QCOMPARE(comp.popup()->model()->rowCount(), 2);
+ QTest::keyClick(&edit, 'm');
+ QTRY_VERIFY(!comp.popup()->isVisible());
+
+ QWidget w;
+ w.show();
+ QApplication::setActiveWindow(&w);
+ QTest::qWaitForWindowShown(&w);
+ QTRY_VERIFY(!edit.hasFocus() && !comp.popup()->hasFocus());
+
+ QVERIFY(fs.createDirectory(tmpDir.filePath("hemo")));
+ //there is no reason creating a file should open a popup, it did in Qt 4.7.0
+ QTest::qWait(60);
+ QVERIFY(!comp.popup()->isVisible());
+}
+
+QTEST_MAIN(tst_QCompleter)
+#include "tst_qcompleter.moc"
diff --git a/tests/auto/widgets/util/qscroller/qscroller.pro b/tests/auto/widgets/util/qscroller/qscroller.pro
new file mode 100644
index 0000000000..de202d66aa
--- /dev/null
+++ b/tests/auto/widgets/util/qscroller/qscroller.pro
@@ -0,0 +1,4 @@
+load(qttest_p4)
+
+QT += widgets
+SOURCES += tst_qscroller.cpp
diff --git a/tests/auto/widgets/util/qscroller/tst_qscroller.cpp b/tests/auto/widgets/util/qscroller/tst_qscroller.cpp
new file mode 100644
index 0000000000..9ed4965d45
--- /dev/null
+++ b/tests/auto/widgets/util/qscroller/tst_qscroller.cpp
@@ -0,0 +1,530 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+#include <QtWidgets>
+#include <QtTest>
+// #include <QDebug>
+
+class tst_QScrollerWidget : public QWidget
+{
+public:
+ tst_QScrollerWidget()
+ : QWidget()
+ {
+ reset();
+ }
+
+ void reset()
+ {
+ receivedPrepare = false;
+ receivedScroll = false;
+ receivedFirst = false;
+ receivedLast = false;
+ receivedOvershoot = false;
+ }
+
+ bool event(QEvent *e)
+ {
+ switch (e->type()) {
+ case QEvent::Gesture:
+ e->setAccepted(false); // better reject the event or QGestureManager will make trouble
+ return false;
+
+ case QEvent::ScrollPrepare:
+ {
+ receivedPrepare = true;
+ QScrollPrepareEvent *se = static_cast<QScrollPrepareEvent *>(e);
+ se->setViewportSize(QSizeF(100,100));
+ se->setContentPosRange(scrollArea);
+ se->setContentPos(scrollPosition);
+ se->accept();
+ return true;
+ }
+
+ case QEvent::Scroll:
+ {
+ receivedScroll = true;
+ QScrollEvent *se = static_cast<QScrollEvent *>(e);
+ // qDebug() << "Scroll for"<<this<<"pos"<<se->scrollPos()<<"ov"<<se->overshoot()<<"first"<<se->isFirst()<<"last"<<se->isLast();
+
+ if (se->scrollState() == QScrollEvent::ScrollStarted)
+ receivedFirst = true;
+ if (se->scrollState() == QScrollEvent::ScrollFinished)
+ receivedLast = true;
+
+ currentPos = se->contentPos();
+ overshoot = se->overshootDistance();
+ if (!qFuzzyCompare( overshoot.x() + 1.0, 1.0 ) ||
+ !qFuzzyCompare( overshoot.y() + 1.0, 1.0 ))
+ receivedOvershoot = true;
+ return true;
+ }
+
+ default:
+ return QObject::event(e);
+ }
+ }
+
+
+ QRectF scrollArea;
+ QPointF scrollPosition;
+
+ bool receivedPrepare;
+ bool receivedScroll;
+ bool receivedFirst;
+ bool receivedLast;
+ bool receivedOvershoot;
+
+ QPointF currentPos;
+ QPointF overshoot;
+};
+
+
+class tst_QScroller : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QScroller() { }
+ ~tst_QScroller() { }
+
+private:
+ void kineticScroll( tst_QScrollerWidget *sw, QPointF from, QPoint touchStart, QPoint touchUpdate, QPoint touchEnd);
+ void kineticScrollNoTest( tst_QScrollerWidget *sw, QPointF from, QPoint touchStart, QPoint touchUpdate, QPoint touchEnd);
+
+private slots:
+ void staticScrollers();
+ void scrollerProperties();
+ void scrollTo();
+#if !defined(QT_NO_GESTURES) && !(defined(Q_OS_MACX) && (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6))
+ void scroll();
+ void overshoot();
+#endif
+};
+
+/*! \internal
+ Generates touchBegin, touchUpdate and touchEnd events to trigger scrolling.
+ Tests some in between states but does not wait until scrolling is finished.
+*/
+void tst_QScroller::kineticScroll( tst_QScrollerWidget *sw, QPointF from, QPoint touchStart, QPoint touchUpdate, QPoint touchEnd)
+{
+ sw->scrollPosition = from;
+ sw->currentPos= from;
+
+ QScroller *s1 = QScroller::scroller(sw);
+ QCOMPARE( s1->state(), QScroller::Inactive );
+
+ QScrollerProperties sp1 = QScroller::scroller(sw)->scrollerProperties();
+ int fps = 60;
+
+ QTouchEvent::TouchPoint rawTouchPoint;
+ rawTouchPoint.setId(0);
+
+ // send the touch begin event
+ QTouchEvent::TouchPoint touchPoint(0);
+ touchPoint.setState(Qt::TouchPointPressed);
+ touchPoint.setPos(touchStart);
+ touchPoint.setScenePos(touchStart);
+ touchPoint.setScreenPos(touchStart);
+ QTouchEvent touchEvent1(QEvent::TouchBegin,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointPressed,
+ (QList<QTouchEvent::TouchPoint>() << touchPoint));
+ QApplication::sendEvent(sw, &touchEvent1);
+
+ QCOMPARE( s1->state(), QScroller::Pressed );
+
+ // send the touch update far enough to trigger a scroll
+ QTest::qWait(200); // we need to wait a little or else the speed would be infinite. now we have around 500 pixel per second.
+ touchPoint.setPos(touchUpdate);
+ touchPoint.setScenePos(touchUpdate);
+ touchPoint.setScreenPos(touchUpdate);
+ QTouchEvent touchEvent2(QEvent::TouchUpdate,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointMoved,
+ (QList<QTouchEvent::TouchPoint>() << touchPoint));
+ QApplication::sendEvent(sw, &touchEvent2);
+
+ QCOMPARE( s1->state(), QScroller::Dragging );
+ QCOMPARE( sw->receivedPrepare, true );
+
+
+ QTest::qWait(1000 / fps * 2); // wait until the first scroll move
+ QCOMPARE( sw->receivedFirst, true );
+ QCOMPARE( sw->receivedScroll, true );
+ QCOMPARE( sw->receivedOvershoot, false );
+
+ // note that the scrolling goes in a different direction than the mouse move
+ QPoint calculatedPos = from.toPoint() - touchUpdate - touchStart;
+ QVERIFY(qAbs(sw->currentPos.x() - calculatedPos.x()) < 1.0);
+ QVERIFY(qAbs(sw->currentPos.y() - calculatedPos.y()) < 1.0);
+
+ // send the touch end
+ touchPoint.setPos(touchEnd);
+ touchPoint.setScenePos(touchEnd);
+ touchPoint.setScreenPos(touchEnd);
+ QTouchEvent touchEvent5(QEvent::TouchEnd,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointReleased,
+ (QList<QTouchEvent::TouchPoint>() << touchPoint));
+ QApplication::sendEvent(sw, &touchEvent5);
+}
+
+/*! \internal
+ Generates touchBegin, touchUpdate and touchEnd events to trigger scrolling.
+ This function does not have any in between tests, it does not expect the scroller to actually scroll.
+*/
+void tst_QScroller::kineticScrollNoTest( tst_QScrollerWidget *sw, QPointF from, QPoint touchStart, QPoint touchUpdate, QPoint touchEnd)
+{
+ sw->scrollPosition = from;
+ sw->currentPos = from;
+
+ QScroller *s1 = QScroller::scroller(sw);
+ QCOMPARE( s1->state(), QScroller::Inactive );
+
+ QScrollerProperties sp1 = s1->scrollerProperties();
+ int fps = 60;
+
+ QTouchEvent::TouchPoint rawTouchPoint;
+ rawTouchPoint.setId(0);
+
+ // send the touch begin event
+ QTouchEvent::TouchPoint touchPoint(0);
+ touchPoint.setState(Qt::TouchPointPressed);
+ touchPoint.setPos(touchStart);
+ touchPoint.setScenePos(touchStart);
+ touchPoint.setScreenPos(touchStart);
+ QTouchEvent touchEvent1(QEvent::TouchBegin,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointPressed,
+ (QList<QTouchEvent::TouchPoint>() << touchPoint));
+ QApplication::sendEvent(sw, &touchEvent1);
+
+ // send the touch update far enough to trigger a scroll
+ QTest::qWait(200); // we need to wait a little or else the speed would be infinite. now we have around 500 pixel per second.
+ touchPoint.setPos(touchUpdate);
+ touchPoint.setScenePos(touchUpdate);
+ touchPoint.setScreenPos(touchUpdate);
+ QTouchEvent touchEvent2(QEvent::TouchUpdate,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointMoved,
+ (QList<QTouchEvent::TouchPoint>() << touchPoint));
+ QApplication::sendEvent(sw, &touchEvent2);
+
+ QTest::qWait(1000 / fps * 2); // wait until the first scroll move
+
+ // send the touch end
+ touchPoint.setPos(touchEnd);
+ touchPoint.setScenePos(touchEnd);
+ touchPoint.setScreenPos(touchEnd);
+ QTouchEvent touchEvent5(QEvent::TouchEnd,
+ QTouchEvent::TouchScreen,
+ Qt::NoModifier,
+ Qt::TouchPointReleased,
+ (QList<QTouchEvent::TouchPoint>() << touchPoint));
+ QApplication::sendEvent(sw, &touchEvent5);
+}
+
+
+void tst_QScroller::staticScrollers()
+{
+ // scrollers
+ {
+ QObject *o1 = new QObject(this);
+ QObject *o2 = new QObject(this);
+
+ // get scroller for object
+ QScroller *s1 = QScroller::scroller(o1);
+ QScroller *s2 = QScroller::scroller(o2);
+
+ QVERIFY(s1);
+ QVERIFY(s2);
+ QVERIFY(s1 != s2);
+
+ QVERIFY(!QScroller::scroller(static_cast<const QObject*>(0)));
+ QCOMPARE(QScroller::scroller(o1), s1);
+
+ delete o1;
+ delete o2;
+ }
+
+ // the same for properties
+ {
+ QObject *o1 = new QObject(this);
+ QObject *o2 = new QObject(this);
+
+ // get scroller for object
+ QScrollerProperties sp1 = QScroller::scroller(o1)->scrollerProperties();
+ QScrollerProperties sp2 = QScroller::scroller(o2)->scrollerProperties();
+
+ // default properties should be the same
+ QVERIFY(sp1 == sp2);
+
+ QCOMPARE(QScroller::scroller(o1)->scrollerProperties(), sp1);
+
+ delete o1;
+ delete o2;
+ }
+}
+
+void tst_QScroller::scrollerProperties()
+{
+ QObject *o1 = new QObject(this);
+ QScrollerProperties sp1 = QScroller::scroller(o1)->scrollerProperties();
+
+ QScrollerProperties::ScrollMetric metrics[] =
+ {
+ QScrollerProperties::MousePressEventDelay, // qreal [s]
+ QScrollerProperties::DragStartDistance, // qreal [m]
+ QScrollerProperties::DragVelocitySmoothingFactor, // qreal [0..1/s] (complex calculation involving time) v = v_new* DASF + v_old * (1-DASF)
+ QScrollerProperties::AxisLockThreshold, // qreal [0..1] atan(|min(dx,dy)|/|max(dx,dy)|)
+
+ QScrollerProperties::DecelerationFactor, // slope of the curve
+
+ QScrollerProperties::MinimumVelocity, // qreal [m/s]
+ QScrollerProperties::MaximumVelocity, // qreal [m/s]
+ QScrollerProperties::MaximumClickThroughVelocity, // qreal [m/s]
+
+ QScrollerProperties::AcceleratingFlickMaximumTime, // qreal [s]
+ QScrollerProperties::AcceleratingFlickSpeedupFactor, // qreal [1..]
+
+ QScrollerProperties::SnapPositionRatio, // qreal [0..1]
+ QScrollerProperties::SnapTime, // qreal [s]
+
+ QScrollerProperties::OvershootDragResistanceFactor, // qreal [0..1]
+ QScrollerProperties::OvershootDragDistanceFactor, // qreal [0..1]
+ QScrollerProperties::OvershootScrollDistanceFactor, // qreal [0..1]
+ QScrollerProperties::OvershootScrollTime, // qreal [s]
+ };
+
+ for (unsigned int i = 0; i < sizeof(metrics) / sizeof(metrics[0]); i++) {
+ sp1.setScrollMetric(metrics[i], 0.9);
+ QCOMPARE(sp1.scrollMetric(metrics[i]).toDouble(), 0.9);
+ }
+ sp1.setScrollMetric(QScrollerProperties::ScrollingCurve, QEasingCurve(QEasingCurve::OutQuart));
+ QCOMPARE(sp1.scrollMetric(QScrollerProperties::ScrollingCurve).toEasingCurve().type(), QEasingCurve::OutQuart);
+
+ sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootAlwaysOff));
+ QCOMPARE(sp1.scrollMetric(QScrollerProperties::HorizontalOvershootPolicy).value<QScrollerProperties::OvershootPolicy>(), QScrollerProperties::OvershootAlwaysOff);
+
+ sp1.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootAlwaysOn));
+ QCOMPARE(sp1.scrollMetric(QScrollerProperties::VerticalOvershootPolicy).value<QScrollerProperties::OvershootPolicy>(), QScrollerProperties::OvershootAlwaysOn);
+
+ sp1.setScrollMetric(QScrollerProperties::FrameRate, QVariant::fromValue(QScrollerProperties::Fps20));
+ QCOMPARE(sp1.scrollMetric(QScrollerProperties::FrameRate).value<QScrollerProperties::FrameRates>(), QScrollerProperties::Fps20);
+}
+
+void tst_QScroller::scrollTo()
+{
+ {
+ tst_QScrollerWidget *sw = new tst_QScrollerWidget();
+ sw->scrollArea = QRectF( 0, 0, 1000, 1000 );
+ sw->scrollPosition = QPointF( 500, 500 );
+
+ QScroller *s1 = QScroller::scroller(sw);
+ QCOMPARE( s1->state(), QScroller::Inactive );
+
+ // a normal scroll
+ s1->scrollTo(QPointF(100,100), 100);
+ QTest::qWait(200);
+
+ QCOMPARE( sw->receivedPrepare, true );
+ QCOMPARE( sw->receivedScroll, true );
+ QCOMPARE( sw->receivedFirst, true );
+ QCOMPARE( sw->receivedLast, true );
+ QCOMPARE( sw->receivedOvershoot, false );
+ QVERIFY(qFuzzyCompare( sw->currentPos.x(), 100 ));
+ QVERIFY(qFuzzyCompare( sw->currentPos.y(), 100 ));
+
+ delete sw;
+ }
+}
+
+// Mac OS X < 10.6 does not support QTouchEvents.
+#if !defined(QT_NO_GESTURES) && !(defined(Q_OS_MACX) && (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6))
+void tst_QScroller::scroll()
+{
+ // -- good case. normal scroll
+ tst_QScrollerWidget *sw = new tst_QScrollerWidget();
+ sw->scrollArea = QRectF(0, 0, 1000, 1000);
+ QScroller::grabGesture(sw, QScroller::TouchGesture);
+ sw->setGeometry(100, 100, 400, 300);
+
+ QScroller *s1 = QScroller::scroller(sw);
+ kineticScroll(sw, QPointF(500, 500), QPoint(0, 0), QPoint(100, 100), QPoint(200, 200));
+ // now we should be scrolling
+ QCOMPARE( s1->state(), QScroller::Scrolling );
+
+ // wait until finished, check that no further first scroll is send
+ sw->receivedFirst = false;
+ sw->receivedScroll = false;
+ while (s1->state() == QScroller::Scrolling)
+ QTest::qWait(100);
+
+ QCOMPARE( sw->receivedFirst, false );
+ QCOMPARE( sw->receivedScroll, true );
+ QCOMPARE( sw->receivedLast, true );
+ QVERIFY(sw->currentPos.x() < 400);
+ QVERIFY(sw->currentPos.y() < 400);
+
+ // -- try to scroll when nothing to scroll
+
+ sw->reset();
+ sw->scrollArea = QRectF(0, 0, 0, 1000);
+ kineticScrollNoTest(sw, QPointF(0, 500), QPoint(0, 0), QPoint(100, 0), QPoint(200, 0));
+
+ while (s1->state() != QScroller::Inactive)
+ QTest::qWait(20);
+
+ QCOMPARE(sw->currentPos.x(), 0.0);
+ QCOMPARE(sw->currentPos.y(), 500.0);
+
+ delete sw;
+}
+#endif
+
+// Mac OS X < 10.6 does not support QTouchEvents.
+#if !defined(QT_NO_GESTURES) && !(defined(Q_OS_MACX) && (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6))
+void tst_QScroller::overshoot()
+{
+ tst_QScrollerWidget *sw = new tst_QScrollerWidget();
+ sw->scrollArea = QRectF(0, 0, 1000, 1000);
+ QScroller::grabGesture(sw, QScroller::TouchGesture);
+ sw->setGeometry(100, 100, 400, 300);
+
+ QScroller *s1 = QScroller::scroller(sw);
+ QScrollerProperties sp1 = s1->scrollerProperties();
+
+ sp1.setScrollMetric(QScrollerProperties::OvershootDragResistanceFactor, 0.5);
+ sp1.setScrollMetric(QScrollerProperties::OvershootDragDistanceFactor, 0.2);
+ sp1.setScrollMetric(QScrollerProperties::OvershootScrollDistanceFactor, 0.2);
+
+ // -- try to scroll with overshoot (when scrollable good case)
+
+ sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootWhenScrollable));
+ s1->setScrollerProperties(sp1);
+ kineticScrollNoTest(sw, QPointF(500, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
+
+ while (s1->state() != QScroller::Inactive)
+ QTest::qWait(20);
+
+ //qDebug() << "Overshoot fuzzy: "<<sw->currentPos;
+ QVERIFY(qFuzzyCompare( sw->currentPos.x(), 0 ));
+ QVERIFY(qFuzzyCompare( sw->currentPos.y(), 500 ));
+ QCOMPARE( sw->receivedOvershoot, true );
+
+ // -- try to scroll with overshoot (when scrollable bad case)
+ sw->reset();
+ sw->scrollArea = QRectF(0, 0, 0, 1000);
+
+ sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootWhenScrollable));
+ s1->setScrollerProperties(sp1);
+ kineticScrollNoTest(sw, QPointF(0, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
+
+ while (s1->state() != QScroller::Inactive)
+ QTest::qWait(20);
+
+ //qDebug() << "Overshoot fuzzy: "<<sw->currentPos;
+ QVERIFY(qFuzzyCompare( sw->currentPos.x(), 0 ));
+ QVERIFY(qFuzzyCompare( sw->currentPos.y(), 500 ));
+ QCOMPARE( sw->receivedOvershoot, false );
+
+ // -- try to scroll with overshoot (always on)
+ sw->reset();
+ sw->scrollArea = QRectF(0, 0, 0, 1000);
+
+ sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootAlwaysOn));
+ s1->setScrollerProperties(sp1);
+ kineticScrollNoTest(sw, QPointF(0, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
+
+ while (s1->state() != QScroller::Inactive)
+ QTest::qWait(20);
+
+ //qDebug() << "Overshoot fuzzy: "<<sw->currentPos;
+
+ QVERIFY(qFuzzyCompare( sw->currentPos.x(), 0 ));
+ QVERIFY(qFuzzyCompare( sw->currentPos.y(), 500 ));
+ QCOMPARE( sw->receivedOvershoot, true );
+
+ // -- try to scroll with overshoot (always off)
+ sw->reset();
+ sw->scrollArea = QRectF(0, 0, 1000, 1000);
+
+ sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootAlwaysOff));
+ s1->setScrollerProperties(sp1);
+ kineticScrollNoTest(sw, QPointF(500, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
+
+ while (s1->state() != QScroller::Inactive)
+ QTest::qWait(20);
+
+ QVERIFY(qFuzzyCompare( sw->currentPos.x(), 0 ));
+ QVERIFY(qFuzzyCompare( sw->currentPos.y(), 500 ));
+ QCOMPARE( sw->receivedOvershoot, false );
+
+ // -- try to scroll with overshoot (always on but max overshoot = 0)
+ sp1.setScrollMetric(QScrollerProperties::OvershootDragDistanceFactor, 0.0);
+ sp1.setScrollMetric(QScrollerProperties::OvershootScrollDistanceFactor, 0.0);
+ sw->reset();
+ sw->scrollArea = QRectF(0, 0, 1000, 1000);
+
+ sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootAlwaysOn));
+ s1->setScrollerProperties(sp1);
+ kineticScrollNoTest(sw, QPointF(500, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0));
+
+ while (s1->state() != QScroller::Inactive)
+ QTest::qWait(20);
+
+ QVERIFY(qFuzzyCompare( sw->currentPos.x(), 0 ));
+ QVERIFY(qFuzzyCompare( sw->currentPos.y(), 500 ));
+ QCOMPARE( sw->receivedOvershoot, false );
+
+ delete sw;
+}
+#endif
+
+QTEST_MAIN(tst_QScroller)
+
+#include "tst_qscroller.moc"
diff --git a/tests/auto/widgets/util/qsystemtrayicon/.gitignore b/tests/auto/widgets/util/qsystemtrayicon/.gitignore
new file mode 100644
index 0000000000..6da1f79209
--- /dev/null
+++ b/tests/auto/widgets/util/qsystemtrayicon/.gitignore
@@ -0,0 +1 @@
+tst_qsystemtrayicon
diff --git a/tests/auto/widgets/util/qsystemtrayicon/icons/icon.png b/tests/auto/widgets/util/qsystemtrayicon/icons/icon.png
new file mode 100644
index 0000000000..7528931ed8
--- /dev/null
+++ b/tests/auto/widgets/util/qsystemtrayicon/icons/icon.png
Binary files differ
diff --git a/tests/auto/widgets/util/qsystemtrayicon/qsystemtrayicon.pro b/tests/auto/widgets/util/qsystemtrayicon/qsystemtrayicon.pro
new file mode 100644
index 0000000000..8a6ea3d0a9
--- /dev/null
+++ b/tests/auto/widgets/util/qsystemtrayicon/qsystemtrayicon.pro
@@ -0,0 +1,9 @@
+############################################################
+# Project file for autotest for file qsystemtrayicon.h
+############################################################
+
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qsystemtrayicon.cpp
+
+
diff --git a/tests/auto/widgets/util/qsystemtrayicon/tst_qsystemtrayicon.cpp b/tests/auto/widgets/util/qsystemtrayicon/tst_qsystemtrayicon.cpp
new file mode 100644
index 0000000000..a4a5ed7ad9
--- /dev/null
+++ b/tests/auto/widgets/util/qsystemtrayicon/tst_qsystemtrayicon.cpp
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qcoreapplication.h>
+#include <qdebug.h>
+#include <qsystemtrayicon.h>
+#include <qmenu.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QSystemTrayIcon: public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QSystemTrayIcon();
+ virtual ~tst_QSystemTrayIcon();
+
+private slots:
+ void getSetCheck();
+ void showHide();
+ void showMessage();
+ void supportsMessages();
+ void lastWindowClosed();
+};
+
+tst_QSystemTrayIcon::tst_QSystemTrayIcon()
+{
+}
+
+tst_QSystemTrayIcon::~tst_QSystemTrayIcon()
+{
+}
+
+// Testing get/set functions
+void tst_QSystemTrayIcon::showHide()
+{
+ QSystemTrayIcon icon;
+ icon.setIcon(QIcon("icons/icon.png"));
+ icon.show();
+ icon.setIcon(QIcon("icons/icon.png"));
+ icon.hide();
+}
+
+// Testing get/set functions
+void tst_QSystemTrayIcon::showMessage()
+{
+ QSystemTrayIcon icon;
+ icon.setIcon(QIcon("icons/icon.png"));
+
+ icon.showMessage("Title", "Messagecontents");
+ icon.showMessage("Title", "Messagecontents", QSystemTrayIcon::NoIcon);
+ icon.showMessage("Title", "Messagecontents", QSystemTrayIcon::Warning);
+ icon.showMessage("Title", "Messagecontents", QSystemTrayIcon::Critical);
+
+ icon.show();
+ icon.showMessage("Title", "Messagecontents");
+ icon.showMessage("Title", "Messagecontents", QSystemTrayIcon::NoIcon);
+ icon.showMessage("Title", "Messagecontents", QSystemTrayIcon::Warning);
+ icon.showMessage("Title", "Messagecontents", QSystemTrayIcon::Critical);
+}
+
+// Testing get/set functions
+void tst_QSystemTrayIcon::getSetCheck()
+{
+ QSystemTrayIcon icon;
+ QCOMPARE(true, icon.toolTip().isEmpty());
+ icon.setToolTip("testToolTip");
+ QCOMPARE(true, "testToolTip" == icon.toolTip());
+
+ QCOMPARE(true, icon.icon().isNull());
+ icon.setIcon(QIcon("icons/icon.png"));
+ QCOMPARE(false, icon.icon().isNull());
+
+ QMenu menu;
+ QCOMPARE(true, icon.contextMenu() == 0);
+ icon.setContextMenu(&menu);
+ QCOMPARE(false, icon.contextMenu() == 0);
+}
+
+void tst_QSystemTrayIcon::supportsMessages()
+{
+#ifdef Q_WS_QPA
+ QEXPECT_FAIL("", "QTBUG-20978 QSystemTrayIcon is unimplemented for qpa", Abort);
+#endif
+
+#if !defined(Q_WS_QWS)
+ QCOMPARE(QSystemTrayIcon::supportsMessages(), true );
+#else
+ QCOMPARE(QSystemTrayIcon::supportsMessages(), false );
+#endif
+
+}
+
+void tst_QSystemTrayIcon::lastWindowClosed()
+{
+ QSignalSpy spy(qApp, SIGNAL(lastWindowClosed()));
+ QWidget window;
+ QSystemTrayIcon icon;
+ icon.setIcon(QIcon("whatever.png"));
+ icon.show();
+ window.show();
+ QTimer::singleShot(2500, &window, SLOT(close()));
+ QTimer::singleShot(20000, qApp, SLOT(quit())); // in case the test fails
+ qApp->exec();
+ QVERIFY(spy.count() == 1);
+}
+
+QTEST_MAIN(tst_QSystemTrayIcon)
+#include "tst_qsystemtrayicon.moc"
diff --git a/tests/auto/widgets/util/qundogroup/.gitignore b/tests/auto/widgets/util/qundogroup/.gitignore
new file mode 100644
index 0000000000..bc3e8c4691
--- /dev/null
+++ b/tests/auto/widgets/util/qundogroup/.gitignore
@@ -0,0 +1 @@
+tst_qundogroup
diff --git a/tests/auto/widgets/util/qundogroup/qundogroup.pro b/tests/auto/widgets/util/qundogroup/qundogroup.pro
new file mode 100644
index 0000000000..c2b6ceb038
--- /dev/null
+++ b/tests/auto/widgets/util/qundogroup/qundogroup.pro
@@ -0,0 +1,4 @@
+CONFIG += qttest_p4
+QT += widgets
+SOURCES += tst_qundogroup.cpp
+TARGET = tst_qundogroup
diff --git a/tests/auto/widgets/util/qundogroup/testdata/qundogroup.ts b/tests/auto/widgets/util/qundogroup/testdata/qundogroup.ts
new file mode 100644
index 0000000000..a059bcb486
--- /dev/null
+++ b/tests/auto/widgets/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/widgets/util/qundogroup/tst_qundogroup.cpp b/tests/auto/widgets/util/qundogroup/tst_qundogroup.cpp
new file mode 100644
index 0000000000..6d51252e22
--- /dev/null
+++ b/tests/auto/widgets/util/qundogroup/tst_qundogroup.cpp
@@ -0,0 +1,668 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtTest/QtTest>
+#include <QUndoGroup>
+#include <QUndoStack>
+#include <QAction>
+
+// Temporarily disabling IRIX due to build issuues with GCC
+#if !defined(__sgi) || defined(__sgi) && !defined(__GNUC__)
+
+/******************************************************************************
+** 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(), (QUndoStack*)0);
+ 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(), (QUndoStack*)0);
+ QCOMPARE(stack1.isActive(), false);
+ QCOMPARE(stack2.isActive(), true);
+ QCOMPARE(stack3.isActive(), false);
+
+ group.removeStack(&stack2);
+ QCOMPARE(group.activeStack(), (QUndoStack*)0);
+ 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(), (QUndoStack*)0);
+
+ 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(), (QUndoStack*)0);
+
+ stack3->setActive(false);
+ QCOMPARE(group.activeStack(), (QUndoStack*)0);
+
+ stack3->setActive(true);
+ QCOMPARE(group.activeStack(), stack3);
+
+ group.removeStack(stack3);
+ QCOMPARE(group.stacks(), QList<QUndoStack*>());
+ QCOMPARE(group.activeStack(), (QUndoStack*)0);
+
+ 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;
+ QAction *undo_action = group.createUndoAction(0, QString("foo"));
+ QAction *redo_action = group.createRedoAction(0, QString("bar"));
+ QSignalSpy indexChangedSpy(&group, SIGNAL(indexChanged(int)));
+ QSignalSpy cleanChangedSpy(&group, SIGNAL(cleanChanged(bool)));
+ QSignalSpy canUndoChangedSpy(&group, SIGNAL(canUndoChanged(bool)));
+ QSignalSpy undoTextChangedSpy(&group, SIGNAL(undoTextChanged(QString)));
+ QSignalSpy canRedoChangedSpy(&group, SIGNAL(canRedoChanged(bool)));
+ QSignalSpy redoTextChangedSpy(&group, SIGNAL(redoTextChanged(QString)));
+
+ 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
+
+ delete undo_action;
+ delete redo_action;
+}
+
+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()
+{
+ QString binDir = QLibraryInfo::location(QLibraryInfo::BinariesPath);
+
+ if (QProcess::execute(binDir + "/lrelease -version") != 0) {
+ QSKIP("lrelease is missing or broken", SkipAll);
+ }
+
+ QVERIFY(!QProcess::execute(binDir + "/lrelease testdata/qundogroup.ts"));
+
+ QTranslator translator;
+ QVERIFY(translator.load("testdata/qundogroup.qm"));
+ qApp->installTranslator(&translator);
+
+ QUndoGroup group;
+ QAction *undo_action = group.createUndoAction(0);
+ QAction *redo_action = group.createRedoAction(0);
+
+ 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);
+}
+
+#else
+class tst_QUndoGroup : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QUndoGroup() {}
+
+private slots:
+ void setActive() { QSKIP( "Not tested on irix-g++", SkipAll); }
+ void addRemoveStack() { QSKIP( "Not tested on irix-g++", SkipAll); }
+ void deleteStack() { QSKIP( "Not tested on irix-g++", SkipAll); }
+ void checkSignals() { QSKIP( "Not tested on irix-g++", SkipAll); }
+ void addStackAndDie() { QSKIP( "Not tested on irix-g++", SkipAll); }
+};
+#endif
+
+QTEST_MAIN(tst_QUndoGroup)
+
+#include "tst_qundogroup.moc"
+
diff --git a/tests/auto/widgets/util/qundostack/.gitignore b/tests/auto/widgets/util/qundostack/.gitignore
new file mode 100644
index 0000000000..f8faf2771f
--- /dev/null
+++ b/tests/auto/widgets/util/qundostack/.gitignore
@@ -0,0 +1 @@
+tst_qundostack
diff --git a/tests/auto/widgets/util/qundostack/qundostack.pro b/tests/auto/widgets/util/qundostack/qundostack.pro
new file mode 100644
index 0000000000..c8cfb70059
--- /dev/null
+++ b/tests/auto/widgets/util/qundostack/qundostack.pro
@@ -0,0 +1,4 @@
+CONFIG += qttest_p4
+QT += widgets
+SOURCES += tst_qundostack.cpp
+TARGET = tst_qundostack
diff --git a/tests/auto/widgets/util/qundostack/testdata/qundostack.ts b/tests/auto/widgets/util/qundostack/testdata/qundostack.ts
new file mode 100644
index 0000000000..4584036af2
--- /dev/null
+++ b/tests/auto/widgets/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/widgets/util/qundostack/tst_qundostack.cpp b/tests/auto/widgets/util/qundostack/tst_qundostack.cpp
new file mode 100644
index 0000000000..834c2d5d50
--- /dev/null
+++ b/tests/auto/widgets/util/qundostack/tst_qundostack.cpp
@@ -0,0 +1,3039 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QAction>
+#include <QUndoStack>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+/******************************************************************************
+** 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();
+};
+
+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()
+{
+}
+
+/******************************************************************************
+** 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 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,
+ QAction *const redoAction,
+ QAction *const 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;
+ QAction *undoAction = stack.createUndoAction(0, QString("foo"));
+ QAction *redoAction = stack.createRedoAction(0, QString("bar"));
+ QSignalSpy indexChangedSpy(&stack, SIGNAL(indexChanged(int)));
+ QSignalSpy cleanChangedSpy(&stack, SIGNAL(cleanChanged(bool)));
+ QSignalSpy canUndoChangedSpy(&stack, SIGNAL(canUndoChanged(bool)));
+ QSignalSpy undoTextChangedSpy(&stack, SIGNAL(undoTextChanged(QString)));
+ QSignalSpy canRedoChangedSpy(&stack, SIGNAL(canRedoChanged(bool)));
+ QSignalSpy redoTextChangedSpy(&stack, SIGNAL(redoTextChanged(QString)));
+ 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;
+ QAction *undoAction = stack.createUndoAction(0, QString("foo"));
+ QAction *redoAction = stack.createRedoAction(0, QString("bar"));
+ QSignalSpy indexChangedSpy(&stack, SIGNAL(indexChanged(int)));
+ QSignalSpy cleanChangedSpy(&stack, SIGNAL(cleanChanged(bool)));
+ QSignalSpy canUndoChangedSpy(&stack, SIGNAL(canUndoChanged(bool)));
+ QSignalSpy undoTextChangedSpy(&stack, SIGNAL(undoTextChanged(QString)));
+ QSignalSpy canRedoChangedSpy(&stack, SIGNAL(canRedoChanged(bool)));
+ QSignalSpy redoTextChangedSpy(&stack, SIGNAL(redoTextChanged(QString)));
+ 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;
+ QAction *undoAction = stack.createUndoAction(0, QString("foo"));
+ QAction *redoAction = stack.createRedoAction(0, QString("bar"));
+ QSignalSpy indexChangedSpy(&stack, SIGNAL(indexChanged(int)));
+ QSignalSpy cleanChangedSpy(&stack, SIGNAL(cleanChanged(bool)));
+ QSignalSpy canUndoChangedSpy(&stack, SIGNAL(canUndoChanged(bool)));
+ QSignalSpy undoTextChangedSpy(&stack, SIGNAL(undoTextChanged(QString)));
+ QSignalSpy canRedoChangedSpy(&stack, SIGNAL(canRedoChanged(bool)));
+ QSignalSpy redoTextChangedSpy(&stack, SIGNAL(redoTextChanged(QString)));
+ 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);
+}
+
+void tst_QUndoStack::clear()
+{
+ QUndoStack stack;
+ QAction *undoAction = stack.createUndoAction(this, QString("foo"));
+ QAction *redoAction = stack.createRedoAction(this, QString("bar"));
+ QSignalSpy indexChangedSpy(&stack, SIGNAL(indexChanged(int)));
+ QSignalSpy cleanChangedSpy(&stack, SIGNAL(cleanChanged(bool)));
+ QSignalSpy canUndoChangedSpy(&stack, SIGNAL(canUndoChanged(bool)));
+ QSignalSpy undoTextChangedSpy(&stack, SIGNAL(undoTextChanged(QString)));
+ QSignalSpy canRedoChangedSpy(&stack, SIGNAL(canRedoChanged(bool)));
+ QSignalSpy redoTextChangedSpy(&stack, SIGNAL(redoTextChanged(QString)));
+ 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;
+ QAction *undoAction = stack.createUndoAction(0, QString("foo"));
+ QAction *redoAction = stack.createRedoAction(0, QString("bar"));
+ QSignalSpy indexChangedSpy(&stack, SIGNAL(indexChanged(int)));
+ QSignalSpy cleanChangedSpy(&stack, SIGNAL(cleanChanged(bool)));
+ QSignalSpy canUndoChangedSpy(&stack, SIGNAL(canUndoChanged(bool)));
+ QSignalSpy undoTextChangedSpy(&stack, SIGNAL(undoTextChanged(QString)));
+ QSignalSpy canRedoChangedSpy(&stack, SIGNAL(canRedoChanged(bool)));
+ QSignalSpy redoTextChangedSpy(&stack, SIGNAL(redoTextChanged(QString)));
+ 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
+
+ delete undoAction;
+ delete redoAction;
+}
+
+void tst_QUndoStack::macroBeginEnd()
+{
+ QUndoStack stack;
+ QAction *undoAction = stack.createUndoAction(0, QString("foo"));
+ QAction *redoAction = stack.createRedoAction(0, QString("bar"));
+ QSignalSpy indexChangedSpy(&stack, SIGNAL(indexChanged(int)));
+ QSignalSpy cleanChangedSpy(&stack, SIGNAL(cleanChanged(bool)));
+ QSignalSpy canUndoChangedSpy(&stack, SIGNAL(canUndoChanged(bool)));
+ QSignalSpy undoTextChangedSpy(&stack, SIGNAL(undoTextChanged(QString)));
+ QSignalSpy canRedoChangedSpy(&stack, SIGNAL(canRedoChanged(bool)));
+ QSignalSpy redoTextChangedSpy(&stack, SIGNAL(redoTextChanged(QString)));
+ 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
+
+ delete undoAction;
+ delete redoAction;
+}
+
+void tst_QUndoStack::compression()
+{
+ QUndoStack stack;
+ QAction *undoAction = stack.createUndoAction(0, QString("foo"));
+ QAction *redoAction = stack.createRedoAction(0, QString("bar"));
+ QSignalSpy indexChangedSpy(&stack, SIGNAL(indexChanged(int)));
+ QSignalSpy cleanChangedSpy(&stack, SIGNAL(cleanChanged(bool)));
+ QSignalSpy canUndoChangedSpy(&stack, SIGNAL(canUndoChanged(bool)));
+ QSignalSpy undoTextChangedSpy(&stack, SIGNAL(undoTextChanged(QString)));
+ QSignalSpy canRedoChangedSpy(&stack, SIGNAL(canRedoChanged(bool)));
+ QSignalSpy redoTextChangedSpy(&stack, SIGNAL(redoTextChanged(QString)));
+ 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
+
+ delete undoAction;
+ delete redoAction;
+}
+
+void tst_QUndoStack::undoLimit()
+{
+ QUndoStack stack;
+ QAction *undoAction = stack.createUndoAction(0, QString("foo"));
+ QAction *redoAction = stack.createRedoAction(0, QString("bar"));
+ QSignalSpy indexChangedSpy(&stack, SIGNAL(indexChanged(int)));
+ QSignalSpy cleanChangedSpy(&stack, SIGNAL(cleanChanged(bool)));
+ QSignalSpy canUndoChangedSpy(&stack, SIGNAL(canUndoChanged(bool)));
+ QSignalSpy undoTextChangedSpy(&stack, SIGNAL(undoTextChanged(QString)));
+ QSignalSpy canRedoChangedSpy(&stack, SIGNAL(canRedoChanged(bool)));
+ QSignalSpy redoTextChangedSpy(&stack, SIGNAL(redoTextChanged(QString)));
+ 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()
+{
+ QString binDir = QLibraryInfo::location(QLibraryInfo::BinariesPath);
+
+ if (QProcess::execute(binDir + "/lrelease -version") != 0) {
+ QSKIP("lrelease is missing or broken", SkipAll);
+ }
+
+ QVERIFY(!QProcess::execute(binDir + "/lrelease testdata/qundostack.ts"));
+
+ QTranslator translator;
+ QVERIFY(translator.load("testdata/qundostack.qm"));
+ qApp->installTranslator(&translator);
+
+ QUndoStack stack;
+ QAction *undo_action = stack.createUndoAction(0);
+ QAction *redo_action = stack.createRedoAction(0);
+
+ 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);
+}
+
+void tst_QUndoStack::separateUndoText()
+{
+ QUndoStack stack;
+ QAction *undo_action = stack.createUndoAction(0);
+ QAction *redo_action = stack.createRedoAction(0);
+
+ 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/widgets/util/util.pro b/tests/auto/widgets/util/util.pro
new file mode 100644
index 0000000000..b7fe35ce4c
--- /dev/null
+++ b/tests/auto/widgets/util/util.pro
@@ -0,0 +1,11 @@
+TEMPLATE=subdirs
+SUBDIRS=\
+ qcompleter \
+ qscroller \
+ qsystemtrayicon \
+ qundogroup \
+ qundostack \
+
+symbian:SUBDIRS -= \
+ qsystemtrayicon \
+