on xenial help sign in
Move downloads to their own threads so they don't muck about with the parent thread's event loop.
9993f6dJussi Pakkanen
plugins/Utils/CMakeLists.txt+1−1
@@ -33,7 +33,7 @@ target_link_libraries(Utils-qml ${GIO_LDFLAGS})
33# files directly in targets.
33# files directly in targets.
34set_target_properties(Utils-qml PROPERTIES COMPILE_FLAGS -fvisibility=default)
34set_target_properties(Utils-qml PROPERTIES COMPILE_FLAGS -fvisibility=default)
35
35
36−qt5_use_modules(Utils-qml Qml Quick DBus Network XmlPatterns)
36+qt5_use_modules(Utils-qml Qml Quick DBus Network XmlPatterns Concurrent)
37
37
38# export the qmldir qmltypes and plugin files
38# export the qmldir qmltypes and plugin files
39export_qmlfiles(Utils Utils)
39export_qmlfiles(Utils Utils)
plugins/Utils/albumartprovider.cpp+23−21
@@ -33,12 +33,27 @@
33#include <QImage>
33#include <QImage>
34#include <QUrl>
34#include <QUrl>
35#include <QUrlQuery>
35#include <QUrlQuery>
36+#include <QtConcurrent>
36
37
37using namespace std;
38using namespace std;
38
39
39const std::string AlbumArtProvider::DEFAULT_ALBUM_ART = "/usr/share/unity/icons/album_missing.png";
40const std::string AlbumArtProvider::DEFAULT_ALBUM_ART = "/usr/share/unity/icons/album_missing.png";
40const std::string AlbumArtProvider::UNITY_LENS_SCHEMA = "com.canonical.Unity.Lenses";
41const std::string AlbumArtProvider::UNITY_LENS_SCHEMA = "com.canonical.Unity.Lenses";
41
42
43+static QByteArray download(QString url) {
44+ QScopedPointer<QNetworkAccessManager> am(new QNetworkAccessManager);
45+ QNetworkReply *reply = am->get(QNetworkRequest(QUrl(url)));
46+ QEventLoop loop;
47+ QObject::connect(am.data(), &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
48+ loop.exec();
49+
50+ if (reply->error() != QNetworkReply::NoError) {
51+ qWarning() << "Error downloading from the network:" << reply->errorString();
52+ return QByteArray();
53+ }
54+ return reply->readAll();
55+}
56+
42AlbumArtProvider::AlbumArtProvider()
57AlbumArtProvider::AlbumArtProvider()
43 : QQuickImageProvider(QQmlImageProviderBase::Image, QQmlImageProviderBase::ForceAsynchronousImageLoading),
58 : QQuickImageProvider(QQmlImageProviderBase::Image, QQmlImageProviderBase::ForceAsynchronousImageLoading),
44 m_settings(nullptr)
59 m_settings(nullptr)
@@ -76,20 +91,14 @@ std::string AlbumArtProvider::get_lastfm_url(const albuminfo &ai) {
76 QString request = QString("http://ws.audioscrobbler.com/1.0/album/%1/%2/info.xml").arg(artist)
91 QString request = QString("http://ws.audioscrobbler.com/1.0/album/%1/%2/info.xml").arg(artist)
77 .arg(album)
92 .arg(album)
78 .toHtmlEscaped();
93 .toHtmlEscaped();
79− QScopedPointer<QNetworkAccessManager> am(new QNetworkAccessManager);
94+ QFuture<QByteArray> future = QtConcurrent::run(download, request);
80− QNetworkReply *reply = am->get(QNetworkRequest(QUrl(request)));
95+ QByteArray arr = future.result();
81− QEventLoop loop;
96+ if(arr.size() == 0) {
82− QObject::connect(am.data(), &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
83− loop.exec();
84−
85− if (reply->error() != QNetworkReply::NoError) {
86− qWarning() << "Error getting the XML:" << reply->errorString();
87 return "";
97 return "";
88 }
98 }
89−
90 QXmlQuery query;
99 QXmlQuery query;
91 QBuffer tmp;
100 QBuffer tmp;
92− tmp.setData(reply->readAll());
101+ tmp.setData(arr);
93 tmp.open(QIODevice::ReadOnly);
102 tmp.open(QIODevice::ReadOnly);
94 query.bindVariable("reply", &tmp);
103 query.bindVariable("reply", &tmp);
95 query.setQuery("doc($reply)/album/coverart/large[1]/text()");
104 query.setQuery("doc($reply)/album/coverart/large[1]/text()");
@@ -109,24 +118,17 @@ std::string AlbumArtProvider::get_lastfm_url(const albuminfo &ai) {
109bool AlbumArtProvider::download_and_store(const std::string &image_url, const std::string &output_file) {
118bool AlbumArtProvider::download_and_store(const std::string &image_url, const std::string &output_file) {
110 QString url = QString::fromStdString(image_url);
119 QString url = QString::fromStdString(image_url);
111 QString fileName = QString::fromStdString(output_file);
120 QString fileName = QString::fromStdString(output_file);
112−
121+ QFuture<QByteArray> future = QtConcurrent::run(download, url);
113− QScopedPointer<QNetworkAccessManager> am(new QNetworkAccessManager);
122+ QByteArray arr = future.result();
114− QNetworkReply *reply = am->get(QNetworkRequest(QUrl(url)));
123+ if (arr.size() == 0) {
115− QEventLoop loop;
116− QObject::connect(am.data(), &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
117− loop.exec();
118−
119− if (reply->error() != QNetworkReply::NoError) {
120− qWarning() << "Error getting the image:" << reply->errorString();
121 return false;
124 return false;
122 }
125 }
123−
124 QFile file(fileName);
126 QFile file(fileName);
125 if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
127 if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
126 qWarning() << "Could not open file for writing:" << file.errorString();
128 qWarning() << "Could not open file for writing:" << file.errorString();
127 return false;
129 return false;
128 }
130 }
129− if (file.write(reply->readAll()) == -1){
131+ if (file.write(arr) == -1){
130 qWarning() << "Could not write the image:" << file.error();
132 qWarning() << "Could not write the image:" << file.error();
131 return false;
133 return false;
132 }
134 }