From c4b50488362ec72bfe053f66ae5cdf6a7417c4f1 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Thu, 7 Sep 2017 11:17:27 +0200 Subject: [PATCH] ShellCommand: Show some progress information without progress parser Show magically timed progress when running a shell command without a progress parser. The assumption is that the timeout is much larger than the expected runtime, but still an indicator for how long it might take. Progress manager does its magic on top of that. This is e.g. used for the update info plugin, for which checking for updates might take quite some while. Change-Id: Ib3d3d37b86fac17816fe592e39e26a3d484bba26 Reviewed-by: Tobias Hunger --- src/libs/utils/shellcommand.cpp | 15 +++++++++++++++ src/libs/utils/shellcommand.h | 2 ++ src/plugins/coreplugin/shellcommand.cpp | 21 ++++++++++++++++++++- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/libs/utils/shellcommand.cpp b/src/libs/utils/shellcommand.cpp index 59c7f97fd0d..6ea2099211e 100644 --- a/src/libs/utils/shellcommand.cpp +++ b/src/libs/utils/shellcommand.cpp @@ -42,6 +42,8 @@ #include #include +#include + /*! \fn void Utils::ProgressParser::parseProgress(const QString &text) @@ -241,6 +243,14 @@ void ShellCommand::addTask(QFuture &future) Q_UNUSED(future); } +int ShellCommand::timeoutS() const +{ + return std::accumulate(d->m_jobs.cbegin(), d->m_jobs.cend(), 0, + [](int sum, const Internal::ShellCommandPrivate::Job &job) { + return sum + job.timeoutS; + }); +} + QString ShellCommand::workDirectory(const QString &wd) const { if (!wd.isEmpty()) @@ -474,6 +484,11 @@ void ShellCommand::setProgressParser(ProgressParser *parser) d->m_progressParser = parser; } +bool ShellCommand::hasProgressParser() const +{ + return d->m_progressParser; +} + void ShellCommand::setProgressiveOutput(bool progressive) { d->m_progressiveOutput = progressive; diff --git a/src/libs/utils/shellcommand.h b/src/libs/utils/shellcommand.h index ce5957c40af..c8bf38af111 100644 --- a/src/libs/utils/shellcommand.h +++ b/src/libs/utils/shellcommand.h @@ -136,6 +136,7 @@ public: void setCodec(QTextCodec *codec); void setProgressParser(ProgressParser *parser); + bool hasProgressParser() const; void setProgressiveOutput(bool progressive); void setOutputProxyFactory(const std::function &factory); @@ -161,6 +162,7 @@ signals: protected: virtual unsigned processFlags() const; virtual void addTask(QFuture &future); + int timeoutS() const; QString workDirectory(const QString &wd) const; private: diff --git a/src/plugins/coreplugin/shellcommand.cpp b/src/plugins/coreplugin/shellcommand.cpp index 4f6a028e51c..a236c906e4d 100644 --- a/src/plugins/coreplugin/shellcommand.cpp +++ b/src/plugins/coreplugin/shellcommand.cpp @@ -28,6 +28,9 @@ #include "icore.h" #include "progressmanager/progressmanager.h" +#include +#include + namespace Core { ShellCommand::ShellCommand(const QString &workingDirectory, const QProcessEnvironment &environment) : @@ -40,7 +43,23 @@ ShellCommand::ShellCommand(const QString &workingDirectory, const QProcessEnviro void ShellCommand::addTask(QFuture &future) { const QString name = displayName(); - Core::ProgressManager::addTask(future, name, Core::Id::fromString(name + QLatin1String(".action"))); + const auto id = Core::Id::fromString(name + QLatin1String(".action")); + if (hasProgressParser()) { + ProgressManager::addTask(future, name, id); + } else { + // add a timed tasked based on timeout + // we cannot access the future interface directly, so we need to create a new one + // with the same lifetime + auto fi = new QFutureInterface(); + auto watcher = new QFutureWatcher(); + connect(watcher, &QFutureWatcherBase::finished, [fi, watcher] { + fi->reportFinished(); + delete fi; + watcher->deleteLater(); + }); + watcher->setFuture(future); + ProgressManager::addTimedTask(*fi, name, id, qMax(2, timeoutS() / 5)/*itsmagic*/); + } } void ShellCommand::coreAboutToClose()