diff --git a/interfaces/iuicontroller.h b/interfaces/iuicontroller.h
--- a/interfaces/iuicontroller.h
+++ b/interfaces/iuicontroller.h
@@ -130,16 +130,6 @@
virtual void registerStatus(QObject* status) = 0;
/**
- * Shows an assistant popup at bottom within the current central widget
- * @p assistant the assistant that will be shown in a popup */
- virtual void popUpAssistant(const QExplicitlySharedDataPointer& assistant) = 0;
-
- /**
- * Hides the assistant if it is currently being shown
- */
- virtual void hideAssistant() = 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
--- a/language/CMakeLists.txt
+++ b/language/CMakeLists.txt
@@ -184,6 +184,7 @@
KF5::TextEditor
KF5::Parts
KF5::Archive
+ KF5::IconThemes
KDev::Util
KDev::Project
)
diff --git a/language/assistant/renameassistant.h b/language/assistant/renameassistant.h
--- a/language/assistant/renameassistant.h
+++ b/language/assistant/renameassistant.h
@@ -40,8 +40,10 @@
explicit RenameAssistant(ILanguageSupport* supportedLanguage);
~RenameAssistant() override;
- void textChanged(KTextEditor::View* view, const KTextEditor::Range& invocationRange, const QString& removedText = QString()) override;
+ void textChanged(KTextEditor::Document* doc, const KTextEditor::Range& invocationRange,
+ const QString& removedText = QString()) override;
bool isUseful() const override;
+ KTextEditor::Range displayRange() const override;
QString title() const override;
diff --git a/language/assistant/renameassistant.cpp b/language/assistant/renameassistant.cpp
--- a/language/assistant/renameassistant.cpp
+++ b/language/assistant/renameassistant.cpp
@@ -48,15 +48,15 @@
return !firstRange.intersect(secondRange + KTextEditor::Range(0, -1, 0, +1)).isEmpty();
}
-Declaration* getDeclarationForChangedRange(KTextEditor::View* view, const KTextEditor::Range& changed)
+Declaration* getDeclarationForChangedRange(KTextEditor::Document* doc, const KTextEditor::Range& changed)
{
const KTextEditor::Cursor cursor(changed.start());
- Declaration* declaration = DUChainUtils::itemUnderCursor(view->document()->url(), cursor);
+ Declaration* declaration = DUChainUtils::itemUnderCursor(doc->url(), cursor);
//If it's null we could be appending, but there's a case where appending gives a wrong decl
//and not a null declaration ... "type var(init)", so check for that too
if (!declaration || !rangesConnect(declaration->rangeInCurrentRevision(), changed)) {
- declaration = DUChainUtils::itemUnderCursor(view->document()->url(), KTextEditor::Cursor(cursor.line(), cursor.column()-1));
+ declaration = DUChainUtils::itemUnderCursor(doc->url(), KTextEditor::Cursor(cursor.line(), cursor.column()-1));
}
//In this case, we may either not have a decl at the cursor, or we got a decl, but are editing its use.
@@ -99,6 +99,8 @@
bool m_isUseful;
bool m_renameFile;
+ KTextEditor::Cursor m_lastChangedLocation;
+ QPointer m_lastChangedDocument = nullptr;
};
RenameAssistant::RenameAssistant(ILanguageSupport* supportedLanguage)
@@ -121,26 +123,28 @@
return d->m_isUseful;
}
-void RenameAssistant::textChanged(KTextEditor::View* view, const KTextEditor::Range& invocationRange, const QString& removedText)
+void RenameAssistant::textChanged(KTextEditor::Document* doc, const KTextEditor::Range& invocationRange, const QString& removedText)
{
clearActions();
+ d->m_lastChangedLocation = invocationRange.end();
+ d->m_lastChangedDocument = doc;
if (!supportedLanguage()->refactoring()) {
qCWarning(LANGUAGE) << "Refactoring not supported. Aborting.";
return;
}
- if (!view)
+ if (!doc)
return;
//If the inserted text isn't valid for a variable name, consider the editing ended
QRegExp validDeclName("^[0-9a-zA-Z_]*$");
- if (removedText.isEmpty() && !validDeclName.exactMatch(view->document()->text(invocationRange))) {
+ if (removedText.isEmpty() && !validDeclName.exactMatch(doc->text(invocationRange))) {
d->reset();
return;
}
- const QUrl url = view->document()->url();
+ const QUrl url = doc->url();
const IndexedString indexedUrl(url);
DUChainReadLocker lock;
@@ -150,7 +154,7 @@
|| d->m_newDeclarationRange->document() != indexedUrl) {
d->reset();
- Declaration* declAtCursor = getDeclarationForChangedRange(view, invocationRange);
+ Declaration* declAtCursor = getDeclarationForChangedRange(doc, invocationRange);
if (!declAtCursor) {
// not editing a declaration
return;
@@ -168,7 +172,7 @@
{
foreach(const RangeInRevision range, it.value()) {
KTextEditor::Range currentRange = declAtCursor->transformFromLocalRevision(range);
- if(currentRange.isEmpty() || view->document()->text(currentRange) != declAtCursor->identifier().identifier().str()) {
+ if(currentRange.isEmpty() || doc->text(currentRange) != declAtCursor->identifier().identifier().str()) {
return; // One of the uses is invalid. Maybe the replacement has already been performed.
}
}
@@ -196,7 +200,7 @@
d->m_newDeclarationRange->range().encompass(invocationRange), indexedUrl, true);
}
- d->m_newDeclarationName = view->document()->text(d->m_newDeclarationRange->range());
+ d->m_newDeclarationName = doc->text(d->m_newDeclarationRange->range());
if (d->m_newDeclarationName == d->m_oldDeclarationName.toString()) {
d->reset();
return;
@@ -220,4 +224,15 @@
emit actionsChanged();
}
+KTextEditor::Range KDevelop::RenameAssistant::displayRange() const
+{
+ if ( !d->m_lastChangedDocument ) {
+ return {};
+ }
+ auto range = d->m_lastChangedDocument->wordRangeAt(d->m_lastChangedLocation);
+ qDebug() << "range:" << range;
+ return range;
+}
+
+
#include "moc_renameassistant.cpp"
diff --git a/language/assistant/staticassistant.h b/language/assistant/staticassistant.h
--- a/language/assistant/staticassistant.h
+++ b/language/assistant/staticassistant.h
@@ -23,9 +23,13 @@
#define KDEVPLATFORM_STATICASSISTANT_H
#include
+#include
+#include
#include
+#include
+
namespace KTextEditor {
class Document;
class View;
@@ -75,15 +79,22 @@
*
* Reimplement in subclass
*/
- virtual void textChanged(KTextEditor::View* view, const KTextEditor::Range& invocationRange,
+ virtual void textChanged(KTextEditor::Document* doc, const KTextEditor::Range& invocationRange,
const QString& removedText = QString()) = 0;
/**
* Whether it's worth showing this assistant to the user
*
* Reimplement in subclass
*/
virtual bool isUseful() const = 0;
+ /**
+ * The range the assistant should be displayed in.
+ */
+ virtual KTextEditor::Range displayRange() const = 0;
+
+ virtual void updateReady(const IndexedString&, const KDevelop::ReferencedTopDUContext&) { }
+
private:
struct Private;
QScopedPointer const d;
diff --git a/language/assistant/staticassistantsmanager.h b/language/assistant/staticassistantsmanager.h
--- a/language/assistant/staticassistantsmanager.h
+++ b/language/assistant/staticassistantsmanager.h
@@ -26,6 +26,9 @@
#include "staticassistant.h"
#include
+#include
+#include
+#include
#include
#include
@@ -56,22 +59,16 @@
explicit StaticAssistantsManager(QObject* parent = nullptr);
~StaticAssistantsManager() override;
- QExplicitlySharedDataPointer activeAssistant();
-
void registerAssistant(const StaticAssistant::Ptr assistant);
void unregisterAssistant(const StaticAssistant::Ptr assistant);
- QList registeredAssistants() const;
-
-public slots:
- void hideAssistant();
+ QVector registeredAssistants() const;
+ void notifyAssistants(const IndexedString& url, const KDevelop::ReferencedTopDUContext& context);
-signals:
- void activeAssistantChanged();
+ QVector problemsForContext(const ReferencedTopDUContext& top);
private:
struct Private;
QScopedPointer const d;
- Q_PRIVATE_SLOT(d, void eventuallyStartAssistant())
};
}
diff --git a/language/assistant/staticassistantsmanager.cpp b/language/assistant/staticassistantsmanager.cpp
--- a/language/assistant/staticassistantsmanager.cpp
+++ b/language/assistant/staticassistantsmanager.cpp
@@ -12,12 +12,13 @@
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
+ 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 "staticassistantsmanager.h"
+#include
#include "util/debug.h"
#include
@@ -44,57 +45,25 @@
{
Private(StaticAssistantsManager* qq)
: q(qq)
- {
- connect(DUChain::self(), &DUChain::updateReady,
- q, [this] (const IndexedString& url, const ReferencedTopDUContext& topContext) {
- updateReady(url, topContext);
- });
- }
-
- void eventuallyStartAssistant();
- void startAssistant(KDevelop::IAssistant::Ptr assistant);
- void checkAssistantForProblems(KDevelop::TopDUContext* top);
+ { }
+ void updateReady(const IndexedString& document, const KDevelop::ReferencedTopDUContext& topContext);
void documentLoaded(KDevelop::IDocument*);
- void textInserted(Document* document, const Cursor& cursor, const QString& text);
- void textRemoved(Document* document, const Range& cursor, const QString& removedText);
- void updateReady(const IndexedString& document, const ReferencedTopDUContext& topContext);
- void documentActivated(KDevelop::IDocument*);
- void cursorPositionChanged(KTextEditor::View*, const KTextEditor::Cursor&);
- void timeout();
+ void textInserted(KTextEditor::Document* document, const Cursor& cursor, const QString& text);
+ void textRemoved(KTextEditor::Document* document, const Range& cursor, const QString& removedText);
StaticAssistantsManager* q;
- QPointer m_currentView;
- KTextEditor::Cursor m_assistantStartedAt;
- KDevelop::IndexedString m_currentDocument;
- QExplicitlySharedDataPointer m_activeAssistant;
- QList m_registeredAssistants;
- bool m_activeProblemAssistant = false;
- QTimer* m_timer;
-
- SafeDocumentPointer m_eventualDocument;
- KTextEditor::Range m_eventualRange;
- QString m_eventualRemovedText;
- QMetaObject::Connection m_cursorPositionChangeConnection;
+ QVector m_registeredAssistants;
};
StaticAssistantsManager::StaticAssistantsManager(QObject* parent)
: QObject(parent)
, d(new Private(this))
{
- d->m_timer = new QTimer(this);
- d->m_timer->setSingleShot(true);
- d->m_timer->setInterval(400);
- connect(d->m_timer, &QTimer::timeout, this, [&] { d->timeout(); });
-
connect(KDevelop::ICore::self()->documentController(),
&IDocumentController::documentLoaded,
this, [&] (IDocument* document) { d->documentLoaded(document); });
- connect(KDevelop::ICore::self()->documentController(),
- &IDocumentController::documentActivated,
- this, [&] (IDocument* doc) { d->documentActivated(doc); });
-
foreach (IDocument* document, ICore::self()->documentController()->openDocuments()) {
d->documentLoaded(document);
}
@@ -104,11 +73,6 @@
{
}
-QExplicitlySharedDataPointer StaticAssistantsManager::activeAssistant()
-{
- return d->m_activeAssistant;
-}
-
void StaticAssistantsManager::registerAssistant(const StaticAssistant::Ptr assistant)
{
if (d->m_registeredAssistants.contains(assistant))
@@ -122,200 +86,86 @@
d->m_registeredAssistants.removeOne(assistant);
}
-QList StaticAssistantsManager::registeredAssistants() const
+QVector StaticAssistantsManager::registeredAssistants() const
{
return d->m_registeredAssistants;
}
void StaticAssistantsManager::Private::documentLoaded(IDocument* document)
{
if (document->textDocument()) {
- connect(document->textDocument(),
- &Document::textInserted, q,
- [&] (Document* document, const Cursor& cursor, const QString& text) { textInserted(document, cursor, text); });
- connect(document->textDocument(),
- &Document::textRemoved, q,
- [&] (Document* document, const Range& range, const QString& removedText) { textRemoved(document, range, removedText); });
+ auto doc = document->textDocument();
+ connect(doc, &KTextEditor::Document::textInserted, q,
+ [&] (KTextEditor::Document* doc, const Cursor& cursor, const QString& text) {
+ textInserted(doc, cursor, text);
+ });
+ connect(doc, &KTextEditor::Document::textRemoved, q,
+ [&] (KTextEditor::Document* doc, const Range& range, const QString& removedText) {
+ textRemoved(doc, range, removedText);
+ });
}
}
-void StaticAssistantsManager::hideAssistant()
+void StaticAssistantsManager::Private::textInserted(Document* doc, const Cursor& cursor, const QString& text)
{
- d->m_activeAssistant = QExplicitlySharedDataPointer();
- d->m_activeProblemAssistant = false;
- emit activeAssistantChanged();
-}
-
-void StaticAssistantsManager::Private::textInserted(Document* document, const Cursor& cursor, const QString& text)
-{
- m_eventualDocument = document;
- m_eventualRange = Range(cursor, text.size());
- m_eventualRemovedText.clear();
- QMetaObject::invokeMethod(q, "eventuallyStartAssistant", Qt::QueuedConnection);
+ Q_FOREACH ( auto assistant, m_registeredAssistants ) {
+ auto range = Range(cursor, cursor+Cursor(0, text.size()));
+ assistant->textChanged(doc, range, {});
+ }
}
-void StaticAssistantsManager::Private::textRemoved(Document* document, const Range& range,
+void StaticAssistantsManager::Private::textRemoved(Document* doc, const Range& range,
const QString& removedText)
{
- m_eventualDocument = document;
- m_eventualRange = range;
- m_eventualRemovedText = removedText;
- QMetaObject::invokeMethod(q, "eventuallyStartAssistant", Qt::QueuedConnection);
+ Q_FOREACH ( auto assistant, m_registeredAssistants ) {
+ assistant->textChanged(doc, range, removedText);
+ }
}
-void StaticAssistantsManager::Private::eventuallyStartAssistant()
+void StaticAssistantsManager::notifyAssistants(const IndexedString& url, const KDevelop::ReferencedTopDUContext& context)
{
- if (!m_eventualDocument) {
- return;
+ Q_FOREACH ( auto assistant, d->m_registeredAssistants ) {
+ assistant->updateReady(url, context);
}
+}
+QVector KDevelop::StaticAssistantsManager::problemsForContext(const KDevelop::ReferencedTopDUContext& top)
+{
View* view = ICore::self()->documentController()->activeTextDocumentView();
- if (!view) {
- return;
- }
- if (view->document() != m_eventualDocument) {
- qWarning(LANGUAGE) << "Active view does not belong to document of last observed change!";
- return;
+ if (!view || !top || IndexedString(view->document()->url()) != top->url()) {
+ return {};
}
- auto language = ICore::self()->languageController()->languagesForUrl(m_eventualDocument.data()->url()).value(0);
+ auto doc = top->url();
+ auto language = ICore::self()->languageController()->languagesForUrl(doc.toUrl()).value(0);
if (!language) {
- return;
+ return {};
}
+ auto ret = QVector();
qCDebug(LANGUAGE) << "Trying to find assistants for language" << language->name();
- foreach (const auto& assistant, m_registeredAssistants) {
+ foreach (const auto& assistant, d->m_registeredAssistants) {
if (assistant->supportedLanguage() != language)
continue;
- // notify assistant about editor changes
- assistant->textChanged(view, m_eventualRange, m_eventualRemovedText);
-
if (assistant->isUseful()) {
- startAssistant(IAssistant::Ptr(assistant.data()));
- break;
+ qDebug() << "assistant is now useful:" << assistant.data();
+
+ auto p = new KDevelop::StaticAssistantProblem();
+ auto range = assistant->displayRange();
+ qDebug() << "range:" << range;
+ p->setFinalLocation(DocumentRange(doc, range));
+ p->setSource(KDevelop::IProblem::SemanticAnalysis);
+ p->setSeverity(KDevelop::IProblem::Warning);
+ p->setDescription(assistant->title());
+ p->setSolutionAssistant(IAssistant::Ptr(assistant.data()));
+
+ ret.append(KDevelop::Problem::Ptr(p));
}
}
-
- // optimize, esp. for setText() calls as done in e.g. reformat source
- // only start the assitant once for multiple textRemoved/textInserted signals
- m_eventualDocument.clear();
- m_eventualRange = Range::invalid();
- m_eventualRemovedText.clear();
+ return ret;
}
-void StaticAssistantsManager::Private::startAssistant(IAssistant::Ptr assistant)
-{
- if (assistant == m_activeAssistant) {
- return;
- }
-
- qCDebug(LANGUAGE()) << "Starting assistant:" << assistant->title();
-
- 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()->popUpAssistant(IAssistant::Ptr(m_activeAssistant.data()));
-
- m_assistantStartedAt = m_currentView.data()->cursorPosition();
- }
-
- emit q->activeAssistantChanged();
-}
-void StaticAssistantsManager::Private::updateReady(const IndexedString& url, const ReferencedTopDUContext& topContext)
-{
- if (ICore::self()->shuttingDown()) {
- return;
- }
-
- if (url != m_currentDocument) {
- return;
- }
-
- if (m_activeAssistant) {
- if (m_activeProblemAssistant) {
- m_activeAssistant->doHide(); //Hide the assistant, as we will create a new one if the problem is still there
- } else {
- return;
- }
- }
-
- DUChainReadLocker lock(DUChain::lock(), 300);
- if (!lock.locked()) {
- return;
- }
-
- if (topContext) {
- checkAssistantForProblems(topContext);
- }
-}
-
-void StaticAssistantsManager::Private::cursorPositionChanged(View*, const Cursor& pos)
-{
- if (m_activeAssistant && m_assistantStartedAt.isValid()
- && abs(m_assistantStartedAt.line() - pos.line()) >= 1)
- {
- m_activeAssistant->doHide();
- }
-
- m_timer->start();
-}
-
-void StaticAssistantsManager::Private::documentActivated(IDocument* doc)
-{
- if (doc) {
- m_currentDocument = IndexedString(doc->url());
- }
-
- if (m_currentView) {
- QObject::disconnect(m_cursorPositionChangeConnection);
- m_currentView.clear();
- }
-
- m_currentView = ICore::self()->documentController()->activeTextDocumentView();
-
- if (m_currentView) {
- m_cursorPositionChangeConnection = connect(m_currentView.data(),
- &View::cursorPositionChanged, q,
- [&] (View* v, const Cursor& pos) { cursorPositionChanged(v, pos); });
- }
-}
-
-void StaticAssistantsManager::Private::checkAssistantForProblems(TopDUContext* top)
-{
- foreach (ProblemPointer problem, top->problems()) {
- if (m_currentView && m_currentView.data()->cursorPosition().line() == problem->range().start.line) {
- IAssistant::Ptr solution = problem->solutionAssistant();
- if(solution) {
- startAssistant(solution);
- m_activeProblemAssistant = true;
- break;
- }
- }
- }
-}
-
-void StaticAssistantsManager::Private::timeout()
-{
- if (!m_activeAssistant && m_currentView) {
- DUChainReadLocker lock(DUChain::lock(), 300);
- if (!lock.locked()) {
- return;
- }
-
- TopDUContext* top = DUChainUtils::standardContextForUrl(m_currentDocument.toUrl());
- if (top) {
- checkAssistantForProblems(top);
- }
- }
-}
#include "moc_staticassistantsmanager.cpp"
diff --git a/language/duchain/navigation/abstractdeclarationnavigationcontext.cpp b/language/duchain/navigation/abstractdeclarationnavigationcontext.cpp
--- a/language/duchain/navigation/abstractdeclarationnavigationcontext.cpp
+++ b/language/duchain/navigation/abstractdeclarationnavigationcontext.cpp
@@ -281,14 +281,14 @@
QByteArray declarationComment = m_declaration->comment();
if( !shorten && (!declarationComment.isEmpty() || doc) ) {
- modifyHtml() += QStringLiteral("
");
+ modifyHtml() += QStringLiteral("");
if(doc) {
QString comment = doc->description();
connect(doc.data(), &IDocumentation::descriptionChanged, this, &AbstractDeclarationNavigationContext::contentsChanged);
if(!comment.isEmpty()) {
- modifyHtml() += "
" + commentHighlight(comment);
+ modifyHtml() += "
" + commentHighlight(comment) + "
";
}
}
@@ -303,14 +303,15 @@
comment.replace('\n', QLatin1String("
")); //Replicate newlines in html
}
modifyHtml() += commentHighlight(comment);
- modifyHtml() += QStringLiteral("
");
+ modifyHtml() += QStringLiteral("
");
}
}
if(!shorten && doc) {
- modifyHtml() += "
" + i18n("Show documentation for ");
+ modifyHtml() += "" + i18n("Show documentation for ");
makeLink(prettyQualifiedName(m_declaration),
m_declaration, NavigationAction::ShowDocumentation);
+ modifyHtml() += "
";
}
diff --git a/language/duchain/navigation/abstractnavigationcontext.h b/language/duchain/navigation/abstractnavigationcontext.h
--- a/language/duchain/navigation/abstractnavigationcontext.h
+++ b/language/duchain/navigation/abstractnavigationcontext.h
@@ -66,6 +66,9 @@
void nextLink();
void previousLink();
+
+ int linkCount() const;
+
void up();
void down();
void setPrefixSuffix( const QString& prefix, const QString& suffix );
diff --git a/language/duchain/navigation/abstractnavigationcontext.cpp b/language/duchain/navigation/abstractnavigationcontext.cpp
--- a/language/duchain/navigation/abstractnavigationcontext.cpp
+++ b/language/duchain/navigation/abstractnavigationcontext.cpp
@@ -330,6 +330,11 @@
Q_ASSERT(m_selectedLink >= 0);
}
+int AbstractNavigationContext::linkCount() const
+{
+ return m_linkCount;
+}
+
void AbstractNavigationContext::setPrefixSuffix( const QString& prefix, const QString& suffix ) {
m_prefix = prefix;
m_suffix = suffix;
@@ -453,6 +458,7 @@
}
QString AbstractNavigationContext::currentHtml() const {
+
return m_currentText;
}
diff --git a/language/duchain/navigation/abstractnavigationwidget.cpp b/language/duchain/navigation/abstractnavigationwidget.cpp
--- a/language/duchain/navigation/abstractnavigationwidget.cpp
+++ b/language/duchain/navigation/abstractnavigationwidget.cpp
@@ -144,9 +144,19 @@
if(!html.isEmpty()) {
int scrollPos = m_browser->verticalScrollBar()->value();
+ // TODO: Only show that the first time, or the first few times this context is shown?
+ html += QStringLiteral("");
+ if (m_context->linkCount() > 0) {
+ html += i18n("(Hold 'Alt' to show. Navigate via arrow keys, activate by pressing 'Enter')");
+ } else {
+ html += i18n("(Hold 'Alt' to show this tooltip)");
+ }
+ html += QStringLiteral("
");
+
m_browser->setHtml( html );
m_currentText = html;
+
m_idealTextSize = QSize();
QSize hint = sizeHint();
diff --git a/language/duchain/navigation/problemnavigationcontext.h b/language/duchain/navigation/problemnavigationcontext.h
--- a/language/duchain/navigation/problemnavigationcontext.h
+++ b/language/duchain/navigation/problemnavigationcontext.h
@@ -20,6 +20,8 @@
#define KDEVPLATFORM_PROBLEMNAVIGATIONCONTEXT_H
#include
+#include
+
#include
#include
#include
@@ -30,18 +32,31 @@
{
Q_OBJECT
public:
- explicit ProblemNavigationContext(const IProblem::Ptr& problem);
+ enum Flag {
+ NoFlag = 0,
+ ShowLocation = 1 << 0,
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ explicit ProblemNavigationContext(const IProblem::Ptr& problem, const Flags flags = {});
~ProblemNavigationContext() override;
QString name() const override;
QString html(bool shorten = false) override;
QWidget* widget() const override;
bool isWidgetMaximized() const override;
+ NavigationContextPointer executeKeyAction(QString key) override;
+
+public slots:
+ void executeAction(int index); // TODO: Add API in base class?
+
private:
IProblem::Ptr m_problem;
+ Flags m_flags;
QPointer m_widget;
+ IAssistant::Ptr m_cachedAssistant; // cache assistant, calling IAssistant::solutionAssistant() might be expensive
};
}
diff --git a/language/duchain/navigation/problemnavigationcontext.cpp b/language/duchain/navigation/problemnavigationcontext.cpp
--- a/language/duchain/navigation/problemnavigationcontext.cpp
+++ b/language/duchain/navigation/problemnavigationcontext.cpp
@@ -17,47 +17,61 @@
*/
#include "problemnavigationcontext.h"
+#include
+#include
+
+#include "util/debug.h"
#include
#include
+#include
+#include
#include
#include
#include
#include
#include
-#include
#include
+#include
+
using namespace KDevelop;
-ProblemNavigationContext::ProblemNavigationContext(const IProblem::Ptr& problem)
+namespace {
+
+QString KEY_INVOKE_ACTION(int num) { return QString("invoke_action_%1").arg(num); }
+
+QString iconForSeverity(IProblem::Severity severity)
+{
+ switch (severity) {
+ case IProblem::Hint:
+ return QStringLiteral("dialog-information");
+ case IProblem::Warning:
+ return QStringLiteral("dialog-warning");
+ case IProblem::Error:
+ return QStringLiteral("dialog-error");
+ }
+ return {};
+}
+
+QString htmlImg(const QString& iconName, KIconLoader::Group group)
+{
+ KIconLoader loader;
+ const int size = loader.currentSize(group);
+ return QString::fromLatin1("")
+ .arg(size)
+ .arg(loader.iconPath(iconName, group));
+}
+
+}
+
+ProblemNavigationContext::ProblemNavigationContext(const IProblem::Ptr& problem, const Flags flags)
: m_problem(problem)
+ , m_flags(flags)
, m_widget(nullptr)
{
- QExplicitlySharedDataPointer< IAssistant > solution = problem->solutionAssistant();
- if(solution && !solution->actions().isEmpty()) {
- m_widget = new QWidget;
- QHBoxLayout* layout = new QHBoxLayout(m_widget);
- RichTextPushButton* button = new RichTextPushButton;
-// button->setPopupMode(QToolButton::InstantPopup);
- if(!solution->title().isEmpty())
- button->setHtml(i18n("Solve: %1", solution->title()));
- else
- button->setHtml(i18n("Solve"));
-
- QMenu* menu = new QMenu;
- menu->setFocusPolicy(Qt::NoFocus);
- foreach(IAssistantAction::Ptr action, solution->actions()) {
- menu->addAction(action->toKAction(this));
- }
- button->setMenu(menu);
-
- layout->addWidget(button);
- layout->setAlignment(button, Qt::AlignLeft);
- m_widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
- }
}
ProblemNavigationContext::~ProblemNavigationContext()
@@ -80,49 +94,129 @@
return i18n("Problem");
}
-
QString ProblemNavigationContext::html(bool shorten)
{
clear();
m_shorten = shorten;
- modifyHtml() += QStringLiteral("");
+ auto iconPath = iconForSeverity(m_problem->severity());
- modifyHtml() += i18n("Problem in %1:
", m_problem->sourceString());
- modifyHtml() += m_problem->description().toHtmlEscaped();
+ modifyHtml() += QStringLiteral("
");
+
+ modifyHtml() += QStringLiteral("%1 | ").arg(htmlImg(iconPath, KIconLoader::Panel));
+
+ // BEGIN: right column
+ modifyHtml() += QStringLiteral("");
+
+ modifyHtml() += i18n("Problem in %1", m_problem->sourceString());
modifyHtml() += QStringLiteral(" ");
- modifyHtml() += "" + m_problem->explanation().toHtmlEscaped() + "";
+
+ if (m_flags & ShowLocation) {
+ const auto duchainProblem = dynamic_cast(m_problem.data());
+ if (duchainProblem) {
+ modifyHtml() += labelHighlight(i18n("Location: "));
+ makeLink(QStringLiteral("%1 :%2")
+ .arg(duchainProblem->finalLocation().document.toUrl().fileName())
+ .arg(duchainProblem->rangeInCurrentRevision().start().line() + 1),
+ QString(),
+ NavigationAction(duchainProblem->finalLocation().document.toUrl(), duchainProblem->finalLocation().start())
+ );
+ modifyHtml() += QStringLiteral(" ");
+ }
+ }
+
+ modifyHtml() += m_problem->description().toHtmlEscaped();
+ if ( !m_problem->explanation().isEmpty() ) {
+ modifyHtml() += "" + m_problem->explanation().toHtmlEscaped() + " ";
+ }
+
+ modifyHtml() += QStringLiteral(" | ");
+ // END: right column
+
+ modifyHtml() += QStringLiteral("
");
const QVector diagnostics = m_problem->diagnostics();
if (!diagnostics.isEmpty()) {
- modifyHtml() += QStringLiteral("
");
DUChainReadLocker lock;
for (auto diagnostic : diagnostics) {
+ modifyHtml() += QStringLiteral("");
modifyHtml() += labelHighlight(QStringLiteral("%1: ").arg(diagnostic->severityString()));
modifyHtml() += diagnostic->description();
const DocumentRange range = diagnostic->finalLocation();
Declaration* declaration = DUChainUtils::itemUnderCursor(range.document.toUrl(), range.start());
if (declaration) {
- modifyHtml() += i18n("
See: ");
+ modifyHtml() += i18n("
See: ");
makeLink(declaration->toString(), DeclarationPointer(declaration), NavigationAction::NavigateDeclaration);
modifyHtml() += i18n(" in ");
makeLink(QStringLiteral("%1 :%2")
.arg(declaration->url().toUrl().fileName())
.arg(declaration->rangeInCurrentRevision().start().line() + 1),
DeclarationPointer(declaration), NavigationAction::NavigateDeclaration);
} else if (range.start().isValid()) {
- modifyHtml() += i18n("
See: ");
+ modifyHtml() += i18n("
See: ");
const auto url = range.document.toUrl();
makeLink(QStringLiteral("%1 :%2")
.arg(url.fileName())
.arg(range.start().line() + 1),
url.toDisplayString(QUrl::PreferLocalFile), NavigationAction(url, range.start()));
}
- modifyHtml() += QStringLiteral("
");
+ modifyHtml() += QStringLiteral("
");
}
}
- modifyHtml() += QStringLiteral("");
+ if (!m_cachedAssistant) {
+ m_cachedAssistant = m_problem->solutionAssistant();
+ }
+ auto assistant = m_cachedAssistant;
+ if (assistant && !assistant->actions().isEmpty()) {
+ modifyHtml() += QString::fromLatin1("").arg("#b3d4ff");
+
+ modifyHtml() += QStringLiteral("%1 | ").arg(htmlImg(QStringLiteral("dialog-ok-apply"), KIconLoader::Panel));
+ int index = 0;
+ foreach (auto assistantAction, assistant->actions()) {
+ if (index != 0) {
+ modifyHtml() += " ";
+ }
+ makeLink(i18n("Solution (%1)", index + 1), KEY_INVOKE_ACTION(index),
+ NavigationAction(KEY_INVOKE_ACTION(index)));
+ modifyHtml() += ": " + assistantAction->description().toHtmlEscaped();
+ ++index;
+ }
+ modifyHtml() += " |
";
+ modifyHtml() += QStringLiteral("
");
+ }
+
return currentHtml();
}
+
+NavigationContextPointer ProblemNavigationContext::executeKeyAction(QString key)
+{
+ auto assistant = m_cachedAssistant;
+ if (!assistant)
+ return {};
+ if (key.startsWith(QLatin1String("invoke_action_"))) {
+ const auto index = key.replace(QLatin1String("invoke_action_"), QString()).toInt();
+ executeAction(index);
+ }
+
+ return {};
+}
+
+void ProblemNavigationContext::executeAction(int index)
+{
+ auto assistant = m_problem->solutionAssistant();
+ if (!assistant)
+ return;
+
+ auto action = assistant->actions().value(index);
+ if (action) {
+ action->execute();
+ if ( topContext() ) {
+ DUChain::self()->updateContextForUrl(topContext()->url(), TopDUContext::ForceUpdate);
+ }
+ } else {
+ qCWarning(LANGUAGE()) << "No such action";
+ return;
+ }
+}
diff --git a/language/duchain/problem.h b/language/duchain/problem.h
--- a/language/duchain/problem.h
+++ b/language/duchain/problem.h
@@ -32,6 +32,7 @@
#include
#include "indexedtopducontext.h"
#include
+#include
namespace KDevelop
{
@@ -237,6 +238,19 @@
//END dynamic data
};
+class KDEVPLATFORMLANGUAGE_EXPORT StaticAssistantProblem : public KDevelop::Problem {
+ public:
+ KDevelop::IAssistant::Ptr solutionAssistant() const override {
+ return m_solution;
+ }
+ void setSolutionAssistant(KDevelop::IAssistant::Ptr p) {
+ m_solution = p;
+ }
+
+ private:
+ KDevelop::IAssistant::Ptr m_solution;
+};
+
}
Q_DECLARE_TYPEINFO(KDevelop::LocalIndexedProblem, Q_MOVABLE_TYPE);
diff --git a/plugins/contextbrowser/browsemanager.h b/plugins/contextbrowser/browsemanager.h
--- a/plugins/contextbrowser/browsemanager.h
+++ b/plugins/contextbrowser/browsemanager.h
@@ -90,6 +90,7 @@
//Emitted when browsing was started using the magic-modifier
void startDelayedBrowsing(KTextEditor::View* view);
void stopDelayedBrowsing();
+ void invokeAction(int index);
public slots:
///Enabled/disables the browsing mode
void setBrowsing(bool);
diff --git a/plugins/contextbrowser/browsemanager.cpp b/plugins/contextbrowser/browsemanager.cpp
--- a/plugins/contextbrowser/browsemanager.cpp
+++ b/plugins/contextbrowser/browsemanager.cpp
@@ -193,6 +193,16 @@
}
}
+ if (keyEvent && m_browsingByKey && m_browsingStartedInView && keyEvent->type() == QEvent::KeyPress) {
+ if (keyEvent->key() >= Qt::Key_1 && keyEvent->key() <= Qt::Key_9) {
+ // user wants to trigger an action in the code browser
+ const int index = keyEvent->key() - Qt::Key_1;
+ emit invokeAction(index);
+ stopDelayedBrowsing();
+ return true;
+ }
+ }
+
if(!view) {
return false;
}
diff --git a/plugins/contextbrowser/contextbrowser.h b/plugins/contextbrowser/contextbrowser.h
--- a/plugins/contextbrowser/contextbrowser.h
+++ b/plugins/contextbrowser/contextbrowser.h
@@ -35,6 +35,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -125,6 +126,7 @@
void startDelayedBrowsing(KTextEditor::View* view);
void stopDelayedBrowsing();
+ void invokeAction(int index);
void previousUseShortcut();
void nextUseShortcut();
@@ -170,6 +172,7 @@
QWidget* toolbarWidgetForMainWindow(Sublime::MainWindow* window);
void createActionsForMainWindow(Sublime::MainWindow* window, QString& xmlFile,
KActionCollection& actions) override;
+ QWidget* navigationWidgetForPosition(KTextEditor::View* view, KTextEditor::Cursor position);
void switchUse(bool forward);
void clearMouseHover();
@@ -224,6 +227,7 @@
QPointer m_currentToolTip;
QPointer m_currentNavigationWidget;
KDevelop::IndexedDeclaration m_currentToolTipDeclaration;
+ KDevelop::Problem::Ptr m_currentToolTipProblem;
QAction* m_findUses;
QPointer m_lastInsertionDocument;
diff --git a/plugins/contextbrowser/contextbrowser.cpp b/plugins/contextbrowser/contextbrowser.cpp
--- a/plugins/contextbrowser/contextbrowser.cpp
+++ b/plugins/contextbrowser/contextbrowser.cpp
@@ -67,6 +67,7 @@
#include
#include
#include
+#include
#include
@@ -195,6 +196,8 @@
this, &ContextBrowserPlugin::startDelayedBrowsing);
connect(m_browseManager, &BrowseManager::stopDelayedBrowsing,
this, &ContextBrowserPlugin::stopDelayedBrowsing);
+ connect(m_browseManager, &BrowseManager::invokeAction,
+ this, &ContextBrowserPlugin::invokeAction);
m_toolbarWidget = toolbarWidgetForMainWindow(window);
m_toolbarWidgetLayout = new QHBoxLayout;
@@ -405,6 +408,20 @@
hideToolTip();
}
+void ContextBrowserPlugin::invokeAction(int index)
+{
+ if (!m_currentNavigationWidget)
+ return;
+
+
+ auto navigationWidget = qobject_cast(m_currentNavigationWidget);
+ if (!navigationWidget)
+ return;
+
+ // TODO: Add API in AbstractNavigation{Widget,Context}?
+ QMetaObject::invokeMethod(navigationWidget->context().data(), "executeAction", Q_ARG(int, index));
+}
+
void ContextBrowserPlugin::startDelayedBrowsing(KTextEditor::View* view) {
if(!m_currentToolTip) {
showToolTip(view, view->cursorPosition());
@@ -416,45 +433,141 @@
m_currentToolTip->deleteLater();
m_currentToolTip = 0;
m_currentNavigationWidget = 0;
+ m_currentToolTipProblem = {};
+ m_currentToolTipDeclaration = {};
}
}
-void ContextBrowserPlugin::showToolTip(KTextEditor::View* view, KTextEditor::Cursor position) {
+static ProblemPointer findProblemUnderCursor(const TopDUContext* topContext, KTextEditor::Cursor position)
+{
+ foreach (auto problem, topContext->problems()) {
+ if (problem->rangeInCurrentRevision().contains(position)) {
+ return problem;
+ }
+ }
- ContextBrowserView* contextView = browserViewForWidget(view);
- if(contextView && contextView->isVisible() && !contextView->isLocked())
- return; // If the context-browser view is visible, it will care about updating by itself
+ return {};
+}
+
+static ProblemPointer findProblemCloseToCursor(const TopDUContext* topContext, KTextEditor::Cursor position, KTextEditor::View* view)
+{
+ auto problems = topContext->problems();
+ if (problems.isEmpty())
+ return {};
+
+ auto closestProblem = std::min_element(problems.constBegin(), problems.constEnd(),
+ [position](const ProblemPointer& a, const ProblemPointer& b) {
+ const auto aRange = a->rangeInCurrentRevision();
+ const auto bRange = b->rangeInCurrentRevision();
+
+ const auto aLineDistance = qMin(qAbs(aRange.start().line() - position.line()),
+ qAbs(aRange.end().line() - position.line()));
+ const auto bLineDistance = qMin(qAbs(bRange.start().line() - position.line()),
+ qAbs(bRange.end().line() - position.line()));
+ if (aLineDistance != bLineDistance) {
+ return aLineDistance < bLineDistance;
+ }
+
+ if (aRange.start().line() == bRange.start().line()) {
+ return qAbs(aRange.start().column() - position.column()) <
+ qAbs(bRange.start().column() - position.column());
+ }
+ return qAbs(aRange.end().column() - position.column()) <
+ qAbs(bRange.end().column() - position.column());
+ });
+
+ auto r = (*closestProblem)->rangeInCurrentRevision();
+ if (!r.contains(position)) {
+ if (r.start().line() == position.line() || r.end().line() == position.line()) {
+ // problem is on the same line, let's use it
+ return *closestProblem;
+ }
+ // if not, only show it in case there's only whitespace between the current cursor pos and the problem
+ auto dist = position < r.start() ? KTextEditor::Range(position, r.start()) : KTextEditor::Range(r.end(), position);
+ auto textBetween = view->document()->text(dist);
+ auto isSpace = std::all_of(textBetween.begin(), textBetween.end(), [](QChar c) { return c.isSpace(); });
+ if (!isSpace) {
+ return {};
+ }
+ }
+
+ return *closestProblem;
+}
+
+QWidget* ContextBrowserPlugin::navigationWidgetForPosition(KTextEditor::View* view, KTextEditor::Cursor position)
+{
QUrl viewUrl = view->document()->url();
auto languages = ICore::self()->languageController()->languagesForUrl(viewUrl);
- QWidget* navigationWidget = 0;
- {
- DUChainReadLocker lock(DUChain::lock());
- foreach (const auto language, languages) {
- auto widget = language->specialLanguageObjectNavigationWidget(viewUrl, KTextEditor::Cursor(position));
- navigationWidget = qobject_cast(widget);
- if(navigationWidget)
- break;
- }
+ DUChainReadLocker lock(DUChain::lock());
+ foreach (const auto language, languages) {
+ auto widget = language->specialLanguageObjectNavigationWidget(viewUrl, KTextEditor::Cursor(position));
+ auto navigationWidget = qobject_cast(widget);
+ if(navigationWidget)
+ return navigationWidget;
+ }
- if(!navigationWidget) {
- Declaration* decl = DUChainUtils::declarationForDefinition( DUChainUtils::itemUnderCursor(viewUrl, KTextEditor::Cursor(position)) );
- if (decl && decl->kind() == Declaration::Alias) {
- AliasDeclaration* alias = dynamic_cast(decl);
- Q_ASSERT(alias);
- DUChainReadLocker lock;
- decl = alias->aliasedDeclaration().declaration();
+ TopDUContext* topContext = DUChainUtils::standardContextForUrl(view->document()->url());
+ if (topContext) {
+ // first pass: find problems under the cursor
+ const auto problem = findProblemUnderCursor(topContext, position);
+ if (problem) {
+ if (problem == m_currentToolTipProblem && m_currentToolTip) {
+ return nullptr;
}
- if(decl) {
- if(m_currentToolTipDeclaration == IndexedDeclaration(decl) && m_currentToolTip)
- return;
- m_currentToolTipDeclaration = IndexedDeclaration(decl);
- navigationWidget = decl->context()->createNavigationWidget(decl, DUChainUtils::standardContextForUrl(viewUrl));
+
+ m_currentToolTipProblem = problem;
+ auto widget = new AbstractNavigationWidget;
+ auto context = new ProblemNavigationContext(problem);
+ context->setTopContext(TopDUContextPointer(topContext));
+ widget->setContext(NavigationContextPointer(context));
+ return widget;
+ }
+ }
+
+ auto declUnderCursor = DUChainUtils::itemUnderCursor(viewUrl, position);
+ Declaration* decl = DUChainUtils::declarationForDefinition(declUnderCursor);
+ if (decl && decl->kind() == Declaration::Alias) {
+ AliasDeclaration* alias = dynamic_cast(decl);
+ Q_ASSERT(alias);
+ DUChainReadLocker lock;
+ decl = alias->aliasedDeclaration().declaration();
+ }
+ if(decl) {
+ if(m_currentToolTipDeclaration == IndexedDeclaration(decl) && m_currentToolTip)
+ return nullptr;
+
+ m_currentToolTipDeclaration = IndexedDeclaration(decl);
+ return decl->context()->createNavigationWidget(decl, DUChainUtils::standardContextForUrl(viewUrl));
+ }
+
+ if (topContext) {
+ // second pass: find closest problem to the cursor
+ const auto problem = findProblemCloseToCursor(topContext, position, view);
+ if (problem) {
+ if (problem == m_currentToolTipProblem && m_currentToolTip) {
+ return nullptr;
}
+
+ m_currentToolTipProblem = problem;
+ auto widget = new AbstractNavigationWidget;
+ // since the problem is not under cursor: show location
+ widget->setContext(NavigationContextPointer(new ProblemNavigationContext(problem, ProblemNavigationContext::ShowLocation)));
+ return widget;
}
}
+ return nullptr;
+}
+
+void ContextBrowserPlugin::showToolTip(KTextEditor::View* view, KTextEditor::Cursor position) {
+
+ ContextBrowserView* contextView = browserViewForWidget(view);
+ if(contextView && contextView->isVisible() && !contextView->isLocked())
+ return; // If the context-browser view is visible, it will care about updating by itself
+
+ auto navigationWidget = navigationWidgetForPosition(view, position);
if(navigationWidget) {
// If we have an invisible context-view, assign the tooltip navigation-widget to it.
@@ -472,7 +585,8 @@
KTextEditor::Range itemRange;
{
DUChainReadLocker lock;
- itemRange = DUChainUtils::itemRangeUnderCursor(viewUrl, KTextEditor::Cursor(position));
+ auto viewUrl = view->document()->url();
+ itemRange = DUChainUtils::itemRangeUnderCursor(viewUrl, position);
}
tooltip->setHandleRect(KTextEditorHelpers::getItemBoundingRect(view, itemRange));
tooltip->resize( navigationWidget->sizeHint() + QSize(10, 10) );
diff --git a/plugins/problemreporter/problemhighlighter.h b/plugins/problemreporter/problemhighlighter.h
--- a/plugins/problemreporter/problemhighlighter.h
+++ b/plugins/problemreporter/problemhighlighter.h
@@ -26,23 +26,8 @@
#include
#include
#include
-#include
#include
-class ProblemHighlighter;
-
-class ProblemTextHintProvider : public KTextEditor::TextHintProvider
-{
-public:
- explicit ProblemTextHintProvider(ProblemHighlighter* highlighter);
-
- QString textHint(KTextEditor::View* view, const KTextEditor::Cursor& position) override;
-
-private:
- ProblemHighlighter* m_highlighter;
- KTextEditor::Range m_currentHintRange;
-};
-
class ProblemHighlighter : public QObject
{
Q_OBJECT
@@ -53,7 +38,6 @@
void setProblems(const QVector& problems);
private slots:
- void viewCreated(KTextEditor::Document*, KTextEditor::View*);
void aboutToRemoveText(const KTextEditor::Range& range);
void clearProblems();
@@ -63,9 +47,6 @@
QVector m_problems;
QMap m_problemsForRanges;
- friend class ProblemTextHintProvider;
- ProblemTextHintProvider m_textHintProvider;
-
public slots:
void settingsChanged();
};
diff --git a/plugins/problemreporter/problemhighlighter.cpp b/plugins/problemreporter/problemhighlighter.cpp
--- a/plugins/problemreporter/problemhighlighter.cpp
+++ b/plugins/problemreporter/problemhighlighter.cpp
@@ -24,7 +24,6 @@
#include
#include
-#include
#include
#include
@@ -67,14 +66,9 @@
ProblemHighlighter::ProblemHighlighter(KTextEditor::Document* document)
: m_document(document)
- , m_textHintProvider(this)
{
Q_ASSERT(m_document);
- foreach (KTextEditor::View* view, m_document->views())
- viewCreated(document, view);
-
- connect(m_document.data(), &Document::viewCreated, this, &ProblemHighlighter::viewCreated);
connect(ICore::self()->languageController()->completionSettings(), &ICompletionSettings::settingsChanged, this,
&ProblemHighlighter::settingsChanged);
connect(m_document.data(), &Document::aboutToReload, this, &ProblemHighlighter::clearProblems);
@@ -93,55 +87,6 @@
setProblems(m_problems);
}
-void ProblemHighlighter::viewCreated(Document*, View* view)
-{
- KTextEditor::TextHintInterface* iface = dynamic_cast(view);
- if (!iface)
- return;
-
- iface->registerTextHintProvider(&m_textHintProvider);
-}
-
-ProblemTextHintProvider::ProblemTextHintProvider(ProblemHighlighter* highlighter)
- : m_highlighter(highlighter)
-{
-}
-
-QString ProblemTextHintProvider::textHint(View* view, const Cursor& pos)
-{
- KTextEditor::MovingInterface* moving = dynamic_cast(view->document());
- if (moving) {
- ///@todo Sort the ranges when writing them, and do binary search instead of linear
- foreach (MovingRange* range, m_highlighter->m_topHLRanges) {
- if (m_highlighter->m_problemsForRanges.contains(range) && range->contains(pos)) {
- // There is a problem which's range contains the cursor
- IProblem::Ptr problem = m_highlighter->m_problemsForRanges[range];
- if (problem->source() == IProblem::ToDo) {
- continue;
- }
-
- if (m_currentHintRange == range->toRange()) {
- continue;
- }
- m_currentHintRange = range->toRange();
-
- KDevelop::AbstractNavigationWidget* widget = new KDevelop::AbstractNavigationWidget;
- widget->setContext(NavigationContextPointer(new ProblemNavigationContext(problem)));
-
- KDevelop::NavigationToolTip* tooltip
- = new KDevelop::NavigationToolTip(view, QCursor::pos() + QPoint(20, 40), widget);
-
- tooltip->resize(widget->sizeHint() + QSize(10, 10));
- tooltip->setHandleRect(KTextEditorHelpers::getItemBoundingRect(view, m_currentHintRange));
- tooltip->connect(tooltip, &ActiveToolTip::destroyed, [&] () { m_currentHintRange = {}; });
- ActiveToolTip::showToolTip(tooltip, 99, QStringLiteral("problem-tooltip"));
- return QString();
- }
- }
- }
- return QString();
-}
-
ProblemHighlighter::~ProblemHighlighter()
{
if (m_topHLRanges.isEmpty() || !m_document)
@@ -152,6 +97,7 @@
void ProblemHighlighter::setProblems(const QVector& problems)
{
+ qDebug() << "updating problem highlight";
if (!m_document)
return;
diff --git a/plugins/problemreporter/problemreporterplugin.cpp b/plugins/problemreporter/problemreporterplugin.cpp
--- a/plugins/problemreporter/problemreporterplugin.cpp
+++ b/plugins/problemreporter/problemreporterplugin.cpp
@@ -44,6 +44,7 @@
#include "problemhighlighter.h"
#include "problemtreeview.h"
#include "problemreportermodel.h"
+#include "language/assistant/staticassistantsmanager.h"
#include
#include
#include
@@ -128,17 +129,29 @@
{
Q_ASSERT(document->textDocument());
m_highlighters.insert(IndexedString(document->url()), new ProblemHighlighter(document->textDocument()));
- DUChainReadLocker lock(DUChain::lock());
DUChain::self()->updateContextForUrl(IndexedString(document->url()),
KDevelop::TopDUContext::AllDeclarationsContextsAndUses, this);
}
-void ProblemReporterPlugin::updateReady(const IndexedString& url, const KDevelop::ReferencedTopDUContext&)
+void ProblemReporterPlugin::updateReady(const IndexedString& url, const KDevelop::ReferencedTopDUContext& top)
{
+ {
+ DUChainWriteLocker lock(DUChain::lock(), 300);
+ if ( !lock.locked() ) {
+ return;
+ }
+ ICore::self()->languageController()->staticAssistantsManager()->notifyAssistants(url, top);
+ auto assistantProblems = ICore::self()->languageController()->staticAssistantsManager()->problemsForContext(top);
+ Q_FOREACH ( const auto p, assistantProblems ) {
+ qDebug() << "adding problem:" << p << "assistant:" << p->solutionAssistant().data() << p->solutionAssistant()->actions().size();
+ top->addProblem(p);
+ }
+ }
+
m_model->problemsUpdated(url);
ProblemHighlighter* ph = m_highlighters.value(url);
if (ph) {
- QVector allProblems = m_model->problems(url, false);
+ auto allProblems = m_model->problems(url, false);
ph->setProblems(allProblems);
}
}
diff --git a/shell/AssistantButton.qml b/shell/AssistantButton.qml
deleted file mode 100644
--- a/shell/AssistantButton.qml
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- Copyright 2014 Sven Brauch
- Copyright 2014 Kevin Funk
-
- 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.
-*/
-
-import QtQuick 2.2
-
-// Component which provides a single button for the assistant widget.
-
-Rectangle {
- id: root
-
- property color foreground
- property color background
- property color highlight
-
- property bool highlighted: false
- // text on the button
- property string text
- // text in the shortcut field
- property int button
- // emitted when the button is clicked with the mouse
- signal triggered()
-
- y: -1
- width: text.width + 4
- height: number.height + 4
-
- color: Qt.lighter(root.background, 1.5)
- border.color: Qt.lighter(root.foreground, 1.5)
-
- Behavior on opacity {
- NumberAnimation { duration: 150; }
- }
- MouseArea {
- id: mouseArea
-
- anchors.fill: parent
- onClicked: root.triggered()
-
- hoverEnabled: true
-
- Row {
- // row containing the separators, shortcut text, and button text
- z: 3
- id: text
- anchors.centerIn: parent
- spacing: 0
- Rectangle { width: 2; height: 1; color: Qt.rgba(0, 0, 0, 0) } // padding
- Text {
- // shortcut key
- anchors.verticalCenter: parent.verticalCenter
- anchors.verticalCenterOffset: 1
- id: number
- color: root.foreground
- text: button
- z: 2
- }
- Rectangle { width: 3; height: 1; color: Qt.rgba(0, 0, 0, 0) } // padding
- Rectangle { y: 1; width: 1; color: root.foreground; height: root.height - 1; opacity: 0.3 } // line
- Rectangle { width: 4; height: 1; color: Qt.rgba(0, 0, 0, 0) } // padding
- Text {
- // actual button text
- anchors.verticalCenter: parent.verticalCenter
- anchors.verticalCenterOffset: 1
- color: root.foreground
- text: root.text
- textFormat: Text.PlainText
- }
- Rectangle { width: 2; height: 1; color: Qt.rgba(0, 0, 0, 0) } // padding
- }
- Rectangle {
- // the background color for the shortcut key box, invisible by default.
- id: highlightArea
- Behavior on opacity {
- NumberAnimation { duration: 200 }
- }
- opacity: (root.highlighted || mouseArea.containsMouse) ? 0.5 : 0.0
- x: 1
- y: 1
- z: 1
- height: text.height
- width: number.width + 6
- color: root.highlight
- }
- }
-}
diff --git a/shell/CMakeLists.txt b/shell/CMakeLists.txt
--- a/shell/CMakeLists.txt
+++ b/shell/CMakeLists.txt
@@ -11,7 +11,6 @@
workingsets/workingsetwidget.cpp
workingsets/closedworkingsetswidget.cpp
workingsets/workingsethelpers.cpp
- assistantpopup.cpp
mainwindow.cpp
mainwindow_p.cpp
plugincontroller.cpp
@@ -171,5 +170,3 @@
filteredproblemstore.h
DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kdevplatform/shell COMPONENT Devel
)
-
-install( FILES AssistantButton.qml assistantpopup.qml DESTINATION ${KDE_INSTALL_DATADIR}/kdevelop )
diff --git a/shell/assistantpopup.h b/shell/assistantpopup.h
deleted file mode 100644
--- a/shell/assistantpopup.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- Copyright 2009 David Nolden
- Copyright 2012 Milian Wolff
- Copyright 2014 Sven Brauch
- Copyright 2014 Kevin Funk
-
- 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 KDEVPLATFORM_ASSISTANTPOPUP_H
-#define KDEVPLATFORM_ASSISTANTPOPUP_H
-
-#include
-#include
-#include
-
-namespace KTextEditor
-{
-class View;
-class Cursor;
-}
-
-class AssistantPopupConfig : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(QColor foreground READ foreground NOTIFY colorsChanged)
- Q_PROPERTY(QColor background READ background NOTIFY colorsChanged)
- Q_PROPERTY(QColor highlight READ highlight NOTIFY colorsChanged)
-
- Q_PROPERTY(QString title READ title NOTIFY titleChanged)
- Q_PROPERTY(QList model READ model NOTIFY modelChanged)
- Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged)
- Q_PROPERTY(QSize viewSize READ viewSize WRITE setViewSize NOTIFY viewSizeChanged)
-
-public:
- explicit AssistantPopupConfig(QObject *parent = nullptr);
-
- QColor foreground() const { return m_foreground; }
- QColor background() const { return m_background; }
- QColor highlight() const { return m_highlight; }
-
- QSize viewSize() const { return m_viewSize; };
- void setViewSize(const QSize &size);
-
- QString title() const { return m_title; }
- void setTitle(const QString& title);
- QList model() const { return m_model; }
- void setModel(const QList& model);
-
- void setColorsFromView(QObject *view);
-
- bool isActive() const;
- void setActive(bool active);
-
-signals:
- void colorsChanged();
-
- void titleChanged(const QString& title);
- void modelChanged(const QList& model);
- void activeChanged(bool active);
- void viewSizeChanged(const QSize& size);
-
-private:
- QColor m_foreground;
- QColor m_background;
- QColor m_highlight;
-
- QString m_title;
- QList m_model;
- bool m_active;
- QSize m_viewSize;
-};
-
-Q_DECLARE_METATYPE(AssistantPopupConfig*)
-
-class AssistantPopup : public QQuickWidget
-{
- Q_OBJECT
-
-public:
- typedef QExplicitlySharedDataPointer Ptr;
-
- /**
- * The current main window will be used as parent widget for the popup.
- * This is to make use of the maximal space available and prevent any lines
- * in e.g. the editor to be hidden by the popup.
- */
- AssistantPopup();
-
- /**
- * Reset this popup for view @p view and show assistant @p assistant
- *
- * @p view The widget below which the assistant should be shown.
- */
- void reset(KTextEditor::View *view, const KDevelop::IAssistant::Ptr &assistant);
-
- KDevelop::IAssistant::Ptr assistant() const;
-
-private slots:
- void updatePosition(KTextEditor::View* view, const KTextEditor::Cursor& newPos);
- void updateState();
- void updateLayout();
-
- void executeHideAction();
- void hideAssistant();
-
-protected:
- bool eventFilter(QObject* object, QEvent* event) override;
-
-private:
- void setView(KTextEditor::View* view);
- void setAssistant(const KDevelop::IAssistant::Ptr& assistant);
- void setActive( bool active );
-
- KDevelop::IAssistant::Ptr m_assistant;
- QPointer m_view;
- AssistantPopupConfig* m_config;
- QList m_shortcuts;
- bool m_firstLayoutCompleted;
-};
-
-#endif // KDEVPLATFORM_ASSISTANTPOPUP_H
diff --git a/shell/assistantpopup.cpp b/shell/assistantpopup.cpp
deleted file mode 100644
--- a/shell/assistantpopup.cpp
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- Copyright 2009 David Nolden
- Copyright 2012 Milian Wolff
- Copyright 2014 Sven Brauch
- Copyright 2014 Kevin Funk
-
- 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 "assistantpopup.h"
-#include "sublime/holdupdates.h"
-#include "util/kdevstringhandler.h"
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-
-using namespace KDevelop;
-
-namespace {
-
-const int ASSISTANT_MODIFIER =
-#ifdef Q_OS_MAC
-Qt::CTRL;
-#else
-Qt::ALT;
-#endif
-
-const int ASSISTANT_MOD_KEY =
-#ifdef Q_OS_MAC
-Qt::Key_Control;
-#else
-Qt::Key_Alt;
-#endif
-
-QWidget* findByClassname(const KTextEditor::View* view, const QString& klass)
-{
- auto children = view->findChildren();
- foreach ( auto child, children ) {
- if ( child->metaObject()->className() == klass ) {
- return child;
- }
- }
- return nullptr;
-};
-
-/**
- * @brief Get the geometry of the inner part (with the text) of the KTextEditor::View being used.
- */
-QRect textWidgetGeometry(const KTextEditor::View *view)
-{
- // Subtract the width of the right scrollbar
- int scrollbarWidth = 0;
- if ( auto scrollbar = findByClassname(view, QStringLiteral("KateScrollBar")) ) {
- scrollbarWidth = scrollbar->width();
- }
- // Subtract the width of the bottom scrollbar
- int bottomScrollbarWidth = 0;
- if ( auto bottom = findByClassname(view, QStringLiteral("QScrollBar")) ) {
- bottomScrollbarWidth = bottom->height();
- }
- auto geom = view->geometry();
-
- geom.adjust(0, 0, -scrollbarWidth, -bottomScrollbarWidth);
- return geom;
-}
-
-}
-
-AssistantPopupConfig::AssistantPopupConfig(QObject *parent)
- : QObject(parent)
- , m_active(false)
-{
-}
-
-void AssistantPopupConfig::setColorsFromView(QObject *view)
-{
- auto iface = dynamic_cast(view);
- Q_ASSERT(iface);
- m_foreground = iface->configValue(QStringLiteral("line-number-color")).value();
- m_background = iface->configValue(QStringLiteral("icon-border-color")).value();
- m_highlight = iface->configValue(QStringLiteral("folding-marker-color")).value();
- if ( KColorUtils::luma(m_background) < 0.3 ) {
- m_foreground = KColorUtils::lighten(m_foreground, 0.7);
- }
- const float lumaDiff = KColorUtils::luma(m_highlight) - KColorUtils::luma(m_background);
- if ( qAbs(lumaDiff) < 0.5 ) {
- m_highlight = QColor::fromHsv(m_highlight.hue(),
- qMin(255, m_highlight.saturation() + 80),
- lumaDiff > 0 ? qMin(255, m_highlight.value() + 120)
- : qMax(80, m_highlight.value() - 40));
- }
- emit colorsChanged();
-}
-
-bool AssistantPopupConfig::isActive() const
-{
- return m_active;
-}
-
-void AssistantPopupConfig::setActive(bool active)
-{
- if (m_active == active) {
- return;
- }
-
- m_active = active;
- emit activeChanged(m_active);
-}
-
-void AssistantPopupConfig::setViewSize(const QSize& size)
-{
- if (size != m_viewSize) {
- m_viewSize = size;
- emit viewSizeChanged(size);
- }
-}
-
-void AssistantPopupConfig::setTitle(const QString& title)
-{
- if (m_title == title) {
- return;
- }
-
- m_title = title;
- emit titleChanged(m_title);
-}
-
-void AssistantPopupConfig::setModel(const QList& model)
-{
- if (m_model == model) {
- return;
- }
-
- qDeleteAll( m_model );
- m_model = model;
- emit modelChanged(model);
-}
-
-AssistantPopup::AssistantPopup()
-// main window as parent to use maximal space available in worst case
- : QQuickWidget(ICore::self()->uiController()->activeMainWindow())
- , m_config(new AssistantPopupConfig(this))
- , m_firstLayoutCompleted(false)
-{
- setAttribute(Qt::WA_ShowWithoutActivating);
-
- rootContext()->setContextProperty(QStringLiteral("config"), m_config);
-
- setSource(QUrl::fromLocalFile(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kdevelop/assistantpopup.qml"))));
- if (!rootObject()) {
- qWarning() << "Failed to load assistant markup! The assistant will not work.";
- } else {
- connect(rootObject(), &QQuickItem::widthChanged, this, &AssistantPopup::updateLayout);
- connect(rootObject(), &QQuickItem::heightChanged, this, &AssistantPopup::updateLayout);
- }
-
- for (int i = Qt::Key_0; i <= Qt::Key_9; ++i) {
- m_shortcuts.append(new QShortcut(ASSISTANT_MODIFIER + i, this));
- }
- setActive(false);
-
- connect(qApp, &QApplication::applicationStateChanged, this, [this]{ setActive(false); });
-}
-
-void AssistantPopup::reset(KTextEditor::View* view, const IAssistant::Ptr& assistant)
-{
- setView(view);
- setAssistant(assistant);
- updateState();
-}
-
-void AssistantPopup::setView(KTextEditor::View* view)
-{
- if (m_view == view) {
- return;
- }
-
- setActive(false);
-
- if (m_view) {
- m_view->removeEventFilter(this);
- disconnect(m_view.data(), &KTextEditor::View::verticalScrollPositionChanged,
- this, &AssistantPopup::updatePosition);
- }
- m_view = view;
- m_config->setViewSize(m_view ? m_view->size() : QSize());
- if (m_view) {
- m_view->installEventFilter(this);
- connect(m_view.data(), &KTextEditor::View::verticalScrollPositionChanged,
- this, &AssistantPopup::updatePosition);
- }
-}
-
-void AssistantPopup::setAssistant(const IAssistant::Ptr& assistant)
-{
- if (m_assistant == assistant) {
- return;
- }
-
- if (m_assistant) {
- disconnect(m_assistant.data(), &IAssistant::hide, this, &AssistantPopup::hideAssistant);
- disconnect(m_assistant.data(), &IAssistant::actionsChanged, this, &AssistantPopup::updateState);
- }
- m_assistant = assistant;
- if (m_assistant) {
- connect(m_assistant.data(), &IAssistant::hide, this, &AssistantPopup::hideAssistant);
- connect(m_assistant.data(), &IAssistant::actionsChanged, this, &AssistantPopup::updateState);
- } else {
- hide();
- }
-}
-
-void AssistantPopup::setActive(bool active)
-{
- m_config->setActive(active);
- foreach (auto shortcut, m_shortcuts) {
- shortcut->setEnabled(active);
- }
-}
-
-bool AssistantPopup::eventFilter(QObject* object, QEvent* event)
-{
- Q_UNUSED(object);
-
- if (!m_view || (object != m_view.data()))
- return false;
-
- if (event->type() == QEvent::Resize) {
- updateLayout();
- } else if (event->type() == QEvent::Hide) {
- executeHideAction();
- } else if (event->type() == QEvent::KeyPress) {
- auto keyEvent = static_cast(event);
- if (keyEvent->modifiers() == ASSISTANT_MODIFIER) {
- setActive(true);
- }
- if (keyEvent->key() == Qt::Key_Escape) {
- executeHideAction();
- }
- } else if (event->type() == QEvent::KeyRelease) {
- auto keyEvent = static_cast(event);
- if (keyEvent->modifiers() == ASSISTANT_MODIFIER || keyEvent->key() == ASSISTANT_MOD_KEY) {
- setActive(false);
- }
- }
- return false;
-}
-
-void AssistantPopup::updatePosition(KTextEditor::View* view, const KTextEditor::Cursor& newPos)
-{
- static const int MARGIN = 12;
-
- if (newPos.isValid() && newPos.line() == 0) {
- // the position is not going to change; don't waste time
- return;
- }
-
- auto editorGeometry = textWidgetGeometry(view);
- const auto startCursorCoordinate = view->cursorToCoordinate(KTextEditor::Cursor(0, 0));
-
- // algorithm for popup positioning:
- // if we are scrolled to the top: show at bottom
- // else:
- // if: current cursor position is in upper half => show at bottom
- // else: show at top
- const bool showAtBottom = startCursorCoordinate.y() == 0 ? true :
- view->cursorPositionCoordinates().y() < view->height()/2;
- const QPoint targetLocation = showAtBottom ?
- parentWidget()->mapFromGlobal(view->mapToGlobal(editorGeometry.bottomRight()
- + QPoint(-width() - MARGIN, -MARGIN - height()))) :
- parentWidget()->mapFromGlobal(view->mapToGlobal(editorGeometry.topRight()
- + QPoint(-width() - MARGIN, MARGIN)));
- if (pos() == targetLocation) {
- return;
- }
-
- Sublime::HoldUpdates hold(ICore::self()->uiController()->activeMainWindow());
- move(targetLocation);
-}
-
-IAssistant::Ptr AssistantPopup::assistant() const
-{
- return m_assistant;
-}
-
-void AssistantPopup::executeHideAction()
-{
- if ( isVisible() ) {
- m_assistant->doHide();
- }
-}
-
-void AssistantPopup::hideAssistant()
-{
- reset(nullptr, {}); // indirectly calls hide()
-}
-
-void AssistantPopup::updateLayout()
-{
- auto root = rootObject();
- if (!m_view || !root) {
- return;
- }
-
- m_config->setViewSize(m_view->size());
- // https://bugreports.qt.io/browse/QTBUG-44876
- resize(root->width(), root->height());
- updatePosition(m_view, KTextEditor::Cursor::invalid());
-
- // HACK: QQuickWidget is corrupted due to above resize on the first show
- if (!m_firstLayoutCompleted) {
- hide();
- show();
- m_firstLayoutCompleted = true;
- }
-}
-
-void AssistantPopup::updateState()
-{
- if (!m_assistant || m_assistant->actions().isEmpty() || !m_view) {
- hide();
- return;
- }
-
- auto curShortcut = m_shortcuts.constBegin();
- auto hideAction = new QAction(i18n("Hide"), this);
- connect(*curShortcut, &QShortcut::activated, hideAction, &QAction::trigger);
- connect(hideAction, &QAction::triggered, this, &AssistantPopup::executeHideAction);
-
- QList items;
- foreach (IAssistantAction::Ptr action, m_assistant->actions()) {
- QAction* asQAction = action->toKAction();
- items << asQAction;
- asQAction->setParent(this);
- //For some reason, QAction's setShortcut does nothing, so we manage with QShortcut
- if (++curShortcut != m_shortcuts.constEnd()) {
- connect(*curShortcut, &QShortcut::activated, asQAction, &QAction::trigger);
- }
- connect(action.data(), SIGNAL(executed(IAssistantAction*)), hideAction, SLOT(trigger()));
- }
- items << hideAction;
-
- auto view = ICore::self()->documentController()->activeTextDocumentView();
- m_config->setColorsFromView(view);
- m_config->setModel(items);
- m_config->setTitle(m_assistant->title());
- setActive(false);
-
- show();
-}
-
diff --git a/shell/assistantpopup.qml b/shell/assistantpopup.qml
deleted file mode 100644
--- a/shell/assistantpopup.qml
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- Copyright 2014 Sven Brauch
- Copyright 2014 Kevin Funk
-
- 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.
-*/
-
-// This file provides the whole assistant, including title and buttons.
-
-import QtQuick 2.2
-
-Rectangle {
- id: root
-
- readonly property int vSpacing: 4
- readonly property int hSpacing: 4
- readonly property real itemsWidth: {
- var totalWidth = title.width;
- for (var i = 0; i < items.count; ++i) {
- totalWidth += items.itemAt(i).width;
- }
- return totalWidth + (items.count + 2) * hSpacing;
- }
- readonly property bool useVerticalLayout: config.viewSize.width * 0.90 < itemsWidth
-
- // QQuickWidget crashes if either of these is zero
- // Use ceil to ensure the widget always fits the non-integral content size
- width: Math.ceil(Math.max(hSpacing, mainFlow.width + hSpacing * 2))
- height: Math.ceil(Math.max(vSpacing, mainFlow.height + vSpacing * 2))
-
- border.width: 1
- border.color: Qt.lighter(config.foreground)
- gradient: Gradient {
- GradientStop { position: 0.0; color: Qt.lighter(config.background) }
- GradientStop { position: 1.0; color: config.background }
- }
-
- Flow {
- id: mainFlow
-
- anchors {
- centerIn: parent
- }
-
- flow: root.useVerticalLayout ? Flow.TopToBottom : Flow.LeftToRight
- spacing: root.useVerticalLayout ? root.vSpacing : root.hSpacing
-
- Text {
- id: title
-
- color: config.foreground
- font.bold: true
- text: config.title
- }
-
-
- Repeater {
- id: items
- objectName: "items"
-
- y: 5
- model: config.model
-
- AssistantButton {
- text: modelData.text
- highlighted: config.active
- // what is displayed in the hotkey field of the button
- button: index == items.model.length - 1 ? 0 : index + 1
- foreground: config.foreground
- background: config.background
- highlight: config.highlight
-
- onTriggered: { modelData.trigger() }
- }
- }
- }
-}
diff --git a/shell/uicontroller.h b/shell/uicontroller.h
--- a/shell/uicontroller.h
+++ b/shell/uicontroller.h
@@ -85,8 +85,6 @@
/*! @p status must implement KDevelop::IStatus */
void registerStatus(QObject* status) override;
- void popUpAssistant(const KDevelop::IAssistant::Ptr& assistant) override;
-
void showErrorMessage(const QString& message, int timeout) override;
/// Returns list of available view factories together with their ToolDocuments.
@@ -112,8 +110,6 @@
void slotAreaChanged(Sublime::Area* area);
void slotActiveToolViewChanged(Sublime::View* view);
- void hideAssistant() override;
-
private:
void addToolViewIfWanted(IToolViewFactory* factory,
Sublime::ToolDocument* doc,
diff --git a/shell/uicontroller.cpp b/shell/uicontroller.cpp
--- a/shell/uicontroller.cpp
+++ b/shell/uicontroller.cpp
@@ -49,7 +49,6 @@
#include "partdocument.h"
#include "textdocument.h"
#include "documentcontroller.h"
-#include "assistantpopup.h"
#include
#include "workingsetcontroller.h"
#include "workingsets/workingset.h"
@@ -146,8 +145,6 @@
QPointer activeSublimeWindow;
bool areasRestored;
- /// Currently shown assistant popup.
- QPointer currentShownAssistant;
/// QWidget implementing IToolViewActionListener interface, or null
QPointer activeActionListener;
QTimer m_assistantTimer;
@@ -722,35 +719,6 @@
QMetaObject::invokeMethod(mw, "showErrorMessage", Q_ARG(QString, message), Q_ARG(int, timeout));
}
-void UiController::hideAssistant()
-{
- if (d->currentShownAssistant) {
- d->currentShownAssistant->hide();
- }
-}
-
-void UiController::popUpAssistant(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(view->widget());
- Q_ASSERT(editorView);
- if (editorView) {
- if ( !d->currentShownAssistant ) {
- d->currentShownAssistant = new AssistantPopup;
- }
- d->currentShownAssistant->reset(editorView, assistant);
- }
-}
-
const QHash< IToolViewFactory*, Sublime::ToolDocument* >& UiController::factoryDocuments() const
{
return d->factoryDocuments;