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