forked from qt-creator/qt-creator
Support external editors for locator, projects and file system tree
When setting an external editor as the default editor in the MIME type settings. Other operations like File > Open, or when using navigation shortcuts like Follow Symbol, and stepping with the debugger will still always open the file within Qt Creator. The Open with... menu can still be used to explicitly open a file in an external editor afterwards. One of the use cases is to be able to open some files that would otherwise unhelpfully be opened in Qt Creator's binary editor in the systems default editor. Fixes: QTCREATORBUG-13880 Change-Id: I852f097da8badd10de78b74e7078987447eebe98 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: David Schulz <david.schulz@qt.io> Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -185,7 +185,9 @@ void OpenCMakeTargetLocatorFilter::accept(Core::LocatorFilterEntry selection,
|
||||
const auto file = FilePath::fromVariant(extraData.value("file"));
|
||||
|
||||
if (line >= 0)
|
||||
Core::EditorManager::openEditorAt({file, line});
|
||||
Core::EditorManager::openEditorAt({file, line},
|
||||
{},
|
||||
Core::EditorManager::AllowExternalEditor);
|
||||
else
|
||||
Core::EditorManager::openEditor(file);
|
||||
Core::EditorManager::openEditor(file, {}, Core::EditorManager::AllowExternalEditor);
|
||||
}
|
||||
|
||||
@@ -135,6 +135,14 @@ using namespace Core;
|
||||
using namespace Core::Internal;
|
||||
using namespace Utils;
|
||||
|
||||
static void checkEditorFlags(EditorManager::OpenEditorFlags flags)
|
||||
{
|
||||
if (flags & EditorManager::OpenInOtherSplit) {
|
||||
QTC_CHECK(!(flags & EditorManager::SwitchSplitIfAlreadyVisible));
|
||||
QTC_CHECK(!(flags & EditorManager::AllowExternalEditor));
|
||||
}
|
||||
}
|
||||
|
||||
//===================EditorManager=====================
|
||||
|
||||
/*!
|
||||
@@ -812,13 +820,21 @@ IEditor *EditorManagerPrivate::openEditor(EditorView *view, const FilePath &file
|
||||
return activateEditor(view, editor, flags);
|
||||
}
|
||||
|
||||
if (skipOpeningBigTextFile(filePath))
|
||||
return nullptr;
|
||||
|
||||
FilePath realFp = autoSaveName(filePath);
|
||||
if (!filePath.exists() || !realFp.exists() || filePath.lastModified() >= realFp.lastModified()) {
|
||||
realFp.removeFile();
|
||||
realFp = filePath;
|
||||
}
|
||||
|
||||
EditorFactoryList factories = EditorManagerPrivate::findFactories(Id(), filePath);
|
||||
EditorTypeList factories = EditorType::preferredEditorTypes(filePath);
|
||||
if (!(flags & EditorManager::AllowExternalEditor)) {
|
||||
factories = Utils::filtered(factories, [](EditorType *type) {
|
||||
return type->asEditorFactory() != nullptr;
|
||||
});
|
||||
}
|
||||
if (factories.isEmpty()) {
|
||||
Utils::MimeType mimeType = Utils::mimeTypeForFile(filePath);
|
||||
QMessageBox msgbox(QMessageBox::Critical, EditorManager::tr("File Error"),
|
||||
@@ -829,48 +845,56 @@ IEditor *EditorManagerPrivate::openEditor(EditorView *view, const FilePath &file
|
||||
return nullptr;
|
||||
}
|
||||
if (editorId.isValid()) {
|
||||
IEditorFactory *factory = Utils::findOrDefault(IEditorFactory::allEditorFactories(),
|
||||
Utils::equal(&IEditorFactory::id, editorId));
|
||||
EditorType *factory = EditorType::editorTypeForId(editorId);
|
||||
if (factory) {
|
||||
QTC_CHECK(factory->asEditorFactory() || (flags & EditorManager::AllowExternalEditor));
|
||||
factories.removeOne(factory);
|
||||
factories.push_front(factory);
|
||||
}
|
||||
}
|
||||
|
||||
if (skipOpeningBigTextFile(filePath))
|
||||
return nullptr;
|
||||
|
||||
IEditor *editor = nullptr;
|
||||
auto overrideCursor = Utils::OverrideCursor(QCursor(Qt::WaitCursor));
|
||||
|
||||
IEditorFactory *factory = factories.takeFirst();
|
||||
EditorType *factory = factories.takeFirst();
|
||||
while (factory) {
|
||||
editor = createEditor(factory, filePath);
|
||||
if (!editor) {
|
||||
factory = factories.takeFirst();
|
||||
continue;
|
||||
}
|
||||
|
||||
QString errorString;
|
||||
IDocument::OpenResult openResult = editor->document()->open(&errorString, filePath, realFp);
|
||||
if (openResult == IDocument::OpenResult::Success)
|
||||
break;
|
||||
|
||||
overrideCursor.reset();
|
||||
delete editor;
|
||||
editor = nullptr;
|
||||
|
||||
if (openResult == IDocument::OpenResult::ReadError) {
|
||||
QMessageBox msgbox(QMessageBox::Critical, EditorManager::tr("File Error"),
|
||||
tr("Could not open \"%1\" for reading. "
|
||||
"Either the file does not exist or you do not have "
|
||||
"the permissions to open it.")
|
||||
.arg(realFp.toUserOutput()),
|
||||
QMessageBox::Ok, ICore::dialogParent());
|
||||
msgbox.exec();
|
||||
return nullptr;
|
||||
if (factory->asEditorFactory()) {
|
||||
editor = createEditor(factory->asEditorFactory(), filePath);
|
||||
if (!editor) {
|
||||
factory = factories.isEmpty() ? nullptr : factories.takeFirst();
|
||||
continue;
|
||||
}
|
||||
IDocument::OpenResult openResult = editor->document()->open(&errorString,
|
||||
filePath,
|
||||
realFp);
|
||||
if (openResult == IDocument::OpenResult::Success)
|
||||
break;
|
||||
overrideCursor.reset();
|
||||
delete editor;
|
||||
editor = nullptr;
|
||||
if (openResult == IDocument::OpenResult::ReadError) {
|
||||
QMessageBox msgbox(QMessageBox::Critical,
|
||||
EditorManager::tr("File Error"),
|
||||
tr("Could not open \"%1\" for reading. "
|
||||
"Either the file does not exist or you do not have "
|
||||
"the permissions to open it.")
|
||||
.arg(realFp.toUserOutput()),
|
||||
QMessageBox::Ok,
|
||||
ICore::dialogParent());
|
||||
msgbox.exec();
|
||||
return nullptr;
|
||||
}
|
||||
// can happen e.g. when trying to open an completely empty .qrc file
|
||||
QTC_CHECK(openResult == IDocument::OpenResult::CannotHandle);
|
||||
} else {
|
||||
QTC_ASSERT(factory->asExternalEditor(),
|
||||
factory = factories.isEmpty() ? nullptr : factories.takeFirst();
|
||||
continue);
|
||||
if (factory->asExternalEditor()->startEditor(filePath, &errorString))
|
||||
break;
|
||||
}
|
||||
QTC_CHECK(openResult == IDocument::OpenResult::CannotHandle);
|
||||
|
||||
if (errorString.isEmpty())
|
||||
errorString = tr("Could not open \"%1\": Unknown error.").arg(realFp.toUserOutput());
|
||||
@@ -881,12 +905,12 @@ IEditor *EditorManagerPrivate::openEditor(EditorView *view, const FilePath &file
|
||||
QMessageBox::Open | QMessageBox::Cancel,
|
||||
ICore::dialogParent());
|
||||
|
||||
IEditorFactory *selectedFactory = nullptr;
|
||||
EditorType *selectedFactory = nullptr;
|
||||
if (!factories.isEmpty()) {
|
||||
auto button = qobject_cast<QPushButton *>(msgbox.button(QMessageBox::Open));
|
||||
QTC_ASSERT(button, return nullptr);
|
||||
auto menu = new QMenu(button);
|
||||
foreach (IEditorFactory *factory, factories) {
|
||||
foreach (EditorType *factory, factories) {
|
||||
QAction *action = menu->addAction(factory->displayName());
|
||||
connect(action, &QAction::triggered, &msgbox, [&selectedFactory, factory, &msgbox]() {
|
||||
selectedFactory = factory;
|
||||
@@ -3020,8 +3044,11 @@ bool EditorManager::closeEditors(const QList<IEditor*> &editorsToClose, bool ask
|
||||
*/
|
||||
void EditorManager::activateEditorForEntry(DocumentModel::Entry *entry, OpenEditorFlags flags)
|
||||
{
|
||||
QTC_CHECK(!(flags & EditorManager::AllowExternalEditor));
|
||||
|
||||
EditorManagerPrivate::activateEditorForEntry(EditorManagerPrivate::currentEditorView(),
|
||||
entry, flags);
|
||||
entry,
|
||||
flags);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -3031,7 +3058,9 @@ void EditorManager::activateEditorForEntry(DocumentModel::Entry *entry, OpenEdit
|
||||
*/
|
||||
void EditorManager::activateEditor(IEditor *editor, OpenEditorFlags flags)
|
||||
{
|
||||
QTC_ASSERT(editor, return);
|
||||
QTC_CHECK(!(flags & EditorManager::AllowExternalEditor));
|
||||
|
||||
QTC_ASSERT(editor, return );
|
||||
EditorView *view = EditorManagerPrivate::viewForEditor(editor);
|
||||
// an IEditor doesn't have to belong to a view, it might be kept in storage by the editor model
|
||||
if (!view)
|
||||
@@ -3045,7 +3074,11 @@ void EditorManager::activateEditor(IEditor *editor, OpenEditorFlags flags)
|
||||
*/
|
||||
IEditor *EditorManager::activateEditorForDocument(IDocument *document, OpenEditorFlags flags)
|
||||
{
|
||||
return EditorManagerPrivate::activateEditorForDocument(EditorManagerPrivate::currentEditorView(), document, flags);
|
||||
QTC_CHECK(!(flags & EditorManager::AllowExternalEditor));
|
||||
|
||||
return EditorManagerPrivate::activateEditorForDocument(EditorManagerPrivate::currentEditorView(),
|
||||
document,
|
||||
flags);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -3066,6 +3099,7 @@ IEditor *EditorManager::activateEditorForDocument(IDocument *document, OpenEdito
|
||||
IEditor *EditorManager::openEditor(const FilePath &filePath, Id editorId,
|
||||
OpenEditorFlags flags, bool *newEditor)
|
||||
{
|
||||
checkEditorFlags(flags);
|
||||
if (flags & EditorManager::OpenInOtherSplit)
|
||||
EditorManager::gotoOtherSplit();
|
||||
|
||||
@@ -3097,6 +3131,7 @@ IEditor *EditorManager::openEditorAt(const Link &link,
|
||||
OpenEditorFlags flags,
|
||||
bool *newEditor)
|
||||
{
|
||||
checkEditorFlags(flags);
|
||||
if (flags & EditorManager::OpenInOtherSplit)
|
||||
EditorManager::gotoOtherSplit();
|
||||
|
||||
@@ -3251,6 +3286,9 @@ IEditor *EditorManager::openEditorWithContents(Id editorId,
|
||||
const QString &uniqueId,
|
||||
OpenEditorFlags flags)
|
||||
{
|
||||
QTC_CHECK(!(flags & EditorManager::AllowExternalEditor));
|
||||
checkEditorFlags(flags);
|
||||
|
||||
if (debugEditorManager)
|
||||
qDebug() << Q_FUNC_INFO << editorId.name() << titlePattern << uniqueId << contents;
|
||||
|
||||
|
||||
@@ -84,7 +84,8 @@ public:
|
||||
DoNotSwitchToDesignMode = 16,
|
||||
DoNotSwitchToEditMode = 32,
|
||||
SwitchSplitIfAlreadyVisible = 64,
|
||||
DoNotRaise = 128
|
||||
DoNotRaise = 128,
|
||||
AllowExternalEditor = 256
|
||||
};
|
||||
Q_DECLARE_FLAGS(OpenEditorFlags, OpenEditorFlag)
|
||||
|
||||
|
||||
@@ -616,7 +616,9 @@ void FolderNavigationWidget::openItem(const QModelIndex &index)
|
||||
if (m_fileSystemModel->isDir(index))
|
||||
return;
|
||||
const QString path = m_fileSystemModel->filePath(index);
|
||||
Core::EditorManager::openEditor(FilePath::fromString(path));
|
||||
Core::EditorManager::openEditor(FilePath::fromString(path),
|
||||
{},
|
||||
Core::EditorManager::AllowExternalEditor);
|
||||
}
|
||||
|
||||
void FolderNavigationWidget::createNewFolder(const QModelIndex &parent)
|
||||
|
||||
@@ -237,11 +237,11 @@ void BaseFileFilter::openEditorAt(const LocatorFilterEntry& selection)
|
||||
const LineColumn lineColumn = LineColumn::extractFromFileName(postfix, postfixPos);
|
||||
if (postfixPos >= 0) {
|
||||
const Link link(selection.filePath, lineColumn.line, lineColumn.column);
|
||||
EditorManager::openEditorAt(link);
|
||||
EditorManager::openEditorAt(link, {}, Core::EditorManager::AllowExternalEditor);
|
||||
return;
|
||||
}
|
||||
}
|
||||
EditorManager::openEditor(selection.filePath);
|
||||
EditorManager::openEditor(selection.filePath, {}, Core::EditorManager::AllowExternalEditor);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -143,8 +143,11 @@ void CppLocatorFilter::accept(Core::LocatorFilterEntry selection,
|
||||
Q_UNUSED(selectionStart)
|
||||
Q_UNUSED(selectionLength)
|
||||
IndexItem::Ptr info = qvariant_cast<IndexItem::Ptr>(selection.internalData);
|
||||
Core::EditorManager::openEditorAt(
|
||||
{Utils::FilePath::fromString(info->fileName()), info->line(), info->column()});
|
||||
Core::EditorManager::openEditorAt({Utils::FilePath::fromString(info->fileName()),
|
||||
info->line(),
|
||||
info->column()},
|
||||
{},
|
||||
Core::EditorManager::AllowExternalEditor);
|
||||
}
|
||||
|
||||
CppClassesFilter::CppClassesFilter(CppLocatorData *locatorData)
|
||||
|
||||
@@ -179,8 +179,11 @@ void SymbolsFindFilter::openEditor(const SearchResultItem &item)
|
||||
if (!item.userData().canConvert<IndexItem::Ptr>())
|
||||
return;
|
||||
IndexItem::Ptr info = item.userData().value<IndexItem::Ptr>();
|
||||
EditorManager::openEditorAt(
|
||||
{FilePath::fromString(info->fileName()), info->line(), info->column()});
|
||||
EditorManager::openEditorAt({FilePath::fromString(info->fileName()),
|
||||
info->line(),
|
||||
info->column()},
|
||||
{},
|
||||
Core::EditorManager::AllowExternalEditor);
|
||||
}
|
||||
|
||||
QWidget *SymbolsFindFilter::createConfigWidget()
|
||||
|
||||
@@ -226,9 +226,11 @@ void DocumentLocatorFilter::accept(Core::LocatorFilterEntry selection,
|
||||
if (selection.internalData.canConvert<Utils::LineColumn>()) {
|
||||
auto lineColumn = qvariant_cast<Utils::LineColumn>(selection.internalData);
|
||||
const Utils::Link link(m_currentUri.toFilePath(), lineColumn.line + 1, lineColumn.column);
|
||||
Core::EditorManager::openEditorAt(link);
|
||||
Core::EditorManager::openEditorAt(link, {}, Core::EditorManager::AllowExternalEditor);
|
||||
} else if (selection.internalData.canConvert<Utils::Link>()) {
|
||||
Core::EditorManager::openEditorAt(qvariant_cast<Utils::Link>(selection.internalData));
|
||||
Core::EditorManager::openEditorAt(qvariant_cast<Utils::Link>(selection.internalData),
|
||||
{},
|
||||
Core::EditorManager::AllowExternalEditor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,7 +331,9 @@ void WorkspaceLocatorFilter::accept(Core::LocatorFilterEntry selection,
|
||||
int * /*selectionLength*/) const
|
||||
{
|
||||
if (selection.internalData.canConvert<Utils::Link>())
|
||||
Core::EditorManager::openEditorAt(qvariant_cast<Utils::Link>(selection.internalData));
|
||||
Core::EditorManager::openEditorAt(qvariant_cast<Utils::Link>(selection.internalData),
|
||||
{},
|
||||
Core::EditorManager::AllowExternalEditor);
|
||||
}
|
||||
|
||||
void WorkspaceLocatorFilter::handleResponse(Client *client,
|
||||
|
||||
@@ -3643,7 +3643,9 @@ void ProjectExplorerPluginPrivate::updateLocationSubMenus()
|
||||
: tr("%1 in %2").arg(li.displayName).arg(li.path.toUserOutput());
|
||||
auto *action = new QAction(displayName, nullptr);
|
||||
connect(action, &QAction::triggered, this, [line, path]() {
|
||||
Core::EditorManager::openEditorAt(Link(path, line));
|
||||
Core::EditorManager::openEditorAt(Link(path, line),
|
||||
{},
|
||||
Core::EditorManager::AllowExternalEditor);
|
||||
});
|
||||
|
||||
projectMenu->addAction(action);
|
||||
|
||||
@@ -563,7 +563,9 @@ void ProjectTreeWidget::openItem(const QModelIndex &mainIndex)
|
||||
Node *node = m_model->nodeForIndex(mainIndex);
|
||||
if (!node || !node->asFileNode())
|
||||
return;
|
||||
IEditor *editor = EditorManager::openEditor(node->filePath());
|
||||
IEditor *editor = EditorManager::openEditor(node->filePath(),
|
||||
{},
|
||||
Core::EditorManager::AllowExternalEditor);
|
||||
if (editor && node->line() >= 0)
|
||||
editor->gotoLine(node->line());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user