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:
Eike Ziller
2021-10-05 14:16:42 +02:00
parent 348c3c98a0
commit b2cdfccf54
8 changed files with 162 additions and 149 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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();

View File

@@ -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;

View File

@@ -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()

View File

@@ -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({

View File

@@ -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;