128b5f8cbc35df9d8cc41f6af528292bb9e7bfd0
[situare] / src / map / mapfetcher.cpp
1 /*
2    Situare - A location system for Facebook
3    Copyright (C) 2010  Ixonos Plc. Authors:
4
5        Jussi Laitinen - jussi.laitinen@ixonos.com
6
7    Situare is free software; you can redistribute it and/or
8    modify it under the terms of the GNU General Public License
9    version 2 as published by the Free Software Foundation.
10
11    Situare 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 Situare; if not, write to the Free Software
18    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
19    USA.
20 */
21
22 #include <QNetworkAccessManager>
23 #include <QNetworkRequest>
24 #include <QNetworkReply>
25 #include <QUrl>
26 #include <QDebug>
27 #include <QPixmap>
28 #include <QNetworkDiskCache>
29 #include <QDesktopServices>
30
31 #include "mapfetcher.h"
32
33 static int MAX_PARALLEL_DOWNLOADS = 2;
34 static int DOWNLOAD_QUEUE_SIZE = 50;
35
36 MapFetcher::MapFetcher(QNetworkAccessManager *manager, QObject *parent)
37     : QObject(parent), m_manager(manager)
38 {
39     QNetworkDiskCache *diskCache = new QNetworkDiskCache(this);
40     diskCache->setCacheDirectory(QDesktopServices::storageLocation(
41             QDesktopServices::CacheLocation));
42     m_manager->setCache(diskCache);
43
44     connect(m_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(
45             downloadFinished(QNetworkReply*)));
46 }
47
48 void MapFetcher::fetchMapImage(const QUrl &url)
49 {
50     //qDebug() << __PRETTY_FUNCTION__;
51
52     if (url.isEmpty() || !url.isValid())
53         return;
54
55     if (loadImageFromCache(url))
56         return;
57
58     if (m_downloadQueue.size() >= DOWNLOAD_QUEUE_SIZE)
59         m_downloadQueue.dequeue();
60
61     m_downloadQueue.enqueue(url);
62
63     if (m_currentDownloads.size() < MAX_PARALLEL_DOWNLOADS)
64         startNextDownload();
65 }
66
67 bool MapFetcher::loadImageFromCache(const QUrl &url)
68 {
69     //qDebug() << __PRETTY_FUNCTION__;
70
71     bool imageFound = false;
72
73     if (m_manager->cache()) {
74         QIODevice *cacheImage = m_manager->cache()->data(url);
75
76         if (cacheImage) {
77             QImage image;
78
79             if (image.load(cacheImage, 0)) {
80                 imageFound = true;
81                 emit mapImageReceived(url, QPixmap::fromImage(image));
82             }
83
84             delete cacheImage;
85         }
86     }
87
88     return imageFound;
89 }
90
91 void MapFetcher::startNextDownload()
92 {
93     //qDebug() << __PRETTY_FUNCTION__;
94
95     if (m_downloadQueue.isEmpty())
96         return;
97
98     QUrl url = m_downloadQueue.dequeue();
99
100     QNetworkRequest request(url);
101     request.setRawHeader("User-Agent", "Map Test");
102     QNetworkReply *reply = m_manager->get(request);
103
104     m_currentDownloads.append(reply);
105 }
106
107 void MapFetcher::downloadFinished(QNetworkReply *reply)
108 {
109     //qDebug() << __PRETTY_FUNCTION__;
110
111     if (reply->error() == QNetworkReply::NoError) {
112         QImage image;
113         QUrl url = reply->url();
114
115         if (!image.load(reply, 0)) {
116             qDebug() << "Could not load image";
117             image = QImage();
118         }
119
120         emit mapImageReceived(url, QPixmap::fromImage(image));
121     }
122     else {
123         emit error(reply->errorString());
124     }
125
126     m_currentDownloads.removeAll(reply);
127     reply->deleteLater();
128     startNextDownload();
129 }
130
131 MapFetcher::~MapFetcher()
132 {
133
134 }