diff --git a/src/plugins/autotest/testtreeitem.cpp b/src/plugins/autotest/testtreeitem.cpp index 679cfc0e19f..76b11a1e0b5 100644 --- a/src/plugins/autotest/testtreeitem.cpp +++ b/src/plugins/autotest/testtreeitem.cpp @@ -41,7 +41,8 @@ TestTreeItem::TestTreeItem(const QString &name, const QString &filePath, Type ty m_filePath(filePath), m_type(type), m_line(0), - m_state(Enabled) + m_state(Enabled), + m_markedForRemoval(false) { switch (m_type) { case TestClass: @@ -71,7 +72,8 @@ TestTreeItem::TestTreeItem(const TestTreeItem &other) m_column(other.m_column), m_mainFile(other.m_mainFile), m_referencingFile(other.m_referencingFile), - m_state(other.m_state) + m_state(other.m_state), + m_markedForRemoval(other.m_markedForRemoval) { for (int row = 0, count = other.childCount(); row < count; ++row) appendChild(new TestTreeItem(*childItem(row))); @@ -198,6 +200,8 @@ bool TestTreeItem::modifyContent(const TestTreeItem *modified) m_state = modified->m_state; hasBeenModified = true; } + if (m_markedForRemoval != modified->m_markedForRemoval) + m_markedForRemoval = modified->m_markedForRemoval; return hasBeenModified; } @@ -242,6 +246,18 @@ Qt::CheckState TestTreeItem::checked() const return Qt::Unchecked; } +void TestTreeItem::markForRemoval(bool mark) +{ + m_markedForRemoval = mark; +} + +void TestTreeItem::markForRemovalRecursively(bool mark) +{ + m_markedForRemoval = mark; + for (int row = 0, count = childCount(); row < count; ++row) + childItem(row)->markForRemovalRecursively(mark); +} + QList TestTreeItem::getChildNames() const { QList names; diff --git a/src/plugins/autotest/testtreeitem.h b/src/plugins/autotest/testtreeitem.h index cf04e780a48..af65d1330b8 100644 --- a/src/plugins/autotest/testtreeitem.h +++ b/src/plugins/autotest/testtreeitem.h @@ -94,6 +94,9 @@ public: Type type() const { return m_type; } void setState(TestStates states) { m_state = states; } TestStates state() const { return m_state; } + void markForRemoval(bool mark); + void markForRemovalRecursively(bool mark); + bool markedForRemoval() const { return m_markedForRemoval; } QList getChildNames() const; TestTreeItem *parentItem() const; TestTreeItem *childItem(int row) const; @@ -110,6 +113,7 @@ private: QString m_mainFile; // main for Quick tests, project file for gtest QString m_referencingFile; TestStates m_state; + bool m_markedForRemoval; }; struct TestCodeLocationAndType { diff --git a/src/plugins/autotest/testtreemodel.cpp b/src/plugins/autotest/testtreemodel.cpp index 2f54aa9e1a1..d84513239aa 100644 --- a/src/plugins/autotest/testtreemodel.cpp +++ b/src/plugins/autotest/testtreemodel.cpp @@ -623,6 +623,87 @@ void TestTreeModel::removeGTests(const QString &filePath) emit testTreeModelChanged(); } +void TestTreeModel::markAllForRemoval() +{ + foreach (Utils::TreeItem *item, m_autoTestRootItem->children()) + static_cast(item)->markForRemovalRecursively(true); + + foreach (Utils::TreeItem *item, m_quickTestRootItem->children()) + static_cast(item)->markForRemovalRecursively(true); + + foreach (Utils::TreeItem *item, m_googleTestRootItem->children()) + static_cast(item)->markForRemovalRecursively(true); +} + +void TestTreeModel::markForRemoval(const QString &filePath) +{ + if (filePath.isEmpty()) + return; + + Type types[] = { AutoTest, QuickTest, GoogleTest }; + for (Type type : types) { + TestTreeItem *root = rootItemForType(type); + for (int childRow = root->childCount() - 1; childRow >= 0; --childRow) { + TestTreeItem *child = root->childItem(childRow); + if (child->markedForRemoval()) + continue; + // Qt + named Quick Tests + if (child->filePath() == filePath || child->referencingFile() == filePath) { + child->markForRemovalRecursively(true); + } else { + // unnamed Quick Tests and GTest and Qt Tests with separated source/header + int grandChildRow = child->childCount() - 1; + for ( ; grandChildRow >= 0; --grandChildRow) { + TestTreeItem *grandChild = child->childItem(grandChildRow); + if (grandChild->filePath() == filePath + || grandChild->referencingFile() == filePath) { + grandChild->markForRemovalRecursively(true); + } + } + } + } + } +} + +void TestTreeModel::sweep() +{ + bool hasChanged = false; + Type types[] = { AutoTest, QuickTest, GoogleTest }; + for (Type type : types) { + TestTreeItem *root = rootItemForType(type); + hasChanged |= sweepChildren(root); + } + if (hasChanged) + emit testTreeModelChanged(); +} + +/** + * @note after calling this function emit testTreeModelChanged() if it returns true + */ +bool TestTreeModel::sweepChildren(TestTreeItem *item) +{ + bool hasChanged = false; + for (int row = item->childCount() - 1; row >= 0; --row) { + TestTreeItem *child = item->childItem(row); + + if (child->parentItem()->type() != TestTreeItem::Root && child->markedForRemoval()) { + delete takeItem(child); + hasChanged = true; + continue; + } + if (bool noEndNode = child->hasChildren()) { + hasChanged |= sweepChildren(child); + if (noEndNode && child->childCount() == 0) { + delete takeItem(child); + hasChanged = true; + continue; + } + } + child->markForRemoval(false); + } + return hasChanged; +} + QMap TestTreeModel::referencingFiles() const { ReferencingFilesFinder finder; diff --git a/src/plugins/autotest/testtreemodel.h b/src/plugins/autotest/testtreemodel.h index 33fafa96422..d2595d3aaa1 100644 --- a/src/plugins/autotest/testtreemodel.h +++ b/src/plugins/autotest/testtreemodel.h @@ -78,6 +78,9 @@ public: QMultiMap gtestNamesAndSets() const; #endif + void markAllForRemoval(); + void markForRemoval(const QString &filePath); + void sweep(); QMap referencingFiles() const; signals: @@ -94,6 +97,7 @@ private: void removeTestTreeItems(const QString &filePath, Type type); void removeUnnamedQuickTests(const QString &filePath); void removeGTests(const QString &filePath); + bool sweepChildren(TestTreeItem *item); TestTreeItem *unnamedQuickTests() const; TestTreeItem *rootItemForType(Type type);