diff options
author | Arttu Tarkiainen <arttu.tarkiainen@qt.io> | 2021-06-23 10:12:36 +0300 |
---|---|---|
committer | Arttu Tarkiainen <arttu.tarkiainen@qt.io> | 2021-08-19 11:57:50 +0300 |
commit | 9729cdff85eb1aef0c1713b5b0d811fe9af50d2b (patch) | |
tree | 16ed86523cbafc3bd726307e9a106f41dea8e02c /src/libs/installer | |
parent | a89e9e2917f0e783ced39769b879b0f4c53e144a (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.cpp | 81 | ||||
-rw-r--r-- | src/libs/installer/downloadarchivesjob.h | 11 | ||||
-rw-r--r-- | src/libs/installer/packagemanagercore.cpp | 3 | ||||
-rw-r--r-- | src/libs/installer/performinstallationform.cpp | 7 |
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); } /*! |