forked from qt-creator/qt-creator
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:
@@ -351,6 +351,7 @@ public:
|
|||||||
void handleAddExistingFiles();
|
void handleAddExistingFiles();
|
||||||
void addExistingDirectory();
|
void addExistingDirectory();
|
||||||
void addNewSubproject();
|
void addNewSubproject();
|
||||||
|
void addExistingProjects();
|
||||||
void removeProject();
|
void removeProject();
|
||||||
void openFile();
|
void openFile();
|
||||||
void searchOnFileSystem();
|
void searchOnFileSystem();
|
||||||
@@ -433,6 +434,7 @@ public:
|
|||||||
QAction *m_addExistingFilesAction;
|
QAction *m_addExistingFilesAction;
|
||||||
QAction *m_addExistingDirectoryAction;
|
QAction *m_addExistingDirectoryAction;
|
||||||
QAction *m_addNewSubprojectAction;
|
QAction *m_addNewSubprojectAction;
|
||||||
|
QAction *m_addExistingProjectsAction;
|
||||||
QAction *m_removeFileAction;
|
QAction *m_removeFileAction;
|
||||||
QAction *m_duplicateFileAction;
|
QAction *m_duplicateFileAction;
|
||||||
QAction *m_removeProjectAction;
|
QAction *m_removeProjectAction;
|
||||||
@@ -1127,6 +1129,13 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
|
|||||||
msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
|
msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
|
||||||
mfolderContextMenu->addAction(cmd, Constants::G_FOLDER_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
|
// add existing directory action
|
||||||
dd->m_addExistingDirectoryAction = new QAction(tr("Add Existing Directory..."), this);
|
dd->m_addExistingDirectoryAction = new QAction(tr("Add Existing Directory..."), this);
|
||||||
cmd = ActionManager::registerAction(dd->m_addExistingDirectoryAction,
|
cmd = ActionManager::registerAction(dd->m_addExistingDirectoryAction,
|
||||||
@@ -1434,6 +1443,8 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
|
|||||||
dd, &ProjectExplorerPluginPrivate::addExistingDirectory);
|
dd, &ProjectExplorerPluginPrivate::addExistingDirectory);
|
||||||
connect(dd->m_addNewSubprojectAction, &QAction::triggered,
|
connect(dd->m_addNewSubprojectAction, &QAction::triggered,
|
||||||
dd, &ProjectExplorerPluginPrivate::addNewSubproject);
|
dd, &ProjectExplorerPluginPrivate::addNewSubproject);
|
||||||
|
connect(dd->m_addExistingProjectsAction, &QAction::triggered,
|
||||||
|
dd, &ProjectExplorerPluginPrivate::addExistingProjects);
|
||||||
connect(dd->m_removeProjectAction, &QAction::triggered,
|
connect(dd->m_removeProjectAction, &QAction::triggered,
|
||||||
dd, &ProjectExplorerPluginPrivate::removeProject);
|
dd, &ProjectExplorerPluginPrivate::removeProject);
|
||||||
connect(dd->m_openFileAction, &QAction::triggered,
|
connect(dd->m_openFileAction, &QAction::triggered,
|
||||||
@@ -3115,6 +3126,7 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions()
|
|||||||
m_addExistingDirectoryAction->setEnabled(false);
|
m_addExistingDirectoryAction->setEnabled(false);
|
||||||
m_addNewFileAction->setEnabled(false);
|
m_addNewFileAction->setEnabled(false);
|
||||||
m_addNewSubprojectAction->setEnabled(false);
|
m_addNewSubprojectAction->setEnabled(false);
|
||||||
|
m_addExistingProjectsAction->setEnabled(false);
|
||||||
m_removeProjectAction->setEnabled(false);
|
m_removeProjectAction->setEnabled(false);
|
||||||
m_removeFileAction->setEnabled(false);
|
m_removeFileAction->setEnabled(false);
|
||||||
m_duplicateFileAction->setEnabled(false);
|
m_duplicateFileAction->setEnabled(false);
|
||||||
@@ -3126,6 +3138,7 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions()
|
|||||||
m_addExistingDirectoryAction->setVisible(true);
|
m_addExistingDirectoryAction->setVisible(true);
|
||||||
m_addNewFileAction->setVisible(true);
|
m_addNewFileAction->setVisible(true);
|
||||||
m_addNewSubprojectAction->setVisible(true);
|
m_addNewSubprojectAction->setVisible(true);
|
||||||
|
m_addExistingProjectsAction->setVisible(true);
|
||||||
m_removeProjectAction->setVisible(true);
|
m_removeProjectAction->setVisible(true);
|
||||||
m_removeFileAction->setVisible(true);
|
m_removeFileAction->setVisible(true);
|
||||||
m_duplicateFileAction->setVisible(false);
|
m_duplicateFileAction->setVisible(false);
|
||||||
@@ -3196,6 +3209,8 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions()
|
|||||||
m_addNewSubprojectAction->setEnabled(currentNode->nodeType() == NodeType::Project
|
m_addNewSubprojectAction->setEnabled(currentNode->nodeType() == NodeType::Project
|
||||||
&& supports(AddSubProject)
|
&& supports(AddSubProject)
|
||||||
&& !ICore::isNewItemDialogRunning());
|
&& !ICore::isNewItemDialogRunning());
|
||||||
|
m_addExistingProjectsAction->setEnabled(currentNode->nodeType() == NodeType::Project
|
||||||
|
&& supports(AddExistingProject));
|
||||||
m_removeProjectAction->setEnabled(currentNode->nodeType() == NodeType::Project
|
m_removeProjectAction->setEnabled(currentNode->nodeType() == NodeType::Project
|
||||||
&& supports(RemoveSubProject));
|
&& supports(RemoveSubProject));
|
||||||
m_addExistingFilesAction->setEnabled(supports(AddExistingFile));
|
m_addExistingFilesAction->setEnabled(supports(AddExistingFile));
|
||||||
@@ -3241,6 +3256,7 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions()
|
|||||||
if (supports(HideFolderActions)) {
|
if (supports(HideFolderActions)) {
|
||||||
m_addNewFileAction->setVisible(false);
|
m_addNewFileAction->setVisible(false);
|
||||||
m_addNewSubprojectAction->setVisible(false);
|
m_addNewSubprojectAction->setVisible(false);
|
||||||
|
m_addExistingProjectsAction->setVisible(false);
|
||||||
m_removeProjectAction->setVisible(false);
|
m_removeProjectAction->setVisible(false);
|
||||||
m_addExistingFilesAction->setVisible(false);
|
m_addExistingFilesAction->setVisible(false);
|
||||||
m_addExistingDirectoryAction->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()
|
void ProjectExplorerPluginPrivate::handleAddExistingFiles()
|
||||||
{
|
{
|
||||||
Node *node = ProjectTree::findCurrentNode();
|
Node *node = ProjectTree::findCurrentNode();
|
||||||
|
@@ -822,6 +822,11 @@ bool ProjectNode::addSubProject(const QString &proFilePath)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList ProjectNode::subProjectFileNamePatterns() const
|
||||||
|
{
|
||||||
|
return QStringList();
|
||||||
|
}
|
||||||
|
|
||||||
bool ProjectNode::removeSubProject(const QString &proFilePath)
|
bool ProjectNode::removeSubProject(const QString &proFilePath)
|
||||||
{
|
{
|
||||||
Q_UNUSED(proFilePath)
|
Q_UNUSED(proFilePath)
|
||||||
|
@@ -68,6 +68,7 @@ enum ProjectAction {
|
|||||||
// Special value to indicate that the actions are handled by the parent
|
// Special value to indicate that the actions are handled by the parent
|
||||||
InheritedFromParent,
|
InheritedFromParent,
|
||||||
AddSubProject,
|
AddSubProject,
|
||||||
|
AddExistingProject,
|
||||||
RemoveSubProject,
|
RemoveSubProject,
|
||||||
// Let's the user select to which project file
|
// Let's the user select to which project file
|
||||||
// the file is added
|
// the file is added
|
||||||
@@ -325,6 +326,7 @@ class PROJECTEXPLORER_EXPORT ProjectNode : public FolderNode
|
|||||||
public:
|
public:
|
||||||
virtual bool canAddSubProject(const QString &proFilePath) const;
|
virtual bool canAddSubProject(const QString &proFilePath) const;
|
||||||
virtual bool addSubProject(const QString &proFile);
|
virtual bool addSubProject(const QString &proFile);
|
||||||
|
virtual QStringList subProjectFileNamePatterns() const;
|
||||||
virtual bool removeSubProject(const QString &proFilePath);
|
virtual bool removeSubProject(const QString &proFilePath);
|
||||||
virtual Utils::optional<Utils::FileName> visibleAfterAddFileAction() const {
|
virtual Utils::optional<Utils::FileName> visibleAfterAddFileAction() const {
|
||||||
return Utils::nullopt;
|
return Utils::nullopt;
|
||||||
|
@@ -132,7 +132,7 @@ bool QmakePriFileNode::supportsAction(ProjectAction action, const Node *node) co
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ProjectType::SubDirsTemplate:
|
case ProjectType::SubDirsTemplate:
|
||||||
if (action == AddSubProject || action == RemoveSubProject)
|
if (action == AddSubProject || action == RemoveSubProject || action == AddExistingProject)
|
||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -168,6 +168,11 @@ bool QmakePriFileNode::removeSubProject(const QString &proFilePath)
|
|||||||
return pri ? pri->removeSubProjects(proFilePath) : false;
|
return pri ? pri->removeSubProjects(proFilePath) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList QmakePriFileNode::subProjectFileNamePatterns() const
|
||||||
|
{
|
||||||
|
return QStringList("*.pro");
|
||||||
|
}
|
||||||
|
|
||||||
bool QmakePriFileNode::addFiles(const QStringList &filePaths, QStringList *notAdded)
|
bool QmakePriFileNode::addFiles(const QStringList &filePaths, QStringList *notAdded)
|
||||||
{
|
{
|
||||||
QmakePriFile *pri = priFile();
|
QmakePriFile *pri = priFile();
|
||||||
|
@@ -51,9 +51,9 @@ public:
|
|||||||
bool showInSimpleTree() const override { return false; }
|
bool showInSimpleTree() const override { return false; }
|
||||||
|
|
||||||
bool canAddSubProject(const QString &proFilePath) const override;
|
bool canAddSubProject(const QString &proFilePath) const override;
|
||||||
|
|
||||||
bool addSubProject(const QString &proFilePath) override;
|
bool addSubProject(const QString &proFilePath) override;
|
||||||
bool removeSubProject(const QString &proFilePath) override;
|
bool removeSubProject(const QString &proFilePath) override;
|
||||||
|
QStringList subProjectFileNamePatterns() const override;
|
||||||
|
|
||||||
bool addFiles(const QStringList &filePaths, QStringList *notAdded = nullptr) override;
|
bool addFiles(const QStringList &filePaths, QStringList *notAdded = nullptr) override;
|
||||||
bool removeFiles(const QStringList &filePaths, QStringList *notRemoved = nullptr) override;
|
bool removeFiles(const QStringList &filePaths, QStringList *notRemoved = nullptr) override;
|
||||||
|
Reference in New Issue
Block a user