Commit eba497d9 authored by Christian Stenger's avatar Christian Stenger Committed by Christian Stenger
Browse files

Add filtering to test results

parent 44db2be1
......@@ -76,4 +76,6 @@ bool operator==(const TestResult &t1, const TestResult &t2);
} // namespace Internal
} // namespace Autotest
Q_DECLARE_METATYPE(Autotest::Internal::ResultType)
#endif // TESTRESULT_H
......@@ -64,9 +64,10 @@ void TestResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
painter->drawRect(opt.rect);
painter->setPen(foreground);
TestResultModel *resultModel = static_cast<TestResultModel *>(view->model());
TestResultFilterModel *resultFilterModel = static_cast<TestResultFilterModel *>(view->model());
TestResultModel *resultModel = static_cast<TestResultModel *>(resultFilterModel->sourceModel());
LayoutPositions positions(opt, resultModel);
TestResult testResult = resultModel->testResult(index);
TestResult testResult = resultModel->testResult(resultFilterModel->mapToSource(index));
ResultType type = testResult.result();
QIcon icon = index.data(Qt::DecorationRole).value<QIcon>();
......@@ -176,13 +177,14 @@ QSize TestResultDelegate::sizeHint(const QStyleOptionViewItem &option, const QMo
QFontMetrics fm(opt.font);
int fontHeight = fm.height();
TestResultModel *resultModel = static_cast<TestResultModel *>(view->model());
TestResultFilterModel *resultFilterModel = static_cast<TestResultFilterModel *>(view->model());
TestResultModel *resultModel = static_cast<TestResultModel *>(resultFilterModel->sourceModel());
LayoutPositions positions(opt, resultModel);
QSize s;
s.setWidth(opt.rect.width());
if (selected) {
TestResult testResult = resultModel->testResult(index);
TestResult testResult = resultModel->testResult(resultFilterModel->mapToSource(index));
QString output;
switch (testResult.result()) {
......
......@@ -21,6 +21,7 @@
#include <QDebug>
#include <QFontMetrics>
#include <QIcon>
#include <QSortFilterProxyModel>
namespace Autotest {
namespace Internal {
......@@ -70,7 +71,7 @@ static QIcon testResultIcon(ResultType result) {
QIcon(QLatin1String(":/images/debug.png")),
QIcon(QLatin1String(":/images/warn.png")),
QIcon(QLatin1String(":/images/fatal.png")),
};
}; // provide an icon for unknown??
if (result < 0 || result >= MESSAGE_INTERNAL)
return QIcon();
......@@ -116,6 +117,9 @@ void TestResultModel::clearTestResults()
return;
beginRemoveRows(QModelIndex(), 0, m_testResults.size() - 1);
m_testResults.clear();
m_lastMaxWidthIndex = 0;
m_maxWidthOfFileName = 0;
m_widthOfLineNumber = 0;
endRemoveRows();
}
......@@ -159,5 +163,57 @@ int TestResultModel::maxWidthOfLineNumber(const QFont &font)
return m_widthOfLineNumber;
}
/********************************** Filter Model **********************************/
TestResultFilterModel::TestResultFilterModel(TestResultModel *sourceModel, QObject *parent)
: QSortFilterProxyModel(parent),
m_sourceModel(sourceModel)
{
setSourceModel(sourceModel);
enableAllResultTypes();
}
void TestResultFilterModel::enableAllResultTypes()
{
m_enabled << ResultType::PASS << ResultType::FAIL << ResultType::EXPECTED_FAIL
<< ResultType::UNEXPECTED_PASS << ResultType::SKIP << ResultType::MESSAGE_DEBUG
<< ResultType::MESSAGE_WARN << ResultType::MESSAGE_INTERNAL
<< ResultType::MESSAGE_FATAL << ResultType::UNKNOWN;
invalidateFilter();
}
void TestResultFilterModel::toggleTestResultType(ResultType type)
{
if (m_enabled.contains(type)) {
m_enabled.remove(type);
} else {
m_enabled.insert(type);
}
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());
}
} // namespace Internal
} // namespace Autotest
......@@ -22,7 +22,9 @@
#include "testresult.h"
#include <QAbstractItemModel>
#include <QSortFilterProxyModel>
#include <QFont>
#include <QSet>
namespace Autotest {
namespace Internal {
......@@ -48,6 +50,9 @@ public:
int maxWidthOfFileName(const QFont &font);
int maxWidthOfLineNumber(const QFont &font);
void enableAllResultTypes();
void toggleTestResultType(ResultType type);
signals:
public slots:
......@@ -60,6 +65,26 @@ private:
QFont m_measurementFont;
};
class TestResultFilterModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
TestResultFilterModel(TestResultModel *sourceModel, QObject *parent = 0);
void enableAllResultTypes();
void toggleTestResultType(ResultType type);
void clearTestResults();
bool hasResults();
TestResult testResult(const QModelIndex &index) const;
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
private:
TestResultModel *m_sourceModel;
QSet<ResultType> m_enabled;
};
} // namespace Internal
} // namespace Autotest
......
......@@ -22,12 +22,14 @@
#include "testrunner.h"
#include "testtreemodel.h"
#include <coreplugin/coreconstants.h>
#include <coreplugin/icontext.h>
#include <texteditor/texteditor.h>
#include <utils/itemviews.h>
#include <QDebug>
#include <QToolButton>
namespace Autotest {
......@@ -39,7 +41,9 @@ TestResultsPane::TestResultsPane(QObject *parent) :
{
m_listView = new Utils::ListView;
m_model = new TestResultModel(this);
m_listView->setModel(m_model);
m_filterModel = new TestResultFilterModel(m_model, this);
m_filterModel->setDynamicSortFilter(true);
m_listView->setModel(m_filterModel);
TestResultDelegate *trd = new TestResultDelegate(this);
m_listView->setItemDelegate(trd);
......@@ -61,6 +65,17 @@ void TestResultsPane::createToolButtons()
m_runSelected->setIcon(QIcon(QLatin1String(":/images/runselected.png")));
m_runSelected->setToolTip(tr("Run Selected Tests"));
connect(m_runSelected, &QToolButton::clicked, this, &TestResultsPane::onRunSelectedTriggered);
m_filterButton = new QToolButton(m_listView);
m_filterButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_FILTER)));
m_filterButton->setToolTip(tr("Filter Test Results"));
m_filterButton->setProperty("noArrow", true);
m_filterButton->setAutoRaise(true);
m_filterButton->setPopupMode(QToolButton::InstantPopup);
m_filterMenu = new QMenu(m_filterButton);
initializeFilterMenu();
connect(m_filterMenu, &QMenu::triggered, this, &TestResultsPane::filterMenuTriggered);
m_filterButton->setMenu(m_filterMenu);
}
static TestResultsPane *m_instance = 0;
......@@ -99,7 +114,7 @@ QWidget *TestResultsPane::outputWidget(QWidget *parent)
QList<QWidget *> TestResultsPane::toolBarWidgets() const
{
return QList<QWidget *>() << m_runAll << m_runSelected; // add filter as well
return QList<QWidget *>() << m_runAll << m_runSelected << m_filterButton;
}
QString TestResultsPane::displayName() const
......@@ -114,7 +129,7 @@ int TestResultsPane::priorityInStatusBar() const
void TestResultsPane::clearContents()
{
m_model->clearTestResults();
m_filterModel->clearTestResults();
navigateStateChanged();
}
......@@ -143,12 +158,12 @@ bool TestResultsPane::canNavigate() const
bool TestResultsPane::canNext() const
{
return m_model->hasResults();
return m_filterModel->hasResults();
}
bool TestResultsPane::canPrevious() const
{
return m_model->hasResults();
return m_filterModel->hasResults();
}
void TestResultsPane::goToNext()
......@@ -159,11 +174,11 @@ void TestResultsPane::goToNext()
QModelIndex currentIndex = m_listView->currentIndex();
if (currentIndex.isValid()) {
int row = currentIndex.row() + 1;
if (row == m_model->rowCount(QModelIndex()))
if (row == m_filterModel->rowCount(QModelIndex()))
row = 0;
currentIndex = m_model->index(row, 0, QModelIndex());
currentIndex = m_filterModel->index(row, 0, QModelIndex());
} else {
currentIndex = m_model->index(0, 0, QModelIndex());
currentIndex = m_filterModel->index(0, 0, QModelIndex());
}
m_listView->setCurrentIndex(currentIndex);
onItemActivated(currentIndex);
......@@ -178,10 +193,10 @@ void TestResultsPane::goToPrev()
if (currentIndex.isValid()) {
int row = currentIndex.row() - 1;
if (row < 0)
row = m_model->rowCount(QModelIndex()) - 1;
currentIndex = m_model->index(row, 0, QModelIndex());
row = m_filterModel->rowCount(QModelIndex()) - 1;
currentIndex = m_filterModel->index(row, 0, QModelIndex());
} else {
currentIndex = m_model->index(m_model->rowCount(QModelIndex()) - 1, 0, QModelIndex());
currentIndex = m_filterModel->index(m_filterModel->rowCount(QModelIndex()) - 1, 0, QModelIndex());
}
m_listView->setCurrentIndex(currentIndex);
onItemActivated(currentIndex);
......@@ -192,7 +207,7 @@ void TestResultsPane::onItemActivated(const QModelIndex &index)
if (!index.isValid())
return;
TestResult tr = m_model->testResult(index);
TestResult tr = m_filterModel->testResult(index);
if (!tr.fileName().isEmpty())
Core::EditorManager::openEditorAt(tr.fileName(), tr.line(), 0);
}
......@@ -209,7 +224,34 @@ void TestResultsPane::onRunSelectedTriggered()
TestRunner *runner = TestRunner::instance();
runner->setSelectedTests(TestTreeModel::instance()->getSelectedTests());
runner->runTests();
}
void TestResultsPane::initializeFilterMenu()
{
QMap<ResultType, QString> textAndType;
textAndType.clear();
textAndType.insert(ResultType::PASS, QLatin1String("Pass"));
textAndType.insert(ResultType::FAIL, QLatin1String("Fail"));
textAndType.insert(ResultType::EXPECTED_FAIL, QLatin1String("Expected Fail"));
textAndType.insert(ResultType::UNEXPECTED_PASS, QLatin1String("Unexpected Pass"));
textAndType.insert(ResultType::SKIP, QLatin1String("Skip"));
textAndType.insert(ResultType::MESSAGE_DEBUG, QLatin1String("Debug Messages"));
textAndType.insert(ResultType::MESSAGE_WARN, QLatin1String("Warning Messages"));
textAndType.insert(ResultType::MESSAGE_INTERNAL, QLatin1String("Internal Messages"));
foreach (ResultType result, textAndType.keys()) {
QAction *action = new QAction(m_filterMenu);
action->setText(textAndType.value(result));
action->setCheckable(true);
action->setChecked(true);
action->setData(result);
m_filterMenu->addAction(action);
}
}
void TestResultsPane::filterMenuTriggered(QAction *action)
{
m_filterModel->toggleTestResultType(static_cast<ResultType>(action->data().value<int>()));
navigateStateChanged();
}
} // namespace Internal
......
......@@ -22,7 +22,9 @@
#include <coreplugin/ioutputpane.h>
QT_BEGIN_NAMESPACE
class QAction;
class QModelIndex;
class QMenu;
class QToolButton;
QT_END_NAMESPACE
......@@ -39,6 +41,7 @@ namespace Internal {
class TestResult;
class TestResultModel;
class TestResultFilterModel;
class TestResultsPane : public Core::IOutputPane
{
......@@ -73,6 +76,8 @@ private slots:
void onItemActivated(const QModelIndex &index);
void onRunAllTriggered();
void onRunSelectedTriggered();
void initializeFilterMenu();
void filterMenuTriggered(QAction *action);
private:
explicit TestResultsPane(QObject *parent = 0);
......@@ -80,9 +85,12 @@ private:
Utils::ListView *m_listView;
TestResultModel *m_model;
TestResultFilterModel *m_filterModel;
Core::IContext *m_context;
QToolButton *m_runAll;
QToolButton *m_runSelected;
QToolButton *m_filterButton;
QMenu *m_filterMenu;
};
} // namespace Internal
......
......@@ -20,9 +20,7 @@
#include "testtreeitem.h"
#include "testtreemodel.h"
#include <texteditor/texteditor.h>
#include <QIcon>
#include <cpptools/cppmodelmanager.h>
#include <projectexplorer/buildtargetinfo.h>
#include <projectexplorer/environmentaspect.h>
......@@ -32,7 +30,11 @@
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
#include <cpptools/cppmodelmanager.h>
#include <texteditor/texteditor.h>
#include <utils/fileutils.h>
#include <QIcon>
namespace Autotest {
namespace Internal {
......@@ -276,16 +278,11 @@ static void addProjectInformation(TestConfiguration *config, const QString &file
if (ProjectExplorer::LocalApplicationRunConfiguration *localRunConfiguration
= qobject_cast<ProjectExplorer::LocalApplicationRunConfiguration *>(rc)) {
if (localRunConfiguration->executable() == targetFile) {
workDir = localRunConfiguration->workingDirectory();
QList<ProjectExplorer::IRunConfigurationAspect *> aspects
= localRunConfiguration->extraAspects();
foreach (ProjectExplorer::IRunConfigurationAspect *aspect, aspects) {
if (ProjectExplorer::EnvironmentAspect *asp
= qobject_cast<ProjectExplorer::EnvironmentAspect *>(aspect)) {
env = asp->environment();
break;
}
}
workDir = Utils::FileUtils::normalizePathName(
localRunConfiguration->workingDirectory());
ProjectExplorer::EnvironmentAspect *envAsp
= localRunConfiguration->extraAspect<ProjectExplorer::EnvironmentAspect>();
env = envAsp->environment();
break;
}
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment