1 /* This file is part of Clementine.
2    Copyright 2012, David Sansome <me@davidsansome.com>
3    Copyright 2012, 2014, John Maguire <john.maguire@gmail.com>
4    Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
5 
6    Clementine is free software: you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation, either version 3 of the License, or
9    (at your option) any later version.
10 
11    Clementine is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with Clementine.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "itunessearchpage.h"
21 
22 #include <QMessageBox>
23 #include <QNetworkReply>
24 #include <QUrlQuery>
25 #include <QJsonDocument>
26 #include <QJsonObject>
27 #include <QJsonParseError>
28 #include <QJsonArray>
29 
30 #include "core/closure.h"
31 #include "core/network.h"
32 #include "podcast.h"
33 #include "podcastdiscoverymodel.h"
34 #include "ui_itunessearchpage.h"
35 #include "ui/iconloader.h"
36 
37 const char* ITunesSearchPage::kUrlBase =
38     "http://ax.phobos.apple.com.edgesuite.net/WebObjects/MZStoreServices.woa/"
39     "wa/wsSearch?country=US&media=podcast";
40 
ITunesSearchPage(Application * app,QWidget * parent)41 ITunesSearchPage::ITunesSearchPage(Application* app, QWidget* parent)
42     : AddPodcastPage(app, parent),
43       ui_(new Ui_ITunesSearchPage),
44       network_(new NetworkAccessManager(this)) {
45   ui_->setupUi(this);
46   connect(ui_->search, SIGNAL(clicked()), SLOT(SearchClicked()));
47   setWindowIcon(IconLoader::Load("itunes", IconLoader::Provider));
48 }
49 
~ITunesSearchPage()50 ITunesSearchPage::~ITunesSearchPage() { delete ui_; }
51 
SearchClicked()52 void ITunesSearchPage::SearchClicked() {
53   emit Busy(true);
54 
55   QUrl url(QUrl::fromEncoded(kUrlBase));
56   QUrlQuery url_query;
57   url_query.addQueryItem("term", ui_->query->text());
58   url.setQuery(url_query);
59 
60   QNetworkReply* reply = network_->get(QNetworkRequest(url));
61   NewClosure(reply, SIGNAL(finished()), this,
62              SLOT(SearchFinished(QNetworkReply*)), reply);
63 }
64 
SearchFinished(QNetworkReply * reply)65 void ITunesSearchPage::SearchFinished(QNetworkReply* reply) {
66   reply->deleteLater();
67   emit Busy(false);
68 
69   model()->clear();
70 
71   // Was there a network error?
72   if (reply->error() != QNetworkReply::NoError) {
73     QMessageBox::warning(this, tr("Failed to fetch podcasts"),
74                          reply->errorString());
75     return;
76   }
77 
78   QJsonParseError error;
79   QJsonDocument json_document = QJsonDocument::fromJson(reply->readAll(), &error);
80 
81   if (error.error != QJsonParseError::NoError) {
82     QMessageBox::warning(
83         this, tr("Failed to fetch podcasts"),
84         tr("There was a problem parsing the response from the iTunes Store"));
85     return;
86   }
87 
88   QJsonObject json_data = json_document.object();
89 
90   // Was there an error message in the JSON?
91   if (!json_data["errorMessage"].isUndefined()) {
92     QMessageBox::warning(this, tr("Failed to fetch podcasts"),
93                          json_data["errorMessage"].toString());
94     return;
95   }
96 
97   for (const QJsonValue& result : json_data["results"].toArray()) {
98     QJsonObject json_result = result.toObject();
99     if (json_result["kind"].toString() != "podcast") {
100       continue;
101     }
102 
103     Podcast podcast;
104     podcast.set_author(json_result["artistName"].toString());
105     podcast.set_title(json_result["trackName"].toString());
106     podcast.set_url(QUrl(json_result["feedUrl"].toString()));
107     podcast.set_link(QUrl(json_result["trackViewUrl"].toString()));
108     podcast.set_image_url_small(QUrl(json_result["artworkUrl30"].toString()));
109     podcast.set_image_url_large(QUrl(json_result["artworkUrl100"].toString()));
110 
111     model()->appendRow(model()->CreatePodcastItem(podcast));
112   }
113 }
114 
Show()115 void ITunesSearchPage::Show() { ui_->query->setFocus(); }
116