Handle downloading of remote books.

This commit is contained in:
Matthieu Gautier 2018-10-17 11:10:42 +02:00
parent 2923b19478
commit 7a83a1038d
8 changed files with 191 additions and 7 deletions

View File

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

View File

@ -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 }}
</span>
<span>
<button v-if="book.path" v-on:click="openBook(book)">Open</button>
<button v-else>Download</button>
<template v-if="book.downloadId">
<span v-if="downloads[book.id]">
{{ niceBytes(downloads[book.id].completedLength) }} / {{ niceBytes(downloads[book.id].totalLength) }}
</span>
</template>
<button v-else-if="book.path" v-on:click="openBook(book)">Open</button>
<button v-else v-on:click="downloadBook(book)">Download ({{niceBytes(book.size)}})</button>
</span>
</div>
<div class="book content">

104
src/downloader.cpp Normal file
View File

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

32
src/downloader.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef DOWNLOADER_H
#define DOWNLOADER_H
#include <QObject>
#include "library.h"
#include <kiwix/downloader.h>
#include <QDebug>
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

View File

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

View File

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

View File

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

View File

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