ProjectExplorer: Add "Generate" sub-menu to build menu

Preparation for adding more generators.

Task-number: QTCREATORBUG-28149
Change-Id: I4afa183a6fbd8ee88fc978b382f28cf9e52f09e9
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
Christian Kandeler
2022-12-01 15:34:21 +01:00
parent 6d8f6ab395
commit 4c1b3c863c
5 changed files with 76 additions and 26 deletions

View File

@@ -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<ClangModelManagerSupport>());
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<GenerateCompilationDbResult>::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.

View File

@@ -28,7 +28,7 @@ private:
private:
void generateCompilationDB();
void createCompilationDBButton();
void createCompilationDBAction();
Utils::ParameterAction *m_generateCompilationDBAction = nullptr;
QFutureWatcher<GenerateCompilationDbResult> m_generatorWatcher;

View File

@@ -40,6 +40,7 @@
#include <utils/stringutils.h>
#include <QFileDialog>
#include <QHash>
#include <limits>
@@ -178,6 +179,7 @@ public:
Context m_projectLanguages;
QVariantMap m_pluginSettings;
std::unique_ptr<Internal::UserFileAccessor> m_accessor;
QHash<Id, QPair<QString, std::function<void()>>> 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<void ()> &runner)
{
d->m_generators.insert(id, qMakePair(displayName, runner));
}
const QList<QPair<Id, QString>> Project::allGenerators() const
{
QList<QPair<Id, QString>> 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)

View File

@@ -162,6 +162,11 @@ public:
virtual bool isEditModePreferred() const;
void registerGenerator(Utils::Id id, const QString &displayName,
const std::function<void()> &runner);
const QList<QPair<Utils::Id, QString>> allGenerators() const;
void runGenerator(Utils::Id id);
signals:
void projectFileIsDirty(const Utils::FilePath &path);

View File

@@ -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"));