diff --git a/src/frontend/helpers/import_job.cpp b/src/frontend/helpers/import_job.cpp index 2486d7a..07eec52 100644 --- a/src/frontend/helpers/import_job.cpp +++ b/src/frontend/helpers/import_job.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include "frontend/helpers/import_job.h" ImportJob::ImportJob(QObject* parent, Core::SDMCImporter& importer_, @@ -11,12 +12,31 @@ ImportJob::ImportJob(QObject* parent, Core::SDMCImporter& importer_, ImportJob::~ImportJob() = default; void ImportJob::run() { - u64 size_imported = 0, count = 0; + u64 total_size = 0; for (const auto& content : contents) { - emit NextContent(size_imported, count + 1, content); - const auto callback = [this, size_imported](std::size_t current_size, - std::size_t /*total_size*/) { - emit ProgressUpdated(size_imported + current_size, current_size); + total_size += content.maximum_size; + } + + u64 size_imported = 0, count = 0; + int eta = -1; + + const auto initial_time = std::chrono::steady_clock::now(); + const auto UpdateETA = [total_size, &eta, initial_time](u64 size_imported) { + if (size_imported >= 10 * 1024 * 1024) { // 10M Threshold + using namespace std::chrono; + const u64 time_elapsed = + duration_cast(steady_clock::now() - initial_time).count(); + eta = static_cast(time_elapsed * (total_size - size_imported) / (size_imported) / + 1000); + } + }; + + for (const auto& content : contents) { + emit NextContent(size_imported, count + 1, content, eta); + const auto callback = [this, total_size, size_imported, &eta, + &UpdateETA](std::size_t current_size, std::size_t /*total_size*/) { + UpdateETA(size_imported + current_size); + emit ProgressUpdated(size_imported + current_size, current_size, eta); }; if (!importer.ImportContent(content, callback)) { importer.DeleteContent(content); @@ -26,6 +46,7 @@ void ImportJob::run() { } count++; size_imported += content.maximum_size; + UpdateETA(size_imported); if (cancelled) { break; diff --git a/src/frontend/helpers/import_job.h b/src/frontend/helpers/import_job.h index b016d7b..3e0a3e0 100644 --- a/src/frontend/helpers/import_job.h +++ b/src/frontend/helpers/import_job.h @@ -27,11 +27,12 @@ signals: * @param total_size_imported Total imported size taking all previous contents into * consideration. * @param current_size_imported Imported size of the current content. + * @param eta ETA in seconds, 0 when not determined. */ - void ProgressUpdated(u64 total_size_imported, u64 current_size_imported); + void ProgressUpdated(u64 total_size_imported, u64 current_size_imported, int eta); /// Dumping of a content has been finished, go on to the next. Called at start as well. - void NextContent(u64 size_imported, u64 count, Core::ContentSpecifier next_content); + void NextContent(u64 size_imported, u64 count, Core::ContentSpecifier next_content, int eta); void Completed(); diff --git a/src/frontend/import_dialog.cpp b/src/frontend/import_dialog.cpp index 4caa830..3a6c269 100644 --- a/src/frontend/import_dialog.cpp +++ b/src/frontend/import_dialog.cpp @@ -446,6 +446,15 @@ std::vector ImportDialog::GetSelectedContentList() { return to_import; } +static QString FormatETA(int eta) { + if (eta < 0) { + return QStringLiteral(" "); + } + return QCoreApplication::translate("ImportDialog", "ETA %1m%2s") + .arg(eta / 60, 2, 10, QLatin1Char('0')) + .arg(eta % 60, 2, 10, QLatin1Char('0')); +} + void ImportDialog::StartImporting() { UpdateSizeDisplay(); if (!ui->buttonBox->button(QDialogButtonBox::StandardButton::Ok)->isEnabled()) { @@ -478,29 +487,31 @@ void ImportDialog::StartImporting() { connect(job, &ImportJob::NextContent, this, [this, dialog, multiplier, total_count](u64 size_imported, u64 count, - Core::ContentSpecifier next_content) { + Core::ContentSpecifier next_content, int eta) { dialog->setValue(static_cast(size_imported / multiplier)); dialog->setLabelText( - tr("

(%1/%2) Importing %3 (%4)...

") + tr("

(%1/%2) Importing %3 (%4)...

 

%5

") .arg(count) .arg(total_count) .arg(GetContentName(next_content)) - .arg(GetContentTypeName(next_content.type))); + .arg(GetContentTypeName(next_content.type)) + .arg(FormatETA(eta))); current_content = next_content; current_count = count; }); connect(job, &ImportJob::ProgressUpdated, this, [this, dialog, multiplier, total_count](u64 total_size_imported, - u64 current_size_imported) { + u64 current_size_imported, int eta) { dialog->setValue(static_cast(total_size_imported / multiplier)); - dialog->setLabelText(tr("

(%1/%2) Importing %3 (%4)...

%5 / %6

") + dialog->setLabelText(tr("

(%1/%2) Importing %3 (%4)...

%5 " + "/ %6

%7

") .arg(current_count) .arg(total_count) .arg(GetContentName(current_content)) .arg(GetContentTypeName(current_content.type)) .arg(ReadableByteSize(current_size_imported)) - .arg(ReadableByteSize(current_content.maximum_size))); + .arg(ReadableByteSize(current_content.maximum_size)) + .arg(FormatETA(eta))); }); connect(job, &ImportJob::Completed, this, [this, dialog, job] { dialog->setValue(dialog->maximum());