diff --git a/plugins/autotest/autotest.pro b/plugins/autotest/autotest.pro
index 19df6bcb2eb..566c6131d12 100644
--- a/plugins/autotest/autotest.pro
+++ b/plugins/autotest/autotest.pro
@@ -15,7 +15,13 @@ SOURCES += \
testvisitor.cpp \
testinfo.cpp \
testcodeparser.cpp \
- autotestplugin.cpp
+ autotestplugin.cpp \
+ testrunner.cpp \
+ testconfiguration.cpp \
+ testresult.cpp \
+ testresultspane.cpp \
+ testresultmodel.cpp \
+ testresultdelegate.cpp
HEADERS += \
testtreeview.h \
@@ -26,7 +32,13 @@ HEADERS += \
testcodeparser.h \
autotestplugin.h \
autotest_global.h \
- autotestconstants.h
+ autotestconstants.h \
+ testrunner.h \
+ testconfiguration.h \
+ testresult.h \
+ testresultspane.h \
+ testresultmodel.h \
+ testresultdelegate.h
RESOURCES += \
autotest.qrc
diff --git a/plugins/autotest/autotest.qrc b/plugins/autotest/autotest.qrc
index 53dee42e310..b4b47f100f6 100644
--- a/plugins/autotest/autotest.qrc
+++ b/plugins/autotest/autotest.qrc
@@ -5,5 +5,16 @@
images/expand.png
images/collapse.png
images/sort.png
+ images/leafsort.png
+ images/debug.png
+ images/fail.png
+ images/fatal.png
+ images/pass.png
+ images/skip.png
+ images/warn.png
+ images/xfail.png
+ images/xpass.png
+ images/run.png
+ images/runselected.png
diff --git a/plugins/autotest/autotestplugin.cpp b/plugins/autotest/autotestplugin.cpp
index b0da2c1cac8..7dcb029d905 100644
--- a/plugins/autotest/autotestplugin.cpp
+++ b/plugins/autotest/autotestplugin.cpp
@@ -18,8 +18,10 @@
#include "autotestplugin.h"
#include "autotestconstants.h"
+#include "testrunner.h"
#include "testtreeview.h"
#include "testtreemodel.h"
+#include "testresultspane.h"
#include
#include
@@ -48,6 +50,8 @@ AutotestPlugin::~AutotestPlugin()
// Delete members
TestTreeModel *model = TestTreeModel::instance();
delete model;
+ TestRunner *runner = TestRunner::instance();
+ delete runner;
}
bool AutotestPlugin::initialize(const QStringList &arguments, QString *errorString)
@@ -74,6 +78,7 @@ bool AutotestPlugin::initialize(const QStringList &arguments, QString *errorStri
Core::ActionManager::actionContainer(Core::Constants::M_TOOLS)->addMenu(menu);
addAutoReleasedObject(new TestViewFactory);
+ addAutoReleasedObject(TestResultsPane::instance());
return true;
}
diff --git a/plugins/autotest/images/debug.png b/plugins/autotest/images/debug.png
new file mode 100644
index 00000000000..e18bd157e4a
Binary files /dev/null and b/plugins/autotest/images/debug.png differ
diff --git a/plugins/autotest/images/fail.png b/plugins/autotest/images/fail.png
new file mode 100644
index 00000000000..38c0d1463a9
Binary files /dev/null and b/plugins/autotest/images/fail.png differ
diff --git a/plugins/autotest/images/fatal.png b/plugins/autotest/images/fatal.png
new file mode 100644
index 00000000000..4e0bf77474a
Binary files /dev/null and b/plugins/autotest/images/fatal.png differ
diff --git a/plugins/autotest/images/leafsort.png b/plugins/autotest/images/leafsort.png
new file mode 100644
index 00000000000..f1a2636deb4
Binary files /dev/null and b/plugins/autotest/images/leafsort.png differ
diff --git a/plugins/autotest/images/pass.png b/plugins/autotest/images/pass.png
new file mode 100644
index 00000000000..33dbe44649e
Binary files /dev/null and b/plugins/autotest/images/pass.png differ
diff --git a/plugins/autotest/images/run.png b/plugins/autotest/images/run.png
new file mode 100644
index 00000000000..e302fe33e00
Binary files /dev/null and b/plugins/autotest/images/run.png differ
diff --git a/plugins/autotest/images/runselected.png b/plugins/autotest/images/runselected.png
new file mode 100644
index 00000000000..328974062ef
Binary files /dev/null and b/plugins/autotest/images/runselected.png differ
diff --git a/plugins/autotest/images/skip.png b/plugins/autotest/images/skip.png
new file mode 100644
index 00000000000..9dfea415f16
Binary files /dev/null and b/plugins/autotest/images/skip.png differ
diff --git a/plugins/autotest/images/warn.png b/plugins/autotest/images/warn.png
new file mode 100644
index 00000000000..a813c1dc9a6
Binary files /dev/null and b/plugins/autotest/images/warn.png differ
diff --git a/plugins/autotest/images/xfail.png b/plugins/autotest/images/xfail.png
new file mode 100644
index 00000000000..deeafe7d941
Binary files /dev/null and b/plugins/autotest/images/xfail.png differ
diff --git a/plugins/autotest/images/xpass.png b/plugins/autotest/images/xpass.png
new file mode 100644
index 00000000000..964bb4a181e
Binary files /dev/null and b/plugins/autotest/images/xpass.png differ
diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp
index dbee199976f..f1cd6872d05 100644
--- a/plugins/autotest/testcodeparser.cpp
+++ b/plugins/autotest/testcodeparser.cpp
@@ -50,8 +50,7 @@ void TestCodeParser::updateTestTree()
TestTreeItem *autoTestRootItem = static_cast(autoTestRootIndex.internalPointer());
autoTestRootItem->removeChildren();
m_model->endResetModel();
- ProjectExplorer::SessionManager *session = static_cast(
- ProjectExplorer::SessionManager::instance());
+ ProjectExplorer::SessionManager *session = ProjectExplorer::SessionManager::instance();
if (!session || !session->hasProjects())
return;
@@ -196,10 +195,10 @@ void TestCodeParser::checkDocumentForTestCode(CPlusPlus::Document::Ptr doc)
m_cppDocMap.insert(file, new TestInfo(tc, privSlots.keys(),
doc->revision(),
doc->editorRevision()));
+ delete info;
break;
}
}
- delete info;
delete ttItem;
} else {
m_model->beginInsertRows(autoTestRootIndex, autoTestRootItem->childCount(), autoTestRootItem->childCount());
diff --git a/plugins/autotest/testcodeparser.h b/plugins/autotest/testcodeparser.h
index 0ef4eedc333..1eaed0b063a 100644
--- a/plugins/autotest/testcodeparser.h
+++ b/plugins/autotest/testcodeparser.h
@@ -38,7 +38,7 @@ class TestCodeParser : public QObject
{
Q_OBJECT
public:
- explicit TestCodeParser(/*QObject*/TestTreeModel *parent = 0);
+ explicit TestCodeParser(TestTreeModel *parent = 0);
signals:
diff --git a/plugins/autotest/testconfiguration.cpp b/plugins/autotest/testconfiguration.cpp
new file mode 100644
index 00000000000..22037989233
--- /dev/null
+++ b/plugins/autotest/testconfiguration.cpp
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Creator Enterprise Auto Test Add-on.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#include "testconfiguration.h"
+
+#include
+
+namespace Autotest {
+namespace Internal {
+
+TestConfiguration::TestConfiguration(const QString &testClass, const QStringList &testCases,
+ QObject *parent)
+ : QObject(parent),
+ m_testClass(testClass),
+ m_testCases(testCases),
+ m_project(0)
+{
+}
+
+TestConfiguration::~TestConfiguration()
+{
+ m_testCases.clear();
+}
+
+void TestConfiguration::setTargetFile(const QString &targetFile)
+{
+ m_targetFile = targetFile;
+}
+
+void TestConfiguration::setTargetName(const QString &targetName)
+{
+ m_targetName = targetName;
+}
+
+void TestConfiguration::setProFile(const QString &proFile)
+{
+ m_proFile = proFile;
+}
+
+void TestConfiguration::setWorkingDirectory(const QString &workingDirectory)
+{
+ m_workingDir = workingDirectory;
+}
+
+void TestConfiguration::setEnvironment(const Utils::Environment &env)
+{
+ m_environment = env;
+}
+
+void TestConfiguration::setProject(ProjectExplorer::Project *project)
+{
+ m_project = project;
+}
+
+} // namespace Internal
+} // namespace Autotest
diff --git a/plugins/autotest/testconfiguration.h b/plugins/autotest/testconfiguration.h
new file mode 100644
index 00000000000..fa9545157b4
--- /dev/null
+++ b/plugins/autotest/testconfiguration.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Creator Enterprise Auto Test Add-on.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#ifndef TESTCONFIGURATION_H
+#define TESTCONFIGURATION_H
+
+#include
+
+#include
+#include
+
+namespace ProjectExplorer {
+class Project;
+}
+
+namespace Autotest {
+namespace Internal {
+
+class TestConfiguration : public QObject
+
+{
+ Q_OBJECT
+public:
+ explicit TestConfiguration(const QString &testClass, const QStringList &testCases,
+ QObject *parent = 0);
+ ~TestConfiguration();
+
+ void setTargetFile(const QString &targetFile);
+ void setTargetName(const QString &targetName);
+ void setProFile(const QString &proFile);
+ void setWorkingDirectory(const QString &workingDirectory);
+ void setEnvironment(const Utils::Environment &env);
+ void setProject(ProjectExplorer::Project *project);
+
+ QString testClass() const { return m_testClass; }
+ QStringList testCases() const { return m_testCases; }
+ QString proFile() const { return m_proFile; }
+ QString targetFile() const { return m_targetFile; }
+ QString targetName() const { return m_targetName; }
+ QString workingDirectory() const { return m_workingDir; }
+ Utils::Environment environment() const { return m_environment; }
+ ProjectExplorer::Project *project() const { return m_project; }
+
+
+signals:
+
+public slots:
+
+private:
+ QString m_testClass;
+ QStringList m_testCases;
+ QString m_proFile;
+ QString m_targetFile;
+ QString m_targetName;
+ QString m_workingDir;
+ Utils::Environment m_environment;
+ ProjectExplorer::Project *m_project;
+};
+
+} // namespace Internal
+} // namespace Autotest
+
+#endif // TESTCONFIGURATION_H
diff --git a/plugins/autotest/testinfo.cpp b/plugins/autotest/testinfo.cpp
index 8e5850c84be..ad904e9a0f1 100644
--- a/plugins/autotest/testinfo.cpp
+++ b/plugins/autotest/testinfo.cpp
@@ -30,5 +30,10 @@ TestInfo::TestInfo(const QString &className, const QStringList &functions, unsig
{
}
+TestInfo::~TestInfo()
+{
+ m_functions.clear();
+}
+
} // namespace Internal
} // namespace Autotest
diff --git a/plugins/autotest/testinfo.h b/plugins/autotest/testinfo.h
index 378afcab589..bfb7ef33c5e 100644
--- a/plugins/autotest/testinfo.h
+++ b/plugins/autotest/testinfo.h
@@ -30,6 +30,7 @@ public:
explicit TestInfo(const QString &className, const QStringList &functions = QStringList(),
unsigned revision = 0, unsigned editorRevision = 0);
+ ~TestInfo();
const QString testClass() const { return m_className; }
void setTestClass(const QString &className) { m_className = className; }
const QStringList testFunctions() const { return m_functions; }
diff --git a/plugins/autotest/testresult.cpp b/plugins/autotest/testresult.cpp
new file mode 100644
index 00000000000..c75ba31ac6f
--- /dev/null
+++ b/plugins/autotest/testresult.cpp
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Creator Enterprise Auto Test Add-on.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#include "testresult.h"
+
+namespace Autotest {
+namespace Internal {
+
+TestResult::TestResult(const QString &className, const QString &testCase, const QString &dataTag,
+ ResultType result, const QString &description)
+ : m_class(className),
+ m_case(testCase),
+ m_dataTag(dataTag),
+ m_result(result),
+ m_description(description),
+ m_line(0)
+{
+}
+
+ResultType TestResult::resultFromString(const QString &resultString)
+{
+ if (resultString == QLatin1String("pass"))
+ return PASS;
+ if (resultString == QLatin1String("fail"))
+ return FAIL;
+ if (resultString == QLatin1String("xfail"))
+ return EXPECTED_FAIL;
+ if (resultString == QLatin1String("xpass"))
+ return UNEXPECTED_PASS;
+ if (resultString == QLatin1String("skip"))
+ return SKIP;
+ if (resultString == QLatin1String("qdebug"))
+ return MESSAGE_DEBUG;
+ if (resultString == QLatin1String("warn"))
+ return MESSAGE_WARN;
+ if (resultString == QLatin1String("qfatal"))
+ return MESSAGE_FATAL;
+ qDebug(" unexpected testresult...");
+ qDebug(resultString.toLatin1());
+ return UNKNOWN;
+}
+
+QString TestResult::resultToString(const ResultType type)
+{
+ switch(type) {
+ case PASS: return QLatin1String("PASS");
+ case FAIL: return QLatin1String("FAIL");
+ case EXPECTED_FAIL: return QLatin1String("XFAIL");
+ case UNEXPECTED_PASS: return QLatin1String("XPASS");
+ case SKIP: return QLatin1String("SKIP");
+ case MESSAGE_DEBUG: return QLatin1String("DEBUG");
+ case MESSAGE_WARN: return QLatin1String("WARN");
+ case MESSAGE_FATAL: return QLatin1String("FATAL");
+ case MESSAGE_INTERNAL: return QString();
+ default:
+ return QLatin1String("UNKNOWN");
+ }
+}
+
+QColor TestResult::colorForType(const ResultType type)
+{
+ switch(type) {
+ case PASS: return QColor("#009900");
+ case FAIL: return QColor("#a00000");
+ case EXPECTED_FAIL: return QColor("#00ff00");
+ case UNEXPECTED_PASS: return QColor("#ff0000");
+ case SKIP: return QColor("#787878");
+ case MESSAGE_DEBUG: return QColor("#329696");
+ case MESSAGE_WARN: return QColor("#d0bb00");
+ case MESSAGE_FATAL: return QColor("#640000");
+ case MESSAGE_INTERNAL: return QColor("transparent");
+ default:
+ return QColor("#000000");
+ }
+}
+
+bool operator==(const TestResult &t1, const TestResult &t2)
+{
+ return t1.className() == t2.className()
+ && t1.testCase() == t2.testCase()
+ && t1.dataTag() == t2.dataTag()
+ && t1.result() == t2.result();
+}
+
+} // namespace Internal
+} // namespace Autotest
diff --git a/plugins/autotest/testresult.h b/plugins/autotest/testresult.h
new file mode 100644
index 00000000000..dc476916645
--- /dev/null
+++ b/plugins/autotest/testresult.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Creator Enterprise Auto Test Add-on.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#ifndef TESTRESULT_H
+#define TESTRESULT_H
+
+#include
+#include
+
+namespace Autotest {
+namespace Internal {
+
+enum ResultType {
+ PASS,
+ FAIL,
+ EXPECTED_FAIL,
+ UNEXPECTED_PASS,
+ SKIP,
+ MESSAGE_DEBUG,
+ MESSAGE_WARN,
+ MESSAGE_FATAL,
+ MESSAGE_INTERNAL,
+ UNKNOWN // ???
+};
+
+class TestResult
+{
+public:
+
+ TestResult(const QString &className, const QString &testCase, const QString &dataTag = QString(),
+ ResultType result = UNKNOWN, const QString &description = QString());
+
+ QString className() const { return m_class; }
+ QString testCase() const { return m_case; }
+ QString dataTag() const { return m_dataTag; }
+ ResultType result() const { return m_result; }
+ QString description() const { return m_description; }
+ QString fileName() const { return m_file; }
+ int line() const { return m_line; }
+
+ void setFileName(const QString &fileName) { m_file = fileName; }
+ void setLine(int line) { m_line = line; }
+
+ static ResultType resultFromString(const QString &resultString);
+ static QString resultToString(const ResultType type);
+ static QColor colorForType(const ResultType type);
+
+private:
+ QString m_class;
+ QString m_case;
+ QString m_dataTag;
+ ResultType m_result;
+ QString m_description;
+ QString m_file;
+ int m_line;
+ // environment?
+};
+
+bool operator==(const TestResult &t1, const TestResult &t2);
+
+} // namespace Internal
+} // namespace Autotest
+
+#endif // TESTRESULT_H
diff --git a/plugins/autotest/testresultdelegate.cpp b/plugins/autotest/testresultdelegate.cpp
new file mode 100644
index 00000000000..1f423d2e3a1
--- /dev/null
+++ b/plugins/autotest/testresultdelegate.cpp
@@ -0,0 +1,244 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Creator Enterprise Auto Test Add-on.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#include "testresultdelegate.h"
+#include "testresultmodel.h"
+
+#include
+#include
+#include
+#include
+
+namespace Autotest {
+namespace Internal {
+
+TestResultDelegate::TestResultDelegate(QObject *parent)
+ : QStyledItemDelegate(parent)
+{
+}
+
+TestResultDelegate::~TestResultDelegate()
+{
+
+}
+
+void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ QStyleOptionViewItemV4 opt = option;
+ initStyleOption(&opt, index);
+ painter->save();
+
+ QFontMetrics fm(opt.font);
+ QColor background;
+ QColor foreground;
+
+ const QAbstractItemView *view = qobject_cast(opt.widget);
+ const bool selected = view->selectionModel()->currentIndex() == index;
+
+ if (selected) {
+ painter->setBrush(opt.palette.highlight().color());
+ background = opt.palette.highlight().color();
+ foreground = opt.palette.highlightedText().color();
+ } else {
+ painter->setBrush(opt.palette.background().color());
+ background = opt.palette.background().color();
+ foreground = opt.palette.text().color();
+ }
+
+ painter->setPen(Qt::NoPen);
+ painter->drawRect(opt.rect);
+
+ painter->setPen(foreground);
+ TestResultModel *resultModel = static_cast(view->model());
+ LayoutPositions positions(opt, resultModel);
+ TestResult testResult = resultModel->testResult(index);
+ ResultType type = testResult.result();
+
+ QIcon icon = index.data(Qt::DecorationRole).value();
+ if (!icon.isNull())
+ painter->drawPixmap(positions.left(), positions.top(),
+ icon.pixmap(positions.iconSize(), positions.iconSize()));
+
+ QString typeStr = TestResult::resultToString(testResult.result());
+ if (selected) {
+ painter->drawText(positions.typeAreaLeft(), positions.top() + fm.ascent(), typeStr);
+ } else {
+ QPen tmp = painter->pen();
+ painter->setPen(TestResult::colorForType(testResult.result()));
+ painter->drawText(positions.typeAreaLeft(), positions.top() + fm.ascent(), typeStr);
+ painter->setPen(tmp);
+ }
+
+ QString output;
+ switch (type) {
+ case ResultType::PASS:
+ case ResultType::FAIL:
+ case ResultType::EXPECTED_FAIL:
+ case ResultType::UNEXPECTED_PASS:
+ output = testResult.className() + QLatin1String("::") + testResult.testCase();
+ if (!testResult.dataTag().isEmpty())
+ output.append(QString::fromLatin1(" (%1)").arg(testResult.dataTag()));
+ if (selected && !testResult.description().isEmpty()) {
+ output.append(QLatin1Char('\n'));
+ output.append(testResult.description());
+ }
+ break;
+ default:
+ output = testResult.description();
+ if (!selected)
+ output = output.split(QLatin1Char('\n')).first();
+ }
+
+ QColor mix;
+ mix.setRgb( static_cast(0.7 * foreground.red() + 0.3 * background.red()),
+ static_cast(0.7 * foreground.green() + 0.3 * background.green()),
+ static_cast(0.7 * foreground.blue() + 0.3 * background.blue()));
+
+ if (selected) {
+ int height = 0;
+ int leading = fm.leading();
+ int firstLineBreak = output.indexOf(QLatin1Char('\n'));
+ output.replace(QLatin1Char('\n'), QChar::LineSeparator);
+ QTextLayout tl(output);
+ if (firstLineBreak != -1) {
+ QTextLayout::FormatRange fr;
+ fr.start = firstLineBreak;
+ fr.length = output.length() - firstLineBreak;
+ fr.format.setFontStyleHint(QFont::Monospace);
+ fr.format.setForeground(mix);
+ tl.setAdditionalFormats(QList() << fr);
+ }
+ tl.beginLayout();
+ while (true) {
+ QTextLine tLine = tl.createLine();
+ if (!tLine.isValid())
+ break;
+ tLine.setLineWidth(positions.textAreaWidth());
+ height += leading;
+ tLine.setPosition(QPoint(0, height));
+ height += fm.ascent() + fm.descent();
+ }
+ tl.endLayout();
+ tl.draw(painter, QPoint(positions.textAreaLeft(), positions.top()));
+
+ painter->setPen(mix);
+
+ int bottomLine = positions.top() + fm.ascent() + height + leading;
+ painter->drawText(positions.textAreaLeft(), bottomLine, testResult.fileName());
+ } else {
+ painter->setClipRect(positions.textArea());
+ painter->drawText(positions.textAreaLeft(), positions.top() + fm.ascent(), output);
+ }
+
+ QString file = testResult.fileName();
+ const int pos = file.lastIndexOf(QLatin1Char('/'));
+ if (pos != -1)
+ file = file.mid(pos + 1);
+
+ painter->setClipRect(positions.fileArea());
+ painter->drawText(positions.fileAreaLeft(), positions.top() + fm.ascent(), file);
+
+
+ if (testResult.line()) {
+ QString line = QString::number(testResult.line());
+ painter->setClipRect(positions.lineArea());
+ painter->drawText(positions.lineAreaLeft(), positions.top() + fm.ascent(), line);
+ }
+
+ painter->setClipRect(opt.rect);
+ painter->setPen(QColor::fromRgb(150, 150, 150));
+ painter->drawLine(0, opt.rect.bottom(), opt.rect.right(), opt.rect.bottom());
+ painter->restore();
+}
+
+QSize TestResultDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ QStyleOptionViewItemV4 opt = option;
+ initStyleOption(&opt, index);
+
+ const QAbstractItemView *view = qobject_cast(opt.widget);
+ const bool selected = view->selectionModel()->currentIndex() == index;
+
+ QFontMetrics fm(opt.font);
+ int fontHeight = fm.height();
+ TestResultModel *resultModel = static_cast(view->model());
+ LayoutPositions positions(opt, resultModel);
+ QSize s;
+ s.setWidth(opt.rect.width());
+
+ if (selected) {
+ TestResult testResult = resultModel->testResult(index);
+
+ QString output;
+ switch (testResult.result()) {
+ case ResultType::PASS:
+ case ResultType::FAIL:
+ case ResultType::EXPECTED_FAIL:
+ case ResultType::UNEXPECTED_PASS:
+ output = testResult.className() + QLatin1String("::") + testResult.testCase();
+ if (!testResult.dataTag().isEmpty())
+ output.append(QString::fromLatin1(" (%1)").arg(testResult.dataTag()));
+ if (!testResult.description().isEmpty()) {
+ output.append(QLatin1Char('\n'));
+ output.append(testResult.description());
+ }
+ break;
+ default:
+ output = testResult.description();
+ }
+
+ output.replace(QLatin1Char('\n'), QChar::LineSeparator);
+
+ int height = 0;
+ int leading = fm.leading();
+ QTextLayout tl(output);
+ tl.beginLayout();
+ while (true) {
+ QTextLine line = tl.createLine();
+ if (!line.isValid())
+ break;
+ height += leading;
+ line.setPosition(QPoint(0, height));
+ height += fm.ascent() + fm.descent();
+ }
+ tl.endLayout();
+
+ s.setHeight(height + leading + 3 + (testResult.fileName().isEmpty() ? 0 : fontHeight));
+ } else {
+ s.setHeight(fontHeight + 3);
+ }
+
+ if (s.height() < positions.minimumHeight())
+ s.setHeight(positions.minimumHeight());
+
+ return s;
+}
+
+void TestResultDelegate::emitSizeHintChanged(const QModelIndex &index)
+{
+ emit sizeHintChanged(index);
+}
+
+void TestResultDelegate::currentChanged(const QModelIndex ¤t, const QModelIndex &previous)
+{
+ emit sizeHintChanged(current);
+ emit sizeHintChanged(previous);
+}
+
+} // namespace Internal
+} // namespace Autotest
diff --git a/plugins/autotest/testresultdelegate.h b/plugins/autotest/testresultdelegate.h
new file mode 100644
index 00000000000..2b85ae1076d
--- /dev/null
+++ b/plugins/autotest/testresultdelegate.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Creator Enterprise Auto Test Add-on.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#ifndef TESTRESULTDELEGATE_H
+#define TESTRESULTDELEGATE_H
+
+#include "testresultmodel.h"
+
+#include
+
+namespace Autotest {
+namespace Internal {
+
+class TestResultDelegate : public QStyledItemDelegate
+{
+ Q_OBJECT
+public:
+ explicit TestResultDelegate(QObject *parent = 0);
+ ~TestResultDelegate();
+
+ void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
+ QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
+
+ void emitSizeHintChanged(const QModelIndex &index);
+
+signals:
+
+public slots:
+ void currentChanged(const QModelIndex ¤t, const QModelIndex &previous);
+
+private:
+ class LayoutPositions
+ {
+ public:
+ LayoutPositions(QStyleOptionViewItemV4 &options, TestResultModel *model)
+ : m_totalWidth(options.rect.width()),
+ m_maxFileLength(model->maxWidthOfFileName(options.font)),
+ m_maxLineLength(model->maxWidthOfLineNumber(options.font)),
+ m_realFileLength(m_maxFileLength),
+ m_top(options.rect.top()),
+ m_bottom(options.rect.bottom())
+ {
+ int flexibleArea = lineAreaLeft() - textAreaLeft() - ITEM_SPACING;
+ if (m_maxFileLength > flexibleArea / 2)
+ m_realFileLength = flexibleArea / 2;
+ m_fontHeight = QFontMetrics(options.font).height();
+ m_typeAreaWidth = QFontMetrics(options.font).width(QLatin1String("XXXXXXXX"));
+ }
+
+ int top() const { return m_top + ITEM_MARGIN; }
+ int left() const { return ITEM_MARGIN; }
+ int right() const { return m_totalWidth - ITEM_MARGIN; }
+ int bottom() const { return m_bottom; }
+ int minimumHeight() const { return ICON_SIZE + 2 * ITEM_MARGIN; }
+
+ int iconSize() const { return ICON_SIZE; }
+ int fontHeight() const { return m_fontHeight; }
+ int typeAreaLeft() const { return left() + ICON_SIZE + ITEM_SPACING; }
+ int typeAreaWidth() const { return m_typeAreaWidth; }
+ int textAreaLeft() const { return typeAreaLeft() + m_typeAreaWidth + ITEM_SPACING; }
+ int textAreaWidth() const { return fileAreaLeft() - ITEM_SPACING - textAreaLeft(); }
+ int fileAreaLeft() const { return lineAreaLeft() - ITEM_SPACING - m_realFileLength; }
+ int lineAreaLeft() const { return right() - m_maxLineLength; }
+
+ QRect typeArea() const { return QRect(typeAreaLeft(), top(),
+ typeAreaWidth(), m_fontHeight); }
+ QRect textArea() const { return QRect(textAreaLeft(), top(),
+ fileAreaLeft() - ITEM_SPACING, m_fontHeight); }
+ QRect fileArea() const { return QRect(fileAreaLeft(), top(),
+ lineAreaLeft() - ITEM_SPACING, m_fontHeight); }
+
+ QRect lineArea() const { return QRect(lineAreaLeft(), top(),
+ m_maxLineLength, m_fontHeight); }
+
+ private:
+ int m_totalWidth;
+ int m_maxFileLength;
+ int m_maxLineLength;
+ int m_realFileLength;
+ int m_top;
+ int m_bottom;
+ int m_fontHeight;
+ int m_typeAreaWidth;
+
+ static const int ICON_SIZE = 16;
+ static const int ITEM_MARGIN = 2;
+ static const int ITEM_SPACING = 4;
+
+ };
+};
+
+} // namespace Internal
+} // namespace Autotest
+
+#endif // TESTRESULTDELEGATE_H
diff --git a/plugins/autotest/testresultmodel.cpp b/plugins/autotest/testresultmodel.cpp
new file mode 100644
index 00000000000..1867987aa1f
--- /dev/null
+++ b/plugins/autotest/testresultmodel.cpp
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Creator Enterprise Auto Test Add-on.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#include "testresultmodel.h"
+
+#include
+#include
+#include
+
+namespace Autotest {
+namespace Internal {
+
+TestResultModel::TestResultModel(QObject *parent) :
+ QAbstractItemModel(parent),
+ m_widthOfLineNumber(0),
+ m_maxWidthOfFileName(0),
+ m_lastMaxWidthIndex(0)
+{
+}
+
+TestResultModel::~TestResultModel()
+{
+ m_testResults.clear();
+}
+
+QModelIndex TestResultModel::index(int row, int column, const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return QModelIndex();
+ return createIndex(row, column);
+}
+
+QModelIndex TestResultModel::parent(const QModelIndex &) const
+{
+ return QModelIndex();
+}
+
+int TestResultModel::rowCount(const QModelIndex &parent) const
+{
+ return parent.isValid() ? 0 : m_testResults.size();
+}
+
+int TestResultModel::columnCount(const QModelIndex &parent) const
+{
+ return parent.isValid() ? 0 : 1;
+}
+
+static QIcon testResultIcon(ResultType result) {
+ static QIcon icons[8] = {
+ QIcon(QLatin1String(":/images/pass.png")),
+ QIcon(QLatin1String(":/images/fail.png")),
+ QIcon(QLatin1String(":/images/xfail.png")),
+ QIcon(QLatin1String(":/images/xpass.png")),
+ QIcon(QLatin1String(":/images/skip.png")),
+ QIcon(QLatin1String(":/images/debug.png")),
+ QIcon(QLatin1String(":/images/warn.png")),
+ QIcon(QLatin1String(":/images/fatal.png")),
+ };
+
+ if (result < 0 || result >= MESSAGE_INTERNAL)
+ return QIcon();
+ return icons[result];
+}
+
+QVariant TestResultModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid() || index.row() >= m_testResults.count() || index.column() != 0)
+ return QVariant();
+ if (role == Qt::DisplayRole) {
+ const TestResult &tr = m_testResults.at(index.row());
+ switch (tr.result()) {
+ case ResultType::PASS:
+ case ResultType::FAIL:
+ case ResultType::EXPECTED_FAIL:
+ case ResultType::UNEXPECTED_PASS:
+ case ResultType::SKIP:
+ return QString::fromLatin1("%1::%2 (%3) - %4").arg(tr.className(), tr.testCase(),
+ tr.dataTag(), tr.fileName());
+ default:
+ return tr.description();
+ }
+ }
+ if (role == Qt::DecorationRole) {
+ const TestResult &tr = m_testResults.at(index.row());
+ return testResultIcon(tr.result());
+ }
+
+ return QVariant();
+}
+
+void TestResultModel::addTestResult(const TestResult &testResult)
+{
+ beginInsertRows(QModelIndex(), m_testResults.size(), m_testResults.size());
+ m_testResults.append(testResult);
+ endInsertRows();
+}
+
+void TestResultModel::clearTestResults()
+{
+ if (m_testResults.size() == 0)
+ return;
+ beginRemoveRows(QModelIndex(), 0, m_testResults.size() - 1);
+ m_testResults.clear();
+ endRemoveRows();
+}
+
+TestResult TestResultModel::testResult(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return TestResult(QString(), QString());
+ return m_testResults.at(index.row());
+}
+
+int TestResultModel::maxWidthOfFileName(const QFont &font)
+{
+ int count = m_testResults.size();
+ if (count == 0)
+ return 0;
+ if (m_maxWidthOfFileName > 0 && font == m_measurementFont && m_lastMaxWidthIndex == count - 1)
+ return m_maxWidthOfFileName;
+
+ QFontMetrics fm(font);
+ m_measurementFont = font;
+
+ for (int i = m_lastMaxWidthIndex; i < count; ++i) {
+ QString filename = m_testResults.at(i).fileName();
+ const int pos = filename.lastIndexOf(QLatin1Char('/'));
+ if (pos != -1)
+ filename = filename.mid(pos +1);
+
+ m_maxWidthOfFileName = qMax(m_maxWidthOfFileName, fm.width(filename));
+ }
+ m_lastMaxWidthIndex = count - 1;
+ return m_maxWidthOfFileName;
+}
+
+int TestResultModel::maxWidthOfLineNumber(const QFont &font)
+{
+ if (m_widthOfLineNumber == 0 || font != m_measurementFont) {
+ QFontMetrics fm(font);
+ m_measurementFont = font;
+ m_widthOfLineNumber = fm.width(QLatin1String("88888"));
+ }
+ return m_widthOfLineNumber;
+}
+
+} // namespace Internal
+} // namespace Autotest
diff --git a/plugins/autotest/testresultmodel.h b/plugins/autotest/testresultmodel.h
new file mode 100644
index 00000000000..fa358205546
--- /dev/null
+++ b/plugins/autotest/testresultmodel.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Creator Enterprise Auto Test Add-on.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#ifndef TESTRESULTMODEL_H
+#define TESTRESULTMODEL_H
+
+#include "testresult.h"
+
+#include
+#include
+
+namespace Autotest {
+namespace Internal {
+
+class TestResultModel : public QAbstractItemModel
+{
+ Q_OBJECT
+public:
+ explicit TestResultModel(QObject *parent = 0);
+ ~TestResultModel();
+ QModelIndex index(int row, int column, const QModelIndex &parent) const;
+ QModelIndex parent(const QModelIndex &) const;
+ int rowCount(const QModelIndex &parent) const;
+ int columnCount(const QModelIndex &parent) const;
+ QVariant data(const QModelIndex &index, int role) const;
+
+ void addTestResult(const TestResult &testResult);
+ void clearTestResults();
+
+ bool hasResults() const { return m_testResults.size() > 0; }
+ TestResult testResult(const QModelIndex &index) const;
+
+ int maxWidthOfFileName(const QFont &font);
+ int maxWidthOfLineNumber(const QFont &font);
+
+signals:
+
+public slots:
+
+private:
+ QList m_testResults;
+ int m_widthOfLineNumber;
+ int m_maxWidthOfFileName;
+ int m_lastMaxWidthIndex;
+ QFont m_measurementFont;
+};
+
+} // namespace Internal
+} // namespace Autotest
+
+#endif // TESTRESULTMODEL_H
diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp
new file mode 100644
index 00000000000..100de73e58b
--- /dev/null
+++ b/plugins/autotest/testresultspane.cpp
@@ -0,0 +1,216 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Creator Enterprise Auto Test Add-on.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#include "testresultspane.h"
+#include "testresultmodel.h"
+#include "testresultdelegate.h"
+#include "testrunner.h"
+#include "testtreemodel.h"
+
+#include
+
+#include
+
+#include
+
+#include
+
+namespace Autotest {
+namespace Internal {
+
+TestResultsPane::TestResultsPane(QObject *parent) :
+ Core::IOutputPane(parent),
+ m_context(new Core::IContext(this))
+{
+ m_listView = new Utils::ListView;
+ m_model = new TestResultModel(this);
+ m_listView->setModel(m_model);
+ TestResultDelegate *trd = new TestResultDelegate(this);
+ m_listView->setItemDelegate(trd);
+
+ createToolButtons();
+
+ connect(m_listView, &Utils::ListView::activated, this, &TestResultsPane::onItemActivated);
+ connect(m_listView->selectionModel(), &QItemSelectionModel::currentChanged,
+ trd, &TestResultDelegate::currentChanged);
+}
+
+void TestResultsPane::createToolButtons()
+{
+ m_runAll = new QToolButton(m_listView);
+ m_runAll->setIcon(QIcon(QLatin1String(":/images/run.png")));
+ m_runAll->setToolTip(tr("Run All Tests"));
+ connect(m_runAll, &QToolButton::clicked, this, &TestResultsPane::onRunAllTriggered);
+
+ m_runSelected = new QToolButton(m_listView);
+ m_runSelected->setIcon(QIcon(QLatin1String(":/images/runselected.png")));
+ m_runSelected->setToolTip(tr("Run Selected Tests"));
+ connect(m_runSelected, &QToolButton::clicked, this, &TestResultsPane::onRunSelectedTriggered);
+}
+
+static TestResultsPane *m_instance = 0;
+
+TestResultsPane *TestResultsPane::instance()
+{
+ if (!m_instance)
+ m_instance = new TestResultsPane;
+ return m_instance;
+}
+
+TestResultsPane::~TestResultsPane()
+{
+ delete m_listView;
+ m_instance = 0;
+}
+
+void TestResultsPane::addTestResult(const TestResult &result)
+{
+ m_model->addTestResult(result);
+ if (!m_listView->isVisible())
+ popup(Core::IOutputPane::NoModeSwitch);
+ flash();
+ navigateStateChanged();
+}
+
+QWidget *TestResultsPane::outputWidget(QWidget *parent)
+{
+ if (m_listView) {
+ m_listView->setParent(parent);
+ } else {
+ m_listView = new Utils::ListView(parent);
+ }
+ return m_listView;
+}
+
+QList TestResultsPane::toolBarWidgets() const
+{
+ return QList() << m_runAll << m_runSelected; // add filter as well
+}
+
+QString TestResultsPane::displayName() const
+{
+ return tr("Test Results");
+}
+
+int TestResultsPane::priorityInStatusBar() const
+{
+ return -666;
+}
+
+void TestResultsPane::clearContents()
+{
+ m_model->clearTestResults();
+ navigateStateChanged();
+}
+
+void TestResultsPane::visibilityChanged(bool)
+{
+}
+
+void TestResultsPane::setFocus()
+{
+}
+
+bool TestResultsPane::hasFocus() const
+{
+ return m_listView->hasFocus();
+}
+
+bool TestResultsPane::canFocus() const
+{
+ return true;
+}
+
+bool TestResultsPane::canNavigate() const
+{
+ return true;
+}
+
+bool TestResultsPane::canNext() const
+{
+ return m_model->hasResults();
+}
+
+bool TestResultsPane::canPrevious() const
+{
+ return m_model->hasResults();
+}
+
+void TestResultsPane::goToNext()
+{
+ if (!canNext())
+ return;
+
+ QModelIndex currentIndex = m_listView->currentIndex();
+ if (currentIndex.isValid()) {
+ int row = currentIndex.row() + 1;
+ if (row == m_model->rowCount(QModelIndex()))
+ row = 0;
+ currentIndex = m_model->index(row, 0, QModelIndex());
+ } else {
+ currentIndex = m_model->index(0, 0, QModelIndex());
+ }
+ m_listView->setCurrentIndex(currentIndex);
+ onItemActivated(currentIndex);
+}
+
+void TestResultsPane::goToPrev()
+{
+ if (!canPrevious())
+ return;
+
+ QModelIndex currentIndex = m_listView->currentIndex();
+ if (currentIndex.isValid()) {
+ int row = currentIndex.row() - 1;
+ if (row < 0)
+ row = m_model->rowCount(QModelIndex()) - 1;
+ currentIndex = m_model->index(row, 0, QModelIndex());
+ } else {
+ currentIndex = m_model->index(m_model->rowCount(QModelIndex()) - 1, 0, QModelIndex());
+ }
+ m_listView->setCurrentIndex(currentIndex);
+ onItemActivated(currentIndex);
+}
+
+void TestResultsPane::onItemActivated(const QModelIndex &index)
+{
+ if (!index.isValid())
+ return;
+
+ TestResult tr = m_model->testResult(index);
+ if (!tr.fileName().isEmpty())
+ Core::EditorManager::openEditorAt(tr.fileName(), tr.line(), 0);
+}
+
+void TestResultsPane::onRunAllTriggered()
+{
+ TestRunner *runner = TestRunner::instance();
+ runner->setSelectedTests(TestTreeModel::instance()->getAllTestCases());
+ runner->runTests();
+}
+
+void TestResultsPane::onRunSelectedTriggered()
+{
+ TestRunner *runner = TestRunner::instance();
+ runner->setSelectedTests(TestTreeModel::instance()->getSelectedTests());
+ runner->runTests();
+
+}
+
+} // namespace Internal
+} // namespace Autotest
diff --git a/plugins/autotest/testresultspane.h b/plugins/autotest/testresultspane.h
new file mode 100644
index 00000000000..28aff09103d
--- /dev/null
+++ b/plugins/autotest/testresultspane.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Creator Enterprise Auto Test Add-on.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#ifndef TESTRESULTSPANE_H
+#define TESTRESULTSPANE_H
+
+#include
+
+QT_BEGIN_NAMESPACE
+class QModelIndex;
+class QToolButton;
+QT_END_NAMESPACE
+
+namespace Core {
+class IContext;
+}
+
+namespace Utils {
+class ListView;
+}
+
+namespace Autotest {
+namespace Internal {
+
+class TestResult;
+class TestResultModel;
+
+class TestResultsPane : public Core::IOutputPane
+{
+ Q_OBJECT
+public:
+ virtual ~TestResultsPane();
+ static TestResultsPane *instance();
+
+ void addTestResult(const TestResult &result);
+
+ // IOutputPane interface
+ QWidget *outputWidget(QWidget *parent);
+ QList toolBarWidgets() const;
+ QString displayName() const;
+ int priorityInStatusBar() const;
+ void clearContents();
+ void visibilityChanged(bool);
+ void setFocus();
+ bool hasFocus() const;
+ bool canFocus() const;
+ bool canNavigate() const;
+ bool canNext() const;
+ bool canPrevious() const;
+ void goToNext();
+ void goToPrev();
+
+signals:
+
+public slots:
+
+private slots:
+ void onItemActivated(const QModelIndex &index);
+ void onRunAllTriggered();
+ void onRunSelectedTriggered();
+
+private:
+ explicit TestResultsPane(QObject *parent = 0);
+ void createToolButtons();
+
+ Utils::ListView *m_listView;
+ TestResultModel *m_model;
+ Core::IContext *m_context;
+ QToolButton *m_runAll;
+ QToolButton *m_runSelected;
+};
+
+} // namespace Internal
+} // namespace Autotest
+
+#endif // TESTRESULTSPANE_H
diff --git a/plugins/autotest/testrunner.cpp b/plugins/autotest/testrunner.cpp
new file mode 100644
index 00000000000..5a1f41baefb
--- /dev/null
+++ b/plugins/autotest/testrunner.cpp
@@ -0,0 +1,371 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Creator Enterprise Auto Test Add-on.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#include "testresultspane.h"
+#include "testrunner.h"
+
+#include // REMOVE
+
+#include
+#include
+#include
+#include
+
+#include
+
+namespace Autotest {
+namespace Internal {
+
+static TestRunner* m_instance = 0;
+
+TestRunner *TestRunner::instance()
+{
+ if (!m_instance)
+ m_instance = new TestRunner;
+ return m_instance;
+}
+
+TestRunner::TestRunner(QObject *parent) :
+ QObject(parent),
+ m_building(false)
+{
+ m_runner.setReadChannelMode(QProcess::MergedChannels);
+ m_runner.setReadChannel(QProcess::StandardOutput);
+
+ connect(&m_runner, &QProcess::readyReadStandardOutput,
+ this, &TestRunner::processOutput, Qt::DirectConnection);
+ connect(&m_runner, SIGNAL(finished(int,QProcess::ExitStatus)),
+ this, SLOT(onRunnerFinished(int,QProcess::ExitStatus)), Qt::DirectConnection);
+}
+
+TestRunner::~TestRunner()
+{
+ qDeleteAll(m_selectedTests);
+ m_selectedTests.clear();
+ m_instance = 0;
+}
+
+void TestRunner::setSelectedTests(const QList &selected)
+{
+ qDeleteAll(m_selectedTests);
+ m_selectedTests.clear();
+ m_selectedTests = selected;
+}
+
+void TestRunner::runTests()
+{
+ if (m_selectedTests.empty()) {
+ TestResultsPane::instance()->addTestResult(
+ TestResult(QString(), QString(), QString(), ResultType::MESSAGE_FATAL,
+ tr("*** No tests selected - canceling Test Run ***")));
+ return;
+ }
+
+ ProjectExplorer::Project *project = m_selectedTests.at(0)->project();
+
+ if (!project) {// add a warning or info to output? possible at all?
+ return;
+ }
+
+ ProjectExplorer::ProjectExplorerPlugin *pep = ProjectExplorer::ProjectExplorerPlugin::instance();
+ ProjectExplorer::Internal::ProjectExplorerSettings pes = pep->projectExplorerSettings();
+ if (pes.buildBeforeDeploy) {
+ if (!project->hasActiveBuildSettings()) {
+ qDebug() << "no active build settings...???"; // let it configure?
+ return;
+ }
+ buildProject(project);
+ while (m_building) {
+ qApp->processEvents();
+ }
+
+ if (!m_buildSucceeded) {
+ TestResultsPane::instance()->addTestResult(
+ TestResult(QString(), QString(), QString(), ResultType::MESSAGE_FATAL,
+ tr("*** Build failed - canceling Test Run ***")));
+ return;
+ }
+ }
+
+ // clear old log and output pane
+ m_xmlLog.clear();
+ TestResultsPane::instance()->clearContents();
+
+ foreach (TestConfiguration *tc, m_selectedTests) {
+ QString cmd = tc->targetFile();
+ QString workDir = tc->workingDirectory();
+ QStringList args;
+ Utils::Environment env = tc->environment();
+
+ args << QLatin1String("-xml");
+ if (tc->testCases().count())
+ args << tc->testCases();
+
+ exec(cmd, args, workDir, env);
+ }
+ qDebug("test run finished");
+}
+
+void TestRunner::stopTestRun()
+{
+
+}
+
+/******************** XML line parser helper ********************/
+
+static bool xmlStartsWith(const QString &code, const QString &start, QString &result)
+{
+ if (code.startsWith(start)) {
+ result = code.mid(start.length());
+ result = result.left(result.indexOf(QLatin1Char('"')));
+ result = result.left(result.indexOf(QLatin1String("")));
+ return !result.isEmpty();
+ }
+ return false;
+}
+
+static bool xmlCData(const QString &code, const QString &start, QString &result)
+{
+ if (code.startsWith(start)) {
+ int index = code.indexOf(QLatin1String(""), index) - index);
+ return !result.isEmpty();
+ }
+ return false;
+}
+
+static bool xmlExtractTypeFileLine(const QString &code, const QString &tagStart,
+ ResultType &result, QString &file, int &line)
+{
+ if (code.startsWith(tagStart)) {
+ int start = code.indexOf(QLatin1String(" type=\"")) + 7;
+ result = TestResult::resultFromString(
+ code.mid(start, code.indexOf(QLatin1Char('"'), start) - start));
+ start = code.indexOf(QLatin1String(" file=\"")) + 7;
+ file = code.mid(start, code.indexOf(QLatin1Char('"'), start) - start);
+ start = code.indexOf(QLatin1String(" line=\"")) + 7;
+ line = code.mid(start, code.indexOf(QLatin1Char('"'), start) - start).toInt();
+ return true;
+ }
+ return false;
+}
+
+/****************** XML line parser helper end ******************/
+
+void TestRunner::processOutput()
+{
+ static QString className;
+ static QString testCase;
+ static QString dataTag;
+ static ResultType result = ResultType::UNKNOWN;
+ static QString description;
+ static QString file;
+ static int lineNumber = 0;
+ static QString duration;
+ static bool readingDescription = false;
+ static QString qtVersion;
+ static QString qtestVersion;
+
+ while (m_runner.canReadLine()) {
+ // TODO Qt5 uses UTF-8 - while Qt4 uses ISO-8859-1 - could this be a problem?
+ QString line = QString::fromUtf8(m_runner.readLine());
+ line = line.trimmed();
+ m_xmlLog.append(line);
+ if (line.isEmpty() || line.startsWith(QLatin1String(""), dataTag))
+ continue;
+ if (xmlCData(line, QLatin1String(""), description)) {
+ if (!line.endsWith(QLatin1String("")))
+ readingDescription = true;
+ continue;
+ }
+ if (xmlExtractTypeFileLine(line, QLatin1String(""))) {
+ TestResult testResult(className, testCase, dataTag, result, description);
+ if (!file.isEmpty())
+ file = QFileInfo(m_runner.workingDirectory(), file).canonicalFilePath();
+ testResult.setFileName(file);
+ testResult.setLine(lineNumber);
+ TestResultsPane::instance()->addTestResult(testResult);
+ }
+ continue;
+ }
+ if (line == QLatin1String("") || line == QLatin1String("")) {
+ TestResult testResult(className, testCase, dataTag, result, description);
+ if (!file.isEmpty())
+ file = QFileInfo(m_runner.workingDirectory(), file).canonicalFilePath();
+ testResult.setFileName(file);
+ testResult.setLine(lineNumber);
+ TestResultsPane::instance()->addTestResult(testResult);
+ description = QString();
+ } else if (line == QLatin1String("") && !duration.isEmpty()) {
+ TestResult testResult(className, testCase, QString(), ResultType::MESSAGE_INTERNAL,
+ tr("execution took %1ms").arg(duration));
+ TestResultsPane::instance()->addTestResult(testResult);
+ } else if (line == QLatin1String("") && !duration.isEmpty()) {
+ TestResult testResult(className, QString(), QString(), ResultType::MESSAGE_INTERNAL,
+ tr("Test execution took %1ms").arg(duration));
+ TestResultsPane::instance()->addTestResult(testResult);
+ } else if (readingDescription) {
+ if (line.endsWith(QLatin1String("]]>"))) {
+ description.append(QLatin1Char('\n'));
+ description.append(line.left(line.indexOf(QLatin1String("]]>"))));
+ readingDescription = false;
+ } else {
+ description.append(QLatin1Char('\n'));
+ description.append(line);
+ }
+ } else if (xmlStartsWith(line, QLatin1String(""), qtVersion)) {
+ TestResultsPane::instance()->addTestResult(
+ TestResult(QString(), QString(), QString(), ResultType::MESSAGE_INTERNAL,
+ tr("Qt Version: %1").arg(qtVersion)));
+ } else if (xmlStartsWith(line, QLatin1String(""), qtestVersion)) {
+ TestResultsPane::instance()->addTestResult(
+ TestResult(QString(), QString(), QString(), ResultType::MESSAGE_INTERNAL,
+ tr("QTest Version: %1").arg(qtestVersion)));
+ } else {
+// qDebug() << "Unhandled line:" << line; // TODO remove
+ }
+ }
+}
+
+void TestRunner::onRunnerFinished(int exitCode, QProcess::ExitStatus exitStatus)
+{
+ qDebug("runnerFinished");
+}
+
+void TestRunner::buildProject(ProjectExplorer::Project *project)
+{
+ m_building = true;
+ m_buildSucceeded = false;
+ ProjectExplorer::BuildManager *mgr = static_cast(
+ ProjectExplorer::BuildManager::instance());
+ ProjectExplorer::ProjectExplorerPlugin *pep = ProjectExplorer::ProjectExplorerPlugin::instance();
+ pep->buildProject(project);
+ connect(mgr, &ProjectExplorer::BuildManager::buildQueueFinished,
+ this, &TestRunner::buildFinished);
+}
+
+void TestRunner::buildFinished(bool success)
+{
+ ProjectExplorer::BuildManager *mgr = static_cast(
+ ProjectExplorer::BuildManager::instance());
+ disconnect(mgr, &ProjectExplorer::BuildManager::buildQueueFinished,
+ this, &TestRunner::buildFinished);
+ m_building = false;
+ m_buildSucceeded = success;
+}
+
+static QString which(const QString &path, const QString &cmd)
+{
+ if (path.isEmpty() || cmd.isEmpty())
+ return QString();
+
+ QStringList paths;
+#ifdef Q_OS_WIN
+ paths = path.split(QLatin1Char(';'));
+#else
+ paths = path.split(QLatin1Char(':'));
+#endif
+
+ foreach (const QString p, paths) {
+ QString fName = p + QDir::separator() + cmd;
+ QFileInfo fi(fName);
+ if (fi.exists() && fi.isExecutable())
+ return fName;
+#ifdef Q_OS_WIN
+ fi = QFileInfo(fName + QLatin1String(".exe"));
+ if (fi.exists())
+ return fi.absoluteFilePath();
+ fi = QFileInfo(fName + QLatin1String(".bat"));
+ if (fi.exists())
+ return fi.absoluteFilePath();
+ fi = QFileInfo(fName + QLatin1String(".cmd"));
+ if (fi.exists())
+ return fi.absoluteFilePath();
+#endif
+ }
+ return QString();
+}
+
+bool TestRunner::exec(const QString &cmd, const QStringList &args, const QString &workingDir,
+ const Utils::Environment &env, int timeout)
+{
+ if (m_runner.state() != QProcess::NotRunning) { // kill the runner if it's running already
+ m_runner.kill();
+ m_runner.waitForFinished();
+ }
+ QString runCmd;
+ if (!QDir::toNativeSeparators(cmd).contains(QDir::separator())) {
+ if (env.hasKey(QLatin1String("PATH")))
+ runCmd = which(env.value(QLatin1String("PATH")), cmd);
+ } else if (QFileInfo(cmd).exists()) {
+ runCmd = cmd;
+ }
+
+ if (runCmd.isEmpty()) {
+ qDebug("Could not find cmd...");
+ return false;
+ }
+
+ m_runner.setWorkingDirectory(workingDir);
+ m_runner.setProcessEnvironment(env.toProcessEnvironment());
+ QTime executionTimer;
+
+ if (args.count()) {
+ m_runner.start(runCmd, args);
+ } else {
+ m_runner.start(runCmd);
+ }
+
+ bool ok = m_runner.waitForStarted();
+ executionTimer.start();
+ if (ok) {
+ while (m_runner.state() == QProcess::Running && executionTimer.elapsed() < timeout) {
+ qApp->processEvents();
+ }
+ }
+ if (ok && executionTimer.elapsed() < timeout) {
+ return m_runner.exitCode() == 0;
+ } else {
+ return false;
+ }
+}
+
+} // namespace Internal
+} // namespace Autotest
diff --git a/plugins/autotest/testrunner.h b/plugins/autotest/testrunner.h
new file mode 100644
index 00000000000..48f674716d2
--- /dev/null
+++ b/plugins/autotest/testrunner.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use contact form at http://qt.digia.com
+**
+** This file is part of the Qt Creator Enterprise Auto Test Add-on.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** contact form at http://qt.digia.com
+**
+****************************************************************************/
+
+#ifndef TESTRUNNER_H
+#define TESTRUNNER_H
+
+#include "testconfiguration.h"
+#include "testresult.h"
+
+#include
+#include
+
+namespace ProjectExplorer {
+class Project;
+}
+
+namespace Autotest {
+namespace Internal {
+
+class TestRunner : public QObject
+{
+ Q_OBJECT
+
+public:
+ static TestRunner* instance();
+ ~TestRunner();
+
+ void setSelectedTests(const QList &selected);
+
+signals:
+
+public slots:
+ void runTests();
+ void stopTestRun();
+
+private slots:
+ void processOutput();
+ void onRunnerFinished(int exitCode, QProcess::ExitStatus exitStatus);
+ void buildProject(ProjectExplorer::Project *project);
+ void buildFinished(bool success);
+
+private:
+ explicit TestRunner(QObject *parent = 0);
+ bool exec(const QString &cmd, const QStringList &args, const QString &workingDir = QString(),
+ const Utils::Environment &env = Utils::Environment(), int timeout = 60000);
+
+ QProcess m_runner;
+ QList m_selectedTests;
+ bool m_building;
+ bool m_buildSucceeded;
+
+ QStringList m_xmlLog; // holds complete xml log of the last test run
+
+};
+
+} // namespace Internal
+} // namespace Autotest
+
+#endif // TESTRUNNER_H
diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp
index 88bc653d4ec..7cf8d2888d8 100644
--- a/plugins/autotest/testtreemodel.cpp
+++ b/plugins/autotest/testtreemodel.cpp
@@ -24,6 +24,16 @@
#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
namespace Autotest {
namespace Internal {
@@ -115,6 +125,16 @@ int TestTreeModel::columnCount(const QModelIndex &) const
return 1;
}
+static QIcon testTreeIcon(TestTreeItem::Type type)
+{
+ static QIcon icons[3] = {
+ QIcon(),
+ QIcon(QLatin1String(":/images/class.png")),
+ QIcon(QLatin1String(":/images/func.png"))
+ };
+ return icons[type];
+}
+
QVariant TestTreeModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
@@ -138,15 +158,7 @@ QVariant TestTreeModel::data(const QModelIndex &index, int role) const
case Qt::ToolTipRole:
return item->filePath();
case Qt::DecorationRole:
- switch(item->type()) {
- case TestTreeItem::TEST_CLASS:
- return QIcon(QLatin1String(":/images/class.png"));
- case TestTreeItem::TEST_FUNCTION:
- return QIcon(QLatin1String(":/images/func.png"));
- case TestTreeItem::ROOT:
- default:
- return QVariant();
- }
+ return testTreeIcon(item->type());
case Qt::CheckStateRole:
if (item->type() == TestTreeItem::ROOT)
return QVariant();
@@ -234,6 +246,110 @@ bool TestTreeModel::hasTests() const
return m_autoTestRootItem->childCount() > 0 /*|| m_quickTestRootItem->childCount() > 0*/;
}
+static void addProjectInformation(TestConfiguration *config, const QString &filePath)
+{
+ QString targetFile;
+ QString targetName;
+ QString workDir;
+ QString proFile;
+ Utils::Environment env;
+ ProjectExplorer::Project *project = 0;
+ CppTools::CppModelManager *cppMM = CppTools::CppModelManager::instance();
+ QList projParts = cppMM->projectPart(filePath);
+ if (!projParts.empty()) {
+ proFile = projParts.at(0)->projectFile;
+ project = projParts.at(0)->project; // necessary to grab this here? or should this be the current active startup project anyway?
+ }
+ if (project) {
+ ProjectExplorer::Target *target = project->activeTarget();
+ ProjectExplorer::BuildTargetInfoList appTargets = target->applicationTargets();
+ foreach (ProjectExplorer::BuildTargetInfo bti, appTargets.list) {
+ if (bti.isValid() && bti.projectFilePath.toString() == proFile) {
+ targetFile = bti.targetFilePath.toString();
+ targetName = bti.targetName;
+ break;
+ }
+ }
+
+ QList rcs = target->runConfigurations();
+ foreach (ProjectExplorer::RunConfiguration *rc, rcs) {
+ if (ProjectExplorer::LocalApplicationRunConfiguration *localRunConfiguration
+ = qobject_cast(rc)) {
+ if (localRunConfiguration->executable() == targetFile) {
+ workDir = localRunConfiguration->workingDirectory();
+ QList aspects
+ = localRunConfiguration->extraAspects();
+ foreach (ProjectExplorer::IRunConfigurationAspect *aspect, aspects) {
+ if (ProjectExplorer::EnvironmentAspect *asp
+ = qobject_cast(aspect)) {
+ env = asp->environment();
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ config->setTargetFile(targetFile);
+ config->setTargetName(targetName);
+ config->setWorkingDirectory(workDir);
+ config->setProFile(proFile);
+ config->setEnvironment(env);
+ config->setProject(project);
+}
+
+QList TestTreeModel::getAllTestCases() const
+{
+ QList result;
+
+ int count = m_autoTestRootItem->childCount();
+ for (int row = 0; row < count; ++row) {
+ TestTreeItem *child = m_autoTestRootItem->child(row);
+
+ TestConfiguration *tc = new TestConfiguration(child->name(), QStringList());
+ addProjectInformation(tc, child->filePath());
+ result << tc;
+ }
+ return result;
+}
+
+QList TestTreeModel::getSelectedTests() const
+{
+ QList result;
+ TestConfiguration *tc;
+
+ int count = m_autoTestRootItem->childCount();
+ for (int row = 0; row < count; ++row) {
+ TestTreeItem *child = m_autoTestRootItem->child(row);
+
+ switch (child->checked()) {
+ case Qt::Unchecked:
+ continue;
+ case Qt::Checked:
+ tc = new TestConfiguration(child->name(), QStringList());
+ addProjectInformation(tc, child->filePath());
+ result << tc;
+ continue;
+ case Qt::PartiallyChecked:
+ default:
+ QString childName = child->name();
+ int grandChildCount = child->childCount();
+ QStringList testCases;
+ for (int grandChildRow = 0; grandChildRow < grandChildCount; ++grandChildRow) {
+ const TestTreeItem *grandChild = child->child(grandChildRow);
+ if (grandChild->checked() == Qt::Checked)
+ testCases << grandChild->name();
+ }
+
+ tc = new TestConfiguration(childName, testCases);
+ addProjectInformation(tc, child->filePath());
+ result << tc;
+ }
+ }
+ return result;
+}
+
void TestTreeModel::modifyAutoTestSubtree(int row, TestTreeItem *newItem)
{
static QVector modificationRoles = QVector() << Qt::DisplayRole
diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h
index 9ec25f04762..040e1c912c0 100644
--- a/plugins/autotest/testtreemodel.h
+++ b/plugins/autotest/testtreemodel.h
@@ -19,6 +19,8 @@
#ifndef TESTTREEMODEL_H
#define TESTTREEMODEL_H
+#include "testconfiguration.h"
+
#include
#include
@@ -56,6 +58,8 @@ public:
TestCodeParser *parser() const { return m_parser; }
bool hasTests() const;
+ QList getAllTestCases() const;
+ QList getSelectedTests() const;
signals:
diff --git a/plugins/autotest/testtreeview.cpp b/plugins/autotest/testtreeview.cpp
index 04b2ffb60fb..fc2fffe1c1d 100644
--- a/plugins/autotest/testtreeview.cpp
+++ b/plugins/autotest/testtreeview.cpp
@@ -18,12 +18,15 @@
#include "autotestconstants.h"
#include "testcodeparser.h"
+#include "testrunner.h"
#include "testtreeitem.h"
#include "testtreemodel.h"
#include "testtreeview.h"
#include
+#include
+
#include
#include
@@ -48,12 +51,11 @@ TestTreeViewWidget::TestTreeViewWidget(QWidget *parent) :
QVBoxLayout *layout = new QVBoxLayout;
layout->setMargin(0);
layout->setSpacing(0);
- layout->addWidget(m_view);
+ layout->addWidget(Core::ItemViewFind::createSearchableWrapper(m_view));
setLayout(layout);
TestCodeParser *parser = m_model->parser();
- ProjectExplorer::SessionManager *sm = static_cast(
- ProjectExplorer::SessionManager::instance());
+ ProjectExplorer::SessionManager *sm = ProjectExplorer::SessionManager::instance();
connect(sm, &ProjectExplorer::SessionManager::startupProjectChanged,
parser, &TestCodeParser::updateTestTree);
@@ -78,6 +80,8 @@ void TestTreeViewWidget::contextMenuEvent(QContextMenuEvent *event)
// TODO remove?
QAction *rescan = new QAction(tr("Rescan"), &menu);
+ connect(runAll, &QAction::triggered, this, &TestTreeViewWidget::onRunAllTriggered);
+ connect(runSelected, &QAction::triggered, this, &TestTreeViewWidget::onRunSelectedTriggered);
connect(selectAll, &QAction::triggered, m_view, &TestTreeView::selectAll);
connect(deselectAll, &QAction::triggered, m_view, &TestTreeView::deselectAll);
connect(rescan, &QAction::triggered,
@@ -103,11 +107,10 @@ QList TestTreeViewWidget::createToolButtons()
{
QList list;
+ m_sortAlphabetically = true;
m_sort = new QToolButton(this);
- m_sort->setIcon((QIcon(QLatin1String(":/images/sort.png"))));
- m_sort->setToolTip(tr("Sort Alphabetically (not implemented yet)")); // TODO
- m_sort->setCheckable(true);
- m_sort->setChecked(true);
+ m_sort->setIcon((QIcon(QLatin1String(":/images/leafsort.png"))));
+ m_sort->setToolTip(tr("Sort Naturally (not implemented yet)"));
QToolButton *expand = new QToolButton(this);
expand->setIcon(QIcon(QLatin1String(":/images/expand.png")));
@@ -119,7 +122,7 @@ QList TestTreeViewWidget::createToolButtons()
connect(expand, &QToolButton::clicked, m_view, &TestTreeView::expandAll);
connect(collapse, &QToolButton::clicked, m_view, &TestTreeView::collapseAll);
-// connect(m_sort, &QToolButton::toggled, m_view, &TestTreeView::onSortToggled); // TODO
+ connect(m_sort, &QToolButton::clicked, this, &TestTreeViewWidget::onSortClicked);
list << m_sort << expand << collapse;
return list;
@@ -136,6 +139,33 @@ void TestTreeViewWidget::onItemActivated(const QModelIndex &index)
}
}
+void TestTreeViewWidget::onRunAllTriggered()
+{
+ TestRunner *runner = TestRunner::instance();
+ runner->setSelectedTests(m_model->getAllTestCases());
+ runner->runTests();
+}
+
+void TestTreeViewWidget::onRunSelectedTriggered()
+{
+ TestRunner *runner = TestRunner::instance();
+ runner->setSelectedTests(m_model->getSelectedTests());
+ runner->runTests();
+}
+
+void TestTreeViewWidget::onSortClicked()
+{
+ if (m_sortAlphabetically) {
+ m_sort->setIcon((QIcon(QLatin1String(":/images/sort.png"))));
+ m_sort->setToolTip(tr("Sort Alphabetically"));
+ } else {
+ m_sort->setIcon((QIcon(QLatin1String(":/images/leafsort.png"))));
+ m_sort->setToolTip(tr("Sort Naturally (not implemented yet)"));
+ }
+ // TODO trigger the sorting change..
+ m_sortAlphabetically = !m_sortAlphabetically;
+}
+
TestViewFactory::TestViewFactory()
{
setDisplayName(tr("Tests"));
@@ -145,10 +175,10 @@ TestViewFactory::TestViewFactory()
Core::NavigationView TestViewFactory::createWidget()
{
- TestTreeViewWidget *treeView = new TestTreeViewWidget;
+ TestTreeViewWidget *treeViewWidget = new TestTreeViewWidget;
Core::NavigationView view;
- view.widget = treeView;
- view.dockToolBarWidgets = treeView->createToolButtons();
+ view.widget = treeViewWidget;
+ view.dockToolBarWidgets = treeViewWidget->createToolButtons();
return view;
}
diff --git a/plugins/autotest/testtreeview.h b/plugins/autotest/testtreeview.h
index cb66fa12ccb..27e475f17c5 100644
--- a/plugins/autotest/testtreeview.h
+++ b/plugins/autotest/testtreeview.h
@@ -68,11 +68,15 @@ public slots:
private slots:
void onItemActivated(const QModelIndex &index);
+ void onRunAllTriggered();
+ void onRunSelectedTriggered();
+ void onSortClicked();
private:
TestTreeModel *m_model;
TestTreeView *m_view;
QToolButton *m_sort;
+ bool m_sortAlphabetically;
};