From b3ae7bb69d48c288fbc49320521a0666b8a1f7dd Mon Sep 17 00:00:00 2001 From: Akos Polster Date: Sat, 30 Oct 2010 16:16:18 +0200 Subject: [PATCH] Project Gutenberg downloads work end-to-end. --- platform.cpp | 5 +++++ platform.h | 1 + search.cpp | 48 +++++++++++++++++++++++++++++++++++++++-------- search.h | 20 ++++++++++++++++++-- searchresultsdialog.cpp | 35 ++++++++++++++++++++++++++++++---- searchresultsdialog.h | 3 ++- 6 files changed, 97 insertions(+), 15 deletions(-) diff --git a/platform.cpp b/platform.cpp index ea09cfe..1c4172b 100644 --- a/platform.cpp +++ b/platform.cpp @@ -48,3 +48,8 @@ QString Platform::version() { return QString(DORIAN_VERSION); } + +QString Platform::downloadDir() +{ + return QDir::home().absoluteFilePath("Books"); +} diff --git a/platform.h b/platform.h index 5f63180..5a25b23 100644 --- a/platform.h +++ b/platform.h @@ -11,6 +11,7 @@ public: static QString icon(const QString &name); static void restart(char *argv[]); static QString version(); + static QString downloadDir(); }; #endif // PLATFORM_H diff --git a/search.cpp b/search.cpp index 0d13733..a2ca1ba 100644 --- a/search.cpp +++ b/search.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "search.h" #include "platform.h" @@ -59,9 +60,11 @@ QList Search::results() return searchResults; } -bool Search::download(const Search::Result &result, const QString &fileName) +void Search::download(const Search::Result &result, const QString &fileName) { Trace t("Search::download"); + downloadResult = result; + downloadFileName = fileName; qDebug() << "UID" << result.id; Q_UNUSED(fileName); emit beginDownload(0); @@ -71,7 +74,6 @@ bool Search::download(const Search::Result &result, const QString &fileName) request.setUrl(url); downloadReply = downloadManager->get(request); connect(downloadReply, SIGNAL(finished()), this, SLOT(downloadFinished())); - return true; } void Search::finished() @@ -133,19 +135,49 @@ void Search::downloadFinished() return; } + // Handle download errors + if (QNetworkReply::NoError != downloadReply->error()) { + qCritical() << "Search::downloadFinished: Network error" + << downloadReply->error(); + downloadReply->deleteLater(); + downloadReply = 0; + emit endDownload(Search::DownloadError, downloadResult, downloadFileName); + return; + } + + // Handle redirection QVariant header = downloadReply->header(QNetworkRequest::LocationHeader); if (header.isValid()) { + // Handle redirection: Download again with the new URL qDebug() << "Redirected to" << header; - downloadReply->deleteLater(); QNetworkRequest request; request.setUrl(header.toUrl()); + downloadReply->deleteLater(); downloadReply = downloadManager->get(request); connect(downloadReply, SIGNAL(finished()), this, SLOT(downloadFinished())); + return; + } + + // Handle download success + QByteArray data = downloadReply->readAll(); + quint64 size = (quint64)data.size(); + qDebug() << "Got" << size << "bytes"; + downloadReply->deleteLater(); + downloadReply = 0; + QFile out(downloadFileName); + int status = Search::FileError; + if (out.open(QIODevice::WriteOnly)) { + if (size == out.write(data, size)) { + qDebug() << "Book saved to" << downloadFileName; + status = Search::Ok; + } else { + qCritical() << "Search::downloadFinished: Failed to write" << size + << "bytes to" << downloadFileName; + } + out.close(); } else { - QByteArray data = downloadReply->readAll(); - qDebug() << "Got" << data.size() << "bytes"; - downloadReply->deleteLater(); - downloadReply = 0; - emit endDownload(); + qCritical() << "Search::downloadFinished: Could not open" + << downloadFileName; } + emit endDownload(status, downloadResult, downloadFileName); } diff --git a/search.h b/search.h index 6405ea1..4908ac6 100644 --- a/search.h +++ b/search.h @@ -16,6 +16,7 @@ class Search: public QObject Q_OBJECT public: + /** Search query. */ struct Query { QString title; @@ -23,6 +24,7 @@ public: QStringList languages; }; + /** Search result. */ struct Result { QString id; @@ -31,6 +33,17 @@ public: QStringList authors; QString language; QImage cover; + bool operator ==(const Result &other) const { + return (source == other.source) && (id == other.id); + } + }; + + /** Download status. */ + enum + { + Ok, + DownloadError, + FileError, }; static Search *instance(); @@ -42,12 +55,13 @@ signals: void endSearch(); void beginDownload(int totalBlocks); void downloading(int blocks); - void endDownload(); + void endDownload(int status, const Search::Result &result, + const QString &fileName); public slots: void start(const Query &query); QList results(); - bool download(const Result &result, const QString &fileName); + void download(const Result &result, const QString &fileName); void finished(); void downloadFinished(); @@ -58,6 +72,8 @@ private: QNetworkReply *reply; QNetworkReply *downloadReply; QList searchResults; + Search::Result downloadResult; + QString downloadFileName; }; #endif // SEARCH_H diff --git a/searchresultsdialog.cpp b/searchresultsdialog.cpp index 3c38816..09bc217 100644 --- a/searchresultsdialog.cpp +++ b/searchresultsdialog.cpp @@ -1,3 +1,4 @@ +#include #include #include "listview.h" @@ -5,6 +6,8 @@ #include "searchresultinfodialog.h" #include "trace.h" #include "progressdialog.h" +#include "library.h" +#include "platform.h" SearchResultsDialog::SearchResultsDialog(const QList results_, QWidget *parent): ListWindow(parent), results(results_) @@ -30,7 +33,10 @@ SearchResultsDialog::SearchResultsDialog(const QList results_, this, SLOT(onItemActivated(const QModelIndex &))); Search *search = Search::instance(); connect(search, SIGNAL(beginDownload(int)), this, SLOT(onBeginDownload(int))); - connect(search, SIGNAL(endDownload()), this, SLOT(onEndDownload())); + connect(search, + SIGNAL(endDownload(int, const Search::Result &, const QString &)), + this, + SLOT(onEndDownload(int, const Search::Result &, const QString &))); progress = new ProgressDialog(tr("Downloading Book"), this); } @@ -58,12 +64,24 @@ void SearchResultsDialog::onDownload() QString SearchResultsDialog::downloadName() const { - // FIXME - return QString("/tmp/book.epub"); + Trace t("SearchResultsDialog::downloadName"); + QString dir = Platform::downloadDir(); + QDir().mkpath(dir); // Not sure if this works. QDir API is quiet lame. + unsigned i = 0; + QString fileName; + do { + char tmp[9]; + snprintf(tmp, 8, "%8.8x", i++); + tmp[8] = '\0'; + fileName = QDir(dir).absoluteFilePath(QString(tmp) + ".epub"); + } while (QFile(fileName).exists()); + qDebug() << fileName; + return fileName; } void SearchResultsDialog::onBeginDownload(int size) { + Q_UNUSED(size); Trace t("SearchResultsDialog::onBeginDownload"); progress->setMinimum(0); progress->setMaximum(0); @@ -71,8 +89,17 @@ void SearchResultsDialog::onBeginDownload(int size) progress->show(); } -void SearchResultsDialog::onEndDownload() +void SearchResultsDialog::onEndDownload(int status, const Search::Result &result, + const QString &fileName) { + Q_UNUSED(result); Trace t("SearchResultsDialog::onEndDownload"); progress->reset(); + if (Search::Ok == status) { + Library::instance()->add(fileName); + int row = results.indexOf(result); + if (-1 != row) { + list->model()->removeRow(row); + } + } } diff --git a/searchresultsdialog.h b/searchresultsdialog.h index 6abc9ad..bf8a389 100644 --- a/searchresultsdialog.h +++ b/searchresultsdialog.h @@ -23,7 +23,8 @@ protected slots: void onDownload(); void onItemActivated(const QModelIndex &index); void onBeginDownload(int size); - void onEndDownload(); + void onEndDownload(int status, const Search::Result &result, + const QString &fileName); protected: QString downloadName() const; -- 1.7.9.5