2014-10-07 15:51:02 +02:00
|
|
|
/****************************************************************************
|
|
|
|
|
**
|
2015-02-19 08:09:02 +01:00
|
|
|
** Copyright (C) 2015 The Qt Company Ltd
|
2014-10-07 15:51:02 +02:00
|
|
|
** All rights reserved.
|
2015-02-19 08:09:02 +01:00
|
|
|
** For any questions to The Qt Company, please use contact form at
|
|
|
|
|
** http://www.qt.io/contact-us
|
2014-10-07 15:51:02 +02:00
|
|
|
**
|
|
|
|
|
** 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
|
2015-02-19 08:09:02 +01:00
|
|
|
** a written agreement between you and The Qt Company.
|
2014-10-07 15:51:02 +02:00
|
|
|
**
|
|
|
|
|
** If you have questions regarding the use of this file, please use
|
2015-02-19 08:09:02 +01:00
|
|
|
** contact form at http://www.qt.io/contact-us
|
2014-10-07 15:51:02 +02:00
|
|
|
**
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "testresultmodel.h"
|
|
|
|
|
|
|
|
|
|
#include <QFontMetrics>
|
|
|
|
|
#include <QIcon>
|
|
|
|
|
|
|
|
|
|
namespace Autotest {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
|
2015-08-20 15:59:15 +02:00
|
|
|
/********************************* TestResultItem ******************************************/
|
2014-10-07 15:51:02 +02:00
|
|
|
|
2015-08-20 15:59:15 +02:00
|
|
|
TestResultItem::TestResultItem(TestResult *testResult)
|
|
|
|
|
: m_testResult(testResult)
|
2014-10-07 15:51:02 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-20 15:59:15 +02:00
|
|
|
TestResultItem::~TestResultItem()
|
2014-10-07 15:51:02 +02:00
|
|
|
{
|
2015-08-20 15:59:15 +02:00
|
|
|
delete m_testResult;
|
2014-10-07 15:51:02 +02:00
|
|
|
}
|
|
|
|
|
|
2015-01-08 13:46:28 +01:00
|
|
|
static QIcon testResultIcon(Result::Type result) {
|
2014-12-01 16:12:05 +01:00
|
|
|
static QIcon icons[11] = {
|
2014-10-07 15:51:02 +02:00
|
|
|
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")),
|
2014-12-01 11:42:28 +01:00
|
|
|
QIcon(QLatin1String(":/images/blacklisted_pass.png")),
|
|
|
|
|
QIcon(QLatin1String(":/images/blacklisted_fail.png")),
|
2014-12-01 16:12:05 +01:00
|
|
|
QIcon(QLatin1String(":/images/benchmark.png")),
|
2014-10-07 15:51:02 +02:00
|
|
|
QIcon(QLatin1String(":/images/debug.png")),
|
|
|
|
|
QIcon(QLatin1String(":/images/warn.png")),
|
|
|
|
|
QIcon(QLatin1String(":/images/fatal.png")),
|
2014-10-21 13:10:37 +02:00
|
|
|
}; // provide an icon for unknown??
|
2014-10-07 15:51:02 +02:00
|
|
|
|
2015-08-20 15:59:15 +02:00
|
|
|
if (result < 0 || result >= Result::MESSAGE_INTERNAL) {
|
|
|
|
|
switch (result) {
|
|
|
|
|
case Result::MESSAGE_TEST_CASE_SUCCESS:
|
|
|
|
|
return icons[Result::PASS];
|
|
|
|
|
case Result::MESSAGE_TEST_CASE_FAIL:
|
|
|
|
|
return icons[Result::FAIL];
|
|
|
|
|
case Result::MESSAGE_TEST_CASE_WARN:
|
|
|
|
|
return icons[Result::MESSAGE_WARN];
|
|
|
|
|
default:
|
|
|
|
|
return QIcon();
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-10-07 15:51:02 +02:00
|
|
|
return icons[result];
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-20 15:59:15 +02:00
|
|
|
QVariant TestResultItem::data(int column, int role) const
|
2014-10-07 15:51:02 +02:00
|
|
|
{
|
2015-08-20 15:59:15 +02:00
|
|
|
if (role == Qt::DecorationRole)
|
|
|
|
|
return m_testResult ? testResultIcon(m_testResult->result()) : QVariant();
|
|
|
|
|
|
|
|
|
|
return Utils::TreeItem::data(column, role);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TestResultItem::updateDescription(const QString &description)
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(m_testResult, return);
|
|
|
|
|
|
|
|
|
|
m_testResult->setDescription(description);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TestResultItem::updateResult()
|
|
|
|
|
{
|
|
|
|
|
if (m_testResult->result() != Result::MESSAGE_TEST_CASE_START)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
Result::Type newResult = Result::MESSAGE_TEST_CASE_SUCCESS;
|
|
|
|
|
foreach (Utils::TreeItem *child, children()) {
|
|
|
|
|
const TestResult *current = static_cast<TestResultItem *>(child)->testResult();
|
|
|
|
|
if (current) {
|
|
|
|
|
switch (current->result()) {
|
|
|
|
|
case Result::FAIL:
|
|
|
|
|
case Result::MESSAGE_FATAL:
|
|
|
|
|
case Result::UNEXPECTED_PASS:
|
|
|
|
|
m_testResult->setResult(Result::MESSAGE_TEST_CASE_FAIL);
|
|
|
|
|
return;
|
|
|
|
|
case Result::EXPECTED_FAIL:
|
|
|
|
|
case Result::MESSAGE_WARN:
|
|
|
|
|
case Result::SKIP:
|
|
|
|
|
case Result::BLACKLISTED_FAIL:
|
|
|
|
|
case Result::BLACKLISTED_PASS:
|
|
|
|
|
newResult = Result::MESSAGE_TEST_CASE_WARN;
|
|
|
|
|
break;
|
|
|
|
|
default: {}
|
|
|
|
|
}
|
2014-10-07 15:51:02 +02:00
|
|
|
}
|
|
|
|
|
}
|
2015-08-20 15:59:15 +02:00
|
|
|
m_testResult->setResult(newResult);
|
|
|
|
|
}
|
2014-10-07 15:51:02 +02:00
|
|
|
|
2015-08-20 15:59:15 +02:00
|
|
|
/********************************* TestResultModel *****************************************/
|
|
|
|
|
|
|
|
|
|
TestResultModel::TestResultModel(QObject *parent)
|
|
|
|
|
: Utils::TreeModel(parent),
|
|
|
|
|
m_widthOfLineNumber(0),
|
|
|
|
|
m_maxWidthOfFileName(0)
|
|
|
|
|
{
|
2014-10-07 15:51:02 +02:00
|
|
|
}
|
|
|
|
|
|
2015-08-20 15:59:15 +02:00
|
|
|
QVariant TestResultModel::data(const QModelIndex &idx, int role) const
|
2014-10-07 15:51:02 +02:00
|
|
|
{
|
2015-08-20 15:59:15 +02:00
|
|
|
if (!idx.isValid())
|
|
|
|
|
return QVariant();
|
|
|
|
|
|
|
|
|
|
if (role == Qt::DecorationRole)
|
|
|
|
|
return itemForIndex(idx)->data(0, Qt::DecorationRole);
|
|
|
|
|
|
|
|
|
|
return QVariant();
|
|
|
|
|
}
|
2014-12-05 14:01:16 +01:00
|
|
|
|
2015-08-20 15:59:15 +02:00
|
|
|
void TestResultModel::addTestResult(TestResult *testResult, bool autoExpand)
|
|
|
|
|
{
|
|
|
|
|
const bool isCurrentTestMssg = testResult->result() == Result::MESSAGE_CURRENT_TEST;
|
2014-12-05 14:01:16 +01:00
|
|
|
|
2015-08-20 15:59:15 +02:00
|
|
|
QVector<Utils::TreeItem *> topLevelItems = rootItem()->children();
|
|
|
|
|
int lastRow = topLevelItems.size() - 1;
|
|
|
|
|
TestResultItem *newItem = new TestResultItem(testResult);
|
|
|
|
|
// we'll add the new item, so raising it's counter
|
|
|
|
|
if (!isCurrentTestMssg) {
|
|
|
|
|
int count = m_testResultCount.value(testResult->result(), 0);
|
|
|
|
|
m_testResultCount.insert(testResult->result(), ++count);
|
2014-12-05 14:01:16 +01:00
|
|
|
} else {
|
2015-08-20 15:59:15 +02:00
|
|
|
// MESSAGE_CURRENT_TEST should always be the last top level item
|
|
|
|
|
if (lastRow >= 0) {
|
|
|
|
|
TestResultItem *current = static_cast<TestResultItem *>(topLevelItems.at(lastRow));
|
|
|
|
|
const TestResult *result = current->testResult();
|
|
|
|
|
if (result && result->result() == Result::MESSAGE_CURRENT_TEST) {
|
|
|
|
|
current->updateDescription(testResult->description());
|
|
|
|
|
emit dataChanged(current->index(), current->index());
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rootItem()->appendChild(newItem);
|
|
|
|
|
return;
|
2014-12-05 14:01:16 +01:00
|
|
|
}
|
|
|
|
|
|
2015-08-20 15:59:15 +02:00
|
|
|
// FIXME this might be totally wrong... we need some more unique information!
|
|
|
|
|
for (int row = lastRow; row >= 0; --row) {
|
|
|
|
|
TestResultItem *current = static_cast<TestResultItem *>(topLevelItems.at(row));
|
|
|
|
|
const TestResult *result = current->testResult();
|
|
|
|
|
if (result && result->className() == testResult->className()) {
|
|
|
|
|
current->appendChild(newItem);
|
|
|
|
|
if (autoExpand)
|
|
|
|
|
current->expand();
|
|
|
|
|
if (testResult->result() == Result::MESSAGE_TEST_CASE_END) {
|
|
|
|
|
current->updateResult();
|
|
|
|
|
emit dataChanged(current->index(), current->index());
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
2014-12-05 14:01:16 +01:00
|
|
|
}
|
2015-08-20 15:59:15 +02:00
|
|
|
// if we have a MESSAGE_CURRENT_TEST present, add the new top level item before it
|
|
|
|
|
if (lastRow >= 0) {
|
|
|
|
|
TestResultItem *current = static_cast<TestResultItem *>(topLevelItems.at(lastRow));
|
|
|
|
|
const TestResult *result = current->testResult();
|
|
|
|
|
if (result && result->result() == Result::MESSAGE_CURRENT_TEST) {
|
|
|
|
|
rootItem()->insertChild(current->index().row(), newItem);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rootItem()->appendChild(newItem);
|
2014-10-07 15:51:02 +02:00
|
|
|
}
|
|
|
|
|
|
2014-12-05 14:01:16 +01:00
|
|
|
void TestResultModel::removeCurrentTestMessage()
|
|
|
|
|
{
|
2015-08-20 15:59:15 +02:00
|
|
|
QVector<Utils::TreeItem *> topLevelItems = rootItem()->children();
|
|
|
|
|
for (int row = topLevelItems.size() - 1; row >= 0; --row) {
|
|
|
|
|
TestResultItem *current = static_cast<TestResultItem *>(topLevelItems.at(row));
|
|
|
|
|
if (current->testResult()->result() == Result::MESSAGE_CURRENT_TEST) {
|
|
|
|
|
delete takeItem(current);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2014-12-05 14:01:16 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-07 15:51:02 +02:00
|
|
|
void TestResultModel::clearTestResults()
|
|
|
|
|
{
|
2015-08-20 15:59:15 +02:00
|
|
|
clear();
|
2014-11-05 15:27:49 +01:00
|
|
|
m_testResultCount.clear();
|
2015-08-20 15:59:15 +02:00
|
|
|
m_processedIndices.clear();
|
2014-10-21 13:10:37 +02:00
|
|
|
m_maxWidthOfFileName = 0;
|
|
|
|
|
m_widthOfLineNumber = 0;
|
2014-10-07 15:51:02 +02:00
|
|
|
}
|
|
|
|
|
|
2015-08-20 15:59:15 +02:00
|
|
|
TestResult TestResultModel::testResult(const QModelIndex &idx)
|
2014-10-07 15:51:02 +02:00
|
|
|
{
|
2015-08-20 15:59:15 +02:00
|
|
|
if (idx.isValid())
|
|
|
|
|
return *(static_cast<TestResultItem *>(itemForIndex(idx))->testResult());
|
|
|
|
|
|
|
|
|
|
return TestResult();
|
2014-10-07 15:51:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int TestResultModel::maxWidthOfFileName(const QFont &font)
|
|
|
|
|
{
|
2015-08-20 15:59:15 +02:00
|
|
|
if (font != m_measurementFont) {
|
|
|
|
|
m_processedIndices.clear();
|
|
|
|
|
m_maxWidthOfFileName = 0;
|
|
|
|
|
m_measurementFont = font;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const QFontMetrics fm(font);
|
|
|
|
|
const QVector<Utils::TreeItem *> &topLevelItems = rootItem()->children();
|
|
|
|
|
const int count = topLevelItems.size();
|
|
|
|
|
for (int row = 0; row < count; ++row) {
|
|
|
|
|
int processed = row < m_processedIndices.size() ? m_processedIndices.at(row) : 0;
|
|
|
|
|
const QVector<Utils::TreeItem *> &children = topLevelItems.at(row)->children();
|
|
|
|
|
const int itemCount = children.size();
|
|
|
|
|
if (processed < itemCount) {
|
|
|
|
|
for (int childRow = processed; childRow < itemCount; ++childRow) {
|
|
|
|
|
const TestResultItem *item = static_cast<TestResultItem *>(children.at(childRow));
|
|
|
|
|
if (const TestResult *result = item->testResult()) {
|
|
|
|
|
QString fileName = result->fileName();
|
|
|
|
|
const int pos = fileName.lastIndexOf(QLatin1Char('/'));
|
|
|
|
|
if (pos != -1)
|
|
|
|
|
fileName = fileName.mid(pos + 1);
|
|
|
|
|
m_maxWidthOfFileName = qMax(m_maxWidthOfFileName, fm.width(fileName));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (row < m_processedIndices.size())
|
|
|
|
|
m_processedIndices.replace(row, itemCount);
|
|
|
|
|
else
|
|
|
|
|
m_processedIndices.insert(row, itemCount);
|
|
|
|
|
}
|
2014-10-07 15:51:02 +02:00
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-21 13:10:37 +02:00
|
|
|
/********************************** Filter Model **********************************/
|
|
|
|
|
|
|
|
|
|
TestResultFilterModel::TestResultFilterModel(TestResultModel *sourceModel, QObject *parent)
|
|
|
|
|
: QSortFilterProxyModel(parent),
|
|
|
|
|
m_sourceModel(sourceModel)
|
|
|
|
|
{
|
|
|
|
|
setSourceModel(sourceModel);
|
|
|
|
|
enableAllResultTypes();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TestResultFilterModel::enableAllResultTypes()
|
|
|
|
|
{
|
2015-01-08 13:46:28 +01:00
|
|
|
m_enabled << Result::PASS << Result::FAIL << Result::EXPECTED_FAIL
|
|
|
|
|
<< Result::UNEXPECTED_PASS << Result::SKIP << Result::MESSAGE_DEBUG
|
|
|
|
|
<< Result::MESSAGE_WARN << Result::MESSAGE_INTERNAL
|
2015-09-23 07:14:25 +02:00
|
|
|
<< Result::MESSAGE_FATAL << Result::INVALID << Result::BLACKLISTED_PASS
|
2015-01-08 13:46:28 +01:00
|
|
|
<< Result::BLACKLISTED_FAIL << Result::BENCHMARK
|
2015-08-20 15:59:15 +02:00
|
|
|
<< Result::MESSAGE_CURRENT_TEST << Result::MESSAGE_TEST_CASE_START
|
|
|
|
|
<< Result::MESSAGE_TEST_CASE_SUCCESS << Result::MESSAGE_TEST_CASE_WARN
|
|
|
|
|
<< Result::MESSAGE_TEST_CASE_FAIL << Result::MESSAGE_TEST_CASE_END;
|
2014-10-21 13:10:37 +02:00
|
|
|
invalidateFilter();
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-08 13:46:28 +01:00
|
|
|
void TestResultFilterModel::toggleTestResultType(Result::Type type)
|
2014-10-21 13:10:37 +02:00
|
|
|
{
|
|
|
|
|
if (m_enabled.contains(type)) {
|
|
|
|
|
m_enabled.remove(type);
|
2015-08-20 15:59:15 +02:00
|
|
|
if (type == Result::MESSAGE_INTERNAL)
|
|
|
|
|
m_enabled.remove(Result::MESSAGE_TEST_CASE_END);
|
2014-10-21 13:10:37 +02:00
|
|
|
} else {
|
|
|
|
|
m_enabled.insert(type);
|
2015-08-20 15:59:15 +02:00
|
|
|
if (type == Result::MESSAGE_INTERNAL)
|
|
|
|
|
m_enabled.insert(Result::MESSAGE_TEST_CASE_END);
|
2014-10-21 13:10:37 +02:00
|
|
|
}
|
|
|
|
|
invalidateFilter();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TestResultFilterModel::clearTestResults()
|
|
|
|
|
{
|
|
|
|
|
m_sourceModel->clearTestResults();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TestResultFilterModel::hasResults()
|
|
|
|
|
{
|
|
|
|
|
return rowCount(QModelIndex());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TestResult TestResultFilterModel::testResult(const QModelIndex &index) const
|
|
|
|
|
{
|
|
|
|
|
return m_sourceModel->testResult(mapToSource(index));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TestResultFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
|
|
|
|
{
|
|
|
|
|
QModelIndex index = m_sourceModel->index(sourceRow, 0, sourceParent);
|
|
|
|
|
if (!index.isValid())
|
|
|
|
|
return false;
|
|
|
|
|
return m_enabled.contains(m_sourceModel->testResult(index).result());
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-07 15:51:02 +02:00
|
|
|
} // namespace Internal
|
|
|
|
|
} // namespace Autotest
|