forked from qt-creator/qt-creator
Copilot: add copilot suggestion tooltips
These tooltips allow to switch the currently visible suggestion as well as applying it using the mouse. Change-Id: I30b9a76ae57c66887f4e1b1311e1a7248ed0f194 Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
This commit is contained in:
BIN
doc/qtcreator/images/qtcreator-debugger-threads.webp
Normal file
BIN
doc/qtcreator/images/qtcreator-debugger-threads.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.7 KiB |
@@ -3,13 +3,15 @@ add_qtc_plugin(Copilot
|
|||||||
SOURCES
|
SOURCES
|
||||||
authwidget.cpp authwidget.h
|
authwidget.cpp authwidget.h
|
||||||
copilot.qrc
|
copilot.qrc
|
||||||
copilotplugin.cpp copilotplugin.h
|
|
||||||
copilotclient.cpp copilotclient.h
|
copilotclient.cpp copilotclient.h
|
||||||
copilotsettings.cpp copilotsettings.h
|
copilothoverhandler.cpp copilothoverhandler.h
|
||||||
copilotoptionspage.cpp copilotoptionspage.h
|
copilotoptionspage.cpp copilotoptionspage.h
|
||||||
requests/getcompletions.h
|
copilotplugin.cpp copilotplugin.h
|
||||||
|
copilotsettings.cpp copilotsettings.h
|
||||||
|
copilotsuggestion.cpp copilotsuggestion.h
|
||||||
requests/checkstatus.h
|
requests/checkstatus.h
|
||||||
requests/signout.h
|
requests/getcompletions.h
|
||||||
requests/signininitiate.h
|
|
||||||
requests/signinconfirm.h
|
requests/signinconfirm.h
|
||||||
|
requests/signininitiate.h
|
||||||
|
requests/signout.h
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -12,18 +12,22 @@ QtcPlugin {
|
|||||||
"authwidget.cpp",
|
"authwidget.cpp",
|
||||||
"authwidget.h",
|
"authwidget.h",
|
||||||
"copilot.qrc",
|
"copilot.qrc",
|
||||||
"copilotplugin.cpp",
|
|
||||||
"copilotplugin.h",
|
|
||||||
"copilotclient.cpp",
|
"copilotclient.cpp",
|
||||||
"copilotclient.h",
|
"copilotclient.h",
|
||||||
"copilotsettings.cpp",
|
"copilothoverhandler.cpp",
|
||||||
"copilotsettings.h",
|
"copilothoverhandler.h",
|
||||||
"copilotoptionspage.cpp",
|
"copilotoptionspage.cpp",
|
||||||
"copilotoptionspage.h",
|
"copilotoptionspage.h",
|
||||||
"requests/getcompletions.h",
|
"copilotplugin.cpp",
|
||||||
|
"copilotplugin.h",
|
||||||
|
"copilotsettings.cpp",
|
||||||
|
"copilotsettings.h",
|
||||||
|
"copilotsuggestion.cpp",
|
||||||
|
"copilotsuggestion.h",
|
||||||
"requests/checkstatus.h",
|
"requests/checkstatus.h",
|
||||||
"requests/signout.h",
|
"requests/getcompletions.h",
|
||||||
"requests/signininitiate.h",
|
|
||||||
"requests/signinconfirm.h",
|
"requests/signinconfirm.h",
|
||||||
|
"requests/signininitiate.h",
|
||||||
|
"requests/signout.h",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
#include "copilotclient.h"
|
#include "copilotclient.h"
|
||||||
|
#include "copilotsuggestion.h"
|
||||||
|
|
||||||
#include <languageclient/languageclientinterface.h>
|
#include <languageclient/languageclientinterface.h>
|
||||||
#include <languageclient/languageclientmanager.h>
|
#include <languageclient/languageclientmanager.h>
|
||||||
@@ -63,6 +64,14 @@ CopilotClient::CopilotClient(const FilePath &nodePath, const FilePath &distPath)
|
|||||||
openDoc(doc);
|
openDoc(doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CopilotClient::~CopilotClient()
|
||||||
|
{
|
||||||
|
for (Core::IEditor *editor : Core::DocumentModel::editorsForOpenedDocuments()) {
|
||||||
|
if (auto textEditor = qobject_cast<BaseTextEditor *>(editor))
|
||||||
|
textEditor->editorWidget()->removeHoverHandler(&m_hoverHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CopilotClient::openDocument(TextDocument *document)
|
void CopilotClient::openDocument(TextDocument *document)
|
||||||
{
|
{
|
||||||
Client::openDocument(document);
|
Client::openDocument(document);
|
||||||
@@ -112,7 +121,7 @@ void CopilotClient::scheduleRequest(TextEditorWidget *editor)
|
|||||||
void CopilotClient::requestCompletions(TextEditorWidget *editor)
|
void CopilotClient::requestCompletions(TextEditorWidget *editor)
|
||||||
{
|
{
|
||||||
Utils::MultiTextCursor cursor = editor->multiTextCursor();
|
Utils::MultiTextCursor cursor = editor->multiTextCursor();
|
||||||
if (cursor.hasMultipleCursors() || cursor.hasSelection())
|
if (cursor.hasMultipleCursors() || cursor.hasSelection() || editor->suggestionVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const Utils::FilePath filePath = editor->textDocument()->filePath();
|
const Utils::FilePath filePath = editor->textDocument()->filePath();
|
||||||
@@ -129,39 +138,6 @@ void CopilotClient::requestCompletions(TextEditorWidget *editor)
|
|||||||
sendMessage(request);
|
sendMessage(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
class CopilotSuggestion final : public TextEditor::TextSuggestion
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CopilotSuggestion(const Completion &completion, QTextDocument *origin)
|
|
||||||
: m_completion(completion)
|
|
||||||
{
|
|
||||||
document()->setPlainText(completion.text());
|
|
||||||
m_start = completion.position().toTextCursor(origin);
|
|
||||||
m_start.setKeepPositionOnInsert(true);
|
|
||||||
setCurrentPosition(m_start.position());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool apply() final
|
|
||||||
{
|
|
||||||
reset();
|
|
||||||
QTextCursor cursor = m_completion.range().toSelection(m_start.document());
|
|
||||||
cursor.insertText(m_completion.text());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
void reset() final
|
|
||||||
{
|
|
||||||
m_start.removeSelectedText();
|
|
||||||
}
|
|
||||||
int position() final
|
|
||||||
{
|
|
||||||
return m_start.position();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Completion m_completion;
|
|
||||||
QTextCursor m_start;
|
|
||||||
};
|
|
||||||
|
|
||||||
void CopilotClient::handleCompletions(const GetCompletionRequest::Response &response,
|
void CopilotClient::handleCompletions(const GetCompletionRequest::Response &response,
|
||||||
TextEditorWidget *editor)
|
TextEditorWidget *editor)
|
||||||
{
|
{
|
||||||
@@ -184,7 +160,9 @@ void CopilotClient::handleCompletions(const GetCompletionRequest::Response &resp
|
|||||||
if (completions.isEmpty())
|
if (completions.isEmpty())
|
||||||
return;
|
return;
|
||||||
editor->insertSuggestion(
|
editor->insertSuggestion(
|
||||||
std::make_unique<CopilotSuggestion>(completions.first(), editor->document()));
|
std::make_unique<CopilotSuggestion>(completions, editor->document()));
|
||||||
|
m_lastCompletions[editor] = *result;
|
||||||
|
editor->addHoverHandler(&m_hoverHandler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,4 +212,9 @@ void CopilotClient::requestSignInConfirm(
|
|||||||
sendMessage(request);
|
sendMessage(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GetCompletionResponse CopilotClient::lastCompletion(TextEditor::TextEditorWidget *editor) const
|
||||||
|
{
|
||||||
|
return m_lastCompletions.value(editor);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Copilot::Internal
|
} // namespace Copilot::Internal
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "copilothoverhandler.h"
|
||||||
#include "requests/checkstatus.h"
|
#include "requests/checkstatus.h"
|
||||||
#include "requests/getcompletions.h"
|
#include "requests/getcompletions.h"
|
||||||
#include "requests/signinconfirm.h"
|
#include "requests/signinconfirm.h"
|
||||||
@@ -18,12 +19,11 @@
|
|||||||
|
|
||||||
namespace Copilot::Internal {
|
namespace Copilot::Internal {
|
||||||
|
|
||||||
class DocumentWatcher;
|
|
||||||
|
|
||||||
class CopilotClient : public LanguageClient::Client
|
class CopilotClient : public LanguageClient::Client
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit CopilotClient(const Utils::FilePath &nodePath, const Utils::FilePath &distPath);
|
CopilotClient(const Utils::FilePath &nodePath, const Utils::FilePath &distPath);
|
||||||
|
~CopilotClient() override;
|
||||||
|
|
||||||
void openDocument(TextEditor::TextDocument *document) override;
|
void openDocument(TextEditor::TextDocument *document) override;
|
||||||
|
|
||||||
@@ -46,6 +46,8 @@ public:
|
|||||||
const QString &userCode,
|
const QString &userCode,
|
||||||
std::function<void(const SignInConfirmRequest::Response &response)> callback);
|
std::function<void(const SignInConfirmRequest::Response &response)> callback);
|
||||||
|
|
||||||
|
GetCompletionResponse lastCompletion(TextEditor::TextEditorWidget *editor) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMap<TextEditor::TextEditorWidget *, GetCompletionRequest> m_runningRequests;
|
QMap<TextEditor::TextEditorWidget *, GetCompletionRequest> m_runningRequests;
|
||||||
struct ScheduleData
|
struct ScheduleData
|
||||||
@@ -54,6 +56,8 @@ private:
|
|||||||
QTimer *timer = nullptr;
|
QTimer *timer = nullptr;
|
||||||
};
|
};
|
||||||
QMap<TextEditor::TextEditorWidget *, ScheduleData> m_scheduledRequests;
|
QMap<TextEditor::TextEditorWidget *, ScheduleData> m_scheduledRequests;
|
||||||
|
CopilotHoverHandler m_hoverHandler;
|
||||||
|
QHash<TextEditor::TextEditorWidget *, GetCompletionResponse> m_lastCompletions;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Copilot::Internal
|
} // namespace Copilot::Internal
|
||||||
|
|||||||
140
src/plugins/copilot/copilothoverhandler.cpp
Normal file
140
src/plugins/copilot/copilothoverhandler.cpp
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#include "copilothoverhandler.h"
|
||||||
|
|
||||||
|
#include "copilotclient.h"
|
||||||
|
#include "copilotsuggestion.h"
|
||||||
|
#include "copilottr.h"
|
||||||
|
|
||||||
|
#include <texteditor/textdocument.h>
|
||||||
|
#include <texteditor/textdocumentlayout.h>
|
||||||
|
#include <texteditor/texteditor.h>
|
||||||
|
|
||||||
|
#include <utils/tooltip/tooltip.h>
|
||||||
|
#include <utils/utilsicons.h>
|
||||||
|
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QToolBar>
|
||||||
|
#include <QToolButton>
|
||||||
|
|
||||||
|
using namespace TextEditor;
|
||||||
|
using namespace LanguageServerProtocol;
|
||||||
|
using namespace Utils;
|
||||||
|
|
||||||
|
namespace Copilot::Internal {
|
||||||
|
|
||||||
|
class CopilotCompletionToolTip : public QToolBar
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CopilotCompletionToolTip(QList<Completion> completions,
|
||||||
|
int currentCompletion,
|
||||||
|
TextEditorWidget *editor)
|
||||||
|
: m_numberLabel(new QLabel)
|
||||||
|
, m_completions(completions)
|
||||||
|
, m_currentCompletion(std::max(0, std::min<int>(currentCompletion, completions.size() - 1)))
|
||||||
|
, m_editor(editor)
|
||||||
|
{
|
||||||
|
auto prev = addAction(Utils::Icons::PREV_TOOLBAR.icon(),
|
||||||
|
Tr::tr("Select Previous Copilot Suggestion"));
|
||||||
|
prev->setEnabled(m_completions.size() > 1);
|
||||||
|
addWidget(m_numberLabel);
|
||||||
|
auto next = addAction(Utils::Icons::NEXT_TOOLBAR.icon(),
|
||||||
|
Tr::tr("Select Next Copilot Suggestion"));
|
||||||
|
next->setEnabled(m_completions.size() > 1);
|
||||||
|
|
||||||
|
auto apply = addAction(Tr::tr("Apply (Tab)"));
|
||||||
|
|
||||||
|
connect(prev, &QAction::triggered, this, &CopilotCompletionToolTip::selectPrevious);
|
||||||
|
connect(next, &QAction::triggered, this, &CopilotCompletionToolTip::selectNext);
|
||||||
|
connect(apply, &QAction::triggered, this, &CopilotCompletionToolTip::apply);
|
||||||
|
|
||||||
|
updateLabels();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updateLabels()
|
||||||
|
{
|
||||||
|
m_numberLabel->setText(Tr::tr("%1 of %2")
|
||||||
|
.arg(m_currentCompletion + 1)
|
||||||
|
.arg(m_completions.count()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void selectPrevious()
|
||||||
|
{
|
||||||
|
--m_currentCompletion;
|
||||||
|
if (m_currentCompletion < 0)
|
||||||
|
m_currentCompletion = m_completions.size() - 1;
|
||||||
|
setCurrentCompletion();
|
||||||
|
}
|
||||||
|
|
||||||
|
void selectNext()
|
||||||
|
{
|
||||||
|
++m_currentCompletion;
|
||||||
|
if (m_currentCompletion >= m_completions.size())
|
||||||
|
m_currentCompletion = 0;
|
||||||
|
setCurrentCompletion();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setCurrentCompletion()
|
||||||
|
{
|
||||||
|
updateLabels();
|
||||||
|
if (TextSuggestion *suggestion = m_editor->currentSuggestion())
|
||||||
|
suggestion->reset();
|
||||||
|
m_editor->insertSuggestion(std::make_unique<CopilotSuggestion>(m_completions,
|
||||||
|
m_editor->document(),
|
||||||
|
m_currentCompletion));
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply()
|
||||||
|
{
|
||||||
|
if (TextSuggestion *suggestion = m_editor->currentSuggestion())
|
||||||
|
suggestion->apply();
|
||||||
|
ToolTip::hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
QLabel *m_numberLabel;
|
||||||
|
QList<Completion> m_completions;
|
||||||
|
int m_currentCompletion = 0;
|
||||||
|
TextEditorWidget *m_editor;
|
||||||
|
};
|
||||||
|
|
||||||
|
void CopilotHoverHandler::identifyMatch(TextEditorWidget *editorWidget,
|
||||||
|
int pos,
|
||||||
|
ReportPriority report)
|
||||||
|
{
|
||||||
|
auto reportNone = qScopeGuard([&] { report(Priority_None); });
|
||||||
|
if (!editorWidget->suggestionVisible())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QTextCursor cursor(editorWidget->document());
|
||||||
|
cursor.setPosition(pos);
|
||||||
|
m_block = cursor.block();
|
||||||
|
auto *suggestion = dynamic_cast<CopilotSuggestion *>(TextDocumentLayout::suggestion(m_block));
|
||||||
|
|
||||||
|
if (!suggestion)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const QList<Completion> completions = suggestion->completions();
|
||||||
|
if (completions.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
reportNone.dismiss();
|
||||||
|
report(Priority_Suggestion);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CopilotHoverHandler::operateTooltip(TextEditorWidget *editorWidget, const QPoint &point)
|
||||||
|
{
|
||||||
|
auto *suggestion = dynamic_cast<CopilotSuggestion *>(TextDocumentLayout::suggestion(m_block));
|
||||||
|
|
||||||
|
if (!suggestion)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto tooltipWidget = new CopilotCompletionToolTip(suggestion->completions(),
|
||||||
|
suggestion->currentCompletion(),
|
||||||
|
editorWidget);
|
||||||
|
const qreal deltay = 2 * editorWidget->textDocument()->fontSettings().lineSpacing();
|
||||||
|
ToolTip::show(point - QPoint{0, int(deltay)}, tooltipWidget, editorWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Copilot::Internal
|
||||||
32
src/plugins/copilot/copilothoverhandler.h
Normal file
32
src/plugins/copilot/copilothoverhandler.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#include "requests/getcompletions.h"
|
||||||
|
|
||||||
|
#include <texteditor/basehoverhandler.h>
|
||||||
|
|
||||||
|
#include <QTextBlock>
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace TextEditor { class TextSuggestion; }
|
||||||
|
namespace Copilot::Internal {
|
||||||
|
|
||||||
|
class CopilotClient;
|
||||||
|
|
||||||
|
class CopilotHoverHandler final : public TextEditor::BaseHoverHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CopilotHoverHandler() = default;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void identifyMatch(TextEditor::TextEditorWidget *editorWidget,
|
||||||
|
int pos,
|
||||||
|
ReportPriority report) final;
|
||||||
|
void operateTooltip(TextEditor::TextEditorWidget *editorWidget, const QPoint &point) final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTextBlock m_block;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Copilot::Internal
|
||||||
41
src/plugins/copilot/copilotsuggestion.cpp
Normal file
41
src/plugins/copilot/copilotsuggestion.cpp
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#include "copilotsuggestion.h"
|
||||||
|
|
||||||
|
namespace Copilot::Internal {
|
||||||
|
|
||||||
|
CopilotSuggestion::CopilotSuggestion(const QList<Completion> &completions,
|
||||||
|
QTextDocument *origin,
|
||||||
|
int currentCompletion)
|
||||||
|
: m_completions(completions)
|
||||||
|
, m_currentCompletion(currentCompletion)
|
||||||
|
{
|
||||||
|
const Completion completion = completions.value(currentCompletion);
|
||||||
|
document()->setPlainText(completion.text());
|
||||||
|
m_start = completion.position().toTextCursor(origin);
|
||||||
|
m_start.setKeepPositionOnInsert(true);
|
||||||
|
setCurrentPosition(m_start.position());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CopilotSuggestion::apply()
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
const Completion completion = m_completions.value(m_currentCompletion);
|
||||||
|
QTextCursor cursor = completion.range().toSelection(m_start.document());
|
||||||
|
cursor.insertText(completion.text());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CopilotSuggestion::reset()
|
||||||
|
{
|
||||||
|
m_start.removeSelectedText();
|
||||||
|
}
|
||||||
|
|
||||||
|
int CopilotSuggestion::position()
|
||||||
|
{
|
||||||
|
return m_start.position();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Copilot::Internal
|
||||||
|
|
||||||
30
src/plugins/copilot/copilotsuggestion.h
Normal file
30
src/plugins/copilot/copilotsuggestion.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "requests/getcompletions.h"
|
||||||
|
|
||||||
|
#include <texteditor/textdocumentlayout.h>
|
||||||
|
|
||||||
|
namespace Copilot::Internal {
|
||||||
|
|
||||||
|
class CopilotSuggestion final : public TextEditor::TextSuggestion
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CopilotSuggestion(const QList<Completion> &completions,
|
||||||
|
QTextDocument *origin,
|
||||||
|
int currentCompletion = 0);
|
||||||
|
|
||||||
|
bool apply() final;
|
||||||
|
void reset() final;
|
||||||
|
int position() final;
|
||||||
|
|
||||||
|
const QList<Completion> &completions() const { return m_completions; }
|
||||||
|
const int currentCompletion() const { return m_currentCompletion; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<Completion> m_completions;
|
||||||
|
int m_currentCompletion = 0;
|
||||||
|
QTextCursor m_start;
|
||||||
|
};
|
||||||
|
} // namespace Copilot::Internal
|
||||||
@@ -39,7 +39,8 @@ protected:
|
|||||||
Priority_None = 0,
|
Priority_None = 0,
|
||||||
Priority_Tooltip = 5,
|
Priority_Tooltip = 5,
|
||||||
Priority_Help = 10,
|
Priority_Help = 10,
|
||||||
Priority_Diagnostic = 20
|
Priority_Diagnostic = 20,
|
||||||
|
Priority_Suggestion = 40
|
||||||
};
|
};
|
||||||
void setPriority(int priority);
|
void setPriority(int priority);
|
||||||
int priority() const;
|
int priority() const;
|
||||||
|
|||||||
@@ -165,7 +165,6 @@ private:
|
|||||||
std::unique_ptr<TextSuggestion> m_suggestion;
|
std::unique_ptr<TextSuggestion> m_suggestion;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class TEXTEDITOR_EXPORT TextDocumentLayout : public QPlainTextDocumentLayout
|
class TEXTEDITOR_EXPORT TextDocumentLayout : public QPlainTextDocumentLayout
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|||||||
@@ -3736,7 +3736,10 @@ bool TextEditorWidget::viewportEvent(QEvent *event)
|
|||||||
// Only handle tool tip for text cursor if mouse is within the block for the text cursor,
|
// Only handle tool tip for text cursor if mouse is within the block for the text cursor,
|
||||||
// and not if the mouse is e.g. in the empty space behind a short line.
|
// and not if the mouse is e.g. in the empty space behind a short line.
|
||||||
if (line.isValid()) {
|
if (line.isValid()) {
|
||||||
if (pos.x() <= blockBoundingGeometry(block).left() + line.naturalTextRect().right()) {
|
const QRectF blockGeometry = blockBoundingGeometry(block);
|
||||||
|
const int width = block == d->m_suggestionBlock ? blockGeometry.width()
|
||||||
|
: line.naturalTextRect().right();
|
||||||
|
if (pos.x() <= blockGeometry.left() + width) {
|
||||||
d->processTooltipRequest(tc);
|
d->processTooltipRequest(tc);
|
||||||
return true;
|
return true;
|
||||||
} else if (d->processAnnotaionTooltipRequest(block, pos)) {
|
} else if (d->processAnnotaionTooltipRequest(block, pos)) {
|
||||||
@@ -5980,8 +5983,8 @@ void TextEditorWidget::addHoverHandler(BaseHoverHandler *handler)
|
|||||||
|
|
||||||
void TextEditorWidget::removeHoverHandler(BaseHoverHandler *handler)
|
void TextEditorWidget::removeHoverHandler(BaseHoverHandler *handler)
|
||||||
{
|
{
|
||||||
d->m_hoverHandlers.removeAll(handler);
|
if (d->m_hoverHandlers.removeAll(handler) > 0)
|
||||||
d->m_hoverHandlerRunner.handlerRemoved(handler);
|
d->m_hoverHandlerRunner.handlerRemoved(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextEditorWidget::insertSuggestion(std::unique_ptr<TextSuggestion> &&suggestion)
|
void TextEditorWidget::insertSuggestion(std::unique_ptr<TextSuggestion> &&suggestion)
|
||||||
@@ -5994,9 +5997,16 @@ void TextEditorWidget::clearSuggestion()
|
|||||||
d->clearCurrentSuggestion();
|
d->clearCurrentSuggestion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextSuggestion *TextEditorWidget::currentSuggestion() const
|
||||||
|
{
|
||||||
|
if (d->m_suggestionBlock.isValid())
|
||||||
|
return TextDocumentLayout::suggestion(d->m_suggestionBlock);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
bool TextEditorWidget::suggestionVisible() const
|
bool TextEditorWidget::suggestionVisible() const
|
||||||
{
|
{
|
||||||
return d->m_suggestionBlock.isValid();
|
return currentSuggestion();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_TESTS
|
#ifdef WITH_TESTS
|
||||||
|
|||||||
@@ -473,6 +473,7 @@ public:
|
|||||||
|
|
||||||
void insertSuggestion(std::unique_ptr<TextSuggestion> &&suggestion);
|
void insertSuggestion(std::unique_ptr<TextSuggestion> &&suggestion);
|
||||||
void clearSuggestion();
|
void clearSuggestion();
|
||||||
|
TextSuggestion *currentSuggestion() const;
|
||||||
bool suggestionVisible() const;
|
bool suggestionVisible() const;
|
||||||
|
|
||||||
#ifdef WITH_TESTS
|
#ifdef WITH_TESTS
|
||||||
|
|||||||
Reference in New Issue
Block a user