forked from qt-creator/qt-creator
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:
@@ -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"));
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user