diff --git a/src/plugins/autotest/CMakeLists.txt b/src/plugins/autotest/CMakeLists.txt index a5291ce3157..2c2051647f2 100644 --- a/src/plugins/autotest/CMakeLists.txt +++ b/src/plugins/autotest/CMakeLists.txt @@ -36,6 +36,7 @@ add_qtc_plugin(AutoTest itestframework.h itestparser.cpp itestparser.h itestsettingspage.h + projectsettingswidget.cpp projectsettingswidget.h qtest/qttest_utils.cpp qtest/qttest_utils.h qtest/qttestconfiguration.cpp qtest/qttestconfiguration.h qtest/qttestconstants.h @@ -59,6 +60,7 @@ add_qtc_plugin(AutoTest testframeworkmanager.cpp testframeworkmanager.h testnavigationwidget.cpp testnavigationwidget.h testoutputreader.cpp testoutputreader.h + testprojectsettings.cpp testprojectsettings.h testresult.cpp testresult.h testresultdelegate.cpp testresultdelegate.h testresultmodel.cpp testresultmodel.h diff --git a/src/plugins/autotest/autotest.pro b/src/plugins/autotest/autotest.pro index 22e2b594c9f..c849d8c4d47 100644 --- a/src/plugins/autotest/autotest.pro +++ b/src/plugins/autotest/autotest.pro @@ -6,23 +6,27 @@ include(../../qtcreatorplugin.pri) DEFINES += AUTOTEST_LIBRARY SOURCES += \ - testtreeview.cpp \ - testtreemodel.cpp \ - testtreeitem.cpp \ - testcodeparser.cpp \ autotestplugin.cpp \ - testrunner.cpp \ + itestparser.cpp \ + projectsettingswidget.cpp \ + testcodeparser.cpp \ testconfiguration.cpp \ - testresult.cpp \ - testresultspane.cpp \ - testresultmodel.cpp \ - testresultdelegate.cpp \ - testtreeitemdelegate.cpp \ - testsettings.cpp \ - testsettingspage.cpp \ + testeditormark.cpp \ + testframeworkmanager.cpp \ testnavigationwidget.cpp \ testoutputreader.cpp \ - itestparser.cpp \ + testprojectsettings.cpp \ + testresult.cpp \ + testresultdelegate.cpp \ + testresultmodel.cpp \ + testresultspane.cpp \ + testrunner.cpp \ + testsettings.cpp \ + testsettingspage.cpp \ + testtreeitem.cpp \ + testtreeitemdelegate.cpp \ + testtreemodel.cpp \ + testtreeview.cpp \ gtest/gtestconfiguration.cpp \ gtest/gtestparser.cpp \ gtest/gtesttreeitem.cpp \ @@ -57,34 +61,37 @@ SOURCES += \ boost/boosttestoutputreader.cpp \ boost/boosttestresult.cpp \ boost/boosttestsettings.cpp \ - boost/boosttestsettingspage.cpp \ - testframeworkmanager.cpp \ - testeditormark.cpp - + boost/boosttestsettingspage.cpp HEADERS += \ - testtreeview.h \ - testtreemodel.h \ - testtreeitem.h \ - testcodeparser.h \ - autotestplugin.h \ autotest_global.h \ autotestconstants.h \ - testrunner.h \ + autotesticons.h \ + autotestplugin.h \ + iframeworksettings.h \ + itestframework.h \ + itestparser.h \ + itestsettingspage.h \ + projectsettingswidget.h \ + testcodeparser.h \ testconfiguration.h \ - testresult.h \ - testresultspane.h \ - testresultmodel.h \ - testresultdelegate.h \ - testtreeitemdelegate.h \ - testsettings.h \ - testsettingspage.h \ + testeditormark.h \ + testframeworkmanager.h \ testnavigationwidget.h \ testoutputreader.h \ - autotesticons.h \ - itestframework.h \ - iframeworksettings.h \ - itestparser.h \ + testprojectsettings.h \ + testresult.h \ + testresultdelegate.h \ + testresultmodel.h \ + testresultspane.h \ + testrunconfiguration.h \ + testrunner.h \ + testsettings.h \ + testsettingspage.h \ + testtreeitem.h \ + testtreeitemdelegate.h \ + testtreemodel.h \ + testtreeview.h \ gtest/gtestconfiguration.h \ gtest/gtestparser.h \ gtest/gtesttreeitem.h \ @@ -122,11 +129,7 @@ HEADERS += \ boost/boosttestoutputreader.h \ boost/boosttestresult.h \ boost/boosttestsettingspage.h \ - boost/boosttestsettings.h \ - testframeworkmanager.h \ - testrunconfiguration.h \ - itestsettingspage.h \ - testeditormark.h + boost/boosttestsettings.h RESOURCES += \ autotest.qrc diff --git a/src/plugins/autotest/autotest.qbs b/src/plugins/autotest/autotest.qbs index 9d31d536468..0336ec75eb5 100644 --- a/src/plugins/autotest/autotest.qbs +++ b/src/plugins/autotest/autotest.qbs @@ -37,6 +37,8 @@ QtcPlugin { "autotestconstants.h", "autotestplugin.cpp", "autotestplugin.h", + "projectsettingswidget.cpp", + "projectsettingswidget.h", "testcodeparser.cpp", "testcodeparser.h", "testconfiguration.cpp", @@ -70,6 +72,8 @@ QtcPlugin { "testtreeview.h", "testoutputreader.cpp", "testoutputreader.h", + "testprojectsettings.cpp", + "testprojectsettings.h", "itestparser.cpp", "itestparser.h", "itestframework.h", diff --git a/src/plugins/autotest/autotestconstants.h b/src/plugins/autotest/autotestconstants.h index 1f92aba915e..9d4ea135b35 100644 --- a/src/plugins/autotest/autotestconstants.h +++ b/src/plugins/autotest/autotestconstants.h @@ -47,6 +47,7 @@ const char FRAMEWORK_PREFIX[] = "AutoTest.Framework."; const char SETTINGSPAGE_PREFIX[] = "A.AutoTest."; const char SETTINGSGROUP[] = "Autotest"; const char TASK_MARK_ID[] = "Autotest.TaskMark"; +const char SK_USE_GLOBAL[] = "AutoTest.UseGlobal"; } // namespace Constants namespace Internal { diff --git a/src/plugins/autotest/autotestplugin.cpp b/src/plugins/autotest/autotestplugin.cpp index 65620220b94..1ef9c9489a6 100644 --- a/src/plugins/autotest/autotestplugin.cpp +++ b/src/plugins/autotest/autotestplugin.cpp @@ -26,8 +26,10 @@ #include "autotestplugin.h" #include "autotestconstants.h" #include "autotesticons.h" +#include "projectsettingswidget.h" #include "testcodeparser.h" #include "testframeworkmanager.h" +#include "testprojectsettings.h" #include "testrunner.h" #include "testsettings.h" #include "testsettingspage.h" @@ -54,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -78,6 +81,7 @@ using namespace Autotest::Internal; using namespace Core; static AutotestPlugin *s_instance = nullptr; +static QHash s_projectSettings; AutotestPlugin::AutotestPlugin() : m_settings(new TestSettings) @@ -103,6 +107,15 @@ QSharedPointer AutotestPlugin::settings() return s_instance->m_settings; } +TestProjectSettings *AutotestPlugin::projectSettings(ProjectExplorer::Project *project) +{ + auto &settings = s_projectSettings[project]; + if (!settings) + settings = new TestProjectSettings(project); + + return settings; +} + void AutotestPlugin::initializeMenuEntries() { ActionContainer *menu = ActionManager::createMenu(Constants::MENU_ID); @@ -184,13 +197,27 @@ bool AutotestPlugin::initialize(const QStringList &arguments, QString *errorStri m_navigationWidgetFactory = new TestNavigationWidgetFactory; m_resultsPane = TestResultsPane::instance(); + auto panelFactory = new ProjectExplorer::ProjectPanelFactory(); + panelFactory->setPriority(666); +// panelFactory->setIcon(); // TODO ? + panelFactory->setDisplayName(tr("Testing")); + panelFactory->setCreateWidgetFunction([](ProjectExplorer::Project *project) { + return new ProjectTestSettingsWidget(project); + }); + ProjectExplorer::ProjectPanelFactory::registerFactory(panelFactory); + m_frameworkManager->activateFrameworksFromSettings(m_settings); - TestTreeModel::instance()->syncTestFrameworks(); + TestTreeModel::instance()->scheduleTestFrameworksSync(true); connect(ProjectExplorer::SessionManager::instance(), &ProjectExplorer::SessionManager::startupProjectChanged, this, [this] { m_runconfigCache.clear(); }); + connect(ProjectExplorer::SessionManager::instance(), + &ProjectExplorer::SessionManager::aboutToRemoveProject, + this, [] (ProjectExplorer::Project *project) { + delete s_projectSettings.take(project); + }); return true; } diff --git a/src/plugins/autotest/autotestplugin.h b/src/plugins/autotest/autotestplugin.h index c846d3e0b05..881c264505f 100644 --- a/src/plugins/autotest/autotestplugin.h +++ b/src/plugins/autotest/autotestplugin.h @@ -31,13 +31,17 @@ #include -namespace ProjectExplorer { class RunConfiguration; } +namespace ProjectExplorer { +class Project; +class RunConfiguration; +} namespace Autotest { namespace Internal { class TestFrameworkManager; class TestNavigationWidgetFactory; +class TestProjectSettings; class TestResultsPane; struct TestSettings; class TestSettingsPage; @@ -67,6 +71,7 @@ public: ShutdownFlag aboutToShutdown() override; static QSharedPointer settings(); + static TestProjectSettings *projectSettings(ProjectExplorer::Project *project); static void updateMenuItemsEnabledState(); static void cacheRunConfigChoice(const QString &buildTargetKey, const ChoicePair &choice); static ChoicePair cachedChoiceFor(const QString &buildTargetKey); diff --git a/src/plugins/autotest/projectsettingswidget.cpp b/src/plugins/autotest/projectsettingswidget.cpp new file mode 100644 index 00000000000..f8263938240 --- /dev/null +++ b/src/plugins/autotest/projectsettingswidget.cpp @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "autotestplugin.h" +#include "projectsettingswidget.h" +#include "testframeworkmanager.h" +#include "testprojectsettings.h" + +#include +#include +#include +#include + +namespace Autotest { +namespace Internal { + +enum ItemDataRole { FrameworkIdRole = Qt::UserRole + 1 }; + +static QSpacerItem *createSpacer(QSizePolicy::Policy horizontal, QSizePolicy::Policy vertical) +{ + return new QSpacerItem(20, 10, horizontal, vertical); +} + +ProjectTestSettingsWidget::ProjectTestSettingsWidget(ProjectExplorer::Project *project, + QWidget *parent) + : QWidget(parent) + , m_projectSettings(AutotestPlugin::projectSettings(project)) +{ + auto verticalLayout = new QVBoxLayout(this); + m_useGlobalSettings = new QComboBox; + m_useGlobalSettings->addItem(tr("Global")); + m_useGlobalSettings->addItem(tr("Custom")); + + auto generalWidget = new QWidget; + auto groupBoxLayout = new QVBoxLayout; + m_activeFrameworks = new QTreeWidget; + m_activeFrameworks->setHeaderHidden(true); + m_activeFrameworks->setRootIsDecorated(false); + groupBoxLayout->addWidget(new QLabel(tr("Active frameworks:"))); + groupBoxLayout->addWidget(m_activeFrameworks); + generalWidget->setLayout(groupBoxLayout); + + auto horizontalLayout = new QHBoxLayout; + horizontalLayout->addWidget(m_useGlobalSettings); + horizontalLayout->addItem(createSpacer(QSizePolicy::Expanding, QSizePolicy::Minimum)); + verticalLayout->addLayout(horizontalLayout); + horizontalLayout = new QHBoxLayout; + verticalLayout->addItem(createSpacer(QSizePolicy::Minimum, QSizePolicy::Fixed)); + horizontalLayout->addWidget(generalWidget); + horizontalLayout->addItem(createSpacer(QSizePolicy::Expanding, QSizePolicy::Minimum)); + verticalLayout->addLayout(horizontalLayout); + verticalLayout->addItem(createSpacer(QSizePolicy::Minimum, QSizePolicy::Expanding)); + + m_useGlobalSettings->setCurrentIndex(m_projectSettings->useGlobalSettings() ? 0 : 1); + generalWidget->setDisabled(m_projectSettings->useGlobalSettings()); + + populateFrameworks(m_projectSettings->activeFrameworks()); + + connect(m_useGlobalSettings, QOverload::of(&QComboBox::currentIndexChanged), + this, [this, generalWidget](int index) { + generalWidget->setEnabled(index != 0); + m_projectSettings->setUseGlobalSettings(index == 0); + }); + connect(m_activeFrameworks, &QTreeWidget::itemChanged, + this, &ProjectTestSettingsWidget::onActiveFrameworkChanged); +} + +void ProjectTestSettingsWidget::populateFrameworks(const QMap &frameworks) +{ + TestFrameworkManager *frameworkManager = TestFrameworkManager::instance(); + auto end = frameworks.cend(); + for (auto it = frameworks.cbegin(); it != end; ++it) { + auto *item = new QTreeWidgetItem(m_activeFrameworks, + QStringList(frameworkManager->frameworkNameForId(it.key()))); + item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable); + item->setCheckState(0, it.value() ? Qt::Checked : Qt::Unchecked); + item->setData(0, FrameworkIdRole, it.key().toSetting()); + } +} + +void ProjectTestSettingsWidget::onActiveFrameworkChanged(QTreeWidgetItem *item, int column) +{ + auto id = Core::Id::fromSetting(item->data(column, FrameworkIdRole)); + m_projectSettings->activateFramework(id, item->data(0, Qt::CheckStateRole) == Qt::Checked); +} + +} // namespace Internal +} // namespace Autotest diff --git a/src/plugins/autotest/projectsettingswidget.h b/src/plugins/autotest/projectsettingswidget.h new file mode 100644 index 00000000000..2424f9138ba --- /dev/null +++ b/src/plugins/autotest/projectsettingswidget.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include + +QT_BEGIN_NAMESPACE +class QComboBox; +class QTreeWidget; +class QTreeWidgetItem; +QT_END_NAMESPACE + +namespace Core { class Id; } +namespace ProjectExplorer { class Project; } + +namespace Autotest { +namespace Internal { + +class TestProjectSettings; + +class ProjectTestSettingsWidget : public QWidget +{ + Q_OBJECT +public: + explicit ProjectTestSettingsWidget(ProjectExplorer::Project *project, + QWidget *parent = nullptr); +private: + void populateFrameworks(const QMap &frameworks); + void onActiveFrameworkChanged(QTreeWidgetItem *item, int column); + TestProjectSettings *m_projectSettings; + QComboBox *m_useGlobalSettings = nullptr; + QTreeWidget *m_activeFrameworks = nullptr; +}; + +} // namespace Internal +} // namespace Autotest diff --git a/src/plugins/autotest/testprojectsettings.cpp b/src/plugins/autotest/testprojectsettings.cpp new file mode 100644 index 00000000000..07c8d3125a0 --- /dev/null +++ b/src/plugins/autotest/testprojectsettings.cpp @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "testprojectsettings.h" +#include "autotestconstants.h" +#include "testframeworkmanager.h" + +#include +#include + +namespace Autotest { +namespace Internal { + +static const char SK_ACTIVE_FRAMEWORKS[] = "AutoTest.ActiveFrameworks"; + +TestProjectSettings::TestProjectSettings(ProjectExplorer::Project *project) + : m_project(project) +{ + load(); + connect(project, &ProjectExplorer::Project::settingsLoaded, + this, &TestProjectSettings::load); + connect(project, &ProjectExplorer::Project::aboutToSaveSettings, + this, &TestProjectSettings::save); +} + +TestProjectSettings::~TestProjectSettings() +{ + save(); +} + +void TestProjectSettings::setUseGlobalSettings(bool useGlobal) +{ + if (m_useGlobalSettings == useGlobal) + return; + m_useGlobalSettings = useGlobal; + TestTreeModel::instance()->scheduleTestFrameworksSync(false); +} + +void TestProjectSettings::activateFramework(const Core::Id &id, bool activate) +{ + if (m_activeTestFrameworks.value(id) != activate) { + m_activeTestFrameworks[id] = activate; + TestTreeModel::instance()->scheduleTestFrameworksSync(false); + } +} + +void TestProjectSettings::load() +{ + const QVariant useGlobal = m_project->namedSettings(Constants::SK_USE_GLOBAL); + m_useGlobalSettings = useGlobal.isValid() ? useGlobal.toBool() : true; + + TestFrameworkManager *frameworkManager = TestFrameworkManager::instance(); + const QList registered = frameworkManager->sortedRegisteredFrameworkIds(); + const QVariant activeFrameworks = m_project->namedSettings(SK_ACTIVE_FRAMEWORKS); + + m_activeTestFrameworks.clear(); + if (activeFrameworks.isValid()) { + const QMap frameworksMap = activeFrameworks.toMap(); + for (const Core::Id &id : registered) { + const QString idStr = id.toString(); + bool active = frameworksMap.value(idStr, frameworkManager->isActive(id)).toBool(); + m_activeTestFrameworks.insert(id, active); + } + } else { + for (const Core::Id &id : registered) + m_activeTestFrameworks.insert(id, frameworkManager->isActive(id)); + } +} + +void TestProjectSettings::save() +{ + m_project->setNamedSettings(Constants::SK_USE_GLOBAL, m_useGlobalSettings); + QVariantMap activeFrameworks; + auto end = m_activeTestFrameworks.cend(); + for (auto it = m_activeTestFrameworks.cbegin(); it != end; ++it) + activeFrameworks.insert(it.key().toString(), it.value()); + m_project->setNamedSettings(SK_ACTIVE_FRAMEWORKS, activeFrameworks); +} + +} // namespace Internal +} // namespace Autotest diff --git a/src/plugins/autotest/testprojectsettings.h b/src/plugins/autotest/testprojectsettings.h new file mode 100644 index 00000000000..1c3d5f2f0df --- /dev/null +++ b/src/plugins/autotest/testprojectsettings.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include + +namespace Autotest { +namespace Internal { + +class TestProjectSettings : public QObject +{ + Q_OBJECT +public: + TestProjectSettings(ProjectExplorer::Project *project); + ~TestProjectSettings(); + + void setUseGlobalSettings(bool useGlobal); + bool useGlobalSettings() const { return m_useGlobalSettings; } + void setActiveFrameworks(const QMap enabledFrameworks) + { m_activeTestFrameworks = enabledFrameworks; } + QMap activeFrameworks() const { return m_activeTestFrameworks; } + void activateFramework(const Core::Id &id, bool activate); +private: + void load(); + void save(); + + ProjectExplorer::Project *m_project; + bool m_useGlobalSettings = true; + QMap m_activeTestFrameworks; +}; + +} // namespace Internal +} // namespace Autotest diff --git a/src/plugins/autotest/testsettingspage.cpp b/src/plugins/autotest/testsettingspage.cpp index 169bab7320c..505c30b7541 100644 --- a/src/plugins/autotest/testsettingspage.cpp +++ b/src/plugins/autotest/testsettingspage.cpp @@ -165,7 +165,6 @@ void TestSettingsPage::apply() if (!m_widget) // page was not shown at all return; const TestSettings newSettings = m_widget->settings(); - bool frameworkSyncNecessary = newSettings.frameworks != m_settings->frameworks; const QList changedIds = Utils::filtered(newSettings.frameworksGrouping.keys(), [newSettings, this] (const Core::Id &id) { return newSettings.frameworksGrouping[id] != m_settings->frameworksGrouping[id]; @@ -174,9 +173,8 @@ void TestSettingsPage::apply() m_settings->toSettings(Core::ICore::settings()); TestFrameworkManager *frameworkManager = TestFrameworkManager::instance(); frameworkManager->activateFrameworksFromSettings(m_settings); - if (frameworkSyncNecessary) - TestTreeModel::instance()->syncTestFrameworks(); - else if (!changedIds.isEmpty()) + TestTreeModel::instance()->scheduleTestFrameworksSync(true); + if (!changedIds.isEmpty()) TestTreeModel::instance()->rebuild(changedIds); } diff --git a/src/plugins/autotest/testtreemodel.cpp b/src/plugins/autotest/testtreemodel.cpp index cb58de73ea0..4f7f3524ce3 100644 --- a/src/plugins/autotest/testtreemodel.cpp +++ b/src/plugins/autotest/testtreemodel.cpp @@ -27,6 +27,7 @@ #include "autotestplugin.h" #include "testcodeparser.h" #include "testframeworkmanager.h" +#include "testprojectsettings.h" #include "testsettings.h" #include "testtreeitem.h" #include "testtreemodel.h" @@ -53,6 +54,11 @@ TestTreeModel::TestTreeModel(QObject *parent) : this, &TestTreeModel::sweep, Qt::QueuedConnection); connect(m_parser, &TestCodeParser::parsingFailed, this, &TestTreeModel::sweep, Qt::QueuedConnection); + + connect(ProjectExplorer::SessionManager::instance(), + &ProjectExplorer::SessionManager::startupProjectChanged, + this, &TestTreeModel::onStartupProjectChanged); + connect(&m_syncFrameworksTimer, &QTimer::timeout, this, &TestTreeModel::syncTestFrameworks); setupParsingConnections(); } @@ -200,13 +206,55 @@ QList TestTreeModel::testItemsByName(const QString &testName) void TestTreeModel::syncTestFrameworks() { + ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); + if (!project) + return; + + QList sortedIds; + TestFrameworkManager *frameworkManager = TestFrameworkManager::instance(); + const QVariant useGlobal = project->namedSettings(Constants::SK_USE_GLOBAL); + if (!useGlobal.isValid() || AutotestPlugin::projectSettings(project)->useGlobalSettings()) { + sortedIds = frameworkManager->sortedActiveFrameworkIds(); + } else { // we've got custom project settings + const TestProjectSettings *settings = AutotestPlugin::projectSettings(project); + const QMap active = settings->activeFrameworks(); + sortedIds = Utils::filtered(active.keys(), [active](const Core::Id &id) { + return active.value(id); + }); + } + + syncFrameworks(sortedIds); +} + +void TestTreeModel::scheduleTestFrameworksSync(bool immediately) +{ + m_syncFrameworksTimer.start(immediately ? 0 : 3000); +} + +void TestTreeModel::syncFrameworks(const QList &sortedIds) +{ + TestFrameworkManager *manager = TestFrameworkManager::instance(); + // pre-check to avoid further processing when frameworks are unchanged + Utils::TreeItem *invisibleRoot = rootItem(); + const int count = invisibleRoot->childCount(); + if (count == sortedIds.size()) { + bool different = false; + QList registered = manager->sortedRegisteredFrameworkIds(); + for (int i = 0; i < count; ++i) { + if (manager->rootNodeForTestFramework(sortedIds[i]) != invisibleRoot->childAt(i)) { + different = true; + break; + } + } + if (!different) + return; + } + // remove all currently registered removeTestRootNodes(); - TestFrameworkManager *frameworkManager = TestFrameworkManager::instance(); - QList sortedIds = frameworkManager->sortedActiveFrameworkIds(); for (const Core::Id &id : sortedIds) - rootItem()->appendChild(frameworkManager->rootNodeForTestFramework(id)); + rootItem()->appendChild(manager->rootNodeForTestFramework(id)); m_parser->syncTestFrameworks(sortedIds); emit updatedActiveFrameworks(sortedIds.size()); @@ -424,6 +472,12 @@ void TestTreeModel::onParseResultReady(const TestParseResultPtr result) handleParseResult(result.data(), rootNode); } +void TestTreeModel::onStartupProjectChanged() +{ + m_syncFrameworksTimer.stop(); + scheduleTestFrameworksSync(true); +} + void TestTreeModel::handleParseResult(const TestParseResult *result, TestTreeItem *parentNode) { const bool groupingEnabled = diff --git a/src/plugins/autotest/testtreemodel.h b/src/plugins/autotest/testtreemodel.h index 895a9a582e4..18aac51d6bf 100644 --- a/src/plugins/autotest/testtreemodel.h +++ b/src/plugins/autotest/testtreemodel.h @@ -33,6 +33,7 @@ #include #include +#include namespace Autotest { namespace Internal { @@ -58,7 +59,7 @@ public: QList getSelectedTests() const; QList getTestsForFile(const Utils::FilePath &fileName) const; QList testItemsByName(const QString &testName); - void syncTestFrameworks(); + void scheduleTestFrameworksSync(bool immediately); void rebuild(const QList &frameworkIds); #ifdef WITH_TESTS @@ -87,6 +88,7 @@ signals: private: void onParseResultReady(const TestParseResultPtr result); + void onStartupProjectChanged(); void handleParseResult(const TestParseResult *result, TestTreeItem *rootNode); void removeAllTestItems(); void removeTestRootNodes(); @@ -97,9 +99,12 @@ private: explicit TestTreeModel(QObject *parent = nullptr); void setupParsingConnections(); void filterAndInsert(TestTreeItem *item, TestTreeItem *root, bool groupingEnabled); + void syncTestFrameworks(); + void syncFrameworks(const QList &sortedIds); QList testItemsByName(TestTreeItem *root, const QString &testName); TestCodeParser *m_parser; + QTimer m_syncFrameworksTimer; }; class TestTreeSortFilterModel : public QSortFilterProxyModel