From 4c1b3c863cdf90f8df62a11de31acfec03ed39e0 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Thu, 1 Dec 2022 15:34:21 +0100 Subject: [PATCH] ProjectExplorer: Add "Generate" sub-menu to build menu Preparation for adding more generators. Task-number: QTCREATORBUG-28149 Change-Id: I4afa183a6fbd8ee88fc978b382f28cf9e52f09e9 Reviewed-by: Christian Stenger --- .../clangcodemodel/clangcodemodelplugin.cpp | 53 ++++++++++--------- .../clangcodemodel/clangcodemodelplugin.h | 2 +- src/plugins/projectexplorer/project.cpp | 23 ++++++++ src/plugins/projectexplorer/project.h | 5 ++ .../projectexplorer/projectexplorer.cpp | 19 +++++++ 5 files changed, 76 insertions(+), 26 deletions(-) diff --git a/src/plugins/clangcodemodel/clangcodemodelplugin.cpp b/src/plugins/clangcodemodel/clangcodemodelplugin.cpp index c3933bd6821..aa418c0e3a0 100644 --- a/src/plugins/clangcodemodel/clangcodemodelplugin.cpp +++ b/src/plugins/clangcodemodel/clangcodemodelplugin.cpp @@ -68,15 +68,6 @@ void ClangCodeModelPlugin::generateCompilationDB() m_generatorWatcher.setFuture(task); } -static bool isDBGenerationEnabled(ProjectExplorer::Project *project) -{ - using namespace CppEditor; - if (!project) - return false; - const ProjectInfo::ConstPtr projectInfo = CppModelManager::instance()->projectInfo(project); - return projectInfo && !projectInfo->projectParts().isEmpty(); -} - ClangCodeModelPlugin::~ClangCodeModelPlugin() { m_generatorWatcher.waitForFinished(); @@ -98,31 +89,25 @@ bool ClangCodeModelPlugin::initialize(const QStringList &arguments, QString *err CppEditor::CppModelManager::instance()->activateClangCodeModel( std::make_unique()); - createCompilationDBButton(); + createCompilationDBAction(); return true; } -void ClangCodeModelPlugin::createCompilationDBButton() +void ClangCodeModelPlugin::createCompilationDBAction() { - Core::ActionContainer *mbuild = - Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_BUILDPROJECT); // generate compile_commands.json m_generateCompilationDBAction = new ParameterAction( tr("Generate Compilation Database"), tr("Generate Compilation Database for \"%1\""), ParameterAction::AlwaysEnabled, this); - ProjectExplorer::Project *startupProject = ProjectExplorer::SessionManager::startupProject(); - m_generateCompilationDBAction->setEnabled(isDBGenerationEnabled(startupProject)); if (startupProject) m_generateCompilationDBAction->setParameter(startupProject->displayName()); - Core::Command *command = Core::ActionManager::registerAction(m_generateCompilationDBAction, Constants::GENERATE_COMPILATION_DB); command->setAttribute(Core::Command::CA_UpdateText); command->setDescription(m_generateCompilationDBAction->text()); - mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_BUILD); connect(&m_generatorWatcher, &QFutureWatcher::finished, this, [this] { @@ -135,13 +120,28 @@ void ClangCodeModelPlugin::createCompilationDBButton() message = tr("Generating Clang compilation database failed: %1").arg(result.error); } Core::MessageManager::writeFlashing(message); - m_generateCompilationDBAction->setEnabled( - isDBGenerationEnabled(ProjectExplorer::SessionManager::startupProject())); + m_generateCompilationDBAction->setEnabled(true); }); connect(m_generateCompilationDBAction, &QAction::triggered, this, [this] { - if (!m_generateCompilationDBAction->isEnabled()) + if (!m_generateCompilationDBAction->isEnabled()) { + Core::MessageManager::writeDisrupting("Cannot generate compilation database: " + "Generator is already running."); return; - + } + ProjectExplorer::Project * const project + = ProjectExplorer::SessionManager::startupProject(); + if (!project) { + Core::MessageManager::writeDisrupting("Cannot generate compilation database: " + "No active project."); + return; + } + const CppEditor::ProjectInfo::ConstPtr projectInfo = CppEditor::CppModelManager::instance() + ->projectInfo(project); + if (!projectInfo || projectInfo->projectParts().isEmpty()) { + Core::MessageManager::writeDisrupting("Cannot generate compilation database: " + "Project has no C/C++ project parts."); + return; + } m_generateCompilationDBAction->setEnabled(false); generateCompilationDB(); }); @@ -150,16 +150,12 @@ void ClangCodeModelPlugin::createCompilationDBButton() if (project != ProjectExplorer::SessionManager::startupProject()) return; m_generateCompilationDBAction->setParameter(project->displayName()); - if (!m_generatorWatcher.isRunning()) - m_generateCompilationDBAction->setEnabled(isDBGenerationEnabled(project)); }); connect(ProjectExplorer::SessionManager::instance(), &ProjectExplorer::SessionManager::startupProjectChanged, this, [this](ProjectExplorer::Project *project) { m_generateCompilationDBAction->setParameter(project ? project->displayName() : ""); - if (!m_generatorWatcher.isRunning()) - m_generateCompilationDBAction->setEnabled(isDBGenerationEnabled(project)); }); connect(ProjectExplorer::SessionManager::instance(), &ProjectExplorer::SessionManager::projectDisplayNameChanged, @@ -169,6 +165,13 @@ void ClangCodeModelPlugin::createCompilationDBButton() return; m_generateCompilationDBAction->setParameter(project->displayName()); }); + connect(ProjectExplorer::SessionManager::instance(), + &ProjectExplorer::SessionManager::projectAdded, this, + [this](ProjectExplorer::Project *project) { + project->registerGenerator(Constants::GENERATE_COMPILATION_DB, + m_generateCompilationDBAction->text(), + [this] { m_generateCompilationDBAction->trigger(); }); + }); } // For e.g. creation of profile-guided optimization builds. diff --git a/src/plugins/clangcodemodel/clangcodemodelplugin.h b/src/plugins/clangcodemodel/clangcodemodelplugin.h index f44b51c8236..3a50df3baea 100644 --- a/src/plugins/clangcodemodel/clangcodemodelplugin.h +++ b/src/plugins/clangcodemodel/clangcodemodelplugin.h @@ -28,7 +28,7 @@ private: private: void generateCompilationDB(); - void createCompilationDBButton(); + void createCompilationDBAction(); Utils::ParameterAction *m_generateCompilationDBAction = nullptr; QFutureWatcher m_generatorWatcher; diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp index c5667920a54..8a4b2eeb7b1 100644 --- a/src/plugins/projectexplorer/project.cpp +++ b/src/plugins/projectexplorer/project.cpp @@ -40,6 +40,7 @@ #include #include +#include #include @@ -178,6 +179,7 @@ public: Context m_projectLanguages; QVariantMap m_pluginSettings; std::unique_ptr m_accessor; + QHash>> m_generators; QString m_displayName; @@ -1054,6 +1056,27 @@ bool Project::isEditModePreferred() const return true; } +void Project::registerGenerator(Utils::Id id, const QString &displayName, + const std::function &runner) +{ + d->m_generators.insert(id, qMakePair(displayName, runner)); +} + +const QList> Project::allGenerators() const +{ + QList> generators; + for (auto it = d->m_generators.cbegin(); it != d->m_generators.cend(); ++it) + generators << qMakePair(it.key(), it.value().first); + return generators; +} + +void Project::runGenerator(Utils::Id id) +{ + const auto it = d->m_generators.constFind(id); + if (it != d->m_generators.constEnd()) + it.value().second(); +} + #if defined(WITH_TESTS) static FilePath constructTestPath(const QString &basePath) diff --git a/src/plugins/projectexplorer/project.h b/src/plugins/projectexplorer/project.h index 1868ea50256..e0b17984073 100644 --- a/src/plugins/projectexplorer/project.h +++ b/src/plugins/projectexplorer/project.h @@ -162,6 +162,11 @@ public: virtual bool isEditModePreferred() const; + void registerGenerator(Utils::Id id, const QString &displayName, + const std::function &runner); + const QList> allGenerators() const; + void runGenerator(Utils::Id id); + signals: void projectFileIsDirty(const Utils::FilePath &path); diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index 75cf8aea01f..766d48429c0 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -239,6 +239,7 @@ const int P_ACTION_BUILDPROJECT = 80; const char M_RECENTPROJECTS[] = "ProjectExplorer.Menu.Recent"; const char M_UNLOADPROJECTS[] = "ProjectExplorer.Menu.Unload"; const char M_SESSION[] = "ProjectExplorer.Menu.Session"; +const char M_GENERATORS[] = "ProjectExplorer.Menu.Generators"; const char RUNMENUCONTEXTMENU[] = "Project.RunMenu"; const char FOLDER_OPEN_LOCATIONS_CONTEXT_MENU[] = "Project.F.OpenLocation.CtxMenu"; @@ -1339,6 +1340,24 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er cmd->setDescription(dd->m_buildForRunConfigAction->text()); mbuild->addAction(cmd, Constants::G_BUILD_BUILD); + // Generators + ActionContainer * const generatorContainer + = ActionManager::createMenu(Id(Constants::M_GENERATORS)); + generatorContainer->setOnAllDisabledBehavior(ActionContainer::Show); + generatorContainer->menu()->setTitle(tr("Run Generator")); + mbuild->addMenu(generatorContainer, Constants::G_BUILD_BUILD); + connect(generatorContainer->menu(), &QMenu::aboutToShow, [menu = generatorContainer->menu()] { + menu->clear(); + if (Project * const project = SessionManager::startupProject()) { + for (const auto &generator : project->allGenerators()) { + menu->addAction(generator.second, [project, id = generator.first] { + project->runGenerator(id); + }); + menu->show(); + } + } + }); + // deploy action dd->m_deployAction = new QAction(tr("Deploy"), this); dd->m_deployAction->setWhatsThis(tr("Deploy Project"));