ProjectExplorer: Allow to add existing project as sub-project

Implemented only for qmake as of now.

Fixes: QTCREATORBUG-5837
Change-Id: I78f6ce55d6a149a75ae595f7a86d39dc55496819
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Christian Kandeler
2019-02-19 18:06:10 +01:00
parent 4652a2b1d8
commit 11f989bb93
5 changed files with 68 additions and 2 deletions

View File

@@ -351,6 +351,7 @@ public:
void handleAddExistingFiles();
void addExistingDirectory();
void addNewSubproject();
void addExistingProjects();
void removeProject();
void openFile();
void searchOnFileSystem();
@@ -433,6 +434,7 @@ public:
QAction *m_addExistingFilesAction;
QAction *m_addExistingDirectoryAction;
QAction *m_addNewSubprojectAction;
QAction *m_addExistingProjectsAction;
QAction *m_removeFileAction;
QAction *m_duplicateFileAction;
QAction *m_removeProjectAction;
@@ -1127,6 +1129,13 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
mfolderContextMenu->addAction(cmd, Constants::G_FOLDER_FILES);
// add existing projects action
dd->m_addExistingProjectsAction = new QAction(tr("Add Existing Projects..."), this);
cmd = ActionManager::registerAction(dd->m_addExistingProjectsAction,
"ProjectExplorer.AddExistingProjects", projecTreeContext);
mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
// add existing directory action
dd->m_addExistingDirectoryAction = new QAction(tr("Add Existing Directory..."), this);
cmd = ActionManager::registerAction(dd->m_addExistingDirectoryAction,
@@ -1434,6 +1443,8 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
dd, &ProjectExplorerPluginPrivate::addExistingDirectory);
connect(dd->m_addNewSubprojectAction, &QAction::triggered,
dd, &ProjectExplorerPluginPrivate::addNewSubproject);
connect(dd->m_addExistingProjectsAction, &QAction::triggered,
dd, &ProjectExplorerPluginPrivate::addExistingProjects);
connect(dd->m_removeProjectAction, &QAction::triggered,
dd, &ProjectExplorerPluginPrivate::removeProject);
connect(dd->m_openFileAction, &QAction::triggered,
@@ -3115,6 +3126,7 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions()
m_addExistingDirectoryAction->setEnabled(false);
m_addNewFileAction->setEnabled(false);
m_addNewSubprojectAction->setEnabled(false);
m_addExistingProjectsAction->setEnabled(false);
m_removeProjectAction->setEnabled(false);
m_removeFileAction->setEnabled(false);
m_duplicateFileAction->setEnabled(false);
@@ -3126,6 +3138,7 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions()
m_addExistingDirectoryAction->setVisible(true);
m_addNewFileAction->setVisible(true);
m_addNewSubprojectAction->setVisible(true);
m_addExistingProjectsAction->setVisible(true);
m_removeProjectAction->setVisible(true);
m_removeFileAction->setVisible(true);
m_duplicateFileAction->setVisible(false);
@@ -3196,6 +3209,8 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions()
m_addNewSubprojectAction->setEnabled(currentNode->nodeType() == NodeType::Project
&& supports(AddSubProject)
&& !ICore::isNewItemDialogRunning());
m_addExistingProjectsAction->setEnabled(currentNode->nodeType() == NodeType::Project
&& supports(AddExistingProject));
m_removeProjectAction->setEnabled(currentNode->nodeType() == NodeType::Project
&& supports(RemoveSubProject));
m_addExistingFilesAction->setEnabled(supports(AddExistingFile));
@@ -3241,6 +3256,7 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions()
if (supports(HideFolderActions)) {
m_addNewFileAction->setVisible(false);
m_addNewSubprojectAction->setVisible(false);
m_addExistingProjectsAction->setVisible(false);
m_removeProjectAction->setVisible(false);
m_addExistingFilesAction->setVisible(false);
m_addExistingDirectoryAction->setVisible(false);
@@ -3342,6 +3358,44 @@ void ProjectExplorerPluginPrivate::addNewSubproject()
}
}
void ProjectExplorerPluginPrivate::addExistingProjects()
{
Node * const currentNode = ProjectTree::findCurrentNode();
QTC_ASSERT(currentNode, return);
ProjectNode *projectNode = currentNode->asProjectNode();
if (!projectNode && currentNode->asContainerNode())
projectNode = currentNode->asContainerNode()->rootProjectNode();
QTC_ASSERT(projectNode, return);
const QString dir = directoryFor(currentNode);
QStringList subProjectFilePaths = QFileDialog::getOpenFileNames(
ICore::mainWindow(), tr("Please choose a project file"), dir,
projectNode->subProjectFileNamePatterns().join(";;"));
const QList<Node *> childNodes = projectNode->nodes();
Utils::erase(subProjectFilePaths, [childNodes](const QString &filePath) {
return Utils::anyOf(childNodes, [filePath](const Node *n) {
return n->filePath().toString() == filePath;
});
});
if (subProjectFilePaths.empty())
return;
QStringList failedProjects;
QStringList addedProjects;
for (const QString &filePath : subProjectFilePaths) {
if (projectNode->addSubProject(filePath))
addedProjects << filePath;
else
failedProjects << filePath;
}
if (!failedProjects.empty()) {
const QString message = tr("The following subprojects could not be added to project "
"\"%2\":").arg(projectNode->managingProject()->displayName());
QMessageBox::warning(ICore::mainWindow(), tr("Adding Subproject Failed"),
message + "\n " + failedProjects.join("\n "));
return;
}
VcsManager::promptToAdd(dir, addedProjects);
}
void ProjectExplorerPluginPrivate::handleAddExistingFiles()
{
Node *node = ProjectTree::findCurrentNode();

View File

@@ -822,6 +822,11 @@ bool ProjectNode::addSubProject(const QString &proFilePath)
return false;
}
QStringList ProjectNode::subProjectFileNamePatterns() const
{
return QStringList();
}
bool ProjectNode::removeSubProject(const QString &proFilePath)
{
Q_UNUSED(proFilePath)

View File

@@ -68,6 +68,7 @@ enum ProjectAction {
// Special value to indicate that the actions are handled by the parent
InheritedFromParent,
AddSubProject,
AddExistingProject,
RemoveSubProject,
// Let's the user select to which project file
// the file is added
@@ -325,6 +326,7 @@ class PROJECTEXPLORER_EXPORT ProjectNode : public FolderNode
public:
virtual bool canAddSubProject(const QString &proFilePath) const;
virtual bool addSubProject(const QString &proFile);
virtual QStringList subProjectFileNamePatterns() const;
virtual bool removeSubProject(const QString &proFilePath);
virtual Utils::optional<Utils::FileName> visibleAfterAddFileAction() const {
return Utils::nullopt;

View File

@@ -132,7 +132,7 @@ bool QmakePriFileNode::supportsAction(ProjectAction action, const Node *node) co
break;
}
case ProjectType::SubDirsTemplate:
if (action == AddSubProject || action == RemoveSubProject)
if (action == AddSubProject || action == RemoveSubProject || action == AddExistingProject)
return true;
break;
default:
@@ -168,6 +168,11 @@ bool QmakePriFileNode::removeSubProject(const QString &proFilePath)
return pri ? pri->removeSubProjects(proFilePath) : false;
}
QStringList QmakePriFileNode::subProjectFileNamePatterns() const
{
return QStringList("*.pro");
}
bool QmakePriFileNode::addFiles(const QStringList &filePaths, QStringList *notAdded)
{
QmakePriFile *pri = priFile();

View File

@@ -51,9 +51,9 @@ public:
bool showInSimpleTree() const override { return false; }
bool canAddSubProject(const QString &proFilePath) const override;
bool addSubProject(const QString &proFilePath) override;
bool removeSubProject(const QString &proFilePath) override;
QStringList subProjectFileNamePatterns() const override;
bool addFiles(const QStringList &filePaths, QStringList *notAdded = nullptr) override;
bool removeFiles(const QStringList &filePaths, QStringList *notRemoved = nullptr) override;