diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp index 1549c51795c..cf01c42801e 100644 --- a/src/plugins/projectexplorer/project.cpp +++ b/src/plugins/projectexplorer/project.cpp @@ -84,38 +84,6 @@ const char PLUGIN_SETTINGS_KEY[] = "ProjectExplorer.Project.PluginSettings"; namespace ProjectExplorer { -class ContainerNode : public ProjectNode -{ -public: - ContainerNode(Project *project) - : ProjectNode(Utils::FileName()), - m_project(project) - {} - - QString displayName() const final - { - QString name = m_project->displayName(); - - const QFileInfo fi = m_project->projectFilePath().toFileInfo(); - const QString dir = fi.isDir() ? fi.absoluteFilePath() : fi.absolutePath(); - if (Core::IVersionControl *vc = Core::VcsManager::findVersionControlForDirectory(dir)) { - QString vcsTopic = vc->vcsTopic(dir); - if (!vcsTopic.isEmpty()) - name += " [" + vcsTopic + ']'; - } - - return name; - } - - QList supportedActions(Node *) const final - { - return {}; - } - -private: - Project *m_project; -}; - // ------------------------------------------------------------------------- // Project // ------------------------------------------------------------------------- @@ -601,7 +569,7 @@ ProjectNode *Project::rootProjectNode() const return d->m_rootProjectNode; } -ProjectNode *Project::containerNode() const +ContainerNode *Project::containerNode() const { return &d->m_containerNode; } diff --git a/src/plugins/projectexplorer/project.h b/src/plugins/projectexplorer/project.h index daed9e5afc9..f5f5fc49fd3 100644 --- a/src/plugins/projectexplorer/project.h +++ b/src/plugins/projectexplorer/project.h @@ -48,6 +48,7 @@ namespace Utils { class MacroExpander; } namespace ProjectExplorer { class BuildInfo; +class ContainerNode; class EditorConfiguration; class FileNode; class NamedWidget; @@ -84,7 +85,7 @@ public: static Utils::FileName projectDirectory(const Utils::FileName &top); virtual ProjectNode *rootProjectNode() const; - ProjectNode *containerNode() const; + ContainerNode *containerNode() const; bool hasActiveBuildSettings() const; diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index ac1f308e5c2..2bbb0e50372 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -2913,7 +2913,13 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions() if (currentNode && currentNode->managingProject()) { QList actions = currentNode->supportedActions(currentNode); - if (ProjectNode *pn = currentNode->asProjectNode()) { + ProjectNode *pn; + if (ContainerNode *cn = currentNode->asContainerNode()) + pn = cn->rootProjectNode(); + else + pn = currentNode->asProjectNode(); + + if (pn) { if (ProjectTree::currentProject() && pn == ProjectTree::currentProject()->rootProjectNode()) { m_runActionContextMenu->setVisible(true); } else { diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp index 7d275d2eac3..f3fa5565b9d 100644 --- a/src/plugins/projectexplorer/projectnodes.cpp +++ b/src/plugins/projectexplorer/projectnodes.cpp @@ -25,6 +25,7 @@ #include "projectnodes.h" +#include "project.h" #include "projectexplorerconstants.h" #include "projecttree.h" @@ -171,8 +172,9 @@ FolderNode *Node::parentFolderNode() const ProjectNode *Node::managingProject() { - if (!m_parentFolderNode) - return nullptr; + if (asContainerNode()) + return asContainerNode()->rootProjectNode(); + QTC_ASSERT(m_parentFolderNode, return nullptr); ProjectNode *pn = parentProjectNode(); return pn ? pn : asProjectNode(); // projects manage themselves... } @@ -790,4 +792,35 @@ bool FolderNode::isEmpty() const return m_nodes.isEmpty(); } +ContainerNode::ContainerNode(Project *project) + : FolderNode(Utils::FileName(), NodeType::Project), m_project(project) +{} + +QString ContainerNode::displayName() const +{ + QString name = m_project->displayName(); + + const QFileInfo fi = m_project->projectFilePath().toFileInfo(); + const QString dir = fi.isDir() ? fi.absoluteFilePath() : fi.absolutePath(); + if (Core::IVersionControl *vc = Core::VcsManager::findVersionControlForDirectory(dir)) { + QString vcsTopic = vc->vcsTopic(dir); + if (!vcsTopic.isEmpty()) + name += " [" + vcsTopic + ']'; + } + + return name; +} + +QList ContainerNode::supportedActions(Node *node) const +{ + if (Node *rootNode = m_project->rootProjectNode()) + return rootNode->supportedActions(node); + return {}; +} + +ProjectNode *ContainerNode::rootProjectNode() const +{ + return m_project->rootProjectNode(); +} + } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/projectnodes.h b/src/plugins/projectexplorer/projectnodes.h index 757529da8b5..4ed5b4eb568 100644 --- a/src/plugins/projectexplorer/projectnodes.h +++ b/src/plugins/projectexplorer/projectnodes.h @@ -39,6 +39,8 @@ namespace Utils { class MimeType; } namespace ProjectExplorer { + +class Project; class RunConfiguration; enum class NodeType : quint16 { @@ -92,6 +94,7 @@ enum ProjectAction { class FileNode; class FolderNode; class ProjectNode; +class ContainerNode; // Documentation inside. class PROJECTEXPLORER_EXPORT Node : public QObject @@ -115,8 +118,9 @@ public: FolderNode *parentFolderNode() const; // parent folder or project ProjectNode *managingProject(); // project managing this node. - // result is nullptr if node is the SessionNode - // or node if node is a ProjectNode directly below SessionNode + // result is the container's rootProject node if this is a project container node + // (i.e. possibly null) + // or node if node is a top-level ProjectNode directly below a container // or node->parentProjectNode() for all other cases. const ProjectNode *managingProject() const; // see above. @@ -137,6 +141,8 @@ public: virtual const FolderNode *asFolderNode() const { return nullptr; } virtual ProjectNode *asProjectNode() { return nullptr; } virtual const ProjectNode *asProjectNode() const { return nullptr; } + virtual ContainerNode *asContainerNode() { return nullptr; } + virtual const ContainerNode *asContainerNode() const { return nullptr; } static bool sortByPath(const Node *a, const Node *b); void setParentFolderNode(FolderNode *parentFolder); @@ -297,6 +303,24 @@ protected: explicit ProjectNode(const Utils::FileName &projectFilePath); }; +class PROJECTEXPLORER_EXPORT ContainerNode : public FolderNode +{ +public: + ContainerNode(Project *project); + + QString displayName() const final; + QList supportedActions(Node *node) const final; + + ContainerNode *asContainerNode() final { return this; } + const ContainerNode *asContainerNode() const final { return this; } + + ProjectNode *rootProjectNode() const; + +private: + Project *m_project; + QList m_nodes; +}; + } // namespace ProjectExplorer Q_DECLARE_METATYPE(ProjectExplorer::Node *) diff --git a/src/plugins/projectexplorer/projecttree.cpp b/src/plugins/projectexplorer/projecttree.cpp index 4c5351beef9..50b8b652566 100644 --- a/src/plugins/projectexplorer/projecttree.cpp +++ b/src/plugins/projectexplorer/projecttree.cpp @@ -322,12 +322,14 @@ void ProjectTree::showContextMenu(ProjectTreeWidget *focus, const QPoint &global contextMenu = Core::ActionManager::actionContainer(Constants::M_SESSIONCONTEXT)->menu(); } else { switch (node->nodeType()) { - case NodeType::Project: - if (!node->parentFolderNode()) + case NodeType::Project: { + if ((node->parentFolderNode() && node->parentFolderNode()->asContainerNode()) + || node->asContainerNode()) contextMenu = Core::ActionManager::actionContainer(Constants::M_PROJECTCONTEXT)->menu(); else contextMenu = Core::ActionManager::actionContainer(Constants::M_SUBPROJECTCONTEXT)->menu(); break; + } case NodeType::VirtualFolder: case NodeType::Folder: contextMenu = Core::ActionManager::actionContainer(Constants::M_FOLDERCONTEXT)->menu(); diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp index 9641c289e48..341ef746523 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp @@ -318,9 +318,11 @@ void QmakeProjectManagerPlugin::updateContextActions() { Node *node = ProjectTree::currentNode(); Project *project = ProjectTree::currentProject(); - m_addLibraryActionContextMenu->setEnabled(dynamic_cast(node)); - auto proFileNode = dynamic_cast(node); + ContainerNode *containerNode = node ? node->asContainerNode() : nullptr; + ProjectNode *proFileNode = containerNode ? containerNode->rootProjectNode() : dynamic_cast(node); + + m_addLibraryActionContextMenu->setEnabled(proFileNode); QmakeProject *qmakeProject = qobject_cast(QmakeManager::contextProject()); QmakeProFileNode *subProjectNode = nullptr; if (node) {