From b9927f9998bc071ae6bc1b09c99126c13cb5029e Mon Sep 17 00:00:00 2001
From: Friedemann Kleint <Friedemann.Kleint@nokia.com>
Date: Wed, 16 Dec 2009 14:19:34 +0100
Subject: [PATCH] Wizards: Add a simple wizard for unit tests.

---
 src/plugins/coreplugin/basefilewizard.cpp     |   2 +-
 src/plugins/coreplugin/basefilewizard.h       |   2 +-
 .../qt4projectmanager/qt4projectmanager.pro   |   9 +-
 .../qt4projectmanagerplugin.cpp               |   2 +
 .../wizards/qtprojectparameters.cpp           |   5 +-
 .../wizards/qtprojectparameters.h             |   1 +
 .../qt4projectmanager/wizards/qtwizard.cpp    |  10 +-
 .../qt4projectmanager/wizards/qtwizard.h      |  12 +-
 .../qt4projectmanager/wizards/testwizard.cpp  | 179 ++++++++++++++++++
 .../qt4projectmanager/wizards/testwizard.h    |  62 ++++++
 .../wizards/testwizarddialog.cpp              |  92 +++++++++
 .../wizards/testwizarddialog.h                |  83 ++++++++
 .../wizards/testwizardpage.cpp                | 148 +++++++++++++++
 .../wizards/testwizardpage.h                  |  79 ++++++++
 .../wizards/testwizardpage.ui                 | 129 +++++++++++++
 15 files changed, 800 insertions(+), 15 deletions(-)
 create mode 100644 src/plugins/qt4projectmanager/wizards/testwizard.cpp
 create mode 100644 src/plugins/qt4projectmanager/wizards/testwizard.h
 create mode 100644 src/plugins/qt4projectmanager/wizards/testwizarddialog.cpp
 create mode 100644 src/plugins/qt4projectmanager/wizards/testwizarddialog.h
 create mode 100644 src/plugins/qt4projectmanager/wizards/testwizardpage.cpp
 create mode 100644 src/plugins/qt4projectmanager/wizards/testwizardpage.h
 create mode 100644 src/plugins/qt4projectmanager/wizards/testwizardpage.ui

diff --git a/src/plugins/coreplugin/basefilewizard.cpp b/src/plugins/coreplugin/basefilewizard.cpp
index cfa151b41c4..191411e1b0f 100644
--- a/src/plugins/coreplugin/basefilewizard.cpp
+++ b/src/plugins/coreplugin/basefilewizard.cpp
@@ -643,7 +643,7 @@ QString BaseFileWizard::buildFileName(const QString &path,
     return rc;
 }
 
