forked from qt-creator/qt-creator
Add "Remove File" to file system view
Task-number: QTCREATORBUG-19208 Change-Id: Iacf1e1468018fa8dd3426bc1325f36bb39a4b4e2 Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
@@ -479,6 +479,12 @@ IContext *ICore::currentContextObject()
|
|||||||
return m_mainwindow->currentContextObject();
|
return m_mainwindow->currentContextObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QWidget *ICore::currentContextWidget()
|
||||||
|
{
|
||||||
|
IContext *context = currentContextObject();
|
||||||
|
return context ? context->widget() : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QWidget *ICore::mainWindow()
|
QWidget *ICore::mainWindow()
|
||||||
{
|
{
|
||||||
|
@@ -106,6 +106,7 @@ public:
|
|||||||
static void raiseWindow(QWidget *widget);
|
static void raiseWindow(QWidget *widget);
|
||||||
|
|
||||||
static IContext *currentContextObject();
|
static IContext *currentContextObject();
|
||||||
|
static QWidget *currentContextWidget();
|
||||||
// Adds and removes additional active contexts, these contexts are appended
|
// Adds and removes additional active contexts, these contexts are appended
|
||||||
// to the currently active contexts.
|
// to the currently active contexts.
|
||||||
static void updateAdditionalContexts(const Context &remove, const Context &add,
|
static void updateAdditionalContexts(const Context &remove, const Context &add,
|
||||||
|
@@ -51,6 +51,7 @@
|
|||||||
#include <utils/hostosinfo.h>
|
#include <utils/hostosinfo.h>
|
||||||
#include <utils/navigationtreeview.h>
|
#include <utils/navigationtreeview.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/removefiledialog.h>
|
||||||
#include <utils/utilsicons.h>
|
#include <utils/utilsicons.h>
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
@@ -161,6 +162,14 @@ static QVector<FolderNode *> renamableFolderNodes(const Utils::FileName &before,
|
|||||||
return folderNodes;
|
return folderNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QStringList projectNames(const QVector<FolderNode *> &folders)
|
||||||
|
{
|
||||||
|
const QStringList names = Utils::transform<QList>(folders, [](FolderNode *n) {
|
||||||
|
return n->managingProject()->filePath().fileName();
|
||||||
|
});
|
||||||
|
return Utils::filteredUnique(names);
|
||||||
|
}
|
||||||
|
|
||||||
bool FolderNavigationModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
bool FolderNavigationModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(index.isValid() && parent(index).isValid() && index.column() == 0
|
QTC_ASSERT(index.isValid() && parent(index).isValid() && index.column() == 0
|
||||||
@@ -186,12 +195,7 @@ bool FolderNavigationModel::setData(const QModelIndex &index, const QVariant &va
|
|||||||
failedNodes.append(folder);
|
failedNodes.append(folder);
|
||||||
}
|
}
|
||||||
if (!failedNodes.isEmpty()) {
|
if (!failedNodes.isEmpty()) {
|
||||||
const QString projects
|
const QString projects = projectNames(failedNodes).join(", ");
|
||||||
= Utils::transform<QList>(failedNodes,
|
|
||||||
[](FolderNode *n) {
|
|
||||||
return n->managingProject()->filePath().fileName();
|
|
||||||
})
|
|
||||||
.join(", ");
|
|
||||||
const QString errorMessage
|
const QString errorMessage
|
||||||
= tr("The file \"%1\" was renamed to \"%2\", "
|
= tr("The file \"%1\" was renamed to \"%2\", "
|
||||||
"but the following projects could not be automatically changed: %3")
|
"but the following projects could not be automatically changed: %3")
|
||||||
@@ -395,6 +399,51 @@ void FolderNavigationWidget::editCurrentItem()
|
|||||||
m_listView->edit(current);
|
m_listView->edit(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QVector<FolderNode *> removableFolderNodes(const Utils::FileName &filePath)
|
||||||
|
{
|
||||||
|
QVector<FolderNode *> folderNodes;
|
||||||
|
ProjectTree::forEachNode([&](Node *node) {
|
||||||
|
if (node->nodeType() == NodeType::File && node->filePath() == filePath
|
||||||
|
&& node->parentFolderNode()
|
||||||
|
&& node->parentFolderNode()->supportsAction(RemoveFile, node)) {
|
||||||
|
folderNodes.append(node->parentFolderNode());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return folderNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FolderNavigationWidget::removeCurrentItem()
|
||||||
|
{
|
||||||
|
const QModelIndex current = m_listView->currentIndex();
|
||||||
|
if (!current.isValid() || m_fileSystemModel->isDir(current))
|
||||||
|
return;
|
||||||
|
const QString filePath = m_fileSystemModel->filePath(current);
|
||||||
|
Utils::RemoveFileDialog dialog(filePath, Core::ICore::dialogParent());
|
||||||
|
dialog.setDeleteFileVisible(false);
|
||||||
|
if (dialog.exec() == QDialog::Accepted) {
|
||||||
|
const QVector<FolderNode *> folderNodes = removableFolderNodes(
|
||||||
|
Utils::FileName::fromString(filePath));
|
||||||
|
const QVector<FolderNode *> failedNodes = Utils::filtered(folderNodes,
|
||||||
|
[filePath](FolderNode *folder) {
|
||||||
|
return !folder->removeFiles(
|
||||||
|
{filePath});
|
||||||
|
});
|
||||||
|
Core::FileChangeBlocker changeGuard(filePath);
|
||||||
|
Core::FileUtils::removeFile(filePath, true /*delete from disk*/);
|
||||||
|
if (!failedNodes.isEmpty()) {
|
||||||
|
const QString projects = projectNames(failedNodes).join(", ");
|
||||||
|
const QString errorMessage
|
||||||
|
= tr("The following projects failed to automatically remove the file: %1")
|
||||||
|
.arg(projects);
|
||||||
|
QTimer::singleShot(0, Core::ICore::instance(), [errorMessage] {
|
||||||
|
QMessageBox::warning(Core::ICore::dialogParent(),
|
||||||
|
ProjectExplorerPlugin::tr("Project Editing Failed"),
|
||||||
|
errorMessage);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool FolderNavigationWidget::autoSynchronization() const
|
bool FolderNavigationWidget::autoSynchronization() const
|
||||||
{
|
{
|
||||||
return m_autoSync;
|
return m_autoSync;
|
||||||
@@ -559,6 +608,8 @@ void FolderNavigationWidget::contextMenuEvent(QContextMenuEvent *ev)
|
|||||||
Core::EditorManager::addNativeDirAndOpenWithActions(&menu, &fakeEntry);
|
Core::EditorManager::addNativeDirAndOpenWithActions(&menu, &fakeEntry);
|
||||||
|
|
||||||
if (hasCurrentItem) {
|
if (hasCurrentItem) {
|
||||||
|
if (!isDir)
|
||||||
|
menu.addAction(Core::ActionManager::command(Constants::REMOVEFILE)->action());
|
||||||
if (m_fileSystemModel->flags(current) & Qt::ItemIsEditable)
|
if (m_fileSystemModel->flags(current) & Qt::ItemIsEditable)
|
||||||
menu.addAction(Core::ActionManager::command(Constants::RENAMEFILE)->action());
|
menu.addAction(Core::ActionManager::command(Constants::RENAMEFILE)->action());
|
||||||
if (!isDir && Core::DiffService::instance()) {
|
if (!isDir && Core::DiffService::instance()) {
|
||||||
@@ -712,17 +763,28 @@ void FolderNavigationWidgetFactory::updateProjectsDirectoryRoot()
|
|||||||
Utils::Icons::PROJECT.icon()});
|
Utils::Icons::PROJECT.icon()});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static FolderNavigationWidget *currentFolderNavigationWidget()
|
||||||
|
{
|
||||||
|
return qobject_cast<FolderNavigationWidget *>(Core::ICore::currentContextWidget());
|
||||||
|
}
|
||||||
|
|
||||||
void FolderNavigationWidgetFactory::registerActions()
|
void FolderNavigationWidgetFactory::registerActions()
|
||||||
{
|
{
|
||||||
Core::Context context(C_FOLDERNAVIGATIONWIDGET);
|
Core::Context context(C_FOLDERNAVIGATIONWIDGET);
|
||||||
|
|
||||||
auto rename = new QAction(this);
|
auto rename = new QAction(this);
|
||||||
Core::ActionManager::registerAction(rename, Constants::RENAMEFILE, context);
|
Core::ActionManager::registerAction(rename, Constants::RENAMEFILE, context);
|
||||||
connect(rename, &QAction::triggered, Core::ICore::instance(), [] {
|
connect(rename, &QAction::triggered, Core::ICore::instance(), [] {
|
||||||
Core::IContext *context = Core::ICore::currentContextObject();
|
if (auto navWidget = currentFolderNavigationWidget())
|
||||||
QWidget *widget = context ? context->widget() : nullptr;
|
|
||||||
if (auto navWidget = qobject_cast<FolderNavigationWidget *>(widget))
|
|
||||||
navWidget->editCurrentItem();
|
navWidget->editCurrentItem();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
auto remove = new QAction(this);
|
||||||
|
Core::ActionManager::registerAction(remove, Constants::REMOVEFILE, context);
|
||||||
|
connect(remove, &QAction::triggered, Core::ICore::instance(), [] {
|
||||||
|
if (auto navWidget = currentFolderNavigationWidget())
|
||||||
|
navWidget->removeCurrentItem();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
int DelayedFileCrumbLabel::immediateHeightForWidth(int w) const
|
int DelayedFileCrumbLabel::immediateHeightForWidth(int w) const
|
||||||
|
@@ -107,6 +107,7 @@ public:
|
|||||||
void removeRootDirectory(const QString &id);
|
void removeRootDirectory(const QString &id);
|
||||||
|
|
||||||
void editCurrentItem();
|
void editCurrentItem();
|
||||||
|
void removeCurrentItem();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void contextMenuEvent(QContextMenuEvent *ev) override;
|
void contextMenuEvent(QContextMenuEvent *ev) override;
|
||||||
|
@@ -208,7 +208,6 @@ const char OPENFILE[] = "ProjectExplorer.OpenFile";
|
|||||||
const char SEARCHONFILESYSTEM[] = "ProjectExplorer.SearchOnFileSystem";
|
const char SEARCHONFILESYSTEM[] = "ProjectExplorer.SearchOnFileSystem";
|
||||||
const char SHOWINGRAPHICALSHELL[] = "ProjectExplorer.ShowInGraphicalShell";
|
const char SHOWINGRAPHICALSHELL[] = "ProjectExplorer.ShowInGraphicalShell";
|
||||||
const char OPENTERMIANLHERE[] = "ProjectExplorer.OpenTerminalHere";
|
const char OPENTERMIANLHERE[] = "ProjectExplorer.OpenTerminalHere";
|
||||||
const char REMOVEFILE[] = "ProjectExplorer.RemoveFile";
|
|
||||||
const char DUPLICATEFILE[] = "ProjectExplorer.DuplicateFile";
|
const char DUPLICATEFILE[] = "ProjectExplorer.DuplicateFile";
|
||||||
const char DELETEFILE[] = "ProjectExplorer.DeleteFile";
|
const char DELETEFILE[] = "ProjectExplorer.DeleteFile";
|
||||||
const char DIFFFILE[] = "ProjectExplorer.DiffFile";
|
const char DIFFFILE[] = "ProjectExplorer.DiffFile";
|
||||||
|
@@ -37,7 +37,7 @@ const char MODE_SESSION[] = "Project";
|
|||||||
const char BUILD[] = "ProjectExplorer.Build";
|
const char BUILD[] = "ProjectExplorer.Build";
|
||||||
const char STOP[] = "ProjectExplorer.Stop";
|
const char STOP[] = "ProjectExplorer.Stop";
|
||||||
const char RENAMEFILE[] = "ProjectExplorer.RenameFile";
|
const char RENAMEFILE[] = "ProjectExplorer.RenameFile";
|
||||||
|
const char REMOVEFILE[] = "ProjectExplorer.RemoveFile";
|
||||||
|
|
||||||
// Context
|
// Context
|
||||||
const char C_PROJECT_TREE[] = "ProjectExplorer.ProjectTreeContext";
|
const char C_PROJECT_TREE[] = "ProjectExplorer.ProjectTreeContext";
|
||||||
|
Reference in New Issue
Block a user