From 59e2774d0d5b4746902e26949c68cf0a63ce81a4 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Thu, 18 Jul 2019 16:19:33 +0200 Subject: [PATCH] Qt Quick: Separate Qt Quick Designer and QMLJS editor factories Currently the QmlJSEditorFactory hardcodes that .qml.ui files are opened "in Design mode", without any option to explicitly open them directly in text mode. While this is the preferred way of working, there are always exceptions. Separate the "Edit mode by default" and the "Design mode by default" parts into separate editor factories. The former one is the default editor for .qml files, the latter for .qml.ui files. This allows users to explicitly choose "Open With > QML JS Editor" to open .qml.ui files directly in Edit mode. Fixes: QTCREATORBUG-18123 Change-Id: I72ab2d25fdc538210123782f6611f9c6e3157dea Reviewed-by: Christian Stenger Reviewed-by: Thomas Hartmann --- src/plugins/qmldesigner/qmldesignerplugin.cpp | 32 ++++++++++++++- src/plugins/qmljseditor/qmljseditor.cpp | 24 ++++++------ src/plugins/qmljseditor/qmljseditor.h | 2 + .../qmljseditor/qmljseditorconstants.h | 3 +- .../qmljseditor/qmljseditordocument.cpp | 39 ++++++++++++------- src/plugins/qmljseditor/qmljseditordocument.h | 5 ++- .../qmljseditor/qmljseditordocument_p.h | 2 +- src/plugins/qmljseditor/qmljseditorplugin.cpp | 11 ++++-- 8 files changed, 83 insertions(+), 35 deletions(-) diff --git a/src/plugins/qmldesigner/qmldesignerplugin.cpp b/src/plugins/qmldesigner/qmldesignerplugin.cpp index eb16cbedd11..752151a88d9 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.cpp +++ b/src/plugins/qmldesigner/qmldesignerplugin.cpp @@ -39,7 +39,9 @@ #include #include +#include #include +#include #include @@ -77,6 +79,29 @@ using namespace QmlDesigner::Internal; namespace QmlDesigner { +namespace Internal { + +class QtQuickDesignerFactory : public QmlJSEditor::QmlJSEditorFactory +{ +public: + QtQuickDesignerFactory(); +}; + +QtQuickDesignerFactory::QtQuickDesignerFactory() + : QmlJSEditorFactory(QmlJSEditor::Constants::C_QTQUICKDESIGNEREDITOR_ID) +{ + setDisplayName(QCoreApplication::translate("OpenWith::Editors", "Qt Quick Designer")); + + addMimeType(QmlJSTools::Constants::QMLUI_MIMETYPE); + setDocumentCreator([this]() { + auto document = new QmlJSEditor::QmlJSEditorDocument(id()); + document->setIsDesignModePreferred(true); + return document; + }); +} + +} // namespace Internal + class QmlDesignerPluginPrivate { public: @@ -87,6 +112,7 @@ public: DesignModeWidget mainWidget; DesignerSettings settings; DesignModeContext *context = nullptr; + QtQuickDesignerFactory m_qtQuickDesignerFactory; bool blockEditorChange = false; }; @@ -99,7 +125,9 @@ static bool isInDesignerMode() static bool checkIfEditorIsQtQuick(Core::IEditor *editor) { - if (editor && editor->document()->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID) { + if (editor + && (editor->document()->id() == QmlJSEditor::Constants::C_QMLJSEDITOR_ID + || editor->document()->id() == QmlJSEditor::Constants::C_QTQUICKDESIGNEREDITOR_ID)) { QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance(); QmlJS::Document::Ptr document = modelManager->ensuredGetDocumentForPath(editor->document()->filePath().toString()); if (!document.isNull()) @@ -545,4 +573,4 @@ void QmlDesignerPlugin::setSettings(const DesignerSettings &s) } } -} +} // namespace QmlDesigner diff --git a/src/plugins/qmljseditor/qmljseditor.cpp b/src/plugins/qmljseditor/qmljseditor.cpp index 0408c9f200f..f9e6dbf46c9 100644 --- a/src/plugins/qmljseditor/qmljseditor.cpp +++ b/src/plugins/qmljseditor/qmljseditor.cpp @@ -1008,37 +1008,39 @@ QmlJSEditor::QmlJSEditor() addContext(ProjectExplorer::Constants::QMLJS_LANGUAGE_ID); } +QmlJSEditorDocument *QmlJSEditor::qmlJSDocument() const +{ + return qobject_cast(document()); +} + bool QmlJSEditor::isDesignModePreferred() const { - bool alwaysPreferDesignMode = false; - // always prefer design mode for .ui.qml files - if (textDocument() && textDocument()->mimeType() == QLatin1String(QmlJSTools::Constants::QMLUI_MIMETYPE)) - alwaysPreferDesignMode = true; - // stay in design mode if we are there - Id mode = ModeManager::currentModeId(); - return alwaysPreferDesignMode || mode == Core::Constants::MODE_DESIGN; + const Id mode = ModeManager::currentModeId(); + return qmlJSDocument()->isDesignModePreferred() || mode == Core::Constants::MODE_DESIGN; } - // // QmlJSEditorFactory // QmlJSEditorFactory::QmlJSEditorFactory() + : QmlJSEditorFactory(Constants::C_QMLJSEDITOR_ID) +{} + +QmlJSEditorFactory::QmlJSEditorFactory(Core::Id _id) { - setId(Constants::C_QMLJSEDITOR_ID); + setId(_id); setDisplayName(QCoreApplication::translate("OpenWith::Editors", "QMLJS Editor")); addMimeType(QmlJSTools::Constants::QML_MIMETYPE); - addMimeType(QmlJSTools::Constants::QMLUI_MIMETYPE); addMimeType(QmlJSTools::Constants::QMLPROJECT_MIMETYPE); addMimeType(QmlJSTools::Constants::QBS_MIMETYPE); addMimeType(QmlJSTools::Constants::QMLTYPES_MIMETYPE); addMimeType(QmlJSTools::Constants::JS_MIMETYPE); - setDocumentCreator([]() { return new QmlJSEditorDocument; }); + setDocumentCreator([this]() { return new QmlJSEditorDocument(id()); }); setEditorWidgetCreator([]() { return new QmlJSEditorWidget; }); setEditorCreator([]() { return new QmlJSEditor; }); setAutoCompleterCreator([]() { return new AutoCompleter; }); diff --git a/src/plugins/qmljseditor/qmljseditor.h b/src/plugins/qmljseditor/qmljseditor.h index 6858a0203cb..e0a68b9a02d 100644 --- a/src/plugins/qmljseditor/qmljseditor.h +++ b/src/plugins/qmljseditor/qmljseditor.h @@ -136,6 +136,7 @@ class QMLJSEDITOR_EXPORT QmlJSEditor : public TextEditor::BaseTextEditor public: QmlJSEditor(); + QmlJSEditorDocument *qmlJSDocument() const; bool isDesignModePreferred() const override; }; @@ -145,6 +146,7 @@ class QMLJSEDITOR_EXPORT QmlJSEditorFactory : public TextEditor::TextEditorFacto public: QmlJSEditorFactory(); + QmlJSEditorFactory(Core::Id id); static void decorateEditor(TextEditor::TextEditorWidget *editor); }; diff --git a/src/plugins/qmljseditor/qmljseditorconstants.h b/src/plugins/qmljseditor/qmljseditorconstants.h index ab58d443161..966b7f1c38f 100644 --- a/src/plugins/qmljseditor/qmljseditorconstants.h +++ b/src/plugins/qmljseditor/qmljseditorconstants.h @@ -34,7 +34,8 @@ const char M_CONTEXT[] = "QML JS Editor.ContextMenu"; const char M_REFACTORING_MENU_INSERTION_POINT[] = "QmlJSEditor.RefactorGroup"; -const char C_QMLJSEDITOR_ID[] = "QMLProjectManager.QMLJSEditor"; +const char C_QMLJSEDITOR_ID[] = "QmlJSEditor.QMLJSEditor"; +const char C_QTQUICKDESIGNEREDITOR_ID[] = "QmlJSEditor.QtQuickDesignerEditor"; const char SETTINGS_CATEGORY_QML[] = "J.QtQuick"; const char SHOW_QT_QUICK_HELPER[] = "QmlJSEditor.ShowQtQuickHelper"; diff --git a/src/plugins/qmljseditor/qmljseditordocument.cpp b/src/plugins/qmljseditor/qmljseditordocument.cpp index 05aa8e649ca..bb487202c05 100644 --- a/src/plugins/qmljseditor/qmljseditordocument.cpp +++ b/src/plugins/qmljseditor/qmljseditordocument.cpp @@ -563,19 +563,6 @@ void QmlJSEditorDocumentPrivate::acceptNewSemanticInfo(const SemanticInfo &seman m_outlineModelNeedsUpdate = true; m_semanticHighlightingNecessary = true; - if (m_firstSementicInfo) { - m_firstSementicInfo = false; - if (semanticInfo.document->language() == Dialect::QmlQtQuick2Ui - && !q->infoBar()->containsInfo(Core::Id(QML_UI_FILE_WARNING))) { - Core::InfoBarEntry info(Core::Id(QML_UI_FILE_WARNING), - tr("This file should only be edited in Design mode.")); - info.setCustomButtonInfo(tr("Switch Mode"), []() { - Core::ModeManager::activateMode(Core::Constants::MODE_DESIGN); - }); - q->infoBar()->addInfo(info); - } - } - createTextMarks(m_semanticInfo); emit q->semanticInfoUpdated(m_semanticInfo); // calls triggerPendingUpdates as necessary } @@ -648,10 +635,10 @@ void QmlJSEditorDocumentPrivate::cleanSemanticMarks() } // Internal -QmlJSEditorDocument::QmlJSEditorDocument() +QmlJSEditorDocument::QmlJSEditorDocument(Core::Id id) : d(new Internal::QmlJSEditorDocumentPrivate(this)) { - setId(Constants::C_QMLJSEDITOR_ID); + setId(id); connect(this, &TextEditor::TextDocument::tabSettingsChanged, d, &Internal::QmlJSEditorDocumentPrivate::invalidateFormatterCache); setSyntaxHighlighter(new QmlJSHighlighter(document())); @@ -688,6 +675,28 @@ TextEditor::IAssistProvider *QmlJSEditorDocument::quickFixAssistProvider() const return Internal::QmlJSEditorPlugin::quickFixAssistProvider(); } +void QmlJSEditorDocument::setIsDesignModePreferred(bool value) +{ + d->m_isDesignModePreferred = value; + if (value) { + if (infoBar()->canInfoBeAdded(QML_UI_FILE_WARNING)) { + Core::InfoBarEntry info(QML_UI_FILE_WARNING, + tr("This file should only be edited in Design mode.")); + info.setCustomButtonInfo(tr("Switch Mode"), []() { + Core::ModeManager::activateMode(Core::Constants::MODE_DESIGN); + }); + infoBar()->addInfo(info); + } + } else if (infoBar()->containsInfo(QML_UI_FILE_WARNING)) { + infoBar()->removeInfo(QML_UI_FILE_WARNING); + } +} + +bool QmlJSEditorDocument::isDesignModePreferred() const +{ + return d->m_isDesignModePreferred; +} + void QmlJSEditorDocument::setDiagnosticRanges(const QVector &ranges) { d->m_diagnosticRanges = ranges; diff --git a/src/plugins/qmljseditor/qmljseditordocument.h b/src/plugins/qmljseditor/qmljseditordocument.h index 47671ad7c8e..0b5c6e34a8f 100644 --- a/src/plugins/qmljseditor/qmljseditordocument.h +++ b/src/plugins/qmljseditor/qmljseditordocument.h @@ -43,7 +43,7 @@ class QMLJSEDITOR_EXPORT QmlJSEditorDocument : public TextEditor::TextDocument { Q_OBJECT public: - QmlJSEditorDocument(); + QmlJSEditorDocument(Core::Id id); ~QmlJSEditorDocument() override; const QmlJSTools::SemanticInfo &semanticInfo() const; @@ -54,6 +54,9 @@ public: TextEditor::IAssistProvider *quickFixAssistProvider() const override; + void setIsDesignModePreferred(bool value); + bool isDesignModePreferred() const; + signals: void updateCodeWarnings(QmlJS::Document::Ptr doc); void semanticInfoUpdated(const QmlJSTools::SemanticInfo &semanticInfo); diff --git a/src/plugins/qmljseditor/qmljseditordocument_p.h b/src/plugins/qmljseditor/qmljseditordocument_p.h index 611c4254fa1..5f24d2cf3ca 100644 --- a/src/plugins/qmljseditor/qmljseditordocument_p.h +++ b/src/plugins/qmljseditor/qmljseditordocument_p.h @@ -76,11 +76,11 @@ public: SemanticHighlighter *m_semanticHighlighter = nullptr; bool m_semanticHighlightingNecessary = false; bool m_outlineModelNeedsUpdate = false; - bool m_firstSementicInfo = true; QTimer m_updateOutlineModelTimer; Internal::QmlOutlineModel *m_outlineModel = nullptr; QVector m_diagnosticMarks; QVector m_semanticMarks; + bool m_isDesignModePreferred = false; }; } // Internal diff --git a/src/plugins/qmljseditor/qmljseditorplugin.cpp b/src/plugins/qmljseditor/qmljseditorplugin.cpp index 7882d8f2d07..4853c6840db 100644 --- a/src/plugins/qmljseditor/qmljseditorplugin.cpp +++ b/src/plugins/qmljseditor/qmljseditorplugin.cpp @@ -141,10 +141,12 @@ QmlJSEditorPluginPrivate::QmlJSEditorPluginPrivate() // recompute messages when project data changes (files added or removed) connect(modelManager, &QmlJS::ModelManagerInterface::projectInfoUpdated, &m_qmlTaskManager, &QmlTaskManager::updateMessages); - connect(modelManager, &QmlJS::ModelManagerInterface::aboutToRemoveFiles, - &m_qmlTaskManager, &QmlTaskManager::documentsRemoved); + connect(modelManager, + &QmlJS::ModelManagerInterface::aboutToRemoveFiles, + &m_qmlTaskManager, + &QmlTaskManager::documentsRemoved); - Context context(Constants::C_QMLJSEDITOR_ID); + Context context(Constants::C_QMLJSEDITOR_ID, Constants::C_QTQUICKDESIGNEREDITOR_ID); ActionContainer *contextMenu = ActionManager::createMenu(Constants::M_CONTEXT); ActionContainer *qmlToolsMenu = ActionManager::actionContainer(Id(QmlJSTools::Constants::M_TOOLS_QMLJS)); @@ -352,7 +354,8 @@ void QmlJSEditorPluginPrivate::autoFormatOnSave(IDocument *document) return; // Check that we are dealing with a QML/JS editor - if (document->id() != Constants::C_QMLJSEDITOR_ID) + if (document->id() != Constants::C_QMLJSEDITOR_ID + && document->id() != Constants::C_QTQUICKDESIGNEREDITOR_ID) return; // Check if file is contained in the current project (if wished)