forked from qt-creator/qt-creator
ProjectExplorer: Add "build for current run config" menu entry
This lets users build the executable corresponding to the currently active run configuration. It's functionally equivalent to locating the corresponding node in the project tree and choosing "Build" from the context menu. Fixes: QTCREATORBUG-22403 Change-Id: Ic2b729c7ce17f1ad944dc06746bb9d6db90b6c61 Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -87,6 +87,7 @@ CMakeProject::CMakeProject(const FilePath &fileName) : Project(Constants::CMAKEM
|
||||
setId(CMakeProjectManager::Constants::CMAKEPROJECT_ID);
|
||||
setProjectLanguages(Core::Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID));
|
||||
setDisplayName(projectDirectory().fileName());
|
||||
setCanBuildProducts();
|
||||
|
||||
// Timer:
|
||||
m_delayedParsingTimer.setSingleShot(true);
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#include "cmakeprojectnodes.h"
|
||||
|
||||
#include "cmakeconfigitem.h"
|
||||
#include "cmakeproject.h"
|
||||
#include "cmakeprojectconstants.h"
|
||||
#include "cmakeprojectplugin.h"
|
||||
|
||||
@@ -264,6 +265,11 @@ Utils::optional<Utils::FilePath> CMakeTargetNode::visibleAfterAddFileAction() co
|
||||
return filePath().pathAppended("CMakeLists.txt");
|
||||
}
|
||||
|
||||
void CMakeTargetNode::build()
|
||||
{
|
||||
static_cast<CMakeProject *>(getProject())->buildCMakeTarget(displayName());
|
||||
}
|
||||
|
||||
void CMakeTargetNode::setTargetInformation(const QList<Utils::FilePath> &artifacts,
|
||||
const QString &type)
|
||||
{
|
||||
|
@@ -76,6 +76,8 @@ public:
|
||||
bool addFiles(const QStringList &filePaths, QStringList *notAdded) override;
|
||||
Utils::optional<Utils::FilePath> visibleAfterAddFileAction() const override;
|
||||
|
||||
void build() override;
|
||||
|
||||
QVariant data(Core::Id role) const override;
|
||||
void setConfig(const CMakeConfig &config);
|
||||
|
||||
|
@@ -164,6 +164,7 @@ public:
|
||||
bool m_isParsing = false;
|
||||
bool m_hasParsingData = false;
|
||||
bool m_needsInitialExpansion = false;
|
||||
bool m_canBuildProducts = false;
|
||||
std::unique_ptr<Core::IDocument> m_document;
|
||||
std::unique_ptr<ProjectNode> m_rootProjectNode;
|
||||
std::unique_ptr<ContainerNode> m_containerNode;
|
||||
@@ -227,6 +228,11 @@ QString Project::mimeType() const
|
||||
return document()->mimeType();
|
||||
}
|
||||
|
||||
bool Project::canBuildProducts() const
|
||||
{
|
||||
return d->m_canBuildProducts;
|
||||
}
|
||||
|
||||
Core::IDocument *Project::document() const
|
||||
{
|
||||
QTC_CHECK(d->m_document);
|
||||
@@ -938,6 +944,11 @@ void Project::setRequiredKitPredicate(const Kit::Predicate &predicate)
|
||||
d->m_requiredKitPredicate = predicate;
|
||||
}
|
||||
|
||||
void Project::setCanBuildProducts()
|
||||
{
|
||||
d->m_canBuildProducts = true;
|
||||
}
|
||||
|
||||
Kit::Predicate Project::preferredKitPredicate() const
|
||||
{
|
||||
return d->m_preferredKitPredicate;
|
||||
|
@@ -99,6 +99,7 @@ public:
|
||||
Core::Id id() const;
|
||||
|
||||
QString mimeType() const;
|
||||
bool canBuildProducts() const;
|
||||
|
||||
Core::IDocument *document() const;
|
||||
Utils::FilePath projectFilePath() const;
|
||||
@@ -249,6 +250,8 @@ protected:
|
||||
// The predicate used to select kits available in TargetSetupPage.
|
||||
void setRequiredKitPredicate(const Kit::Predicate &predicate);
|
||||
|
||||
void setCanBuildProducts();
|
||||
|
||||
void setId(Core::Id id);
|
||||
void setRootProjectNode(std::unique_ptr<ProjectNode> &&root); // takes ownership!
|
||||
void setProjectLanguages(Core::Context language);
|
||||
|
@@ -420,6 +420,7 @@ public:
|
||||
QAction *m_closeAllProjects;
|
||||
QAction *m_buildProjectOnlyAction;
|
||||
Utils::ParameterAction *m_buildAction;
|
||||
Utils::ParameterAction *m_buildForRunConfigAction;
|
||||
Utils::ProxyAction *m_modeBarBuildAction;
|
||||
QAction *m_buildActionContextMenu;
|
||||
QAction *m_buildDependenciesActionContextMenu;
|
||||
@@ -1043,6 +1044,17 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
|
||||
dd->m_modeBarBuildAction->setAction(cmd->action());
|
||||
ModeManager::addAction(dd->m_modeBarBuildAction, Constants::P_ACTION_BUILDPROJECT);
|
||||
|
||||
// build for run config
|
||||
dd->m_buildForRunConfigAction = new Utils::ParameterAction(
|
||||
tr("Build for Run Configuration"), tr("Build for Run Configuration \"%1\""),
|
||||
Utils::ParameterAction::EnabledWithParameter, this);
|
||||
dd->m_buildForRunConfigAction->setIcon(buildIcon);
|
||||
cmd = ActionManager::registerAction(dd->m_buildForRunConfigAction,
|
||||
"ProjectExplorer.BuildForRunConfig");
|
||||
cmd->setAttribute(Command::CA_UpdateText);
|
||||
cmd->setDescription(dd->m_buildForRunConfigAction->text());
|
||||
mbuild->addAction(cmd, Constants::G_BUILD_BUILD);
|
||||
|
||||
// deploy action
|
||||
dd->m_deployAction = new Utils::ParameterAction(tr("Deploy Project"), tr("Deploy Project \"%1\""),
|
||||
Utils::ParameterAction::AlwaysEnabled, this);
|
||||
@@ -1391,6 +1403,21 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
|
||||
connect(dd->m_buildActionContextMenu, &QAction::triggered, dd, [] {
|
||||
dd->queue({ ProjectTree::currentProject() }, { Id(Constants::BUILDSTEPS_BUILD) });
|
||||
});
|
||||
connect(dd->m_buildForRunConfigAction, &QAction::triggered, dd, [] {
|
||||
const Project * const project = SessionManager::startupProject();
|
||||
QTC_ASSERT(project, return);
|
||||
const Target * const target = project->activeTarget();
|
||||
QTC_ASSERT(target, return);
|
||||
const RunConfiguration * const runConfig = target->activeRunConfiguration();
|
||||
QTC_ASSERT(runConfig, return);
|
||||
const auto buildKeyMatcher = [runConfig](const ProjectNode *candidate) {
|
||||
return candidate->buildKey() == runConfig->buildKey();
|
||||
};
|
||||
ProjectNode * const productNode
|
||||
= project->rootProjectNode()->findProjectNode(buildKeyMatcher);
|
||||
QTC_ASSERT(productNode->isProduct(), return);
|
||||
productNode->build();
|
||||
});
|
||||
connect(dd->m_buildDependenciesActionContextMenu, &QAction::triggered, dd, [] {
|
||||
dd->queue(SessionManager::projectOrder(ProjectTree::currentProject()),
|
||||
{ Id(Constants::BUILDSTEPS_BUILD) });
|
||||
@@ -2436,8 +2463,13 @@ void ProjectExplorerPluginPrivate::updateActions()
|
||||
? Icons::CANCELBUILD_FLAT.icon()
|
||||
: buildAction->icon());
|
||||
|
||||
const RunConfiguration * const runConfig = project && project->activeTarget()
|
||||
? project->activeTarget()->activeRunConfiguration() : nullptr;
|
||||
|
||||
// Normal actions
|
||||
m_buildAction->setParameter(projectName);
|
||||
if (runConfig)
|
||||
m_buildForRunConfigAction->setParameter(runConfig->displayName());
|
||||
m_rebuildAction->setParameter(projectName);
|
||||
m_cleanAction->setParameter(projectName);
|
||||
|
||||
@@ -2445,6 +2477,11 @@ void ProjectExplorerPluginPrivate::updateActions()
|
||||
m_rebuildAction->setEnabled(buildActionState.first);
|
||||
m_cleanAction->setEnabled(buildActionState.first);
|
||||
|
||||
// The last condition is there to prevent offering this action for custom run configurations.
|
||||
m_buildForRunConfigAction->setEnabled(buildActionState.first
|
||||
&& runConfig && project->canBuildProducts()
|
||||
&& !runConfig->buildTargetInfo().projectFilePath.isEmpty());
|
||||
|
||||
m_buildAction->setToolTip(buildActionState.second);
|
||||
m_rebuildAction->setToolTip(buildActionState.second);
|
||||
m_cleanAction->setToolTip(buildActionState.second);
|
||||
@@ -2935,6 +2972,7 @@ void ProjectExplorerPluginPrivate::activeRunConfigurationChanged()
|
||||
rc = startupProject->activeTarget()->activeRunConfiguration();
|
||||
if (rc == previousRunConfiguration)
|
||||
return;
|
||||
updateActions();
|
||||
emit m_instance->updateRunActions();
|
||||
}
|
||||
|
||||
|
@@ -212,6 +212,15 @@ const ProjectNode *Node::managingProject() const
|
||||
return const_cast<Node *>(this)->managingProject();
|
||||
}
|
||||
|
||||
Project *Node::getProject() const
|
||||
{
|
||||
if (const ContainerNode * const cn = asContainerNode())
|
||||
return cn->project();
|
||||
if (!m_parentFolderNode)
|
||||
return nullptr;
|
||||
return m_parentFolderNode->getProject();
|
||||
}
|
||||
|
||||
/*!
|
||||
The path of the file or folder in the filesystem the node represents.
|
||||
*/
|
||||
|
@@ -121,6 +121,8 @@ public:
|
||||
// or node->parentProjectNode() for all other cases.
|
||||
const ProjectNode *managingProject() const; // see above.
|
||||
|
||||
Project *getProject() const;
|
||||
|
||||
const Utils::FilePath &filePath() const; // file system path
|
||||
int line() const;
|
||||
virtual QString displayName() const;
|
||||
@@ -359,6 +361,13 @@ public:
|
||||
|
||||
bool isProduct() const { return m_isProduct; }
|
||||
|
||||
// TODO: Currently used only for "Build for current run config" functionality, but we should
|
||||
// probably use it to centralize the node-specific "Build" functionality that
|
||||
// currently each project manager plugin adds to the context menu by itself.
|
||||
// The function should then move up to the Node class, so it can also serve the
|
||||
// "build single file" case.
|
||||
virtual void build() {}
|
||||
|
||||
protected:
|
||||
void setIsProduct() { m_isProduct = true; }
|
||||
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#include "qbsnodetreebuilder.h"
|
||||
#include "qbsproject.h"
|
||||
#include "qbsprojectmanagerconstants.h"
|
||||
#include "qbsprojectmanagerplugin.h"
|
||||
#include "qbsrunconfiguration.h"
|
||||
|
||||
#include <android/androidconstants.h>
|
||||
@@ -391,6 +392,12 @@ bool QbsProductNode::renameFile(const QString &filePath, const QString &newFileP
|
||||
return prjNode->project()->renameFileInProduct(filePath, newFilePath, m_qbsProductData, grp);
|
||||
}
|
||||
|
||||
void QbsProductNode::build()
|
||||
{
|
||||
QbsProjectManagerPlugin::buildNamedProduct(static_cast<QbsProject *>(getProject()),
|
||||
QbsProject::uniqueProductName(qbsProductData()));
|
||||
}
|
||||
|
||||
QStringList QbsProductNode::targetApplications() const
|
||||
{
|
||||
return QStringList{m_qbsProductData.targetExecutable()};
|
||||
|
@@ -70,6 +70,7 @@ public:
|
||||
bool addFiles(const QStringList &filePaths, QStringList *notAdded = nullptr) override;
|
||||
bool removeFiles(const QStringList &filePaths, QStringList *notRemoved = nullptr) override;
|
||||
bool renameFile(const QString &filePath, const QString &newFilePath) override;
|
||||
void build() override;
|
||||
QStringList targetApplications() const override;
|
||||
|
||||
QString buildKey() const override;
|
||||
|
@@ -129,6 +129,7 @@ QbsProject::QbsProject(const FilePath &fileName) :
|
||||
|
||||
setId(Constants::PROJECT_ID);
|
||||
setProjectLanguages(Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID));
|
||||
setCanBuildProducts();
|
||||
|
||||
rebuildProjectTree();
|
||||
|
||||
|
@@ -578,5 +578,11 @@ void QbsProjectManagerPlugin::reparseProject(QbsProject *project)
|
||||
project->parseCurrentBuildConfiguration();
|
||||
}
|
||||
|
||||
void QbsProjectManagerPlugin::buildNamedProduct(QbsProject *project, const QString &product)
|
||||
{
|
||||
QbsProjectManagerPlugin::runStepsForProducts(project, QStringList(product),
|
||||
{Core::Id(ProjectExplorer::Constants::BUILDSTEPS_BUILD)});
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace QbsProjectManager
|
||||
|
@@ -42,6 +42,10 @@ class QbsProjectManagerPlugin : public ExtensionSystem::IPlugin
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "QbsProjectManager.json")
|
||||
|
||||
public:
|
||||
static void buildNamedProduct(QbsProject *project, const QString &product);
|
||||
|
||||
private:
|
||||
~QbsProjectManagerPlugin() final;
|
||||
|
||||
bool initialize(const QStringList &arguments, QString *errorMessage) final;
|
||||
@@ -77,8 +81,8 @@ class QbsProjectManagerPlugin : public ExtensionSystem::IPlugin
|
||||
const QStringList &activeFileTags);
|
||||
void buildSingleFile(QbsProject *project, const QString &file);
|
||||
|
||||
void runStepsForProducts(QbsProject *project, const QStringList &products,
|
||||
const QList<Core::Id> &stepTypes);
|
||||
static void runStepsForProducts(QbsProject *project, const QStringList &products,
|
||||
const QList<Core::Id> &stepTypes);
|
||||
|
||||
QbsProjectManagerPluginPrivate *d = nullptr;
|
||||
QAction *m_reparseQbs = nullptr;
|
||||
|
@@ -24,7 +24,9 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "qmakenodes.h"
|
||||
|
||||
#include "qmakeproject.h"
|
||||
#include "qmakeprojectmanager.h"
|
||||
|
||||
#include <projectexplorer/buildconfiguration.h>
|
||||
#include <projectexplorer/runconfiguration.h>
|
||||
@@ -255,6 +257,11 @@ bool QmakeProFileNode::validParse() const
|
||||
return pro && pro->validParse();
|
||||
}
|
||||
|
||||
void QmakeProFileNode::build()
|
||||
{
|
||||
QmakeManager::buildProduct(getProject(), this);
|
||||
}
|
||||
|
||||
QStringList QmakeProFileNode::targetApplications() const
|
||||
{
|
||||
QStringList apps;
|
||||
|
@@ -97,6 +97,8 @@ public:
|
||||
bool parseInProgress() const override;
|
||||
bool validParse() const override;
|
||||
|
||||
void build() override;
|
||||
|
||||
QStringList targetApplications() const override;
|
||||
AddNewInformation addNewInformation(const QStringList &files, Node *context) const override;
|
||||
QVariant data(Core::Id role) const override;
|
||||
|
@@ -129,6 +129,7 @@ QmakeProject::QmakeProject(const FilePath &fileName) :
|
||||
setId(Constants::QMAKEPROJECT_ID);
|
||||
setProjectLanguages(Core::Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID));
|
||||
setDisplayName(fileName.toFileInfo().completeBaseName());
|
||||
setCanBuildProducts();
|
||||
|
||||
const QTextCodec *codec = Core::EditorManager::defaultTextCodec();
|
||||
m_qmakeVfs->setTextCodec(codec);
|
||||
|
@@ -194,6 +194,11 @@ void QmakeManager::buildFile()
|
||||
}
|
||||
}
|
||||
|
||||
void QmakeManager::buildProduct(Project *project, Node *proFileNode)
|
||||
{
|
||||
handleSubDirContextMenu(BUILD, false, project, proFileNode, nullptr);
|
||||
}
|
||||
|
||||
void QmakeManager::handleSubDirContextMenu(QmakeManager::Action action, bool isFileBuild)
|
||||
{
|
||||
handleSubDirContextMenu(action,
|
||||
|
@@ -62,9 +62,11 @@ public:
|
||||
void buildFileContextMenu();
|
||||
void buildFile();
|
||||
|
||||
static void buildProduct(ProjectExplorer::Project *project, ProjectExplorer::Node *proFileNode);
|
||||
|
||||
private:
|
||||
void handleSubDirContextMenu(Action action, bool isFileBuild);
|
||||
void handleSubDirContextMenu(QmakeManager::Action action, bool isFileBuild,
|
||||
static void handleSubDirContextMenu(QmakeManager::Action action, bool isFileBuild,
|
||||
ProjectExplorer::Project *contextProject,
|
||||
ProjectExplorer::Node *contextProFileNode,
|
||||
ProjectExplorer::FileNode *buildableFile);
|
||||
|
Reference in New Issue
Block a user