diff --git a/win-linux/extras/update-daemon/src/classes/csocket.h b/win-linux/extras/update-daemon/src/classes/csocket.h index 12568e0c4..184c0575e 100644 --- a/win-linux/extras/update-daemon/src/classes/csocket.h +++ b/win-linux/extras/update-daemon/src/classes/csocket.h @@ -66,6 +66,7 @@ enum MsgCommands { MSG_StartReplacingFiles, MSG_ClearTempFiles, MSG_Progress, + MSG_UnzipProgress, MSG_StopDownload, MSG_OtherError, MSG_SetLanguage, diff --git a/win-linux/extras/update-daemon/src/classes/csvcmanager.cpp b/win-linux/extras/update-daemon/src/classes/csvcmanager.cpp index ef7716c32..057244d3a 100644 --- a/win-linux/extras/update-daemon/src/classes/csvcmanager.cpp +++ b/win-linux/extras/update-daemon/src/classes/csvcmanager.cpp @@ -224,6 +224,9 @@ void CSvcManager::init() m_pUnzip->onComplete([=](int error) { onCompleteUnzip(error); }); + m_pUnzip->onProgress([=](int percent) { + m_socket->sendMessage(MSG_UnzipProgress, to_tstring(percent)); + }); m_socket->onMessageReceived([=](void *data, size_t) { vector params; if (m_socket->parseMessage(data, params) == 3) { diff --git a/win-linux/extras/update-daemon/src/classes/platform_linux/cunzip.cpp b/win-linux/extras/update-daemon/src/classes/platform_linux/cunzip.cpp index 9a0a0c242..28a1667c9 100644 --- a/win-linux/extras/update-daemon/src/classes/platform_linux/cunzip.cpp +++ b/win-linux/extras/update-daemon/src/classes/platform_linux/cunzip.cpp @@ -34,6 +34,7 @@ #include "platform_linux/utils.h" #include #include +#include #include #define BLOCK_SIZE 10240 @@ -53,6 +54,10 @@ public: error = "Archive path is empty or dest dir not exist"; return UNZIP_ERROR; } + int prev_percent = -1; + struct stat file_stat; + long total_size = (stat(zipFilePath.c_str(), &file_stat) == 0) ? file_stat.st_size : 0; + struct archive *arch = archive_read_new(); archive_read_support_filter_xz(arch); archive_read_support_format_tar(arch); @@ -89,6 +94,13 @@ public: error = "Cannot extract entry"; break; } + if (total_size > 0 && progress_callback) { + int percent = static_cast(100.0 * ((double)archive_filter_bytes(arch, -1)/total_size)); + if (percent != prev_percent) { + progress_callback(percent); + prev_percent = percent; + } + } } } @@ -102,7 +114,8 @@ public: return ex_code; } - FnVoidInt complete_callback = nullptr; + FnVoidInt complete_callback = nullptr, + progress_callback = nullptr; std::atomic_bool run; std::future future; }; @@ -148,3 +161,8 @@ void CUnzip::onComplete(FnVoidInt callback) { pimpl->complete_callback = callback; } + +void CUnzip::onProgress(FnVoidInt callback) +{ + pimpl->progress_callback = callback; +} diff --git a/win-linux/extras/update-daemon/src/classes/platform_linux/cunzip.h b/win-linux/extras/update-daemon/src/classes/platform_linux/cunzip.h index 60bfe68b0..4dbccbc62 100644 --- a/win-linux/extras/update-daemon/src/classes/platform_linux/cunzip.h +++ b/win-linux/extras/update-daemon/src/classes/platform_linux/cunzip.h @@ -57,6 +57,7 @@ public: /* callback */ void onComplete(FnVoidInt callback); + void onProgress(FnVoidInt callback); private: class CUnzipPrivate; diff --git a/win-linux/extras/update-daemon/src/classes/platform_win/cunzip.cpp b/win-linux/extras/update-daemon/src/classes/platform_win/cunzip.cpp index faa44e8d0..d3d7d4224 100644 --- a/win-linux/extras/update-daemon/src/classes/platform_win/cunzip.cpp +++ b/win-linux/extras/update-daemon/src/classes/platform_win/cunzip.cpp @@ -44,6 +44,40 @@ public: ~CUnzipPrivate() {} + bool calcFilesCountRecursively(IShellDispatch *pISD, const CComPtr &pSrcFolder) + { + CComPtr pItems; + if (FAILED(pSrcFolder->Items(&pItems))) + return false; + + long itemCount = 0; + if (FAILED(pItems->get_Count(&itemCount))) + return false; + + for (int i = 0; i < itemCount; i++) { + CComPtr pItem; + if (FAILED(pItems->Item(CComVariant(i), &pItem))) + return false; + + VARIANT_BOOL isFolder = VARIANT_FALSE; + if (FAILED(pItem->get_IsFolder(&isFolder))) + return false; + + if (isFolder == VARIANT_TRUE) { + CComPtr pSubFolder; + if (FAILED(pISD->NameSpace(CComVariant(pItem), &pSubFolder))) + return false; + + if (!calcFilesCountRecursively(pISD, pSubFolder)) + return false; + + } else { + ++total_count; + } + } + return true; + } + int extractRecursively(IShellDispatch *pISD, const CComPtr &pSrcFolder, const wstring &destFolder) { CComPtr pItems; @@ -92,6 +126,14 @@ public: return UNZIP_ERROR; if (FAILED(pDestFolder->CopyHere(CComVariant(pItem), CComVariant(1024 | 512 | 16 | 4)))) return UNZIP_ERROR; + if (total_count > 0 && progress_callback) { + ++curr_count; + int percent = static_cast(100.0 * ((double)curr_count / total_count)); + if (percent != prev_percent) { + progress_callback(percent); + prev_percent = percent; + } + } } } return UNZIP_OK; @@ -122,6 +164,12 @@ public: CoUninitialize(); return UNZIP_ERROR; } + + prev_percent = -1; + curr_count = 0; + total_count = 0; + if (!calcFilesCountRecursively(pShell, pSrcFolder)) + total_count = 0; int res = extractRecursively(pShell, pSrcFolder, path); pSrcFolder.Release(); pShell->Release(); @@ -129,9 +177,13 @@ public: return res; } - FnVoidInt complete_callback = nullptr; + FnVoidInt complete_callback = nullptr, + progress_callback = nullptr; std::atomic_bool run; std::future future; + int curr_count = 0, + total_count = 0, + prev_percent = -1; }; CUnzip::CUnzip() : @@ -170,3 +222,8 @@ void CUnzip::onComplete(FnVoidInt callback) { pimpl->complete_callback = callback; } + +void CUnzip::onProgress(FnVoidInt callback) +{ + pimpl->progress_callback = callback; +} diff --git a/win-linux/extras/update-daemon/src/classes/platform_win/cunzip.h b/win-linux/extras/update-daemon/src/classes/platform_win/cunzip.h index 5938fea96..f5b96d821 100644 --- a/win-linux/extras/update-daemon/src/classes/platform_win/cunzip.h +++ b/win-linux/extras/update-daemon/src/classes/platform_win/cunzip.h @@ -57,6 +57,7 @@ public: /* callback */ void onComplete(FnVoidInt callback); + void onProgress(FnVoidInt callback); private: class CUnzipPrivate; diff --git a/win-linux/src/cupdatemanager.cpp b/win-linux/src/cupdatemanager.cpp index 857ea1d4b..9bc1981f7 100644 --- a/win-linux/src/cupdatemanager.cpp +++ b/win-linux/src/cupdatemanager.cpp @@ -91,6 +91,7 @@ const char *SVC_TXT_ERR_UNPACKING = QT_TRANSLATE_NOOP("CUpdateManager", "An er *TXT_AVAILABLE_UPD = QT_TRANSLATE_NOOP("CUpdateManager", "Update is available (version %1)"), *TXT_DOWNLOADING_UPD = QT_TRANSLATE_NOOP("CUpdateManager", "Downloading new version %1 (%2%)"), *TXT_PREPARING_UPD = QT_TRANSLATE_NOOP("CUpdateManager", "Preparing update..."), + *TXT_UNZIP_UPD = QT_TRANSLATE_NOOP("CUpdateManager", "Preparing update (%1%)"), *TXT_RESTART_TO_UPD = QT_TRANSLATE_NOOP("CUpdateManager", "To finish updating, restart app"), *TXT_ERR_NOT_ALLOWED = QT_TRANSLATE_NOOP("CUpdateManager", "Updates are not allowed!"), *TXT_ERR_URL = QT_TRANSLATE_NOOP("CUpdateManager", "Unable to check update: URL not defined."), @@ -351,6 +352,10 @@ void CUpdateManager::init() QMetaObject::invokeMethod(this, "onProgressSlot", Qt::QueuedConnection, Q_ARG(int, std::stoi(params[1]))); break; + case MSG_UnzipProgress: + QMetaObject::invokeMethod(this, "onUnzipProgressSlot", Qt::QueuedConnection, Q_ARG(int, std::stoi(params[1]))); + break; + case MSG_RequestContentLenght: { double fileSize = std::stod(params[1])/1024/1024; m_packageData->fileSize = (fileSize == 0) ? "--" : QString::number(fileSize, 'f', 1); @@ -450,6 +455,11 @@ void CUpdateManager::onProgressSlot(const int percent) refreshStartPage({"", {TXT_DOWNLOADING_UPD, m_packageData->version, QString::number(percent)}}); } +void CUpdateManager::onUnzipProgressSlot(const int percent) +{ + refreshStartPage({"", {TXT_UNZIP_UPD, QString::number(percent)}}); +} + void CUpdateManager::onError(const QString &error) { const char *_error = SVC_TXT_ERR_OTHER; diff --git a/win-linux/src/cupdatemanager.h b/win-linux/src/cupdatemanager.h index 56303444d..df6e89095 100644 --- a/win-linux/src/cupdatemanager.h +++ b/win-linux/src/cupdatemanager.h @@ -141,6 +141,7 @@ private slots: void onLoadUpdateFinished(const QString &filePath); void showStartInstallMessage(QWidget *parent); void onProgressSlot(const int percent); + void onUnzipProgressSlot(const int percent); void onError(const QString &error); void criticalMsg(QWidget *parent, const QString &msg); };