Commit eef043e0 authored by Konstantin Tokarev's avatar Konstantin Tokarev Committed by Eike Ziller

Implemented file rename in ResourceEditor.

Renaming supports version control.

To prevent code duplication part of ProjectExplorerPlugin::renameFile
implementation was separated into FileUtils::renameFile.

Change-Id: I28481bea89d0824339e5db025ceb7216713bd5a0
Reviewed-by: default avatarEike Ziller <eike.ziller@nokia.com>
parent bb66e546
......@@ -32,6 +32,9 @@
#include "fileutils.h"
#include <coreplugin/documentmanager.h>
#include <coreplugin/iversioncontrol.h>
#include <coreplugin/vcsmanager.h>
#include <utils/environment.h>
#include <QDir>
......@@ -41,6 +44,10 @@
#include <QMessageBox>
#include <QWidget>
#if QT_VERSION < 0x050000
#include <QAbstractFileEngine>
#endif
#ifndef Q_OS_WIN
#include <coreplugin/icore.h>
#include <utils/consoleprocess.h>
......@@ -165,3 +172,35 @@ QString FileUtils::msgTerminalAction()
return QApplication::translate("Core::Internal", "Open Terminal Here");
#endif
}
static inline bool fileSystemRenameFile(const QString &orgFilePath,
const QString &newFilePath)
{
#if QT_VERSION < 0x050000 // ### fixme: QTBUG-3570 might be fixed in Qt 5?
QFile f(orgFilePath); // Due to QTBUG-3570
QAbstractFileEngine *fileEngine = f.fileEngine();
if (!fileEngine->caseSensitive() && orgFilePath.compare(newFilePath, Qt::CaseInsensitive) == 0)
return fileEngine->rename(newFilePath);
#endif
return QFile::rename(orgFilePath, newFilePath);
}
bool FileUtils::renameFile(const QString &orgFilePath, const QString &newFilePath)
{
if (orgFilePath == newFilePath)
return false;
QString dir = QFileInfo(orgFilePath).absolutePath();
Core::IVersionControl *vc = Core::ICore::vcsManager()->findVersionControlForDirectory(dir);
bool result = false;
if (vc && vc->supportsOperation(Core::IVersionControl::MoveOperation))
result = vc->vcsMove(orgFilePath, newFilePath);
if (!result) // The moving via vcs failed or the vcs does not support moving, fall back
result = fileSystemRenameFile(orgFilePath, newFilePath);
if (result) {
// yeah we moved, tell the filemanager about it
Core::DocumentManager::renamedFile(orgFilePath, newFilePath);
}
return result;
}
......@@ -49,6 +49,8 @@ struct CORE_EXPORT FileUtils
// Platform-dependent action descriptions
static QString msgGraphicalShellAction();
static QString msgTerminalAction();
// File rename aware of version control and file system case-insensitiveness
static bool renameFile(const QString &from, const QString &to);
};
} // namespace Core
......
......@@ -127,10 +127,6 @@
#include <QFileInfo>
#include <QSettings>
#if QT_VERSION < 0x050000
#include <QAbstractFileEngine>
#endif
#include <QAction>
#include <QApplication>
#include <QFileDialog>
......@@ -2822,18 +2818,6 @@ void ProjectExplorerPlugin::renameFile()
}
}
static inline bool fileSystemRenameFile(const QString &orgFilePath,
const QString &newFilePath)
{
#if QT_VERSION < 0x050000 // ### fixme: QTBUG-3570 might be fixed in Qt 5?
QFile f(orgFilePath); // Due to QTBUG-3570
QAbstractFileEngine *fileEngine = f.fileEngine();
if (!fileEngine->caseSensitive() && orgFilePath.compare(newFilePath, Qt::CaseInsensitive) == 0)
return fileEngine->rename(newFilePath);
#endif
return QFile::rename(orgFilePath, newFilePath);
}
void ProjectExplorerPlugin::renameFile(Node *node, const QString &to)
{
FileNode *fileNode = qobject_cast<FileNode *>(node);
......@@ -2843,20 +2827,8 @@ void ProjectExplorerPlugin::renameFile(Node *node, const QString &to)
QString dir = QFileInfo(orgFilePath).absolutePath();
QString newFilePath = dir + QLatin1Char('/') + to;
if (orgFilePath == newFilePath)
return;
Core::IVersionControl *vc = Core::ICore::vcsManager()->findVersionControlForDirectory(dir);
bool result = false;
if (vc && vc->supportsOperation(Core::IVersionControl::MoveOperation))
result = vc->vcsMove(orgFilePath, newFilePath);
if (!result) // The moving via vcs failed or the vcs does not support moving, fall back
result = fileSystemRenameFile(orgFilePath, newFilePath);
if (result) {
// yeah we moved, tell the filemanager about it
Core::DocumentManager::renamedFile(orgFilePath, newFilePath);
// Tell the project plugin about it
if (Core::FileUtils::renameFile(orgFilePath, newFilePath)) {
// Tell the project plugin about rename
ProjectNode *projectNode = fileNode->projectNode();
if (!projectNode->renameFile(fileNode->fileType(), orgFilePath, newFilePath)) {
QMessageBox::warning(Core::ICore::mainWindow(), tr("Project Editing Failed"),
......
......@@ -54,6 +54,8 @@
#include <QMainWindow>
#include <QMenu>
#include <QToolBar>
#include <QInputDialog>
#include <QMessageBox>
namespace ResourceEditor {
namespace Internal {
......@@ -103,6 +105,7 @@ ResourceEditorW::ResourceEditorW(const Core::Context &context,
m_resourceEditor->setResourceDragEnabled(true);
m_contextMenu->addAction(tr("Open File"), this, SLOT(openCurrentFile()));
m_openWithMenu = m_contextMenu->addMenu(tr("Open With"));
m_renameAction = m_contextMenu->addAction(tr("Rename File..."), this, SLOT(renameCurrentFile()), Qt::Key_F2);
// Below we need QueuedConnection because otherwise, if this qrc file
// is inside of the qrc file, crashes happen when using "Open With" on it.
// (That is because this editor instance is deleted in executeOpenWithMenuAction
......@@ -298,10 +301,9 @@ void ResourceEditorW::onUndoStackChanged(bool canUndo, bool canRedo)
void ResourceEditorW::showContextMenu(const QPoint &globalPoint, const QString &fileName)
{
Core::DocumentManager::populateOpenWithMenu(m_openWithMenu, fileName);
if (!m_openWithMenu->actions().isEmpty()) {
m_currentFileName = fileName;
m_contextMenu->popup(globalPoint);
}
m_currentFileName = fileName;
m_renameAction->setEnabled(!document()->isFileReadOnly());
m_contextMenu->popup(globalPoint);
}
void ResourceEditorW::openCurrentFile()
......@@ -320,6 +322,11 @@ void ResourceEditorW::onRefresh()
m_resourceEditor.data()->refresh();
}
void ResourceEditorW::renameCurrentFile()
{
m_resourceEditor->editCurrentItem();
}
void ResourceEditorW::onUndo()
{
if (!m_resourceEditor.isNull())
......
......@@ -111,6 +111,7 @@ private slots:
void showContextMenu(const QPoint &globalPoint, const QString &fileName);
void openCurrentFile();
void openFile(const QString &fileName);
void renameCurrentFile();
private:
const QString m_extension;
......@@ -126,6 +127,7 @@ private:
QMenu *m_openWithMenu;
QString m_currentFileName;
QToolBar *m_toolBar;
QAction *m_renameAction;
public slots:
void onRefresh();
......
......@@ -349,12 +349,12 @@ void QrcEditor::addFile(const QString &prefix, const QString &file)
m_treeview->addFile(prefix, file);
}
/*
void QrcEditor::removeFile(const QString &prefix, const QString &file)
void QrcEditor::editCurrentItem()
{
m_treeview->removeFile(prefix, file);
if (m_treeview->selectionModel()->currentIndex().isValid())
m_treeview->edit(m_treeview->selectionModel()->currentIndex());
}
*/
// Slot for change of line edit content 'alias'
void QrcEditor::onAliasChanged(const QString &alias)
{
......
......@@ -63,11 +63,11 @@ public:
bool resourceDragEnabled() const;
void addFile(const QString &prefix, const QString &file);
// void removeFile(const QString &prefix, const QString &file);
const QUndoStack *commandHistory() const { return &m_history; }
void refresh();
void editCurrentItem();
signals:
void dirtyChanged(bool dirty);
......
......@@ -33,6 +33,8 @@
#include "resourcefile_p.h"
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/fileutils.h>
#include <utils/fileutils.h>
#include <QCoreApplication>
#include <QDebug>
......@@ -89,6 +91,11 @@ bool File::exists()
return m_exists;
}
void File::setExists(bool exists)
{
m_exists = exists;
}
/******************************************************************************
** FileList
*/
......@@ -378,6 +385,41 @@ void ResourceFile::replaceAlias(int prefix_idx, int file_idx, const QString &ali
fileList[file_idx]->alias = alias;
}
bool ResourceFile::renameFile(const QString fileName, const QString &newFileName)
{
bool success = true;
FileList entries;
for (int i = 0; i < prefixCount(); ++i) {
const FileList &file_list = m_prefix_list.at(i)->file_list;
foreach (File *file, file_list) {
if (file->name == fileName)
entries.append(file);
if (file->name == newFileName)
return false; // prevent conflicts
}
}
Q_ASSERT(!entries.isEmpty());
entries.at(0)->checkExistence();
if (entries.at(0)->exists()) {
foreach (File *file, entries)
file->setExists(true);
success = Core::FileUtils::renameFile(entries.at(0)->name, newFileName);
}
if (success) {
bool exists = QFile::exists(newFileName);
foreach (File *file, entries) {
file->name = newFileName;
file->setExists(exists);
}
}
return success;
}
void ResourceFile::replaceFile(int pref_idx, int file_idx, const QString &file)
{
......@@ -646,6 +688,22 @@ void ResourceModel::refresh()
m_resource_file.refresh();
}
Qt::ItemFlags ResourceModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags f = QAbstractItemModel::flags(index);
const void *internalPointer = index.internalPointer();
const Node *node = reinterpret_cast<const Node *>(internalPointer);
const Prefix *prefix = node->prefix();
Q_ASSERT(prefix);
const bool isFileNode = (prefix != node);
if (isFileNode)
f |= Qt::ItemIsEditable;
return f;
}
bool ResourceModel::iconFileExtension(const QString &path)
{
static QStringList ext_list;
......@@ -701,7 +759,7 @@ QVariant ResourceModel::data(const QModelIndex &index, int role) const
// File node
Q_ASSERT(file);
QString conv_file = m_resource_file.relativePath(file->name);
stringRes = conv_file.replace(QDir::separator(), QLatin1Char('/'));
stringRes = QDir::fromNativeSeparators(conv_file);
const QString alias = file->alias;
if (!alias.isEmpty())
appendParenthesized(alias, stringRes);
......@@ -727,6 +785,13 @@ QVariant ResourceModel::data(const QModelIndex &index, int role) const
result = m_prefixIcon;
}
break;
case Qt::EditRole:
if (isFileNode) {
Q_ASSERT(file);
QString conv_file = m_resource_file.relativePath(file->name);
result = QDir::fromNativeSeparators(conv_file);
}
break;
case Qt::ForegroundRole:
if (isFileNode) {
// File node
......@@ -741,6 +806,26 @@ QVariant ResourceModel::data(const QModelIndex &index, int role) const
return result;
}
bool ResourceModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (!index.isValid())
return false;
if (role != Qt::EditRole)
return false;
const QDir baseDir = QFileInfo(fileName()).absoluteDir();
Utils::FileName newFileName = Utils::FileName::fromUserInput(
baseDir.absoluteFilePath(value.toString()));
if (newFileName.isEmpty())
return false;
if (!newFileName.isChildOf(Utils::FileName::fromString(baseDir.absolutePath())))
return false;
return renameFile(file(index), newFileName.toString());
}
void ResourceModel::getItem(const QModelIndex &index, QString &prefix, QString &file) const
{
prefix.clear();
......@@ -924,6 +1009,14 @@ void ResourceModel::insertFile(int prefixIndex, int fileIndex,
setDirty(true);
}
bool ResourceModel::renameFile(const QString &fileName, const QString &newFileName)
{
bool success = m_resource_file.renameFile(fileName, newFileName);
if (success)
setDirty(true);
return success;
}
void ResourceModel::changePrefix(const QModelIndex &model_idx, const QString &prefix)
{
if (!model_idx.isValid())
......
......@@ -77,6 +77,7 @@ public:
File(Prefix *prefix, const QString &_name, const QString &_alias = QString());
void checkExistence();
bool exists();
void setExists(bool exists);
bool operator < (const File &other) const { return name < other.name; }
bool operator == (const File &other) const { return name == other.name; }
......@@ -161,6 +162,8 @@ public:
void replaceLang(int prefix_idx, const QString &lang);
void replaceAlias(int prefix_idx, int file_idx, const QString &alias);
bool renameFile(const QString fileName, const QString &newFileName);
private:
void replaceFile(int pref_idx, int file_idx, const QString &file);
public:
......@@ -211,11 +214,13 @@ public:
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const;
bool hasChildren(const QModelIndex &parent) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
void refresh();
protected:
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
bool setData(const QModelIndex &index, const QVariant &value, int role);
public:
QString fileName() const { return m_resource_file.fileName(); }
......@@ -247,6 +252,7 @@ private:
QString relativePath(const QString &path) const
{ return m_resource_file.relativePath(path); }
QString lastResourceOpenDirectory() const;
bool renameFile(const QString &fileName, const QString &newFileName);
public:
virtual bool reload();
......
......@@ -183,6 +183,7 @@ ResourceView::ResourceView(QUndoStack *history, QWidget *parent) :
advanceMergeId();
setModel(m_qrcModel);
setContextMenuPolicy(Qt::CustomContextMenu);
setEditTriggers(EditKeyPressed);
header()->hide();
......
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