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.
This commit is contained in:
Veloman Yunkan 2023-12-13 21:33:11 +04:00
parent ef2131d7f3
commit c20eedf9f6
4 changed files with 26 additions and 6 deletions

View File

@ -136,6 +136,7 @@ std::shared_ptr<RowNode> ContentManagerModel::createNode(BookInfo bookItem, QMap
}, id, weakRoot));
std::weak_ptr<RowNode> weakRowNodePtr = rowNodePtr;
const auto descNodePtr = std::make_shared<DescriptionNode>(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<RowNode> getSharedPointer(RowNode* ptr)
void ContentManagerModel::startDownload(QModelIndex index)
{
auto node = getSharedPointer(static_cast<RowNode*>(index.internalPointer()));
node->setDownloadState(new DownloadState);
QTimer *timer = node->getDownloadState()->getDownloadUpdateTimer();
const auto bookId = node->getBookId();
const auto newDownload = std::make_shared<DownloadState>();
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<RowNode*>(index.internalPointer());
node->setDownloadState(nullptr);
m_downloads.remove(node->getBookId());
emit dataChanged(index, index);
}

View File

@ -6,6 +6,7 @@
#include <QVariant>
#include <QIcon>
#include "thumbnaildownloader.h"
#include "rownode.h"
#include <memory>
class RowNode;
@ -58,6 +59,7 @@ private: // data
int zimCount = 0;
ThumbnailDownloader td;
QMap<QString, QByteArray> iconMap;
QMap<QString, std::shared_ptr<DownloadState>> m_downloads;
};
#endif // CONTENTMANAGERMODEL_H

View File

@ -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()

View File

@ -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