Commit 798fa669 authored by Daniel Teske's avatar Daniel Teske

ProjectExplorer: Check if the project can rename a specific file

before renaming the file.

This adds a new api:
FolderNode::canRename(oldFileName, newFileName) that asks the
project manager if a specific file renaming could be applied to
the project file.

Change-Id: I77bae56db06d81fd03e590285d6079abea2c514b
Task-number: QTCREATORBUG-14521
Reviewed-by: default avatarTobias Hunger <tobias.hunger@theqtcompany.com>
parent 366e89e9
......@@ -3264,11 +3264,28 @@ void ProjectExplorerPluginPrivate::handleRenameFile()
void ProjectExplorerPlugin::renameFile(Node *node, const QString &newFilePath)
{
QString orgFilePath = node->path().toFileInfo().absoluteFilePath();
FolderNode *folderNode = node->parentFolderNode();
QString projectFileName = folderNode->projectNode()->path().fileName();
if (!folderNode->canRenameFile(orgFilePath, newFilePath)) {
QTimer::singleShot(0, [orgFilePath, newFilePath, projectFileName] {
int res = QMessageBox::question(ICore::mainWindow(),
tr("Project Editing Failed"),
tr("The project file %1 cannot be automatically changed\n\n"
"Rename %2 to %3 anyway?")
.arg(projectFileName)
.arg(orgFilePath)
.arg(newFilePath));
if (res == QMessageBox::Yes)
FileUtils::renameFile(orgFilePath, newFilePath);
});
return;
}
if (FileUtils::renameFile(orgFilePath, newFilePath)) {
// Tell the project plugin about rename
FolderNode *folderNode = node->parentFolderNode();
QString projectFileName = folderNode->projectNode()->path().fileName();
if (!folderNode->renameFile(orgFilePath, newFilePath)) {
QString renameFileError = tr("The file %1 was renamed to %2, but the project file %3 could not be automatically changed.")
.arg(orgFilePath)
......
......@@ -357,6 +357,13 @@ bool FolderNode::deleteFiles(const QStringList &filePaths)
return false;
}
bool FolderNode::canRenameFile(const QString &filePath, const QString &newFilePath)
{
if (projectNode())
return projectNode()->canRenameFile(filePath, newFilePath);
return false;
}
bool FolderNode::renameFile(const QString &filePath, const QString &newFilePath)
{
if (projectNode())
......@@ -629,6 +636,13 @@ bool ProjectNode::deleteFiles(const QStringList &filePaths)
return false;
}
bool ProjectNode::canRenameFile(const QString &filePath, const QString &newFilePath)
{
Q_UNUSED(filePath);
Q_UNUSED(newFilePath);
return true;
}
bool ProjectNode::renameFile(const QString &filePath, const QString &newFilePath)
{
Q_UNUSED(filePath)
......
......@@ -188,6 +188,7 @@ public:
virtual bool addFiles(const QStringList &filePaths, QStringList *notAdded = 0);
virtual bool removeFiles(const QStringList &filePaths, QStringList *notRemoved = 0);
virtual bool deleteFiles(const QStringList &filePaths);
virtual bool canRenameFile(const QString &filePath, const QString &newFilePath);
virtual bool renameFile(const QString &filePath, const QString &newFilePath);
class AddNewInformation
......@@ -252,6 +253,7 @@ public:
bool addFiles(const QStringList &filePaths, QStringList *notAdded = 0) override;
bool removeFiles(const QStringList &filePaths, QStringList *notRemoved = 0) override;
bool deleteFiles(const QStringList &filePaths) override;
bool canRenameFile(const QString &filePath, const QString &newFilePath) override;
bool renameFile(const QString &filePath, const QString &newFilePath) override;
// by default returns false
......
......@@ -1108,23 +1108,32 @@ bool QmakePriFileNode::deleteFiles(const QStringList &filePaths)
return true;
}
bool QmakePriFileNode::renameFile(const QString &filePath, const QString &newFilePath)
bool QmakePriFileNode::canRenameFile(const QString &filePath, const QString &newFilePath)
{
if (newFilePath.isEmpty())
return false;
bool changeProFileOptional = deploysFolder(QFileInfo(filePath).absolutePath());
if (changeProFileOptional)
return true;
Utils::MimeDatabase mdb;
const Utils::MimeType mt = mdb.mimeTypeForFile(newFilePath);
QStringList dummy;
changeFiles(mt.name(), QStringList() << filePath, &dummy, RemoveFromProFile);
if (!dummy.isEmpty() && !changeProFileOptional)
return false;
changeFiles(mt.name(), QStringList() << newFilePath, &dummy, AddToProFile);
if (!dummy.isEmpty() && !changeProFileOptional)
return renameFile(filePath, newFilePath, mt.name(), Change::TestOnly);
}
bool QmakePriFileNode::renameFile(const QString &filePath, const QString &newFilePath)
{
if (newFilePath.isEmpty())
return false;
return true;
bool changeProFileOptional = deploysFolder(QFileInfo(filePath).absolutePath());
Utils::MimeDatabase mdb;
const Utils::MimeType mt = mdb.mimeTypeForFile(newFilePath);
if (renameFile(filePath, newFilePath, mt.name()))
return true;
return changeProFileOptional;
}
FolderNode::AddNewInformation QmakePriFileNode::addNewInformation(const QStringList &files, Node *context) const
......@@ -1235,10 +1244,47 @@ QPair<ProFile *, QStringList> QmakePriFileNode::readProFile(const QString &file)
return qMakePair(includeFile, lines);
}
bool QmakePriFileNode::prepareForChange()
{
return saveModifiedEditors() && ensureWriteableProFile(m_projectFilePath.toString());
}
bool QmakePriFileNode::renameFile(const QString &oldName,
const QString &newName,
const QString &mimeType,
Change mode)
{
if (!prepareForChange())
return false;
QPair<ProFile *, QStringList> pair = readProFile(m_projectFilePath.toString());
ProFile *includeFile = pair.first;
QStringList lines = pair.second;
if (!includeFile)
return false;
QDir priFileDir = QDir(m_qmakeProFileNode->m_projectDir);
QStringList notChanged = ProWriter::removeFiles(includeFile, &lines, priFileDir,
QStringList(oldName), varNamesForRemoving());
if (!notChanged.isEmpty()) {
includeFile->deref();
return false;
}
ProWriter::addFiles(includeFile, &lines,
QStringList(newName),
varNameForAdding(mimeType));
if (mode == Change::Save)
save(lines);
includeFile->deref();
return true;
}
void QmakePriFileNode::changeFiles(const QString &mimeType,
const QStringList &filePaths,
QStringList *notChanged,
ChangeType change)
ChangeType change, Change mode)
{
if (filePaths.isEmpty())
return;
......@@ -1246,11 +1292,9 @@ void QmakePriFileNode::changeFiles(const QString &mimeType,
*notChanged = filePaths;
// Check for modified editors
if (!saveModifiedEditors())
if (!prepareForChange())
return;
if (!ensureWriteableProFile(m_projectFilePath.toString()))
return;
QPair<ProFile *, QStringList> pair = readProFile(m_projectFilePath.toString());
ProFile *includeFile = pair.first;
QStringList lines = pair.second;
......@@ -1258,7 +1302,6 @@ void QmakePriFileNode::changeFiles(const QString &mimeType,
if (!includeFile)
return;
if (change == AddToProFile) {
// Use the first variable for adding.
ProWriter::addFiles(includeFile, &lines, filePaths, varNameForAdding(mimeType));
......@@ -1269,13 +1312,14 @@ void QmakePriFileNode::changeFiles(const QString &mimeType,
}
// save file
save(lines);
if (mode == Change::Save)
save(lines);
includeFile->deref();
}
bool QmakePriFileNode::setProVariable(const QString &var, const QStringList &values, const QString &scope, int flags)
{
if (!ensureWriteableProFile(m_projectFilePath.toString()))
if (!prepareForChange())
return false;
QPair<ProFile *, QStringList> pair = readProFile(m_projectFilePath.toString());
......
......@@ -156,6 +156,7 @@ public:
bool addFiles(const QStringList &filePaths, QStringList *notAdded = 0);
bool removeFiles(const QStringList &filePaths, QStringList *notRemoved = 0);
bool deleteFiles(const QStringList &filePaths);
bool canRenameFile(const QString &filePath, const QString &newFilePath);
bool renameFile(const QString &filePath, const QString &newFilePath);
AddNewInformation addNewInformation(const QStringList &files, Node *context) const;
......@@ -175,6 +176,7 @@ public:
bool includedInExactParse() const;
static QSet<Utils::FileName> recursiveEnumerate(const QString &folder);
protected:
void setIncludedInExactParse(bool b);
static QStringList varNames(ProjectExplorer::FileType type, QtSupport::ProFileReader *readerExact);
......@@ -189,14 +191,21 @@ protected:
RemoveFromProFile
};
enum class Change { Save, TestOnly };
bool renameFile(const QString &oldName,
const QString &newName,
const QString &mimeType,
Change mode = Change::Save);
void changeFiles(const QString &mimeType,
const QStringList &filePaths,
QStringList *notChanged,
ChangeType change);
ChangeType change,
Change mode = Change::Save);
private:
void scheduleUpdate();
bool prepareForChange();
static bool ensureWriteableProFile(const QString &file);
static QPair<ProFile *, QStringList> readProFile(const QString &file);
static QPair<ProFile *, QStringList> readProFileFromContents(const QString &contents);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment