summaryrefslogtreecommitdiffstats
path: root/src/libs/installer
diff options
context:
space:
mode:
authorArttu Tarkiainen <arttu.tarkiainen@qt.io>2021-06-23 10:12:36 +0300
committerArttu Tarkiainen <arttu.tarkiainen@qt.io>2021-08-19 11:57:50 +0300
commit9729cdff85eb1aef0c1713b5b0d811fe9af50d2b (patch)
tree16ed86523cbafc3bd726307e9a106f41dea8e02c /src/libs/installer
parenta89e9e2917f0e783ced39769b879b0f4c53e144a (diff)
Add total remaining download time estimation for archives
Task-number: QTIFW-2207 Change-Id: Ia4ccc5f71a489a1663cdbf66a69f442366e65fc9 Reviewed-by: Katja Marttila <katja.marttila@qt.io>
Diffstat (limited to 'src/libs/installer')
-rw-r--r--src/libs/installer/downloadarchivesjob.cpp81
-rw-r--r--src/libs/installer/downloadarchivesjob.h11
-rw-r--r--src/libs/installer/packagemanagercore.cpp3
-rw-r--r--src/libs/installer/performinstallationform.cpp7
4 files changed, 96 insertions, 6 deletions
diff --git a/src/libs/installer/downloadarchivesjob.cpp b/src/libs/installer/downloadarchivesjob.cpp
index 5dbccc0b6..c7ba9dc80 100644
--- a/src/libs/installer/downloadarchivesjob.cpp
+++ b/src/libs/installer/downloadarchivesjob.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -32,6 +32,7 @@
#include "messageboxhandler.h"
#include "packagemanagercore.h"
#include "utils.h"
+#include "fileutils.h"
#include "filedownloader.h"
#include "filedownloaderfactory.h"
@@ -55,6 +56,8 @@ DownloadArchivesJob::DownloadArchivesJob(PackageManagerCore *core)
, m_canceled(false)
, m_lastFileProgress(0)
, m_progressChangedTimerId(0)
+ , m_totalSizeToDownload(0)
+ , m_totalSizeDownloaded(0)
{
setCapabilities(Cancelable);
}
@@ -79,10 +82,19 @@ void DownloadArchivesJob::setArchivesToDownload(const QList<QPair<QString, QStri
}
/*!
+ Sets the expected total size of archives to download to \a total.
+*/
+void DownloadArchivesJob::setExpectedTotalSize(quint64 total)
+{
+ m_totalSizeToDownload = total;
+}
+
+/*!
\reimp
*/
void DownloadArchivesJob::doStart()
{
+ m_totalDownloadSpeedTimer.start();
m_archivesDownloaded = 0;
fetchNextArchiveHash();
}
@@ -198,6 +210,70 @@ void DownloadArchivesJob::timerEvent(QTimerEvent *event)
}
/*!
+ Builds a textual representation of the total download \a status and
+ emits the \c {downloadStatusChanged()} signal.
+*/
+void DownloadArchivesJob::onDownloadStatusChanged(const QString &status)
+{
+ if (!m_downloader || m_canceled) {
+ emit downloadStatusChanged(status);
+ return;
+ }
+
+ QString extendedStatus;
+ quint64 currentDownloaded = m_totalSizeDownloaded + m_downloader->getBytesReceived();
+ if (m_totalSizeToDownload > 0) {
+ QString bytesReceived = humanReadableSize(currentDownloaded);
+ const QString bytesToReceive = humanReadableSize(m_totalSizeToDownload);
+
+ // remove the unit from the bytesReceived value if bytesToReceive has the same
+ const QString tmp = bytesToReceive.mid(bytesToReceive.indexOf(QLatin1Char(' ')));
+ if (bytesReceived.endsWith(tmp))
+ bytesReceived.chop(tmp.length());
+
+ extendedStatus = tr("%1 of %2").arg(bytesReceived, bytesToReceive);
+ } else if (currentDownloaded > 0) {
+ extendedStatus = tr("%1 downloaded.").arg(humanReadableSize(currentDownloaded));
+ }
+
+ const quint64 totalDownloadSpeed = currentDownloaded
+ / double(m_totalDownloadSpeedTimer.elapsed() / 1000);
+
+ if (m_totalSizeToDownload > 0 && totalDownloadSpeed > 0) {
+ const qint64 time = (m_totalSizeToDownload - currentDownloaded) / totalDownloadSpeed;
+
+ int s = time % 60;
+ const int d = time / 86400;
+ const int h = (time / 3600) - (d * 24);
+ const int m = (time / 60) - (d * 1440) - (h * 60);
+
+ QString days;
+ if (d > 0)
+ days = tr("%n day(s), ", "", d);
+
+ QString hours;
+ if (h > 0)
+ hours = tr("%n hour(s), ", "", h);
+
+ QString minutes;
+ if (m > 0)
+ minutes = tr("%n minute(s)", "", m);
+
+ QString seconds;
+ if (s >= 0 && minutes.isEmpty()) {
+ s = (s <= 0 ? 1 : s);
+ seconds = tr("%n second(s)", "", s);
+ }
+ extendedStatus += tr(" - %1%2%3%4 remaining.").arg(days, hours, minutes, seconds);
+ } else {
+ extendedStatus += tr(" - unknown time remaining.");
+ }
+
+ emit downloadStatusChanged(QLatin1String("Archive: ") + status
+ + QLatin1String("<br>Total: ") + extendedStatus);
+}
+
+/*!
Registers the just downloaded file in the installer's file system.
*/
void DownloadArchivesJob::registerFile()
@@ -224,6 +300,7 @@ void DownloadArchivesJob::registerFile()
}
} else {
++m_archivesDownloaded;
+ m_totalSizeDownloaded += QFile(m_downloader->downloadedFileName()).size();
if (m_progressChangedTimerId) {
killTimer(m_progressChangedTimerId);
m_progressChangedTimerId = 0;
@@ -295,7 +372,7 @@ KDUpdater::FileDownloader *DownloadArchivesJob::setupDownloader(const QString &s
connect(downloader, &FileDownloader::downloadCanceled, this, &DownloadArchivesJob::downloadCanceled);
connect(downloader, &FileDownloader::downloadAborted, this, &DownloadArchivesJob::downloadFailed,
Qt::QueuedConnection);
- connect(downloader, &FileDownloader::downloadStatus, this, &DownloadArchivesJob::downloadStatusChanged);
+ connect(downloader, &FileDownloader::downloadStatus, this, &DownloadArchivesJob::onDownloadStatusChanged);
if (FileDownloaderFactory::isSupportedScheme(scheme)) {
downloader->setDownloadedFileName(component->localTempPath() + QLatin1Char('/')
diff --git a/src/libs/installer/downloadarchivesjob.h b/src/libs/installer/downloadarchivesjob.h
index 8f2392064..bd764e01c 100644
--- a/src/libs/installer/downloadarchivesjob.h
+++ b/src/libs/installer/downloadarchivesjob.h
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -32,6 +32,7 @@
#include "job.h"
#include <QtCore/QPair>
+#include <QtCore/QElapsedTimer>
QT_BEGIN_NAMESPACE
class QTimerEvent;
@@ -56,6 +57,7 @@ public:
int numberOfDownloads() const { return m_archivesDownloaded; }
void setArchivesToDownload(const QList<QPair<QString, QString> > &archives);
+ void setExpectedTotalSize(quint64 total);
Q_SIGNALS:
void progressChanged(double progress);
@@ -67,6 +69,9 @@ protected:
void doCancel();
void timerEvent(QTimerEvent *event);
+public Q_SLOTS:
+ void onDownloadStatusChanged(const QString &status);
+
protected Q_SLOTS:
void registerFile();
void downloadCanceled();
@@ -92,6 +97,10 @@ private:
QByteArray m_currentHash;
double m_lastFileProgress;
int m_progressChangedTimerId;
+
+ quint64 m_totalSizeToDownload;
+ quint64 m_totalSizeDownloaded;
+ QElapsedTimer m_totalDownloadSpeedTimer;
};
} // namespace QInstaller
diff --git a/src/libs/installer/packagemanagercore.cpp b/src/libs/installer/packagemanagercore.cpp
index addb291eb..a0a010142 100644
--- a/src/libs/installer/packagemanagercore.cpp
+++ b/src/libs/installer/packagemanagercore.cpp
@@ -764,6 +764,7 @@ int PackageManagerCore::downloadNeededArchives(double partProgressSize)
Q_ASSERT(partProgressSize >= 0 && partProgressSize <= 1);
QList<QPair<QString, QString> > archivesToDownload;
+ quint64 archivesToDownloadTotalSize = 0;
QList<Component*> neededComponents = orderedComponentsToInstall();
foreach (Component *component, neededComponents) {
// collect all archives to be downloaded
@@ -773,6 +774,7 @@ int PackageManagerCore::downloadNeededArchives(double partProgressSize)
.arg(component->name(), versionFreeString), QString::fromLatin1("%1/%2/%3")
.arg(component->repositoryUrl().toString(), component->name(), versionFreeString)));
}
+ archivesToDownloadTotalSize += component->value(scCompressedSize).toULongLong();
}
if (archivesToDownload.isEmpty())
@@ -783,6 +785,7 @@ int PackageManagerCore::downloadNeededArchives(double partProgressSize)
DownloadArchivesJob archivesJob(this);
archivesJob.setAutoDelete(false);
archivesJob.setArchivesToDownload(archivesToDownload);
+ archivesJob.setExpectedTotalSize(archivesToDownloadTotalSize);
connect(this, &PackageManagerCore::installationInterrupted, &archivesJob, &Job::cancel);
connect(&archivesJob, &DownloadArchivesJob::outputTextChanged,
ProgressCoordinator::instance(), &ProgressCoordinator::emitLabelAndDetailTextChanged);
diff --git a/src/libs/installer/performinstallationform.cpp b/src/libs/installer/performinstallationform.cpp
index 31b61ceeb..a61c0d88b 100644
--- a/src/libs/installer/performinstallationform.cpp
+++ b/src/libs/installer/performinstallationform.cpp
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** Copyright (C) 2020 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Installer Framework.
@@ -121,6 +121,8 @@ void PerformInstallationForm::setupUi(QWidget *widget)
m_downloadStatus = new QLabel(widget);
m_downloadStatus->setObjectName(QLatin1String("DownloadStatus"));
m_downloadStatus->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
+ m_downloadStatus->setWordWrap(true);
+ m_downloadStatus->setTextFormat(Qt::TextFormat::RichText);
topLayout->addWidget(m_downloadStatus);
connect(ProgressCoordinator::instance(), &ProgressCoordinator::downloadStatusChanged, this,
&PerformInstallationForm::onDownloadStatusChanged);
@@ -282,8 +284,7 @@ bool PerformInstallationForm::isShowingDetails() const
*/
void PerformInstallationForm::onDownloadStatusChanged(const QString &status)
{
- m_downloadStatus->setText(m_downloadStatus->fontMetrics().elidedText(status, Qt::ElideRight,
- m_downloadStatus->width()));
+ m_downloadStatus->setText(status);
}
/*!