From c20eedf9f65cb2321f881d12dd810911743dd59a Mon Sep 17 00:00:00 2001 From: Veloman Yunkan Date: Wed, 13 Dec 2023 21:33:11 +0400 Subject: [PATCH] ContentManagerModel maintains the download state This fixes the bugs related to pending download statuses being discarded by filtering and similar operations that result in full update of the ContentManagerModel. Instead this commit leads to a new bug - completion of a download is not always properly detected for very small (and thus instantaneous) downloads. This is caused by library update events triggered by ZIM directory monitoring (which notifies about a new ZIM file appearing in the download directory) interfering with the download status update signal. --- src/contentmanagermodel.cpp | 24 ++++++++++++++++++++---- src/contentmanagermodel.h | 2 ++ src/rownode.cpp | 4 +++- src/rownode.h | 2 +- 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/contentmanagermodel.cpp b/src/contentmanagermodel.cpp index cbca712..91d195f 100644 --- a/src/contentmanagermodel.cpp +++ b/src/contentmanagermodel.cpp @@ -136,6 +136,7 @@ std::shared_ptr ContentManagerModel::createNode(BookInfo bookItem, QMap }, id, weakRoot)); std::weak_ptr weakRowNodePtr = rowNodePtr; const auto descNodePtr = std::make_shared(DescriptionNode(bookItem["description"].toString(), weakRowNodePtr)); + rowNodePtr->appendChild(descNodePtr); return rowNodePtr; } @@ -144,7 +145,15 @@ void ContentManagerModel::setupNodes() { beginResetModel(); for (auto bookItem : m_data) { - rootNode->appendChild(createNode(bookItem, iconMap)); + const auto rowNode = createNode(bookItem, iconMap); + + // Restore download state during model updates (filtering, etc) + const auto downloadIter = m_downloads.constFind(rowNode->getBookId()); + if ( downloadIter != m_downloads.constEnd() ) { + rowNode->setDownloadState(downloadIter.value()); + } + + rootNode->appendChild(rowNode); } endResetModel(); } @@ -239,10 +248,16 @@ std::shared_ptr getSharedPointer(RowNode* ptr) void ContentManagerModel::startDownload(QModelIndex index) { auto node = getSharedPointer(static_cast(index.internalPointer())); - node->setDownloadState(new DownloadState); - QTimer *timer = node->getDownloadState()->getDownloadUpdateTimer(); + const auto bookId = node->getBookId(); + const auto newDownload = std::make_shared(); + m_downloads[bookId] = newDownload; + node->setDownloadState(newDownload); + QTimer *timer = newDownload->getDownloadUpdateTimer(); connect(timer, &QTimer::timeout, this, [=]() { - node->getDownloadState()->update(node->getBookId()); + if ( ! newDownload->update(bookId) ) { + m_downloads.remove(bookId); + node->setDownloadState(nullptr); + } emit dataChanged(index, index); }); } @@ -265,6 +280,7 @@ void ContentManagerModel::cancelDownload(QModelIndex index) { auto node = static_cast(index.internalPointer()); node->setDownloadState(nullptr); + m_downloads.remove(node->getBookId()); emit dataChanged(index, index); } diff --git a/src/contentmanagermodel.h b/src/contentmanagermodel.h index 2a86b01..1a42190 100644 --- a/src/contentmanagermodel.h +++ b/src/contentmanagermodel.h @@ -6,6 +6,7 @@ #include #include #include "thumbnaildownloader.h" +#include "rownode.h" #include class RowNode; @@ -58,6 +59,7 @@ private: // data int zimCount = 0; ThumbnailDownloader td; QMap iconMap; + QMap> m_downloads; }; #endif // CONTENTMANAGERMODEL_H diff --git a/src/rownode.cpp b/src/rownode.cpp index 5d03ad5..2a5c15f 100644 --- a/src/rownode.cpp +++ b/src/rownode.cpp @@ -33,7 +33,7 @@ QString convertToUnits(QString size) } // unnamed namespace -void DownloadState::update(QString id) +bool DownloadState::update(QString id) { auto downloadInfos = KiwixApp::instance()->getContentManager()->updateDownloadInfos(id, {"status", "completedLength", "totalLength", "downloadSpeed"}); double percent = downloadInfos["completedLength"].toDouble() / downloadInfos["totalLength"].toDouble(); @@ -51,7 +51,9 @@ void DownloadState::update(QString id) // from another thread. m_downloadUpdateTimer.reset(); m_downloadInfo = {0, "", "", false}; + return false; } + return true; } void DownloadState::pause() diff --git a/src/rownode.h b/src/rownode.h index bbcf25d..85cbe61 100644 --- a/src/rownode.h +++ b/src/rownode.h @@ -24,7 +24,7 @@ public: QTimer* getDownloadUpdateTimer() const { return m_downloadUpdateTimer.get(); } void pause(); void resume(); - void update(QString id); + bool update(QString id); protected: // This is non-NULL only for a pending (even if paused) download