Core: Merge editor factory classes

Mainly to simplify the implementation and naming.

Kind of follow-up to 862c9694.

There is some consolidation needed as followup as well as some potential
renamings. I'd leave that for separate patches to keep this here
somewhat self-contained.

Change-Id: I152e138a1d5baadec3f7542fed0894b8d4ffc8a3
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
hjk
2023-08-21 11:42:56 +02:00
parent 512da70456
commit 4943f387c7
11 changed files with 278 additions and 352 deletions

View File

@@ -192,7 +192,7 @@ void FilePropertiesDialog::refresh()
const Utils::MimeType mimeType = Utils::mimeTypeForFile(m_filePath); const Utils::MimeType mimeType = Utils::mimeTypeForFile(m_filePath);
m_mimeType->setText(mimeType.name()); m_mimeType->setText(mimeType.name());
const EditorTypeList factories = IEditorFactory::preferredEditorTypes(m_filePath); const EditorFactories factories = IEditorFactory::preferredEditorTypes(m_filePath);
m_defaultEditor->setText(!factories.isEmpty() ? factories.at(0)->displayName() m_defaultEditor->setText(!factories.isEmpty() ? factories.at(0)->displayName()
: Tr::tr("Undefined")); : Tr::tr("Undefined"));

View File

@@ -797,12 +797,10 @@ IEditor *EditorManagerPrivate::openEditor(EditorView *view, const FilePath &file
realFp = filePath; realFp = filePath;
} }
EditorTypeList factories = EditorType::preferredEditorTypes(filePath); EditorFactories factories = IEditorFactory::preferredEditorTypes(filePath);
if (!(flags & EditorManager::AllowExternalEditor)) { if (!(flags & EditorManager::AllowExternalEditor))
factories = Utils::filtered(factories, [](EditorType *type) { factories = Utils::filtered(factories, &IEditorFactory::isInternalEditor);
return type->asEditorFactory() != nullptr;
});
}
if (factories.isEmpty()) { if (factories.isEmpty()) {
Utils::MimeType mimeType = Utils::mimeTypeForFile(filePath); Utils::MimeType mimeType = Utils::mimeTypeForFile(filePath);
QMessageBox msgbox(QMessageBox::Critical, ::Core::Tr::tr("File Error"), QMessageBox msgbox(QMessageBox::Critical, ::Core::Tr::tr("File Error"),
@@ -813,9 +811,9 @@ IEditor *EditorManagerPrivate::openEditor(EditorView *view, const FilePath &file
return nullptr; return nullptr;
} }
if (editorId.isValid()) { if (editorId.isValid()) {
EditorType *factory = EditorType::editorTypeForId(editorId); IEditorFactory *factory = IEditorFactory::editorFactoryForId(editorId);
if (factory) { if (factory) {
QTC_CHECK(factory->asEditorFactory() || (flags & EditorManager::AllowExternalEditor)); QTC_CHECK(factory->isInternalEditor() || (flags & EditorManager::AllowExternalEditor));
factories.removeOne(factory); factories.removeOne(factory);
factories.push_front(factory); factories.push_front(factory);
} }
@@ -824,12 +822,12 @@ IEditor *EditorManagerPrivate::openEditor(EditorView *view, const FilePath &file
IEditor *editor = nullptr; IEditor *editor = nullptr;
auto overrideCursor = Utils::OverrideCursor(QCursor(Qt::WaitCursor)); auto overrideCursor = Utils::OverrideCursor(QCursor(Qt::WaitCursor));
EditorType *factory = factories.takeFirst(); IEditorFactory *factory = factories.takeFirst();
while (factory) { while (factory) {
QString errorString; QString errorString;
if (factory->asEditorFactory()) { if (factory->isInternalEditor()) {
editor = createEditor(factory->asEditorFactory(), filePath); editor = createEditor(factory, filePath);
if (!editor) { if (!editor) {
factory = factories.isEmpty() ? nullptr : factories.takeFirst(); factory = factories.isEmpty() ? nullptr : factories.takeFirst();
continue; continue;
@@ -857,10 +855,10 @@ IEditor *EditorManagerPrivate::openEditor(EditorView *view, const FilePath &file
// can happen e.g. when trying to open an completely empty .qrc file // can happen e.g. when trying to open an completely empty .qrc file
QTC_CHECK(openResult == IDocument::OpenResult::CannotHandle); QTC_CHECK(openResult == IDocument::OpenResult::CannotHandle);
} else { } else {
QTC_ASSERT(factory->asExternalEditor(), QTC_ASSERT(factory->isExternalEditor(),
factory = factories.isEmpty() ? nullptr : factories.takeFirst(); factory = factories.isEmpty() ? nullptr : factories.takeFirst();
continue); continue);
if (factory->asExternalEditor()->startEditor(filePath, &errorString)) if (factory->startEditor(filePath, &errorString))
break; break;
} }
@@ -873,12 +871,12 @@ IEditor *EditorManagerPrivate::openEditor(EditorView *view, const FilePath &file
QMessageBox::Open | QMessageBox::Cancel, QMessageBox::Open | QMessageBox::Cancel,
ICore::dialogParent()); ICore::dialogParent());
EditorType *selectedFactory = nullptr; IEditorFactory *selectedFactory = nullptr;
if (!factories.isEmpty()) { if (!factories.isEmpty()) {
auto button = qobject_cast<QPushButton *>(msgbox.button(QMessageBox::Open)); auto button = qobject_cast<QPushButton *>(msgbox.button(QMessageBox::Open));
QTC_ASSERT(button, return nullptr); QTC_ASSERT(button, return nullptr);
auto menu = new QMenu(button); auto menu = new QMenu(button);
for (EditorType *factory : std::as_const(factories)) { for (IEditorFactory *factory : std::as_const(factories)) {
QAction *action = menu->addAction(factory->displayName()); QAction *action = menu->addAction(factory->displayName());
connect(action, &QAction::triggered, &msgbox, [&selectedFactory, factory, &msgbox] { connect(action, &QAction::triggered, &msgbox, [&selectedFactory, factory, &msgbox] {
selectedFactory = factory; selectedFactory = factory;
@@ -1148,7 +1146,7 @@ Id EditorManagerPrivate::getOpenWithEditorId(const Utils::FilePath &fileName, bo
QList<Id> allEditorIds; QList<Id> allEditorIds;
QStringList allEditorDisplayNames; QStringList allEditorDisplayNames;
// Built-in // Built-in
const EditorTypeList editors = EditorType::preferredEditorTypes(fileName); const EditorFactories editors = IEditorFactory::preferredEditorTypes(fileName);
const int size = editors.size(); const int size = editors.size();
allEditorDisplayNames.reserve(size); allEditorDisplayNames.reserve(size);
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
@@ -1166,13 +1164,13 @@ Id EditorManagerPrivate::getOpenWithEditorId(const Utils::FilePath &fileName, bo
return Id(); return Id();
const Id selectedId = allEditorIds.at(dialog.editor()); const Id selectedId = allEditorIds.at(dialog.editor());
if (isExternalEditor) { if (isExternalEditor) {
EditorType *type = EditorType::editorTypeForId(selectedId); IEditorFactory *type = IEditorFactory::editorFactoryForId(selectedId);
*isExternalEditor = type && type->asExternalEditor() != nullptr; *isExternalEditor = type && type->isExternalEditor();
} }
return selectedId; return selectedId;
} }
static QMap<QString, QVariant> toMap(const QHash<Utils::MimeType, EditorType *> &hash) static QMap<QString, QVariant> toMap(const QHash<Utils::MimeType, IEditorFactory *> &hash)
{ {
QMap<QString, QVariant> map; QMap<QString, QVariant> map;
auto it = hash.begin(); auto it = hash.begin();
@@ -1184,18 +1182,18 @@ static QMap<QString, QVariant> toMap(const QHash<Utils::MimeType, EditorType *>
return map; return map;
} }
static QHash<Utils::MimeType, EditorType *> fromMap(const QMap<QString, QVariant> &map) static QHash<Utils::MimeType, IEditorFactory *> fromMap(const QMap<QString, QVariant> &map)
{ {
const EditorTypeList factories = EditorType::allEditorTypes(); const EditorFactories factories = IEditorFactory::allEditorFactories();
QHash<Utils::MimeType, EditorType *> hash; QHash<Utils::MimeType, IEditorFactory *> hash;
auto it = map.begin(); auto it = map.begin();
const auto end = map.end(); const auto end = map.end();
while (it != end) { while (it != end) {
const Utils::MimeType mimeType = Utils::mimeTypeForName(it.key()); const Utils::MimeType mimeType = Utils::mimeTypeForName(it.key());
if (mimeType.isValid()) { if (mimeType.isValid()) {
const Id factoryId = Id::fromSetting(it.value()); const Id factoryId = Id::fromSetting(it.value());
EditorType *factory = Utils::findOrDefault(factories, IEditorFactory *factory = Utils::findOrDefault(factories,
Utils::equal(&EditorType::id, factoryId)); Utils::equal(&IEditorFactory::id, factoryId));
if (factory) if (factory)
hash.insert(mimeType, factory); hash.insert(mimeType, factory);
} }
@@ -1225,7 +1223,7 @@ void EditorManagerPrivate::readSettings()
else else
HostOsInfo::setOverrideFileNameCaseSensitivity(sensitivity); HostOsInfo::setOverrideFileNameCaseSensitivity(sensitivity);
const QHash<Utils::MimeType, EditorType *> preferredEditorFactories = fromMap( const QHash<Utils::MimeType, IEditorFactory *> preferredEditorFactories = fromMap(
qs->value(preferredEditorFactoriesKey).toMap()); qs->value(preferredEditorFactoriesKey).toMap());
setUserPreferredEditorTypes(preferredEditorFactories); setUserPreferredEditorTypes(preferredEditorFactories);
@@ -1266,12 +1264,12 @@ void EditorManagerPrivate::writeFileSystemSensitivity(Utils::QtcSettings *settin
HostOsInfo::hostOs()))); HostOsInfo::hostOs())));
} }
EditorFactoryList EditorManagerPrivate::findFactories(Id editorId, const FilePath &filePath) EditorFactories EditorManagerPrivate::findFactories(Id editorId, const FilePath &filePath)
{ {
if (debugEditorManager) if (debugEditorManager)
qDebug() << Q_FUNC_INFO << editorId.name() << filePath; qDebug() << Q_FUNC_INFO << editorId.name() << filePath;
EditorFactoryList factories; EditorFactories factories;
if (!editorId.isValid()) { if (!editorId.isValid()) {
factories = IEditorFactory::preferredEditorFactories(filePath); factories = IEditorFactory::preferredEditorFactories(filePath);
} else { } else {
@@ -2810,11 +2808,11 @@ void EditorManager::populateOpenWithMenu(QMenu *menu, const FilePath &filePath)
{ {
menu->clear(); menu->clear();
const EditorTypeList factories = IEditorFactory::preferredEditorTypes(filePath); const EditorFactories factories = IEditorFactory::preferredEditorTypes(filePath);
const bool anyMatches = !factories.empty(); const bool anyMatches = !factories.empty();
if (anyMatches) { if (anyMatches) {
// Add all suitable editors // Add all suitable editors
for (EditorType *editorType : factories) { for (IEditorFactory *editorType : factories) {
const Id editorId = editorType->id(); const Id editorId = editorType->id();
// Add action to open with this very editor factory // Add action to open with this very editor factory
QString const actionTitle = editorType->displayName(); QString const actionTitle = editorType->displayName();
@@ -2824,8 +2822,8 @@ void EditorManager::populateOpenWithMenu(QMenu *menu, const FilePath &filePath)
// crashes happen, because the editor instance is deleted by openEditorWith // crashes happen, because the editor instance is deleted by openEditorWith
// while the menu is still being processed. // while the menu is still being processed.
connect(action, &QAction::triggered, d, [filePath, editorId] { connect(action, &QAction::triggered, d, [filePath, editorId] {
EditorType *type = EditorType::editorTypeForId(editorId); IEditorFactory *type = IEditorFactory::editorFactoryForId(editorId);
if (type && type->asExternalEditor()) if (type && type->isExternalEditor())
EditorManager::openExternalEditor(filePath, editorId); EditorManager::openExternalEditor(filePath, editorId);
else else
EditorManagerPrivate::openEditorWith(filePath, editorId); EditorManagerPrivate::openEditorWith(filePath, editorId);
@@ -2839,11 +2837,10 @@ void EditorManager::runWithTemporaryEditor(const Utils::FilePath &filePath,
const std::function<void (IEditor *)> &callback) const std::function<void (IEditor *)> &callback)
{ {
const MimeType mt = mimeTypeForFile(filePath, MimeMatchMode::MatchDefaultAndRemote); const MimeType mt = mimeTypeForFile(filePath, MimeMatchMode::MatchDefaultAndRemote);
const QList<IEditorFactory *> factories = Utils::transform( const QList<IEditorFactory *> factories = IEditorFactory::defaultEditorFactories(mt);
EditorType::defaultEditorTypes(mt), [](EditorType *t) {
return t->asEditorFactory(); });
for (IEditorFactory * const factory : factories) { for (IEditorFactory * const factory : factories) {
if (!factory) QTC_ASSERT(factory, continue);
if (!factory->isInternalEditor())
continue; continue;
std::unique_ptr<IEditor> editor(factory->createEditor()); std::unique_ptr<IEditor> editor(factory->createEditor());
if (!editor) if (!editor)
@@ -3103,8 +3100,11 @@ bool EditorManager::autoSaveAfterRefactoring()
*/ */
bool EditorManager::openExternalEditor(const FilePath &filePath, Id editorId) bool EditorManager::openExternalEditor(const FilePath &filePath, Id editorId)
{ {
IExternalEditor *ee = Utils::findOrDefault(IExternalEditor::allExternalEditors(), IEditorFactory *ee = Utils::findOrDefault(IEditorFactory::allEditorFactories(),
Utils::equal(&IExternalEditor::id, editorId)); [editorId](IEditorFactory *factory) {
return factory->isExternalEditor() && factory->id() == editorId;
});
if (!ee) if (!ee)
return false; return false;
QString errorMessage; QString errorMessage;
@@ -3228,7 +3228,7 @@ IEditor *EditorManager::openEditorWithContents(Id editorId,
} }
const FilePath filePath = FilePath::fromString(title); const FilePath filePath = FilePath::fromString(title);
EditorFactoryList factories = EditorManagerPrivate::findFactories(editorId, filePath); EditorFactories factories = EditorManagerPrivate::findFactories(editorId, filePath);
if (factories.isEmpty()) if (factories.isEmpty())
return nullptr; return nullptr;

View File

@@ -167,7 +167,7 @@ private:
static OpenEditorsWindow *windowPopup(); static OpenEditorsWindow *windowPopup();
static void showPopupOrSelectDocument(); static void showPopupOrSelectDocument();
static EditorFactoryList findFactories(Utils::Id editorId, const Utils::FilePath &filePath); static EditorFactories findFactories(Utils::Id editorId, const Utils::FilePath &filePath);
static IEditor *createEditor(IEditorFactory *factory, const Utils::FilePath &filePath); static IEditor *createEditor(IEditorFactory *factory, const Utils::FilePath &filePath);
static void addEditor(IEditor *editor); static void addEditor(IEditor *editor);
static void removeEditor(IEditor *editor, bool removeSusependedEntry); static void removeEditor(IEditor *editor, bool removeSusependedEntry);

View File

@@ -51,29 +51,26 @@ static void mimeTypeFactoryLookup(const Utils::MimeType &mimeType,
IEditorFactory is then asked to create an editor. IEditorFactory is then asked to create an editor.
Implementations should set the properties of the IEditorFactory subclass in Implementations should set the properties of the IEditorFactory subclass in
their constructor with EditorType::setId(), EditorType::setDisplayName(), their constructor with IEditorFactory::setId(), IEditorFactory::setDisplayName(),
EditorType::setMimeTypes(), and setEditorCreator() IEditorFactory::setMimeTypes(), and setEditorCreator()
IEditorFactory instances automatically register themselves in \QC in their IEditorFactory instances automatically register themselves in \QC in their
constructor. constructor.
\sa Core::EditorType There are two varieties of editors: Internal and external. Internal editors
open within the main editing area of Qt Creator. An IEditorFactory defines
an internal editor by using the \c setEditorCreator function. External
editors are external applications and are defined by using the
\c setEditorStarter function. They are accessible by the user using
the \uicontrol{Open With} dialog
\sa Core::IEditor \sa Core::IEditor
\sa Core::IDocument \sa Core::IDocument
\sa Core::EditorManager \sa Core::EditorManager
*/ */
/*! /*!
\class Core::EditorType \fn void Core::IEditorFactory::addMimeType(const QString &mimeType)
\inheaderfile coreplugin/editormanager/ieditorfactory.h
\inmodule QtCreator
\brief The EditorType class is the base class for Core::IEditorFactory and
Core::IExternalEditor.
*/
/*!
\fn void Core::EditorType::addMimeType(const QString &mimeType)
Adds \a mimeType to the list of MIME types supported by this editor type. Adds \a mimeType to the list of MIME types supported by this editor type.
@@ -82,7 +79,7 @@ static void mimeTypeFactoryLookup(const Utils::MimeType &mimeType,
*/ */
/*! /*!
\fn QString Core::EditorType::displayName() const \fn QString Core::IEditorFactory::displayName() const
Returns a user-visible description of the editor type. Returns a user-visible description of the editor type.
@@ -90,7 +87,7 @@ static void mimeTypeFactoryLookup(const Utils::MimeType &mimeType,
*/ */
/*! /*!
\fn Utils::Id Core::EditorType::id() const \fn Utils::Id Core::IEditorFactory::id() const
Returns the ID of the editors' document type. Returns the ID of the editors' document type.
@@ -98,7 +95,7 @@ static void mimeTypeFactoryLookup(const Utils::MimeType &mimeType,
*/ */
/*! /*!
\fn QString Core::EditorType::mimeTypes() const \fn QString Core::IEditorFactory::mimeTypes() const
Returns the list of supported MIME types of this editor type. Returns the list of supported MIME types of this editor type.
@@ -107,7 +104,7 @@ static void mimeTypeFactoryLookup(const Utils::MimeType &mimeType,
*/ */
/*! /*!
\fn void Core::EditorType::setDisplayName(const QString &displayName) \fn void Core::IEditorFactory::setDisplayName(const QString &displayName)
Sets the \a displayName of the editor type. This is for example shown in Sets the \a displayName of the editor type. This is for example shown in
the \uicontrol {Open With} menu and the MIME type preferences. the \uicontrol {Open With} menu and the MIME type preferences.
@@ -116,7 +113,7 @@ static void mimeTypeFactoryLookup(const Utils::MimeType &mimeType,
*/ */
/*! /*!
\fn void Core::EditorType::setId(Utils::Id id) \fn void Core::IEditorFactory::setId(Utils::Id id)
Sets the \a id of the editors' document type. This must be the same as the Sets the \a id of the editors' document type. This must be the same as the
IDocument::id() of the documents returned by created editors. IDocument::id() of the documents returned by created editors.
@@ -125,7 +122,7 @@ static void mimeTypeFactoryLookup(const Utils::MimeType &mimeType,
*/ */
/*! /*!
\fn void Core::EditorType::setMimeTypes(const QStringList &mimeTypes) \fn void Core::IEditorFactory::setMimeTypes(const QStringList &mimeTypes)
Sets the MIME types supported by the editor type to \a mimeTypes. Sets the MIME types supported by the editor type to \a mimeTypes.
@@ -133,88 +130,8 @@ static void mimeTypeFactoryLookup(const Utils::MimeType &mimeType,
\sa mimeTypes() \sa mimeTypes()
*/ */
static QList<EditorType *> g_editorTypes;
static QHash<Utils::MimeType, EditorType *> g_userPreferredEditorTypes;
static QList<IEditorFactory *> g_editorFactories; static QList<IEditorFactory *> g_editorFactories;
static QHash<Utils::MimeType, IEditorFactory *> g_userPreferredEditorTypes;
/*!
\internal
*/
EditorType::EditorType()
{
g_editorTypes.append(this);
}
/*!
\internal
*/
EditorType::~EditorType()
{
g_editorTypes.removeOne(this);
}
/*!
Returns all registered internal and external editors.
*/
const EditorTypeList EditorType::allEditorTypes()
{
return g_editorTypes;
}
EditorType *EditorType::editorTypeForId(const Utils::Id &id)
{
return Utils::findOrDefault(allEditorTypes(), Utils::equal(&EditorType::id, id));
}
/*!
Returns all available internal and external editors for the \a mimeType in the
default order: Editor types ordered by MIME type hierarchy, internal editors
first.
*/
const EditorTypeList EditorType::defaultEditorTypes(const MimeType &mimeType)
{
EditorTypeList result;
const EditorTypeList allTypes = EditorType::allEditorTypes();
const EditorTypeList allEditorFactories = Utils::filtered(allTypes, [](EditorType *e) {
return e->asEditorFactory() != nullptr;
});
const EditorTypeList allExternalEditors = Utils::filtered(allTypes, [](EditorType *e) {
return e->asExternalEditor() != nullptr;
});
mimeTypeFactoryLookup(mimeType, allEditorFactories, &result);
mimeTypeFactoryLookup(mimeType, allExternalEditors, &result);
return result;
}
const EditorTypeList EditorType::preferredEditorTypes(const FilePath &filePath)
{
// default factories by mime type
const Utils::MimeType mimeType = Utils::mimeTypeForFile(filePath,
MimeMatchMode::MatchDefaultAndRemote);
EditorTypeList factories = defaultEditorTypes(mimeType);
// user preferred factory to front
EditorType *userPreferred = Internal::userPreferredEditorTypes().value(mimeType);
if (userPreferred) {
factories.removeAll(userPreferred);
factories.prepend(userPreferred);
}
// make binary editor first internal editor for text files > 48 MB
if (filePath.fileSize() > EditorManager::maxTextFileSize() && mimeType.inherits("text/plain")) {
const Utils::MimeType binary = Utils::mimeTypeForName("application/octet-stream");
const EditorTypeList binaryEditors = defaultEditorTypes(binary);
if (!binaryEditors.isEmpty()) {
EditorType *binaryEditor = binaryEditors.first();
factories.removeAll(binaryEditor);
int insertionIndex = 0;
while (factories.size() > insertionIndex
&& factories.at(insertionIndex)->asExternalEditor() != nullptr) {
++insertionIndex;
}
factories.insert(insertionIndex, binaryEditor);
}
}
return factories;
}
/*! /*!
Creates an IEditorFactory. Creates an IEditorFactory.
@@ -235,54 +152,124 @@ IEditorFactory::~IEditorFactory()
} }
/*! /*!
\internal Returns all registered internal and external editors.
*/ */
const EditorFactoryList IEditorFactory::allEditorFactories() const EditorFactories IEditorFactory::allEditorFactories()
{ {
return g_editorFactories; return g_editorFactories;
} }
IEditorFactory *IEditorFactory::editorFactoryForId(const Utils::Id &id)
{
return Utils::findOrDefault(allEditorFactories(), Utils::equal(&IEditorFactory::id, id));
}
/*!
Returns all available internal and external editors for the \a mimeType in the
default order: Editor types ordered by MIME type hierarchy, internal editors
first.
*/
const EditorFactories IEditorFactory::defaultEditorFactories(const MimeType &mimeType)
{
EditorFactories result;
const EditorFactories allTypes = IEditorFactory::allEditorFactories();
const EditorFactories allEditorFactories
= Utils::filtered(allTypes, &IEditorFactory::isInternalEditor);
const EditorFactories allExternalEditors
= Utils::filtered(allTypes, &IEditorFactory::isExternalEditor);
mimeTypeFactoryLookup(mimeType, allEditorFactories, &result);
mimeTypeFactoryLookup(mimeType, allExternalEditors, &result);
return result;
}
// FIXME: Consolidate with preferredEditorFactories()
const EditorFactories IEditorFactory::preferredEditorTypes(const FilePath &filePath)
{
// default factories by mime type
const Utils::MimeType mimeType = Utils::mimeTypeForFile(filePath,
MimeMatchMode::MatchDefaultAndRemote);
EditorFactories factories = defaultEditorFactories(mimeType);
// user preferred factory to front
IEditorFactory *userPreferred = Internal::userPreferredEditorTypes().value(mimeType);
if (userPreferred) {
factories.removeAll(userPreferred);
factories.prepend(userPreferred);
}
// make binary editor first internal editor for text files > 48 MB
if (filePath.fileSize() > EditorManager::maxTextFileSize() && mimeType.inherits("text/plain")) {
const Utils::MimeType binary = Utils::mimeTypeForName("application/octet-stream");
const EditorFactories binaryEditors = defaultEditorFactories(binary);
if (!binaryEditors.isEmpty()) {
IEditorFactory *binaryEditor = binaryEditors.first();
factories.removeAll(binaryEditor);
int insertionIndex = 0;
while (factories.size() > insertionIndex
&& !factories.at(insertionIndex)->isInternalEditor()) {
++insertionIndex;
}
factories.insert(insertionIndex, binaryEditor);
}
}
return factories;
}
/*! /*!
Returns the available editor factories for \a filePath in order of Returns the available editor factories for \a filePath in order of
preference. That is the default order for the document's MIME type but with preference. That is the default order for the document's MIME type but with
a user overridden default editor first, and the binary editor as the very a user overridden default editor first, and the binary editor as the very
first item if a text document is too large to be opened as a text file. first item if a text document is too large to be opened as a text file.
*/ */
const EditorFactoryList IEditorFactory::preferredEditorFactories(const FilePath &filePath) const EditorFactories IEditorFactory::preferredEditorFactories(const FilePath &filePath)
{ {
const auto defaultEditorFactories = [](const MimeType &mimeType) { const auto defaultEditorFactories = [](const MimeType &mimeType) {
QList<IEditorFactory *> editorFactories; QList<IEditorFactory *> editorFactories;
for (EditorType *type : defaultEditorTypes(mimeType)) { for (IEditorFactory *type : IEditorFactory::defaultEditorFactories(mimeType)) {
if (IEditorFactory *editorFactory = type->asEditorFactory()) if (type->isInternalEditor())
editorFactories.append(editorFactory); editorFactories.append(type);
} }
return editorFactories; return editorFactories;
}; };
// default factories by mime type // default factories by mime type
const Utils::MimeType mimeType = Utils::mimeTypeForFile(filePath); const Utils::MimeType mimeType = Utils::mimeTypeForFile(filePath);
EditorFactoryList factories = defaultEditorFactories(mimeType); EditorFactories factories = defaultEditorFactories(mimeType);
const auto factories_moveToFront = [&factories](IEditorFactory *f) { const auto factories_moveToFront = [&factories](IEditorFactory *f) {
factories.removeAll(f); factories.removeAll(f);
factories.prepend(f); factories.prepend(f);
}; };
// user preferred factory to front // user preferred factory to front
EditorType *userPreferred = Internal::userPreferredEditorTypes().value(mimeType); IEditorFactory *userPreferred = Internal::userPreferredEditorTypes().value(mimeType);
if (userPreferred && userPreferred->asEditorFactory()) if (userPreferred && userPreferred->isInternalEditor())
factories_moveToFront(userPreferred->asEditorFactory()); factories_moveToFront(userPreferred);
// open text files > 48 MB in binary editor // open text files > 48 MB in binary editor
if (filePath.fileSize() > EditorManager::maxTextFileSize() if (filePath.fileSize() > EditorManager::maxTextFileSize()
&& mimeType.inherits("text/plain")) { && mimeType.inherits("text/plain")) {
const Utils::MimeType binary = Utils::mimeTypeForName("application/octet-stream"); const Utils::MimeType binary = Utils::mimeTypeForName("application/octet-stream");
const EditorFactoryList binaryEditors = defaultEditorFactories(binary); const EditorFactories binaryEditors = defaultEditorFactories(binary);
if (!binaryEditors.isEmpty()) if (!binaryEditors.isEmpty())
factories_moveToFront(binaryEditors.first()); factories_moveToFront(binaryEditors.first());
} }
return factories; return factories;
} }
/**
Returns true if this factory creates internal editors.
*/
bool IEditorFactory::isInternalEditor() const
{
return bool(m_creator);
}
/**
Returns true if this factory creates external editors.
*/
bool IEditorFactory::isExternalEditor() const
{
return bool(m_starter);
}
/*! /*!
Creates an editor. Creates an internal editor.
Uses the function set with setEditorCreator() to create the editor. Uses the function set with setEditorCreator() to create the editor.
@@ -294,21 +281,54 @@ IEditor *IEditorFactory::createEditor() const
return m_creator(); return m_creator();
} }
/*!
Starts an external editor.
Uses the function set with setEditorStarter() to start the editor.
\sa setEditorStarter()
*/
bool IEditorFactory::startEditor(const FilePath &filePath, QString *errorMessage)
{
QTC_ASSERT(m_starter, return false);
return m_starter(filePath, errorMessage);
}
/*! /*!
Sets the function that is used to create an editor instance in Sets the function that is used to create an editor instance in
createEditor() to \a creator. createEditor() to \a creator.
This is mutually exclusive with the use of setEditorStarter.
\sa createEditor() \sa createEditor()
*/ */
void IEditorFactory::setEditorCreator(const std::function<IEditor *()> &creator) void IEditorFactory::setEditorCreator(const std::function<IEditor *()> &creator)
{ {
QTC_CHECK(!m_starter);
// The check below triggers within the TextEditorFactory sub-hierarchy
// as the base TextEditorFactory already sets as simple creator.
//QTC_CHECK(!m_creator);
m_creator = creator; m_creator = creator;
} }
/*!
Opens the editor with \a fileName. Returns \c true on success or \c false
on failure along with the error in \a errorMessage.
This is mutually exclusive with the use of setEditorCreator.
*/
void IEditorFactory::setEditorStarter(const std::function<bool(const FilePath &, QString *)> &starter)
{
QTC_CHECK(!m_starter);
QTC_CHECK(!m_creator);
m_starter = starter;
}
/*! /*!
\internal \internal
*/ */
QHash<Utils::MimeType, Core::EditorType *> Core::Internal::userPreferredEditorTypes() QHash<Utils::MimeType, IEditorFactory *> Internal::userPreferredEditorTypes()
{ {
return g_userPreferredEditorTypes; return g_userPreferredEditorTypes;
} }
@@ -316,64 +336,10 @@ QHash<Utils::MimeType, Core::EditorType *> Core::Internal::userPreferredEditorTy
/*! /*!
\internal \internal
*/ */
void Internal::setUserPreferredEditorTypes(const QHash<Utils::MimeType, EditorType *> &factories) void Internal::setUserPreferredEditorTypes(const QHash<Utils::MimeType, IEditorFactory *> &factories)
{ {
g_userPreferredEditorTypes = factories; g_userPreferredEditorTypes = factories;
} }
/*!
\class Core::IExternalEditor
\inheaderfile coreplugin/editormanager/ieditorfactory.h
\inmodule QtCreator
\ingroup mainclasses
\brief The IExternalEditor class enables registering an external
editor in the \uicontrol{Open With} dialog.
*/
/*!
\fn bool Core::IExternalEditor::startEditor(const Utils::FilePath &fileName, QString *errorMessage)
Opens the editor with \a fileName. Returns \c true on success or \c false
on failure along with the error in \a errorMessage.
*/
static QList<IExternalEditor *> g_externalEditors;
/*!
\internal
*/
IExternalEditor::IExternalEditor()
{
g_externalEditors.append(this);
}
/*!
\internal
*/
IExternalEditor::~IExternalEditor()
{
g_externalEditors.removeOne(this);
}
/*!
Returns all available external editors.
*/
const ExternalEditorList IExternalEditor::allExternalEditors()
{
return g_externalEditors;
}
/*!
Returns all external editors available for this \a mimeType in the default
order (editors ordered by MIME type hierarchy).
*/
const ExternalEditorList IExternalEditor::externalEditors(const Utils::MimeType &mimeType)
{
ExternalEditorList rc;
const ExternalEditorList allEditors = IExternalEditor::allExternalEditors();
mimeTypeFactoryLookup(mimeType, allEditors, &rc);
return rc;
}
} // Core } // Core

View File

@@ -18,77 +18,48 @@ class MimeType;
namespace Core { namespace Core {
class IExternalEditor;
class IEditor; class IEditor;
class IEditorFactory; class IEditorFactory;
class EditorType;
using EditorFactoryList = QList<IEditorFactory *>; using EditorFactories = QList<IEditorFactory *>;
using EditorTypeList = QList<EditorType *>;
using ExternalEditorList = QList<IExternalEditor *>;
class CORE_EXPORT EditorType class CORE_EXPORT IEditorFactory
{ {
public: public:
virtual ~EditorType(); virtual ~IEditorFactory();
static const EditorTypeList allEditorTypes(); static const EditorFactories allEditorFactories();
static EditorType *editorTypeForId(const Utils::Id &id); static IEditorFactory *editorFactoryForId(const Utils::Id &id);
static const EditorTypeList defaultEditorTypes(const Utils::MimeType &mimeType); static const EditorFactories defaultEditorFactories(const Utils::MimeType &mimeType);
static const EditorTypeList preferredEditorTypes(const Utils::FilePath &filePath); static const EditorFactories preferredEditorTypes(const Utils::FilePath &filePath);
static const EditorFactories preferredEditorFactories(const Utils::FilePath &filePath);
Utils::Id id() const { return m_id; } Utils::Id id() const { return m_id; }
QString displayName() const { return m_displayName; } QString displayName() const { return m_displayName; }
QStringList mimeTypes() const { return m_mimeTypes; } QStringList mimeTypes() const { return m_mimeTypes; }
virtual IEditorFactory *asEditorFactory() { return nullptr; }; bool isInternalEditor() const;
virtual IExternalEditor *asExternalEditor() { return nullptr; }; bool isExternalEditor() const;
IEditor *createEditor() const;
bool startEditor(const Utils::FilePath &filePath, QString *errorMessage);
protected: protected:
EditorType(); IEditorFactory();
void setId(Utils::Id id) { m_id = id; } void setId(Utils::Id id) { m_id = id; }
void setDisplayName(const QString &displayName) { m_displayName = displayName; } void setDisplayName(const QString &displayName) { m_displayName = displayName; }
void setMimeTypes(const QStringList &mimeTypes) { m_mimeTypes = mimeTypes; } void setMimeTypes(const QStringList &mimeTypes) { m_mimeTypes = mimeTypes; }
void addMimeType(const QString &mimeType) { m_mimeTypes.append(mimeType); } void addMimeType(const QString &mimeType) { m_mimeTypes.append(mimeType); }
void setEditorCreator(const std::function<IEditor *()> &creator);
void setEditorStarter(const std::function<bool(const Utils::FilePath &, QString *)> &starter);
private: private:
Utils::Id m_id; Utils::Id m_id;
QString m_displayName; QString m_displayName;
QStringList m_mimeTypes; QStringList m_mimeTypes;
};
class CORE_EXPORT IEditorFactory : public EditorType
{
public:
IEditorFactory();
~IEditorFactory() override;
static const EditorFactoryList allEditorFactories();
static const EditorFactoryList preferredEditorFactories(const Utils::FilePath &filePath);
IEditor *createEditor() const;
IEditorFactory *asEditorFactory() override { return this; }
protected:
void setEditorCreator(const std::function<IEditor *()> &creator);
private:
std::function<IEditor *()> m_creator; std::function<IEditor *()> m_creator;
}; std::function<bool(const Utils::FilePath &, QString *)> m_starter;
class CORE_EXPORT IExternalEditor : public EditorType
{
public:
explicit IExternalEditor();
~IExternalEditor() override;
static const ExternalEditorList allExternalEditors();
static const ExternalEditorList externalEditors(const Utils::MimeType &mimeType);
IExternalEditor *asExternalEditor() override { return this; }
virtual bool startEditor(const Utils::FilePath &filePath, QString *errorMessage) = 0;
}; };
} // namespace Core } // namespace Core

View File

@@ -9,12 +9,12 @@
namespace Core { namespace Core {
class EditorType; class IEditorFactory;
namespace Internal { namespace Internal {
QHash<Utils::MimeType, EditorType *> userPreferredEditorTypes(); QHash<Utils::MimeType, IEditorFactory *> userPreferredEditorTypes();
void setUserPreferredEditorTypes(const QHash<Utils::MimeType, EditorType *> &factories); void setUserPreferredEditorTypes(const QHash<Utils::MimeType, IEditorFactory *> &factories);
} // Internal } // Internal
} // Core } // Core

View File

@@ -7,7 +7,6 @@
#include <utils/filepath.h> #include <utils/filepath.h>
#include <QStringList>
#include <QUrl> #include <QUrl>
#include <QDesktopServices> #include <QDesktopServices>
@@ -20,20 +19,19 @@ SystemEditor::SystemEditor()
setId("CorePlugin.OpenWithSystemEditor"); setId("CorePlugin.OpenWithSystemEditor");
setDisplayName(Tr::tr("System Editor")); setDisplayName(Tr::tr("System Editor"));
setMimeTypes({"application/octet-stream"}); setMimeTypes({"application/octet-stream"});
}
bool SystemEditor::startEditor(const FilePath &filePath, QString *errorMessage) setEditorStarter([](const FilePath &filePath, QString *errorMessage) {
{ Q_UNUSED(errorMessage)
Q_UNUSED(errorMessage) QUrl url;
QUrl url; url.setPath(filePath.toString());
url.setPath(filePath.toString()); url.setScheme(QLatin1String("file"));
url.setScheme(QLatin1String("file")); if (!QDesktopServices::openUrl(url)) {
if (!QDesktopServices::openUrl(url)) { if (errorMessage)
if (errorMessage) *errorMessage = Tr::tr("Could not open URL %1.").arg(url.toString());
*errorMessage = Tr::tr("Could not open URL %1.").arg(url.toString()); return false;
return false; }
} return true;
return true; });
} }
} // Core::Internal } // Core::Internal

View File

@@ -7,12 +7,10 @@
namespace Core::Internal { namespace Core::Internal {
class SystemEditor : public IExternalEditor class SystemEditor final : public IEditorFactory
{ {
public: public:
explicit SystemEditor(); SystemEditor();
bool startEditor(const Utils::FilePath &filePath, QString *errorMessage) override;
}; };
} // namespace Core::Internal } // namespace Core::Internal

View File

@@ -98,13 +98,13 @@ public:
void load(); void load();
QList<EditorType *> handlersForMimeType(const Utils::MimeType &mimeType) const; QList<IEditorFactory *> handlersForMimeType(const Utils::MimeType &mimeType) const;
EditorType *defaultHandlerForMimeType(const Utils::MimeType &mimeType) const; IEditorFactory *defaultHandlerForMimeType(const Utils::MimeType &mimeType) const;
void resetUserDefaults(); void resetUserDefaults();
QList<Utils::MimeType> m_mimeTypes; QList<Utils::MimeType> m_mimeTypes;
mutable QHash<Utils::MimeType, QList<EditorType *>> m_handlersByMimeType; mutable QHash<Utils::MimeType, QList<IEditorFactory *>> m_handlersByMimeType;
QHash<Utils::MimeType, EditorType *> m_userDefault; QHash<Utils::MimeType, IEditorFactory *> m_userDefault;
}; };
int MimeTypeSettingsModel::rowCount(const QModelIndex &) const int MimeTypeSettingsModel::rowCount(const QModelIndex &) const
@@ -139,7 +139,7 @@ QVariant MimeTypeSettingsModel::data(const QModelIndex &modelIndex, int role) co
if (column == 0) { if (column == 0) {
return type.name(); return type.name();
} else { } else {
EditorType *defaultHandler = defaultHandlerForMimeType(type); IEditorFactory *defaultHandler = defaultHandlerForMimeType(type);
return defaultHandler ? defaultHandler->displayName() : QString(); return defaultHandler ? defaultHandler->displayName() : QString();
} }
} else if (role == Qt::EditRole) { } else if (role == Qt::EditRole) {
@@ -166,12 +166,12 @@ bool MimeTypeSettingsModel::setData(const QModelIndex &index, const QVariant &va
{ {
if (role != int(Role::DefaultHandler) || index.column() != 1) if (role != int(Role::DefaultHandler) || index.column() != 1)
return false; return false;
auto factory = value.value<EditorType *>(); auto factory = value.value<IEditorFactory *>();
QTC_ASSERT(factory, return false); QTC_ASSERT(factory, return false);
const int row = index.row(); const int row = index.row();
QTC_ASSERT(row >= 0 && row < m_mimeTypes.size(), return false); QTC_ASSERT(row >= 0 && row < m_mimeTypes.size(), return false);
const Utils::MimeType mimeType = m_mimeTypes.at(row); const Utils::MimeType mimeType = m_mimeTypes.at(row);
const QList<EditorType *> handlers = handlersForMimeType(mimeType); const QList<IEditorFactory *> handlers = handlersForMimeType(mimeType);
QTC_ASSERT(handlers.contains(factory), return false); QTC_ASSERT(handlers.contains(factory), return false);
if (handlers.first() == factory) // selection is the default anyhow if (handlers.first() == factory) // selection is the default anyhow
m_userDefault.remove(mimeType); m_userDefault.remove(mimeType);
@@ -200,18 +200,18 @@ void MimeTypeSettingsModel::load()
endResetModel(); endResetModel();
} }
QList<EditorType *> MimeTypeSettingsModel::handlersForMimeType(const Utils::MimeType &mimeType) const QList<IEditorFactory *> MimeTypeSettingsModel::handlersForMimeType(const Utils::MimeType &mimeType) const
{ {
if (!m_handlersByMimeType.contains(mimeType)) if (!m_handlersByMimeType.contains(mimeType))
m_handlersByMimeType.insert(mimeType, EditorType::defaultEditorTypes(mimeType)); m_handlersByMimeType.insert(mimeType, IEditorFactory::defaultEditorFactories(mimeType));
return m_handlersByMimeType.value(mimeType); return m_handlersByMimeType.value(mimeType);
} }
EditorType *MimeTypeSettingsModel::defaultHandlerForMimeType(const Utils::MimeType &mimeType) const IEditorFactory *MimeTypeSettingsModel::defaultHandlerForMimeType(const Utils::MimeType &mimeType) const
{ {
if (m_userDefault.contains(mimeType)) if (m_userDefault.contains(mimeType))
return m_userDefault.value(mimeType); return m_userDefault.value(mimeType);
const QList<EditorType *> handlers = handlersForMimeType(mimeType); const QList<IEditorFactory *> handlers = handlersForMimeType(mimeType);
return handlers.isEmpty() ? nullptr : handlers.first(); return handlers.isEmpty() ? nullptr : handlers.first();
} }
@@ -808,13 +808,13 @@ QWidget *MimeEditorDelegate::createEditor(QWidget *parent,
void MimeEditorDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const void MimeEditorDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{ {
auto box = static_cast<QComboBox *>(editor); auto box = static_cast<QComboBox *>(editor);
const auto factories = index.model()->data(index, Qt::EditRole).value<QList<EditorType *>>(); const auto factories = index.model()->data(index, Qt::EditRole).value<QList<IEditorFactory *>>();
for (EditorType *factory : factories) for (IEditorFactory *factory : factories)
box->addItem(factory->displayName(), QVariant::fromValue(factory)); box->addItem(factory->displayName(), QVariant::fromValue(factory));
int currentIndex = factories.indexOf( int currentIndex = factories.indexOf(
index.model() index.model()
->data(index, int(MimeTypeSettingsModel::Role::DefaultHandler)) ->data(index, int(MimeTypeSettingsModel::Role::DefaultHandler))
.value<EditorType *>()); .value<IEditorFactory *>());
if (QTC_GUARD(currentIndex != -1)) if (QTC_GUARD(currentIndex != -1))
box->setCurrentIndex(currentIndex); box->setCurrentIndex(currentIndex);
} }

View File

@@ -258,63 +258,62 @@ DesignerExternalEditor::DesignerExternalEditor()
setId("Qt.Designer"); setId("Qt.Designer");
setDisplayName(::Core::Tr::tr("Qt Designer")); setDisplayName(::Core::Tr::tr("Qt Designer"));
setMimeTypes({ProjectExplorer::Constants::FORM_MIMETYPE}); setMimeTypes({ProjectExplorer::Constants::FORM_MIMETYPE});
}
bool DesignerExternalEditor::startEditor(const FilePath &filePath, QString *errorMessage) setEditorStarter([this](const FilePath &filePath, QString *errorMessage) {
{ LaunchData data;
LaunchData data;
// Find the editor binary // Find the editor binary
if (!getEditorLaunchData(designerBinary, filePath, &data, errorMessage)) if (!getEditorLaunchData(designerBinary, filePath, &data, errorMessage))
return false; return false;
if (HostOsInfo::isMacHost()) if (HostOsInfo::isMacHost())
return startEditorProcess(data, errorMessage); return startEditorProcess(data, errorMessage);
/* Qt Designer on the remaining platforms: Uses Designer's own /* Qt Designer on the remaining platforms: Uses Designer's own
* Tcp-based communication mechanism to ensure all files are opened * Tcp-based communication mechanism to ensure all files are opened
* in one instance (per version). */ * in one instance (per version). */
// Known one? // Known one?
const ProcessCache::iterator it = m_processCache.find(data.binary); const ProcessCache::iterator it = m_processCache.find(data.binary);
if (it != m_processCache.end()) { if (it != m_processCache.end()) {
// Process is known, write to its socket to cause it to open the file // Process is known, write to its socket to cause it to open the file
if (debug) if (debug)
qDebug() << Q_FUNC_INFO << "\nWriting to socket:" << data.binary << filePath; qDebug() << Q_FUNC_INFO << "\nWriting to socket:" << data.binary << filePath;
QTcpSocket *socket = it.value(); QTcpSocket *socket = it.value();
if (!socket->write(filePath.toString().toUtf8() + '\n')) { if (!socket->write(filePath.toString().toUtf8() + '\n')) {
*errorMessage = Tr::tr("Qt Designer is not responding (%1).").arg(socket->errorString()); *errorMessage = Tr::tr("Qt Designer is not responding (%1).").arg(socket->errorString());
return false;
}
return true;
}
// No process yet. Create socket & launch the process
QTcpServer server;
if (!server.listen(QHostAddress::LocalHost)) {
*errorMessage = Tr::tr("Unable to create server socket: %1").arg(server.errorString());
return false; return false;
} }
return true; const quint16 port = server.serverPort();
} if (debug)
// No process yet. Create socket & launch the process qDebug() << Q_FUNC_INFO << "\nLaunching server:" << port << data.binary << filePath;
QTcpServer server; // Start first one with file and socket as '-client port file'
if (!server.listen(QHostAddress::LocalHost)) { // Wait for the socket listening
*errorMessage = Tr::tr("Unable to create server socket: %1").arg(server.errorString()); data.arguments.push_front(QString::number(port));
return false; data.arguments.push_front(QLatin1String("-client"));
}
const quint16 port = server.serverPort();
if (debug)
qDebug() << Q_FUNC_INFO << "\nLaunching server:" << port << data.binary << filePath;
// Start first one with file and socket as '-client port file'
// Wait for the socket listening
data.arguments.push_front(QString::number(port));
data.arguments.push_front(QLatin1String("-client"));
if (!startEditorProcess(data, errorMessage)) if (!startEditorProcess(data, errorMessage))
return false; return false;
// Insert into cache if socket is created, else try again next time // Insert into cache if socket is created, else try again next time
if (server.waitForNewConnection(3000)) { if (server.waitForNewConnection(3000)) {
QTcpSocket *socket = server.nextPendingConnection(); QTcpSocket *socket = server.nextPendingConnection();
socket->setParent(&m_guard); socket->setParent(&m_guard);
const QString binary = data.binary; const QString binary = data.binary;
m_processCache.insert(binary, socket); m_processCache.insert(binary, socket);
auto mapSlot = [binary] { processTerminated(binary); }; auto mapSlot = [binary] { processTerminated(binary); };
QObject::connect(socket, &QAbstractSocket::disconnected, &m_guard, mapSlot); QObject::connect(socket, &QAbstractSocket::disconnected, &m_guard, mapSlot);
QObject::connect(socket, &QAbstractSocket::errorOccurred, &m_guard, mapSlot); QObject::connect(socket, &QAbstractSocket::errorOccurred, &m_guard, mapSlot);
} }
return true; return true;
});
} }
// Linguist // Linguist
@@ -331,13 +330,11 @@ LinguistEditor::LinguistEditor()
setId("Qt.Linguist"); setId("Qt.Linguist");
setDisplayName(::Core::Tr::tr("Qt Linguist")); setDisplayName(::Core::Tr::tr("Qt Linguist"));
setMimeTypes({ProjectExplorer::Constants::LINGUIST_MIMETYPE}); setMimeTypes({ProjectExplorer::Constants::LINGUIST_MIMETYPE});
} setEditorStarter([](const FilePath &filePath, QString *errorMessage) {
LaunchData data;
bool LinguistEditor::startEditor(const Utils::FilePath &filePath, QString *errorMessage) return getEditorLaunchData(linguistBinary, filePath, &data, errorMessage)
{ && startEditorProcess(data, errorMessage);
LaunchData data; });
return getEditorLaunchData(linguistBinary, filePath, &data, errorMessage)
&& startEditorProcess(data, errorMessage);
} }
} // QtSupport::Internal } // QtSupport::Internal

View File

@@ -9,23 +9,19 @@
namespace QtSupport::Internal { namespace QtSupport::Internal {
class DesignerExternalEditor : public Core::IExternalEditor class DesignerExternalEditor : public Core::IEditorFactory
{ {
public: public:
DesignerExternalEditor(); DesignerExternalEditor();
bool startEditor(const Utils::FilePath &filePath, QString *errorMessage) final;
private: private:
QObject m_guard; QObject m_guard;
}; };
class LinguistEditor : public Core::IExternalEditor class LinguistEditor : public Core::IEditorFactory
{ {
public: public:
LinguistEditor(); LinguistEditor();
bool startEditor(const Utils::FilePath &filePath, QString *errorMessage) final;
}; };
} // QtSupport::Internal } // QtSupport::Internal