diff options
author | David Schulz <[email protected]> | 2020-01-27 14:52:46 +0100 |
---|---|---|
committer | David Schulz <[email protected]> | 2020-01-31 08:41:26 +0000 |
commit | c032b302ade45a13e72c9d3d75c6c84dce89538f (patch) | |
tree | 69d99c846375974931961cd6b55f93792a903149 /src/plugins | |
parent | 972e5b1668494767487abf2f864d327bd547afde (diff) |
LanguageClient: outline combo box for editor toolbar
Fixes: QTCREATORBUG-21916
Change-Id: Ia4e1711f0f5e67222e4f5274792820917f4114db
Reviewed-by: Christian Stenger <[email protected]>
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/languageclient/languageclientoutline.cpp | 94 | ||||
-rw-r--r-- | src/plugins/languageclient/languageclientoutline.h | 8 | ||||
-rw-r--r-- | src/plugins/languageclient/languageclientutils.cpp | 23 |
3 files changed, 124 insertions, 1 deletions
diff --git a/src/plugins/languageclient/languageclientoutline.cpp b/src/plugins/languageclient/languageclientoutline.cpp index a85ff0f6a84..550e391dda4 100644 --- a/src/plugins/languageclient/languageclientoutline.cpp +++ b/src/plugins/languageclient/languageclientoutline.cpp @@ -36,6 +36,7 @@ #include <utils/itemviews.h> #include <utils/mimetypes/mimedatabase.h> #include <utils/treemodel.h> +#include <utils/treeviewcombobox.h> #include <utils/utilsicons.h> #include <QBoxLayout> @@ -218,7 +219,8 @@ void LanguageClientOutlineWidget::onItemActivated(const QModelIndex &index) m_editor->widget()->setFocus(); } -static bool clientSupportsDocumentSymbols(const Client *client, const TextEditor::TextDocument *doc) +bool LanguageClientOutlineWidgetFactory::clientSupportsDocumentSymbols( + const Client *client, const TextEditor::TextDocument *doc) { if (!client) return false; @@ -249,4 +251,94 @@ TextEditor::IOutlineWidget *LanguageClientOutlineWidgetFactory::createWidget(Cor return new LanguageClientOutlineWidget(client, textEditor); } +class OutlineComboBox : public Utils::TreeViewComboBox +{ +public: + OutlineComboBox(Client *client, TextEditor::BaseTextEditor *editor); + +private: + void updateModel(const DocumentUri &resultUri, const DocumentSymbolsResult &result); + void updateEntry(); + void activateEntry(); + void requestSymbols(); + + LanguageClientOutlineModel m_model; + QPointer<Client> m_client; + TextEditor::TextEditorWidget *m_editorWidget; + const DocumentUri m_uri; +}; + +Utils::TreeViewComboBox *LanguageClientOutlineWidgetFactory::createComboBox(Client *client, + Core::IEditor *editor) +{ + auto textEditor = qobject_cast<TextEditor::BaseTextEditor *>(editor); + QTC_ASSERT(textEditor, return nullptr); + TextEditor::TextDocument *document = textEditor->textDocument(); + if (!client || !clientSupportsDocumentSymbols(client, document)) + return nullptr; + + return new OutlineComboBox(client, textEditor); +} + +OutlineComboBox::OutlineComboBox(Client *client, TextEditor::BaseTextEditor *editor) + : m_client(client) + , m_editorWidget(editor->editorWidget()) + , m_uri(DocumentUri::fromFilePath(editor->document()->filePath())) +{ + setModel(&m_model); + setMinimumContentsLength(13); + QSizePolicy policy = sizePolicy(); + policy.setHorizontalPolicy(QSizePolicy::Expanding); + setSizePolicy(policy); + setMaxVisibleItems(40); + + connect(client->documentSymbolCache(), &DocumentSymbolCache::gotSymbols, + this, &OutlineComboBox::updateModel); + connect(editor->textDocument(), &TextEditor::TextDocument::contentsChanged, + this, &OutlineComboBox::requestSymbols); + connect(m_editorWidget, &TextEditor::TextEditorWidget::cursorPositionChanged, + this, &OutlineComboBox::updateEntry); + connect(this, QOverload<int>::of(&QComboBox::activated), this, &OutlineComboBox::activateEntry); +} + +void OutlineComboBox::updateModel(const DocumentUri &resultUri, const DocumentSymbolsResult &result) +{ + if (m_uri != resultUri) + return; + if (Utils::holds_alternative<QList<SymbolInformation>>(result)) + m_model.setInfo(Utils::get<QList<SymbolInformation>>(result)); + else if (Utils::holds_alternative<QList<DocumentSymbol>>(result)) + m_model.setInfo(Utils::get<QList<DocumentSymbol>>(result)); + else + m_model.clear(); +} + +void OutlineComboBox::updateEntry() +{ + const Position pos(m_editorWidget->textCursor()); + LanguageClientOutlineItem *itemForCursor = m_model.findNonRootItem( + [&](const LanguageClientOutlineItem *item) { return item->contains(pos); }); + if (itemForCursor) + setCurrentIndex(m_model.indexForItem(itemForCursor)); +} + +void OutlineComboBox::activateEntry() +{ + const QModelIndex modelIndex = view()->currentIndex(); + if (modelIndex.isValid()) { + const Position &pos = m_model.itemForIndex(modelIndex)->pos(); + Core::EditorManager::cutForwardNavigationHistory(); + Core::EditorManager::addCurrentPositionToNavigationHistory(); + // line has to be 1 based, column 0 based! + m_editorWidget->gotoLine(pos.line() + 1, pos.character(), true, true); + emit m_editorWidget->activateEditor(); + } +} + +void OutlineComboBox::requestSymbols() +{ + if (m_client) + m_client->documentSymbolCache()->requestSymbols(m_uri); +} + } // namespace LanguageClient diff --git a/src/plugins/languageclient/languageclientoutline.h b/src/plugins/languageclient/languageclientoutline.h index 100f8a783d8..2384ea7f6ab 100644 --- a/src/plugins/languageclient/languageclientoutline.h +++ b/src/plugins/languageclient/languageclientoutline.h @@ -27,13 +27,21 @@ #include <texteditor/ioutlinewidget.h> +namespace TextEditor { class TextDocument; } +namespace Utils { class TreeViewComboBox; } + namespace LanguageClient { +class Client; + class LanguageClientOutlineWidgetFactory : public TextEditor::IOutlineWidgetFactory { public: using IOutlineWidgetFactory::IOutlineWidgetFactory; + static Utils::TreeViewComboBox *createComboBox(Client *client, Core::IEditor *editor); + static bool clientSupportsDocumentSymbols(const Client *client, + const TextEditor::TextDocument *doc); // IOutlineWidgetFactory interface public: bool supportsEditor(Core::IEditor *editor) const override; diff --git a/src/plugins/languageclient/languageclientutils.cpp b/src/plugins/languageclient/languageclientutils.cpp index eeb64b406ea..9cc1ad488fa 100644 --- a/src/plugins/languageclient/languageclientutils.cpp +++ b/src/plugins/languageclient/languageclientutils.cpp @@ -28,6 +28,7 @@ #include "client.h" #include "languageclient_global.h" #include "languageclientmanager.h" +#include "languageclientoutline.h" #include <coreplugin/editormanager/documentmodel.h> #include <coreplugin/icore.h> @@ -37,6 +38,7 @@ #include <texteditor/textdocument.h> #include <texteditor/texteditor.h> #include <utils/textutils.h> +#include <utils/treeviewcombobox.h> #include <utils/utilsicons.h> #include <QFile> @@ -246,6 +248,27 @@ void updateEditorToolBar(Core::IEditor *editor) actions.remove(widget); }); } + + static QMap<QWidget *, QPair<Client *, QAction *>> outlines; + + if (outlines.contains(widget)) { + auto outline = outlines[widget]; + if (outline.first != client + || !LanguageClientOutlineWidgetFactory::clientSupportsDocumentSymbols(client, + document)) { + auto oldAction = outline.second; + widget->toolBar()->removeAction(oldAction); + delete oldAction; + outlines.remove(widget); + } + } + + if (!outlines.contains(widget)) { + if (QWidget *comboBox = LanguageClientOutlineWidgetFactory::createComboBox(client, editor)) { + outlines[widget] = {client, + widget->insertExtraToolBarWidget(TextEditorWidget::Left, comboBox)}; + } + } } const QIcon symbolIcon(int type) |