1 #include <QNetworkRequest>
2 #include <QNetworkReply>
5 #include <QNetworkAccessManager>
7 #include <QWebElementCollection>
16 Search *Search::instance()
30 Search::Search(): QObject(0), reply(0), downloadReply(0)
32 manager = new QNetworkAccessManager(this);
33 downloadManager = new QNetworkAccessManager(this);
36 void Search::start(const Query &query)
42 searchResults.clear();
43 QNetworkRequest request;
44 request.setUrl(QUrl("http://www.gutenberg.org/catalog/world/results"));
45 // request.setRawHeader("User-Agent", "Dorian " + Platform::version());
46 QString title = query.title;
47 if (title.isEmpty()) {
51 data = "title=" + QUrl::toPercentEncoding(title) + "&author=" +
52 QUrl::toPercentEncoding(query.author);
53 qDebug() << "Request:" << (request.url().toString() + "?" + data);
54 reply = manager->post(request, data);
55 connect(reply, SIGNAL(finished()), this, SLOT(finished()));
58 QList<Search::Result> Search::results()
63 void Search::download(const Search::Result &result, const QString &fileName)
66 downloadResult = result;
67 downloadFileName = fileName;
68 qDebug() << "UID" << result.id;
70 emit beginDownload(0);
71 QUrl url("http://www.gutenberg.org/ebooks/" + result.id + ".epub");
72 qDebug() << "Requesting" << url;
73 QNetworkRequest request;
75 downloadReply = downloadManager->get(request);
76 connect(downloadReply, SIGNAL(finished()), this, SLOT(downloadFinished()));
79 void Search::finished()
87 QByteArray data = reply->readAll();
89 // Parse search results
92 QWebFrame *frame = page.mainFrame();
93 frame->setHtml(QString(data));
94 QWebElementCollection tables = frame->findAllElements("table");
95 if (tables.count() == 1) {
96 QWebElement table = tables[0];
97 foreach (QWebElement row, table.findAll("tr")) {
98 QWebElementCollection cols = row.findAll("td");
99 if (cols.count() < 5) {
102 QString id = cols[0].toPlainText().trimmed();
106 QString author = cols[2].toPlainText().trimmed();
107 QStringList titles = cols[3].toPlainText().trimmed().
108 split("\n", QString::SkipEmptyParts);
110 r.authors = author.split("\n", QString::SkipEmptyParts);
112 if (titles.count()) {
115 r.language = cols[4].toPlainText().trimmed();
116 r.source = "Project Gutenberg";
117 searchResults.append(r);
119 qDebug() << " Authors:" << r.authors;
120 qDebug() << " Title:" << r.title;
121 qDebug() << " Language:" << r.language;
125 reply->deleteLater();
130 void Search::downloadFinished()
134 if (!downloadReply) {
138 // Handle download errors
139 if (QNetworkReply::NoError != downloadReply->error()) {
140 qCritical() << "Search::downloadFinished: Network error"
141 << downloadReply->error();
142 downloadReply->deleteLater();
144 emit endDownload(Search::DownloadError, downloadResult, downloadFileName);
148 // Handle redirection
149 QVariant header = downloadReply->header(QNetworkRequest::LocationHeader);
150 if (header.isValid()) {
151 // Handle redirection: Download again with the new URL
152 qDebug() << "Redirected to" << header;
153 QNetworkRequest request;
154 request.setUrl(header.toUrl());
155 downloadReply->deleteLater();
156 downloadReply = downloadManager->get(request);
157 connect(downloadReply, SIGNAL(finished()), this, SLOT(downloadFinished()));
161 // Handle download success
162 QByteArray data = downloadReply->readAll();
163 qint64 size = (qint64)data.size();
164 qDebug() << "Got" << size << "bytes";
165 downloadReply->deleteLater();
167 QFile out(downloadFileName);
168 int status = Search::FileError;
169 if (out.open(QIODevice::WriteOnly)) {
170 if (size == out.write(data, size)) {
171 qDebug() << "Book saved to" << downloadFileName;
174 qCritical() << "Search::downloadFinished: Failed to write" << size
175 << "bytes to" << downloadFileName;
179 qCritical() << "Search::downloadFinished: Could not open"
182 emit endDownload(status, downloadResult, downloadFileName);