diff --git a/src/contentmanager.cpp b/src/contentmanager.cpp index ebe39dc..c3adca4 100644 --- a/src/contentmanager.cpp +++ b/src/contentmanager.cpp @@ -525,16 +525,36 @@ void ContentManager::downloadBook(const QString &id) return; } - startDownload(id); + mp_library->addBookBeingDownloaded(book, downloadPath); + mp_library->save(); + + DownloadManager::addRequest(DownloadState::START, id); + const auto downloadState = DownloadManager::getDownloadState(id); + managerModel->setDownloadState(id, downloadState); } +// This function is called asynchronously in a worker thread processing all +// download operations. The call is initiated in downloadBook(). void ContentManager::startDownload(QString id) { kiwix::Book book = getRemoteOrLocalBook(id); const auto downloadPath = getSettingsManager()->getDownloadDir(); + // downloadPath may be different from the value used in + // downloadBook(). This may happen in the following scenario: + // + // 1. aria2c is stuck because of having to save to + // slow storage (and the fact that it is a single-threaded + // application). This may result in startDownload() being + // called with significant delay after downloadBook(). + // + // 2. The user changes the download directory after starting + // a download. + // + // That's why the checkThatBookCanBeDownloaded() check is repeated here. std::string downloadId; try { + DownloadManager::checkThatBookCanBeDownloaded(book, downloadPath); downloadId = DownloadManager::startDownload(book, downloadPath); } catch ( const KiwixAppError& err ) { emit error(err.summary(), err.details()); @@ -544,8 +564,6 @@ void ContentManager::startDownload(QString id) book.setDownloadId(downloadId); mp_library->addBookBeingDownloaded(book, downloadPath); mp_library->save(); - const auto downloadState = DownloadManager::getDownloadState(id); - managerModel->setDownloadState(id, downloadState); emit(oneBookChanged(id)); } diff --git a/src/contentmanager.h b/src/contentmanager.h index f87aa70..1b697d6 100644 --- a/src/contentmanager.h +++ b/src/contentmanager.h @@ -119,7 +119,7 @@ private: // functions const kiwix::Book& getRemoteOrLocalBook(const QString &id); QString getRemoteLibraryUrl() const; - void startDownload(QString bookId); + void startDownload(QString bookId) override; void removeDownload(QString bookId); void downloadDisappeared(QString bookId); void downloadCompleted(QString bookId, QString path); diff --git a/src/downloadmanagement.cpp b/src/downloadmanagement.cpp index 20fbab0..f4f6990 100644 --- a/src/downloadmanagement.cpp +++ b/src/downloadmanagement.cpp @@ -131,7 +131,7 @@ void DownloadManager::processDownloadActions() const Request req = m_requestQueue.dequeue(); if ( !req.bookId.isEmpty() ) { switch ( req.action ) { - case DownloadState::START: /* startDownload(req.bookId); */ break; // API problem + case DownloadState::START: startDownload(req.bookId); break; case DownloadState::PAUSE: pauseDownload(req.bookId); break; case DownloadState::RESUME: resumeDownload(req.bookId); break; case DownloadState::CANCEL: cancelDownload(req.bookId); break; @@ -280,12 +280,15 @@ std::string DownloadManager::startDownload(const kiwix::Book& book, const QStrin } catch (std::exception& e) { throwDownloadUnavailableError(); } - m_downloads.set(bookId, std::make_shared()); return downloadId; } void DownloadManager::addRequest(Action action, QString bookId) { + if ( action == DownloadState::START ) { + m_downloads.set(bookId, std::make_shared()); + } + if ( const auto downloadState = getDownloadState(bookId) ) { m_requestQueue.enqueue({action, bookId}); if ( action != DownloadState::UPDATE ) { diff --git a/src/downloadmanagement.h b/src/downloadmanagement.h index 48f55f1..38e77df 100644 --- a/src/downloadmanagement.h +++ b/src/downloadmanagement.h @@ -160,8 +160,6 @@ public: // functions // successful download void checkThatBookCanBeDownloaded(const kiwix::Book& book, const QString& downloadDirPath); - // returns the download id - std::string startDownload(const kiwix::Book& book, const QString& downloadDirPath); void removeDownload(QString bookId); DownloadStatePtr getDownloadState(QString bookId) const @@ -175,6 +173,10 @@ signals: void downloadCancelled(QString bookId); void downloadDisappeared(QString bookId); +protected: + // returns the download id + std::string startDownload(const kiwix::Book& book, const QString& downloadDirPath); + private: // types struct Request { @@ -190,6 +192,7 @@ private: // types private: // functions void processDownloadActions(); + virtual void startDownload(QString bookId) = 0; void pauseDownload(const QString& bookId); void resumeDownload(const QString& bookId); void updateDownload(QString bookId);