From d43f1662d0b44b3b930989f11604661c377bd67e Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Tue, 11 Feb 2020 14:00:09 +0100 Subject: [PATCH] Make TextEditor setup more flexible So far it was only possible to combine TextEditorFactory, BaseTextEditor and TextEditorWidget directly. That TextEditorWidget is also directly a QPlainTextEdit made it impossible to "decorate" the text editor widget with something else without a lot of effort. Make it possible to create a text editor factory that returns an arbitrary widget, as long as it can be "cast" to a TextEditorWidget with either qobject_cast or Aggregation::query. That way the TextEditorWidget instance can be attached to the editor widget via Aggregation. Adapt other code that accesses TextEditorWidget from editors accordingly. Introduce a common method how to do that. Change-Id: I72b8721f3a8a8d8281c39af75253e9c80cbe1250 Reviewed-by: Orgad Shaneh Reviewed-by: David Schulz --- src/plugins/beautifier/beautifierplugin.cpp | 2 +- src/plugins/bookmarks/bookmarksplugin.cpp | 4 +- .../test/clangautomationutils.cpp | 2 +- src/plugins/cpptools/cppcompletion_test.cpp | 2 +- src/plugins/debugger/debuggerplugin.cpp | 2 +- src/plugins/debugger/disassembleragent.cpp | 4 +- src/plugins/debugger/qml/qmlengineutils.cpp | 4 +- src/plugins/fakevim/fakevimplugin.cpp | 10 +++-- .../projectexplorer/editorconfiguration.cpp | 2 +- src/plugins/texteditor/refactoringchanges.cpp | 4 +- src/plugins/texteditor/texteditor.cpp | 45 +++++++++++-------- src/plugins/texteditor/texteditor.h | 4 +- .../texteditor/texteditoractionhandler.cpp | 4 +- src/plugins/valgrind/callgrindtool.cpp | 2 +- 14 files changed, 54 insertions(+), 37 deletions(-) diff --git a/src/plugins/beautifier/beautifierplugin.cpp b/src/plugins/beautifier/beautifierplugin.cpp index 67784477d57..046a54448a6 100644 --- a/src/plugins/beautifier/beautifierplugin.cpp +++ b/src/plugins/beautifier/beautifierplugin.cpp @@ -186,7 +186,7 @@ void BeautifierPluginPrivate::autoFormatOnSave(Core::IDocument *document) const QList editors = Core::DocumentModel::editorsForDocument(document); if (editors.isEmpty()) return; - if (auto widget = qobject_cast(editors.first()->widget())) + if (auto widget = TextEditorWidget::fromEditor(editors.first())) TextEditor::formatEditor(widget, command); } } diff --git a/src/plugins/bookmarks/bookmarksplugin.cpp b/src/plugins/bookmarks/bookmarksplugin.cpp index 06eb6b49c91..911702cc1dd 100644 --- a/src/plugins/bookmarks/bookmarksplugin.cpp +++ b/src/plugins/bookmarks/bookmarksplugin.cpp @@ -190,7 +190,7 @@ void BookmarksPluginPrivate::updateActions(bool enableToggle, int state) void BookmarksPluginPrivate::editorOpened(IEditor *editor) { - if (auto widget = qobject_cast(editor->widget())) { + if (auto widget = TextEditorWidget::fromEditor(editor)) { connect(widget, &TextEditorWidget::markRequested, this, [this, editor](TextEditorWidget *, int line, TextMarkRequestKind kind) { if (kind == BookmarkRequest && !editor->document()->isTemporary()) @@ -204,7 +204,7 @@ void BookmarksPluginPrivate::editorOpened(IEditor *editor) void BookmarksPluginPrivate::editorAboutToClose(IEditor *editor) { - if (auto widget = qobject_cast(editor->widget())) { + if (auto widget = TextEditorWidget::fromEditor(editor)) { disconnect(widget, &TextEditorWidget::markContextMenuRequested, this, &BookmarksPluginPrivate::requestContextMenu); } diff --git a/src/plugins/clangcodemodel/test/clangautomationutils.cpp b/src/plugins/clangcodemodel/test/clangautomationutils.cpp index e4a421ffe95..bd2e99b8b15 100644 --- a/src/plugins/clangcodemodel/test/clangautomationutils.cpp +++ b/src/plugins/clangcodemodel/test/clangautomationutils.cpp @@ -106,7 +106,7 @@ TextEditor::ProposalModelPtr completionResults(TextEditor::BaseTextEditor *textE { using namespace TextEditor; - auto textEditorWidget = qobject_cast(textEditor->widget()); + auto textEditorWidget = TextEditorWidget::fromEditor(textEditor); QTC_ASSERT(textEditorWidget, return TextEditor::ProposalModelPtr()); AssistInterface *assistInterface = textEditorWidget->createAssistInterface( TextEditor::Completion, TextEditor::ExplicitlyInvoked); diff --git a/src/plugins/cpptools/cppcompletion_test.cpp b/src/plugins/cpptools/cppcompletion_test.cpp index b8ba85fc159..44274da9548 100644 --- a/src/plugins/cpptools/cppcompletion_test.cpp +++ b/src/plugins/cpptools/cppcompletion_test.cpp @@ -81,7 +81,7 @@ public: m_editor = EditorManager::openEditor(fileName); QVERIFY(m_editor); closeEditorAtEndOfTestCase(m_editor); - m_editorWidget = qobject_cast(m_editor->widget()); + m_editorWidget = TextEditorWidget::fromEditor(m_editor); QVERIFY(m_editorWidget); m_textDocument = m_editorWidget->document(); diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 6f634f870a9..b3d60e49955 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -1835,7 +1835,7 @@ void DebuggerPluginPrivate::runScheduled() void DebuggerPluginPrivate::editorOpened(IEditor *editor) { - if (auto widget = qobject_cast(editor->widget())) { + if (auto widget = TextEditorWidget::fromEditor(editor)) { connect(widget, &TextEditorWidget::markRequested, this, &DebuggerPluginPrivate::requestMark); diff --git a/src/plugins/debugger/disassembleragent.cpp b/src/plugins/debugger/disassembleragent.cpp index 3af906f2980..0c41c1475d5 100644 --- a/src/plugins/debugger/disassembleragent.cpp +++ b/src/plugins/debugger/disassembleragent.cpp @@ -266,7 +266,7 @@ void DisassemblerAgentPrivate::configureMimeType() Utils::MimeType mtype = Utils::mimeTypeForName(mimeType); if (mtype.isValid()) { foreach (IEditor *editor, DocumentModel::editorsForDocument(document)) - if (auto widget = qobject_cast(editor->widget())) + if (auto widget = TextEditorWidget::fromEditor(editor)) widget->configureGenericHighlighter(); } else { qWarning("Assembler mimetype '%s' not found.", qPrintable(mimeType)); @@ -314,7 +314,7 @@ void DisassemblerAgent::setContentsToDocument(const DisassemblerLines &contents) Core::Constants::K_DEFAULT_TEXT_EDITOR_ID, &titlePattern); QTC_ASSERT(editor, return); - if (auto widget = qobject_cast(editor->widget())) { + if (auto widget = TextEditorWidget::fromEditor(editor)) { widget->setReadOnly(true); widget->setRequestMarkEnabled(true); } diff --git a/src/plugins/debugger/qml/qmlengineutils.cpp b/src/plugins/debugger/qml/qmlengineutils.cpp index 042df6b6a65..cc3e11d2126 100644 --- a/src/plugins/debugger/qml/qmlengineutils.cpp +++ b/src/plugins/debugger/qml/qmlengineutils.cpp @@ -230,7 +230,7 @@ void clearExceptionSelection() QList selections; foreach (IEditor *editor, DocumentModel::editorsForOpenedDocuments()) { - if (auto ed = qobject_cast(editor->widget())) + if (auto ed = TextEditorWidget::fromEditor(editor)) ed->setExtraSelections(TextEditorWidget::DebuggerExceptionSelection, selections); } } @@ -244,7 +244,7 @@ QStringList highlightExceptionCode(int lineNumber, const QString &filePath, cons QTextCharFormat errorFormat = fontSettings.toTextCharFormat(TextEditor::C_ERROR); for (IEditor *editor : editors) { - auto ed = qobject_cast(editor->widget()); + auto ed = TextEditorWidget::fromEditor(editor); if (!ed) continue; diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp index 5dd35f75c70..b0a0e9c9c60 100644 --- a/src/plugins/fakevim/fakevimplugin.cpp +++ b/src/plugins/fakevim/fakevimplugin.cpp @@ -1267,7 +1267,7 @@ void FakeVimPluginPrivate::userActionTriggered(int key) void FakeVimPluginPrivate::createRelativeNumberWidget(IEditor *editor) { - if (auto textEditor = qobject_cast(editor->widget())) { + if (auto textEditor = TextEditorWidget::fromEditor(editor)) { auto relativeNumbers = new RelativeNumbersColumn(textEditor); connect(theFakeVimSetting(ConfigRelativeNumber), &SavedAction::valueChanged, relativeNumbers, &QObject::deleteLater); @@ -1532,10 +1532,14 @@ void FakeVimPluginPrivate::editorOpened(IEditor *editor) return; // we can only handle QTextEdit and QPlainTextEdit - if (!qobject_cast(widget) && !qobject_cast(widget)) + if (auto edit = Aggregation::query(widget)) + widget = edit; + else if (auto edit = Aggregation::query(widget)) + widget = edit; + else return; - auto tew = qobject_cast(widget); + auto tew = TextEditorWidget::fromEditor(editor); //qDebug() << "OPENING: " << editor << editor->widget() // << "MODE: " << theFakeVimSetting(ConfigUseFakeVim)->value(); diff --git a/src/plugins/projectexplorer/editorconfiguration.cpp b/src/plugins/projectexplorer/editorconfiguration.cpp index a78afc440d1..1bb2d4f27c2 100644 --- a/src/plugins/projectexplorer/editorconfiguration.cpp +++ b/src/plugins/projectexplorer/editorconfiguration.cpp @@ -274,7 +274,7 @@ void EditorConfiguration::setUseGlobalSettings(bool use) d->m_useGlobal = use; d->m_defaultCodeStyle->setCurrentDelegate(use ? TextEditorSettings::codeStyle() : nullptr); foreach (Core::IEditor *editor, Core::DocumentModel::editorsForOpenedDocuments()) { - if (auto widget = qobject_cast(editor->widget())) { + if (auto widget = TextEditorWidget::fromEditor(editor)) { Project *project = SessionManager::projectForFile(editor->document()->filePath()); if (project && project->editorConfiguration() == this) switchSettings(widget); diff --git a/src/plugins/texteditor/refactoringchanges.cpp b/src/plugins/texteditor/refactoringchanges.cpp index 01c61f10f87..9e91463349f 100644 --- a/src/plugins/texteditor/refactoringchanges.cpp +++ b/src/plugins/texteditor/refactoringchanges.cpp @@ -132,7 +132,7 @@ TextEditorWidget *RefactoringChanges::openEditor(const QString &fileName, bool a IEditor *editor = EditorManager::openEditorAt(fileName, line, column, Id(), flags); if (editor) - return qobject_cast(editor->widget()); + return TextEditorWidget::fromEditor(editor); else return nullptr; } @@ -163,7 +163,7 @@ RefactoringFile::RefactoringFile(const QString &fileName, const QSharedPointer editors = DocumentModel::editorsForFilePath(fileName); if (!editors.isEmpty()) { - auto editorWidget = qobject_cast(editors.first()->widget()); + auto editorWidget = TextEditorWidget::fromEditor(editors.first()); if (editorWidget && !editorWidget->isReadOnly()) m_editor = editorWidget; } diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index 7e92bc24eb8..635acd6e661 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -1461,8 +1461,14 @@ TextDocumentPtr TextEditorWidget::textDocumentPtr() const TextEditorWidget *TextEditorWidget::currentTextEditorWidget() { - auto editor = qobject_cast(EditorManager::currentEditor()); - return editor ? editor->editorWidget() : nullptr; + return fromEditor(EditorManager::currentEditor()); +} + +TextEditorWidget *TextEditorWidget::fromEditor(const IEditor *editor) +{ + if (editor) + return Aggregation::query(editor->widget()); + return nullptr; } void TextEditorWidgetPrivate::editorContentsChange(int position, int charsRemoved, int charsAdded) @@ -8370,8 +8376,9 @@ QVector BaseTextEditor::textEditorsForDocument(TextDocument *t TextEditorWidget *BaseTextEditor::editorWidget() const { - QTC_ASSERT(qobject_cast(m_widget.data()), return nullptr); - return static_cast(m_widget.data()); + auto textEditorWidget = TextEditorWidget::fromEditor(this); + QTC_CHECK(textEditorWidget); + return textEditorWidget; } void BaseTextEditor::setTextCursor(const QTextCursor &cursor) @@ -8649,10 +8656,12 @@ void TextEditorFactory::setParenthesesMatchingEnabled(bool on) BaseTextEditor *TextEditorFactoryPrivate::createEditorHelper(const TextDocumentPtr &document) { - TextEditorWidget *widget = m_widgetCreator(); - widget->setMarksVisible(m_marksVisible); - widget->setParenthesesMatchingEnabled(m_paranthesesMatchinEnabled); - widget->setCodeFoldingSupported(m_codeFoldingSupported); + QWidget *widget = m_widgetCreator(); + TextEditorWidget *textEditorWidget = Aggregation::query(widget); + QTC_ASSERT(textEditorWidget, return nullptr); + textEditorWidget->setMarksVisible(m_marksVisible); + textEditorWidget->setParenthesesMatchingEnabled(m_paranthesesMatchinEnabled); + textEditorWidget->setCodeFoldingSupported(m_codeFoldingSupported); BaseTextEditor *editor = m_editorCreator(); editor->setDuplicateSupported(m_duplicatedSupported); @@ -8663,25 +8672,25 @@ BaseTextEditor *TextEditorFactoryPrivate::createEditorHelper(const TextDocumentP // Needs to go before setTextDocument as this copies the current settings. if (m_autoCompleterCreator) - widget->setAutoCompleter(m_autoCompleterCreator()); + textEditorWidget->setAutoCompleter(m_autoCompleterCreator()); - widget->setTextDocument(document); - widget->autoCompleter()->setTabSettings(document->tabSettings()); - widget->d->m_hoverHandlers = m_hoverHandlers; + textEditorWidget->setTextDocument(document); + textEditorWidget->autoCompleter()->setTabSettings(document->tabSettings()); + textEditorWidget->d->m_hoverHandlers = m_hoverHandlers; - widget->d->m_codeAssistant.configure(widget); - widget->d->m_commentDefinition = m_commentDefinition; + textEditorWidget->d->m_codeAssistant.configure(textEditorWidget); + textEditorWidget->d->m_commentDefinition = m_commentDefinition; - QObject::connect(widget, + QObject::connect(textEditorWidget, &TextEditorWidget::activateEditor, - widget, + textEditorWidget, [editor](EditorManager::OpenEditorFlags flags) { EditorManager::activateEditor(editor, flags); }); if (m_useGenericHighlighter) - widget->setupGenericHighlighter(); - widget->finalizeInitialization(); + textEditorWidget->setupGenericHighlighter(); + textEditorWidget->finalizeInitialization(); editor->finalizeInitialization(); return editor; } diff --git a/src/plugins/texteditor/texteditor.h b/src/plugins/texteditor/texteditor.h index a2512384da1..403d2f2b6f5 100644 --- a/src/plugins/texteditor/texteditor.h +++ b/src/plugins/texteditor/texteditor.h @@ -556,6 +556,7 @@ public: void setContextHelpItem(const Core::HelpItem &item); static TextEditorWidget *currentTextEditorWidget(); + static TextEditorWidget *fromEditor(const Core::IEditor *editor); protected: /*! @@ -641,7 +642,8 @@ public: using EditorCreator = std::function; using DocumentCreator = std::function; - using EditorWidgetCreator = std::function; + // editor widget must be castable (qobject_cast or Aggregate::query) to TextEditorWidget + using EditorWidgetCreator = std::function; using SyntaxHighLighterCreator = std::function; using IndenterCreator = std::function; using AutoCompleterCreator = std::function; diff --git a/src/plugins/texteditor/texteditoractionhandler.cpp b/src/plugins/texteditor/texteditoractionhandler.cpp index 4cae664cb42..67d58985092 100644 --- a/src/plugins/texteditor/texteditoractionhandler.cpp +++ b/src/plugins/texteditor/texteditoractionhandler.cpp @@ -31,6 +31,8 @@ #include "texteditorconstants.h" #include "texteditorplugin.h" +#include + #include #include #include @@ -592,7 +594,7 @@ TextEditorActionHandler::TextEditorActionHandler(Core::Id editorId, if (resolver) d->m_findTextWidget = resolver; else - d->m_findTextWidget = [](Core::IEditor *editor) { return qobject_cast(editor->widget()); }; + d->m_findTextWidget = TextEditorWidget::fromEditor; } TextEditorActionHandler::~TextEditorActionHandler() diff --git a/src/plugins/valgrind/callgrindtool.cpp b/src/plugins/valgrind/callgrindtool.cpp index 41ee7ce4117..a6e5f078d6b 100644 --- a/src/plugins/valgrind/callgrindtool.cpp +++ b/src/plugins/valgrind/callgrindtool.cpp @@ -863,7 +863,7 @@ void CallgrindToolPrivate::showParserResults(const ParseData *data) void CallgrindToolPrivate::editorOpened(IEditor *editor) { - if (auto widget = qobject_cast(editor->widget())) { + if (auto widget = TextEditorWidget::fromEditor(editor)) { connect(widget, &TextEditorWidget::markContextMenuRequested, this, &CallgrindToolPrivate::requestContextMenu); }