diff --git a/src/plugins/autotest/projectsettingswidget.cpp b/src/plugins/autotest/projectsettingswidget.cpp index dd05ad1f149..b2d507f8efb 100644 --- a/src/plugins/autotest/projectsettingswidget.cpp +++ b/src/plugins/autotest/projectsettingswidget.cpp @@ -31,6 +31,7 @@ #include "testtreemodel.h" #include +#include #include #include @@ -40,7 +41,10 @@ namespace Autotest { namespace Internal { -enum ItemDataRole { FrameworkIdRole = Qt::UserRole + 1 }; +enum ItemDataRole { + BaseIdRole = Qt::UserRole + 1, + BaseTypeRole +}; static QSpacerItem *createSpacer(QSizePolicy::Policy horizontal, QSizePolicy::Policy vertical) { @@ -90,13 +94,15 @@ ProjectTestSettingsWidget::ProjectTestSettingsWidget(ProjectExplorer::Project *p m_useGlobalSettings->setCurrentIndex(m_projectSettings->useGlobalSettings() ? 0 : 1); generalWidget->setDisabled(m_projectSettings->useGlobalSettings()); - populateFrameworks(m_projectSettings->activeFrameworks()); + populateFrameworks(m_projectSettings->activeFrameworks(), + m_projectSettings->activeTestTools()); connect(m_useGlobalSettings, QOverload::of(&QComboBox::currentIndexChanged), this, [this, generalWidget](int index) { generalWidget->setEnabled(index != 0); m_projectSettings->setUseGlobalSettings(index == 0); - m_syncFrameworksTimer.start(3000); + m_syncTimer.start(3000); + m_syncType = ITestBase::Framework | ITestBase::Tool; }); connect(m_activeFrameworks, &QTreeWidget::itemChanged, this, &ProjectTestSettingsWidget::onActiveFrameworkChanged); @@ -104,29 +110,53 @@ ProjectTestSettingsWidget::ProjectTestSettingsWidget(ProjectExplorer::Project *p this, [this](int index) { m_projectSettings->setRunAfterBuild(RunAfterBuildMode(index)); }); - m_syncFrameworksTimer.setSingleShot(true); - connect(&m_syncFrameworksTimer, &QTimer::timeout, - TestTreeModel::instance(), &TestTreeModel::synchronizeTestFrameworks); + m_syncTimer.setSingleShot(true); + connect(&m_syncTimer, &QTimer::timeout, + [this]() { + auto testTreeModel = TestTreeModel::instance(); + if (m_syncType & ITestBase::Framework) + testTreeModel->synchronizeTestFrameworks(); + if (m_syncType & ITestBase::Tool) + testTreeModel->synchronizeTestTools(); + m_syncType = ITestBase::None; + }); } -void ProjectTestSettingsWidget::populateFrameworks(const QHash &frameworks) +void ProjectTestSettingsWidget::populateFrameworks(const QHash &frameworks, + const QHash &testTools) { TestFrameworks sortedFrameworks = frameworks.keys(); Utils::sort(sortedFrameworks, &ITestFramework::priority); - for (ITestFramework *framework : sortedFrameworks) { - auto item = new QTreeWidgetItem(m_activeFrameworks, QStringList(QLatin1String(framework->name()))); + auto generateItem = [this](ITestBase *frameworkOrTestTool, bool checked) { + auto item = new QTreeWidgetItem(m_activeFrameworks, {QLatin1String(frameworkOrTestTool->name())}); item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable); - item->setCheckState(0, frameworks.value(framework) ? Qt::Checked : Qt::Unchecked); - item->setData(0, FrameworkIdRole, framework->id().toSetting()); - } + item->setCheckState(0, checked ? Qt::Checked : Qt::Unchecked); + item->setData(0, BaseIdRole, frameworkOrTestTool->id().toSetting()); + item->setData(0, BaseTypeRole, frameworkOrTestTool->type()); + }; + + for (ITestFramework *framework : qAsConst(sortedFrameworks)) + generateItem(framework, frameworks.value(framework)); + + // FIXME: testTools aren't sorted and we cannot use priority here + auto end = testTools.cend(); + for (auto it = testTools.cbegin(); it != end; ++it) + generateItem(it.key(), it.value()); } void ProjectTestSettingsWidget::onActiveFrameworkChanged(QTreeWidgetItem *item, int column) { - auto id = Utils::Id::fromSetting(item->data(column, FrameworkIdRole)); - m_projectSettings->activateFramework(id, item->data(0, Qt::CheckStateRole) == Qt::Checked); - m_syncFrameworksTimer.start(3000); + auto id = Utils::Id::fromSetting(item->data(column, BaseIdRole)); + int type = item->data(column, BaseTypeRole).toInt(); + if (type == ITestBase::Framework) + m_projectSettings->activateFramework(id, item->data(0, Qt::CheckStateRole) == Qt::Checked); + else if (type == ITestBase::Tool) + m_projectSettings->activateTestTool(id, item->data(0, Qt::CheckStateRole) == Qt::Checked); + else + QTC_ASSERT(! "unexpected test base type", return); + m_syncTimer.start(3000); + m_syncType |= type; } } // namespace Internal diff --git a/src/plugins/autotest/projectsettingswidget.h b/src/plugins/autotest/projectsettingswidget.h index b8c0d47addf..b11429e9675 100644 --- a/src/plugins/autotest/projectsettingswidget.h +++ b/src/plugins/autotest/projectsettingswidget.h @@ -39,6 +39,7 @@ namespace ProjectExplorer { class Project; } namespace Autotest { class ITestFramework; +class ITestTool; namespace Internal { @@ -51,13 +52,15 @@ public: explicit ProjectTestSettingsWidget(ProjectExplorer::Project *project, QWidget *parent = nullptr); private: - void populateFrameworks(const QHash &frameworks); + void populateFrameworks(const QHash &frameworks, + const QHash &testTools); void onActiveFrameworkChanged(QTreeWidgetItem *item, int column); TestProjectSettings *m_projectSettings; QComboBox *m_useGlobalSettings = nullptr; QTreeWidget *m_activeFrameworks = nullptr; QComboBox *m_runAfterBuild = nullptr; - QTimer m_syncFrameworksTimer; + QTimer m_syncTimer; + int m_syncType = 0; }; } // namespace Internal diff --git a/src/plugins/autotest/testframeworkmanager.cpp b/src/plugins/autotest/testframeworkmanager.cpp index 94f49879b46..d6edee794c5 100644 --- a/src/plugins/autotest/testframeworkmanager.cpp +++ b/src/plugins/autotest/testframeworkmanager.cpp @@ -99,6 +99,14 @@ ITestFramework *TestFrameworkManager::frameworkForId(Id frameworkId) }); } +ITestTool *TestFrameworkManager::testToolForId(Id testToolId) +{ + return Utils::findOrDefault(s_instance->m_registeredTestTools, + [testToolId](ITestTool *testTool) { + return testTool->id() == testToolId; + }); +} + ITestTool *TestFrameworkManager::testToolForBuildSystemId(Id buildSystemId) { if (!buildSystemId.isValid()) diff --git a/src/plugins/autotest/testframeworkmanager.h b/src/plugins/autotest/testframeworkmanager.h index 13a48afda1f..69b7a0294ed 100644 --- a/src/plugins/autotest/testframeworkmanager.h +++ b/src/plugins/autotest/testframeworkmanager.h @@ -48,6 +48,7 @@ public: void synchronizeSettings(QSettings *s); static ITestFramework *frameworkForId(Utils::Id frameworkId); + static ITestTool *testToolForId(Utils::Id testToolId); static ITestTool *testToolForBuildSystemId(Utils::Id buildSystemId); static void activateFrameworksAndToolsFromSettings(const Internal::TestSettings *settings); static const TestFrameworks registeredFrameworks(); diff --git a/src/plugins/autotest/testprojectsettings.cpp b/src/plugins/autotest/testprojectsettings.cpp index 14d55d16c78..087393740ea 100644 --- a/src/plugins/autotest/testprojectsettings.cpp +++ b/src/plugins/autotest/testprojectsettings.cpp @@ -73,26 +73,43 @@ void TestProjectSettings::activateFramework(const Utils::Id &id, bool activate) framework->resetRootNode(); } +void TestProjectSettings::activateTestTool(const Utils::Id &id, bool activate) +{ + ITestTool *testTool = TestFrameworkManager::testToolForId(id); + m_activeTestTools[testTool] = activate; + if (!activate) + testTool->resetRootNode(); +} + void TestProjectSettings::load() { const QVariant useGlobal = m_project->namedSettings(Constants::SK_USE_GLOBAL); m_useGlobalSettings = useGlobal.isValid() ? useGlobal.toBool() : true; - const TestFrameworks registered = TestFrameworkManager::registeredFrameworks(); - qCDebug(LOG) << "Registered frameworks sorted by priority" << registered; + const TestFrameworks registeredFrameworks = TestFrameworkManager::registeredFrameworks(); + qCDebug(LOG) << "Registered frameworks sorted by priority" << registeredFrameworks; + const TestTools registeredTestTools = TestFrameworkManager::registeredTestTools(); const QVariant activeFrameworks = m_project->namedSettings(SK_ACTIVE_FRAMEWORKS); m_activeTestFrameworks.clear(); + m_activeTestTools.clear(); if (activeFrameworks.isValid()) { const QMap frameworksMap = activeFrameworks.toMap(); - for (ITestFramework *framework : registered) { + for (ITestFramework *framework : registeredFrameworks) { const Utils::Id id = framework->id(); bool active = frameworksMap.value(id.toString(), framework->active()).toBool(); m_activeTestFrameworks.insert(framework, active); } + for (ITestTool *testTool : registeredTestTools) { + const Utils::Id id = testTool->id(); + bool active = frameworksMap.value(id.toString(), testTool->active()).toBool(); + m_activeTestTools.insert(testTool, active); + } } else { - for (ITestFramework *framework : registered) + for (ITestFramework *framework : registeredFrameworks) m_activeTestFrameworks.insert(framework, framework->active()); + for (ITestTool *testTool : registeredTestTools) + m_activeTestTools.insert(testTool, testTool->active()); } const QVariant runAfterBuild = m_project->namedSettings(SK_RUN_AFTER_BUILD); @@ -108,6 +125,9 @@ void TestProjectSettings::save() auto end = m_activeTestFrameworks.cend(); for (auto it = m_activeTestFrameworks.cbegin(); it != end; ++it) activeFrameworks.insert(it.key()->id().toString(), it.value()); + auto endTools = m_activeTestTools.cend(); + for (auto it = m_activeTestTools.cbegin(); it != endTools; ++it) + activeFrameworks.insert(it.key()->id().toString(), it.value()); m_project->setNamedSettings(SK_ACTIVE_FRAMEWORKS, activeFrameworks); m_project->setNamedSettings(SK_RUN_AFTER_BUILD, int(m_runAfterBuild)); m_project->setNamedSettings(SK_CHECK_STATES, m_checkStateCache.toSettings()); diff --git a/src/plugins/autotest/testprojectsettings.h b/src/plugins/autotest/testprojectsettings.h index 84884932456..1c5741c2bc7 100644 --- a/src/plugins/autotest/testprojectsettings.h +++ b/src/plugins/autotest/testprojectsettings.h @@ -33,6 +33,7 @@ namespace ProjectExplorer { class Project; } namespace Autotest { class ITestFramework; +class ITestTool; namespace Internal { @@ -40,17 +41,21 @@ class TestProjectSettings : public QObject { Q_OBJECT public: - TestProjectSettings(ProjectExplorer::Project *project); + explicit TestProjectSettings(ProjectExplorer::Project *project); ~TestProjectSettings(); void setUseGlobalSettings(bool useGlobal); bool useGlobalSettings() const { return m_useGlobalSettings; } void setRunAfterBuild(RunAfterBuildMode mode) {m_runAfterBuild = mode; } RunAfterBuildMode runAfterBuild() const { return m_runAfterBuild; } - void setActiveFrameworks(const QHash enabledFrameworks) + void setActiveFrameworks(const QHash &enabledFrameworks) { m_activeTestFrameworks = enabledFrameworks; } QHash activeFrameworks() const { return m_activeTestFrameworks; } void activateFramework(const Utils::Id &id, bool activate); + void setActiveTestTools(const QHash &enabledTestTools) + { m_activeTestTools = enabledTestTools; } + QHash activeTestTools() const { return m_activeTestTools; } + void activateTestTool(const Utils::Id &id, bool activate); Internal::ItemDataCache *checkStateCache() { return &m_checkStateCache; } private: void load(); @@ -60,6 +65,7 @@ private: bool m_useGlobalSettings = true; RunAfterBuildMode m_runAfterBuild = RunAfterBuildMode::None; QHash m_activeTestFrameworks; + QHash m_activeTestTools; Internal::ItemDataCache m_checkStateCache; }; diff --git a/src/plugins/autotest/testtreemodel.cpp b/src/plugins/autotest/testtreemodel.cpp index 1b7a76ef8cf..89cfc3dff05 100644 --- a/src/plugins/autotest/testtreemodel.cpp +++ b/src/plugins/autotest/testtreemodel.cpp @@ -353,7 +353,21 @@ void TestTreeModel::synchronizeTestFrameworks() void TestTreeModel::synchronizeTestTools() { - // currently no project settings... + ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); + TestTools tools; + if (!project || AutotestPlugin::projectSettings(project)->useGlobalSettings()) { + tools = Utils::filtered(TestFrameworkManager::registeredTestTools(), + &ITestFramework::active); + qCDebug(LOG) << "Active test tools" << tools; // FIXME tools aren't sorted + } else { // we've got custom project settings + const TestProjectSettings *settings = AutotestPlugin::projectSettings(project); + const QHash active = settings->activeTestTools(); + tools = Utils::filtered(TestFrameworkManager::registeredTestTools(), + [active](ITestTool *testTool) { + return active.value(testTool, false); + }); + } + // pre-check to avoid further processing when test tools are unchanged Utils::TreeItem *invisibleRoot = rootItem(); QSet newlyAdded; @@ -367,7 +381,7 @@ void TestTreeModel::synchronizeTestTools() for (ITestTreeItem *oldFrameworkRoot : oldFrameworkRoots) takeItem(oldFrameworkRoot); // do NOT delete the ptr is still held by TestFrameworkManager - for (ITestTool *testTool : TestFrameworkManager::registeredTestTools()) { + for (ITestTool *testTool : tools) { ITestTreeItem *testToolRootNode = testTool->rootNode(); if (testTool->active()) { invisibleRoot->appendChild(testToolRootNode); @@ -376,7 +390,6 @@ void TestTreeModel::synchronizeTestTools() } } - const Project *project = SessionManager::startupProject(); if (project) { const QList &allTargets = project->targets(); auto target = allTargets.empty() ? nullptr : allTargets.first();