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;
 
 };