forked from qt-creator/qt-creator
Add filtering to test results
This commit is contained in:
committed by
Christian Stenger
parent
44db2be195
commit
eba497d921
@@ -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;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user