feat: estimate remining time on downloads
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
This commit is contained in:
		| @@ -93,6 +93,59 @@ QString truncateUrlHumanFriendly(QUrl &url, int max_len, bool hard_limit = false | ||||
|  | ||||
| } | ||||
|  | ||||
| QString humanReadableDuration(double duration, int precision = 0) { | ||||
|  | ||||
|     using days = std::chrono::duration<int, std::ratio<86400>>; | ||||
|  | ||||
|     QString outStr; | ||||
|     QTextStream os(&outStr); | ||||
|  | ||||
|     auto std_duration = std::chrono::duration<double>(duration); | ||||
|     auto d = std::chrono::duration_cast<days>(std_duration); | ||||
|     std_duration -= d; | ||||
|     auto h = std::chrono::duration_cast<std::chrono::hours>(std_duration); | ||||
|     std_duration -= h; | ||||
|     auto m = std::chrono::duration_cast<std::chrono::minutes>(std_duration); | ||||
|     std_duration -= m; | ||||
|     auto s = std::chrono::duration_cast<std::chrono::seconds>(std_duration); | ||||
|     std_duration -= s; | ||||
|     auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(std_duration); | ||||
|  | ||||
|     auto dc = d.count(); | ||||
|     auto hc = h.count(); | ||||
|     auto mc = m.count(); | ||||
|     auto sc = s.count(); | ||||
|     auto msc = ms.count(); | ||||
|  | ||||
|     if (dc) { | ||||
|         os << dc << "days"; | ||||
|     } | ||||
|     if (hc) { | ||||
|         if (dc) | ||||
|             os << " "; | ||||
|         os << qSetFieldWidth(2) << hc << "h"; | ||||
|     } | ||||
|     if (mc) { | ||||
|         if (dc || hc) | ||||
|             os << " "; | ||||
|         os << qSetFieldWidth(2) << mc << "m"; | ||||
|     } | ||||
|     if (dc || hc || mc || sc) { | ||||
|         if (dc || hc || mc) | ||||
|             os << " "; | ||||
|         os << qSetFieldWidth(2) << sc << "s"; | ||||
|     } | ||||
|     if ((msc && (precision > 0)) || !(dc || hc || mc || sc)) { | ||||
|         if (dc || hc || mc || sc) | ||||
|             os << " "; | ||||
|         os << qSetFieldWidth(0) << qSetRealNumberPrecision(precision) << msc << "ms"; | ||||
|     } | ||||
|  | ||||
|     os.flush(); | ||||
|  | ||||
|     return outStr; | ||||
| } | ||||
|  | ||||
| auto Download::makeCached(QUrl url, MetaEntryPtr entry, Options options) -> Download::Ptr | ||||
| { | ||||
|     auto dl = makeShared<Download>(); | ||||
| @@ -193,21 +246,23 @@ void Download::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) | ||||
|     auto elapsed = now - m_last_progress_time; | ||||
|  | ||||
|     // use milliseconds for speed precision | ||||
|     auto elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count(); | ||||
|     auto elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed); | ||||
|     auto bytes_recived_since = bytesReceived - m_last_progress_bytes; | ||||
|     auto dl_speed_bps = (double)bytes_recived_since / elapsed_ms.count() * 1000; | ||||
|     auto remaing_time_s = (bytesTotal - bytesReceived) / dl_speed_bps; | ||||
|  | ||||
|     // current bytes out of total bytes | ||||
|     QString dl_progress = tr("%1  / %2").arg(humanReadableFileSize(bytesReceived)).arg(humanReadableFileSize(bytesTotal)); | ||||
|      | ||||
|     QString dl_speed; | ||||
|     if (elapsed_ms > 0) { | ||||
|     QString dl_speed_str; | ||||
|     if (elapsed_ms.count() > 0) { | ||||
|         // bytes per second | ||||
|         dl_speed = tr("%1/s").arg(humanReadableFileSize(bytes_recived_since / elapsed_ms * 1000)); | ||||
|         dl_speed_str = tr("%1/s (%2)").arg(humanReadableFileSize(dl_speed_bps)).arg(humanReadableDuration(remaing_time_s)); | ||||
|     } else { | ||||
|         dl_speed = tr("0 b/s"); | ||||
|         dl_speed_str = tr("0 b/s"); | ||||
|     }  | ||||
|  | ||||
|     setDetails(dl_progress + "\n" + dl_speed); | ||||
|     setDetails(dl_progress + "\n" + dl_speed_str); | ||||
|  | ||||
|     setProgress(bytesReceived, bytesTotal); | ||||
| } | ||||
|   | ||||
| @@ -47,20 +47,19 @@ | ||||
| static const QStringList s_units_si  {"kb", "MB", "GB", "TB"}; | ||||
| static const QStringList s_units_kibi {"kiB", "MiB", "Gib", "TiB"}; | ||||
|  | ||||
| inline QString humanReadableFileSize(qint64 bytes, bool use_si = false, int decimal_points = 1) { | ||||
| inline QString humanReadableFileSize(double bytes, bool use_si = false, int decimal_points = 1) { | ||||
|     const QStringList units = use_si ? s_units_si : s_units_kibi; | ||||
|     const int scale = use_si ? 1000 : 1024; | ||||
|     double size = bytes; | ||||
|  | ||||
|     int u = -1; | ||||
|     double r = pow(10,  decimal_points); | ||||
|  | ||||
|     do { | ||||
|         size /= scale; | ||||
|         bytes /= scale; | ||||
|         u++; | ||||
|     } while (round(abs(size) * r) / r >= scale && u < units.length() - 1); | ||||
|     } while (round(abs(bytes) * r) / r >= scale && u < units.length() - 1); | ||||
|  | ||||
|     return QString::number(size, 'f', 2) + " " + units[u]; | ||||
|     return QString::number(bytes, 'f', 2) + " " + units[u]; | ||||
| } | ||||
|  | ||||
| class NetAction : public Task { | ||||
|   | ||||
| @@ -197,6 +197,10 @@ void ConcurrentTask::subTaskStatus(Task::Ptr task, const QString& msg) | ||||
|     task_progress->state = TaskStepState::Running; | ||||
|      | ||||
|     emit stepProgress(*task_progress.get()); | ||||
|  | ||||
|     if (totalSize() == 1) { | ||||
|         setStatus(msg); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void ConcurrentTask::subTaskDetails(Task::Ptr task, const QString& msg) | ||||
| @@ -206,6 +210,10 @@ void ConcurrentTask::subTaskDetails(Task::Ptr task, const QString& msg) | ||||
|     task_progress->state = TaskStepState::Running; | ||||
|      | ||||
|     emit stepProgress(*task_progress.get()); | ||||
|  | ||||
|     if (totalSize() == 1) { | ||||
|         setDetails(msg); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void ConcurrentTask::subTaskProgress(Task::Ptr task, qint64 current, qint64 total) | ||||
| @@ -222,6 +230,10 @@ void ConcurrentTask::subTaskProgress(Task::Ptr task, qint64 current, qint64 tota | ||||
|     emit stepProgress(*task_progress.get()); | ||||
|     updateStepProgress(*task_progress.get(), Operation::CHANGED); | ||||
|     updateState(); | ||||
|  | ||||
|     if (totalSize() == 1) { | ||||
|         setProgress(task_progress->current, task_progress->total); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void ConcurrentTask::subTaskStepProgress(Task::Ptr task, TaskStepProgress const& task_progress) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user