diff options
author | Christian Stenger <christian.stenger@theqtcompany.com> | 2015-02-05 16:07:45 +0100 |
---|---|---|
committer | Christian Stenger <christian.stenger@theqtcompany.com> | 2015-02-16 15:43:02 +0200 |
commit | 2ce99680b20802a370e6d20a1467a1d41fbee690 (patch) | |
tree | 66d68ac3cb3231b121e90cb3be683da1b2e8b63a /plugins/autotest/testtreemodel.cpp | |
parent | 61c50e4aa343387b56192a34db6384d1dfcfa3c5 (diff) | |
download | qt-creator-2ce99680b20802a370e6d20a1467a1d41fbee690.tar.gz |
Decouple code parser and model
Additionally some minor refactorings to increase readability.
Change-Id: I0be120fcedcf31dbb0116d84f0d3c23cf95e7d91
Reviewed-by: Andre Poenitz <andre.poenitz@theqtcompany.com>
Diffstat (limited to 'plugins/autotest/testtreemodel.cpp')
-rw-r--r-- | plugins/autotest/testtreemodel.cpp | 329 |
1 files changed, 216 insertions, 113 deletions
diff --git a/plugins/autotest/testtreemodel.cpp b/plugins/autotest/testtreemodel.cpp index 9c8d235a04..f2ea94d626 100644 --- a/plugins/autotest/testtreemodel.cpp +++ b/plugins/autotest/testtreemodel.cpp @@ -50,6 +50,17 @@ TestTreeModel::TestTreeModel(QObject *parent) : { m_rootItem->appendChild(m_autoTestRootItem); m_rootItem->appendChild(m_quickTestRootItem); + + connect(m_parser, &TestCodeParser::cacheCleared, this, &TestTreeModel::removeAllTestItems); + connect(m_parser, &TestCodeParser::testItemCreated, this, &TestTreeModel::addTestTreeItem); + connect(m_parser, &TestCodeParser::testItemsCreated, this, &TestTreeModel::addTestTreeItems); + connect(m_parser, &TestCodeParser::testItemModified, this, &TestTreeModel::modifyTestTreeItem); + connect(m_parser, &TestCodeParser::testItemsRemoved, this, &TestTreeModel::removeTestTreeItems); + connect(m_parser, &TestCodeParser::unnamedQuickTestsUpdated, + this, &TestTreeModel::updateUnnamedQuickTest); + connect(m_parser, &TestCodeParser::unnamedQuickTestsRemoved, + this, &TestTreeModel::removeUnnamedQuickTests); + m_parser->updateTestTree(); // CppTools::CppModelManagerInterface *cppMM = CppTools::CppModelManagerInterface::instance(); @@ -524,6 +535,62 @@ QList<TestConfiguration *> TestTreeModel::getSelectedTests() const return result; } +QString TestTreeModel::getMainFileForUnnamedQuickTest(const QString &qmlFile) const +{ + const TestTreeItem *unnamed = unnamedQuickTests(); + for (int row = 0, count = unnamed->childCount(); row < count; ++row) { + const TestTreeItem *child = unnamed->child(row); + if (qmlFile == child->filePath()) + return child->mainFile(); + } + return QString(); +} + +void TestTreeModel::qmlFilesAndFunctionNamesForMainFile(const QString &mainFile, + QSet<QString> *filePaths, + QList<QString> *functionNames) const +{ + TestTreeItem *unnamed = unnamedQuickTests(); + for (int i = 0; i < unnamed->childCount(); ++i) { + const TestTreeItem *child = unnamed->child(i); + if (child->mainFile() == mainFile) { + filePaths->insert(child->filePath()); + functionNames->append(child->name()); + } + } +} + +QList<QString> TestTreeModel::getUnnamedQuickTestFunctions() const +{ + TestTreeItem *unnamed = unnamedQuickTests(); + if (unnamed) + return unnamed->getChildNames(); + return QList<QString>(); +} + +QSet<QString> TestTreeModel::qmlFilesForProFile(const QString &proFile) const +{ + QSet<QString> filePaths; + CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance(); + if (TestTreeItem *unnamed = unnamedQuickTests()) { + for (int i = 0; i < unnamed->childCount(); ++i) { + const TestTreeItem *child = unnamed->child(i); + QList<CppTools::ProjectPart::Ptr> ppList = modelManager->projectPart(child->mainFile()); + if (ppList.size() && ppList.at(0)->projectFile == proFile) + filePaths.insert(child->filePath()); + } + } + return filePaths; +} + +bool TestTreeModel::hasUnnamedQuickTests() const +{ + for (int row = 0, count = m_quickTestRootItem->childCount(); row < count; ++row) + if (m_quickTestRootItem->child(row)->name().isEmpty()) + return true; + return false; +} + TestTreeItem *TestTreeModel::unnamedQuickTests() const { for (int row = 0, count = m_quickTestRootItem->childCount(); row < count; ++row) { @@ -534,177 +601,213 @@ TestTreeItem *TestTreeModel::unnamedQuickTests() const return 0; } -void TestTreeModel::modifyAutoTestSubtree(int row, TestTreeItem *newItem) +void TestTreeModel::removeUnnamedQuickTests(const QString &filePath) { - QModelIndex toBeModifiedIndex = index(0, 0).child(row, 0); - modifyTestSubtree(toBeModifiedIndex, newItem); -} + TestTreeItem *unnamedQT = unnamedQuickTests(); + if (!unnamedQT) + return; -void TestTreeModel::removeAutoTestSubtreeByFilePath(const QString &file) -{ - const QModelIndex atRootIndex = index(0, 0); - const int count = rowCount(atRootIndex); - for (int row = 0; row < count; ++row) { - const QModelIndex childIndex = atRootIndex.child(row, 0); - TestTreeItem *childItem = static_cast<TestTreeItem *>(childIndex.internalPointer()); - if (file == childItem->filePath()) { - removeRow(row, atRootIndex); - break; - } + 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); } + + if (unnamedQT->childCount() == 0) + removeRow(unnamedQT->row(), unnamedQTIndex.parent()); emit testTreeModelChanged(); } -void TestTreeModel::addAutoTest(TestTreeItem *newItem) +void TestTreeModel::addTestTreeItem(const TestTreeItem &item, TestTreeModel::Type type) { - beginInsertRows(index(0, 0), m_autoTestRootItem->childCount(), m_autoTestRootItem->childCount()); - m_autoTestRootItem->appendChild(newItem); + TestTreeItem *parent = rootItemForType(type); + QModelIndex index = rootIndexForType(type); + TestTreeItem *toBeAdded = new TestTreeItem(item); + toBeAdded->setParent(parent); + + beginInsertRows(index, parent->childCount(), parent->childCount()); + parent->appendChild(toBeAdded); endInsertRows(); emit testTreeModelChanged(); } -void TestTreeModel::removeAllAutoTests() +void TestTreeModel::addTestTreeItems(const QList<TestTreeItem> &itemList, TestTreeModel::Type type) { - beginResetModel(); - m_autoTestRootItem->removeChildren(); - endResetModel(); + TestTreeItem *parent = rootItemForType(type); + QModelIndex index = rootIndexForType(type); + + beginInsertRows(index, parent->childCount(), parent->childCount() + itemList.size() - 1); + foreach (const TestTreeItem &item, itemList) { + TestTreeItem *toBeAdded = new TestTreeItem(item); + toBeAdded->setParent(parent); + parent->appendChild(toBeAdded); + } + endInsertRows(); emit testTreeModelChanged(); } -void TestTreeModel::modifyQuickTestSubtree(int row, TestTreeItem *newItem) +void TestTreeModel::updateUnnamedQuickTest(const QString &fileName, const QString &mainFile, + const QMap<QString, TestCodeLocationAndType> &functions) { - QModelIndex toBeModifiedIndex = index(1, 0).child(row, 0); - modifyTestSubtree(toBeModifiedIndex, newItem); -} + removeUnnamedQuickTests(fileName); + TestTreeItem unnamed = hasUnnamedQuickTests() + ? TestTreeItem(*unnamedQuickTests()) + : TestTreeItem(QString(), QString(), TestTreeItem::TEST_CLASS, rootItemForType(QuickTest)); -void TestTreeModel::removeQuickTestSubtreeByFilePath(const QString &file) -{ - const QModelIndex qtRootIndex = index(1, 0); - for (int row = 0, count = rowCount(qtRootIndex); row < count; ++row) { - const QModelIndex childIndex = qtRootIndex.child(row, 0); - const TestTreeItem *childItem = static_cast<TestTreeItem *>(childIndex.internalPointer()); - if (file == childItem->filePath()) { - removeRow(row, qtRootIndex); - break; - } + foreach (const QString &functionName, functions.keys()) { + const TestCodeLocationAndType locationAndType = functions.value(functionName); + TestTreeItem *testFunction = new TestTreeItem(functionName, locationAndType.m_fileName, + locationAndType.m_type, &unnamed); + testFunction->setLine(locationAndType.m_line); + testFunction->setColumn(locationAndType.m_column); + testFunction->setMainFile(mainFile); + unnamed.appendChild(testFunction); } - emit testTreeModelChanged(); + if (hasUnnamedQuickTests()) + modifyTestTreeItem(unnamed, QuickTest, QString()); + else + addTestTreeItem(unnamed, QuickTest); } -void TestTreeModel::addQuickTest(TestTreeItem *newItem) +void TestTreeModel::modifyTestTreeItem(TestTreeItem item, TestTreeModel::Type type, const QString &file) { - beginInsertRows(index(1, 0), m_quickTestRootItem->childCount(), m_quickTestRootItem->childCount()); - m_quickTestRootItem->appendChild(newItem); - endInsertRows(); - emit testTreeModelChanged(); + QModelIndex index = rootIndexForType(type); + TestTreeItem *parent = rootItemForType(type); + item.setParent(parent); + if (file.isEmpty()) { + if (TestTreeItem *unnamed = unnamedQuickTests()) { + index = index.child(unnamed->row(), 0); + modifyTestSubtree(index, item); + } + } else { + for (int row = 0; row < parent->childCount(); ++row) { + if (parent->child(row)->filePath() == file) { + index = index.child(row, 0); + modifyTestSubtree(index, item); + break; + } + } + } } -void TestTreeModel::removeAllQuickTests() +void TestTreeModel::removeAllTestItems() { beginResetModel(); + m_autoTestRootItem->removeChildren(); m_quickTestRootItem->removeChildren(); endResetModel(); emit testTreeModelChanged(); } -bool TestTreeModel::removeUnnamedQuickTests(const QString &filePath) +void TestTreeModel::removeTestTreeItems(const QString &filePath, Type type) { - TestTreeItem *unnamedQT = unnamedQuickTests(); - if (!unnamedQT) - 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()) - removed |= removeRow(childRow, unnamedQTIndex); + const QModelIndex rootIndex = rootIndexForType(type); + const int count = rowCount(rootIndex); + for (int row = count - 1; row >= 0; --row) { + const QModelIndex childIndex = rootIndex.child(row, 0); + TestTreeItem *childItem = static_cast<TestTreeItem *>(childIndex.internalPointer()); + if (filePath == childItem->filePath()) + removed |= removeRow(row, rootIndex); } + if (removed) + emit testTreeModelChanged(); +} - if (unnamedQT->childCount() == 0) - removeRow(unnamedQT->row(), unnamedQTIndex.parent()); - emit testTreeModelChanged(); - return removed; +TestTreeItem *TestTreeModel::rootItemForType(TestTreeModel::Type type) +{ + switch (type) { + case AutoTest: + return m_autoTestRootItem; + case QuickTest: + return m_quickTestRootItem; + } + QTC_ASSERT(false, return 0); +} + +QModelIndex TestTreeModel::rootIndexForType(TestTreeModel::Type type) +{ + switch (type) { + case AutoTest: + return index(0, 0); + case QuickTest: + return index(1, 0); + } + QTC_ASSERT(false, return QModelIndex()); } -void TestTreeModel::modifyTestSubtree(QModelIndex &toBeModifiedIndex, TestTreeItem *newItem) +void TestTreeModel::modifyTestSubtree(QModelIndex &toBeModifiedIndex, const TestTreeItem &newItem) + { if (!toBeModifiedIndex.isValid()) return; - static QVector<int> modificationRoles = QVector<int>() << Qt::DisplayRole - << Qt::ToolTipRole << LinkRole; TestTreeItem *toBeModifiedItem = static_cast<TestTreeItem *>(toBeModifiedIndex.internalPointer()); - if (toBeModifiedItem->modifyContent(newItem)) - emit dataChanged(toBeModifiedIndex, toBeModifiedIndex, modificationRoles); + if (toBeModifiedItem->modifyContent(&newItem)) + emit dataChanged(toBeModifiedIndex, toBeModifiedIndex, + QVector<int>() << Qt::DisplayRole << Qt::ToolTipRole << LinkRole); // process sub-items as well... const int childCount = toBeModifiedItem->childCount(); - const int newChildCount = newItem->childCount(); + 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; + // TODO might still fail for duplicate entries + QHash<QString, Qt::CheckState> checkStates; for (int row = 0; row < childCount; ++row) { const TestTreeItem *child = toBeModifiedItem->child(row); - originalItems.insert(child->name(), child->checked()); + checkStates.insert(child->name(), child->checked()); } if (childCount <= newChildCount) { - for (int row = 0; row < childCount; ++row) { - QModelIndex child = toBeModifiedIndex.child(row, 0); - TestTreeItem *toBeModifiedChild = toBeModifiedItem->child(row); - TestTreeItem *modifiedChild = newItem->child(row); - if (toBeModifiedChild->modifyContent(modifiedChild)) { - emit dataChanged(child, child, modificationRoles); - } - if (originalItems.contains(toBeModifiedChild->name())) { - Qt::CheckState state = originalItems.value(toBeModifiedChild->name()); - if (state != toBeModifiedChild->checked()) { - toBeModifiedChild->setChecked(state); - emit dataChanged(child, child, QVector<int>() << Qt::CheckStateRole); - } - } else { // newly added (BAD: happens for renaming as well) - toBeModifiedChild->setChecked(Qt::Checked); - emit dataChanged(child, child, QVector<int>() << Qt::CheckStateRole); - } - } - if (childCount < newChildCount) { // add aditional items - for (int row = childCount; row < newChildCount; ++row) { - TestTreeItem *newChild = newItem->child(row); - TestTreeItem *toBeAdded = new TestTreeItem(*newChild); - toBeAdded->setParent(toBeModifiedItem); - beginInsertRows(toBeModifiedIndex, row, row); - toBeModifiedItem->appendChild(toBeAdded); - endInsertRows(); - if (originalItems.contains(toBeAdded->name()) - && originalItems.value(toBeAdded->name()) != Qt::Checked) - toBeAdded->setChecked(originalItems.value(toBeAdded->name())); - } + processChildren(toBeModifiedIndex, newItem, childCount, checkStates); + // add additional items + for (int row = childCount; row < newChildCount; ++row) { + TestTreeItem *newChild = newItem.child(row); + TestTreeItem *toBeAdded = new TestTreeItem(*newChild); + toBeAdded->setParent(toBeModifiedItem); + if (checkStates.contains(toBeAdded->name()) + && checkStates.value(toBeAdded->name()) != Qt::Checked) + toBeAdded->setChecked(checkStates.value(toBeAdded->name())); + beginInsertRows(toBeModifiedIndex, row, row); + toBeModifiedItem->appendChild(toBeAdded); + endInsertRows(); } } else { - for (int row = 0; row < newChildCount; ++row) { - QModelIndex child = toBeModifiedIndex.child(row, 0); - TestTreeItem *toBeModifiedChild = toBeModifiedItem->child(row); - TestTreeItem *modifiedChild = newItem->child(row); - if (toBeModifiedChild->modifyContent(modifiedChild)) - emit dataChanged(child, child, modificationRoles); - if (originalItems.contains(toBeModifiedChild->name())) { - Qt::CheckState state = originalItems.value(toBeModifiedChild->name()); - if (state != toBeModifiedChild->checked()) { - toBeModifiedChild->setChecked(state); - emit dataChanged(child, child, QVector<int>() << Qt::CheckStateRole); - } - } else { // newly added (BAD: happens for renaming as well) - toBeModifiedChild->setChecked(Qt::Checked); - emit dataChanged(child, child, QVector<int>() << Qt::CheckStateRole); - } - } // remove rest of the items + processChildren(toBeModifiedIndex, newItem, newChildCount, checkStates); + // remove rest of the items removeRows(newChildCount, childCount - newChildCount, toBeModifiedIndex); } emit testTreeModelChanged(); } +void TestTreeModel::processChildren(QModelIndex &parentIndex, const TestTreeItem &newItem, + const int upperBound, + const QHash<QString, Qt::CheckState> &checkStates) +{ + static QVector<int> modificationRoles = QVector<int>() << Qt::DisplayRole + << Qt::ToolTipRole << LinkRole; + TestTreeItem *toBeModifiedItem = static_cast<TestTreeItem *>(parentIndex.internalPointer()); + for (int row = 0; row < upperBound; ++row) { + QModelIndex child = parentIndex.child(row, 0); + TestTreeItem *toBeModifiedChild = toBeModifiedItem->child(row); + TestTreeItem *modifiedChild = newItem.child(row); + if (toBeModifiedChild->modifyContent(modifiedChild)) + emit dataChanged(child, child, modificationRoles); + if (checkStates.contains(toBeModifiedChild->name())) { + Qt::CheckState state = checkStates.value(toBeModifiedChild->name()); + if (state != toBeModifiedChild->checked()) { + toBeModifiedChild->setChecked(state); + emit dataChanged(child, child, QVector<int>() << Qt::CheckStateRole); + } + } else { // newly added (BAD: happens for renaming as well) + toBeModifiedChild->setChecked(Qt::Checked); + emit dataChanged(child, child, QVector<int>() << Qt::CheckStateRole); + } + } +} + /***************************** Sort/Filter Model **********************************/ TestTreeSortFilterModel::TestTreeSortFilterModel(TestTreeModel *sourceModel, QObject *parent) |