forked from qt-creator/qt-creator
ProjectExplorer: Let build systems do renamings in bulk
Like for the add and remove operations. Change-Id: I734396b1b0f5a4ffb9cf193a0e32c8f7f60259ae Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -2558,4 +2558,14 @@ FilePath TemporaryFilePath::filePath() const
|
|||||||
return d->filePath;
|
return d->filePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FilePaths firstPaths(const FilePairs &pairs)
|
||||||
|
{
|
||||||
|
return transform(pairs, &FilePair::first);
|
||||||
|
}
|
||||||
|
|
||||||
|
FilePaths secondPaths(const FilePairs &pairs)
|
||||||
|
{
|
||||||
|
return transform(pairs, &FilePair::second);
|
||||||
|
}
|
||||||
|
|
||||||
} // Utils
|
} // Utils
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <utility>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
@@ -53,7 +54,12 @@ public:
|
|||||||
const QDirIterator::IteratorFlags iteratorFlags = QDirIterator::NoIteratorFlags;
|
const QDirIterator::IteratorFlags iteratorFlags = QDirIterator::NoIteratorFlags;
|
||||||
};
|
};
|
||||||
|
|
||||||
using FilePaths = QList<class FilePath>;
|
class FilePath;
|
||||||
|
using FilePaths = QList<FilePath>;
|
||||||
|
using FilePair = std::pair<FilePath, FilePath>;
|
||||||
|
using FilePairs = QList<FilePair>;
|
||||||
|
QTCREATOR_UTILS_EXPORT FilePaths firstPaths(const FilePairs &pairs);
|
||||||
|
QTCREATOR_UTILS_EXPORT FilePaths secondPaths(const FilePairs &pairs);
|
||||||
|
|
||||||
class QTCREATOR_UTILS_EXPORT FilePathWatcher : public QObject
|
class QTCREATOR_UTILS_EXPORT FilePathWatcher : public QObject
|
||||||
{
|
{
|
||||||
|
@@ -962,74 +962,95 @@ bool CMakeBuildSystem::canRenameFile(Node *context,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CMakeBuildSystem::renameFile(Node *context,
|
bool CMakeBuildSystem::renameFiles(Node *context, const FilePairs &filesToRename, FilePaths *notRenamed)
|
||||||
const FilePath &oldFilePath,
|
|
||||||
const FilePath &newFilePath)
|
|
||||||
{
|
{
|
||||||
if (auto n = dynamic_cast<CMakeTargetNode *>(context)) {
|
const auto n = dynamic_cast<CMakeTargetNode *>(context);
|
||||||
const FilePath projDir = n->filePath().canonicalPath();
|
if (!n) {
|
||||||
const FilePath newRelPath = newFilePath.canonicalPath().relativePathFrom(projDir).cleanPath();
|
if (notRenamed)
|
||||||
const QString newRelPathName = newRelPath.toString();
|
*notRenamed = firstPaths(filesToRename);
|
||||||
|
return false;
|
||||||
const QString targetName = n->buildKey();
|
|
||||||
const QString key
|
|
||||||
= QStringList{projDir.path(), targetName, oldFilePath.path(), newFilePath.path()}.join(
|
|
||||||
";");
|
|
||||||
|
|
||||||
std::optional<CMakeBuildSystem::ProjectFileArgumentPosition> fileToRename
|
|
||||||
= m_filesToBeRenamed.take(key);
|
|
||||||
if (!fileToRename->cmakeFile.exists()) {
|
|
||||||
qCCritical(cmakeBuildSystemLog).noquote()
|
|
||||||
<< "File" << fileToRename->cmakeFile.path() << "does not exist.";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool haveGlobbing = false;
|
|
||||||
do {
|
|
||||||
if (!fileToRename->fromGlobbing) {
|
|
||||||
BaseTextEditor *editor = qobject_cast<BaseTextEditor *>(
|
|
||||||
Core::EditorManager::openEditorAt(
|
|
||||||
{fileToRename->cmakeFile,
|
|
||||||
static_cast<int>(fileToRename->argumentPosition.Line),
|
|
||||||
static_cast<int>(fileToRename->argumentPosition.Column - 1)},
|
|
||||||
Constants::CMAKE_EDITOR_ID,
|
|
||||||
Core::EditorManager::DoNotMakeVisible
|
|
||||||
| Core::EditorManager::DoNotChangeCurrentEditor));
|
|
||||||
if (!editor) {
|
|
||||||
qCCritical(cmakeBuildSystemLog).noquote()
|
|
||||||
<< "BaseTextEditor cannot be obtained for" << fileToRename->cmakeFile.path()
|
|
||||||
<< fileToRename->argumentPosition.Line
|
|
||||||
<< int(fileToRename->argumentPosition.Column);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If quotes were used for the source file, skip the starting quote
|
|
||||||
if (fileToRename->argumentPosition.Delim == cmListFileArgument::Quoted)
|
|
||||||
editor->setCursorPosition(editor->position() + 1);
|
|
||||||
|
|
||||||
editor->replace(fileToRename->relativeFileName.length(), newRelPathName);
|
|
||||||
|
|
||||||
editor->editorWidget()->autoIndent();
|
|
||||||
if (!Core::DocumentManager::saveDocument(editor->document())) {
|
|
||||||
qCCritical(cmakeBuildSystemLog).noquote()
|
|
||||||
<< "Changes to" << fileToRename->cmakeFile.path() << "could not be saved.";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
haveGlobbing = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try the next occurrence. This can happen if set_source_file_properties is used
|
|
||||||
fileToRename = projectFileArgumentPosition(targetName, fileToRename->relativeFileName);
|
|
||||||
} while (fileToRename && !fileToRename->fromGlobbing);
|
|
||||||
|
|
||||||
if (haveGlobbing && settings(project()).autorunCMake())
|
|
||||||
runCMake();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
bool shouldRunCMake = false;
|
||||||
|
bool success = true;
|
||||||
|
for (const auto &[oldFilePath, newFilePath] : filesToRename) {
|
||||||
|
if (!renameFile(n, oldFilePath, newFilePath, shouldRunCMake)) {
|
||||||
|
success = false;
|
||||||
|
if (notRenamed)
|
||||||
|
*notRenamed << oldFilePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldRunCMake && settings(project()).autorunCMake())
|
||||||
|
runCMake();
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CMakeBuildSystem::renameFile(
|
||||||
|
CMakeTargetNode *context,
|
||||||
|
const Utils::FilePath &oldFilePath,
|
||||||
|
const Utils::FilePath &newFilePath,
|
||||||
|
bool &shouldRunCMake)
|
||||||
|
{
|
||||||
|
const FilePath projDir = context->filePath().canonicalPath();
|
||||||
|
const FilePath newRelPath = newFilePath.canonicalPath().relativePathFrom(projDir).cleanPath();
|
||||||
|
const QString newRelPathName = newRelPath.toString();
|
||||||
|
|
||||||
|
const QString targetName = context->buildKey();
|
||||||
|
const QString key
|
||||||
|
= QStringList{projDir.path(), targetName, oldFilePath.path(), newFilePath.path()}.join(
|
||||||
|
";");
|
||||||
|
|
||||||
|
std::optional<CMakeBuildSystem::ProjectFileArgumentPosition> fileToRename
|
||||||
|
= m_filesToBeRenamed.take(key);
|
||||||
|
if (!fileToRename->cmakeFile.exists()) {
|
||||||
|
qCCritical(cmakeBuildSystemLog).noquote()
|
||||||
|
<< "File" << fileToRename->cmakeFile.path() << "does not exist.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool haveGlobbing = false;
|
||||||
|
do {
|
||||||
|
if (!fileToRename->fromGlobbing) {
|
||||||
|
BaseTextEditor *editor = qobject_cast<BaseTextEditor *>(
|
||||||
|
Core::EditorManager::openEditorAt(
|
||||||
|
{fileToRename->cmakeFile,
|
||||||
|
static_cast<int>(fileToRename->argumentPosition.Line),
|
||||||
|
static_cast<int>(fileToRename->argumentPosition.Column - 1)},
|
||||||
|
Constants::CMAKE_EDITOR_ID,
|
||||||
|
Core::EditorManager::DoNotMakeVisible
|
||||||
|
| Core::EditorManager::DoNotChangeCurrentEditor));
|
||||||
|
if (!editor) {
|
||||||
|
qCCritical(cmakeBuildSystemLog).noquote()
|
||||||
|
<< "BaseTextEditor cannot be obtained for" << fileToRename->cmakeFile.path()
|
||||||
|
<< fileToRename->argumentPosition.Line
|
||||||
|
<< int(fileToRename->argumentPosition.Column);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If quotes were used for the source file, skip the starting quote
|
||||||
|
if (fileToRename->argumentPosition.Delim == cmListFileArgument::Quoted)
|
||||||
|
editor->setCursorPosition(editor->position() + 1);
|
||||||
|
|
||||||
|
editor->replace(fileToRename->relativeFileName.length(), newRelPathName);
|
||||||
|
editor->editorWidget()->autoIndent();
|
||||||
|
if (!Core::DocumentManager::saveDocument(editor->document())) {
|
||||||
|
qCCritical(cmakeBuildSystemLog).noquote()
|
||||||
|
<< "Changes to" << fileToRename->cmakeFile.path() << "could not be saved.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
haveGlobbing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try the next occurrence. This can happen if set_source_file_properties is used
|
||||||
|
fileToRename = projectFileArgumentPosition(targetName, fileToRename->relativeFileName);
|
||||||
|
} while (fileToRename && !fileToRename->fromGlobbing);
|
||||||
|
|
||||||
|
if (haveGlobbing)
|
||||||
|
shouldRunCMake = true;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMakeBuildSystem::buildNamedTarget(const QString &target)
|
void CMakeBuildSystem::buildNamedTarget(const QString &target)
|
||||||
|
@@ -61,9 +61,9 @@ public:
|
|||||||
bool canRenameFile(ProjectExplorer::Node *context,
|
bool canRenameFile(ProjectExplorer::Node *context,
|
||||||
const Utils::FilePath &oldFilePath,
|
const Utils::FilePath &oldFilePath,
|
||||||
const Utils::FilePath &newFilePath) final;
|
const Utils::FilePath &newFilePath) final;
|
||||||
bool renameFile(ProjectExplorer::Node *context,
|
bool renameFiles(ProjectExplorer::Node *context,
|
||||||
const Utils::FilePath &oldFilePath,
|
const Utils::FilePairs &filesToRename,
|
||||||
const Utils::FilePath &newFilePath) final;
|
Utils::FilePaths *notRenamed) final;
|
||||||
void buildNamedTarget(const QString &target) final;
|
void buildNamedTarget(const QString &target) final;
|
||||||
|
|
||||||
Utils::FilePaths filesGeneratedFrom(const Utils::FilePath &sourceFile) const final;
|
Utils::FilePaths filesGeneratedFrom(const Utils::FilePath &sourceFile) const final;
|
||||||
@@ -157,6 +157,9 @@ private:
|
|||||||
Utils::FilePaths *);
|
Utils::FilePaths *);
|
||||||
bool addTsFiles(ProjectExplorer::Node *context, const Utils::FilePaths &filePaths,
|
bool addTsFiles(ProjectExplorer::Node *context, const Utils::FilePaths &filePaths,
|
||||||
Utils::FilePaths *);
|
Utils::FilePaths *);
|
||||||
|
bool renameFile(CMakeTargetNode *context,
|
||||||
|
const Utils::FilePath &oldFilePath,
|
||||||
|
const Utils::FilePath &newFilePath, bool &shouldRunCMake);
|
||||||
|
|
||||||
// Actually ask for parsing:
|
// Actually ask for parsing:
|
||||||
enum ReparseParameters {
|
enum ReparseParameters {
|
||||||
|
@@ -114,7 +114,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
RemovedFilesFromProject removeFiles(Node *, const FilePaths &filePaths, FilePaths *) final;
|
RemovedFilesFromProject removeFiles(Node *, const FilePaths &filePaths, FilePaths *) final;
|
||||||
bool renameFile(Node *, const FilePath &oldFilePath, const FilePath &newFilePath) final;
|
bool renameFiles(
|
||||||
|
Node *,
|
||||||
|
const Utils::FilePairs &filesToRename,
|
||||||
|
Utils::FilePaths *notRenamed) final;
|
||||||
bool addFiles(Node *, const FilePaths &filePaths, FilePaths *) final;
|
bool addFiles(Node *, const FilePaths &filePaths, FilePaths *) final;
|
||||||
QString name() const final { return QLatin1String("generic"); }
|
QString name() const final { return QLatin1String("generic"); }
|
||||||
|
|
||||||
@@ -376,21 +379,42 @@ bool GenericBuildSystem::setFiles(const QStringList &filePaths)
|
|||||||
return saveRawFileList(newList);
|
return saveRawFileList(newList);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GenericBuildSystem::renameFile(Node *, const FilePath &oldFilePath, const FilePath &newFilePath)
|
bool GenericBuildSystem::renameFiles(Node *, const FilePairs &filesToRename, FilePaths *notRenamed)
|
||||||
{
|
{
|
||||||
QStringList newList = m_rawFileList;
|
QStringList newList = m_rawFileList;
|
||||||
|
|
||||||
QHash<QString, QString>::iterator i = m_rawListEntries.find(oldFilePath.toString());
|
bool success = true;
|
||||||
if (i != m_rawListEntries.end()) {
|
for (const auto &[oldFilePath, newFilePath] : filesToRename) {
|
||||||
int index = newList.indexOf(i.value());
|
const auto fail = [&] {
|
||||||
if (index != -1) {
|
success = false;
|
||||||
QDir baseDir(projectDirectory().toString());
|
if (notRenamed)
|
||||||
newList.removeAt(index);
|
*notRenamed << oldFilePath;
|
||||||
insertSorted(&newList, baseDir.relativeFilePath(newFilePath.toString()));
|
};
|
||||||
|
|
||||||
|
const auto i = m_rawListEntries.find(oldFilePath.toString());
|
||||||
|
if (i == m_rawListEntries.end()) {
|
||||||
|
fail();
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int index = newList.indexOf(i.value());
|
||||||
|
if (index == -1) {
|
||||||
|
fail();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDir baseDir(projectDirectory().toString());
|
||||||
|
newList.removeAt(index);
|
||||||
|
insertSorted(&newList, baseDir.relativeFilePath(newFilePath.toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return saveRawFileList(newList);
|
if (!saveRawFileList(newList)) {
|
||||||
|
success = false;
|
||||||
|
if (notRenamed)
|
||||||
|
*notRenamed = firstPaths(filesToRename);
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QStringList readFlags(const QString &filePath)
|
static QStringList readFlags(const QString &filePath)
|
||||||
|
@@ -234,9 +234,17 @@ bool NimbleBuildSystem::deleteFiles(Node *, const FilePaths &)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NimbleBuildSystem::renameFile(Node *, const FilePath &oldFilePath, const FilePath &newFilePath)
|
bool NimbleBuildSystem::renameFiles(Node *, const FilePairs &filesToRename, FilePaths *notRenamed)
|
||||||
{
|
{
|
||||||
return m_projectScanner.renameFile(oldFilePath.toString(), newFilePath.toString());
|
bool success = true;
|
||||||
|
for (const auto &[oldFilePath, newFilePath] : filesToRename) {
|
||||||
|
if (!m_projectScanner.renameFile(oldFilePath.toString(), newFilePath.toString())) {
|
||||||
|
success = false;
|
||||||
|
if (notRenamed)
|
||||||
|
*notRenamed << oldFilePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // Nim
|
} // Nim
|
||||||
|
@@ -58,8 +58,10 @@ private:
|
|||||||
const Utils::FilePaths &filePaths,
|
const Utils::FilePaths &filePaths,
|
||||||
Utils::FilePaths *) override;
|
Utils::FilePaths *) override;
|
||||||
bool deleteFiles(ProjectExplorer::Node *, const Utils::FilePaths &) override;
|
bool deleteFiles(ProjectExplorer::Node *, const Utils::FilePaths &) override;
|
||||||
bool renameFile(ProjectExplorer::Node *,
|
bool renameFiles(
|
||||||
const Utils::FilePath &oldFilePath, const Utils::FilePath &newFilePath) override;
|
ProjectExplorer::Node *,
|
||||||
|
const Utils::FilePairs &filesToRename,
|
||||||
|
Utils::FilePaths *notRenamed) override;
|
||||||
QString name() const final { return QLatin1String("mimble"); }
|
QString name() const final { return QLatin1String("mimble"); }
|
||||||
void triggerParsing() final;
|
void triggerParsing() final;
|
||||||
|
|
||||||
|
@@ -152,7 +152,10 @@ public:
|
|||||||
const FilePaths &filePaths,
|
const FilePaths &filePaths,
|
||||||
FilePaths *) final;
|
FilePaths *) final;
|
||||||
bool deleteFiles(Node *, const FilePaths &) final;
|
bool deleteFiles(Node *, const FilePaths &) final;
|
||||||
bool renameFile(Node *, const FilePath &oldFilePath, const FilePath &newFilePath) final;
|
bool renameFiles(
|
||||||
|
Node *,
|
||||||
|
const Utils::FilePairs &filesToRename,
|
||||||
|
Utils::FilePaths *notRenamed) final;
|
||||||
QString name() const final { return QLatin1String("nim"); }
|
QString name() const final { return QLatin1String("nim"); }
|
||||||
|
|
||||||
void triggerParsing() final;
|
void triggerParsing() final;
|
||||||
@@ -237,9 +240,17 @@ bool NimBuildSystem::deleteFiles(Node *, const FilePaths &)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NimBuildSystem::renameFile(Node *, const FilePath &oldFilePath, const FilePath &newFilePath)
|
bool NimBuildSystem::renameFiles(Node *, const FilePairs &filesToRename, FilePaths *notRenamed)
|
||||||
{
|
{
|
||||||
return m_projectScanner.renameFile(oldFilePath.toString(), newFilePath.toString());
|
bool success = true;
|
||||||
|
for (const auto &[oldFilePath, newFilePath] : filesToRename) {
|
||||||
|
if (!m_projectScanner.renameFile(oldFilePath.toString(), newFilePath.toString())) {
|
||||||
|
success = false;
|
||||||
|
if (notRenamed)
|
||||||
|
*notRenamed << oldFilePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
BuildSystem *createNimBuildSystem(Target *target)
|
BuildSystem *createNimBuildSystem(Target *target)
|
||||||
|
@@ -224,10 +224,10 @@ bool BuildSystem::canRenameFile(Node *, const FilePath &oldFilePath, const FileP
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BuildSystem::renameFile(Node *, const FilePath &oldFilePath, const FilePath &newFilePath)
|
bool BuildSystem::renameFiles(Node *, const FilePairs &filesToRename, FilePaths *notRenamed)
|
||||||
{
|
{
|
||||||
Q_UNUSED(oldFilePath)
|
if (notRenamed)
|
||||||
Q_UNUSED(newFilePath)
|
*notRenamed = firstPaths(filesToRename);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -77,9 +77,8 @@ public:
|
|||||||
virtual bool canRenameFile(Node *context,
|
virtual bool canRenameFile(Node *context,
|
||||||
const Utils::FilePath &oldFilePath,
|
const Utils::FilePath &oldFilePath,
|
||||||
const Utils::FilePath &newFilePath);
|
const Utils::FilePath &newFilePath);
|
||||||
virtual bool renameFile(Node *context,
|
virtual bool renameFiles(
|
||||||
const Utils::FilePath &oldFilePath,
|
Node *context, const Utils::FilePairs &filesToRename, Utils::FilePaths *notRenamed);
|
||||||
const Utils::FilePath &newFilePath);
|
|
||||||
virtual bool addDependencies(Node *context, const QStringList &dependencies);
|
virtual bool addDependencies(Node *context, const QStringList &dependencies);
|
||||||
virtual bool supportsAction(Node *context, ProjectAction action, const Node *node) const;
|
virtual bool supportsAction(Node *context, ProjectAction action, const Node *node) const;
|
||||||
virtual void buildNamedTarget(const QString &target) { Q_UNUSED(target) }
|
virtual void buildNamedTarget(const QString &target) { Q_UNUSED(target) }
|
||||||
|
@@ -2478,16 +2478,88 @@ void ProjectExplorerPlugin::showOutputPaneForRunControl(RunControl *runControl)
|
|||||||
appOutputPane().showOutputPaneForRunControl(runControl);
|
appOutputPane().showOutputPaneForRunControl(runControl);
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<std::pair<FilePath, FilePath>> ProjectExplorerPlugin::renameFiles(
|
static HandleIncludeGuards canTryToRenameIncludeGuards(const Node *node)
|
||||||
const QList<std::pair<Node *, Utils::FilePath>> &nodesAndNewFilePaths)
|
|
||||||
{
|
{
|
||||||
QList<std::pair<FilePath, FilePath>> renamedFiles;
|
return node->asFileNode() && node->asFileNode()->fileType() == FileType::Header
|
||||||
for (const auto &[node, newFilePath] : nodesAndNewFilePaths) {
|
? HandleIncludeGuards::Yes : HandleIncludeGuards::No;
|
||||||
if (const auto res = renameFile(node, newFilePath.toString()))
|
}
|
||||||
renamedFiles << *res;
|
|
||||||
|
FilePairs ProjectExplorerPlugin::renameFiles(
|
||||||
|
const QList<std::pair<Node *, FilePath>> &nodesAndNewFilePaths)
|
||||||
|
{
|
||||||
|
const QList<std::pair<Node *, FilePath>> nodesAndNewFilePathsFiltered
|
||||||
|
= Utils::filtered(nodesAndNewFilePaths, [](const std::pair<Node *, FilePath> &elem) {
|
||||||
|
return !elem.first->filePath().equalsCaseSensitive(elem.second);
|
||||||
|
});
|
||||||
|
FilePaths renamedOnly;
|
||||||
|
FilePaths failedRenamings;
|
||||||
|
const auto renameFile = [&failedRenamings](const Node *node, const FilePath &newFilePath) {
|
||||||
|
if (!Core::FileUtils::renameFile(
|
||||||
|
node->filePath(), newFilePath, canTryToRenameIncludeGuards(node))) {
|
||||||
|
failedRenamings << node->filePath();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
QHash<FolderNode *, QList<std::pair<Node *, FilePath>>> renamingsPerParentNode;
|
||||||
|
for (const auto &elem : nodesAndNewFilePathsFiltered) {
|
||||||
|
if (FolderNode * const folderNode = elem.first->parentFolderNode())
|
||||||
|
renamingsPerParentNode[folderNode] << elem;
|
||||||
|
else if (renameFile(elem.first, elem.second))
|
||||||
|
renamedOnly << elem.first->filePath();
|
||||||
}
|
}
|
||||||
emit instance()->filesRenamed(renamedFiles);
|
|
||||||
return renamedFiles;
|
for (auto it = renamingsPerParentNode.cbegin(); it != renamingsPerParentNode.cend(); ++it) {
|
||||||
|
FilePairs toUpdateInProject;
|
||||||
|
for (const std::pair<Node *, FilePath> &elem : it.value()) {
|
||||||
|
const bool canUpdateProject
|
||||||
|
= it.key()->canRenameFile(elem.first->filePath(), elem.second);
|
||||||
|
if (renameFile(elem.first, elem.second)) {
|
||||||
|
if (canUpdateProject )
|
||||||
|
toUpdateInProject << std::make_pair(elem.first->filePath(), elem.second);
|
||||||
|
else
|
||||||
|
renamedOnly << elem.first->filePath();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (toUpdateInProject.isEmpty())
|
||||||
|
continue;
|
||||||
|
FilePaths notRenamed;
|
||||||
|
if (!it.key()->renameFiles(toUpdateInProject, ¬Renamed))
|
||||||
|
renamedOnly << notRenamed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!failedRenamings.isEmpty() || !renamedOnly.isEmpty()) {
|
||||||
|
const auto pathsAsHtmlList = [](const FilePaths &files) {
|
||||||
|
QString s("<ul>");
|
||||||
|
for (const FilePath &f : files)
|
||||||
|
s.append("<li>").append(f.toUserOutput()).append("</li>");
|
||||||
|
return s.append("</ul>");
|
||||||
|
};
|
||||||
|
QString failedRenamingsString;
|
||||||
|
if (!failedRenamings.isEmpty()) {
|
||||||
|
failedRenamingsString = Tr::tr("The following files could not be renamed: %1")
|
||||||
|
.arg(pathsAsHtmlList(failedRenamings));
|
||||||
|
}
|
||||||
|
QString renamedOnlyString;
|
||||||
|
if (!renamedOnly.isEmpty()) {
|
||||||
|
renamedOnlyString = Tr::tr(
|
||||||
|
"<br>The following files were renamed, but their project files could not "
|
||||||
|
"be updated accordingly: %1")
|
||||||
|
.arg(pathsAsHtmlList(renamedOnly));
|
||||||
|
}
|
||||||
|
QTimer::singleShot(0, m_instance, [message = failedRenamingsString + renamedOnlyString] {
|
||||||
|
QMessageBox::warning(
|
||||||
|
ICore::dialogParent(), Tr::tr("Renaming Did Not Fully Succeed"), message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
FilePairs allRenamedFiles;
|
||||||
|
for (const std::pair<Node *, FilePath> &candidate : nodesAndNewFilePathsFiltered) {
|
||||||
|
if (!failedRenamings.contains(candidate.first->filePath()))
|
||||||
|
allRenamedFiles.emplaceBack(candidate.first->filePath(), candidate.second);
|
||||||
|
}
|
||||||
|
emit instance()->filesRenamed(allRenamedFiles);
|
||||||
|
return allRenamedFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_TESTS
|
#ifdef WITH_TESTS
|
||||||
@@ -2761,7 +2833,7 @@ void ProjectExplorerPluginPrivate::extendFolderNavigationWidgetFactory()
|
|||||||
const QVector<FolderNode *> folderNodes = renamableFolderNodes(before, after);
|
const QVector<FolderNode *> folderNodes = renamableFolderNodes(before, after);
|
||||||
QVector<FolderNode *> failedNodes;
|
QVector<FolderNode *> failedNodes;
|
||||||
for (FolderNode *folder : folderNodes) {
|
for (FolderNode *folder : folderNodes) {
|
||||||
if (!folder->renameFile(before, after))
|
if (!folder->renameFiles({std::make_pair(before, after)}, nullptr))
|
||||||
failedNodes.append(folder);
|
failedNodes.append(folder);
|
||||||
}
|
}
|
||||||
if (!failedNodes.isEmpty()) {
|
if (!failedNodes.isEmpty()) {
|
||||||
@@ -3859,12 +3931,6 @@ void ProjectExplorerPluginPrivate::removeFile()
|
|||||||
Core::FileUtils::removeFiles(pathList, deleteFile);
|
Core::FileUtils::removeFiles(pathList, deleteFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
static HandleIncludeGuards canTryToRenameIncludeGuards(const Node *node)
|
|
||||||
{
|
|
||||||
return node->asFileNode() && node->asFileNode()->fileType() == FileType::Header
|
|
||||||
? HandleIncludeGuards::Yes : HandleIncludeGuards::No;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProjectExplorerPluginPrivate::duplicateFile()
|
void ProjectExplorerPluginPrivate::duplicateFile()
|
||||||
{
|
{
|
||||||
Node *currentNode = ProjectTree::currentNode();
|
Node *currentNode = ProjectTree::currentNode();
|
||||||
@@ -3959,67 +4025,6 @@ void ProjectExplorerPluginPrivate::handleRenameFile()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::pair<FilePath, FilePath>>
|
|
||||||
ProjectExplorerPlugin::renameFile(Node *node, const QString &newFileName)
|
|
||||||
{
|
|
||||||
const FilePath oldFilePath = node->filePath().absoluteFilePath();
|
|
||||||
FolderNode *folderNode = node->parentFolderNode();
|
|
||||||
QTC_ASSERT(folderNode, return {});
|
|
||||||
const QString projectFileName = folderNode->managingProject()->filePath().fileName();
|
|
||||||
|
|
||||||
const FilePath newFilePath = FilePath::fromString(newFileName);
|
|
||||||
|
|
||||||
if (oldFilePath.equalsCaseSensitive(newFilePath))
|
|
||||||
return {};
|
|
||||||
|
|
||||||
const HandleIncludeGuards handleGuards = canTryToRenameIncludeGuards(node);
|
|
||||||
if (!folderNode->canRenameFile(oldFilePath, newFilePath)) {
|
|
||||||
QTimer::singleShot(0, m_instance,
|
|
||||||
[oldFilePath, newFilePath, projectFileName, handleGuards] {
|
|
||||||
int res = QMessageBox::question(ICore::dialogParent(),
|
|
||||||
Tr::tr("Project Editing Failed"),
|
|
||||||
Tr::tr("The project file %1 cannot be automatically changed.\n\n"
|
|
||||||
"Rename %2 to %3 anyway?")
|
|
||||||
.arg(projectFileName)
|
|
||||||
.arg(oldFilePath.toUserOutput())
|
|
||||||
.arg(newFilePath.toUserOutput()));
|
|
||||||
if (res == QMessageBox::Yes) {
|
|
||||||
QTC_CHECK(Core::FileUtils::renameFile(oldFilePath, newFilePath, handleGuards));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Core::FileUtils::renameFile(oldFilePath, newFilePath, handleGuards)) {
|
|
||||||
// Tell the project plugin about rename
|
|
||||||
// TODO: We might want to separate this into an extra step to make bulk renamings safer;
|
|
||||||
// see CppModelManager::renameIncludes().
|
|
||||||
if (!folderNode->renameFile(oldFilePath, newFilePath)) {
|
|
||||||
const QString renameFileError = Tr::tr("The file %1 was renamed to %2, but the project "
|
|
||||||
"file %3 could not be automatically changed.")
|
|
||||||
.arg(oldFilePath.toUserOutput())
|
|
||||||
.arg(newFilePath.toUserOutput())
|
|
||||||
.arg(projectFileName);
|
|
||||||
|
|
||||||
QTimer::singleShot(0, m_instance, [renameFileError] {
|
|
||||||
QMessageBox::warning(ICore::dialogParent(),
|
|
||||||
Tr::tr("Project Editing Failed"),
|
|
||||||
renameFileError);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return std::make_pair(oldFilePath, newFilePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString renameFileError = Tr::tr("The file %1 could not be renamed %2.")
|
|
||||||
.arg(oldFilePath.toUserOutput())
|
|
||||||
.arg(newFilePath.toUserOutput());
|
|
||||||
|
|
||||||
QTimer::singleShot(0, m_instance, [renameFileError] {
|
|
||||||
QMessageBox::warning(ICore::dialogParent(), Tr::tr("Cannot Rename File"), renameFileError);
|
|
||||||
});
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProjectExplorerPluginPrivate::handleSetStartupProject()
|
void ProjectExplorerPluginPrivate::handleSetStartupProject()
|
||||||
{
|
{
|
||||||
setStartupProject(ProjectTree::currentProject());
|
setStartupProject(ProjectTree::currentProject());
|
||||||
@@ -4133,7 +4138,7 @@ void ProjectExplorerPlugin::renameFilesForSymbol(const QString &oldSymbolName,
|
|||||||
const QString &newSymbolName, const FilePaths &files, bool preferLowerCaseFileNames)
|
const QString &newSymbolName, const FilePaths &files, bool preferLowerCaseFileNames)
|
||||||
{
|
{
|
||||||
static const auto isAllLowerCase = [](const QString &text) { return text.toLower() == text; };
|
static const auto isAllLowerCase = [](const QString &text) { return text.toLower() == text; };
|
||||||
QList<std::pair<FilePath, FilePath>> renamedFiles;
|
QList<std::pair<Node *, FilePath>> filesToRename;
|
||||||
for (const FilePath &file : files) {
|
for (const FilePath &file : files) {
|
||||||
Node * const node = ProjectTree::nodeForFile(file);
|
Node * const node = ProjectTree::nodeForFile(file);
|
||||||
if (!node)
|
if (!node)
|
||||||
@@ -4164,10 +4169,9 @@ void ProjectExplorerPlugin::renameFilesForSymbol(const QString &oldSymbolName,
|
|||||||
|
|
||||||
const QString newFilePath = file.absolutePath().toString() + '/' + newBaseName + '.'
|
const QString newFilePath = file.absolutePath().toString() + '/' + newBaseName + '.'
|
||||||
+ file.completeSuffix();
|
+ file.completeSuffix();
|
||||||
if (const auto res = renameFile(node, newFilePath))
|
filesToRename.emplaceBack(node, FilePath::fromString(newFilePath));
|
||||||
renamedFiles << *res;
|
|
||||||
}
|
}
|
||||||
emit instance()->filesRenamed(renamedFiles);
|
renameFiles(filesToRename);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProjectManager::registerProjectCreator(const QString &mimeType,
|
void ProjectManager::registerProjectCreator(const QString &mimeType,
|
||||||
|
@@ -123,8 +123,8 @@ public:
|
|||||||
static void startRunControl(RunControl *runControl);
|
static void startRunControl(RunControl *runControl);
|
||||||
static void showOutputPaneForRunControl(RunControl *runControl);
|
static void showOutputPaneForRunControl(RunControl *runControl);
|
||||||
|
|
||||||
static QList<std::pair<Utils::FilePath, Utils::FilePath>>
|
static Utils::FilePairs renameFiles(
|
||||||
renameFiles(const QList<std::pair<Node *, Utils::FilePath>> &nodesAndNewFilePaths);
|
const QList<std::pair<Node *, Utils::FilePath>> &nodesAndNewFilePaths);
|
||||||
|
|
||||||
#ifdef WITH_TESTS
|
#ifdef WITH_TESTS
|
||||||
static bool renameFile(const Utils::FilePath &source, const Utils::FilePath &target,
|
static bool renameFile(const Utils::FilePath &source, const Utils::FilePath &target,
|
||||||
@@ -182,13 +182,11 @@ signals:
|
|||||||
void runControlStarted(ProjectExplorer::RunControl *runControl);
|
void runControlStarted(ProjectExplorer::RunControl *runControl);
|
||||||
void runControlStoped(ProjectExplorer::RunControl *runControl);
|
void runControlStoped(ProjectExplorer::RunControl *runControl);
|
||||||
|
|
||||||
void filesRenamed(const QList<std::pair<Utils::FilePath, Utils::FilePath>> &oldAndNewPaths);
|
void filesRenamed(const Utils::FilePairs &oldAndNewPaths);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool coreAboutToClose();
|
static bool coreAboutToClose();
|
||||||
void handleCommandLineArguments(const QStringList &arguments);
|
void handleCommandLineArguments(const QStringList &arguments);
|
||||||
static std::optional<std::pair<Utils::FilePath, Utils::FilePath>>
|
|
||||||
renameFile(Node *node, const QString &newFilePath);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ProjectExplorer
|
} // namespace ProjectExplorer
|
||||||
|
@@ -837,11 +837,11 @@ bool FolderNode::canRenameFile(const FilePath &oldFilePath, const FilePath &newF
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FolderNode::renameFile(const FilePath &oldFilePath, const FilePath &newFilePath)
|
bool FolderNode::renameFiles(const FilePairs &filesToRename, FilePaths *notRenamed)
|
||||||
{
|
{
|
||||||
ProjectNode *pn = managingProject();
|
ProjectNode *pn = managingProject();
|
||||||
if (pn)
|
if (pn)
|
||||||
return pn->renameFile(oldFilePath, newFilePath);
|
return pn->renameFiles(filesToRename, notRenamed);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -970,17 +970,20 @@ bool ProjectNode::deleteFiles(const FilePaths &filePaths)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProjectNode::canRenameFile(const Utils::FilePath &oldFilePath, const Utils::FilePath &newFilePath)
|
bool ProjectNode::canRenameFile(
|
||||||
|
const Utils::FilePath &oldFilePath, const Utils::FilePath &newFilePath)
|
||||||
{
|
{
|
||||||
if (BuildSystem *bs = buildSystem())
|
if (BuildSystem * const bs = buildSystem())
|
||||||
return bs->canRenameFile(this, oldFilePath, newFilePath);
|
return bs->canRenameFile(this, oldFilePath, newFilePath);
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProjectNode::renameFile(const Utils::FilePath &oldFilePath, const Utils::FilePath &newFilePath)
|
bool ProjectNode::renameFiles(const FilePairs &filesToRename, FilePaths *notRenamed)
|
||||||
{
|
{
|
||||||
if (BuildSystem *bs = buildSystem())
|
if (BuildSystem *bs = buildSystem())
|
||||||
return bs->renameFile(this, oldFilePath, newFilePath);
|
return bs->renameFiles(this, filesToRename, notRenamed);
|
||||||
|
if (notRenamed)
|
||||||
|
*notRenamed = firstPaths(filesToRename);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <utility>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
namespace Utils { class MimeType; }
|
namespace Utils { class MimeType; }
|
||||||
@@ -300,7 +301,7 @@ public:
|
|||||||
virtual bool deleteFiles(const Utils::FilePaths &filePaths);
|
virtual bool deleteFiles(const Utils::FilePaths &filePaths);
|
||||||
virtual bool canRenameFile(const Utils::FilePath &oldFilePath,
|
virtual bool canRenameFile(const Utils::FilePath &oldFilePath,
|
||||||
const Utils::FilePath &newFilePath);
|
const Utils::FilePath &newFilePath);
|
||||||
virtual bool renameFile(const Utils::FilePath &oldFilePath, const Utils::FilePath &newFilePath);
|
virtual bool renameFiles(const Utils::FilePairs &filesToRename, Utils::FilePaths *notRenamed);
|
||||||
virtual bool addDependencies(const QStringList &dependencies);
|
virtual bool addDependencies(const QStringList &dependencies);
|
||||||
|
|
||||||
class AddNewInformation
|
class AddNewInformation
|
||||||
@@ -382,8 +383,9 @@ public:
|
|||||||
RemovedFilesFromProject removeFiles(const Utils::FilePaths &filePaths,
|
RemovedFilesFromProject removeFiles(const Utils::FilePaths &filePaths,
|
||||||
Utils::FilePaths *notRemoved = nullptr) final;
|
Utils::FilePaths *notRemoved = nullptr) final;
|
||||||
bool deleteFiles(const Utils::FilePaths &filePaths) final;
|
bool deleteFiles(const Utils::FilePaths &filePaths) final;
|
||||||
bool canRenameFile(const Utils::FilePath &oldFilePath, const Utils::FilePath &newFilePath) final;
|
bool canRenameFile(
|
||||||
bool renameFile(const Utils::FilePath &oldFilePath, const Utils::FilePath &newFilePath) final;
|
const Utils::FilePath &oldFilePath, const Utils::FilePath &newFilePath) override;
|
||||||
|
bool renameFiles(const Utils::FilePairs &filesToRename, Utils::FilePaths *notRenamed) final;
|
||||||
bool addDependencies(const QStringList &dependencies) final;
|
bool addDependencies(const QStringList &dependencies) final;
|
||||||
bool supportsAction(ProjectAction action, const Node *node) const final;
|
bool supportsAction(ProjectAction action, const Node *node) const final;
|
||||||
|
|
||||||
|
@@ -305,17 +305,33 @@ bool PythonBuildSystem::deleteFiles(Node *, const FilePaths &)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PythonBuildSystem::renameFile(Node *, const FilePath &oldFilePath, const FilePath &newFilePath)
|
bool PythonBuildSystem::renameFiles(Node *, const FilePairs &filesToRename, FilePaths *notRenamed)
|
||||||
{
|
{
|
||||||
for (FileEntry &entry : m_files) {
|
bool success = true;
|
||||||
if (entry.filePath == oldFilePath) {
|
for (const auto &[oldFilePath, newFilePath] : filesToRename) {
|
||||||
entry.filePath = newFilePath;
|
bool found = false;
|
||||||
entry.rawEntry = newFilePath.relativeChildPath(projectDirectory()).toString();
|
for (FileEntry &entry : m_files) {
|
||||||
break;
|
if (entry.filePath == oldFilePath) {
|
||||||
|
found = true;
|
||||||
|
entry.filePath = newFilePath;
|
||||||
|
entry.rawEntry = newFilePath.relativeChildPath(projectDirectory()).toString();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
success = false;
|
||||||
|
if (notRenamed)
|
||||||
|
*notRenamed << oldFilePath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return save();
|
if (!save()) {
|
||||||
|
if (notRenamed)
|
||||||
|
*notRenamed = firstPaths(filesToRename);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PythonBuildSystem::parse()
|
void PythonBuildSystem::parse()
|
||||||
|
@@ -25,9 +25,10 @@ public:
|
|||||||
const Utils::FilePaths &filePaths,
|
const Utils::FilePaths &filePaths,
|
||||||
Utils::FilePaths *) override;
|
Utils::FilePaths *) override;
|
||||||
bool deleteFiles(ProjectExplorer::Node *, const Utils::FilePaths &) override;
|
bool deleteFiles(ProjectExplorer::Node *, const Utils::FilePaths &) override;
|
||||||
bool renameFile(ProjectExplorer::Node *,
|
bool renameFiles(
|
||||||
const Utils::FilePath &oldFilePath,
|
ProjectExplorer::Node *,
|
||||||
const Utils::FilePath &newFilePath) override;
|
const Utils::FilePairs &filesToRename,
|
||||||
|
Utils::FilePaths *notRenamed) override;
|
||||||
QString name() const override { return QLatin1String("python"); }
|
QString name() const override { return QLatin1String("python"); }
|
||||||
|
|
||||||
void parse();
|
void parse();
|
||||||
|
@@ -267,27 +267,43 @@ RemovedFilesFromProject QbsBuildSystem::removeFiles(Node *context, const FilePat
|
|||||||
return BuildSystem::removeFiles(context, filePaths, notRemoved);
|
return BuildSystem::removeFiles(context, filePaths, notRemoved);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QbsBuildSystem::renameFile(Node *context,
|
bool QbsBuildSystem::renameFiles(Node *context, const FilePairs &filesToRename, FilePaths *notRenamed)
|
||||||
const FilePath &oldFilePath,
|
|
||||||
const FilePath &newFilePath)
|
|
||||||
{
|
{
|
||||||
if (auto *n = dynamic_cast<QbsGroupNode *>(context)) {
|
if (auto *n = dynamic_cast<QbsGroupNode *>(context)) {
|
||||||
const QbsProductNode * const prdNode = parentQbsProductNode(n);
|
const QbsProductNode * const prdNode = parentQbsProductNode(n);
|
||||||
QTC_ASSERT(prdNode, return false);
|
QTC_ASSERT(prdNode, return false);
|
||||||
return renameFileInProduct(oldFilePath.toString(),
|
bool success = true;
|
||||||
newFilePath.toString(),
|
for (const auto &[oldFilePath, newFilePath] : filesToRename) {
|
||||||
prdNode->productData(),
|
if (!renameFileInProduct(
|
||||||
n->groupData());
|
oldFilePath.toString(),
|
||||||
|
newFilePath.toString(),
|
||||||
|
prdNode->productData(),
|
||||||
|
n->groupData())) {
|
||||||
|
success = false;
|
||||||
|
if (notRenamed)
|
||||||
|
*notRenamed << oldFilePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto *n = dynamic_cast<QbsProductNode *>(context)) {
|
if (auto *n = dynamic_cast<QbsProductNode *>(context)) {
|
||||||
return renameFileInProduct(oldFilePath.toString(),
|
bool success = true;
|
||||||
newFilePath.toString(),
|
for (const auto &[oldFilePath, newFilePath] : filesToRename) {
|
||||||
n->productData(),
|
if (!renameFileInProduct(
|
||||||
n->mainGroup());
|
oldFilePath.toString(),
|
||||||
|
newFilePath.toString(),
|
||||||
|
n->productData(),
|
||||||
|
n->mainGroup())) {
|
||||||
|
success = false;
|
||||||
|
if (notRenamed)
|
||||||
|
*notRenamed << oldFilePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
return BuildSystem::renameFile(context, oldFilePath, newFilePath);
|
return BuildSystem::renameFiles(context, filesToRename, notRenamed);
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant QbsBuildSystem::additionalData(Id id) const
|
QVariant QbsBuildSystem::additionalData(Id id) const
|
||||||
@@ -409,6 +425,7 @@ bool QbsBuildSystem::renameFileInProduct(
|
|||||||
if (newPath.isEmpty())
|
if (newPath.isEmpty())
|
||||||
return false;
|
return false;
|
||||||
FilePaths dummy;
|
FilePaths dummy;
|
||||||
|
// FIXME: The qbs API need a (bulk) renaming feature
|
||||||
if (removeFilesFromProduct({FilePath::fromString(oldPath)}, product, group, &dummy)
|
if (removeFilesFromProduct({FilePath::fromString(oldPath)}, product, group, &dummy)
|
||||||
!= RemovedFilesFromProject::Ok) {
|
!= RemovedFilesFromProject::Ok) {
|
||||||
return false;
|
return false;
|
||||||
|
@@ -67,8 +67,10 @@ public:
|
|||||||
ProjectExplorer::RemovedFilesFromProject removeFiles(ProjectExplorer::Node *context,
|
ProjectExplorer::RemovedFilesFromProject removeFiles(ProjectExplorer::Node *context,
|
||||||
const Utils::FilePaths &filePaths,
|
const Utils::FilePaths &filePaths,
|
||||||
Utils::FilePaths *notRemoved = nullptr) final;
|
Utils::FilePaths *notRemoved = nullptr) final;
|
||||||
bool renameFile(ProjectExplorer::Node *context,
|
bool renameFiles(
|
||||||
const Utils::FilePath &oldFilePath, const Utils::FilePath &newFilePath) final;
|
ProjectExplorer::Node *context,
|
||||||
|
const Utils::FilePairs &filesToRename,
|
||||||
|
Utils::FilePaths *notRenamed) final;
|
||||||
Utils::FilePaths filesGeneratedFrom(const Utils::FilePath &sourceFile) const final;
|
Utils::FilePaths filesGeneratedFrom(const Utils::FilePath &sourceFile) const final;
|
||||||
QVariant additionalData(Utils::Id id) const final;
|
QVariant additionalData(Utils::Id id) const final;
|
||||||
QString name() const final { return QLatin1String("qbs"); }
|
QString name() const final { return QLatin1String("qbs"); }
|
||||||
|
@@ -254,16 +254,27 @@ bool QmakeBuildSystem::canRenameFile(Node *context,
|
|||||||
return BuildSystem::canRenameFile(context, oldFilePath, newFilePath);
|
return BuildSystem::canRenameFile(context, oldFilePath, newFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QmakeBuildSystem::renameFile(Node *context,
|
bool QmakeBuildSystem::renameFiles(Node *context, const FilePairs &filesToRename, FilePaths *notRenamed)
|
||||||
const FilePath &oldFilePath,
|
|
||||||
const FilePath &newFilePath)
|
|
||||||
{
|
{
|
||||||
if (auto n = dynamic_cast<QmakePriFileNode *>(context)) {
|
if (auto n = dynamic_cast<QmakePriFileNode *>(context)) {
|
||||||
QmakePriFile *pri = n->priFile();
|
QmakePriFile *pri = n->priFile();
|
||||||
return pri ? pri->renameFile(oldFilePath, newFilePath) : false;
|
if (!pri) {
|
||||||
|
if (notRenamed)
|
||||||
|
*notRenamed = firstPaths(filesToRename);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool success = true;
|
||||||
|
for (const auto &[oldFilePath, newFilePath] : filesToRename) {
|
||||||
|
if (!pri->renameFile(oldFilePath, newFilePath)) {
|
||||||
|
success = false;
|
||||||
|
if (notRenamed)
|
||||||
|
*notRenamed << oldFilePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
return BuildSystem::renameFile(context, oldFilePath, newFilePath);
|
return BuildSystem::renameFiles(context, filesToRename, notRenamed);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QmakeBuildSystem::addDependencies(Node *context, const QStringList &dependencies)
|
bool QmakeBuildSystem::addDependencies(Node *context, const QStringList &dependencies)
|
||||||
|
@@ -79,9 +79,9 @@ public:
|
|||||||
bool canRenameFile(ProjectExplorer::Node *context,
|
bool canRenameFile(ProjectExplorer::Node *context,
|
||||||
const Utils::FilePath &oldFilePath,
|
const Utils::FilePath &oldFilePath,
|
||||||
const Utils::FilePath &newFilePath) override;
|
const Utils::FilePath &newFilePath) override;
|
||||||
bool renameFile(ProjectExplorer::Node *context,
|
bool renameFiles(ProjectExplorer::Node *context,
|
||||||
const Utils::FilePath &oldFilePath,
|
const Utils::FilePairs &filesToRename,
|
||||||
const Utils::FilePath &newFilePath) override;
|
Utils::FilePaths *notRenamed) override;
|
||||||
bool addDependencies(ProjectExplorer::Node *context,
|
bool addDependencies(ProjectExplorer::Node *context,
|
||||||
const QStringList &dependencies) override;
|
const QStringList &dependencies) override;
|
||||||
QString name() const final { return QLatin1String("qmake"); }
|
QString name() const final { return QLatin1String("qmake"); }
|
||||||
|
@@ -627,19 +627,35 @@ bool QmlBuildSystem::deleteFiles(Node *context, const Utils::FilePaths &filePath
|
|||||||
return BuildSystem::deleteFiles(context, filePaths);
|
return BuildSystem::deleteFiles(context, filePaths);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QmlBuildSystem::renameFile(Node *context,
|
bool QmlBuildSystem::renameFiles(Node *context,
|
||||||
const Utils::FilePath &oldFilePath,
|
const Utils::FilePairs &filesToRename,
|
||||||
const Utils::FilePath &newFilePath)
|
Utils::FilePaths *notRenamed)
|
||||||
{
|
{
|
||||||
if (dynamic_cast<Internal::QmlProjectNode *>(context)) {
|
if (!dynamic_cast<Internal::QmlProjectNode *>(context))
|
||||||
if (oldFilePath.endsWith(mainFile()))
|
return BuildSystem::renameFiles(context, filesToRename, notRenamed);
|
||||||
return setMainFileInProjectFile(newFilePath);
|
|
||||||
if (oldFilePath.endsWith(m_projectItem->mainUiFile()))
|
bool success = true;
|
||||||
return setMainUiFileInProjectFile(newFilePath);
|
for (const auto &[oldFilePath, newFilePath] : filesToRename) {
|
||||||
return true;
|
const auto fail = [&] {
|
||||||
|
success = false;
|
||||||
|
if (notRenamed)
|
||||||
|
*notRenamed << oldFilePath;
|
||||||
|
};
|
||||||
|
if (oldFilePath.endsWith(mainFile())) {
|
||||||
|
if (!setMainFileInProjectFile(newFilePath))
|
||||||
|
fail();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (oldFilePath.endsWith(m_projectItem->mainUiFile())) {
|
||||||
|
if (!setMainUiFileInProjectFile(newFilePath))
|
||||||
|
fail();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Why is this not an error?
|
||||||
}
|
}
|
||||||
|
|
||||||
return BuildSystem::renameFile(context, oldFilePath, newFilePath);
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QmlBuildSystem::mainFile() const
|
QString QmlBuildSystem::mainFile() const
|
||||||
|
@@ -35,9 +35,9 @@ public:
|
|||||||
const Utils::FilePaths &filePaths,
|
const Utils::FilePaths &filePaths,
|
||||||
Utils::FilePaths *notAdded = nullptr) override;
|
Utils::FilePaths *notAdded = nullptr) override;
|
||||||
bool deleteFiles(ProjectExplorer::Node *context, const Utils::FilePaths &filePaths) override;
|
bool deleteFiles(ProjectExplorer::Node *context, const Utils::FilePaths &filePaths) override;
|
||||||
bool renameFile(ProjectExplorer::Node *context,
|
bool renameFiles(ProjectExplorer::Node *context,
|
||||||
const Utils::FilePath &oldFilePath,
|
const Utils::FilePairs &filesToRename,
|
||||||
const Utils::FilePath &newFilePath) override;
|
Utils::FilePaths *notRenamed) override;
|
||||||
|
|
||||||
bool updateProjectFile();
|
bool updateProjectFile();
|
||||||
|
|
||||||
|
@@ -157,7 +157,7 @@ public:
|
|||||||
RemovedFilesFromProject removeFiles(const Utils::FilePaths &filePaths,
|
RemovedFilesFromProject removeFiles(const Utils::FilePaths &filePaths,
|
||||||
Utils::FilePaths *notRemoved) final;
|
Utils::FilePaths *notRemoved) final;
|
||||||
bool canRenameFile(const Utils::FilePath &oldFilePath, const Utils::FilePath &newFilePath) override;
|
bool canRenameFile(const Utils::FilePath &oldFilePath, const Utils::FilePath &newFilePath) override;
|
||||||
bool renameFile(const Utils::FilePath &oldFilePath, const Utils::FilePath &newFilePath) final;
|
bool renameFiles(const FilePairs &filesToRename, FilePaths *notRenamed) final;
|
||||||
|
|
||||||
QString prefix() const { return m_prefix; }
|
QString prefix() const { return m_prefix; }
|
||||||
ResourceTopLevelNode *resourceNode() const { return m_topLevelNode; }
|
ResourceTopLevelNode *resourceNode() const { return m_topLevelNode; }
|
||||||
@@ -211,9 +211,9 @@ bool SimpleResourceFolderNode::canRenameFile(const FilePath &oldFilePath,
|
|||||||
return prefixNode()->canRenameFile(oldFilePath, newFilePath);
|
return prefixNode()->canRenameFile(oldFilePath, newFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SimpleResourceFolderNode::renameFile(const FilePath &oldFilePath, const FilePath &newFilePath)
|
bool SimpleResourceFolderNode::renameFiles(const FilePairs &filesToRename, FilePaths *notRenamed)
|
||||||
{
|
{
|
||||||
return prefixNode()->renameFile(oldFilePath, newFilePath);
|
return prefixNode()->renameFiles(filesToRename, notRenamed);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // Internal
|
} // Internal
|
||||||
@@ -531,7 +531,7 @@ bool ResourceFolderNode::canRenameFile(const FilePath &oldFilePath, const FilePa
|
|||||||
return fileEntryExists;
|
return fileEntryExists;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ResourceFolderNode::renameFile(const FilePath &oldFilePath, const FilePath &newFilePath)
|
bool ResourceFolderNode::renameFiles(const FilePairs &filesToRename, FilePaths *notRenamed)
|
||||||
{
|
{
|
||||||
ResourceFile file(m_topLevelNode->filePath());
|
ResourceFile file(m_topLevelNode->filePath());
|
||||||
if (file.load() != IDocument::OpenResult::Success)
|
if (file.load() != IDocument::OpenResult::Success)
|
||||||
@@ -540,16 +540,27 @@ bool ResourceFolderNode::renameFile(const FilePath &oldFilePath, const FilePath
|
|||||||
if (index == -1)
|
if (index == -1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (int j = 0; j < file.fileCount(index); ++j) {
|
bool success = true;
|
||||||
if (file.file(index, j) == oldFilePath.toString()) {
|
for (const auto &[oldFilePath, newFilePath] : filesToRename) {
|
||||||
file.replaceFile(index, j, newFilePath.toString());
|
bool found = false;
|
||||||
FileChangeBlocker changeGuard(m_topLevelNode->filePath());
|
for (int j = 0; j < file.fileCount(index); ++j) {
|
||||||
file.save();
|
if (file.file(index, j) == oldFilePath.toString()) {
|
||||||
return true;
|
file.replaceFile(index, j, newFilePath.toString());
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
success = false;
|
||||||
|
if (notRenamed)
|
||||||
|
*notRenamed << oldFilePath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
FileChangeBlocker changeGuard(m_topLevelNode->filePath());
|
||||||
|
file.save();
|
||||||
|
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ResourceFolderNode::renamePrefix(const QString &prefix, const QString &lang)
|
bool ResourceFolderNode::renamePrefix(const QString &prefix, const QString &lang)
|
||||||
|
@@ -55,7 +55,8 @@ public:
|
|||||||
ProjectExplorer::RemovedFilesFromProject removeFiles(const Utils::FilePaths &filePaths,
|
ProjectExplorer::RemovedFilesFromProject removeFiles(const Utils::FilePaths &filePaths,
|
||||||
Utils::FilePaths *notRemoved) override;
|
Utils::FilePaths *notRemoved) override;
|
||||||
bool canRenameFile(const Utils::FilePath &oldFilePath, const Utils::FilePath &newFilePath) override;
|
bool canRenameFile(const Utils::FilePath &oldFilePath, const Utils::FilePath &newFilePath) override;
|
||||||
bool renameFile(const Utils::FilePath &oldFilePath, const Utils::FilePath &newFilePath) override;
|
bool renameFiles(
|
||||||
|
const Utils::FilePairs &filesToRename, Utils::FilePaths *notRenamed) override;
|
||||||
|
|
||||||
bool renamePrefix(const QString &prefix, const QString &lang);
|
bool renamePrefix(const QString &prefix, const QString &lang);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user