{
return QString(DORIAN_VERSION);
}
+
+QString Platform::downloadDir()
+{
+ return QDir::home().absoluteFilePath("Books");
+}
static QString icon(const QString &name);
static void restart(char *argv[]);
static QString version();
+ static QString downloadDir();
};
#endif // PLATFORM_H
#include <QWebPage>
#include <QWebElementCollection>
#include <QWebElement>
+#include <QFile>
#include "search.h"
#include "platform.h"
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);
request.setUrl(url);
downloadReply = downloadManager->get(request);
connect(downloadReply, SIGNAL(finished()), this, SLOT(downloadFinished()));
- return true;
}
void Search::finished()
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);
}
Q_OBJECT
public:
+ /** Search query. */
struct Query
{
QString title;
QStringList languages;
};
+ /** Search result. */
struct Result
{
QString id;
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();
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<Result> results();
- bool download(const Result &result, const QString &fileName);
+ void download(const Result &result, const QString &fileName);
void finished();
void downloadFinished();
QNetworkReply *reply;
QNetworkReply *downloadReply;
QList<Result> searchResults;
+ Search::Result downloadResult;
+ QString downloadFileName;
};
#endif // SEARCH_H
+#include <stdio.h>
#include <QtGui>
#include "listview.h"
#include "searchresultinfodialog.h"
#include "trace.h"
#include "progressdialog.h"
+#include "library.h"
+#include "platform.h"
SearchResultsDialog::SearchResultsDialog(const QList<Search::Result> results_,
QWidget *parent): ListWindow(parent), results(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);
}
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);
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);
+ }
+ }
}
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;