[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [kdevplatform] /: Move assistant completion to its own KTextEditor::CompletionModel
From: Olivier JG <olivier.jg () gmail ! com>
Date: 2015-10-11 8:40:21
Message-ID: E1ZlCB3-0004BZ-VZ () scm ! kde ! org
[Download RAW message or body]
Git commit 039caf63fa0bdd643cd5c81eaee33bb378610f59 by Olivier JG.
Committed on 11/10/2015 at 08:44.
Pushed by olivierjg into branch 'master'.
Move assistant completion to its own KTextEditor::CompletionModel
M +0 -5 interfaces/iuicontroller.h
M +1 -0 language/CMakeLists.txt
A +90 -0 language/assistant/assistantcompletionmodel.cpp [License: LGPL \
(v2)] A +55 -0 language/assistant/assistantcompletionmodel.h [License: LGPL \
(v2)] M +51 -30 language/assistant/staticassistantsmanager.cpp
M +0 -3 language/assistant/staticassistantsmanager.h
M +0 -106 language/codecompletion/codecompletionmodel.cpp
M +0 -3 language/codecompletion/codecompletionmodel.h
M +0 -25 shell/uicontroller.cpp
M +0 -2 shell/uicontroller.h
http://commits.kde.org/kdevplatform/039caf63fa0bdd643cd5c81eaee33bb378610f59
diff --git a/interfaces/iuicontroller.h b/interfaces/iuicontroller.h
index 9d5fc19..50ddb99 100644
--- a/interfaces/iuicontroller.h
+++ b/interfaces/iuicontroller.h
@@ -130,11 +130,6 @@ public:
virtual void registerStatus(QObject* status) = 0;
/**
- * Show the assistant specified by @p assistant
- */
- virtual void showAssistant(const QExplicitlySharedDataPointer<IAssistant>& \
assistant) = 0;
-
- /**
* This is meant to be used by IDocument subclasses to initialize the
* Sublime::Document.
*/
diff --git a/language/CMakeLists.txt b/language/CMakeLists.txt
index d53bc2c..6c48bbc 100644
--- a/language/CMakeLists.txt
+++ b/language/CMakeLists.txt
@@ -21,6 +21,7 @@ set(KDevPlatformLanguage_LIB_SRCS
assistant/renameassistant.cpp
assistant/renamefileaction.cpp
assistant/staticassistant.cpp
+ assistant/assistantcompletionmodel.cpp
editor/persistentmovingrangeprivate.cpp
editor/persistentmovingrange.cpp
diff --git a/language/assistant/assistantcompletionmodel.cpp \
b/language/assistant/assistantcompletionmodel.cpp new file mode 100644
index 0000000..78bd544
--- /dev/null
+++ b/language/assistant/assistantcompletionmodel.cpp
@@ -0,0 +1,90 @@
+/*
+ Copyright 2015 Olivier de Gaalon <olivier.jg@gmail.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "assistantcompletionmodel.h"
+
+#include "staticassistantsmanager.h"
+
+#include "interfaces/iassistant.h"
+#include "interfaces/icore.h"
+#include "interfaces/ilanguagecontroller.h"
+
+namespace KDevelop {
+
+AssistantCompletionModel::AssistantCompletionModel(QObject* parent)
+ : KTextEditor::CodeCompletionModel(parent)
+{
+}
+
+void AssistantCompletionModel::executeCompletionItem(KTextEditor::View*, const \
KTextEditor::Range&, const QModelIndex& index) const +{
+ if (auto action = actionForIndex(index)) {
+ action->execute();
+ }
+}
+
+void AssistantCompletionModel::setActions(const QList<IAssistantAction::Ptr>& \
actions) +{
+ if (m_actions == actions) {
+ return;
+ }
+
+ beginResetModel();
+ m_actions = actions;
+ endResetModel();
+
+ if (rowCount()) {
+ emit hasCompletions();
+ }
+}
+
+QVariant AssistantCompletionModel::data(const QModelIndex& index, const int role) \
const +{
+ if (role == Qt::DisplayRole && index.column() == Name) {
+ if (auto action = actionForIndex(index)) {
+ return action->description();
+ }
+ } else if (role == ArgumentHintDepth) {
+ return 1;
+ }
+ return {};
+}
+
+QModelIndex AssistantCompletionModel::index(int row, int column, const QModelIndex& \
parent) const +{
+ if (!hasIndex(row, column, parent))
+ return {};
+
+ return createIndex(row, column);
+}
+
+int AssistantCompletionModel::rowCount(const QModelIndex& parent) const
+{
+ return parent.isValid() ? 0 : m_actions.size();
+}
+
+IAssistantAction* AssistantCompletionModel::actionForIndex(const QModelIndex& index) \
const +{
+ if (index.row() < 0 || index.row() >= m_actions.size()) {
+ return nullptr;
+ }
+
+ return m_actions.at(index.row()).data();
+}
+
+}
diff --git a/language/assistant/assistantcompletionmodel.h \
b/language/assistant/assistantcompletionmodel.h new file mode 100644
index 0000000..4a6836a
--- /dev/null
+++ b/language/assistant/assistantcompletionmodel.h
@@ -0,0 +1,55 @@
+/*
+ Copyright 2015 Olivier de Gaalon <olivier.jg@gmail.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef ASSISTANTCOMPLETIONMODEL_H
+#define ASSISTANTCOMPLETIONMODEL_H
+
+#include <KTextEditor/CodeCompletionModel>
+
+#include <QExplicitlySharedDataPointer>
+
+namespace KDevelop {
+
+class IAssistantAction;
+
+class AssistantCompletionModel : public KTextEditor::CodeCompletionModel
+{
+ Q_OBJECT
+public:
+ AssistantCompletionModel(QObject* parent = {});
+
+ void setActions(const QList<QExplicitlySharedDataPointer<IAssistantAction>> \
&actions); +
+ void executeCompletionItem(KTextEditor::View* view, const KTextEditor::Range& \
word, const QModelIndex& index) const override; +
+ QVariant data(const QModelIndex& index, const int role = Qt::DisplayRole) const;
+ QModelIndex index(int row, int column, const QModelIndex& parent = \
QModelIndex()) const override; + int rowCount(const QModelIndex& parent = \
QModelIndex()) const override; +
+signals:
+ void hasCompletions();
+
+private:
+ IAssistantAction *actionForIndex(const QModelIndex& index) const;
+
+ QList<QExplicitlySharedDataPointer<IAssistantAction>> m_actions;
+};
+
+}
+
+#endif // ASSISTANTCOMPLETIONMODEL_H
diff --git a/language/assistant/staticassistantsmanager.cpp \
b/language/assistant/staticassistantsmanager.cpp index 3aa60bf..92ca321 100644
--- a/language/assistant/staticassistantsmanager.cpp
+++ b/language/assistant/staticassistantsmanager.cpp
@@ -17,6 +17,7 @@
Boston, MA 02110-1301, USA.
*/
+#include "assistantcompletionmodel.h"
#include "staticassistantsmanager.h"
#include "util/debug.h"
@@ -37,6 +38,7 @@
#include <language/backgroundparser/backgroundparser.h>
#include <language/backgroundparser/parsejob.h>
+#include <language/codecompletion/codecompletion.h>
#include <language/duchain/problem.h>
using namespace KDevelop;
@@ -54,7 +56,6 @@ struct StaticAssistantsManager::Private
}
void eventuallyStartAssistant();
- void startAssistant(KDevelop::IAssistant::Ptr assistant);
void checkAssistantForProblems(KDevelop::TopDUContext* top);
void documentLoaded(KDevelop::IDocument*);
@@ -64,6 +65,7 @@ struct StaticAssistantsManager::Private
void documentActivated(KDevelop::IDocument*);
void cursorPositionChanged(KTextEditor::View*, const KTextEditor::Cursor&);
void timeout();
+ void setActiveAssistant(const IAssistant::Ptr& assistant);
StaticAssistantsManager* q;
@@ -74,6 +76,7 @@ struct StaticAssistantsManager::Private
QList<StaticAssistant::Ptr> m_registeredAssistants;
bool m_activeProblemAssistant = false;
QTimer* m_timer;
+ AssistantCompletionModel* m_completionModel;
SafeDocumentPointer m_eventualDocument;
KTextEditor::Range m_eventualRange;
@@ -100,6 +103,20 @@ StaticAssistantsManager::StaticAssistantsManager(QObject* \
parent)
foreach (IDocument* document, \
ICore::self()->documentController()->openDocuments()) { d->documentLoaded(document);
}
+
+ d->m_completionModel = new AssistantCompletionModel(this);
+ connect(d->m_completionModel, &AssistantCompletionModel::hasCompletions, this, \
[this]{ + if (auto view = d->m_currentView.data()) {
+ // We cannot use KTextEditor::CodeCompletionInterface::startCompletion \
for now + // It randomly disappears and refuses to invoke in many/various \
situations + // Would be very nice to fix this in KTextEditor, because we \
/really/ want to + // be able to invoke completion only on the assistants \
model as we could with + // CodeCompletionInterface::startCompletion
+ // HACK: private internal slot invocation
+ QMetaObject::invokeMethod(view, "userInvokedCompletion");
+ }
+ });
+ new KDevelop::CodeCompletion(this, d->m_completionModel, {});
}
StaticAssistantsManager::~StaticAssistantsManager()
@@ -143,9 +160,7 @@ void StaticAssistantsManager::Private::documentLoaded(IDocument* \
document)
void StaticAssistantsManager::hideAssistant()
{
- d->m_activeAssistant = QExplicitlySharedDataPointer<KDevelop::IAssistant>();
- d->m_activeProblemAssistant = false;
- emit activeAssistantChanged();
+ d->setActiveAssistant({});
}
void StaticAssistantsManager::Private::textInserted(Document* document, const \
Cursor& cursor, const QString& text) @@ -194,7 +209,7 @@ void \
StaticAssistantsManager::Private::eventuallyStartAssistant()
assistant->textChanged(view, m_eventualRange, m_eventualRemovedText);
if (assistant->isUseful()) {
- startAssistant(IAssistant::Ptr(assistant.data()));
+ setActiveAssistant(IAssistant::Ptr(assistant.data()));
break;
}
}
@@ -206,30 +221,6 @@ void \
StaticAssistantsManager::Private::eventuallyStartAssistant() \
m_eventualRemovedText.clear(); }
-void StaticAssistantsManager::Private::startAssistant(IAssistant::Ptr assistant)
-{
- if (assistant == m_activeAssistant) {
- return;
- }
-
- if (m_activeAssistant) {
- m_activeAssistant->doHide();
- }
-
- if (!m_currentView)
- return;
-
- m_activeAssistant = assistant;
- if (m_activeAssistant) {
- connect(m_activeAssistant.data(), &IAssistant::hide, q, \
&StaticAssistantsManager::hideAssistant, Qt::UniqueConnection);
- ICore::self()->uiController()->showAssistant(IAssistant::Ptr(m_activeAssistant.data()));
-
- m_assistantStartedAt = m_currentView.data()->cursorPosition();
- }
-
- emit q->activeAssistantChanged();
-}
-
void StaticAssistantsManager::Private::parseJobFinished(ParseJob* job)
{
if (job->document() != m_currentDocument) {
@@ -291,7 +282,7 @@ void \
StaticAssistantsManager::Private::checkAssistantForProblems(TopDUContext* \
t
if (m_currentView && m_currentView.data()->cursorPosition().line() == \
problem->range().start.line) { IAssistant::Ptr solution = \
problem->solutionAssistant(); if(solution) {
- startAssistant(solution);
+ setActiveAssistant(solution);
m_activeProblemAssistant = true;
break;
}
@@ -314,4 +305,34 @@ void StaticAssistantsManager::Private::timeout()
}
}
+void StaticAssistantsManager::Private::setActiveAssistant(const IAssistant::Ptr& \
assistant) +{
+ if (assistant == m_activeAssistant) {
+ return;
+ }
+
+ m_activeAssistant = QExplicitlySharedDataPointer<KDevelop::IAssistant>();
+
+ if (m_activeAssistant) {
+ m_activeAssistant->doHide();
+ m_activeAssistant->disconnect(q);
+ m_activeAssistant->disconnect(m_completionModel);
+ }
+
+ m_activeAssistant = assistant;
+
+ if (auto activeAssistant = m_activeAssistant.data()) {
+ auto updateActions = [=]{ \
m_completionModel->setActions(activeAssistant->actions()); }; + \
connect(activeAssistant, &IAssistant::hide, q, \
&StaticAssistantsManager::hideAssistant); + connect(activeAssistant, \
&IAssistant::actionsChanged, m_completionModel, updateActions); + if \
(m_currentView) { + m_assistantStartedAt = \
m_currentView.data()->cursorPosition(); + updateActions();
+ }
+ } else {
+ m_activeProblemAssistant = false;
+ m_completionModel->setActions({});
+ }
+}
+
#include "moc_staticassistantsmanager.cpp"
diff --git a/language/assistant/staticassistantsmanager.h \
b/language/assistant/staticassistantsmanager.h index a03e03a..1cfd3fb 100644
--- a/language/assistant/staticassistantsmanager.h
+++ b/language/assistant/staticassistantsmanager.h
@@ -66,9 +66,6 @@ public:
public slots:
void hideAssistant();
-signals:
- void activeAssistantChanged();
-
private:
struct Private;
QScopedPointer<Private> const d;
diff --git a/language/codecompletion/codecompletionmodel.cpp \
b/language/codecompletion/codecompletionmodel.cpp index 4bf0c14..6ee981b 100644
--- a/language/codecompletion/codecompletionmodel.cpp
+++ b/language/codecompletion/codecompletionmodel.cpp
@@ -31,9 +31,6 @@
#include <ktexteditor/view.h>
#include <ktexteditor/document.h>
-#include <language/assistant/staticassistant.h>
-#include <language/assistant/staticassistantsmanager.h>
-
#include "../duchain/declaration.h"
#include "../duchain/classfunctiondeclaration.h"
#include "../duchain/ducontext.h"
@@ -59,73 +56,6 @@ using namespace KTextEditor;
//Multi-threaded completion creates some multi-threading related crashes, and \
sometimes shows the completions in the wrong position if the cursor was moved // \
#define SINGLE_THREADED_COMPLETION
-namespace {
-
-class AssistantItem : public KDevelop::CompletionTreeItem
-{
-public:
- AssistantItem(const KDevelop::IAssistantAction::Ptr& action)
- : CompletionTreeItem()
- , m_action(action)
- {
- Q_ASSERT(action);
- }
-
- QVariant data(const QModelIndex& index, int role, const \
KDevelop::CodeCompletionModel*) const override
- {
- switch (role) {
- case Qt::DisplayRole:
- if (index.column() == KTextEditor::CodeCompletionModel::Name)
- return m_action->description();
- break;
- }
- return QVariant();
- }
-
- int argumentHintDepth() const override
- {
- return 1;
- }
-
- void execute(KTextEditor::View*, const KTextEditor::Range&) override
- {
- m_action->execute();
- }
-
-private:
- KDevelop::IAssistantAction::Ptr m_action;
-};
-
-class AssistantGroup : public KDevelop::CompletionCustomGroupNode
-{
-public:
- AssistantGroup(const QList<KDevelop::IAssistantAction::Ptr>& actions)
- : CompletionCustomGroupNode(QObject::tr("Assistants"), 0)
- {
- for (const auto& action: actions) {
- appendChild(KDevelop::CompletionTreeItemPointer(new \
AssistantItem(action)));
- }
- }
-};
-
-KDevelop::IAssistant* activeAssistant()
-{
- return KDevelop::ICore::self()->languageController()-> \
staticAssistantsManager()->activeAssistant().data();
-}
-
-KDevelop::CompletionTreeElementPointer assistantActionsGroup(KDevelop::IAssistant* \
assistant)
-{
- if (assistant) {
- const auto actions = assistant->actions();
- if (!actions.isEmpty()) {
- return KDevelop::CompletionTreeElementPointer(new \
AssistantGroup(actions));
- }
- }
- return {};
-}
-
-}
-
namespace KDevelop {
class CompletionWorkerThread : public QThread
@@ -176,10 +106,6 @@ CodeCompletionModel::CodeCompletionModel( QObject * parent )
, m_thread(0)
{
qRegisterMetaType<KTextEditor::Cursor>();
-
- connect(ICore::self()->languageController()->staticAssistantsManager(),
- &StaticAssistantsManager::activeAssistantChanged,
- this, &CodeCompletionModel::updateAssistantItems);
}
void CodeCompletionModel::initialize() {
@@ -219,35 +145,6 @@ KDevelop::CodeCompletionWorker* CodeCompletionModel::worker() \
const { return m_thread->m_worker;
}
-void CodeCompletionModel::updateAssistantItems()
-{
- const auto assistant = activeAssistant();
- disconnect(m_connection);
- if (assistant) {
- m_connection = connect(assistant, &IAssistant::actionsChanged,
- this, &CodeCompletionModel::updateAssistantItems);
- }
-
- const bool hasAssistantNode = !m_completionItems.isEmpty() &&
- dynamic_cast<AssistantGroup*>(m_completionItems.last().data());
-
- if (!assistant && !hasAssistantNode) {
- return;
- }
- // KateCompletionModel will happily ignore beginRemoveRows/endRemoveRows for \
argument hint items
- // We use argument hints otherwise we have to hack the currently typed text into \
the item's Name column
- // because KateCompletionModel offers no way to force an item to skip text \
filtering (other than arg hints)
- // Event if we didn't, KateCompletionModel doesn't correctly balance \
begin/endInsertRows, so... meh
- beginResetModel();
- if (hasAssistantNode) {
- m_completionItems.removeLast();
- }
- if (auto assists = assistantActionsGroup(assistant)) {
- m_completionItems.append(assists);
- }
- endResetModel();
-}
-
void CodeCompletionModel::clear()
{
beginResetModel();
@@ -367,9 +264,6 @@ void CodeCompletionModel::foundDeclarations(const \
QList<QExplicitlySharedDataPoi
beginResetModel();
m_completionItems = items;
- if (auto assists = assistantActionsGroup(activeAssistant())) {
- m_completionItems.append(assists);
- }
endResetModel();
if(m_completionContext) {
diff --git a/language/codecompletion/codecompletionmodel.h \
b/language/codecompletion/codecompletionmodel.h index b141fa5..4b048f4 100644
--- a/language/codecompletion/codecompletionmodel.h
+++ b/language/codecompletion/codecompletionmodel.h
@@ -136,10 +136,7 @@ class KDEVPLATFORMLANGUAGE_EXPORT CodeCompletionModel : public \
KTextEditor::Code
CodeCompletionWorker* worker() const;
- void updateAssistantItems();
-
private:
- QMetaObject::Connection m_connection;
bool m_forceWaitForModel;
bool m_fullCompletion;
QMutex* m_mutex;
diff --git a/shell/uicontroller.cpp b/shell/uicontroller.cpp
index 1df7a96..2510267 100644
--- a/shell/uicontroller.cpp
+++ b/shell/uicontroller.cpp
@@ -718,31 +718,6 @@ void UiController::showErrorMessage(const QString& message, int \
timeout)
QMetaObject::invokeMethod(mw, "showErrorMessage", Q_ARG(QString, message), \
Q_ARG(int, timeout)); }
-void UiController::showAssistant(const KDevelop::IAssistant::Ptr& assistant)
-{
- if(!assistant)
- return;
-
- Sublime::View* view = d->activeSublimeWindow->activeView();
- if( !view )
- {
- qCDebug(SHELL) << "no active view in mainwindow";
- return;
- }
-
- auto editorView = qobject_cast<KTextEditor::View*>(view->widget());
- Q_ASSERT(editorView);
- if (editorView) {
- // TODO: See if we can use CodeCompletionInterface::startCompletion for this
- // See if we can split the assistant actions into their own model and use \
the model param as well
- // That way we don't get unwanted completions when the assistant completions \
are shown
- if (!assistant->actions().isEmpty()) {
- // HACK: Internal, unexposed API -- do NOT git blame this line
- QMetaObject::invokeMethod(editorView, "userInvokedCompletion");
- }
- }
-}
-
const QMap< IToolViewFactory*, Sublime::ToolDocument* >& \
UiController::factoryDocuments() const {
return d->factoryDocuments;
diff --git a/shell/uicontroller.h b/shell/uicontroller.h
index 06b4104..b3bc417 100644
--- a/shell/uicontroller.h
+++ b/shell/uicontroller.h
@@ -85,8 +85,6 @@ public:
/*! @p status must implement KDevelop::IStatus */
virtual void registerStatus(QObject* status) override;
- virtual void showAssistant(const KDevelop::IAssistant::Ptr& assistant) override;
-
virtual void showErrorMessage(const QString& message, int timeout) override;
/// Returns list of available view factories together with their ToolDocuments.
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic