From 7a83a1038d9514b5e97a850c6259110ac8cd3bed Mon Sep 17 00:00:00 2001 From: Matthieu Gautier Date: Wed, 17 Oct 2018 11:10:42 +0200 Subject: [PATCH] Handle downloading of remote books. --- kiwix-desktop.pro | 6 +- resources/texts/_contentManager.html | 41 +++++++++-- src/downloader.cpp | 104 +++++++++++++++++++++++++++ src/downloader.h | 32 +++++++++ src/kiwixapp.cpp | 4 +- src/kiwixapp.h | 2 + src/library.cpp | 8 +++ src/library.h | 1 + 8 files changed, 191 insertions(+), 7 deletions(-) create mode 100644 src/downloader.cpp create mode 100644 src/downloader.h diff --git a/kiwix-desktop.pro b/kiwix-desktop.pro index e41653d..fee6cc3 100644 --- a/kiwix-desktop.pro +++ b/kiwix-desktop.pro @@ -57,7 +57,8 @@ SOURCES += \ src/about.cpp \ src/tocsidebar.cpp \ src/contentmanager.cpp \ - src/contentmanagerview.cpp + src/contentmanagerview.cpp \ + src/downloader.cpp HEADERS += \ src/mainwindow.h \ @@ -76,7 +77,8 @@ HEADERS += \ src/about.h \ src/tocsidebar.h \ src/contentmanager.h \ - src/contentmanagerview.h + src/contentmanagerview.h \ + src/downloader.h FORMS += \ ui/mainwindow.ui \ diff --git a/resources/texts/_contentManager.html b/resources/texts/_contentManager.html index ccb640d..bfe2961 100644 --- a/resources/texts/_contentManager.html +++ b/resources/texts/_contentManager.html @@ -20,9 +20,12 @@ function createDict(keys, values) { } return d; } -const BOOK_KEYS = ["id", "name", "path", "url", "size", "description", "title", "tags", "date", "favicon", "faviconMimeType"]; +const BOOK_KEYS = ["id", "name", "path", "url", "size", "description", "title", "tags", "date", "favicon", "faviconMimeType", "downloadId"]; function addBook(values) { var b = createDict(BOOK_KEYS, values); + if (b.downloadId && !downloadUpdaters.hasOwnProperty(b.id)) { + downloadUpdaters[b.id] = setInterval(function() { getDownloadInfo(b.id); }, 1000); + } app.books.push(b); } function onBooksChanged () { @@ -33,18 +36,37 @@ function onBooksChanged () { } } +downloadUpdaters = {} +const DOWNLOAD_KEYS = ["id", "status", "followedBy", "path", "totalLength", "completedLength", "downloadSpeed", "verifiedLength"]; +function getDownloadInfo(id) { + downloader.updateDownloadInfos(id, DOWNLOAD_KEYS, function(values) { + if (values.length == 0) { + clearInterval(downloadUpdaters[id]); + return; + } + d = createDict(DOWNLOAD_KEYS, values); + if (d.status == "completed") { + clearInterval(downloadUpdaters[id]); + } + Vue.set(app.downloads, id, createDict(DOWNLOAD_KEYS, values)); + }); +} + function init() { new QWebChannel(qt.webChannelTransport, function(channel) { contentManager = channel.objects.contentManager; library = channel.objects.library; kiwix = channel.objects.kiwix; + downloader = channel.objects.downloader; app = new Vue({ el: "#app", data: { contentManager: contentManager, library: library, kiwix: kiwix, - books: [] + downloader: downloader, + books: [], + downloads: {} }, methods: { openBook : function(book) { @@ -56,6 +78,12 @@ function init() { if (newPage > contentManager.nbPages) newPage = contentManager.nbPages; contentManager.currentPage = newPage; }, + downloadBook : function(book) { + downloader.downloadBook(book.id, function(did) { + book.downloadId = did; + downloadUpdaters[book.id] = setInterval(function() { getDownloadInfo(book.id); }, 1000); + }); + }, niceBytes : niceBytes } }); @@ -108,8 +136,13 @@ function init() { {{ book.tags }} - - + + +
diff --git a/src/downloader.cpp b/src/downloader.cpp new file mode 100644 index 0000000..ea90601 --- /dev/null +++ b/src/downloader.cpp @@ -0,0 +1,104 @@ +#include "downloader.h" + +Downloader::Downloader(Library* library, QObject *parent) + : QObject(parent), + mp_library(library) +{ + +} + +Downloader::~Downloader() +{ + m_downloader.close(); +} + +QStringList Downloader::getDownloadIds() +{ + QStringList list; + for(auto& id: m_downloader.getDownloadIds()) { + list.append(QString::fromStdString(id)); + } + return list; +} + +QString Downloader::downloadBook(const QString& id) { + auto& book = mp_library->getBookById(id); + auto download = m_downloader.startDownload(book.getUrl()); + book.setDownloadId(download->getDid()); + return QString::fromStdString(download->getDid()); +} + +#define ADD_V(KEY, METH) {if(key==KEY) {values.append(QString::fromStdString((d->METH()))); continue;}} +QStringList Downloader::updateDownloadInfos(QString id, const QStringList &keys) +{ + QStringList values; + if (id.endsWith(".zim")) { + id.resize(id.size()-4); + } + auto& b = mp_library->getBookById(id); + kiwix::Download* d; + try { + d = m_downloader.getDownload(b.getDownloadId()); + } catch(...) { + b.setDownloadId(""); + mp_library->save(); + emit(mp_library->booksChanged()); + return values; + } + + d->updateStatus(true); + if (d->getStatus() == kiwix::Download::COMPLETE) { + b.setPath(d->getPath()); + b.setDownloadId(""); + mp_library->save(); + emit(mp_library->booksChanged()); + } + for(auto& key: keys){ + ADD_V("id", getDid); + if(key == "status") { + switch(d->getStatus()){ + case kiwix::Download::ACTIVE: + values.append("active"); + break; + case kiwix::Download::WAITING: + values.append("waiting"); + break; + case kiwix::Download::PAUSED: + values.append("paused"); + break; + case kiwix::Download::ERROR: + values.append("error"); + break; + case kiwix::Download::COMPLETE: + values.append("completed"); + break; + case kiwix::Download::REMOVED: + values.append("removed"); + break; + default: + values.append("unknown"); + } + continue; + } + ADD_V("followedBy", getFollowedBy); + ADD_V("path", getPath); + if(key == "totalLength") { + values.append(QString::number(d->getTotalLength())); + } + if(key == "completedLength") { + values.append(QString::number(d->getCompletedLength())); + } + if(key == "downloadSpeed") { + values.append(QString::number(d->getDownloadSpeed())); + } + if(key == "verifiedLength") { + values.append(QString::number(d->getVerifiedLength())); + } + } + return values; +} +#undef ADD_V + +int Downloader::getNbDownload() { + return m_downloader.getNbDownload(); +} diff --git a/src/downloader.h b/src/downloader.h new file mode 100644 index 0000000..4965992 --- /dev/null +++ b/src/downloader.h @@ -0,0 +1,32 @@ +#ifndef DOWNLOADER_H +#define DOWNLOADER_H + +#include +#include "library.h" +#include +#include + +class Downloader : public QObject +{ + Q_OBJECT + Q_PROPERTY(int nbDownload READ getNbDownload NOTIFY downloadsChanged) + Q_PROPERTY(QStringList downloadIds READ getDownloadIds NOTIFY downloadsChanged) +public: + explicit Downloader(Library* library, QObject *parent = nullptr); + virtual ~Downloader(); + QStringList getDownloadIds(); + +signals: + void downloadsChanged(); + +public slots: + QString downloadBook(const QString& id); + QStringList updateDownloadInfos(QString id, const QStringList& keys); + int getNbDownload(); + +private: + Library* mp_library; + kiwix::Downloader m_downloader; +}; + +#endif // DOWNLOADER_H diff --git a/src/kiwixapp.cpp b/src/kiwixapp.cpp index 87f6080..2706dee 100644 --- a/src/kiwixapp.cpp +++ b/src/kiwixapp.cpp @@ -14,7 +14,8 @@ KiwixApp::KiwixApp(int& argc, char *argv[]) : QApplication(argc, argv), m_library(), - m_manager(&m_library) + m_manager(&m_library), + m_downloader(&m_library) { m_qtTranslator.load(QLocale(), "qt", "_", QLibraryInfo::location(QLibraryInfo::TranslationsPath)); @@ -73,6 +74,7 @@ KiwixApp::KiwixApp(int& argc, char *argv[]) mp_tabWidget = mp_mainWindow->getTabWidget(); mp_tabWidget->setContentManagerView(m_manager.getView()); m_manager.getView()->registerObject("kiwix", this); + m_manager.getView()->registerObject("downloader", &m_downloader); postInit(); mp_errorDialog = new QErrorMessage(mp_mainWindow); diff --git a/src/kiwixapp.h b/src/kiwixapp.h index d3b640c..8ab9d3a 100644 --- a/src/kiwixapp.h +++ b/src/kiwixapp.h @@ -4,6 +4,7 @@ #include "library.h" #include "contentmanager.h" #include "mainwindow.h" +#include "downloader.h" #include "tabwidget.h" #include "tocsidebar.h" #include "urlschemehandler.h" @@ -78,6 +79,7 @@ private: QTranslator m_qtTranslator, m_appTranslator; Library m_library; ContentManager m_manager; + Downloader m_downloader; MainWindow* mp_mainWindow; TabWidget* mp_tabWidget; QErrorMessage* mp_errorDialog; diff --git a/src/library.cpp b/src/library.cpp index 666e018..44044c2 100644 --- a/src/library.cpp +++ b/src/library.cpp @@ -133,3 +133,11 @@ QStringList Library::getBookInfos(QString id, const QStringList &keys) } return values; } + +kiwix::Book &Library::getBookById(QString id) +{ + if (id.endsWith(".zim")) { + id.resize(id.size()-4); + } + return m_library.getBookById(id.toStdString()); +} diff --git a/src/library.h b/src/library.h index 129525c..ce8e5b1 100644 --- a/src/library.h +++ b/src/library.h @@ -33,6 +33,7 @@ public: public slots: QStringList getBookInfos(QString id, const QStringList &keys); QString openBookById(const QString& _id); + kiwix::Book& getBookById(QString id); signals: void booksChanged();