aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorDavid Schulz <[email protected]>2020-01-27 14:52:46 +0100
committerDavid Schulz <[email protected]>2020-01-31 08:41:26 +0000
commitc032b302ade45a13e72c9d3d75c6c84dce89538f (patch)
tree69d99c846375974931961cd6b55f93792a903149 /src/plugins
parent972e5b1668494767487abf2f864d327bd547afde (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.cpp94
-rw-r--r--src/plugins/languageclient/languageclientoutline.h8
-rw-r--r--src/plugins/languageclient/languageclientutils.cpp23
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)