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 <languageserverprotocol/progresssupport.h>
|
||||||
|
|
||||||
#include <QTime>
|
#include <QTime>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
using namespace LanguageServerProtocol;
|
using namespace LanguageServerProtocol;
|
||||||
|
|
||||||
@@ -81,9 +82,28 @@ void ProgressManager::beginProgress(const ProgressToken &token, const WorkDonePr
|
|||||||
auto interface = new QFutureInterface<void>();
|
auto interface = new QFutureInterface<void>();
|
||||||
interface->reportStarted();
|
interface->reportStarted();
|
||||||
interface->setProgressRange(0, 100); // LSP always reports percentage of the task
|
interface->setProgressRange(0, 100); // LSP always reports percentage of the task
|
||||||
const QString title = m_titles.value(token, begin.title());
|
ProgressItem progressItem;
|
||||||
Core::FutureProgress *progress = Core::ProgressManager::addTask(
|
progressItem.futureInterface = interface;
|
||||||
interface->future(), title, languageClientProgressId(token));
|
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);
|
const std::function<void()> clickHandler = m_clickHandlers.value(token);
|
||||||
if (clickHandler)
|
if (clickHandler)
|
||||||
QObject::connect(progress, &Core::FutureProgress::clicked, 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);
|
QObject::connect(progress, &Core::FutureProgress::canceled, cancelHandler);
|
||||||
else
|
else
|
||||||
progress->setCancelEnabled(false);
|
progress->setCancelEnabled(false);
|
||||||
m_progress[token] = {progress, interface};
|
if (!progressItem.message.isEmpty()) {
|
||||||
if (LOGPROGRESS().isDebugEnabled())
|
progress->setSubtitle(progressItem.message);
|
||||||
m_timer[token].start();
|
progress->setSubtitleVisibleInStatusBar(true);
|
||||||
reportProgress(token, begin);
|
}
|
||||||
|
progressItem.progressInterface = progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProgressManager::reportProgress(const ProgressToken &token,
|
void ProgressManager::reportProgress(const ProgressToken &token,
|
||||||
const WorkDoneProgressReport &report)
|
const WorkDoneProgressReport &report)
|
||||||
{
|
{
|
||||||
const LanguageClientProgress &progress = m_progress.value(token);
|
ProgressItem &progress = m_progress[token];
|
||||||
if (progress.progressInterface) {
|
|
||||||
const std::optional<QString> &message = report.message();
|
const std::optional<QString> &message = report.message();
|
||||||
|
if (progress.progressInterface) {
|
||||||
if (message.has_value()) {
|
if (message.has_value()) {
|
||||||
progress.progressInterface->setSubtitle(*message);
|
progress.progressInterface->setSubtitle(*message);
|
||||||
const bool showSubtitle = !message->isEmpty();
|
const bool showSubtitle = !message->isEmpty();
|
||||||
progress.progressInterface->setSubtitleVisibleInStatusBar(showSubtitle);
|
progress.progressInterface->setSubtitleVisibleInStatusBar(showSubtitle);
|
||||||
}
|
}
|
||||||
|
} else if (message.has_value()) {
|
||||||
|
progress.message = *message;
|
||||||
}
|
}
|
||||||
if (progress.futureInterface) {
|
if (progress.futureInterface) {
|
||||||
if (const std::optional<double> &percentage = report.percentage(); percentage.has_value())
|
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)
|
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());
|
const QString &message = end.message().value_or(QString());
|
||||||
if (progress.progressInterface) {
|
if (progress.progressInterface) {
|
||||||
if (!message.isEmpty()) {
|
if (!message.isEmpty()) {
|
||||||
@@ -127,11 +150,11 @@ void ProgressManager::endProgress(const ProgressToken &token, const WorkDoneProg
|
|||||||
}
|
}
|
||||||
progress.progressInterface->setSubtitle(message);
|
progress.progressInterface->setSubtitle(message);
|
||||||
progress.progressInterface->setSubtitleVisibleInStatusBar(!message.isEmpty());
|
progress.progressInterface->setSubtitleVisibleInStatusBar(!message.isEmpty());
|
||||||
auto timer = m_timer.take(token);
|
if (progress.timer.isValid()) {
|
||||||
if (timer.isValid()) {
|
|
||||||
qCDebug(LOGPROGRESS) << QString("%1 took %2")
|
qCDebug(LOGPROGRESS) << QString("%1 took %2")
|
||||||
.arg(progress.progressInterface->title())
|
.arg(progress.progressInterface->title())
|
||||||
.arg(QTime::fromMSecsSinceStartOfDay(timer.elapsed())
|
.arg(QTime::fromMSecsSinceStartOfDay(
|
||||||
|
progress.timer.elapsed())
|
||||||
.toString(Qt::ISODateWithMs));
|
.toString(Qt::ISODateWithMs));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -140,7 +163,8 @@ void ProgressManager::endProgress(const ProgressToken &token, const WorkDoneProg
|
|||||||
|
|
||||||
void ProgressManager::endProgressReport(const ProgressToken &token)
|
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)
|
if (progress.futureInterface)
|
||||||
progress.futureInterface->reportFinished();
|
progress.futureInterface->reportFinished();
|
||||||
delete progress.futureInterface;
|
delete progress.futureInterface;
|
||||||
|
|||||||
@@ -11,6 +11,10 @@
|
|||||||
#include <QFutureInterface>
|
#include <QFutureInterface>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QTimer;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace LanguageServerProtocol {
|
namespace LanguageServerProtocol {
|
||||||
class ProgressParams;
|
class ProgressParams;
|
||||||
class ProgressToken;
|
class ProgressToken;
|
||||||
@@ -46,15 +50,20 @@ private:
|
|||||||
const LanguageServerProtocol::WorkDoneProgressReport &report);
|
const LanguageServerProtocol::WorkDoneProgressReport &report);
|
||||||
void endProgress(const LanguageServerProtocol::ProgressToken &token,
|
void endProgress(const LanguageServerProtocol::ProgressToken &token,
|
||||||
const LanguageServerProtocol::WorkDoneProgressEnd &end);
|
const LanguageServerProtocol::WorkDoneProgressEnd &end);
|
||||||
|
void spawnProgressBar(const LanguageServerProtocol::ProgressToken &token);
|
||||||
|
|
||||||
struct LanguageClientProgress {
|
struct ProgressItem
|
||||||
|
{
|
||||||
QPointer<Core::FutureProgress> progressInterface = nullptr;
|
QPointer<Core::FutureProgress> progressInterface = nullptr;
|
||||||
QFutureInterface<void> *futureInterface = 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, QString> m_titles;
|
||||||
QMap<LanguageServerProtocol::ProgressToken, QElapsedTimer> m_timer;
|
|
||||||
QMap<LanguageServerProtocol::ProgressToken, std::function<void()>> m_clickHandlers;
|
QMap<LanguageServerProtocol::ProgressToken, std::function<void()>> m_clickHandlers;
|
||||||
QMap<LanguageServerProtocol::ProgressToken, std::function<void()>> m_cancelHandlers;
|
QMap<LanguageServerProtocol::ProgressToken, std::function<void()>> m_cancelHandlers;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user