forked from qt-creator/qt-creator
Make File System view independent from ProjectExplorer
As preparation for moving it to Core so the "Show in File System View" functionality can spread more. Change-Id: I0f7d36f1d7eebe7b074c7949dd95b2cd985bfec8 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Cristian Adam <cristian.adam@qt.io>
This commit is contained in:
@@ -54,5 +54,9 @@ const Icon MODE_DESIGN_FLAT({
|
|||||||
const Icon MODE_DESIGN_FLAT_ACTIVE({
|
const Icon MODE_DESIGN_FLAT_ACTIVE({
|
||||||
{":/fancyactionbar/images/mode_design_mask.png", Theme::IconsModeDesignActiveColor}});
|
{":/fancyactionbar/images/mode_design_mask.png", Theme::IconsModeDesignActiveColor}});
|
||||||
|
|
||||||
|
const Icon DESKTOP_DEVICE_SMALL({{":/utils/images/desktopdevicesmall.png",
|
||||||
|
Theme::PanelTextColorDark}},
|
||||||
|
Icon::Tint);
|
||||||
|
|
||||||
} // namespace Icons
|
} // namespace Icons
|
||||||
} // namespace Core
|
} // namespace Core
|
||||||
|
@@ -43,6 +43,7 @@ CORE_EXPORT extern const Utils::Icon MODE_EDIT_FLAT_ACTIVE;
|
|||||||
CORE_EXPORT extern const Utils::Icon MODE_DESIGN_CLASSIC;
|
CORE_EXPORT extern const Utils::Icon MODE_DESIGN_CLASSIC;
|
||||||
CORE_EXPORT extern const Utils::Icon MODE_DESIGN_FLAT;
|
CORE_EXPORT extern const Utils::Icon MODE_DESIGN_FLAT;
|
||||||
CORE_EXPORT extern const Utils::Icon MODE_DESIGN_FLAT_ACTIVE;
|
CORE_EXPORT extern const Utils::Icon MODE_DESIGN_FLAT_ACTIVE;
|
||||||
|
CORE_EXPORT extern const Utils::Icon DESKTOP_DEVICE_SMALL;
|
||||||
|
|
||||||
} // namespace Icons
|
} // namespace Icons
|
||||||
} // namespace Core
|
} // namespace Core
|
||||||
|
@@ -28,6 +28,7 @@
|
|||||||
#include <projectexplorer/projectexplorerconstants.h>
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
#include <projectexplorer/projectexplorericons.h>
|
#include <projectexplorer/projectexplorericons.h>
|
||||||
|
|
||||||
|
#include <coreplugin/coreicons.h>
|
||||||
#include <utils/icon.h>
|
#include <utils/icon.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
@@ -42,9 +43,9 @@ DesktopDeviceFactory::DesktopDeviceFactory()
|
|||||||
setConstructionFunction([] { return IDevice::Ptr(new DesktopDevice); });
|
setConstructionFunction([] { return IDevice::Ptr(new DesktopDevice); });
|
||||||
setDisplayName(DesktopDevice::tr("Desktop"));
|
setDisplayName(DesktopDevice::tr("Desktop"));
|
||||||
setIcon(Utils::creatorTheme()->flag(Utils::Theme::FlatSideBarIcons)
|
setIcon(Utils::creatorTheme()->flag(Utils::Theme::FlatSideBarIcons)
|
||||||
? Utils::Icon::combinedIcon({Icons::DESKTOP_DEVICE.icon(),
|
? Utils::Icon::combinedIcon(
|
||||||
Icons::DESKTOP_DEVICE_SMALL.icon()})
|
{Icons::DESKTOP_DEVICE.icon(), Core::Icons::DESKTOP_DEVICE_SMALL.icon()})
|
||||||
: QApplication::style()->standardIcon(QStyle::SP_ComputerIcon));
|
: QApplication::style()->standardIcon(QStyle::SP_ComputerIcon));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -24,14 +24,10 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "foldernavigationwidget.h"
|
#include "foldernavigationwidget.h"
|
||||||
#include "projectexplorer.h"
|
|
||||||
#include "projectexplorerconstants.h"
|
|
||||||
#include "projectexplorericons.h"
|
|
||||||
#include "projectnodes.h"
|
|
||||||
#include "projecttree.h"
|
|
||||||
|
|
||||||
#include <coreplugin/actionmanager/actionmanager.h>
|
#include <coreplugin/actionmanager/actionmanager.h>
|
||||||
#include <coreplugin/actionmanager/command.h>
|
#include <coreplugin/actionmanager/command.h>
|
||||||
|
#include <coreplugin/coreicons.h>
|
||||||
#include <coreplugin/diffservice.h>
|
#include <coreplugin/diffservice.h>
|
||||||
#include <coreplugin/documentmanager.h>
|
#include <coreplugin/documentmanager.h>
|
||||||
#include <coreplugin/editormanager/editormanager.h>
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
@@ -90,6 +86,10 @@ const char kSyncKey[] = ".SyncWithEditor";
|
|||||||
const char kShowBreadCrumbs[] = ".ShowBreadCrumbs";
|
const char kShowBreadCrumbs[] = ".ShowBreadCrumbs";
|
||||||
const char kSyncRootWithEditor[] = ".SyncRootWithEditor";
|
const char kSyncRootWithEditor[] = ".SyncRootWithEditor";
|
||||||
|
|
||||||
|
const char ADDNEWFILE[] = "QtCreator.FileSystem.AddNewFile";
|
||||||
|
const char RENAMEFILE[] = "QtCreator.FileSystem.RenameFile";
|
||||||
|
const char REMOVEFILE[] = "QtCreator.FileSystem.RemoveFile";
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
@@ -199,29 +199,6 @@ Qt::ItemFlags FolderNavigationModel::flags(const QModelIndex &index) const
|
|||||||
return QFileSystemModel::flags(index);
|
return QFileSystemModel::flags(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static QVector<FolderNode *> renamableFolderNodes(const Utils::FilePath &before,
|
|
||||||
const Utils::FilePath &after)
|
|
||||||
{
|
|
||||||
QVector<FolderNode *> folderNodes;
|
|
||||||
ProjectTree::forEachNode([&](Node *node) {
|
|
||||||
if (node->asFileNode()
|
|
||||||
&& node->filePath() == before
|
|
||||||
&& node->parentFolderNode()
|
|
||||||
&& node->parentFolderNode()->canRenameFile(before, after)) {
|
|
||||||
folderNodes.append(node->parentFolderNode());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
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
|
||||||
@@ -238,25 +215,7 @@ bool FolderNavigationModel::setData(const QModelIndex &index, const QVariant &va
|
|||||||
// for files we can do more than just rename on disk, for directories the user is on his/her own
|
// for files we can do more than just rename on disk, for directories the user is on his/her own
|
||||||
if (success && fileInfo(index).isFile()) {
|
if (success && fileInfo(index).isFile()) {
|
||||||
Core::DocumentManager::renamedFile(beforeFilePath, afterFilePath);
|
Core::DocumentManager::renamedFile(beforeFilePath, afterFilePath);
|
||||||
const QVector<FolderNode *> folderNodes = renamableFolderNodes(beforeFilePath,
|
emit m_instance->fileRenamed(beforeFilePath, afterFilePath);
|
||||||
afterFilePath);
|
|
||||||
QVector<FolderNode *> failedNodes;
|
|
||||||
for (FolderNode *folder : folderNodes) {
|
|
||||||
if (!folder->renameFile(beforeFilePath, afterFilePath))
|
|
||||||
failedNodes.append(folder);
|
|
||||||
}
|
|
||||||
if (!failedNodes.isEmpty()) {
|
|
||||||
const QString projects = projectNames(failedNodes).join(", ");
|
|
||||||
const QString errorMessage
|
|
||||||
= FolderNavigationWidget::tr("The file \"%1\" was renamed to \"%2\", "
|
|
||||||
"but the following projects could not be automatically changed: %3")
|
|
||||||
.arg(beforeFilePath.toUserOutput(), afterFilePath.toUserOutput(), projects);
|
|
||||||
QTimer::singleShot(0, Core::ICore::instance(), [errorMessage] {
|
|
||||||
QMessageBox::warning(Core::ICore::dialogParent(),
|
|
||||||
ProjectExplorerPlugin::tr("Project Editing Failed"),
|
|
||||||
errorMessage);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
@@ -509,7 +468,7 @@ void FolderNavigationWidget::addNewItem()
|
|||||||
return;
|
return;
|
||||||
const auto filePath = Utils::FilePath::fromString(m_fileSystemModel->filePath(current));
|
const auto filePath = Utils::FilePath::fromString(m_fileSystemModel->filePath(current));
|
||||||
const Utils::FilePath path = filePath.isDir() ? filePath : filePath.parentDir();
|
const Utils::FilePath path = filePath.isDir() ? filePath : filePath.parentDir();
|
||||||
Core::ICore::showNewItemDialog(ProjectExplorerPlugin::tr("New File", "Title of dialog"),
|
Core::ICore::showNewItemDialog(tr("New File", "Title of dialog"),
|
||||||
Utils::filtered(Core::IWizardFactory::allWizardFactories(),
|
Utils::filtered(Core::IWizardFactory::allWizardFactories(),
|
||||||
Utils::equal(&Core::IWizardFactory::kind,
|
Utils::equal(&Core::IWizardFactory::kind,
|
||||||
Core::IWizardFactory::FileWizard)),
|
Core::IWizardFactory::FileWizard)),
|
||||||
@@ -523,20 +482,6 @@ void FolderNavigationWidget::editCurrentItem()
|
|||||||
m_listView->edit(current);
|
m_listView->edit(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
static QVector<FolderNode *> removableFolderNodes(const Utils::FilePath &filePath)
|
|
||||||
{
|
|
||||||
QVector<FolderNode *> folderNodes;
|
|
||||||
ProjectTree::forEachNode([&](Node *node) {
|
|
||||||
if (node->asFileNode()
|
|
||||||
&& node->filePath() == filePath
|
|
||||||
&& node->parentFolderNode()
|
|
||||||
&& node->parentFolderNode()->supportsAction(RemoveFile, node)) {
|
|
||||||
folderNodes.append(node->parentFolderNode());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return folderNodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderNavigationWidget::removeCurrentItem()
|
void FolderNavigationWidget::removeCurrentItem()
|
||||||
{
|
{
|
||||||
const QModelIndex current = m_sortProxyModel->mapToSource(m_listView->currentIndex());
|
const QModelIndex current = m_sortProxyModel->mapToSource(m_listView->currentIndex());
|
||||||
@@ -546,24 +491,9 @@ void FolderNavigationWidget::removeCurrentItem()
|
|||||||
RemoveFileDialog dialog(filePath, Core::ICore::dialogParent());
|
RemoveFileDialog dialog(filePath, Core::ICore::dialogParent());
|
||||||
dialog.setDeleteFileVisible(false);
|
dialog.setDeleteFileVisible(false);
|
||||||
if (dialog.exec() == QDialog::Accepted) {
|
if (dialog.exec() == QDialog::Accepted) {
|
||||||
const QVector<FolderNode *> folderNodes = removableFolderNodes(filePath);
|
emit m_instance->aboutToRemoveFile(filePath);
|
||||||
const QVector<FolderNode *> failedNodes = Utils::filtered(folderNodes,
|
|
||||||
[filePath](FolderNode *folder) {
|
|
||||||
return folder->removeFiles({filePath}) != RemovedFilesFromProject::Ok;
|
|
||||||
});
|
|
||||||
Core::FileChangeBlocker changeGuard(filePath);
|
Core::FileChangeBlocker changeGuard(filePath);
|
||||||
Core::FileUtils::removeFiles({filePath}, true /*delete from disk*/);
|
Core::FileUtils::removeFiles({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);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -674,24 +604,6 @@ void FolderNavigationWidget::openItem(const QModelIndex &index)
|
|||||||
Core::EditorManager::openEditor(path);
|
Core::EditorManager::openEditor(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList FolderNavigationWidget::projectsInDirectory(const QModelIndex &index) const
|
|
||||||
{
|
|
||||||
QTC_ASSERT(index.isValid() && m_fileSystemModel->isDir(index), return {});
|
|
||||||
const QFileInfo fi = m_fileSystemModel->fileInfo(index);
|
|
||||||
if (!fi.isReadable() || !fi.isExecutable())
|
|
||||||
return {};
|
|
||||||
const QString path = m_fileSystemModel->filePath(index);
|
|
||||||
// Try to find project files in directory and open those.
|
|
||||||
return FolderNavigationWidget::projectFilesInDirectory(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderNavigationWidget::openProjectsInDirectory(const QModelIndex &index)
|
|
||||||
{
|
|
||||||
const QStringList projectFiles = projectsInDirectory(index);
|
|
||||||
if (!projectFiles.isEmpty())
|
|
||||||
Core::ICore::openFiles(Utils::transform(projectFiles, &FilePath::fromString));
|
|
||||||
}
|
|
||||||
|
|
||||||
void FolderNavigationWidget::createNewFolder(const QModelIndex &parent)
|
void FolderNavigationWidget::createNewFolder(const QModelIndex &parent)
|
||||||
{
|
{
|
||||||
static const QString baseName = tr("New Folder");
|
static const QString baseName = tr("New Folder");
|
||||||
@@ -748,24 +660,15 @@ void FolderNavigationWidget::contextMenuEvent(QContextMenuEvent *ev)
|
|||||||
const QModelIndex current = m_sortProxyModel->mapToSource(m_listView->currentIndex());
|
const QModelIndex current = m_sortProxyModel->mapToSource(m_listView->currentIndex());
|
||||||
const bool hasCurrentItem = current.isValid();
|
const bool hasCurrentItem = current.isValid();
|
||||||
QAction *actionOpenFile = nullptr;
|
QAction *actionOpenFile = nullptr;
|
||||||
QAction *actionOpenProjects = nullptr;
|
|
||||||
QAction *actionOpenAsProject = nullptr;
|
|
||||||
QAction *newFolder = nullptr;
|
QAction *newFolder = nullptr;
|
||||||
const bool isDir = m_fileSystemModel->isDir(current);
|
const bool isDir = m_fileSystemModel->isDir(current);
|
||||||
const Utils::FilePath filePath = hasCurrentItem ? Utils::FilePath::fromString(
|
const Utils::FilePath filePath = hasCurrentItem ? Utils::FilePath::fromString(
|
||||||
m_fileSystemModel->filePath(current))
|
m_fileSystemModel->filePath(current))
|
||||||
: Utils::FilePath();
|
: Utils::FilePath();
|
||||||
if (hasCurrentItem) {
|
if (hasCurrentItem) {
|
||||||
const QString fileName = m_fileSystemModel->fileName(current);
|
if (!isDir)
|
||||||
if (isDir) {
|
actionOpenFile = menu.addAction(tr("Open \"%1\"").arg(filePath.toUserOutput()));
|
||||||
actionOpenProjects = menu.addAction(tr("Open Project in \"%1\"").arg(fileName));
|
emit m_instance->aboutToShowContextMenu(&menu, filePath, isDir);
|
||||||
if (projectsInDirectory(current).isEmpty())
|
|
||||||
actionOpenProjects->setEnabled(false);
|
|
||||||
} else {
|
|
||||||
actionOpenFile = menu.addAction(tr("Open \"%1\"").arg(fileName));
|
|
||||||
if (ProjectExplorerPlugin::isProjectFile(Utils::FilePath::fromString(fileName)))
|
|
||||||
actionOpenAsProject = menu.addAction(tr("Open Project \"%1\"").arg(fileName));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// we need dummy DocumentModel::Entry with absolute file path in it
|
// we need dummy DocumentModel::Entry with absolute file path in it
|
||||||
@@ -777,11 +680,11 @@ void FolderNavigationWidget::contextMenuEvent(QContextMenuEvent *ev)
|
|||||||
Core::EditorManager::addNativeDirAndOpenWithActions(&menu, &fakeEntry);
|
Core::EditorManager::addNativeDirAndOpenWithActions(&menu, &fakeEntry);
|
||||||
|
|
||||||
if (hasCurrentItem) {
|
if (hasCurrentItem) {
|
||||||
menu.addAction(Core::ActionManager::command(Constants::ADDNEWFILE)->action());
|
menu.addAction(Core::ActionManager::command(ADDNEWFILE)->action());
|
||||||
if (!isDir)
|
if (!isDir)
|
||||||
menu.addAction(Core::ActionManager::command(Constants::REMOVEFILE)->action());
|
menu.addAction(Core::ActionManager::command(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(RENAMEFILE)->action());
|
||||||
newFolder = menu.addAction(tr("New Folder"));
|
newFolder = menu.addAction(tr("New Folder"));
|
||||||
if (!isDir && Core::DiffService::instance()) {
|
if (!isDir && Core::DiffService::instance()) {
|
||||||
menu.addAction(
|
menu.addAction(
|
||||||
@@ -792,7 +695,7 @@ void FolderNavigationWidget::contextMenuEvent(QContextMenuEvent *ev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
QAction * const collapseAllAction = menu.addAction(ProjectExplorerPlugin::tr("Collapse All"));
|
QAction *const collapseAllAction = menu.addAction(tr("Collapse All"));
|
||||||
|
|
||||||
QAction *action = menu.exec(ev->globalPos());
|
QAction *action = menu.exec(ev->globalPos());
|
||||||
if (!action)
|
if (!action)
|
||||||
@@ -801,11 +704,7 @@ void FolderNavigationWidget::contextMenuEvent(QContextMenuEvent *ev)
|
|||||||
ev->accept();
|
ev->accept();
|
||||||
if (action == actionOpenFile) {
|
if (action == actionOpenFile) {
|
||||||
openItem(current);
|
openItem(current);
|
||||||
} else if (action == actionOpenAsProject) {
|
} else if (action == newFolder) {
|
||||||
ProjectExplorerPlugin::openProject(filePath);
|
|
||||||
} else if (action == actionOpenProjects)
|
|
||||||
openProjectsInDirectory(current);
|
|
||||||
else if (action == newFolder) {
|
|
||||||
if (isDir)
|
if (isDir)
|
||||||
createNewFolder(current);
|
createNewFolder(current);
|
||||||
else
|
else
|
||||||
@@ -846,15 +745,6 @@ bool FolderNavigationWidget::isShowingFoldersOnTop() const
|
|||||||
return m_showFoldersOnTopAction->isChecked();
|
return m_showFoldersOnTopAction->isChecked();
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList FolderNavigationWidget::projectFilesInDirectory(const QString &path)
|
|
||||||
{
|
|
||||||
QDir dir(path);
|
|
||||||
QStringList projectFiles;
|
|
||||||
foreach (const QFileInfo &i, dir.entryInfoList(ProjectExplorerPlugin::projectFileGlobs(), QDir::Files))
|
|
||||||
projectFiles.append(i.absoluteFilePath());
|
|
||||||
return projectFiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------FolderNavigationWidgetFactory
|
// --------------------FolderNavigationWidgetFactory
|
||||||
FolderNavigationWidgetFactory::FolderNavigationWidgetFactory()
|
FolderNavigationWidgetFactory::FolderNavigationWidgetFactory()
|
||||||
{
|
{
|
||||||
@@ -868,7 +758,7 @@ FolderNavigationWidgetFactory::FolderNavigationWidgetFactory()
|
|||||||
0 /*sortValue*/,
|
0 /*sortValue*/,
|
||||||
FolderNavigationWidget::tr("Computer"),
|
FolderNavigationWidget::tr("Computer"),
|
||||||
Utils::FilePath(),
|
Utils::FilePath(),
|
||||||
Icons::DESKTOP_DEVICE_SMALL.icon()});
|
Core::Icons::DESKTOP_DEVICE_SMALL.icon()});
|
||||||
insertRootDirectory({QLatin1String("A.Home"),
|
insertRootDirectory({QLatin1String("A.Home"),
|
||||||
10 /*sortValue*/,
|
10 /*sortValue*/,
|
||||||
FolderNavigationWidget::tr("Home"),
|
FolderNavigationWidget::tr("Home"),
|
||||||
@@ -999,21 +889,21 @@ void FolderNavigationWidgetFactory::registerActions()
|
|||||||
Core::Context context(C_FOLDERNAVIGATIONWIDGET);
|
Core::Context context(C_FOLDERNAVIGATIONWIDGET);
|
||||||
|
|
||||||
auto add = new QAction(tr("Add New..."), this);
|
auto add = new QAction(tr("Add New..."), this);
|
||||||
Core::ActionManager::registerAction(add, Constants::ADDNEWFILE, context);
|
Core::ActionManager::registerAction(add, ADDNEWFILE, context);
|
||||||
connect(add, &QAction::triggered, Core::ICore::instance(), [] {
|
connect(add, &QAction::triggered, Core::ICore::instance(), [] {
|
||||||
if (auto navWidget = currentFolderNavigationWidget())
|
if (auto navWidget = currentFolderNavigationWidget())
|
||||||
navWidget->addNewItem();
|
navWidget->addNewItem();
|
||||||
});
|
});
|
||||||
|
|
||||||
auto rename = new QAction(tr("Rename..."), this);
|
auto rename = new QAction(tr("Rename..."), this);
|
||||||
Core::ActionManager::registerAction(rename, Constants::RENAMEFILE, context);
|
Core::ActionManager::registerAction(rename, RENAMEFILE, context);
|
||||||
connect(rename, &QAction::triggered, Core::ICore::instance(), [] {
|
connect(rename, &QAction::triggered, Core::ICore::instance(), [] {
|
||||||
if (auto navWidget = currentFolderNavigationWidget())
|
if (auto navWidget = currentFolderNavigationWidget())
|
||||||
navWidget->editCurrentItem();
|
navWidget->editCurrentItem();
|
||||||
});
|
});
|
||||||
|
|
||||||
auto remove = new QAction(tr("Remove..."), this);
|
auto remove = new QAction(tr("Remove..."), this);
|
||||||
Core::ActionManager::registerAction(remove, Constants::REMOVEFILE, context);
|
Core::ActionManager::registerAction(remove, REMOVEFILE, context);
|
||||||
connect(remove, &QAction::triggered, Core::ICore::instance(), [] {
|
connect(remove, &QAction::triggered, Core::ICore::instance(), [] {
|
||||||
if (auto navWidget = currentFolderNavigationWidget())
|
if (auto navWidget = currentFolderNavigationWidget())
|
||||||
navWidget->removeCurrentItem();
|
navWidget->removeCurrentItem();
|
||||||
|
@@ -46,6 +46,7 @@ QT_BEGIN_NAMESPACE
|
|||||||
class QAction;
|
class QAction;
|
||||||
class QComboBox;
|
class QComboBox;
|
||||||
class QFileSystemModel;
|
class QFileSystemModel;
|
||||||
|
class QMenu;
|
||||||
class QModelIndex;
|
class QModelIndex;
|
||||||
class QSortFilterProxyModel;
|
class QSortFilterProxyModel;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
@@ -85,6 +86,10 @@ signals:
|
|||||||
void rootDirectoryAdded(const RootDirectory &directory);
|
void rootDirectoryAdded(const RootDirectory &directory);
|
||||||
void rootDirectoryRemoved(const QString &id);
|
void rootDirectoryRemoved(const QString &id);
|
||||||
|
|
||||||
|
void aboutToShowContextMenu(QMenu *menu, const Utils::FilePath &filePath, bool isDir);
|
||||||
|
void fileRenamed(const Utils::FilePath &before, const Utils::FilePath &after);
|
||||||
|
void aboutToRemoveFile(const Utils::FilePath &filePath);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static int rootIndex(const QString &id);
|
static int rootIndex(const QString &id);
|
||||||
void updateProjectsDirectoryRoot();
|
void updateProjectsDirectoryRoot();
|
||||||
@@ -101,8 +106,6 @@ class FolderNavigationWidget : public QWidget
|
|||||||
public:
|
public:
|
||||||
explicit FolderNavigationWidget(QWidget *parent = nullptr);
|
explicit FolderNavigationWidget(QWidget *parent = nullptr);
|
||||||
|
|
||||||
static QStringList projectFilesInDirectory(const QString &path);
|
|
||||||
|
|
||||||
bool autoSynchronization() const;
|
bool autoSynchronization() const;
|
||||||
bool hiddenFilesFilter() const;
|
bool hiddenFilesFilter() const;
|
||||||
bool isShowingBreadCrumbs() const;
|
bool isShowingBreadCrumbs() const;
|
||||||
@@ -138,8 +141,6 @@ private:
|
|||||||
void setRootDirectory(const Utils::FilePath &directory);
|
void setRootDirectory(const Utils::FilePath &directory);
|
||||||
int bestRootForFile(const Utils::FilePath &filePath);
|
int bestRootForFile(const Utils::FilePath &filePath);
|
||||||
void openItem(const QModelIndex &index);
|
void openItem(const QModelIndex &index);
|
||||||
QStringList projectsInDirectory(const QModelIndex &index) const;
|
|
||||||
void openProjectsInDirectory(const QModelIndex &index);
|
|
||||||
void createNewFolder(const QModelIndex &parent);
|
void createNewFolder(const QModelIndex &parent);
|
||||||
|
|
||||||
Utils::NavigationTreeView *m_listView = nullptr;
|
Utils::NavigationTreeView *m_listView = nullptr;
|
||||||
|
@@ -491,6 +491,8 @@ public:
|
|||||||
|
|
||||||
QList<QPair<QString, QString> > recentProjects() const;
|
QList<QPair<QString, QString> > recentProjects() const;
|
||||||
|
|
||||||
|
void extendFolderNavigationWidgetFactory();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QMenu *m_sessionMenu;
|
QMenu *m_sessionMenu;
|
||||||
QMenu *m_openWithMenu;
|
QMenu *m_openWithMenu;
|
||||||
@@ -692,6 +694,57 @@ public:
|
|||||||
static ProjectExplorerPlugin *m_instance = nullptr;
|
static ProjectExplorerPlugin *m_instance = nullptr;
|
||||||
static ProjectExplorerPluginPrivate *dd = nullptr;
|
static ProjectExplorerPluginPrivate *dd = nullptr;
|
||||||
|
|
||||||
|
static FilePaths projectFilesInDirectory(const FilePath &path)
|
||||||
|
{
|
||||||
|
return path.dirEntries(ProjectExplorerPlugin::projectFileGlobs(), QDir::Files);
|
||||||
|
}
|
||||||
|
|
||||||
|
static FilePaths projectsInDirectory(const FilePath &filePath)
|
||||||
|
{
|
||||||
|
if (!filePath.isReadableDir())
|
||||||
|
return {};
|
||||||
|
return projectFilesInDirectory(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void openProjectsInDirectory(const FilePath &filePath)
|
||||||
|
{
|
||||||
|
const FilePaths projectFiles = projectsInDirectory(filePath);
|
||||||
|
if (!projectFiles.isEmpty())
|
||||||
|
Core::ICore::openFiles(projectFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static QVector<FolderNode *> renamableFolderNodes(const FilePath &before, const FilePath &after)
|
||||||
|
{
|
||||||
|
QVector<FolderNode *> folderNodes;
|
||||||
|
ProjectTree::forEachNode([&](Node *node) {
|
||||||
|
if (node->asFileNode() && node->filePath() == before && node->parentFolderNode()
|
||||||
|
&& node->parentFolderNode()->canRenameFile(before, after)) {
|
||||||
|
folderNodes.append(node->parentFolderNode());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return folderNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
static QVector<FolderNode *> removableFolderNodes(const Utils::FilePath &filePath)
|
||||||
|
{
|
||||||
|
QVector<FolderNode *> folderNodes;
|
||||||
|
ProjectTree::forEachNode([&](Node *node) {
|
||||||
|
if (node->asFileNode() && node->filePath() == filePath && node->parentFolderNode()
|
||||||
|
&& node->parentFolderNode()->supportsAction(RemoveFile, node)) {
|
||||||
|
folderNodes.append(node->parentFolderNode());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return folderNodes;
|
||||||
|
}
|
||||||
|
|
||||||
ProjectExplorerPlugin::ProjectExplorerPlugin()
|
ProjectExplorerPlugin::ProjectExplorerPlugin()
|
||||||
{
|
{
|
||||||
m_instance = this;
|
m_instance = this;
|
||||||
@@ -726,6 +779,8 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
|
|||||||
|
|
||||||
dd = new ProjectExplorerPluginPrivate;
|
dd = new ProjectExplorerPluginPrivate;
|
||||||
|
|
||||||
|
dd->extendFolderNavigationWidgetFactory();
|
||||||
|
|
||||||
qRegisterMetaType<ProjectExplorer::BuildSystem *>();
|
qRegisterMetaType<ProjectExplorer::BuildSystem *>();
|
||||||
qRegisterMetaType<ProjectExplorer::RunControl *>();
|
qRegisterMetaType<ProjectExplorer::RunControl *>();
|
||||||
qRegisterMetaType<ProjectExplorer::DeployableFile>("ProjectExplorer::DeployableFile");
|
qRegisterMetaType<ProjectExplorer::DeployableFile>("ProjectExplorer::DeployableFile");
|
||||||
@@ -1377,7 +1432,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
|
|||||||
msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_RUN);
|
msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_RUN);
|
||||||
|
|
||||||
// add new file action
|
// add new file action
|
||||||
dd->m_addNewFileAction = new QAction(this);
|
dd->m_addNewFileAction = new QAction(tr("Add New..."), this);
|
||||||
cmd = ActionManager::registerAction(dd->m_addNewFileAction, Constants::ADDNEWFILE,
|
cmd = ActionManager::registerAction(dd->m_addNewFileAction, Constants::ADDNEWFILE,
|
||||||
projectTreeContext);
|
projectTreeContext);
|
||||||
mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
|
mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
|
||||||
@@ -1446,7 +1501,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
|
|||||||
mfileContextMenu->addAction(cmd, Constants::G_FILE_OTHER);
|
mfileContextMenu->addAction(cmd, Constants::G_FILE_OTHER);
|
||||||
|
|
||||||
// remove file action
|
// remove file action
|
||||||
dd->m_removeFileAction = new QAction(this);
|
dd->m_removeFileAction = new QAction(tr("Remove..."), this);
|
||||||
cmd = ActionManager::registerAction(dd->m_removeFileAction, Constants::REMOVEFILE,
|
cmd = ActionManager::registerAction(dd->m_removeFileAction, Constants::REMOVEFILE,
|
||||||
projectTreeContext);
|
projectTreeContext);
|
||||||
cmd->setDefaultKeySequences({QKeySequence::Delete, QKeySequence::Backspace});
|
cmd->setDefaultKeySequences({QKeySequence::Delete, QKeySequence::Backspace});
|
||||||
@@ -1472,7 +1527,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
|
|||||||
mfileContextMenu->addAction(cmd, Constants::G_FILE_OTHER);
|
mfileContextMenu->addAction(cmd, Constants::G_FILE_OTHER);
|
||||||
|
|
||||||
// renamefile action
|
// renamefile action
|
||||||
dd->m_renameFileAction = new QAction(this);
|
dd->m_renameFileAction = new QAction(tr("Rename..."), this);
|
||||||
cmd = ActionManager::registerAction(dd->m_renameFileAction, Constants::RENAMEFILE,
|
cmd = ActionManager::registerAction(dd->m_renameFileAction, Constants::RENAMEFILE,
|
||||||
projectTreeContext);
|
projectTreeContext);
|
||||||
mfileContextMenu->addAction(cmd, Constants::G_FILE_OTHER);
|
mfileContextMenu->addAction(cmd, Constants::G_FILE_OTHER);
|
||||||
@@ -2116,10 +2171,9 @@ void ProjectExplorerPlugin::extensionsInitialized()
|
|||||||
|
|
||||||
dd->m_documentFactory.setOpener([](FilePath filePath) {
|
dd->m_documentFactory.setOpener([](FilePath filePath) {
|
||||||
if (filePath.isDir()) {
|
if (filePath.isDir()) {
|
||||||
const QStringList files =
|
const FilePaths files = projectFilesInDirectory(filePath.absoluteFilePath());
|
||||||
FolderNavigationWidget::projectFilesInDirectory(filePath.absoluteFilePath().toString());
|
|
||||||
if (!files.isEmpty())
|
if (!files.isEmpty())
|
||||||
filePath = FilePath::fromString(files.front());
|
filePath = files.front();
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenProjectResult result = ProjectExplorerPlugin::openProject(filePath);
|
OpenProjectResult result = ProjectExplorerPlugin::openProject(filePath);
|
||||||
@@ -2876,11 +2930,76 @@ bool ProjectExplorerPlugin::saveModifiedFiles()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//NBS handle case where there is no activeBuildConfiguration
|
ProjectExplorerPluginPrivate::ProjectExplorerPluginPrivate() {}
|
||||||
// because someone delete all build configurations
|
|
||||||
|
|
||||||
ProjectExplorerPluginPrivate::ProjectExplorerPluginPrivate()
|
void ProjectExplorerPluginPrivate::extendFolderNavigationWidgetFactory()
|
||||||
{
|
{
|
||||||
|
connect(&m_folderNavigationWidgetFactory,
|
||||||
|
&FolderNavigationWidgetFactory::aboutToShowContextMenu,
|
||||||
|
this,
|
||||||
|
[this](QMenu *menu, const FilePath &filePath, bool isDir) {
|
||||||
|
if (isDir) {
|
||||||
|
QAction *actionOpenProjects = menu->addAction(
|
||||||
|
ProjectExplorerPlugin::tr("Open Project in \"%1\"")
|
||||||
|
.arg(filePath.toUserOutput()));
|
||||||
|
connect(actionOpenProjects, &QAction::triggered, this, [filePath] {
|
||||||
|
openProjectsInDirectory(filePath);
|
||||||
|
});
|
||||||
|
if (projectsInDirectory(filePath).isEmpty())
|
||||||
|
actionOpenProjects->setEnabled(false);
|
||||||
|
} else if (ProjectExplorerPlugin::isProjectFile(filePath)) {
|
||||||
|
QAction *actionOpenAsProject = menu->addAction(
|
||||||
|
tr("Open Project \"%1\"").arg(filePath.toUserOutput()));
|
||||||
|
connect(actionOpenAsProject, &QAction::triggered, this, [filePath] {
|
||||||
|
ProjectExplorerPlugin::openProject(filePath);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
connect(&m_folderNavigationWidgetFactory,
|
||||||
|
&FolderNavigationWidgetFactory::fileRenamed,
|
||||||
|
this,
|
||||||
|
[](const FilePath &before, const FilePath &after) {
|
||||||
|
const QVector<FolderNode *> folderNodes = renamableFolderNodes(before, after);
|
||||||
|
QVector<FolderNode *> failedNodes;
|
||||||
|
for (FolderNode *folder : folderNodes) {
|
||||||
|
if (!folder->renameFile(before, after))
|
||||||
|
failedNodes.append(folder);
|
||||||
|
}
|
||||||
|
if (!failedNodes.isEmpty()) {
|
||||||
|
const QString projects = projectNames(failedNodes).join(", ");
|
||||||
|
const QString errorMessage
|
||||||
|
= ProjectExplorerPlugin::tr(
|
||||||
|
"The file \"%1\" was renamed to \"%2\", "
|
||||||
|
"but the following projects could not be automatically changed: %3")
|
||||||
|
.arg(before.toUserOutput(), after.toUserOutput(), projects);
|
||||||
|
QTimer::singleShot(0, Core::ICore::instance(), [errorMessage] {
|
||||||
|
QMessageBox::warning(Core::ICore::dialogParent(),
|
||||||
|
ProjectExplorerPlugin::tr("Project Editing Failed"),
|
||||||
|
errorMessage);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
connect(&m_folderNavigationWidgetFactory,
|
||||||
|
&FolderNavigationWidgetFactory::aboutToRemoveFile,
|
||||||
|
this,
|
||||||
|
[](const FilePath &filePath) {
|
||||||
|
const QVector<FolderNode *> folderNodes = removableFolderNodes(filePath);
|
||||||
|
const QVector<FolderNode *> failedNodes
|
||||||
|
= Utils::filtered(folderNodes, [filePath](FolderNode *folder) {
|
||||||
|
return folder->removeFiles({filePath}) != RemovedFilesFromProject::Ok;
|
||||||
|
});
|
||||||
|
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(),
|
||||||
|
tr("Project Editing Failed"),
|
||||||
|
errorMessage);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProjectExplorerPluginPrivate::runProjectContextMenu()
|
void ProjectExplorerPluginPrivate::runProjectContextMenu()
|
||||||
|
@@ -94,8 +94,6 @@ const Icon BUILDSTEP_REMOVE({
|
|||||||
|
|
||||||
const Icon DESKTOP_DEVICE({
|
const Icon DESKTOP_DEVICE({
|
||||||
{":/projectexplorer/images/desktopdevice.png", Theme::IconsBaseColor}});
|
{":/projectexplorer/images/desktopdevice.png", Theme::IconsBaseColor}});
|
||||||
const Icon DESKTOP_DEVICE_SMALL({
|
|
||||||
{":/utils/images/desktopdevicesmall.png", Theme::PanelTextColorDark}}, Icon::Tint);
|
|
||||||
|
|
||||||
const Icon MODE_PROJECT_CLASSIC(":/projectexplorer/images/mode_project.png");
|
const Icon MODE_PROJECT_CLASSIC(":/projectexplorer/images/mode_project.png");
|
||||||
const Icon MODE_PROJECT_FLAT({
|
const Icon MODE_PROJECT_FLAT({
|
||||||
|
@@ -61,7 +61,6 @@ PROJECTEXPLORER_EXPORT extern const Utils::Icon BUILDSTEP_DISABLE;
|
|||||||
PROJECTEXPLORER_EXPORT extern const Utils::Icon BUILDSTEP_REMOVE;
|
PROJECTEXPLORER_EXPORT extern const Utils::Icon BUILDSTEP_REMOVE;
|
||||||
|
|
||||||
PROJECTEXPLORER_EXPORT extern const Utils::Icon DESKTOP_DEVICE;
|
PROJECTEXPLORER_EXPORT extern const Utils::Icon DESKTOP_DEVICE;
|
||||||
PROJECTEXPLORER_EXPORT extern const Utils::Icon DESKTOP_DEVICE_SMALL;
|
|
||||||
|
|
||||||
PROJECTEXPLORER_EXPORT extern const Utils::Icon MODE_PROJECT_CLASSIC;
|
PROJECTEXPLORER_EXPORT extern const Utils::Icon MODE_PROJECT_CLASSIC;
|
||||||
PROJECTEXPLORER_EXPORT extern const Utils::Icon MODE_PROJECT_FLAT;
|
PROJECTEXPLORER_EXPORT extern const Utils::Icon MODE_PROJECT_FLAT;
|
||||||
|
Reference in New Issue
Block a user