forked from qt-creator/qt-creator
LanguageClient: postpone creating progressbars
Some language servers are spawning progress reports for many small tasks. This can get distracting in the case where those progress bars are spawned while typing, like in the case of the python language server that creates a report for every lint that gets triggered after receiving a document change notification. So in order to reduce the amount of progress bars created from progress reports we postpone the creation of the bars. Fixes: QTCREATORBUG-29224 Change-Id: I2e658be0a26b21e41c80b444184648ba70682522 Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io> Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
#include <languageserverprotocol/progresssupport.h>
|
||||
|
||||
#include <QTime>
|
||||
#include <QTimer>
|
||||
|
||||
using namespace LanguageServerProtocol;
|
||||
|
||||
@@ -81,9 +82,28 @@ void ProgressManager::beginProgress(const ProgressToken &token, const WorkDonePr
|
||||
auto interface = new QFutureInterface<void>();
|
||||
interface->reportStarted();
|
||||
interface->setProgressRange(0, 100); // LSP always reports percentage of the task
|
||||
const QString title = m_titles.value(token, begin.title());
|
||||
Core::FutureProgress *progress = Core::ProgressManager::addTask(
|
||||
interface->future(), title, languageClientProgressId(token));
|
||||
ProgressItem progressItem;
|
||||
progressItem.futureInterface = interface;
|
||||
progressItem.title = m_titles.value(token, begin.title());
|
||||
if (LOGPROGRESS().isDebugEnabled())
|
||||
progressItem.timer.start();
|
||||
progressItem.showBarTimer = new QTimer();
|
||||
progressItem.showBarTimer->setSingleShot(true);
|
||||
progressItem.showBarTimer->setInterval(750);
|
||||
progressItem.showBarTimer->callOnTimeout([this, token]() { spawnProgressBar(token); });
|
||||
progressItem.showBarTimer->start();
|
||||
m_progress[token] = progressItem;
|
||||
reportProgress(token, begin);
|
||||
}
|
||||
|
||||
void ProgressManager::spawnProgressBar(const LanguageServerProtocol::ProgressToken &token)
|
||||
{
|
||||
ProgressItem &progressItem = m_progress[token];
|
||||
QTC_ASSERT(progressItem.futureInterface, return);
|
||||
Core::FutureProgress *progress
|
||||
= Core::ProgressManager::addTask(progressItem.futureInterface->future(),
|
||||
progressItem.title,
|
||||
languageClientProgressId(token));
|
||||
const std::function<void()> clickHandler = m_clickHandlers.value(token);
|
||||
if (clickHandler)
|
||||
QObject::connect(progress, &Core::FutureProgress::clicked, clickHandler);
|
||||
@@ -92,23 +112,26 @@ void ProgressManager::beginProgress(const ProgressToken &token, const WorkDonePr
|
||||
QObject::connect(progress, &Core::FutureProgress::canceled, cancelHandler);
|
||||
else
|
||||
progress->setCancelEnabled(false);
|
||||
m_progress[token] = {progress, interface};
|
||||
if (LOGPROGRESS().isDebugEnabled())
|
||||
m_timer[token].start();
|
||||
reportProgress(token, begin);
|
||||
if (!progressItem.message.isEmpty()) {
|
||||
progress->setSubtitle(progressItem.message);
|
||||
progress->setSubtitleVisibleInStatusBar(true);
|
||||
}
|
||||
progressItem.progressInterface = progress;
|
||||
}
|
||||
|
||||
void ProgressManager::reportProgress(const ProgressToken &token,
|
||||
const WorkDoneProgressReport &report)
|
||||
{
|
||||
const LanguageClientProgress &progress = m_progress.value(token);
|
||||
if (progress.progressInterface) {
|
||||
ProgressItem &progress = m_progress[token];
|
||||
const std::optional<QString> &message = report.message();
|
||||
if (progress.progressInterface) {
|
||||
if (message.has_value()) {
|
||||
progress.progressInterface->setSubtitle(*message);
|
||||
const bool showSubtitle = !message->isEmpty();
|
||||
progress.progressInterface->setSubtitleVisibleInStatusBar(showSubtitle);
|
||||
}
|
||||
} else if (message.has_value()) {
|
||||
progress.message = *message;
|
||||
}
|
||||
if (progress.futureInterface) {
|
||||
if (const std::optional<double> &percentage = report.percentage(); percentage.has_value())
|
||||
@@ -118,7 +141,7 @@ void ProgressManager::reportProgress(const ProgressToken &token,
|
||||
|
||||
void ProgressManager::endProgress(const ProgressToken &token, const WorkDoneProgressEnd &end)
|
||||
{
|
||||
const LanguageClientProgress &progress = m_progress.value(token);
|
||||
const ProgressItem &progress = m_progress.value(token);
|
||||
const QString &message = end.message().value_or(QString());
|
||||
if (progress.progressInterface) {
|
||||
if (!message.isEmpty()) {
|
||||
@@ -127,11 +150,11 @@ void ProgressManager::endProgress(const ProgressToken &token, const WorkDoneProg
|
||||
}
|
||||
progress.progressInterface->setSubtitle(message);
|
||||
progress.progressInterface->setSubtitleVisibleInStatusBar(!message.isEmpty());
|
||||
auto timer = m_timer.take(token);
|
||||
if (timer.isValid()) {
|
||||
if (progress.timer.isValid()) {
|
||||
qCDebug(LOGPROGRESS) << QString("%1 took %2")
|
||||
.arg(progress.progressInterface->title())
|
||||
.arg(QTime::fromMSecsSinceStartOfDay(timer.elapsed())
|
||||
.arg(QTime::fromMSecsSinceStartOfDay(
|
||||
progress.timer.elapsed())
|
||||
.toString(Qt::ISODateWithMs));
|
||||
}
|
||||
}
|
||||
@@ -140,7 +163,8 @@ void ProgressManager::endProgress(const ProgressToken &token, const WorkDoneProg
|
||||
|
||||
void ProgressManager::endProgressReport(const ProgressToken &token)
|
||||
{
|
||||
const LanguageClientProgress &progress = m_progress.take(token);
|
||||
ProgressItem progress = m_progress.take(token);
|
||||
delete progress.showBarTimer;
|
||||
if (progress.futureInterface)
|
||||
progress.futureInterface->reportFinished();
|
||||
delete progress.futureInterface;
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
#include <QFutureInterface>
|
||||
#include <QPointer>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QTimer;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace LanguageServerProtocol {
|
||||
class ProgressParams;
|
||||
class ProgressToken;
|
||||
@@ -46,15 +50,20 @@ private:
|
||||
const LanguageServerProtocol::WorkDoneProgressReport &report);
|
||||
void endProgress(const LanguageServerProtocol::ProgressToken &token,
|
||||
const LanguageServerProtocol::WorkDoneProgressEnd &end);
|
||||
void spawnProgressBar(const LanguageServerProtocol::ProgressToken &token);
|
||||
|
||||
struct LanguageClientProgress {
|
||||
struct ProgressItem
|
||||
{
|
||||
QPointer<Core::FutureProgress> progressInterface = nullptr;
|
||||
QFutureInterface<void> *futureInterface = nullptr;
|
||||
QElapsedTimer timer;
|
||||
QTimer *showBarTimer = nullptr;
|
||||
QString message;
|
||||
QString title;
|
||||
};
|
||||
|
||||
QMap<LanguageServerProtocol::ProgressToken, LanguageClientProgress> m_progress;
|
||||
QMap<LanguageServerProtocol::ProgressToken, ProgressItem> m_progress;
|
||||
QMap<LanguageServerProtocol::ProgressToken, QString> m_titles;
|
||||
QMap<LanguageServerProtocol::ProgressToken, QElapsedTimer> m_timer;
|
||||
QMap<LanguageServerProtocol::ProgressToken, std::function<void()>> m_clickHandlers;
|
||||
QMap<LanguageServerProtocol::ProgressToken, std::function<void()>> m_cancelHandlers;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user