-QString BaseFileWizard::preferredSuffix(const QString &mimeType) const
+QString BaseFileWizard::preferredSuffix(const QString &mimeType)
 {
     const QString rc = Core::ICore::instance()->mimeDatabase()->preferredSuffixByType(mimeType);
     if (rc.isEmpty())
diff --git a/src/plugins/coreplugin/basefilewizard.h b/src/plugins/coreplugin/basefilewizard.h
index 4b77bdb9df1..7bd2aed6584 100644
--- a/src/plugins/coreplugin/basefilewizard.h
+++ b/src/plugins/coreplugin/basefilewizard.h
@@ -190,7 +190,7 @@ protected:
     virtual bool postGenerateFiles(const GeneratedFiles &l, QString *errorMessage);
 
     // Utility that returns the preferred suffix for a mime type
-    QString preferredSuffix(const QString &mimeType) const;
+    static QString preferredSuffix(const QString &mimeType);
 
     // Utility that performs an overwrite check on a set of files. It checks if
     // the file exists, can be overwritten at all and prompts the user.
diff --git a/src/plugins/qt4projectmanager/qt4projectmanager.pro b/src/plugins/qt4projectmanager/qt4projectmanager.pro
index 1d5b261c01c..b44f104a717 100644
--- a/src/plugins/qt4projectmanager/qt4projectmanager.pro
+++ b/src/plugins/qt4projectmanager/qt4projectmanager.pro
@@ -21,6 +21,9 @@ HEADERS += qt4projectmanagerplugin.h \
     wizards/guiappwizarddialog.h \
     wizards/emptyprojectwizard.h \
     wizards/emptyprojectwizarddialog.h \
+    wizards/testwizard.h \
+    wizards/testwizarddialog.h \
+    wizards/testwizardpage.h \
     wizards/modulespage.h \
     wizards/filespage.h \
     wizards/qtwizard.h \
@@ -58,6 +61,9 @@ SOURCES += qt4projectmanagerplugin.cpp \
     wizards/guiappwizarddialog.cpp \
     wizards/emptyprojectwizard.cpp \
     wizards/emptyprojectwizarddialog.cpp \
+    wizards/testwizard.cpp \
+    wizards/testwizarddialog.cpp \
+    wizards/testwizardpage.cpp \
     wizards/modulespage.cpp \
     wizards/filespage.cpp \
     wizards/qtwizard.cpp \
@@ -81,7 +87,8 @@ FORMS += makestep.ui \
     qt4projectconfigwidget.ui \
     qtversionmanager.ui \
     showbuildlog.ui \
-    gettingstartedwelcomepagewidget.ui
+    gettingstartedwelcomepagewidget.ui \
+    wizards/testwizardpage.ui
 RESOURCES += qt4projectmanager.qrc \
     wizards/wizards.qrc
 include(../../shared/proparser/proparser.pri)
diff --git a/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp b/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp
index e5b0e4e4e47..141462382cb 100644
--- a/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp
+++ b/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp
@@ -33,6 +33,7 @@
 #include "wizards/consoleappwizard.h"
 #include "wizards/guiappwizard.h"
 #include "wizards/librarywizard.h"
+#include "wizards/testwizard.h"
 #include "wizards/emptyprojectwizard.h"
 #include "customwidgetwizard/customwidgetwizard.h"
 #include "profileeditorfactory.h"
@@ -132,6 +133,7 @@ bool Qt4ProjectManagerPlugin::initialize(const QStringList &arguments, QString *
 
     LibraryWizard *libWizard = new LibraryWizard;
     addAutoReleasedObject(libWizard);
+    addAutoReleasedObject(new TestWizard);
     addAutoReleasedObject(new CustomWidgetWizard);
 
     addAutoReleasedObject(new QMakeStepFactory);
diff --git a/src/plugins/qt4projectmanager/wizards/qtprojectparameters.cpp b/src/plugins/qt4projectmanager/wizards/qtprojectparameters.cpp
index a658a6bc223..e91aedaa62a 100644
--- a/src/plugins/qt4projectmanager/wizards/qtprojectparameters.cpp
+++ b/src/plugins/qt4projectmanager/wizards/qtprojectparameters.cpp
@@ -60,8 +60,9 @@ void QtProjectParameters::writeProFile(QTextStream &str) const
         str << "QT       += " << selectedModules << "\n\n";
     if (!deselectedModules.isEmpty())
         str << "QT       -= " << deselectedModules << "\n\n";
-    if (!name.isEmpty())
-        str << "TARGET = " <<  name << '\n';
+    const QString &effectiveTarget = target.isEmpty() ? name : target;
+    if (!effectiveTarget.isEmpty())
+        str << "TARGET = " <<  effectiveTarget << '\n';
     switch (type) {
     case ConsoleApp:
         // Mac: Command line apps should not be bundles
diff --git a/src/plugins/qt4projectmanager/wizards/qtprojectparameters.h b/src/plugins/qt4projectmanager/wizards/qtprojectparameters.h
index 4865c757048..c3614040515 100644
--- a/src/plugins/qt4projectmanager/wizards/qtprojectparameters.h
+++ b/src/plugins/qt4projectmanager/wizards/qtprojectparameters.h
@@ -62,6 +62,7 @@ struct QtProjectParameters {
 
     Type type;
     QString name;
+    QString target;
     QString path;
     QString selectedModules;
     QString deselectedModules;
diff --git a/src/plugins/qt4projectmanager/wizards/qtwizard.cpp b/src/plugins/qt4projectmanager/wizards/qtwizard.cpp
index e27eeb68139..9bd987f7aa2 100644
--- a/src/plugins/qt4projectmanager/wizards/qtwizard.cpp
+++ b/src/plugins/qt4projectmanager/wizards/qtwizard.cpp
@@ -71,22 +71,22 @@ QtWizard::QtWizard(const QString &id, const QString &name,
 {
 }
 
-QString QtWizard::sourceSuffix()  const
+QString QtWizard::sourceSuffix()
 {
     return preferredSuffix(QLatin1String(Constants::CPP_SOURCE_MIMETYPE));
 }
 
-QString QtWizard::headerSuffix()  const
+QString QtWizard::headerSuffix()
 {
     return preferredSuffix(QLatin1String(Constants::CPP_HEADER_MIMETYPE));
 }
 
-QString QtWizard::formSuffix()    const
+QString QtWizard::formSuffix()
 {
     return preferredSuffix(QLatin1String(Constants::FORM_MIMETYPE));
 }
 
-QString QtWizard::profileSuffix() const
+QString QtWizard::profileSuffix()
 {
     return preferredSuffix(QLatin1String(Constants::PROFILE_MIMETYPE));
 }
@@ -102,7 +102,7 @@ bool QtWizard::postGenerateFiles(const Core::GeneratedFiles &l, QString *errorMe
     return true;
 }
 
-QString QtWizard::templateDir() const
+QString QtWizard::templateDir()
 {
     QString rc = Core::ICore::instance()->resourcePath();
     rc += QLatin1String("/templates/qt4project");
diff --git a/src/plugins/qt4projectmanager/wizards/qtwizard.h b/src/plugins/qt4projectmanager/wizards/qtwizard.h
index c0cffd54292..9844f394d84 100644
--- a/src/plugins/qt4projectmanager/wizards/qtwizard.h
+++ b/src/plugins/qt4projectmanager/wizards/qtwizard.h
@@ -60,12 +60,14 @@ protected:
              const QString &description,
              const QIcon &icon);
 
-    QString templateDir() const;
+public:
+
+    static QString templateDir();
 
-    QString sourceSuffix()  const;
-    QString headerSuffix()  const;
-    QString formSuffix()    const;
-    QString profileSuffix() const;
+    static QString sourceSuffix();
+    static QString headerSuffix();
+    static QString formSuffix();
+    static QString profileSuffix();
 
     // Query CppTools settings for the class wizard settings
     static bool lowerCaseFiles();
diff --git a/src/plugins/qt4projectmanager/wizards/testwizard.cpp b/src/plugins/qt4projectmanager/wizards/testwizard.cpp
new file mode 100644
index 00000000000..2257daa01ba
--- /dev/null
+++ b/src/plugins/qt4projectmanager/wizards/testwizard.cpp
@@ -0,0 +1,179 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "testwizard.h"
+#include "testwizarddialog.h"
+#include <cpptools/cppmodelmanager.h>
+
+#include <utils/qtcassert.h>
+
+#include <QtCore/QTextStream>
+#include <QtCore/QFileInfo>
+
+#include <QtGui/QIcon>
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+TestWizard::TestWizard() :
+    QtWizard(QLatin1String("E.Qt4Test"),
+             tr("Qt4 Unit Test"),
+             tr("Creates a Qt4 Unit Test."),
+             QIcon(QLatin1String(":/wizards/images/console.png")))
+{
+}
+
+QWizard *TestWizard::createWizardDialog(QWidget *parent,
+                                        const QString &defaultPath,
+                                        const WizardPageList &extensionPages) const
+{
+    TestWizardDialog *dialog = new TestWizardDialog(name(), icon(), extensionPages, parent);
+    dialog->setPath(defaultPath);
+    dialog->setName(TestWizardDialog::projectName(defaultPath));
+    return dialog;
+}
+
+// ---------------- code generation helpers
+static const char initTestCaseC[] = "initTestCase";
+static const char cleanupTestCaseC[] = "cleanupTestCase";
+static const char closeFunctionC[] = "}\n\n";
+static const char testDataTypeC[] = "QString";
+
+static inline void writeVoidMemberDeclaration(QTextStream &str,
+                                              const QString &indent,
+                                              const QString &methodName)
+{
+    str << indent << "void " << methodName << "();\n";
+}
+
+static inline void writeVoidMemberBody(QTextStream &str,
+                                       const QString &className,
+                                       const QString &methodName,
+                                       bool close = true)
+{
+    str << "void " << className << "::" << methodName << "()\n{\n";
+    if (close)
+        str << closeFunctionC;
+}
+
+static QString generateTestCode(const TestWizardParameters &testParams,
+                                const QString &sourceBaseName)
+{
+    QString rc;
+    const QString indent = QString(4, QLatin1Char(' '));
+    QTextStream str(&rc);
+    // Includes
+    str << CppTools::AbstractEditorSupport::licenseTemplate()
+        << "#include <QtCore/QString>\n#include <QtTest/QtTest>\n";
+    if (testParams.requiresQApplication)
+        str << "#include <QtCore/QCoreApplication>\n";
+    // Class declaration
+    str  << "\nclass " << testParams.className << " : public QObject\n"
+        "{\n" << indent << "Q_OBJECT\n\npublic:\n"
+        << indent << testParams.className << "();\n\nprivate Q_SLOTS:\n";
+    if (testParams.initializationCode) {
+        writeVoidMemberDeclaration(str, indent, QLatin1String(initTestCaseC));
+        writeVoidMemberDeclaration(str, indent, QLatin1String(cleanupTestCaseC));
+    }
+    const QString dataSlot = testParams.testSlot + QLatin1String("_data");
+    writeVoidMemberDeclaration(str, indent, testParams.testSlot);
+    if (testParams.useDataSet)
+        writeVoidMemberDeclaration(str, indent, dataSlot);
+    str << "};\n\n";
+    // Code: Constructor
+    str << testParams.className << "::" << testParams.className << "()\n{\n}\n\n";
+    // Code: Initialization slots
+    if (testParams.initializationCode) {
+        writeVoidMemberBody(str, testParams.className, QLatin1String(initTestCaseC));
+        writeVoidMemberBody(str, testParams.className, QLatin1String(cleanupTestCaseC));
+    }
+    // Test slot with data or dummy
+    writeVoidMemberBody(str, testParams.className, testParams.testSlot, false);
+    if (testParams.useDataSet) {
+        str << indent << "QFETCH(" << testDataTypeC << ", data);\n";
+    }
+    switch (testParams.type) {
+    case TestWizardParameters::Test:
+        str << indent << "QVERIFY2(true, \"Failure\");\n";
+        break;
+    case TestWizardParameters::Benchmark:
+        str << indent << "QBENCHMARK {\n" << indent << "}\n";
+        break;
+    }
+    str << closeFunctionC;
+    // test data generation slot
+    if (testParams.useDataSet) {
+        writeVoidMemberBody(str, testParams.className, dataSlot, false);
+        str << indent << "QTest::addColumn<" << testDataTypeC << ">(\"data\");\n"
+            << indent << "QTest::newRow(\"0\") << " << testDataTypeC << "();\n"
+            << closeFunctionC;
+    }
+    // Main & moc include
+    str << (testParams.requiresQApplication ? "QTEST_MAIN" : "QTEST_APPLESS_MAIN")
+        << '(' << testParams.className << ");\n\n"
+        << "#include \"" << sourceBaseName << ".moc\"\n";
+    return rc;
+}
+
+Core::GeneratedFiles TestWizard::generateFiles(const QWizard *w, QString *errorMessage) const
+{
+    Q_UNUSED(errorMessage)
+
+    const TestWizardDialog *wizardDialog = qobject_cast<const TestWizardDialog *>(w);
+    QTC_ASSERT(wizardDialog, return Core::GeneratedFiles())
+
+    const QtProjectParameters projectParams = wizardDialog->projectParameters();
+    const TestWizardParameters testParams = wizardDialog->testParameters();
+    const QString projectPath = projectParams.projectPath();
+
+    // Create files: Source
+    const QString sourceFilePath = Core::BaseFileWizard::buildFileName(projectPath, testParams.fileName, sourceSuffix());
+    const QFileInfo sourceFileInfo(sourceFilePath);
+
+    Core::GeneratedFile source(sourceFilePath);
+    source.setContents(generateTestCode(testParams, sourceFileInfo.baseName()));
+
+    // Create profile with define for base dir to find test data
+    const QString profileName = Core::BaseFileWizard::buildFileName(projectPath, projectParams.name, profileSuffix());
+    Core::GeneratedFile profile(profileName);
+    QString contents;
+    {
+        QTextStream proStr(&contents);
+        QtProjectParameters::writeProFileHeader(proStr);
+        projectParams.writeProFile(proStr);
+        proStr << "\n\nSOURCES += " << QFileInfo(sourceFilePath).fileName() << '\n'
+               << "DEFINES += SRCDIR=\\\\\\\"$$PWD/\\\\\\\"\n";
+    }
+    profile.setContents(contents);
+
+    return Core::GeneratedFiles() <<  source << profile;
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/wizards/testwizard.h b/src/plugins/qt4projectmanager/wizards/testwizard.h
new file mode 100644
index 00000000000..a1d0e344ca2
--- /dev/null
+++ b/src/plugins/qt4projectmanager/wizards/testwizard.h
@@ -0,0 +1,62 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef TESTWIZARD_H
+#define TESTWIZARD_H
+
+#include "qtwizard.h"
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+class TestWizard : public QtWizard
+{
+    Q_OBJECT
+    Q_DISABLE_COPY(TestWizard)
+public:
+    TestWizard();
+
+protected:
+    virtual QWizard *createWizardDialog(QWidget *parent,
+                                        const QString &defaultPath,
+                                        const WizardPageList &extensionPages) const;
+
+    virtual Core::GeneratedFiles generateFiles(const QWizard *w,
+                                               QString *errorMessage) const;
+
+signals:
+
+public slots:
+
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // TESTWIZARD_H
diff --git a/src/plugins/qt4projectmanager/wizards/testwizarddialog.cpp b/src/plugins/qt4projectmanager/wizards/testwizarddialog.cpp
new file mode 100644
index 00000000000..590e4c41d5e
--- /dev/null
+++ b/src/plugins/qt4projectmanager/wizards/testwizarddialog.cpp
@@ -0,0 +1,92 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "testwizarddialog.h"
+#include "testwizardpage.h"
+
+#include <QtCore/QFileInfo>
+
+enum PageIds { StartPageId, TestPageId, ModulesPageId };
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+const char *TestWizardParameters::filePrefix = "tst_";
+
+TestWizardParameters::TestWizardParameters() :
+    type(Test),
+    initializationCode(false),
+    useDataSet(false),
+    requiresQApplication(requiresQApplicationDefault)
+{
+}
+
+TestWizardDialog::TestWizardDialog(const QString &templateName,
+                                   const QIcon &icon,
+                                   const QList<QWizardPage*> &extensionPages,
+                                   QWidget *parent)  :
+    BaseQt4ProjectWizardDialog(true, parent),
+    m_testPage(new TestWizardPage)
+{
+    setWindowIcon(icon);
+    setWindowTitle(templateName);
+    setSelectedModules(QLatin1String("core testlib"), true);
+    setPage(TestPageId, m_testPage);
+    addModulesPage(ModulesPageId);
+    foreach (QWizardPage *p, extensionPages)
+        addPage(p);
+    connect(this, SIGNAL(currentIdChanged(int)), this, SLOT(slotCurrentIdChanged(int)));
+}
+
+void TestWizardDialog::slotCurrentIdChanged(int id)
+{
+    if (id == TestPageId)
+        m_testPage->setProjectName(name());
+}
+
+TestWizardParameters TestWizardDialog::testParameters() const
+{
+    return m_testPage->parameters();
+}
+
+QtProjectParameters TestWizardDialog::projectParameters() const
+{
+    QtProjectParameters rc;
+    rc.type = QtProjectParameters::ConsoleApp;
+    rc.name = name();
+    rc.path = path();
+    // Name binary "tst_xx" after the main source
+    rc.target = QFileInfo(m_testPage->sourcefileName()).baseName();
+    rc.selectedModules = selectedModules();
+    rc.deselectedModules = deselectedModules();
+    return rc;
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/wizards/testwizarddialog.h b/src/plugins/qt4projectmanager/wizards/testwizarddialog.h
new file mode 100644
index 00000000000..a91e423618c
--- /dev/null
+++ b/src/plugins/qt4projectmanager/wizards/testwizarddialog.h
@@ -0,0 +1,83 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef TESTWIZARDDIALOG_H
+#define TESTWIZARDDIALOG_H
+
+#include "qtwizard.h"
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+class TestWizardPage;
+
+// Parameters of the test wizard.
+struct TestWizardParameters {
+    enum { requiresQApplicationDefault = 0 };
+
+    static const char *filePrefix;
+
+    TestWizardParameters();
+
+
+    enum Type { Test, Benchmark };
+
+    Type type;
+    bool initializationCode;
+    bool useDataSet;
+    bool requiresQApplication;
+
+    QString className;
+    QString testSlot;
+    QString fileName;
+};
+
+class TestWizardDialog : public BaseQt4ProjectWizardDialog
+{
+    Q_OBJECT
+public:
+    explicit TestWizardDialog(const QString &templateName,
+                              const QIcon &icon,
+                              const QList<QWizardPage*> &extensionPages,
+                              QWidget *parent = 0);
+
+    TestWizardParameters testParameters() const;
+    QtProjectParameters projectParameters() const;
+
+private slots:
+    void slotCurrentIdChanged(int id);
+
+private:
+    TestWizardPage *m_testPage;
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+
+#endif // TESTWIZARDDIALOG_H
diff --git a/src/plugins/qt4projectmanager/wizards/testwizardpage.cpp b/src/plugins/qt4projectmanager/wizards/testwizardpage.cpp
new file mode 100644
index 00000000000..843d5f7227e
--- /dev/null
+++ b/src/plugins/qt4projectmanager/wizards/testwizardpage.cpp
@@ -0,0 +1,148 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "testwizardpage.h"
+#include "testwizarddialog.h"
+#include "qtwizard.h"
+#include "ui_testwizardpage.h"
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+TestWizardPage::TestWizardPage(QWidget *parent) :
+    QWizardPage(parent),
+    m_sourceSuffix(QtWizard::sourceSuffix()),
+    m_lowerCaseFileNames(QtWizard::lowerCaseFiles()),
+    ui(new Ui::TestWizardPage),
+    m_fileNameEdited(false),
+    m_valid(false)
+{
+    ui->setupUi(this);
+    ui->testSlotLineEdit->setText(QLatin1String("testCase1"));
+    ui->testClassLineEdit->setLowerCaseFileName(m_lowerCaseFileNames);
+    ui->qApplicationCheckBox->setChecked(TestWizardParameters::requiresQApplicationDefault);
+    connect(ui->testClassLineEdit, SIGNAL(updateFileName(QString)),
+            this, SLOT(slotClassNameEdited(QString)));
+    connect(ui->fileLineEdit, SIGNAL(textEdited(QString)), \
+                this, SLOT(slotFileNameEdited()));
+    connect(ui->testClassLineEdit, SIGNAL(validChanged()),
+            this, SLOT(slotUpdateValid()));
+    connect(ui->testSlotLineEdit, SIGNAL(validChanged()),
+            this, SLOT(slotUpdateValid()));
+    connect(ui->fileLineEdit, SIGNAL(validChanged()),
+            this, SLOT(slotUpdateValid()));
+}
+
+TestWizardPage::~TestWizardPage()
+{
+    delete ui;
+}
+
+bool TestWizardPage::isComplete() const
+{
+    return m_valid;
+}
+
+QString TestWizardPage::sourcefileName() const
+{
+    return ui->fileLineEdit->text();
+}
+
+TestWizardParameters TestWizardPage::parameters() const
+{
+    TestWizardParameters rc;
+    rc.type = static_cast<TestWizardParameters::Type>(ui->typeComboBox->currentIndex());
+    rc.initializationCode = ui->initCheckBox->isChecked();
+    rc.useDataSet = ui->dataCheckBox->isChecked();
+    rc.requiresQApplication = ui->qApplicationCheckBox->isChecked();
+    rc.className = ui->testClassLineEdit->text();
+    rc.testSlot = ui->testSlotLineEdit->text();
+    rc.fileName = sourcefileName();
+    return rc;
+}
+
+static QString fileNameFromClass(const QString &className,
+                                 bool lowerCase,
+                                 const QString &suffix)
+{
+    QString rc = QLatin1String(TestWizardParameters::filePrefix);
+    rc += lowerCase ? className.toLower() : className;
+    rc += QLatin1Char('.');
+    rc += suffix;
+    return rc;
+}
+
+void TestWizardPage::setProjectName(const QString &t)
+{
+    if (t.isEmpty())
+        return;
+    // initially populate
+    QString className = t;
+    className[0] = className.at(0).toUpper();
+    className += QLatin1String("Test");
+    ui->testClassLineEdit->setText(className);
+    ui->fileLineEdit->setText(fileNameFromClass(className, m_lowerCaseFileNames, m_sourceSuffix));
+}
+
+void TestWizardPage::slotClassNameEdited(const QString &className)
+{
+    if (!m_fileNameEdited)
+        ui->fileLineEdit->setText(fileNameFromClass(className, m_lowerCaseFileNames, m_sourceSuffix));
+}
+
+void TestWizardPage::slotFileNameEdited()
+{
+    m_fileNameEdited = true;
+}
+
+void TestWizardPage::slotUpdateValid()
+{
+    const bool newValid = ui->fileLineEdit->isValid()
+                          && ui->testClassLineEdit->isValid()
+                          && ui->testSlotLineEdit->isValid();
+    if (newValid != m_valid) {
+        m_valid = newValid;
+        emit completeChanged();
+    }
+}
+
+void TestWizardPage::changeEvent(QEvent *e)
+{
+    QWizardPage::changeEvent(e);
+    switch (e->type()) {
+    case QEvent::LanguageChange:
+        ui->retranslateUi(this);
+        break;
+    default:
+        break;
+    }
+}
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
diff --git a/src/plugins/qt4projectmanager/wizards/testwizardpage.h b/src/plugins/qt4projectmanager/wizards/testwizardpage.h
new file mode 100644
index 00000000000..2f00979d257
--- /dev/null
+++ b/src/plugins/qt4projectmanager/wizards/testwizardpage.h
@@ -0,0 +1,79 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef TESTWIZARDPAGE_H
+#define TESTWIZARDPAGE_H
+
+#include <QtGui/QWizardPage>
+
+namespace Qt4ProjectManager {
+namespace Internal {
+
+namespace Ui {
+    class TestWizardPage;
+}
+
+struct TestWizardParameters;
+
+/* TestWizardPage: Let's the user input test class name, slot
+ * (for which a CLassNameValidatingLineEdit is abused) and file name. */
+
+class TestWizardPage : public QWizardPage {
+    Q_OBJECT
+public:
+    explicit TestWizardPage(QWidget *parent = 0);
+    ~TestWizardPage();
+    virtual bool isComplete() const;
+
+    TestWizardParameters parameters() const;
+    QString sourcefileName() const;
+
+public slots:
+    void setProjectName(const QString &);
+
+private slots:
+    void slotClassNameEdited(const QString&);
+    void slotFileNameEdited();
+    void slotUpdateValid();
+
+protected:
+    void changeEvent(QEvent *e);
+
+private:
+    const QString m_sourceSuffix;
+    const bool m_lowerCaseFileNames;
+    Ui::TestWizardPage *ui;
+    bool m_fileNameEdited;
+    bool m_valid;
+
+};
+
+} // namespace Internal
+} // namespace Qt4ProjectManager
+#endif // TESTWIZARDPAGE_H
diff --git a/src/plugins/qt4projectmanager/wizards/testwizardpage.ui b/src/plugins/qt4projectmanager/wizards/testwizardpage.ui
new file mode 100644
index 00000000000..cd085f5c057
--- /dev/null
+++ b/src/plugins/qt4projectmanager/wizards/testwizardpage.ui
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Qt4ProjectManager::Internal::TestWizardPage</class>
+ <widget class="QWizardPage" name="Qt4ProjectManager::Internal::TestWizardPage">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>WizardPage</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <layout class="QFormLayout" name="formLayout">
+     <property name="fieldGrowthPolicy">
+      <enum>QFormLayout::ExpandingFieldsGrow</enum>
+     </property>
+     <item row="0" column="0">
+      <widget class="QLabel" name="testClassLabel">
+       <property name="text">
+        <string>Class name:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="1">
+      <widget class="Utils::ClassNameValidatingLineEdit" name="testClassLineEdit"/>
+     </item>
+     <item row="2" column="0">
+      <widget class="QLabel" name="typeLabel">
+       <property name="text">
+        <string>Type:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="2" column="1">
+      <widget class="QComboBox" name="typeComboBox">
+       <item>
+        <property name="text">
+         <string>Test</string>
+        </property>
+       </item>
+       <item>
+        <property name="text">
+         <string>Benchmark</string>
+        </property>
+       </item>
+      </widget>
+     </item>
+     <item row="6" column="0">
+      <widget class="QLabel" name="fileLabel">
+       <property name="text">
+        <string>File:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="6" column="1">
+      <widget class="Utils::FileNameValidatingLineEdit" name="fileLineEdit">
+       <property name="allowDirectories">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+     <item row="5" column="0" colspan="2">
+      <widget class="QCheckBox" name="initCheckBox">
+       <property name="text">
+        <string>Generate initialization and cleanup code</string>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="0">
+      <widget class="QLabel" name="label">
+       <property name="text">
+        <string>Test slot:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="1">
+      <widget class="Utils::ClassNameValidatingLineEdit" name="testSlotLineEdit"/>
+     </item>
+     <item row="4" column="0" colspan="2">
+      <widget class="QCheckBox" name="qApplicationCheckBox">
+       <property name="text">
+        <string>Requires QApplication</string>
+       </property>
+      </widget>
+     </item>
+     <item row="3" column="0" colspan="2">
+      <widget class="QCheckBox" name="dataCheckBox">
+       <property name="text">
+        <string>Use a test data set</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <spacer name="verticalSpacer">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>194</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>Utils::ClassNameValidatingLineEdit</class>
+   <extends>QLineEdit</extends>
+   <header location="global">utils/classnamevalidatinglineedit.h</header>
+  </customwidget>
+  <customwidget>
+   <class>Utils::FileNameValidatingLineEdit</class>
+   <extends>QLineEdit</extends>
+   <header location="global">utils/filenamevalidatinglineedit.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
-- 
GitLab