From c7ce2fb2b2d0977a263ff0a1e3c93c4ad7601381 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 21 Apr 2020 16:31:23 +0200 Subject: [PATCH] ProjectExplorer: Support bulk removal of files in project tree Find files with the same base name and offer the user to remove these as well, like we already do for the renaming action. Fixes: QTCREATORBUG-23869 Change-Id: Ibaa068e6e4d21b884e14c4ad1e95ec14b6e5e036 Reviewed-by: hjk Reviewed-by: Leena Miettinen --- .../projectexplorer/projectexplorer.cpp | 45 +++++++++++++------ 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index 6528b1de700..8897638ff65 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -156,6 +156,7 @@ #include #include #include +#include #include #include @@ -3604,38 +3605,54 @@ void ProjectExplorerPluginPrivate::removeFile() QTC_ASSERT(currentNode && currentNode->asFileNode(), return); const Utils::FilePath filePath = currentNode->filePath(); + using NodeAndPath = QPair; + QList filesToRemove{qMakePair(currentNode, currentNode->filePath())}; + QList siblings; + for (const Node * const n : ProjectTree::siblingsWithSameBaseName(currentNode)) + siblings << qMakePair(n, n->filePath()); + Utils::RemoveFileDialog removeFileDialog(filePath.toString(), ICore::mainWindow()); + if (removeFileDialog.exec() != QDialog::Accepted) + return; - if (removeFileDialog.exec() == QDialog::Accepted) { - const bool deleteFile = removeFileDialog.isDeleteFileChecked(); + const bool deleteFile = removeFileDialog.isDeleteFileChecked(); - // Re-read the current node, in case the project is re-parsed while the dialog is open - if (!ProjectTree::hasNode(currentNode)) { + const QMessageBox::StandardButton reply = QMessageBox::question( + Core::ICore::mainWindow(), tr("Remove More Files?"), + tr("Would you like to remove these files as well?\n %1") + .arg(Utils::transform(siblings, [](const NodeAndPath &np) { + return np.second.toFileInfo().fileName(); + }).join("\n "))); + if (reply == QMessageBox::Yes) + filesToRemove << siblings; + + for (const NodeAndPath &file : filesToRemove) { + // Nodes can become invalid if the project was re-parsed while the dialog was open + if (!ProjectTree::hasNode(file.first)) { QMessageBox::warning(ICore::mainWindow(), tr("Removing File Failed"), - tr("File %1 was not removed, because the project has changed " + tr("File \"%1\" was not removed, because the project has changed " "in the meantime.\nPlease try again.") - .arg(filePath.toUserOutput())); + .arg(file.second.toUserOutput())); return; } // remove from project - FolderNode *folderNode = currentNode->asFileNode()->parentFolderNode(); + FolderNode *folderNode = file.first->asFileNode()->parentFolderNode(); QTC_ASSERT(folderNode, return); const RemovedFilesFromProject status - = folderNode->removeFiles(QStringList(filePath.toString())); + = folderNode->removeFiles(QStringList(file.second.toString())); const bool success = status == RemovedFilesFromProject::Ok || (status == RemovedFilesFromProject::Wildcard && removeFileDialog.isDeleteFileChecked()); if (!success) { - QMessageBox::warning(ICore::mainWindow(), tr("Removing File Failed"), - tr("Could not remove file %1 from project %2.") - .arg(filePath.toUserOutput()) - .arg(folderNode->managingProject()->displayName())); + TaskHub::addTask(BuildSystemTask(Task::Error, + tr("Could not remove file \"%1\" from project \"%2\".") + .arg(filePath.toUserOutput(), folderNode->managingProject()->displayName()), + folderNode->managingProject()->filePath())); if (!deleteFile) - return; + continue; } - FileChangeBlocker changeGuard(filePath.toString()); FileUtils::removeFile(filePath.toString(), deleteFile); }