diff --git a/plugins/autotest/autotestconstants.h b/plugins/autotest/autotestconstants.h index 3cfc770d45d859b21a596a11efea65d060f42728..a4f6bdc7d9ffcdd033cff66547a4438ca8e2b6f3 100644 --- a/plugins/autotest/autotestconstants.h +++ b/plugins/autotest/autotestconstants.h @@ -19,6 +19,8 @@ #ifndef AUTOTESTCONSTANTS_H #define AUTOTESTCONSTANTS_H +#include <QtGlobal> + namespace Autotest { namespace Constants { @@ -27,6 +29,7 @@ const char MENU_ID[] = "AutoTest.Menu"; const char AUTOTEST_ID[] = "AutoTest.ATP"; const char AUTOTEST_CONTEXT[] = "Auto Tests"; const char TASK_INDEX[] = "AutoTest.Task.Index"; +const char UNNAMED_QUICKTESTS[] = QT_TR_NOOP("<unnamed>"); } // namespace Autotest } // namespace Constants diff --git a/plugins/autotest/testcodeparser.cpp b/plugins/autotest/testcodeparser.cpp index f58b2a448917330dc5f122478b91c3101ece00f6..9d4f41af06a71b0e1d8bc25b623726a16a66f9f4 100644 --- a/plugins/autotest/testcodeparser.cpp +++ b/plugins/autotest/testcodeparser.cpp @@ -16,6 +16,7 @@ ** ****************************************************************************/ +#include "autotestconstants.h" #include "testcodeparser.h" #include "testinfo.h" #include "testtreeitem.h" @@ -385,51 +386,60 @@ void TestCodeParser::handleQtQuickTest(CPlusPlus::Document::Ptr doc) m_model->removeQuickTestSubtreeByFilePath(d->fileName()); m_quickDocMap.remove(d->fileName()); } - bool hadUnnamedTestsBefore; - TestTreeItem *ttItem = m_model->unnamedQuickTests(); - if (!ttItem) { - hadUnnamedTestsBefore = false; - ttItem = new TestTreeItem(QString(), QString(), TestTreeItem::TEST_CLASS, - quickTestRootItem); - foreach (const QString &func, testFunctions.keys()) { - const TestCodeLocation location = testFunctions.value(func); - TestTreeItem *ttSub = new TestTreeItem(func, location.m_fileName, - TestTreeItem::TEST_FUNCTION, ttItem); - ttSub->setLine(location.m_line); - ttSub->setColumn(location.m_column); - ttSub->setMainFile(doc->fileName()); - ttItem->appendChild(ttSub); - } - } else { - hadUnnamedTestsBefore = true; + TestTreeItem *unnamedQTItem = m_model->unnamedQuickTests(); + if (unnamedQTItem) { // remove unnamed quick tests that are already found for this qml file - m_model->removeUnnamedQuickTest(d->fileName()); - - foreach (const QString &func, testFunctions.keys()) { - const TestCodeLocation location = testFunctions.value(func); - TestTreeItem *ttSub = new TestTreeItem(func, location.m_fileName, - TestTreeItem::TEST_FUNCTION, ttItem); - ttSub->setLine(location.m_line); - ttSub->setColumn(location.m_column); - ttSub->setMainFile(doc->fileName()); - ttItem->appendChild(ttSub); + if (m_model->removeUnnamedQuickTests(d->fileName())) { + // make sure m_quickDocMap does not have a inconsistent state now + TestInfo ti = m_quickDocMap[tr(Constants::UNNAMED_QUICKTESTS)]; + QStringList tiFunctions = ti.testFunctions(); + foreach (const QString &func, testFunctions.keys()) + tiFunctions.removeOne(func); + ti.setTestFunctions(tiFunctions); + if (tiFunctions.size() == 0) + m_quickDocMap.remove(tr(Constants::UNNAMED_QUICKTESTS)); + else + m_quickDocMap.insert(tr(Constants::UNNAMED_QUICKTESTS), ti); } + // as removeUnnamedQuickTests() could delete this item itself try to get it again + unnamedQTItem = m_model->unnamedQuickTests(); } - TestInfo info = m_quickDocMap.contains(QLatin1String("<unnamed>")) - ? m_quickDocMap[QLatin1String("<unnamed>")] - : TestInfo(QString(), QStringList(), 666); - QStringList originalFunctions(info.testFunctions()); + // construct new/modified TestTreeItem + TestTreeItem *ttItem = new TestTreeItem(QString(), QString(), + TestTreeItem::TEST_CLASS, + quickTestRootItem); + if (unnamedQTItem) { + for (int i = 0, count = unnamedQTItem->childCount(); i < count; ++i) { + TestTreeItem *child = new TestTreeItem(*unnamedQTItem->child(i)); + child->setParent(ttItem); + ttItem->appendChild(child); + } + } + foreach (const QString &func, testFunctions.keys()) { - if (!originalFunctions.contains(func)) - originalFunctions.append(func); + const TestCodeLocation location = testFunctions.value(func); + TestTreeItem *ttSub = new TestTreeItem(func, location.m_fileName, + TestTreeItem::TEST_FUNCTION, ttItem); + ttSub->setLine(location.m_line); + ttSub->setColumn(location.m_column); + ttSub->setMainFile(doc->fileName()); + ttItem->appendChild(ttSub); } + TestInfo info = m_quickDocMap.contains(tr(Constants::UNNAMED_QUICKTESTS)) + ? m_quickDocMap[tr(Constants::UNNAMED_QUICKTESTS)] + : TestInfo(QString(), QStringList(), 666); + QStringList originalFunctions(info.testFunctions()); + foreach (const QString &func, testFunctions.keys()) + originalFunctions.append(func); info.setTestFunctions(originalFunctions); - if (hadUnnamedTestsBefore) - m_model->modifyQuickTestSubtree(ttItem->row(), ttItem); - else + if (unnamedQTItem) { + m_model->modifyQuickTestSubtree(unnamedQTItem->row(), ttItem); + delete ttItem; + } else { m_model->addQuickTest(ttItem); - m_quickDocMap.insert(QLatin1String("<unnamed>"), info); + } + m_quickDocMap.insert(tr(Constants::UNNAMED_QUICKTESTS), info); continue; } // end of handling test cases without name property @@ -468,15 +478,20 @@ void TestCodeParser::handleQtQuickTest(CPlusPlus::Document::Ptr doc) delete ttItem; } else { // if it was formerly unnamed remove the respective items - if (m_quickDocMap.contains(QLatin1String("<unnamed>"))) { - m_model->removeUnnamedQuickTest(d->fileName()); - TestInfo unnamedInfo = m_quickDocMap[QLatin1String("<unnamed>")]; - QStringList functions = unnamedInfo.testFunctions(); - foreach (const QString &func, testFunctions.keys()) - if (functions.contains(func)) - functions.removeOne(func); - unnamedInfo.setTestFunctions(functions); - m_quickDocMap.insert(QLatin1String("<unnamed>"), unnamedInfo); + if (m_quickDocMap.contains(tr(Constants::UNNAMED_QUICKTESTS))) { + if (m_model->removeUnnamedQuickTests(d->fileName())) { + // make sure m_quickDocMap does not have a inconsistent state now + TestInfo unnamedInfo = m_quickDocMap[tr(Constants::UNNAMED_QUICKTESTS)]; + QStringList functions = unnamedInfo.testFunctions(); + foreach (const QString &func, testFunctions.keys()) + if (functions.contains(func)) + functions.removeOne(func); + unnamedInfo.setTestFunctions(functions); + if (functions.size() == 0) + m_quickDocMap.remove(tr(Constants::UNNAMED_QUICKTESTS)); + else + m_quickDocMap.insert(tr(Constants::UNNAMED_QUICKTESTS), unnamedInfo); + } } m_model->addQuickTest(ttItem); @@ -523,7 +538,7 @@ void TestCodeParser::onQmlDocumentUpdated(const QmlJS::Document::Ptr &doc) && snapshot.contains(m_quickDocMap[fileName].referencingFile())) { checkDocumentForTestCode(snapshot.document(m_quickDocMap[fileName].referencingFile())); } - if (!m_quickDocMap.contains(QLatin1String("<unnamed>"))) + if (!m_quickDocMap.contains(tr(Constants::UNNAMED_QUICKTESTS))) return; // special case of having unnamed TestCases diff --git a/plugins/autotest/testresult.cpp b/plugins/autotest/testresult.cpp index c75ba31ac6fcfb87074cce2f90df4beb6479d6b2..e3b974113bee5eace84b6eb828664c462a2ccf0a 100644 --- a/plugins/autotest/testresult.cpp +++ b/plugins/autotest/testresult.cpp @@ -55,18 +55,53 @@ ResultType TestResult::resultFromString(const QString &resultString) return UNKNOWN; } +ResultType TestResult::toResultType(int rt) +{ + switch(rt) { + case PASS: + return PASS; + case FAIL: + return FAIL; + case EXPECTED_FAIL: + return EXPECTED_FAIL; + case UNEXPECTED_PASS: + return UNEXPECTED_PASS; + case SKIP: + return SKIP; + case MESSAGE_DEBUG: + return MESSAGE_DEBUG; + case MESSAGE_WARN: + return MESSAGE_WARN; + case MESSAGE_FATAL: + return MESSAGE_FATAL; + case MESSAGE_INTERNAL: + return MESSAGE_INTERNAL; + default: + 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(); + 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"); } @@ -75,15 +110,24 @@ QString TestResult::resultToString(const ResultType type) 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"); + 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"); } diff --git a/plugins/autotest/testresult.h b/plugins/autotest/testresult.h index b8b6a2dd1a6beb6467e917cf2fa617037fda5d73..aa0d01e4e7cb13ba1ea5a627a2db21f3c9610ec6 100644 --- a/plugins/autotest/testresult.h +++ b/plugins/autotest/testresult.h @@ -57,6 +57,7 @@ public: void setLine(int line) { m_line = line; } static ResultType resultFromString(const QString &resultString); + static ResultType toResultType(int rt); static QString resultToString(const ResultType type); static QColor colorForType(const ResultType type); diff --git a/plugins/autotest/testresultspane.cpp b/plugins/autotest/testresultspane.cpp index 06a3257b0a157f842b0bea9f3f654284cd9a7471..e9d0f1be561b4953c7f4f665626b8ed88d9598d6 100644 --- a/plugins/autotest/testresultspane.cpp +++ b/plugins/autotest/testresultspane.cpp @@ -322,7 +322,7 @@ void TestResultsPane::updateFilterMenu() foreach (QAction *action, m_filterMenu->actions()) { if (action->isCheckable()) action->setEnabled(m_model->hasResultType( - static_cast<ResultType>(action->data().value<int>()))); + TestResult::toResultType(action->data().value<int>()))); } } @@ -337,7 +337,7 @@ void TestResultsPane::enableAllFilter() void TestResultsPane::filterMenuTriggered(QAction *action) { - m_filterModel->toggleTestResultType(static_cast<ResultType>(action->data().value<int>())); + m_filterModel->toggleTestResultType(TestResult::toResultType(action->data().value<int>())); navigateStateChanged(); } diff --git a/plugins/autotest/testtreeitem.cpp b/plugins/autotest/testtreeitem.cpp index 3b7c27fcde4bf23e5c4f2fcbe1233abc9bcd36dc..5ffd1927613a3e29ecd2c2c80056242db5854fbd 100644 --- a/plugins/autotest/testtreeitem.cpp +++ b/plugins/autotest/testtreeitem.cpp @@ -36,6 +36,23 @@ TestTreeItem::~TestTreeItem() removeChildren(); } +TestTreeItem::TestTreeItem(const TestTreeItem &other) + : m_name(other.m_name), + m_filePath(other.m_filePath), + m_checked(other.m_checked), + m_type(other.m_type), + m_line(other.m_line), + m_column(other.m_column), + m_mainFile(other.m_mainFile), + m_parent(other.m_parent) +{ + foreach (const TestTreeItem *child, other.m_children) { + TestTreeItem *reparentedChild = new TestTreeItem(*child); + reparentedChild->m_parent = this; + m_children.append(reparentedChild); + } +} + TestTreeItem *TestTreeItem::child(int row) { return m_children.at(row); diff --git a/plugins/autotest/testtreeitem.h b/plugins/autotest/testtreeitem.h index eaa1d68656cb3fcde7f350fad67aec28842e4f7b..6f0ca88e2d03c360157584ba01e6c525115bd009 100644 --- a/plugins/autotest/testtreeitem.h +++ b/plugins/autotest/testtreeitem.h @@ -35,6 +35,7 @@ public: TestTreeItem(const QString &name, const QString &filePath, Type type, TestTreeItem *parent = 0); virtual ~TestTreeItem(); + TestTreeItem(const TestTreeItem& other); TestTreeItem *child(int row); TestTreeItem *parent() const; @@ -58,6 +59,7 @@ public: void setChecked(const Qt::CheckState checked); Qt::CheckState checked() const { return m_checked; } Type type() const { return m_type; } + void setParent(TestTreeItem *parent) { m_parent = parent; } private: void revalidateCheckState(); diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 38a38c51f93a8b209038485759b5488c8c1cfb02..93d9d160ef72af3c2e63bb27acb1e3008c8098c6 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -16,6 +16,7 @@ ** ****************************************************************************/ +#include "autotestconstants.h" #include "testcodeparser.h" #include "testtreeitem.h" #include "testtreemodel.h" @@ -152,7 +153,7 @@ QVariant TestTreeModel::data(const QModelIndex &index, int role) const return QString(item->name() + tr(" (none)")); } else { if (item->name().isEmpty()) - return tr("<unnamed>"); + return tr(Constants::UNNAMED_QUICKTESTS); return item->name(); } @@ -535,19 +536,24 @@ void TestTreeModel::removeAllQuickTests() emit testTreeModelChanged(); } -void TestTreeModel::removeUnnamedQuickTest(const QString &filePath) +bool TestTreeModel::removeUnnamedQuickTests(const QString &filePath) { TestTreeItem *unnamedQT = unnamedQuickTests(); if (!unnamedQT) - return; + return false; + bool removed = false; const QModelIndex unnamedQTIndex = index(1, 0).child(unnamedQT->row(), 0); for (int childRow = unnamedQT->childCount() - 1; childRow >= 0; --childRow) { const TestTreeItem *child = unnamedQT->child(childRow); if (filePath == child->filePath()) - removeRow(childRow, unnamedQTIndex); + removed |= removeRow(childRow, unnamedQTIndex); } + + if (unnamedQT->childCount() == 0) + removeRow(unnamedQT->row(), unnamedQTIndex.parent()); emit testTreeModelChanged(); + return removed; } void TestTreeModel::modifyTestSubtree(QModelIndex &toBeModifiedIndex, TestTreeItem *newItem) @@ -566,6 +572,7 @@ void TestTreeModel::modifyTestSubtree(QModelIndex &toBeModifiedIndex, TestTreeIt const int newChildCount = newItem->childCount(); // for keeping the CheckState on modifications + // TODO might still fail for duplicate entries (e.g. unnamed Quick Tests) QHash<QString, Qt::CheckState> originalItems; for (int row = 0; row < childCount; ++row) { const TestTreeItem *child = toBeModifiedItem->child(row); @@ -594,9 +601,8 @@ void TestTreeModel::modifyTestSubtree(QModelIndex &toBeModifiedIndex, TestTreeIt if (childCount < newChildCount) { // add aditional items for (int row = childCount; row < newChildCount; ++row) { TestTreeItem *newChild = newItem->child(row); - TestTreeItem *toBeAdded = new TestTreeItem(newChild->name(), newChild->filePath(), - newChild->type(), toBeModifiedItem); - toBeAdded->setLine(newChild->line()); + TestTreeItem *toBeAdded = new TestTreeItem(*newChild); + toBeAdded->setParent(toBeModifiedItem); beginInsertRows(toBeModifiedIndex, row, row); toBeModifiedItem->appendChild(toBeAdded); endInsertRows(); @@ -628,5 +634,97 @@ void TestTreeModel::modifyTestSubtree(QModelIndex &toBeModifiedIndex, TestTreeIt emit testTreeModelChanged(); } +/***************************** Sort/Filter Model **********************************/ + +TestTreeSortFilterModel::TestTreeSortFilterModel(TestTreeModel *sourceModel, QObject *parent) + : QSortFilterProxyModel(parent), + m_sourceModel(sourceModel), + m_sortMode(Alphabetically), + m_filterMode(Basic) +{ + setSourceModel(sourceModel); +} + +void TestTreeSortFilterModel::setSortMode(SortMode sortMode) +{ + m_sortMode = sortMode; + invalidate(); +} + +void TestTreeSortFilterModel::setFilterMode(FilterMode filterMode) +{ + m_filterMode = filterMode; + invalidateFilter(); +} + +void TestTreeSortFilterModel::toggleFilter(FilterMode filterMode) +{ + m_filterMode = toFilterMode(m_filterMode ^ filterMode); + invalidateFilter(); +} + +TestTreeSortFilterModel::FilterMode TestTreeSortFilterModel::toFilterMode(int f) +{ + switch (f) { + case TestTreeSortFilterModel::ShowInitAndCleanup: + return TestTreeSortFilterModel::ShowInitAndCleanup; + case TestTreeSortFilterModel::ShowTestData: + return TestTreeSortFilterModel::ShowTestData; + case TestTreeSortFilterModel::ShowAll: + return TestTreeSortFilterModel::ShowAll; + default: + return TestTreeSortFilterModel::Basic; + } +} + +bool TestTreeSortFilterModel::lessThan(const QModelIndex &left, const QModelIndex &right) const +{ + // root items keep the intended order: 1st Auto Tests, 2nd Quick Tests + const TestTreeItem *leftItem = static_cast<TestTreeItem *>(left.internalPointer()); + if (leftItem->type() == TestTreeItem::ROOT) + return left.row() > right.row(); + + const QString leftVal = m_sourceModel->data(left).toString(); + const QString rightVal = m_sourceModel->data(right).toString(); + + // unnamed Quick Tests will always be listed first + if (leftVal == tr(Constants::UNNAMED_QUICKTESTS)) + return false; + if (rightVal == tr(Constants::UNNAMED_QUICKTESTS)) + return true; + + switch (m_sortMode) { + case Alphabetically: + return leftVal > rightVal; + case Naturally: { + const TextEditor::TextEditorWidget::Link leftLink = + m_sourceModel->data(left, LinkRole).value<TextEditor::TextEditorWidget::Link>(); + const TextEditor::TextEditorWidget::Link rightLink = + m_sourceModel->data(right, LinkRole).value<TextEditor::TextEditorWidget::Link>(); + + if (leftLink.targetFileName == rightLink.targetFileName) { + return leftLink.targetLine == rightLink.targetLine + ? leftLink.targetColumn > rightLink.targetColumn + : leftLink.targetLine > rightLink.targetLine; + } else { + return leftLink.targetFileName > rightLink.targetFileName; + } + } + default: + return true; + } +} + +bool TestTreeSortFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const +{ + // TODO add filtering capabilities + QModelIndex index = m_sourceModel->index(sourceRow, 0,sourceParent); + if (!index.isValid()) + return false; + + + return true; +} + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testtreemodel.h b/plugins/autotest/testtreemodel.h index 72ecf88ff4245d9d05e0df98ffdc1fd087183621..94cb874f8e59b1776e955705bfe93d2eb0653538 100644 --- a/plugins/autotest/testtreemodel.h +++ b/plugins/autotest/testtreemodel.h @@ -24,6 +24,7 @@ #include <cplusplus/CppDocument.h> #include <QAbstractItemModel> +#include <QSortFilterProxyModel> namespace { enum ItemRole { @@ -71,7 +72,7 @@ public: void removeQuickTestSubtreeByFilePath(const QString &file); void addQuickTest(TestTreeItem *newItem); void removeAllQuickTests(); - void removeUnnamedQuickTest(const QString &filePath); + bool removeUnnamedQuickTests(const QString &filePath); signals: void testTreeModelChanged(); @@ -89,6 +90,39 @@ private: }; +class TestTreeSortFilterModel : public QSortFilterProxyModel +{ + Q_OBJECT +public: + enum SortMode { + Alphabetically, + Naturally + }; + + enum FilterMode { + Basic, + ShowInitAndCleanup = 0x01, + ShowTestData = 0x02, + ShowAll = ShowInitAndCleanup | ShowTestData + }; + + TestTreeSortFilterModel(TestTreeModel *sourceModel, QObject *parent = 0); + void setSortMode(SortMode sortMode); + void setFilterMode(FilterMode filterMode); + void toggleFilter(FilterMode filterMode); + static FilterMode toFilterMode(int f); + +protected: + bool lessThan(const QModelIndex &left, const QModelIndex &right) const; + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; + +private: + TestTreeModel *m_sourceModel; + SortMode m_sortMode; + FilterMode m_filterMode; + +}; + } // namespace Internal } // namespace Autotest diff --git a/plugins/autotest/testtreeview.cpp b/plugins/autotest/testtreeview.cpp index 37739832897f9b83cf29017294d9e164b365e1c7..45376db383054ed35ab08f54afa34d1f226d1c81 100644 --- a/plugins/autotest/testtreeview.cpp +++ b/plugins/autotest/testtreeview.cpp @@ -23,6 +23,7 @@ #include "testtreemodel.h" #include "testtreeview.h" +#include <coreplugin/coreconstants.h> #include <coreplugin/icore.h> #include <coreplugin/find/itemviewfind.h> @@ -47,8 +48,11 @@ TestTreeViewWidget::TestTreeViewWidget(QWidget *parent) : { setWindowTitle(tr("Tests")); m_model = TestTreeModel::instance(); + m_sortFilterModel = new TestTreeSortFilterModel(m_model, m_model); + m_sortFilterModel->setDynamicSortFilter(true); m_view = new TestTreeView(this); - m_view->setModel(m_model); + m_view->setModel(m_sortFilterModel); + m_view->setSortingEnabled(true); QVBoxLayout *layout = new QVBoxLayout; layout->setMargin(0); @@ -116,10 +120,21 @@ QList<QToolButton *> TestTreeViewWidget::createToolButtons() { QList<QToolButton *> list; + m_filterButton = new QToolButton(m_view); + m_filterButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_FILTER))); + m_filterButton->setToolTip(tr("Filter Test Tree")); + 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, &TestTreeViewWidget::onFilterMenuTriggered); + m_filterButton->setMenu(m_filterMenu); + m_sortAlphabetically = true; m_sort = new QToolButton(this); m_sort->setIcon((QIcon(QLatin1String(":/images/leafsort.png")))); - m_sort->setToolTip(tr("Sort Naturally (not implemented yet)")); + m_sort->setToolTip(tr("Sort Naturally")); QToolButton *expand = new QToolButton(this); expand->setIcon(QIcon(QLatin1String(":/images/expand.png"))); @@ -133,7 +148,7 @@ QList<QToolButton *> TestTreeViewWidget::createToolButtons() connect(collapse, &QToolButton::clicked, m_view, &TestTreeView::collapseAll); connect(m_sort, &QToolButton::clicked, this, &TestTreeViewWidget::onSortClicked); - list << m_sort << expand << collapse; + list << m_filterButton << m_sort << expand << collapse; return list; } @@ -167,14 +182,37 @@ void TestTreeViewWidget::onSortClicked() if (m_sortAlphabetically) { m_sort->setIcon((QIcon(QLatin1String(":/images/sort.png")))); m_sort->setToolTip(tr("Sort Alphabetically")); + m_sortFilterModel->setSortMode(TestTreeSortFilterModel::Naturally); } else { m_sort->setIcon((QIcon(QLatin1String(":/images/leafsort.png")))); - m_sort->setToolTip(tr("Sort Naturally (not implemented yet)")); + m_sort->setToolTip(tr("Sort Naturally")); + m_sortFilterModel->setSortMode(TestTreeSortFilterModel::Alphabetically); } - // TODO trigger the sorting change.. m_sortAlphabetically = !m_sortAlphabetically; } +void TestTreeViewWidget::onFilterMenuTriggered(QAction *action) +{ + m_sortFilterModel->toggleFilter( + TestTreeSortFilterModel::toFilterMode(action->data().value<int>())); +} + +void TestTreeViewWidget::initializeFilterMenu() +{ + QAction *action = new QAction(m_filterMenu); + action->setText(tr("Show init and cleanup functions")); + action->setCheckable(true); + action->setChecked(false); + action->setData(TestTreeSortFilterModel::ShowInitAndCleanup); + m_filterMenu->addAction(action); + action = new QAction(m_filterMenu); + action->setText(tr("Show data functions")); + action->setCheckable(true); + action->setChecked(false); + action->setData(TestTreeSortFilterModel::ShowTestData); + m_filterMenu->addAction(action); +} + TestViewFactory::TestViewFactory() { setDisplayName(tr("Tests")); diff --git a/plugins/autotest/testtreeview.h b/plugins/autotest/testtreeview.h index 27e475f17c5d1827b26d5a59bc3a84835a39557d..5f6c8670adf7ac7a11d9b86a321c25a2b074e077 100644 --- a/plugins/autotest/testtreeview.h +++ b/plugins/autotest/testtreeview.h @@ -24,6 +24,8 @@ #include <utils/navigationtreeview.h> QT_BEGIN_NAMESPACE +class QAction; +class QMenu; class QModelIndex; class QToolButton; QT_END_NAMESPACE @@ -36,6 +38,7 @@ namespace Autotest { namespace Internal { class TestTreeModel; +class TestTreeSortFilterModel; class TestTreeView : public Utils::NavigationTreeView { @@ -71,11 +74,17 @@ private slots: void onRunAllTriggered(); void onRunSelectedTriggered(); void onSortClicked(); + void onFilterMenuTriggered(QAction *action); private: + void initializeFilterMenu(); + TestTreeModel *m_model; + TestTreeSortFilterModel *m_sortFilterModel; TestTreeView *m_view; QToolButton *m_sort; + QToolButton *m_filterButton; + QMenu *m_filterMenu; bool m_sortAlphabetically; };