Commit 69747957 authored by Eike Ziller's avatar Eike Ziller

Move Open With... handling to editor manager.

Change-Id: I27faa327ae33244927e21aa74875d9601aaf9e50
Reviewed-by: default avatarDavid Schulz <david.schulz@theqtcompany.com>
parent 2e4a86a8
......@@ -1375,88 +1375,6 @@ void DocumentManager::notifyFilesChangedInternally(const QStringList &files)
emit m_instance->filesChangedInternally(files);
}
static void openEditorWith(const QString &fileName, Core::Id editorId)
{
// close any open editors that have this file open
// remember the views to open new editors in there
QList<EditorView *> views;
QList<IEditor *> editorsOpenForFile
= DocumentModel::editorsForFilePath(fileName);
foreach (IEditor *openEditor, editorsOpenForFile) {
EditorView *view = EditorManagerPrivate::viewForEditor(openEditor);
if (view && view->currentEditor() == openEditor) // visible
views.append(view);
}
if (!EditorManager::closeEditors(editorsOpenForFile)) // don't open if cancel was pressed
return;
if (views.isEmpty()) {
EditorManager::openEditor(fileName, editorId);
} else {
if (EditorView *currentView = EditorManagerPrivate::currentEditorView()) {
if (views.removeOne(currentView))
views.prepend(currentView); // open editor in current view first
}
EditorManager::OpenEditorFlags flags;
foreach (EditorView *view, views) {
IEditor *editor = EditorManagerPrivate::openEditor(view, fileName, editorId, flags);
// Do not change the current editor after opening the first one. That
// * prevents multiple updates of focus etc which are not necessary
// * lets us control which editor is made current by putting the current editor view
// to the front (if that was in the list in the first place)
flags |= EditorManager::DoNotChangeCurrentEditor;
// do not try to open more editors if this one failed, or editor type does not
// support duplication anyhow
if (!editor || !editor->duplicateSupported())
break;
}
}
}
void DocumentManager::populateOpenWithMenu(QMenu *menu, const QString &fileName)
{
typedef QList<IEditorFactory*> EditorFactoryList;
typedef QList<IExternalEditor*> ExternalEditorList;
menu->clear();
bool anyMatches = false;
Utils::MimeDatabase mdb;
const Utils::MimeType mt = mdb.mimeTypeForFile(fileName);
if (mt.isValid()) {
const EditorFactoryList factories = EditorManager::editorFactories(mt, false);
const ExternalEditorList externalEditors = EditorManager::externalEditors(mt, false);
anyMatches = !factories.empty() || !externalEditors.empty();
if (anyMatches) {
// Add all suitable editors
foreach (IEditorFactory *editorFactory, factories) {
Core::Id editorId = editorFactory->id();
// Add action to open with this very editor factory
QString const actionTitle = editorFactory->displayName();
QAction *action = menu->addAction(actionTitle);
// Below we need QueuedConnection because otherwise, if a qrc file
// is inside of a qrc file itself, and the qrc editor opens the Open with menu,
// crashes happen, because the editor instance is deleted by openEditorWith
// while the menu is still being processed.
connect(action, &QAction::triggered, EditorManager::instance(),
[fileName, editorId]() {
openEditorWith(fileName, editorId);
}, Qt::QueuedConnection);
}
// Add all suitable external editors
foreach (IExternalEditor *externalEditor, externalEditors) {
QAction *action = menu->addAction(externalEditor->displayName());
Core::Id editorId = externalEditor->id();
connect(action, &QAction::triggered, [fileName, editorId]() {
EditorManager::openExternalEditor(fileName, editorId);
});
}
}
}
menu->setEnabled(anyMatches);
}
bool DocumentManager::eventFilter(QObject *obj, QEvent *e)
{
if (obj == qApp && e->type() == QEvent::ApplicationActivate) {
......
......@@ -137,8 +137,6 @@ public:
static QString buildDirectory();
static void setBuildDirectory(const QString &directory);
static void populateOpenWithMenu(QMenu *menu, const QString &fileName);
/* Used to notify e.g. the code model to update the given files. Does *not*
lead to any editors to reload or any other editor manager actions. */
static void notifyFilesChangedInternally(const QStringList &files);
......
......@@ -686,6 +686,48 @@ IEditor *EditorManagerPrivate::openEditorAt(EditorView *view, const QString &fil
return editor;
}
IEditor *EditorManagerPrivate::openEditorWith(const QString &fileName, Core::Id editorId)
{
// close any open editors that have this file open
// remember the views to open new editors in there
QList<EditorView *> views;
QList<IEditor *> editorsOpenForFile
= DocumentModel::editorsForFilePath(fileName);
foreach (IEditor *openEditor, editorsOpenForFile) {
EditorView *view = EditorManagerPrivate::viewForEditor(openEditor);
if (view && view->currentEditor() == openEditor) // visible
views.append(view);
}
if (!EditorManager::closeEditors(editorsOpenForFile)) // don't open if cancel was pressed
return 0;
IEditor *openedEditor = 0;
if (views.isEmpty()) {
openedEditor = EditorManager::openEditor(fileName, editorId);
} else {
if (EditorView *currentView = EditorManagerPrivate::currentEditorView()) {
if (views.removeOne(currentView))
views.prepend(currentView); // open editor in current view first
}
EditorManager::OpenEditorFlags flags;
foreach (EditorView *view, views) {
IEditor *editor = EditorManagerPrivate::openEditor(view, fileName, editorId, flags);
if (!openedEditor && editor)
openedEditor = editor;
// Do not change the current editor after opening the first one. That
// * prevents multiple updates of focus etc which are not necessary
// * lets us control which editor is made current by putting the current editor view
// to the front (if that was in the list in the first place)
flags |= EditorManager::DoNotChangeCurrentEditor;
// do not try to open more editors if this one failed, or editor type does not
// support duplication anyhow
if (!editor || !editor->duplicateSupported())
break;
}
}
return openedEditor;
}
IEditor *EditorManagerPrivate::activateEditorForDocument(EditorView *view, IDocument *document,
EditorManager::OpenEditorFlags flags)
{
......@@ -2087,7 +2129,51 @@ void EditorManager::addNativeDirAndOpenWithActions(QMenu *contextMenu, DocumentM
QMenu *openWith = contextMenu->addMenu(tr("Open With"));
openWith->setEnabled(enabled);
if (enabled)
DocumentManager::populateOpenWithMenu(openWith, entry->fileName().toString());
populateOpenWithMenu(openWith, entry->fileName().toString());
}
void EditorManager::populateOpenWithMenu(QMenu *menu, const QString &fileName)
{
typedef QList<IEditorFactory*> EditorFactoryList;
typedef QList<IExternalEditor*> ExternalEditorList;
menu->clear();
bool anyMatches = false;
Utils::MimeDatabase mdb;
const Utils::MimeType mt = mdb.mimeTypeForFile(fileName);
if (mt.isValid()) {
const EditorFactoryList factories = editorFactories(mt, false);
const ExternalEditorList extEditors = externalEditors(mt, false);
anyMatches = !factories.empty() || !extEditors.empty();
if (anyMatches) {
// Add all suitable editors
foreach (IEditorFactory *editorFactory, factories) {
Core::Id editorId = editorFactory->id();
// Add action to open with this very editor factory
QString const actionTitle = editorFactory->displayName();
QAction *action = menu->addAction(actionTitle);
// Below we need QueuedConnection because otherwise, if a qrc file
// is inside of a qrc file itself, and the qrc editor opens the Open with menu,
// crashes happen, because the editor instance is deleted by openEditorWith
// while the menu is still being processed.
connect(action, &QAction::triggered, d,
[fileName, editorId]() {
EditorManagerPrivate::openEditorWith(fileName, editorId);
}, Qt::QueuedConnection);
}
// Add all suitable external editors
foreach (IExternalEditor *externalEditor, extEditors) {
QAction *action = menu->addAction(externalEditor->displayName());
Core::Id editorId = externalEditor->id();
connect(action, &QAction::triggered, [fileName, editorId]() {
EditorManager::openExternalEditor(fileName, editorId);
});
}
}
}
menu->setEnabled(anyMatches);
}
void EditorManager::saveDocument()
......
......@@ -169,6 +169,7 @@ public:
static void addSaveAndCloseEditorActions(QMenu *contextMenu, DocumentModel::Entry *entry,
IEditor *editor = 0);
static void addNativeDirAndOpenWithActions(QMenu *contextMenu, DocumentModel::Entry *entry);
static void populateOpenWithMenu(QMenu *menu, const QString &fileName);
signals:
void currentEditorChanged(Core::IEditor *editor);
......
......@@ -85,6 +85,7 @@ public:
Id editorId = Id(),
EditorManager::OpenEditorFlags flags = EditorManager::NoFlags,
bool *newEditor = 0);
static IEditor *openEditorWith(const QString &fileName, Core::Id editorId);
static IEditor *duplicateEditor(IEditor *editor);
static IEditor *activateEditor(EditorView *view, IEditor *editor,
EditorManager::OpenEditorFlags flags = EditorManager::NoFlags);
......
......@@ -37,7 +37,6 @@
#include <coreplugin/icore.h>
#include <coreplugin/idocument.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/documentmanager.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/coreconstants.h>
......@@ -365,8 +364,8 @@ void FolderNavigationWidget::contextMenuEvent(QContextMenuEvent *ev)
// open with...
if (hasCurrentItem && !isDirectory) {
QMenu *openWith = menu.addMenu(tr("Open With"));
Core::DocumentManager::populateOpenWithMenu(openWith,
m_fileSystemModel->filePath(current));
Core::EditorManager::populateOpenWithMenu(openWith,
m_fileSystemModel->filePath(current));
}
// Open file dialog to choose a path starting from current
......
......@@ -2944,7 +2944,8 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions()
m_removeFileAction->setVisible(!enableDelete || enableRemove);
m_renameFileAction->setEnabled(actions.contains(Rename));
DocumentManager::populateOpenWithMenu(m_openWithMenu, ProjectTree::currentNode()->path().toString());
EditorManager::populateOpenWithMenu(m_openWithMenu,
ProjectTree::currentNode()->path().toString());
}
if (actions.contains(HidePathActions)) {
......
......@@ -37,7 +37,6 @@
#include <coreplugin/icore.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/documentmanager.h>
#include <coreplugin/id.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
......@@ -346,7 +345,7 @@ void ResourceEditorPlugin::updateContextActions(Node *node, Project *)
m_removeNonExisting->setVisible(isResourceNode);
if (isResourceNode)
Core::DocumentManager::populateOpenWithMenu(m_openWithMenu, node->path().toString());
Core::EditorManager::populateOpenWithMenu(m_openWithMenu, node->path().toString());
else
m_openWithMenu->clear();
m_openWithMenu->menuAction()->setVisible(!m_openWithMenu->actions().isEmpty());
......
......@@ -39,7 +39,6 @@
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/commandbutton.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/documentmanager.h>
#include <coreplugin/find/itemviewfind.h>
#include <utils/reloadpromptutils.h>
#include <utils/fileutils.h>
......@@ -280,7 +279,7 @@ void ResourceEditorW::onUndoStackChanged(bool canUndo, bool canRedo)
void ResourceEditorW::showContextMenu(const QPoint &globalPoint, const QString &fileName)
{
Core::DocumentManager::populateOpenWithMenu(m_openWithMenu, fileName);
Core::EditorManager::populateOpenWithMenu(m_openWithMenu, fileName);
m_currentFileName = fileName;
m_renameAction->setEnabled(!document()->isFileReadOnly());
m_contextMenu->popup(globalPoint);
......
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