3 * Copyright (C) 2011 Roman Moravcik
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "medarddownloader.h"
28 #define DOWNLOAD_CACHE_DIR ".cache/medard-downloader"
30 #define MEDARD_URL "http://www.medard-online.cz"
31 #define MEDARD_IMAGE_URL "http://www.medard-online.cz/scripts/getimage.php?initDate=%1&domain=%2&variable=%3&offset=%4"
33 #define FC_SEA_LEVEL_PRESSURE "slp"
34 #define FC_PRECIPITATION "precip"
35 #define FC_WIND_VELOCITY "wv"
36 #define FC_CLOUDINESS "cloud"
37 #define FC_TEMPERATURE "temp"
40 #define FD_CZECH_REPUBLIC "2"
45 #define IMAGE_WIDTH 556
46 #define IMAGE_HEIGHT 408
48 #define MAX_DOWNLOAD_RETRIES 3
50 MedardDownloader::MedardDownloader() : QObject()
52 m_forecastType = FC_SEA_LEVEL_PRESSURE;
53 m_forecastDomain = FD_EUROPE;
54 m_forecastInitialDateCode.clear();
55 m_forecastDateOffset = 0;
57 m_network = new QNetworkAccessManager();
61 m_retryTimer = new QTimer();
62 m_retryTimer->setInterval(5000);
63 connect(m_retryTimer, SIGNAL(timeout()), this, SLOT(retryTimerEvent()));
65 m_cachePath = QString("%1/%2")
66 .arg(QDir().homePath())
67 .arg(DOWNLOAD_CACHE_DIR);
69 createCacheDirectory();
72 MedardDownloader::~MedardDownloader()
74 if (m_retryTimer->isActive())
83 QSize MedardDownloader::getImageSize()
85 return QSize(IMAGE_WIDTH, IMAGE_HEIGHT);
88 void MedardDownloader::setForecastType(ForecastType type)
91 case SeaLevelPressure:
92 m_forecastType = FC_SEA_LEVEL_PRESSURE;
96 m_forecastType = FC_PRECIPITATION;
100 m_forecastType = FC_WIND_VELOCITY;
104 m_forecastType = FC_CLOUDINESS;
108 m_forecastType = FC_TEMPERATURE;
113 void MedardDownloader::setForecastDomain(ForecastDomain domain)
117 m_forecastDomain = FD_EUROPE;
121 m_forecastDomain = FD_CZECH_REPUBLIC;
126 void MedardDownloader::setForecastInitialDate(QDateTime date)
130 m_forecastInitialDate = date.toUTC();
132 if (date.toUTC().time().hour() >= 18) {
133 m_forecastInitialDate.setTime(QTime(18, 0, 0));
135 } else if (date.toUTC().time().hour() >= 12) {
136 m_forecastInitialDate.setTime(QTime(12, 0, 0));
138 } else if (date.toUTC().time().hour() >= 6) {
139 m_forecastInitialDate.setTime(QTime(6, 0, 0));
142 m_forecastInitialDate.setTime(QTime(0, 0, 0));
146 if (offset == "18") {
147 /* use previous day */
148 m_forecastInitialDateCode = QString("%1_%2")
149 .arg(date.addDays(-1).toUTC().toString("yyMMdd"))
152 /* use current day */
153 m_forecastInitialDateCode = QString("%1_%2")
154 .arg(date.toUTC().toString("yyMMdd"))
158 cleanCacheDirectory();
161 QDateTime MedardDownloader::getForecastInitialDate()
163 return m_forecastInitialDate.toLocalTime();
166 QDateTime MedardDownloader::getForecastDate()
168 return m_forecastInitialDate.addSecs(3600 * m_forecastDateOffset).toLocalTime();
171 void MedardDownloader::setForecastDateOffset(int offset)
173 m_forecastDateOffset = offset;
174 if (m_forecastDateOffset > MAX_OFFSET)
175 m_forecastDateOffset = MAX_OFFSET;
177 if (m_forecastDateOffset < MIN_OFFSET)
178 m_forecastDateOffset = MIN_OFFSET;
181 void MedardDownloader::retryTimerEvent()
183 if (m_retryTimer->isActive())
184 m_retryTimer->stop();
189 void MedardDownloader::tryDownloadImageAgain()
193 if (m_retryCounter < MAX_DOWNLOAD_RETRIES) {
194 m_retryTimer->start();
197 emit downloadFailed();
201 void MedardDownloader::clearDownloadRequest()
203 qDebug() << "clearDownloadRequest: m_reply=" << m_reply;
209 void MedardDownloader::downloadImageFinished()
211 qDebug() << "downloadImageFinished: m_reply=" << m_reply;
213 QByteArray picture = m_reply->readAll();
215 if (picture.isNull() || picture.size() <= 0)
221 if (!image.loadFromData(picture, "png"))
224 QString filename = QString("%1/%2_%3_%4_%5.png")
227 .arg(m_forecastDomain)
228 .arg(m_forecastInitialDateCode)
229 .arg(QString().number(m_forecastDateOffset));
231 if ((image.width() == 512) && (image.height() == 512)) {
232 QImage croped(512, 400, QImage::Format_ARGB32_Premultiplied);
233 croped = image.copy(0, 52, 512, IMAGE_HEIGHT);
234 croped.save(filename, "png");
236 QImage croped(560, 400, QImage::Format_ARGB32_Premultiplied);
237 croped = image.copy(10, 96, IMAGE_WIDTH, IMAGE_HEIGHT);
238 croped.save(filename, "png");
241 qDebug() << "downloadImageFinished: downloadFinished=" << filename;
242 emit downloadFinished(filename, getForecastDate());
244 QTimer::singleShot(0, this, SLOT(clearDownloadRequest()));
247 void MedardDownloader::downloadImageError(QNetworkReply::NetworkError /* code */)
249 tryDownloadImageAgain();
250 QTimer::singleShot(0, this, SLOT(clearDownloadRequest()));
253 void MedardDownloader::downloadImage()
255 qDebug() << "downloadImage: retry=" << m_retryCounter << "date:" << m_forecastInitialDate.toString("dd.MM.yyyy hh:mm");
257 if (m_forecastInitialDateCode.isNull()) {
258 retrieveForecastInitialDate();
259 tryDownloadImageAgain();
263 QString filename = QString("%1/%2_%3_%4_%5.png")
266 .arg(m_forecastDomain)
267 .arg(m_forecastInitialDateCode)
268 .arg(QString().number(m_forecastDateOffset));
270 if (isDownloaded(filename)) {
271 qDebug() << "downloadImage: downloadFinished=" << filename;
273 emit downloadFinished(filename, getForecastDate());
277 QString imageUrl = QString(MEDARD_IMAGE_URL)
278 .arg(m_forecastInitialDateCode)
279 .arg(m_forecastDomain)
281 .arg(QString().number(m_forecastDateOffset));
284 QNetworkRequest request(url);
287 clearDownloadRequest();
288 m_reply = m_network->get(request);
290 connect(m_reply, SIGNAL(finished()), this, SLOT(downloadImageFinished()));
291 connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), this,
292 SLOT(downloadImageError(QNetworkReply::NetworkError)));
295 bool MedardDownloader::isDownloaded(const QString filename)
297 return QFile(filename).exists();
300 int MedardDownloader::getForecastDateOffset()
302 return m_forecastDateOffset;
305 int MedardDownloader::getMinForecastDateOffset()
310 int MedardDownloader::getMaxForecastDateOffset()
315 void MedardDownloader::retrieveForecastInitialDateFinished()
317 qDebug() << "retrieveForecastInitialDateFinished: m_reply=" << m_reply;
319 QByteArray data = m_reply->readAll();
321 int index1 = data.indexOf("var fcst_initDatestamp=\"", 0);
322 int index2 = data.indexOf("\";", index1);
325 for (int i = index1 + 24; i < index2; i++) {
326 temp.append(data.at(i));
328 QDateTime date = QDateTime::fromTime_t(temp.toULong() + 6 * 3600);
329 if (!date.isNull()) {
330 setForecastInitialDate(date.toLocalTime());
332 int forecastDateOffset = date.toLocalTime().secsTo(QDateTime().currentDateTime()) / 3600;
333 setForecastDateOffset(forecastDateOffset);
338 QTimer::singleShot(0, this, SLOT(clearDownloadRequest()));
341 void MedardDownloader::retrieveForecastInitialDateError(QNetworkReply::NetworkError /* code */)
343 qDebug() << "retrieveForecastInitialDateError: m_reply=" << m_reply;
346 void MedardDownloader::retrieveForecastInitialDate()
348 qDebug() << "retrieveForecastInitialDate: m_reply=" << m_reply;
350 QString serverUrl = QString(MEDARD_URL);
353 QNetworkRequest request(url);
356 clearDownloadRequest();
357 m_reply = m_network->get(request);
359 connect(m_reply, SIGNAL(finished()), this, SLOT(retrieveForecastInitialDateFinished()));
360 connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), this,
361 SLOT(retrieveForecastInitialDateError(QNetworkReply::NetworkError)));
364 void MedardDownloader::createCacheDirectory()
366 QDir cacheDir(m_cachePath);
367 if (!cacheDir.exists())
368 cacheDir.mkpath(cacheDir.path());
371 void MedardDownloader::cleanCacheDirectory()
373 QDir cacheDir(m_cachePath);
374 QStringList list = cacheDir.entryList();
375 for (int i = 0; i < list.size(); i++) {
376 if (!list.at(i).contains(m_forecastInitialDateCode)) {
377 QFile(m_cachePath + "/" + list.at(i)).remove();